+**Hook architecture**: Consolidated dispatchers (2 processes per Bash tool call: `pre-bash.sh` + `post-bash.sh`). All hooks are jq-free — use `parse_json_field`, `json_build`, and `python3` for JSON parsing. Hook optimization: `tool_logging` and `tool_use_guard` removed from per-call dispatchers; `validation_gate` removed from Edit/Write dispatchers (kept in pre-bash.sh); early-exit guards skip narrow hooks when command keywords don't match. Review workflow timing fix: hash capture occurs after auto-fix passes to prevent drift. On review gate mismatch, diagnostic dump writes to `$ARTIFACTS_DIR/mismatch-diagnostics-<timestamp>.log`; breadcrumb trail in `$ARTIFACTS_DIR/commit-breadcrumbs.log`. See `plugins/dso/hooks/dispatchers/` and `plugins/dso/hooks/lib/`. **Review gate (two-layer defense-in-depth)**: Layer 1 — `pre-commit-review-gate.sh` is a git pre-commit hook (registered in `.pre-commit-config.yaml`); uses `git diff --cached --name-only` for reliable staged-file detection (no command-string parsing); default-deny allowlist from `review-gate-allowlist.conf`; checks review-status file + diff hash; writes JSONL telemetry to `$ARTIFACTS_DIR/review-gate-telemetry.jsonl`; formatting-only hash mismatches self-heal by re-running `ruff format`. Layer 2 — `review-gate.sh` is a PreToolUse hook (thin wrapper around `review-gate-bypass-sentinel.sh`); blocks bypass vectors: `--no-verify`, `-n` on git commit, `core.hooksPath=` override, `git commit-tree`, direct `.git/hooks/` writes, direct writes/deletions to `test-gate-status` and `test-exemptions` (only `record-test-status.sh` and `record-test-exemption.sh` are authorized writers). Test suite: `bash tests/hooks/test-two-layer-review-gate.sh` (or via `bash tests/run-all.sh`). **test gate (two-layer defense-in-depth)**: Layer 1 — `pre-commit-test-gate.sh` is a git pre-commit hook (registered in `.pre-commit-config.yaml`); for each staged source file with an associated test (found via fuzzy matching or `.test-index`), verifies that `test-gate-status` in `$ARTIFACTS_DIR` is present, has `passed` on line 1, and has a matching `diff_hash`; files with no associated test are exempt. Test directories are configurable via `test_gate.test_dirs` in `.claude/dso-config.conf` (default: `tests/`). `.test-index` — a repo-root file for mapping source files to unconventionally-named tests; format: `source/path.ext: test/path1.ext, test/path2.ext` (one entry per line; `#` comments and blank lines ignored); associations from `.test-index` are unioned with fuzzy-match results; the hook self-heals by pruning stale entries (test paths that no longer exist on disk) atomically before each commit and auto-staging the result; `.test-index` is excluded from the diff hash (via `review-gate-allowlist.conf`) to prevent mismatch loops when pruning modifies it. **RED marker format**: `source/path.ext: test/path.ext [first_red_test_name]` — the optional `[marker]` after a test path marks the boundary between GREEN tests (already passing) and RED tests (not yet implemented); failures at or after `first_red_test_name` are tolerated (non-blocking), failures before it still block. RED tests must be placed at the end of the test file. **TDD workflow for agents**: When writing a TDD test for a not-yet-implemented feature, add the test at the end of the test file and add a `[test_name]` marker to the `.test-index` entry — e.g., `source/foo.sh: tests/test_foo.sh [test_new_feature]`. After implementation passes, remove the `[marker]` from `.test-index`. **Epic closure enforcement**: `tk close <epic-id>` is blocked while any `[marker]` entries remain in `.test-index` — remove all RED markers before closing an epic. Layer 2 — `review-gate-bypass-sentinel.sh` blocks direct writes/deletions to `test-gate-status` and `test-exemptions`; only `record-test-status.sh` (authorized by COMMIT-WORKFLOW.md Step 3.5) and `record-test-exemption.sh` (for inherently slow tests, exit 124) may write these files.
0 commit comments