@encore-os/eos-spec 0.3.1

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 (256) hide show
  1. package/LICENSE +17 -0
  2. package/bin/check-dist-fresh.js +51 -0
  3. package/bin/eos-spec.js +7 -0
  4. package/dist/commands/ac-backfill.d.ts +31 -0
  5. package/dist/commands/ac-backfill.js +198 -0
  6. package/dist/commands/ac-backfill.js.map +1 -0
  7. package/dist/commands/archive.d.ts +2 -0
  8. package/dist/commands/archive.js +101 -0
  9. package/dist/commands/archive.js.map +1 -0
  10. package/dist/commands/audit.d.ts +30 -0
  11. package/dist/commands/audit.js +107 -0
  12. package/dist/commands/audit.js.map +1 -0
  13. package/dist/commands/backfill.d.ts +41 -0
  14. package/dist/commands/backfill.js +239 -0
  15. package/dist/commands/backfill.js.map +1 -0
  16. package/dist/commands/checkArtifacts.d.ts +2 -0
  17. package/dist/commands/checkArtifacts.js +48 -0
  18. package/dist/commands/checkArtifacts.js.map +1 -0
  19. package/dist/commands/checkPlacement.d.ts +2 -0
  20. package/dist/commands/checkPlacement.js +31 -0
  21. package/dist/commands/checkPlacement.js.map +1 -0
  22. package/dist/commands/claim.d.ts +4 -0
  23. package/dist/commands/claim.js +46 -0
  24. package/dist/commands/claim.js.map +1 -0
  25. package/dist/commands/complete.d.ts +2 -0
  26. package/dist/commands/complete.js +138 -0
  27. package/dist/commands/complete.js.map +1 -0
  28. package/dist/commands/conformance.d.ts +23 -0
  29. package/dist/commands/conformance.js +124 -0
  30. package/dist/commands/conformance.js.map +1 -0
  31. package/dist/commands/create.d.ts +6 -0
  32. package/dist/commands/create.js +277 -0
  33. package/dist/commands/create.js.map +1 -0
  34. package/dist/commands/deferred.d.ts +2 -0
  35. package/dist/commands/deferred.js +85 -0
  36. package/dist/commands/deferred.js.map +1 -0
  37. package/dist/commands/delta.d.ts +17 -0
  38. package/dist/commands/delta.js +292 -0
  39. package/dist/commands/delta.js.map +1 -0
  40. package/dist/commands/freshness.d.ts +13 -0
  41. package/dist/commands/freshness.js +72 -0
  42. package/dist/commands/freshness.js.map +1 -0
  43. package/dist/commands/funnel.d.ts +2 -0
  44. package/dist/commands/funnel.js +61 -0
  45. package/dist/commands/funnel.js.map +1 -0
  46. package/dist/commands/gen-tests.d.ts +2 -0
  47. package/dist/commands/gen-tests.js +53 -0
  48. package/dist/commands/gen-tests.js.map +1 -0
  49. package/dist/commands/init.d.ts +2 -0
  50. package/dist/commands/init.js +64 -0
  51. package/dist/commands/init.js.map +1 -0
  52. package/dist/commands/list.d.ts +9 -0
  53. package/dist/commands/list.js +61 -0
  54. package/dist/commands/list.js.map +1 -0
  55. package/dist/commands/metrics.d.ts +2 -0
  56. package/dist/commands/metrics.js +66 -0
  57. package/dist/commands/metrics.js.map +1 -0
  58. package/dist/commands/next.d.ts +48 -0
  59. package/dist/commands/next.js +344 -0
  60. package/dist/commands/next.js.map +1 -0
  61. package/dist/commands/precedent.d.ts +66 -0
  62. package/dist/commands/precedent.js +343 -0
  63. package/dist/commands/precedent.js.map +1 -0
  64. package/dist/commands/ready.d.ts +28 -0
  65. package/dist/commands/ready.js +147 -0
  66. package/dist/commands/ready.js.map +1 -0
  67. package/dist/commands/reconcile.d.ts +44 -0
  68. package/dist/commands/reconcile.js +187 -0
  69. package/dist/commands/reconcile.js.map +1 -0
  70. package/dist/commands/rollup.d.ts +2 -0
  71. package/dist/commands/rollup.js +43 -0
  72. package/dist/commands/rollup.js.map +1 -0
  73. package/dist/commands/scorecard.d.ts +11 -0
  74. package/dist/commands/scorecard.js +55 -0
  75. package/dist/commands/scorecard.js.map +1 -0
  76. package/dist/commands/signoff.d.ts +2 -0
  77. package/dist/commands/signoff.js +114 -0
  78. package/dist/commands/signoff.js.map +1 -0
  79. package/dist/commands/status.d.ts +2 -0
  80. package/dist/commands/status.js +100 -0
  81. package/dist/commands/status.js.map +1 -0
  82. package/dist/commands/tasks.d.ts +13 -0
  83. package/dist/commands/tasks.js +81 -0
  84. package/dist/commands/tasks.js.map +1 -0
  85. package/dist/commands/validate.d.ts +16 -0
  86. package/dist/commands/validate.js +89 -0
  87. package/dist/commands/validate.js.map +1 -0
  88. package/dist/commands/verify-acs.d.ts +15 -0
  89. package/dist/commands/verify-acs.js +196 -0
  90. package/dist/commands/verify-acs.js.map +1 -0
  91. package/dist/commands/verifyRollout.d.ts +2 -0
  92. package/dist/commands/verifyRollout.js +125 -0
  93. package/dist/commands/verifyRollout.js.map +1 -0
  94. package/dist/index.d.ts +21 -0
  95. package/dist/index.js +138 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/lib/ac-draft-prompt.d.ts +18 -0
  98. package/dist/lib/ac-draft-prompt.js +38 -0
  99. package/dist/lib/ac-draft-prompt.js.map +1 -0
  100. package/dist/lib/ac-response-parser.d.ts +18 -0
  101. package/dist/lib/ac-response-parser.js +57 -0
  102. package/dist/lib/ac-response-parser.js.map +1 -0
  103. package/dist/lib/ai-call.d.ts +13 -0
  104. package/dist/lib/ai-call.js +17 -0
  105. package/dist/lib/ai-call.js.map +1 -0
  106. package/dist/lib/archive.d.ts +21 -0
  107. package/dist/lib/archive.js +136 -0
  108. package/dist/lib/archive.js.map +1 -0
  109. package/dist/lib/artifact-integrity.d.ts +5 -0
  110. package/dist/lib/artifact-integrity.js +65 -0
  111. package/dist/lib/artifact-integrity.js.map +1 -0
  112. package/dist/lib/backfill-queue.d.ts +11 -0
  113. package/dist/lib/backfill-queue.js +14 -0
  114. package/dist/lib/backfill-queue.js.map +1 -0
  115. package/dist/lib/blockers.d.ts +66 -0
  116. package/dist/lib/blockers.js +103 -0
  117. package/dist/lib/blockers.js.map +1 -0
  118. package/dist/lib/claims.d.ts +39 -0
  119. package/dist/lib/claims.js +133 -0
  120. package/dist/lib/claims.js.map +1 -0
  121. package/dist/lib/classify-debt.d.ts +17 -0
  122. package/dist/lib/classify-debt.js +13 -0
  123. package/dist/lib/classify-debt.js.map +1 -0
  124. package/dist/lib/code-evidence.d.ts +35 -0
  125. package/dist/lib/code-evidence.js +171 -0
  126. package/dist/lib/code-evidence.js.map +1 -0
  127. package/dist/lib/coherence.d.ts +14 -0
  128. package/dist/lib/coherence.js +188 -0
  129. package/dist/lib/coherence.js.map +1 -0
  130. package/dist/lib/completion-gate.d.ts +17 -0
  131. package/dist/lib/completion-gate.js +28 -0
  132. package/dist/lib/completion-gate.js.map +1 -0
  133. package/dist/lib/compliance-signoff.d.ts +39 -0
  134. package/dist/lib/compliance-signoff.js +81 -0
  135. package/dist/lib/compliance-signoff.js.map +1 -0
  136. package/dist/lib/config.d.ts +63 -0
  137. package/dist/lib/config.js +40 -0
  138. package/dist/lib/config.js.map +1 -0
  139. package/dist/lib/cost.d.ts +12 -0
  140. package/dist/lib/cost.js +12 -0
  141. package/dist/lib/cost.js.map +1 -0
  142. package/dist/lib/debt-dashboard.d.ts +25 -0
  143. package/dist/lib/debt-dashboard.js +36 -0
  144. package/dist/lib/debt-dashboard.js.map +1 -0
  145. package/dist/lib/embedding-store.d.ts +103 -0
  146. package/dist/lib/embedding-store.js +133 -0
  147. package/dist/lib/embedding-store.js.map +1 -0
  148. package/dist/lib/embeddings-source.d.ts +36 -0
  149. package/dist/lib/embeddings-source.js +62 -0
  150. package/dist/lib/embeddings-source.js.map +1 -0
  151. package/dist/lib/enforcement-allowlist.d.ts +12 -0
  152. package/dist/lib/enforcement-allowlist.js +25 -0
  153. package/dist/lib/enforcement-allowlist.js.map +1 -0
  154. package/dist/lib/events.d.ts +47 -0
  155. package/dist/lib/events.js +75 -0
  156. package/dist/lib/events.js.map +1 -0
  157. package/dist/lib/exec.d.ts +8 -0
  158. package/dist/lib/exec.js +25 -0
  159. package/dist/lib/exec.js.map +1 -0
  160. package/dist/lib/frontmatter.d.ts +112 -0
  161. package/dist/lib/frontmatter.js +261 -0
  162. package/dist/lib/frontmatter.js.map +1 -0
  163. package/dist/lib/funnel.d.ts +22 -0
  164. package/dist/lib/funnel.js +41 -0
  165. package/dist/lib/funnel.js.map +1 -0
  166. package/dist/lib/git-mtime.d.ts +4 -0
  167. package/dist/lib/git-mtime.js +23 -0
  168. package/dist/lib/git-mtime.js.map +1 -0
  169. package/dist/lib/metrics.d.ts +42 -0
  170. package/dist/lib/metrics.js +92 -0
  171. package/dist/lib/metrics.js.map +1 -0
  172. package/dist/lib/migration-collision.d.ts +20 -0
  173. package/dist/lib/migration-collision.js +61 -0
  174. package/dist/lib/migration-collision.js.map +1 -0
  175. package/dist/lib/next-action.d.ts +44 -0
  176. package/dist/lib/next-action.js +138 -0
  177. package/dist/lib/next-action.js.map +1 -0
  178. package/dist/lib/ollama-embed.d.ts +21 -0
  179. package/dist/lib/ollama-embed.js +65 -0
  180. package/dist/lib/ollama-embed.js.map +1 -0
  181. package/dist/lib/output.d.ts +35 -0
  182. package/dist/lib/output.js +46 -0
  183. package/dist/lib/output.js.map +1 -0
  184. package/dist/lib/pipeline-config.d.ts +20 -0
  185. package/dist/lib/pipeline-config.js +208 -0
  186. package/dist/lib/pipeline-config.js.map +1 -0
  187. package/dist/lib/pipeline-map.d.ts +68 -0
  188. package/dist/lib/pipeline-map.js +256 -0
  189. package/dist/lib/pipeline-map.js.map +1 -0
  190. package/dist/lib/pipeline-schema.d.ts +48 -0
  191. package/dist/lib/pipeline-schema.js +22 -0
  192. package/dist/lib/pipeline-schema.js.map +1 -0
  193. package/dist/lib/placement.d.ts +6 -0
  194. package/dist/lib/placement.js +40 -0
  195. package/dist/lib/placement.js.map +1 -0
  196. package/dist/lib/precedent-search.d.ts +18 -0
  197. package/dist/lib/precedent-search.js +160 -0
  198. package/dist/lib/precedent-search.js.map +1 -0
  199. package/dist/lib/predicate-registry.d.ts +6 -0
  200. package/dist/lib/predicate-registry.js +40 -0
  201. package/dist/lib/predicate-registry.js.map +1 -0
  202. package/dist/lib/recall-cases.d.ts +15 -0
  203. package/dist/lib/recall-cases.js +39 -0
  204. package/dist/lib/recall-cases.js.map +1 -0
  205. package/dist/lib/repo.d.ts +20 -0
  206. package/dist/lib/repo.js +82 -0
  207. package/dist/lib/repo.js.map +1 -0
  208. package/dist/lib/requirements.d.ts +91 -0
  209. package/dist/lib/requirements.js +179 -0
  210. package/dist/lib/requirements.js.map +1 -0
  211. package/dist/lib/rollup.d.ts +24 -0
  212. package/dist/lib/rollup.js +34 -0
  213. package/dist/lib/rollup.js.map +1 -0
  214. package/dist/lib/scorecard-run.d.ts +6 -0
  215. package/dist/lib/scorecard-run.js +48 -0
  216. package/dist/lib/scorecard-run.js.map +1 -0
  217. package/dist/lib/scorecard.d.ts +69 -0
  218. package/dist/lib/scorecard.js +113 -0
  219. package/dist/lib/scorecard.js.map +1 -0
  220. package/dist/lib/semantic-search.d.ts +36 -0
  221. package/dist/lib/semantic-search.js +56 -0
  222. package/dist/lib/semantic-search.js.map +1 -0
  223. package/dist/lib/session-state.d.ts +8 -0
  224. package/dist/lib/session-state.js +25 -0
  225. package/dist/lib/session-state.js.map +1 -0
  226. package/dist/lib/spec-debt.d.ts +8 -0
  227. package/dist/lib/spec-debt.js +17 -0
  228. package/dist/lib/spec-debt.js.map +1 -0
  229. package/dist/lib/spec-pure.d.ts +59 -0
  230. package/dist/lib/spec-pure.js +215 -0
  231. package/dist/lib/spec-pure.js.map +1 -0
  232. package/dist/lib/specs.d.ts +148 -0
  233. package/dist/lib/specs.js +373 -0
  234. package/dist/lib/specs.js.map +1 -0
  235. package/dist/lib/test-generator.d.ts +5 -0
  236. package/dist/lib/test-generator.js +72 -0
  237. package/dist/lib/test-generator.js.map +1 -0
  238. package/dist/lib/user-stories.d.ts +6 -0
  239. package/dist/lib/user-stories.js +56 -0
  240. package/dist/lib/user-stories.js.map +1 -0
  241. package/dist/lib/verifies-scan.d.ts +9 -0
  242. package/dist/lib/verifies-scan.js +73 -0
  243. package/dist/lib/verifies-scan.js.map +1 -0
  244. package/dist/lib/verify-core.d.ts +23 -0
  245. package/dist/lib/verify-core.js +48 -0
  246. package/dist/lib/verify-core.js.map +1 -0
  247. package/dist/lib/with-event-log.d.ts +12 -0
  248. package/dist/lib/with-event-log.js +65 -0
  249. package/dist/lib/with-event-log.js.map +1 -0
  250. package/dist/lib/wizard-specs.d.ts +17 -0
  251. package/dist/lib/wizard-specs.js +34 -0
  252. package/dist/lib/wizard-specs.js.map +1 -0
  253. package/dist/pure.d.ts +19 -0
  254. package/dist/pure.js +31 -0
  255. package/dist/pure.js.map +1 -0
  256. package/package.json +69 -0
@@ -0,0 +1,81 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join, posix } from 'node:path';
3
+ import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
4
+ import { getRepoRoot } from '../lib/repo.js';
5
+ import { findSpec } from '../lib/specs.js';
6
+ export function registerTasks(program) {
7
+ program
8
+ .command('tasks <id>')
9
+ .description('Generate or refresh a TASKS.md from TASKS_TEMPLATE.md, scaffolding standard + per-core tasks.')
10
+ .option('--force', 'Overwrite existing TASKS file', false)
11
+ .action(async (id, options, cmd) => {
12
+ const global = getGlobalOptions(cmd);
13
+ const repoRoot = getRepoRoot(global.repoRoot);
14
+ const upper = id.toUpperCase();
15
+ const spec = findSpec(repoRoot, upper);
16
+ if (!spec) {
17
+ emit(global, {
18
+ ok: false,
19
+ error: { code: ErrorCode.SPEC_NOT_FOUND, message: `tasks: spec ${upper} not found` },
20
+ data: null,
21
+ text: `tasks: spec ${upper} not found`,
22
+ });
23
+ }
24
+ const tasksDir = join(repoRoot, 'specs', spec.core, 'tasks');
25
+ mkdirSync(tasksDir, { recursive: true });
26
+ const target = join(tasksDir, `${spec.id}-TASKS.md`);
27
+ if (existsSync(target) && !options.force) {
28
+ emit(global, {
29
+ ok: false,
30
+ data: { target, exists: true },
31
+ text: `tasks: ${target} already exists (pass --force to overwrite)`,
32
+ });
33
+ }
34
+ const templatePath = join(repoRoot, 'specs', '_templates', 'TASKS_TEMPLATE.md');
35
+ const substituted = readFileSync(templatePath, 'utf8')
36
+ .replace(/\{\{ID\}\}/g, spec.id)
37
+ .replace(/\{\{TITLE\}\}/g, spec.title ?? spec.id)
38
+ .replace(/\{\{DATE\}\}/g, new Date().toISOString().slice(0, 10));
39
+ // The template's relative links are written relative to specs/_templates/,
40
+ // but this file lands in specs/{core}/tasks/. Rebase them so they resolve
41
+ // from the new location (#997 Bug 1); otherwise every link is broken and
42
+ // the staged-markdown link gate rejects the fresh file.
43
+ const template = rebaseRelativeLinks(substituted, 'specs/_templates', `specs/${spec.core}/tasks`);
44
+ writeFileSync(target, template, 'utf8');
45
+ emit(global, {
46
+ ok: true,
47
+ data: { target, spec: spec.id },
48
+ text: `tasks: wrote ${relPath(repoRoot, target)}\nReview the per-core insertions in .cursor/skills/_shared/module-phases-tasks.md`,
49
+ });
50
+ });
51
+ }
52
+ function relPath(repoRoot, p) {
53
+ return p.startsWith(repoRoot) ? p.slice(repoRoot.length + 1) : p;
54
+ }
55
+ const MD_LINK_RE = /\[([^\]]*)\]\(([^)]+)\)/g;
56
+ /**
57
+ * Rebase relative markdown-link targets written relative to `fromDir` so they
58
+ * resolve from `toDir` instead. In-document (`#…`), absolute (`/…`), and external
59
+ * (`scheme:`) links are left untouched; `#anchors` are preserved. Generic — it
60
+ * handles the TASKS template's sibling (`_templates/…`) and cross-core
61
+ * (`../pf/…`) links without hardcoding any path (#997 Bug 1).
62
+ *
63
+ * Exported for unit testing. Both dirs are POSIX, repo-relative; only their
64
+ * relative depth matters.
65
+ */
66
+ export function rebaseRelativeLinks(body, fromDir, toDir) {
67
+ const fromAbs = posix.resolve('/', fromDir);
68
+ const toAbs = posix.resolve('/', toDir);
69
+ return body.replace(MD_LINK_RE, (whole, text, target) => {
70
+ if (/^(#|\/|[a-z][a-z0-9+.-]*:)/i.test(target))
71
+ return whole; // anchor / absolute / scheme
72
+ const hashIdx = target.indexOf('#');
73
+ const filePart = hashIdx === -1 ? target : target.slice(0, hashIdx);
74
+ const anchor = hashIdx === -1 ? '' : target.slice(hashIdx);
75
+ if (filePart === '')
76
+ return whole;
77
+ const rebased = posix.relative(toAbs, posix.resolve(fromAbs, filePart));
78
+ return `[${text}](${rebased}${anchor})`;
79
+ });
80
+ }
81
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/commands/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,+FAA+F,CAAC;SAC5G,MAAM,CAAC,SAAS,EAAE,+BAA+B,EAAE,KAAK,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,MAAM,EAAE;gBACX,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,OAAO,EAAE,eAAe,KAAK,YAAY,EAAE;gBACpF,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,eAAe,KAAK,YAAY;aACvC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7D,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;QAErD,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,EAAE;gBACX,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;gBAC9B,IAAI,EAAE,UAAU,MAAM,6CAA6C;aACpE,CAAC,CAAC;QACL,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;QAChF,MAAM,WAAW,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC;aACnD,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC;aAC/B,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC;aAChD,OAAO,CAAC,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAEnE,2EAA2E;QAC3E,0EAA0E;QAC1E,yEAAyE;QACzE,wDAAwD;QACxD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,EAAE,SAAS,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC;QAElG,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE;YACX,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YAC/B,IAAI,EAAE,gBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,mFAAmF;SACnI,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,OAAO,CAAC,QAAgB,EAAE,CAAS;IAC1C,OAAO,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAe,EAAE,KAAa;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,MAAc,EAAE,EAAE;QACtE,IAAI,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,6BAA6B;QAC3F,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,QAAQ,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QAClC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACxE,OAAO,IAAI,IAAI,KAAK,OAAO,GAAG,MAAM,GAAG,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Command } from 'commander';
2
+ import { type SpecFile } from '../lib/specs.js';
3
+ export type ValidateIssue = {
4
+ file: string;
5
+ rule: string;
6
+ message: string;
7
+ };
8
+ /**
9
+ * Group an already-listed corpus by upper-cased spec id. Built once per run so
10
+ * per-spec validation is a Map lookup instead of the old existsSync probe on an
11
+ * unslugged path + findSpec re-list per spec (O(n²) — ~46s of a 57s full run).
12
+ */
13
+ export declare function buildSpecIndex(specs: SpecFile[]): Map<string, SpecFile[]>;
14
+ /** Spec-existence rule evaluated against the prebuilt index (no filesystem access). */
15
+ export declare function validateSpecFromIndex(specId: string, index: Map<string, SpecFile[]>): ValidateIssue[];
16
+ export declare function registerValidate(program: Command): void;
@@ -0,0 +1,89 @@
1
+ import { runScript } from '../lib/exec.js';
2
+ import { ErrorCode, emit, emitContinuing, getGlobalOptions } from '../lib/output.js';
3
+ import { getRepoRoot } from '../lib/repo.js';
4
+ import { findSpec, listSpecs } from '../lib/specs.js';
5
+ /**
6
+ * Group an already-listed corpus by upper-cased spec id. Built once per run so
7
+ * per-spec validation is a Map lookup instead of the old existsSync probe on an
8
+ * unslugged path + findSpec re-list per spec (O(n²) — ~46s of a 57s full run).
9
+ */
10
+ export function buildSpecIndex(specs) {
11
+ const index = new Map();
12
+ for (const spec of specs) {
13
+ const key = spec.id.toUpperCase();
14
+ const entries = index.get(key);
15
+ if (entries)
16
+ entries.push(spec);
17
+ else
18
+ index.set(key, [spec]);
19
+ }
20
+ return index;
21
+ }
22
+ /** Spec-existence rule evaluated against the prebuilt index (no filesystem access). */
23
+ export function validateSpecFromIndex(specId, index) {
24
+ const entries = index.get(specId.toUpperCase());
25
+ if (!entries || entries.length === 0) {
26
+ return [{ file: specId, rule: 'spec-exists', message: `Spec file not found for ${specId}` }];
27
+ }
28
+ return [];
29
+ }
30
+ export function registerValidate(program) {
31
+ program
32
+ .command('validate')
33
+ .description('Validate specs, plans, and tasks. Wraps the validate-specs-templates audit.')
34
+ .option('--core <core>', 'Limit to one core (pf|cl|pm|hr|fa|...)')
35
+ .option('--spec <id>', 'Limit to one spec id (e.g. PF-37)')
36
+ .action(async (options, cmd) => {
37
+ const global = getGlobalOptions(cmd);
38
+ const repoRoot = getRepoRoot(global.repoRoot);
39
+ if (options.spec) {
40
+ const spec = findSpec(repoRoot, options.spec);
41
+ if (!spec) {
42
+ emit(global, {
43
+ ok: false,
44
+ error: { code: ErrorCode.SPEC_NOT_FOUND, message: `validate: spec ${options.spec} not found` },
45
+ data: { spec: options.spec, found: false },
46
+ text: `validate: spec ${options.spec} not found`,
47
+ });
48
+ }
49
+ const issues = validateSpecFromIndex(spec.id, buildSpecIndex([spec]));
50
+ emit(global, {
51
+ ok: issues.length === 0,
52
+ data: { spec: spec.id, issues },
53
+ text: issues.length === 0
54
+ ? `validate: ${spec.id} OK`
55
+ : `validate: ${spec.id} — ${issues.length} issue(s)\n${formatIssues(issues)}`,
56
+ exitCode: issues.length === 0 ? 0 : 1,
57
+ });
58
+ }
59
+ const specs = listSpecs(repoRoot, options.core);
60
+ const index = buildSpecIndex(specs);
61
+ const allIssues = [];
62
+ for (const s of specs) {
63
+ allIssues.push(...validateSpecFromIndex(s.id, index));
64
+ }
65
+ // Run the repo-wide template-structure validator
66
+ emitContinuing(global, 'Running scripts/audit/validate-specs-templates.ts ...');
67
+ const tplResult = runScript(['npx', 'tsx', 'scripts/audit/validate-specs-templates.ts'], repoRoot);
68
+ if (tplResult.exitCode !== 0) {
69
+ allIssues.push({
70
+ file: 'scripts/audit/validate-specs-templates.ts',
71
+ rule: 'templates',
72
+ message: tplResult.stdout || tplResult.stderr,
73
+ });
74
+ }
75
+ const exitCode = allIssues.length === 0 ? 0 : 1;
76
+ emit(global, {
77
+ ok: allIssues.length === 0,
78
+ data: { specCount: specs.length, issues: allIssues },
79
+ text: allIssues.length === 0
80
+ ? `validate: OK (${specs.length} specs)`
81
+ : `validate: ${allIssues.length} issue(s) across ${specs.length} specs\n${formatIssues(allIssues)}`,
82
+ exitCode,
83
+ });
84
+ });
85
+ }
86
+ function formatIssues(issues) {
87
+ return issues.map((i) => ` - ${i.file} [${i.rule}] ${i.message.split('\n')[0]}`).join('\n');
88
+ }
89
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Command } from 'commander';
2
+ export type Section = 'acceptance_criteria' | 'user_stories' | 'requirements';
3
+ export type Item = {
4
+ section: Section;
5
+ id: string;
6
+ status: string;
7
+ };
8
+ /** Flatten a spec's frontmatter AC/US/FR into a uniform item list (id + current status). */
9
+ export declare function resolveItems(text: string): Item[];
10
+ /** Split backing test files into those the root Vitest can run vs. deferred lanes. */
11
+ export declare function partitionBackingFiles(files: string[]): {
12
+ rootVitest: string[];
13
+ deferred: string[];
14
+ };
15
+ export declare function registerVerifyAcs(program: Command): void;
@@ -0,0 +1,196 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { readFileSync, readdirSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join, relative } from 'node:path';
5
+ import { readFrontmatter, setRequirementStatus } from '../lib/frontmatter.js';
6
+ import { emit, getGlobalOptions } from '../lib/output.js';
7
+ import { getRepoRoot, isProtectedBranch } from '../lib/repo.js';
8
+ import { findSpec } from '../lib/specs.js';
9
+ import { verdictFor } from '../lib/verify-core.js';
10
+ import { normalizeAcceptanceCriteria, normalizeRequirements, normalizeUserStories } from '../lib/requirements.js';
11
+ /** Flatten a spec's frontmatter AC/US/FR into a uniform item list (id + current status). */
12
+ export function resolveItems(text) {
13
+ const fm = readFrontmatter(text);
14
+ const out = [];
15
+ for (const ac of normalizeAcceptanceCriteria(fm.acceptance_criteria).acs)
16
+ out.push({ section: 'acceptance_criteria', id: ac.id, status: ac.status });
17
+ for (const us of normalizeUserStories(fm.user_stories).uss)
18
+ out.push({ section: 'user_stories', id: us.id, status: us.status ?? 'planned' });
19
+ for (const fr of normalizeRequirements(fm.requirements).frs)
20
+ out.push({ section: 'requirements', id: fr.id, status: fr.status });
21
+ return out;
22
+ }
23
+ /** Split backing test files into those the root Vitest can run vs. deferred lanes. */
24
+ export function partitionBackingFiles(files) {
25
+ const rootVitest = [];
26
+ const deferred = [];
27
+ for (const f of files) {
28
+ if ((f.startsWith('src/') || f.startsWith('scripts/')) && /\.(test|spec)\.tsx?$/.test(f))
29
+ rootVitest.push(f);
30
+ else
31
+ deferred.push(f);
32
+ }
33
+ return { rootVitest, deferred };
34
+ }
35
+ /** Run root-Vitest files, returning rel-path → {passed,failed,skipped}. */
36
+ function runRootVitest(repoRoot, relFiles) {
37
+ const stats = new Map();
38
+ if (relFiles.length === 0)
39
+ return stats;
40
+ const outFile = join(tmpdir(), `eos-verify-acs-${process.pid}.json`);
41
+ try {
42
+ execFileSync('bunx', ['vitest', 'run', ...relFiles, '--reporter=json', `--outputFile=${outFile}`], {
43
+ cwd: repoRoot,
44
+ stdio: ['ignore', 'ignore', 'inherit'],
45
+ });
46
+ }
47
+ catch {
48
+ /* nonzero exit = a failing test; the JSON report still carries the per-file outcome */
49
+ }
50
+ let report;
51
+ try {
52
+ report = JSON.parse(readFileSync(outFile, 'utf8'));
53
+ }
54
+ catch {
55
+ return stats;
56
+ }
57
+ for (const tr of report.testResults ?? []) {
58
+ const s = { passed: 0, failed: 0, skipped: 0 };
59
+ for (const a of tr.assertionResults ?? []) {
60
+ if (a.status === 'passed')
61
+ s.passed++;
62
+ else if (a.status === 'failed')
63
+ s.failed++;
64
+ else
65
+ s.skipped++;
66
+ }
67
+ stats.set(relative(repoRoot, tr.name), s);
68
+ }
69
+ return stats;
70
+ }
71
+ /** id → Set(backing test files, repo-relative) for one spec (per-file granularity). */
72
+ function backlinkFilesByItem(repoRoot, specId) {
73
+ const map = new Map();
74
+ const TEST_FILE = /\.(test|spec)\.tsx?$/;
75
+ const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.output', '.vercel']);
76
+ const walk = (dir) => {
77
+ let entries;
78
+ try {
79
+ entries = readdirSync(dir, { withFileTypes: true });
80
+ }
81
+ catch {
82
+ return;
83
+ }
84
+ for (const e of entries) {
85
+ const p = join(dir, e.name);
86
+ if (e.isDirectory()) {
87
+ if (!SKIP.has(e.name))
88
+ walk(p);
89
+ }
90
+ else if (TEST_FILE.test(e.name)) {
91
+ for (const id of parseBacklinks(readFileSync(p, 'utf8'), specId)) {
92
+ if (!map.has(id))
93
+ map.set(id, new Set());
94
+ map.get(id).add(relative(repoRoot, p));
95
+ }
96
+ }
97
+ }
98
+ };
99
+ for (const root of ['e2e', 'src', 'runner', 'scripts'])
100
+ walk(join(repoRoot, root));
101
+ return map;
102
+ }
103
+ function parseBacklinks(text, specId) {
104
+ const ids = [];
105
+ const esc = specId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
106
+ const re = new RegExp(`@verifies\\s+${esc}\\s+((?:(?:AC|US|FR)-\\d+[,\\s]*)+)`, 'g');
107
+ let m;
108
+ while ((m = re.exec(text)) !== null)
109
+ for (const id of m[1].match(/(?:AC|US|FR)-\d+/g) ?? [])
110
+ ids.push(id);
111
+ return ids;
112
+ }
113
+ export function registerVerifyAcs(program) {
114
+ program
115
+ .command('verify-acs')
116
+ .description('Promotion gate: run the @verifies-backing tests for a spec and flip per-item status planned->verified only on a real pass.')
117
+ .requiredOption('--spec <id>', 'Spec id (e.g. RUNNER-03)')
118
+ .option('--write', 'Apply promotions to the spec file (working-tree only; never on a protected branch)', false)
119
+ .option('--enforce', 'CI mode: exit non-zero if any item claims verified without a passing test', false)
120
+ .action((options, cmd) => {
121
+ const global = getGlobalOptions(cmd);
122
+ const repoRoot = getRepoRoot(global.repoRoot);
123
+ const spec = findSpec(repoRoot, options.spec);
124
+ if (!spec)
125
+ emit(global, {
126
+ ok: false,
127
+ data: { spec: options.spec, found: false },
128
+ text: `verify-acs: spec ${options.spec} not found`,
129
+ exitCode: 2,
130
+ });
131
+ const text = readFileSync(spec.path, 'utf8');
132
+ const items = resolveItems(text);
133
+ const backlinkFiles = backlinkFilesByItem(repoRoot, spec.id);
134
+ const allRoot = partitionBackingFiles([
135
+ ...new Set([...backlinkFiles.values()].flatMap((s) => [...s])),
136
+ ]).rootVitest;
137
+ const stats = runRootVitest(repoRoot, allRoot);
138
+ const results = items.map((it) => {
139
+ const files = [...(backlinkFiles.get(it.id) ?? [])];
140
+ const { rootVitest, deferred } = partitionBackingFiles(files);
141
+ const v = verdictFor(rootVitest, stats);
142
+ const reason = !files.length
143
+ ? 'no @verifies backlink'
144
+ : rootVitest.length === 0
145
+ ? `not_run (lane not wired: ${deferred.join(', ')})`
146
+ : v.reason;
147
+ return { ...it, files, proven: rootVitest.length > 0 && v.proven, reason };
148
+ });
149
+ if (options.enforce) {
150
+ const liars = results.filter((r) => r.status === 'verified' && !r.proven);
151
+ if (liars.length)
152
+ emit(global, {
153
+ ok: false,
154
+ data: { spec: spec.id, liars },
155
+ text: `verify-acs: ${liars.length} item(s) claim verified without a passing test`,
156
+ exitCode: 1,
157
+ });
158
+ }
159
+ let written = 0;
160
+ if (options.write) {
161
+ if (isProtectedBranch(repoRoot))
162
+ emit(global, {
163
+ ok: false,
164
+ data: { spec: spec.id },
165
+ text: 'verify-acs: refusing to --write on a protected branch (main); run on a feature branch',
166
+ exitCode: 2,
167
+ });
168
+ let next = text;
169
+ for (const r of results) {
170
+ if (r.proven && r.status !== 'verified') {
171
+ const after = setRequirementStatus(next, r.section, r.id, 'verified');
172
+ if (after !== next) {
173
+ written++;
174
+ next = after;
175
+ }
176
+ }
177
+ }
178
+ if (written > 0)
179
+ writeFileSync(spec.path, next);
180
+ }
181
+ const proven = results.filter((r) => r.proven).length;
182
+ emit(global, {
183
+ ok: true,
184
+ data: {
185
+ spec: spec.id,
186
+ proven,
187
+ total: results.length,
188
+ written,
189
+ results: results.map(({ section, id, proven, reason }) => ({ section, id, proven, reason })),
190
+ },
191
+ text: `verify-acs: ${spec.id} — ${proven}/${results.length} proven${options.write ? ` (${written} written)` : ' (dry run — pass --write)'}\n` +
192
+ results.map((r) => ` ${r.proven ? '✅ verified' : '⏸ planned '} ${r.id.padEnd(6)} ${r.reason}`).join('\n'),
193
+ });
194
+ });
195
+ }
196
+ //# sourceMappingURL=verify-acs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-acs.js","sourceRoot":"","sources":["../../src/commands/verify-acs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerVerifyRollout(program: Command): void;
@@ -0,0 +1,125 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { loadConfig } from '../lib/config.js';
4
+ import { runScript } from '../lib/exec.js';
5
+ import { emit, emitContinuing, getGlobalOptions } from '../lib/output.js';
6
+ import { getRepoRoot } from '../lib/repo.js';
7
+ export function registerVerifyRollout(program) {
8
+ program
9
+ .command('verify-rollout')
10
+ .description('Run OpenSpec rollout verification checks (config, templates, CLI smoke, delta format).')
11
+ .option('--layer <n>', 'Run only layer N (1=audits, 2=CLI smoke, 3=spot checks)')
12
+ .action(async (options, cmd) => {
13
+ const global = getGlobalOptions(cmd);
14
+ const repoRoot = getRepoRoot(global.repoRoot);
15
+ const layers = [];
16
+ const targetLayer = options.layer ? parseInt(options.layer, 10) : undefined;
17
+ if (!targetLayer || targetLayer === 1) {
18
+ emitContinuing(global, 'verify-rollout: Layer 1 — Automated audits');
19
+ layers.push(runLayer1(repoRoot));
20
+ }
21
+ if (!targetLayer || targetLayer === 2) {
22
+ emitContinuing(global, 'verify-rollout: Layer 2 — CLI build + smoke');
23
+ layers.push(runLayer2(repoRoot));
24
+ }
25
+ if (!targetLayer || targetLayer === 3) {
26
+ emitContinuing(global, 'verify-rollout: Layer 3 — Phase 4 spot checks');
27
+ layers.push(runLayer3(repoRoot, global.config));
28
+ }
29
+ const allPassed = layers.every((l) => l.passed);
30
+ const summary = layers
31
+ .map((l) => ` ${l.passed ? 'PASS' : 'FAIL'} ${l.layer}${l.details.length > 0 ? `\n${l.details.map((d) => ` ${d}`).join('\n')}` : ''}`)
32
+ .join('\n');
33
+ emit(global, {
34
+ ok: allPassed,
35
+ data: { layers, allPassed },
36
+ text: `verify-rollout: ${allPassed ? 'ALL PASS' : 'SOME FAILED'}\n${summary}`,
37
+ exitCode: allPassed ? 0 : 1,
38
+ });
39
+ });
40
+ }
41
+ function runLayer1(repoRoot) {
42
+ const details = [];
43
+ let passed = true;
44
+ const tplResult = runScript(['npx', 'tsx', 'scripts/audit/validate-specs-templates.ts'], repoRoot);
45
+ if (tplResult.exitCode !== 0) {
46
+ passed = false;
47
+ details.push(`validate-specs-templates: FAIL (exit ${tplResult.exitCode})`);
48
+ }
49
+ else {
50
+ details.push('validate-specs-templates: PASS');
51
+ }
52
+ return { layer: 'Layer 1: Automated audits', passed, details };
53
+ }
54
+ function runLayer2(repoRoot) {
55
+ const details = [];
56
+ let passed = true;
57
+ const buildResult = runScript(['npm', 'run', '-w', 'tools/eos-spec', 'build'], repoRoot);
58
+ if (buildResult.exitCode !== 0) {
59
+ passed = false;
60
+ details.push(`build: FAIL (exit ${buildResult.exitCode})`);
61
+ return { layer: 'Layer 2: CLI build + smoke', passed, details };
62
+ }
63
+ details.push('build: PASS');
64
+ const commands = ['init', 'list', 'status'];
65
+ for (const cmd of commands) {
66
+ const r = runScript(['node', 'tools/eos-spec/bin/eos-spec.js', cmd, '--json'], repoRoot);
67
+ details.push(`${cmd}: ${r.exitCode === 0 ? 'PASS' : `FAIL (exit ${r.exitCode})`}`);
68
+ if (r.exitCode !== 0)
69
+ passed = false;
70
+ }
71
+ return { layer: 'Layer 2: CLI build + smoke', passed, details };
72
+ }
73
+ function runLayer3(repoRoot, configPath) {
74
+ const details = [];
75
+ let passed = true;
76
+ try {
77
+ const config = loadConfig(repoRoot, configPath);
78
+ details.push('specs/config.yaml: parsed OK');
79
+ if (!config.delta_types || config.delta_types.length === 0) {
80
+ passed = false;
81
+ details.push('delta_types: MISSING');
82
+ }
83
+ else {
84
+ details.push(`delta_types: [${config.delta_types.join(', ')}]`);
85
+ }
86
+ if (!config.archive) {
87
+ passed = false;
88
+ details.push('archive policy: MISSING');
89
+ }
90
+ else {
91
+ details.push(`archive policy: enabled=${config.archive.enabled}`);
92
+ }
93
+ }
94
+ catch (e) {
95
+ passed = false;
96
+ details.push(`specs/config.yaml: FAIL (${e instanceof Error ? e.message : String(e)})`);
97
+ }
98
+ const liteTemplatePath = join(repoRoot, 'specs', '_templates', 'SPEC_TEMPLATE_LITE.md');
99
+ if (existsSync(liteTemplatePath)) {
100
+ const content = readFileSync(liteTemplatePath, 'utf8');
101
+ if (content.includes('## Changes from current behavior')) {
102
+ details.push('SPEC_TEMPLATE_LITE.md: "Changes from current behavior" section present');
103
+ }
104
+ else {
105
+ passed = false;
106
+ details.push('SPEC_TEMPLATE_LITE.md: "Changes from current behavior" section MISSING');
107
+ }
108
+ }
109
+ else {
110
+ passed = false;
111
+ details.push('SPEC_TEMPLATE_LITE.md: file not found');
112
+ }
113
+ const whatsNextPath = join(repoRoot, '.cursor', 'commands', 'specs', 'whats-next.md');
114
+ if (existsSync(whatsNextPath)) {
115
+ const content = readFileSync(whatsNextPath, 'utf8');
116
+ if (content.includes('Fluid mode')) {
117
+ details.push('whats-next.md: Fluid mode section present');
118
+ }
119
+ else {
120
+ details.push('whats-next.md: Fluid mode section NOT FOUND (warning)');
121
+ }
122
+ }
123
+ return { layer: 'Layer 3: Phase 4 spot checks', passed, details };
124
+ }
125
+ //# sourceMappingURL=verifyRollout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyRollout.js","sourceRoot":"","sources":["../../src/commands/verifyRollout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ export type { SpecFile, SpecSignals, MissingSpecDiagnosis } from './lib/specs.js';
3
+ export { listSpecs, findSpec, findSpecsById, deriveSignals, diagnoseMissingSpec } from './lib/specs.js';
4
+ export { loadConfig, resetConfigCache, coresFromConfig, type SpecConfig, type CoreDef } from './lib/config.js';
5
+ export type { EmbeddingsSource } from './lib/embeddings-source.js';
6
+ export { embeddingsSourceFromConfig, FilesystemEmbeddingsSource } from './lib/embeddings-source.js';
7
+ export { recommendAction } from './commands/next.js';
8
+ export type { NextAction } from './lib/next-action.js';
9
+ export { getRepoRoot, coresList } from './lib/repo.js';
10
+ export { buildScorecardForCore } from './lib/scorecard-run.js';
11
+ export { scanVerifies } from './lib/verifies-scan.js';
12
+ export { computeStage, PIPELINE, type ActorType } from './lib/pipeline-map.js';
13
+ export { isCompleteStatus, collectSpecIds } from './lib/blockers.js';
14
+ export { uiEvidenceGate } from './lib/completion-gate.js';
15
+ export { parseComplianceSignoff } from './lib/compliance-signoff.js';
16
+ export type { SessionState } from './lib/session-state.js';
17
+ /** The fully-registered CLI program. Exported (not parsed on import — the parse
18
+ * call below is guarded by the main-module check) so the command-surface gate
19
+ * and conformance pack can enumerate the registered command set. */
20
+ export declare const program: Command;
21
+ export declare function run(argv: string[]): Promise<void>;