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,122 @@
1
+ ---
2
+ description: "Observability system with dual-storage trace events (SQLite + JSONL), structured logging across all harness subsystems (hooks, commands, TUI, agents), and CLI querying with filtering, stats aggregation, and real-time tailing."
3
+ ---
4
+
5
+ ## Intent
6
+
7
+ When multiple agents run concurrently across tmux windows, debugging failures requires structured observability. The trace system captures events from every harness subsystem -- hooks, CLI commands, TUI actions, agent spawning -- and stores them in both a queryable SQLite database and a greppable JSONL file. The dual-storage design reflects the two access patterns: SQL for filtered queries and aggregation, JSONL for `grep`/`tail -f` workflows.
8
+
9
+ ## Event Model
10
+
11
+ Every trace event carries agent context derived from environment variables (AGENT_ID, AGENT_TYPE, PROMPT_NUMBER, SPEC_NAME, BRANCH), enabling filtering by which agent produced the event. The `viaDaemon` flag distinguishes events from the CLI daemon vs direct tsx execution.
12
+
13
+ ### Event Types
14
+
15
+ ```mermaid
16
+ graph LR
17
+ subgraph Session
18
+ ss[session.start]
19
+ se[session.end]
20
+ end
21
+
22
+ subgraph Tools
23
+ tp[tool.pre]
24
+ tpost[tool.post]
25
+ tf[tool.failure]
26
+ td[tool.denied]
27
+ be[bash.error]
28
+ end
29
+
30
+ subgraph Hooks
31
+ hs[hook.start]
32
+ hok[hook.success]
33
+ he[hook.error]
34
+ end
35
+
36
+ subgraph Commands
37
+ cs[command.start]
38
+ cok[command.success]
39
+ ce[command.error]
40
+ end
41
+
42
+ subgraph TUI
43
+ ta[tui.action]
44
+ tl[tui.lifecycle]
45
+ te[tui.error]
46
+ end
47
+
48
+ subgraph Agents
49
+ as2[agent.spawn]
50
+ ast[agent.stop]
51
+ ac[agent.compact]
52
+ end
53
+
54
+ subgraph Prompts
55
+ ps[prompt.submit]
56
+ end
57
+
58
+ subgraph Harness
59
+ herr[harness.error]
60
+ end
61
+ ```
62
+
63
+ Error events are explicitly enumerated for fast filtering: `tool.failure`, `tool.denied`, `bash.error`, `hook.error`, `harness.error`, `tui.error`, `command.error`.
64
+
65
+ ## Storage Architecture
66
+
67
+ [ref:.allhands/harness/src/lib/trace-store.ts:logEvent:36af65f] writes to both backends on every event:
68
+
69
+ - **SQLite** (`.allhands/harness/.cache/trace/trace.db`): Indexed columns for agent_id, agent_type, event_type, tool_name, timestamp, is_error. Enables efficient filtered queries.
70
+ - **JSONL** (`.allhands/harness/.cache/trace/trace.jsonl`): Append-only file, one JSON object per line. Enables `grep`, `jq`, and file-watching workflows.
71
+
72
+ Both writes use silent failure -- trace errors never break the operation being traced.
73
+
74
+ ## Payload Sanitization
75
+
76
+ To prevent log bloat from large tool inputs/outputs, payloads are trimmed before storage:
77
+
78
+ | Control | Default | Env Override |
79
+ |---------|---------|--------------|
80
+ | Max string length | 200 chars | `TRACE_MAX_STRING_LENGTH` |
81
+ | Max nesting depth | 3 levels | `TRACE_MAX_DEPTH` |
82
+ | Max array items | 5 | `TRACE_MAX_ARRAY_ITEMS` |
83
+ | Max object keys | 8 | `TRACE_MAX_OBJECT_KEYS` |
84
+
85
+ [ref:.allhands/harness/src/lib/trace-store.ts:sanitizePayload:36af65f] applies [ref:.allhands/harness/src/lib/trace-store.ts:trimStrings:36af65f] and [ref:.allhands/harness/src/lib/trace-store.ts:truncateStructure:36af65f] to enforce these limits with cycle detection via WeakSet.
86
+
87
+ ## Structured Logging Helpers
88
+
89
+ The trace store provides typed logging functions that construct appropriate event payloads:
90
+
91
+ | Function | Event Type | Use Case |
92
+ |----------|-----------|----------|
93
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logHarnessError:36af65f] | `harness.error` | Internal harness failures |
94
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logHookStart:36af65f] | `hook.start` | Hook execution begins |
95
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logHookSuccess:36af65f] | `hook.success` | Hook completes |
96
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logCommandStart:36af65f] | `command.start` | CLI command begins |
97
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logCommandSuccess:36af65f] | `command.success` | CLI command completes |
98
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logCommandError:36af65f] | `command.error` | CLI command fails |
99
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logTuiError:36af65f] | `tui.error` | TUI runtime error |
100
+ | [ref:.allhands/harness/src/lib/trace-store.ts:logTuiAction:36af65f] | `tui.action` | User action in TUI |
101
+
102
+ ## Query Interface
103
+
104
+ [ref:.allhands/harness/src/lib/trace-store.ts:queryEvents:36af65f] builds parameterized SQL queries from filter options:
105
+
106
+ - `agentId`, `agentType` -- Filter by agent identity
107
+ - `eventType` -- Single event type filter
108
+ - `toolName` -- Filter by tool
109
+ - `since` -- Time filter supporting relative strings (`1h`, `30m`, `2d`) and ISO timestamps
110
+ - `errorsOnly` -- Boolean flag that filters on `is_error = 1`
111
+ - `limit`/`offset` -- Pagination (default limit: 100)
112
+
113
+ [ref:.allhands/harness/src/lib/trace-store.ts:getStats:36af65f] provides aggregate statistics with breakdowns by event type, agent type, and tool name, all supporting the `since` time filter.
114
+
115
+ ## CLI Commands
116
+
117
+ [ref:.allhands/harness/src/commands/trace.ts:register:089fb26] exposes four subcommands:
118
+
119
+ - **`ah trace list`** -- Query events with full filter support. Human-readable output highlights errors in red, shows truncated payloads for tool events, and displays prompt text for `prompt.submit` events.
120
+ - **`ah trace errors`** -- Shortcut for `list --errors`. Prominently displays error messages, command summaries, hook names, and truncated stack traces.
121
+ - **`ah trace stats`** -- Aggregate statistics with breakdowns. Useful for understanding activity patterns and error rates across agents.
122
+ - **`ah trace tail`** -- Real-time event watching via filesystem change detection on the JSONL file. Supports `--agent` and `--type` filters. Uses `fs.watch` with position tracking to read only new lines.
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: "Unix socket daemon that eliminates ~400ms Node.js startup overhead per hook invocation by running hooks in-process, using stdout interception and process.exit() catching to maintain hook compatibility."
3
+ ---
4
+
5
+ # CLI Daemon
6
+
7
+ The CLI daemon solves a performance problem: every hook invocation spawns a new Node.js process, paying ~400ms of startup overhead. When the TUI is running dozens of hooks per minute across multiple agents, this adds up. The daemon pre-loads all hook handlers into a long-running process and serves them over a Unix socket.
8
+
9
+ ## The Problem
10
+
11
+ ```
12
+ Without daemon:
13
+ Agent tool call -> Claude Code hook -> spawn node -> parse CLI -> import modules -> run hook -> exit
14
+ ~400ms per invocation
15
+
16
+ With daemon:
17
+ Agent tool call -> Claude Code hook -> connect socket -> send JSON -> receive result
18
+ ~5ms per invocation
19
+ ```
20
+
21
+ ## Architecture
22
+
23
+ ```mermaid
24
+ flowchart LR
25
+ subgraph TUI Process
26
+ D[CLIDaemon] --> S[Unix Socket Server]
27
+ S --> H[Handler Registry]
28
+ H --> C[context hooks]
29
+ H --> V[validation hooks]
30
+ H --> O[observability hooks]
31
+ H --> E[enforcement hooks]
32
+ end
33
+
34
+ subgraph Agent Hook
35
+ CLI[ah hooks ...] --> |connect| S
36
+ S --> |JSON response| CLI
37
+ end
38
+ ```
39
+
40
+ [ref:.allhands/harness/src/lib/cli-daemon.ts:CLIDaemon:e269aee] manages the server lifecycle. It listens on a Unix socket at `.allhands/harness/.cache/cli-daemon.sock` (resolved by [ref:.allhands/harness/src/lib/cli-daemon.ts:getSocketPath:e269aee]).
41
+
42
+ ## Handler Registration
43
+
44
+ [ref:.allhands/harness/src/lib/cli-daemon.ts:registerHandler:e269aee] adds hook handlers to a global registry keyed by `"category.name"` (e.g., `"context.tldr-inject"`, `"validation.schema-check"`). Hook modules register via [ref:.allhands/harness/src/hooks/shared.ts:registerCategoryForDaemon:ca0caaf], which takes the same `HookCategory` definition used for CLI registration and adapts it for daemon mode.
45
+
46
+ This dual-registration design means hook authors define their hooks once. The same handler function works whether invoked via the CLI (Commander subcommand) or the daemon (socket message).
47
+
48
+ ## I/O Interception
49
+
50
+ The core challenge: existing hooks call `process.exit()` and write to `process.stdout`. In a daemon, these would kill the server or corrupt the socket stream.
51
+
52
+ [ref:.allhands/harness/src/lib/cli-daemon.ts:runWithInterceptedIO:e269aee] solves this by:
53
+
54
+ 1. **Replacing `process.exit()`** with a throw of [ref:.allhands/harness/src/lib/cli-daemon.ts:ExitSignal:e269aee] -- a custom error class that the runner catches. The hook thinks it exited; the daemon stays alive.
55
+ 2. **Replacing `process.stdout.write()`** with a buffer capture. Hook output is collected into a string instead of going to the terminal.
56
+ 3. **Setting `AH_VIA_DAEMON=1`** in the environment so hooks can detect daemon mode for trace logging.
57
+ 4. **Restoring all originals** in a `finally` block, ensuring the daemon's I/O is never permanently corrupted even if a hook throws.
58
+
59
+ ## Command Protocol
60
+
61
+ Communication uses newline-delimited JSON over the Unix socket:
62
+
63
+ | Command | Fields | Response |
64
+ |---------|--------|----------|
65
+ | `hook` | `category`, `name`, `input` (HookInput) | `{success, output}` or `{success, output, fallback: true}` |
66
+ | `ping` | -- | `{success, pong: true, handlers: N}` |
67
+ | `list` | -- | `{success, handlers: ["ctx.tldr-inject", ...]}` |
68
+ | `shutdown` | -- | `{success, shutting_down: true}` |
69
+
70
+ [ref:.allhands/harness/src/lib/cli-daemon.ts:processCommand:e269aee] dispatches commands. For `hook` commands, it looks up the handler, runs it with intercepted I/O, and returns the captured output. If the handler is not registered, it returns `fallback: true` -- signaling the caller to fall back to CLI execution.
71
+
72
+ [ref:.allhands/harness/src/lib/cli-daemon.ts:createConnectionHandler:e269aee] handles socket connections with buffered reads, splitting on newlines to support multiple commands per connection.
73
+
74
+ ## Stale Socket Handling
75
+
76
+ On startup, `CLIDaemon.start()` checks if the socket file already exists. If another daemon is actively listening (verified by attempting a connection), it skips starting. If the socket is stale (left behind by a crashed process), it unlinks the file and starts fresh.
77
+
78
+ On stop, the server closes and the socket file is cleaned up.
79
+
80
+ ## TLDR Daemon (Companion)
81
+
82
+ The CLI daemon coexists with the TLDR daemon -- a separate process that handles code analysis. Key TLDR lifecycle functions:
83
+
84
+ - [ref:.allhands/harness/src/lib/tldr.ts:isTldrInstalled:702ae0d] -- Checks if the `tldr` binary is available
85
+ - [ref:.allhands/harness/src/lib/tldr.ts:isTldrDaemonRunning:702ae0d] -- Checks the TLDR socket (separate from CLI daemon socket)
86
+ - [ref:.allhands/harness/src/lib/tldr.ts:ensureTldrDaemon:702ae0d] -- Starts the TLDR daemon if not running
87
+ - [ref:.allhands/harness/src/lib/tldr.ts:hasSemanticIndex:702ae0d] / [ref:.allhands/harness/src/lib/tldr.ts:buildSemanticIndex:702ae0d] -- Manages the semantic search index
88
+ - [ref:.allhands/harness/src/lib/tldr.ts:warmCallGraph:702ae0d] -- Pre-builds the call graph cache for impact analysis
89
+
90
+ The TLDR daemon communicates via its own Unix socket, queried synchronously by [ref:.allhands/harness/src/lib/tldr.ts:queryDaemonSync:702ae0d] or asynchronously by [ref:.allhands/harness/src/lib/tldr.ts:queryDaemon:702ae0d]. When the daemon is unavailable, functions like [ref:.allhands/harness/src/lib/tldr.ts:searchDaemon:702ae0d] fall back to [ref:.allhands/harness/src/lib/tldr.ts:ripgrepFallback:702ae0d].
91
+
92
+ The TUI starts both daemons at initialization and stops them on teardown.
@@ -0,0 +1,184 @@
1
+ ---
2
+ description: "Background polling daemon that monitors git branches, dispatches prompt execution, spawns hypothesis planner with exponential backoff, tracks agent windows, detects PR review feedback, and coordinates parallel agent spawning with cooldown guards."
3
+ ---
4
+
5
+ # Event Loop
6
+
7
+ The event loop is a non-blocking polling daemon that bridges external state (git, tmux, GitHub) with the TUI's reactive model. It runs on a configurable tick interval and fires callbacks when state changes, enabling the TUI to stay current without blocking user interaction.
8
+
9
+ ## Tick Architecture
10
+
11
+ Each tick runs four independent checks in parallel, followed by a sequential prompt loop check:
12
+
13
+ ```mermaid
14
+ graph TD
15
+ T[tick] --> P[checkPRReviewFeedback]
16
+ T --> G[checkGitBranch]
17
+ T --> A[checkAgentWindows]
18
+ T --> F[checkPromptFiles]
19
+ P & G & A & F --> L[checkPromptLoop]
20
+ ```
21
+
22
+ [ref:.allhands/harness/src/lib/event-loop.ts:EventLoop:940f18a] stores all state in an [ref:.allhands/harness/src/lib/event-loop.ts:EventLoopState:940f18a] object that tracks the current branch, spec, PR URL, active agents, executor prompts, tick count, and hypothesis planner backoff counters (`emergentSpawnCount`, `emergentLastPromptCount`).
23
+
24
+ ## Check: PR Review Feedback
25
+
26
+ [ref:.allhands/harness/src/lib/pr-review.ts:checkPRReviewStatus:ca5f05b] polls GitHub for PR review comments. The event loop only runs this check every N ticks (configured via `settings.prReview.checkFrequency`, default 3) since reviews take minutes to complete.
27
+
28
+ The detection pipeline:
29
+ 1. [ref:.allhands/harness/src/lib/pr-review.ts:parsePRUrl:ca5f05b] validates the PR URL format
30
+ 2. Reads `lastReviewRunTime` from `status.yaml` to filter old comments
31
+ 3. Checks for comments matching the configured `reviewDetectionString` (default: "greptile")
32
+ 4. [ref:.allhands/harness/src/lib/pr-review.ts:hasNewReview:ca5f05b] compares previous and current `PRReviewState` to detect new reviews
33
+ 5. On detection, fires `onPRReviewFeedback` callback and updates `status.yaml`
34
+
35
+ [ref:.allhands/harness/src/lib/pr-review.ts:triggerPRReview:ca5f05b] posts a comment (default: "@greptile") to trigger a new review cycle.
36
+
37
+ ## Check: Git Branch
38
+
39
+ The event loop treats the git branch as the primary context key. On each tick, it reads the current branch and compares it to stored state. When a branch change is detected:
40
+
41
+ 1. Updates `currentBranch`, `planningKey` (sanitized branch name for `.planning/` lookup)
42
+ 2. Resolves the new spec via `getSpecForBranch()`
43
+ 3. Fires `onBranchChange` callback so the TUI reloads prompts and planning artifacts
44
+
45
+ This implements the **branch-keyed model**: no separate "active spec" tracking is needed because the branch determines the spec.
46
+
47
+ ## Check: Agent Windows
48
+
49
+ Monitors tmux windows to track which agents are alive. Only considers windows that appear in the spawned agent registry (preventing pickup of unrelated tmux windows).
50
+
51
+ When agents disappear:
52
+ - Their MCP daemons are cleaned up via `shutdownDaemon()`
53
+ - They are unregistered from the spawn registry
54
+ - Active executor prompt numbers are reconciled (executor/emergent windows encode prompt numbers in their names, e.g., `executor-03`)
55
+ - The spawn cooldown timestamp is cleared when an executor or emergent window disappears, allowing new spawns immediately
56
+
57
+ The reconciliation step also runs proactively: if `activeExecutorPrompts` contains numbers with no matching running window, those entries are pruned. This handles edge cases where an agent dies before the next `checkAgentWindows` tick.
58
+
59
+ ## Check: Prompt Files
60
+
61
+ [ref:.allhands/harness/src/lib/prompts.ts:loadAllPrompts:89011a7] reads all prompt files from the current planning directory. The event loop computes a hash-based snapshot of prompt filenames, statuses, and numbers. When the hash changes, it fires `onPromptsChange` with the full prompt list and a `PromptSnapshot` containing counts by status.
62
+
63
+ When new pending prompts are detected (snapshot pending count increases), the hypothesis planner backoff resets to zero -- external prompt creation signals productive work.
64
+
65
+ This makes the harness the coordinator: it detects when agents create, modify, or complete prompts without those agents needing to know about the TUI.
66
+
67
+ ## Prompt Execution Loop
68
+
69
+ The prompt loop is the sequential check that runs after all parallel checks complete, implemented in [ref:.allhands/harness/src/lib/event-loop.ts:EventLoop:940f18a]. It implements a unified decision path:
70
+
71
+ ```mermaid
72
+ stateDiagram-v2
73
+ [*] --> CheckEnabled: loopEnabled?
74
+ CheckEnabled --> Paused: No
75
+ CheckEnabled --> CheckEmergent: Yes
76
+ CheckEmergent --> Blocked: emergent planner running
77
+ CheckEmergent --> CheckCapacity: no emergent
78
+ CheckCapacity --> AtMax: executors >= maxParallel
79
+ CheckCapacity --> CheckCooldown: has capacity
80
+ CheckCooldown --> Cooling: spawned < cooldown ago
81
+ CheckCooldown --> PickPrompt: cooldown clear
82
+ PickPrompt --> SpawnExecutor: pending prompt found
83
+ PickPrompt --> CheckBackoff: no pending + no in_progress
84
+ CheckBackoff --> BackoffWait: within backoff window
85
+ CheckBackoff --> SpawnHypothesisPlanner: backoff clear
86
+ PickPrompt --> Wait: no pending + in_progress exist
87
+ ```
88
+
89
+ 1. **Loop enabled + pending prompts** -- Pick next eligible prompt, spawn executor
90
+ 2. **Loop enabled + no pending + no in_progress** -- Spawn hypothesis planner (with backoff)
91
+ 3. **Loop enabled + no pending + in_progress exist** -- Wait for running executors
92
+ 4. **Loop disabled** -- Nothing happens
93
+
94
+ ### Parallel Execution Rules
95
+
96
+ 1. **One agent per tick** -- Only one agent spawns per event loop cycle, preventing thundering herds
97
+ 2. **Hypothesis planner singleton** -- At most one emergent planner runs at a time; the planner spawns only when all prompts are done (none pending, none in_progress)
98
+ 3. **Parallel executors** -- When parallel mode is enabled, up to `settings.spawn.maxParallelPrompts` (default 3) executors can run simultaneously
99
+ 4. **10-second base cooldown** -- [ref:.allhands/harness/src/lib/event-loop.ts:SPAWN_COOLDOWN_MS:940f18a] prevents race conditions where tmux hasn't registered the new window yet
100
+ 5. **Prompt exclusion** -- `activeExecutorPrompts` tracks which prompts have running agents, preventing duplicate assignment
101
+
102
+ Two toggles control execution: **Loop** (O) enables/disables the entire prompt loop, **Parallel** (P) toggles multi-executor mode.
103
+
104
+ ### Prompt Selection
105
+
106
+ [ref:.allhands/harness/src/lib/prompts.ts:pickNextPrompt:89011a7] selects the next prompt to execute:
107
+ - Filters to `pending` status only
108
+ - Checks dependency satisfaction via [ref:.allhands/harness/src/lib/prompts.ts:dependenciesSatisfied:89011a7] -- all dependency prompt numbers must be `done`
109
+ - Excludes prompts already being worked on (`excludePrompts` parameter)
110
+ - Returns the lowest-numbered eligible prompt (FIFO ordering)
111
+
112
+ [ref:.allhands/harness/src/lib/prompts.ts:markPromptInProgress:89011a7] atomically updates the prompt's frontmatter status to `in_progress` using file locking via [ref:.allhands/harness/src/lib/prompts.ts:withFileLock:89011a7].
113
+
114
+ ## Hypothesis Planner Backoff
115
+
116
+ When no pending or in-progress prompts remain, the event loop spawns a hypothesis planner to generate new work. To avoid wasteful respawning when the planner fails to produce prompts, exponential backoff is applied.
117
+
118
+ ### Tracking Productivity
119
+
120
+ [ref:.allhands/harness/src/lib/event-loop.ts:EventLoopState:940f18a] tracks two fields:
121
+
122
+ | Field | Purpose |
123
+ |-------|---------|
124
+ | `emergentSpawnCount` | Consecutive unproductive spawns (planner ran but did not create new prompts) |
125
+ | `emergentLastPromptCount` | Total prompt count at time of last planner spawn -- compared against current count to detect new prompt creation |
126
+
127
+ After each spawn, if `currentPromptCount <= emergentLastPromptCount`, the spawn was unproductive and `emergentSpawnCount` increments. If the planner produced new prompts, the count resets to zero.
128
+
129
+ ### Backoff Formula
130
+
131
+ ```
132
+ cooldown = SPAWN_COOLDOWN_MS * 2^min(emergentSpawnCount, 4)
133
+ ```
134
+
135
+ | Unproductive Spawns | Cooldown |
136
+ |---------------------|----------|
137
+ | 0 | 10s |
138
+ | 1 | 20s |
139
+ | 2 | 40s |
140
+ | 3 | 80s |
141
+ | 4+ | 160s (cap) |
142
+
143
+ The base cooldown is [ref:.allhands/harness/src/lib/event-loop.ts:SPAWN_COOLDOWN_MS:940f18a] (10 seconds). The exponent caps at 4, giving a maximum wait of 160 seconds.
144
+
145
+ ### Backoff Resets
146
+
147
+ The backoff counter resets to zero when:
148
+ - **Loop toggle** -- `setLoopEnabled()` resets `emergentSpawnCount` on any toggle
149
+ - **New pending prompt detection** -- `checkPromptFiles()` resets when `snapshot.pending > previousSnapshot.pending`
150
+
151
+ Backoff status is traced via the `onLoopStatus` callback, logging messages like `Emergent planner backoff: waiting 40s (2 unproductive spawns)`.
152
+
153
+ ## Event Loop Callbacks
154
+
155
+ [ref:.allhands/harness/src/lib/event-loop.ts:EventLoopCallbacks:940f18a] defines the callback interface:
156
+
157
+ | Callback | Trigger |
158
+ |----------|---------|
159
+ | `onPRReviewFeedback` | New PR review detected |
160
+ | `onBranchChange` | Git branch changed |
161
+ | `onAgentsChange` | Agent windows appeared or disappeared |
162
+ | `onSpawnExecutor` | Pending prompt picked for execution |
163
+ | `onSpawnEmergentPlanning` | Hypothesis planner spawn triggered (no arguments -- planner uses profile defaults) |
164
+ | `onLoopStatus` | Status messages for activity log |
165
+ | `onPromptsChange` | Prompt files created, modified, or completed |
166
+
167
+ ## Configuration
168
+
169
+ All timing and behavior is configurable via `.allhands/settings.json`:
170
+
171
+ | Setting | Path | Default | Purpose |
172
+ |---------|------|---------|---------|
173
+ | Tick interval | `eventLoop.tickIntervalMs` | 5000 | Milliseconds between ticks |
174
+ | PR check frequency | `prReview.checkFrequency` | 3 | Check PR every N ticks |
175
+ | Review detection | `prReview.reviewDetectionString` | "greptile" | Comment substring to detect |
176
+ | Rerun comment | `prReview.rerunComment` | "@greptile" | Comment to post for rerun |
177
+ | Max parallel | `spawn.maxParallelPrompts` | 3 | Max concurrent executors |
178
+
179
+ ## Lifecycle
180
+
181
+ - **Start**: `start()` begins the interval timer and runs an initial tick
182
+ - **Stop**: `stop()` clears the interval
183
+ - **Force tick**: `forceTick()` triggers an immediate tick, used when enabling parallel mode to spawn without waiting
184
+ - **Branch sync**: `setBranchContext()` manually overrides branch state after TUI-initiated changes, preventing the event loop from re-detecting the change and overwriting TUI state
@@ -0,0 +1,15 @@
1
+ ---
2
+ description: "Index of harness hook documentation covering context injection, validation enforcement, and lifecycle/observability hooks."
3
+ ---
4
+
5
+ # Hooks
6
+
7
+ Hooks intercept tool calls (PreToolUse, PostToolUse) and session events (Stop, Compact, SessionStart) to inject context, enforce rules, and observe agent behavior.
8
+
9
+ ## Hook Categories
10
+
11
+ | Category | Doc |
12
+ |---|---|
13
+ | Context injection (tldr, edit, search routing, transcript safeguard) | `docs/harness/hooks/context-hooks.md` |
14
+ | Validation (diagnostics, schema, formatting) | `docs/harness/hooks/validation-hooks.md` |
15
+ | Lifecycle, observability, enforcement, notifications | `docs/harness/hooks/lifecycle-and-observability-hooks.md` |
@@ -0,0 +1,96 @@
1
+ ---
2
+ description: "Pre/post tool hooks that inject TLDR-powered code analysis context, route searches through AST-grep and semantic layers, enforce token-efficient file reads, and provide impact analysis for refactoring operations."
3
+ ---
4
+
5
+ # Context Hooks
6
+
7
+ Context hooks intercept tool invocations to inject code intelligence before, during, and after agent tool use. They bridge the TLDR analysis daemon with the agent's tool pipeline, ensuring agents receive structured code understanding without consuming raw file tokens.
8
+
9
+ All hooks gracefully degrade when TLDR is not installed -- they fall back to allowing the tool unmodified.
10
+
11
+ ## Intent-Driven Context Injection
12
+
13
+ The primary entry point [ref:.allhands/harness/src/hooks/context.ts:detectIntent:f5da0a1] classifies agent prompts into analysis intents that determine which TLDR layers to query:
14
+
15
+ | Intent | Trigger Patterns | TLDR Layers |
16
+ |--------|-----------------|-------------|
17
+ | `debug` | "debug", "investigate", "trace", "why does" | Call Graph + CFG |
18
+ | `dataflow` | "where does", "come from", "data flow" | DFG |
19
+ | `slice` | "what affects", "depends on", "impact of" | PDG/slice |
20
+ | `structure` | "show structure", "list functions" | AST only |
21
+ | `arch` | "plan", "design", "refactor", "architecture" | Architecture layers |
22
+ | `default` | Everything else | Call Graph |
23
+
24
+ [ref:.allhands/harness/src/hooks/context.ts:extractReferences:f5da0a1] supplements intent detection by pulling function/symbol references from backtick-quoted identifiers and function-call syntax in prompts.
25
+
26
+ ## Hook Inventory
27
+
28
+ ### PreToolUse Hooks
29
+
30
+ **tldr-inject** -- [ref:.allhands/harness/src/hooks/context.ts:tldrContextInject:f5da0a1]
31
+ Intercepts Task tool invocations. Routes to the appropriate TLDR daemon endpoint (context, CFG, DFG, arch) based on detected intent. Injects the analysis result as additional context so the agent sees code structure alongside its task.
32
+
33
+ **edit-inject** -- [ref:.allhands/harness/src/hooks/context.ts:editContextInject:f5da0a1]
34
+ Intercepts Edit tool invocations. Before an edit executes, fetches the file's code structure via TLDR extract, providing the agent with function signatures, class definitions, and import maps for the target file.
35
+
36
+ **arch-inject** -- [ref:.allhands/harness/src/hooks/context.ts:archContextInject:f5da0a1]
37
+ Intercepts architecture-related tool calls. Queries [ref:.allhands/harness/src/lib/tldr.ts:archDaemon:702ae0d] to inject architectural layer information (module boundaries, dependency direction, layer violations) into the agent's context.
38
+
39
+ **signature-helper** -- [ref:.allhands/harness/src/hooks/context.ts:signatureHelper:f5da0a1]
40
+ Intercepts code editing operations. Extracts function calls from the code being edited via [ref:.allhands/harness/src/hooks/context.ts:extractFunctionCalls:f5da0a1], then searches for their signatures using [ref:.allhands/harness/src/hooks/context.ts:getSearchPattern:f5da0a1]. Prevents agents from guessing function signatures by providing the actual definitions.
41
+
42
+ **import-validator** -- [ref:.allhands/harness/src/hooks/context.ts:importValidator:f5da0a1]
43
+ Validates import statements in edited files. Cross-references imports against the TLDR daemon's knowledge of the project's module graph, catching broken imports before they reach runtime.
44
+
45
+ **read-enforcer** -- [ref:.allhands/harness/src/hooks/context.ts:tldrReadEnforcer:f5da0a1]
46
+ Intercepts Read tool calls for large code files. Instead of allowing the agent to consume an entire file's tokens, returns a TLDR-generated summary (imports, classes, functions with signatures and line numbers) and denies the raw read. Bypasses for: files under 100 lines, explicit offset/limit parameters, non-code files, and recent search context indicating a specific location.
47
+
48
+ **search-router** -- [ref:.allhands/harness/src/hooks/context.ts:smartSearchRouter:f5da0a1]
49
+ Intercepts Grep tool calls and routes them through a three-tier search strategy:
50
+ 1. AST-grep for structural code patterns (function defs, class declarations)
51
+ 2. TLDR semantic search for natural language / conceptual queries
52
+ 3. Literal ripgrep fallback if both fail
53
+
54
+ Uses [ref:.allhands/harness/src/hooks/context.ts:classifySearchPattern:f5da0a1] to determine query type and [ref:.allhands/harness/src/hooks/context.ts:suggestLayers:f5da0a1] to select the optimal search layer. Saves search context via [ref:.allhands/harness/src/hooks/shared.ts:saveSearchContext:ca0caaf] for downstream hooks (read-enforcer uses this to allow targeted reads after a search).
55
+
56
+ ### PostToolUse Hooks
57
+
58
+ **post-edit-diagnostics** -- [ref:.allhands/harness/src/hooks/context.ts:postEditDiagnostics:f5da0a1]
59
+ Runs after Edit tool completes. Queries [ref:.allhands/harness/src/lib/tldr.ts:diagnosticsDaemon:702ae0d] against the edited file, surfacing type errors and lint issues immediately so agents can self-correct without a separate diagnostic step.
60
+
61
+ **edit-notify** -- [ref:.allhands/harness/src/hooks/context.ts:editNotify:f5da0a1]
62
+ Async notification after file edits. Calls [ref:.allhands/harness/src/lib/tldr.ts:notifyFileChanged:702ae0d] to update the TLDR daemon's dirty file tracking, keeping the analysis cache consistent with the current working tree.
63
+
64
+ ### UserPromptSubmit Hooks
65
+
66
+ **impact-refactor** -- [ref:.allhands/harness/src/hooks/context.ts:impactRefactor:f5da0a1]
67
+ Triggers when a user prompt mentions refactoring keywords (refactor, rename, move, delete, extract, inline). Extracts function names via [ref:.allhands/harness/src/hooks/context.ts:extractImpactFunctionNames:f5da0a1], queries [ref:.allhands/harness/src/lib/tldr.ts:impactDaemon:702ae0d] for the reverse call graph, and injects a caller listing so agents understand the blast radius before modifying code.
68
+
69
+ **transcript-safeguard** -- [ref:.allhands/harness/src/hooks/context.ts:transcriptSafeguardPre:f5da0a1]
70
+ PreToolUse guard on TaskOutput. Blocks all TaskOutput calls unconditionally -- background tasks broadcast a completion notification with their result when they finish, making TaskOutput redundant. Blocking prevents dumping massive raw transcripts into agent context.
71
+
72
+ ## Search Context Pipeline
73
+
74
+ ```mermaid
75
+ sequenceDiagram
76
+ participant Agent
77
+ participant SearchRouter
78
+ participant ReadEnforcer
79
+ participant Cache
80
+
81
+ Agent->>SearchRouter: Grep(pattern="handleAction")
82
+ SearchRouter->>SearchRouter: classifySearchPattern() -> structural/function
83
+ SearchRouter->>Cache: saveSearchContext({target, layers})
84
+ SearchRouter-->>Agent: AST-grep results with file:line
85
+
86
+ Agent->>ReadEnforcer: Read(file_path, no offset)
87
+ ReadEnforcer->>Cache: loadSearchContext()
88
+ ReadEnforcer->>ReadEnforcer: Has definitionLocation? Allow full read
89
+ ReadEnforcer-->>Agent: Full file content (search-targeted)
90
+ ```
91
+
92
+ The search context cache connects the search-router and read-enforcer hooks. When a search finds a specific definition location, the subsequent read is allowed in full rather than being replaced with a summary. This prevents the frustrating pattern of search finding a result but the read being blocked.
93
+
94
+ ## Graceful Degradation
95
+
96
+ Every hook in this module checks [ref:.allhands/harness/src/lib/tldr.ts:isTldrInstalled:702ae0d] and [ref:.allhands/harness/src/lib/tldr.ts:isTldrDaemonRunning:702ae0d] before attempting analysis. If TLDR is unavailable, hooks call [ref:.allhands/harness/src/hooks/shared.ts:allowTool:ca0caaf] and exit silently. This means the harness functions without TLDR -- agents just lose the enriched context layer.
@@ -0,0 +1,135 @@
1
+ ---
2
+ description: "Agent lifecycle management (stop, compact, session start), observability tracing across all hook events, enforcement rules for tool access, notification delivery, hook discovery/registration, and shared utilities underpinning the hook system."
3
+ ---
4
+
5
+ # Lifecycle, Observability, and Infrastructure Hooks
6
+
7
+ This document covers the hooks that manage agent lifecycles, record observability data, enforce access policies, handle notifications, and provide the shared infrastructure that all hooks depend on.
8
+
9
+ ## Agent Lifecycle
10
+
11
+ ### Stop Handler
12
+
13
+ [ref:.allhands/harness/src/hooks/lifecycle.ts:handleAgentStop:166f290] runs when an agent signals completion. It:
14
+ 1. Checks if the agent's tmux window exists via the tmux library
15
+ 2. Sends a notification that the agent has stopped
16
+ 3. Retrieves the prompt associated with the agent via [ref:.allhands/harness/src/lib/prompts.ts:getPromptByNumber:89011a7]
17
+ 4. Kills the tmux window to free resources
18
+
19
+ The stop handler uses [ref:.allhands/harness/src/hooks/shared.ts:outputStopHook:ca0caaf] with `decision: 'approve'` to confirm the agent should terminate.
20
+
21
+ ### Compaction Handler
22
+
23
+ [ref:.allhands/harness/src/hooks/lifecycle.ts:handleAgentCompact:166f290] intercepts the PreCompact event -- triggered when an agent's context window fills up. Instead of losing context, it:
24
+ 1. Delegates to [ref:.allhands/harness/src/lib/compaction.ts:runCompaction:031e2fc] which analyzes the conversation state
25
+ 2. The compaction system uses an oracle to analyze what the agent accomplished and recommend next actions
26
+ 3. Generates a progress update via [ref:.allhands/harness/src/lib/compaction.ts:formatProgressUpdate:031e2fc]
27
+ 4. Appends the progress to the prompt file via [ref:.allhands/harness/src/lib/prompts.ts:appendToProgressSection:89011a7]
28
+ 5. Executes the recommendation (commit, continue, or stop) via [ref:.allhands/harness/src/lib/compaction.ts:executeRecommendation:031e2fc]
29
+ 6. Outputs a system message via [ref:.allhands/harness/src/hooks/shared.ts:outputPreCompact:ca0caaf] that survives the compaction
30
+
31
+ The compaction pipeline captures git diff state through [ref:.allhands/harness/src/lib/compaction.ts:getGitDiffSummary:031e2fc] and [ref:.allhands/harness/src/lib/compaction.ts:getGitDiffFull:031e2fc] to give the oracle full visibility into what changed.
32
+
33
+ ### Session Start
34
+
35
+ [ref:.allhands/harness/src/hooks/session.ts:tldrWarm:98e8198] runs on SessionStart. It warms the TLDR daemon cache by calling [ref:.allhands/harness/src/lib/tldr.ts:warmIndex:702ae0d]. The hook is entirely non-blocking -- if TLDR is not installed or the daemon is already running, it exits silently. Errors are swallowed to never block session initialization.
36
+
37
+ ## Observability
38
+
39
+ [ref:.allhands/harness/src/hooks/observability.ts::239a80d] provides structured logging across every hook event type. Each handler logs to the trace store via [ref:.allhands/harness/src/lib/trace-store.ts:logEvent:36af65f].
40
+
41
+ ### Event Coverage
42
+
43
+ | Event | Handler | What Gets Logged |
44
+ |-------|---------|-----------------|
45
+ | SessionStart | [ref:.allhands/harness/src/hooks/observability.ts:handleSessionStart:239a80d] | Session ID, timestamp |
46
+ | PromptSubmit | [ref:.allhands/harness/src/hooks/observability.ts:handlePromptSubmit:239a80d] | Prompt content summary |
47
+ | PreToolUse | [ref:.allhands/harness/src/hooks/observability.ts:handleToolPre:239a80d] | Tool name, input summary |
48
+ | PostToolUse | [ref:.allhands/harness/src/hooks/observability.ts:handleToolPost:239a80d] | Tool result, error detection |
49
+ | ToolFailure | [ref:.allhands/harness/src/hooks/observability.ts:handleToolFailure:239a80d] | Error details, stderr |
50
+ | ToolDenied | [ref:.allhands/harness/src/hooks/observability.ts:handleToolDenied:239a80d] | Denial reason |
51
+ | TaskSpawn | [ref:.allhands/harness/src/hooks/observability.ts:handleTaskSpawn:239a80d] | Sub-agent metadata |
52
+ | AgentStop | [ref:.allhands/harness/src/hooks/observability.ts:handleAgentStop:239a80d] | Completion status |
53
+ | AgentCompact | [ref:.allhands/harness/src/hooks/observability.ts:handleAgentCompact:239a80d] | Compaction trigger reason |
54
+
55
+ [ref:.allhands/harness/src/hooks/observability.ts:shouldLogTool:239a80d] filters noise by skipping high-frequency, low-value tool calls. [ref:.allhands/harness/src/hooks/observability.ts:summarizeBashCommand:239a80d] truncates long shell commands to keep log entries readable. [ref:.allhands/harness/src/hooks/observability.ts:isBashError:239a80d] parses Bash tool results to detect non-zero exit codes and stderr output.
56
+
57
+ [ref:.allhands/harness/src/hooks/observability.ts:handleToolPreWithTaskRouting:239a80d] extends the base PreToolUse handler with task-aware routing logic, tracking sub-agent spawns alongside regular tool usage.
58
+
59
+ ## Enforcement Rules
60
+
61
+ [ref:.allhands/harness/src/hooks/enforcement.ts::e905788] contains PreToolUse hooks that enforce access policies:
62
+
63
+ - [ref:.allhands/harness/src/hooks/enforcement.ts:enforceGitHubUrl:e905788] -- Intercepts WebFetch/WebSearch for GitHub URLs and redirects agents to use `gh` CLI instead, which has authenticated access and richer output
64
+ - [ref:.allhands/harness/src/hooks/enforcement.ts:enforceResearchFetch:e905788] -- Controls web fetch operations during research phases, ensuring agents use approved research channels
65
+ - [ref:.allhands/harness/src/hooks/enforcement.ts:enforceResearchSearch:e905788] -- Controls web search operations, applying similar research-phase policies
66
+
67
+ Enforcement hooks use [ref:.allhands/harness/src/hooks/shared.ts:denyTool:ca0caaf] with specific guidance messages, redirecting agents to better alternatives rather than simply blocking.
68
+
69
+ ## Notifications
70
+
71
+ [ref:.allhands/harness/src/hooks/notification.ts:handleStopNotification:5b5578d] and [ref:.allhands/harness/src/hooks/notification.ts:handleCompactNotification:5b5578d] send system notifications when agents stop or compact. They use [ref:.allhands/harness/src/lib/notification.ts:sendGateNotification:8f14a76] to deliver alerts, keeping operators informed of agent lifecycle events without requiring TUI visibility.
72
+
73
+ ## Transcript Parsing
74
+
75
+ [ref:.allhands/harness/src/hooks/transcript-parser.ts:parseTranscript:338596c] is a utility that processes Claude Code JSONL transcript files into structured summaries (`TranscriptSummary`). It streams the file line-by-line via readline for memory efficiency.
76
+
77
+ [ref:.allhands/harness/src/hooks/transcript-parser.ts:summarizeToolInput:338596c] condenses verbose tool inputs into one-line summaries. [ref:.allhands/harness/src/hooks/transcript-parser.ts:buildCompactionMessage:338596c] transforms a parsed transcript summary into a system message suitable for compaction injection.
78
+
79
+ ## Hook Registration Infrastructure
80
+
81
+ ### Auto-Discovery
82
+
83
+ [ref:.allhands/harness/src/hooks/index.ts:discoverAndRegisterHooks:8fe9903] scans the hooks directory at runtime, dynamically importing every `.ts` file (except `index.ts`, `shared.ts`, and `transcript-parser.ts`). Each module must export a `register(parent: Command)` function that attaches its subcommands to the CLI.
84
+
85
+ This pattern means adding a new hook category requires only creating the file -- no manual registration.
86
+
87
+ ### Category-Based Registration
88
+
89
+ [ref:.allhands/harness/src/hooks/shared.ts:registerCategory:ca0caaf] provides declarative hook registration. A `HookCategory` object describes all hooks in a category with their names, event types, matchers, and handler functions. The function generates Commander subcommands for CLI execution.
90
+
91
+ [ref:.allhands/harness/src/hooks/shared.ts:registerCategoryForDaemon:ca0caaf] does the same registration but targets the CLI daemon's in-process handler registry instead of Commander, enabling the same hook definitions to work in both CLI and daemon modes.
92
+
93
+ ### Shared I/O Protocol
94
+
95
+ All hooks communicate through a JSON stdin/stdout protocol defined in [ref:.allhands/harness/src/hooks/shared.ts::ca0caaf]:
96
+
97
+ ```mermaid
98
+ stateDiagram-v2
99
+ [*] --> ReadInput: stdin JSON
100
+ ReadInput --> ProcessHook: HookInput parsed
101
+ ProcessHook --> AllowTool: No action needed
102
+ ProcessHook --> DenyTool: Block with reason
103
+ ProcessHook --> InjectContext: Add context
104
+ ProcessHook --> OutputContext: Post-tool info
105
+ ProcessHook --> BlockTool: Post-tool block
106
+ ProcessHook --> OutputStopHook: Lifecycle decision
107
+ ProcessHook --> OutputPreCompact: Compaction message
108
+ AllowTool --> [*]: exit(0), no output
109
+ DenyTool --> [*]: JSON + exit(0)
110
+ InjectContext --> [*]: JSON + exit(0)
111
+ OutputContext --> [*]: JSON + exit(0)
112
+ BlockTool --> [*]: JSON + exit(0)
113
+ OutputStopHook --> [*]: JSON + exit(0)
114
+ OutputPreCompact --> [*]: JSON + exit(0)
115
+ ```
116
+
117
+ Key I/O functions:
118
+ - [ref:.allhands/harness/src/hooks/shared.ts:readHookInput:ca0caaf] -- Reads and parses stdin JSON, normalizing `tool_response` to `tool_result`
119
+ - [ref:.allhands/harness/src/hooks/shared.ts:allowTool:ca0caaf] -- Silent exit (no output = allow)
120
+ - [ref:.allhands/harness/src/hooks/shared.ts:denyTool:ca0caaf] -- Outputs deny decision with reason
121
+ - [ref:.allhands/harness/src/hooks/shared.ts:blockTool:ca0caaf] -- Outputs block decision with message
122
+ - [ref:.allhands/harness/src/hooks/shared.ts:injectContext:ca0caaf] -- Modifies tool input to add context
123
+ - [ref:.allhands/harness/src/hooks/shared.ts:preToolContext:ca0caaf] -- Adds pre-tool context
124
+ - [ref:.allhands/harness/src/hooks/shared.ts:outputContext:ca0caaf] -- Adds post-tool context
125
+ - [ref:.allhands/harness/src/hooks/shared.ts:outputStopHook:ca0caaf] -- Approve or block agent stop
126
+ - [ref:.allhands/harness/src/hooks/shared.ts:outputPreCompact:ca0caaf] -- Inject compaction system message
127
+
128
+ ### Utility Functions
129
+
130
+ - [ref:.allhands/harness/src/hooks/shared.ts:getProjectDir:ca0caaf] -- Resolves the project root directory
131
+ - [ref:.allhands/harness/src/hooks/shared.ts:loadProjectSettings:ca0caaf] -- Reads `.allhands/settings.json` for project-level configuration
132
+ - [ref:.allhands/harness/src/hooks/shared.ts:getBaseBranch:ca0caaf] -- Determines the base branch for git operations
133
+ - [ref:.allhands/harness/src/hooks/shared.ts:detectLanguage:ca0caaf] -- Infers programming language from file extension, glob pattern, or type hints
134
+ - [ref:.allhands/harness/src/hooks/shared.ts:getCacheDir:ca0caaf] / [ref:.allhands/harness/src/hooks/shared.ts:getCacheSubdir:ca0caaf] -- Manage per-project cache directories
135
+ - [ref:.allhands/harness/src/hooks/shared.ts:saveSearchContext:ca0caaf] / [ref:.allhands/harness/src/hooks/shared.ts:loadSearchContext:ca0caaf] -- Persist search state between hooks within a session