@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,20 @@
1
+ export type Collision = {
2
+ table: string;
3
+ migration: string;
4
+ };
5
+ /** Map of every CREATE TABLE name across supabase/migrations -> first migration file declaring it.
6
+ * Lowercased; tolerant of IF NOT EXISTS, optional schema prefix, and quoting. One pass over all files. */
7
+ export declare function migrationTables(repoRoot: string): Map<string, string>;
8
+ /** Collisions between the given identifiers and existing migration tables. */
9
+ export declare function findMigrationCollisions(repoRoot: string, identifiers: string[]): Collision[];
10
+ /** Does the spec body declare it CREATES this table (vs merely referencing / reusing it)?
11
+ * Two accepted declaration forms:
12
+ * 1. Literal DDL: `CREATE TABLE [IF NOT EXISTS] [schema.]<table>` (tolerant of quoting).
13
+ * 2. Data-Model heading whose entire text is the table name: `#### \`<table>\`` / `### <table>`.
14
+ * Inline mentions (bullets, prose, "reuses `x`") are treated as references, not creates —
15
+ * that removes the false-positive class (FA-29) while keeping real declarations (PM-21).
16
+ * A spec that defines a table some other way is treated as a reference; a missed real
17
+ * collision is still caught later at migration-authoring time. */
18
+ export declare function specCreatesTable(body: string, table: string): boolean;
19
+ /** Filter identifiers down to those the spec body declares it CREATES. */
20
+ export declare function createdTables(body: string, identifiers: string[]): string[];
@@ -0,0 +1,61 @@
1
+ // Mirrors scripts/specs/migration-collision.ts
2
+ // Self-contained copy to avoid deep cross-package relative imports (no-restricted-imports).
3
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ /** Map of every CREATE TABLE name across supabase/migrations -> first migration file declaring it.
6
+ * Lowercased; tolerant of IF NOT EXISTS, optional schema prefix, and quoting. One pass over all files. */
7
+ export function migrationTables(repoRoot) {
8
+ const dir = join(repoRoot, 'supabase/migrations');
9
+ const map = new Map();
10
+ if (!existsSync(dir))
11
+ return map;
12
+ const re = /create\s+table\s+(?:if\s+not\s+exists\s+)?(?:"?[a-z_]+"?\.)?"?([a-z_][a-z0-9_]*)"?/gi;
13
+ for (const f of readdirSync(dir)) {
14
+ if (!f.endsWith('.sql'))
15
+ continue;
16
+ const sql = readFileSync(join(dir, f), 'utf8');
17
+ let m;
18
+ while ((m = re.exec(sql)) !== null) {
19
+ const t = m[1].toLowerCase();
20
+ if (!map.has(t))
21
+ map.set(t, f);
22
+ }
23
+ }
24
+ return map;
25
+ }
26
+ /** Collisions between the given identifiers and existing migration tables. */
27
+ export function findMigrationCollisions(repoRoot, identifiers) {
28
+ const tables = migrationTables(repoRoot);
29
+ const out = [];
30
+ const seen = new Set();
31
+ for (const id of identifiers) {
32
+ const key = id.toLowerCase();
33
+ if (tables.has(key) && !seen.has(key)) {
34
+ out.push({ table: key, migration: tables.get(key) });
35
+ seen.add(key);
36
+ }
37
+ }
38
+ return out;
39
+ }
40
+ /** Does the spec body declare it CREATES this table (vs merely referencing / reusing it)?
41
+ * Two accepted declaration forms:
42
+ * 1. Literal DDL: `CREATE TABLE [IF NOT EXISTS] [schema.]<table>` (tolerant of quoting).
43
+ * 2. Data-Model heading whose entire text is the table name: `#### \`<table>\`` / `### <table>`.
44
+ * Inline mentions (bullets, prose, "reuses `x`") are treated as references, not creates —
45
+ * that removes the false-positive class (FA-29) while keeping real declarations (PM-21).
46
+ * A spec that defines a table some other way is treated as a reference; a missed real
47
+ * collision is still caught later at migration-authoring time. */
48
+ export function specCreatesTable(body, table) {
49
+ const t = table.toLowerCase().replace(/[^a-z0-9_]/g, '');
50
+ const ddl = new RegExp(`create\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?(?:"?[a-z_]+"?\\.)?"?${t}"?\\b`, 'i');
51
+ // Heading declaration: a markdown heading line whose whole text is the table name
52
+ // (optionally backtick-wrapped). Anchored to line start/end so a heading that merely
53
+ // mentions the table among other words does not match.
54
+ const heading = new RegExp(`^\\s{0,3}#{2,6}\\s*\`?${t}\`?\\s*$`, 'im');
55
+ return ddl.test(body) || heading.test(body);
56
+ }
57
+ /** Filter identifiers down to those the spec body declares it CREATES. */
58
+ export function createdTables(body, identifiers) {
59
+ return identifiers.filter((id) => specCreatesTable(body, id));
60
+ }
61
+ //# sourceMappingURL=migration-collision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-collision.js","sourceRoot":"","sources":["../../src/lib/migration-collision.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,4FAA4F;AAE5F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC;2GAC2G;AAC3G,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACjC,MAAM,EAAE,GAAG,sFAAsF,CAAC;IAClG,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAS;QAClC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAAE,WAAqB;IAC7E,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;mEAOmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAa;IAC1D,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,uEAAuE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7G,kFAAkF;IAClF,qFAAqF;IACrF,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,yBAAyB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAqB;IAC/D,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pure next-action computation — the artifact-derived "what gate is next" logic
3
+ * extracted from `commands/next.ts` so it can run with NO filesystem access
4
+ * (WEB-22 FR-1). The CLI wrapper (`recommendAction` in next.ts) reads the TASKS
5
+ * file and the landscape advisory; everything here is pure and takes the
6
+ * already-fetched TASKS content as a parameter, so app code (Spec Studio's
7
+ * gate-router) can compute the next action without importing node:fs.
8
+ *
9
+ * Behavioral contract: `recommendActionPure(spec, tasksText)` is byte-for-byte
10
+ * equivalent to the old `recommendAction(spec)` when `tasksText` is the content
11
+ * the CLI would have read (or null when the read fails) — the existing
12
+ * next.test.ts is the regression gate.
13
+ */
14
+ import { type ActorType, type Transition } from './pipeline-map.js';
15
+ import type { SpecFile } from './specs.js';
16
+ export type NextAction = {
17
+ type: string;
18
+ specId: string;
19
+ reason: string;
20
+ actor: string;
21
+ actorType: ActorType;
22
+ invocation: string;
23
+ optional?: boolean;
24
+ /** Disagreement between pipeline_status and on-disk artifacts, if any. */
25
+ note?: string;
26
+ /** Set for the implement/complete tail. */
27
+ taskHint?: string;
28
+ };
29
+ /** True when TASKS.md carries at least one status marker we know how to read —
30
+ * a GitHub checkbox (`[ ]`/`[x]`) or a ballot-box glyph (☐/☑/☒). Used to
31
+ * distinguish "genuinely all complete" from "format we cannot parse". */
32
+ export declare function hasRecognizedTaskMarkers(text: string): boolean;
33
+ export declare function findIncompleteTaskHint(text: string): string | null;
34
+ /** Task-level tail the pipeline-map does not model: drill into TASKS.md or mark
35
+ * complete. `tasksText` is the already-fetched TASKS content (null when the
36
+ * caller could not read it — equivalent to the CLI's failed read). */
37
+ export declare function implementOrCompletePure(spec: SpecFile, tasksText: string | null): NextAction;
38
+ /** Walk the SSOT pipeline; return the first applicable, not-done transition, else
39
+ * the implement/complete tail. PURE: no fs. `tasksText` is the already-fetched
40
+ * TASKS content (null when unavailable). `pipeline` selects the layout — defaults
41
+ * to the engine's (encore1) PIPELINE; a consumer driving a different layout (e.g.
42
+ * Spec Studio over the builder layout) passes `buildPipeline(schema, registry).PIPELINE`
43
+ * so the next-action matches the same layout its `computeStage` uses. */
44
+ export declare function recommendActionPure(spec: SpecFile, tasksText: string | null, pipeline?: readonly Transition[]): NextAction;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Pure next-action computation — the artifact-derived "what gate is next" logic
3
+ * extracted from `commands/next.ts` so it can run with NO filesystem access
4
+ * (WEB-22 FR-1). The CLI wrapper (`recommendAction` in next.ts) reads the TASKS
5
+ * file and the landscape advisory; everything here is pure and takes the
6
+ * already-fetched TASKS content as a parameter, so app code (Spec Studio's
7
+ * gate-router) can compute the next action without importing node:fs.
8
+ *
9
+ * Behavioral contract: `recommendActionPure(spec, tasksText)` is byte-for-byte
10
+ * equivalent to the old `recommendAction(spec)` when `tasksText` is the content
11
+ * the CLI would have read (or null when the read fails) — the existing
12
+ * next.test.ts is the regression gate.
13
+ */
14
+ import { PIPELINE } from './pipeline-map.js';
15
+ import { isCompleteStatus } from './blockers.js';
16
+ /** A shipped (status:complete/implemented) spec needs no pre-implementation
17
+ * navigator action. Its skipped pipeline gates are historical (the spec was
18
+ * often authored post-hoc), so surface them as advisory, never as a TODO. */
19
+ function shippedAction(spec, pipeline = PIPELINE) {
20
+ const skipped = pipeline.filter((t) => !t.optional && !t.isDone(spec)).map((t) => t.id);
21
+ return {
22
+ type: 'shipped',
23
+ specId: spec.id,
24
+ reason: `status is \`${spec.status}\` — this spec is shipped; no pre-implementation navigator action`,
25
+ actor: 'eos-spec CLI',
26
+ actorType: 'command',
27
+ invocation: `nothing to do — change \`status:\` from \`${spec.status}\` only to deliberately re-open the pipeline`,
28
+ note: skipped.length > 0
29
+ ? `skipped pipeline artifacts (historical): ${skipped.join(', ')} — backfill only if you need them`
30
+ : undefined,
31
+ };
32
+ }
33
+ /** True when TASKS.md carries at least one status marker we know how to read —
34
+ * a GitHub checkbox (`[ ]`/`[x]`) or a ballot-box glyph (☐/☑/☒). Used to
35
+ * distinguish "genuinely all complete" from "format we cannot parse". */
36
+ export function hasRecognizedTaskMarkers(text) {
37
+ return /\[\s*[ xX]\s*\]/.test(text) || /[☐☑☒]/.test(text);
38
+ }
39
+ export function findIncompleteTaskHint(text) {
40
+ const headedTask = /^###\s+(T\d+[^\n]*)[\s\S]{0,240}?\*\*Status:\*\*\s*`?\[\s\]`?/m.exec(text);
41
+ if (headedTask?.[1])
42
+ return headedTask[1].trim();
43
+ const inlineTask = /^\s*-\s*\[\s\]\s+((?:T\d+|Task)[^\n]+)/m.exec(text);
44
+ if (inlineTask?.[1])
45
+ return inlineTask[1].trim();
46
+ // Table/glyph format: an open ballot-box glyph ☐ (U+2610) marks an incomplete
47
+ // row. Capture the first T-id on that line, else the line text, as the hint.
48
+ const glyphLine = /^.*☐.*$/m.exec(text);
49
+ if (glyphLine) {
50
+ const line = glyphLine[0];
51
+ const tid = /\bT\d+\b/.exec(line)?.[0];
52
+ return (tid ? `${tid} (incomplete)` : line.replace(/\|/g, ' ').replace(/\s+/g, ' ').trim()).slice(0, 120);
53
+ }
54
+ return null;
55
+ }
56
+ /** Task-level tail the pipeline-map does not model: drill into TASKS.md or mark
57
+ * complete. `tasksText` is the already-fetched TASKS content (null when the
58
+ * caller could not read it — equivalent to the CLI's failed read). */
59
+ export function implementOrCompletePure(spec, tasksText) {
60
+ const cli = { specId: spec.id, actor: 'eos-spec CLI', actorType: 'command' };
61
+ if (!spec.hasTasks) {
62
+ return { ...cli, type: 'generate-tasks', reason: 'No TASKS.md yet.', invocation: `eos-spec tasks ${spec.id}` };
63
+ }
64
+ if (tasksText !== null) {
65
+ const hint = findIncompleteTaskHint(tasksText);
66
+ if (hint) {
67
+ return {
68
+ specId: spec.id,
69
+ actor: 'implementer',
70
+ actorType: 'human-gate',
71
+ type: 'implement',
72
+ reason: 'Incomplete task found in TASKS.md',
73
+ invocation: `implement the next incomplete task in specs/${spec.core}/tasks/${spec.id}-TASKS.md, then check it off`,
74
+ taskHint: hint.slice(0, 120),
75
+ };
76
+ }
77
+ // Guard against the false "all complete" verdict: a TASKS.md with zero
78
+ // recognized status markers ([ ]/[x]/☐/☑) is unparseable, NOT done. Never
79
+ // recommend marking the spec complete when completion cannot be proven
80
+ // from artifacts.
81
+ if (!hasRecognizedTaskMarkers(tasksText)) {
82
+ return {
83
+ ...cli,
84
+ type: 'verify-tasks',
85
+ reason: 'TASKS.md has no recognized task-status markers ([ ]/[x]/☐/☑) — completion cannot be derived from artifacts. Verify the task format before completing.',
86
+ invocation: `eos-spec status --spec ${spec.id} # then re-run \`eos-spec tasks ${spec.id} --force\` if the format is stale`,
87
+ };
88
+ }
89
+ }
90
+ return {
91
+ ...cli,
92
+ type: 'mark-complete',
93
+ reason: 'All tasks appear complete.',
94
+ invocation: `set \`status: complete\` in ${spec.id}'s frontmatter, then \`eos-spec archive --spec ${spec.id}\` when ready`,
95
+ };
96
+ }
97
+ /** Walk the SSOT pipeline; return the first applicable, not-done transition, else
98
+ * the implement/complete tail. PURE: no fs. `tasksText` is the already-fetched
99
+ * TASKS content (null when unavailable). `pipeline` selects the layout — defaults
100
+ * to the engine's (encore1) PIPELINE; a consumer driving a different layout (e.g.
101
+ * Spec Studio over the builder layout) passes `buildPipeline(schema, registry).PIPELINE`
102
+ * so the next-action matches the same layout its `computeStage` uses. */
103
+ export function recommendActionPure(spec, tasksText, pipeline = PIPELINE) {
104
+ // A shipped spec is terminal: status (lifecycle) overrides the artifact pipeline
105
+ // for the explicit `--spec` query so the navigator never nags about gates an
106
+ // already-merged feature skipped. (Corpus `next` already filters these out.)
107
+ if (isCompleteStatus(spec.status))
108
+ return shippedAction(spec, pipeline);
109
+ // Derived from artifacts only — mirror the same predicates the PIPELINE uses for isDone.
110
+ if (spec.signals.hasSpecReview && !spec.signals.hasUserStories && !spec.signals.hasAcceptanceCriteria) {
111
+ return {
112
+ type: 'backfill-frontmatter',
113
+ specId: spec.id,
114
+ reason: 'Spec passed review but has neither user stories nor acceptance_criteria — draft-acs and generate-tests both silently skip, so it would reach plan with no ACs.',
115
+ actor: 'spec author',
116
+ actorType: 'human-gate',
117
+ invocation: `add user stories and Given/When/Then acceptance criteria to ${spec.id}'s frontmatter before planning`,
118
+ };
119
+ }
120
+ for (const t of pipeline) {
121
+ if (t.optional)
122
+ continue; // advisories never block; surfaced separately
123
+ // Artifacts are the single source of truth. `pipeline_status` is derived/cached
124
+ // (see eos-spec reconcile) and is intentionally NOT consulted here.
125
+ if (t.isDone(spec))
126
+ continue;
127
+ return {
128
+ type: t.id,
129
+ specId: spec.id,
130
+ reason: t.reason,
131
+ actor: t.actor,
132
+ actorType: t.actorType,
133
+ invocation: t.invocation(spec.id),
134
+ };
135
+ }
136
+ return implementOrCompletePure(spec, tasksText);
137
+ }
138
+ //# sourceMappingURL=next-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-action.js","sourceRoot":"","sources":["../../src/lib/next-action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Ollama embedding adapter for semantic precedent search. Documents are embedded
3
+ * WITHOUT the instruction; queries WITH it — qwen3-embedding requires the
4
+ * instruction prefix for query/document asymmetric retrieval, and omitting it
5
+ * collapses recall AND breaks exact matching (measured: para@15 7/8 → 4/8,
6
+ * exact@5 8/8 → 4/8). The model + instruction are recorded in the embedding
7
+ * manifest so the committed vectors stay reproducible.
8
+ */
9
+ export declare const EMBED_MODEL = "qwen3-embedding:0.6b";
10
+ export declare const EMBED_DIMS = 1024;
11
+ export declare const QUERY_INSTRUCTION = "Instruct: Given a feature or capability search query, retrieve the most relevant product specification.\nQuery:";
12
+ /** Low-level batch embed (no instruction applied). Throws on transport/HTTP error. */
13
+ export declare function ollamaEmbed(inputs: string[], model?: string): Promise<number[][]>;
14
+ /** Embed a search query (instruction prefix applied) → normalized vector. */
15
+ export declare function embedQueryOllama(query: string, model?: string): Promise<Float32Array>;
16
+ /**
17
+ * Graceful query embedder for runtime use: returns the normalized query vector,
18
+ * or null when Ollama is unreachable (callers fall back to lexical search). A
19
+ * short timeout keeps `eos-spec next`/`create` snappy when no embedder is present.
20
+ */
21
+ export declare function tryEmbedQueryOllama(query: string, timeoutMs?: number): Promise<Float32Array | null>;
@@ -0,0 +1,65 @@
1
+ import { normalize } from './embedding-store.js';
2
+ /**
3
+ * Ollama embedding adapter for semantic precedent search. Documents are embedded
4
+ * WITHOUT the instruction; queries WITH it — qwen3-embedding requires the
5
+ * instruction prefix for query/document asymmetric retrieval, and omitting it
6
+ * collapses recall AND breaks exact matching (measured: para@15 7/8 → 4/8,
7
+ * exact@5 8/8 → 4/8). The model + instruction are recorded in the embedding
8
+ * manifest so the committed vectors stay reproducible.
9
+ */
10
+ export const EMBED_MODEL = 'qwen3-embedding:0.6b';
11
+ export const EMBED_DIMS = 1024;
12
+ export const QUERY_INSTRUCTION = 'Instruct: Given a feature or capability search query, retrieve the most relevant product specification.\nQuery:';
13
+ function ollamaUrl() {
14
+ const host = process.env.OLLAMA_HOST ?? 'http://localhost:11434';
15
+ return `${host.replace(/\/$/, '')}/api/embed`;
16
+ }
17
+ /** Low-level batch embed (no instruction applied). Throws on transport/HTTP error. */
18
+ export async function ollamaEmbed(inputs, model = EMBED_MODEL) {
19
+ const res = await fetch(ollamaUrl(), {
20
+ method: 'POST',
21
+ headers: { 'content-type': 'application/json' },
22
+ body: JSON.stringify({ model, input: inputs }),
23
+ });
24
+ if (!res.ok)
25
+ throw new Error(`ollama embed failed: ${res.status} ${res.statusText}`);
26
+ const json = (await res.json());
27
+ if (!json.embeddings || json.embeddings.length !== inputs.length) {
28
+ throw new Error('ollama embed: malformed response (missing/!=length embeddings)');
29
+ }
30
+ return json.embeddings;
31
+ }
32
+ /** Embed a search query (instruction prefix applied) → normalized vector. */
33
+ export async function embedQueryOllama(query, model = EMBED_MODEL) {
34
+ const [vec] = await ollamaEmbed([`${QUERY_INSTRUCTION}${query}`], model);
35
+ return normalize(Float32Array.from(vec));
36
+ }
37
+ /**
38
+ * Graceful query embedder for runtime use: returns the normalized query vector,
39
+ * or null when Ollama is unreachable (callers fall back to lexical search). A
40
+ * short timeout keeps `eos-spec next`/`create` snappy when no embedder is present.
41
+ */
42
+ export async function tryEmbedQueryOllama(query, timeoutMs = 4000) {
43
+ const ctrl = new AbortController();
44
+ const timer = setTimeout(() => ctrl.abort(), timeoutMs);
45
+ try {
46
+ const res = await fetch(ollamaUrl(), {
47
+ method: 'POST',
48
+ headers: { 'content-type': 'application/json' },
49
+ body: JSON.stringify({ model: EMBED_MODEL, input: [`${QUERY_INSTRUCTION}${query}`] }),
50
+ signal: ctrl.signal,
51
+ });
52
+ if (!res.ok)
53
+ return null;
54
+ const json = (await res.json());
55
+ const vec = json.embeddings?.[0];
56
+ return vec ? normalize(Float32Array.from(vec)) : null;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ finally {
62
+ clearTimeout(timer);
63
+ }
64
+ }
65
+ //# sourceMappingURL=ollama-embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama-embed.js","sourceRoot":"","sources":["../../src/lib/ollama-embed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { Command } from 'commander';
2
+ export type GlobalOptions = {
3
+ json: boolean;
4
+ quiet: boolean;
5
+ repoRoot?: string;
6
+ config?: string;
7
+ };
8
+ /**
9
+ * Machine-actionable error codes for the JSON envelope. A headless agent can switch
10
+ * on `error.code` rather than regex the human `text`. Frozen so the set is a stable
11
+ * contract; `ErrorCodeValue` is the union of the values for `emit()`'s payload type.
12
+ */
13
+ export declare const ErrorCode: {
14
+ readonly SPEC_NOT_FOUND: "SPEC_NOT_FOUND";
15
+ readonly UNKNOWN_CORE: "UNKNOWN_CORE";
16
+ readonly INVALID_ARGUMENT: "INVALID_ARGUMENT";
17
+ readonly SCOPE_REQUIRED: "SCOPE_REQUIRED";
18
+ readonly VALIDATION_FAILED: "VALIDATION_FAILED";
19
+ readonly SUBPROCESS_ERROR: "SUBPROCESS_ERROR";
20
+ readonly IO_ERROR: "IO_ERROR";
21
+ readonly INTERNAL: "INTERNAL";
22
+ };
23
+ export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
24
+ export declare function getGlobalOptions(cmd: Command): GlobalOptions;
25
+ export declare function emit(global: GlobalOptions, payload: {
26
+ ok: boolean;
27
+ data?: unknown;
28
+ text?: string;
29
+ exitCode?: number;
30
+ error?: {
31
+ code: ErrorCodeValue;
32
+ message: string;
33
+ };
34
+ }): never;
35
+ export declare function emitContinuing(global: GlobalOptions, text: string): void;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Machine-actionable error codes for the JSON envelope. A headless agent can switch
3
+ * on `error.code` rather than regex the human `text`. Frozen so the set is a stable
4
+ * contract; `ErrorCodeValue` is the union of the values for `emit()`'s payload type.
5
+ */
6
+ export const ErrorCode = {
7
+ SPEC_NOT_FOUND: 'SPEC_NOT_FOUND',
8
+ UNKNOWN_CORE: 'UNKNOWN_CORE',
9
+ INVALID_ARGUMENT: 'INVALID_ARGUMENT',
10
+ SCOPE_REQUIRED: 'SCOPE_REQUIRED',
11
+ VALIDATION_FAILED: 'VALIDATION_FAILED',
12
+ SUBPROCESS_ERROR: 'SUBPROCESS_ERROR',
13
+ IO_ERROR: 'IO_ERROR',
14
+ INTERNAL: 'INTERNAL',
15
+ };
16
+ export function getGlobalOptions(cmd) {
17
+ const root = cmd.parent ?? cmd;
18
+ const opts = root.opts();
19
+ return {
20
+ json: Boolean(opts.json),
21
+ quiet: Boolean(opts.quiet),
22
+ repoRoot: opts.repoRoot,
23
+ config: opts.config,
24
+ };
25
+ }
26
+ export function emit(global, payload) {
27
+ if (global.json) {
28
+ const envelope = {
29
+ ok: payload.ok,
30
+ data: payload.data ?? null,
31
+ };
32
+ if (payload.error)
33
+ envelope.error = payload.error;
34
+ process.stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
35
+ }
36
+ else if (payload.text && !global.quiet) {
37
+ process.stdout.write(`${payload.text}\n`);
38
+ }
39
+ process.exit(payload.exitCode ?? (payload.ok ? 0 : 1));
40
+ }
41
+ export function emitContinuing(global, text) {
42
+ if (!global.json && !global.quiet) {
43
+ process.stdout.write(`${text}\n`);
44
+ }
45
+ }
46
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;IAC5B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,iBAAiB,EAAE,mBAAmB;IACtC,gBAAgB,EAAE,kBAAkB;IACpC,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;CACZ,CAAC;AAIX,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAiB,CAAC;IACxC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,MAAqB,EACrB,OAMC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAsF;YAClG,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;SAC3B,CAAC;QACF,IAAI,OAAO,CAAC,KAAK;YAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAqB,EAAE,IAAY;IAChE,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { PipelineSchema } from './pipeline-schema.js';
2
+ /** The canonical encoreos-1 spec/test pipeline as config-driven data. This is a
3
+ * faithful transcription of the imperative `PIPELINE`/`STATUS_ORDER`/`computeStage`
4
+ * in pipeline-map.ts: every stage `id`, `actor`, `actorType`, `reason`,
5
+ * `regulatedOnly`/`optional`, `completesStatus`, the exact `statusOrder`, and the
6
+ * two honest caps are preserved verbatim. Each stage's `isDone` closure becomes a
7
+ * named `gate` resolved against DEFAULT_PREDICATES; each `invocation: (id) => ...`
8
+ * closure becomes a literal string with a `${id}` placeholder substituted at
9
+ * interpret time. The Task 1.5 parity gate validates this against pipeline-map.ts. */
10
+ export declare const ENCORE1_PIPELINE_SCHEMA: PipelineSchema;
11
+ /** The builder (encoreos-switchboard) 7-stage / 6-status layout as config-driven
12
+ * data — a faithful transcription of the imperative PIPELINE/STATUS_ORDER in
13
+ * encoreos-builder's `tools/eos-spec/src/lib/pipeline-map.ts`. Distinct from
14
+ * encore1: a 6-value statusOrder (no regulatory_grounded/compliance_reviewed/
15
+ * ux_reviewed), NO regulated-only stages, and NO caps — so builder's computeStage
16
+ * is a pure "highest done completesStatus". The draft-acs/generate-tests gates
17
+ * carry no `completesStatus` (they never advance the stage enum), so any drift in
18
+ * their predicate polarity cannot affect stage parity. Proven against the captured
19
+ * builder baseline by `pipeline-parity.builder.test.ts`. */
20
+ export declare const BUILDER_PIPELINE_SCHEMA: PipelineSchema;