@encore-os/eos-spec 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/LICENSE +17 -0
  2. package/bin/check-dist-fresh.js +51 -0
  3. package/bin/eos-spec.js +7 -0
  4. package/dist/commands/ac-backfill.d.ts +31 -0
  5. package/dist/commands/ac-backfill.js +198 -0
  6. package/dist/commands/ac-backfill.js.map +1 -0
  7. package/dist/commands/archive.d.ts +2 -0
  8. package/dist/commands/archive.js +101 -0
  9. package/dist/commands/archive.js.map +1 -0
  10. package/dist/commands/audit.d.ts +30 -0
  11. package/dist/commands/audit.js +107 -0
  12. package/dist/commands/audit.js.map +1 -0
  13. package/dist/commands/backfill.d.ts +41 -0
  14. package/dist/commands/backfill.js +239 -0
  15. package/dist/commands/backfill.js.map +1 -0
  16. package/dist/commands/checkArtifacts.d.ts +2 -0
  17. package/dist/commands/checkArtifacts.js +48 -0
  18. package/dist/commands/checkArtifacts.js.map +1 -0
  19. package/dist/commands/checkPlacement.d.ts +2 -0
  20. package/dist/commands/checkPlacement.js +31 -0
  21. package/dist/commands/checkPlacement.js.map +1 -0
  22. package/dist/commands/claim.d.ts +4 -0
  23. package/dist/commands/claim.js +46 -0
  24. package/dist/commands/claim.js.map +1 -0
  25. package/dist/commands/complete.d.ts +2 -0
  26. package/dist/commands/complete.js +138 -0
  27. package/dist/commands/complete.js.map +1 -0
  28. package/dist/commands/conformance.d.ts +23 -0
  29. package/dist/commands/conformance.js +124 -0
  30. package/dist/commands/conformance.js.map +1 -0
  31. package/dist/commands/create.d.ts +6 -0
  32. package/dist/commands/create.js +277 -0
  33. package/dist/commands/create.js.map +1 -0
  34. package/dist/commands/deferred.d.ts +2 -0
  35. package/dist/commands/deferred.js +85 -0
  36. package/dist/commands/deferred.js.map +1 -0
  37. package/dist/commands/delta.d.ts +17 -0
  38. package/dist/commands/delta.js +292 -0
  39. package/dist/commands/delta.js.map +1 -0
  40. package/dist/commands/freshness.d.ts +13 -0
  41. package/dist/commands/freshness.js +72 -0
  42. package/dist/commands/freshness.js.map +1 -0
  43. package/dist/commands/funnel.d.ts +2 -0
  44. package/dist/commands/funnel.js +61 -0
  45. package/dist/commands/funnel.js.map +1 -0
  46. package/dist/commands/gen-tests.d.ts +2 -0
  47. package/dist/commands/gen-tests.js +53 -0
  48. package/dist/commands/gen-tests.js.map +1 -0
  49. package/dist/commands/init.d.ts +2 -0
  50. package/dist/commands/init.js +64 -0
  51. package/dist/commands/init.js.map +1 -0
  52. package/dist/commands/list.d.ts +9 -0
  53. package/dist/commands/list.js +61 -0
  54. package/dist/commands/list.js.map +1 -0
  55. package/dist/commands/metrics.d.ts +2 -0
  56. package/dist/commands/metrics.js +66 -0
  57. package/dist/commands/metrics.js.map +1 -0
  58. package/dist/commands/next.d.ts +48 -0
  59. package/dist/commands/next.js +344 -0
  60. package/dist/commands/next.js.map +1 -0
  61. package/dist/commands/precedent.d.ts +66 -0
  62. package/dist/commands/precedent.js +343 -0
  63. package/dist/commands/precedent.js.map +1 -0
  64. package/dist/commands/ready.d.ts +28 -0
  65. package/dist/commands/ready.js +147 -0
  66. package/dist/commands/ready.js.map +1 -0
  67. package/dist/commands/reconcile.d.ts +44 -0
  68. package/dist/commands/reconcile.js +187 -0
  69. package/dist/commands/reconcile.js.map +1 -0
  70. package/dist/commands/rollup.d.ts +2 -0
  71. package/dist/commands/rollup.js +43 -0
  72. package/dist/commands/rollup.js.map +1 -0
  73. package/dist/commands/scorecard.d.ts +11 -0
  74. package/dist/commands/scorecard.js +55 -0
  75. package/dist/commands/scorecard.js.map +1 -0
  76. package/dist/commands/signoff.d.ts +2 -0
  77. package/dist/commands/signoff.js +114 -0
  78. package/dist/commands/signoff.js.map +1 -0
  79. package/dist/commands/status.d.ts +2 -0
  80. package/dist/commands/status.js +100 -0
  81. package/dist/commands/status.js.map +1 -0
  82. package/dist/commands/tasks.d.ts +13 -0
  83. package/dist/commands/tasks.js +81 -0
  84. package/dist/commands/tasks.js.map +1 -0
  85. package/dist/commands/validate.d.ts +16 -0
  86. package/dist/commands/validate.js +89 -0
  87. package/dist/commands/validate.js.map +1 -0
  88. package/dist/commands/verify-acs.d.ts +15 -0
  89. package/dist/commands/verify-acs.js +196 -0
  90. package/dist/commands/verify-acs.js.map +1 -0
  91. package/dist/commands/verifyRollout.d.ts +2 -0
  92. package/dist/commands/verifyRollout.js +125 -0
  93. package/dist/commands/verifyRollout.js.map +1 -0
  94. package/dist/index.d.ts +21 -0
  95. package/dist/index.js +138 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/lib/ac-draft-prompt.d.ts +18 -0
  98. package/dist/lib/ac-draft-prompt.js +38 -0
  99. package/dist/lib/ac-draft-prompt.js.map +1 -0
  100. package/dist/lib/ac-response-parser.d.ts +18 -0
  101. package/dist/lib/ac-response-parser.js +57 -0
  102. package/dist/lib/ac-response-parser.js.map +1 -0
  103. package/dist/lib/ai-call.d.ts +13 -0
  104. package/dist/lib/ai-call.js +17 -0
  105. package/dist/lib/ai-call.js.map +1 -0
  106. package/dist/lib/archive.d.ts +21 -0
  107. package/dist/lib/archive.js +136 -0
  108. package/dist/lib/archive.js.map +1 -0
  109. package/dist/lib/artifact-integrity.d.ts +5 -0
  110. package/dist/lib/artifact-integrity.js +65 -0
  111. package/dist/lib/artifact-integrity.js.map +1 -0
  112. package/dist/lib/backfill-queue.d.ts +11 -0
  113. package/dist/lib/backfill-queue.js +14 -0
  114. package/dist/lib/backfill-queue.js.map +1 -0
  115. package/dist/lib/blockers.d.ts +66 -0
  116. package/dist/lib/blockers.js +103 -0
  117. package/dist/lib/blockers.js.map +1 -0
  118. package/dist/lib/claims.d.ts +39 -0
  119. package/dist/lib/claims.js +133 -0
  120. package/dist/lib/claims.js.map +1 -0
  121. package/dist/lib/classify-debt.d.ts +17 -0
  122. package/dist/lib/classify-debt.js +13 -0
  123. package/dist/lib/classify-debt.js.map +1 -0
  124. package/dist/lib/code-evidence.d.ts +35 -0
  125. package/dist/lib/code-evidence.js +171 -0
  126. package/dist/lib/code-evidence.js.map +1 -0
  127. package/dist/lib/coherence.d.ts +14 -0
  128. package/dist/lib/coherence.js +188 -0
  129. package/dist/lib/coherence.js.map +1 -0
  130. package/dist/lib/completion-gate.d.ts +17 -0
  131. package/dist/lib/completion-gate.js +28 -0
  132. package/dist/lib/completion-gate.js.map +1 -0
  133. package/dist/lib/compliance-signoff.d.ts +39 -0
  134. package/dist/lib/compliance-signoff.js +81 -0
  135. package/dist/lib/compliance-signoff.js.map +1 -0
  136. package/dist/lib/config.d.ts +63 -0
  137. package/dist/lib/config.js +40 -0
  138. package/dist/lib/config.js.map +1 -0
  139. package/dist/lib/cost.d.ts +12 -0
  140. package/dist/lib/cost.js +12 -0
  141. package/dist/lib/cost.js.map +1 -0
  142. package/dist/lib/debt-dashboard.d.ts +25 -0
  143. package/dist/lib/debt-dashboard.js +36 -0
  144. package/dist/lib/debt-dashboard.js.map +1 -0
  145. package/dist/lib/embedding-store.d.ts +103 -0
  146. package/dist/lib/embedding-store.js +133 -0
  147. package/dist/lib/embedding-store.js.map +1 -0
  148. package/dist/lib/embeddings-source.d.ts +36 -0
  149. package/dist/lib/embeddings-source.js +62 -0
  150. package/dist/lib/embeddings-source.js.map +1 -0
  151. package/dist/lib/enforcement-allowlist.d.ts +12 -0
  152. package/dist/lib/enforcement-allowlist.js +25 -0
  153. package/dist/lib/enforcement-allowlist.js.map +1 -0
  154. package/dist/lib/events.d.ts +47 -0
  155. package/dist/lib/events.js +75 -0
  156. package/dist/lib/events.js.map +1 -0
  157. package/dist/lib/exec.d.ts +8 -0
  158. package/dist/lib/exec.js +25 -0
  159. package/dist/lib/exec.js.map +1 -0
  160. package/dist/lib/frontmatter.d.ts +112 -0
  161. package/dist/lib/frontmatter.js +261 -0
  162. package/dist/lib/frontmatter.js.map +1 -0
  163. package/dist/lib/funnel.d.ts +22 -0
  164. package/dist/lib/funnel.js +41 -0
  165. package/dist/lib/funnel.js.map +1 -0
  166. package/dist/lib/git-mtime.d.ts +4 -0
  167. package/dist/lib/git-mtime.js +23 -0
  168. package/dist/lib/git-mtime.js.map +1 -0
  169. package/dist/lib/metrics.d.ts +42 -0
  170. package/dist/lib/metrics.js +92 -0
  171. package/dist/lib/metrics.js.map +1 -0
  172. package/dist/lib/migration-collision.d.ts +20 -0
  173. package/dist/lib/migration-collision.js +61 -0
  174. package/dist/lib/migration-collision.js.map +1 -0
  175. package/dist/lib/next-action.d.ts +44 -0
  176. package/dist/lib/next-action.js +138 -0
  177. package/dist/lib/next-action.js.map +1 -0
  178. package/dist/lib/ollama-embed.d.ts +21 -0
  179. package/dist/lib/ollama-embed.js +65 -0
  180. package/dist/lib/ollama-embed.js.map +1 -0
  181. package/dist/lib/output.d.ts +35 -0
  182. package/dist/lib/output.js +46 -0
  183. package/dist/lib/output.js.map +1 -0
  184. package/dist/lib/pipeline-config.d.ts +20 -0
  185. package/dist/lib/pipeline-config.js +208 -0
  186. package/dist/lib/pipeline-config.js.map +1 -0
  187. package/dist/lib/pipeline-map.d.ts +68 -0
  188. package/dist/lib/pipeline-map.js +256 -0
  189. package/dist/lib/pipeline-map.js.map +1 -0
  190. package/dist/lib/pipeline-schema.d.ts +48 -0
  191. package/dist/lib/pipeline-schema.js +22 -0
  192. package/dist/lib/pipeline-schema.js.map +1 -0
  193. package/dist/lib/placement.d.ts +6 -0
  194. package/dist/lib/placement.js +40 -0
  195. package/dist/lib/placement.js.map +1 -0
  196. package/dist/lib/precedent-search.d.ts +18 -0
  197. package/dist/lib/precedent-search.js +160 -0
  198. package/dist/lib/precedent-search.js.map +1 -0
  199. package/dist/lib/predicate-registry.d.ts +6 -0
  200. package/dist/lib/predicate-registry.js +40 -0
  201. package/dist/lib/predicate-registry.js.map +1 -0
  202. package/dist/lib/recall-cases.d.ts +15 -0
  203. package/dist/lib/recall-cases.js +39 -0
  204. package/dist/lib/recall-cases.js.map +1 -0
  205. package/dist/lib/repo.d.ts +20 -0
  206. package/dist/lib/repo.js +82 -0
  207. package/dist/lib/repo.js.map +1 -0
  208. package/dist/lib/requirements.d.ts +91 -0
  209. package/dist/lib/requirements.js +179 -0
  210. package/dist/lib/requirements.js.map +1 -0
  211. package/dist/lib/rollup.d.ts +24 -0
  212. package/dist/lib/rollup.js +34 -0
  213. package/dist/lib/rollup.js.map +1 -0
  214. package/dist/lib/scorecard-run.d.ts +6 -0
  215. package/dist/lib/scorecard-run.js +48 -0
  216. package/dist/lib/scorecard-run.js.map +1 -0
  217. package/dist/lib/scorecard.d.ts +69 -0
  218. package/dist/lib/scorecard.js +113 -0
  219. package/dist/lib/scorecard.js.map +1 -0
  220. package/dist/lib/semantic-search.d.ts +36 -0
  221. package/dist/lib/semantic-search.js +56 -0
  222. package/dist/lib/semantic-search.js.map +1 -0
  223. package/dist/lib/session-state.d.ts +8 -0
  224. package/dist/lib/session-state.js +25 -0
  225. package/dist/lib/session-state.js.map +1 -0
  226. package/dist/lib/spec-debt.d.ts +8 -0
  227. package/dist/lib/spec-debt.js +17 -0
  228. package/dist/lib/spec-debt.js.map +1 -0
  229. package/dist/lib/spec-pure.d.ts +59 -0
  230. package/dist/lib/spec-pure.js +215 -0
  231. package/dist/lib/spec-pure.js.map +1 -0
  232. package/dist/lib/specs.d.ts +148 -0
  233. package/dist/lib/specs.js +373 -0
  234. package/dist/lib/specs.js.map +1 -0
  235. package/dist/lib/test-generator.d.ts +5 -0
  236. package/dist/lib/test-generator.js +72 -0
  237. package/dist/lib/test-generator.js.map +1 -0
  238. package/dist/lib/user-stories.d.ts +6 -0
  239. package/dist/lib/user-stories.js +56 -0
  240. package/dist/lib/user-stories.js.map +1 -0
  241. package/dist/lib/verifies-scan.d.ts +9 -0
  242. package/dist/lib/verifies-scan.js +73 -0
  243. package/dist/lib/verifies-scan.js.map +1 -0
  244. package/dist/lib/verify-core.d.ts +23 -0
  245. package/dist/lib/verify-core.js +48 -0
  246. package/dist/lib/verify-core.js.map +1 -0
  247. package/dist/lib/with-event-log.d.ts +12 -0
  248. package/dist/lib/with-event-log.js +65 -0
  249. package/dist/lib/with-event-log.js.map +1 -0
  250. package/dist/lib/wizard-specs.d.ts +17 -0
  251. package/dist/lib/wizard-specs.js +34 -0
  252. package/dist/lib/wizard-specs.js.map +1 -0
  253. package/dist/pure.d.ts +19 -0
  254. package/dist/pure.js +31 -0
  255. package/dist/pure.js.map +1 -0
  256. package/package.json +69 -0
@@ -0,0 +1,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"}
@@ -0,0 +1,6 @@
1
+ export type Misplaced = {
2
+ id: string;
3
+ path: string;
4
+ expectedDir: string;
5
+ };
6
+ export declare function findMisplacedSpecs(repoRoot: string): Misplaced[];