harness-everything 0.2.0

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.
Files changed (169) hide show
  1. package/AGENTS.md +2 -0
  2. package/BENCHMARK_SOP.md +62 -0
  3. package/CHANGELOG.md +107 -0
  4. package/Dockerfile +18 -0
  5. package/LICENSE +201 -0
  6. package/README.md +197 -0
  7. package/VERIFICATION.md +347 -0
  8. package/bin/cli.js +97 -0
  9. package/build-multi-agent-system/AGENTS.md +50 -0
  10. package/build-multi-agent-system/README.md +63 -0
  11. package/build-multi-agent-system/SKILL.md +68 -0
  12. package/create-agent-launcher/SKILL.md +48 -0
  13. package/create-agent-launcher/examples/csharp-monorepo.md +123 -0
  14. package/create-agent-launcher/examples/typescript-cli.md +126 -0
  15. package/create-agent-launcher/guidelines/platform-claude.md +77 -0
  16. package/create-agent-launcher/guidelines/platform-codex.md +146 -0
  17. package/create-agent-launcher/guidelines/platform-copilot.md +74 -0
  18. package/create-agent-launcher/guidelines/platform-gemini.md +101 -0
  19. package/create-agent-launcher/guidelines/role-capabilities.md +108 -0
  20. package/create-agent-launcher/templates/README.md +17 -0
  21. package/create-agent-launcher/templates/agent-launcher.md +68 -0
  22. package/create-agent-launcher/templates/backend-developer-csharp.md +56 -0
  23. package/create-agent-launcher/templates/backend-developer-polyglot.md +62 -0
  24. package/create-agent-launcher/templates/backend-developer-ts.md +57 -0
  25. package/create-agent-launcher/templates/memory-keeper.md +37 -0
  26. package/create-agent-launcher/templates/requirement-analyzer.md +66 -0
  27. package/create-agent-launcher/templates/specialist-agent.md +34 -0
  28. package/create-agent-launcher/templates/task-verifier.md +56 -0
  29. package/create-agent-launcher/templates/tool-maker.md +33 -0
  30. package/create-agent-launcher/workflows/01-init.md +22 -0
  31. package/create-agent-launcher/workflows/02-analysis.md +26 -0
  32. package/create-agent-launcher/workflows/03-generation.md +29 -0
  33. package/create-agent-launcher/workflows/04-launcher.md +20 -0
  34. package/docker-verify.sh +266 -0
  35. package/docs/architecture.md +95 -0
  36. package/docs/philosophy.md +45 -0
  37. package/docs/reflection.md +34 -0
  38. package/docs/routing.md +45 -0
  39. package/docs/workflows/build-multi-agent-system.md +62 -0
  40. package/docs/workflows/create-agent-launcher.md +62 -0
  41. package/docs/workflows/environment-detection.md +63 -0
  42. package/docs/workflows/eval-harness.md +57 -0
  43. package/docs/workflows/fable-discipline.md +59 -0
  44. package/docs/workflows/fable-mode.md +32 -0
  45. package/docs/workflows/git-commit.md +62 -0
  46. package/docs/workflows/grill-me.md +62 -0
  47. package/docs/workflows/grill-with-docs.md +62 -0
  48. package/docs/workflows/harness-everything.md +92 -0
  49. package/docs/workflows/improve-codebase-architecture.md +60 -0
  50. package/docs/workflows/install-cognitive-os.md +60 -0
  51. package/docs/workflows/repo-docs.md +59 -0
  52. package/docs/workflows/rewrite-commits.md +60 -0
  53. package/docs/workflows/security-review.md +58 -0
  54. package/docs/workflows/self-evolve.md +59 -0
  55. package/docs/workflows/skill-creator.md +75 -0
  56. package/docs/workflows/skill-style.md +64 -0
  57. package/docs/workflows/tdd.md +39 -0
  58. package/docs/workflows/todo-driven-workflow.md +36 -0
  59. package/docs/workflows/using-git-worktrees.md +63 -0
  60. package/docs/workflows/verification-loop.md +69 -0
  61. package/docs/workflows/verify-before-claim.md +60 -0
  62. package/docs/workflows/zoom-out.md +62 -0
  63. package/environment-detection/SKILL.md +77 -0
  64. package/environment-detection/scripts/preflight.js +93 -0
  65. package/eval-framework/behavioral-test.js +105 -0
  66. package/eval-framework/cases/case1.json +5 -0
  67. package/eval-framework/cases/case2.json +5 -0
  68. package/eval-framework/cases/case3.json +5 -0
  69. package/eval-framework/cases/case4-zh-tier2.json +5 -0
  70. package/eval-framework/cases/case5-zh-tier3.json +5 -0
  71. package/eval-framework/mechanism-test.js +251 -0
  72. package/eval-framework/runner.js +56 -0
  73. package/eval-harness/SKILL.md +59 -0
  74. package/eval-harness/scripts/evaluate.js +61 -0
  75. package/fable-discipline/SKILL.md +38 -0
  76. package/fable-mode/CONTRACT-FORMAT.md +51 -0
  77. package/fable-mode/SKILL.md +51 -0
  78. package/fable-mode/agents/fable-orchestrator.md +92 -0
  79. package/fable-mode/agents/fable-verifier.md +32 -0
  80. package/fable-mode/agents/fable-worker-haiku.md +48 -0
  81. package/fable-mode/agents/fable-worker-sonnet.md +49 -0
  82. package/fable-mode/execution-guardrails/SKILL.md +87 -0
  83. package/fable-mode/fable-haiku/SKILL.md +48 -0
  84. package/git-commit/SKILL.md +55 -0
  85. package/git-commit/guides/ANGULAR_STYLE.md +61 -0
  86. package/git-commit/guides/COMMIT_GENERATION.md +24 -0
  87. package/git-commit/guides/LANGUAGE_DETECTION.md +16 -0
  88. package/git-commit/guides/MAIN_REPO.md +15 -0
  89. package/git-commit/guides/SUBMODULES.md +27 -0
  90. package/grill-me/SKILL.md +36 -0
  91. package/grill-with-docs/ADR-FORMAT.md +47 -0
  92. package/grill-with-docs/CONTEXT-FORMAT.md +63 -0
  93. package/grill-with-docs/SKILL.md +99 -0
  94. package/harness-everything/SKILL.md +141 -0
  95. package/harness-everything/examples/README.md +9 -0
  96. package/harness-everything/examples/todo-workflow.md +22 -0
  97. package/harness-everything/scripts/bootstrap.js +140 -0
  98. package/harness-everything/scripts/self-heal.js +189 -0
  99. package/harness-everything/scripts/tier-router.js +219 -0
  100. package/harness-everything/scripts/todo-cli.js +157 -0
  101. package/harness-everything/scripts/verify-gate.js +31 -0
  102. package/hooks/hooks.json +155 -0
  103. package/hooks/scripts/atomic-commit-check.js +68 -0
  104. package/hooks/scripts/boundary-guard.js +55 -0
  105. package/hooks/scripts/context-compact.js +114 -0
  106. package/hooks/scripts/contract-test.js +79 -0
  107. package/hooks/scripts/depth-guard.js +65 -0
  108. package/hooks/scripts/lib/harness-state.js +202 -0
  109. package/hooks/scripts/lib/platforms/claude.js +42 -0
  110. package/hooks/scripts/lib/platforms/codex.js +46 -0
  111. package/hooks/scripts/lib/platforms/continue.js +41 -0
  112. package/hooks/scripts/lib/platforms/copilot.js +41 -0
  113. package/hooks/scripts/lib/platforms/cursor.js +41 -0
  114. package/hooks/scripts/lib/platforms/hermes.js +32 -0
  115. package/hooks/scripts/lib/platforms/index.js +17 -0
  116. package/hooks/scripts/lib/platforms/worktrees.js +20 -0
  117. package/hooks/scripts/reset-circuit-breaker.js +30 -0
  118. package/hooks/scripts/rule-of-3-tracker.js +91 -0
  119. package/hooks/scripts/rule-of-3.js +176 -0
  120. package/hooks/scripts/state-persist.js +99 -0
  121. package/hooks/scripts/stop-gate.js +80 -0
  122. package/hooks/scripts/subagent-scope-guard.js +88 -0
  123. package/improve-codebase-architecture/SKILL.md +44 -0
  124. package/improve-codebase-architecture/guides/DEEPENING.md +37 -0
  125. package/improve-codebase-architecture/guides/HTML-REPORT.md +123 -0
  126. package/improve-codebase-architecture/guides/INTERFACE-DESIGN.md +44 -0
  127. package/improve-codebase-architecture/guides/LANGUAGE.md +53 -0
  128. package/install-cognitive-os/SKILL.md +95 -0
  129. package/package.json +22 -0
  130. package/repo-docs/SKILL.md +45 -0
  131. package/repo-docs/templates/agents-template.md +264 -0
  132. package/repo-docs/templates/knowledge-agents-template.md +50 -0
  133. package/repo-docs/templates/knowledge-readme-template.md +83 -0
  134. package/repo-docs/templates/manual-recon.md +117 -0
  135. package/repo-docs/templates/multi-skills-readme-template.md +72 -0
  136. package/repo-docs/templates/product-agents-template.md +78 -0
  137. package/repo-docs/templates/product-readme-template.md +95 -0
  138. package/repo-docs/templates/readme-template.md +136 -0
  139. package/repo-docs/templates/single-skill-readme-template.md +70 -0
  140. package/repo-docs/templates/skills-agents-template.md +60 -0
  141. package/rewrite-commits/SKILL.md +32 -0
  142. package/scripts/installer.js +649 -0
  143. package/scripts/lib/advisory-text.js +163 -0
  144. package/scripts/lib/claude-hooks.js +71 -0
  145. package/scripts/lib/gitignore.js +58 -0
  146. package/scripts/lib/manifest.js +82 -0
  147. package/scripts/lib/prompts.js +241 -0
  148. package/scripts/lib/skills.js +172 -0
  149. package/scripts/lib/workspace.js +28 -0
  150. package/security-review/SKILL.md +511 -0
  151. package/self-evolve/SKILL.md +54 -0
  152. package/self-evolve/scripts/persist-memory.js +40 -0
  153. package/self-evolve/scripts/self-regression.js +113 -0
  154. package/skill-creator/SKILL.md +91 -0
  155. package/skill-creator/references/quality-principles.md +81 -0
  156. package/skill-creator/references/testing-workflow.md +32 -0
  157. package/skill-style/SKILL.md +48 -0
  158. package/skill-style/STYLE.md +37 -0
  159. package/tdd/SKILL.md +53 -0
  160. package/tdd/guides/deep-modules.md +33 -0
  161. package/tdd/guides/interface-design.md +31 -0
  162. package/tdd/guides/mocking.md +59 -0
  163. package/tdd/guides/refactoring.md +10 -0
  164. package/tdd/guides/tests.md +61 -0
  165. package/todo-driven-workflow/SKILL.md +54 -0
  166. package/using-git-worktrees/SKILL.md +161 -0
  167. package/verification-loop/SKILL.md +138 -0
  168. package/verify-before-claim/SKILL.md +86 -0
  169. package/zoom-out/SKILL.md +90 -0
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ const { execSync } = require('child_process');
3
+
4
+ function run(userPrompt) {
5
+ console.log(`[Tier Routing Pre-check]`);
6
+
7
+ const promptLower = userPrompt.toLowerCase();
8
+
9
+ // Basic keyword heuristic (bilingual - the Human Partner often prompts in
10
+ // Chinese, and an English-only net silently degrades to Tier 1 for them).
11
+ // Deliberately NOT driven by the diff stats above: those measure what is
12
+ // already sitting uncommitted in the tree - usually the PREVIOUS task's
13
+ // leftovers - not the complexity of the task being asked for now.
14
+ const TIER3_KEYWORDS = ["architecture", "refactor", "rewrite the", "架構", "重構", "重寫"];
15
+ const TIER2_KEYWORDS = ["test", "api", "integration", "endpoint", "測試", "整合", "端點", "介面"];
16
+
17
+ let recommendedTier = "Tier 1 (Trivial)";
18
+ let rationale = "No structural/testing signals in the prompt.";
19
+
20
+ if (TIER3_KEYWORDS.some(k => promptLower.includes(k))) {
21
+ recommendedTier = "Tier 3 (Macro Task)";
22
+ rationale = "Prompt implies system-wide or architectural change.";
23
+ } else if (TIER2_KEYWORDS.some(k => promptLower.includes(k))) {
24
+ recommendedTier = "Tier 2 (Standard Task)";
25
+ rationale = "Prompt implies development work needing TDD validation or multi-file coordination.";
26
+ }
27
+
28
+ console.log(`\n=> RECOMMENDED TIER: ${recommendedTier}`);
29
+ console.log(`=> RATIONALE: ${rationale}`);
30
+
31
+ // Base execution loop: Tier 2/3 must run on the todo-driven-workflow
32
+ // checklist (Tier 1 is exempt to avoid checklist bloat on trivial edits).
33
+ if (!recommendedTier.startsWith("Tier 1")) {
34
+ console.log(`\n=> BASE EXECUTION LOOP: Load 'todo-driven-workflow' and initialize its checklist (3-7 verifiable sub-tasks) BEFORE editing any file.`);
35
+ console.log(` Track exactly ONE item in-progress at a time; verify with real evidence before marking completed.`);
36
+ }
37
+
38
+ // Analyze and output relevant Knowledge Guides / Templates based on user prompt keywords
39
+ const recommendedGuides = [];
40
+
41
+ const TDD_TEST_KEYWORDS = [
42
+ "tdd", "test", "mock", "stub", "api", "endpoint", "integration", "debugging", "bug", "error", "fix",
43
+ "測試", "單測", "模組測試", "端點", "介面", "除錯", "錯誤", "修復"
44
+ ];
45
+ if (TDD_TEST_KEYWORDS.some(k => promptLower.includes(k))) {
46
+ recommendedGuides.push(
47
+ "- tdd/SKILL.md (Test-Driven Development Red-Green-Refactor loop)",
48
+ "- tdd/guides/mocking.md (Mocking principles & isolation)",
49
+ "- tdd/guides/interface-design.md (Interface and contract design)",
50
+ "- tdd/guides/deep-modules.md (Testing deep nested modules)",
51
+ "- tdd/guides/tests.md (General test architecture)",
52
+ "- environment-detection/SKILL.md (Detect active shell/OS & preflight syntax before running commands)",
53
+ "- verify-before-claim/SKILL.md (Fact-audit discipline: verify external claims and unmeasured estimates before asserting them)",
54
+ "- verification-loop/SKILL.md (Pre-PR verification gate: build, types, lint, tests, security scan)"
55
+ );
56
+ }
57
+
58
+ const GIT_COMMIT_KEYWORDS = [
59
+ "commit", "git", "save", "submodule", "pr", "pull request", "release", "quality gate", "ready to ship",
60
+ "提交", "版控", "合併", "分支", "發行"
61
+ ];
62
+ if (GIT_COMMIT_KEYWORDS.some(k => promptLower.includes(k))) {
63
+ recommendedGuides.push(
64
+ "- git-commit/SKILL.md (Angular-style commit convention generation)",
65
+ "- git-commit/guides/ANGULAR_STYLE.md (Commit conventions reference)",
66
+ "- git-commit/guides/COMMIT_GENERATION.md (Commit generation patterns)",
67
+ "- git-commit/guides/LANGUAGE_DETECTION.md (Multi-language commits)",
68
+ "- git-commit/guides/MAIN_REPO.md (Commits in main repositories)",
69
+ "- git-commit/guides/SUBMODULES.md (Submodule commit handling)",
70
+ "- rewrite-commits/SKILL.md (Rewrite commit history safely to Angular style)",
71
+ "- using-git-worktrees/SKILL.md (Git Worktrees isolation for feature work, avoids workspace pollution)",
72
+ "- verification-loop/SKILL.md (Pre-PR verification gate: build, types, lint, tests, security scan)"
73
+ );
74
+ }
75
+
76
+ if (promptLower.includes("doc") || promptLower.includes("readme") || promptLower.includes("文件") || promptLower.includes("說明文件")) {
77
+ recommendedGuides.push(
78
+ "- repo-docs/templates/readme-template.md (Standard README template)",
79
+ "- repo-docs/templates/product-readme-template.md (Product README template)",
80
+ "- repo-docs/templates/agents-template.md (Agent onboarding instructions template)"
81
+ );
82
+ }
83
+
84
+ const AGENT_KEYWORDS = [
85
+ "agent", "multi-agent", "launcher", "subagent", "sub-agent", "delegate", "orchestrate", "specialist",
86
+ "workspace scaffolding", "scaffold workspace", "division of labor", "fable", "macro", "orchestrator",
87
+ "代理", "多代理", "啟動器", "子代理", "委派", "指派", "分工", "協調", "任務分配", "規劃"
88
+ ];
89
+ if (AGENT_KEYWORDS.some(k => promptLower.includes(k))) {
90
+ recommendedGuides.push(
91
+ "- fable-mode/SKILL.md (Macro task planning & execution orchestrator)",
92
+ "- fable-discipline/SKILL.md (Shadow guard preventing context bloat and managing token limits)",
93
+ "- build-multi-agent-system/SKILL.md (Universal Multi-Agent Workspace scaffolding & memory db)",
94
+ "- create-agent-launcher/SKILL.md (Sub-agent generator for specialized task delegation)",
95
+ "- repo-docs/templates/agents-template.md (Agent onboarding instructions template)",
96
+ "- grill-with-docs/SKILL.md (Decision tracking, Glossary & ADR-driven design grilling)"
97
+ );
98
+ }
99
+
100
+ const ARCH_REFACTOR_KEYWORDS = [
101
+ "refactor", "architecture", "structure", "couple", "seam", "adr", "design plan", "decision", "grill",
102
+ "重構", "架構", "結構", "解耦", "設計", "決策", "辯論", "質疑"
103
+ ];
104
+ if (ARCH_REFACTOR_KEYWORDS.some(k => promptLower.includes(k))) {
105
+ recommendedGuides.push(
106
+ "- improve-codebase-architecture/guides/DEEPENING.md (Deepening opportunities & depth rules)",
107
+ "- improve-codebase-architecture/guides/INTERFACE-DESIGN.md (Interface design principles)",
108
+ "- improve-codebase-architecture/guides/LANGUAGE.md (Language-specific patterns)",
109
+ "- improve-codebase-architecture/guides/HTML-REPORT.md (Mermaid dependency report generation)",
110
+ "- grill-with-docs/SKILL.md (Decision tracking, Glossary & ADR-driven design grilling)",
111
+ "- grill-me/SKILL.md (Challenger interview to stress-test your architecture plan)",
112
+ "- fable-mode/SKILL.md (Macro task planning & execution orchestrator)"
113
+ );
114
+ }
115
+
116
+ const ENV_KEYWORDS = [
117
+ "shell", "terminal", "powershell", "bash", "cmd", "env", "preflight", "command", "run",
118
+ "終端機", "命令", "環境", "指令", "執行"
119
+ ];
120
+ if (ENV_KEYWORDS.some(k => promptLower.includes(k))) {
121
+ recommendedGuides.push(
122
+ "- environment-detection/SKILL.md (Detect active shell/OS & preflight syntax before running commands)",
123
+ "- using-git-worktrees/SKILL.md (Git Worktrees isolation for feature work, avoids workspace pollution)"
124
+ );
125
+ }
126
+
127
+ const VERIFY_KEYWORDS = [
128
+ "verify", "fact", "audit", "estimate", "benchmark", "performance", "speed", "scale",
129
+ "驗證", "查證", "核對", "效能", "評測", "性能", "估計"
130
+ ];
131
+ if (VERIFY_KEYWORDS.some(k => promptLower.includes(k))) {
132
+ recommendedGuides.push(
133
+ "- verify-before-claim/SKILL.md (Fact-audit discipline: verify external claims and unmeasured estimates before asserting them)",
134
+ "- verification-loop/SKILL.md (Pre-PR verification gate: build, types, lint, tests, security scan)",
135
+ "- eval-harness/SKILL.md (AI performance evaluation metrics & anti-loop metrics)"
136
+ );
137
+ }
138
+
139
+ if (/\bskill\b|skill\.md|new skill|write a skill/.test(promptLower)) {
140
+ recommendedGuides.push(
141
+ "- skill-creator/SKILL.md (Authoring, auditing, and testing workflow for SKILL.md files, incl. dynamic skill generation)",
142
+ "- skill-style/SKILL.md (Terse Skill Contract format spec that skill-creator builds on)"
143
+ );
144
+ }
145
+
146
+ if (recommendedGuides.length > 0) {
147
+ console.log(`\n=> RECOMMENDED KNOWLEDGE GUIDES (Auto-loaded based on keywords):`);
148
+ recommendedGuides.forEach(guide => {
149
+ const match = guide.match(/^- ([^\s]+)/);
150
+ if (match) {
151
+ const guidePath = require('path').join(__dirname, '..', '..', match[1]);
152
+ if (!require('fs').existsSync(guidePath)) {
153
+ console.log(`${guide} [NOT INSTALLED - Ignore this recommendation]`);
154
+ return;
155
+ }
156
+ }
157
+ console.log(guide);
158
+ });
159
+ }
160
+
161
+ // Fact-audit nudge: broad, cheap keyword net for claims that risk being
162
+ // asserted from stale/wrong training memory instead of verified. False
163
+ // positives cost nothing here (it's a reminder, not a block) so recall
164
+ // matters more than precision.
165
+ const externalClaimTriggers = [
166
+ "does it support", "does support", "how does", "what's the default", "what is the default",
167
+ "exit code", "schema", "sdk", " api", "hook", "payload", "pricing", "rate limit",
168
+ "latest version", "current version", "deprecated", "breaking change", "changelog",
169
+ "spec", "documentation", "according to", "endpoint", "config option", "flag"
170
+ ];
171
+ const estimateTriggers = [
172
+ "benchmark", "performance", "how fast", "how long will", "how much memory",
173
+ "how many requests", "estimate", "roughly how", "big o", "complexity",
174
+ "will this scale", "throughput", "latency"
175
+ ];
176
+ const hitExternalClaim = externalClaimTriggers.some(kw => promptLower.includes(kw));
177
+ const hitEstimate = estimateTriggers.some(kw => promptLower.includes(kw));
178
+
179
+ if (hitExternalClaim || hitEstimate) {
180
+ console.log(`\n=> FACT-AUDIT REMINDER:`);
181
+ if (hitExternalClaim) {
182
+ console.log(`This looks like it may require a claim about an external framework/library/API/tool's current behavior.`);
183
+ console.log(`Verify via WebFetch/WebSearch against the authoritative source before asserting it - do not answer from training memory alone; it can be stale or confidently wrong (e.g. exit-code semantics, schema fields, defaults, pricing).`);
184
+ }
185
+ if (hitEstimate) {
186
+ console.log(`This looks like it may call for a performance/cost/timing number.`);
187
+ console.log(`Prefer an actual measurement over a reasoned estimate when the stakes justify it - an unmeasured number (including one you generate yourself) is a hypothesis, not a fact.`);
188
+ }
189
+ }
190
+
191
+ // Constraint strength must match judgment reliability: this routing is a
192
+ // keyword heuristic, so it is a default, not an order.
193
+ console.log(`\nTreat the tier above as the default route. If your own read of the task clearly disagrees, follow your read and say why in one line. An explicit instruction from the Human Partner always wins.`);
194
+ }
195
+
196
+ let userPrompt = process.argv[2] || '';
197
+
198
+ if (process.argv[2]) {
199
+ // If a command-line argument is passed, use it and execute immediately.
200
+ run(userPrompt);
201
+ } else if (process.stdin.isTTY) {
202
+ // Running interactively in a terminal without piped input, execute immediately.
203
+ run('');
204
+ } else {
205
+ // Piped input or non-TTY, read from standard input.
206
+ let inputData = '';
207
+ process.stdin.on('data', chunk => { inputData += chunk; });
208
+ process.stdin.on('end', () => {
209
+ try {
210
+ if (inputData.trim()) {
211
+ const payload = JSON.parse(inputData);
212
+ if (typeof payload.prompt === 'string') userPrompt = payload.prompt;
213
+ }
214
+ } catch (err) {
215
+ // Not valid JSON on stdin - fall back to argv (useful for direct/manual testing).
216
+ }
217
+ run(userPrompt);
218
+ });
219
+ }
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Harness Todo CLI
4
+ * A strict state machine for task management.
5
+ * Designed to slap the LLM with Exit Code 1 if it violates the Todo-Driven Workflow.
6
+ */
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const { getWorkspaceRoot, getStateRoot } = require('../../hooks/scripts/lib/harness-state');
10
+
11
+ // Shared across sessions (not scoped to one): todo-cli.js is invoked as a
12
+ // plain CLI command by the agent, not a hook, so it never receives a
13
+ // session_id to scope by.
14
+ const harnessDir = getStateRoot(getWorkspaceRoot());
15
+ const stateFile = path.join(harnessDir, 'todo-state.json');
16
+
17
+ if (!fs.existsSync(harnessDir)) {
18
+ fs.mkdirSync(harnessDir, { recursive: true });
19
+ }
20
+
21
+ function loadState() {
22
+ if (fs.existsSync(stateFile)) {
23
+ return JSON.parse(fs.readFileSync(stateFile, 'utf8'));
24
+ }
25
+ return { tasks: [], activeId: null };
26
+ }
27
+
28
+ function saveState(state) {
29
+ // Atomic write (temp file + rename): todo-state.json is shared across the
30
+ // whole workspace, not scoped per session_id like the hook state files
31
+ // are, so parallel subagent Task bursts can genuinely call `todo-cli.js`
32
+ // around the same time. A plain writeFileSync lets a reader observe a
33
+ // truncated/partial JSON file if two writes interleave; rename is atomic
34
+ // at the filesystem level, so readers only ever see the old or the new
35
+ // file in full, never a half-written one. This doesn't resolve the
36
+ // separate lost-update race (last writer still wins) - that needs real
37
+ // cross-process locking, out of scope for what a CLI state file needs.
38
+ const tmpFile = `${stateFile}.tmp.${process.pid}`;
39
+ fs.writeFileSync(tmpFile, JSON.stringify(state, null, 2));
40
+ fs.renameSync(tmpFile, stateFile);
41
+ }
42
+
43
+ function printList(state) {
44
+ console.log('\n📋 Current Todo List:');
45
+ if (state.tasks.length === 0) {
46
+ console.log(' (Empty)');
47
+ }
48
+ state.tasks.forEach(t => {
49
+ const status = t.id === state.activeId ? '[IN-PROGRESS]' : (t.completed ? '[COMPLETED]' : '[NOT-STARTED]');
50
+ console.log(` ${t.id}. ${status} ${t.title}`);
51
+ });
52
+ console.log('');
53
+ }
54
+
55
+ const args = process.argv.slice(2);
56
+ const command = args[0];
57
+
58
+ if (!command) {
59
+ console.error("❌ Error: Missing command. Use 'init', 'add', 'start', 'complete', or 'status'.");
60
+ process.exit(1);
61
+ }
62
+
63
+ const state = loadState();
64
+
65
+ switch (command) {
66
+ case 'init':
67
+ state.tasks = [];
68
+ state.activeId = null;
69
+ args.slice(1).forEach((title, idx) => {
70
+ state.tasks.push({ id: idx + 1, title, completed: false });
71
+ });
72
+ saveState(state);
73
+ console.log("✅ Todo list initialized.");
74
+ printList(state);
75
+ break;
76
+
77
+ case 'add':
78
+ const title = args.slice(1).join(' ');
79
+ if (!title) {
80
+ console.error("❌ Error: Missing task title.");
81
+ process.exit(1);
82
+ }
83
+ const nextId = state.tasks.length > 0 ? Math.max(...state.tasks.map(t => t.id)) + 1 : 1;
84
+ state.tasks.push({ id: nextId, title, completed: false });
85
+ saveState(state);
86
+ console.log(`✅ Added task ${nextId}.`);
87
+ printList(state);
88
+ break;
89
+
90
+ case 'start':
91
+ const startId = parseInt(args[1], 10);
92
+ if (!startId) {
93
+ console.error("❌ Error: Missing task ID. Usage: start <id>");
94
+ process.exit(1);
95
+ }
96
+ if (state.activeId !== null && state.activeId !== startId) {
97
+ console.error(`❌ [BLOCKED] Task ${state.activeId} is already IN-PROGRESS.`);
98
+ console.error(`You MUST complete or un-start task ${state.activeId} before starting a new one. No multitasking.`);
99
+ process.exit(1);
100
+ }
101
+ const taskToStart = state.tasks.find(t => t.id === startId);
102
+ if (!taskToStart) {
103
+ console.error(`❌ Error: Task ${startId} not found.`);
104
+ process.exit(1);
105
+ }
106
+ if (taskToStart.completed) {
107
+ console.error(`❌ Error: Task ${startId} is already completed.`);
108
+ process.exit(1);
109
+ }
110
+ state.activeId = startId;
111
+ saveState(state);
112
+ console.log(`🚀 Started task ${startId}: ${taskToStart.title}`);
113
+ break;
114
+
115
+ case 'complete':
116
+ const compId = parseInt(args[1], 10);
117
+ if (!compId) {
118
+ console.error("❌ Error: Missing task ID. Usage: complete <id>");
119
+ process.exit(1);
120
+ }
121
+ if (state.activeId !== compId) {
122
+ console.error(`❌ [BLOCKED] Task ${compId} is NOT currently in-progress.`);
123
+ console.error(`You can only complete the active task. Active task is: ${state.activeId || 'None'}`);
124
+ process.exit(1);
125
+ }
126
+
127
+ // ACTIONABLE RECOMMENDATION #1: Enforce State Transitions Programmatically
128
+ // Do not rely on prompt obedience for running verify-gate.js. The CLI should block the complete command
129
+ console.log("=== 🛡️ Executing Pre-Completion Verification Gate ===");
130
+ try {
131
+ const verifyScript = path.join(__dirname, 'verify-gate.js');
132
+ if (fs.existsSync(verifyScript)) {
133
+ require('child_process').execSync(`node "${verifyScript}"`, { stdio: 'inherit' });
134
+ }
135
+ } catch (err) {
136
+ console.error(`\n❌ [BLOCKED] Verification Gate Failed (Exit Code 1).`);
137
+ console.error(`You CANNOT complete this task. The code is broken.`);
138
+ console.error(`Please fix the errors shown above and try again.`);
139
+ process.exit(1);
140
+ }
141
+
142
+ const taskToComp = state.tasks.find(t => t.id === compId);
143
+ taskToComp.completed = true;
144
+ state.activeId = null;
145
+ saveState(state);
146
+ console.log(`✅ Completed task ${compId}: ${taskToComp.title}`);
147
+ printList(state);
148
+ break;
149
+
150
+ case 'status':
151
+ printList(state);
152
+ break;
153
+
154
+ default:
155
+ console.error(`❌ Error: Unknown command '${command}'.`);
156
+ process.exit(1);
157
+ }
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Verification Gatekeeper
4
+ * Forces the AI to run this script to prove quality gates before declaring a task done.
5
+ */
6
+ const { execSync } = require('child_process');
7
+
8
+ console.log("=== 🛡️ Harness Verification Gate ===");
9
+
10
+ try {
11
+ console.log("Running basic checks (simulated for now)...");
12
+
13
+ // In a real project, this would run `npm run lint` and `npm test`
14
+ // We'll simulate a failure if `.verify-fail.tmp` exists just to prove the mechanism.
15
+ const fs = require('fs');
16
+ if (fs.existsSync('.verify-fail.tmp')) {
17
+ console.error("❌ Verification FAILED: Found broken tests or lint errors.");
18
+ console.error("Please fix the code and run this gate again.");
19
+ process.exit(1);
20
+ }
21
+
22
+ console.log("✅ Lint passed.");
23
+ console.log("✅ Tests passed.");
24
+ console.log("✅ Verification SUCCESS. You may now complete the task.");
25
+ process.exit(0);
26
+
27
+ } catch (err) {
28
+ console.error("❌ Verification FAILED.");
29
+ console.error(err.message);
30
+ process.exit(1);
31
+ }
@@ -0,0 +1,155 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node harness-everything/scripts/bootstrap.js"
10
+ }
11
+ ],
12
+ "description": "Bootstrap Harness Skills OS on session start",
13
+ "id": "harness:pre:bootstrap"
14
+ }
15
+ ],
16
+ "UserPromptSubmit": [
17
+ {
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "node harness-everything/scripts/tier-router.js"
22
+ }
23
+ ],
24
+ "description": "Auto-route user requests using tier-router",
25
+ "id": "harness:pre:tier-router"
26
+ }
27
+ ],
28
+ "PreToolUse": [
29
+ {
30
+ "matcher": "Bash|PowerShell|Edit|Write",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "node hooks/scripts/rule-of-3.js"
35
+ }
36
+ ],
37
+ "description": "Rule of 3 Circuit Breaker - Prevents micro-error looping",
38
+ "id": "harness:pre:rule-of-3"
39
+ },
40
+ {
41
+ "matcher": "Grep|Glob|Read",
42
+ "hooks": [
43
+ {
44
+ "type": "command",
45
+ "command": "node hooks/scripts/boundary-guard.js"
46
+ }
47
+ ],
48
+ "description": "Physical boundary enforcement for searches and large file reads",
49
+ "id": "harness:pre:boundary-guard"
50
+ },
51
+ {
52
+ "matcher": "Edit|Write",
53
+ "hooks": [
54
+ {
55
+ "type": "command",
56
+ "command": "node hooks/scripts/depth-guard.js"
57
+ }
58
+ ],
59
+ "description": "Information depth guard - Enforce impact assessment before writing code",
60
+ "id": "harness:pre:depth-guard"
61
+ },
62
+ {
63
+ "matcher": "Edit|Write|Bash|PowerShell",
64
+ "hooks": [
65
+ {
66
+ "type": "command",
67
+ "command": "node hooks/scripts/context-compact.js"
68
+ }
69
+ ],
70
+ "description": "Strategic context compaction enforcement",
71
+ "id": "harness:pre:context-compact"
72
+ },
73
+ {
74
+ "matcher": "Task",
75
+ "hooks": [
76
+ {
77
+ "type": "command",
78
+ "command": "node hooks/scripts/subagent-scope-guard.js"
79
+ }
80
+ ],
81
+ "description": "Snapshot repo state before a subagent burst starts",
82
+ "id": "harness:pre:subagent-scope-guard"
83
+ }
84
+ ],
85
+ "Stop": [
86
+ {
87
+ "hooks": [
88
+ {
89
+ "type": "command",
90
+ "command": "node hooks/scripts/stop-gate.js"
91
+ }
92
+ ],
93
+ "description": "Pre-delivery gate - bounce the end of a turn once per edit batch when edits were never verified",
94
+ "id": "harness:stop:stop-gate"
95
+ }
96
+ ],
97
+ "PostToolUse": [
98
+ {
99
+ "matcher": "Bash|PowerShell",
100
+ "hooks": [
101
+ {
102
+ "type": "command",
103
+ "command": "node hooks/scripts/rule-of-3-tracker.js"
104
+ }
105
+ ],
106
+ "description": "Track error signatures for Rule of 3",
107
+ "id": "harness:post:rule-of-3-tracker"
108
+ },
109
+ {
110
+ "matcher": "Edit|Write|Bash|PowerShell",
111
+ "hooks": [
112
+ {
113
+ "type": "command",
114
+ "command": "node hooks/scripts/state-persist.js"
115
+ }
116
+ ],
117
+ "description": "Save skill transition state",
118
+ "id": "harness:post:state-persist"
119
+ },
120
+ {
121
+ "matcher": "Edit|Write",
122
+ "hooks": [
123
+ {
124
+ "type": "command",
125
+ "command": "node hooks/scripts/atomic-commit-check.js"
126
+ }
127
+ ],
128
+ "description": "Atomic commit enforcement",
129
+ "id": "harness:post:atomic-commit-check"
130
+ },
131
+ {
132
+ "matcher": "Bash|PowerShell",
133
+ "hooks": [
134
+ {
135
+ "type": "command",
136
+ "command": "node hooks/scripts/contract-test.js"
137
+ }
138
+ ],
139
+ "description": "Contract testing between sub-agents",
140
+ "id": "harness:post:contract-test"
141
+ },
142
+ {
143
+ "matcher": "Task",
144
+ "hooks": [
145
+ {
146
+ "type": "command",
147
+ "command": "node hooks/scripts/subagent-scope-guard.js"
148
+ }
149
+ ],
150
+ "description": "Diff the whole repo after a subagent burst finishes - catches scope creep past what the task briefed",
151
+ "id": "harness:post:subagent-scope-guard"
152
+ }
153
+ ]
154
+ }
155
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Atomic Commit Check (PostToolUse: Edit|Write)
4
+ * PostToolUse can't block - the edit/write already happened. So this counts
5
+ * Edit/Write calls since the last commit and, once the count crosses a
6
+ * threshold, feeds a strong reminder back to Claude (exit 2) to commit the
7
+ * completed chunk before piling on more changes. Resets whenever HEAD moves.
8
+ * Fails open on any error - this is a nudge, never a hard stop.
9
+ */
10
+ const { execSync } = require('child_process');
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const { getWorkspaceRoot, getSessionDir } = require('./lib/harness-state');
14
+
15
+ const THRESHOLD = 6;
16
+ const RENUDGE_EVERY = 3;
17
+
18
+ function main(payload) {
19
+ try {
20
+ const root = getWorkspaceRoot();
21
+ const head = execSync('git rev-parse HEAD', { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
22
+
23
+ const stateFile = path.join(getSessionDir(root, payload && payload.session_id), 'atomic-commit-state.json');
24
+
25
+ let state = { lastHead: head, editCount: 0 };
26
+ if (fs.existsSync(stateFile)) {
27
+ try { state = JSON.parse(fs.readFileSync(stateFile, 'utf8')); } catch (e) { /* use default */ }
28
+ }
29
+
30
+ if (state.lastHead !== head) {
31
+ // A commit happened since we last checked - fresh start.
32
+ state.lastHead = head;
33
+ state.editCount = 0;
34
+ }
35
+
36
+ state.editCount += 1;
37
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
38
+
39
+ const overThreshold = state.editCount >= THRESHOLD;
40
+ const onNudgeBeat = overThreshold && (state.editCount - THRESHOLD) % RENUDGE_EVERY === 0;
41
+
42
+ if (onNudgeBeat) {
43
+ const statusRaw = execSync('git status --porcelain', { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
44
+ const changedFiles = statusRaw ? statusRaw.split('\n').length : 0;
45
+ console.error(`[Atomic Commit Check] ${state.editCount} Edit/Write calls since the last commit (${changedFiles} files currently changed).`);
46
+ console.error(`If a logically complete chunk of work is done, commit it now before continuing - large uncommitted diffs are harder to review and harder to recover from.`);
47
+ process.exit(2);
48
+ }
49
+
50
+ process.exit(0);
51
+ } catch (err) {
52
+ process.exit(0);
53
+ }
54
+ }
55
+
56
+ let inputData = '';
57
+ const timeout = setTimeout(() => { main(null); }, 200);
58
+ process.stdin.on('data', chunk => { inputData += chunk; });
59
+ process.stdin.on('end', () => {
60
+ clearTimeout(timeout);
61
+ let payload = null;
62
+ try { payload = JSON.parse(inputData.trim()); } catch (err) { /* no payload */ }
63
+ main(payload);
64
+ });
65
+ process.stdin.on('error', () => {
66
+ clearTimeout(timeout);
67
+ main(null);
68
+ });