@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.
- package/LICENSE +17 -0
- package/bin/check-dist-fresh.js +51 -0
- package/bin/eos-spec.js +7 -0
- package/dist/commands/ac-backfill.d.ts +31 -0
- package/dist/commands/ac-backfill.js +198 -0
- package/dist/commands/ac-backfill.js.map +1 -0
- package/dist/commands/archive.d.ts +2 -0
- package/dist/commands/archive.js +101 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/audit.d.ts +30 -0
- package/dist/commands/audit.js +107 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/backfill.d.ts +41 -0
- package/dist/commands/backfill.js +239 -0
- package/dist/commands/backfill.js.map +1 -0
- package/dist/commands/checkArtifacts.d.ts +2 -0
- package/dist/commands/checkArtifacts.js +48 -0
- package/dist/commands/checkArtifacts.js.map +1 -0
- package/dist/commands/checkPlacement.d.ts +2 -0
- package/dist/commands/checkPlacement.js +31 -0
- package/dist/commands/checkPlacement.js.map +1 -0
- package/dist/commands/claim.d.ts +4 -0
- package/dist/commands/claim.js +46 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/complete.d.ts +2 -0
- package/dist/commands/complete.js +138 -0
- package/dist/commands/complete.js.map +1 -0
- package/dist/commands/conformance.d.ts +23 -0
- package/dist/commands/conformance.js +124 -0
- package/dist/commands/conformance.js.map +1 -0
- package/dist/commands/create.d.ts +6 -0
- package/dist/commands/create.js +277 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/deferred.d.ts +2 -0
- package/dist/commands/deferred.js +85 -0
- package/dist/commands/deferred.js.map +1 -0
- package/dist/commands/delta.d.ts +17 -0
- package/dist/commands/delta.js +292 -0
- package/dist/commands/delta.js.map +1 -0
- package/dist/commands/freshness.d.ts +13 -0
- package/dist/commands/freshness.js +72 -0
- package/dist/commands/freshness.js.map +1 -0
- package/dist/commands/funnel.d.ts +2 -0
- package/dist/commands/funnel.js +61 -0
- package/dist/commands/funnel.js.map +1 -0
- package/dist/commands/gen-tests.d.ts +2 -0
- package/dist/commands/gen-tests.js +53 -0
- package/dist/commands/gen-tests.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +64 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +9 -0
- package/dist/commands/list.js +61 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/metrics.d.ts +2 -0
- package/dist/commands/metrics.js +66 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/next.d.ts +48 -0
- package/dist/commands/next.js +344 -0
- package/dist/commands/next.js.map +1 -0
- package/dist/commands/precedent.d.ts +66 -0
- package/dist/commands/precedent.js +343 -0
- package/dist/commands/precedent.js.map +1 -0
- package/dist/commands/ready.d.ts +28 -0
- package/dist/commands/ready.js +147 -0
- package/dist/commands/ready.js.map +1 -0
- package/dist/commands/reconcile.d.ts +44 -0
- package/dist/commands/reconcile.js +187 -0
- package/dist/commands/reconcile.js.map +1 -0
- package/dist/commands/rollup.d.ts +2 -0
- package/dist/commands/rollup.js +43 -0
- package/dist/commands/rollup.js.map +1 -0
- package/dist/commands/scorecard.d.ts +11 -0
- package/dist/commands/scorecard.js +55 -0
- package/dist/commands/scorecard.js.map +1 -0
- package/dist/commands/signoff.d.ts +2 -0
- package/dist/commands/signoff.js +114 -0
- package/dist/commands/signoff.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +100 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tasks.d.ts +13 -0
- package/dist/commands/tasks.js +81 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/commands/validate.d.ts +16 -0
- package/dist/commands/validate.js +89 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/verify-acs.d.ts +15 -0
- package/dist/commands/verify-acs.js +196 -0
- package/dist/commands/verify-acs.js.map +1 -0
- package/dist/commands/verifyRollout.d.ts +2 -0
- package/dist/commands/verifyRollout.js +125 -0
- package/dist/commands/verifyRollout.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/ac-draft-prompt.d.ts +18 -0
- package/dist/lib/ac-draft-prompt.js +38 -0
- package/dist/lib/ac-draft-prompt.js.map +1 -0
- package/dist/lib/ac-response-parser.d.ts +18 -0
- package/dist/lib/ac-response-parser.js +57 -0
- package/dist/lib/ac-response-parser.js.map +1 -0
- package/dist/lib/ai-call.d.ts +13 -0
- package/dist/lib/ai-call.js +17 -0
- package/dist/lib/ai-call.js.map +1 -0
- package/dist/lib/archive.d.ts +21 -0
- package/dist/lib/archive.js +136 -0
- package/dist/lib/archive.js.map +1 -0
- package/dist/lib/artifact-integrity.d.ts +5 -0
- package/dist/lib/artifact-integrity.js +65 -0
- package/dist/lib/artifact-integrity.js.map +1 -0
- package/dist/lib/backfill-queue.d.ts +11 -0
- package/dist/lib/backfill-queue.js +14 -0
- package/dist/lib/backfill-queue.js.map +1 -0
- package/dist/lib/blockers.d.ts +66 -0
- package/dist/lib/blockers.js +103 -0
- package/dist/lib/blockers.js.map +1 -0
- package/dist/lib/claims.d.ts +39 -0
- package/dist/lib/claims.js +133 -0
- package/dist/lib/claims.js.map +1 -0
- package/dist/lib/classify-debt.d.ts +17 -0
- package/dist/lib/classify-debt.js +13 -0
- package/dist/lib/classify-debt.js.map +1 -0
- package/dist/lib/code-evidence.d.ts +35 -0
- package/dist/lib/code-evidence.js +171 -0
- package/dist/lib/code-evidence.js.map +1 -0
- package/dist/lib/coherence.d.ts +14 -0
- package/dist/lib/coherence.js +188 -0
- package/dist/lib/coherence.js.map +1 -0
- package/dist/lib/completion-gate.d.ts +17 -0
- package/dist/lib/completion-gate.js +28 -0
- package/dist/lib/completion-gate.js.map +1 -0
- package/dist/lib/compliance-signoff.d.ts +39 -0
- package/dist/lib/compliance-signoff.js +81 -0
- package/dist/lib/compliance-signoff.js.map +1 -0
- package/dist/lib/config.d.ts +63 -0
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cost.d.ts +12 -0
- package/dist/lib/cost.js +12 -0
- package/dist/lib/cost.js.map +1 -0
- package/dist/lib/debt-dashboard.d.ts +25 -0
- package/dist/lib/debt-dashboard.js +36 -0
- package/dist/lib/debt-dashboard.js.map +1 -0
- package/dist/lib/embedding-store.d.ts +103 -0
- package/dist/lib/embedding-store.js +133 -0
- package/dist/lib/embedding-store.js.map +1 -0
- package/dist/lib/embeddings-source.d.ts +36 -0
- package/dist/lib/embeddings-source.js +62 -0
- package/dist/lib/embeddings-source.js.map +1 -0
- package/dist/lib/enforcement-allowlist.d.ts +12 -0
- package/dist/lib/enforcement-allowlist.js +25 -0
- package/dist/lib/enforcement-allowlist.js.map +1 -0
- package/dist/lib/events.d.ts +47 -0
- package/dist/lib/events.js +75 -0
- package/dist/lib/events.js.map +1 -0
- package/dist/lib/exec.d.ts +8 -0
- package/dist/lib/exec.js +25 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +112 -0
- package/dist/lib/frontmatter.js +261 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/funnel.d.ts +22 -0
- package/dist/lib/funnel.js +41 -0
- package/dist/lib/funnel.js.map +1 -0
- package/dist/lib/git-mtime.d.ts +4 -0
- package/dist/lib/git-mtime.js +23 -0
- package/dist/lib/git-mtime.js.map +1 -0
- package/dist/lib/metrics.d.ts +42 -0
- package/dist/lib/metrics.js +92 -0
- package/dist/lib/metrics.js.map +1 -0
- package/dist/lib/migration-collision.d.ts +20 -0
- package/dist/lib/migration-collision.js +61 -0
- package/dist/lib/migration-collision.js.map +1 -0
- package/dist/lib/next-action.d.ts +44 -0
- package/dist/lib/next-action.js +138 -0
- package/dist/lib/next-action.js.map +1 -0
- package/dist/lib/ollama-embed.d.ts +21 -0
- package/dist/lib/ollama-embed.js +65 -0
- package/dist/lib/ollama-embed.js.map +1 -0
- package/dist/lib/output.d.ts +35 -0
- package/dist/lib/output.js +46 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/pipeline-config.d.ts +20 -0
- package/dist/lib/pipeline-config.js +208 -0
- package/dist/lib/pipeline-config.js.map +1 -0
- package/dist/lib/pipeline-map.d.ts +68 -0
- package/dist/lib/pipeline-map.js +256 -0
- package/dist/lib/pipeline-map.js.map +1 -0
- package/dist/lib/pipeline-schema.d.ts +48 -0
- package/dist/lib/pipeline-schema.js +22 -0
- package/dist/lib/pipeline-schema.js.map +1 -0
- package/dist/lib/placement.d.ts +6 -0
- package/dist/lib/placement.js +40 -0
- package/dist/lib/placement.js.map +1 -0
- package/dist/lib/precedent-search.d.ts +18 -0
- package/dist/lib/precedent-search.js +160 -0
- package/dist/lib/precedent-search.js.map +1 -0
- package/dist/lib/predicate-registry.d.ts +6 -0
- package/dist/lib/predicate-registry.js +40 -0
- package/dist/lib/predicate-registry.js.map +1 -0
- package/dist/lib/recall-cases.d.ts +15 -0
- package/dist/lib/recall-cases.js +39 -0
- package/dist/lib/recall-cases.js.map +1 -0
- package/dist/lib/repo.d.ts +20 -0
- package/dist/lib/repo.js +82 -0
- package/dist/lib/repo.js.map +1 -0
- package/dist/lib/requirements.d.ts +91 -0
- package/dist/lib/requirements.js +179 -0
- package/dist/lib/requirements.js.map +1 -0
- package/dist/lib/rollup.d.ts +24 -0
- package/dist/lib/rollup.js +34 -0
- package/dist/lib/rollup.js.map +1 -0
- package/dist/lib/scorecard-run.d.ts +6 -0
- package/dist/lib/scorecard-run.js +48 -0
- package/dist/lib/scorecard-run.js.map +1 -0
- package/dist/lib/scorecard.d.ts +69 -0
- package/dist/lib/scorecard.js +113 -0
- package/dist/lib/scorecard.js.map +1 -0
- package/dist/lib/semantic-search.d.ts +36 -0
- package/dist/lib/semantic-search.js +56 -0
- package/dist/lib/semantic-search.js.map +1 -0
- package/dist/lib/session-state.d.ts +8 -0
- package/dist/lib/session-state.js +25 -0
- package/dist/lib/session-state.js.map +1 -0
- package/dist/lib/spec-debt.d.ts +8 -0
- package/dist/lib/spec-debt.js +17 -0
- package/dist/lib/spec-debt.js.map +1 -0
- package/dist/lib/spec-pure.d.ts +59 -0
- package/dist/lib/spec-pure.js +215 -0
- package/dist/lib/spec-pure.js.map +1 -0
- package/dist/lib/specs.d.ts +148 -0
- package/dist/lib/specs.js +373 -0
- package/dist/lib/specs.js.map +1 -0
- package/dist/lib/test-generator.d.ts +5 -0
- package/dist/lib/test-generator.js +72 -0
- package/dist/lib/test-generator.js.map +1 -0
- package/dist/lib/user-stories.d.ts +6 -0
- package/dist/lib/user-stories.js +56 -0
- package/dist/lib/user-stories.js.map +1 -0
- package/dist/lib/verifies-scan.d.ts +9 -0
- package/dist/lib/verifies-scan.js +73 -0
- package/dist/lib/verifies-scan.js.map +1 -0
- package/dist/lib/verify-core.d.ts +23 -0
- package/dist/lib/verify-core.js +48 -0
- package/dist/lib/verify-core.js.map +1 -0
- package/dist/lib/with-event-log.d.ts +12 -0
- package/dist/lib/with-event-log.js +65 -0
- package/dist/lib/with-event-log.js.map +1 -0
- package/dist/lib/wizard-specs.d.ts +17 -0
- package/dist/lib/wizard-specs.js +34 -0
- package/dist/lib/wizard-specs.js.map +1 -0
- package/dist/pure.d.ts +19 -0
- package/dist/pure.js +31 -0
- package/dist/pure.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { buildQueue } from '../lib/backfill-queue.js';
|
|
4
|
+
import { classifyTier } from '../lib/classify-debt.js';
|
|
5
|
+
import { deriveCodeEvidence } from '../lib/code-evidence.js';
|
|
6
|
+
import { renderDebtDashboard } from '../lib/debt-dashboard.js';
|
|
7
|
+
import { ErrorCode, emit, getGlobalOptions } from '../lib/output.js';
|
|
8
|
+
import { coresList, getRepoRoot, isKnownCore } from '../lib/repo.js';
|
|
9
|
+
import { buildScorecardForCore } from '../lib/scorecard-run.js';
|
|
10
|
+
import { findSpec } from '../lib/specs.js';
|
|
11
|
+
import { scanVerifies } from '../lib/verifies-scan.js';
|
|
12
|
+
import { withEventLog } from '../lib/with-event-log.js';
|
|
13
|
+
/**
|
|
14
|
+
* Rewrite ONLY the frontmatter `status:` line to `newStatus`, preserving the trailing newline —
|
|
15
|
+
* the exact single-line replacement approach as scripts/specs/remap-status-values.ts. Returns the
|
|
16
|
+
* text unchanged when no `status:` line is present. Pure (string in / string out) so the apply path
|
|
17
|
+
* is unit-testable without touching the real repo.
|
|
18
|
+
*/
|
|
19
|
+
export function rewriteStatusLine(text, newStatus) {
|
|
20
|
+
const m = /^status:[ \t]*(.+?)[ \t]*$/m.exec(text);
|
|
21
|
+
if (!m)
|
|
22
|
+
return { text, changed: false };
|
|
23
|
+
if (m[1] === newStatus)
|
|
24
|
+
return { text, changed: false };
|
|
25
|
+
return { text: text.replace(m[0], `status: ${newStatus}`), changed: true };
|
|
26
|
+
}
|
|
27
|
+
/** Append a one-line evidence receipt as an HTML comment near the frontmatter (after the closing `---`). */
|
|
28
|
+
export function appendEvidenceReceipt(text, receipt) {
|
|
29
|
+
const comment = `<!-- backfill: ${receipt} -->`;
|
|
30
|
+
// Insert right after the closing frontmatter fence so it sits near the top, not at EOF.
|
|
31
|
+
const fenceEnd = /^---\s*$/m;
|
|
32
|
+
const first = fenceEnd.exec(text);
|
|
33
|
+
if (first) {
|
|
34
|
+
const second = fenceEnd.exec(text.slice(first.index + first[0].length));
|
|
35
|
+
if (second) {
|
|
36
|
+
const insertAt = first.index + first[0].length + second.index + second[0].length;
|
|
37
|
+
return `${text.slice(0, insertAt)}\n${comment}${text.slice(insertAt)}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return `${comment}\n${text}`;
|
|
41
|
+
}
|
|
42
|
+
/** Apply a downgrade to one spec's text: rewrite status + append the receipt. Pure. */
|
|
43
|
+
export function applyDowngrade(text, newStatus, receipt) {
|
|
44
|
+
const { text: rewritten, changed } = rewriteStatusLine(text, newStatus);
|
|
45
|
+
if (!changed)
|
|
46
|
+
return { text, changed: false };
|
|
47
|
+
return { text: appendEvidenceReceipt(rewritten, receipt), changed: true };
|
|
48
|
+
}
|
|
49
|
+
/** Compute the list of missing verification artifacts for a claimed-complete spec. */
|
|
50
|
+
export function computeMissing(row, report, tier) {
|
|
51
|
+
if (tier.tier === 'T0')
|
|
52
|
+
return [];
|
|
53
|
+
const missing = [];
|
|
54
|
+
if (tier.tier === 'T1') {
|
|
55
|
+
// Tests exist but @verifies linkage is broken — the one missing artifact is the (re)link.
|
|
56
|
+
missing.push('@verifies');
|
|
57
|
+
return missing;
|
|
58
|
+
}
|
|
59
|
+
// T2/T3/T4: count what's absent.
|
|
60
|
+
if (row.requirementsVerified === 0)
|
|
61
|
+
missing.push('tests');
|
|
62
|
+
if (!report.hasE2E)
|
|
63
|
+
missing.push('e2e');
|
|
64
|
+
if (!report.hasDocshots)
|
|
65
|
+
missing.push('docshots');
|
|
66
|
+
return missing;
|
|
67
|
+
}
|
|
68
|
+
/** Effort heuristic: S for T1 (relink only); M for T2 with a small requirement count; L for T4 / large. */
|
|
69
|
+
export function computeEffort(tier, requirementsTotal) {
|
|
70
|
+
if (tier.tier === 'T0' || tier.tier === 'T1')
|
|
71
|
+
return 'S';
|
|
72
|
+
if (tier.tier === 'T2')
|
|
73
|
+
return requirementsTotal <= 8 ? 'M' : 'L';
|
|
74
|
+
if (tier.tier === 'T3')
|
|
75
|
+
return 'M';
|
|
76
|
+
return 'L'; // T4
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build one BackfillEntry per claimed-complete spec in the core. Pure-ish: reads the filesystem via
|
|
80
|
+
* the scorecard + code-evidence probe but performs NO writes. The caller decides dry-run vs apply.
|
|
81
|
+
*/
|
|
82
|
+
export function buildBackfill(repoRoot, core) {
|
|
83
|
+
const verified = scanVerifies(repoRoot);
|
|
84
|
+
const report = buildScorecardForCore(repoRoot, core, verified);
|
|
85
|
+
const entries = [];
|
|
86
|
+
const relinkQueue = [];
|
|
87
|
+
for (const row of report.rows) {
|
|
88
|
+
if (!row.claimsComplete)
|
|
89
|
+
continue;
|
|
90
|
+
const spec = findSpec(repoRoot, row.id);
|
|
91
|
+
if (!spec)
|
|
92
|
+
continue;
|
|
93
|
+
const evidence = deriveCodeEvidence(repoRoot, spec, row);
|
|
94
|
+
const tier = classifyTier({
|
|
95
|
+
claimsComplete: row.claimsComplete,
|
|
96
|
+
requirementsTotal: row.requirementsTotal,
|
|
97
|
+
requirementsVerified: row.requirementsVerified,
|
|
98
|
+
}, evidence);
|
|
99
|
+
const missing = computeMissing(row, report, tier);
|
|
100
|
+
const debtRow = {
|
|
101
|
+
id: row.id,
|
|
102
|
+
claimed: row.claimedStatus ?? 'complete',
|
|
103
|
+
tier: tier.tier,
|
|
104
|
+
honestStatus: tier.honestStatus,
|
|
105
|
+
missing,
|
|
106
|
+
effort: computeEffort(tier, row.requirementsTotal),
|
|
107
|
+
reason: evidence.reason,
|
|
108
|
+
};
|
|
109
|
+
entries.push({ row: debtRow, tier, scorecardRow: row, specPath: spec.path });
|
|
110
|
+
if (tier.action === 'relink') {
|
|
111
|
+
relinkQueue.push({ id: row.id, reason: evidence.reason || 'tests exist; @verifies linkage broken' });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { entries, relinkQueue };
|
|
115
|
+
}
|
|
116
|
+
export function registerBackfill(program) {
|
|
117
|
+
program
|
|
118
|
+
.command('backfill')
|
|
119
|
+
.description('Verification-debt classifier: per claimed-complete spec, classify a debt tier (T0..T4) from code/test evidence, write specs/<core>/VERIFICATION_DEBT.md, and (with --apply) downgrade overstated status lines.')
|
|
120
|
+
.requiredOption('--core <core>', 'Core to classify (e.g. hr)')
|
|
121
|
+
.option('--apply', 'Rewrite overstated status lines to the honest status (T1 relinks are NOT downgraded)', false)
|
|
122
|
+
.option('--plan', 'Print the prioritised work queue (T1 relinks first, then T2/T3/T4 rebuilds) — read-only, no writes', false)
|
|
123
|
+
.action(withEventLog('backfill', async (options, cmd) => {
|
|
124
|
+
const global = getGlobalOptions(cmd);
|
|
125
|
+
const repoRoot = getRepoRoot(global.repoRoot);
|
|
126
|
+
const core = String(options.core).toLowerCase();
|
|
127
|
+
if (!isKnownCore(core, repoRoot)) {
|
|
128
|
+
emit(global, {
|
|
129
|
+
ok: false,
|
|
130
|
+
error: {
|
|
131
|
+
code: ErrorCode.UNKNOWN_CORE,
|
|
132
|
+
message: `backfill: unknown core "${options.core}". Valid cores: ${coresList(repoRoot).join(', ')}`,
|
|
133
|
+
},
|
|
134
|
+
data: { core: options.core, validCores: coresList(repoRoot) },
|
|
135
|
+
text: `backfill: unknown core "${options.core}". Valid cores: ${coresList(repoRoot).join(', ')}`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const { entries, relinkQueue } = buildBackfill(repoRoot, core);
|
|
139
|
+
// --plan: print the prioritised work queue and return early (read-only).
|
|
140
|
+
if (options.plan) {
|
|
141
|
+
// Build the queue from all non-T0 entries (both relinks and downgrades), T1 first.
|
|
142
|
+
const queueRows = entries.map((e) => ({ ...e.row, action: e.tier.action }));
|
|
143
|
+
const queue = buildQueue(queueRows);
|
|
144
|
+
if (queue.length === 0) {
|
|
145
|
+
const planText = [
|
|
146
|
+
`Backfill plan (${core}): queue is empty.`,
|
|
147
|
+
` ${entries.length} claimed-complete spec(s) classified — all are T0 (no work needed).`,
|
|
148
|
+
].join('\n');
|
|
149
|
+
emit(global, {
|
|
150
|
+
ok: true,
|
|
151
|
+
data: { core, queue: [] },
|
|
152
|
+
text: planText,
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const header = `Backfill plan (${core}): ${queue.length} spec(s) queued (T1 relinks first, then T2→T4 rebuilds)\n`;
|
|
157
|
+
const rows = queue.map((r) => {
|
|
158
|
+
const missingStr = r.missing.length > 0 ? r.missing.join(', ') : '—';
|
|
159
|
+
const nextStep = r.tier === 'T1'
|
|
160
|
+
? 'add @verifies tags in test files pointing to this spec id'
|
|
161
|
+
: `restore missing artifacts: ${missingStr}`;
|
|
162
|
+
return [
|
|
163
|
+
` ${r.id}`,
|
|
164
|
+
` tier : ${r.tier}`,
|
|
165
|
+
` action : ${r.action}`,
|
|
166
|
+
` honest : ${r.honestStatus} (claimed: ${r.claimed})`,
|
|
167
|
+
` missing : ${missingStr}`,
|
|
168
|
+
` next step : ${nextStep}`,
|
|
169
|
+
` effort : ${r.effort}`,
|
|
170
|
+
].join('\n');
|
|
171
|
+
});
|
|
172
|
+
const planText = `${header}\n${rows.join('\n\n')}`;
|
|
173
|
+
emit(global, {
|
|
174
|
+
ok: true,
|
|
175
|
+
data: {
|
|
176
|
+
core,
|
|
177
|
+
queue: queue.map((r) => ({
|
|
178
|
+
id: r.id,
|
|
179
|
+
tier: r.tier,
|
|
180
|
+
action: r.action,
|
|
181
|
+
honestStatus: r.honestStatus,
|
|
182
|
+
missing: r.missing,
|
|
183
|
+
effort: r.effort,
|
|
184
|
+
})),
|
|
185
|
+
},
|
|
186
|
+
text: planText,
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Always write the dashboard.
|
|
191
|
+
const dashboard = renderDebtDashboard(core, entries.map((e) => e.row), { relinkQueue });
|
|
192
|
+
const dashboardPath = join(repoRoot, 'specs', core, 'VERIFICATION_DEBT.md');
|
|
193
|
+
mkdirSync(dirname(dashboardPath), { recursive: true });
|
|
194
|
+
writeFileSync(dashboardPath, dashboard);
|
|
195
|
+
const downgrades = entries.filter((e) => e.tier.action === 'downgrade');
|
|
196
|
+
let applied = 0;
|
|
197
|
+
if (options.apply) {
|
|
198
|
+
for (const e of downgrades) {
|
|
199
|
+
const text = readFileSync(e.specPath, 'utf8');
|
|
200
|
+
const failed = e.row.missing.length > 0 ? e.row.missing.join('/') : 'unverified';
|
|
201
|
+
const receipt = `${e.tier.tier} ${e.row.claimed}→${e.tier.honestStatus} (missing: ${failed})`;
|
|
202
|
+
const { text: next, changed } = applyDowngrade(text, e.tier.honestStatus, receipt);
|
|
203
|
+
if (changed) {
|
|
204
|
+
writeFileSync(e.specPath, next);
|
|
205
|
+
applied++;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const previewLines = downgrades.map((e) => ` ${e.row.id} ${e.row.claimed} → ${e.tier.honestStatus} (${e.tier.tier})`);
|
|
210
|
+
const text = [
|
|
211
|
+
`Verification debt (${core}): ${entries.length} claimed-complete specs classified`,
|
|
212
|
+
` dashboard written: specs/${core}/VERIFICATION_DEBT.md`,
|
|
213
|
+
` would downgrade : ${downgrades.length}`,
|
|
214
|
+
` relink queue : ${relinkQueue.length}`,
|
|
215
|
+
options.apply ? ` APPLIED downgrades: ${applied}` : ' (dry-run — no spec frontmatter changed)',
|
|
216
|
+
'',
|
|
217
|
+
...(downgrades.length
|
|
218
|
+
? [options.apply ? ' Downgraded:' : ' Would downgrade (current → honest, tier):', ...previewLines]
|
|
219
|
+
: [' No downgrades.']),
|
|
220
|
+
].join('\n');
|
|
221
|
+
emit(global, {
|
|
222
|
+
ok: true,
|
|
223
|
+
data: {
|
|
224
|
+
core,
|
|
225
|
+
classified: entries.length,
|
|
226
|
+
downgrades: downgrades.map((e) => ({
|
|
227
|
+
id: e.row.id,
|
|
228
|
+
from: e.row.claimed,
|
|
229
|
+
to: e.tier.honestStatus,
|
|
230
|
+
tier: e.tier.tier,
|
|
231
|
+
})),
|
|
232
|
+
relinkQueue,
|
|
233
|
+
applied: options.apply ? applied : 0,
|
|
234
|
+
},
|
|
235
|
+
text,
|
|
236
|
+
});
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../src/commands/backfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { checkArtifactIntegrity } from '../lib/artifact-integrity.js';
|
|
2
|
+
import { emit, getGlobalOptions } from '../lib/output.js';
|
|
3
|
+
import { getRepoRoot } from '../lib/repo.js';
|
|
4
|
+
export function registerCheckArtifacts(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('check-artifacts')
|
|
7
|
+
.description('Smoke-check automation artifact integrity: verifies that every automation/skills/*/SKILL.md, automation/commands/*.md, and automation/agents/*.md has non-empty YAML frontmatter with a `name` field, and that .claude/.cursor symlinks into automation/ resolve (no dangling links). Measure-only — does not modify anything.')
|
|
8
|
+
.action(async (_options, cmd) => {
|
|
9
|
+
const global = getGlobalOptions(cmd);
|
|
10
|
+
const repoRoot = getRepoRoot(global.repoRoot);
|
|
11
|
+
const report = checkArtifactIntegrity(repoRoot);
|
|
12
|
+
const { missingFrontmatter, danglingSymlinks } = report;
|
|
13
|
+
const totalIssues = missingFrontmatter.length + danglingSymlinks.length;
|
|
14
|
+
if (totalIssues === 0) {
|
|
15
|
+
emit(global, {
|
|
16
|
+
ok: true,
|
|
17
|
+
data: { missingFrontmatter: [], danglingSymlinks: [] },
|
|
18
|
+
text: '0 issues — all automation artifacts have valid frontmatter and all symlinks resolve.',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const lines = [];
|
|
22
|
+
if (missingFrontmatter.length > 0) {
|
|
23
|
+
lines.push(`${missingFrontmatter.length} file(s) missing frontmatter (no "name:" field in first 600 chars):`);
|
|
24
|
+
for (const p of missingFrontmatter) {
|
|
25
|
+
lines.push(` ${p}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
lines.push('0 files missing frontmatter.');
|
|
30
|
+
}
|
|
31
|
+
if (danglingSymlinks.length > 0) {
|
|
32
|
+
lines.push(`${danglingSymlinks.length} dangling symlink(s) in .claude/.cursor:`);
|
|
33
|
+
for (const p of danglingSymlinks) {
|
|
34
|
+
lines.push(` ${p}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
lines.push('0 dangling symlinks.');
|
|
39
|
+
}
|
|
40
|
+
emit(global, {
|
|
41
|
+
ok: false,
|
|
42
|
+
data: { missingFrontmatter, danglingSymlinks },
|
|
43
|
+
text: lines.join('\n'),
|
|
44
|
+
exitCode: 1,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=checkArtifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkArtifacts.js","sourceRoot":"","sources":["../../src/commands/checkArtifacts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CACV,gUAAgU,CACjU;SACA,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;QAC9B,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAC;QACxD,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;QAExE,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,EAAE;gBACX,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;gBACtD,IAAI,EAAE,sFAAsF;aAC7F,CAAC,CAAC;QACL,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,qEAAqE,CAAC,CAAC;YAC9G,KAAK,MAAM,CAAC,IAAI,kBAAkB,EAAE,CAAC;gBACnC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,MAAM,0CAA0C,CAAC,CAAC;YACjF,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,MAAM,EAAE;YACX,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,EAAE,kBAAkB,EAAE,gBAAgB,EAAE;YAC9C,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACtB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { emit, getGlobalOptions } from '../lib/output.js';
|
|
2
|
+
import { findMisplacedSpecs } from '../lib/placement.js';
|
|
3
|
+
import { getRepoRoot } from '../lib/repo.js';
|
|
4
|
+
export function registerCheckPlacement(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('check-placement')
|
|
7
|
+
.description('Report primary spec files that live outside their canonical location (specs/<core>/specs/ or specs/<core>/ux/). Lifecycle artifacts (TASKS, PLAN, CONTEXT, etc.) are ignored.')
|
|
8
|
+
.action(async (_options, cmd) => {
|
|
9
|
+
const global = getGlobalOptions(cmd);
|
|
10
|
+
const repoRoot = getRepoRoot(global.repoRoot);
|
|
11
|
+
const misplaced = findMisplacedSpecs(repoRoot);
|
|
12
|
+
if (misplaced.length === 0) {
|
|
13
|
+
emit(global, {
|
|
14
|
+
ok: true,
|
|
15
|
+
data: { count: 0, misplaced: [] },
|
|
16
|
+
text: '0 misplaced specs',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const text = [
|
|
20
|
+
`${misplaced.length} misplaced spec(s):`,
|
|
21
|
+
...misplaced.map((m) => ` ${m.id} ${m.path}\n → expected in: ${m.expectedDir}`),
|
|
22
|
+
].join('\n');
|
|
23
|
+
emit(global, {
|
|
24
|
+
ok: false,
|
|
25
|
+
data: { count: misplaced.length, misplaced },
|
|
26
|
+
text,
|
|
27
|
+
exitCode: 1,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=checkPlacement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkPlacement.js","sourceRoot":"","sources":["../../src/commands/checkPlacement.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CACV,+KAA+K,CAChL;SACA,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;QAC9B,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,EAAE;gBACX,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;gBACjC,IAAI,EAAE,mBAAmB;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,GAAG;YACX,GAAG,SAAS,CAAC,MAAM,qBAAqB;YACxC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,wBAAwB,CAAC,CAAC,WAAW,EAAE,CAAC;SACrF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,IAAI,CAAC,MAAM,EAAE;YACX,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE;YAC5C,IAAI;YACJ,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
/** `--by` wins, then $EOS_SPEC_CLAIMED_BY, then the worktree basename. */
|
|
3
|
+
export declare function resolveClaimedBy(explicit: string | undefined, repoRoot: string): string;
|
|
4
|
+
export declare function registerClaim(program: Command): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { activeClaims, addClaim, DEFAULT_TTL_MINUTES, readClaims, releaseClaim } from '../lib/claims.js';
|
|
3
|
+
import { emit, getGlobalOptions } from '../lib/output.js';
|
|
4
|
+
import { getRepoRoot } from '../lib/repo.js';
|
|
5
|
+
import { withEventLog } from '../lib/with-event-log.js';
|
|
6
|
+
/** `--by` wins, then $EOS_SPEC_CLAIMED_BY, then the worktree basename. */
|
|
7
|
+
export function resolveClaimedBy(explicit, repoRoot) {
|
|
8
|
+
return explicit ?? process.env.EOS_SPEC_CLAIMED_BY ?? basename(repoRoot);
|
|
9
|
+
}
|
|
10
|
+
export function registerClaim(program) {
|
|
11
|
+
program
|
|
12
|
+
.command('claim <id>')
|
|
13
|
+
.description('Reserve a spec for this worktree (TTL lease shared across parallel worktrees); --release frees it.')
|
|
14
|
+
.option('--by <who>', 'Claimant label (defaults to $EOS_SPEC_CLAIMED_BY or the worktree basename)')
|
|
15
|
+
.option('--ttl <min>', 'Lease length in minutes', String(DEFAULT_TTL_MINUTES))
|
|
16
|
+
.option('--release', 'Release the claim instead of taking it', false)
|
|
17
|
+
.action(withEventLog('claim', async (options, cmd) => {
|
|
18
|
+
const command = cmd;
|
|
19
|
+
const global = getGlobalOptions(command);
|
|
20
|
+
const repoRoot = getRepoRoot(global.repoRoot);
|
|
21
|
+
// `claim <id>` is a positional command: commander supplies the id on the
|
|
22
|
+
// Command's args, not in the options object (withEventLog forwards the real
|
|
23
|
+
// Command as `cmd`).
|
|
24
|
+
const id = String(command.args[0] ?? '').toUpperCase();
|
|
25
|
+
if (options.release) {
|
|
26
|
+
releaseClaim(repoRoot, id);
|
|
27
|
+
const active = activeClaims(readClaims(repoRoot), Date.now());
|
|
28
|
+
emit(global, {
|
|
29
|
+
ok: true,
|
|
30
|
+
data: { released: id, active },
|
|
31
|
+
text: `claim: released ${id} (${active.length} active claim(s) remain)`,
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const by = resolveClaimedBy(options.by, repoRoot);
|
|
36
|
+
const ttlMinutes = Number.parseInt(String(options.ttl), 10) || DEFAULT_TTL_MINUTES;
|
|
37
|
+
const claim = addClaim(repoRoot, id, { by, ttlMinutes });
|
|
38
|
+
const active = activeClaims(readClaims(repoRoot), Date.now());
|
|
39
|
+
emit(global, {
|
|
40
|
+
ok: true,
|
|
41
|
+
data: { claim, active },
|
|
42
|
+
text: `claim: ${claim.id} reserved by ${claim.claimedBy} for ${claim.ttlMinutes}m (${active.length} active claim(s))`,
|
|
43
|
+
});
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=claim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/commands/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,QAA4B,EAAE,QAAgB;IAC7E,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,oGAAoG,CAAC;SACjH,MAAM,CAAC,YAAY,EAAE,4EAA4E,CAAC;SAClG,MAAM,CAAC,aAAa,EAAE,yBAAyB,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;SAC7E,MAAM,CAAC,WAAW,EAAE,wCAAwC,EAAE,KAAK,CAAC;SACpE,MAAM,CACL,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,GAAc,CAAC;QAC/B,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,yEAAyE;QACzE,4EAA4E;QAC5E,qBAAqB;QACrB,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAEvD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9D,IAAI,CAAC,MAAM,EAAE;gBACX,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE;gBAC9B,IAAI,EAAE,mBAAmB,EAAE,KAAK,MAAM,CAAC,MAAM,0BAA0B;aACxE,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC;QACnF,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE;YACX,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;YACvB,IAAI,EAAE,UAAU,KAAK,CAAC,EAAE,gBAAgB,KAAK,CAAC,SAAS,QAAQ,KAAK,CAAC,UAAU,MAAM,MAAM,CAAC,MAAM,mBAAmB;SACtH,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { archiveSpec } from '../lib/archive.js';
|
|
2
|
+
import { evaluateCoherence } from '../lib/coherence.js';
|
|
3
|
+
import { uiEvidenceGate } from '../lib/completion-gate.js';
|
|
4
|
+
import { loadEnforcementAllowlist } from '../lib/enforcement-allowlist.js';
|
|
5
|
+
import { runScript } from '../lib/exec.js';
|
|
6
|
+
import { ErrorCode, emit, emitContinuing, getGlobalOptions } from '../lib/output.js';
|
|
7
|
+
import { getRepoRoot } from '../lib/repo.js';
|
|
8
|
+
import { findSpec } from '../lib/specs.js';
|
|
9
|
+
export function registerComplete(program) {
|
|
10
|
+
program
|
|
11
|
+
.command('complete')
|
|
12
|
+
.description('Wrap scripts/audit/audit-spec-completion.js — verify and optionally update registry/tracking and archive a completed spec.')
|
|
13
|
+
.option('--spec <id>', 'Single spec id (e.g. PF-37)')
|
|
14
|
+
.option('--core <core>', 'Limit to one core')
|
|
15
|
+
.option('--all', 'All specs across all cores', false)
|
|
16
|
+
.option('--update-registry', 'Write back to specs/SPEC_STATUS_REGISTRY.md', false)
|
|
17
|
+
.option('--include-deferred', 'Include deferred items in audit', false)
|
|
18
|
+
.option('--archive', 'After audit passes, move spec/plan/tasks to specs/{core}/archive/', false)
|
|
19
|
+
.option('--strict', 'Fail when coherence warnings are present', false)
|
|
20
|
+
.option('--no-ui-gate', 'Skip the UI-evidence completion check (docshots + heal sign-off)')
|
|
21
|
+
.option('--signoff', 'Acknowledge the UI-evidence gate (equivalent to --no-ui-gate for this run)', false)
|
|
22
|
+
.action(async (options, cmd) => {
|
|
23
|
+
const global = getGlobalOptions(cmd);
|
|
24
|
+
const repoRoot = getRepoRoot(global.repoRoot);
|
|
25
|
+
// C1 inline UI-evidence gate: warn at completion time when a UI-bearing
|
|
26
|
+
// spec lacks docshots + a heal sign-off. Warn-first (never refuses) — the
|
|
27
|
+
// non-bypassable enforcement is the corpus invariant (spec:registry:check).
|
|
28
|
+
// commander maps `--no-ui-gate` to options.uiGate === false.
|
|
29
|
+
if (options.spec && options.uiGate !== false && !options.signoff) {
|
|
30
|
+
try {
|
|
31
|
+
const spec = findSpec(repoRoot, String(options.spec));
|
|
32
|
+
if (spec) {
|
|
33
|
+
const verdict = uiEvidenceGate(spec);
|
|
34
|
+
if (!verdict.ok) {
|
|
35
|
+
const allow = loadEnforcementAllowlist(repoRoot);
|
|
36
|
+
const blocked = allow.block.includes(spec.core);
|
|
37
|
+
emitContinuing(global, `complete: ui-evidence ${blocked ? 'GATE' : 'warning'} — ${verdict.reason}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// fail-open: a gate must never make `complete` unusable.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const args = ['node', 'scripts/audit/audit-spec-completion.js'];
|
|
46
|
+
if (options.spec)
|
|
47
|
+
args.push(`--spec=${options.spec}`);
|
|
48
|
+
if (options.core)
|
|
49
|
+
args.push(`--core=${options.core}`);
|
|
50
|
+
if (options.all)
|
|
51
|
+
args.push('--all');
|
|
52
|
+
if (options.updateRegistry)
|
|
53
|
+
args.push('--update-registry');
|
|
54
|
+
if (options.includeDeferred)
|
|
55
|
+
args.push('--include-deferred');
|
|
56
|
+
// F6: in JSON mode, ask the audit script for its machine-readable array so
|
|
57
|
+
// we can embed structured data instead of the raw stdout/stderr blob.
|
|
58
|
+
if (global.json)
|
|
59
|
+
args.push('--json');
|
|
60
|
+
emitContinuing(global, `complete: ${args.join(' ')}`);
|
|
61
|
+
const result = runScript(args, repoRoot);
|
|
62
|
+
const ok = result.exitCode === 0;
|
|
63
|
+
let archived = [];
|
|
64
|
+
let coherenceWarnings = [];
|
|
65
|
+
if (ok && options.spec) {
|
|
66
|
+
const core = String(options.spec).toUpperCase().split('-')[0]?.toLowerCase();
|
|
67
|
+
if (core) {
|
|
68
|
+
const coherence = evaluateCoherence(repoRoot, String(options.spec).toUpperCase(), core);
|
|
69
|
+
coherenceWarnings = coherence.warnings.map((w) => w.message);
|
|
70
|
+
if (coherenceWarnings.length > 0 && !global.json && !global.quiet) {
|
|
71
|
+
emitContinuing(global, `complete: coherence warnings (${coherenceWarnings.length})`);
|
|
72
|
+
for (const warning of coherenceWarnings.slice(0, 10)) {
|
|
73
|
+
emitContinuing(global, ` - ${warning}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (options.strict && coherenceWarnings.length > 0) {
|
|
77
|
+
emit(global, {
|
|
78
|
+
ok: false,
|
|
79
|
+
data: { coherenceWarnings },
|
|
80
|
+
text: `complete: strict mode failed due to ${coherenceWarnings.length} coherence warning(s)`,
|
|
81
|
+
exitCode: 1,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (ok && options.archive) {
|
|
87
|
+
if (!options.spec) {
|
|
88
|
+
emit(global, {
|
|
89
|
+
ok: false,
|
|
90
|
+
error: {
|
|
91
|
+
code: ErrorCode.SCOPE_REQUIRED,
|
|
92
|
+
message: 'complete: --archive requires --spec <id>; refusing to bulk-archive',
|
|
93
|
+
},
|
|
94
|
+
data: { reason: '--archive requires --spec' },
|
|
95
|
+
text: 'complete: --archive requires --spec <id>; refusing to bulk-archive',
|
|
96
|
+
exitCode: 2,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const archiveResult = archiveSpec(repoRoot, options.spec, global.json || global.quiet ? null : (m) => emitContinuing(global, m), global.config);
|
|
100
|
+
archived = archiveResult.moved;
|
|
101
|
+
}
|
|
102
|
+
// F6: when the caller asked for JSON, the audit subprocess emitted its
|
|
103
|
+
// machine-readable array on stdout; parse it and embed it as `audit`.
|
|
104
|
+
// Fail-open (mirrors the L36 ui-gate): a malformed/absent JSON payload must
|
|
105
|
+
// never make `complete` unusable — fall back to the raw stdout blob.
|
|
106
|
+
let audit = null;
|
|
107
|
+
if (global.json && ok) {
|
|
108
|
+
try {
|
|
109
|
+
audit = JSON.parse(result.stdout);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
audit = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// On the JSON success path emit structured data only (the point of F6 —
|
|
116
|
+
// no raw stdout/stderr blob). Human mode or a JSON parse failure keeps the
|
|
117
|
+
// raw blob as a usable fallback.
|
|
118
|
+
const data = audit !== null
|
|
119
|
+
? { exitCode: result.exitCode, archived, coherenceWarnings, audit }
|
|
120
|
+
: {
|
|
121
|
+
exitCode: result.exitCode,
|
|
122
|
+
stdout: result.stdout,
|
|
123
|
+
stderr: result.stderr,
|
|
124
|
+
archived,
|
|
125
|
+
coherenceWarnings,
|
|
126
|
+
audit,
|
|
127
|
+
};
|
|
128
|
+
emit(global, {
|
|
129
|
+
ok,
|
|
130
|
+
data,
|
|
131
|
+
text: ok
|
|
132
|
+
? `complete: ${result.stdout.trim()}${coherenceWarnings.length ? `\nCoherence warnings: ${coherenceWarnings.length}` : ''}${archived.length ? `\nArchived ${archived.length} file(s) → specs/{core}/archive/` : ''}`
|
|
133
|
+
: `complete: failed (exit ${result.exitCode})\n${result.stderr || result.stdout}`,
|
|
134
|
+
exitCode: ok ? 0 : 1,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/commands/complete.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* The conformance pack the engine EXPORTS (epic #300, Wave-1 G5). A single
|
|
4
|
+
* `eos-spec conformance` runs the engine's own invariants in-process so a consumer
|
|
5
|
+
* adoption PR — and the npm-pack install smoke (scripts/conformance/pack-smoke.mjs,
|
|
6
|
+
* which runs THIS command from a clean tarball install) — has one green gate:
|
|
7
|
+
* - both pipeline layouts (encore1 + builder) validate against the predicate registry
|
|
8
|
+
* - each built pipeline materializes a sane stage from synthetic signals
|
|
9
|
+
* - the typed AC model + the /pure fs-free helpers resolve and behave
|
|
10
|
+
*
|
|
11
|
+
* The golden-corpus parity, command-surface snapshot, and /pure purity gate run in
|
|
12
|
+
* CI as colocated vitest suites; this command is the runnable, post-install subset
|
|
13
|
+
* that proves the *published artifact* is sound (catches the DATA_DIR-wrong-root /
|
|
14
|
+
* missing-dist / broken-export classes a unit suite on source can't).
|
|
15
|
+
*/
|
|
16
|
+
type Check = {
|
|
17
|
+
name: string;
|
|
18
|
+
ok: boolean;
|
|
19
|
+
detail: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function runConformanceChecks(): Check[];
|
|
22
|
+
export declare function registerConformance(program: Command): void;
|
|
23
|
+
export {};
|