all-hands-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) hide show
  1. package/.allhands/README.md +75 -0
  2. package/.allhands/agents/compounder.yaml +15 -0
  3. package/.allhands/agents/coordinator.yaml +17 -0
  4. package/.allhands/agents/documentor.yaml +15 -0
  5. package/.allhands/agents/e2e-test-planner.yaml +17 -0
  6. package/.allhands/agents/emergent.yaml +22 -0
  7. package/.allhands/agents/executor.yaml +14 -0
  8. package/.allhands/agents/ideation.yaml +11 -0
  9. package/.allhands/agents/initiative-steering.yaml +19 -0
  10. package/.allhands/agents/judge.yaml +13 -0
  11. package/.allhands/agents/planner.yaml +19 -0
  12. package/.allhands/agents/pr-reviewer.yaml +15 -0
  13. package/.allhands/docs.json +5 -0
  14. package/.allhands/docs.local.json +26 -0
  15. package/.allhands/flows/COMPOUNDING.md +203 -0
  16. package/.allhands/flows/COORDINATION.md +89 -0
  17. package/.allhands/flows/CORE.md +87 -0
  18. package/.allhands/flows/DOCUMENTATION.md +218 -0
  19. package/.allhands/flows/E2E_TEST_PLAN_BUILDING.md +140 -0
  20. package/.allhands/flows/EMERGENT_PLANNING.md +57 -0
  21. package/.allhands/flows/IDEATION_SCOPING.md +154 -0
  22. package/.allhands/flows/INITIATIVE_STEERING.md +110 -0
  23. package/.allhands/flows/JUDGE_REVIEWING.md +79 -0
  24. package/.allhands/flows/PROMPT_TASK_EXECUTION.md +68 -0
  25. package/.allhands/flows/PR_REVIEWING.md +43 -0
  26. package/.allhands/flows/SPEC_PLANNING.md +216 -0
  27. package/.allhands/flows/harness/WRITING_HARNESS_FLOWS.md +27 -0
  28. package/.allhands/flows/harness/WRITING_HARNESS_KNOWLEDGE.md +27 -0
  29. package/.allhands/flows/harness/WRITING_HARNESS_ORCHESTRATION.md +27 -0
  30. package/.allhands/flows/harness/WRITING_HARNESS_SKILLS.md +27 -0
  31. package/.allhands/flows/harness/WRITING_HARNESS_TOOLS.md +27 -0
  32. package/.allhands/flows/harness/WRITING_HARNESS_VALIDATION_TOOLING.md +27 -0
  33. package/.allhands/flows/shared/CODEBASE_UNDERSTANDING.md +72 -0
  34. package/.allhands/flows/shared/CREATE_HARNESS_SPEC.md +48 -0
  35. package/.allhands/flows/shared/CREATE_SPEC.md +41 -0
  36. package/.allhands/flows/shared/CREATE_VALIDATION_TOOLING_SPEC.md +70 -0
  37. package/.allhands/flows/shared/DOCUMENTATION_DISCOVERY.md +123 -0
  38. package/.allhands/flows/shared/DOCUMENTATION_WRITER.md +101 -0
  39. package/.allhands/flows/shared/EMERGENT_REFINEMENT_ANALYSIS.md +76 -0
  40. package/.allhands/flows/shared/EXTERNAL_TECH_GUIDANCE.md +97 -0
  41. package/.allhands/flows/shared/IDEATION_CODEBASE_GROUNDING.md +49 -0
  42. package/.allhands/flows/shared/PLAN_DEEPENING.md +152 -0
  43. package/.allhands/flows/shared/PROMPT_TASKS_CURATION.md +113 -0
  44. package/.allhands/flows/shared/PROMPT_VALIDATION_REVIEW.MD +99 -0
  45. package/.allhands/flows/shared/QUICK_PREMORTEM.md +70 -0
  46. package/.allhands/flows/shared/RESEARCH_GUIDANCE.md +38 -0
  47. package/.allhands/flows/shared/REVIEW_OPTIONS_BREAKDOWN.md +68 -0
  48. package/.allhands/flows/shared/SKILL_EXTRACTION.md +84 -0
  49. package/.allhands/flows/shared/SPEC_FLOW_ANALYSIS.md +119 -0
  50. package/.allhands/flows/shared/TDD_WORKFLOW.md +109 -0
  51. package/.allhands/flows/shared/UTILIZE_VALIDATION_TOOLING.md +84 -0
  52. package/.allhands/flows/shared/WRITING_HARNESS_FLOWS.md +11 -0
  53. package/.allhands/flows/shared/WRITING_HARNESS_MCP_TOOLS.md +84 -0
  54. package/.allhands/flows/shared/jury/ARCHITECTURE_REVIEW.md +91 -0
  55. package/.allhands/flows/shared/jury/BEST_PRACTICES_REVIEW.md +80 -0
  56. package/.allhands/flows/shared/jury/CLAIM_VERIFICATION_REVIEW.md +101 -0
  57. package/.allhands/flows/shared/jury/EXPECTATIONS_FIT_REVIEW.md +78 -0
  58. package/.allhands/flows/shared/jury/MAINTAINABILITY_REVIEW.md +110 -0
  59. package/.allhands/flows/shared/jury/PROMPTS_EXPECTATIONS_FIT.md +74 -0
  60. package/.allhands/flows/shared/jury/PROMPTS_FLOW_ANALYSIS.md +92 -0
  61. package/.allhands/flows/shared/jury/PROMPTS_YAGNI.md +78 -0
  62. package/.allhands/flows/shared/jury/PROMPT_PREMORTEM.md +125 -0
  63. package/.allhands/flows/shared/jury/SECURITY_REVIEW.md +86 -0
  64. package/.allhands/flows/shared/jury/YAGNI_REVIEW.md +82 -0
  65. package/.allhands/flows/wip/DEBUG_INVESTIGATION.md +162 -0
  66. package/.allhands/flows/wip/MEMORY_RECALL.md +62 -0
  67. package/.allhands/harness/ah +131 -0
  68. package/.allhands/harness/package-lock.json +5292 -0
  69. package/.allhands/harness/package.json +52 -0
  70. package/.allhands/harness/src/__tests__/e2e/commands.test.ts +307 -0
  71. package/.allhands/harness/src/__tests__/e2e/event-loop.test.ts +539 -0
  72. package/.allhands/harness/src/__tests__/e2e/hooks.test.ts +427 -0
  73. package/.allhands/harness/src/__tests__/e2e/new-initiative-routing.test.ts +137 -0
  74. package/.allhands/harness/src/__tests__/e2e/run-e2e.ts +109 -0
  75. package/.allhands/harness/src/__tests__/e2e/specs-type.test.ts +210 -0
  76. package/.allhands/harness/src/__tests__/e2e/validation-hooks.test.ts +669 -0
  77. package/.allhands/harness/src/__tests__/e2e/validation-path-consistency.test.ts +354 -0
  78. package/.allhands/harness/src/__tests__/e2e/validation.test.ts +528 -0
  79. package/.allhands/harness/src/__tests__/harness/assertions.ts +318 -0
  80. package/.allhands/harness/src/__tests__/harness/cli-runner.ts +359 -0
  81. package/.allhands/harness/src/__tests__/harness/fixture.ts +384 -0
  82. package/.allhands/harness/src/__tests__/harness/hook-runner.ts +411 -0
  83. package/.allhands/harness/src/__tests__/harness/index.ts +122 -0
  84. package/.allhands/harness/src/cli.ts +36 -0
  85. package/.allhands/harness/src/commands/complexity.ts +177 -0
  86. package/.allhands/harness/src/commands/context7.ts +202 -0
  87. package/.allhands/harness/src/commands/docs.ts +557 -0
  88. package/.allhands/harness/src/commands/hooks.ts +24 -0
  89. package/.allhands/harness/src/commands/index.ts +51 -0
  90. package/.allhands/harness/src/commands/knowledge.ts +382 -0
  91. package/.allhands/harness/src/commands/memories.ts +302 -0
  92. package/.allhands/harness/src/commands/notify.ts +61 -0
  93. package/.allhands/harness/src/commands/oracle.ts +158 -0
  94. package/.allhands/harness/src/commands/perplexity.ts +220 -0
  95. package/.allhands/harness/src/commands/planning.ts +245 -0
  96. package/.allhands/harness/src/commands/schema.ts +73 -0
  97. package/.allhands/harness/src/commands/skills.ts +128 -0
  98. package/.allhands/harness/src/commands/solutions.ts +353 -0
  99. package/.allhands/harness/src/commands/spawn.ts +158 -0
  100. package/.allhands/harness/src/commands/specs.ts +532 -0
  101. package/.allhands/harness/src/commands/tavily.ts +226 -0
  102. package/.allhands/harness/src/commands/tools.ts +579 -0
  103. package/.allhands/harness/src/commands/trace.ts +327 -0
  104. package/.allhands/harness/src/commands/tui.ts +960 -0
  105. package/.allhands/harness/src/commands/validate.ts +143 -0
  106. package/.allhands/harness/src/commands/validation-tools.ts +108 -0
  107. package/.allhands/harness/src/hooks/context.ts +1442 -0
  108. package/.allhands/harness/src/hooks/enforcement.ts +170 -0
  109. package/.allhands/harness/src/hooks/index.ts +54 -0
  110. package/.allhands/harness/src/hooks/lifecycle.ts +229 -0
  111. package/.allhands/harness/src/hooks/notification.ts +104 -0
  112. package/.allhands/harness/src/hooks/observability.ts +551 -0
  113. package/.allhands/harness/src/hooks/session.ts +88 -0
  114. package/.allhands/harness/src/hooks/shared.ts +815 -0
  115. package/.allhands/harness/src/hooks/transcript-parser.ts +208 -0
  116. package/.allhands/harness/src/hooks/validation.ts +617 -0
  117. package/.allhands/harness/src/lib/__tests__/ctags.test.ts +244 -0
  118. package/.allhands/harness/src/lib/__tests__/docs-validation.test.ts +344 -0
  119. package/.allhands/harness/src/lib/__tests__/mcp-runtime.test.ts +190 -0
  120. package/.allhands/harness/src/lib/__tests__/schema.test.ts +861 -0
  121. package/.allhands/harness/src/lib/base-command.ts +198 -0
  122. package/.allhands/harness/src/lib/cli-daemon.ts +343 -0
  123. package/.allhands/harness/src/lib/compaction.ts +313 -0
  124. package/.allhands/harness/src/lib/ctags.ts +497 -0
  125. package/.allhands/harness/src/lib/docs-validation.ts +907 -0
  126. package/.allhands/harness/src/lib/event-loop.ts +662 -0
  127. package/.allhands/harness/src/lib/flows.ts +155 -0
  128. package/.allhands/harness/src/lib/git.ts +276 -0
  129. package/.allhands/harness/src/lib/knowledge-worker.ts +72 -0
  130. package/.allhands/harness/src/lib/knowledge.ts +810 -0
  131. package/.allhands/harness/src/lib/llm.ts +255 -0
  132. package/.allhands/harness/src/lib/mcp-client.ts +432 -0
  133. package/.allhands/harness/src/lib/mcp-daemon.ts +486 -0
  134. package/.allhands/harness/src/lib/mcp-runtime.ts +418 -0
  135. package/.allhands/harness/src/lib/notification.ts +115 -0
  136. package/.allhands/harness/src/lib/opencode/index.ts +70 -0
  137. package/.allhands/harness/src/lib/opencode/profiles.ts +300 -0
  138. package/.allhands/harness/src/lib/opencode/prompts/codesearch.md +98 -0
  139. package/.allhands/harness/src/lib/opencode/prompts/knowledge-aggregator.md +67 -0
  140. package/.allhands/harness/src/lib/opencode/runner.ts +281 -0
  141. package/.allhands/harness/src/lib/oracle.ts +926 -0
  142. package/.allhands/harness/src/lib/planning-utils.ts +150 -0
  143. package/.allhands/harness/src/lib/planning.ts +605 -0
  144. package/.allhands/harness/src/lib/pr-review.ts +225 -0
  145. package/.allhands/harness/src/lib/prompts.ts +522 -0
  146. package/.allhands/harness/src/lib/schema.ts +418 -0
  147. package/.allhands/harness/src/lib/schemas/agent-profile.ts +141 -0
  148. package/.allhands/harness/src/lib/schemas/template-vars.ts +138 -0
  149. package/.allhands/harness/src/lib/session.ts +164 -0
  150. package/.allhands/harness/src/lib/specs.ts +348 -0
  151. package/.allhands/harness/src/lib/tldr.ts +829 -0
  152. package/.allhands/harness/src/lib/tmux.ts +1051 -0
  153. package/.allhands/harness/src/lib/trace-store.ts +714 -0
  154. package/.allhands/harness/src/mcp/__tests__/index.test.ts +46 -0
  155. package/.allhands/harness/src/mcp/_template.ts +47 -0
  156. package/.allhands/harness/src/mcp/filesystem.ts +33 -0
  157. package/.allhands/harness/src/mcp/index.ts +69 -0
  158. package/.allhands/harness/src/mcp/playwright.ts +34 -0
  159. package/.allhands/harness/src/mcp/xcodebuild.ts +29 -0
  160. package/.allhands/harness/src/schemas/docs.schema.json +44 -0
  161. package/.allhands/harness/src/schemas/settings.schema.json +214 -0
  162. package/.allhands/harness/src/tui/actions.ts +227 -0
  163. package/.allhands/harness/src/tui/file-viewer-modal.ts +270 -0
  164. package/.allhands/harness/src/tui/index.ts +1574 -0
  165. package/.allhands/harness/src/tui/modal.ts +232 -0
  166. package/.allhands/harness/src/tui/prompts-pane.ts +186 -0
  167. package/.allhands/harness/src/tui/status-pane.ts +434 -0
  168. package/.allhands/harness/tsconfig.json +22 -0
  169. package/.allhands/harness/vitest.config.ts +13 -0
  170. package/.allhands/pillars.md +33 -0
  171. package/.allhands/principles.md +88 -0
  172. package/.allhands/schemas/alignment.yaml +51 -0
  173. package/.allhands/schemas/documentation.yaml +10 -0
  174. package/.allhands/schemas/prompt.yaml +92 -0
  175. package/.allhands/schemas/skill.yaml +34 -0
  176. package/.allhands/schemas/solution.yaml +131 -0
  177. package/.allhands/schemas/spec.yaml +67 -0
  178. package/.allhands/schemas/validation-suite.yaml +49 -0
  179. package/.allhands/schemas/workflow.yaml +51 -0
  180. package/.allhands/settings.json +57 -0
  181. package/.allhands/skills/claude-code-patterns/SKILL.md +60 -0
  182. package/.allhands/skills/claude-code-patterns/docs/context-hygiene.md +19 -0
  183. package/.allhands/skills/harness-maintenance/SKILL.md +449 -0
  184. package/.allhands/skills/harness-maintenance/references/core-architecture.md +187 -0
  185. package/.allhands/skills/harness-maintenance/references/harness-skills.md +87 -0
  186. package/.allhands/skills/harness-maintenance/references/knowledge-compounding.md +78 -0
  187. package/.allhands/skills/harness-maintenance/references/tools-commands-mcp-hooks.md +115 -0
  188. package/.allhands/skills/harness-maintenance/references/validation-tooling.md +77 -0
  189. package/.allhands/skills/harness-maintenance/references/writing-flows.md +84 -0
  190. package/.allhands/validation/browser-automation.md +109 -0
  191. package/.allhands/validation/xcode-automation.md +195 -0
  192. package/.allhands/workflows/documentation.md +86 -0
  193. package/.allhands/workflows/investigation.md +81 -0
  194. package/.allhands/workflows/milestone.md +91 -0
  195. package/.allhands/workflows/optimization.md +85 -0
  196. package/.allhands/workflows/refactor.md +99 -0
  197. package/.allhands/workflows/triage.md +81 -0
  198. package/.claude/README.md +1 -0
  199. package/.claude/agents/explorer.md +10 -0
  200. package/.claude/agents/researcher.md +11 -0
  201. package/.claude/agents/task-runner.md +8 -0
  202. package/.claude/settings.json +231 -0
  203. package/.env.ai.example +7 -0
  204. package/.github/workflows/npm-publish.yml +69 -0
  205. package/.internal.json +45 -0
  206. package/.tldr/config.json +11 -0
  207. package/.tldrignore +90 -0
  208. package/CLAUDE.md +6 -0
  209. package/README.md +98 -0
  210. package/bin/sync-cli.js +7552 -0
  211. package/concerns.md +7 -0
  212. package/docs/README.md +41 -0
  213. package/docs/agents/README.md +24 -0
  214. package/docs/agents/agent-configuration-system.md +86 -0
  215. package/docs/agents/execution-agents.md +50 -0
  216. package/docs/agents/knowledge-agents.md +61 -0
  217. package/docs/agents/orchestration-agent.md +57 -0
  218. package/docs/agents/planning-agents.md +84 -0
  219. package/docs/agents/quality-review-agents.md +67 -0
  220. package/docs/agents/workflow-agent-orchestration.md +69 -0
  221. package/docs/flows/README.md +44 -0
  222. package/docs/flows/compounding.md +126 -0
  223. package/docs/flows/coordination.md +72 -0
  224. package/docs/flows/core-harness-integration.md +63 -0
  225. package/docs/flows/documentation-orchestration.md +98 -0
  226. package/docs/flows/e2e-test-plan-building.md +83 -0
  227. package/docs/flows/emergent-refinement.md +104 -0
  228. package/docs/flows/flow-authoring-and-mcp-tools.md +89 -0
  229. package/docs/flows/judge-reviewing.md +112 -0
  230. package/docs/flows/plan-deepening-and-research.md +107 -0
  231. package/docs/flows/plan-review-jury.md +114 -0
  232. package/docs/flows/pr-reviewing.md +54 -0
  233. package/docs/flows/prompt-task-execution.md +119 -0
  234. package/docs/flows/spec-planning.md +162 -0
  235. package/docs/flows/type-specific-scoping-flows.md +49 -0
  236. package/docs/flows/validation-and-skills-integration.md +145 -0
  237. package/docs/flows/wip/wip-flows.md +102 -0
  238. package/docs/harness/README.md +23 -0
  239. package/docs/harness/agent-profiles.md +84 -0
  240. package/docs/harness/cli/README.md +24 -0
  241. package/docs/harness/cli/cli-entry-and-command-discovery.md +91 -0
  242. package/docs/harness/cli/docs-command.md +87 -0
  243. package/docs/harness/cli/knowledge-command.md +91 -0
  244. package/docs/harness/cli/minor-cli-commands.md +65 -0
  245. package/docs/harness/cli/oracle-command.md +113 -0
  246. package/docs/harness/cli/planning-command.md +95 -0
  247. package/docs/harness/cli/schema-and-validation-commands.md +154 -0
  248. package/docs/harness/cli/search-commands.md +97 -0
  249. package/docs/harness/cli/spawn-command.md +136 -0
  250. package/docs/harness/cli/specs-command.md +102 -0
  251. package/docs/harness/cli/tools-command.md +122 -0
  252. package/docs/harness/cli/trace-command.md +122 -0
  253. package/docs/harness/cli-daemon.md +92 -0
  254. package/docs/harness/event-loop.md +184 -0
  255. package/docs/harness/hooks/README.md +15 -0
  256. package/docs/harness/hooks/context-hooks.md +96 -0
  257. package/docs/harness/hooks/lifecycle-and-observability-hooks.md +135 -0
  258. package/docs/harness/hooks/validation-hooks.md +97 -0
  259. package/docs/harness/test-harness.md +149 -0
  260. package/docs/harness/tui.md +176 -0
  261. package/docs/memories.md +20 -0
  262. package/docs/solutions/agentic-issues/premature-agent-deletion-tui-action-dependency-20260130.md +49 -0
  263. package/docs/solutions/agentic-issues/ref-anchor-scope-mismatch-skill-references-20260131.md +55 -0
  264. package/docs/solutions/agentic-issues/tautological-tests-routing-20260131.md +52 -0
  265. package/docs/solutions/integration_issue/blocktool-output-format-mismatch-hook-runner-20260130.md +52 -0
  266. package/docs/solutions/integration_issue/dual-validation-path-divergence-schema-20260130.md +66 -0
  267. package/docs/solutions/security-issues/unsanitized-domain-path-join-20260131.md +52 -0
  268. package/docs/solutions/test-failures/event-loop-mock-ordering-checkAgentWindows-20260130.md +63 -0
  269. package/docs/sync-cli/README.md +19 -0
  270. package/docs/sync-cli/cli-entrypoint-and-commands.md +39 -0
  271. package/docs/sync-cli/commands/README.md +11 -0
  272. package/docs/sync-cli/commands/pull-manifest-command.md +36 -0
  273. package/docs/sync-cli/commands/push-command.md +84 -0
  274. package/docs/sync-cli/commands/sync-command.md +71 -0
  275. package/docs/sync-cli/systems/README.md +14 -0
  276. package/docs/sync-cli/systems/git-and-github-integration.md +49 -0
  277. package/docs/sync-cli/systems/interactive-ui.md +43 -0
  278. package/docs/sync-cli/systems/manifest-and-distribution.md +51 -0
  279. package/docs/sync-cli/systems/path-resolution.md +42 -0
  280. package/package.json +46 -0
  281. package/scripts/install-shim.sh +40 -0
  282. package/scripts/pre-pack.sh +25 -0
  283. package/specs/harness-maintenance-skill.spec.md +138 -0
  284. package/specs/roadmap/git-spec-lifecycle-management.spec.md +113 -0
  285. package/specs/sync-init-flag.spec.md +117 -0
  286. package/specs/unified-workflow-orchestration.spec.md +250 -0
  287. package/specs/validation-tooling-practice.spec.md +98 -0
  288. package/specs/workflow-domain-configuration.spec.md +265 -0
  289. package/src/commands/pull-manifest.ts +31 -0
  290. package/src/commands/push.ts +344 -0
  291. package/src/commands/sync.ts +289 -0
  292. package/src/lib/constants.ts +10 -0
  293. package/src/lib/dotfiles.ts +36 -0
  294. package/src/lib/fs-utils.ts +18 -0
  295. package/src/lib/gh.ts +40 -0
  296. package/src/lib/git.ts +63 -0
  297. package/src/lib/gitignore.ts +167 -0
  298. package/src/lib/manifest.ts +121 -0
  299. package/src/lib/marker-sync.ts +39 -0
  300. package/src/lib/paths.ts +38 -0
  301. package/src/lib/target-lines.ts +66 -0
  302. package/src/lib/ui.ts +78 -0
  303. package/src/sync-cli.ts +120 -0
  304. package/target-lines.json +23 -0
  305. package/tsconfig.json +20 -0
@@ -0,0 +1,528 @@
1
+ /**
2
+ * E2E Tests - Validation System
3
+ *
4
+ * Tests the complete validation system including:
5
+ * - Schema validation for prompts, specs, alignment docs
6
+ * - Frontmatter parsing
7
+ * - File type detection
8
+ * - Validation error messages
9
+ */
10
+
11
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
12
+ import { join } from 'path';
13
+ import {
14
+ createFixture,
15
+ runValidate,
16
+ runInFixture,
17
+ assertSuccess,
18
+ assertFailure,
19
+ assertFileExists,
20
+ assertValidFrontmatter,
21
+ type TestFixture,
22
+ } from '../harness/index.js';
23
+
24
+ /** Helper to run validate command with full path */
25
+ async function validateFile(fixture: TestFixture, relativePath: string) {
26
+ const filePath = join(fixture.root, relativePath);
27
+ return runInFixture(fixture, ['validate', 'file', filePath]);
28
+ }
29
+
30
+ // ─────────────────────────────────────────────────────────────────────────────
31
+ // Test Fixtures
32
+ // ─────────────────────────────────────────────────────────────────────────────
33
+
34
+ // Valid prompt matching .allhands/schemas/prompt.yaml
35
+ const VALID_PROMPT = `---
36
+ number: 1
37
+ title: Task Title
38
+ type: planned
39
+ planning_session: 1
40
+ status: pending
41
+ dependencies: []
42
+ ---
43
+
44
+ # Tasks
45
+
46
+ - Implement the feature
47
+ - Add tests
48
+
49
+ # Acceptance Criteria
50
+
51
+ - Requirements are met
52
+ `;
53
+
54
+ const VALID_PROMPT_IN_PROGRESS = `---
55
+ number: 2
56
+ title: Active Task
57
+ type: planned
58
+ planning_session: 1
59
+ status: in_progress
60
+ dependencies: []
61
+ ---
62
+
63
+ # Tasks
64
+
65
+ - Working on this now
66
+
67
+ # Acceptance Criteria
68
+
69
+ - Task is complete
70
+ `;
71
+
72
+ const VALID_PROMPT_COMPLETED = `---
73
+ number: 3
74
+ title: Done Task
75
+ type: planned
76
+ planning_session: 1
77
+ status: done
78
+ dependencies: []
79
+ ---
80
+
81
+ # Tasks
82
+
83
+ - This task has been completed
84
+
85
+ # Acceptance Criteria
86
+
87
+ - All done
88
+ `;
89
+
90
+ const VALID_PROMPT_BLOCKED = `---
91
+ number: 4
92
+ title: Blocked Task
93
+ type: planned
94
+ planning_session: 1
95
+ status: pending
96
+ dependencies: [1, 2]
97
+ ---
98
+
99
+ # Tasks
100
+
101
+ - Waiting for dependencies
102
+
103
+ # Acceptance Criteria
104
+
105
+ - Dependencies complete first
106
+ `;
107
+
108
+ const INVALID_PROMPT_BAD_STATUS = `---
109
+ number: 1
110
+ title: Bad Status Task
111
+ type: planned
112
+ planning_session: 1
113
+ status: invalid_status
114
+ ---
115
+
116
+ # Tasks
117
+
118
+ - This status doesn't exist in the enum
119
+
120
+ # Acceptance Criteria
121
+
122
+ - N/A
123
+ `;
124
+
125
+ const INVALID_PROMPT_MISSING_STATUS = `---
126
+ number: 1
127
+ title: Some Task
128
+ type: planned
129
+ ---
130
+
131
+ # Tasks
132
+
133
+ - Missing required status field
134
+
135
+ # Acceptance Criteria
136
+
137
+ - N/A
138
+ `;
139
+
140
+ const INVALID_PROMPT_NO_FRONTMATTER = `# No Frontmatter
141
+
142
+ This file has no YAML frontmatter.
143
+ `;
144
+
145
+ // Valid alignment matching .allhands/schemas/alignment.yaml
146
+ const VALID_ALIGNMENT = `---
147
+ spec_name: test-spec
148
+ spec_path: specs/test.spec.md
149
+ planning_session: 1
150
+ ---
151
+
152
+ # Overview
153
+
154
+ Build the feature.
155
+
156
+ # Hard User Requirements
157
+
158
+ - Follow existing patterns
159
+ `;
160
+
161
+ const INVALID_ALIGNMENT_MISSING_SPEC = `---
162
+ planning_session: 1
163
+ ---
164
+
165
+ # Overview
166
+
167
+ Missing spec_name field.
168
+
169
+ # Hard User Requirements
170
+
171
+ - N/A
172
+ `;
173
+
174
+ // Valid spec matching .allhands/schemas/spec.yaml
175
+ const VALID_SPEC = `---
176
+ name: api-spec
177
+ domain_name: api-domain
178
+ status: roadmap
179
+ dependencies: []
180
+ ---
181
+
182
+ # Motivation
183
+
184
+ This spec defines the API.
185
+
186
+ # Goals
187
+
188
+ - Define endpoints
189
+ `;
190
+
191
+ const INVALID_SPEC_MISSING_DOMAIN = `---
192
+ name: incomplete-spec
193
+ status: roadmap
194
+ ---
195
+
196
+ # Motivation
197
+
198
+ Missing domain_name field.
199
+
200
+ # Goals
201
+
202
+ - N/A
203
+ `;
204
+
205
+ // ─────────────────────────────────────────────────────────────────────────────
206
+ // Prompt Validation Tests
207
+ // ─────────────────────────────────────────────────────────────────────────────
208
+
209
+ describe('Prompt Validation E2E', () => {
210
+ let fixture: TestFixture;
211
+
212
+ beforeAll(() => {
213
+ fixture = createFixture({ name: 'prompt-validation-test' });
214
+ });
215
+
216
+ afterAll(() => {
217
+ fixture.cleanup();
218
+ });
219
+
220
+ describe('valid prompts', () => {
221
+ it('accepts prompt with status: pending', async () => {
222
+ fixture.writeFile('.planning/m1/prompts/01.md', VALID_PROMPT);
223
+ assertValidFrontmatter(fixture, '.planning/m1/prompts/01.md', ['status']);
224
+
225
+ const result = await validateFile(fixture, '.planning/m1/prompts/01.md');
226
+ assertSuccess(result);
227
+ });
228
+
229
+ it('accepts prompt with status: in_progress', async () => {
230
+ fixture.writeFile('.planning/m1/prompts/02.md', VALID_PROMPT_IN_PROGRESS);
231
+ const result = await validateFile(fixture,'.planning/m1/prompts/02.md');
232
+ assertSuccess(result);
233
+ });
234
+
235
+ it('accepts prompt with status: completed', async () => {
236
+ fixture.writeFile('.planning/m1/prompts/03.md', VALID_PROMPT_COMPLETED);
237
+ const result = await validateFile(fixture,'.planning/m1/prompts/03.md');
238
+ assertSuccess(result);
239
+ });
240
+
241
+ it('accepts prompt with status: blocked', async () => {
242
+ fixture.writeFile('.planning/m1/prompts/04.md', VALID_PROMPT_BLOCKED);
243
+ const result = await validateFile(fixture,'.planning/m1/prompts/04.md');
244
+ assertSuccess(result);
245
+ });
246
+ });
247
+
248
+ describe('invalid prompts', () => {
249
+ it('rejects prompt with invalid status enum value', async () => {
250
+ fixture.writeFile('.planning/m1/prompts/bad-status.md', INVALID_PROMPT_BAD_STATUS);
251
+ const result = await validateFile(fixture,'.planning/m1/prompts/bad-status.md');
252
+ // Should fail or warn about invalid enum
253
+ expect(result.combined).toBeDefined();
254
+ });
255
+
256
+ it('rejects prompt missing required status field', async () => {
257
+ fixture.writeFile('.planning/m1/prompts/no-status.md', INVALID_PROMPT_MISSING_STATUS);
258
+ const result = await validateFile(fixture,'.planning/m1/prompts/no-status.md');
259
+ expect(result.combined).toBeDefined();
260
+ });
261
+
262
+ it('handles prompt without frontmatter', async () => {
263
+ fixture.writeFile('.planning/m1/prompts/no-fm.md', INVALID_PROMPT_NO_FRONTMATTER);
264
+ const result = await validateFile(fixture,'.planning/m1/prompts/no-fm.md');
265
+ // Should fail gracefully
266
+ expect(result.exitCode).toBeDefined();
267
+ });
268
+ });
269
+ });
270
+
271
+ // ─────────────────────────────────────────────────────────────────────────────
272
+ // Alignment Validation Tests
273
+ // ─────────────────────────────────────────────────────────────────────────────
274
+
275
+ describe('Alignment Validation E2E', () => {
276
+ let fixture: TestFixture;
277
+
278
+ beforeAll(() => {
279
+ fixture = createFixture({ name: 'alignment-validation-test' });
280
+ });
281
+
282
+ afterAll(() => {
283
+ fixture.cleanup();
284
+ });
285
+
286
+ describe('valid alignment docs', () => {
287
+ it('accepts alignment with required fields', async () => {
288
+ fixture.writeFile('.planning/m1/alignment.md', VALID_ALIGNMENT);
289
+ assertValidFrontmatter(fixture, '.planning/m1/alignment.md', ['spec_name', 'spec_path']);
290
+
291
+ const result = await validateFile(fixture,'.planning/m1/alignment.md');
292
+ assertSuccess(result);
293
+ });
294
+ });
295
+
296
+ describe('invalid alignment docs', () => {
297
+ it('rejects alignment missing spec field', async () => {
298
+ fixture.writeFile('.planning/m2/alignment.md', INVALID_ALIGNMENT_MISSING_SPEC);
299
+ const result = await validateFile(fixture,'.planning/m2/alignment.md');
300
+ expect(result.combined).toBeDefined();
301
+ });
302
+ });
303
+ });
304
+
305
+ // ─────────────────────────────────────────────────────────────────────────────
306
+ // Spec Validation Tests
307
+ // ─────────────────────────────────────────────────────────────────────────────
308
+
309
+ describe('Spec Validation E2E', () => {
310
+ let fixture: TestFixture;
311
+
312
+ beforeAll(() => {
313
+ fixture = createFixture({ name: 'spec-validation-test' });
314
+ });
315
+
316
+ afterAll(() => {
317
+ fixture.cleanup();
318
+ });
319
+
320
+ describe('valid specs', () => {
321
+ it('accepts spec with name and domain_name', async () => {
322
+ fixture.writeFile('specs/api.spec.md', VALID_SPEC);
323
+ assertValidFrontmatter(fixture, 'specs/api.spec.md', ['name', 'domain_name']);
324
+
325
+ const result = await validateFile(fixture,'specs/api.spec.md');
326
+ assertSuccess(result);
327
+ });
328
+ });
329
+
330
+ describe('invalid specs', () => {
331
+ it('rejects spec missing domain_name field', async () => {
332
+ fixture.writeFile('specs/incomplete.spec.md', INVALID_SPEC_MISSING_DOMAIN);
333
+ const result = await validateFile(fixture,'specs/incomplete.spec.md');
334
+ expect(result.combined).toBeDefined();
335
+ });
336
+ });
337
+ });
338
+
339
+ // ─────────────────────────────────────────────────────────────────────────────
340
+ // File Type Detection Tests
341
+ // ─────────────────────────────────────────────────────────────────────────────
342
+
343
+ describe('File Type Detection E2E', () => {
344
+ let fixture: TestFixture;
345
+
346
+ beforeAll(() => {
347
+ fixture = createFixture({ name: 'file-type-detection-test' });
348
+ });
349
+
350
+ afterAll(() => {
351
+ fixture.cleanup();
352
+ });
353
+
354
+ it('detects prompt files by path pattern', async () => {
355
+ fixture.writeFile('.planning/spec/prompts/01.md', VALID_PROMPT);
356
+ fixture.writeFile('.planning/spec/prompts/99.md', VALID_PROMPT);
357
+
358
+ const r1 = await validateFile(fixture,'.planning/spec/prompts/01.md');
359
+ const r2 = await validateFile(fixture,'.planning/spec/prompts/99.md');
360
+
361
+ assertSuccess(r1);
362
+ assertSuccess(r2);
363
+ });
364
+
365
+ it('detects alignment files by name', async () => {
366
+ fixture.writeFile('.planning/m1/alignment.md', VALID_ALIGNMENT);
367
+ const result = await validateFile(fixture,'.planning/m1/alignment.md');
368
+ assertSuccess(result);
369
+ });
370
+
371
+ it('detects spec files by .spec.md extension', async () => {
372
+ fixture.writeFile('specs/data.spec.md', VALID_SPEC);
373
+ const result = await validateFile(fixture,'specs/data.spec.md');
374
+ assertSuccess(result);
375
+ });
376
+
377
+ it('reports error for non-schema-managed files (no schema type)', async () => {
378
+ fixture.writeFile('README.md', '# README\n\nJust a readme.');
379
+ // CLI cannot determine schema type for README.md - this is expected
380
+ const result = await validateFile(fixture,'README.md');
381
+ // Should fail because schema type cannot be inferred
382
+ assertFailure(result);
383
+ expect(result.stderr || result.stdout).toContain('Could not determine schema type');
384
+ });
385
+ });
386
+
387
+ // ─────────────────────────────────────────────────────────────────────────────
388
+ // Batch Validation Tests
389
+ // ─────────────────────────────────────────────────────────────────────────────
390
+
391
+ describe('Batch Validation E2E', () => {
392
+ let fixture: TestFixture;
393
+
394
+ beforeAll(() => {
395
+ fixture = createFixture({
396
+ name: 'batch-validation-test',
397
+ files: {
398
+ '.planning/m1/alignment.md': VALID_ALIGNMENT,
399
+ '.planning/m1/prompts/01.md': VALID_PROMPT,
400
+ '.planning/m1/prompts/02.md': VALID_PROMPT_IN_PROGRESS,
401
+ '.planning/m1/prompts/03.md': VALID_PROMPT_COMPLETED,
402
+ 'specs/api.spec.md': VALID_SPEC,
403
+ },
404
+ });
405
+ });
406
+
407
+ afterAll(() => {
408
+ fixture.cleanup();
409
+ });
410
+
411
+ it('validates multiple files in sequence', async () => {
412
+ const files = [
413
+ '.planning/m1/alignment.md',
414
+ '.planning/m1/prompts/01.md',
415
+ '.planning/m1/prompts/02.md',
416
+ '.planning/m1/prompts/03.md',
417
+ 'specs/api.spec.md',
418
+ ];
419
+
420
+ for (const file of files) {
421
+ const result = await validateFile(fixture,file);
422
+ assertSuccess(result);
423
+ }
424
+ });
425
+ });
426
+
427
+ // ─────────────────────────────────────────────────────────────────────────────
428
+ // Edge Cases
429
+ // ─────────────────────────────────────────────────────────────────────────────
430
+
431
+ describe('Validation Edge Cases E2E', () => {
432
+ let fixture: TestFixture;
433
+
434
+ beforeAll(() => {
435
+ fixture = createFixture({ name: 'validation-edge-cases' });
436
+ });
437
+
438
+ afterAll(() => {
439
+ fixture.cleanup();
440
+ });
441
+
442
+ it('handles empty file', async () => {
443
+ fixture.writeFile('.planning/m1/prompts/empty.md', '');
444
+ const result = await validateFile(fixture,'.planning/m1/prompts/empty.md');
445
+ // Should handle gracefully
446
+ expect(result.exitCode).toBeDefined();
447
+ });
448
+
449
+ it('handles file with only frontmatter', async () => {
450
+ fixture.writeFile('.planning/m1/prompts/only-fm.md', `---
451
+ number: 1
452
+ title: Only Frontmatter
453
+ type: planned
454
+ planning_session: 1
455
+ status: pending
456
+ ---
457
+ `);
458
+ const result = await validateFile(fixture,'.planning/m1/prompts/only-fm.md');
459
+ // Frontmatter is valid but body sections may be missing - behavior depends on schema
460
+ expect(result.exitCode).toBeDefined();
461
+ });
462
+
463
+ it('handles malformed YAML in frontmatter', async () => {
464
+ fixture.writeFile('.planning/m1/prompts/bad-yaml.md', `---
465
+ number: 1
466
+ status: pending
467
+ bad indentation:
468
+ - this is wrong
469
+ ---
470
+
471
+ # Tasks
472
+
473
+ - Content
474
+
475
+ # Acceptance Criteria
476
+
477
+ - Criteria
478
+ `);
479
+ const result = await validateFile(fixture,'.planning/m1/prompts/bad-yaml.md');
480
+ // Should handle YAML parse error
481
+ expect(result.exitCode).toBeDefined();
482
+ });
483
+
484
+ it('handles unicode content', async () => {
485
+ fixture.writeFile('.planning/m1/prompts/unicode.md', `---
486
+ number: 1
487
+ title: Unicode Task
488
+ type: planned
489
+ planning_session: 1
490
+ status: pending
491
+ ---
492
+
493
+ # Tasks
494
+
495
+ - 日本語タスク
496
+ - 实现功能 🚀
497
+
498
+ # Acceptance Criteria
499
+
500
+ - Works with unicode
501
+ `);
502
+ const result = await validateFile(fixture,'.planning/m1/prompts/unicode.md');
503
+ assertSuccess(result);
504
+ });
505
+
506
+ it('handles very long frontmatter', async () => {
507
+ const longValue = 'a'.repeat(1000);
508
+ fixture.writeFile('.planning/m1/prompts/long-fm.md', `---
509
+ number: 1
510
+ title: ${longValue.substring(0, 50)}
511
+ type: planned
512
+ planning_session: 1
513
+ status: pending
514
+ description: ${longValue}
515
+ ---
516
+
517
+ # Tasks
518
+
519
+ - Task with long title
520
+
521
+ # Acceptance Criteria
522
+
523
+ - Handles long values
524
+ `);
525
+ const result = await validateFile(fixture,'.planning/m1/prompts/long-fm.md');
526
+ assertSuccess(result);
527
+ });
528
+ });