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