@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,187 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { isAbsolute, join } from 'node:path';
4
+ import { resolveTasksArtifact, setPipelineStatus, setTasksArtifact } from '../lib/frontmatter.js';
5
+ import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
6
+ import { computeStage, rank } from '../lib/pipeline-map.js';
7
+ import { getRepoRoot } from '../lib/repo.js';
8
+ import { extractSpecId, listSpecs } from '../lib/specs.js';
9
+ import { withEventLog } from '../lib/with-event-log.js';
10
+ /** Classify frontmatter status vs the artifact-derived stage. */
11
+ export function classify(written, computed) {
12
+ if (written === computed)
13
+ return 'ok';
14
+ return rank(computed) > rank(written) ? 'lagging' : 'overstated';
15
+ }
16
+ /** Human-output scope label: `--spec` wins over `--core`; `--changed` → 'changed'; default `all`. */
17
+ export function reconcileScopeLabel(opts) {
18
+ if (opts.spec)
19
+ return String(opts.spec).toUpperCase();
20
+ if (opts.core)
21
+ return String(opts.core).toLowerCase();
22
+ if (opts.changed)
23
+ return 'changed';
24
+ return 'all';
25
+ }
26
+ /** Human-readable report: header + BOTH divergence directions, each with ids. */
27
+ export function formatReconcileText(args) {
28
+ const diverged = args.rows.filter((r) => r.direction !== 'ok');
29
+ const overstated = diverged.filter((r) => r.direction === 'overstated');
30
+ const lagging = diverged.filter((r) => r.direction === 'lagging');
31
+ const line = (r) => ` ${r.id}: written=${r.written ?? '(none)'} computed=${r.computed ?? '(none)'}`;
32
+ return [
33
+ `reconcile (${args.scope}): ${args.total} specs, ${diverged.length} diverged${args.write ? ' (written)' : ' (dry-run; pass --write to apply)'}`,
34
+ ` overstated (status claims more than artifacts prove): ${overstated.length}`,
35
+ ...overstated.slice(0, 50).map(line),
36
+ ` lagging (artifacts prove more than status claims): ${lagging.length}`,
37
+ ...lagging.slice(0, 50).map(line),
38
+ ].join('\n');
39
+ }
40
+ /**
41
+ * Map a list of changed file paths to the spec IDs they belong to. Counts
42
+ * canonical spec markdown under `specs/<core>/specs/…` AND wizard/UX specs under
43
+ * `specs/<core>/ux/…` (ignores research/reviews/reports and non-spec files).
44
+ * Ids are extracted with the same parser `listSpecs` uses (`extractSpecId`) so
45
+ * the `--changed` filter matches corpus identity exactly — including qualifier
46
+ * ids like `HR-UX-14`. Upper-cased, de-duplicated, input order preserved.
47
+ * Used by `reconcile --changed` to scope the write to branch-touched specs.
48
+ */
49
+ export function specIdsFromChangedPaths(paths) {
50
+ const ids = [];
51
+ for (const p of paths) {
52
+ const m = /(^|\/)specs\/([a-z]{2,3})\/(?:specs|ux)\/.+\.md$/i.exec(p);
53
+ if (!m)
54
+ continue;
55
+ const base = p.split('/').pop() ?? '';
56
+ const id = extractSpecId(base, m[2]);
57
+ if (id)
58
+ ids.push(id.toUpperCase());
59
+ }
60
+ return [...new Set(ids)];
61
+ }
62
+ /** Parse `git status --porcelain` output into pathnames (rename rows yield the new path). */
63
+ export function pathsFromPorcelain(out) {
64
+ return out
65
+ .split('\n')
66
+ .filter((line) => line.length > 3)
67
+ .map((line) => line.slice(3).trim())
68
+ .map((p) => (p.includes(' -> ') ? (p.split(' -> ').pop() ?? p) : p))
69
+ .map((p) => p.replace(/^"(.*)"$/, '$1'))
70
+ .filter(Boolean);
71
+ }
72
+ /**
73
+ * Files changed on this branch vs `base` (three-dot; falling back to the diff
74
+ * vs HEAD when the base ref is unavailable), UNIONED with uncommitted
75
+ * working-tree changes from `git status --porcelain` — so post-signoff spec
76
+ * edits that haven't been committed yet are still in scope for `--changed`.
77
+ */
78
+ export function gitChangedPaths(repoRoot, base) {
79
+ const split = (out) => out
80
+ .split('\n')
81
+ .map((l) => l.trim())
82
+ .filter(Boolean);
83
+ let committed = [];
84
+ try {
85
+ committed = split(execSync(`git diff --name-only ${base}...HEAD`, { cwd: repoRoot, encoding: 'utf8' }));
86
+ }
87
+ catch {
88
+ try {
89
+ committed = split(execSync('git diff --name-only HEAD', { cwd: repoRoot, encoding: 'utf8' }));
90
+ }
91
+ catch {
92
+ committed = [];
93
+ }
94
+ }
95
+ let workingTree = [];
96
+ try {
97
+ workingTree = pathsFromPorcelain(execSync('git status --porcelain', { cwd: repoRoot, encoding: 'utf8' }));
98
+ }
99
+ catch {
100
+ workingTree = [];
101
+ }
102
+ return [...new Set([...committed, ...workingTree])];
103
+ }
104
+ export function registerReconcile(program) {
105
+ program
106
+ .command('reconcile')
107
+ .description('Recompute pipeline_status from artifacts; report divergence and (with --write) materialize it.')
108
+ .option('--core <core>', 'Limit to one core (default: all)')
109
+ .option('--spec <id>', 'Limit to one spec ID (safer than a whole-corpus write)')
110
+ .option('--changed', 'Limit to specs changed vs --base (scoped write — avoids corpus-wide conflicts)', false)
111
+ .option('--base <ref>', 'Base ref for --changed', 'origin/development')
112
+ .option('--write', 'Materialize the computed status into spec frontmatter', false)
113
+ .action(withEventLog('reconcile', async (options, cmd) => {
114
+ const global = getGlobalOptions(cmd);
115
+ const repoRoot = getRepoRoot(global.repoRoot);
116
+ // A bare `reconcile --write` rewrites pipeline_status across the WHOLE corpus,
117
+ // which collides with other parallel branches. Require an explicit scope when
118
+ // writing; dry-run stays unscoped. `--core`, `--spec`, and `--changed` all count.
119
+ if (options.write && !options.spec && !options.core && !options.changed) {
120
+ emit(global, {
121
+ ok: false,
122
+ error: {
123
+ code: ErrorCode.SCOPE_REQUIRED,
124
+ message: 'reconcile --write requires --spec/--core/--changed',
125
+ },
126
+ text: 'reconcile: --write requires a scope — pass --spec <id>, --core <core>, or --changed (bare corpus-wide writes are rejected)',
127
+ exitCode: 2,
128
+ });
129
+ return;
130
+ }
131
+ const all = listSpecs(repoRoot, options.core);
132
+ let specs = all;
133
+ if (options.changed) {
134
+ const ids = new Set(specIdsFromChangedPaths(gitChangedPaths(repoRoot, options.base)));
135
+ specs = specs.filter((s) => ids.has(s.id.toUpperCase()));
136
+ }
137
+ if (options.spec) {
138
+ specs = specs.filter((s) => s.id.toUpperCase() === String(options.spec).toUpperCase());
139
+ }
140
+ const rows = specs.map((spec) => {
141
+ const computed = computeStage(spec);
142
+ const written = spec.signals.pipelineStatus;
143
+ const direction = classify(written, computed);
144
+ if (options.write && computed) {
145
+ const original = readFileSync(spec.path, 'utf8');
146
+ let text = original;
147
+ if (direction !== 'ok')
148
+ text = setPipelineStatus(text, computed);
149
+ // Materialize artifacts.tasks alongside pipeline_status so a spec that
150
+ // reaches tasks_generated satisfies the pipeline-status validator
151
+ // (pipeline/missing-tasks-artifact) without hand-editing (#997 Bug 2).
152
+ // Non-destructive: a VALID existing pointer (canonical or not — many
153
+ // specs use `<id>-credentialing-compliance-TASKS.md` etc.) is preserved.
154
+ // Only an absent or stale (dangling) pointer is set to the canonical
155
+ // path, and only when that canonical file actually exists (#16).
156
+ if (spec.hasTasks) {
157
+ const fileExists = (rel) => existsSync(isAbsolute(rel) ? rel : join(repoRoot, rel));
158
+ const next = resolveTasksArtifact(text, `specs/${spec.core}/tasks/${spec.id}-TASKS.md`, fileExists);
159
+ if (next)
160
+ text = setTasksArtifact(text, next);
161
+ }
162
+ if (text !== original)
163
+ writeFileSync(spec.path, text, 'utf8');
164
+ }
165
+ return { id: spec.id, core: spec.core, written, computed, direction };
166
+ });
167
+ const diverged = rows.filter((r) => r.direction !== 'ok');
168
+ const overstated = diverged.filter((r) => r.direction === 'overstated');
169
+ emit(global, {
170
+ ok: true,
171
+ data: {
172
+ total: rows.length,
173
+ diverged: diverged.length,
174
+ overstated: overstated.length,
175
+ wrote: Boolean(options.write),
176
+ rows: diverged,
177
+ },
178
+ text: formatReconcileText({
179
+ scope: reconcileScopeLabel({ spec: options.spec, core: options.core, changed: options.changed }),
180
+ total: rows.length,
181
+ rows,
182
+ write: Boolean(options.write),
183
+ }),
184
+ });
185
+ }));
186
+ }
187
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/commands/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerReadinessRollup(program: Command): void;
@@ -0,0 +1,43 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { emit, getGlobalOptions } from '../lib/output.js';
4
+ import { coresList, getRepoRoot } from '../lib/repo.js';
5
+ import { computeRollup } from '../lib/rollup.js';
6
+ import { buildScorecardForCore } from '../lib/scorecard-run.js';
7
+ import { scanVerifies } from '../lib/verifies-scan.js';
8
+ import { withEventLog } from '../lib/with-event-log.js';
9
+ export function registerReadinessRollup(program) {
10
+ program
11
+ .command('readiness-rollup')
12
+ .description("Aggregate every core's scorecard into a ranked platform readiness view (most-ready first).")
13
+ .option('--save', 'Write docs/development/PLATFORM_READINESS_ROLLUP_<date>.md', false)
14
+ .action(withEventLog('readiness-rollup', async (options, cmd) => {
15
+ const global = getGlobalOptions(cmd);
16
+ const repoRoot = getRepoRoot(global.repoRoot);
17
+ const verifiedBySpec = scanVerifies(repoRoot);
18
+ const perCore = coresList(repoRoot).map((core) => buildScorecardForCore(repoRoot, core, verifiedBySpec));
19
+ const report = computeRollup(perCore);
20
+ const header = '| Core | Specs | Authored % | Claims complete | Unverified-complete | Verified % |';
21
+ const sep = '|------|-------|-----------|-----------------|---------------------|-----------|';
22
+ const rowLines = report.rows.map((r) => `| ${r.core} | ${r.total} | ${r.authoredPct}% | ${r.claimsComplete} | ${r.claimedCompleteButUnverified} | ${r.verifiedPct}% |`);
23
+ const text = [
24
+ `Platform readiness rollup — ${report.cores.length} cores, ${report.totals.specs} specs`,
25
+ ` claimed complete : ${report.totals.claimsComplete}`,
26
+ ` claimed-complete-UNVERIFIED : ${report.totals.claimedCompleteButUnverified} ← the platform verification-debt headline`,
27
+ ` specs w/ verified reqs : ${report.totals.withVerifiedRequirements} (${report.totals.verifiedPct}%)`,
28
+ '',
29
+ header,
30
+ sep,
31
+ ...rowLines,
32
+ ].join('\n');
33
+ if (options.save) {
34
+ const date = new Date().toISOString().slice(0, 10);
35
+ const dir = join(repoRoot, 'docs/development');
36
+ mkdirSync(dir, { recursive: true });
37
+ const body = `# Platform Readiness Rollup — ${date}\n\n> Ranked most-ready first. Source: \`eos-spec scorecard\` per core (deterministic). "Verified %" = specs with >=1 \`@verifies\`-backed requirement; "Authored %" = specs at \`tasks_generated\`.\n\n\`\`\`\n${text}\n\`\`\`\n`;
38
+ writeFileSync(join(dir, `PLATFORM_READINESS_ROLLUP_${date}.md`), body, 'utf8');
39
+ }
40
+ emit(global, { ok: true, data: report, text });
41
+ }));
42
+ }
43
+ //# sourceMappingURL=rollup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollup.js","sourceRoot":"","sources":["../../src/commands/rollup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Command } from 'commander';
2
+ /**
3
+ * Validate `--core` against the canonical cores list. A bogus core used to fall through to
4
+ * listSpecs() → 0 specs → an all-zero scorecard with exit 0 — dangerously plausible output.
5
+ * Returns the normalized core, or an error message naming the valid cores.
6
+ */
7
+ export declare function resolveCoreFilter(core: string | undefined, repoRoot: string): {
8
+ core?: string;
9
+ error?: string;
10
+ };
11
+ export declare function registerScorecard(program: Command): void;
@@ -0,0 +1,55 @@
1
+ import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
2
+ import { coresList, getRepoRoot, isKnownCore } from '../lib/repo.js';
3
+ import { buildScorecardForCore } from '../lib/scorecard-run.js';
4
+ import { scanVerifies } from '../lib/verifies-scan.js';
5
+ import { withEventLog } from '../lib/with-event-log.js';
6
+ /**
7
+ * Validate `--core` against the canonical cores list. A bogus core used to fall through to
8
+ * listSpecs() → 0 specs → an all-zero scorecard with exit 0 — dangerously plausible output.
9
+ * Returns the normalized core, or an error message naming the valid cores.
10
+ */
11
+ export function resolveCoreFilter(core, repoRoot) {
12
+ if (!core)
13
+ return {};
14
+ const normalized = core.toLowerCase();
15
+ if (isKnownCore(normalized, repoRoot))
16
+ return { core: normalized };
17
+ return { error: `scorecard: unknown core "${core}". Valid cores: ${coresList(repoRoot).join(', ')}` };
18
+ }
19
+ export function registerScorecard(program) {
20
+ program
21
+ .command('scorecard')
22
+ .description('Deterministic readiness scorecard: per-spec stage, frontmatter accuracy, and @verifies-backed AC validation. Headline: claimed-complete-but-unverified.')
23
+ .option('--core <core>', 'Limit to one core')
24
+ .action(withEventLog('scorecard', async (options, cmd) => {
25
+ const global = getGlobalOptions(cmd);
26
+ const repoRoot = getRepoRoot(global.repoRoot);
27
+ const resolved = resolveCoreFilter(options.core, repoRoot);
28
+ if (resolved.error) {
29
+ emit(global, {
30
+ ok: false,
31
+ error: { code: ErrorCode.UNKNOWN_CORE, message: resolved.error },
32
+ data: { core: options.core, validCores: coresList(repoRoot) },
33
+ text: resolved.error,
34
+ });
35
+ }
36
+ const verifiedBySpec = scanVerifies(repoRoot);
37
+ const report = buildScorecardForCore(repoRoot, resolved.core, verifiedBySpec);
38
+ const flagged = report.rows.filter((r) => r.claimedCompleteButUnverified);
39
+ const text = [
40
+ `Readiness scorecard (${report.core}): ${report.total} specs`,
41
+ ` claims complete : ${report.claimsComplete}`,
42
+ ` claimed-complete-UNVERIFIED : ${report.claimedCompleteButUnverified} ← @verifies-backed AC validation = 0`,
43
+ ` specs w/ verified reqs : ${report.withVerifiedRequirements}`,
44
+ '',
45
+ ...(flagged.length
46
+ ? [
47
+ ' Claimed complete but unverified:',
48
+ ...flagged.map((r) => ` ${r.id} (${r.stage}, ${r.requirementsVerified}/${r.requirementsTotal} reqs verified)`),
49
+ ]
50
+ : [' None claimed-complete-but-unverified.']),
51
+ ].join('\n');
52
+ emit(global, { ok: true, data: report, text });
53
+ }));
54
+ }
55
+ //# sourceMappingURL=scorecard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scorecard.js","sourceRoot":"","sources":["../../src/commands/scorecard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSignoff(program: Command): void;
@@ -0,0 +1,114 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { insertSignoffMarker } from '../lib/frontmatter.js';
4
+ import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
5
+ import { getRepoRoot, specsRoot } from '../lib/repo.js';
6
+ import { diagnoseMissingSpec, findSpec } from '../lib/specs.js';
7
+ import { withEventLog } from '../lib/with-event-log.js';
8
+ const VALID_TYPES = [
9
+ 'validated',
10
+ 'spec-reviewed',
11
+ 'ux-reviewed',
12
+ 'heal-verified',
13
+ 'docshots',
14
+ 'ui-gate-waived',
15
+ 'submit-e2e-waived',
16
+ 'compliance',
17
+ ];
18
+ /** Today's date in YYYY-MM-DD form in the operator's LOCAL timezone, suitable for
19
+ * sign-off markers. Local (not UTC) so an evening sign-off doesn't stamp tomorrow. */
20
+ function isoToday() {
21
+ // en-CA formats as YYYY-MM-DD; using local time avoids the UTC off-by-one.
22
+ return new Date().toLocaleDateString('en-CA');
23
+ }
24
+ export function registerSignoff(program) {
25
+ program
26
+ .command('signoff')
27
+ .description('Write a sign-off marker (validated | ux-reviewed | heal-verified | docshots | ui-gate-waived | submit-e2e-waived | compliance) to a spec; idempotent.')
28
+ .requiredOption('--spec <id>', 'Spec id (e.g. PM-21)')
29
+ .requiredOption('--type <type>', 'Marker: validated | spec-reviewed | ux-reviewed | heal-verified | docshots | ui-gate-waived | submit-e2e-waived | compliance')
30
+ .option('--date <YYYY-MM-DD>', 'Override the marker date (default: today)')
31
+ .option('--reviewer <name>', 'Reviewer name (compliance sign-off only)')
32
+ .action(withEventLog('signoff', async (options, cmd) => {
33
+ const global = getGlobalOptions(cmd);
34
+ const repoRoot = getRepoRoot(global.repoRoot);
35
+ const type = options.type;
36
+ if (!VALID_TYPES.includes(type)) {
37
+ emit(global, {
38
+ ok: false,
39
+ error: {
40
+ code: ErrorCode.INVALID_ARGUMENT,
41
+ message: `signoff: --type must be one of ${VALID_TYPES.join(' | ')} (got "${options.type}")`,
42
+ },
43
+ data: null,
44
+ text: `signoff: --type must be one of ${VALID_TYPES.join(' | ')} (got "${options.type}")`,
45
+ });
46
+ return;
47
+ }
48
+ const spec = findSpec(repoRoot, options.spec);
49
+ if (!spec) {
50
+ const diag = diagnoseMissingSpec(repoRoot, options.spec);
51
+ emit(global, {
52
+ ok: false,
53
+ error: {
54
+ code: ErrorCode.SPEC_NOT_FOUND,
55
+ message: `signoff: spec ${options.spec} not found (${diag.reason})`,
56
+ },
57
+ data: null,
58
+ text: `signoff: spec ${options.spec} not found (${diag.reason})`,
59
+ });
60
+ return;
61
+ }
62
+ const date = options.date ?? isoToday();
63
+ if (type === 'compliance') {
64
+ const reviewsDir = join(specsRoot(repoRoot), spec.core, 'reviews');
65
+ const filePath = join(reviewsDir, `${spec.id}-COMPLIANCE-SIGNOFF.md`);
66
+ if (existsSync(filePath)) {
67
+ emit(global, {
68
+ ok: true,
69
+ data: { specId: spec.id, type, date, inserted: false, path: filePath },
70
+ text: `signoff: ${spec.id} already has a compliance sign-off file (no change)\n ${filePath}`,
71
+ });
72
+ return;
73
+ }
74
+ mkdirSync(dirname(filePath), { recursive: true });
75
+ const body = [
76
+ '---',
77
+ `spec_id: ${spec.id}`,
78
+ `reviewer: ${options.reviewer ?? '<name>'}`,
79
+ `date: ${date}`,
80
+ 'determinations:',
81
+ ' - regime: <regime>',
82
+ ' status: <reviewed | not-applicable | deferred>',
83
+ '---',
84
+ '',
85
+ `# Compliance Sign-Off: ${spec.id}`,
86
+ '',
87
+ '| # | Item | Regulation | Confirmed | Signed Off By | Date |',
88
+ '|---|------|------------|-----------|---------------|------|',
89
+ '',
90
+ ].join('\n');
91
+ writeFileSync(filePath, body, 'utf8');
92
+ emit(global, {
93
+ ok: true,
94
+ data: { specId: spec.id, type, date, inserted: true, path: filePath },
95
+ text: `signoff: wrote compliance sign-off scaffold to ${filePath}\n` +
96
+ ' edit reviewer + determinations[] (regimes from docs/compliance/*_TRACKING.md), then commit\n' +
97
+ ` next: run \`eos-spec reconcile --spec ${spec.id} --write\` to materialize derived pipeline_status`,
98
+ });
99
+ return;
100
+ }
101
+ const text = readFileSync(spec.path, 'utf8');
102
+ const { text: next, inserted } = insertSignoffMarker(text, type, date);
103
+ if (inserted)
104
+ writeFileSync(spec.path, next, 'utf8');
105
+ emit(global, {
106
+ ok: true,
107
+ data: { specId: spec.id, type, date, inserted, path: spec.path },
108
+ text: inserted
109
+ ? `signoff: wrote <!-- ${type}: ${date} --> to ${spec.id}\n ${spec.path}\n next: run \`eos-spec reconcile --spec ${spec.id} --write\` to materialize derived pipeline_status`
110
+ : `signoff: ${spec.id} already has a ${type} marker (no change)\n ${spec.path}`,
111
+ });
112
+ }));
113
+ }
114
+ //# sourceMappingURL=signoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signoff.js","sourceRoot":"","sources":["../../src/commands/signoff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerStatus(program: Command): void;
@@ -0,0 +1,100 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
4
+ import { computeStage } from '../lib/pipeline-map.js';
5
+ import { getRepoRoot } from '../lib/repo.js';
6
+ import { isClaimedCompleteUnverified } from '../lib/spec-debt.js';
7
+ import { findSpec, listSpecs } from '../lib/specs.js';
8
+ import { withEventLog } from '../lib/with-event-log.js';
9
+ export function registerStatus(program) {
10
+ program
11
+ .command('status')
12
+ .description('Show detail (status, files, completion) for one spec or summary for a core.')
13
+ .option('--core <core>', 'Show summary for one core')
14
+ .option('--spec <id>', 'Show detail for one spec')
15
+ .option('--include-archived', 'Include specs from specs/{core}/archive/', false)
16
+ .action(withEventLog('status', async (options, cmd) => {
17
+ const global = getGlobalOptions(cmd);
18
+ const repoRoot = getRepoRoot(global.repoRoot);
19
+ if (options.spec) {
20
+ const spec = findSpec(repoRoot, options.spec, { includeArchived: options.includeArchived });
21
+ if (!spec) {
22
+ emit(global, {
23
+ ok: false,
24
+ error: { code: ErrorCode.SPEC_NOT_FOUND, message: `status: spec ${options.spec} not found` },
25
+ data: null,
26
+ text: `status: spec ${options.spec} not found`,
27
+ });
28
+ }
29
+ const tasksPath = join(repoRoot, 'specs', spec.core, 'tasks', `${spec.id}-TASKS.md`);
30
+ let totalTasks = 0;
31
+ let completedTasks = 0;
32
+ if (existsSync(tasksPath)) {
33
+ const text = readFileSync(tasksPath, 'utf8');
34
+ totalTasks = (text.match(/^\s*-\s*\[\s*[xX ]\s*\]\s+/gm) ?? []).length;
35
+ completedTasks = (text.match(/^\s*-\s*\[\s*[xX]\s*\]\s+/gm) ?? []).length;
36
+ }
37
+ const claimedCompleteUnverified = isClaimedCompleteUnverified(repoRoot, spec.id);
38
+ const data = {
39
+ id: spec.id,
40
+ core: spec.core,
41
+ title: spec.title,
42
+ status: spec.status,
43
+ pipelineStatus: spec.signals.pipelineStatus,
44
+ computedStage: computeStage(spec),
45
+ paths: { spec: spec.path, hasContext: spec.hasContext, hasPlan: spec.hasPlan, hasTasks: spec.hasTasks },
46
+ tasks: { total: totalTasks, completed: completedTasks },
47
+ claimedCompleteButUnverified: claimedCompleteUnverified,
48
+ };
49
+ emit(global, {
50
+ ok: true,
51
+ data,
52
+ text: [
53
+ `Spec : ${spec.id} — ${spec.title ?? '(no title)'}`,
54
+ `Status : ${spec.status ?? 'unknown'}`,
55
+ `Stage : computed=${computeStage(spec) ?? '(none)'} frontmatter=${spec.signals.pipelineStatus ?? '(none)'}`,
56
+ `Archived: ${spec.archived ? 'yes' : 'no'}`,
57
+ `Files : context=${spec.hasContext} plan=${spec.hasPlan} tasks=${spec.hasTasks}`,
58
+ `Tasks : ${completedTasks}/${totalTasks} complete`,
59
+ `Path : ${spec.path}`,
60
+ ...(claimedCompleteUnverified
61
+ ? [
62
+ `⚠ verification-debt: claims complete but 0 @verifies-backed ACs — run \`npm run spec:check-debt\` / \`npm run spec:verify-acs -- --enforce --spec ${spec.id}\``,
63
+ ]
64
+ : []),
65
+ ].join('\n'),
66
+ });
67
+ }
68
+ const specs = listSpecs(repoRoot, options.core, { includeArchived: options.includeArchived });
69
+ const summary = {
70
+ core: options.core ?? 'all',
71
+ total: specs.length,
72
+ archived: specs.filter((s) => s.archived).length,
73
+ byStatus: tally(specs.map((s) => s.status ?? 'unknown')),
74
+ byComputedStage: tally(specs.map((s) => computeStage(s))),
75
+ withPlan: specs.filter((s) => s.hasPlan).length,
76
+ withTasks: specs.filter((s) => s.hasTasks).length,
77
+ };
78
+ const text = [
79
+ `Status summary (${summary.core}):`,
80
+ ` Total specs : ${summary.total}`,
81
+ ` Archived : ${summary.archived}`,
82
+ ` By status (body) : ${Object.entries(summary.byStatus)
83
+ .map(([k, v]) => `${k}=${v}`)
84
+ .join(' ')}`,
85
+ ` By computed stage : ${Object.entries(summary.byComputedStage)
86
+ .map(([k, v]) => `${k}=${v}`)
87
+ .join(' ')}`,
88
+ ` With plan : ${summary.withPlan}`,
89
+ ` With tasks : ${summary.withTasks}`,
90
+ ].join('\n');
91
+ emit(global, { ok: true, data: summary, text });
92
+ }));
93
+ }
94
+ function tally(items) {
95
+ const out = {};
96
+ for (const item of items)
97
+ out[item] = (out[item] ?? 0) + 1;
98
+ return out;
99
+ }
100
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerTasks(program: Command): void;
3
+ /**
4
+ * Rebase relative markdown-link targets written relative to `fromDir` so they
5
+ * resolve from `toDir` instead. In-document (`#…`), absolute (`/…`), and external
6
+ * (`scheme:`) links are left untouched; `#anchors` are preserved. Generic — it
7
+ * handles the TASKS template's sibling (`_templates/…`) and cross-core
8
+ * (`../pf/…`) links without hardcoding any path (#997 Bug 1).
9
+ *
10
+ * Exported for unit testing. Both dirs are POSIX, repo-relative; only their
11
+ * relative depth matters.
12
+ */
13
+ export declare function rebaseRelativeLinks(body: string, fromDir: string, toDir: string): string;