diff --git a/.claude/skills/issue-to-pr/SKILL.md b/.claude/skills/issue-to-pr/SKILL.md index dc8b4db26..3f112189f 100644 --- a/.claude/skills/issue-to-pr/SKILL.md +++ b/.claude/skills/issue-to-pr/SKILL.md @@ -83,8 +83,9 @@ EOF ### 7. Review -Open the PR ready-for-review, then run the global `review-and-ship` skill (global laws 2 and 11). -Taskdeck-specific lenses: `taskdeck-pr-review-loop`. +Open the PR ready-for-review, then apply the global `review-and-ship` skill (global laws 2 and 11) +through merge readiness only. Do not execute its merge action: this skill's output contract is an +open, unmerged PR for human review. Taskdeck-specific lenses: `taskdeck-pr-review-loop`. ### 8. Report back @@ -96,4 +97,4 @@ Provide the PR URL and the handoff summary from `taskdeck-verification-doc-sync` - do not skip tests - if the issue is ambiguous, ask the user before implementing - if the issue is too large for one PR, propose a split and implement the first slice -- always self-review and post findings on the PR before reporting done \ No newline at end of file +- complete the review-only handoff in step 7 before reporting done diff --git a/.claude/skills/pre-merge-gate/SKILL.md b/.claude/skills/pre-merge-gate/SKILL.md index bd70e81d9..983d89ec6 100644 --- a/.claude/skills/pre-merge-gate/SKILL.md +++ b/.claude/skills/pre-merge-gate/SKILL.md @@ -1,6 +1,6 @@ --- name: pre-merge-gate -description: "Final validation gate before merging a PR: tests, lint, type-check, build, self-review, CI green check. Use before merging." +description: "Final validation gate before merging a PR: tests, lint, type-check, build, review evidence, and CI green check. Use before merging." user-invocable: true --- @@ -15,7 +15,7 @@ Run all validation checks before a PR can be merged. Execute as one atomic opera ## Step 1: Identify PR and branch ```bash -gh pr view $ARGUMENTS --json number,headRefName,baseRefName,mergeable,statusCheckRollup +gh pr view $ARGUMENTS --json number,headRefName,baseRefName,headRefOid,baseRefOid,mergeable,statusCheckRollup ``` If mergeable is "CONFLICTING", stop and report — do not auto-resolve. @@ -24,11 +24,16 @@ If mergeable is "CONFLICTING", stop and report — do not auto-resolve. Read ALL comments on the PR: ```bash -gh api repos/{owner}/{repo}/pulls/{number}/comments -gh api repos/{owner}/{repo}/issues/{number}/comments +gh api --paginate repos/{owner}/{repo}/pulls/{number}/comments +gh api --paginate repos/{owner}/{repo}/pulls/{number}/reviews +gh api --paginate repos/{owner}/{repo}/issues/{number}/comments gh pr view $ARGUMENTS --comments ``` +Also query the PR's GraphQL `reviewThreads` connection (or the equivalent GitHub MCP review-thread +read) through its final cursor because REST comment lists do not expose `isResolved` and a partial +connection is not evidence that all threads are settled. + Check for unaddressed findings from any source: - Human review comments not yet resolved - Dependabot alerts or suggestions @@ -36,7 +41,8 @@ Check for unaddressed findings from any source: - CI bot failure messages - Previous adversarial review comments not yet resolved -If actionable comments exist, fix them before proceeding. +If any comment lacks a recorded disposition from the global `review-and-ship` pipeline, report the +PR as blocked and stop. This gate does not create a separate finding-disposition or fix loop. ## Step 3: Run local checks @@ -50,29 +56,39 @@ cd frontend/taskdeck-web && npm run build && npx vitest --run --reporter=verbose Report any failures immediately — do not proceed to merge. -## Step 4: Self-review - -Read the full diff (`gh pr diff $ARGUMENTS`) and check for: - -- Secrets accidentally committed (.env, tokens, keys, connection strings) -- Debug code left in (console.log, Console.WriteLine used for debugging, breakpoints) -- TODO comments without issue references -- Hardcoded values that violate conventions -- Missing tests for behavior changes -- Clean architecture violations (Domain referencing Infrastructure) -- Agent safety violations (GP-06: no approve_proposal or direct board mutation) -- HTTP semantics violations (wrong status codes) -- Unused `using` statements or dead code - -If any issues found, fix them, commit, and push before proceeding. +## Step 4: Refresh external state and confirm exact-head/base declared-review evidence + +Immediately after the local checks, rerun the Step 1 PR query, every Step 2 comment/review/thread +read through its final cursor, and `gh pr checks`. This is the final external-state snapshot used by +the verdict. Compare its `headRefOid` and `baseRefOid` with the initial values. If either OID changed, +if mergeability changed, if a cursor is incomplete, or if the PR changes while the snapshot is being +read, fail closed and return the PR to the canonical pipeline; never combine old review evidence with +new local-check evidence. + +Read the repository's current authority and the canonical pipeline result instead of copying its +tier row here. When that declared gate requires independent review, use the refreshed `headRefOid`, +`baseRefOid`, reviews, review summaries, comments, threads, and checks from this final snapshot. +Require an **arrived independent review of that exact head and base** which posts either findings or +an explicit no-finding result. The evidence artifact must record both reviewed OIDs (or a stable +diff identity derived from both), and the gate must compare them with the current values. GitHub's +review `commit_id` binds only the head; it is not proof of the reviewed base. A review request, +acknowledgement/reaction, evidence authored by the PR author, implementation worker, or coordinator, +or a coordinator metadata scan does not satisfy an independent-review requirement. A distinct, +declared read-only reviewer artifact does satisfy the authorship boundary when it records both exact +OIDs, whether that fresh-context reviewer ran inline or as a reviewer worker. Evidence from an older +head or an older base is stale. + +Confirm that every finding from that review has a recorded disposition and that all review threads +are settled. If exact-head independent-review evidence is missing or unsettled, report the PR as +blocked and return it to the global `review-and-ship` pipeline. This gate confirms the completed +review; it does not perform another review lens or start a separate review/fix cycle. ## Step 5: CI status -```bash -gh pr checks $ARGUMENTS -``` - -All checks must be green. If any are failing, diagnose and fix. +Use the `gh pr checks` result from Step 4's refreshed snapshot. All checks must be terminal and green. +If any are pending or red, report the PR as not ready. Route +red-check diagnosis and any canonical-pipeline-selected fix batch through +`taskdeck-ci-conflict-recovery`; this gate does not choose or execute fixes. ## Step 6: Report @@ -86,7 +102,7 @@ Output a merge-readiness summary: - [ ] Frontend build: PASS/FAIL - [ ] Frontend tests: PASS/FAIL - [ ] CI checks: GREEN/RED -- [ ] Self-review: CLEAN/ISSUES FIXED +- [ ] Declared exact-head/base review evidence: SATISFIED/MISSING (head SHA, base SHA, and evidence URL) - [ ] Bot comments: ADDRESSED/NONE - [ ] Secrets scan: CLEAN @@ -96,6 +112,7 @@ Output a merge-readiness summary: ## Rules - Do NOT merge the PR — only validate and report readiness -- If CI is red, attempt to fix — only report "blocked" if the fix is non-trivial +- If CI is red or review evidence is missing, report not ready and return the PR to the owning + canonical pipeline/recovery lane; do not introduce a local fix threshold - Finding severity, comment triage, and how many review rounds are owed: the global `review-and-ship` skill and global laws 2 and 11. This skill only runs the local checks. diff --git a/.claude/skills/taskdeck-issue-batch-orchestrator/SKILL.md b/.claude/skills/taskdeck-issue-batch-orchestrator/SKILL.md index 4ad82a027..e4dc6cb51 100644 --- a/.claude/skills/taskdeck-issue-batch-orchestrator/SKILL.md +++ b/.claude/skills/taskdeck-issue-batch-orchestrator/SKILL.md @@ -52,12 +52,15 @@ For isolated workers: 3. Require the first command from `docs/WORKTREE_AGENT_PROTOCOL.md` or `powershell -File scripts/worktree_guard.ps1`. 4. Assign explicit file/module ownership. 5. Tell workers they are not alone in the codebase and must not revert others' edits. -6. Require targeted tests and self-review before handoff. +6. Require targeted tests and handoff to the global `review-and-ship` pipeline. 7. Require every file-editing worker prompt to restate the structured patch discipline above. ## Review And CI -Review rounds, severity bar, and comment triage: the global `review-and-ship` skill (laws 2 and 11). Flag these surfaces so the coordinator can decide whether an extra independent lens is warranted: +Review rounds, tier gate, severity bar, and comment triage: the global `review-and-ship` skill +(laws 2 and 11). Satisfy the repository's current declared tier before merge; only lenses beyond +that canonical gate are discretionary. Flag these surfaces when deciding whether an additional +lens is warranted: - auth, sessions, tokens, security, secrets, redaction - migrations, persistence, deletion, import/export diff --git a/.claude/skills/taskdeck-pr-review-loop/SKILL.md b/.claude/skills/taskdeck-pr-review-loop/SKILL.md index 7dcc86360..7de92cf3f 100644 --- a/.claude/skills/taskdeck-pr-review-loop/SKILL.md +++ b/.claude/skills/taskdeck-pr-review-loop/SKILL.md @@ -32,6 +32,18 @@ the entry point. Read only the relevant section of `docs/STATUS.md` (source of t - docs drift in `docs/STATUS.md` / `docs/IMPLEMENTATION_MASTERPLAN.md` - CI, scripts, or project-automation breakage +## Sensitive-Surface Flag + +Flag these surfaces so the coordinator can decide whether an additional independent lens beyond +the tier-required pass is warranted: + +- security/auth/session/token behavior +- migrations or data deletion/retention +- MCP or external-agent write surfaces +- capture/review/proposal execution +- GitHub workflows/project automation +- broad frontend route or state flow + ## Targeted Verification - Backend: `dotnet test backend/Taskdeck.sln -c Release --filter "FullyQualifiedName~RelevantTest"` diff --git a/.claude/skills/taskdeck-worktree-issue-worker/SKILL.md b/.claude/skills/taskdeck-worktree-issue-worker/SKILL.md index b2d405cc5..bab40c78b 100644 --- a/.claude/skills/taskdeck-worktree-issue-worker/SKILL.md +++ b/.claude/skills/taskdeck-worktree-issue-worker/SKILL.md @@ -1,6 +1,6 @@ --- name: taskdeck-worktree-issue-worker -description: Implement one Taskdeck issue in an isolated Claude or git worktree with narrow ownership, tests, PR creation, and self-review. +description: Implement one Taskdeck issue in an isolated Claude or git worktree with narrow ownership, tests, PR creation, and review handoff. --- # Taskdeck Worktree Issue Worker @@ -36,7 +36,8 @@ Own only the files/modules assigned by the coordinator. You are not alone in the 5. Run targeted checks first. 6. Update docs only if current reality, roadmap, testing expectations, or operator workflow changed. 7. Open a PR with summary, linked issue, tests, docs impact, and risks. -8. Perform a self-review and fix findings before handoff. +8. Hand the ready-for-review PR to the global `review-and-ship` pipeline; use + `taskdeck-pr-review-loop` only for Taskdeck-specific lenses. ## Stop Conditions diff --git a/.codex/config.toml b/.codex/config.toml index eca22a8ee..6dd92f5fc 100644 --- a/.codex/config.toml +++ b/.codex/config.toml @@ -16,7 +16,7 @@ max_depth = 2 job_max_runtime_seconds = 8000 [agents.issue_worker] -description = "Implement one Taskdeck issue in an isolated worktree. Use taskdeck-worktree-issue-worker, keep ownership narrow, commit small, test, open a PR, and self-review." +description = "Implement one Taskdeck issue in an isolated worktree. Use taskdeck-worktree-issue-worker, keep ownership narrow, commit small, test, open a PR, and hand it to the canonical review pipeline." nickname_candidates = ["IssueWorker", "WorktreeWorker", "PatchWorker"] [agents.pr_reviewer] diff --git a/.codex/skills/taskdeck-issue-batch-orchestrator/SKILL.md b/.codex/skills/taskdeck-issue-batch-orchestrator/SKILL.md index ceea8d404..7de58483e 100644 --- a/.codex/skills/taskdeck-issue-batch-orchestrator/SKILL.md +++ b/.codex/skills/taskdeck-issue-batch-orchestrator/SKILL.md @@ -86,34 +86,34 @@ Use `taskdeck-worktree-issue-worker` for implementation workers. ## Review loop -Every PR needs: - -1. Worker self-review after opening the PR. -2. Coordinator review of PR body, linked issue, test evidence, and docs impact. -3. Flag these surfaces so the coordinator can decide whether an extra independent lens is warranted (round count and severity bar: the global `review-and-ship` skill): - - auth/authz/security - - migrations/persistence - - capture/review/proposal execution - - CI/workflows/project automation - - broad frontend flow changes - - flaky or failing tests -4. Posted review findings or explicit no-finding comment. -5. Fix commits for findings. -6. Re-review after fixes. - -Use `taskdeck-pr-review-loop` for review workers. +Every PR follows the global `review-and-ship` pipeline and must satisfy the repository's current +declared tier before merge; only lenses beyond that canonical gate are discretionary. + +The coordinator also reviews the PR body, linked issue, test evidence, and docs impact. Flag these +surfaces when deciding whether an additional independent lens is warranted: + +- auth/authz/security +- migrations/persistence +- capture/review/proposal execution +- CI/workflows/project automation +- broad frontend flow changes +- flaky or failing tests + +Use `taskdeck-pr-review-loop` for Taskdeck-specific lenses. Finding disposition, verification after +changes, and convergence remain owned by the global pipeline. ## CI and comments -After PR creation and after every fix push: +Within the global `review-and-ship` pipeline: + +- inspect exact-head CI status plus review and bot comments +- classify every red check by lane and investigate its cause +- for a fix batch selected by the canonical pipeline, address root causes rather than symptoms +- rerun the checks affected by that selected batch when practical +- push only the signed commits that belong to that batch +- post the finding-to-fix mapping and verification evidence -- inspect CI status -- inspect review comments and bot comments -- classify failures by lane -- address root causes, not symptoms -- rerun only the affected checks locally when practical -- push fix commits -- comment with what changed and what was re-run +These are Taskdeck execution mechanics, not another finding-disposition or review/fix cycle. Use `taskdeck-ci-conflict-recovery` for failing CI, comments, or conflicts. diff --git a/.codex/skills/taskdeck-pr-review-loop/SKILL.md b/.codex/skills/taskdeck-pr-review-loop/SKILL.md index 0f66f7541..a39685583 100644 --- a/.codex/skills/taskdeck-pr-review-loop/SKILL.md +++ b/.codex/skills/taskdeck-pr-review-loop/SKILL.md @@ -32,12 +32,12 @@ Do not spend review energy on unrelated style unless it creates risk. ## Sensitive-surface flag -Flag these surfaces in the review so the coordinator can decide whether the change warrants the -extra independent lens its tier allows: +Flag these surfaces so the coordinator can decide whether an additional independent lens beyond +the tier-required pass is warranted: - security/auth/session/token behavior - migrations or data deletion/retention -- MCP or external agent write surfaces +- MCP or external-agent write surfaces - capture/review/proposal execution - GitHub workflows/project automation - broad frontend route or state flow diff --git a/.codex/skills/taskdeck-pr-review-loop/agents/openai.yaml b/.codex/skills/taskdeck-pr-review-loop/agents/openai.yaml index 9bdefef47..8582e7cbe 100644 --- a/.codex/skills/taskdeck-pr-review-loop/agents/openai.yaml +++ b/.codex/skills/taskdeck-pr-review-loop/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Taskdeck PR Review Loop" short_description: "Review PRs and address feedback" - default_prompt: "Use $taskdeck-pr-review-loop to perform adversarial review, post findings, address comments, and re-review Taskdeck PRs." + default_prompt: "Use $taskdeck-pr-review-loop for Taskdeck-specific review lenses while the global review-and-ship skill owns the review pipeline." diff --git a/.codex/skills/taskdeck-worktree-issue-worker/SKILL.md b/.codex/skills/taskdeck-worktree-issue-worker/SKILL.md index 5dda28a86..bd1fc591a 100644 --- a/.codex/skills/taskdeck-worktree-issue-worker/SKILL.md +++ b/.codex/skills/taskdeck-worktree-issue-worker/SKILL.md @@ -81,7 +81,8 @@ PR body must include: - risks/follow-ups - `Closes #` -After opening the PR, run a deliberate self-review using `taskdeck-pr-review-loop`. Fix findings before handing back to the coordinator. +After opening the PR, hand the ready-for-review branch to the global `review-and-ship` pipeline. +Use `taskdeck-pr-review-loop` only for Taskdeck-specific lenses. ## Handoff @@ -92,5 +93,5 @@ Report: - tests added - commands run and results - docs changed -- review findings fixed or explicit no-finding result +- review-pipeline evidence and disposition - any deferred follow-up issue numbers or blocked seeding notes diff --git a/docs/IMPLEMENTATION_MASTERPLAN.md b/docs/IMPLEMENTATION_MASTERPLAN.md index ab7bf1cc7..4307ba471 100644 --- a/docs/IMPLEMENTATION_MASTERPLAN.md +++ b/docs/IMPLEMENTATION_MASTERPLAN.md @@ -15,6 +15,10 @@ Companion Active Docs: - **`#1513` local review-fix implementation:** the registered OpenAI, Gemini, Ollama, and outbound-webhook handlers set `UseProxy = false`, keeping the configured origin as the connect-time validation target. Just before send, protected registrations mask the URI seen by outer .NET HTTP diagnostics; the inner handler restores the real URI for transport and re-masks it for retry/completion. Public caller-owned provider clients keep normal `HttpClient` behavior. The four protected clients remove default request loggers, disable distributed-trace header propagation, and use a private HTTP metric scope; Taskdeck's configured OpenTelemetry provider drops their marked activities and scope. Enabled Sentry removes its outbound factory handler only from these four client pipelines, so unrelated clients retain instrumentation and server-side exception tracking remains active. The proven boundary includes pre-handler `System.Net.Http` EventSource path/query suppression, but excludes independently installed process-global activity/meter listeners and transport-stage host/IP observers. Existing localhost opt-ins and automatic-redirect blocking remain unchanged. No proxy-aware outbound mode exists; corporate proxy-only deployments fail closed. - **Current evidence boundary:** the exact documented filters pass 66/66 API and 158/158 Application tests (151 provider/policy compatibility plus seven constructor/remasking controls); registered EventSource and scoped-Sentry controls pass three fresh-process repetitions. At pre-documentation head `dad8d22a`, the full serialized backend passed 7,539 tests with five intentional skips and no failures, including Architecture 20/20 with one intentional skip and Integration 35/35. The independent security review was clean; the correctness review found only the now-corrected seven-test evidence omission. The merged Dockerless Testcontainers repair is absorbed, and the only later issue-scope change is this verification-document correction; the current-main merge touched only the independently reviewed `#1522` frontend/docs slice. Signed publication, exact hosted Required CI, CodeQL, and merge remain outstanding, so this is not yet a shipped delivery entry. +## Delivery update (2026-07-27, agentic review-doctrine consolidation) + +- **Single review-workflow home (`#1531` merged; remediation `#1532` / PR `#1534`):** Taskdeck's local instructions, skills, overnight manuals, and PR-create hook are reduced to routing, Taskdeck-specific lenses, and repository mechanics while the estate-wide `review-and-ship` skill owns the executable pipeline. PR `#1531` landed before two HIGH and six MEDIUM exact-head review findings were repaired; the bounded remediation restores the issue-to-PR external-state contract, the mandatory T3 independent pass, policy-neutral Fable/pre-merge/worker/hook routing, runtime-mirror risk-lens parity, and current documentation. This supersedes the review/aging portion of `#1269` without rewriting historical delivery records. The live `.codex` mirror is retained until its separately tracked retirement under `#1291`. + ## Delivery update (2026-07-27, test substrate, Windows API diagnostics, and realtime reconciliation) - **Dockerless Testcontainers gate (`#1518`):** the PostgreSQL collection fixture now evaluates `DockerAvailableCheck` before `PostgreSqlBuilder.Build`, restoring the documented graceful-skip behavior on hosts without Docker. Public-constructor and injected-factory regressions prove the unavailable path cannot construct a container, while a timed-out Docker CLI probe is killed as a process tree and boundedly reaped. The local exact tree finishes with 7 passed / 28 skipped / 0 failed and no surviving `docker info`; at reviewed head `6650370b`, the full serialized backend passed 7,465 tests with 33 intentional skips and hosted Container Integration proved the positive lifecycle with 35 passed / 0 skipped / 0 failed. Four DCO-signed-off commits merged as `ff1ee066`; exact-main Required CI `30257236213` and CodeQL `30257235538` are green. diff --git a/docs/ISSUE_EXECUTION_GUIDE.md b/docs/ISSUE_EXECUTION_GUIDE.md index 8106790b6..12556d872 100644 --- a/docs/ISSUE_EXECUTION_GUIDE.md +++ b/docs/ISSUE_EXECUTION_GUIDE.md @@ -469,7 +469,9 @@ Execution note: 4. Run required verification commands. 5. Update docs (`STATUS`/`IMPLEMENTATION_MASTERPLAN`/test docs) if reality changed. 6. Open PR with linked issue and risk notes. -7. Perform a deliberate reviewer-style self-review of the PR diff after opening it; capture findings, fixes, or explicit no-finding conclusion before handoff. +7. Hand the ready PR to the global `review-and-ship` pipeline. Use `taskdeck-pr-review-loop` only + for Taskdeck-specific lenses and thread settlement; record exact-head/base pipeline evidence + and satisfy the declared-tier review gate before any merge handoff. 8. Move project item to `Review`. 9. After merge, move item to `Done` and post final verification summary. diff --git a/docs/REVIVAL_PLAN.md b/docs/REVIVAL_PLAN.md index 516100aed..af80b86e0 100644 --- a/docs/REVIVAL_PLAN.md +++ b/docs/REVIVAL_PLAN.md @@ -114,7 +114,7 @@ Seeded 2026-07-13 from the maintainer's twin-app evaluation (decision: extend th ## 5. What agents need to know (execution contract) - Every REVIVAL issue body is a self-contained agent brief: context, acceptance criteria, entry-point files, traps, and verification commands. Do not start work that lacks a tracked issue. -- Review gate: the global `review-and-ship` skill and global laws 2 and 11 (Taskdeck is T3 — merge on green CI at the head, one comment-triage pass, one independent review pass). The 2026-06 two-tier FULL/LIGHT gate with its aging rule is superseded; #1269 tracks retiring the phrase. Changes touching the capture→proposal→apply loop, auth, or migrations are still the ones to flag for the independent lens. +- Review gate: the repository's current declared tier, global `review-and-ship` skill, and global laws 2 and 11; do not copy the tier row here. The 2026-06 two-tier FULL/LIGHT gate with its aging rule is superseded; #1269 tracks retiring the phrase. Changes touching the capture→proposal→apply loop, auth, or migrations remain Taskdeck-specific lens-selection flags for the canonical pipeline. - **Intake severity bar** (#1269): new issues only for data loss, silent corruption, security exposure real under the deployment model, or dogfooding/beta-user findings. Everything else is fixed in-PR or recorded as dated accepted-risk. - Wave membership is the admission ticket. Review-seeded follow-ups go through the severity bar, not straight into the wave. - Worktree protocol (`docs/WORKTREE_AGENT_PROTOCOL.md`) for parallel work; one coordinator synthesizes. diff --git a/docs/STATUS.md b/docs/STATUS.md index f260c543f..413fdaeb5 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -6,6 +6,9 @@ Proxy-safe direct egress implementation checkpoint (2026-07-27, `#1513`): - **The registered OpenAI, Gemini, Ollama, and outbound-webhook primary clients preserve the validated direct origin without exporting protected path/query data through Taskdeck's configured telemetry.** Each primary handler sets `UseProxy = false`, so ambient/system proxy settings cannot replace the `OutboundWebhookConnectCallback` target. Immediately before `SendAsync`, registered providers and webhook delivery mask the request URI from outer .NET HTTP diagnostics; the protected inner handler restores the configured URI for transport and re-masks it for retry/completion. Public caller-owned provider clients do not opt into this mechanism and retain ordinary `HttpClient` URI/body/auth behavior. The four protected clients remove default `IHttpClientFactory` request loggers, disable distributed-trace header propagation, and use a private HTTP metric scope; Taskdeck's OpenTelemetry configuration drops marked activities and that scope. When Sentry is enabled, its outbound handler is removed only from these protected clients; unrelated clients such as `GitHubConnectorProvider` retain Sentry instrumentation, while server-side exception tracking remains enabled. The proven boundary covers pre-handler `System.Net.Http` EventSource path/query data and Taskdeck's configured exporters, not independently installed process-global activity/meter listeners or transport-stage host/IP observation. Existing localhost opt-ins and automatic-redirect blocking are unchanged. Proxy-aware outbound support does not exist, so corporate proxy-only deployments fail closed. - **The current-main review-fix working tree is local and not yet shipped:** the documented exact filters pass 66/66 API and 158/158 Application tests (151 provider/policy compatibility plus seven constructor/remasking controls) across registered pipelines, proxy canaries, delivery, EventSource, OpenTelemetry, and scoped-Sentry boundaries. The registered EventSource and Sentry positive/negative controls passed three fresh-process repetitions. At pre-documentation head `dad8d22a`, the full serialized backend passed 7,539 tests with five intentional skips and no failures, including Architecture 20/20 with one intentional skip and Integration 35/35. The independent security review was clean; the correctness review found only the now-corrected seven-test evidence omission. The only later issue-scope change is this verification-document correction; the current-main merge touched only the independently reviewed `#1522` frontend/docs slice, so `#1513` source behavior is unchanged. Signed publication, exact hosted CI, and CodeQL remain outstanding. +Agentic review-doctrine consolidation (2026-07-27, `#1531` merged; remediation `#1532` / PR `#1534`): +- **The one-home sweep landed before its exact-head findings were repaired; `#1532` and PR `#1534` carry the bounded remediation.** PR `#1531` moved Taskdeck's executable review workflow toward the estate-wide `review-and-ship` skill, but merged with contradictory issue-to-PR, T3 independent-review, Fable, pre-merge, worker-routing, hook, and runtime-mirror instructions still present. The intended boundary is unchanged: retain the declared T3 row, Taskdeck-specific risk lenses, exact-head verification, and settlement mechanics without parallel severity, round-count, or aging rules. This narrows the review/aging portion of `#1269`; historical delivery records remain intact, and retirement of the still-live `.codex` mirror remains separate work under `#1291`. + Realtime column reconciliation (2026-07-27, `#1522`): - **A successful create-column response can no longer duplicate or overwrite a fresher same-id SignalR update.** Reconciliation now preserves the existing realtime object and its identity when that id is already present, and appends the HTTP response only when the column is absent. The store regression races a newer realtime column against the older POST payload and pins its identity, name, position, WIP limit, card count, and timestamp. The board E2E helper waits for the matching successful POST and the completed form lifecycle before asserting one scoped lane; collision-name mobile coverage selects exact lanes/cards instead of hiding duplicates with `.first()`. Exact local verification passed 13/13 focused store tests, 3,915/3,915 full Vitest tests, 5/5 focused mobile tests on each of Chromium and WebKit, typecheck, build, and lint (zero errors; six pre-existing warnings). diff --git a/docs/WORKTREE_AGENT_PROTOCOL.md b/docs/WORKTREE_AGENT_PROTOCOL.md index da0dfcd6e..610636bb2 100644 --- a/docs/WORKTREE_AGENT_PROTOCOL.md +++ b/docs/WORKTREE_AGENT_PROTOCOL.md @@ -97,7 +97,9 @@ Use AGENTS.md and the relevant .codex skill(s). Own only: . Do not reference or edit the main checkout. Do not revert edits made by others. Keep scope to acceptance criteria. Make small signed-off commits with git commit -s --no-gpg-sign. Run targeted tests first. Open a PR with Closes #NNN and test evidence. -After opening the PR, self-review, post findings or explicit no-finding result, fix findings, and report back. +After opening the ready PR, hand it to the global review-and-ship pipeline. Use +taskdeck-pr-review-loop only for Taskdeck-specific lenses and thread settlement; report the +pipeline evidence and disposition. ``` ## Parallel Runtime Isolation diff --git a/docs/agentic/OVERNIGHT_LOOP.claude.md b/docs/agentic/OVERNIGHT_LOOP.claude.md index e1ee05f3f..d09011870 100644 --- a/docs/agentic/OVERNIGHT_LOOP.claude.md +++ b/docs/agentic/OVERNIGHT_LOOP.claude.md @@ -193,9 +193,13 @@ which is genuinely mechanical, and how the lanes are shaped.** ## 4) REVIEW — run the global pipeline, once **Doctrine has one home: global laws 2 and 11 and the global `review-and-ship` skill.** Round -count, severity bar, comment triage, and when to reopen or park all live there — do not restate -them in this manual. Taskdeck's tier row (T3 per `.agent-harness/tier.json`): push free, merge free on -green CI at the head plus one comment-triage pass and one independent review pass. +count, tier gate, severity bar, comment triage, and when to reopen or park all live there — do not +restate them in this manual. Read Taskdeck's current tier from repository authority and satisfy it +through the canonical pipeline. + +Run `review-and-ship` only through its merge-readiness decision in this section; do **not** +execute its merge action yet. Section 5 owns the actual merge after Taskdeck's complete local +gate also passes. What this manual adds: use **`taskdeck-pr-review-loop`** for the Taskdeck lenses, prefer a **distinct lens** over a duplicate pass when a second reviewer is warranted, and record the @@ -215,15 +219,18 @@ Use **`pre-merge-gate`** + **`verification-closeout`**. Gate: CONTENT**: read unresolved threads AND top-level PR comments AND review-summary bodies posted since the final push; findings land in all three places, not just inline threads. Never gate on reviewer names or review-event presence; a "review" with no findings looks identical to - one carrying P2s until read. Applies to docs-only PRs too. There is no aging requirement — - waiting for bots to weigh in is not a gate. + one carrying P2s until read. Applies to docs-only PRs too. Post-push eligibility and observation + requirements belong to the canonical pipeline; satisfy them without copying a local duration or + polling rule. 4. No unresolved blockers; back-compat preserved; canonical docs synced if reality changed (**`docs-sweep`** / **`taskdeck-verification-doc-sync`**). -Merge in **dependency-safe order** (base-first; never delete a stacked base; pull `main`; after -a wave **verify `main` clean + CI green**). **Strategic direction docs or security/deny-floor -gates that flip project posture are maintainer decisions — stage + defer (Q-N), don't -self-merge.** +After every preceding Taskdeck-local gate holds, resume the canonical `review-and-ship` pipeline +and execute its merge action only when that pipeline and the declared authority permit. That +canonical action must preserve **dependency-safe order** (base-first; never delete a stacked base; +pull `main`; after a wave **verify `main` clean + CI green**). **Strategic direction docs or +security/deny-floor gates that flip project posture are maintainer decisions — stage + defer +(Q-N), don't self-merge.** --- diff --git a/docs/agentic/OVERNIGHT_LOOP.codex.md b/docs/agentic/OVERNIGHT_LOOP.codex.md index 588470d4f..7144993ea 100644 --- a/docs/agentic/OVERNIGHT_LOOP.codex.md +++ b/docs/agentic/OVERNIGHT_LOOP.codex.md @@ -177,16 +177,18 @@ before the hard tasks. ## 4) REVIEW — run the global pipeline, once **Doctrine has one home: global laws 2 and 11 and the global `review-and-ship` skill.** Round -count, severity bar, comment triage, and when to reopen or park all live there — do not restate -them in this manual. Taskdeck's tier row (T3 per `.agent-harness/tier.json`): push free, merge free on -green CI at the head plus one comment-triage pass and one independent review pass. +count, tier gate, severity bar, comment triage, and when to reopen or park all live there — do not +restate them in this manual. Read Taskdeck's current tier from repository authority and satisfy it +through the canonical pipeline. + +Run `review-and-ship` only through its merge-readiness decision in this section; do **not** +execute its merge action yet. Section 5 owns the actual merge after Taskdeck's complete local +gate also passes. What this manual adds: - Use `taskdeck-pr-review-loop` for the Taskdeck lenses; prefer a **distinct lens** over a duplicate pass when a second reviewer is warranted. -- Request the `@codex` review on the exact head at ready-for-review and once more after the - final fix round; batch fixes rather than chasing round-by-round. - Record each finding and its resolution in the findings ledger. --- @@ -200,15 +202,18 @@ What this manual adds: without proof (rerun; if it passes on identical code it's flaky → **track it as an issue and move on**, don't silently ignore). Because CI Extended (`ci-nightly.yml`) has had systemic `startup_failure` modes before, confirm the failure is understood, not just "red". -3. The review round owed by law 2 has run; every human + bot thread triaged once. There is no - aging requirement — waiting for bots to weigh in is not a gate. +3. The review round owed by law 2 has run; every human + bot thread triaged once. Post-push + eligibility and observation requirements belong to the canonical pipeline; satisfy them without + copying a local duration or polling rule. 4. No unresolved blockers; backward compatibility preserved; canonical docs synced if reality changed (`STATUS.md` for current state, `MASTERPLAN` for delivery history — via docs gate). -Then merge in **dependency-safe order** (base-first in a stack; never delete a stacked base; -pull `main`; after a wave, **verify `main` is clean and its CI green**). If merging strategic -direction docs or a security gate that flips project posture, that's a **maintainer decision** -— stage it and defer (Q-N), don't self-merge. +After every preceding Taskdeck-local gate holds, resume the canonical `review-and-ship` pipeline +and execute its merge action only when that pipeline and the declared authority permit. That +canonical action must preserve **dependency-safe order** (base-first in a stack; never delete a +stacked base; pull `main`; after a wave, **verify `main` is clean and its CI green**). If merging +strategic direction docs or a security gate that flips project posture, that's a **maintainer +decision** — stage it and defer (Q-N), don't self-merge. --- diff --git a/docs/agentic/OVERNIGHT_LOOP.fable.md b/docs/agentic/OVERNIGHT_LOOP.fable.md index 2d21b4fdf..fe7b3a398 100644 --- a/docs/agentic/OVERNIGHT_LOOP.fable.md +++ b/docs/agentic/OVERNIGHT_LOOP.fable.md @@ -87,7 +87,8 @@ and take the actual model and effort for each rung from the skill. - Wave planning and task selection; architecture and ADR drafting; security-posture judgment; EF migration-snapshot merges; race/concurrency analysis; genuinely ambiguous multi-file debugging **after** a cheaper agent has gathered the evidence and failed to crack it. -- Adjudicating review findings: every CRITICAL/HIGH, and any conflict between reviewers. +- Adjudicating review findings under the global `review-and-ship` pipeline, including conflicts + between reviewer lenses. - **Final synthesis, the verification verdict, and every merge decision.** These are never delegated — branch protection is lenient, so you are the only real gate (base §5). - Keep your turns lean: don't bulk-read what a subagent can summarize; don't sit through long @@ -167,11 +168,11 @@ applies — the gate is never thinned to save tokens (see STOP CONDITIONS for ho your finalized text. Required orientation and gate reads are never delegated to save tokens: the coordinator still reads the source-of-truth docs (base §1 — STATUS, OUTSTANDING_TASKS, the handoff) and every gate input itself. -- **Gate-marshals per lane (implementation rung):** one worker owns a PR's whole - fix→verify→settle cycle end-to-end — "verify" meaning the worker's TARGETED runs; full-suite - verdicts stay with the ops lane + coordinator per BUDGET & CADENCE — continued via - `SendMessage` round after round, never respawned per round, so context (the PR's history, - reviewers' phrasing, prior verdicts) is paid for once. Thread settlement (reply + `resolveReviewThread` + report +- **Gate-marshals per lane (implementation rung):** one worker owns a PR's targeted verification + and settlement mechanics throughout the global `review-and-ship` pipeline; full-suite verdicts + stay with the ops lane + coordinator per BUDGET & CADENCE. Continue with the same worker via + `SendMessage` so context (the PR's history, reviewers' phrasing, prior verdicts) is paid for + once. Thread settlement (reply + `resolveReviewThread` + report `unresolved == 0`) is owned by exactly ONE lane per PR — default the gate-marshal; the coordinator may reassign a PR's settlement to the ops agent in that packet explicitly (e.g. the marshal is retired), but never lets both act on the same PR's threads. (Honest @@ -215,26 +216,27 @@ applies — the gate is never thinned to save tokens (see STOP CONDITIONS for ho ## PER-PR GATE SEQUENCE (proven across 20+ merges; run it every time) -worker round → 2 read-only reviewers (distinct lenses) → coordinator adjudication → ONE -batched fix push to the same worker → full backend suite on the EXACT head (coordinator owns -the verdict; delegate the run to a subagent that executes it in its OWN foreground turn, or -run it inline — never as background Bash; serialize so only ONE full suite runs box-wide at a -time) → CI green on that head → -30–60 min bot window from the FINAL push → **feedback check by CONTENT** (unresolved review -threads AND top-level PR comments AND review-summary bodies posted since the final push) → -merge → pull `main` → prune worktree+branch (cd out of a worktree before removing it). +worker delivers a ready-for-review PR → run the global `review-and-ship` pipeline **through its +merge-readiness decision only; do not execute its merge action yet** → full backend suite on the +EXACT head (coordinator owns the verdict; delegate the run to a subagent that executes it in its +OWN foreground turn, or run it inline — never as background Bash; serialize so only ONE full suite +runs box-wide at a time) → CI green on that head → **feedback check by CONTENT** (unresolved +review threads AND top-level PR comments AND review-summary bodies posted since the final push) → +after every preceding Taskdeck-local gate holds, execute the canonical merge action when the +pipeline and declared authority permit → pull `main` → prune worktree+branch (cd out of a +worktree before removing it). Reviewer count, finding disposition, fix/verification convergence, +and any waiting requirement belong only to the canonical pipeline; do not add local values here. - **Feedback check by content, never by reviewer names**: query `reviewThreads` (count `isResolved == false` and READ the bodies), AND sweep top-level PR comments and review-summary bodies since the final push — bots put findings in all three places, and a - "review" entry with no findings looks identical to one with two P2s until you read it. This applies to docs-only PRs too (a docs sweep has been merged + "review" entry with no findings looks identical to one carrying findings until you read it. This applies to docs-only PRs too (a docs sweep has been merged over two valid unresolved P2s before; the fix cost a follow-up PR). -- **Review-loop discipline**: batch fixes into ONE push per round; every worker — or the PR's - designated settlement lane, when FRUGALITY MODE has reassigned it — replies AND - resolves threads via GraphQL `resolveReviewThread` and reports `unresolved == 0`; new bot - findings on a final head are reported to the coordinator, never cycled unilaterally. When - bot rounds keep finding new interleavings in one seam, issue ONE structural redesign - directive with a hard timebox ("further findings → report and hand off"). +- **Review execution**: the global `review-and-ship` skill owns review/fix decisions and + convergence. Every worker — or the PR's designated settlement lane, when FRUGALITY MODE has + reassigned it — replies AND resolves threads via GraphQL `resolveReviewThread` and reports + `unresolved == 0`; new bot findings on a final head are reported to the coordinator for + canonical triage, never cycled unilaterally. - **Merge order**: when a wide (many-file / frontend-touching) PR and narrow PRs approach the gate together, land the wide one first. - **Generated files**: `docs/agentic/FAILURE_LEDGER.md` is rendered from `failure_ledger.jsonl` diff --git a/docs/ops/TASKDECK_HUMAN_OPERATIONS.md b/docs/ops/TASKDECK_HUMAN_OPERATIONS.md index c57bfc0b1..3cb25fabb 100644 --- a/docs/ops/TASKDECK_HUMAN_OPERATIONS.md +++ b/docs/ops/TASKDECK_HUMAN_OPERATIONS.md @@ -35,7 +35,9 @@ Codex cannot reliably configure GitHub repository settings unless you explicitly Do in GitHub UI: - Protect `main`: - - require PR reviews (even 1 self-review is fine) + - align review protection with the repository's declared tier and canonical `review-and-ship` + gate; author self-review is not independent-review evidence, but do not impose an + approval-only rule when the declared gate accepts an arrived independent comment review - require status checks to pass: - docs-governance - backend-architecture diff --git a/docs/tooling/CODEX_AUTONOMY_RUNBOOK.md b/docs/tooling/CODEX_AUTONOMY_RUNBOOK.md index 9b35da9fd..12ac82933 100644 --- a/docs/tooling/CODEX_AUTONOMY_RUNBOOK.md +++ b/docs/tooling/CODEX_AUTONOMY_RUNBOOK.md @@ -1,12 +1,12 @@ # Codex Autonomy Runbook -Last Updated: 2026-07-26 +Last Updated: 2026-07-27 Scope: How Codex should execute high-autonomy Taskdeck work such as "take care of as many issues as possible", "check the PRs", "spin fresh adversarial reviewers", "fix failing CI", or "reconcile docs after a batch". ## Core Rule -Codex may automate coordination, worktree setup, implementation, testing, PR creation, review, CI recovery, and docs reconciliation. It must not silently defer work, silently skip tests, merge PRs, change repo settings/secrets/protections, or bypass Taskdeck's review-first automation safety. +Codex may automate coordination, worktree setup, implementation, testing, PR creation, review, CI recovery, docs reconciliation, and merges permitted by the repository's declared authority and the canonical `review-and-ship` gate. It must not silently defer work, silently skip tests, change repo settings/secrets/protections, or bypass Taskdeck's review-first automation safety. An explicit user stop-before-merge boundary remains binding. Spawned subagents are optional execution machinery, not a default assumption. Use them without asking for extra permission when they are efficient or effective for safely parallelizable work with clear ownership and a coordinator-owned synthesis path. When subagents are unavailable or do not fit the work, use normal local execution, explicit git worktrees, or separate agent sessions as appropriate and state what actually happened. @@ -16,7 +16,8 @@ Use these skills: - Many issues / batch execution: `taskdeck-issue-batch-orchestrator` - One issue in an isolated branch/worktree: `taskdeck-worktree-issue-worker` -- PR self-review or fresh adversarial review: `taskdeck-pr-review-loop` +- Canonical PR disposition and convergence: global `review-and-ship`; Taskdeck review lenses and + thread settlement: `taskdeck-pr-review-loop` - Failing CI, comments, conflicts, stale branches: `taskdeck-ci-conflict-recovery` - Backend implementation: `taskdeck-backend-slice` - Frontend implementation: `taskdeck-frontend-workspace-slice` @@ -100,14 +101,18 @@ Do not revert edits made by others. Keep scope to the issue acceptance criteria. Make small present-tense signed-off commits with git commit -s --no-gpg-sign. Do not use --no-verify. Add tests for behavior changes. Run targeted checks first. Open a PR with Closes #NNN, test evidence, docs impact, and risks. -After opening the PR, perform a self-review, post findings or explicit no-finding result, fix findings, and report back. +After opening the ready PR, hand it to the global review-and-ship pipeline. Use taskdeck-pr-review-loop +only for Taskdeck-specific lenses and thread settlement; report the pipeline evidence and disposition. ``` ## PR Review Loop -Every PR needs a self-review. Sensitive PRs need a fresh adversarial review. +Every ready PR goes through the global `review-and-ship` pipeline. The repository's declared tier +determines whether an arrived independent review at the exact head and base is required; an author +self-review, review request, or reviewer reaction is not a substitute for that evidence. -Sensitive means: +The following surfaces are risk flags for choosing a distinct Taskdeck-specific lens. They do not +replace or narrow the canonical pipeline's tier-derived review requirement: - auth, session, token, or cross-user policy - security, SSRF, secret handling, logging redaction @@ -118,7 +123,8 @@ Sensitive means: - broad route/store/frontend shell behavior - flaky or failing CI -Reviewers should post findings as PR comments or a summary comment. A no-finding review must still mention residual risk and test gaps. +Reviewers post findings or an explicit no-finding result as PR evidence. The coordinator routes +every finding through the canonical pipeline's dispositions and owns the final synthesis. ## CI, Comments, And Conflicts @@ -128,14 +134,16 @@ Use: powershell -File scripts/github/Inspect-TaskdeckPrs.ps1 ``` -For each PR: +For each PR, within the canonical `review-and-ship` pipeline: -1. Check CI state and failing logs. -2. Check normal comments, review threads, bot comments, annotations, and artifacts. -3. Reproduce the narrow failure locally where practical. -4. Fix root cause with focused commits. -5. Push and monitor updated CI. -6. Comment with the fix and verification. +1. Read normal comments, review threads, bot comments, review summaries, annotations, and artifacts + against the exact head and base. +2. Check CI state and investigate every failing log; reproduce the narrow failure locally where + practical. +3. Implement only the fix batch selected by the canonical pipeline, using focused signed commits. +4. Push and monitor updated CI at the new exact head. +5. Reply to and resolve every settled thread, then post a finding-to-disposition mapping with fix + commits, verification, or tracked/declined evidence as applicable. For conflicts, prefer merge over rebase when reconciliation stalls. Replace `BRANCH_NAME` with the source ref in `git merge --signoff --no-gpg-sign BRANCH_NAME`. If it conflicts, preserve both branches' intended behavior, stage the resolution, finish with `git commit -s --no-gpg-sign --no-edit` instead of `git merge --continue`, and re-run tests for both touched areas. @@ -227,7 +235,8 @@ Check all open PRs. Address review comments, bot comments, conflicts, and failin ``` ```text -Spin fresh adversarial reviewers on the security-sensitive PRs and have them comment findings, then fix what they find. +Spin fresh adversarial reviewers on the security-sensitive PRs, have them comment findings, route +every finding through the global review-and-ship dispositions, and post settlement evidence. ``` ```text diff --git a/scripts/agent_hooks/post_tool_use.py b/scripts/agent_hooks/post_tool_use.py index 5c39b98c5..22a35b067 100644 --- a/scripts/agent_hooks/post_tool_use.py +++ b/scripts/agent_hooks/post_tool_use.py @@ -40,10 +40,7 @@ def main() -> int: if tool_name == "Bash": command = " ".join(str(tool_input.get("command", "")).split()) if PR_CREATE_RE.search(command): - emit_context( - "PR created. Run the review pipeline now: the global review-and-ship skill " - "(one review round, fix merge-blocking findings, track the rest)." - ) + emit_context("PR created. Run the global review-and-ship skill now.") return 0 diff --git a/scripts/agent_hooks/smoke_test.py b/scripts/agent_hooks/smoke_test.py index a3d15711c..bb73104d0 100644 --- a/scripts/agent_hooks/smoke_test.py +++ b/scripts/agent_hooks/smoke_test.py @@ -102,6 +102,21 @@ def expect_json_context(result: subprocess.CompletedProcess[str], label: str, ev raise AssertionError(f"{label} missing context {needle!r}: {output}") +def expect_json_context_exact( + result: subprocess.CompletedProcess[str], label: str, event_name: str, expected_context: str +) -> None: + expect_ok(result, label) + data = json.loads(result.stdout) + expected = { + "hookSpecificOutput": { + "hookEventName": event_name, + "additionalContext": expected_context, + } + } + if data != expected: + raise AssertionError(f"{label} payload drifted: expected={expected!r}, got={data!r}") + + def expect_pretool_deny(command: str, handler: dict[str, Any] | None = None) -> None: payload = {"hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": {"command": command}} result = run_handler(handler, payload) if handler else run_python("scripts/agent_hooks/pre_tool_use.py", payload) @@ -131,6 +146,41 @@ def expect_text_order(path: str, before: str, after: str, label: str) -> None: raise AssertionError(f"{label} must render the failure ledger before testing synchronization") +def test_review_gate_contracts() -> None: + pre_merge = (ROOT / ".claude" / "skills" / "pre-merge-gate" / "SKILL.md").read_text(encoding="utf-8") + step_3 = pre_merge.find("## Step 3: Run local checks") + refresh = pre_merge.find("## Step 4: Refresh external state") + report = pre_merge.find("## Step 6: Report") + if not 0 <= step_3 < refresh < report: + raise AssertionError("pre-merge gate must refresh external state after local checks and before its verdict") + + required_pre_merge_contracts = [ + "rerun the Step 1 PR query, every Step 2 comment/review/thread", + "If either OID changed", + "distinct,\ndeclared read-only reviewer artifact", + "PR author, implementation worker, or coordinator", + "Use the `gh pr checks` result from Step 4's refreshed snapshot", + ] + for contract in required_pre_merge_contracts: + if contract not in pre_merge: + raise AssertionError(f"pre-merge gate lost required contract: {contract!r}") + if "worker-authored review" in pre_merge: + raise AssertionError("pre-merge gate must not reject a distinct read-only reviewer solely for being a worker") + + for path in [ + "docs/agentic/OVERNIGHT_LOOP.claude.md", + "docs/agentic/OVERNIGHT_LOOP.codex.md", + ]: + manual = (ROOT / path).read_text(encoding="utf-8") + normalized_manual = " ".join(manual.split()) + if "resume the canonical `review-and-ship` pipeline" not in manual: + raise AssertionError(f"{path} must re-enter the canonical pipeline for the merge action") + if "Post-push eligibility and observation requirements belong to the canonical pipeline" not in normalized_manual: + raise AssertionError(f"{path} must delegate post-push eligibility to the canonical pipeline") + if "There is no aging requirement" in manual: + raise AssertionError(f"{path} must not waive the canonical post-push eligibility floor") + + def test_failure_ledger_command_order() -> None: local_workflows = [ ( @@ -404,11 +454,11 @@ def test_configured_commands(settings: dict[str, object]) -> None: ) pr_reminder = hooks["PostToolUse"][1]["hooks"][0] # type: ignore[index] - expect_json_context( + expect_json_context_exact( run_handler(pr_reminder, {"hook_event_name": "PostToolUse", "tool_name": "Bash", "tool_input": {"command": "gh pr create --fill"}}), "pr reminder", "PostToolUse", - "review-and-ship", + "PR created. Run the global review-and-ship skill now.", ) session_start = hooks["SessionStart"][0]["hooks"][0] # type: ignore[index] @@ -471,6 +521,7 @@ def test_pre_commit_hook(settings: dict[str, object]) -> None: def main() -> int: settings = load_settings() + test_review_gate_contracts() test_failure_ledger_command_order() test_configured_python_launchers(settings) test_pre_tool_use(settings)