@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,208 @@
|
|
|
1
|
+
/** The canonical encoreos-1 spec/test pipeline as config-driven data. This is a
|
|
2
|
+
* faithful transcription of the imperative `PIPELINE`/`STATUS_ORDER`/`computeStage`
|
|
3
|
+
* in pipeline-map.ts: every stage `id`, `actor`, `actorType`, `reason`,
|
|
4
|
+
* `regulatedOnly`/`optional`, `completesStatus`, the exact `statusOrder`, and the
|
|
5
|
+
* two honest caps are preserved verbatim. Each stage's `isDone` closure becomes a
|
|
6
|
+
* named `gate` resolved against DEFAULT_PREDICATES; each `invocation: (id) => ...`
|
|
7
|
+
* closure becomes a literal string with a `${id}` placeholder substituted at
|
|
8
|
+
* interpret time. The Task 1.5 parity gate validates this against pipeline-map.ts. */
|
|
9
|
+
export const ENCORE1_PIPELINE_SCHEMA = {
|
|
10
|
+
statusOrder: [
|
|
11
|
+
'stub',
|
|
12
|
+
'clarified',
|
|
13
|
+
'validated',
|
|
14
|
+
'regulatory_grounded',
|
|
15
|
+
'reviewed',
|
|
16
|
+
'compliance_reviewed',
|
|
17
|
+
'ux_reviewed',
|
|
18
|
+
'planned',
|
|
19
|
+
'tasks_generated',
|
|
20
|
+
],
|
|
21
|
+
stages: [
|
|
22
|
+
{
|
|
23
|
+
id: 'clarify-spec',
|
|
24
|
+
gate: 'hasContext',
|
|
25
|
+
actor: 'clarify-spec command',
|
|
26
|
+
actorType: 'command',
|
|
27
|
+
invocation: 'clarify-spec --spec ${id}',
|
|
28
|
+
reason: 'Spec has unresolved placeholders — clarify before validating.',
|
|
29
|
+
completesStatus: 'clarified',
|
|
30
|
+
// Clarify is conditional remediation, not a required artifact — non-blocking.
|
|
31
|
+
optional: true,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'validate-spec',
|
|
35
|
+
gate: 'hasValidationSignoff',
|
|
36
|
+
actor: 'validate-spec command',
|
|
37
|
+
actorType: 'command',
|
|
38
|
+
// The /validate-spec slash command (not `eos-spec validate`, the lint) writes
|
|
39
|
+
// the `<!-- validated: -->` marker this gate keys on.
|
|
40
|
+
invocation: 'the /validate-spec command on ${id} (writes the <!-- validated: --> marker; alt: `eos-spec signoff --type validated --spec ${id}`)',
|
|
41
|
+
reason: 'Spec not validated — run structure/constitution validation.',
|
|
42
|
+
completesStatus: 'validated',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'ground-research',
|
|
46
|
+
gate: 'hasResearch',
|
|
47
|
+
actor: 'encore-spec-research skill',
|
|
48
|
+
actorType: 'skill',
|
|
49
|
+
invocation: 'the encore-spec-research skill on ${id}',
|
|
50
|
+
reason: 'Regulated spec needs a research appendix before review.',
|
|
51
|
+
regulatedOnly: true,
|
|
52
|
+
completesStatus: 'regulatory_grounded',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'spec-review',
|
|
56
|
+
gate: 'hasSpecReview',
|
|
57
|
+
actor: 'spec-review skill',
|
|
58
|
+
actorType: 'skill',
|
|
59
|
+
invocation: 'the spec-review skill on ${id}',
|
|
60
|
+
reason: 'Spec is grounded — run the implementability/landscape review.',
|
|
61
|
+
completesStatus: 'reviewed',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'compliance-review',
|
|
65
|
+
gate: 'hasComplianceSignoff',
|
|
66
|
+
actor: 'compliance-reviewer agent',
|
|
67
|
+
actorType: 'agent',
|
|
68
|
+
invocation: 'the compliance-reviewer agent on ${id}, then merge its review PR',
|
|
69
|
+
reason: 'Regulated spec needs compliance sign-off (human-gated PR).',
|
|
70
|
+
regulatedOnly: true,
|
|
71
|
+
completesStatus: 'compliance_reviewed',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'draft-acs',
|
|
75
|
+
gate: 'acsDraftedOrNoStories',
|
|
76
|
+
actor: 'encore-spec-ac-draft skill',
|
|
77
|
+
actorType: 'skill',
|
|
78
|
+
invocation: 'the encore-spec-ac-draft skill on ${id}',
|
|
79
|
+
reason: 'Spec has user stories but no acceptance criteria — draft ACs before generating tests.',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'generate-tests',
|
|
83
|
+
gate: 'testsGeneratedOrProven',
|
|
84
|
+
actor: 'encore-spec-to-test skill',
|
|
85
|
+
actorType: 'skill',
|
|
86
|
+
invocation: 'the encore-spec-to-test skill on ${id}',
|
|
87
|
+
reason: 'Acceptance criteria exist but no E2E tests are linked — generate them.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'a11y-audit',
|
|
91
|
+
gate: 'hasUxSignoff',
|
|
92
|
+
actor: 'encore-a11y-audit skill',
|
|
93
|
+
actorType: 'skill',
|
|
94
|
+
invocation: 'the encore-a11y-audit skill on ${id} (UI-bearing specs)',
|
|
95
|
+
reason: 'Optional: run a per-route accessibility audit for UI-bearing specs.',
|
|
96
|
+
optional: true,
|
|
97
|
+
completesStatus: 'ux_reviewed',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'create-plan',
|
|
101
|
+
gate: 'hasPlan',
|
|
102
|
+
actor: 'create-plan / validate-plan command',
|
|
103
|
+
actorType: 'command',
|
|
104
|
+
invocation: 'validate-spec --spec ${id} --auto-plan (or create-plan), then validate-plan --spec ${id}',
|
|
105
|
+
reason: 'No implementation plan yet.',
|
|
106
|
+
completesStatus: 'planned',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'generate-tasks',
|
|
110
|
+
gate: 'hasTasks',
|
|
111
|
+
actor: 'generate-tasks command',
|
|
112
|
+
actorType: 'command',
|
|
113
|
+
invocation: 'eos-spec tasks ${id}',
|
|
114
|
+
reason: 'Plan exists but no task breakdown.',
|
|
115
|
+
completesStatus: 'tasks_generated',
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
caps: [
|
|
119
|
+
// Research cap: a regulated spec without a research appendix has not passed
|
|
120
|
+
// regulatory_grounded, so later artifacts cannot lift its stage to/beyond it.
|
|
121
|
+
{ unless: 'hasResearch', whenRegulated: true, capBelow: 'regulatory_grounded' },
|
|
122
|
+
// Acceptance-criteria cap: a spec with a TASKS file but no ACs cannot honestly
|
|
123
|
+
// reach tasks_generated. Uses `hasAcceptanceCriteria` (NOT testsGeneratedOrProven,
|
|
124
|
+
// which has opposite polarity). Cap applies when `unless` returns FALSE.
|
|
125
|
+
{ unless: 'hasAcceptanceCriteria', capBelow: 'tasks_generated' },
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
/** The builder (encoreos-switchboard) 7-stage / 6-status layout as config-driven
|
|
129
|
+
* data — a faithful transcription of the imperative PIPELINE/STATUS_ORDER in
|
|
130
|
+
* encoreos-builder's `tools/eos-spec/src/lib/pipeline-map.ts`. Distinct from
|
|
131
|
+
* encore1: a 6-value statusOrder (no regulatory_grounded/compliance_reviewed/
|
|
132
|
+
* ux_reviewed), NO regulated-only stages, and NO caps — so builder's computeStage
|
|
133
|
+
* is a pure "highest done completesStatus". The draft-acs/generate-tests gates
|
|
134
|
+
* carry no `completesStatus` (they never advance the stage enum), so any drift in
|
|
135
|
+
* their predicate polarity cannot affect stage parity. Proven against the captured
|
|
136
|
+
* builder baseline by `pipeline-parity.builder.test.ts`. */
|
|
137
|
+
export const BUILDER_PIPELINE_SCHEMA = {
|
|
138
|
+
statusOrder: ['stub', 'clarified', 'validated', 'reviewed', 'planned', 'tasks_generated'],
|
|
139
|
+
stages: [
|
|
140
|
+
{
|
|
141
|
+
id: 'clarify-spec',
|
|
142
|
+
gate: 'hasContext',
|
|
143
|
+
actor: 'spec author',
|
|
144
|
+
actorType: 'human-gate',
|
|
145
|
+
invocation: 'resolve open placeholders/ambiguities in ${id} and record the answers in a ${id}-CONTEXT.md next to the spec',
|
|
146
|
+
reason: 'Spec has unresolved placeholders — clarify before validating.',
|
|
147
|
+
completesStatus: 'clarified',
|
|
148
|
+
optional: true,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: 'validate-spec',
|
|
152
|
+
gate: 'hasValidationSignoff',
|
|
153
|
+
actor: 'eos-spec CLI',
|
|
154
|
+
actorType: 'command',
|
|
155
|
+
invocation: 'check ${id} against the spec template structure, then `eos-spec signoff --type validated --spec ${id}` (writes the <!-- validated: --> marker)',
|
|
156
|
+
reason: 'Spec not validated — review structure against the template, then record the validation marker.',
|
|
157
|
+
completesStatus: 'validated',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'spec-review',
|
|
161
|
+
gate: 'hasSpecReview',
|
|
162
|
+
actor: 'reviewer',
|
|
163
|
+
actorType: 'human-gate',
|
|
164
|
+
invocation: 'review ${id} for implementability and overlap with existing specs, then record a review marker: `eos-spec signoff --type spec-reviewed --spec ${id}`',
|
|
165
|
+
reason: 'Spec is validated — review it and record a review marker.',
|
|
166
|
+
completesStatus: 'reviewed',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'draft-acs',
|
|
170
|
+
gate: 'acsDraftedOrNoStories',
|
|
171
|
+
actor: 'spec author',
|
|
172
|
+
actorType: 'human-gate',
|
|
173
|
+
invocation: "draft Given/When/Then acceptance criteria in ${id}'s frontmatter (acceptance_criteria:)",
|
|
174
|
+
reason: 'Spec has user stories but no acceptance criteria — draft ACs before writing tests.',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'generate-tests',
|
|
178
|
+
// BUILDER layout keys on e2e_tests-LISTED (hasGeneratedTests), not the
|
|
179
|
+
// fs-verified active suite — matching the retired builder fork + read-economy
|
|
180
|
+
// consumers (Spec Studio). See predicate-registry `testsListedOrProven`.
|
|
181
|
+
gate: 'testsListedOrProven',
|
|
182
|
+
actor: 'test author',
|
|
183
|
+
actorType: 'human-gate',
|
|
184
|
+
invocation: "write Vitest coverage for ${id}'s acceptance criteria and link it — add a colocated `@verifies ${id} AC-N` backlink in the test (the repo convention, proven by `eos-spec verify-acs`), or list the test file under e2e_tests: in the frontmatter",
|
|
185
|
+
reason: 'Acceptance criteria exist but no tests are linked — write them and add a @verifies backlink (or list them under e2e_tests:).',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: 'create-plan',
|
|
189
|
+
gate: 'hasPlan',
|
|
190
|
+
actor: 'spec author',
|
|
191
|
+
actorType: 'human-gate',
|
|
192
|
+
invocation: 'write specs/{core}/plans/${id}-PLAN.md from the plan template (specs/_templates/PLAN_TEMPLATE.md)',
|
|
193
|
+
reason: 'No implementation plan yet.',
|
|
194
|
+
completesStatus: 'planned',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: 'generate-tasks',
|
|
198
|
+
gate: 'hasTasks',
|
|
199
|
+
actor: 'eos-spec CLI',
|
|
200
|
+
actorType: 'command',
|
|
201
|
+
invocation: 'eos-spec tasks ${id}',
|
|
202
|
+
reason: 'Plan exists but no task breakdown.',
|
|
203
|
+
completesStatus: 'tasks_generated',
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
caps: [],
|
|
207
|
+
};
|
|
208
|
+
//# sourceMappingURL=pipeline-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-config.js","sourceRoot":"","sources":["../../src/lib/pipeline-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ActorType, PipelineSchema, PredicateRegistry } from './pipeline-schema.js';
|
|
2
|
+
import type { SpecFile } from './specs.js';
|
|
3
|
+
export type { ActorType } from './pipeline-schema.js';
|
|
4
|
+
export type Transition = {
|
|
5
|
+
/** Stable id; doubles as the emitted NextAction.type. */
|
|
6
|
+
id: string;
|
|
7
|
+
/** Who/what performs this transition. */
|
|
8
|
+
actor: string;
|
|
9
|
+
actorType: ActorType;
|
|
10
|
+
/** Exact thing to run/do, given a spec id. */
|
|
11
|
+
invocation: (specId: string) => string;
|
|
12
|
+
/** Human-readable reason shown when this is the next step. */
|
|
13
|
+
reason: string;
|
|
14
|
+
/** Only applies to regulated cores (cl/pm/hr/rh/gr). */
|
|
15
|
+
regulatedOnly?: boolean;
|
|
16
|
+
/** Advisory — surfaced as a hint but never blocks progression. */
|
|
17
|
+
optional?: boolean;
|
|
18
|
+
/** The pipeline_status enum value this transition completes (for schema-coverage + reconciliation). */
|
|
19
|
+
completesStatus?: string;
|
|
20
|
+
/** True when this transition's output already exists for the spec. */
|
|
21
|
+
isDone: (spec: SpecFile) => boolean;
|
|
22
|
+
};
|
|
23
|
+
/** Numeric rank of a pipeline_status value; unknown/undefined ranks below everything. */
|
|
24
|
+
export declare function rank(status?: string): number;
|
|
25
|
+
/** Legacy hand-written pipeline, preserved verbatim for parity + rollback. The
|
|
26
|
+
* active {@link PIPELINE} export is the config-driven {@link buildPipeline} output
|
|
27
|
+
* (selectable back to this via `EOS_PIPELINE=legacy`). */
|
|
28
|
+
export declare const LEGACY_PIPELINE: Transition[];
|
|
29
|
+
/** Derive a spec's furthest-reached pipeline stage from artifacts only.
|
|
30
|
+
*
|
|
31
|
+
* Sign-off markers are treated as **cumulative**: the stage is the highest
|
|
32
|
+
* `completesStatus` among *all* done transitions, regardless of whether an
|
|
33
|
+
* earlier gate's marker happens to be missing (a later marker implies the
|
|
34
|
+
* earlier stages were reached). This deliberately does NOT hard-cap at the
|
|
35
|
+
* first incomplete gate — that older behavior collapsed any spec missing an
|
|
36
|
+
* early marker (e.g. a `<!-- validated: -->` that was never written even though
|
|
37
|
+
* the spec was later reviewed, compliance-signed, planned and tasked) down to
|
|
38
|
+
* `clarified`/`stub`, which made `funnel`/`status` under-report the pipeline
|
|
39
|
+
* (H5). Out-of-order gaps are not hidden — `next` still walks for the first
|
|
40
|
+
* incomplete gate and surfaces the gap via its `outOfOrder` note.
|
|
41
|
+
*
|
|
42
|
+
* Returns `'stub'` as the floor when no stage has been reached. Ignores
|
|
43
|
+
* `pipeline_status` (that field is the cached output of this function,
|
|
44
|
+
* materialized by `reconcile`). */
|
|
45
|
+
export declare function legacyComputeStage(spec: SpecFile): string;
|
|
46
|
+
/** Interpret a config-driven {@link PipelineSchema} into the runtime engine —
|
|
47
|
+
* the `{ STATUS_ORDER, PIPELINE, rank, computeStage }` quartet the rest of the
|
|
48
|
+
* CLI consumes. The built `PIPELINE` is structurally a {@link Transition}[]: each
|
|
49
|
+
* stage's `invocation` template string is rendered into an `invocation(id)`
|
|
50
|
+
* FUNCTION and its named `gate` resolved to an `isDone` closure via `registry`,
|
|
51
|
+
* so callers (`next.ts`, `reconcile.ts`, scorecard/funnel) need ZERO changes.
|
|
52
|
+
*
|
|
53
|
+
* `computeStage` reproduces {@link legacyComputeStage} EXACTLY: same per-cap
|
|
54
|
+
* `whenRegulated` skip, same MIN-of-caps, the same regulatedOnly stage skip, and
|
|
55
|
+
* the same `best ?? 'stub'` floor. The Task 1.5 parity gate proves byte-for-byte
|
|
56
|
+
* equivalence against the captured encore1 baseline. */
|
|
57
|
+
export declare function buildPipeline(schema: PipelineSchema, registry: PredicateRegistry): {
|
|
58
|
+
STATUS_ORDER: string[];
|
|
59
|
+
PIPELINE: Transition[];
|
|
60
|
+
rank: (status?: string) => number;
|
|
61
|
+
computeStage: (spec: SpecFile) => string;
|
|
62
|
+
};
|
|
63
|
+
/** Canonical, ordered spec/test pipeline. First not-done applicable transition is
|
|
64
|
+
* the next step. Config-driven by default; `EOS_PIPELINE=legacy` selects {@link LEGACY_PIPELINE}. */
|
|
65
|
+
export declare const PIPELINE: Transition[];
|
|
66
|
+
/** Derive a spec's furthest-reached pipeline stage from artifacts only.
|
|
67
|
+
* Config-driven by default; `EOS_PIPELINE=legacy` selects {@link legacyComputeStage}. */
|
|
68
|
+
export declare const computeStage: (spec: SpecFile) => string;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { ENCORE1_PIPELINE_SCHEMA } from './pipeline-config.js';
|
|
2
|
+
import { validateSchema } from './pipeline-schema.js';
|
|
3
|
+
import { DEFAULT_PREDICATES } from './predicate-registry.js';
|
|
4
|
+
const STATUS_ORDER = [
|
|
5
|
+
'stub',
|
|
6
|
+
'clarified',
|
|
7
|
+
'validated',
|
|
8
|
+
'regulatory_grounded',
|
|
9
|
+
'reviewed',
|
|
10
|
+
'compliance_reviewed',
|
|
11
|
+
'ux_reviewed',
|
|
12
|
+
'planned',
|
|
13
|
+
'tasks_generated',
|
|
14
|
+
];
|
|
15
|
+
/** Numeric rank of a pipeline_status value; unknown/undefined ranks below everything. */
|
|
16
|
+
export function rank(status) {
|
|
17
|
+
if (!status)
|
|
18
|
+
return -1;
|
|
19
|
+
const i = STATUS_ORDER.indexOf(status);
|
|
20
|
+
return i === -1 ? -1 : i;
|
|
21
|
+
}
|
|
22
|
+
// TODO(post-cutover): once the schema pipeline bakes, delete LEGACY_PIPELINE,
|
|
23
|
+
// legacyComputeStage, and the EOS_PIPELINE ternary selector below.
|
|
24
|
+
/** Legacy hand-written pipeline, preserved verbatim for parity + rollback. The
|
|
25
|
+
* active {@link PIPELINE} export is the config-driven {@link buildPipeline} output
|
|
26
|
+
* (selectable back to this via `EOS_PIPELINE=legacy`). */
|
|
27
|
+
export const LEGACY_PIPELINE = [
|
|
28
|
+
{
|
|
29
|
+
id: 'clarify-spec',
|
|
30
|
+
actor: 'clarify-spec command',
|
|
31
|
+
actorType: 'command',
|
|
32
|
+
invocation: (id) => `clarify-spec --spec ${id}`,
|
|
33
|
+
reason: 'Spec has unresolved placeholders — clarify before validating.',
|
|
34
|
+
completesStatus: 'clarified',
|
|
35
|
+
// Clarify is conditional remediation, not a required artifact (CONTEXT.md exists
|
|
36
|
+
// for only ~30% of specs in practice). `optional: true` means non-blocking for
|
|
37
|
+
// derivation and skipped by the navigator unless explicitly run.
|
|
38
|
+
optional: true,
|
|
39
|
+
isDone: (s) => s.hasContext, // CONTEXT.md is the clarify artifact when present
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'validate-spec',
|
|
43
|
+
actor: 'validate-spec command',
|
|
44
|
+
actorType: 'command',
|
|
45
|
+
// The /validate-spec slash command (not `eos-spec validate`, the lint) is
|
|
46
|
+
// what writes the `<!-- validated: -->` marker this gate keys on. Name it
|
|
47
|
+
// explicitly so agents don't run the look-alike CLI lint and loop here.
|
|
48
|
+
invocation: (id) => `the /validate-spec command on ${id} (writes the <!-- validated: --> marker; alt: \`eos-spec signoff --type validated --spec ${id}\`)`,
|
|
49
|
+
reason: 'Spec not validated — run structure/constitution validation.',
|
|
50
|
+
completesStatus: 'validated',
|
|
51
|
+
isDone: (s) => s.signals.hasValidationSignoff,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'ground-research',
|
|
55
|
+
actor: 'encore-spec-research skill',
|
|
56
|
+
actorType: 'skill',
|
|
57
|
+
invocation: (id) => `the encore-spec-research skill on ${id}`,
|
|
58
|
+
reason: 'Regulated spec needs a research appendix before review.',
|
|
59
|
+
regulatedOnly: true,
|
|
60
|
+
completesStatus: 'regulatory_grounded',
|
|
61
|
+
isDone: (s) => s.signals.hasResearch,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'spec-review',
|
|
65
|
+
actor: 'spec-review skill',
|
|
66
|
+
actorType: 'skill',
|
|
67
|
+
invocation: (id) => `the spec-review skill on ${id}`,
|
|
68
|
+
reason: 'Spec is grounded — run the implementability/landscape review.',
|
|
69
|
+
completesStatus: 'reviewed',
|
|
70
|
+
isDone: (s) => s.signals.hasSpecReview,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'compliance-review',
|
|
74
|
+
actor: 'compliance-reviewer agent',
|
|
75
|
+
actorType: 'agent',
|
|
76
|
+
invocation: (id) => `the compliance-reviewer agent on ${id}, then merge its review PR`,
|
|
77
|
+
reason: 'Regulated spec needs compliance sign-off (human-gated PR).',
|
|
78
|
+
regulatedOnly: true,
|
|
79
|
+
completesStatus: 'compliance_reviewed',
|
|
80
|
+
isDone: (s) => s.signals.hasComplianceSignoff,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'draft-acs',
|
|
84
|
+
actor: 'encore-spec-ac-draft skill',
|
|
85
|
+
actorType: 'skill',
|
|
86
|
+
invocation: (id) => `the encore-spec-ac-draft skill on ${id}`,
|
|
87
|
+
reason: 'Spec has user stories but no acceptance criteria — draft ACs before generating tests.',
|
|
88
|
+
isDone: (s) => !s.signals.hasUserStories || s.signals.hasAcceptanceCriteria,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'generate-tests',
|
|
92
|
+
actor: 'encore-spec-to-test skill',
|
|
93
|
+
actorType: 'skill',
|
|
94
|
+
invocation: (id) => `the encore-spec-to-test skill on ${id}`,
|
|
95
|
+
reason: 'Acceptance criteria exist but no E2E tests are linked — generate them.',
|
|
96
|
+
// B5: a generated suite counts as done only when it has ≥1 ACTIVE test()
|
|
97
|
+
// (hasActiveGeneratedTests) — a stub-only test.fixme scaffold is tests-STUBBED,
|
|
98
|
+
// not tests-generated, so the navigator keeps surfacing the implement step.
|
|
99
|
+
// (Funnel/scorecard are unaffected: requirementsVerified already ignores fixme.)
|
|
100
|
+
// C1: hand-authored proof — all-ACs-verified (and, after Task 2, a linked
|
|
101
|
+
// `@verifies` local spec) — also satisfies this gate; a stub-only test.fixme
|
|
102
|
+
// scaffold still does not (B5).
|
|
103
|
+
isDone: (s) => !s.signals.hasAcceptanceCriteria ||
|
|
104
|
+
s.signals.hasActiveGeneratedTests ||
|
|
105
|
+
s.signals.hasVerifiedAcceptanceCriteria ||
|
|
106
|
+
s.signals.hasLinkedLocalTest,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'a11y-audit',
|
|
110
|
+
actor: 'encore-a11y-audit skill',
|
|
111
|
+
actorType: 'skill',
|
|
112
|
+
invocation: (id) => `the encore-a11y-audit skill on ${id} (UI-bearing specs)`,
|
|
113
|
+
reason: 'Optional: run a per-route accessibility audit for UI-bearing specs.',
|
|
114
|
+
optional: true,
|
|
115
|
+
completesStatus: 'ux_reviewed',
|
|
116
|
+
isDone: (s) => s.signals.hasUxSignoff,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'create-plan',
|
|
120
|
+
actor: 'create-plan / validate-plan command',
|
|
121
|
+
actorType: 'command',
|
|
122
|
+
invocation: (id) => `validate-spec --spec ${id} --auto-plan (or create-plan), then validate-plan --spec ${id}`,
|
|
123
|
+
reason: 'No implementation plan yet.',
|
|
124
|
+
completesStatus: 'planned',
|
|
125
|
+
isDone: (s) => s.hasPlan,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'generate-tasks',
|
|
129
|
+
actor: 'generate-tasks command',
|
|
130
|
+
actorType: 'command',
|
|
131
|
+
invocation: (id) => `eos-spec tasks ${id}`,
|
|
132
|
+
reason: 'Plan exists but no task breakdown.',
|
|
133
|
+
completesStatus: 'tasks_generated',
|
|
134
|
+
isDone: (s) => s.hasTasks,
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
/** Derive a spec's furthest-reached pipeline stage from artifacts only.
|
|
138
|
+
*
|
|
139
|
+
* Sign-off markers are treated as **cumulative**: the stage is the highest
|
|
140
|
+
* `completesStatus` among *all* done transitions, regardless of whether an
|
|
141
|
+
* earlier gate's marker happens to be missing (a later marker implies the
|
|
142
|
+
* earlier stages were reached). This deliberately does NOT hard-cap at the
|
|
143
|
+
* first incomplete gate — that older behavior collapsed any spec missing an
|
|
144
|
+
* early marker (e.g. a `<!-- validated: -->` that was never written even though
|
|
145
|
+
* the spec was later reviewed, compliance-signed, planned and tasked) down to
|
|
146
|
+
* `clarified`/`stub`, which made `funnel`/`status` under-report the pipeline
|
|
147
|
+
* (H5). Out-of-order gaps are not hidden — `next` still walks for the first
|
|
148
|
+
* incomplete gate and surfaces the gap via its `outOfOrder` note.
|
|
149
|
+
*
|
|
150
|
+
* Returns `'stub'` as the floor when no stage has been reached. Ignores
|
|
151
|
+
* `pipeline_status` (that field is the cached output of this function,
|
|
152
|
+
* materialized by `reconcile`). */
|
|
153
|
+
export function legacyComputeStage(spec) {
|
|
154
|
+
// Honest caps: some downstream artifacts exist on disk yet the spec has not
|
|
155
|
+
// actually cleared the evidence gate the corresponding pipeline_status keys on.
|
|
156
|
+
// Each unmet prerequisite caps the computed stage *below* the status it would
|
|
157
|
+
// otherwise claim, surfacing the latent overclaim instead of masking it — and
|
|
158
|
+
// avoids the drift catch-22 where written pipeline_status can't honestly drop
|
|
159
|
+
// below a computed value reached out-of-order. We take the MINIMUM (tightest)
|
|
160
|
+
// of the applicable caps so all of them apply.
|
|
161
|
+
//
|
|
162
|
+
// • Research cap: a regulated spec without a research appendix has not passed
|
|
163
|
+
// regulatory_grounded, so later-stage artifacts (plan/tasks/compliance)
|
|
164
|
+
// cannot lift its stage to or beyond regulatory_grounded.
|
|
165
|
+
// • Acceptance-criteria cap: the generate-tasks transition is "done" merely
|
|
166
|
+
// because a TASKS file exists, but the evidence gate
|
|
167
|
+
// (scripts/specs/validate-pipeline-status.ts) requires acceptance_criteria
|
|
168
|
+
// at tasks_generated. A spec with a tasks file but no ACs therefore cannot
|
|
169
|
+
// honestly reach tasks_generated.
|
|
170
|
+
const caps = [];
|
|
171
|
+
if (spec.signals.isRegulated && !spec.signals.hasResearch)
|
|
172
|
+
caps.push(rank('regulatory_grounded'));
|
|
173
|
+
if (!spec.signals.hasAcceptanceCriteria)
|
|
174
|
+
caps.push(rank('tasks_generated'));
|
|
175
|
+
const capRank = caps.length ? Math.min(...caps) : Number.POSITIVE_INFINITY;
|
|
176
|
+
let best;
|
|
177
|
+
for (const t of LEGACY_PIPELINE) {
|
|
178
|
+
if (t.regulatedOnly && !spec.signals.isRegulated)
|
|
179
|
+
continue;
|
|
180
|
+
if (!t.isDone(spec) || !t.completesStatus)
|
|
181
|
+
continue;
|
|
182
|
+
if (rank(t.completesStatus) >= capRank)
|
|
183
|
+
continue; // honest cap
|
|
184
|
+
if (rank(t.completesStatus) > rank(best))
|
|
185
|
+
best = t.completesStatus;
|
|
186
|
+
}
|
|
187
|
+
return best ?? 'stub';
|
|
188
|
+
}
|
|
189
|
+
/** Interpret a config-driven {@link PipelineSchema} into the runtime engine —
|
|
190
|
+
* the `{ STATUS_ORDER, PIPELINE, rank, computeStage }` quartet the rest of the
|
|
191
|
+
* CLI consumes. The built `PIPELINE` is structurally a {@link Transition}[]: each
|
|
192
|
+
* stage's `invocation` template string is rendered into an `invocation(id)`
|
|
193
|
+
* FUNCTION and its named `gate` resolved to an `isDone` closure via `registry`,
|
|
194
|
+
* so callers (`next.ts`, `reconcile.ts`, scorecard/funnel) need ZERO changes.
|
|
195
|
+
*
|
|
196
|
+
* `computeStage` reproduces {@link legacyComputeStage} EXACTLY: same per-cap
|
|
197
|
+
* `whenRegulated` skip, same MIN-of-caps, the same regulatedOnly stage skip, and
|
|
198
|
+
* the same `best ?? 'stub'` floor. The Task 1.5 parity gate proves byte-for-byte
|
|
199
|
+
* equivalence against the captured encore1 baseline. */
|
|
200
|
+
export function buildPipeline(schema, registry) {
|
|
201
|
+
validateSchema(schema, registry);
|
|
202
|
+
const order = schema.statusOrder;
|
|
203
|
+
const rankFn = (status) => {
|
|
204
|
+
if (!status)
|
|
205
|
+
return -1;
|
|
206
|
+
const i = order.indexOf(status);
|
|
207
|
+
return i === -1 ? -1 : i;
|
|
208
|
+
};
|
|
209
|
+
const pipeline = schema.stages.map((st) => ({
|
|
210
|
+
id: st.id,
|
|
211
|
+
actor: st.actor,
|
|
212
|
+
actorType: st.actorType,
|
|
213
|
+
// Render the `${id}` template literal into the legacy `invocation` FUNCTION shape.
|
|
214
|
+
invocation: (id) => st.invocation.replaceAll('${id}', id),
|
|
215
|
+
reason: st.reason,
|
|
216
|
+
regulatedOnly: st.regulatedOnly,
|
|
217
|
+
optional: st.optional,
|
|
218
|
+
completesStatus: st.completesStatus,
|
|
219
|
+
isDone: registry[st.gate],
|
|
220
|
+
}));
|
|
221
|
+
const computeStageFn = (spec) => {
|
|
222
|
+
const caps = [];
|
|
223
|
+
for (const cap of schema.caps) {
|
|
224
|
+
if (cap.whenRegulated && !spec.signals.isRegulated)
|
|
225
|
+
continue;
|
|
226
|
+
if (!registry[cap.unless](spec))
|
|
227
|
+
caps.push(rankFn(cap.capBelow));
|
|
228
|
+
}
|
|
229
|
+
const capRank = caps.length ? Math.min(...caps) : Number.POSITIVE_INFINITY;
|
|
230
|
+
let best;
|
|
231
|
+
for (const t of pipeline) {
|
|
232
|
+
if (t.regulatedOnly && !spec.signals.isRegulated)
|
|
233
|
+
continue;
|
|
234
|
+
if (!t.isDone(spec) || !t.completesStatus)
|
|
235
|
+
continue;
|
|
236
|
+
if (rankFn(t.completesStatus) >= capRank)
|
|
237
|
+
continue; // honest cap
|
|
238
|
+
if (rankFn(t.completesStatus) > rankFn(best))
|
|
239
|
+
best = t.completesStatus;
|
|
240
|
+
}
|
|
241
|
+
return best ?? 'stub';
|
|
242
|
+
};
|
|
243
|
+
return { STATUS_ORDER: order, PIPELINE: pipeline, rank: rankFn, computeStage: computeStageFn };
|
|
244
|
+
}
|
|
245
|
+
// Active selection — config-driven by default; `EOS_PIPELINE=legacy` rolls back
|
|
246
|
+
// to the hand-written engine. STATUS_ORDER/rank are identical in both
|
|
247
|
+
// (schema.statusOrder === legacy STATUS_ORDER), so the existing exports stand.
|
|
248
|
+
const _built = buildPipeline(ENCORE1_PIPELINE_SCHEMA, DEFAULT_PREDICATES);
|
|
249
|
+
// NOTE: EOS_PIPELINE is read once at module load — set it before import, not mid-test.
|
|
250
|
+
/** Canonical, ordered spec/test pipeline. First not-done applicable transition is
|
|
251
|
+
* the next step. Config-driven by default; `EOS_PIPELINE=legacy` selects {@link LEGACY_PIPELINE}. */
|
|
252
|
+
export const PIPELINE = process.env.EOS_PIPELINE === 'legacy' ? LEGACY_PIPELINE : _built.PIPELINE;
|
|
253
|
+
/** Derive a spec's furthest-reached pipeline stage from artifacts only.
|
|
254
|
+
* Config-driven by default; `EOS_PIPELINE=legacy` selects {@link legacyComputeStage}. */
|
|
255
|
+
export const computeStage = process.env.EOS_PIPELINE === 'legacy' ? legacyComputeStage : _built.computeStage;
|
|
256
|
+
//# sourceMappingURL=pipeline-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-map.js","sourceRoot":"","sources":["../../src/lib/pipeline-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SpecFile } from './specs.js';
|
|
2
|
+
/** Who/what performs a pipeline stage transition. */
|
|
3
|
+
export type ActorType = 'command' | 'skill' | 'agent' | 'human-gate';
|
|
4
|
+
/** A named gate/cap predicate over a spec's artifacts/signals. */
|
|
5
|
+
export type StagePredicate = (spec: SpecFile) => boolean;
|
|
6
|
+
/** Registry of named predicates referenced by a {@link PipelineSchema}. */
|
|
7
|
+
export type PredicateRegistry = Record<string, StagePredicate>;
|
|
8
|
+
/** A single pipeline stage, as pure data (the runtime `isDone` closure is
|
|
9
|
+
* supplied by name via the {@link PredicateRegistry} `gate`). */
|
|
10
|
+
export type StageDef = {
|
|
11
|
+
/** Stable id; doubles as the emitted NextAction.type. */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Name of the predicate in the registry that determines whether this stage is done. */
|
|
14
|
+
gate: string;
|
|
15
|
+
/** Who/what performs this transition. */
|
|
16
|
+
actor: string;
|
|
17
|
+
actorType: ActorType;
|
|
18
|
+
/** Exact thing to run/do; a `${id}` literal placeholder is substituted at interpret time. */
|
|
19
|
+
invocation: string;
|
|
20
|
+
/** Human-readable reason shown when this is the next step. */
|
|
21
|
+
reason: string;
|
|
22
|
+
/** Only applies to regulated cores (cl/pm/hr/rh/gr). */
|
|
23
|
+
regulatedOnly?: boolean;
|
|
24
|
+
/** Advisory — surfaced as a hint but never blocks progression. */
|
|
25
|
+
optional?: boolean;
|
|
26
|
+
/** The pipeline_status enum value this transition completes (for schema-coverage + reconciliation). */
|
|
27
|
+
completesStatus?: string;
|
|
28
|
+
};
|
|
29
|
+
/** An honest-cap rule: when the `unless` predicate returns FALSE, the computed
|
|
30
|
+
* stage is capped below `capBelow`. `whenRegulated` scopes the cap to regulated specs. */
|
|
31
|
+
export type CapDef = {
|
|
32
|
+
/** Name of the registry predicate; the cap applies when it returns FALSE. */
|
|
33
|
+
unless: string;
|
|
34
|
+
/** Scope the cap to regulated specs only. */
|
|
35
|
+
whenRegulated?: boolean;
|
|
36
|
+
/** The pipeline_status the computed stage is capped below when the cap applies. */
|
|
37
|
+
capBelow: string;
|
|
38
|
+
};
|
|
39
|
+
/** The full config-driven pipeline definition. */
|
|
40
|
+
export type PipelineSchema = {
|
|
41
|
+
statusOrder: string[];
|
|
42
|
+
stages: StageDef[];
|
|
43
|
+
caps: CapDef[];
|
|
44
|
+
};
|
|
45
|
+
/** Validate a {@link PipelineSchema} against its {@link PredicateRegistry}: every
|
|
46
|
+
* stage gate and cap predicate must be registered, and every `completesStatus`/
|
|
47
|
+
* `capBelow` must be a known status. Throws on the first violation. */
|
|
48
|
+
export declare function validateSchema(schema: PipelineSchema, registry: PredicateRegistry): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Validate a {@link PipelineSchema} against its {@link PredicateRegistry}: every
|
|
2
|
+
* stage gate and cap predicate must be registered, and every `completesStatus`/
|
|
3
|
+
* `capBelow` must be a known status. Throws on the first violation. */
|
|
4
|
+
export function validateSchema(schema, registry) {
|
|
5
|
+
for (const st of schema.stages) {
|
|
6
|
+
if (!registry[st.gate]) {
|
|
7
|
+
throw new Error(`pipeline schema: unknown gate predicate '${st.gate}' for stage '${st.id}'`);
|
|
8
|
+
}
|
|
9
|
+
if (st.completesStatus && !schema.statusOrder.includes(st.completesStatus)) {
|
|
10
|
+
throw new Error(`pipeline schema: stage '${st.id}' completesStatus '${st.completesStatus}' not in statusOrder`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
for (const cap of schema.caps) {
|
|
14
|
+
if (!registry[cap.unless]) {
|
|
15
|
+
throw new Error(`pipeline schema: unknown cap predicate '${cap.unless}'`);
|
|
16
|
+
}
|
|
17
|
+
if (!schema.statusOrder.includes(cap.capBelow)) {
|
|
18
|
+
throw new Error(`pipeline schema: cap capBelow '${cap.capBelow}' not in statusOrder`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=pipeline-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-schema.js","sourceRoot":"","sources":["../../src/lib/pipeline-schema.ts"],"names":[],"mappings":"AAmDA;;wEAEwE;AACxE,MAAM,UAAU,cAAc,CAAC,MAAsB,EAAE,QAA2B;IAChF,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,EAAE,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3E,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE,CAAC,EAAE,sBAAsB,EAAE,CAAC,eAAe,sBAAsB,CAAC,CAAC;QAClH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,2CAA2C,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,QAAQ,sBAAsB,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;AACH,CAAC"}
|