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,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ephemeral Test Fixture Creation
|
|
3
|
+
*
|
|
4
|
+
* Creates temporary project directories with the proper structure
|
|
5
|
+
* for testing harness functionality in isolation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { mkdirSync, writeFileSync, rmSync, cpSync, existsSync, readFileSync } from 'fs';
|
|
9
|
+
import { join, dirname } from 'path';
|
|
10
|
+
import { tmpdir } from 'os';
|
|
11
|
+
import { randomBytes } from 'crypto';
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
// Types
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
export interface FixtureOptions {
|
|
19
|
+
/** Unique name for the fixture (auto-generated if not provided) */
|
|
20
|
+
name?: string;
|
|
21
|
+
/** Whether to copy the real harness from .allhands/ */
|
|
22
|
+
copyHarness?: boolean;
|
|
23
|
+
/** Whether to initialize as a git repo */
|
|
24
|
+
initGit?: boolean;
|
|
25
|
+
/** Initial files to create (path -> content) */
|
|
26
|
+
files?: Record<string, string>;
|
|
27
|
+
/** Environment variables to set when running commands */
|
|
28
|
+
env?: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TestFixture {
|
|
32
|
+
/** Root directory of the fixture */
|
|
33
|
+
root: string;
|
|
34
|
+
/** Path to .allhands directory */
|
|
35
|
+
allhands: string;
|
|
36
|
+
/** Path to .planning directory */
|
|
37
|
+
planning: string;
|
|
38
|
+
/** Path to specs directory */
|
|
39
|
+
specs: string;
|
|
40
|
+
/** Path to src directory */
|
|
41
|
+
src: string;
|
|
42
|
+
/** Environment variables for this fixture */
|
|
43
|
+
env: Record<string, string>;
|
|
44
|
+
/** Write a file relative to fixture root */
|
|
45
|
+
writeFile: (relativePath: string, content: string) => void;
|
|
46
|
+
/** Read a file relative to fixture root */
|
|
47
|
+
readFile: (relativePath: string) => string;
|
|
48
|
+
/** Check if file exists relative to fixture root */
|
|
49
|
+
exists: (relativePath: string) => boolean;
|
|
50
|
+
/** Clean up the fixture */
|
|
51
|
+
cleanup: () => void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
55
|
+
// Fixture Templates
|
|
56
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
/** Prompt file template matching .allhands/schemas/prompt.yaml */
|
|
59
|
+
export const PROMPT_TEMPLATE = (
|
|
60
|
+
status: 'pending' | 'in_progress' | 'done' = 'pending',
|
|
61
|
+
title: string = 'Test Task',
|
|
62
|
+
number: number = 1
|
|
63
|
+
) => `---
|
|
64
|
+
number: ${number}
|
|
65
|
+
title: "${title.replace(/"/g, '\\"')}"
|
|
66
|
+
type: planned
|
|
67
|
+
planning_session: 1
|
|
68
|
+
status: ${status}
|
|
69
|
+
dependencies: []
|
|
70
|
+
attempts: 0
|
|
71
|
+
commits: []
|
|
72
|
+
validation_suites: []
|
|
73
|
+
skills: []
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
# Tasks
|
|
77
|
+
|
|
78
|
+
- Implement the feature
|
|
79
|
+
- Add tests
|
|
80
|
+
|
|
81
|
+
# Acceptance Criteria
|
|
82
|
+
|
|
83
|
+
- Feature works as expected
|
|
84
|
+
- Tests pass
|
|
85
|
+
`;
|
|
86
|
+
|
|
87
|
+
/** Alignment doc template matching .allhands/schemas/alignment.yaml */
|
|
88
|
+
export const ALIGNMENT_TEMPLATE = (
|
|
89
|
+
specName: string = 'test-spec',
|
|
90
|
+
specPath: string = 'specs/test.spec.md'
|
|
91
|
+
) => `---
|
|
92
|
+
spec_name: ${specName}
|
|
93
|
+
spec_path: ${specPath}
|
|
94
|
+
planning_session: 1
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
# Overview
|
|
98
|
+
|
|
99
|
+
Test alignment document.
|
|
100
|
+
|
|
101
|
+
# Hard User Requirements
|
|
102
|
+
|
|
103
|
+
- Must follow existing patterns
|
|
104
|
+
`;
|
|
105
|
+
|
|
106
|
+
/** Spec file template matching .allhands/schemas/spec.yaml */
|
|
107
|
+
export const SPEC_TEMPLATE = (
|
|
108
|
+
name: string = 'test-spec',
|
|
109
|
+
domainName: string = 'test-domain'
|
|
110
|
+
) => `---
|
|
111
|
+
name: ${name}
|
|
112
|
+
domain_name: ${domainName}
|
|
113
|
+
status: roadmap
|
|
114
|
+
dependencies: []
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
# Motivation
|
|
118
|
+
|
|
119
|
+
Test specification motivation.
|
|
120
|
+
|
|
121
|
+
# Goals
|
|
122
|
+
|
|
123
|
+
- Goal 1
|
|
124
|
+
- Goal 2
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
/** Sample Python file for edit/validation tests */
|
|
128
|
+
export const PYTHON_SAMPLE = `"""Sample Python module for testing."""
|
|
129
|
+
|
|
130
|
+
def hello(name: str) -> str:
|
|
131
|
+
"""Return a greeting."""
|
|
132
|
+
return f"Hello, {name}!"
|
|
133
|
+
|
|
134
|
+
class Calculator:
|
|
135
|
+
"""Simple calculator class."""
|
|
136
|
+
|
|
137
|
+
def add(self, a: int, b: int) -> int:
|
|
138
|
+
"""Add two numbers."""
|
|
139
|
+
return a + b
|
|
140
|
+
|
|
141
|
+
def subtract(self, a: int, b: int) -> int:
|
|
142
|
+
"""Subtract b from a."""
|
|
143
|
+
return a - b
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
/** Sample TypeScript file */
|
|
147
|
+
export const TYPESCRIPT_SAMPLE = `/**
|
|
148
|
+
* Sample TypeScript module for testing.
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
export interface User {
|
|
152
|
+
id: string;
|
|
153
|
+
name: string;
|
|
154
|
+
email: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function greet(user: User): string {
|
|
158
|
+
return \`Hello, \${user.name}!\`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export class UserService {
|
|
162
|
+
private users: Map<string, User> = new Map();
|
|
163
|
+
|
|
164
|
+
add(user: User): void {
|
|
165
|
+
this.users.set(user.id, user);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get(id: string): User | undefined {
|
|
169
|
+
return this.users.get(id);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
|
|
174
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
175
|
+
// Fixture Creation
|
|
176
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get the real harness directory (for copying to fixtures).
|
|
180
|
+
*/
|
|
181
|
+
function getRealHarnessDir(): string {
|
|
182
|
+
// Navigate from this file to the harness root
|
|
183
|
+
return join(dirname(dirname(dirname(__dirname))));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get the real .allhands directory.
|
|
188
|
+
*/
|
|
189
|
+
function getRealAllhandsDir(): string {
|
|
190
|
+
return join(getRealHarnessDir(), '..');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Create an ephemeral test fixture.
|
|
195
|
+
*/
|
|
196
|
+
export function createFixture(options: FixtureOptions = {}): TestFixture {
|
|
197
|
+
const {
|
|
198
|
+
name = `ah-test-${randomBytes(4).toString('hex')}`,
|
|
199
|
+
copyHarness = false,
|
|
200
|
+
initGit = true,
|
|
201
|
+
files = {},
|
|
202
|
+
env = {},
|
|
203
|
+
} = options;
|
|
204
|
+
|
|
205
|
+
// Create temp directory
|
|
206
|
+
const root = join(tmpdir(), name);
|
|
207
|
+
|
|
208
|
+
// Clean up if exists from previous failed run
|
|
209
|
+
if (existsSync(root)) {
|
|
210
|
+
rmSync(root, { recursive: true, force: true });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
mkdirSync(root, { recursive: true });
|
|
214
|
+
|
|
215
|
+
// Create standard directories
|
|
216
|
+
const allhands = join(root, '.allhands');
|
|
217
|
+
const planning = join(root, '.planning');
|
|
218
|
+
const specs = join(root, 'specs');
|
|
219
|
+
const src = join(root, 'src');
|
|
220
|
+
|
|
221
|
+
mkdirSync(allhands, { recursive: true });
|
|
222
|
+
mkdirSync(planning, { recursive: true });
|
|
223
|
+
mkdirSync(specs, { recursive: true });
|
|
224
|
+
mkdirSync(src, { recursive: true });
|
|
225
|
+
|
|
226
|
+
// Copy real harness if requested
|
|
227
|
+
if (copyHarness) {
|
|
228
|
+
const realAllhands = getRealAllhandsDir();
|
|
229
|
+
cpSync(realAllhands, allhands, { recursive: true });
|
|
230
|
+
} else {
|
|
231
|
+
// Create minimal harness structure
|
|
232
|
+
mkdirSync(join(allhands, 'harness'), { recursive: true });
|
|
233
|
+
mkdirSync(join(allhands, 'flows'), { recursive: true });
|
|
234
|
+
mkdirSync(join(allhands, 'schemas'), { recursive: true });
|
|
235
|
+
mkdirSync(join(allhands, 'validation'), { recursive: true });
|
|
236
|
+
|
|
237
|
+
// Create minimal schema files
|
|
238
|
+
writeFileSync(
|
|
239
|
+
join(allhands, 'schemas', 'prompt.yaml'),
|
|
240
|
+
`# Prompt schema\nrequired:\n - status\nproperties:\n status:\n type: string\n enum: [pending, in_progress, completed, blocked]\n`
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
writeFileSync(
|
|
244
|
+
join(allhands, 'schemas', 'alignment.yaml'),
|
|
245
|
+
`# Alignment schema\nrequired:\n - spec_name\nproperties:\n spec_name:\n type: string\n`
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
writeFileSync(
|
|
249
|
+
join(allhands, 'schemas', 'spec.yaml'),
|
|
250
|
+
`# Spec schema\nrequired:\n - name\n - version\nproperties:\n name:\n type: string\n version:\n type: integer\n`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Initialize git repo if requested
|
|
255
|
+
if (initGit) {
|
|
256
|
+
execSync('git init', { cwd: root, stdio: 'pipe' });
|
|
257
|
+
execSync('git config user.email "test@example.com"', { cwd: root, stdio: 'pipe' });
|
|
258
|
+
execSync('git config user.name "Test User"', { cwd: root, stdio: 'pipe' });
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Write initial files
|
|
262
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
263
|
+
const fullPath = join(root, relativePath);
|
|
264
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
265
|
+
writeFileSync(fullPath, content);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Build fixture object
|
|
269
|
+
const fixture: TestFixture = {
|
|
270
|
+
root,
|
|
271
|
+
allhands,
|
|
272
|
+
planning,
|
|
273
|
+
specs,
|
|
274
|
+
src,
|
|
275
|
+
env: {
|
|
276
|
+
CLAUDE_PROJECT_DIR: root,
|
|
277
|
+
...env,
|
|
278
|
+
},
|
|
279
|
+
writeFile: (relativePath: string, content: string) => {
|
|
280
|
+
const fullPath = join(root, relativePath);
|
|
281
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
282
|
+
writeFileSync(fullPath, content);
|
|
283
|
+
},
|
|
284
|
+
readFile: (relativePath: string) => {
|
|
285
|
+
return readFileSync(join(root, relativePath), 'utf-8');
|
|
286
|
+
},
|
|
287
|
+
exists: (relativePath: string) => {
|
|
288
|
+
return existsSync(join(root, relativePath));
|
|
289
|
+
},
|
|
290
|
+
cleanup: () => {
|
|
291
|
+
rmSync(root, { recursive: true, force: true });
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return fixture;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Create a fixture with a complete spec structure.
|
|
300
|
+
*/
|
|
301
|
+
export function createSpecFixture(
|
|
302
|
+
specName: string = 'test-spec',
|
|
303
|
+
promptCount: number = 3
|
|
304
|
+
): TestFixture {
|
|
305
|
+
const files: Record<string, string> = {
|
|
306
|
+
// Spec file
|
|
307
|
+
[`specs/${specName}.spec.md`]: SPEC_TEMPLATE(specName, 'test-domain'),
|
|
308
|
+
// Alignment doc
|
|
309
|
+
[`.planning/${specName}/alignment.md`]: ALIGNMENT_TEMPLATE(
|
|
310
|
+
specName,
|
|
311
|
+
`specs/${specName}.spec.md`
|
|
312
|
+
),
|
|
313
|
+
// Sample source files
|
|
314
|
+
['src/sample.py']: PYTHON_SAMPLE,
|
|
315
|
+
['src/sample.ts']: TYPESCRIPT_SAMPLE,
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// Add prompts
|
|
319
|
+
for (let i = 1; i <= promptCount; i++) {
|
|
320
|
+
const num = i.toString().padStart(2, '0');
|
|
321
|
+
files[`.planning/${specName}/prompts/${num}.md`] = PROMPT_TEMPLATE(
|
|
322
|
+
i === 1 ? 'in_progress' : 'pending',
|
|
323
|
+
`Task ${i}: Implement feature ${i}`,
|
|
324
|
+
i
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return createFixture({
|
|
329
|
+
name: `ah-spec-${specName}`,
|
|
330
|
+
files,
|
|
331
|
+
env: {
|
|
332
|
+
SPEC_NAME: specName,
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Alias for createSpecFixture (used in E2E tests).
|
|
339
|
+
*/
|
|
340
|
+
export const createMilestoneFixture = createSpecFixture;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Create a fixture with multiple spec files (no prompts).
|
|
344
|
+
*/
|
|
345
|
+
export function createMultiSpecFixture(specs: string[] = ['api', 'data-model']): TestFixture {
|
|
346
|
+
const files: Record<string, string> = {};
|
|
347
|
+
|
|
348
|
+
for (const spec of specs) {
|
|
349
|
+
files[`specs/${spec}.spec.md`] = SPEC_TEMPLATE(spec, 'test-domain');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return createFixture({
|
|
353
|
+
name: 'ah-specs-test',
|
|
354
|
+
files,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
359
|
+
// Fixture Pool (for reuse across tests)
|
|
360
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
361
|
+
|
|
362
|
+
const fixturePool: Map<string, TestFixture> = new Map();
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Get or create a named fixture from the pool.
|
|
366
|
+
* Useful for sharing fixtures across tests in the same file.
|
|
367
|
+
*/
|
|
368
|
+
export function getPooledFixture(name: string, factory: () => TestFixture): TestFixture {
|
|
369
|
+
if (!fixturePool.has(name)) {
|
|
370
|
+
fixturePool.set(name, factory());
|
|
371
|
+
}
|
|
372
|
+
return fixturePool.get(name)!;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Clean up all pooled fixtures.
|
|
377
|
+
* Call this in afterAll() hooks.
|
|
378
|
+
*/
|
|
379
|
+
export function cleanupPool(): void {
|
|
380
|
+
for (const fixture of fixturePool.values()) {
|
|
381
|
+
fixture.cleanup();
|
|
382
|
+
}
|
|
383
|
+
fixturePool.clear();
|
|
384
|
+
}
|