Skip to content

A Claude Code recipe: hooks that turn coding sessions into verified lessons (story 28.9) - #226

Merged
fabbrik merged 4 commits into
mainfrom
feat/28-9-claude-code
Oct 31, 2026
Merged

fabbrik merged 4 commits into
mainfrom
feat/28-9-claude-code

Conversation

@fabbrik

@fabbrik fabbrik commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Story 28.9 of Epic 28. Built on the aexp tool (28.8).

  • aexp hook <event> for Claude Code hooks (reference: code.claude.com/docs/en/hooks, fetched 2026-10-30): the first prompt opens a run and gets the Historical Reference block; PostToolUse/PostToolUseFailure record each call (allowed arguments only; results only under a recipe consent) and give the failure hint; Stop ends a turn that changed something and finalizes it on the configured verifier (never the model's word), reporting with a one-line systemMessage only; SessionEnd stores an open run for a later aexp finalize. Every hook exits 0 and logs to an owner-only .aexp/hook.log without prompts or tool content.
  • Holdout per session: the session, not the turn, is the randomization unit (a block given in one turn stays in context); every run of a session lands in the session's arm.
  • Trust: nothing in hook input selects config, identity, scope or command; an untrusted or changed config still records and injects but never runs the verifier. setup prints deny rules for user settings protecting .aexp/, .claude/, the trust file and aexp trust, and says plainly that Bash write paths stay open unless Bash is restricted.
  • aexp setup claude-code: merges hooks into .claude/settings.json without removing anything (keeps escaping, BOM, CRLF, mode, symlinks), writes a default config only when none exists (verifier detected for dotnet/npm/pytest/go, else a placeholder that refuses to run), ignores .aexp/.
  • Managed CLAUDE.md/AGENTS.md section with the measured-helpful lessons: only the fenced section changes, byte-stable, locked, mode kept.
  • Guide: docs/guide/claude-code.md. No library API change.

Tests: Cli.Tests 97 (recorded hook inputs in the documented shapes, the built tool over real stdin), every Docker-free project, pack and verify-packages.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy

fabbrik and others added 4 commits October 30, 2026 20:09
… (story 28.9)

aexp hook <event> handles SessionStart, UserPromptSubmit, PostToolUse,
PostToolUseFailure, Stop and SessionEnd from the hook JSON on stdin; Stop
finalizes the turn's run on the configured verifier inside the hook's time
(an untrusted config records and injects but never runs it). aexp setup
claude-code merges the hooks into .claude/settings.json, writes a default
config and the .gitignore entry. aexp export --claude-md/--agents-md keeps a
fenced, byte-stable section of the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
…tory 28.9)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
…ent (story 28.9)

Tool results in a coding session are file contents and command output; the
hooks pass them to capture only when a recipe consent for the tool asks for
its result excerpt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
Pin each session to one holdout arm (run IDs drawn in the session's arm,
fail closed past the bound); parse hook arguments inside the hook so every
outcome exits 0; refuse without CLAUDE_PROJECT_DIR; keep a run linked when
recall fails; configurable read-only tools and Bash prefixes; deny rules for
user settings covering .aexp, .claude, the trust file and aexp trust;
settings written through links with BOM, CRLF and mode kept; managed
section under a lock, keeping mode and ownership; prune stale sessions;
deterministic timeout tests and the listed test gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
@fabbrik
fabbrik merged commit 2705305 into main Oct 31, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant