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,91 @@
1
+ ---
2
+ description: "CLI entry point architecture: how the `ah` binary boots, auto-discovers command modules, and provides base-command utilities for tracing, context, and output formatting."
3
+ ---
4
+
5
+ # CLI Entry and Command Discovery
6
+
7
+ ## Why This Architecture Exists
8
+
9
+ The harness CLI (`ah`) serves as the single entry surface for both human operators and agent processes. Two constraints shaped its design:
10
+
11
+ 1. **Commands must be independently deployable** -- adding a new capability should require only dropping a file into the commands directory, with zero registration boilerplate.
12
+ 2. **Every invocation must be observable** -- agents operate autonomously, so every command execution needs trace logging for post-hoc debugging.
13
+
14
+ These constraints produced a three-layer stack: a thin entry point, a filesystem-based command registry, and a shared base-command layer that handles cross-cutting concerns.
15
+
16
+ ## Boot Sequence
17
+
18
+ ```mermaid
19
+ sequenceDiagram
20
+ participant User as ah CLI
21
+ participant Main as main()
22
+ participant Discover as discoverAndRegister()
23
+ participant Modules as Command Modules
24
+ participant Commander as Commander.js
25
+
26
+ User->>Main: process invocation
27
+ Main->>Commander: create program with name, version, default action
28
+ Main->>Discover: pass program instance
29
+ Discover->>Discover: readdirSync(commands/)
30
+ loop each .ts file (skip index.ts)
31
+ Discover->>Modules: dynamic import(./module.js)
32
+ Modules->>Commander: module.register(program)
33
+ end
34
+ Main->>Commander: parseAsync()
35
+ Commander->>User: execute matched command or launch TUI
36
+ ```
37
+
38
+ When no subcommand is provided, [ref:.allhands/harness/src/cli.ts:main:dc6aae1] falls through to the default action, which launches the TUI via `launchTUI`. This makes the bare `ah` command an interactive experience while subcommands remain agent-scriptable.
39
+
40
+ ## Command Auto-Discovery
41
+
42
+ [ref:.allhands/harness/src/commands/index.ts:discoverAndRegister:33f0cd2] implements convention-over-configuration discovery:
43
+
44
+ | Rule | Behavior |
45
+ |------|----------|
46
+ | File ends with `.ts` | Candidate for import |
47
+ | File is `index.ts` | Skipped (it *is* the registry) |
48
+ | File is a directory | Skipped (single-file modules only) |
49
+ | Module exports `register(program)` | Registered as a command |
50
+ | Module fails to load | Warning logged, other commands unaffected |
51
+
52
+ The `CommandModule` interface enforces a single contract: export a `register` function that receives a Commander `Command` instance. This means adding a new CLI command is a single-file operation with no central manifest to update.
53
+
54
+ **Key decision**: Error isolation. A broken command module logs a warning but does not prevent the rest of the CLI from functioning. This is critical for agent reliability -- a partial harness is better than no harness.
55
+
56
+ ## Base Command Utilities
57
+
58
+ [ref:.allhands/harness/src/lib/base-command.ts::b6b76d4] provides the cross-cutting layer that every command can opt into.
59
+
60
+ ### Environment Context
61
+
62
+ [ref:.allhands/harness/src/lib/base-command.ts:getEnvContext:b6b76d4] reads agent identity from environment variables (`AGENT_TYPE`, `PROMPT_NUMBER`, `SPEC_NAME`). These are set by the tmux window spawner when agents are launched, providing automatic trace attribution without commands needing to accept explicit agent flags.
63
+
64
+ ### Context Resolution
65
+
66
+ [ref:.allhands/harness/src/lib/base-command.ts:parseContext:b6b76d4] merges CLI options with environment context. The precedence order:
67
+
68
+ 1. Explicit `--agent` flag (highest)
69
+ 2. `AGENT_TYPE` environment variable
70
+ 3. Undefined (no agent context)
71
+
72
+ This allows both human operators (who pass flags) and automated agents (who inherit env vars) to use the same commands.
73
+
74
+ ### Output Formatting
75
+
76
+ [ref:.allhands/harness/src/lib/base-command.ts:formatOutput:b6b76d4] switches between JSON (for agent consumption) and human-readable text based on the `--json` flag. Every command that uses `executeCommand` gets this for free.
77
+
78
+ ### Traced Execution
79
+
80
+ Two patterns exist for adding trace logging:
81
+
82
+ | Pattern | Use Case |
83
+ |---------|----------|
84
+ | [ref:.allhands/harness/src/lib/base-command.ts:executeCommand:b6b76d4] | Commands that return `CommandResult` objects |
85
+ | [ref:.allhands/harness/src/lib/base-command.ts:tracedAction:b6b76d4] | Lightweight wrapper for commands that handle their own output |
86
+
87
+ Both patterns log start, success, and error events to the trace store. `tracedAction` is the more common pattern -- it wraps a Commander action handler and extracts arguments for logging automatically, filtering out the Commander object that Commander.js appends as the last argument.
88
+
89
+ ### Common Options
90
+
91
+ [ref:.allhands/harness/src/lib/base-command.ts:addCommonOptions:b6b76d4] attaches `--agent`, `--json`, and `--verbose` flags to any command. These are the harness-standard options that enable agent-mode operation and observability.
@@ -0,0 +1,87 @@
1
+ ---
2
+ description: "Documentation integrity system that validates file references and symbol lookups via ctags, detects stale hashes, and finalizes placeholder refs into versioned references with git blob hashes (content-addressable, stable across merges and rebases)."
3
+ ---
4
+
5
+ ## Intent
6
+
7
+ Documentation in this codebase uses file-reference markers (with file path, symbol name, and git hash components) instead of code snippets. This solves the staleness problem -- when code changes, refs become stale rather than silently incorrect. The docs command provides the validation and finalization pipeline that makes this reference system work.
8
+
9
+ The core trade-off: **references add maintenance overhead but eliminate silent drift**. A stale ref is a known problem; a stale code snippet is an unknown one.
10
+
11
+ ## Reference Lifecycle
12
+
13
+ ```mermaid
14
+ stateDiagram-v2
15
+ [*] --> Placeholder: Writer creates ref marker
16
+ Placeholder --> Finalized: ah docs finalize
17
+ Finalized --> Valid: Hash matches current file
18
+ Valid --> Stale: Source file modified
19
+ Stale --> Finalized: ah docs finalize (re-run)
20
+ Finalized --> Invalid: Symbol removed or file deleted
21
+ Invalid --> [*]: Manual fix required
22
+ ```
23
+
24
+ Writers create placeholder refs during authoring (file path and symbol name, without a hash). The finalize command resolves these into versioned refs by appending the git blob hash of the referenced file. Blob hashes are content-addressable, meaning they depend only on file content -- not commit history. This makes staleness detection resilient to merges, rebases, squash merges, and cherry-picks. Validation then checks that hashes still match and symbols still exist.
25
+
26
+ ## Validation Pipeline
27
+
28
+ [ref:.allhands/harness/src/commands/docs.ts:validate:3912018] orchestrates the full validation pass:
29
+
30
+ 1. Check ctags availability ([ref:.allhands/harness/src/lib/ctags.ts:checkCtagsAvailable:45c4520])
31
+ 2. Generate a ctags index for the project ([ref:.allhands/harness/src/lib/ctags.ts:generateCtagsIndex:45c4520])
32
+ 3. Find all markdown files in the docs path ([ref:.allhands/harness/src/lib/docs-validation.ts:findMarkdownFiles:8f3104d])
33
+ 4. For each file, run [ref:.allhands/harness/src/lib/docs-validation.ts:validateDocs:8f3104d] which:
34
+ - Validates frontmatter (requires `description` field) via [ref:.allhands/harness/src/lib/docs-validation.ts:validateFrontMatter:8f3104d]
35
+ - Extracts all ref patterns via [ref:.allhands/harness/src/lib/docs-validation.ts:extractRefs:8f3104d]
36
+ - Validates each ref via [ref:.allhands/harness/src/lib/docs-validation.ts:validateRef:8f3104d]
37
+ - Detects placeholder hashes via [ref:.allhands/harness/src/lib/docs-validation.ts:detectPlaceholders:8f3104d]
38
+ - Detects unfinalized refs via [ref:.allhands/harness/src/lib/docs-validation.ts:detectUnfinalizedRefs:8f3104d]
39
+
40
+ ### Ref Validation Logic
41
+
42
+ [ref:.allhands/harness/src/lib/docs-validation.ts:validateRef:8f3104d] classifies each reference into three states:
43
+
44
+ | State | Condition | Meaning |
45
+ |-------|-----------|---------|
46
+ | **valid** | File exists, hash matches, symbol found (if code file) | Reference is current |
47
+ | **stale** | File exists but hash differs from ref | Source has been modified since ref was created |
48
+ | **invalid** | File missing, git hash lookup failed, or symbol not found | Reference is broken |
49
+
50
+ For non-code files (markdown, YAML, JSON), the symbol portion is treated as a label -- only the file hash is verified. For code files, [ref:.allhands/harness/src/lib/ctags.ts:lookupSymbol:45c4520] checks that the symbol exists in the ctags index.
51
+
52
+ ## Finalization
53
+
54
+ [ref:.allhands/harness/src/commands/docs.ts:finalize:3912018] converts placeholder refs into finalized refs:
55
+
56
+ 1. Scan all markdown files for ref patterns without existing hash
57
+ 2. Batch-collect all referenced files and compute their blob hashes via [ref:.allhands/harness/src/lib/docs-validation.ts:batchGetBlobHashes:8f3104d]
58
+ 3. For each placeholder in [ref:.allhands/harness/src/commands/docs.ts:finalizeSingleFile:3912018]:
59
+ - Verify the file exists
60
+ - Look up the blob hash
61
+ - For code files with symbols, verify the symbol exists via [ref:.allhands/harness/src/lib/ctags.ts:findSymbolInFile:45c4520]
62
+ - Append the resolved blob hash to each placeholder ref
63
+ 4. Write modified content back to disk
64
+
65
+ Supports both single-file and directory (batch) operation. Certain paths are excluded from processing (e.g., `docs/memories.md`, `docs/solutions`).
66
+
67
+ ### Refresh Mode
68
+
69
+ When `--refresh` is passed, `ah docs finalize --refresh` operates on ALL finalized refs (not just placeholders). For each existing `[ref:file:symbol:hash]` marker, it recomputes the current blob hash and replaces the stored hash in-place. This is useful after switching from commit-based hashes to blob-based hashes, or after any operation that may have caused hash drift without changing file content (e.g., merges, rebases).
70
+
71
+ Counts reported: updated (hash changed), unchanged (hash already correct), errored (file missing or hash lookup failed).
72
+
73
+ ## Ctags Integration
74
+
75
+ The ctags layer ([ref:.allhands/harness/src/lib/ctags.ts::45c4520]) provides symbol lookup without requiring language-specific AST parsers:
76
+
77
+ - [ref:.allhands/harness/src/lib/ctags.ts:generateCtagsIndex:45c4520] runs Universal Ctags to build an index mapping files to their symbols
78
+ - [ref:.allhands/harness/src/lib/ctags.ts:lookupSymbol:45c4520] finds symbols by name within a specific file
79
+ - [ref:.allhands/harness/src/lib/ctags.ts:findSymbolInFile:45c4520] is the single-file variant used during finalization
80
+ - [ref:.allhands/harness/src/lib/ctags.ts:searchSymbol:45c4520] searches across all files for a symbol name
81
+ - [ref:.allhands/harness/src/lib/ctags.ts:getFileSymbols:45c4520] returns all symbols in a file (used by the complexity command)
82
+
83
+ This design choice (ctags over AST parsing) trades precision for breadth -- ctags supports TypeScript, Python, Go, Rust, Java, and Ruby with a single tool.
84
+
85
+ ## Doc Tree Coverage
86
+
87
+ [ref:.allhands/harness/src/commands/docs.ts:tree:3912018] generates a source tree annotated with documentation coverage. For each source file, it checks whether a corresponding doc exists at predictable paths (`docs/{path}.md`, `docs/{dir}/{name}.md`, `docs/{path}/index.md`). The output includes coverage statistics (total files, covered files, percentage).
@@ -0,0 +1,91 @@
1
+ ---
2
+ description: "Embedding-based semantic search over project knowledge: how documents are indexed into USearch HNSW indexes, searched by similarity, and incrementally reindexed from git changes."
3
+ ---
4
+
5
+ # Knowledge Command
6
+
7
+ ## Intent
8
+
9
+ Agents need to discover relevant project knowledge without knowing exact file paths or keywords. The knowledge system provides semantic search -- query with a natural language description and get back the most relevant documents ranked by embedding similarity. This is the infrastructure behind `ah knowledge docs search <query>`.
10
+
11
+ ## Architecture
12
+
13
+ ```mermaid
14
+ flowchart TD
15
+ Query["Search Query"] --> Embed["Embed query<br/>gtr-t5-quant"]
16
+ Embed --> Search["USearch HNSW<br/>cosine similarity"]
17
+ Search --> Filter["Threshold + Token Budget"]
18
+ Filter --> Aggregate{"Total tokens > 3500?"}
19
+ Aggregate -->|Yes| AI["AI Aggregator<br/>synthesize insights"]
20
+ Aggregate -->|No| Raw["Return raw results"]
21
+ AI --> Output["Structured output:<br/>insight, LSP entry points, design notes"]
22
+ Raw --> Output
23
+ ```
24
+
25
+ ## Index Configuration
26
+
27
+ [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] manages multiple named indexes, each configured for a specific document domain:
28
+
29
+ | Index | Paths Scanned | Description |
30
+ |-------|---------------|-------------|
31
+ | `docs` | `docs/`, `specs/` | Project documentation and specifications |
32
+ | `roadmap` | `specs/roadmap/` | Planned work specifications |
33
+
34
+ Each index stores its data as two files in `.allhands/harness/.knowledge/`:
35
+ - `{name}.usearch` -- the HNSW vector index (768-dimensional, cosine metric)
36
+ - `{name}.meta.json` -- bidirectional path-to-ID mappings, document metadata, timestamps
37
+
38
+ Files named `memories.md` are excluded from indexing -- they contain project-specific learnings that are not suited for semantic search.
39
+
40
+ ## Embedding and Search
41
+
42
+ [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] exposes an `embed` method that generates 768-dimensional embeddings using the `gtr-t5-quant` model from `@visheratin/web-ai-node`. The model is lazy-loaded on first use and cached for the process lifetime.
43
+
44
+ The `search` method on [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] executes similarity search with several filtering layers:
45
+
46
+ | Filter | Threshold | Purpose |
47
+ |--------|-----------|---------|
48
+ | Similarity minimum | 0.65 (configurable) | Discard irrelevant results |
49
+ | Token budget | 5000 tokens (configurable) | Bound context size for agents |
50
+ | Full context threshold | 0.82 (configurable) | Only include full file content for high-confidence matches |
51
+
52
+ The similarity score converts cosine distance to a 0-1 scale: `similarity = 1 - distance/2`. The search over-fetches by 2x to compensate for deleted entries that remain in the vector index (USearch does not support true deletion).
53
+
54
+ Thresholds are configurable via project settings under `knowledge.similarityThreshold`, `knowledge.contextTokenLimit`, and `knowledge.fullContextSimilarityThreshold`.
55
+
56
+ ## Search Command with Aggregation
57
+
58
+ [ref:.allhands/harness/src/commands/knowledge.ts:SearchCommand:681f3dc] adds an AI aggregation layer on top of raw search results. When the total token count of results exceeds 3500 tokens, it invokes an aggregator agent that synthesizes the raw results into structured output: an insight summary, LSP entry points for code navigation, and design notes.
59
+
60
+ The aggregation can be disabled with `--no-aggregate` for raw results, or `--metadata-only` for just file paths and descriptions without content.
61
+
62
+ ## Indexing
63
+
64
+ ### Full Reindex
65
+
66
+ The `reindexAll` method on [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] rebuilds an index from scratch:
67
+
68
+ 1. Discovers all files matching the index configuration (paths + extensions)
69
+ 2. Parses frontmatter from markdown files for metadata (description, relevant_files)
70
+ 3. Strips frontmatter from content before embedding (when configured)
71
+ 4. Generates embeddings and adds vectors to a fresh USearch index
72
+ 5. Saves index and metadata to disk
73
+
74
+ ### Incremental Reindex
75
+
76
+ The `reindexFromChanges` method on [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] updates an existing index based on a list of file changes:
77
+
78
+ - **Added/Modified files**: Re-embed and upsert into the index
79
+ - **Deleted files**: Remove from metadata (vector remains in index but is filtered during search)
80
+
81
+ [ref:.allhands/harness/src/commands/knowledge.ts:getChangesFromGit:681f3dc] detects changes by comparing the current branch against the base branch using `git diff --name-status`. This powers the `--from-changes` flag on reindex commands.
82
+
83
+ [ref:.allhands/harness/src/commands/knowledge.ts:ReindexCommand:681f3dc] supports both full and incremental modes, and can operate on a single index or all indexes at once.
84
+
85
+ ### Document Indexing
86
+
87
+ The `indexDocument` method on [ref:.allhands/harness/src/lib/knowledge.ts:KnowledgeService:0f31ba1] handles individual document insertion. It assigns or reuses numeric IDs, removes old entries before re-adding (USearch requires unique keys), generates embeddings, and stores metadata including description, relevant files, and estimated token count.
88
+
89
+ ## Status Checking
90
+
91
+ [ref:.allhands/harness/src/commands/knowledge.ts:StatusCommand:681f3dc] reports which indexes exist on disk, enabling agents to determine whether they need to trigger a reindex before searching.
@@ -0,0 +1,65 @@
1
+ ---
2
+ description: "Smaller CLI utilities: skills discovery from YAML frontmatter, desktop notifications via jamf/Notifier with gate/hook variants, and ctags-based complexity metrics for files and directories."
3
+ ---
4
+
5
+ ## Skills Discovery
6
+
7
+ [ref:.allhands/harness/src/commands/skills.ts:listSkills:4fb6c9f] scans `.allhands/skills/*/SKILL.md` for skill definitions. Each skill file must have YAML frontmatter with `name`, `description`, and `globs` fields. The command outputs a JSON array of discovered skills with their glob patterns, enabling agents to find domain-specific expertise.
8
+
9
+ Skills are organized as directories under `.allhands/skills/`, where each directory contains a `SKILL.md` file. The frontmatter schema:
10
+
11
+ | Field | Required | Purpose |
12
+ |-------|----------|---------|
13
+ | `name` | Yes | Skill identifier |
14
+ | `description` | Yes | What the skill provides |
15
+ | `globs` | Yes | File patterns the skill is relevant for |
16
+ | `version` | No | Skill version |
17
+ | `license` | No | License information |
18
+
19
+ ## Desktop Notifications
20
+
21
+ The notification system uses jamf/Notifier (macOS) for system-level desktop notifications. This is designed for situations where agents need human attention -- gate approvals, idle detection, or completion signals.
22
+
23
+ ### Notification Layout
24
+
25
+ [ref:.allhands/harness/src/lib/notification.ts:sendNotification:8f14a76] constructs notifications with three parts:
26
+ - **Title**: Event type (e.g., "Agent Stopped", "Plan Gate")
27
+ - **Subtitle**: Auto-detected from `repo + branch` context
28
+ - **Message**: Specific details for the user
29
+
30
+ ### Notification Variants
31
+
32
+ | Function | Type | Behavior |
33
+ |----------|------|----------|
34
+ | [ref:.allhands/harness/src/lib/notification.ts:sendNotification:8f14a76] | Configurable | Base function, supports banner or alert |
35
+ | [ref:.allhands/harness/src/lib/notification.ts:sendGateNotification:8f14a76] | `alert` | Persists until dismissed. Used for decisions requiring human input |
36
+ | `sendHookNotification` | `banner` | Auto-dismisses. Used for informational hook events |
37
+
38
+ Banners auto-dismiss after the system default; alerts persist until the user interacts with them. The `--sound` option triggers a macOS system sound.
39
+
40
+ The notifier binary is located at `/Applications/Utilities/Notifier.app/Contents/MacOS/Notifier` or via PATH lookup. If not installed, notifications silently fail (no error propagation) -- this is intentional so agents don't break on systems without the notifier.
41
+
42
+ ## Complexity Analysis
43
+
44
+ [ref:.allhands/harness/src/commands/complexity.ts:complexity:ec1532e] provides complexity metrics for files and directories using ctags for symbol counting rather than language-specific AST parsers.
45
+
46
+ ### File Metrics
47
+
48
+ For a single file, the output includes:
49
+
50
+ | Metric | Source |
51
+ |--------|--------|
52
+ | lines | Line count |
53
+ | functions | ctags `function` + `method` kinds |
54
+ | classes | ctags `class` kind |
55
+ | interfaces | ctags `interface` + `type` kinds |
56
+ | imports | Regex match on `^import\s` |
57
+ | exports | Regex match on `^export\s` |
58
+ | total_symbols | Total ctags entries |
59
+ | estimated_tokens | `lines * 10` (rough heuristic) |
60
+
61
+ ### Directory Metrics
62
+
63
+ For directories, the command recursively scans source files (`.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.go`, `.rs`, `.java`), generates a ctags index for the subtree, and aggregates line counts and symbol counts across all files. The output includes `file_count` alongside the aggregated metrics.
64
+
65
+ Both modes require Universal Ctags to be installed ([ref:.allhands/harness/src/lib/ctags.ts:checkCtagsAvailable:45c4520]).
@@ -0,0 +1,113 @@
1
+ ---
2
+ description: "LLM-powered oracle system: multi-provider inference layer, PR generation from alignment docs, conversation analysis for compaction, and action recommendation for agent retry logic."
3
+ ---
4
+
5
+ # Oracle Command
6
+
7
+ ## Intent
8
+
9
+ The oracle is the harness's bridge to external LLM providers. It serves two purposes:
10
+
11
+ 1. **Generic inference** (`ah oracle ask`) -- a provider-agnostic way for any harness component to call an LLM
12
+ 2. **Harness-specific AI tasks** -- PR generation, conversation analysis, and retry recommendations that are internal functions not exposed to agents
13
+
14
+ The separation between [ref:.allhands/harness/src/lib/llm.ts::697d7e2] (generic provider layer) and [ref:.allhands/harness/src/lib/oracle.ts::3d01f6c] (harness-specific logic) keeps the LLM infrastructure reusable while concentrating domain-specific prompting in one place.
15
+
16
+ ## Provider Architecture
17
+
18
+ ```mermaid
19
+ flowchart TD
20
+ Ask["ask(query, options)"] --> Resolve["Resolve provider"]
21
+ Resolve --> Key["Read API key<br/>from environment"]
22
+ Key --> Build["Build prompt:<br/>context + files + query"]
23
+ Build --> Dispatch{"Provider?"}
24
+ Dispatch -->|gemini| Gemini["callGemini()<br/>@google/genai SDK"]
25
+ Dispatch -->|openai| OpenAI["callOpenAI()<br/>OpenAI-compatible API"]
26
+ Gemini --> Result["LLMResult:<br/>text, model, provider, durationMs"]
27
+ OpenAI --> Result
28
+ ```
29
+
30
+ [ref:.allhands/harness/src/lib/llm.ts:ask:697d7e2] is the unified entry point. It resolves the provider, reads the API key from environment, builds a prompt with optional file and context prefixes, dispatches to the provider-specific implementation, and returns a result with timing metadata.
31
+
32
+ ### Provider Configuration
33
+
34
+ | Provider | API Key Env Var | Default Model | SDK |
35
+ |----------|----------------|---------------|-----|
36
+ | Gemini | `GEMINI_API_KEY` | `gemini-3-pro-preview` | `@google/genai` |
37
+ | OpenAI | `OPENAI_API_KEY` | `gpt-5.2` | OpenAI-compatible REST |
38
+
39
+ [ref:.allhands/harness/src/lib/llm.ts:getDefaultProvider:697d7e2] reads the default from project settings (`oracle.defaultProvider`), falling back to `gemini`.
40
+
41
+ [ref:.allhands/harness/src/lib/llm.ts:getCompactionProvider:697d7e2] is separate because compaction (conversation analysis) benefits from large context windows. It defaults to `gemini` for its 1M+ token context, configurable via `oracle.compactionProvider`.
42
+
43
+ ### Provider Implementations
44
+
45
+ [ref:.allhands/harness/src/lib/llm.ts:callGemini:697d7e2] uses the official `@google/genai` SDK with API key authentication (Gemini Developer API, not Vertex AI).
46
+
47
+ [ref:.allhands/harness/src/lib/llm.ts:callOpenAI:697d7e2] uses the OpenAI-compatible REST API.
48
+
49
+ [ref:.allhands/harness/src/lib/llm.ts:callProvider:697d7e2] dispatches to the appropriate implementation based on provider name.
50
+
51
+ ## PR Generation
52
+
53
+ [ref:.allhands/harness/src/lib/oracle.ts:buildPR:3d01f6c] orchestrates the full PR creation workflow:
54
+
55
+ ```mermaid
56
+ sequenceDiagram
57
+ participant Build as buildPR()
58
+ participant Plan as Planning State
59
+ participant Gen as generatePRDescription()
60
+ participant GH as gh CLI
61
+ participant Comments as postPRComments()
62
+
63
+ Build->>Plan: Read alignment doc + status
64
+ Build->>Gen: Generate title, body, review steps
65
+ Gen-->>Build: PRContent
66
+ alt PR already exists in status.yaml
67
+ Build->>GH: Update PR description
68
+ Build->>Comments: Update review comments
69
+ else No existing PR
70
+ Build->>GH: Push branch + create PR
71
+ Build->>Comments: Post review comments
72
+ Build->>Plan: Update status.yaml with PR info
73
+ end
74
+ ```
75
+
76
+ [ref:.allhands/harness/src/lib/oracle.ts:generatePRDescription:3d01f6c] takes alignment content, spec name, and optional spec content, then:
77
+
78
+ 1. Gets the git diff from base branch
79
+ 2. Parses changed files from the diff
80
+ 3. Prompts the LLM to generate a title, body, and review steps grouped by file category
81
+ 4. Validates the response against a Zod schema (`PRContentSchema`)
82
+ 5. Falls back to [ref:.allhands/harness/src/lib/oracle.ts:extractAlignmentSummary:3d01f6c] + [ref:.allhands/harness/src/lib/oracle.ts:generateFallbackReviewSteps:3d01f6c] if LLM fails
83
+
84
+ **Key decision**: The fallback groups changed files by type (Core Logic, API/Routes, Components, Tests, Configuration) using path pattern matching, ensuring review steps always exist even when the LLM is unavailable.
85
+
86
+ [ref:.allhands/harness/src/lib/oracle.ts:postPRComments:3d01f6c] adds review step comments to the PR via `gh api`. [ref:.allhands/harness/src/lib/oracle.ts:updatePRDescription:3d01f6c] and [ref:.allhands/harness/src/lib/oracle.ts:updatePRComments:3d01f6c] handle the update-existing-PR path, finding and replacing previous harness-generated comments.
87
+
88
+ ## Conversation Analysis
89
+
90
+ [ref:.allhands/harness/src/lib/oracle.ts:analyzeConversation:3d01f6c] examines agent conversation logs after a session to extract:
91
+
92
+ - Whether the agent was making meaningful progress
93
+ - Estimated completion percentage (0-100)
94
+ - Key learnings for the next attempt
95
+ - Blockers that prevented completion
96
+ - Partial work worth preserving
97
+
98
+ The response is validated against `ConversationAnalysisSchema` (Zod with `z.coerce` to handle LLMs returning strings for boolean/number fields). On failure, it returns a conservative fallback assuming 50% progress.
99
+
100
+ ## Action Recommendation
101
+
102
+ [ref:.allhands/harness/src/lib/oracle.ts:recommendAction:3d01f6c] uses the conversation analysis to decide the next step:
103
+
104
+ | Decision | Criteria |
105
+ |----------|----------|
106
+ | `continue` | >40% progress, code compiles, meaningful logic exists |
107
+ | `scratch` | <20% progress, code broken, mostly boilerplate, wrong approach |
108
+
109
+ The recommendation includes `preserveFiles` and `discardFiles` lists, enabling selective code preservation during retry. On LLM failure, it defaults to `continue` to avoid losing code unnecessarily.
110
+
111
+ ## Response Parsing
112
+
113
+ All oracle functions that expect structured LLM responses use [ref:.allhands/harness/src/lib/oracle.ts:extractJSON:3d01f6c] to handle the variety of response formats LLMs produce. It tries markdown code block extraction first (```` ```json ... ``` ````), then falls back to brace-matching with proper string escape handling.
@@ -0,0 +1,95 @@
1
+ ---
2
+ description: "Branch-keyed planning directories: how the harness creates and manages per-branch planning state including status tracking, alignment documents, and decision logs."
3
+ ---
4
+
5
+ # Planning Command
6
+
7
+ ## Intent
8
+
9
+ Every spec under active development needs a working directory for mutable planning state: which stage the work is in, what decisions have been made, and what the alignment document says. The planning system maps this state to git branches, making the current branch the sole determinant of which planning context is active.
10
+
11
+ This is the harness's answer to the question: *where does ephemeral implementation state live?*
12
+
13
+ ## Branch-to-Directory Model
14
+
15
+ ```mermaid
16
+ flowchart LR
17
+ Branch["git branch<br/>feature/auth-flow"] -->|sanitize| Key["feature-auth-flow"]
18
+ Key -->|resolve| Dir[".planning/feature-auth-flow/"]
19
+ Dir --> Status["status.yaml"]
20
+ Dir --> Alignment["alignment.md"]
21
+ Dir --> Prompts["prompts/"]
22
+ ```
23
+
24
+ [ref:.allhands/harness/src/lib/planning.ts:sanitizeBranchForDir:41639ef] converts branch names to filesystem-safe directory keys by replacing non-alphanumeric characters (slashes, dots) with hyphens. `feature/foo-bar` becomes `feature-foo-bar`.
25
+
26
+ ### Locked Branches
27
+
28
+ Not every branch should have planning state. [ref:.allhands/harness/src/lib/planning.ts:isLockedBranch:41639ef] prevents planning directories for:
29
+
30
+ | Category | Examples |
31
+ |----------|----------|
32
+ | Protected names | `main`, `master`, `develop`, `staging`, `production` |
33
+ | Configured base branch | Whatever `BASE_BRANCH` resolves to |
34
+ | Prefix patterns | `wt-*` (worktrees), `quick/*` (quick fixes) |
35
+
36
+ ## Planning Directory Structure
37
+
38
+ Each planning directory at `.planning/{key}/` contains:
39
+
40
+ | File | Purpose | Managed By |
41
+ |------|---------|------------|
42
+ | `status.yaml` | Session state: stage, loop config, PR info | [ref:.allhands/harness/src/lib/planning.ts:writeStatus:41639ef] |
43
+ | `alignment.md` | Decisions, overview, hard requirements | [ref:.allhands/harness/src/lib/planning.ts:initializeAlignment:41639ef] |
44
+ | `prompts/` | Prompt files for agent execution | External (planner agents) |
45
+
46
+ ### Status Lifecycle
47
+
48
+ ```mermaid
49
+ stateDiagram-v2
50
+ [*] --> planning: initializeStatus()
51
+ planning --> executing: Agent begins prompt work
52
+ executing --> reviewing: All prompts completed
53
+ reviewing --> pr: PR created
54
+ pr --> compound: Compound run triggered
55
+ compound --> pr: PR updated
56
+ ```
57
+
58
+ [ref:.allhands/harness/src/lib/planning.ts:initializeStatus:41639ef] creates the initial `StatusFile` with the `planning` stage, linking it to the spec path and recording the original branch name for collision detection.
59
+
60
+ [ref:.allhands/harness/src/lib/planning.ts:updateStatus:41639ef] performs partial updates, merging new fields into the existing status while preserving the `updated` timestamp.
61
+
62
+ ### Alignment Document
63
+
64
+ The alignment document is the shared memory between planning and execution agents. It contains:
65
+
66
+ - **Frontmatter**: spec name, spec path, timestamps
67
+ - **Overview**: high-level description from the planner
68
+ - **Hard Requirements**: non-negotiable constraints from the spec
69
+ - **Decisions**: append-only log of implementation decisions
70
+
71
+ [ref:.allhands/harness/src/lib/planning.ts:appendDecision:41639ef] adds timestamped decision entries recording which prompt prompted the decision, what was decided, which files were affected, and a summary. This creates an audit trail that execution agents and PR reviewers can reference.
72
+
73
+ [ref:.allhands/harness/src/lib/planning.ts:readAlignment:41639ef] returns the full alignment content, while [ref:.allhands/harness/src/lib/planning.ts:readAlignmentFrontmatter:41639ef] returns just the parsed YAML header for metadata access without loading the full document body.
74
+
75
+ ## CLI Subcommands
76
+
77
+ [ref:.allhands/harness/src/commands/planning.ts:register:351bd20] exposes three subcommands:
78
+
79
+ - **`ah planning status`** -- Reports the current branch's planning state. Resolves the branch, finds the linked spec via [ref:.allhands/harness/src/lib/specs.ts:getSpecForBranch:ce6f7c5], and reads the status file. Outputs spec info, stage, and PR status when available.
80
+
81
+ - **`ah planning list`** -- Enumerates all planning directories via [ref:.allhands/harness/src/lib/planning.ts:listPlanningDirs:41639ef], showing key, spec path, stage, and marking the current branch's directory.
82
+
83
+ - **`ah planning ensure`** -- Idempotent setup: creates the planning directory and initializes status if they do not exist for the current branch. Requires a spec to be linked to the branch.
84
+
85
+ ## Planning Utilities
86
+
87
+ [ref:.allhands/harness/src/lib/planning-utils.ts:findSpecForPath:f283c2d] resolves a spec path to its planning directory key, bridging the gap when code needs to go from a spec file to its planning state. It does this by checking spec frontmatter for a `branch` field and sanitizing it.
88
+
89
+ [ref:.allhands/harness/src/lib/planning-utils.ts:listAllSpecs:f283c2d] provides a flat list of all specs with their planning directory links, useful for TUI spec selection and overview displays.
90
+
91
+ ## Key Design Decisions
92
+
93
+ - **Branch as key, not spec name**: Using the branch ensures each working context is independent even when the same spec is attempted on different branches.
94
+ - **Append-only decisions**: The alignment document never overwrites previous decisions, preserving the reasoning chain for future agents and human reviewers.
95
+ - **Locked branches**: Prevents accidental planning state on shared branches, which would cause conflicts in multi-agent environments.