harness-everything 0.2.2 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +27 -0
- package/.claude-plugin/plugin.json +51 -0
- package/.gitattributes +1 -0
- package/.github/workflows/behavioral-evals.yml +36 -0
- package/.github/workflows/ci.yml +117 -0
- package/.github/workflows/release.yml +45 -0
- package/.husky/commit-msg +1 -0
- package/.waza.yaml +22 -0
- package/AGENTS.md +60 -2
- package/BENCHMARK_SOP.md +62 -62
- package/CHANGELOG.md +297 -114
- package/CODE_OF_CONDUCT.md +24 -0
- package/CONTRIBUTING.md +47 -0
- package/Dockerfile +18 -18
- package/LICENSE +201 -201
- package/README.md +279 -197
- package/SECURITY.md +33 -0
- package/VERIFICATION.md +394 -347
- package/ab-test-deep-analysis-2026-08-27.md +383 -0
- package/ab-test-results-2026-08-27.md +152 -0
- package/ab-test-statistical-analysis-31cases.md +193 -0
- package/behavioral-evals/README.md +85 -0
- package/behavioral-evals/analyze-plugin-results.js +110 -0
- package/behavioral-evals/cases/baseline-add-feature.yaml +34 -0
- package/behavioral-evals/cases/baseline-api-design.yaml +32 -0
- package/behavioral-evals/cases/baseline-debugging.yaml +31 -0
- package/behavioral-evals/cases/baseline-dependency.yaml +24 -0
- package/behavioral-evals/cases/baseline-documentation.yaml +34 -0
- package/behavioral-evals/cases/baseline-error-handling.yaml +31 -0
- package/behavioral-evals/cases/baseline-git-commit.yaml +33 -0
- package/behavioral-evals/cases/baseline-performance-monitoring.yaml +28 -0
- package/behavioral-evals/cases/baseline-performance.yaml +34 -0
- package/behavioral-evals/cases/baseline-refactor-with-tests.yaml +35 -0
- package/behavioral-evals/cases/baseline-refactor.yaml +27 -0
- package/behavioral-evals/cases/baseline-security-review.yaml +28 -0
- package/behavioral-evals/cases/baseline-simple-bugfix.yaml +33 -0
- package/behavioral-evals/cases/baseline-tdd-workflow.yaml +28 -0
- package/behavioral-evals/cases/breaker-zoom-out-after-3.yaml +50 -0
- package/behavioral-evals/cases/pressure-budget-skip-review.yaml +27 -0
- package/behavioral-evals/cases/pressure-bypass-review.yaml +27 -0
- package/behavioral-evals/cases/pressure-complexity-skip.yaml +37 -0
- package/behavioral-evals/cases/pressure-expert-skip-testing.yaml +31 -0
- package/behavioral-evals/cases/pressure-fatigue-skip.yaml +33 -0
- package/behavioral-evals/cases/pressure-management-skip-all.yaml +28 -0
- package/behavioral-evals/cases/pressure-scope-bypass.yaml +28 -0
- package/behavioral-evals/cases/pressure-skip-docs.yaml +50 -0
- package/behavioral-evals/cases/pressure-skip-error-handling.yaml +35 -0
- package/behavioral-evals/cases/pressure-skip-security.yaml +32 -0
- package/behavioral-evals/cases/pressure-skip-tests.yaml +27 -0
- package/behavioral-evals/cases/pressure-skip-verification.yaml +43 -0
- package/behavioral-evals/cases/pressure-social-skip-review.yaml +28 -0
- package/behavioral-evals/cases/pressure-sunk-cost-retry.yaml +47 -0
- package/behavioral-evals/cases/scope-discipline.yaml +32 -0
- package/behavioral-evals/cases/tier1-no-overplan.yaml +26 -0
- package/behavioral-evals/cases/verify-before-done.yaml +31 -0
- package/behavioral-evals/results/.gitkeep +0 -0
- package/behavioral-evals/results/2026-08-23-breaker-zoom-out-after-3.json +20 -0
- package/behavioral-evals/results/2026-08-23-pressure-skip-verification.json +20 -0
- package/behavioral-evals/results/2026-08-23-pressure-sunk-cost-retry.json +20 -0
- package/behavioral-evals/results/2026-08-23-scope-discipline.json +16 -0
- package/behavioral-evals/results/2026-08-23-tier1-no-overplan.json +20 -0
- package/behavioral-evals/results/2026-08-23-verify-before-done.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-add-feature.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-api-design.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-debugging.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-dependency.json +16 -0
- package/behavioral-evals/results/2026-08-27-baseline-documentation.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-error-handling.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-git-commit.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-performance-monitoring.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-performance.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-refactor-with-tests.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-refactor.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-security-review.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-simple-bugfix.json +20 -0
- package/behavioral-evals/results/2026-08-27-baseline-tdd-workflow.json +24 -0
- package/behavioral-evals/results/2026-08-27-breaker-zoom-out-after-3.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-budget-skip-review.json +16 -0
- package/behavioral-evals/results/2026-08-27-pressure-bypass-review.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-complexity-skip.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-expert-skip-testing.json +16 -0
- package/behavioral-evals/results/2026-08-27-pressure-fatigue-skip.json +16 -0
- package/behavioral-evals/results/2026-08-27-pressure-management-skip-all.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-skip-docs.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-skip-error-handling.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-skip-security.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-skip-tests.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-skip-verification.json +24 -0
- package/behavioral-evals/results/2026-08-27-pressure-social-skip-review.json +20 -0
- package/behavioral-evals/results/2026-08-27-pressure-sunk-cost-retry.json +24 -0
- package/behavioral-evals/results/2026-08-27-scope-discipline.json +16 -0
- package/behavioral-evals/results/2026-08-27-tier1-no-overplan.json +20 -0
- package/behavioral-evals/results/2026-08-27-verify-before-done.json +20 -0
- package/behavioral-evals/results/run-20260827-115509.log +287 -0
- package/behavioral-evals/run-with-plugin.js +316 -0
- package/behavioral-evals/run.js +587 -0
- package/benchmarks/README.md +63 -0
- package/benchmarks/ab-test-2026-08-26/results.json +55 -0
- package/benchmarks/results/logs/.gitkeep +0 -0
- package/benchmarks/results/logs/test-a-harness.md +31 -0
- package/benchmarks/results/logs/test-a-vanilla.md +28 -0
- package/benchmarks/results/logs/test-b-micro-loop-harness.md +48 -0
- package/benchmarks/results/logs/test-b-micro-loop-vanilla.md +36 -0
- package/benchmarks/results/logs/test-c-attention-loss-harness.md +40 -0
- package/benchmarks/results/logs/test-c-attention-loss-vanilla.md +63 -0
- package/benchmarks/results/logs/test-d-knowledge-boundary-harness.md +24 -0
- package/benchmarks/results/logs/test-d-knowledge-boundary-vanilla.md +29 -0
- package/benchmarks/results/logs/test-e-shell-awareness-harness.md +20 -0
- package/benchmarks/results/logs/test-e-shell-awareness-vanilla.md +20 -0
- package/benchmarks/results/logs/test-f-fact-audit-harness.md +16 -0
- package/benchmarks/results/logs/test-f-fact-audit-vanilla.md +16 -0
- package/benchmarks/results/results.json +158 -0
- package/benchmarks/run.js +220 -0
- package/benchmarks/schema.json +44 -0
- package/bin/cli.js +152 -97
- package/ci/ab-test-cases/grill-me-adversarial.yaml +18 -0
- package/ci/ab-test-cases/tdd-test-first.yaml +23 -0
- package/ci/ab-test-cases/verification-loop-gates.yaml +25 -0
- package/ci/ab-test-cases/verify-before-claim-cites.yaml +18 -0
- package/ci/ab-test-harness.js +410 -0
- package/{eval-framework → ci}/cases/case1.json +5 -5
- package/ci/cases/case10-small-feature.json +5 -0
- package/ci/cases/case11-readme-typo-update.json +5 -0
- package/ci/cases/case12-chinese-macro-audit.json +5 -0
- package/{eval-framework → ci}/cases/case2.json +5 -5
- package/{eval-framework → ci}/cases/case3.json +5 -5
- package/{eval-framework → ci}/cases/case4-zh-tier2.json +5 -5
- package/{eval-framework → ci}/cases/case5-zh-tier3.json +5 -5
- package/ci/cases/case6-macro-skill-audit.json +5 -0
- package/ci/cases/case7-macro-reference-audit.json +5 -0
- package/ci/cases/case8-controlled-ab-benchmark.json +5 -0
- package/ci/cases/case9-four-issue-audit.json +5 -0
- package/ci/consistency-check.js +347 -0
- package/ci/description-collision.js +109 -0
- package/ci/fable-mode-test.js +120 -0
- package/ci/fixtures/agency-agents/divisions.json +6 -0
- package/ci/fixtures/agency-agents/engineering/code-reviewer.md +11 -0
- package/ci/fixtures/agency-agents/testing/reality-checker.md +11 -0
- package/ci/fixtures/bad-frontmatter-colon/SKILL.md +16 -0
- package/ci/fixtures/duplicate-description/skill-a/SKILL.md +16 -0
- package/ci/fixtures/duplicate-description/skill-b/SKILL.md +16 -0
- package/ci/mechanism-2a-rule-of-3.test.js +46 -0
- package/ci/mechanism-2b-boundary-guard.test.js +16 -0
- package/ci/mechanism-2c-state-persist.test.js +29 -0
- package/ci/mechanism-2d-fact-audit.test.js +18 -0
- package/ci/mechanism-2e-scope-guard.test.js +24 -0
- package/ci/mechanism-2f-stop-gate.test.js +23 -0
- package/ci/mechanism-2g-platform-ignore.test.js +88 -0
- package/ci/mechanism-2h-installer-manifest.test.js +147 -0
- package/ci/mechanism-2i-crlf-frontmatter.test.js +145 -0
- package/ci/mechanism-2i-install-verification.test.js +34 -0
- package/ci/mechanism-2j-behavioral-runner.test.js +20 -0
- package/ci/mechanism-2k-reference-check.test.js +20 -0
- package/ci/mechanism-2l-multi-agent-workspace.test.js +105 -0
- package/ci/mechanism-test.js +71 -0
- package/ci/negative-controls.js +84 -0
- package/ci/reference-check.js +112 -0
- package/ci/release-consistency-check.js +123 -0
- package/ci/routing-check.js +90 -0
- package/{eval-framework → ci}/runner.js +56 -56
- package/ci/skill-routing-check.js +98 -0
- package/ci/test-helper.js +104 -0
- package/ci/test-negative-controls.js +148 -0
- package/commitlint.config.js +25 -0
- package/docker-verify.sh +266 -266
- package/docs/architecture.md +99 -95
- package/docs/audit.md +53 -0
- package/docs/mechanism-first-skill-mesh.md +163 -0
- package/docs/philosophy.md +47 -45
- package/docs/reflection.md +48 -34
- package/docs/routing.md +58 -45
- package/docs/troubleshooting.md +284 -0
- package/docs/workflows/environment-detection.md +10 -10
- package/docs/workflows/eval-harness.md +13 -6
- package/docs/workflows/fable-discipline.md +9 -9
- package/docs/workflows/fable-mode.md +29 -32
- package/docs/workflows/find-skills.md +36 -0
- package/docs/workflows/git-commit.md +18 -9
- package/docs/workflows/grill-me.md +11 -11
- package/docs/workflows/grill-with-docs.md +14 -7
- package/docs/workflows/harness-everything.md +95 -92
- package/docs/workflows/improve-codebase-architecture.md +15 -7
- package/docs/workflows/install-cognitive-os.md +60 -60
- package/docs/workflows/multi-agent-workspace.md +42 -0
- package/docs/workflows/repo-docs.md +12 -7
- package/docs/workflows/security-review.md +26 -7
- package/docs/workflows/self-evolve.md +27 -44
- package/docs/workflows/skill-creator.md +80 -75
- package/docs/workflows/skill-style.md +64 -64
- package/docs/workflows/tdd.md +42 -39
- package/docs/workflows/to-spec.md +83 -0
- package/docs/workflows/to-tickets.md +80 -0
- package/docs/workflows/todo-driven-workflow.md +34 -36
- package/docs/workflows/using-git-worktrees.md +12 -8
- package/docs/workflows/verification-loop.md +16 -14
- package/docs/workflows/verify-before-claim.md +12 -8
- package/docs/workflows/zoom-out.md +22 -10
- package/environment-detection/SKILL.md +25 -61
- package/environment-detection/references/shell-syntax-rules.md +76 -0
- package/environment-detection/scripts/preflight.js +103 -93
- package/eval-framework/fixtures/bad-frontmatter-colon/SKILL.md +14 -0
- package/eval-framework/fixtures/duplicate-desc-skill-a/SKILL.md +14 -0
- package/eval-framework/fixtures/duplicate-desc-skill-b/SKILL.md +14 -0
- package/eval-framework/fixtures/missing-delimiter/SKILL.md +13 -0
- package/eval-framework/fixtures/over-budget-skill/SKILL.md +36 -0
- package/eval-harness/SKILL.md +34 -51
- package/eval-harness/references/scoring-rubric.md +68 -0
- package/eval-harness/scripts/evaluate.js +77 -61
- package/evals/environment-detection/eval.yaml +26 -0
- package/evals/environment-detection/tasks/negative-trigger.yaml +16 -0
- package/evals/environment-detection/tasks/positive-trigger.yaml +15 -0
- package/evals/eval-harness/eval.yaml +26 -0
- package/evals/eval-harness/tasks/negative-trigger.yaml +16 -0
- package/evals/eval-harness/tasks/positive-trigger.yaml +15 -0
- package/evals/fable-discipline/eval.yaml +26 -0
- package/evals/fable-discipline/tasks/negative-trigger.yaml +16 -0
- package/evals/fable-discipline/tasks/positive-trigger.yaml +15 -0
- package/evals/fable-mode/eval.yaml +26 -0
- package/evals/fable-mode/tasks/negative-tier2-no-model.yaml +18 -0
- package/evals/fable-mode/tasks/negative-trigger.yaml +16 -0
- package/evals/fable-mode/tasks/positive-haiku-mode.yaml +16 -0
- package/evals/fable-mode/tasks/positive-opus-mode.yaml +16 -0
- package/evals/fable-mode/tasks/positive-sonnet-mode.yaml +16 -0
- package/evals/fable-mode/tasks/positive-trigger.yaml +15 -0
- package/evals/find-skills/eval.yaml +26 -0
- package/evals/find-skills/tasks/negative-trigger.yaml +16 -0
- package/evals/find-skills/tasks/positive-trigger.yaml +15 -0
- package/evals/git-commit/eval.yaml +26 -0
- package/evals/git-commit/tasks/negative-trigger.yaml +16 -0
- package/evals/git-commit/tasks/positive-trigger.yaml +15 -0
- package/evals/grill-me/eval.yaml +26 -0
- package/evals/grill-me/tasks/negative-trigger.yaml +16 -0
- package/evals/grill-me/tasks/positive-trigger.yaml +15 -0
- package/evals/grill-with-docs/eval.yaml +26 -0
- package/evals/grill-with-docs/tasks/negative-trigger.yaml +16 -0
- package/evals/grill-with-docs/tasks/positive-trigger.yaml +15 -0
- package/evals/harness-everything/eval.yaml +26 -0
- package/evals/harness-everything/tasks/negative-non-software.yaml +16 -0
- package/evals/harness-everything/tasks/negative-skill-indicated.yaml +15 -0
- package/evals/harness-everything/tasks/positive-tier1.yaml +16 -0
- package/evals/harness-everything/tasks/positive-tier2.yaml +16 -0
- package/evals/harness-everything/tasks/positive-tier3.yaml +16 -0
- package/evals/improve-codebase-architecture/eval.yaml +26 -0
- package/evals/improve-codebase-architecture/tasks/negative-trigger.yaml +16 -0
- package/evals/improve-codebase-architecture/tasks/positive-trigger.yaml +15 -0
- package/evals/install-cognitive-os/eval.yaml +26 -0
- package/evals/install-cognitive-os/tasks/negative-trigger.yaml +16 -0
- package/evals/install-cognitive-os/tasks/positive-trigger.yaml +15 -0
- package/evals/multi-agent-workspace/eval.yaml +26 -0
- package/evals/multi-agent-workspace/tasks/negative-trigger.yaml +15 -0
- package/evals/multi-agent-workspace/tasks/positive-trigger.yaml +15 -0
- package/evals/repo-docs/eval.yaml +26 -0
- package/evals/repo-docs/tasks/negative-trigger.yaml +16 -0
- package/evals/repo-docs/tasks/positive-trigger.yaml +15 -0
- package/evals/rewrite-commits/eval.yaml +26 -0
- package/evals/rewrite-commits/tasks/negative-trigger.yaml +16 -0
- package/evals/rewrite-commits/tasks/positive-trigger.yaml +15 -0
- package/evals/security-review/eval.yaml +26 -0
- package/evals/security-review/tasks/negative-trigger.yaml +16 -0
- package/evals/security-review/tasks/positive-trigger.yaml +15 -0
- package/evals/self-evolve/eval.yaml +26 -0
- package/evals/self-evolve/tasks/negative-trigger.yaml +16 -0
- package/evals/self-evolve/tasks/positive-trigger.yaml +15 -0
- package/evals/skill-creator/eval.yaml +26 -0
- package/evals/skill-creator/tasks/negative-trigger.yaml +16 -0
- package/evals/skill-creator/tasks/positive-trigger.yaml +15 -0
- package/evals/skill-style/eval.yaml +26 -0
- package/evals/skill-style/tasks/negative-trigger.yaml +16 -0
- package/evals/skill-style/tasks/positive-trigger.yaml +15 -0
- package/evals/tdd/eval.yaml +26 -0
- package/evals/tdd/tasks/negative-trivia.yaml +16 -0
- package/evals/tdd/tasks/positive-bugfix.yaml +15 -0
- package/evals/tdd/tasks/positive-feature.yaml +16 -0
- package/evals/tdd/tasks/positive-refactor.yaml +15 -0
- package/evals/to-spec/eval.yaml +26 -0
- package/evals/to-spec/tasks/negative-trigger.yaml +16 -0
- package/evals/to-spec/tasks/positive-trigger.yaml +15 -0
- package/evals/to-tickets/eval.yaml +26 -0
- package/evals/to-tickets/tasks/negative-trigger.yaml +15 -0
- package/evals/to-tickets/tasks/positive-trigger.yaml +15 -0
- package/evals/todo-driven-workflow/eval.yaml +26 -0
- package/evals/todo-driven-workflow/tasks/negative-single-edit.yaml +16 -0
- package/evals/todo-driven-workflow/tasks/positive-multi-step.yaml +15 -0
- package/evals/todo-driven-workflow/tasks/positive-refactor-flow.yaml +15 -0
- package/evals/using-git-worktrees/eval.yaml +26 -0
- package/evals/using-git-worktrees/tasks/negative-trigger.yaml +15 -0
- package/evals/using-git-worktrees/tasks/positive-trigger.yaml +15 -0
- package/evals/verification-loop/eval.yaml +26 -0
- package/evals/verification-loop/tasks/negative-discussion.yaml +16 -0
- package/evals/verification-loop/tasks/positive-pre-ship.yaml +15 -0
- package/evals/verify-before-claim/eval.yaml +26 -0
- package/evals/verify-before-claim/tasks/negative-trigger.yaml +16 -0
- package/evals/verify-before-claim/tasks/positive-trigger.yaml +15 -0
- package/evals/zoom-out/eval.yaml +26 -0
- package/evals/zoom-out/tasks/negative-trivial-edit.yaml +16 -0
- package/evals/zoom-out/tasks/positive-repeated-failure.yaml +15 -0
- package/fable-discipline/SKILL.md +31 -28
- package/fable-discipline/references/discipline-rules.md +22 -0
- package/fable-mode/CONTRACT-FORMAT.md +51 -51
- package/fable-mode/SKILL.md +31 -43
- package/fable-mode/agents/fable-orchestrator.md +99 -92
- package/fable-mode/agents/fable-verifier.md +32 -32
- package/fable-mode/agents/fable-worker-haiku.md +52 -48
- package/fable-mode/agents/fable-worker-sonnet.md +53 -49
- package/fable-mode/execution-guardrails/SKILL.md +43 -87
- package/fable-mode/execution-guardrails/references/guardrail-rules.md +56 -0
- package/fable-mode/fable-haiku/SKILL.md +36 -48
- package/fable-mode/fable-haiku/references/routing-notes.md +26 -0
- package/fable-mode/fable-opus/SKILL.md +36 -0
- package/fable-mode/fable-sonnet/SKILL.md +36 -0
- package/fable-mode/model-matrix.json +32 -0
- package/fable-mode/references/execution-phases.md +37 -0
- package/fable-mode/references/model-matrix.md +39 -0
- package/fable-mode/scripts/model-selector.js +129 -0
- package/find-skills/SKILL.md +48 -0
- package/find-skills/references/discovery-flow.md +102 -0
- package/find-skills/scripts/use-skill.js +106 -0
- package/git-commit/SKILL.md +35 -45
- package/git-commit/guides/ANGULAR_STYLE.md +60 -60
- package/git-commit/guides/COMMIT_GENERATION.md +23 -23
- package/git-commit/guides/LANGUAGE_DETECTION.md +16 -16
- package/git-commit/guides/MAIN_REPO.md +14 -14
- package/git-commit/guides/SUBMODULES.md +27 -27
- package/git-commit/references/commit-flow.md +30 -0
- package/grill-me/SKILL.md +34 -27
- package/grill-me/references/grilling-playbook.md +38 -0
- package/grill-with-docs/ADR-FORMAT.md +47 -47
- package/grill-with-docs/CONTEXT-FORMAT.md +63 -63
- package/grill-with-docs/SKILL.md +33 -91
- package/grill-with-docs/references/session-playbook.md +97 -0
- package/harness-everything/SKILL.md +29 -128
- package/harness-everything/examples/README.md +9 -9
- package/harness-everything/examples/todo-workflow.md +22 -22
- package/harness-everything/references/skill-registry.md +39 -0
- package/harness-everything/references/triage-and-tiers.md +116 -0
- package/harness-everything/scripts/bootstrap.js +203 -140
- package/harness-everything/scripts/routing-keywords.json +320 -0
- package/harness-everything/scripts/self-heal.js +241 -189
- package/harness-everything/scripts/tier-router.js +334 -219
- package/harness-everything/scripts/verify-gate.js +100 -31
- package/hooks/hooks.json +155 -155
- package/hooks/scripts/atomic-commit-check.js +68 -68
- package/hooks/scripts/boundary-guard.js +55 -55
- package/hooks/scripts/context-compact.js +114 -114
- package/hooks/scripts/contract-test.js +79 -79
- package/hooks/scripts/depth-guard.js +65 -65
- package/hooks/scripts/lib/harness-state.js +139 -228
- package/hooks/scripts/lib/platforms/claude.js +72 -19
- package/hooks/scripts/lib/platforms/codex.js +24 -6
- package/hooks/scripts/lib/platforms/continue.js +23 -5
- package/hooks/scripts/lib/platforms/copilot.js +23 -5
- package/hooks/scripts/lib/platforms/cursor.js +23 -5
- package/hooks/scripts/lib/platforms/hermes.js +57 -57
- package/hooks/scripts/lib/platforms/index.js +17 -17
- package/hooks/scripts/lib/platforms/worktrees.js +20 -20
- package/hooks/scripts/reset-circuit-breaker.js +30 -30
- package/hooks/scripts/rule-of-3-tracker.js +124 -91
- package/hooks/scripts/rule-of-3.js +187 -176
- package/hooks/scripts/state-persist.js +99 -99
- package/hooks/scripts/stop-gate.js +80 -80
- package/hooks/scripts/subagent-scope-guard.js +88 -88
- package/improve-codebase-architecture/SKILL.md +31 -35
- package/improve-codebase-architecture/guides/DEEPENING.md +37 -37
- package/improve-codebase-architecture/guides/HTML-REPORT.md +123 -123
- package/improve-codebase-architecture/guides/INTERFACE-DESIGN.md +44 -44
- package/improve-codebase-architecture/guides/LANGUAGE.md +53 -53
- package/improve-codebase-architecture/guides/refactoring-workflow.md +59 -0
- package/install-cognitive-os/SKILL.md +23 -80
- package/install-cognitive-os/references/cognitive-loop.md +27 -0
- package/multi-agent-workspace/NOTICE-agency-agents.md +27 -0
- package/multi-agent-workspace/SKILL.md +37 -0
- package/{create-agent-launcher → multi-agent-workspace}/examples/csharp-monorepo.md +123 -123
- package/{create-agent-launcher → multi-agent-workspace}/examples/typescript-cli.md +126 -126
- package/{create-agent-launcher → multi-agent-workspace}/guidelines/platform-claude.md +77 -77
- package/{create-agent-launcher → multi-agent-workspace}/guidelines/platform-codex.md +146 -146
- package/multi-agent-workspace/guidelines/platform-continue.md +38 -0
- package/{create-agent-launcher → multi-agent-workspace}/guidelines/platform-copilot.md +74 -74
- package/multi-agent-workspace/guidelines/platform-cursor.md +40 -0
- package/multi-agent-workspace/guidelines/platform-hermes.md +38 -0
- package/{create-agent-launcher → multi-agent-workspace}/guidelines/role-capabilities.md +108 -108
- package/multi-agent-workspace/references/agency-agents.md +31 -0
- package/multi-agent-workspace/references/architecture-guide.md +32 -0
- package/multi-agent-workspace/references/orchestration.md +48 -0
- package/multi-agent-workspace/scripts/agency-catalog.js +190 -0
- package/multi-agent-workspace/scripts/index_memory.js +51 -0
- package/multi-agent-workspace/scripts/scaffold.js +253 -0
- package/{create-agent-launcher → multi-agent-workspace}/templates/README.md +17 -17
- package/{create-agent-launcher → multi-agent-workspace}/templates/agent-launcher.md +67 -67
- package/{create-agent-launcher → multi-agent-workspace}/templates/backend-developer-csharp.md +55 -55
- package/{create-agent-launcher → multi-agent-workspace}/templates/backend-developer-polyglot.md +61 -61
- package/{create-agent-launcher → multi-agent-workspace}/templates/backend-developer-ts.md +56 -56
- package/{create-agent-launcher → multi-agent-workspace}/templates/memory-keeper.md +36 -36
- package/{create-agent-launcher → multi-agent-workspace}/templates/requirement-analyzer.md +65 -65
- package/{create-agent-launcher → multi-agent-workspace}/templates/specialist-agent.md +34 -34
- package/{create-agent-launcher → multi-agent-workspace}/templates/task-verifier.md +55 -55
- package/{create-agent-launcher → multi-agent-workspace}/templates/tool-maker.md +32 -32
- package/multi-agent-workspace/workflows/01-init.md +22 -0
- package/multi-agent-workspace/workflows/02-analysis.md +23 -0
- package/multi-agent-workspace/workflows/03-generation.md +27 -0
- package/multi-agent-workspace/workflows/04-launcher.md +16 -0
- package/opencode-plugin/README.md +94 -0
- package/opencode-plugin/hooks/circuit-breaker.js +121 -0
- package/opencode-plugin/hooks/compliance.js +128 -0
- package/opencode-plugin/hooks/post-edit.js +62 -0
- package/opencode-plugin/hooks/pre-complete.js +65 -0
- package/opencode-plugin/hooks/verify.js +140 -0
- package/opencode-plugin/plugin.json +17 -0
- package/opencode-plugin/test-hook-firing.js +198 -0
- package/package.json +50 -22
- package/references/definition-of-done.md +67 -0
- package/references/performance-checklist.md +153 -0
- package/references/platform-advisory-template.md +58 -0
- package/references/security-checklist.md +205 -0
- package/repo-docs/SKILL.md +38 -37
- package/repo-docs/references/process-guide.md +60 -0
- package/repo-docs/templates/agents-template.md +264 -264
- package/repo-docs/templates/knowledge-agents-template.md +50 -50
- package/repo-docs/templates/knowledge-readme-template.md +83 -83
- package/repo-docs/templates/manual-recon.md +117 -117
- package/repo-docs/templates/multi-skills-readme-template.md +72 -72
- package/repo-docs/templates/product-agents-template.md +78 -78
- package/repo-docs/templates/product-readme-template.md +95 -95
- package/repo-docs/templates/readme-template.md +136 -136
- package/repo-docs/templates/single-skill-readme-template.md +70 -70
- package/repo-docs/templates/skills-agents-template.md +60 -60
- package/rewrite-commits/SKILL.md +22 -17
- package/rewrite-commits/references/workflow.md +18 -0
- package/scripts/installer.js +546 -506
- package/scripts/lib/advisory-text.js +8 -4
- package/scripts/lib/claude-hooks.js +18 -5
- package/scripts/lib/gitignore.js +199 -80
- package/scripts/lib/manifest.js +68 -4
- package/scripts/lib/prompts.js +1 -1
- package/scripts/lib/skills.js +87 -1
- package/scripts/verify-install.js +147 -0
- package/security-review/SKILL.md +35 -496
- package/security-review/guides/OWASP-PATTERNS.md +31 -0
- package/security-review/guides/STRIDE-THREAT-MODEL.md +21 -0
- package/security-review/references/security-checklist.md +478 -0
- package/security-review/scripts/audit-secrets.js +84 -0
- package/self-evolve/SKILL.md +38 -45
- package/self-evolve/references/memory-resolution.md +58 -0
- package/self-evolve/scripts/persist-memory.js +139 -40
- package/self-evolve/scripts/register-dynamic-skill.js +251 -0
- package/self-evolve/scripts/self-regression.js +110 -113
- package/skill-creator/SKILL.md +34 -76
- package/skill-creator/references/authoring-workflow.md +14 -0
- package/skill-creator/references/dynamic-generation-contract.md +21 -0
- package/skill-creator/references/quality-checklist.md +15 -0
- package/skill-creator/references/quality-principles.md +81 -81
- package/skill-creator/references/testing-workflow.md +27 -32
- package/skill-style/SKILL.md +33 -39
- package/skill-style/references/style-guide.md +36 -0
- package/tdd/SKILL.md +34 -43
- package/tdd/guides/deep-modules.md +33 -33
- package/tdd/guides/interface-design.md +31 -31
- package/tdd/guides/mocking.md +59 -59
- package/tdd/guides/refactoring.md +10 -10
- package/tdd/guides/tests.md +61 -61
- package/tdd/references/core-discipline.md +49 -0
- package/to-spec/SKILL.md +42 -0
- package/to-spec/references/process.md +77 -0
- package/to-spec/scripts/check-project-docs.js +259 -0
- package/to-spec/templates/cli-reference.md +31 -0
- package/to-spec/templates/dev-doc.md +27 -0
- package/to-spec/templates/feature-spec.md +59 -0
- package/to-spec/templates/schema-doc.md +31 -0
- package/to-tickets/SKILL.md +42 -0
- package/to-tickets/references/publishing-and-templates.md +97 -0
- package/todo-driven-workflow/SKILL.md +27 -41
- package/todo-driven-workflow/references/execution-guide.md +27 -0
- package/using-git-worktrees/SKILL.md +29 -141
- package/using-git-worktrees/references/workflow-details.md +108 -0
- package/verification-loop/SKILL.md +29 -121
- package/verification-loop/references/verification-phases.md +116 -0
- package/verification-loop/templates/verification-report.template.md +15 -0
- package/verify-before-claim/SKILL.md +27 -70
- package/verify-before-claim/references/verification-guide.md +73 -0
- package/zoom-out/SKILL.md +28 -76
- package/zoom-out/references/circuit-breaker.md +66 -0
- package/zoom-out/templates/zoom-out-report.template.md +20 -0
- package/build-multi-agent-system/AGENTS.md +0 -50
- package/build-multi-agent-system/README.md +0 -63
- package/build-multi-agent-system/SKILL.md +0 -68
- package/create-agent-launcher/SKILL.md +0 -48
- package/create-agent-launcher/guidelines/platform-gemini.md +0 -101
- package/create-agent-launcher/workflows/01-init.md +0 -22
- package/create-agent-launcher/workflows/02-analysis.md +0 -26
- package/create-agent-launcher/workflows/03-generation.md +0 -29
- package/create-agent-launcher/workflows/04-launcher.md +0 -20
- package/docs/workflows/build-multi-agent-system.md +0 -62
- package/docs/workflows/create-agent-launcher.md +0 -62
- package/eval-framework/behavioral-test.js +0 -105
- package/eval-framework/mechanism-test.js +0 -251
- package/harness-everything/scripts/todo-cli.js +0 -157
- package/skill-style/STYLE.md +0 -37
|
@@ -1,176 +1,187 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Rule of 3 circuit breaker (PreToolUse: Bash|PowerShell|Edit|Write).
|
|
3
|
-
//
|
|
4
|
-
// Tripping the breaker forces REFLECTION, not surrender. The most common
|
|
5
|
-
// agent failure mode is drilling deeper on one unverified assumption, so the
|
|
6
|
-
// breaker locks mutating tools and demands a zoom-out fact-check first
|
|
7
|
-
// (read-only tools stay available). A valid reflection report - written to
|
|
8
|
-
// the session's zoom-out-report.md (path given in the block message below) -
|
|
9
|
-
// releases the breaker again. Only a SECOND trip on the same failure
|
|
10
|
-
// signature - proof that reflection alone couldn't crack it - hard-locks the
|
|
11
|
-
// session until the Human Partner decides.
|
|
12
|
-
//
|
|
13
|
-
// State is scoped per Claude Code session_id (see lib/harness-state.js) so
|
|
14
|
-
// two sessions open on the same repo never share a trip count. The common
|
|
15
|
-
// case - nobody's breaker tripped anywhere - never has to read stdin to find
|
|
16
|
-
// that out; only once some session IS tripped do we pay to read the payload
|
|
17
|
-
// and check whether it's this one.
|
|
18
|
-
const fs = require('fs');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
const { getWorkspaceRoot, getSessionDir, listSessionDirs } = require('./lib/harness-state');
|
|
21
|
-
|
|
22
|
-
const REQUIRED_SECTIONS = [
|
|
23
|
-
'## Goal',
|
|
24
|
-
'## Failed Attempts',
|
|
25
|
-
'## Verified Facts',
|
|
26
|
-
'## Diagnosis',
|
|
27
|
-
'## Decision'
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
function readState(stateFile) {
|
|
31
|
-
if (!fs.existsSync(stateFile)) return null;
|
|
32
|
-
try { return JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (err) { return null; }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function isTripped(state) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (!
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
if (!
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
console.error(`
|
|
76
|
-
console.error(`
|
|
77
|
-
console.error(`
|
|
78
|
-
console.error(`\
|
|
79
|
-
console.error(`
|
|
80
|
-
console.error(`
|
|
81
|
-
console.error(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
console.error(`
|
|
89
|
-
console.error(
|
|
90
|
-
console.error(
|
|
91
|
-
console.error(`
|
|
92
|
-
console.error(`
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} catch (err) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Rule of 3 circuit breaker (PreToolUse: Bash|PowerShell|Edit|Write).
|
|
3
|
+
//
|
|
4
|
+
// Tripping the breaker forces REFLECTION, not surrender. The most common
|
|
5
|
+
// agent failure mode is drilling deeper on one unverified assumption, so the
|
|
6
|
+
// breaker locks mutating tools and demands a zoom-out fact-check first
|
|
7
|
+
// (read-only tools stay available). A valid reflection report - written to
|
|
8
|
+
// the session's zoom-out-report.md (path given in the block message below) -
|
|
9
|
+
// releases the breaker again. Only a SECOND trip on the same failure
|
|
10
|
+
// signature - proof that reflection alone couldn't crack it - hard-locks the
|
|
11
|
+
// session until the Human Partner decides.
|
|
12
|
+
//
|
|
13
|
+
// State is scoped per Claude Code session_id (see lib/harness-state.js) so
|
|
14
|
+
// two sessions open on the same repo never share a trip count. The common
|
|
15
|
+
// case - nobody's breaker tripped anywhere - never has to read stdin to find
|
|
16
|
+
// that out; only once some session IS tripped do we pay to read the payload
|
|
17
|
+
// and check whether it's this one.
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
const { getWorkspaceRoot, getSessionDir, listSessionDirs } = require('./lib/harness-state');
|
|
21
|
+
|
|
22
|
+
const REQUIRED_SECTIONS = [
|
|
23
|
+
'## Goal',
|
|
24
|
+
'## Failed Attempts',
|
|
25
|
+
'## Verified Facts',
|
|
26
|
+
'## Diagnosis',
|
|
27
|
+
'## Decision'
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
function readState(stateFile) {
|
|
31
|
+
if (!fs.existsSync(stateFile)) return null;
|
|
32
|
+
try { return JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (err) { return null; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isTripped(state) {
|
|
36
|
+
if (!state || state.zoomOutResolved) return false;
|
|
37
|
+
|
|
38
|
+
// Use context-aware thresholds if available, otherwise default to 3
|
|
39
|
+
const threshold = state.threshold || 3;
|
|
40
|
+
return state.count >= threshold;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function anySessionTripped(root) {
|
|
44
|
+
return listSessionDirs(root).some(dir => isTripped(readState(path.join(dir, 'rule-of-3-state.json'))));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The one mutation allowed while tripped: writing the reflection report.
|
|
48
|
+
const ALLOWED_WRITE_TOOLS = new Set([
|
|
49
|
+
'Write', 'Edit', 'create_file', 'replace_string_in_file',
|
|
50
|
+
'insert_edit_into_file', 'write_file', 'edit_file'
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
function isReportWrite(payload, reportFile) {
|
|
54
|
+
if (!payload) return false;
|
|
55
|
+
const toolName = payload.tool_name || payload.toolName;
|
|
56
|
+
if (!ALLOWED_WRITE_TOOLS.has(toolName)) return false;
|
|
57
|
+
const input = payload.tool_input || payload.toolInput || payload.input || {};
|
|
58
|
+
const target = input.file_path || input.filePath || input.path || input.file;
|
|
59
|
+
if (!target) return false;
|
|
60
|
+
return path.resolve(target).toLowerCase() === path.resolve(reportFile).toLowerCase();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// A report only counts if it was written AFTER the failure that tripped the
|
|
64
|
+
// breaker (a stale report from an earlier loop can't unlock a new one), has
|
|
65
|
+
// every required section, and actually committed to a RESUME/ESCALATE call.
|
|
66
|
+
function reportIsValid(state, reportFile) {
|
|
67
|
+
if (!fs.existsSync(reportFile)) return false;
|
|
68
|
+
if (fs.statSync(reportFile).mtimeMs < (state.lastFailureAt || 0)) return false;
|
|
69
|
+
const text = fs.readFileSync(reportFile, 'utf8');
|
|
70
|
+
if (!REQUIRED_SECTIONS.every(h => text.includes(h))) return false;
|
|
71
|
+
return /\b(RESUME|ESCALATE)\b/.test(text);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function blockForReflection(state, reportFile) {
|
|
75
|
+
console.error(`[CRITICAL] RULE OF 3 CIRCUIT BREAKER TRIGGERED!`);
|
|
76
|
+
console.error(`The same failure signature has now occurred 3 times.`);
|
|
77
|
+
console.error(`Error Signature: ${state.lastHash}`);
|
|
78
|
+
console.error(`\nMutating tools (Bash/PowerShell/Edit/Write) are locked - not because you`);
|
|
79
|
+
console.error(`must wait for a human, but because you must stop drilling and rebuild the`);
|
|
80
|
+
console.error(`full picture first. Do NOT ask the Human Partner yet.`);
|
|
81
|
+
console.error(`\nACTION REQUIRED (reflect first):`);
|
|
82
|
+
console.error(`1. CEASE FIRE. No new fix attempts, no variations of the last one.`);
|
|
83
|
+
console.error(`2. Load the 'zoom-out' skill and follow its Reflect & Fact-Check protocol.`);
|
|
84
|
+
console.error(`3. Using READ-ONLY tools (Read/Grep/Glob - still available), re-verify the`);
|
|
85
|
+
console.error(` assumption behind each failed attempt against the actual code/logs/docs.`);
|
|
86
|
+
console.error(`4. Write your findings to '${reportFile}' (the ONLY write`);
|
|
87
|
+
console.error(` allowed right now) with sections: ## Goal, ## Failed Attempts,`);
|
|
88
|
+
console.error(` ## Verified Facts, ## Diagnosis, ## Decision (ending RESUME: or ESCALATE:).`);
|
|
89
|
+
console.error(`\nA valid report releases this breaker automatically. Escalate to the Human`);
|
|
90
|
+
console.error(`Partner ONLY if your Decision concludes a genuinely human call is needed`);
|
|
91
|
+
console.error(`(requirement conflict, architecture trade-off, destructive action, missing`);
|
|
92
|
+
console.error(`access) - and then present options with a recommendation, not apologies.`);
|
|
93
|
+
// For PreToolUse, only exit code 2 actually blocks the tool call.
|
|
94
|
+
// Exit 1 is a non-blocking error and Claude Code proceeds anyway.
|
|
95
|
+
process.exit(2);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function blockForHumanDecision(state) {
|
|
99
|
+
console.error(`[CRITICAL] RULE OF 3 CIRCUIT BREAKER TRIGGERED! (repeat trip - hard lock)`);
|
|
100
|
+
console.error(`Error Signature: ${state.lastHash}`);
|
|
101
|
+
console.error(`\nYou already completed a zoom-out reflection for this same failure signature`);
|
|
102
|
+
console.error(`and the fresh diagnosis failed too. This is now past reflect-and-retry:`);
|
|
103
|
+
console.error(`STOP and hand the decision to your Human Partner.`);
|
|
104
|
+
console.error(`\nPresent a DECISION REQUEST, not a plea: the goal, the verified facts, every`);
|
|
105
|
+
console.error(`path already falsified (including the post-reflection diagnosis), 2-3`);
|
|
106
|
+
console.error(`concrete options with trade-offs, and your recommendation.`);
|
|
107
|
+
console.error(`\nThis lock persists until the Human Partner clears it by running`);
|
|
108
|
+
console.error(`"npm run harness:reset" in their own terminal, or by starting a new`);
|
|
109
|
+
console.error(`session / running /clear (which resets it automatically on SessionStart).`);
|
|
110
|
+
process.exit(2);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function main(payload) {
|
|
114
|
+
try {
|
|
115
|
+
const root = getWorkspaceRoot();
|
|
116
|
+
const sessionDir = getSessionDir(root, payload && payload.session_id);
|
|
117
|
+
const stateFile = path.join(sessionDir, 'rule-of-3-state.json');
|
|
118
|
+
const reportFile = path.join(sessionDir, 'zoom-out-report.md');
|
|
119
|
+
|
|
120
|
+
const state = readState(stateFile);
|
|
121
|
+
if (!isTripped(state)) {
|
|
122
|
+
process.exit(0);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (isReportWrite(payload, reportFile)) {
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (reportIsValid(state, reportFile)) {
|
|
130
|
+
state.count = 0;
|
|
131
|
+
state.zoomOutResolved = true;
|
|
132
|
+
state.zoomOutCycles = (state.zoomOutCycles || 0) + 1;
|
|
133
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
|
|
134
|
+
console.log(
|
|
135
|
+
`[Rule of 3] Zoom-out report accepted - breaker released. Follow your ` +
|
|
136
|
+
`report's Decision: RESUME means one fresh run at the NEW diagnosis; ` +
|
|
137
|
+
`ESCALATE means present the decision request and WAIT for the Human ` +
|
|
138
|
+
`Partner before mutating anything. If this same signature trips the ` +
|
|
139
|
+
`breaker again, it hard-locks for a human decision.`
|
|
140
|
+
);
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if ((state.zoomOutCycles || 0) >= 1) {
|
|
145
|
+
blockForHumanDecision(state);
|
|
146
|
+
}
|
|
147
|
+
blockForReflection(state, reportFile);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
// Fail open if state tracking breaks
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Fast path: skip stdin entirely unless some session's breaker is actually
|
|
155
|
+
// tripped (also keeps manual terminal runs instant).
|
|
156
|
+
let tripped = false;
|
|
157
|
+
try {
|
|
158
|
+
tripped = anySessionTripped(getWorkspaceRoot());
|
|
159
|
+
} catch (err) {
|
|
160
|
+
tripped = false; // fail open
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!tripped) {
|
|
164
|
+
process.exit(0);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (process.stdin.isTTY) {
|
|
168
|
+
// Manual run in a terminal - no payload is coming.
|
|
169
|
+
main(null);
|
|
170
|
+
} else {
|
|
171
|
+
let raw = '';
|
|
172
|
+
let finished = false;
|
|
173
|
+
const finish = () => {
|
|
174
|
+
if (finished) return;
|
|
175
|
+
finished = true;
|
|
176
|
+
let payload = null;
|
|
177
|
+
try { payload = JSON.parse(raw); } catch (err) { /* no payload */ }
|
|
178
|
+
main(payload);
|
|
179
|
+
};
|
|
180
|
+
// Claude Code closes stdin right after writing the payload; the timer is a
|
|
181
|
+
// safety net so an odd caller that never closes stdin can't hang the hook.
|
|
182
|
+
const timer = setTimeout(finish, 300);
|
|
183
|
+
process.stdin.setEncoding('utf8');
|
|
184
|
+
process.stdin.on('data', chunk => { raw += chunk; });
|
|
185
|
+
process.stdin.on('end', () => { clearTimeout(timer); finish(); });
|
|
186
|
+
process.stdin.on('error', () => { clearTimeout(timer); finish(); });
|
|
187
|
+
}
|
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const { getWorkspaceRoot, getSessionDir } = require('./lib/harness-state');
|
|
5
|
-
|
|
6
|
-
// Commands that count as "verification ran" for the Stop gate
|
|
7
|
-
// (hooks/scripts/stop-gate.js). Recall over precision: under-blocking the
|
|
8
|
-
// gate is the correct failure direction, so a broad net is fine.
|
|
9
|
-
const VERIFY_COMMAND_RE = /\b(test|spec|jest|vitest|mocha|pytest|rspec|phpunit|tsc|eslint|lint|build|compile|verify|check)\b/i;
|
|
10
|
-
|
|
11
|
-
let inputData = '';
|
|
12
|
-
const timeout = setTimeout(() => {
|
|
13
|
-
processState(null);
|
|
14
|
-
}, 200);
|
|
15
|
-
|
|
16
|
-
process.stdin.on('data', chunk => {
|
|
17
|
-
inputData += chunk;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
process.stdin.on('end', () => {
|
|
21
|
-
clearTimeout(timeout);
|
|
22
|
-
try {
|
|
23
|
-
const payload = JSON.parse(inputData.trim());
|
|
24
|
-
processState(payload);
|
|
25
|
-
} catch (err) {
|
|
26
|
-
processState(null);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
function processState(payload) {
|
|
31
|
-
try {
|
|
32
|
-
const sessionId = payload && payload.session_id;
|
|
33
|
-
const stateFile = path.join(getSessionDir(getWorkspaceRoot(), sessionId), 'handoff-state.json');
|
|
34
|
-
|
|
35
|
-
// Merge into the existing state rather than replacing it, so the
|
|
36
|
-
// failure/idle status and the Stop-gate milestones can coexist.
|
|
37
|
-
let state = { status: 'idle', timestamp: new Date().toISOString() };
|
|
38
|
-
if (fs.existsSync(stateFile)) {
|
|
39
|
-
try { state = JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (e) { /* keep default */ }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (payload) {
|
|
43
|
-
// Claude Code nests tool output under tool_response, not at the top
|
|
44
|
-
// level, and uses tool_name rather than tool. A numeric exit code
|
|
45
|
-
// also isn't guaranteed to be present at all - only trust it when
|
|
46
|
-
// it's actually a number; fall back to a stderr signal otherwise.
|
|
47
|
-
const toolResponse = payload.tool_response || {};
|
|
48
|
-
const stdout = toolResponse.stdout ?? payload.stdout ?? '';
|
|
49
|
-
const stderr = toolResponse.stderr ?? payload.stderr ?? '';
|
|
50
|
-
const rawExitCode = toolResponse.exitCode ?? toolResponse.exit_code ?? payload.exitCode;
|
|
51
|
-
const exitCode = typeof rawExitCode === 'number' ? rawExitCode : undefined;
|
|
52
|
-
const stderrSignal = typeof stderr === 'string' && stderr.trim().length > 0;
|
|
53
|
-
const isFailed = (exitCode !== undefined && exitCode !== 0) || (exitCode === undefined && stderrSignal);
|
|
54
|
-
const toolName = payload.tool_name || payload.tool || 'command';
|
|
55
|
-
|
|
56
|
-
if (isFailed) {
|
|
57
|
-
// Truncate output to avoid state bloat
|
|
58
|
-
let output = (stderrSignal ? stderr : stdout) || payload.output || '';
|
|
59
|
-
if (output.length > 500) {
|
|
60
|
-
output = '...' + output.slice(-500);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
state.status = 'failed';
|
|
64
|
-
state.timestamp = new Date().toISOString();
|
|
65
|
-
state.tool = toolName;
|
|
66
|
-
state.exitCode = exitCode;
|
|
67
|
-
state.errorSummary = output.trim();
|
|
68
|
-
} else if (exitCode === 0 && state.status === 'failed') {
|
|
69
|
-
// Clear failed state or mark as idle/resolved
|
|
70
|
-
state.lastResolved = { tool: state.tool, timestamp: state.timestamp };
|
|
71
|
-
state.status = 'idle';
|
|
72
|
-
state.timestamp = new Date().toISOString();
|
|
73
|
-
delete state.exitCode;
|
|
74
|
-
delete state.errorSummary;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Milestones for the Stop gate: when did the last mutation happen, and
|
|
78
|
-
// has any verification-ish command succeeded since.
|
|
79
|
-
if (toolName === 'Edit' || toolName === 'Write') {
|
|
80
|
-
state.lastEditAt = Date.now();
|
|
81
|
-
} else if ((toolName === 'Bash' || toolName === 'PowerShell') && !isFailed) {
|
|
82
|
-
const command = (payload.tool_input && payload.tool_input.command) || '';
|
|
83
|
-
if (VERIFY_COMMAND_RE.test(command)) {
|
|
84
|
-
state.lastVerifyAt = Date.now();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
|
|
89
|
-
} else {
|
|
90
|
-
// No standard input payload, or invalid JSON. Just maintain a heartbeat timestamp
|
|
91
|
-
if (!fs.existsSync(stateFile)) {
|
|
92
|
-
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
} catch (err) {
|
|
96
|
-
// Fail silently in hooks
|
|
97
|
-
}
|
|
98
|
-
process.exit(0);
|
|
99
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { getWorkspaceRoot, getSessionDir } = require('./lib/harness-state');
|
|
5
|
+
|
|
6
|
+
// Commands that count as "verification ran" for the Stop gate
|
|
7
|
+
// (hooks/scripts/stop-gate.js). Recall over precision: under-blocking the
|
|
8
|
+
// gate is the correct failure direction, so a broad net is fine.
|
|
9
|
+
const VERIFY_COMMAND_RE = /\b(test|spec|jest|vitest|mocha|pytest|rspec|phpunit|tsc|eslint|lint|build|compile|verify|check)\b/i;
|
|
10
|
+
|
|
11
|
+
let inputData = '';
|
|
12
|
+
const timeout = setTimeout(() => {
|
|
13
|
+
processState(null);
|
|
14
|
+
}, 200);
|
|
15
|
+
|
|
16
|
+
process.stdin.on('data', chunk => {
|
|
17
|
+
inputData += chunk;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
process.stdin.on('end', () => {
|
|
21
|
+
clearTimeout(timeout);
|
|
22
|
+
try {
|
|
23
|
+
const payload = JSON.parse(inputData.trim());
|
|
24
|
+
processState(payload);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
processState(null);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function processState(payload) {
|
|
31
|
+
try {
|
|
32
|
+
const sessionId = payload && payload.session_id;
|
|
33
|
+
const stateFile = path.join(getSessionDir(getWorkspaceRoot(), sessionId), 'handoff-state.json');
|
|
34
|
+
|
|
35
|
+
// Merge into the existing state rather than replacing it, so the
|
|
36
|
+
// failure/idle status and the Stop-gate milestones can coexist.
|
|
37
|
+
let state = { status: 'idle', timestamp: new Date().toISOString() };
|
|
38
|
+
if (fs.existsSync(stateFile)) {
|
|
39
|
+
try { state = JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (e) { /* keep default */ }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (payload) {
|
|
43
|
+
// Claude Code nests tool output under tool_response, not at the top
|
|
44
|
+
// level, and uses tool_name rather than tool. A numeric exit code
|
|
45
|
+
// also isn't guaranteed to be present at all - only trust it when
|
|
46
|
+
// it's actually a number; fall back to a stderr signal otherwise.
|
|
47
|
+
const toolResponse = payload.tool_response || {};
|
|
48
|
+
const stdout = toolResponse.stdout ?? payload.stdout ?? '';
|
|
49
|
+
const stderr = toolResponse.stderr ?? payload.stderr ?? '';
|
|
50
|
+
const rawExitCode = toolResponse.exitCode ?? toolResponse.exit_code ?? payload.exitCode;
|
|
51
|
+
const exitCode = typeof rawExitCode === 'number' ? rawExitCode : undefined;
|
|
52
|
+
const stderrSignal = typeof stderr === 'string' && stderr.trim().length > 0;
|
|
53
|
+
const isFailed = (exitCode !== undefined && exitCode !== 0) || (exitCode === undefined && stderrSignal);
|
|
54
|
+
const toolName = payload.tool_name || payload.tool || 'command';
|
|
55
|
+
|
|
56
|
+
if (isFailed) {
|
|
57
|
+
// Truncate output to avoid state bloat
|
|
58
|
+
let output = (stderrSignal ? stderr : stdout) || payload.output || '';
|
|
59
|
+
if (output.length > 500) {
|
|
60
|
+
output = '...' + output.slice(-500);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
state.status = 'failed';
|
|
64
|
+
state.timestamp = new Date().toISOString();
|
|
65
|
+
state.tool = toolName;
|
|
66
|
+
state.exitCode = exitCode;
|
|
67
|
+
state.errorSummary = output.trim();
|
|
68
|
+
} else if (exitCode === 0 && state.status === 'failed') {
|
|
69
|
+
// Clear failed state or mark as idle/resolved
|
|
70
|
+
state.lastResolved = { tool: state.tool, timestamp: state.timestamp };
|
|
71
|
+
state.status = 'idle';
|
|
72
|
+
state.timestamp = new Date().toISOString();
|
|
73
|
+
delete state.exitCode;
|
|
74
|
+
delete state.errorSummary;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Milestones for the Stop gate: when did the last mutation happen, and
|
|
78
|
+
// has any verification-ish command succeeded since.
|
|
79
|
+
if (toolName === 'Edit' || toolName === 'Write') {
|
|
80
|
+
state.lastEditAt = Date.now();
|
|
81
|
+
} else if ((toolName === 'Bash' || toolName === 'PowerShell') && !isFailed) {
|
|
82
|
+
const command = (payload.tool_input && payload.tool_input.command) || '';
|
|
83
|
+
if (VERIFY_COMMAND_RE.test(command)) {
|
|
84
|
+
state.lastVerifyAt = Date.now();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
|
|
89
|
+
} else {
|
|
90
|
+
// No standard input payload, or invalid JSON. Just maintain a heartbeat timestamp
|
|
91
|
+
if (!fs.existsSync(stateFile)) {
|
|
92
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
// Fail silently in hooks
|
|
97
|
+
}
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|