all-hands-cli 0.1.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 (305) hide show
  1. package/.allhands/README.md +75 -0
  2. package/.allhands/agents/compounder.yaml +15 -0
  3. package/.allhands/agents/coordinator.yaml +17 -0
  4. package/.allhands/agents/documentor.yaml +15 -0
  5. package/.allhands/agents/e2e-test-planner.yaml +17 -0
  6. package/.allhands/agents/emergent.yaml +22 -0
  7. package/.allhands/agents/executor.yaml +14 -0
  8. package/.allhands/agents/ideation.yaml +11 -0
  9. package/.allhands/agents/initiative-steering.yaml +19 -0
  10. package/.allhands/agents/judge.yaml +13 -0
  11. package/.allhands/agents/planner.yaml +19 -0
  12. package/.allhands/agents/pr-reviewer.yaml +15 -0
  13. package/.allhands/docs.json +5 -0
  14. package/.allhands/docs.local.json +26 -0
  15. package/.allhands/flows/COMPOUNDING.md +203 -0
  16. package/.allhands/flows/COORDINATION.md +89 -0
  17. package/.allhands/flows/CORE.md +87 -0
  18. package/.allhands/flows/DOCUMENTATION.md +218 -0
  19. package/.allhands/flows/E2E_TEST_PLAN_BUILDING.md +140 -0
  20. package/.allhands/flows/EMERGENT_PLANNING.md +57 -0
  21. package/.allhands/flows/IDEATION_SCOPING.md +154 -0
  22. package/.allhands/flows/INITIATIVE_STEERING.md +110 -0
  23. package/.allhands/flows/JUDGE_REVIEWING.md +79 -0
  24. package/.allhands/flows/PROMPT_TASK_EXECUTION.md +68 -0
  25. package/.allhands/flows/PR_REVIEWING.md +43 -0
  26. package/.allhands/flows/SPEC_PLANNING.md +216 -0
  27. package/.allhands/flows/harness/WRITING_HARNESS_FLOWS.md +27 -0
  28. package/.allhands/flows/harness/WRITING_HARNESS_KNOWLEDGE.md +27 -0
  29. package/.allhands/flows/harness/WRITING_HARNESS_ORCHESTRATION.md +27 -0
  30. package/.allhands/flows/harness/WRITING_HARNESS_SKILLS.md +27 -0
  31. package/.allhands/flows/harness/WRITING_HARNESS_TOOLS.md +27 -0
  32. package/.allhands/flows/harness/WRITING_HARNESS_VALIDATION_TOOLING.md +27 -0
  33. package/.allhands/flows/shared/CODEBASE_UNDERSTANDING.md +72 -0
  34. package/.allhands/flows/shared/CREATE_HARNESS_SPEC.md +48 -0
  35. package/.allhands/flows/shared/CREATE_SPEC.md +41 -0
  36. package/.allhands/flows/shared/CREATE_VALIDATION_TOOLING_SPEC.md +70 -0
  37. package/.allhands/flows/shared/DOCUMENTATION_DISCOVERY.md +123 -0
  38. package/.allhands/flows/shared/DOCUMENTATION_WRITER.md +101 -0
  39. package/.allhands/flows/shared/EMERGENT_REFINEMENT_ANALYSIS.md +76 -0
  40. package/.allhands/flows/shared/EXTERNAL_TECH_GUIDANCE.md +97 -0
  41. package/.allhands/flows/shared/IDEATION_CODEBASE_GROUNDING.md +49 -0
  42. package/.allhands/flows/shared/PLAN_DEEPENING.md +152 -0
  43. package/.allhands/flows/shared/PROMPT_TASKS_CURATION.md +113 -0
  44. package/.allhands/flows/shared/PROMPT_VALIDATION_REVIEW.MD +99 -0
  45. package/.allhands/flows/shared/QUICK_PREMORTEM.md +70 -0
  46. package/.allhands/flows/shared/RESEARCH_GUIDANCE.md +38 -0
  47. package/.allhands/flows/shared/REVIEW_OPTIONS_BREAKDOWN.md +68 -0
  48. package/.allhands/flows/shared/SKILL_EXTRACTION.md +84 -0
  49. package/.allhands/flows/shared/SPEC_FLOW_ANALYSIS.md +119 -0
  50. package/.allhands/flows/shared/TDD_WORKFLOW.md +109 -0
  51. package/.allhands/flows/shared/UTILIZE_VALIDATION_TOOLING.md +84 -0
  52. package/.allhands/flows/shared/WRITING_HARNESS_FLOWS.md +11 -0
  53. package/.allhands/flows/shared/WRITING_HARNESS_MCP_TOOLS.md +84 -0
  54. package/.allhands/flows/shared/jury/ARCHITECTURE_REVIEW.md +91 -0
  55. package/.allhands/flows/shared/jury/BEST_PRACTICES_REVIEW.md +80 -0
  56. package/.allhands/flows/shared/jury/CLAIM_VERIFICATION_REVIEW.md +101 -0
  57. package/.allhands/flows/shared/jury/EXPECTATIONS_FIT_REVIEW.md +78 -0
  58. package/.allhands/flows/shared/jury/MAINTAINABILITY_REVIEW.md +110 -0
  59. package/.allhands/flows/shared/jury/PROMPTS_EXPECTATIONS_FIT.md +74 -0
  60. package/.allhands/flows/shared/jury/PROMPTS_FLOW_ANALYSIS.md +92 -0
  61. package/.allhands/flows/shared/jury/PROMPTS_YAGNI.md +78 -0
  62. package/.allhands/flows/shared/jury/PROMPT_PREMORTEM.md +125 -0
  63. package/.allhands/flows/shared/jury/SECURITY_REVIEW.md +86 -0
  64. package/.allhands/flows/shared/jury/YAGNI_REVIEW.md +82 -0
  65. package/.allhands/flows/wip/DEBUG_INVESTIGATION.md +162 -0
  66. package/.allhands/flows/wip/MEMORY_RECALL.md +62 -0
  67. package/.allhands/harness/ah +131 -0
  68. package/.allhands/harness/package-lock.json +5292 -0
  69. package/.allhands/harness/package.json +52 -0
  70. package/.allhands/harness/src/__tests__/e2e/commands.test.ts +307 -0
  71. package/.allhands/harness/src/__tests__/e2e/event-loop.test.ts +539 -0
  72. package/.allhands/harness/src/__tests__/e2e/hooks.test.ts +427 -0
  73. package/.allhands/harness/src/__tests__/e2e/new-initiative-routing.test.ts +137 -0
  74. package/.allhands/harness/src/__tests__/e2e/run-e2e.ts +109 -0
  75. package/.allhands/harness/src/__tests__/e2e/specs-type.test.ts +210 -0
  76. package/.allhands/harness/src/__tests__/e2e/validation-hooks.test.ts +669 -0
  77. package/.allhands/harness/src/__tests__/e2e/validation-path-consistency.test.ts +354 -0
  78. package/.allhands/harness/src/__tests__/e2e/validation.test.ts +528 -0
  79. package/.allhands/harness/src/__tests__/harness/assertions.ts +318 -0
  80. package/.allhands/harness/src/__tests__/harness/cli-runner.ts +359 -0
  81. package/.allhands/harness/src/__tests__/harness/fixture.ts +384 -0
  82. package/.allhands/harness/src/__tests__/harness/hook-runner.ts +411 -0
  83. package/.allhands/harness/src/__tests__/harness/index.ts +122 -0
  84. package/.allhands/harness/src/cli.ts +36 -0
  85. package/.allhands/harness/src/commands/complexity.ts +177 -0
  86. package/.allhands/harness/src/commands/context7.ts +202 -0
  87. package/.allhands/harness/src/commands/docs.ts +557 -0
  88. package/.allhands/harness/src/commands/hooks.ts +24 -0
  89. package/.allhands/harness/src/commands/index.ts +51 -0
  90. package/.allhands/harness/src/commands/knowledge.ts +382 -0
  91. package/.allhands/harness/src/commands/memories.ts +302 -0
  92. package/.allhands/harness/src/commands/notify.ts +61 -0
  93. package/.allhands/harness/src/commands/oracle.ts +158 -0
  94. package/.allhands/harness/src/commands/perplexity.ts +220 -0
  95. package/.allhands/harness/src/commands/planning.ts +245 -0
  96. package/.allhands/harness/src/commands/schema.ts +73 -0
  97. package/.allhands/harness/src/commands/skills.ts +128 -0
  98. package/.allhands/harness/src/commands/solutions.ts +353 -0
  99. package/.allhands/harness/src/commands/spawn.ts +158 -0
  100. package/.allhands/harness/src/commands/specs.ts +532 -0
  101. package/.allhands/harness/src/commands/tavily.ts +226 -0
  102. package/.allhands/harness/src/commands/tools.ts +579 -0
  103. package/.allhands/harness/src/commands/trace.ts +327 -0
  104. package/.allhands/harness/src/commands/tui.ts +960 -0
  105. package/.allhands/harness/src/commands/validate.ts +143 -0
  106. package/.allhands/harness/src/commands/validation-tools.ts +108 -0
  107. package/.allhands/harness/src/hooks/context.ts +1442 -0
  108. package/.allhands/harness/src/hooks/enforcement.ts +170 -0
  109. package/.allhands/harness/src/hooks/index.ts +54 -0
  110. package/.allhands/harness/src/hooks/lifecycle.ts +229 -0
  111. package/.allhands/harness/src/hooks/notification.ts +104 -0
  112. package/.allhands/harness/src/hooks/observability.ts +551 -0
  113. package/.allhands/harness/src/hooks/session.ts +88 -0
  114. package/.allhands/harness/src/hooks/shared.ts +815 -0
  115. package/.allhands/harness/src/hooks/transcript-parser.ts +208 -0
  116. package/.allhands/harness/src/hooks/validation.ts +617 -0
  117. package/.allhands/harness/src/lib/__tests__/ctags.test.ts +244 -0
  118. package/.allhands/harness/src/lib/__tests__/docs-validation.test.ts +344 -0
  119. package/.allhands/harness/src/lib/__tests__/mcp-runtime.test.ts +190 -0
  120. package/.allhands/harness/src/lib/__tests__/schema.test.ts +861 -0
  121. package/.allhands/harness/src/lib/base-command.ts +198 -0
  122. package/.allhands/harness/src/lib/cli-daemon.ts +343 -0
  123. package/.allhands/harness/src/lib/compaction.ts +313 -0
  124. package/.allhands/harness/src/lib/ctags.ts +497 -0
  125. package/.allhands/harness/src/lib/docs-validation.ts +907 -0
  126. package/.allhands/harness/src/lib/event-loop.ts +662 -0
  127. package/.allhands/harness/src/lib/flows.ts +155 -0
  128. package/.allhands/harness/src/lib/git.ts +276 -0
  129. package/.allhands/harness/src/lib/knowledge-worker.ts +72 -0
  130. package/.allhands/harness/src/lib/knowledge.ts +810 -0
  131. package/.allhands/harness/src/lib/llm.ts +255 -0
  132. package/.allhands/harness/src/lib/mcp-client.ts +432 -0
  133. package/.allhands/harness/src/lib/mcp-daemon.ts +486 -0
  134. package/.allhands/harness/src/lib/mcp-runtime.ts +418 -0
  135. package/.allhands/harness/src/lib/notification.ts +115 -0
  136. package/.allhands/harness/src/lib/opencode/index.ts +70 -0
  137. package/.allhands/harness/src/lib/opencode/profiles.ts +300 -0
  138. package/.allhands/harness/src/lib/opencode/prompts/codesearch.md +98 -0
  139. package/.allhands/harness/src/lib/opencode/prompts/knowledge-aggregator.md +67 -0
  140. package/.allhands/harness/src/lib/opencode/runner.ts +281 -0
  141. package/.allhands/harness/src/lib/oracle.ts +926 -0
  142. package/.allhands/harness/src/lib/planning-utils.ts +150 -0
  143. package/.allhands/harness/src/lib/planning.ts +605 -0
  144. package/.allhands/harness/src/lib/pr-review.ts +225 -0
  145. package/.allhands/harness/src/lib/prompts.ts +522 -0
  146. package/.allhands/harness/src/lib/schema.ts +418 -0
  147. package/.allhands/harness/src/lib/schemas/agent-profile.ts +141 -0
  148. package/.allhands/harness/src/lib/schemas/template-vars.ts +138 -0
  149. package/.allhands/harness/src/lib/session.ts +164 -0
  150. package/.allhands/harness/src/lib/specs.ts +348 -0
  151. package/.allhands/harness/src/lib/tldr.ts +829 -0
  152. package/.allhands/harness/src/lib/tmux.ts +1051 -0
  153. package/.allhands/harness/src/lib/trace-store.ts +714 -0
  154. package/.allhands/harness/src/mcp/__tests__/index.test.ts +46 -0
  155. package/.allhands/harness/src/mcp/_template.ts +47 -0
  156. package/.allhands/harness/src/mcp/filesystem.ts +33 -0
  157. package/.allhands/harness/src/mcp/index.ts +69 -0
  158. package/.allhands/harness/src/mcp/playwright.ts +34 -0
  159. package/.allhands/harness/src/mcp/xcodebuild.ts +29 -0
  160. package/.allhands/harness/src/schemas/docs.schema.json +44 -0
  161. package/.allhands/harness/src/schemas/settings.schema.json +214 -0
  162. package/.allhands/harness/src/tui/actions.ts +227 -0
  163. package/.allhands/harness/src/tui/file-viewer-modal.ts +270 -0
  164. package/.allhands/harness/src/tui/index.ts +1574 -0
  165. package/.allhands/harness/src/tui/modal.ts +232 -0
  166. package/.allhands/harness/src/tui/prompts-pane.ts +186 -0
  167. package/.allhands/harness/src/tui/status-pane.ts +434 -0
  168. package/.allhands/harness/tsconfig.json +22 -0
  169. package/.allhands/harness/vitest.config.ts +13 -0
  170. package/.allhands/pillars.md +33 -0
  171. package/.allhands/principles.md +88 -0
  172. package/.allhands/schemas/alignment.yaml +51 -0
  173. package/.allhands/schemas/documentation.yaml +10 -0
  174. package/.allhands/schemas/prompt.yaml +92 -0
  175. package/.allhands/schemas/skill.yaml +34 -0
  176. package/.allhands/schemas/solution.yaml +131 -0
  177. package/.allhands/schemas/spec.yaml +67 -0
  178. package/.allhands/schemas/validation-suite.yaml +49 -0
  179. package/.allhands/schemas/workflow.yaml +51 -0
  180. package/.allhands/settings.json +57 -0
  181. package/.allhands/skills/claude-code-patterns/SKILL.md +60 -0
  182. package/.allhands/skills/claude-code-patterns/docs/context-hygiene.md +19 -0
  183. package/.allhands/skills/harness-maintenance/SKILL.md +449 -0
  184. package/.allhands/skills/harness-maintenance/references/core-architecture.md +187 -0
  185. package/.allhands/skills/harness-maintenance/references/harness-skills.md +87 -0
  186. package/.allhands/skills/harness-maintenance/references/knowledge-compounding.md +78 -0
  187. package/.allhands/skills/harness-maintenance/references/tools-commands-mcp-hooks.md +115 -0
  188. package/.allhands/skills/harness-maintenance/references/validation-tooling.md +77 -0
  189. package/.allhands/skills/harness-maintenance/references/writing-flows.md +84 -0
  190. package/.allhands/validation/browser-automation.md +109 -0
  191. package/.allhands/validation/xcode-automation.md +195 -0
  192. package/.allhands/workflows/documentation.md +86 -0
  193. package/.allhands/workflows/investigation.md +81 -0
  194. package/.allhands/workflows/milestone.md +91 -0
  195. package/.allhands/workflows/optimization.md +85 -0
  196. package/.allhands/workflows/refactor.md +99 -0
  197. package/.allhands/workflows/triage.md +81 -0
  198. package/.claude/README.md +1 -0
  199. package/.claude/agents/explorer.md +10 -0
  200. package/.claude/agents/researcher.md +11 -0
  201. package/.claude/agents/task-runner.md +8 -0
  202. package/.claude/settings.json +231 -0
  203. package/.env.ai.example +7 -0
  204. package/.github/workflows/npm-publish.yml +69 -0
  205. package/.internal.json +45 -0
  206. package/.tldr/config.json +11 -0
  207. package/.tldrignore +90 -0
  208. package/CLAUDE.md +6 -0
  209. package/README.md +98 -0
  210. package/bin/sync-cli.js +7552 -0
  211. package/concerns.md +7 -0
  212. package/docs/README.md +41 -0
  213. package/docs/agents/README.md +24 -0
  214. package/docs/agents/agent-configuration-system.md +86 -0
  215. package/docs/agents/execution-agents.md +50 -0
  216. package/docs/agents/knowledge-agents.md +61 -0
  217. package/docs/agents/orchestration-agent.md +57 -0
  218. package/docs/agents/planning-agents.md +84 -0
  219. package/docs/agents/quality-review-agents.md +67 -0
  220. package/docs/agents/workflow-agent-orchestration.md +69 -0
  221. package/docs/flows/README.md +44 -0
  222. package/docs/flows/compounding.md +126 -0
  223. package/docs/flows/coordination.md +72 -0
  224. package/docs/flows/core-harness-integration.md +63 -0
  225. package/docs/flows/documentation-orchestration.md +98 -0
  226. package/docs/flows/e2e-test-plan-building.md +83 -0
  227. package/docs/flows/emergent-refinement.md +104 -0
  228. package/docs/flows/flow-authoring-and-mcp-tools.md +89 -0
  229. package/docs/flows/judge-reviewing.md +112 -0
  230. package/docs/flows/plan-deepening-and-research.md +107 -0
  231. package/docs/flows/plan-review-jury.md +114 -0
  232. package/docs/flows/pr-reviewing.md +54 -0
  233. package/docs/flows/prompt-task-execution.md +119 -0
  234. package/docs/flows/spec-planning.md +162 -0
  235. package/docs/flows/type-specific-scoping-flows.md +49 -0
  236. package/docs/flows/validation-and-skills-integration.md +145 -0
  237. package/docs/flows/wip/wip-flows.md +102 -0
  238. package/docs/harness/README.md +23 -0
  239. package/docs/harness/agent-profiles.md +84 -0
  240. package/docs/harness/cli/README.md +24 -0
  241. package/docs/harness/cli/cli-entry-and-command-discovery.md +91 -0
  242. package/docs/harness/cli/docs-command.md +87 -0
  243. package/docs/harness/cli/knowledge-command.md +91 -0
  244. package/docs/harness/cli/minor-cli-commands.md +65 -0
  245. package/docs/harness/cli/oracle-command.md +113 -0
  246. package/docs/harness/cli/planning-command.md +95 -0
  247. package/docs/harness/cli/schema-and-validation-commands.md +154 -0
  248. package/docs/harness/cli/search-commands.md +97 -0
  249. package/docs/harness/cli/spawn-command.md +136 -0
  250. package/docs/harness/cli/specs-command.md +102 -0
  251. package/docs/harness/cli/tools-command.md +122 -0
  252. package/docs/harness/cli/trace-command.md +122 -0
  253. package/docs/harness/cli-daemon.md +92 -0
  254. package/docs/harness/event-loop.md +184 -0
  255. package/docs/harness/hooks/README.md +15 -0
  256. package/docs/harness/hooks/context-hooks.md +96 -0
  257. package/docs/harness/hooks/lifecycle-and-observability-hooks.md +135 -0
  258. package/docs/harness/hooks/validation-hooks.md +97 -0
  259. package/docs/harness/test-harness.md +149 -0
  260. package/docs/harness/tui.md +176 -0
  261. package/docs/memories.md +20 -0
  262. package/docs/solutions/agentic-issues/premature-agent-deletion-tui-action-dependency-20260130.md +49 -0
  263. package/docs/solutions/agentic-issues/ref-anchor-scope-mismatch-skill-references-20260131.md +55 -0
  264. package/docs/solutions/agentic-issues/tautological-tests-routing-20260131.md +52 -0
  265. package/docs/solutions/integration_issue/blocktool-output-format-mismatch-hook-runner-20260130.md +52 -0
  266. package/docs/solutions/integration_issue/dual-validation-path-divergence-schema-20260130.md +66 -0
  267. package/docs/solutions/security-issues/unsanitized-domain-path-join-20260131.md +52 -0
  268. package/docs/solutions/test-failures/event-loop-mock-ordering-checkAgentWindows-20260130.md +63 -0
  269. package/docs/sync-cli/README.md +19 -0
  270. package/docs/sync-cli/cli-entrypoint-and-commands.md +39 -0
  271. package/docs/sync-cli/commands/README.md +11 -0
  272. package/docs/sync-cli/commands/pull-manifest-command.md +36 -0
  273. package/docs/sync-cli/commands/push-command.md +84 -0
  274. package/docs/sync-cli/commands/sync-command.md +71 -0
  275. package/docs/sync-cli/systems/README.md +14 -0
  276. package/docs/sync-cli/systems/git-and-github-integration.md +49 -0
  277. package/docs/sync-cli/systems/interactive-ui.md +43 -0
  278. package/docs/sync-cli/systems/manifest-and-distribution.md +51 -0
  279. package/docs/sync-cli/systems/path-resolution.md +42 -0
  280. package/package.json +46 -0
  281. package/scripts/install-shim.sh +40 -0
  282. package/scripts/pre-pack.sh +25 -0
  283. package/specs/harness-maintenance-skill.spec.md +138 -0
  284. package/specs/roadmap/git-spec-lifecycle-management.spec.md +113 -0
  285. package/specs/sync-init-flag.spec.md +117 -0
  286. package/specs/unified-workflow-orchestration.spec.md +250 -0
  287. package/specs/validation-tooling-practice.spec.md +98 -0
  288. package/specs/workflow-domain-configuration.spec.md +265 -0
  289. package/src/commands/pull-manifest.ts +31 -0
  290. package/src/commands/push.ts +344 -0
  291. package/src/commands/sync.ts +289 -0
  292. package/src/lib/constants.ts +10 -0
  293. package/src/lib/dotfiles.ts +36 -0
  294. package/src/lib/fs-utils.ts +18 -0
  295. package/src/lib/gh.ts +40 -0
  296. package/src/lib/git.ts +63 -0
  297. package/src/lib/gitignore.ts +167 -0
  298. package/src/lib/manifest.ts +121 -0
  299. package/src/lib/marker-sync.ts +39 -0
  300. package/src/lib/paths.ts +38 -0
  301. package/src/lib/target-lines.ts +66 -0
  302. package/src/lib/ui.ts +78 -0
  303. package/src/sync-cli.ts +120 -0
  304. package/target-lines.json +23 -0
  305. package/tsconfig.json +20 -0
@@ -0,0 +1,154 @@
1
+ ---
2
+ description: "Schema definitions and validation pipeline: how YAML schemas enforce file structure for prompts, specs, alignments, validation suites (with tools field and body sections), and agent profiles, with runtime Zod validation for template variables. Includes array item-type enforcement and the SPEC_TYPE template variable registry."
3
+ ---
4
+
5
+ # Schema and Validation Commands
6
+
7
+ ## Intent
8
+
9
+ The harness manages many structured file types (prompts, specs, alignment docs, agent profiles, validation suites). Each has a required frontmatter shape and sometimes body structure. The schema system is the single source of truth for these requirements, serving two audiences:
10
+
11
+ 1. **Agents** query schemas to understand how to write valid files (`ah schema <type>`)
12
+ 2. **Validation** checks files against schemas before they enter the pipeline (`ah validate <file>`)
13
+
14
+ ## Two Validation Approaches
15
+
16
+ The codebase uses two complementary validation strategies depending on the file type:
17
+
18
+ ```mermaid
19
+ flowchart TD
20
+ File["Input File"] --> Detect{"Detect schema type"}
21
+ Detect -->|YAML schema exists| Static["Static YAML Schema<br/>prompt, spec, alignment,<br/>documentation, validation-suite"]
22
+ Detect -->|Zod schema| Runtime["Runtime Zod Schema<br/>agent-profile, template-vars"]
23
+ Static --> FrontmatterParse["Extract frontmatter"]
24
+ FrontmatterParse --> FieldValidation["Validate each field<br/>against SchemaField rules"]
25
+ Runtime --> ZodParse["Zod safeParse"]
26
+ ZodParse --> Semantic["Semantic validation<br/>(cross-field checks)"]
27
+ ```
28
+
29
+ ### Static YAML Schemas
30
+
31
+ YAML schema files in `.allhands/schemas/` define frontmatter field requirements. [ref:.allhands/harness/src/lib/schema.ts:loadSchema:c65e65d] reads and caches these definitions. [ref:.allhands/harness/src/lib/schema.ts:listSchemas:c65e65d] discovers available types by scanning the schema directory.
32
+
33
+ [ref:.allhands/harness/src/lib/schema.ts:validateField:c65e65d] checks individual values against their field definition, supporting these types:
34
+
35
+ | Type | Validation Rule |
36
+ |------|----------------|
37
+ | `string` | `typeof === 'string'` |
38
+ | `integer` | `typeof === 'number'` and `Number.isInteger()` |
39
+ | `boolean` | `typeof === 'boolean'` |
40
+ | `date` | String parseable as ISO 8601 |
41
+ | `enum` | Value in allowed `values` list |
42
+ | `array` | `Array.isArray()`, plus item-type enforcement when schema specifies `items` |
43
+ | `object` | Recursive property validation via nested `properties` |
44
+
45
+ When a schema field declares `items` (e.g., `items: string`), [ref:.allhands/harness/src/lib/schema.ts:validateField:c65e65d] enforces that every element matches the declared type. For example, `tools: [123]` is rejected when the schema specifies `items: string`. Integer item validation also catches floats -- `[1, 2.5]` fails against `items: integer`. Arrays without an `items` constraint accept mixed types.
46
+
47
+ ### Runtime Zod Schemas
48
+
49
+ For types requiring cross-field validation or normalization from YAML snake_case to TypeScript camelCase:
50
+
51
+ **Agent profiles**: [ref:.allhands/harness/src/lib/schemas/agent-profile.ts:validateProfileSemantics:fb892e5] performs semantic validation beyond schema checks -- verifying that template variables referenced in `message_template` match the declared `template_vars` list, and that no unknown variables are used.
52
+
53
+ **Template variables**: [ref:.allhands/harness/src/lib/schemas/template-vars.ts:validateTemplateString:730f114] extracts `${VAR_NAME}` references from templates and validates each against the registry of known variables. [ref:.allhands/harness/src/lib/schemas/template-vars.ts:validateContext:730f114] checks that all required variables have valid values at resolution time.
54
+
55
+ The template variable registry [ref:.allhands/harness/src/lib/schemas/template-vars.ts:TemplateVars:730f114] defines all valid variables with individual Zod schemas:
56
+
57
+ | Variable | Type | Description |
58
+ |----------|------|-------------|
59
+ | `SPEC_PATH` | `string` | Path to spec file |
60
+ | `ALIGNMENT_PATH` | `string` | Path to alignment doc |
61
+ | `PROMPTS_FOLDER` | `string` | Path to prompts directory |
62
+ | `PROMPT_PATH` | `string` | Path to specific prompt file |
63
+ | `OUTPUT_PATH` | `string` | Output file path |
64
+ | `PLANNING_FOLDER` | `string` | Path to `.planning/{branch}` directory |
65
+ | `SPEC_NAME` | `string` | Current spec name |
66
+ | `PROMPT_NUMBER` | `string` (regex: `/^\d{2}$/`) | Two-digit prompt number |
67
+ | `BRANCH` | `string` | Current git branch name |
68
+ | `SPEC_TYPE` | `string` | Spec type from frontmatter (milestone, investigation, optimization, refactor, documentation, triage) |
69
+ | `HYPOTHESIS_DOMAINS` | `string` | Comma-separated hypothesis domains from settings.json |
70
+
71
+ [ref:.allhands/harness/src/lib/schemas/template-vars.ts:TEMPLATE_VAR_NAMES:730f114] exports the full variable name list for runtime validation.
72
+
73
+ ## Schema Type Detection
74
+
75
+ The system can automatically determine which schema applies to a file:
76
+
77
+ [ref:.allhands/harness/src/lib/schema.ts:detectSchemaType:c65e65d] uses glob pattern matching against known paths:
78
+
79
+ | Pattern | Schema Type |
80
+ |---------|-------------|
81
+ | `.planning/**/prompts/*.md` | `prompt` |
82
+ | `.planning/**/alignment.md` | `alignment` |
83
+ | `specs/**/*.spec.md` | `spec` |
84
+ | `docs/**/*.md` | `documentation` |
85
+ | `.allhands/validation/*.md` | `validation-suite` |
86
+ | `.allhands/skills/*/SKILL.md` | `skill` |
87
+
88
+ [ref:.allhands/harness/src/lib/schema.ts:inferSchemaType:c65e65d] provides a string-matching fallback when glob patterns fail, using path segments and file name patterns.
89
+
90
+ ## CLI Commands
91
+
92
+ ### `ah schema <type> [property]`
93
+
94
+ [ref:.allhands/harness/src/commands/schema.ts:register:38074a4] exposes schema definitions to agents. Given a type name, it reads the corresponding YAML schema and outputs it. The optional `property` argument extracts a single top-level key, reducing output for agents that only need to understand one aspect of a schema.
95
+
96
+ [ref:.allhands/harness/src/commands/schema.ts:getAvailableSchemas:38074a4] lists all `.yaml` files in the schemas directory when an unknown type is requested, guiding agents toward valid types.
97
+
98
+ ### `ah validate <file>`
99
+
100
+ [ref:.allhands/harness/src/commands/validate.ts:register:66f613b] validates a file against its detected or inferred schema. The validation pipeline:
101
+
102
+ 1. Read the file
103
+ 2. Detect schema type from path (glob match, then string inference)
104
+ 3. Extract frontmatter
105
+ 4. Validate against schema fields
106
+ 5. Format errors with [ref:.allhands/harness/src/lib/schema.ts:formatErrors:c65e65d]
107
+
108
+ ### `ah validation-tools list`
109
+
110
+ [ref:.allhands/harness/src/commands/validation-tools.ts:register:d44fa2a] discovers validation suite definitions in `.allhands/validation/`. Each suite is a markdown file with frontmatter declaring:
111
+
112
+ | Field | Type | Purpose |
113
+ |-------|------|---------|
114
+ | `name` | `string` | Unique suite identifier (matches filename) |
115
+ | `description` | `string` | When/why to use this suite |
116
+ | `globs` | `string[]` | File patterns the suite validates (used for discovery) |
117
+ | `tools` | `string[]` | CLI tools and packages the suite uses (e.g., `agent-browser`, `playwright`) |
118
+
119
+ The `tools` field enables agent-to-suite mapping -- agents can find which validation suites are relevant based on the tools they have available. [ref:.allhands/harness/src/commands/validation-tools.ts:listValidationSuites:d44fa2a] delegates frontmatter validation to [ref:.allhands/harness/src/lib/schema.ts:validateFrontmatter:c65e65d], ensuring suites with invalid or incomplete frontmatter are silently excluded from the listing rather than causing errors. This delegation keeps schema enforcement centralized in `lib/schema.ts` rather than duplicated in command files.
120
+
121
+ ## Validation Suite Schema
122
+
123
+ The `validation-suite` schema type ([ref:.allhands/schemas/validation-suite.yaml::d45ebc8]) defines the structure for two-dimensional validation playbooks in `.allhands/validation/`. Per **Agentic Validation Tooling**, every suite has both a stochastic dimension (agent-driven exploratory testing) and a deterministic dimension (CI-gated binary pass/fail).
124
+
125
+ ### Frontmatter Fields
126
+
127
+ | Field | Type | Required | Description |
128
+ |-------|------|----------|-------------|
129
+ | `name` | `string` | Yes | Unique suite identifier matching filename |
130
+ | `description` | `string` | Yes | Use case description for suite discovery |
131
+ | `globs` | `array` (`items: string`) | Yes | File patterns this suite validates |
132
+ | `tools` | `array` (`items: string`) | Yes | CLI tools and packages used by the suite |
133
+
134
+ The `tools` and `globs` fields both enforce item-type validation via `items: string` in the schema -- non-string array elements are rejected at validation time.
135
+
136
+ ### Body Sections
137
+
138
+ The schema defines 5 body sections that structure the validation playbook:
139
+
140
+ | Section | Required | Content |
141
+ |---------|----------|---------|
142
+ | **Purpose** | Yes | Quality aspects this suite validates (stability, performance, UX, accessibility) |
143
+ | **Tooling** | Yes | Tools used, installation, and configuration |
144
+ | **Stochastic Validation** | Yes | Agent-driven exploratory playbook: patterns, edge case strategies, death spiral escape hatches |
145
+ | **Deterministic Integration** | Yes | CI-gated scripted validation: test scripts, success/failure criteria, artifact capture |
146
+ | **ENV Configuration** | No | Environment variables needed for both dimensions (only when suite requires external configuration) |
147
+
148
+ This structure reflects the crystallization lifecycle from principles: stochastic exploration discovers patterns, patterns crystallize into deterministic checks, deterministic checks entrench in CI/CD, and stochastic exploration shifts to the frontier.
149
+
150
+ ## Key Design Decisions
151
+
152
+ - **YAML for static schemas, Zod for runtime**: YAML schemas are agent-readable (via `ah schema`) and work for simple field-level checks. Zod schemas handle normalization and cross-field logic that YAML cannot express.
153
+ - **Schema caching**: [ref:.allhands/harness/src/lib/schema.ts:loadSchema:c65e65d] caches parsed schemas in memory, avoiding repeated filesystem reads during validation of multiple files.
154
+ - **Defaults via schema**: [ref:.allhands/harness/src/lib/schema.ts:applyDefaults:c65e65d] fills missing frontmatter fields from schema defaults, enabling minimal frontmatter in files while maintaining complete data.
@@ -0,0 +1,97 @@
1
+ ---
2
+ description: "Knowledge retrieval commands for agents: local solution and memory search via keyword scoring, plus external web research through Perplexity, Tavily, and Context7 integrations."
3
+ ---
4
+
5
+ ## Intent
6
+
7
+ Agents need to retrieve knowledge from two distinct sources: **local project knowledge** (solutions, memories) and **external web knowledge** (documentation, research). The search commands provide a unified CLI surface for both, with consistent JSON output that agents can parse. The local search commands use weighted keyword scoring against structured frontmatter rather than full-text search, trading recall for precision and avoiding embedding infrastructure.
8
+
9
+ ## Local Knowledge Search
10
+
11
+ ### Solutions Search
12
+
13
+ [ref:.allhands/harness/src/commands/solutions.ts:searchSolutions:19e47dd] searches documented solutions in `docs/solutions/`. Solutions are markdown files with YAML frontmatter containing structured fields (title, tags, component, symptoms, root_cause, severity).
14
+
15
+ Scoring weights determine field importance:
16
+
17
+ | Field | Weight | Rationale |
18
+ |-------|--------|-----------|
19
+ | title | 3 | Strongest signal -- direct topic match |
20
+ | tags | 3 | Curated identifiers, high precision |
21
+ | component | 2 | Narrows to subsystem |
22
+ | symptoms | 2 | Matches problem description |
23
+ | problem_type | 1 | Broad categorization |
24
+ | root_cause | 1 | Technical detail |
25
+
26
+ [ref:.allhands/harness/src/commands/solutions.ts:scoreSolution:19e47dd] computes a cumulative score per keyword across all fields. [ref:.allhands/harness/src/commands/solutions.ts:extractKeywords:19e47dd] handles quoted phrases and whitespace splitting, allowing queries like `"tmux session" timeout`.
27
+
28
+ ### Memories Search
29
+
30
+ [ref:.allhands/harness/src/commands/memories.ts:searchMemories:49c8ec9] searches project memories stored as markdown tables in `docs/memories.md`. Each table row has Name, Domain, Source, and Description columns grouped under section headers.
31
+
32
+ [ref:.allhands/harness/src/commands/memories.ts:scoreMemory:49c8ec9] applies similar weighted scoring:
33
+
34
+ | Field | Weight |
35
+ |-------|--------|
36
+ | name | 3 |
37
+ | description | 2 |
38
+ | domain | 2 |
39
+ | source | 1 |
40
+
41
+ Memories support additional filtering by `--domain` and `--source` before scoring, enabling queries like `ah memories search "hook" --domain planning`.
42
+
43
+ ### Shared Search Design
44
+
45
+ Both local search commands share these characteristics:
46
+ - Keyword extraction with quoted phrase support ([ref:.allhands/harness/src/commands/solutions.ts:extractKeywords:19e47dd])
47
+ - Cumulative scoring across multiple fields
48
+ - Results sorted by score descending, truncated to `--limit`
49
+ - JSON output with `matchedFields` array explaining why each result matched
50
+ - Zero external dependencies (pure filesystem reads + YAML parsing)
51
+
52
+ ## External Web Research
53
+
54
+ ### Perplexity
55
+
56
+ [ref:.allhands/harness/src/commands/perplexity.ts:callPerplexityApi:e041bed] sends queries to Perplexity's `sonar-pro` model, which returns AI-synthesized answers with citation URLs. The distinctive feature is the `--challenge` flag, which sends Perplexity's findings to [ref:.allhands/harness/src/commands/perplexity.ts:callGrokChallengeApi:e041bed] (Grok/X.AI) for adversarial validation. The Grok challenger prompt specifically targets contradicting opinions, newer alternatives, and developer sentiment from X/Twitter posts.
57
+
58
+ ```mermaid
59
+ sequenceDiagram
60
+ participant Agent
61
+ participant Perplexity as Perplexity API
62
+ participant Grok as Grok/X.AI API
63
+
64
+ Agent->>Perplexity: research query
65
+ Perplexity-->>Agent: findings + citations
66
+
67
+ opt --challenge flag
68
+ Agent->>Grok: findings + original query
69
+ Note right of Grok: Searches X for contradictions,<br/>alternatives, sentiment
70
+ Grok-->>Agent: challenge analysis + sources
71
+ end
72
+ ```
73
+
74
+ ### Tavily
75
+
76
+ [ref:.allhands/harness/src/commands/tavily.ts:callTavilyApi:3ab56fe] provides two capabilities:
77
+
78
+ - **Search** (`ah tavily search`): Web search with optional LLM-generated answer, configurable max results (capped at 20)
79
+ - **Extract** (`ah tavily extract`): Full content extraction from up to 20 URLs, returned as markdown
80
+
81
+ ### Context7
82
+
83
+ Context7 bridges from library names to documentation context in a two-step flow:
84
+
85
+ 1. `ah context7 search <library>` -- Finds libraries by name, returns IDs with trust scores and snippet counts
86
+ 2. `ah context7 context <libraryId> <query>` -- Retrieves documentation context for a known library, supporting both JSON (structured docs) and `--text` (plain text for direct LLM consumption) output modes
87
+
88
+ ## API Key Requirements
89
+
90
+ | Command | Environment Variable | Required |
91
+ |---------|---------------------|----------|
92
+ | `ah perplexity research` | `PERPLEXITY_API_KEY` | Yes |
93
+ | `ah perplexity research --challenge` | `X_AI_API_KEY` | Additionally required |
94
+ | `ah tavily search` / `extract` | `TAVILY_API_KEY` | Yes |
95
+ | `ah context7 search` / `context` | `CONTEXT7_API_KEY` | Yes |
96
+
97
+ All external commands use abort controllers with configurable timeouts (default 60s for Perplexity, 120s for Grok/Tavily/Context7) and surface errors as structured JSON when `--json` is passed.
@@ -0,0 +1,136 @@
1
+ ---
2
+ description: "Agent spawning system that uses tmux sessions and windows to run isolated Claude Code agents, with profile-based configuration, flowOverride for type-routed spawning, template context resolution (including SPEC_TYPE and HYPOTHESIS_DOMAINS), and persistent session state tracking."
3
+ ---
4
+
5
+ ## Intent
6
+
7
+ The spawn system solves the problem of running multiple concurrent Claude Code agents in isolated environments while maintaining a coherent session model. Each agent runs in its own tmux window with dedicated environment variables, ensuring MCP daemon isolation via AGENT_ID and preventing resource conflicts between agents.
8
+
9
+ The key design decision is that **tmux windows are the unit of agent isolation**. The window name becomes the AGENT_ID, which cascades into MCP daemon socket paths, trace event attribution, and session state tracking.
10
+
11
+ ## Agent Lifecycle
12
+
13
+ ```mermaid
14
+ stateDiagram-v2
15
+ [*] --> ProfileLoaded: spawnAgentFromProfile
16
+ [*] --> ConfigBuilt: spawnAgent (direct)
17
+ ProfileLoaded --> Validated: buildAgentInvocation
18
+ Validated --> ConfigBuilt: Convert to SpawnConfig
19
+ ConfigBuilt --> WindowCreated: createWindow (detached)
20
+ WindowCreated --> Registered: registerSpawnedAgent
21
+ Registered --> EnvSet: buildAgentEnv
22
+ EnvSet --> LauncherWritten: Write launcher script
23
+ LauncherWritten --> Running: sendKeys (exec bash launcher)
24
+ Running --> Focused: focusWindow=true
25
+ Running --> Background: focusWindow=false
26
+ Running --> [*]: Agent exits, window closes
27
+ ```
28
+
29
+ ## Three Spawning Paths
30
+
31
+ | Path | Entry Point | Use Case |
32
+ |------|-------------|----------|
33
+ | Profile-based | [ref:.allhands/harness/src/lib/tmux.ts:spawnAgentFromProfile:553666b] | Preferred path. Loads YAML profile from `.allhands/agents/`, validates template variables, resolves message template. Supports `flowOverride` for type-routed spawning. |
34
+ | Direct spawn | [ref:.allhands/harness/src/lib/tmux.ts:spawnAgent:553666b] | Lower-level. Takes a complete SpawnConfig with explicit flow path and preamble |
35
+ | Custom flow | [ref:.allhands/harness/src/lib/tmux.ts:spawnCustomFlow:553666b] | Ad-hoc flows. Takes an absolute flow path and custom message, uses a generated window name |
36
+
37
+ The `ah spawn codesearch` CLI command ([ref:.allhands/harness/src/commands/spawn.ts:CodesearchCommand:71f3aed]) takes a separate approach entirely -- it uses the OpenCode SDK's AgentRunner rather than tmux, running an AI agent with ast-grep, ripgrep, and LSP tools within a single process with a tool budget and step limit.
38
+
39
+ ## Flow Override
40
+
41
+ [ref:.allhands/harness/src/lib/tmux.ts:ProfileSpawnConfig:553666b] accepts an optional `flowOverride` field. When provided, it takes precedence over the profile's default flow path in the resulting `SpawnConfig`:
42
+
43
+ ```
44
+ flowPath = config.flowOverride || invocation.flowPath
45
+ ```
46
+
47
+ This enables **type-routed spawning**: the TUI's New Initiative action selects a spec type, looks up the corresponding scoping flow via [ref:.allhands/harness/src/commands/tui.ts:SCOPING_FLOW_MAP:4ca2008], and passes it as `flowOverride` to the ideation agent profile. The same agent profile serves all initiative types -- only the flow changes.
48
+
49
+ For milestone spec type, `flowOverride` is `undefined` (profile default flow is used). All other spec types resolve to a dedicated scoping flow file (e.g., `INVESTIGATION_SCOPING.md`, `REFACTOR_SCOPING.md`).
50
+
51
+ ## Template Context Resolution
52
+
53
+ [ref:.allhands/harness/src/lib/tmux.ts:buildTemplateContext:553666b] constructs the `TemplateContext` used for resolving `${VAR_NAME}` placeholders in agent profile message templates. It resolves variables from the current git state, planning paths, spec metadata, and project settings:
54
+
55
+ | Variable | Resolution Source |
56
+ |----------|-------------------|
57
+ | `BRANCH` | Current git branch via `getCurrentBranch()` |
58
+ | `PLANNING_FOLDER` | `.planning/{branch}` root directory |
59
+ | `PROMPTS_FOLDER` | `.planning/{branch}/prompts/` |
60
+ | `ALIGNMENT_PATH` | `.planning/{branch}/alignment.md` |
61
+ | `OUTPUT_PATH` | `.planning/{branch}/e2e-test-plan.md` |
62
+ | `SPEC_NAME` | Display name from status, or planning key |
63
+ | `SPEC_PATH` | Read from `status.yaml` spec field |
64
+ | `SPEC_TYPE` | Spec frontmatter type via `getSpecForBranch()`, defaults to `'milestone'` |
65
+ | `PROMPT_NUMBER` | Zero-padded two-digit number (when prompt-scoped) |
66
+ | `PROMPT_PATH` | Absolute path to prompt file (when prompt-scoped) |
67
+ | `HYPOTHESIS_DOMAINS` | Comma-separated list from [ref:.allhands/harness/src/hooks/shared.ts:EmergentSettings:ca0caaf] in `settings.json`, defaulting to `testing, stability, performance, feature, ux, integration` |
68
+
69
+ `SPEC_TYPE` is resolved by reading the spec file's frontmatter `type` field for the current branch. This enables type-aware agent behavior -- agents can tailor their approach based on whether the initiative is a milestone, investigation, refactor, etc.
70
+
71
+ `HYPOTHESIS_DOMAINS` is read from the `emergent.hypothesisDomains` array in `.allhands/settings.json` and joined with commas for template injection.
72
+
73
+ ## EmergentSettings
74
+
75
+ [ref:.allhands/harness/src/hooks/shared.ts:EmergentSettings:ca0caaf] is the TypeScript interface for the `emergent` section of `.allhands/settings.json`:
76
+
77
+ | Field | Type | Default | Purpose |
78
+ |-------|------|---------|---------|
79
+ | `hypothesisDomains` | `string[]` | `["testing", "stability", "performance", "feature", "ux", "integration"]` | Pool of domains the emergent planner diversifies across when generating hypothesis prompts |
80
+
81
+ The settings schema is defined in [ref:.allhands/harness/src/schemas/settings.schema.json::77942b7]. The `emergent` object replaces the removed workflow YAML configuration system -- hypothesis domains are now centralized in project settings rather than per-workflow YAML files.
82
+
83
+ ## Window Naming and Prompt Scoping
84
+
85
+ Window naming determines agent identity and concurrency rules:
86
+
87
+ - **Non-prompt-scoped agents** (planner, coordinator): Window name = agent name. Only one instance allowed. [ref:.allhands/harness/src/lib/tmux.ts:buildWindowName:553666b] throws if a window with that name already exists.
88
+ - **Prompt-scoped agents** (executor): Window name = `{name}-{promptNumber:02d}` (e.g., `executor-01`). Multiple concurrent instances allowed, one per prompt. Existing windows are killed and recreated on re-spawn.
89
+
90
+ ## Environment Variable Propagation
91
+
92
+ [ref:.allhands/harness/src/lib/tmux.ts:buildAgentEnv:553666b] constructs the environment for each spawned agent:
93
+
94
+ | Variable | Source | Purpose |
95
+ |----------|--------|---------|
96
+ | AGENT_ID | Window name | MCP daemon socket isolation, trace attribution |
97
+ | AGENT_TYPE | Profile name | Agent role identification |
98
+ | BRANCH | Current git branch | Branch context for operations |
99
+ | PROMPT_NUMBER | SpawnConfig (if prompt-scoped) | Prompt tracking |
100
+ | SPEC_NAME | SpawnConfig | Spec context |
101
+ | PROMPT_SCOPED | "true" if applicable | Signals prompt-scoped behavior |
102
+ | CLAUDE_AUTOCOMPACT_PCT_OVERRIDE | Project settings | Configurable autocompact threshold for prompt-scoped agents |
103
+ | PYENV_REHASH_SKIP | Always "1" | Avoids lock contention when spawning multiple agents |
104
+
105
+ ## Session Management
106
+
107
+ The tmux session layer handles multi-agent coordination through a standardized session named `ah-hub`.
108
+
109
+ [ref:.allhands/harness/src/lib/tmux.ts:setupTUISession:553666b] orchestrates session setup with this decision tree:
110
+
111
+ - **Not in tmux** --> Create new session, rename to `ah-hub`
112
+ - **In tmux, multiple windows** --> Prompt user: create new session or reuse current
113
+ - **In tmux, single window** --> Reuse current session, rename to `ah-hub`
114
+
115
+ [ref:.allhands/harness/src/lib/tmux.ts:getSessionDecision:553666b] encodes this logic as a pure function returning `'create-new' | 'use-current' | 'no-prompt-needed'`.
116
+
117
+ ## Persistent Session State
118
+
119
+ [ref:.allhands/harness/src/lib/session.ts::d831d20] persists session state to `.allhands/harness/.cache/session.json` (not git-tracked). This enables cross-process visibility into which agents are running.
120
+
121
+ The state tracks two things:
122
+ - **hub_window_id**: The tmux window ID where the TUI runs ([ref:.allhands/harness/src/lib/session.ts:setHubWindowId:d831d20])
123
+ - **spawned_windows**: List of agent window names ([ref:.allhands/harness/src/lib/session.ts:addSpawnedWindow:d831d20], [ref:.allhands/harness/src/lib/session.ts:removeSpawnedWindow:d831d20])
124
+
125
+ All mutations go through [ref:.allhands/harness/src/lib/session.ts:withSessionLock:d831d20], which uses `proper-lockfile` for cross-process file locking to prevent race conditions when multiple agents modify session state simultaneously.
126
+
127
+ ## Launcher Script Pattern
128
+
129
+ Rather than constructing complex shell commands with escaping issues, the spawn system writes a temporary bash launcher script per agent. This script:
130
+
131
+ 1. Exports all environment variables
132
+ 2. Reads the combined prompt from a separate file (flow content + preamble + base branch info)
133
+ 3. Invokes `claude --settings .claude/settings.json --dangerously-skip-permissions` with the prompt
134
+ 4. Uses `exec bash` so the shell process is replaced, ensuring the window closes when claude exits
135
+
136
+ Old launcher scripts (>24 hours) are cleaned up automatically by [ref:.allhands/harness/src/lib/tmux.ts:cleanupOldLaunchers:553666b].
@@ -0,0 +1,102 @@
1
+ ---
2
+ description: "Spec file lifecycle management: listing by domain, status transitions between roadmap/in-progress/completed, branch-spec linking, and knowledge reindexing on spec moves."
3
+ ---
4
+
5
+ # Specs Command
6
+
7
+ ## Intent
8
+
9
+ Specs are the units of planned work in the harness. They live as markdown files with YAML frontmatter, organized into directories by lifecycle stage. The specs command manages the transitions between these stages, maintains the link between specs and git branches, and keeps knowledge indexes consistent when files move.
10
+
11
+ ## Spec File Organization
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ subgraph "specs/"
16
+ Root["Active specs<br/>(in_progress)"]
17
+ subgraph "roadmap/"
18
+ Planned["Planned specs<br/>(roadmap)"]
19
+ end
20
+ subgraph "completed/"
21
+ Done["Completed specs<br/>(completed)"]
22
+ end
23
+ end
24
+ ```
25
+
26
+ Each spec file (`*.spec.md` or `*.md`) contains frontmatter with:
27
+
28
+ | Field | Type | Purpose |
29
+ |-------|------|---------|
30
+ | `name` | string | Spec identifier |
31
+ | `domain_name` | string | Grouping domain (e.g., `harness`, `tui`) |
32
+ | `status` | enum | `roadmap`, `in_progress`, or `completed` |
33
+ | `dependencies` | string[] | Other spec names this depends on |
34
+ | `branch` | string | Source of truth for which git branch implements this spec |
35
+
36
+ ## Spec Discovery
37
+
38
+ Two discovery implementations exist for different contexts:
39
+
40
+ **Library layer** ([ref:.allhands/harness/src/lib/specs.ts:loadAllSpecs:ce6f7c5]): Scans `specs/roadmap/`, `specs/`, and `specs/completed/` directories. Returns specs grouped by category with full metadata including title extraction from H1 headings via [ref:.allhands/harness/src/lib/specs.ts:extractTitle:ce6f7c5].
41
+
42
+ **Command layer** ([ref:.allhands/harness/src/commands/specs.ts:loadAllSpecs:6d7289a]): Scans `specs/` and `specs/roadmap/` for `.spec.md` files specifically. Used by CLI subcommands for listing and status changes.
43
+
44
+ ## Branch-Spec Linking
45
+
46
+ The `branch` field in spec frontmatter is the source of truth for which branch implements a spec. Two lookup functions serve different use cases:
47
+
48
+ - [ref:.allhands/harness/src/lib/specs.ts:findSpecByBranch:ce6f7c5] -- strict match: scans all specs for one whose `branch` field matches the given branch name exactly
49
+ - [ref:.allhands/harness/src/lib/specs.ts:getSpecForBranch:ce6f7c5] -- enhanced match: tries `findSpecByBranch` first, then falls back to initializing a planning directory if the branch has a spec assigned
50
+
51
+ [ref:.allhands/harness/src/lib/specs.ts:findSpecById:ce6f7c5] provides ID-based lookup, searching across all category groups.
52
+
53
+ ## CLI Subcommands
54
+
55
+ ### `ah specs list`
56
+
57
+ Lists all specs grouped by `domain_name`. Supports filtering:
58
+
59
+ | Flag | Effect |
60
+ |------|--------|
61
+ | `--roadmap` | Only roadmap status specs |
62
+ | `--completed` | Only completed specs |
63
+ | `--in-progress` | Only in-progress specs |
64
+ | `--domain <name>` | Filter to a single domain |
65
+ | `--domains-only` | Just list domain names |
66
+
67
+ ### `ah specs current`
68
+
69
+ Shows the spec linked to the current git branch. Uses [ref:.allhands/harness/src/lib/specs.ts:getSpecForBranch:ce6f7c5] with the current branch to display spec ID, title, path, domain, status, and dependencies.
70
+
71
+ ### `ah specs complete <name>`
72
+
73
+ Marks a spec as completed:
74
+
75
+ 1. Finds the spec by name via [ref:.allhands/harness/src/commands/specs.ts:findSpecByName:6d7289a]
76
+ 2. Updates frontmatter status to `completed` via [ref:.allhands/harness/src/commands/specs.ts:updateSpecStatus:6d7289a]
77
+ 3. If the spec was in `specs/roadmap/`, moves it to `specs/`
78
+ 4. Triggers knowledge reindexing via [ref:.allhands/harness/src/commands/specs.ts:reindexAfterMove:6d7289a]
79
+
80
+ ### `ah specs resurrect <name>`
81
+
82
+ Reverses completion -- moves a spec back to `specs/roadmap/` and sets status to `roadmap`. Mirrors the `complete` flow in reverse, including knowledge reindexing.
83
+
84
+ ### `ah specs persist <path>`
85
+
86
+ Creates a branch for a spec, updates the spec frontmatter with the branch name, and commits the spec file to the base branch. This is the entry point for turning a planned spec into active work.
87
+
88
+ ## Knowledge Reindexing on Move
89
+
90
+ When specs move between directories (complete or resurrect), the knowledge indexes must be updated to reflect the new file paths. [ref:.allhands/harness/src/commands/specs.ts:reindexAfterMove:6d7289a] handles this:
91
+
92
+ - If the old path was in `specs/roadmap/`, mark it as deleted in the `roadmap` index
93
+ - If the new path is in `specs/roadmap/`, mark it as added in the `roadmap` index
94
+ - Always update the `docs` index (which covers all of `specs/`) with a delete + add pair
95
+
96
+ This ensures semantic search returns results with correct file paths immediately after a spec transitions.
97
+
98
+ ## TUI Integration
99
+
100
+ [ref:.allhands/harness/src/lib/specs.ts:specsToModalItems:ce6f7c5] converts spec groups into a format suitable for TUI selection modals, with category headers and selectable items. When no specs exist, it provides a helpful message directing users to create spec files.
101
+
102
+ [ref:.allhands/harness/src/lib/specs.ts:loadSpecsByDomain:ce6f7c5] groups specs by `domain_name` for domain-oriented views, sorting both domains and specs within each domain alphabetically.
@@ -0,0 +1,122 @@
1
+ ---
2
+ description: "MCP tool system providing daemon-managed server sessions, tool discovery and invocation, and a convention-based server registry with auto-discovery from config files."
3
+ ---
4
+
5
+ ## Intent
6
+
7
+ The tools system gives agents access to external capabilities (browser automation, file operations, custom tools) through the Model Context Protocol. The central design tension is **session lifecycle management**: MCP servers are expensive to start, so the system uses a per-agent daemon process that keeps server sessions alive between tool calls. This avoids the cold-start penalty while preventing resource leaks through configurable timeouts.
8
+
9
+ ## Architecture
10
+
11
+ ```mermaid
12
+ flowchart TB
13
+ subgraph CLI["CLI Layer"]
14
+ tools["ah tools &lt;server&gt;:&lt;tool&gt; args"]
15
+ list["ah tools list"]
16
+ servers["ah tools servers"]
17
+ shutdown["ah tools shutdown"]
18
+ end
19
+
20
+ subgraph Client["mcp-client.ts"]
21
+ callTool["callTool"]
22
+ discoverTools["discoverTools"]
23
+ sendToDaemon["sendToDaemon"]
24
+ startDaemon["startDaemon"]
25
+ end
26
+
27
+ subgraph Daemon["mcp-daemon.ts (per-agent process)"]
28
+ processCmd["processCommand"]
29
+ sessions["Session Map"]
30
+ timeout["checkSessionTimeouts"]
31
+ end
32
+
33
+ subgraph Registry["mcp/index.ts"]
34
+ discover["discoverServers"]
35
+ configs["Server Configs (.ts files)"]
36
+ end
37
+
38
+ subgraph Servers["MCP Servers"]
39
+ playwright["Playwright"]
40
+ filesystem["Filesystem"]
41
+ custom["Custom servers..."]
42
+ end
43
+
44
+ tools --> callTool
45
+ list --> discoverTools
46
+ servers --> discover
47
+ shutdown --> sendToDaemon
48
+
49
+ callTool --> sendToDaemon
50
+ discoverTools --> sendToDaemon
51
+ sendToDaemon --> |Unix socket| processCmd
52
+ startDaemon --> Daemon
53
+
54
+ processCmd --> sessions
55
+ sessions --> Servers
56
+ timeout --> |idle cleanup| sessions
57
+
58
+ discover --> configs
59
+ ```
60
+
61
+ ## Daemon Lifecycle
62
+
63
+ The daemon is a long-lived background process scoped to a single agent (identified by AGENT_ID). It manages MCP server sessions via a Unix domain socket.
64
+
65
+ **Startup**: [ref:.allhands/harness/src/lib/mcp-client.ts:startDaemon:50bc6e5] spawns the daemon as a detached child process. The daemon writes its PID and creates the socket at a path derived from the agent ID.
66
+
67
+ **Communication**: [ref:.allhands/harness/src/lib/mcp-client.ts:sendToDaemon:50bc6e5] connects to the Unix socket and sends newline-delimited JSON commands. The daemon's [ref:.allhands/harness/src/lib/mcp-daemon.ts:handleConnection:263f999] buffers incoming data and dispatches complete messages to [ref:.allhands/harness/src/lib/mcp-daemon.ts:processCommand:263f999].
68
+
69
+ **Session management**: Each MCP server gets a session (client + transport) created on first use via [ref:.allhands/harness/src/lib/mcp-daemon.ts:ensureSession:263f999]. Sessions track `lastUsedAt` timestamps and are reaped by [ref:.allhands/harness/src/lib/mcp-daemon.ts:checkSessionTimeouts:263f999] when idle beyond their configured timeout.
70
+
71
+ **Shutdown**: [ref:.allhands/harness/src/lib/mcp-daemon.ts:gracefulShutdown:263f999] closes all MCP transports, clears sessions, closes the server socket, and cleans up PID/socket files. The daemon also exits when its last session closes.
72
+
73
+ ## Daemon Command Protocol
74
+
75
+ | Command | Handler | Behavior |
76
+ |---------|---------|----------|
77
+ | `call` | [ref:.allhands/harness/src/lib/mcp-daemon.ts:handleCall:263f999] | Auto-starts session, invokes tool, returns result |
78
+ | `discover` | [ref:.allhands/harness/src/lib/mcp-daemon.ts:handleDiscover:263f999] | Lists available tools (filters hiddenTools), caches per session |
79
+ | `restart` | [ref:.allhands/harness/src/lib/mcp-daemon.ts:handleRestart:263f999] | Closes existing session, creates fresh one |
80
+ | `list` | [ref:.allhands/harness/src/lib/mcp-daemon.ts:handleList:263f999] | Returns all active sessions with timing info |
81
+ | `ping` | [ref:.allhands/harness/src/lib/mcp-daemon.ts:handlePing:263f999] | Refreshes all session timestamps (keepalive) |
82
+ | `info` | N/A | Returns PID, session count, session names |
83
+ | `shutdown` | N/A | Graceful shutdown of all sessions and daemon |
84
+
85
+ ## Server Registry
86
+
87
+ [ref:.allhands/harness/src/mcp/index.ts:discoverServers:55a5a7f] auto-discovers server configurations by scanning `.ts` files in the `mcp/` directory (excluding `index.ts` and `_template.ts`). Each file exports a `config` object of type `McpServerConfig`.
88
+
89
+ Key config fields that shape behavior:
90
+
91
+ | Field | Effect |
92
+ |-------|--------|
93
+ | `stateful` | If true, daemon keeps session alive between calls. If false, one-shot connections |
94
+ | `stateful_session_timeout` | Custom idle timeout (default from `DAEMON_DEFAULT_MCP_TIMEOUT`) |
95
+ | `hiddenTools` | Tool names to exclude from discovery results |
96
+ | `toolHints` | Extra usage hints shown in `--help` output |
97
+
98
+ Built-in servers: [ref:.allhands/harness/src/mcp/filesystem.ts::1d8cb8a] (stateless file operations) and [ref:.allhands/harness/src/mcp/playwright.ts::98edc6a] (stateful browser automation). New servers are added by copying [ref:.allhands/harness/src/mcp/_template.ts::2919984].
99
+
100
+ ## Runtime Layer
101
+
102
+ [ref:.allhands/harness/src/lib/mcp-runtime.ts::f359acf] provides shared utilities used by both daemon and one-shot paths:
103
+
104
+ - [ref:.allhands/harness/src/lib/mcp-runtime.ts:buildServerCommand:f359acf] resolves the command array from config, handling `npx`, `uvx`, and direct binary paths
105
+ - [ref:.allhands/harness/src/lib/mcp-runtime.ts:resolveEnvVars:f359acf] interpolates `${VAR_NAME}` patterns in environment config from the process environment
106
+ - [ref:.allhands/harness/src/lib/mcp-runtime.ts:formatToolHelp:f359acf] generates human-readable help text for tools including parameter schemas and hints
107
+ - Tool discovery results are cached to disk per server ([ref:.allhands/harness/src/lib/mcp-runtime.ts:getToolsWithCache:f359acf]) to avoid repeated cold starts for tool listing
108
+
109
+ ## CLI Surface
110
+
111
+ [ref:.allhands/harness/src/commands/tools.ts:register:dbc48c6] exposes these subcommands:
112
+
113
+ - `ah tools <server>:<tool> [args...]` -- Invoke a tool with key=value arguments ([ref:.allhands/harness/src/commands/tools.ts:parseToolArgs:dbc48c6] handles JSON auto-parsing)
114
+ - `ah tools list [server]` -- List tools for a server ([ref:.allhands/harness/src/commands/tools.ts:handleListTools:dbc48c6])
115
+ - `ah tools servers` -- List all available servers with session status ([ref:.allhands/harness/src/commands/tools.ts:handleListServers:dbc48c6])
116
+ - `ah tools sessions` -- Show active daemon sessions ([ref:.allhands/harness/src/commands/tools.ts:handleListSessions:dbc48c6])
117
+ - `ah tools shutdown` -- Shut down the daemon ([ref:.allhands/harness/src/commands/tools.ts:handleShutdownDaemon:dbc48c6])
118
+ - `ah tools restart <server>` -- Restart a server session ([ref:.allhands/harness/src/commands/tools.ts:handleSessionRestart:dbc48c6])
119
+
120
+ ## One-Shot vs Daemon Path
121
+
122
+ The client layer ([ref:.allhands/harness/src/lib/mcp-client.ts::50bc6e5]) transparently routes through the daemon when running or falls back to one-shot connections via [ref:.allhands/harness/src/lib/mcp-client.ts:createOneShot:50bc6e5]. This dual-path design means tools work even without the daemon, at the cost of cold-starting the server each time.