@encore-os/eos-spec 0.8.0 → 0.9.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.
- package/dist/commands/close-out.d.ts +2 -0
- package/dist/commands/close-out.js +167 -0
- package/dist/commands/close-out.js.map +1 -0
- package/dist/commands/conformance.js +20 -1
- package/dist/commands/conformance.js.map +1 -1
- package/dist/commands/metrics.js +15 -0
- package/dist/commands/metrics.js.map +1 -1
- package/dist/commands/run.d.ts +10 -0
- package/dist/commands/run.js +230 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.js +46 -7
- package/dist/commands/validate.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ai-call.d.ts +12 -0
- package/dist/lib/ai-call.js +6 -0
- package/dist/lib/ai-call.js.map +1 -1
- package/dist/lib/closeout-core.d.ts +46 -0
- package/dist/lib/closeout-core.js +34 -0
- package/dist/lib/closeout-core.js.map +1 -0
- package/dist/lib/closeout-predicate.d.ts +36 -0
- package/dist/lib/closeout-predicate.js +130 -0
- package/dist/lib/closeout-predicate.js.map +1 -0
- package/dist/lib/cost.js +7 -0
- package/dist/lib/cost.js.map +1 -1
- package/dist/lib/events.d.ts +11 -0
- package/dist/lib/events.js.map +1 -1
- package/dist/lib/frontmatter.d.ts +22 -0
- package/dist/lib/frontmatter.js +37 -0
- package/dist/lib/frontmatter.js.map +1 -1
- package/dist/lib/gate-executor.d.ts +80 -0
- package/dist/lib/gate-executor.js +311 -0
- package/dist/lib/gate-executor.js.map +1 -0
- package/dist/lib/llm-health.d.ts +28 -0
- package/dist/lib/llm-health.js +46 -0
- package/dist/lib/llm-health.js.map +1 -0
- package/dist/lib/metrics.d.ts +26 -0
- package/dist/lib/metrics.js +35 -0
- package/dist/lib/metrics.js.map +1 -1
- package/dist/lib/next-action.d.ts +10 -4
- package/dist/lib/next-action.js +10 -4
- package/dist/lib/next-action.js.map +1 -1
- package/dist/lib/ollama-embed.d.ts +5 -0
- package/dist/lib/ollama-embed.js +5 -0
- package/dist/lib/ollama-embed.js.map +1 -1
- package/dist/lib/output.d.ts +3 -0
- package/dist/lib/output.js +3 -0
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/pipeline-config.js +10 -0
- package/dist/lib/pipeline-config.js.map +1 -1
- package/dist/lib/pipeline-map.js +9 -0
- package/dist/lib/pipeline-map.js.map +1 -1
- package/dist/lib/predicate-registry.js +7 -0
- package/dist/lib/predicate-registry.js.map +1 -1
- package/dist/lib/run-pipeline.d.ts +118 -0
- package/dist/lib/run-pipeline.js +106 -0
- package/dist/lib/run-pipeline.js.map +1 -0
- package/dist/lib/spec-pure.d.ts +69 -4
- package/dist/lib/spec-pure.js +125 -15
- package/dist/lib/spec-pure.js.map +1 -1
- package/dist/lib/specs.d.ts +3 -3
- package/dist/lib/specs.js +43 -20
- package/dist/lib/specs.js.map +1 -1
- package/dist/lib/version.d.ts +1 -1
- package/dist/lib/version.js +1 -1
- 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 {
|
|
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
|
-
|
|
58
|
-
|
|
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 =
|
|
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:
|
|
88
|
+
data: { spec: matches[0].id, issues },
|
|
89
|
+
error: dupError,
|
|
70
90
|
text: issues.length === 0
|
|
71
|
-
? `validate: ${
|
|
72
|
-
: `validate: ${
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,
|
|
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';
|
|
@@ -24,6 +25,7 @@ import { registerPrecedent } from './commands/precedent.js';
|
|
|
24
25
|
import { registerProfile } from './commands/profile.js';
|
|
25
26
|
import { registerReady } from './commands/ready.js';
|
|
26
27
|
import { registerReconcile } from './commands/reconcile.js';
|
|
28
|
+
import { registerRun } from './commands/run.js';
|
|
27
29
|
import { registerReadinessRollup } from './commands/rollup.js';
|
|
28
30
|
import { registerScorecard } from './commands/scorecard.js';
|
|
29
31
|
import { registerSignoff } from './commands/signoff.js';
|
|
@@ -101,6 +103,7 @@ registerList(program);
|
|
|
101
103
|
registerCreate(program);
|
|
102
104
|
registerTasks(program);
|
|
103
105
|
registerComplete(program);
|
|
106
|
+
registerCloseOut(program);
|
|
104
107
|
registerArchive(program);
|
|
105
108
|
registerDeferred(program);
|
|
106
109
|
registerDelta(program);
|
|
@@ -115,6 +118,7 @@ registerVerifyRollout(program);
|
|
|
115
118
|
registerCheckPlacement(program);
|
|
116
119
|
registerCheckArtifacts(program);
|
|
117
120
|
registerReconcile(program);
|
|
121
|
+
registerRun(program);
|
|
118
122
|
registerSignoff(program);
|
|
119
123
|
registerWalkthrough(program);
|
|
120
124
|
registerVerifyAcs(program);
|
|
@@ -128,6 +132,8 @@ Examples:
|
|
|
128
132
|
$ eos-spec validate --core cl --json # Validate CL specs, JSON output
|
|
129
133
|
$ eos-spec next --core hr # Show next recommended action for HR (blocker-aware)
|
|
130
134
|
$ eos-spec next --spec FA-12 --strict # Also enforce mid-pipeline parity gates as BLOCKING
|
|
135
|
+
$ eos-spec run --spec LO-50 --autonomy suggest # Print the planned gate sequence; execute nothing
|
|
136
|
+
$ eos-spec run --spec LO-50 --strict-local # Drive to tasks_generated on the LOCAL model (no cloud fallback)
|
|
131
137
|
$ eos-spec complete --spec CE-58 --enforce # Hard-block completion until docshots + heal exist (UI-bearing)
|
|
132
138
|
$ eos-spec ready --core lo # List LO specs whose blockers are all Complete
|
|
133
139
|
$ eos-spec ready --propose --core lo # Propose blocked_by entries from legacy dependencies
|
|
@@ -137,6 +143,8 @@ Examples:
|
|
|
137
143
|
$ eos-spec create PF-99 "Foo Feature" # Scaffold spec/plan/tasks files (stubs)
|
|
138
144
|
$ eos-spec tasks PF-99 # Generate or refresh TASKS file
|
|
139
145
|
$ eos-spec complete --spec PF-37 --update-registry
|
|
146
|
+
$ eos-spec close-out --spec LO-50 # Verified close-out: promote status->complete when ACs are verified at tasks_generated
|
|
147
|
+
$ eos-spec close-out --spec LO-50 --dry-run # Preview the close-out promotion without writing
|
|
140
148
|
$ eos-spec archive --spec PF-37 # Archive a completed spec
|
|
141
149
|
$ eos-spec deferred --sync # Sync deferred dashboard
|
|
142
150
|
$ eos-spec scorecard --core fm # Per-spec readiness; headline: claimed-complete-but-unverified
|
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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"}
|
package/dist/lib/ai-call.d.ts
CHANGED
|
@@ -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). */
|
package/dist/lib/ai-call.js
CHANGED
|
@@ -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
|
package/dist/lib/ai-call.js.map
CHANGED
|
@@ -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;
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,2BAA2B,EAA0B,MAAM,mBAAmB,CAAC;AAExF;;;;iEAIiE;AACjE,MAAM,CAAC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAEzD;;gFAEgF;AAChF,MAAM,CAAC,MAAM,6BAA6B,GAAiC,CAAC,UAAU,CAAC,CAAC;AAExF;;;gFAGgF;AAChF,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,OAAO;IACP,MAAM;IACN,SAAS;IACT,SAAS;IACT,aAAa;IACb,aAAa;IACb,MAAM;IACN,KAAK;IACL,MAAM;CACP,CAAC;AAkBF,iGAAiG;AACjG,SAAS,SAAS,CAAC,MAA0B,EAAE,GAAsB;IACnE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAmB,EAAE,OAAwB,EAAE;IAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,IAAI,6BAA6B,CAAC;IAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,IAAI,yBAAyB,CAAC;IAElE,mFAAmF;IACnF,qFAAqF;IACrF,6EAA6E;IAC7E,wFAAwF;IACxF,IAAI,gBAAgB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC,MAAM,oBAAoB,EAAE,CAAC;IAClG,CAAC;IACD,IAAI,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC;QAC7F,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,iCAAiC,GAAG,oBAAoB,EAAE,CAAC;IAChG,CAAC;IAED,+EAA+E;IAC/E,qFAAqF;IACrF,oEAAoE;IACpE,MAAM,GAAG,GAAG,2BAA2B,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC;IACpE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,+CAA+C,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,SAAS,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,EAAE,CAAC,eAAe,KAAK,aAAa,CAAC;IAE3D,iFAAiF;IACjF,IAAI,YAAY,IAAI,aAAa,EAAE,CAAC;QAClC,OAAO;YACL,UAAU,EAAE,UAAU;YACtB,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,cAAc,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,aAAa,EAAE;SACpG,CAAC;IACJ,CAAC;IAED,iFAAiF;IACjF,qFAAqF;IACrF,oFAAoF;IACpF,IAAI,UAAU,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QACjE,OAAO;YACL,UAAU,EAAE,aAAa;YACzB,MAAM,EAAE,sBAAsB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,kBAAkB,SAAS,CAAC,MAAM,aAAa;SACzH,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,kBAAkB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,SAAS,CAAC,CAAC,CAAE,CAAC,EAAE,GAAG;SAC9G,CAAC;IACJ,CAAC;IACD,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,qCAAqC,EAAE,CAAC,eAAe,IAAI,QAAQ,OAAO,aAAa,EAAE;KAClG,CAAC;AACJ,CAAC"}
|
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];
|
package/dist/lib/cost.js.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/lib/events.d.ts
CHANGED
|
@@ -29,6 +29,17 @@ export type EosSpecEvent = {
|
|
|
29
29
|
* fired (expected, autonomy working); 'crash' = unexpected tooling failure.
|
|
30
30
|
* Derived at read time if absent; writers may set it explicitly. */
|
|
31
31
|
haltCause?: 'gate' | 'crash';
|
|
32
|
+
/** TOOL-06 (`eos-spec run`) gate-offload fields — set on a per-gate executor
|
|
33
|
+
* event so `metrics` can roll up per-gate model/executor/autonomy and the
|
|
34
|
+
* local-vs-cloud ratio. All optional + additive. */
|
|
35
|
+
/** Which executor ran the gate (e.g. 'direct-model'). Presence marks an event
|
|
36
|
+
* as a gate-offload event for the metrics execution rollup. */
|
|
37
|
+
executor?: string;
|
|
38
|
+
/** The run's autonomy mode the gate executed under ('drive'). */
|
|
39
|
+
autonomy?: string;
|
|
40
|
+
/** True when the gate fell back from an unhealthy LOCAL endpoint to the cloud
|
|
41
|
+
* gateway (AC-4). Absent/false ⇒ the gate ran on the local model. */
|
|
42
|
+
escalatedToCloud?: boolean;
|
|
32
43
|
/** D3 run correlation: an opaque, PHI-free id for the originating process/run.
|
|
33
44
|
* Set once per process (see RUN_ID below) — never a spec title/path. */
|
|
34
45
|
runId?: string;
|
package/dist/lib/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA6C1C;;;;0EAI0E;AAC1E,MAAM,CAAC,MAAM,MAAM,GAAW,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,UAAU,EAAE,CAAC;AAE1E;kFACkF;AAClF,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,uBAAuB,CAAC,CAAC;AAEpF;;mEAEmE;AACnE,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACrD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAmB,EAAE,OAA0B,EAAE;IACxE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,WAAW,EAAE,CAAC;QAC5E,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,MAAM;IACN,WAAW;IACX,KAAK;IACL,iBAAiB;IACjB,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AACH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/F;2FAC2F;AAC3F,MAAM,UAAU,UAAU,CAAC,OAAgC;IACzD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACjE,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -36,6 +36,28 @@ export type SpecFrontmatter = {
|
|
|
36
36
|
* Returns the text unchanged when there is no frontmatter block.
|
|
37
37
|
*/
|
|
38
38
|
export declare function setPipelineStatus(text: string, status: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Surgically set the org-lifecycle `status:` field inside the leading frontmatter
|
|
41
|
+
* block (scalar field, exactly like {@link setPipelineStatus}). Replaces the
|
|
42
|
+
* existing top-level `status:` line or appends one. The replace regex is
|
|
43
|
+
* column-0-anchored, so it NEVER touches `pipeline_status:` (a different key) or an
|
|
44
|
+
* indented per-AC `status:` inside an `acceptance_criteria:` list item. Returns the
|
|
45
|
+
* text unchanged when there is no frontmatter block.
|
|
46
|
+
*
|
|
47
|
+
* This is the engine's canonical writer for the verified close-out promotion
|
|
48
|
+
* (docs/adr/0001-engine-owns-verified-close-out-status-promotion.md): close-out
|
|
49
|
+
* OWNS the `status:` -> complete write in-engine rather than delegating it to a
|
|
50
|
+
* consumer audit script. (`backfill` still owns the inverse DOWNGRADE via its own
|
|
51
|
+
* `rewriteStatusLine`; these are deliberately separate verbs.)
|
|
52
|
+
*/
|
|
53
|
+
export declare function setStatus(text: string, status: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Mark a spec complete by setting `status: complete` — the verified close-out the
|
|
56
|
+
* engine owns (ADR-0001). A thin, intention-revealing wrapper over {@link setStatus};
|
|
57
|
+
* the `close-out` verb gates the call behind the conservative `decideCloseout`
|
|
58
|
+
* predicate, so this is only ever reached on real, AC-backed evidence.
|
|
59
|
+
*/
|
|
60
|
+
export declare function markSpecComplete(text: string): string;
|
|
39
61
|
/**
|
|
40
62
|
* Surgically set `superseded_by: <id>` in the leading frontmatter block (scalar
|
|
41
63
|
* field, like pipeline_status). Replaces the existing line or appends one. Used by
|
package/dist/lib/frontmatter.js
CHANGED
|
@@ -17,6 +17,43 @@ export function setPipelineStatus(text, status) {
|
|
|
17
17
|
// function replacer avoids `$` in newBlock being treated as a backreference
|
|
18
18
|
return text.replace(FRONTMATTER_RE, () => `---\n${newBlock}\n---`);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Surgically set the org-lifecycle `status:` field inside the leading frontmatter
|
|
22
|
+
* block (scalar field, exactly like {@link setPipelineStatus}). Replaces the
|
|
23
|
+
* existing top-level `status:` line or appends one. The replace regex is
|
|
24
|
+
* column-0-anchored, so it NEVER touches `pipeline_status:` (a different key) or an
|
|
25
|
+
* indented per-AC `status:` inside an `acceptance_criteria:` list item. Returns the
|
|
26
|
+
* text unchanged when there is no frontmatter block.
|
|
27
|
+
*
|
|
28
|
+
* This is the engine's canonical writer for the verified close-out promotion
|
|
29
|
+
* (docs/adr/0001-engine-owns-verified-close-out-status-promotion.md): close-out
|
|
30
|
+
* OWNS the `status:` -> complete write in-engine rather than delegating it to a
|
|
31
|
+
* consumer audit script. (`backfill` still owns the inverse DOWNGRADE via its own
|
|
32
|
+
* `rewriteStatusLine`; these are deliberately separate verbs.)
|
|
33
|
+
*/
|
|
34
|
+
export function setStatus(text, status) {
|
|
35
|
+
const match = FRONTMATTER_RE.exec(text);
|
|
36
|
+
if (!match)
|
|
37
|
+
return text;
|
|
38
|
+
const block = match[1];
|
|
39
|
+
const line = `status: ${status}`;
|
|
40
|
+
// `^status:` (no leading whitespace) cannot match `pipeline_status:` (starts with
|
|
41
|
+
// `p`) nor an indented list-item `status:` — only the top-level org-lifecycle key.
|
|
42
|
+
const statusLineRe = /^status:.*$/m;
|
|
43
|
+
const newBlock = statusLineRe.test(block) ? block.replace(statusLineRe, line) : `${block}\n${line}`;
|
|
44
|
+
if (newBlock === block)
|
|
45
|
+
return text;
|
|
46
|
+
return text.replace(FRONTMATTER_RE, () => `---\n${newBlock}\n---`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Mark a spec complete by setting `status: complete` — the verified close-out the
|
|
50
|
+
* engine owns (ADR-0001). A thin, intention-revealing wrapper over {@link setStatus};
|
|
51
|
+
* the `close-out` verb gates the call behind the conservative `decideCloseout`
|
|
52
|
+
* predicate, so this is only ever reached on real, AC-backed evidence.
|
|
53
|
+
*/
|
|
54
|
+
export function markSpecComplete(text) {
|
|
55
|
+
return setStatus(text, 'complete');
|
|
56
|
+
}
|
|
20
57
|
/**
|
|
21
58
|
* Surgically set `superseded_by: <id>` in the leading frontmatter block (scalar
|
|
22
59
|
* field, like pipeline_status). Replaces the existing line or appends one. Used by
|