feat(harness): context map, @AGENTS.md single source, contexts rule, and commit-msg + anti-bypass hooks - #136
Merged
Merged
Conversation
…ness doc Bootstrap the agent-and-contributor harness layer. Part of #134. - .claude/rules/contexts-authoring.md: a path-scoped Claude Code rule (paths: contexts/**) that surfaces the contexts authoring standard just-in-time. It points at the canonical write-contexts.md instead of duplicating it. Codex has no per-file path-scoped instruction rule, so no parallel file is added; the asymmetry is documented, not worked around. - commit-msg git hook (scripts/hooks/commit_msg_check.py + a commit-msg stage in .pre-commit-config.yaml): rejects a non-English (CJK) or non-Conventional-Commit subject line. Tool-agnostic, so it fires for a human, Claude, or Codex alike because git itself invokes it. - anti-bypass agent hook (scripts/hooks/pre_tool_use_no_bypass.py, shared by .claude/settings.json and .codex/hooks.json): a PreToolUse deny when a Bash git command carries --no-verify, which would skip the commit-msg / pre-commit / pre-push checks. This is the one guarantee a git hook cannot self-enforce, so it lives at the agent layer. - contexts/dev/harness-engineering.md: documents the enforcement layers (CI / git hooks / agent controls), the Claude-vs-Codex mechanism map, the content-alignment-vs-behavior-alignment principle, and a canonical-source table. Registered in contexts/dev/README.md. - Focused tests under tests/hooks/ for both hook scripts. verify.sh passes: ruff format + ruff check + basedpyright + import-linter + pytest --cov (420 passed, 85.66% coverage). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The guard matched a naive substring, so any Bash command that merely mentioned the flag (an echo, a grep, a commit message, a JSON test payload on the command line) was denied even though it ran no git invocation. This surfaced live while building #136. Tokenize the command with shlex, split into simple commands on shell operators, strip leading VAR=value and prefix words (env / command / sudo / ...), and deny only when --no-verify is a real argument token of a real git invocation. A flag mentioned inside a quoted string stays in one token and passes. Fails open on unbalanced quotes. Residual gap (shell indirection such as $VAR / eval) is documented, not resolved. Adds tests for the previously-false-positive cases and updates the mechanical -check description in contexts/dev/harness-engineering.md. verify.sh passes (426 passed, 85.66% coverage). Confirmed live: a command echoing the literal is no longer blocked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ENTS.md import - contexts/CONTEXT_MAP.md: the navigation index for contexts/ (a directory map plus task-to-page routes). AGENTS.md points here as the first read, and it is registered in contexts/README.md. - AGENTS.md becomes the single source of repository instructions; its intro, entry-point pointer, and skills-section wording are updated accordingly. - CLAUDE.md is reduced to `@AGENTS.md` (plus a human-only HTML comment), so the two guides can no longer drift; Claude Code expands the import at load. - tests/test_contexts.py: a `_guide_text` helper inlines `@path` imports when it checks a guide, so the literal-content assertions still hold for CLAUDE.md. verify.sh passes (426 passed, 85.66% coverage). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bootstrap the agent-and-contributor harness: a path-scoped rule, two hooks (one git, one agent), and a design doc that explains how the pieces fit and how Claude Code and Codex stay aligned. This is the first implementation slice of the harness work; it adds no runtime/library behavior.
Rule — contexts authoring, surfaced just-in-time
.claude/rules/contexts-authoring.mdis a path-scoped Claude Code rule (paths: contexts/**) that loads the contexts authoring standard when an agent edits acontexts/page. It is thin and points at the canonicalwrite-contexts.mdrather than duplicating it. The structural rules themselves are already hard-enforced bytests/test_contexts.py; this rule just helps an agent get them right up front..codex/rules/are an execution-policy allowlist (not path-scoped instructions), and its closest instruction equivalent is a coarser nestedAGENTS.md. The asymmetry is documented in the harness doc instead of worked around.Git hook — commit message format
scripts/hooks/commit_msg_check.py, wired as acommit-msgstage in.pre-commit-config.yaml, rejects a non-English (CJK) or non-Conventional-Commit subject line. It is tool-agnostic: a human, Claude, or Codex all trigger it because git invokes it.scripts/pre-commit-setup.shnow installs thecommit-msghook type.Agent hook — no verification bypass
scripts/hooks/pre_tool_use_no_bypass.pyis a sharedPreToolUseguard invoked from both.claude/settings.jsonand.codex/hooks.json. It denies a Bashgitcommand that carries--no-verify, which would otherwise skip the commit-msg / pre-commit / pre-push checks. This is the one guarantee a git hook cannot self-enforce (that flag is what turns git hooks off), so it lives at the agent layer. It is a mechanical check only.Doc
contexts/dev/harness-engineering.mddocuments the enforcement layers (CI is the only floor for external contributors; local git hooks and agent controls sit on top), the Claude-vs-Codex mechanism map (the word "rules" means different things on each side), the principle of aligning content by default and behavior (a shared hook) only for hard guarantees, and a canonical-source table. Registered incontexts/dev/README.md. It cites the Claude Code best-practices, Claude Code rules, and Codex hooks docs.Context map and single-source agent instructions
contexts/CONTEXT_MAP.mdis the navigation index forcontexts/: a directory map with a one-line purpose per page, and a task-to-page route table.AGENTS.mdpoints here as the first read, and it is registered incontexts/README.md.AGENTS.mdbecomes the single source of repository instructions.CLAUDE.mdis reduced to an@AGENTS.mdimport (plus a human-only HTML comment), so the two guides can no longer drift by hand; Claude Code expands the import at load.tests/test_contexts.pygains a_guide_texthelper that inlines@pathimports, so its literal-content assertions still hold forCLAUDE.md.Anti-bypass guard: precise matching
The guard tokenizes the command with
shlex, splits on shell operators, strips leadingVAR=valueand prefix words (env/command/sudo/ ...), and denies only when--no-verifyis a real argument token of a realgitinvocation. A command that merely mentions the flag inside a quoted string (a doc example, a grep, a commit message, a JSON test payload) keeps it inside one token and passes. It fails open on unbalanced quotes. Residual gap: shell indirection such as$VARexpansion orevalis not resolved, which is out of scope for a mechanical guard.An earlier substring version denied any command that mentioned the flag; that false positive surfaced live while building this PR and is fixed in the second commit, with tests for the previously-blocked cases and a live confirmation that echoing the literal is no longer denied.
Not in this PR
pre-commit install). Separate follow-up, noted in the harness doc.Related Issue
Part of #134.
Verification
bash scripts/verify.shpasses: ruff format + ruff check + basedpyright + import-linter + pytest --cov (426 passed, 85.66% coverage).git+ no-verify command and passes everything else. Both also covered bytests/hooks/.Checklist
type(scope): summary.bash scripts/verify.shpasses.