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.
- package/.allhands/README.md +75 -0
- package/.allhands/agents/compounder.yaml +15 -0
- package/.allhands/agents/coordinator.yaml +17 -0
- package/.allhands/agents/documentor.yaml +15 -0
- package/.allhands/agents/e2e-test-planner.yaml +17 -0
- package/.allhands/agents/emergent.yaml +22 -0
- package/.allhands/agents/executor.yaml +14 -0
- package/.allhands/agents/ideation.yaml +11 -0
- package/.allhands/agents/initiative-steering.yaml +19 -0
- package/.allhands/agents/judge.yaml +13 -0
- package/.allhands/agents/planner.yaml +19 -0
- package/.allhands/agents/pr-reviewer.yaml +15 -0
- package/.allhands/docs.json +5 -0
- package/.allhands/docs.local.json +26 -0
- package/.allhands/flows/COMPOUNDING.md +203 -0
- package/.allhands/flows/COORDINATION.md +89 -0
- package/.allhands/flows/CORE.md +87 -0
- package/.allhands/flows/DOCUMENTATION.md +218 -0
- package/.allhands/flows/E2E_TEST_PLAN_BUILDING.md +140 -0
- package/.allhands/flows/EMERGENT_PLANNING.md +57 -0
- package/.allhands/flows/IDEATION_SCOPING.md +154 -0
- package/.allhands/flows/INITIATIVE_STEERING.md +110 -0
- package/.allhands/flows/JUDGE_REVIEWING.md +79 -0
- package/.allhands/flows/PROMPT_TASK_EXECUTION.md +68 -0
- package/.allhands/flows/PR_REVIEWING.md +43 -0
- package/.allhands/flows/SPEC_PLANNING.md +216 -0
- package/.allhands/flows/harness/WRITING_HARNESS_FLOWS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_KNOWLEDGE.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_ORCHESTRATION.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_SKILLS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_TOOLS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_VALIDATION_TOOLING.md +27 -0
- package/.allhands/flows/shared/CODEBASE_UNDERSTANDING.md +72 -0
- package/.allhands/flows/shared/CREATE_HARNESS_SPEC.md +48 -0
- package/.allhands/flows/shared/CREATE_SPEC.md +41 -0
- package/.allhands/flows/shared/CREATE_VALIDATION_TOOLING_SPEC.md +70 -0
- package/.allhands/flows/shared/DOCUMENTATION_DISCOVERY.md +123 -0
- package/.allhands/flows/shared/DOCUMENTATION_WRITER.md +101 -0
- package/.allhands/flows/shared/EMERGENT_REFINEMENT_ANALYSIS.md +76 -0
- package/.allhands/flows/shared/EXTERNAL_TECH_GUIDANCE.md +97 -0
- package/.allhands/flows/shared/IDEATION_CODEBASE_GROUNDING.md +49 -0
- package/.allhands/flows/shared/PLAN_DEEPENING.md +152 -0
- package/.allhands/flows/shared/PROMPT_TASKS_CURATION.md +113 -0
- package/.allhands/flows/shared/PROMPT_VALIDATION_REVIEW.MD +99 -0
- package/.allhands/flows/shared/QUICK_PREMORTEM.md +70 -0
- package/.allhands/flows/shared/RESEARCH_GUIDANCE.md +38 -0
- package/.allhands/flows/shared/REVIEW_OPTIONS_BREAKDOWN.md +68 -0
- package/.allhands/flows/shared/SKILL_EXTRACTION.md +84 -0
- package/.allhands/flows/shared/SPEC_FLOW_ANALYSIS.md +119 -0
- package/.allhands/flows/shared/TDD_WORKFLOW.md +109 -0
- package/.allhands/flows/shared/UTILIZE_VALIDATION_TOOLING.md +84 -0
- package/.allhands/flows/shared/WRITING_HARNESS_FLOWS.md +11 -0
- package/.allhands/flows/shared/WRITING_HARNESS_MCP_TOOLS.md +84 -0
- package/.allhands/flows/shared/jury/ARCHITECTURE_REVIEW.md +91 -0
- package/.allhands/flows/shared/jury/BEST_PRACTICES_REVIEW.md +80 -0
- package/.allhands/flows/shared/jury/CLAIM_VERIFICATION_REVIEW.md +101 -0
- package/.allhands/flows/shared/jury/EXPECTATIONS_FIT_REVIEW.md +78 -0
- package/.allhands/flows/shared/jury/MAINTAINABILITY_REVIEW.md +110 -0
- package/.allhands/flows/shared/jury/PROMPTS_EXPECTATIONS_FIT.md +74 -0
- package/.allhands/flows/shared/jury/PROMPTS_FLOW_ANALYSIS.md +92 -0
- package/.allhands/flows/shared/jury/PROMPTS_YAGNI.md +78 -0
- package/.allhands/flows/shared/jury/PROMPT_PREMORTEM.md +125 -0
- package/.allhands/flows/shared/jury/SECURITY_REVIEW.md +86 -0
- package/.allhands/flows/shared/jury/YAGNI_REVIEW.md +82 -0
- package/.allhands/flows/wip/DEBUG_INVESTIGATION.md +162 -0
- package/.allhands/flows/wip/MEMORY_RECALL.md +62 -0
- package/.allhands/harness/ah +131 -0
- package/.allhands/harness/package-lock.json +5292 -0
- package/.allhands/harness/package.json +52 -0
- package/.allhands/harness/src/__tests__/e2e/commands.test.ts +307 -0
- package/.allhands/harness/src/__tests__/e2e/event-loop.test.ts +539 -0
- package/.allhands/harness/src/__tests__/e2e/hooks.test.ts +427 -0
- package/.allhands/harness/src/__tests__/e2e/new-initiative-routing.test.ts +137 -0
- package/.allhands/harness/src/__tests__/e2e/run-e2e.ts +109 -0
- package/.allhands/harness/src/__tests__/e2e/specs-type.test.ts +210 -0
- package/.allhands/harness/src/__tests__/e2e/validation-hooks.test.ts +669 -0
- package/.allhands/harness/src/__tests__/e2e/validation-path-consistency.test.ts +354 -0
- package/.allhands/harness/src/__tests__/e2e/validation.test.ts +528 -0
- package/.allhands/harness/src/__tests__/harness/assertions.ts +318 -0
- package/.allhands/harness/src/__tests__/harness/cli-runner.ts +359 -0
- package/.allhands/harness/src/__tests__/harness/fixture.ts +384 -0
- package/.allhands/harness/src/__tests__/harness/hook-runner.ts +411 -0
- package/.allhands/harness/src/__tests__/harness/index.ts +122 -0
- package/.allhands/harness/src/cli.ts +36 -0
- package/.allhands/harness/src/commands/complexity.ts +177 -0
- package/.allhands/harness/src/commands/context7.ts +202 -0
- package/.allhands/harness/src/commands/docs.ts +557 -0
- package/.allhands/harness/src/commands/hooks.ts +24 -0
- package/.allhands/harness/src/commands/index.ts +51 -0
- package/.allhands/harness/src/commands/knowledge.ts +382 -0
- package/.allhands/harness/src/commands/memories.ts +302 -0
- package/.allhands/harness/src/commands/notify.ts +61 -0
- package/.allhands/harness/src/commands/oracle.ts +158 -0
- package/.allhands/harness/src/commands/perplexity.ts +220 -0
- package/.allhands/harness/src/commands/planning.ts +245 -0
- package/.allhands/harness/src/commands/schema.ts +73 -0
- package/.allhands/harness/src/commands/skills.ts +128 -0
- package/.allhands/harness/src/commands/solutions.ts +353 -0
- package/.allhands/harness/src/commands/spawn.ts +158 -0
- package/.allhands/harness/src/commands/specs.ts +532 -0
- package/.allhands/harness/src/commands/tavily.ts +226 -0
- package/.allhands/harness/src/commands/tools.ts +579 -0
- package/.allhands/harness/src/commands/trace.ts +327 -0
- package/.allhands/harness/src/commands/tui.ts +960 -0
- package/.allhands/harness/src/commands/validate.ts +143 -0
- package/.allhands/harness/src/commands/validation-tools.ts +108 -0
- package/.allhands/harness/src/hooks/context.ts +1442 -0
- package/.allhands/harness/src/hooks/enforcement.ts +170 -0
- package/.allhands/harness/src/hooks/index.ts +54 -0
- package/.allhands/harness/src/hooks/lifecycle.ts +229 -0
- package/.allhands/harness/src/hooks/notification.ts +104 -0
- package/.allhands/harness/src/hooks/observability.ts +551 -0
- package/.allhands/harness/src/hooks/session.ts +88 -0
- package/.allhands/harness/src/hooks/shared.ts +815 -0
- package/.allhands/harness/src/hooks/transcript-parser.ts +208 -0
- package/.allhands/harness/src/hooks/validation.ts +617 -0
- package/.allhands/harness/src/lib/__tests__/ctags.test.ts +244 -0
- package/.allhands/harness/src/lib/__tests__/docs-validation.test.ts +344 -0
- package/.allhands/harness/src/lib/__tests__/mcp-runtime.test.ts +190 -0
- package/.allhands/harness/src/lib/__tests__/schema.test.ts +861 -0
- package/.allhands/harness/src/lib/base-command.ts +198 -0
- package/.allhands/harness/src/lib/cli-daemon.ts +343 -0
- package/.allhands/harness/src/lib/compaction.ts +313 -0
- package/.allhands/harness/src/lib/ctags.ts +497 -0
- package/.allhands/harness/src/lib/docs-validation.ts +907 -0
- package/.allhands/harness/src/lib/event-loop.ts +662 -0
- package/.allhands/harness/src/lib/flows.ts +155 -0
- package/.allhands/harness/src/lib/git.ts +276 -0
- package/.allhands/harness/src/lib/knowledge-worker.ts +72 -0
- package/.allhands/harness/src/lib/knowledge.ts +810 -0
- package/.allhands/harness/src/lib/llm.ts +255 -0
- package/.allhands/harness/src/lib/mcp-client.ts +432 -0
- package/.allhands/harness/src/lib/mcp-daemon.ts +486 -0
- package/.allhands/harness/src/lib/mcp-runtime.ts +418 -0
- package/.allhands/harness/src/lib/notification.ts +115 -0
- package/.allhands/harness/src/lib/opencode/index.ts +70 -0
- package/.allhands/harness/src/lib/opencode/profiles.ts +300 -0
- package/.allhands/harness/src/lib/opencode/prompts/codesearch.md +98 -0
- package/.allhands/harness/src/lib/opencode/prompts/knowledge-aggregator.md +67 -0
- package/.allhands/harness/src/lib/opencode/runner.ts +281 -0
- package/.allhands/harness/src/lib/oracle.ts +926 -0
- package/.allhands/harness/src/lib/planning-utils.ts +150 -0
- package/.allhands/harness/src/lib/planning.ts +605 -0
- package/.allhands/harness/src/lib/pr-review.ts +225 -0
- package/.allhands/harness/src/lib/prompts.ts +522 -0
- package/.allhands/harness/src/lib/schema.ts +418 -0
- package/.allhands/harness/src/lib/schemas/agent-profile.ts +141 -0
- package/.allhands/harness/src/lib/schemas/template-vars.ts +138 -0
- package/.allhands/harness/src/lib/session.ts +164 -0
- package/.allhands/harness/src/lib/specs.ts +348 -0
- package/.allhands/harness/src/lib/tldr.ts +829 -0
- package/.allhands/harness/src/lib/tmux.ts +1051 -0
- package/.allhands/harness/src/lib/trace-store.ts +714 -0
- package/.allhands/harness/src/mcp/__tests__/index.test.ts +46 -0
- package/.allhands/harness/src/mcp/_template.ts +47 -0
- package/.allhands/harness/src/mcp/filesystem.ts +33 -0
- package/.allhands/harness/src/mcp/index.ts +69 -0
- package/.allhands/harness/src/mcp/playwright.ts +34 -0
- package/.allhands/harness/src/mcp/xcodebuild.ts +29 -0
- package/.allhands/harness/src/schemas/docs.schema.json +44 -0
- package/.allhands/harness/src/schemas/settings.schema.json +214 -0
- package/.allhands/harness/src/tui/actions.ts +227 -0
- package/.allhands/harness/src/tui/file-viewer-modal.ts +270 -0
- package/.allhands/harness/src/tui/index.ts +1574 -0
- package/.allhands/harness/src/tui/modal.ts +232 -0
- package/.allhands/harness/src/tui/prompts-pane.ts +186 -0
- package/.allhands/harness/src/tui/status-pane.ts +434 -0
- package/.allhands/harness/tsconfig.json +22 -0
- package/.allhands/harness/vitest.config.ts +13 -0
- package/.allhands/pillars.md +33 -0
- package/.allhands/principles.md +88 -0
- package/.allhands/schemas/alignment.yaml +51 -0
- package/.allhands/schemas/documentation.yaml +10 -0
- package/.allhands/schemas/prompt.yaml +92 -0
- package/.allhands/schemas/skill.yaml +34 -0
- package/.allhands/schemas/solution.yaml +131 -0
- package/.allhands/schemas/spec.yaml +67 -0
- package/.allhands/schemas/validation-suite.yaml +49 -0
- package/.allhands/schemas/workflow.yaml +51 -0
- package/.allhands/settings.json +57 -0
- package/.allhands/skills/claude-code-patterns/SKILL.md +60 -0
- package/.allhands/skills/claude-code-patterns/docs/context-hygiene.md +19 -0
- package/.allhands/skills/harness-maintenance/SKILL.md +449 -0
- package/.allhands/skills/harness-maintenance/references/core-architecture.md +187 -0
- package/.allhands/skills/harness-maintenance/references/harness-skills.md +87 -0
- package/.allhands/skills/harness-maintenance/references/knowledge-compounding.md +78 -0
- package/.allhands/skills/harness-maintenance/references/tools-commands-mcp-hooks.md +115 -0
- package/.allhands/skills/harness-maintenance/references/validation-tooling.md +77 -0
- package/.allhands/skills/harness-maintenance/references/writing-flows.md +84 -0
- package/.allhands/validation/browser-automation.md +109 -0
- package/.allhands/validation/xcode-automation.md +195 -0
- package/.allhands/workflows/documentation.md +86 -0
- package/.allhands/workflows/investigation.md +81 -0
- package/.allhands/workflows/milestone.md +91 -0
- package/.allhands/workflows/optimization.md +85 -0
- package/.allhands/workflows/refactor.md +99 -0
- package/.allhands/workflows/triage.md +81 -0
- package/.claude/README.md +1 -0
- package/.claude/agents/explorer.md +10 -0
- package/.claude/agents/researcher.md +11 -0
- package/.claude/agents/task-runner.md +8 -0
- package/.claude/settings.json +231 -0
- package/.env.ai.example +7 -0
- package/.github/workflows/npm-publish.yml +69 -0
- package/.internal.json +45 -0
- package/.tldr/config.json +11 -0
- package/.tldrignore +90 -0
- package/CLAUDE.md +6 -0
- package/README.md +98 -0
- package/bin/sync-cli.js +7552 -0
- package/concerns.md +7 -0
- package/docs/README.md +41 -0
- package/docs/agents/README.md +24 -0
- package/docs/agents/agent-configuration-system.md +86 -0
- package/docs/agents/execution-agents.md +50 -0
- package/docs/agents/knowledge-agents.md +61 -0
- package/docs/agents/orchestration-agent.md +57 -0
- package/docs/agents/planning-agents.md +84 -0
- package/docs/agents/quality-review-agents.md +67 -0
- package/docs/agents/workflow-agent-orchestration.md +69 -0
- package/docs/flows/README.md +44 -0
- package/docs/flows/compounding.md +126 -0
- package/docs/flows/coordination.md +72 -0
- package/docs/flows/core-harness-integration.md +63 -0
- package/docs/flows/documentation-orchestration.md +98 -0
- package/docs/flows/e2e-test-plan-building.md +83 -0
- package/docs/flows/emergent-refinement.md +104 -0
- package/docs/flows/flow-authoring-and-mcp-tools.md +89 -0
- package/docs/flows/judge-reviewing.md +112 -0
- package/docs/flows/plan-deepening-and-research.md +107 -0
- package/docs/flows/plan-review-jury.md +114 -0
- package/docs/flows/pr-reviewing.md +54 -0
- package/docs/flows/prompt-task-execution.md +119 -0
- package/docs/flows/spec-planning.md +162 -0
- package/docs/flows/type-specific-scoping-flows.md +49 -0
- package/docs/flows/validation-and-skills-integration.md +145 -0
- package/docs/flows/wip/wip-flows.md +102 -0
- package/docs/harness/README.md +23 -0
- package/docs/harness/agent-profiles.md +84 -0
- package/docs/harness/cli/README.md +24 -0
- package/docs/harness/cli/cli-entry-and-command-discovery.md +91 -0
- package/docs/harness/cli/docs-command.md +87 -0
- package/docs/harness/cli/knowledge-command.md +91 -0
- package/docs/harness/cli/minor-cli-commands.md +65 -0
- package/docs/harness/cli/oracle-command.md +113 -0
- package/docs/harness/cli/planning-command.md +95 -0
- package/docs/harness/cli/schema-and-validation-commands.md +154 -0
- package/docs/harness/cli/search-commands.md +97 -0
- package/docs/harness/cli/spawn-command.md +136 -0
- package/docs/harness/cli/specs-command.md +102 -0
- package/docs/harness/cli/tools-command.md +122 -0
- package/docs/harness/cli/trace-command.md +122 -0
- package/docs/harness/cli-daemon.md +92 -0
- package/docs/harness/event-loop.md +184 -0
- package/docs/harness/hooks/README.md +15 -0
- package/docs/harness/hooks/context-hooks.md +96 -0
- package/docs/harness/hooks/lifecycle-and-observability-hooks.md +135 -0
- package/docs/harness/hooks/validation-hooks.md +97 -0
- package/docs/harness/test-harness.md +149 -0
- package/docs/harness/tui.md +176 -0
- package/docs/memories.md +20 -0
- package/docs/solutions/agentic-issues/premature-agent-deletion-tui-action-dependency-20260130.md +49 -0
- package/docs/solutions/agentic-issues/ref-anchor-scope-mismatch-skill-references-20260131.md +55 -0
- package/docs/solutions/agentic-issues/tautological-tests-routing-20260131.md +52 -0
- package/docs/solutions/integration_issue/blocktool-output-format-mismatch-hook-runner-20260130.md +52 -0
- package/docs/solutions/integration_issue/dual-validation-path-divergence-schema-20260130.md +66 -0
- package/docs/solutions/security-issues/unsanitized-domain-path-join-20260131.md +52 -0
- package/docs/solutions/test-failures/event-loop-mock-ordering-checkAgentWindows-20260130.md +63 -0
- package/docs/sync-cli/README.md +19 -0
- package/docs/sync-cli/cli-entrypoint-and-commands.md +39 -0
- package/docs/sync-cli/commands/README.md +11 -0
- package/docs/sync-cli/commands/pull-manifest-command.md +36 -0
- package/docs/sync-cli/commands/push-command.md +84 -0
- package/docs/sync-cli/commands/sync-command.md +71 -0
- package/docs/sync-cli/systems/README.md +14 -0
- package/docs/sync-cli/systems/git-and-github-integration.md +49 -0
- package/docs/sync-cli/systems/interactive-ui.md +43 -0
- package/docs/sync-cli/systems/manifest-and-distribution.md +51 -0
- package/docs/sync-cli/systems/path-resolution.md +42 -0
- package/package.json +46 -0
- package/scripts/install-shim.sh +40 -0
- package/scripts/pre-pack.sh +25 -0
- package/specs/harness-maintenance-skill.spec.md +138 -0
- package/specs/roadmap/git-spec-lifecycle-management.spec.md +113 -0
- package/specs/sync-init-flag.spec.md +117 -0
- package/specs/unified-workflow-orchestration.spec.md +250 -0
- package/specs/validation-tooling-practice.spec.md +98 -0
- package/specs/workflow-domain-configuration.spec.md +265 -0
- package/src/commands/pull-manifest.ts +31 -0
- package/src/commands/push.ts +344 -0
- package/src/commands/sync.ts +289 -0
- package/src/lib/constants.ts +10 -0
- package/src/lib/dotfiles.ts +36 -0
- package/src/lib/fs-utils.ts +18 -0
- package/src/lib/gh.ts +40 -0
- package/src/lib/git.ts +63 -0
- package/src/lib/gitignore.ts +167 -0
- package/src/lib/manifest.ts +121 -0
- package/src/lib/marker-sync.ts +39 -0
- package/src/lib/paths.ts +38 -0
- package/src/lib/target-lines.ts +66 -0
- package/src/lib/ui.ts +78 -0
- package/src/sync-cli.ts +120 -0
- package/target-lines.json +23 -0
- 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
|