@encore-os/eos-spec 0.8.0 → 0.10.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 (112) hide show
  1. package/dist/commands/archive.js +1 -1
  2. package/dist/commands/archive.js.map +1 -1
  3. package/dist/commands/close-out.d.ts +2 -0
  4. package/dist/commands/close-out.js +167 -0
  5. package/dist/commands/close-out.js.map +1 -0
  6. package/dist/commands/complete.js +81 -4
  7. package/dist/commands/complete.js.map +1 -1
  8. package/dist/commands/conformance.js +20 -1
  9. package/dist/commands/conformance.js.map +1 -1
  10. package/dist/commands/create.js +6 -6
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/funnel.js +7 -0
  13. package/dist/commands/funnel.js.map +1 -1
  14. package/dist/commands/metrics.js +15 -0
  15. package/dist/commands/metrics.js.map +1 -1
  16. package/dist/commands/next.d.ts +10 -4
  17. package/dist/commands/next.js +23 -12
  18. package/dist/commands/next.js.map +1 -1
  19. package/dist/commands/proceed.d.ts +48 -0
  20. package/dist/commands/proceed.js +144 -0
  21. package/dist/commands/proceed.js.map +1 -0
  22. package/dist/commands/reconcile.js +7 -1
  23. package/dist/commands/reconcile.js.map +1 -1
  24. package/dist/commands/run.d.ts +13 -0
  25. package/dist/commands/run.js +238 -0
  26. package/dist/commands/run.js.map +1 -0
  27. package/dist/commands/scorecard.d.ts +24 -0
  28. package/dist/commands/scorecard.js +49 -3
  29. package/dist/commands/scorecard.js.map +1 -1
  30. package/dist/commands/signoff.js +3 -2
  31. package/dist/commands/signoff.js.map +1 -1
  32. package/dist/commands/status.js +7 -1
  33. package/dist/commands/status.js.map +1 -1
  34. package/dist/commands/tasks.d.ts +7 -0
  35. package/dist/commands/tasks.js +13 -1
  36. package/dist/commands/tasks.js.map +1 -1
  37. package/dist/commands/validate.d.ts +7 -0
  38. package/dist/commands/validate.js +46 -7
  39. package/dist/commands/validate.js.map +1 -1
  40. package/dist/index.js +19 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/lib/ai-call.d.ts +12 -0
  43. package/dist/lib/ai-call.js +6 -0
  44. package/dist/lib/ai-call.js.map +1 -1
  45. package/dist/lib/closeout-core.d.ts +46 -0
  46. package/dist/lib/closeout-core.js +34 -0
  47. package/dist/lib/closeout-core.js.map +1 -0
  48. package/dist/lib/closeout-predicate.d.ts +36 -0
  49. package/dist/lib/closeout-predicate.js +130 -0
  50. package/dist/lib/closeout-predicate.js.map +1 -0
  51. package/dist/lib/config.d.ts +10 -0
  52. package/dist/lib/config.js.map +1 -1
  53. package/dist/lib/cost.js +7 -0
  54. package/dist/lib/cost.js.map +1 -1
  55. package/dist/lib/coverage-gate.d.ts +43 -0
  56. package/dist/lib/coverage-gate.js +54 -0
  57. package/dist/lib/coverage-gate.js.map +1 -0
  58. package/dist/lib/events.d.ts +12 -0
  59. package/dist/lib/events.js +8 -1
  60. package/dist/lib/events.js.map +1 -1
  61. package/dist/lib/frontmatter.d.ts +23 -1
  62. package/dist/lib/frontmatter.js +37 -0
  63. package/dist/lib/frontmatter.js.map +1 -1
  64. package/dist/lib/funnel.d.ts +5 -0
  65. package/dist/lib/funnel.js +2 -1
  66. package/dist/lib/funnel.js.map +1 -1
  67. package/dist/lib/gate-executor.d.ts +80 -0
  68. package/dist/lib/gate-executor.js +311 -0
  69. package/dist/lib/gate-executor.js.map +1 -0
  70. package/dist/lib/llm-health.d.ts +28 -0
  71. package/dist/lib/llm-health.js +46 -0
  72. package/dist/lib/llm-health.js.map +1 -0
  73. package/dist/lib/metrics.d.ts +26 -0
  74. package/dist/lib/metrics.js +35 -0
  75. package/dist/lib/metrics.js.map +1 -1
  76. package/dist/lib/next-action.d.ts +10 -4
  77. package/dist/lib/next-action.js +10 -4
  78. package/dist/lib/next-action.js.map +1 -1
  79. package/dist/lib/ollama-embed.d.ts +5 -0
  80. package/dist/lib/ollama-embed.js +5 -0
  81. package/dist/lib/ollama-embed.js.map +1 -1
  82. package/dist/lib/output.d.ts +3 -0
  83. package/dist/lib/output.js +3 -0
  84. package/dist/lib/output.js.map +1 -1
  85. package/dist/lib/pipeline-config.js +10 -0
  86. package/dist/lib/pipeline-config.js.map +1 -1
  87. package/dist/lib/pipeline-map.d.ts +24 -0
  88. package/dist/lib/pipeline-map.js +54 -5
  89. package/dist/lib/pipeline-map.js.map +1 -1
  90. package/dist/lib/predicate-registry.js +7 -0
  91. package/dist/lib/predicate-registry.js.map +1 -1
  92. package/dist/lib/reconcile-core.d.ts +20 -3
  93. package/dist/lib/reconcile-core.js +16 -6
  94. package/dist/lib/reconcile-core.js.map +1 -1
  95. package/dist/lib/run-pipeline.d.ts +118 -0
  96. package/dist/lib/run-pipeline.js +106 -0
  97. package/dist/lib/run-pipeline.js.map +1 -0
  98. package/dist/lib/scorecard.d.ts +5 -0
  99. package/dist/lib/scorecard.js +1 -0
  100. package/dist/lib/scorecard.js.map +1 -1
  101. package/dist/lib/spec-pure.d.ts +69 -4
  102. package/dist/lib/spec-pure.js +129 -15
  103. package/dist/lib/spec-pure.js.map +1 -1
  104. package/dist/lib/specs.d.ts +9 -3
  105. package/dist/lib/specs.js +43 -20
  106. package/dist/lib/specs.js.map +1 -1
  107. package/dist/lib/version.d.ts +1 -1
  108. package/dist/lib/version.js +1 -1
  109. package/dist/lib/version.js.map +1 -1
  110. package/dist/lib/with-event-log.js +17 -3
  111. package/dist/lib/with-event-log.js.map +1 -1
  112. package/package.json +1 -1
@@ -3,7 +3,20 @@ import { join } from 'node:path';
3
3
  import { runScript } from '../lib/exec.js';
4
4
  import { ErrorCode, emit, emitContinuing, getGlobalOptions } from '../lib/output.js';
5
5
  import { getRepoRoot } from '../lib/repo.js';
6
- import { findSpec, listSpecs } from '../lib/specs.js';
6
+ import { findDuplicateSpecIds, findSpecsById, listSpecs } from '../lib/specs.js';
7
+ /**
8
+ * Build the `ValidateIssue`s for any spec id claimed by more than one primary spec
9
+ * (issue #27, mode b). One issue per colliding id, naming every offending path, so the
10
+ * old silent lowest-path-wins drop becomes a loud, actionable failure. Pure over the
11
+ * already-listed corpus — `findDuplicateSpecIds` does the fs-free grouping.
12
+ */
13
+ export function duplicateIdIssues(specs) {
14
+ return findDuplicateSpecIds(specs).map((dup) => ({
15
+ file: dup.paths.join(', '),
16
+ rule: 'duplicate-spec-id',
17
+ message: `Duplicate spec id ${dup.id}: ${dup.paths.length} files resolve to it — ${dup.paths.join(', ')}`,
18
+ }));
19
+ }
7
20
  /** Decide whether to invoke the consumer-local template-structure validator.
8
21
  * Skips when `--no-templates` is passed (commander maps it to options.templates ===
9
22
  * false) OR when scripts/audit/validate-specs-templates.ts is absent (builder has
@@ -54,8 +67,10 @@ export function registerValidate(program) {
54
67
  const global = getGlobalOptions(cmd);
55
68
  const repoRoot = getRepoRoot(global.repoRoot);
56
69
  if (options.spec) {
57
- const spec = findSpec(repoRoot, options.spec);
58
- if (!spec) {
70
+ // Use findSpecsById (not findSpec) so a duplicate id surfaces as a hard error
71
+ // here too, instead of findSpec's silent lowest-path-wins pick (#27).
72
+ const matches = findSpecsById(repoRoot, options.spec);
73
+ if (matches.length === 0) {
59
74
  emit(global, {
60
75
  ok: false,
61
76
  error: { code: ErrorCode.SPEC_NOT_FOUND, message: `validate: spec ${options.spec} not found` },
@@ -63,13 +78,18 @@ export function registerValidate(program) {
63
78
  text: `validate: spec ${options.spec} not found`,
64
79
  });
65
80
  }
66
- const issues = validateSpecFromIndex(spec.id, buildSpecIndex([spec]));
81
+ const issues = [
82
+ ...validateSpecFromIndex(matches[0].id, buildSpecIndex(matches)),
83
+ ...duplicateIdIssues(matches),
84
+ ];
85
+ const dupError = duplicateError(issues);
67
86
  emit(global, {
68
87
  ok: issues.length === 0,
69
- data: { spec: spec.id, issues },
88
+ data: { spec: matches[0].id, issues },
89
+ error: dupError,
70
90
  text: issues.length === 0
71
- ? `validate: ${spec.id} OK`
72
- : `validate: ${spec.id} — ${issues.length} issue(s)\n${formatIssues(issues)}`,
91
+ ? `validate: ${matches[0].id} OK`
92
+ : `validate: ${matches[0].id} — ${issues.length} issue(s)\n${formatIssues(issues)}`,
73
93
  exitCode: issues.length === 0 ? 0 : 1,
74
94
  });
75
95
  }
@@ -79,6 +99,9 @@ export function registerValidate(program) {
79
99
  for (const s of specs) {
80
100
  allIssues.push(...validateSpecFromIndex(s.id, index));
81
101
  }
102
+ // Duplicate spec ids: a hard loader error (issue #27, mode b), not the old
103
+ // silent dedupe. Detected over the already-listed corpus (no extra fs work).
104
+ allIssues.push(...duplicateIdIssues(specs));
82
105
  // Run the repo-wide template-structure validator, gated by --no-templates and a
83
106
  // root-cause existence guard (a repo without the script is not a `templates` issue).
84
107
  const tplDecision = templateValidatorDecision(repoRoot, options);
@@ -103,6 +126,7 @@ export function registerValidate(program) {
103
126
  emit(global, {
104
127
  ok: allIssues.length === 0,
105
128
  data: { specCount: specs.length, issues: allIssues },
129
+ error: duplicateError(allIssues),
106
130
  text: allIssues.length === 0
107
131
  ? `validate: OK (${specs.length} specs)`
108
132
  : `validate: ${allIssues.length} issue(s) across ${specs.length} specs\n${formatIssues(allIssues)}`,
@@ -110,6 +134,21 @@ export function registerValidate(program) {
110
134
  });
111
135
  });
112
136
  }
137
+ /**
138
+ * Promote any duplicate-spec-id issues to the machine-actionable top-level error
139
+ * envelope (issue #27): a headless agent switches on `error.code === DUPLICATE_SPEC_ID`
140
+ * rather than scraping the human text. Returns undefined when there are no collisions,
141
+ * leaving other rule failures (spec-exists, templates) to the issues list + nonzero exit.
142
+ */
143
+ function duplicateError(issues) {
144
+ const dups = issues.filter((i) => i.rule === 'duplicate-spec-id');
145
+ if (dups.length === 0)
146
+ return undefined;
147
+ return {
148
+ code: ErrorCode.DUPLICATE_SPEC_ID,
149
+ message: `${dups.length} duplicate spec id(s) — ${dups.map((d) => d.message).join('; ')}`,
150
+ };
151
+ }
113
152
  function formatIssues(issues) {
114
153
  return issues.map((i) => ` - ${i.file} [${i.rule}] ${i.message.split('\n')[0]}`).join('\n');
115
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { registerBackfill } from './commands/backfill.js';
7
7
  import { registerCheckArtifacts } from './commands/checkArtifacts.js';
8
8
  import { registerCheckPlacement } from './commands/checkPlacement.js';
9
9
  import { registerClaim } from './commands/claim.js';
10
+ import { registerCloseOut } from './commands/close-out.js';
10
11
  import { registerComplete } from './commands/complete.js';
11
12
  import { registerConformance } from './commands/conformance.js';
12
13
  import { registerCreate } from './commands/create.js';
@@ -21,9 +22,11 @@ import { registerList } from './commands/list.js';
21
22
  import { registerMetrics } from './commands/metrics.js';
22
23
  import { registerNext } from './commands/next.js';
23
24
  import { registerPrecedent } from './commands/precedent.js';
25
+ import { registerProceed } from './commands/proceed.js';
24
26
  import { registerProfile } from './commands/profile.js';
25
27
  import { registerReady } from './commands/ready.js';
26
28
  import { registerReconcile } from './commands/reconcile.js';
29
+ import { registerRun } from './commands/run.js';
27
30
  import { registerReadinessRollup } from './commands/rollup.js';
28
31
  import { registerScorecard } from './commands/scorecard.js';
29
32
  import { registerSignoff } from './commands/signoff.js';
@@ -96,11 +99,13 @@ registerNext(program);
96
99
  registerReady(program);
97
100
  registerClaim(program);
98
101
  registerPrecedent(program);
102
+ registerProceed(program);
99
103
  registerStatus(program);
100
104
  registerList(program);
101
105
  registerCreate(program);
102
106
  registerTasks(program);
103
107
  registerComplete(program);
108
+ registerCloseOut(program);
104
109
  registerArchive(program);
105
110
  registerDeferred(program);
106
111
  registerDelta(program);
@@ -115,6 +120,7 @@ registerVerifyRollout(program);
115
120
  registerCheckPlacement(program);
116
121
  registerCheckArtifacts(program);
117
122
  registerReconcile(program);
123
+ registerRun(program);
118
124
  registerSignoff(program);
119
125
  registerWalkthrough(program);
120
126
  registerVerifyAcs(program);
@@ -128,6 +134,8 @@ Examples:
128
134
  $ eos-spec validate --core cl --json # Validate CL specs, JSON output
129
135
  $ eos-spec next --core hr # Show next recommended action for HR (blocker-aware)
130
136
  $ eos-spec next --spec FA-12 --strict # Also enforce mid-pipeline parity gates as BLOCKING
137
+ $ eos-spec run --spec LO-50 --autonomy suggest # Print the planned gate sequence; execute nothing
138
+ $ eos-spec run --spec LO-50 --strict-local # Drive to tasks_generated on the LOCAL model (no cloud fallback)
131
139
  $ eos-spec complete --spec CE-58 --enforce # Hard-block completion until docshots + heal exist (UI-bearing)
132
140
  $ eos-spec ready --core lo # List LO specs whose blockers are all Complete
133
141
  $ eos-spec ready --propose --core lo # Propose blocked_by entries from legacy dependencies
@@ -137,6 +145,8 @@ Examples:
137
145
  $ eos-spec create PF-99 "Foo Feature" # Scaffold spec/plan/tasks files (stubs)
138
146
  $ eos-spec tasks PF-99 # Generate or refresh TASKS file
139
147
  $ eos-spec complete --spec PF-37 --update-registry
148
+ $ eos-spec close-out --spec LO-50 # Verified close-out: promote status->complete when ACs are verified at tasks_generated
149
+ $ eos-spec close-out --spec LO-50 --dry-run # Preview the close-out promotion without writing
140
150
  $ eos-spec archive --spec PF-37 # Archive a completed spec
141
151
  $ eos-spec deferred --sync # Sync deferred dashboard
142
152
  $ eos-spec scorecard --core fm # Per-spec readiness; headline: claimed-complete-but-unverified
@@ -150,6 +160,15 @@ Documentation:
150
160
  specs/_templates/SPEC_GUIDE.md # Spec authoring decision tree
151
161
  specs/_templates/TEMPLATE_INDEX.md # Template selection
152
162
  AI_GUIDE.md # Spec workflow process
163
+
164
+ Environment:
165
+ EOS_SPEC_EVENTS_PATH Override the telemetry sink file. By default events are
166
+ written to <repo-root>/.claude/tmp/eos-spec-events.jsonl,
167
+ where <repo-root> honors --repo-root (falling back to
168
+ git rev-parse --show-toplevel). Set an absolute path to
169
+ redirect the log; set it to /dev/null to discard events.
170
+ EOS_SPEC_RUN_ID Externally-supplied opaque run id to correlate events
171
+ across CLI invocations (defaults to a per-process UUID).
153
172
  `);
154
173
  export async function run(argv) {
155
174
  await program.parseAsync(argv);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,18 @@ export type LogAiCallInput = {
7
7
  tokens?: AiTokens;
8
8
  error?: string;
9
9
  ts?: string;
10
+ /** Optional CLI context, threaded onto the event for per-spec/-core metrics. */
11
+ specId?: string;
12
+ core?: string;
13
+ /** TOOL-06 gate-offload context (`eos-spec run`): the pipeline gate this call
14
+ * drove, the executor that ran it, the run's autonomy mode, and whether it
15
+ * escalated to the cloud. All optional so existing callers are unaffected; when
16
+ * present they let `metrics` roll the call up by gate/executor/autonomy and into
17
+ * the local-vs-cloud ratio. */
18
+ gate?: string;
19
+ executor?: string;
20
+ autonomy?: string;
21
+ escalatedToCloud?: boolean;
10
22
  };
11
23
  /** Log a single AI gateway call as an eos-spec event, computing USD cost from token counts.
12
24
  * Shared by every AI-calling command so token/cost capture is uniform (DRY). */
@@ -12,6 +12,12 @@ export function logAiCall(input) {
12
12
  tokens: input.tokens,
13
13
  costUsd: input.tokens ? computeCostUsd(input.model, input.tokens) : undefined,
14
14
  error: input.error,
15
+ specId: input.specId,
16
+ core: input.core,
17
+ gate: input.gate,
18
+ executor: input.executor,
19
+ autonomy: input.autonomy,
20
+ escalatedToCloud: input.escalatedToCloud,
15
21
  });
16
22
  }
17
23
  //# sourceMappingURL=ai-call.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-call.js","sourceRoot":"","sources":["../../src/lib/ai-call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAYvC;iFACiF;AACjF,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,QAAQ,CAAC;QACP,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACxC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7E,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"ai-call.js","sourceRoot":"","sources":["../../src/lib/ai-call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAwBvC;iFACiF;AACjF,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,QAAQ,CAAC;QACP,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACxC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7E,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { type CloseoutDecision, type CloseoutOptions } from './closeout-predicate.js';
2
+ import { type ReconcileRow } from './reconcile-core.js';
3
+ import type { SpecFile } from './specs.js';
4
+ /**
5
+ * The per-spec close-out core (issue #30, TOOL-06 terminal complement), extracted
6
+ * so the `close-out` command stays a thin adapter and the verified status: ->
7
+ * complete write lives in ONE place the engine owns
8
+ * (docs/adr/0001-engine-owns-verified-close-out-status-promotion.md). fs-bound
9
+ * (reads + writes the spec markdown, delegates to the fs-bound reconcileSpec) — stays
10
+ * behind the package main entry, never `/pure`.
11
+ *
12
+ * close-out composes the three pipeline-tail steps the issue names, reusing their
13
+ * lib functions rather than shelling the CLI:
14
+ * 1. reconcile — heal `pipeline_status` from the on-disk artifacts so the gate
15
+ * sees the TRUE stage, not a stale frontmatter value (reconcileSpec).
16
+ * 2. verify-acs — the conservative gate reads the per-AC `status` that
17
+ * `verify-acs --write` has already promoted to `verified`
18
+ * (decideCloseout mirrors the `hasVerifiedAcceptanceCriteria` signal;
19
+ * close-out does NOT re-run the test harness — that is verify-acs's job).
20
+ * 3. complete — when (and only when) the gate says so, the engine writes
21
+ * `status: complete` (markSpecComplete). An optional `--update-registry`
22
+ * delegation to a consumer audit script remains a separate, explicit
23
+ * opt-in handled by the command layer.
24
+ */
25
+ export type CloseoutRow = {
26
+ id: string;
27
+ core: string;
28
+ /** The conservative gate's verdict (decideCloseout). */
29
+ decision: CloseoutDecision;
30
+ /** The status value written, or that WOULD be written in a dry-run, or null. */
31
+ status: 'complete' | 'in_progress' | null;
32
+ /** True only when this run actually wrote a new `status:` to the spec file. */
33
+ written: boolean;
34
+ /** The reconcile divergence row (pipeline_status recompute) computed as step 1. */
35
+ reconcile: ReconcileRow;
36
+ };
37
+ export type CloseoutSpecOptions = CloseoutOptions & {
38
+ /** When false (dry-run), compute the decision + reconcile divergence but write nothing. */
39
+ write: boolean;
40
+ };
41
+ /**
42
+ * Close out a single spec: reconcile, decide, and (when `write`) materialize the
43
+ * verified `status:` promotion. The decision is computed against the
44
+ * artifact-recomputed stage so a dry-run preview and a real write always agree.
45
+ */
46
+ export declare function closeOutSpec(repoRoot: string, spec: SpecFile, opts: CloseoutSpecOptions): CloseoutRow;
@@ -0,0 +1,34 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { decideCloseout } from './closeout-predicate.js';
3
+ import { markSpecComplete, readFrontmatter, setStatus } from './frontmatter.js';
4
+ import { reconcileSpec } from './reconcile-core.js';
5
+ /**
6
+ * Close out a single spec: reconcile, decide, and (when `write`) materialize the
7
+ * verified `status:` promotion. The decision is computed against the
8
+ * artifact-recomputed stage so a dry-run preview and a real write always agree.
9
+ */
10
+ export function closeOutSpec(repoRoot, spec, opts) {
11
+ const { write, ...decisionOpts } = opts;
12
+ // Step 1 — reconcile. In a real run this writes the artifact-computed
13
+ // `pipeline_status` back; in a dry-run nothing is written, but we still capture the
14
+ // computed stage and feed it to the gate below so dry-run == apply.
15
+ const reconcile = reconcileSpec(repoRoot, spec, write);
16
+ // Step 2 — decide. Read the (possibly just-reconciled) frontmatter and overlay the
17
+ // artifact-computed stage so the gate keys on reality, not a stale/lagging value.
18
+ const text = readFileSync(spec.path, 'utf8');
19
+ const fm = readFrontmatter(text);
20
+ const effectiveFm = { ...fm, pipeline_status: reconcile.computed ?? fm.pipeline_status };
21
+ const decision = decideCloseout(effectiveFm, decisionOpts);
22
+ // Step 3 — promote. The engine OWNS the verified status write; it happens only when
23
+ // the gate returned a status AND --write (non-dry-run) was requested.
24
+ let written = false;
25
+ if (write && decision.nextStatus) {
26
+ const next = decision.nextStatus === 'complete' ? markSpecComplete(text) : setStatus(text, decision.nextStatus);
27
+ if (next !== text) {
28
+ writeFileSync(spec.path, next, 'utf8');
29
+ written = true;
30
+ }
31
+ }
32
+ return { id: spec.id, core: spec.core, decision, status: decision.nextStatus, written, reconcile };
33
+ }
34
+ //# sourceMappingURL=closeout-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closeout-core.js","sourceRoot":"","sources":["../../src/lib/closeout-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAA+C,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtG,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAqB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA2CvE;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,IAAc,EAAE,IAAyB;IACtF,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IAExC,sEAAsE;IACtE,oFAAoF;IACpF,oEAAoE;IACpE,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAEvD,mFAAmF;IACnF,kFAAkF;IAClF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,EAAE,eAAe,EAAE,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,eAAe,EAAE,CAAC;IACzF,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAE3D,oFAAoF;IACpF,sEAAsE;IACtE,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,KAAK,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;QAChH,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YACvC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACrG,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { SpecFrontmatter } from './frontmatter.js';
2
+ import { type RequirementStatus } from './requirements.js';
3
+ /** The pipeline stage a spec must have reached before close-out will promote it.
4
+ * It is the terminal stage of BOTH built-in layouts — `ENCORE1_PIPELINE_SCHEMA` and
5
+ * `BUILDER_PIPELINE_SCHEMA` `statusOrder` both end on it — kept as a named constant
6
+ * so the canonical predicate carries no magic string. A consumer on a custom layout
7
+ * can override it via {@link CloseoutOptions.terminalStage}. */
8
+ export declare const CLOSEOUT_TERMINAL_STAGE = "tasks_generated";
9
+ /** The default closeable AC vocabulary: encoreos's binary planned->verified model.
10
+ * A consumer on the builder/Switchboard model passes `['verified', 'hand_closed']`
11
+ * (and may add `'deferred'`) via {@link CloseoutOptions.closeableStatuses}. */
12
+ export declare const DEFAULT_CLOSEABLE_AC_STATUSES: readonly RequirementStatus[];
13
+ /** Pre-work `status:` values that close-out may UPGRADE to `in_progress` once work
14
+ * has demonstrably started (>=1 closeable AC) but the spec is not yet closeable. An
15
+ * empty/absent status is also treated as pre-work. Conservative: a status OUTSIDE
16
+ * this set is human-meaningful and is left untouched (we never clobber it). */
17
+ export declare const DEFAULT_PRE_WORK_STATUSES: readonly string[];
18
+ export type CloseoutOptions = {
19
+ /** AC statuses that count as terminally closed (default `['verified']`). */
20
+ closeableStatuses?: readonly string[];
21
+ /** The pipeline stage gating promotion (default `'tasks_generated'`). */
22
+ terminalStage?: string;
23
+ /** Pre-work statuses eligible for the in_progress nudge (default {@link DEFAULT_PRE_WORK_STATUSES}). */
24
+ preWorkStatuses?: readonly string[];
25
+ };
26
+ export type CloseoutDecision = {
27
+ /** `'complete'` => promote; `'in_progress'` => nudge a pre-work status; `null` => leave unchanged. */
28
+ nextStatus: 'complete' | 'in_progress' | null;
29
+ /** Human-readable justification — surfaced in `--json` output and per-spec telemetry. */
30
+ reason: string;
31
+ };
32
+ /**
33
+ * Decide whether the spec described by `fm` may be closed out. Pure over parsed
34
+ * frontmatter; see the module header for the canonical predicate and invariants.
35
+ */
36
+ export declare function decideCloseout(fm: SpecFrontmatter, opts?: CloseoutOptions): CloseoutDecision;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The conservative close-out gate (issue #30, TOOL-06 terminal complement).
3
+ *
4
+ * `decideCloseout` is the single source of truth for whether a spec's
5
+ * org-lifecycle `status:` may be promoted to `complete` — the verified close-out
6
+ * the engine now OWNS rather than delegating to a consumer audit script
7
+ * (docs/adr/0001-engine-owns-verified-close-out-status-promotion.md). It is a PURE
8
+ * leaf: it reads ONLY already-parsed frontmatter (no node:fs, no child_process, no
9
+ * network), so it sits behind the package main entry yet stays as cheap and
10
+ * side-effect-free as the predicate registry it mirrors. (Deliberately NOT wired
11
+ * into `/pure` — see CLAUDE.md; it is importable from the main graph.)
12
+ *
13
+ * The canonical predicate (deliberately conservative — never blind-stamp):
14
+ * closeable(spec) <=>
15
+ * nonEmpty(acceptance_criteria)
16
+ * AND acceptance_criteria.every(ac => ac.status in closeableStatuses)
17
+ * AND pipeline_status === terminalStage (default 'tasks_generated')
18
+ * => status: complete
19
+ * else: leave unchanged (null) — or nudge a *pre-work* status to in_progress once
20
+ * some ACs are terminal but the spec is not yet closeable.
21
+ *
22
+ * Two invariants the verb must never break:
23
+ * 1. NEVER downgrade an already complete / archived / superseded / deferred spec —
24
+ * those are terminal org-lifecycle states; close-out returns `null` for them.
25
+ * 2. NEVER promote past the evidence — a single `planned` AC, or a pipeline_status
26
+ * short of the terminal stage, blocks `complete`.
27
+ *
28
+ * The terminal AC vocabulary is PARAMETRIZED so both consuming layouts pass:
29
+ * - encoreos: the binary planned->verified model => closeableStatuses ['verified'].
30
+ * - Switchboard/builder: verified + hand_closed => ['verified', 'hand_closed'].
31
+ * It mirrors the existing `hasVerifiedAcceptanceCriteria` signal (which keys on
32
+ * `allAcceptanceCriteriaTerminal`) but is STRICTER by default: only `verified`
33
+ * closes a spec unless the consumer opts `hand_closed`/`deferred` in.
34
+ */
35
+ import { isCompleteStatus, isTerminalStatus } from './blockers.js';
36
+ import { normalizeAcceptanceCriteria } from './requirements.js';
37
+ /** The pipeline stage a spec must have reached before close-out will promote it.
38
+ * It is the terminal stage of BOTH built-in layouts — `ENCORE1_PIPELINE_SCHEMA` and
39
+ * `BUILDER_PIPELINE_SCHEMA` `statusOrder` both end on it — kept as a named constant
40
+ * so the canonical predicate carries no magic string. A consumer on a custom layout
41
+ * can override it via {@link CloseoutOptions.terminalStage}. */
42
+ export const CLOSEOUT_TERMINAL_STAGE = 'tasks_generated';
43
+ /** The default closeable AC vocabulary: encoreos's binary planned->verified model.
44
+ * A consumer on the builder/Switchboard model passes `['verified', 'hand_closed']`
45
+ * (and may add `'deferred'`) via {@link CloseoutOptions.closeableStatuses}. */
46
+ export const DEFAULT_CLOSEABLE_AC_STATUSES = ['verified'];
47
+ /** Pre-work `status:` values that close-out may UPGRADE to `in_progress` once work
48
+ * has demonstrably started (>=1 closeable AC) but the spec is not yet closeable. An
49
+ * empty/absent status is also treated as pre-work. Conservative: a status OUTSIDE
50
+ * this set is human-meaningful and is left untouched (we never clobber it). */
51
+ export const DEFAULT_PRE_WORK_STATUSES = [
52
+ 'draft',
53
+ 'todo',
54
+ 'backlog',
55
+ 'planned',
56
+ 'not started',
57
+ 'not_started',
58
+ 'stub',
59
+ 'new',
60
+ 'open',
61
+ ];
62
+ /** True when `status` is empty/absent or one of the pre-work values (eligible for the nudge). */
63
+ function isPreWork(status, set) {
64
+ if (status === undefined)
65
+ return true;
66
+ const norm = status.trim().toLowerCase();
67
+ if (norm === '')
68
+ return true;
69
+ return set.includes(norm);
70
+ }
71
+ /**
72
+ * Decide whether the spec described by `fm` may be closed out. Pure over parsed
73
+ * frontmatter; see the module header for the canonical predicate and invariants.
74
+ */
75
+ export function decideCloseout(fm, opts = {}) {
76
+ const closeable = opts.closeableStatuses ?? DEFAULT_CLOSEABLE_AC_STATUSES;
77
+ const terminalStage = opts.terminalStage ?? CLOSEOUT_TERMINAL_STAGE;
78
+ const preWork = opts.preWorkStatuses ?? DEFAULT_PRE_WORK_STATUSES;
79
+ // (1) Terminal-state guard: NEVER downgrade. An already complete/implemented spec,
80
+ // or an archived/superseded/blocked/deferred one, is left exactly as-is. Keys on the
81
+ // org-lifecycle `status` axis (+ the `superseded_by` pointer), mirroring the
82
+ // navigator's own terminal checks (isCompleteStatus / isTerminalStatus in blockers.ts).
83
+ if (isCompleteStatus(fm.status)) {
84
+ return { nextStatus: null, reason: `already complete (status: ${fm.status}); never downgrade` };
85
+ }
86
+ if (isTerminalStatus(fm.status, fm.superseded_by)) {
87
+ const why = fm.superseded_by ? `superseded_by: ${fm.superseded_by}` : `status: ${fm.status}`;
88
+ return { nextStatus: null, reason: `terminal org-lifecycle state (${why}); never downgrade` };
89
+ }
90
+ // (2) ACs are the unit of evidence. No well-formed AC => nothing to close out.
91
+ // (Malformed/id-less entries are dropped by normalizeAcceptanceCriteria — `validate`
92
+ // flags them separately — so they never silently satisfy the gate.)
93
+ const acs = normalizeAcceptanceCriteria(fm.acceptance_criteria).acs;
94
+ if (acs.length === 0) {
95
+ return { nextStatus: null, reason: 'no acceptance criteria — nothing to close out' };
96
+ }
97
+ const closeableSet = new Set(closeable);
98
+ const remaining = acs.filter((ac) => !closeableSet.has(ac.status));
99
+ const allCloseable = remaining.length === 0;
100
+ const someClosed = acs.some((ac) => closeableSet.has(ac.status));
101
+ const pipelineReady = fm.pipeline_status === terminalStage;
102
+ // (3) Closeable => promote to complete (the verified close-out the engine owns).
103
+ if (allCloseable && pipelineReady) {
104
+ return {
105
+ nextStatus: 'complete',
106
+ reason: `all ${acs.length} AC(s) in {${closeable.join(', ')}} and pipeline_status=${terminalStage}`,
107
+ };
108
+ }
109
+ // (4) Not closeable. Offer a conservative in_progress UPGRADE only when work has
110
+ // demonstrably started (>=1 closeable AC) AND the current status is pre-work — never
111
+ // a no-op restamp, never a clobber of a human-meaningful status, never a downgrade.
112
+ if (someClosed && !allCloseable && isPreWork(fm.status, preWork)) {
113
+ return {
114
+ nextStatus: 'in_progress',
115
+ reason: `work in progress — ${acs.length - remaining.length}/${acs.length} AC(s) closed, ${remaining.length} still open`,
116
+ };
117
+ }
118
+ // (5) Otherwise leave unchanged, with a precise reason for the no-op.
119
+ if (!allCloseable) {
120
+ return {
121
+ nextStatus: null,
122
+ reason: `${remaining.length}/${acs.length} AC(s) not in {${closeable.join(', ')}} (e.g. ${remaining[0].id})`,
123
+ };
124
+ }
125
+ return {
126
+ nextStatus: null,
127
+ reason: `ACs closeable but pipeline_status=${fm.pipeline_status ?? '(none)'} != ${terminalStage}`,
128
+ };
129
+ }
130
+ //# sourceMappingURL=closeout-predicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closeout-predicate.js","sourceRoot":"","sources":["../../src/lib/closeout-predicate.ts"],"names":[],"mappings":"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"}
@@ -70,6 +70,16 @@ export type SpecConfig = {
70
70
  pipeline?: {
71
71
  layout?: 'encore1' | 'builder';
72
72
  };
73
+ /** D2: opt-in verification-coverage gate on `eos-spec complete`. Absent (the
74
+ * whole block, or the `verification_coverage_min` key) ⇒ no gate — fully
75
+ * backward-compatible. `per_core` overrides win over the repo-wide default;
76
+ * see `resolveCoverageThreshold` in `lib/coverage-gate.ts`. Distinct from
77
+ * `defaults.test_coverage_target` (test-LINE coverage, 0–100): this is the
78
+ * requirement-VERIFICATION ratio (0–1), i.e. requirementsVerified/requirementsTotal. */
79
+ gate_thresholds?: {
80
+ verification_coverage_min?: number;
81
+ per_core?: Record<string, number>;
82
+ };
73
83
  };
74
84
  export declare function loadConfig(repoRoot: string, configOverride?: string): SpecConfig;
75
85
  export declare function resetConfigCache(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
package/dist/lib/cost.js CHANGED
@@ -2,6 +2,13 @@
2
2
  * Cross-package import is blocked by tools/eos-spec's tsconfig rootDir; tests assert parity. */
3
3
  export const MODEL_RATES = {
4
4
  'anthropic/claude-sonnet-4': { promptPer1m: 3, completionPer1m: 15 },
5
+ // TOOL-06 local models (`eos-spec run` default offload, Ollama): self-hosted, so
6
+ // their marginal token cost is $0. Listing them with zero rates makes a
7
+ // strict-local run report $0.0000 (an honest "free"), rather than `(unknown)`
8
+ // which a missing rate would yield. An unknown local model still returns null
9
+ // (handled in metrics) — only these named defaults are pinned to zero.
10
+ 'qwen3-coder:30b': { promptPer1m: 0, completionPer1m: 0 },
11
+ 'gpt-oss:20b': { promptPer1m: 0, completionPer1m: 0 },
5
12
  };
6
13
  export function computeCostUsd(model, tokens) {
7
14
  const rate = MODEL_RATES[model];
@@ -1 +1 @@
1
- {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/lib/cost.ts"],"names":[],"mappings":"AAAA;iGACiG;AACjG,MAAM,CAAC,MAAM,WAAW,GAAqE;IAC3F,2BAA2B,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE;CACrE,CAAC;AAIF,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,MAAgB;IAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;AACnG,CAAC"}
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/lib/cost.ts"],"names":[],"mappings":"AAAA;iGACiG;AACjG,MAAM,CAAC,MAAM,WAAW,GAAqE;IAC3F,2BAA2B,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE;IACpE,iFAAiF;IACjF,wEAAwE;IACxE,8EAA8E;IAC9E,8EAA8E;IAC9E,uEAAuE;IACvE,iBAAiB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;IACzD,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;CACtD,CAAC;AAIF,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,MAAgB;IAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;AACnG,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { SpecConfig } from './config.js';
2
+ /** Verdicts a single `eos-spec complete` invocation can reach for the D2
3
+ * verification-coverage gate. `no-gate` means the consuming repo never opted
4
+ * in (`gate_thresholds` absent from `specs/config.yaml`) — behavior is
5
+ * unchanged from before this gate existed. */
6
+ export type CoverageGateVerdict = 'no-gate' | 'pass' | 'waived' | 'blocked';
7
+ /**
8
+ * Resolve the verification-coverage threshold (a 0–1 ratio) for a core, per the
9
+ * D2 design: a `per_core` override wins, then the repo-wide
10
+ * `verification_coverage_min`, else `null` — meaning no gate is configured at
11
+ * all. `null` is load-bearing: it is how the gate stays fully opt-in (a repo
12
+ * that never sets `gate_thresholds` sees zero behavior change). Pure.
13
+ */
14
+ export declare function resolveCoverageThreshold(config: SpecConfig, core: string): number | null;
15
+ /**
16
+ * Evaluate the coverage gate's verdict from a computed ratio, the resolved
17
+ * threshold, and whether the spec carries a `coverage-waived` sign-off marker.
18
+ * Pure — the CLI wires the real coverage/threshold/waiver lookups.
19
+ */
20
+ export declare function evaluateCoverageGate(input: {
21
+ ratio: number;
22
+ threshold: number | null;
23
+ hasWaiver: boolean;
24
+ }): {
25
+ gate: CoverageGateVerdict;
26
+ };
27
+ /**
28
+ * A single spec's verification coverage — `requirementsVerified/requirementsTotal`
29
+ * from the same machinery `eos-spec scorecard` runs (`scanVerifies` +
30
+ * `buildScorecardForCore`), mirroring `spec-debt.ts`'s
31
+ * `isClaimedCompleteUnverified` so `scorecard`/`complete`/this gate never drift.
32
+ * `total === 0` (no declared AC/US/FR) is vacuously fully covered (`ratio: 1`) —
33
+ * there is nothing left un-backed, though a caller may still want to treat an
34
+ * all-zero "complete" spec as advisory-suspicious. An unknown spec id (no
35
+ * scorecard row) also reads as `{ verified: 0, total: 0, ratio: 1 }`; callers
36
+ * that gate on this should have already confirmed the spec exists (e.g. via
37
+ * `findSpec`) before calling in.
38
+ */
39
+ export declare function verificationCoverage(repoRoot: string, specId: string): {
40
+ verified: number;
41
+ total: number;
42
+ ratio: number;
43
+ };