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