@caiqueoak/flow 0.7.0 → 0.8.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 (172) hide show
  1. package/README.md +65 -43
  2. package/dist/artifacts/backlog.d.mts +16 -0
  3. package/dist/artifacts/backlog.d.mts.map +1 -0
  4. package/dist/artifacts/backlog.mjs +193 -0
  5. package/dist/artifacts/backlog.mjs.map +1 -0
  6. package/dist/artifacts/document.d.mts +6 -0
  7. package/dist/artifacts/document.d.mts.map +1 -0
  8. package/dist/artifacts/document.mjs +39 -0
  9. package/dist/artifacts/document.mjs.map +1 -0
  10. package/dist/artifacts/engineering.d.mts +5 -0
  11. package/dist/artifacts/engineering.d.mts.map +1 -0
  12. package/dist/artifacts/engineering.mjs +27 -0
  13. package/dist/artifacts/engineering.mjs.map +1 -0
  14. package/dist/artifacts/gates.d.mts +7 -0
  15. package/dist/artifacts/gates.d.mts.map +1 -0
  16. package/dist/artifacts/gates.mjs +42 -0
  17. package/dist/artifacts/gates.mjs.map +1 -0
  18. package/dist/artifacts/implementation-plan.d.mts +11 -0
  19. package/dist/artifacts/implementation-plan.d.mts.map +1 -0
  20. package/dist/artifacts/implementation-plan.mjs +30 -0
  21. package/dist/artifacts/implementation-plan.mjs.map +1 -0
  22. package/dist/artifacts/prd.d.mts +4 -0
  23. package/dist/artifacts/prd.d.mts.map +1 -0
  24. package/dist/artifacts/prd.mjs +13 -0
  25. package/dist/artifacts/prd.mjs.map +1 -0
  26. package/dist/artifacts/review.d.mts +11 -0
  27. package/dist/artifacts/review.d.mts.map +1 -0
  28. package/dist/artifacts/review.mjs +27 -0
  29. package/dist/artifacts/review.mjs.map +1 -0
  30. package/dist/artifacts/spec.d.mts +14 -0
  31. package/dist/artifacts/spec.d.mts.map +1 -0
  32. package/dist/artifacts/spec.mjs +50 -0
  33. package/dist/artifacts/spec.mjs.map +1 -0
  34. package/dist/artifacts/state.d.mts +44 -0
  35. package/dist/artifacts/state.d.mts.map +1 -0
  36. package/dist/artifacts/state.mjs +60 -0
  37. package/dist/artifacts/state.mjs.map +1 -0
  38. package/dist/artifacts/tasks.d.mts +10 -0
  39. package/dist/artifacts/tasks.d.mts.map +1 -0
  40. package/dist/artifacts/tasks.mjs +107 -0
  41. package/dist/artifacts/tasks.mjs.map +1 -0
  42. package/dist/artifacts/work-items.d.mts +21 -0
  43. package/dist/artifacts/work-items.d.mts.map +1 -0
  44. package/dist/artifacts/work-items.mjs +81 -0
  45. package/dist/artifacts/work-items.mjs.map +1 -0
  46. package/dist/cli/command-registry.d.mts +498 -0
  47. package/dist/cli/command-registry.d.mts.map +1 -0
  48. package/dist/cli/command-registry.mjs +230 -0
  49. package/dist/cli/command-registry.mjs.map +1 -0
  50. package/dist/cli.d.mts +3 -0
  51. package/dist/cli.d.mts.map +1 -0
  52. package/dist/cli.mjs +48 -0
  53. package/dist/cli.mjs.map +1 -0
  54. package/dist/commands/doctor.d.mts +21 -0
  55. package/dist/commands/doctor.d.mts.map +1 -0
  56. package/dist/commands/doctor.mjs +79 -0
  57. package/dist/commands/doctor.mjs.map +1 -0
  58. package/dist/commands/gates.d.mts +14 -0
  59. package/dist/commands/gates.d.mts.map +1 -0
  60. package/dist/commands/gates.mjs +136 -0
  61. package/dist/commands/gates.mjs.map +1 -0
  62. package/dist/commands/graph.d.mts +11 -0
  63. package/dist/commands/graph.d.mts.map +1 -0
  64. package/dist/commands/graph.mjs +78 -0
  65. package/dist/commands/graph.mjs.map +1 -0
  66. package/dist/commands/init.d.mts +6 -0
  67. package/dist/commands/init.d.mts.map +1 -0
  68. package/dist/commands/init.mjs +126 -0
  69. package/dist/commands/init.mjs.map +1 -0
  70. package/dist/commands/migrate.d.mts +27 -0
  71. package/dist/commands/migrate.d.mts.map +1 -0
  72. package/dist/commands/migrate.mjs +379 -0
  73. package/dist/commands/migrate.mjs.map +1 -0
  74. package/dist/commands/operations.d.mts +13 -0
  75. package/dist/commands/operations.d.mts.map +1 -0
  76. package/dist/commands/operations.mjs +340 -0
  77. package/dist/commands/operations.mjs.map +1 -0
  78. package/dist/commands/route.d.mts +12 -0
  79. package/dist/commands/route.d.mts.map +1 -0
  80. package/dist/commands/route.mjs +45 -0
  81. package/dist/commands/route.mjs.map +1 -0
  82. package/dist/commands/schemas.d.mts +5 -0
  83. package/dist/commands/schemas.d.mts.map +1 -0
  84. package/dist/commands/schemas.mjs +14 -0
  85. package/dist/commands/schemas.mjs.map +1 -0
  86. package/dist/commands/status.d.mts +4 -0
  87. package/dist/commands/status.d.mts.map +1 -0
  88. package/dist/commands/status.mjs +18 -0
  89. package/dist/commands/status.mjs.map +1 -0
  90. package/dist/commands/sync.d.mts +18 -0
  91. package/dist/commands/sync.d.mts.map +1 -0
  92. package/dist/commands/sync.mjs +29 -0
  93. package/dist/commands/sync.mjs.map +1 -0
  94. package/dist/commands/trace.d.mts +30 -0
  95. package/dist/commands/trace.d.mts.map +1 -0
  96. package/dist/commands/trace.mjs +111 -0
  97. package/dist/commands/trace.mjs.map +1 -0
  98. package/dist/commands/validate.d.mts +8 -0
  99. package/dist/commands/validate.d.mts.map +1 -0
  100. package/dist/commands/validate.mjs +82 -0
  101. package/dist/commands/validate.mjs.map +1 -0
  102. package/dist/domain/contracts.d.mts +203 -0
  103. package/dist/domain/contracts.d.mts.map +1 -0
  104. package/dist/domain/contracts.mjs +126 -0
  105. package/dist/domain/contracts.mjs.map +1 -0
  106. package/dist/domain/types.d.ts +45 -0
  107. package/dist/domain/types.d.ts.map +1 -0
  108. package/dist/domain/types.js +2 -0
  109. package/dist/domain/types.js.map +1 -0
  110. package/dist/entry.d.ts +3 -0
  111. package/dist/entry.d.ts.map +1 -0
  112. package/dist/entry.js +4 -0
  113. package/dist/entry.js.map +1 -0
  114. package/dist/shared/cli-io.d.mts +15 -0
  115. package/dist/shared/cli-io.d.mts.map +1 -0
  116. package/dist/shared/cli-io.mjs +83 -0
  117. package/dist/shared/cli-io.mjs.map +1 -0
  118. package/dist/shared/profiles.d.mts +17 -0
  119. package/dist/shared/profiles.d.mts.map +1 -0
  120. package/dist/shared/profiles.mjs +25 -0
  121. package/dist/shared/profiles.mjs.map +1 -0
  122. package/dist/shared/project-config.d.mts +21 -0
  123. package/dist/shared/project-config.d.mts.map +1 -0
  124. package/dist/shared/project-config.mjs +41 -0
  125. package/dist/shared/project-config.mjs.map +1 -0
  126. package/dist/shared/project-path.d.mts +3 -0
  127. package/dist/shared/project-path.d.mts.map +1 -0
  128. package/dist/shared/project-path.mjs +9 -0
  129. package/dist/shared/project-path.mjs.map +1 -0
  130. package/dist/shared/skill-installer.d.mts +2 -0
  131. package/dist/shared/skill-installer.d.mts.map +1 -0
  132. package/dist/shared/skill-installer.mjs +33 -0
  133. package/dist/shared/skill-installer.mjs.map +1 -0
  134. package/package.json +16 -8
  135. package/schemas/backlog.schema.json +85 -0
  136. package/schemas/config.schema.json +29 -0
  137. package/schemas/gates.schema.json +17 -0
  138. package/schemas/review.schema.json +28 -0
  139. package/schemas/tasks.schema.json +66 -0
  140. package/skills/flow/SKILL.md +10 -11
  141. package/skills/flow/build/step-01-execute-task.md +2 -2
  142. package/skills/flow/discovery/bmad-comparison.md +5 -0
  143. package/skills/flow/discovery/step-01-project.md +8 -3
  144. package/skills/flow/engineering/profiles/readability-first.md +1 -0
  145. package/skills/flow/engineering/step-02-synthesize.md +1 -1
  146. package/skills/flow/invariants.md +4 -4
  147. package/skills/flow/planning/step-01-create-tasks.md +3 -0
  148. package/skills/flow/planning/step-01-plan-work-item.md +2 -2
  149. package/skills/flow/review/step-01-review-work-item.md +1 -1
  150. package/skills/flow/specification/step-01-deepen-spec.md +7 -0
  151. package/src/artifacts/backlog.mjs +0 -157
  152. package/src/artifacts/document.mjs +0 -30
  153. package/src/artifacts/engineering.mjs +0 -26
  154. package/src/artifacts/gates.mjs +0 -28
  155. package/src/artifacts/implementation-plan.mjs +0 -27
  156. package/src/artifacts/prd.mjs +0 -12
  157. package/src/artifacts/state.mjs +0 -63
  158. package/src/artifacts/tasks.mjs +0 -90
  159. package/src/cli.mjs +0 -62
  160. package/src/commands/gates.mjs +0 -71
  161. package/src/commands/graph.mjs +0 -92
  162. package/src/commands/init.mjs +0 -111
  163. package/src/commands/migrate.mjs +0 -224
  164. package/src/commands/route.mjs +0 -140
  165. package/src/commands/status.mjs +0 -35
  166. package/src/commands/trace.mjs +0 -58
  167. package/src/commands/validate.mjs +0 -197
  168. package/src/shared/cli-io.mjs +0 -86
  169. package/src/shared/profiles.mjs +0 -27
  170. package/src/shared/project-config.mjs +0 -39
  171. package/src/shared/project-path.mjs +0 -10
  172. package/src/shared/skill-installer.mjs +0 -34
package/README.md CHANGED
@@ -1,75 +1,97 @@
1
1
  # Flow
2
2
 
3
- Repository-resumable software delivery with deterministic workflow checks and explicit human approval.
3
+ ## Canonical work-items
4
4
 
5
- ## Install and use
5
+ Each `_flow/work-items/W###-*/` directory is the sole source of truth. Creating a work-item writes versionable shells for `spec.md`, `tasks.yaml`, `implementation-plan.md`, and `review.yaml`. A spec may remain `outlined`; tasks require a `ready` spec and implementation requires an approved plan.
6
+
7
+ Run `flow sync` to materialize `_flow/generated/backlog.yaml` and `_flow/generated/graph.md`. Sync only reads canonical work-items and only writes `_flow/generated/`; it never alters a canonical source. Generated files are disposable and ignored by Git.
8
+
9
+ Complete a task with one commit whose exact subject is `type(domain): description [W###-T###]` and whose body contains matching `Flow-Work-Item` and `Flow-Task` trailers. Complete review with `flow work-item review-complete W### --domain domain`, which creates `chore(domain): complete review [W###]`. The review commit may contain only that item's `spec.md` and `review.yaml`; a deliberate review-time `spec.md` amendment belongs in the same commit.
10
+
11
+ CLI-first, repository-resumable delivery for coding agents. Flow keeps deterministic state, IDs, dependency routing, approvals, Git evidence, gates and migrations in the CLI while the agent owns product and engineering judgment.
12
+
13
+ ## Install
6
14
 
7
15
  ```bash
8
16
  npm install --save-dev @caiqueoak/flow
9
17
  npx --no-install flow init --runtime codex
18
+ npx --no-install flow doctor --quick --json
10
19
  ```
11
20
 
12
- Invoke `/flow` to start or continue. The agent routes from repository state, reads the returned instruction/context, executes one step, persists artifacts, validates and routes again. Consequential decisions require explicit human input; status updates alone are not terminal stops.
21
+ The project records the Flow package version that initialized or explicitly updated its artifacts. Flow never checks npm or upgrades a project automatically.
13
22
 
14
- ## Engineering preferences
23
+ ## Workflow
15
24
 
16
- The single built-in template is **Readability First**, ID `flow/readability-first@1`. It covers Clean Code, SOLID, mandatory SRP, semantic naming, low coupling, high cohesion, vertical slices, modular ownership, locality and complexity justified by demonstrable value.
25
+ `doctor quick discovery PRD engineering outlined backlog selected eligible item ready spec tasks and plan approval implementation gates implementation commit evidence persistence → review`
17
26
 
18
- The agent-readable template ships with the npm package and is installed with the runtime skill. It is loaded when generating or explicitly revising engineering, not on every task. The approved `.flow/docs/engineering.md` is the project engineering source of truth and must be read in full before planning, implementation and review. Package/profile updates never silently change that contract.
27
+ The backlog contains every known work-item and its DAG, but deep specs are created on demand. `spec_maturity: outlined|ready` is independent of `state: pending|in_progress|completed`. Eligibility is derived from completed dependencies plus resolved external/decision blockers; then routing uses lower priority number and lower numeric ID.
19
28
 
20
- For existing code, `--existing-code improve` (**Improve existing structure**) treats current style as evidence, not authority; `preserve` (**Keep existing structure**) gives consistent conventions stronger weight. Both preserve behavior and external contracts; neither authorizes automatic refactoring. New projects use `not_applicable` when no meaningful code exists.
29
+ Generated `backlog.yaml` and `graph.md` are disposable projections under `_flow/generated/`. Product truth lives in `docs/prd.md`, technical truth in `docs/engineering.md`, and work-item maturity/DAG in canonical work-item specs.
21
30
 
22
- ## Lifecycle and approval
31
+ ## CLI
23
32
 
24
- Discovery PRD approval engineering approval complete backlog planning implementation-plan approval serial implementation review.
33
+ Run `flow --help` or `flow <command> --help`. Help and parsing share one declarative command registry, so unknown flags and invalid combinations are rejected before writes.
25
34
 
26
- After product and engineering are approved, create every known work item's directory, `spec.md` and `tasks.yaml` before implementation. Then draft a concrete `implementation-plan.md` per selected work item and request human validation. It identifies exact paths, symbols/contracts, ordered changes, task mapping, engineering compliance, tests, risks, rollback and exclusions. Approval is tied to SHA256 revisions of the exact engineering and spec documents; stale plans return to drafting.
35
+ Core read operations:
27
36
 
28
- PRD, engineering and plans use YAML frontmatter with `schema_version: 1`, `status: draft|approved`, and `approved_at` when approved. Engineering records baseline profile and existing-code policy. Plans record work_item, engineering_revision and spec_revision. Completed work retains its historical approval; later outcome records or engineering changes do not retroactively invalidate completed delivery.
37
+ ```bash
38
+ flow doctor --quick --json
39
+ flow status
40
+ flow route --json
41
+ flow validate [--work-item W015] [--gates]
42
+ flow trace W015-T003
43
+ flow gates list|run [--id ID|--task W015-T003|--work-item W015|--stage task|work-item-review|full|--all]
44
+ ```
29
45
 
30
- ## Canonical artifacts
46
+ Structured writes:
31
47
 
32
- - `config.yaml`: runtime/bootstrap preferences; installed package metadata owns version.
33
- - `docs/prd.md`: global, cross-work-item product truth and learner-visible constraints; `docs/engineering.md`: approved global technical/code/infra truth.
34
- - `backlog.yaml`: schema 2, W### IDs, W###-kebab-case folders, kinds, priority, dependency DAG and lifecycle.
35
- - `work-items/W###-slug/spec.md`: bounded scope, delivery decisions, and acceptance for one work item; it references applicable PRD rules without redefining them. `tasks.yaml`: schema 1, work_item, local T### task DAG.
36
- - `implementation-plan.md`: human-approved implementation approach.
37
- - `state.yaml`: resume cursor and migration reconciliation status.
38
- - `gates.yaml`: schema 1, command/builtin checks only; qualitative judgment remains review instructions.
39
- - `docs/graph.md`: deterministic derived projection; regenerate rather than hand-edit.
48
+ ```bash
49
+ flow work-item create --title "Customer search" --priority 2
50
+ flow work-item dependencies W015 --depends-on W003,W009
51
+ flow work-item blocker-add W015 --id vendor-approval --type external_action --description "Vendor approval"
52
+ flow work-item blocker-resolve W015 --id vendor-approval
53
+ flow work-item promote W015
54
+ flow task create W015 --title "Add query contract"
55
+ flow task start W015-T001
56
+ flow scope validate W015-T001 --files src/query.js,test/query.test.js
57
+ flow task commit W015-T001 --message "feat(search): add customer query [W015-T001]" --files src/query.js,test/query.test.js
58
+ flow approval record _flow/work-items/W015-customer-search/implementation-plan.md
59
+ ```
40
60
 
41
- Persist only pending, in_progress and completed. Ready/Blocked are derived exclusively from work-item dependency edges. Blockers use `{id, type: external_action|consequential_decision, description, status: unresolved|resolved}` as context for the agent to address within the work item; they do not change execution status. Only one mutating work item/task may be active across the project. Read-only analysis may be parallel; automatic concurrent worktrees are out of scope.
61
+ ## Git traceability
42
62
 
43
- ## CLI
63
+ `W###-T###` is permanent task identity. A repository-mutating task creates exactly one coherent implementation commit. Its objective message contains the task ID for human visibility and its body contains the canonical machine evidence:
44
64
 
45
- All commands use the local installation:
65
+ ```text
66
+ Flow-Work-Item: W015
67
+ Flow-Task: W015-T003
68
+ ```
46
69
 
47
- | Command | Purpose |
48
- | ---------------------------------------- | --------------------------------------------------------------------------- |
49
- | `npx --no-install flow init` | Configure or add/refresh runtime integrations. |
50
- | `npx --no-install flow migrate` | Atomic structural migration, followed by semantic reconciliation via /flow. |
51
- | `npx --no-install flow status` | Progress and dependency/external blockers. |
52
- | `npx --no-install flow validate` | Fast artifact integrity, approvals, DAGs and traceability checks. |
53
- | `npx --no-install flow validate --gates` | Full validation, including configured deterministic project gates. |
54
- | `npx --no-install flow route --json` | Next legal step and required context. |
55
- | `npx --no-install flow graph` | Regenerate dependency graph. |
56
- | `npx --no-install flow trace W015-T003` | Resolve a task's implementation commit. |
70
+ `flow trace W015-T003` resolves a unique reachable commit only when its subject and both trailers agree. SHA evidence is never stored in tasks.yaml. `flow trace W015` aggregates reachable implementation commits by `Flow-Work-Item`, including task, SHA, title and changed files.
57
71
 
58
- Use `--help` for options; `--path` selects a project. Existing managed projects cannot change engineering through init; use /flow and approval. Older config is refused without mutation and must be migrated first. Update with your package manager, then rerun init to refresh integrations; there is no separate update/config/gates workflow command.
72
+ ## Gates and performance
59
73
 
60
- ## Git and migration
74
+ `flow validate` performs cheap structural checks and does not run the project test suite. `--gates` is explicit. Gates declare stage (`task`, `work-item-review`, `full`), expected cost and optional task/work-item scope. JSON output includes duration, process and Git-read metrics. Engineering maps changed paths/contracts to the smallest safe test scope and falls back to broader checks when impact is unknown.
61
75
 
62
- New completed code tasks have exactly one HEAD-reachable implementation commit with both trailers:
76
+ ## Migration
63
77
 
64
- ```text
65
- Flow-Work-Item: W015
66
- Flow-Task: W015-T003
78
+ ```bash
79
+ flow doctor
80
+ flow migrate --plan --json
81
+ flow migrate --apply
67
82
  ```
68
83
 
69
- Non-code tasks use implementation: none. SHA is derived, not canonical task identity. Pre-commit verification uses `validate --pre-commit W015-T003`; normal validation checks the integrated commit. Avoid squashing task commits when preserving task traceability.
84
+ Planning is read-only. Apply rechecks preconditions, transforms a staging copy, validates it, swaps only on success and preserves the prior `_flow` under `_flow-backups`. Structural migration never invents semantic decisions; ambiguous legacy truths route to assisted reconcile.
70
85
 
71
- Migration stages transformations before swapping artifacts, rejects collisions/invalid DAGs before mutation, preserves legacy documents and commit evidence, normalizes qualified task IDs/dependencies, and routes first to semantic reconciliation. Completed migrated tasks use implementation: legacy and optional legacy_commit; they do not require invented Git trailers or rewritten historical spec headings. Pending legacy folders may be absent during reconciliation, but complete backlog planning must materialize them before native implementation. Private project artifacts are not committed as fixtures.
86
+ ## Development
72
87
 
73
- ## Releases
88
+ ```bash
89
+ npm run typecheck
90
+ npm run lint
91
+ npm run format:check
92
+ npm test
93
+ npm run test:package
94
+ npm run pack:check
95
+ ```
74
96
 
75
- Merges to main are released automatically after the test matrix passes. Conventional Commit PR titles drive semantic-release. Installed package metadata is the Flow version source of truth; project config does not duplicate it.
97
+ The npm binary points at ESM build output. Runtime sources remain JavaScript in this staged packaging migration and are not strict TypeScript-checked; a full source conversion is intentionally separate. The published package contains compiled source, skills and generated JSON Schemas.
@@ -0,0 +1,16 @@
1
+ export declare class ArtifactValidationError extends Error {
2
+ constructor(message: any);
3
+ }
4
+ export declare function parseBacklog(text: any, { source }?: {
5
+ source?: string | undefined;
6
+ }): {
7
+ schema_version: number;
8
+ work_items: any;
9
+ };
10
+ export declare function validateAcyclic(items: any): void;
11
+ export declare function deriveExecutionStatus(item: any, byId: any): {
12
+ status: string;
13
+ reasons: any[];
14
+ };
15
+ export declare function topologicalOrder(items: any): any[];
16
+ //# sourceMappingURL=backlog.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backlog.d.mts","sourceRoot":"","sources":["../../src/artifacts/backlog.mjs"],"names":[],"mappings":"AAQA,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAO,KAAA,EAGlB;CACF;AAsBD,wBAAgB,YAAY,CAAC,IAAI,KAAA,EAAE,EAAE,MAAuB,EAAE;;CAAK;;;EAwFlE;AAED,wBAAgB,eAAe,CAAC,KAAK,KAAA,QAgBpC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,KAAA,EAAE,IAAI,KAAA;;;EAU/C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,KAAA,SA6BrC"}
@@ -0,0 +1,193 @@
1
+ import { parseDocument } from 'yaml';
2
+ import { BACKLOG_SCHEMA_VERSION, LIFECYCLE_STATES, SPEC_MATURITIES, WORK_ITEM_ID as WORK_ITEM_ID_PATTERN } from '../domain/contracts.mjs';
3
+ export class ArtifactValidationError extends Error {
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = 'ArtifactValidationError';
7
+ }
8
+ }
9
+ const KINDS = new Set(['feature', 'technical', 'maintenance']);
10
+ const STATES = new Set(LIFECYCLE_STATES);
11
+ const SPEC_MATURITY = new Set(SPEC_MATURITIES);
12
+ const WORK_ITEM_ID = WORK_ITEM_ID_PATTERN;
13
+ const WORK_ITEM_FOLDER = /^W\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/;
14
+ function fail(message) {
15
+ throw new ArtifactValidationError(message);
16
+ }
17
+ function requireObject(value, label) {
18
+ if (!value || typeof value !== 'object' || Array.isArray(value))
19
+ fail(`${label} must be a mapping.`);
20
+ return value;
21
+ }
22
+ function requireString(value, label) {
23
+ if (typeof value !== 'string' || !value.trim())
24
+ fail(`${label} must be a non-empty string.`);
25
+ return value.trim();
26
+ }
27
+ export function parseBacklog(text, { source = 'backlog.yaml' } = {}) {
28
+ const document = parseDocument(text, { prettyErrors: false, uniqueKeys: true });
29
+ if (document.errors.length)
30
+ fail(`${source} is invalid: ${document.errors[0].message}`);
31
+ const backlog = requireObject(document.toJS(), source);
32
+ if (backlog.schema_version !== BACKLOG_SCHEMA_VERSION)
33
+ fail(`${source} schema_version must be ${BACKLOG_SCHEMA_VERSION}.`);
34
+ if (!Array.isArray(backlog.work_items))
35
+ fail(`${source} work_items must be a list.`);
36
+ const ids = new Set();
37
+ const items = backlog.work_items.map((raw, index) => {
38
+ const label = `work_items[${index}]`;
39
+ const item = requireObject(raw, label);
40
+ const id = requireString(item.id, `${label}.id`);
41
+ if (!WORK_ITEM_ID.test(id))
42
+ fail(`${label}.id must use W followed by a zero-padded numeric sequence, e.g. W015.`);
43
+ if (ids.has(id))
44
+ fail(`${source} contains duplicate work-item ID '${id}'.`);
45
+ ids.add(id);
46
+ const folder = requireString(item.folder ?? item.path, `${label}.folder`);
47
+ if (!WORK_ITEM_FOLDER.test(folder))
48
+ fail(`${label}.folder must use W###-kebab-case, e.g. W015-learner-web-application.`);
49
+ const numericId = id.slice(1);
50
+ if (!folder.startsWith(`W${numericId}-`))
51
+ fail(`${label}.folder must preserve the numeric sequence from ${id}.`);
52
+ if (!KINDS.has(item.kind))
53
+ fail(`${label}.kind must be feature, technical, or maintenance.`);
54
+ const title = requireString(item.title, `${label}.title`);
55
+ const state = item.state ?? item.status;
56
+ if (!STATES.has(state))
57
+ fail(`${label}.state must be pending, in_progress, or completed.`);
58
+ if (!Number.isInteger(item.priority) || item.priority < 1)
59
+ fail(`${label}.priority must be a positive integer.`);
60
+ const specMaturity = item.spec_maturity ?? (item.state === 'pending' ? 'outlined' : 'ready');
61
+ if (!SPEC_MATURITY.has(specMaturity))
62
+ fail(`${label}.spec_maturity must be outlined or ready.`);
63
+ if (state !== 'pending' && specMaturity !== 'ready')
64
+ fail(`${id}: in_progress or completed work must have spec_maturity ready.`);
65
+ if (!Array.isArray(item.depends_on ?? []))
66
+ fail(`${label}.depends_on must be a list.`);
67
+ if (!Array.isArray(item.blockers ?? []))
68
+ fail(`${label}.blockers must be a list when present.`);
69
+ const dependencies = [];
70
+ const seenDependencies = new Set();
71
+ for (const rawDependency of item.depends_on ?? []) {
72
+ const dependency = requireString(rawDependency, `${label}.depends_on entry`);
73
+ if (!WORK_ITEM_ID.test(dependency))
74
+ fail(`${label}.depends_on contains invalid work-item ID '${dependency}'.`);
75
+ if (dependency === id)
76
+ fail(`Work item '${id}' cannot depend on itself.`);
77
+ if (seenDependencies.has(dependency))
78
+ fail(`Work item '${id}' lists dependency '${dependency}' more than once.`);
79
+ seenDependencies.add(dependency);
80
+ dependencies.push(dependency);
81
+ }
82
+ return {
83
+ id,
84
+ folder,
85
+ kind: item.kind,
86
+ title,
87
+ state,
88
+ priority: item.priority,
89
+ spec_maturity: specMaturity,
90
+ depends_on: dependencies,
91
+ blockers: (item.blockers ?? []).map((blocker) => {
92
+ requireObject(blocker, `${id} blocker`);
93
+ if (!/^[a-z][a-z0-9-]*$/.test(blocker.id ?? ''))
94
+ fail(`${id} blocker.id must be stable kebab-case.`);
95
+ if (!['external_action', 'consequential_decision'].includes(blocker.type))
96
+ fail(`${id} blocker.type is invalid.`);
97
+ requireString(blocker.description, `${id} blocker.description`);
98
+ if (!['unresolved', 'resolved'].includes(blocker.status))
99
+ fail(`${id} blocker.status is invalid.`);
100
+ return blocker;
101
+ }),
102
+ ...(item.objective ? { objective: requireString(item.objective, `${label}.objective`) } : {}),
103
+ boundaries: Array.isArray(item.boundaries) ? item.boundaries : [],
104
+ requirements: Array.isArray(item.requirements) ? item.requirements : [],
105
+ provides: Array.isArray(item.provides) ? item.provides : [],
106
+ consumes: Array.isArray(item.consumes) ? item.consumes : [],
107
+ dependency_rationale: item.dependency_rationale &&
108
+ typeof item.dependency_rationale === 'object' &&
109
+ !Array.isArray(item.dependency_rationale)
110
+ ? item.dependency_rationale
111
+ : {}
112
+ };
113
+ });
114
+ const byId = new Map(items.map((item) => [item.id, item]));
115
+ for (const item of items) {
116
+ for (const dependency of item.depends_on) {
117
+ if (!byId.has(dependency))
118
+ fail(`Work item '${item.id}' depends on unknown work item '${dependency}'.`);
119
+ }
120
+ }
121
+ validateAcyclic(items);
122
+ if (items.filter((item) => item.state === 'in_progress').length > 1)
123
+ fail('Only one mutating work item may be in_progress.');
124
+ return { schema_version: BACKLOG_SCHEMA_VERSION, work_items: items };
125
+ }
126
+ export function validateAcyclic(items) {
127
+ const indegree = new Map(items.map((item) => [item.id, item.depends_on.length]));
128
+ const dependents = new Map(items.map((item) => [item.id, []]));
129
+ for (const item of items)
130
+ for (const dependency of item.depends_on)
131
+ dependents.get(dependency).push(item.id);
132
+ const queue = items.filter((item) => indegree.get(item.id) === 0).map((item) => item.id);
133
+ let visited = 0;
134
+ while (queue.length) {
135
+ const id = queue.shift();
136
+ visited += 1;
137
+ for (const dependent of dependents.get(id)) {
138
+ const next = indegree.get(dependent) - 1;
139
+ indegree.set(dependent, next);
140
+ if (next === 0)
141
+ queue.push(dependent);
142
+ }
143
+ }
144
+ if (visited !== items.length)
145
+ fail('backlog.yaml work-item dependencies contain a cycle.');
146
+ }
147
+ export function deriveExecutionStatus(item, byId) {
148
+ if (item.state === 'completed')
149
+ return { status: 'completed', reasons: [] };
150
+ const incompleteDependencies = item.depends_on.filter((id) => byId.get(id)?.state !== 'completed');
151
+ const unresolvedBlockers = item.blockers.filter((blocker) => blocker.status === 'unresolved');
152
+ const reasons = [
153
+ ...incompleteDependencies.map((id) => ({ type: 'dependency', ref: id })),
154
+ ...unresolvedBlockers.map((blocker) => ({ type: 'blocker', ref: blocker.id, blocker_type: blocker.type }))
155
+ ];
156
+ if (reasons.length)
157
+ return { status: 'blocked', reasons };
158
+ return { status: item.state === 'in_progress' ? 'in_progress' : 'eligible', reasons: [] };
159
+ }
160
+ export function topologicalOrder(items) {
161
+ const byId = new Map(items.map((item) => [item.id, item]));
162
+ const remaining = new Map(items.map((item) => [item.id, item.depends_on.length]));
163
+ const dependents = new Map(items.map((item) => [item.id, []]));
164
+ for (const item of items)
165
+ for (const dependency of item.depends_on)
166
+ dependents.get(dependency).push(item.id);
167
+ const compare = (a, b) => a.localeCompare(b);
168
+ for (const ids of dependents.values())
169
+ ids.sort(compare);
170
+ const ready = items
171
+ .filter((item) => item.depends_on.length === 0)
172
+ .map((item) => item.id)
173
+ .sort(compare);
174
+ const levels = new Map(ready.map((id) => [id, 0]));
175
+ const orderedIds = [];
176
+ while (ready.length) {
177
+ const id = ready.shift();
178
+ orderedIds.push(id);
179
+ for (const dependent of dependents.get(id)) {
180
+ levels.set(dependent, Math.max(levels.get(dependent) ?? 0, (levels.get(id) ?? 0) + 1));
181
+ const count = remaining.get(dependent) - 1;
182
+ remaining.set(dependent, count);
183
+ if (count === 0) {
184
+ ready.push(dependent);
185
+ ready.sort(compare);
186
+ }
187
+ }
188
+ }
189
+ return orderedIds
190
+ .map((id) => byId.get(id))
191
+ .sort((a, b) => levels.get(a.id) - levels.get(b.id) || compare(a.id, b.id));
192
+ }
193
+ //# sourceMappingURL=backlog.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backlog.mjs","sourceRoot":"","sources":["../../src/artifacts/backlog.mjs"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function documentRevision(text: any): any;
2
+ export declare function documentMetadata(text: any): any;
3
+ export declare function validateDocument(text: any, headings: any): {
4
+ errors: any[];
5
+ };
6
+ //# sourceMappingURL=document.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.mts","sourceRoot":"","sources":["../../src/artifacts/document.mjs"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,IAAI,KAAA,OAEpC;AACD,wBAAgB,gBAAgB,CAAC,IAAI,KAAA,OAQpC;AACD,wBAAgB,gBAAgB,CAAC,IAAI,KAAA,EAAE,QAAQ,KAAA;;EAe9C"}
@@ -0,0 +1,39 @@
1
+ import { parseDocument } from 'yaml';
2
+ import { createHash } from 'node:crypto';
3
+ export function documentRevision(text) {
4
+ return createHash('sha256').update(text).digest('hex');
5
+ }
6
+ export function documentMetadata(text) {
7
+ const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
8
+ if (!match)
9
+ throw new Error('Missing YAML frontmatter.');
10
+ const doc = parseDocument(match[1], { uniqueKeys: true });
11
+ if (doc.errors.length)
12
+ throw new Error(doc.errors[0].message);
13
+ const value = doc.toJS();
14
+ if (!value || typeof value !== 'object' || Array.isArray(value))
15
+ throw new Error('Frontmatter must be a mapping.');
16
+ return value;
17
+ }
18
+ export function validateDocument(text, headings) {
19
+ let metadata = {};
20
+ const errors = [];
21
+ try {
22
+ metadata = documentMetadata(text);
23
+ }
24
+ catch (error) {
25
+ errors.push(error.message);
26
+ }
27
+ if (metadata.schema_version !== 1)
28
+ errors.push('schema_version must be 1.');
29
+ if (!['draft', 'approved'].includes(metadata.status))
30
+ errors.push('status must be draft or approved.');
31
+ if (metadata.status === 'approved' && (!metadata.approved_at || Number.isNaN(Date.parse(metadata.approved_at))))
32
+ errors.push('approved_at must record the human approval timestamp.');
33
+ const actual = new Set(text.split(/\r?\n/).filter((line) => /^#{1,2} /.test(line)));
34
+ for (const heading of headings)
35
+ if (!actual.has(heading))
36
+ errors.push(`Missing ${heading}.`);
37
+ return { ...metadata, errors };
38
+ }
39
+ //# sourceMappingURL=document.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.mjs","sourceRoot":"","sources":["../../src/artifacts/document.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,MAAM,UAAU,gBAAgB,CAAC,IAAI;IACnC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,IAAI;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACnE,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACnH,OAAO,KAAK,CAAC;AACf,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,IAAI,EAAE,QAAQ;IAC7C,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,QAAQ,CAAC,cAAc,KAAK,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC5E,IAAI,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACvG,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QAC7G,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpF,KAAK,MAAM,OAAO,IAAI,QAAQ;QAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,WAAW,OAAO,GAAG,CAAC,CAAC;IAC7F,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const ENGINEERING_HEADINGS: string[];
2
+ export declare function validateEngineeringDocument(text: any): {
3
+ errors: any[];
4
+ };
5
+ //# sourceMappingURL=engineering.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineering.d.mts","sourceRoot":"","sources":["../../src/artifacts/engineering.mjs"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,UAehC,CAAC;AACF,wBAAgB,2BAA2B,CAAC,IAAI,KAAA;;EAO/C"}
@@ -0,0 +1,27 @@
1
+ import { validateDocument } from './document.mjs';
2
+ import { READABILITY_FIRST_PROFILE } from '../shared/profiles.mjs';
3
+ export const ENGINEERING_HEADINGS = [
4
+ '# Engineering',
5
+ '## System shape',
6
+ '## Modules and ownership',
7
+ '## Dependency direction and boundaries',
8
+ '## Vertical slices and code organization',
9
+ '## Naming and readability conventions',
10
+ '## Data ownership and persistence',
11
+ '## Error handling',
12
+ '## Testing and verification',
13
+ '## Dependencies and external services',
14
+ '## Security and operations',
15
+ '## Deterministic gates',
16
+ '## Deferred complexity',
17
+ '## Exceptions'
18
+ ];
19
+ export function validateEngineeringDocument(text) {
20
+ const result = validateDocument(text, ENGINEERING_HEADINGS);
21
+ if (result.baseline?.profile !== READABILITY_FIRST_PROFILE.id)
22
+ result.errors.push('baseline.profile must be flow/readability-first@1.');
23
+ if (!['improve', 'preserve', 'not_applicable'].includes(result.baseline?.existing_code_policy))
24
+ result.errors.push('baseline.existing_code_policy is invalid.');
25
+ return result;
26
+ }
27
+ //# sourceMappingURL=engineering.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineering.mjs","sourceRoot":"","sources":["../../src/artifacts/engineering.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,eAAe;IACf,iBAAiB;IACjB,0BAA0B;IAC1B,wCAAwC;IACxC,0CAA0C;IAC1C,uCAAuC;IACvC,mCAAmC;IACnC,mBAAmB;IACnB,6BAA6B;IAC7B,uCAAuC;IACvC,4BAA4B;IAC5B,wBAAwB;IACxB,wBAAwB;IACxB,eAAe;CAChB,CAAC;AACF,MAAM,UAAU,2BAA2B,CAAC,IAAI;IAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC5D,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,KAAK,yBAAyB,CAAC,EAAE;QAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IAC3E,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,oBAAoB,CAAC;QAC5F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function parseGates(text: any, { source }?: {
2
+ source?: string | undefined;
3
+ }): {
4
+ schema_version: number;
5
+ gates: any;
6
+ };
7
+ //# sourceMappingURL=gates.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.d.mts","sourceRoot":"","sources":["../../src/artifacts/gates.mjs"],"names":[],"mappings":"AAMA,wBAAgB,UAAU,CAAC,IAAI,KAAA,EAAE,EAAE,MAAqB,EAAE;;CAAK;;;EAgC9D"}
@@ -0,0 +1,42 @@
1
+ import { parseDocument } from 'yaml';
2
+ import { ArtifactValidationError } from './backlog.mjs';
3
+ import { GATES_SCHEMA_VERSION } from '../domain/contracts.mjs';
4
+ const KINDS = new Set(['command', 'builtin']);
5
+ export function parseGates(text, { source = 'gates.yaml' } = {}) {
6
+ const document = parseDocument(text, { prettyErrors: false, uniqueKeys: true });
7
+ if (document.errors.length)
8
+ throw new ArtifactValidationError(`${source} is invalid: ${document.errors[0].message}`);
9
+ const value = document.toJS();
10
+ if (!value || typeof value !== 'object' || Array.isArray(value))
11
+ throw new ArtifactValidationError(`${source} must be a mapping.`);
12
+ if (value.schema_version !== GATES_SCHEMA_VERSION)
13
+ throw new ArtifactValidationError(`${source} schema_version must be ${GATES_SCHEMA_VERSION}.`);
14
+ if (!Array.isArray(value.gates))
15
+ throw new ArtifactValidationError(`${source} gates must be a list.`);
16
+ const ids = new Set();
17
+ const gates = value.gates.map((gate, index) => {
18
+ if (!gate || typeof gate !== 'object' || Array.isArray(gate))
19
+ throw new ArtifactValidationError(`gates[${index}] must be a mapping.`);
20
+ if (typeof gate.id !== 'string' || !/^[a-z][a-z0-9-]*$/.test(gate.id))
21
+ throw new ArtifactValidationError(`gates[${index}].id must be lower kebab-case.`);
22
+ if (ids.has(gate.id))
23
+ throw new ArtifactValidationError(`duplicate gate '${gate.id}'.`);
24
+ ids.add(gate.id);
25
+ if (!KINDS.has(gate.kind))
26
+ throw new ArtifactValidationError(`${gate.id}.kind must be command or builtin.`);
27
+ if (gate.kind === 'command' && (!gate.command || typeof gate.command !== 'string'))
28
+ throw new ArtifactValidationError(`${gate.id} command gate requires command.`);
29
+ const stage = gate.stage ?? 'full';
30
+ if (!['task', 'work-item-review', 'full'].includes(stage))
31
+ throw new ArtifactValidationError(`${gate.id}.stage must be task, work-item-review or full.`);
32
+ const cost = gate.cost ?? 'medium';
33
+ if (!['low', 'medium', 'high'].includes(cost))
34
+ throw new ArtifactValidationError(`${gate.id}.cost must be low, medium or high.`);
35
+ const scope = gate.scope ?? {};
36
+ if (!scope || typeof scope !== 'object' || Array.isArray(scope))
37
+ throw new ArtifactValidationError(`${gate.id}.scope must be a mapping.`);
38
+ return { ...gate, stage, cost, scope, blocking: gate.blocking !== false };
39
+ });
40
+ return { schema_version: GATES_SCHEMA_VERSION, gates };
41
+ }
42
+ //# sourceMappingURL=gates.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.mjs","sourceRoot":"","sources":["../../src/artifacts/gates.mjs"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { documentRevision } from './document.mjs';
2
+ export declare const PLAN_HEADINGS: string[];
3
+ export declare function validateImplementationPlan(text: any, { workItem, engineeringText, specText, checkRevisions }: {
4
+ checkRevisions?: boolean | undefined;
5
+ engineeringText: any;
6
+ specText: any;
7
+ workItem: any;
8
+ }): {
9
+ errors: any[];
10
+ };
11
+ //# sourceMappingURL=implementation-plan.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implementation-plan.d.mts","sourceRoot":"","sources":["../../src/artifacts/implementation-plan.mjs"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,eAAO,MAAM,aAAa,UAazB,CAAC;AACF,wBAAgB,0BAA0B,CAAC,IAAI,KAAA,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAqB,EAAE;;;;;CAAA;;EAU9G"}
@@ -0,0 +1,30 @@
1
+ import { documentRevision, validateDocument } from './document.mjs';
2
+ export { documentRevision } from './document.mjs';
3
+ export const PLAN_HEADINGS = [
4
+ '# Implementation Plan',
5
+ '## Outcome',
6
+ '## Current state',
7
+ '## Proposed changes',
8
+ '## Execution sequence',
9
+ '## Task mapping',
10
+ '## Data and control flow',
11
+ '## Engineering compliance',
12
+ '## Tests and validation',
13
+ '## Risks and rollback',
14
+ '## Deliberately excluded',
15
+ '## Human decisions required'
16
+ ];
17
+ export function validateImplementationPlan(text, { workItem, engineeringText, specText, checkRevisions = true }) {
18
+ const result = validateDocument(text, PLAN_HEADINGS);
19
+ if (result.work_item !== workItem)
20
+ result.errors.push('Plan belongs to a different work item.');
21
+ for (const key of ['engineering_revision', 'spec_revision'])
22
+ if (!/^[a-f0-9]{64}$/.test(result[key] ?? ''))
23
+ result.errors.push(`${key} must be SHA256.`);
24
+ if (checkRevisions && result.engineering_revision !== documentRevision(engineeringText))
25
+ result.errors.push('Engineering revision is stale.');
26
+ if (checkRevisions && result.spec_revision !== documentRevision(specText))
27
+ result.errors.push('Spec revision is stale.');
28
+ return result;
29
+ }
30
+ //# sourceMappingURL=implementation-plan.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implementation-plan.mjs","sourceRoot":"","sources":["../../src/artifacts/implementation-plan.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,uBAAuB;IACvB,YAAY;IACZ,kBAAkB;IAClB,qBAAqB;IACrB,uBAAuB;IACvB,iBAAiB;IACjB,0BAA0B;IAC1B,2BAA2B;IAC3B,yBAAyB;IACzB,uBAAuB;IACvB,0BAA0B;IAC1B,6BAA6B;CAC9B,CAAC;AACF,MAAM,UAAU,0BAA0B,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,EAAE;IAC7G,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAChG,KAAK,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC;QACzD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,kBAAkB,CAAC,CAAC;IAC9F,IAAI,cAAc,IAAI,MAAM,CAAC,oBAAoB,KAAK,gBAAgB,CAAC,eAAe,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACvD,IAAI,cAAc,IAAI,MAAM,CAAC,aAAa,KAAK,gBAAgB,CAAC,QAAQ,CAAC;QACvE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function validatePrdDocument(text: any): {
2
+ errors: any[];
3
+ };
4
+ //# sourceMappingURL=prd.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd.d.mts","sourceRoot":"","sources":["../../src/artifacts/prd.mjs"],"names":[],"mappings":"AACA,wBAAgB,mBAAmB,CAAC,IAAI,KAAA;;EAUvC"}