From c8194a6ea9c677cf18c3dab69747509a6e3758d2 Mon Sep 17 00:00:00 2001 From: sebi Date: Sat, 31 Oct 2026 13:52:41 -0500 Subject: [PATCH 1/2] Restore tmp/.keep files; build the extension in tmp/ext rake clobber removed all of tmp/, including the demo app's tracked tmp/.keep, tmp/pids/.keep and tmp/storage/.keep (lost in #7). The extension now builds in tmp/ext, so clobber only removes that. Co-Authored-By: Claude Opus 5.5 --- Rakefile | 3 +++ tmp/.keep | 0 tmp/pids/.keep | 0 tmp/storage/.keep | 0 4 files changed, 3 insertions(+) create mode 100644 tmp/.keep create mode 100644 tmp/pids/.keep create mode 100644 tmp/storage/.keep diff --git a/Rakefile b/Rakefile index cdf690a..077fce6 100644 --- a/Rakefile +++ b/Rakefile @@ -38,6 +38,9 @@ else Rake::ExtensionTask.new('ruby2html') do |ext| ext.lib_dir = 'lib/ruby2html' ext.ext_dir = 'ext/ruby2html' + # Build in tmp/ext, not tmp/: `rake clobber` removes the tmp dir, and tmp/ holds the demo + # app's tracked .keep files. + ext.tmp_dir = 'tmp/ext' end rescue LoadError desc 'Compile the C extension (requires rake-compiler)' diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/pids/.keep b/tmp/pids/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/storage/.keep b/tmp/storage/.keep new file mode 100644 index 0000000..e69de29 From fdaf1a83b3b0a459892baa6f3cb6460aaad6d96b Mon Sep 17 00:00:00 2001 From: sebi Date: Sat, 31 Oct 2026 13:53:15 -0500 Subject: [PATCH 2/2] Claude Code settings: no prompts for routine work, deny publishing The ask list made every commit and push prompt. Routine git/gh/rake commands are allowed; tags, force pushes, rake release, gem push/yank and gh release are denied outright (release.yml publishes on merge). Co-Authored-By: Claude Opus 5.5 --- .claude/settings.json | 54 +++++++++++++++++++++++++++++++++++-------- AGENTS.md | 2 +- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index 33e5aff..b36f0da 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -43,22 +43,56 @@ "Bash(RUBY2HTML_DISABLE_EXT=1 bundle exec rspec *)", "Bash(RUBY2HTML_NO_SIMD=1 bundle exec rake compile)", "Bash(bin/build-ext)", - "Bash(bin/build-ext *)" - ], - "ask": [ + "Bash(bin/build-ext *)", + "Bash(git add *)", + "Bash(git commit *)", + "Bash(git push)", "Bash(git push *)", + "Bash(git checkout *)", + "Bash(git switch *)", + "Bash(git branch *)", + "Bash(git fetch *)", + "Bash(git pull *)", + "Bash(git pull)", + "Bash(git rebase *)", + "Bash(git stash *)", + "Bash(git restore *)", + "Bash(git rm *)", + "Bash(git mv *)", + "Bash(gh pr *)", + "Bash(gh issue *)", + "Bash(gh api *)", + "Bash(gh workflow *)", + "Bash(gh run *)", + "Bash(gh repo view *)", + "Bash(gh label *)", + "Bash(bundle exec rake *)", + "Bash(bundle exec ruby *)", + "Bash(bundle exec rails *)", + "Bash(bin/rails *)", + "Bash(bundle update *)", + "Bash(bundle outdated *)", + "Bash(bundle lock *)", + "Bash(ruby *)", + "Bash(bin/*)" + ], + "deny": [ + "Read(./config/master.key)", + "Read(./.env*)", + "Read(./tmp/local_secret.txt)", "Bash(git tag *)", - "Bash(git commit *)", + "Bash(git push --tags*)", + "Bash(git push * --tags*)", + "Bash(git push --force*)", + "Bash(git push * --force*)", + "Bash(git push -f*)", + "Bash(git push * -f*)", "Bash(bundle exec rake release*)", "Bash(rake release*)", "Bash(gem push *)", "Bash(gem yank *)", - "Bash(gh release *)" - ], - "deny": [ - "Read(./config/master.key)", - "Read(./.env*)", - "Read(./tmp/local_secret.txt)" + "Bash(gh release *)", + "Bash(gh repo delete *)" ] }, "hooks": { diff --git a/AGENTS.md b/AGENTS.md index 633a6b9..83a6fd1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -121,7 +121,7 @@ Keep it that way: don't hardcode version lists or benchmark numbers in docs; poi - Project skills (`.claude/skills/`): `release` (bump → changelog → verify → `release: X.Y.Z` PR; merging publishes; manual-only), `benchmark` (before/after), `add-html-tag`, `review` (checklist for `ext/` and renderer diffs), `debug-render` (C vs Ruby output diffs, sanitizer builds), `upgrade-deps`. - Subagents (`.claude/agents/`, read-only tools): `perf-reviewer`, `xss-auditor`. Use them for an independent pass on hot-path or escaping changes. -- `.claude/settings.json`: allowlists specs, `rake compile/spec/bench/build/smoke`, rubocop, brakeman, bench scripts and read-only git/gh; `git commit`, `git push`, `git tag`, `rake release`, `gem push/yank`, `gh release` always ask. A PostToolUse hook (`.claude/hooks/post-edit-reminder.sh`, non-blocking) reminds to recompile after `ext/` edits and to keep Native/PureRuby parity after renderer edits. +- `.claude/settings.json`: allowlists the whole routine workflow (specs, `rake`, rubocop, brakeman, bench scripts, `bin/*`, git add/commit/push/branch, `gh pr|issue|api|run|workflow`), so agents work without prompts. Denied outright (never needed: merging a version bump publishes): `git tag`, force pushes, `rake release`, `gem push/yank`, `gh release`, reading `.env*`/`config/master.key`. A PostToolUse hook (`.claude/hooks/post-edit-reminder.sh`, non-blocking) reminds to recompile after `ext/` edits and to keep Native/PureRuby parity after renderer edits. ## Definition of done