Repository navigation
Harden the codebase: types, module layers and checks catch wrong code - #11
Merged
Merged
Conversation
Implement the 13 findings of the hardening audit. Each one moves a mistake from code review to a check that fails in CI: - Statuses, levels, verdicts and actions are Literal types. pyright (standard mode, exhaustive match) runs in `make check`. - Exit codes are one ExitCode enum. A usage error exits with 1. - Finding is frozen. Its `blocking` value is computed from the corpus and the verification. Only validate_findings and read_findings make a Finding. - git.py and claude.py are the only modules that start processes. import-linter checks that deterministic modules never import a model module and that only shall.jev imports the TypeSafe SDK. - The config rejects unknown keys and bad hooks.actions rows in the local shall.yaml. In the extended org config, shall drops a row that it cannot read and writes a note to stderr, so the hooks do not fail open. - Agents and the review model are pinned to claude-sonnet-5. A test checks that they agree. - tests/fakes.py gives a FakeJev that pyright checks against JevLike. - The JTOOL RFCs list the test or check for each statement. - CI runs `make check` and pins the Claude Code CLI. Code-review findings that were fixed (the code that showed each one): - cli.py cmd_list printed "None" for an invalid status: format of rfc.status. Now Rfc.status_label. - cli.py cmd_eval_verify ignored review.verify_model. Now Config.verify_model, also used by verify.py and triage.py. - config.py load_json crashed on a cache file that is not an object. - hooks.py action_for raised on an org row that it could not read, so the whole hook failed open. Now config.py drops the row at load. - ci.yml installed an unpinned Claude Code CLI. - pyproject.toml: pyright needed a network download of Node. Now pyright[nodejs]. Self-review: claude.py run_claude retried the `claude -p` call at once, with no delay (JRFC-0006.2). Now it waits with backoff and jitter. Verification: make test (200 passed), make check, make self-check, make test-plugin (7 passed), make self-review (0 findings), /verify (hook drives: force push and secret key denied, write and Stop fail-open; CLI probes for config and status). Co-Authored-By: Claude Opus 5.5 <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
This change implements the 13 findings of a hardening audit. Each fix moves a class of mistake from code review to a check that fails in CI.
Literaltypes. pyright (standard mode, exhaustivematch) now runs inmake check.ExitCodeenum. A usage error exits with 1.Findingis frozen, andblockingis computed from the corpus and the verification. Onlyvalidate_findingsandread_findingsmake aFinding(newfindings.py).git.pyandclaude.pyare the only modules that start processes.shall.jevimports the TypeSafe SDK.hooks.actionsrows in the localshall.yamlstop shall at load. In the extended org config, shall drops a row that it cannot read and writes a note to stderr, so the hooks do not fail open.claude-sonnet-5, and a test checks that they agree.tests/fakes.pyhas aFakeJevthat pyright checks againstJevLike.make testandmake check, and it pins the Claude Code CLI.The plugin version is now 0.4.1, because the agents changed.
Code-review fixes
shall listandshall showprinted "None" for an invalid status. They now print "invalid" (Rfc.status_label).shall eval-verifyignoredreview.verify_model. NowConfig.verify_modelis the one rule, and verify and triage use it too.load_jsoncrashed on a cache file that is not a JSON object.hooks.actionsrow made the whole hook fail open.pyright[nodejs].The self-review also found that
run_clauderetriedclaude -pat once (JRFC-0006.2). It now waits with exponential backoff and jitter.Verification
make test: 200 passed.make check: corpus lint, pyright 0 errors, import-linter 2 contracts kept, index current.make self-check: OK.make test-plugin: 7 passed.make self-review: 0 findings./verify, through headless Claude Code with the plugin:JRFC-0012.2, with and withouthookd;JRFC-0004.1);listandshowshow "invalid".Not in this change
The self-review gave two advisory findings, JTOOL-0002.6 and JTOOL-0004.2. They are about code that existed before this change and only moved to
findings.py. A separate task is fixing them.Known friction: shall writes the note about dropped org rows each time it loads the config. A hook loads the config on each tool call, so the note repeats.
🤖 Generated with Claude Code