v6.7 Tranche 1: kanban_complete verification gates (#28, #62, #64) - #11
Merged
Conversation
Adds three pre-write-txn gates that fire before complete_task transitions a task to done. Mirrors the existing _verify_created_cards / HallucinatedCardsError pattern: any violation is recorded as an audit event and raised, so worker state is unchanged and the worker can retry after fixing the underlying issue. Closes hermes-jarvis#28 (repo hygiene gate) Closes hermes-jarvis#62 (workspace-diff verification) Closes hermes-jarvis#64 (per-role runtime floor) Context: hermes-jarvis#61 (bootstrap-paradox case study) ## The three gates 1. verify_runtime_floor — per-role floor on completed_at - started_at. build roles 5min, review roles 90s, orchestration roles 0. Catches Tony's 20-second "approve" verdicts and Friday's 59-second "implemented 7 dispatcher gates" claims. 2. verify_workspace_diff — when a non-review worker on a dir/worktree workspace claims to have produced code, git diff against the tracking base must show actual changes. Catches Friday's "Wave A gates implemented" with an empty diff on the branch. 3. verify_no_stray_artifacts — rejects untracked or tracked artifacts matching patterns the swarm has historically committed by accident: *evidence*, commit-hash*, triage/*, tmp-*, and tracked files with no extension and no shebang (the "all prior block evidence files" failure mode from agent-dashboard PR #1). ## Opt-outs Workers may bypass individual gates via per-call metadata keys: x_fast_justified → allow_below_floor x_no_code → allow_no_code x_stray_ok → allow_stray Opt-outs are recorded as part of the completed event for audit. ## Tests 28 new tests cover the exact 2026-06-09 failure modes (Tony 20s, Friday 59s + empty diff, PR-1 "all prior block evidence files") plus clean-path passes and opt-outs. 258 passed / 0 failed in the wider kanban+complete+task test suite — zero regressions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Jun 9, 2026
…, dead-code removal Independent review of PR #11 surfaced two P0s and several P1s that would have actively recreated the v6.7 failure mode the gates exist to prevent. This commit addresses every finding. Findings + fixes: ## P0 — Opt-outs were free keyword bypasses `bool(metadata.get("x_fast_justified"))` accepted `True`, `"x"`, `"ok"` — all truthy under bool(). A worker that learned the metadata key could pass `{"x_fast_justified": true}` and bypass every gate. The docstring also lied: it claimed "opt-outs are recorded as part of the completed event for audit" but nothing in `complete_task` copied the opt-out keys to any event. Fix: new `_validate_opt_out` requires the value be a STRING of at least 20 non-whitespace characters and raises `InvalidOptOutError` on anything else. Accepted opt-outs are emitted as a `completion_opt_out_used` event with verbatim reasons. ## P0 — Hygiene gate false-positived on legitimate tracked files `verify_no_stray_artifacts` flagged `LICENSE`, `Dockerfile`, `Makefile`, `Vagrantfile`, `README` because the no-extension rule was applied universally. The `evidence` regex also matched legitimate filenames like `optional-skills/security/oss-forensics/references/ evidence-types.md` and `scripts/evidence-store.py`. Verified by running the gate against the hermes-agent repo itself: 15 stray paths, all legitimate. Fix: - Tightened patterns: `evidence/` must be a directory segment; `*-evidence.<ext>` only matches with explicit artifact extensions (.json/.png/.log/.txt/.md/.yaml/.yml); `triage/` matches as a segment. - No-extension+no-shebang rule now applies to UNTRACKED files only. Specific patterns (commit-hash.txt, triage/, tmp-*) still match tracked files too — a worker who actually committed those is just as wrong. - Allowlist for well-known no-extension basenames (LICENSE, Dockerfile, Makefile, ...) as defense in depth. ## P1 — Workspace-diff was bypassable by avoiding trigger verbs `_summary_claims_implementation` only triggered on a fixed verb list. A worker who wrote "Per spec, the changes land in hermes_cli and tests pass" had no trigger verb and bypassed the gate even with an empty branch. Fix: build-role + dir/worktree workspace ALWAYS requires a non-empty diff. Workers who honestly produced no code should call kanban_block with a reason, or opt out via x_no_code with a string justification ≥20 chars. Dead `_summary_claims_implementation` and `_IMPLEMENTATION_CLAIM_PATTERNS` removed. ## P1 — Other production callers didn't catch the new errors `complete_task` is also called from `hermes_cli/kanban.py:_cmd_complete` (CLI) and `plugins/kanban/dashboard/plugin_api.py` (PATCH endpoints ×2). Without explicit catches, the new exceptions would have been stack traces — to stderr in the CLI, to a 500 in the dashboard. Fix: CLI prints the error and continues per task; dashboard endpoints translate to HTTP 409 (single PATCH) or per-entry error (bulk). Block-task callers updated for `FabricatedAuthClaimError` too. ## P1 — Pure-function tests missed integration regressions Added `TestOptOutAudit` (5 tests) and `TestCompleteTaskIntegration` (2 tests) that exercise the full `complete_task` → gate → event → state-unchanged path. A wiring regression in `_v6_7_run_completion_gates` would now fail in CI. ## Test results 40 passed in tests/cli/test_kanban_completion_gates.py — up from 28 in the original PR #11 (12 new + 1 replacing the verb-trigger test). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ce-diff gate Empty/None summary on a build role with no diff previously crashed `splitlines()[0]` before `verify_workspace_diff` could surface its violation. The crash bubbled past the gate, skipped the `completion_blocked_v6_7_gates` audit event, and surfaced as a 500 in the dashboard. Fix: guard the excerpt construction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Jun 10, 2026
jarvis-stark-ops
pushed a commit
that referenced
this pull request
Jun 10, 2026
…1/N6 fixes A second-pass independent review of the reviewer-fields PR found three new findings that this commit addresses: ## N1 — Empty body crashed splitlines()[0] Same shape as the workspace-diff crash bug fixed on PR #11. When `body` was empty or None, `verify_reviewer_fields` raised IndexError before constructing the violation. Real tasks with empty body columns hit this. Fix: guard splitlines result. ## N2 — Inline prose ≥20 chars bypassed adversarial_pass gates `adversarial_pass.env_vars: see above explanation about general env safety` (51 chars of prose, zero structure) passed the gate because the substantive check was character count. Same laundering shape as the prose-evidence bypass we fixed in the previous self-review. Fix: introduce `_has_adversarial_structure` requiring at least one of: bullet item line, UPPER_SNAKE env-var token followed by colon, path-like substring with a slash (e.g. `lib/ingest.ts`), or a source file extension (.ts, .py, .yaml, etc.). Honest empty markers ([], none, n/a) still accepted. Pure prose now correctly rejected. ## N6 — `evidence: none` bypassed citation discipline on code reviews When the body indicated code-touching review (`app/api/...`, `route.ts`, etc.), the previous gate accepted `evidence: none` as an honest-empty declaration. But for a code review, "no test evidence" is exactly the problem — Tony's job is to verify tests cover the deliverable. Fix: `_field_present` now takes `code_change_context` and disallows the honest-empty escape on `test_quality.evidence` when the body triggers adversarial requirements. Non-code reviews (docs, design) still accept `evidence: none`. ## Tests 7 new tests in `TestReviewerFieldsSelfReviewFixes`: - empty body doesn't crash - None body doesn't crash - adversarial inline prose bypass rejected (the N2 exploit) - structured inline values (ENV: bound, file.ts, path/like) pass - evidence:none blocked when body triggers adversarial - evidence:none allowed for pure docs review - bullet list under adversarial fields is the canonical happy path 64 passed in tests/cli/test_kanban_completion_gates.py — up from 57. 87 passed across PR #12 + adjacent regression set; zero failures. Co-Authored-By: Claude Opus 4.7 (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
Adds three pre-write-txn gates in
complete_taskthat catch the failure modes the 2026-06-09 v6.7 build chain demonstrated. See hermes-jarvis#61 for the full case study — 9 tasks reported done in ~10 minutes with zero real deliverables.Pattern mirrors the existing
_verify_created_cards/HallucinatedCardsErrorflow athermes_cli/kanban_db.py:3607. State unchanged on rejection; worker can retry after fixing the issue.Gates
verify_runtime_floor(closes hermes-jarvis#64) — per-role floor oncompleted_at - started_at. build 5min, review 90s, orchestration 0. Catches Tony's 20s "approve" verdicts and Friday's 59s "implementation".verify_workspace_diff(closes hermes-jarvis#62) — non-review workers ondir/worktreeworkspaces that claim implementation must produce a non-emptygit diffagainst the tracking base. Catches Friday's empty branch + fabricated summary.verify_no_stray_artifacts(closes hermes-jarvis#28) — rejects*evidence*,commit-hash*,triage/*,tmp-*, no-extension/no-shebang files. Catches the agent-dashboard PR schema: express conditional-required constraints for grok-style tool callers #1 "all prior block evidence files" mode.Opt-outs
metadata.x_fast_justified→ bypasses runtime floormetadata.x_no_code→ bypasses workspace-diffmetadata.x_stray_ok→ bypasses hygiene gateOpt-outs recorded on the completed event for audit.
Test plan
tests/cli/test_kanban_completion_gates.py— each pin the exact 2026-06-09 failure modes plus clean-path passes and opt-outspytest tests/cli/ tests/tools/ -k 'kanban or complete or task'→ 258 passed / 0 failedkanban_completeWhy this PR alone (Tranche 1)
v6.7 has 11 total issues. This addresses the three that would have rejected 2026-06-09's chain on first attempt. Tranche 2: NousResearch#29/NousResearch#30/NousResearch#31 (verdict-field validation + auto-spawn integrative review + reviewer SOULs in hermes-jarvis). Tranche 3: NousResearch#32/NousResearch#33/NousResearch#34/NousResearch#63/NousResearch#65.
🤖 Generated with Claude Code