@eir-labs/coltrane 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +85 -0
  3. package/agents/anticipation-mapper.json +34 -0
  4. package/agents/claim-amender.json +34 -0
  5. package/agents/claim-architect.json +34 -0
  6. package/agents/claim-rewriter.json +32 -0
  7. package/agents/delivery-finalizer.json +40 -0
  8. package/agents/diamond-cutter.json +33 -0
  9. package/agents/disclosure-analyst.json +26 -0
  10. package/agents/domain-explorer.json +37 -0
  11. package/agents/e2e-runner.json +34 -0
  12. package/agents/e2e-suite-judge.json +26 -0
  13. package/agents/event-clusterer.json +29 -0
  14. package/agents/novelty-searcher.json +40 -0
  15. package/agents/patent-browser-scout.json +49 -0
  16. package/agents/patent-examiner.json +36 -0
  17. package/agents/phase_agents/claim-rewriter.md +44 -0
  18. package/agents/phase_agents/delivery-finalizer.md +30 -0
  19. package/agents/phase_agents/diamond-cutter.md +47 -0
  20. package/agents/phase_agents/domain-explorer.md +27 -0
  21. package/agents/phase_agents/novelty-searcher.md +50 -0
  22. package/agents/phase_agents/problem-definer.md +32 -0
  23. package/agents/phase_agents/solution-developer.md +26 -0
  24. package/agents/phase_agents/verdict-judger.md +70 -0
  25. package/agents/players/audience-modeler.md +40 -0
  26. package/agents/players/chain-audit-keeper.md +41 -0
  27. package/agents/players/illumination-reviewer.md +42 -0
  28. package/agents/players/methodology-cadence-keeper.md +42 -0
  29. package/agents/players/substrate-edge-keeper.md +45 -0
  30. package/agents/prior-art-scout.json +45 -0
  31. package/agents/problem-definer.json +35 -0
  32. package/agents/seeds/steve_seed_a.json +12 -0
  33. package/agents/seeds/steve_seed_b.json +12 -0
  34. package/agents/seeds/steve_seed_c.json +12 -0
  35. package/agents/seeds/steve_seed_d.json +12 -0
  36. package/agents/sensor.json +22 -0
  37. package/agents/solution-developer.json +35 -0
  38. package/agents/source-walker.json +38 -0
  39. package/agents/spec-drafter.json +31 -0
  40. package/agents/sub_thread_soft_judge.json +26 -0
  41. package/agents/sub_thread_trace_sensor.json +22 -0
  42. package/agents/summarizer.json +25 -0
  43. package/agents/synthesis-writer.json +29 -0
  44. package/agents/triage-judge.json +39 -0
  45. package/agents/user_flow_judge.json +26 -0
  46. package/agents/user_flow_sensor.json +22 -0
  47. package/agents/verdict-judger.json +39 -0
  48. package/core_types/artifact.json +17 -0
  49. package/core_types/interpretation.json +16 -0
  50. package/core_types/judgment.json +16 -0
  51. package/core_types/plan.json +16 -0
  52. package/core_types/signal.json +16 -0
  53. package/core_types/verdict.json +27 -0
  54. package/dist/src/access_grant.d.ts +46 -0
  55. package/dist/src/access_grant.js +76 -0
  56. package/dist/src/access_grant.js.map +1 -0
  57. package/dist/src/acoustics.d.ts +9 -0
  58. package/dist/src/acoustics.js +65 -0
  59. package/dist/src/acoustics.js.map +1 -0
  60. package/dist/src/agent_profile.d.ts +36 -0
  61. package/dist/src/agent_profile.js +57 -0
  62. package/dist/src/agent_profile.js.map +1 -0
  63. package/dist/src/bifrost_invoker.d.ts +33 -0
  64. package/dist/src/bifrost_invoker.js +85 -0
  65. package/dist/src/bifrost_invoker.js.map +1 -0
  66. package/dist/src/canonical_core_types.d.ts +2 -0
  67. package/dist/src/canonical_core_types.js +111 -0
  68. package/dist/src/canonical_core_types.js.map +1 -0
  69. package/dist/src/canonical_form.d.ts +55 -0
  70. package/dist/src/canonical_form.js +93 -0
  71. package/dist/src/canonical_form.js.map +1 -0
  72. package/dist/src/charter.d.ts +37 -0
  73. package/dist/src/charter.js +86 -0
  74. package/dist/src/charter.js.map +1 -0
  75. package/dist/src/circle_of_fifths.d.ts +27 -0
  76. package/dist/src/circle_of_fifths.js +78 -0
  77. package/dist/src/circle_of_fifths.js.map +1 -0
  78. package/dist/src/claude_invoker.d.ts +102 -0
  79. package/dist/src/claude_invoker.js +760 -0
  80. package/dist/src/claude_invoker.js.map +1 -0
  81. package/dist/src/coltrane_profile.d.ts +87 -0
  82. package/dist/src/coltrane_profile.js +132 -0
  83. package/dist/src/coltrane_profile.js.map +1 -0
  84. package/dist/src/composition.d.ts +57 -0
  85. package/dist/src/composition.js +447 -0
  86. package/dist/src/composition.js.map +1 -0
  87. package/dist/src/core_types.d.ts +6 -0
  88. package/dist/src/core_types.js +25 -0
  89. package/dist/src/core_types.js.map +1 -0
  90. package/dist/src/document_factory.d.ts +89 -0
  91. package/dist/src/document_factory.js +176 -0
  92. package/dist/src/document_factory.js.map +1 -0
  93. package/dist/src/genome_schema.d.ts +512 -0
  94. package/dist/src/genome_schema.js +168 -0
  95. package/dist/src/genome_schema.js.map +1 -0
  96. package/dist/src/genome_writer.d.ts +67 -0
  97. package/dist/src/genome_writer.js +179 -0
  98. package/dist/src/genome_writer.js.map +1 -0
  99. package/dist/src/gig_song.d.ts +29 -0
  100. package/dist/src/gig_song.js +56 -0
  101. package/dist/src/gig_song.js.map +1 -0
  102. package/dist/src/gig_tracker.d.ts +54 -0
  103. package/dist/src/gig_tracker.js +109 -0
  104. package/dist/src/gig_tracker.js.map +1 -0
  105. package/dist/src/harmonic_validation.d.ts +11 -0
  106. package/dist/src/harmonic_validation.js +35 -0
  107. package/dist/src/harmonic_validation.js.map +1 -0
  108. package/dist/src/hooks.d.ts +27 -0
  109. package/dist/src/hooks.js +2 -0
  110. package/dist/src/hooks.js.map +1 -0
  111. package/dist/src/index.d.ts +36 -0
  112. package/dist/src/index.js +37 -0
  113. package/dist/src/index.js.map +1 -0
  114. package/dist/src/jsong.d.ts +47 -0
  115. package/dist/src/jsong.js +130 -0
  116. package/dist/src/jsong.js.map +1 -0
  117. package/dist/src/judges/user_flow_judge.d.ts +89 -0
  118. package/dist/src/judges/user_flow_judge.js +200 -0
  119. package/dist/src/judges/user_flow_judge.js.map +1 -0
  120. package/dist/src/learner.d.ts +37 -0
  121. package/dist/src/learner.js +30 -0
  122. package/dist/src/learner.js.map +1 -0
  123. package/dist/src/ledger.d.ts +225 -0
  124. package/dist/src/ledger.js +306 -0
  125. package/dist/src/ledger.js.map +1 -0
  126. package/dist/src/loader.d.ts +87 -0
  127. package/dist/src/loader.js +504 -0
  128. package/dist/src/loader.js.map +1 -0
  129. package/dist/src/mcp.d.ts +23 -0
  130. package/dist/src/mcp.js +125 -0
  131. package/dist/src/mcp.js.map +1 -0
  132. package/dist/src/modulation_path.d.ts +42 -0
  133. package/dist/src/modulation_path.js +60 -0
  134. package/dist/src/modulation_path.js.map +1 -0
  135. package/dist/src/output_validation.d.ts +19 -0
  136. package/dist/src/output_validation.js +51 -0
  137. package/dist/src/output_validation.js.map +1 -0
  138. package/dist/src/outputs.d.ts +125 -0
  139. package/dist/src/outputs.js +452 -0
  140. package/dist/src/outputs.js.map +1 -0
  141. package/dist/src/overtones.d.ts +42 -0
  142. package/dist/src/overtones.js +98 -0
  143. package/dist/src/overtones.js.map +1 -0
  144. package/dist/src/player_to_claude_code.d.ts +17 -0
  145. package/dist/src/player_to_claude_code.js +141 -0
  146. package/dist/src/player_to_claude_code.js.map +1 -0
  147. package/dist/src/playwright_cage.d.ts +28 -0
  148. package/dist/src/playwright_cage.js +47 -0
  149. package/dist/src/playwright_cage.js.map +1 -0
  150. package/dist/src/polyphony.d.ts +46 -0
  151. package/dist/src/polyphony.js +91 -0
  152. package/dist/src/polyphony.js.map +1 -0
  153. package/dist/src/portfolio.d.ts +52 -0
  154. package/dist/src/portfolio.js +186 -0
  155. package/dist/src/portfolio.js.map +1 -0
  156. package/dist/src/pricing.d.ts +23 -0
  157. package/dist/src/pricing.js +16 -0
  158. package/dist/src/pricing.js.map +1 -0
  159. package/dist/src/registry.d.ts +46 -0
  160. package/dist/src/registry.js +199 -0
  161. package/dist/src/registry.js.map +1 -0
  162. package/dist/src/runtime.d.ts +304 -0
  163. package/dist/src/runtime.js +1099 -0
  164. package/dist/src/runtime.js.map +1 -0
  165. package/dist/src/server.d.ts +88 -0
  166. package/dist/src/server.js +1692 -0
  167. package/dist/src/server.js.map +1 -0
  168. package/dist/src/server_entry.d.ts +2 -0
  169. package/dist/src/server_entry.js +40 -0
  170. package/dist/src/server_entry.js.map +1 -0
  171. package/dist/src/server_relay.d.ts +82 -0
  172. package/dist/src/server_relay.js +341 -0
  173. package/dist/src/server_relay.js.map +1 -0
  174. package/dist/src/simulate.d.ts +60 -0
  175. package/dist/src/simulate.js +72 -0
  176. package/dist/src/simulate.js.map +1 -0
  177. package/dist/src/skill_runner.mjs +34 -0
  178. package/dist/src/skill_subprocess.d.ts +65 -0
  179. package/dist/src/skill_subprocess.js +132 -0
  180. package/dist/src/skill_subprocess.js.map +1 -0
  181. package/dist/src/skills.d.ts +85 -0
  182. package/dist/src/skills.js +258 -0
  183. package/dist/src/skills.js.map +1 -0
  184. package/dist/src/subthread_recorder.d.ts +68 -0
  185. package/dist/src/subthread_recorder.js +166 -0
  186. package/dist/src/subthread_recorder.js.map +1 -0
  187. package/dist/src/tensor_read.d.ts +38 -0
  188. package/dist/src/tensor_read.js +60 -0
  189. package/dist/src/tensor_read.js.map +1 -0
  190. package/dist/src/test_honest_broker.d.ts +34 -0
  191. package/dist/src/test_honest_broker.js +155 -0
  192. package/dist/src/test_honest_broker.js.map +1 -0
  193. package/dist/src/test_topology.d.ts +22 -0
  194. package/dist/src/test_topology.js +137 -0
  195. package/dist/src/test_topology.js.map +1 -0
  196. package/dist/src/tones.d.ts +20 -0
  197. package/dist/src/tones.js +81 -0
  198. package/dist/src/tones.js.map +1 -0
  199. package/dist/src/tool_providers.d.ts +45 -0
  200. package/dist/src/tool_providers.js +104 -0
  201. package/dist/src/tool_providers.js.map +1 -0
  202. package/dist/src/type_versioning.d.ts +23 -0
  203. package/dist/src/type_versioning.js +31 -0
  204. package/dist/src/type_versioning.js.map +1 -0
  205. package/dist/src/version.d.ts +28 -0
  206. package/dist/src/version.js +86 -0
  207. package/dist/src/version.js.map +1 -0
  208. package/domain_types/claim-draft.json +34 -0
  209. package/domain_types/coverage-report.json +31 -0
  210. package/domain_types/draft-agent-profile.json +31 -0
  211. package/domain_types/draft-domain-type.json +28 -0
  212. package/domain_types/draft-standard.json +46 -0
  213. package/domain_types/e2e-observation.json +32 -0
  214. package/domain_types/e2e-report.json +30 -0
  215. package/domain_types/e2e-target.json +26 -0
  216. package/domain_types/e2e-verdict.json +26 -0
  217. package/domain_types/examine-round-record.json +40 -0
  218. package/domain_types/examiner-rejection.json +28 -0
  219. package/domain_types/failure-modes.json +31 -0
  220. package/domain_types/invention-analysis.json +34 -0
  221. package/domain_types/invention-spec.json +34 -0
  222. package/domain_types/novelty-analysis.json +28 -0
  223. package/domain_types/novelty-verdict.json +35 -0
  224. package/domain_types/parsed-conversation-trace.json +38 -0
  225. package/domain_types/pattern-extraction.json +62 -0
  226. package/domain_types/prior-art-hit.json +50 -0
  227. package/domain_types/project-charter.json +71 -0
  228. package/domain_types/provisional-draft.json +34 -0
  229. package/domain_types/raw-note.json +19 -0
  230. package/domain_types/repo-survey.json +28 -0
  231. package/domain_types/seeding-verdict.json +70 -0
  232. package/domain_types/soft-verdict.json +55 -0
  233. package/domain_types/summary.json +19 -0
  234. package/domain_types/triage-verdict.json +59 -0
  235. package/domain_types/user-flow-transcript.json +43 -0
  236. package/domain_types/user-flow-verdict.json +60 -0
  237. package/domain_types/verdict-record.json +39 -0
  238. package/package.json +82 -0
  239. package/skills/citation-verify/fixtures/basic.json +14 -0
  240. package/skills/citation-verify/meta.json +10 -0
  241. package/skills/citation-verify/skill.mjs +26 -0
  242. package/skills/claim-element-decompose/fixtures/basic.json +11 -0
  243. package/skills/claim-element-decompose/meta.json +10 -0
  244. package/skills/claim-element-decompose/skill.mjs +14 -0
  245. package/skills/diamond-cutting-discipline/fixtures/basic.json +13 -0
  246. package/skills/diamond-cutting-discipline/meta.json +19 -0
  247. package/skills/diamond-cutting-discipline/skill.md +46 -0
  248. package/skills/element-mapping-matrix/fixtures/basic.json +13 -0
  249. package/skills/element-mapping-matrix/meta.json +10 -0
  250. package/skills/element-mapping-matrix/skill.mjs +20 -0
  251. package/skills/number-adder/fixtures/basic.json +9 -0
  252. package/skills/number-adder/meta.json +10 -0
  253. package/skills/number-adder/skill.mjs +12 -0
  254. package/skills/patent-fetch/fixtures/parse.json +18 -0
  255. package/skills/patent-fetch/meta.json +11 -0
  256. package/skills/patent-fetch/skill.mjs +34 -0
  257. package/skills/query-expand/fixtures/basic.json +14 -0
  258. package/skills/query-expand/meta.json +10 -0
  259. package/skills/query-expand/skill.mjs +29 -0
  260. package/skills/run-vitest-band/fixtures/basic.json +9 -0
  261. package/skills/run-vitest-band/meta.json +18 -0
  262. package/skills/run-vitest-band/skill.mjs +22 -0
  263. package/skills/statutory-checklist/fixtures/basic.json +16 -0
  264. package/skills/statutory-checklist/meta.json +10 -0
  265. package/skills/statutory-checklist/skill.mjs +25 -0
  266. package/skills/summarize-tight/fixtures/basic.json +13 -0
  267. package/skills/summarize-tight/meta.json +20 -0
  268. package/skills/summarize-tight/skill.md +1 -0
  269. package/skills/verdict-gate/fixtures/basic.json +9 -0
  270. package/skills/verdict-gate/meta.json +10 -0
  271. package/skills/verdict-gate/skill.mjs +82 -0
  272. package/standards/e2e-suite-v0.json +44 -0
  273. package/standards/patent-triage-v0.json +98 -0
  274. package/standards/patent-triage-v1.json +84 -0
  275. package/standards/seed-from-local-repos-v0.json +115 -0
  276. package/standards/sub_thread_invocation.json +50 -0
  277. package/standards/summarize.json +40 -0
  278. package/standards/synthesis-walk-v0.json +108 -0
  279. package/standards/user_flow_correctness.json +57 -0
@@ -0,0 +1,225 @@
1
+ export interface GigUsage {
2
+ input_tokens: number;
3
+ output_tokens: number;
4
+ total_cost_usd: number;
5
+ /** actual model id → its spend (the model that ran, not just the configured tier). */
6
+ by_model: Record<string, {
7
+ input_tokens: number;
8
+ output_tokens: number;
9
+ cost_usd: number;
10
+ }>;
11
+ /** Model invocations this gig STARTED (skill-backed chairs run no model and are not counted). */
12
+ invocations?: number;
13
+ /** Of those, how many produced no usable usage payload. Their spend is UNKNOWN, not zero. */
14
+ unattributed_invocations?: number;
15
+ /** Set ONLY when unattributed_invocations > 0: the scalars above are a LOWER BOUND. */
16
+ partial?: true;
17
+ /** Set ONLY when ≥1 attributed invocation carried no `modelUsage` breakdown: `by_model` does
18
+ * not account for the whole of `total_cost_usd` and is itself a LOWER BOUND. */
19
+ by_model_partial?: true;
20
+ }
21
+ /**
22
+ * The ledger records three classes of event, not one (#212).
23
+ *
24
+ * v1 modelled exactly one — *a gig finished* — so every other event class was smuggled into
25
+ * that shape: the event kind stuffed into `standard_slug`, the event class into a `:`-prefix
26
+ * on `gig_id`, and the sentinel `"n/a"` into the identity fields, with the payload dropped
27
+ * entirely. Seven of twelve append sites wrote `"n/a"`.
28
+ *
29
+ * The discriminated union makes that unrepresentable rather than merely discouraged:
30
+ * `genome_hash`/`run_fingerprint` exist ONLY on `kind:"gig"`, so there is nowhere to put a
31
+ * sentinel on a promotion or an abort.
32
+ */
33
+ export type LedgerEntryKind = "gig" | "genome_mutation" | "governance";
34
+ export declare const LEDGER_SCHEMA_VERSION = 2;
35
+ interface LedgerEntryBase {
36
+ schema_version: typeof LEDGER_SCHEMA_VERSION;
37
+ /** This ROW's identity. v1 overloaded `gig_id` for it, which is why non-gig rows needed a
38
+ * synthetic `promote:<uuid>` / `abort:<gid>` namespace. */
39
+ entry_id: string;
40
+ kind: LedgerEntryKind;
41
+ output_hashes: readonly string[];
42
+ started_at: string;
43
+ finished_at: string;
44
+ /** Set ONLY by the read-side v1 upgrade. Without this marker the upgrade would launder a
45
+ * known gap into apparent completeness — the same class of dishonesty as `"n/a"` itself. */
46
+ legacy?: true;
47
+ /**
48
+ * WHO asked for this. Optional, caller-supplied, and **provenance only**.
49
+ *
50
+ * The ledger already answers *what produced this and from what* — `content_sha`,
51
+ * `input_shas`, `skill_provenance`, `genome_hash`, `run_fingerprint`. It answered *who
52
+ * initiated it* nowhere. `principal` is the same category of fact as the rest of that list,
53
+ * which is the whole reason it sits on the base rather than on one arm: a run, a genome
54
+ * mutation, and a governance act can each have an initiator.
55
+ *
56
+ * **This is NOT an access control, and must not be read as one.** The engine records it and
57
+ * never looks at it: it is deliberately absent from `LedgerQuery`, no read handler consults
58
+ * it, and nothing filters on it. That is the architecture, not an oversight —
59
+ * `src/hooks.ts:1-9` states the engine provides "ONLY these types + the loop… ZERO built-in
60
+ * hooks… Everything opinionated lives in the wrapper." Tenancy enforcement is the consumer's
61
+ * job. If you are here because you want rows scoped by principal, that scoping belongs in
62
+ * the wrapper reading the ledger, not in the engine writing it.
63
+ *
64
+ * Landed inside the v1→v2 bump precisely because it is free here: additive, unset by every
65
+ * current call site, and needing no new upgrade arm. Adding it after v2 shipped would have
66
+ * cost a `schema_version: 3` and a second arm in `upgradeV1` for a purely additive field.
67
+ */
68
+ principal?: string;
69
+ }
70
+ /** A run completed. The only class that carries reproducibility identity. */
71
+ export interface GigLedgerEntry extends LedgerEntryBase {
72
+ kind: "gig";
73
+ gig_id: string;
74
+ standard_slug: string;
75
+ genome_hash: string;
76
+ run_fingerprint: string;
77
+ usage?: GigUsage;
78
+ }
79
+ /** A definition entered the substrate. Identity is the canonical hash chain, NOT a run
80
+ * fingerprint — src/genome_writer.ts used to copy `effective_hash` into both, which was a
81
+ * small lie: an effective hash is not a run fingerprint. */
82
+ export interface GenomeMutationLedgerEntry extends LedgerEntryBase {
83
+ kind: "genome_mutation";
84
+ /** agent_define | agent_evolve | standard_compose | type_register | type_extend | skill_define */
85
+ event: string;
86
+ /** WHICH definition was sealed. v1 buried this in a `:`-delimited gig_id. */
87
+ subject_slug: string;
88
+ content_hash: string;
89
+ dependency_hash?: string;
90
+ effective_hash: string;
91
+ }
92
+ /** A governance act: a promotion, a registration, a review, a proposal, an abort. */
93
+ export interface GovernanceLedgerEntry extends LedgerEntryBase {
94
+ kind: "governance";
95
+ event: string;
96
+ /** WHICH entity the act was about — the promoted slug, the registered tool, the reviewed
97
+ * agent. v1 recorded none of these. */
98
+ subject_slug: string;
99
+ /** The real gig this act concerns (an abort, a review). First-class so `query({subject_gig_id})`
100
+ * answers "what happened to gig X" — v1 filed aborts under a synthetic `abort:<gid>` that
101
+ * exact-equality filtering could never return (#213). */
102
+ subject_gig_id?: string;
103
+ /** The payload. v1 dropped it entirely, leaving a durable trail of content-free UUIDs. */
104
+ detail?: Record<string, unknown>;
105
+ }
106
+ export type LedgerEntry = GigLedgerEntry | GenomeMutationLedgerEntry | GovernanceLedgerEntry;
107
+ export interface LedgerQuery {
108
+ kind?: LedgerEntryKind;
109
+ event?: string;
110
+ subject_slug?: string;
111
+ subject_gig_id?: string;
112
+ gig_id?: string;
113
+ standard_slug?: string;
114
+ genome_hash?: string;
115
+ effective_hash?: string;
116
+ after?: string;
117
+ before?: string;
118
+ }
119
+ /** One damaged line, located. Skip-and-REPORT: silently dropping a row would let corruption
120
+ * hide an entry, which is the wrong remedy for an audit trail (contrast src/outputs.ts:180-184). */
121
+ export interface LedgerCorruption {
122
+ line_no: number;
123
+ reason: string;
124
+ preview: string;
125
+ }
126
+ export interface LedgerIntegrityReport {
127
+ ok: boolean;
128
+ path: string;
129
+ entries: number;
130
+ corrupt: LedgerCorruption[];
131
+ }
132
+ /** Filters that can only ever match a gig row: the discriminator itself, or a field that
133
+ * exists solely on the gig arm. Narrowing on these is what lets `query({gig_id})[0].usage`
134
+ * type-check without a cast at every read site. */
135
+ export type GigOnlyQuery = (LedgerQuery & {
136
+ kind: "gig";
137
+ }) | (LedgerQuery & {
138
+ gig_id: string;
139
+ }) | (LedgerQuery & {
140
+ standard_slug: string;
141
+ }) | (LedgerQuery & {
142
+ genome_hash: string;
143
+ });
144
+ export interface Ledger {
145
+ append(entry: LedgerEntry): void;
146
+ query(filter?: LedgerQuery): LedgerEntry[];
147
+ count(filter?: LedgerQuery): number;
148
+ /**
149
+ * #255 — is this audit trail whole, and if not, where is the damage.
150
+ *
151
+ * On the INTERFACE deliberately. `FileLedger` had it as a class method only, so a
152
+ * consumer holding a `Ledger` could not ask the question without narrowing — which is
153
+ * why tests/ledger_integrity.test.ts had to cast through `Record<string, unknown>` to
154
+ * reach it, and why `system_health` surfaced nothing. An audit trail that cannot be
155
+ * asked whether it is intact is not an audit trail.
156
+ *
157
+ * Every implementation answers, including one that cannot tear: "in-memory, so there is
158
+ * nothing to corrupt" is an ANSWER. A missing method is a gap, and gaps get assumed away.
159
+ */
160
+ integrity(): LedgerIntegrityReport;
161
+ }
162
+ export declare class LedgerError extends Error {
163
+ }
164
+ export declare const isGig: (e: LedgerEntry) => e is GigLedgerEntry;
165
+ export declare const isGenomeMutation: (e: LedgerEntry) => e is GenomeMutationLedgerEntry;
166
+ export declare const isGovernance: (e: LedgerEntry) => e is GovernanceLedgerEntry;
167
+ /**
168
+ * Resolve the ledger file. `COLTRANE_LEDGER_PATH` wins; otherwise `<root>/.coltrane/ledger.jsonl`.
169
+ *
170
+ * Genome-scoped, deliberately NOT `$HOME`-global like `defaultOutputsPersistDir` (#210): a
171
+ * `genome_hash` is only meaningful relative to a genome and `standard_slug` is not namespaced,
172
+ * so a global ledger would interleave rows from every genome the operator has ever run and
173
+ * `query({standard_slug})` would return unrelated genomes' runs as one history. Outputs
174
+ * tolerate a global root only because they are sharded into per-gig_id files.
175
+ * `.gitignore` already carries `.coltrane/`.
176
+ */
177
+ export declare function defaultLedgerPath(root?: string): string;
178
+ /**
179
+ * THE shared validator. Both implementations call this; the duplicated guard triplet it
180
+ * replaces (v1 `src/ledger.ts:56-58` and `:102-104`) is how the MemoryLedger/FileLedger
181
+ * immutability divergence in #214 crept in unnoticed.
182
+ */
183
+ export declare function validateEntry(entry: LedgerEntry): void;
184
+ export declare class FileLedger implements Ledger {
185
+ private readonly path;
186
+ constructor(path: string);
187
+ append(entry: LedgerEntry): void;
188
+ /** Single read pass shared by query / count / integrity, so the three can never disagree
189
+ * about what the file contains (v1 `count()` never parsed, so it reported a healthy total
190
+ * for a ledger `query()` could not open). */
191
+ private read;
192
+ query(filter: GigOnlyQuery): GigLedgerEntry[];
193
+ query(filter: LedgerQuery & {
194
+ kind: "genome_mutation";
195
+ }): GenomeMutationLedgerEntry[];
196
+ query(filter: LedgerQuery & {
197
+ kind: "governance";
198
+ }): GovernanceLedgerEntry[];
199
+ query(filter?: LedgerQuery): LedgerEntry[];
200
+ count(filter?: LedgerQuery): number;
201
+ /**
202
+ * Skip-and-REPORT. A silent skip (the src/outputs.ts:180-184 shape) is the wrong remedy for
203
+ * an audit trail: it lets a single corrupted byte delete a row with no trace. `query()`
204
+ * keeps serving the intact rows; this is how an operator learns the ledger is damaged.
205
+ */
206
+ integrity(): LedgerIntegrityReport;
207
+ }
208
+ export declare class MemoryLedger implements Ledger {
209
+ private readonly entries;
210
+ constructor();
211
+ append(entry: LedgerEntry): void;
212
+ query(filter: GigOnlyQuery): GigLedgerEntry[];
213
+ query(filter: LedgerQuery & {
214
+ kind: "genome_mutation";
215
+ }): GenomeMutationLedgerEntry[];
216
+ query(filter: LedgerQuery & {
217
+ kind: "governance";
218
+ }): GovernanceLedgerEntry[];
219
+ query(filter?: LedgerQuery): LedgerEntry[];
220
+ count(filter?: LedgerQuery): number;
221
+ /** Nothing is parsed from bytes here, so there is no torn-line failure mode to report.
222
+ * `path` is empty because there is no file — not because we failed to find one. */
223
+ integrity(): LedgerIntegrityReport;
224
+ }
225
+ export {};
@@ -0,0 +1,306 @@
1
+ import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ export const LEDGER_SCHEMA_VERSION = 2;
4
+ /** sha256, lowercase — what canonical_form actually emits (src/canonical_form.ts:29-31). */
5
+ const HEX64 = /^[0-9a-f]{64}$/;
6
+ export class LedgerError extends Error {
7
+ }
8
+ // Narrowing helpers for consumers holding the `Ledger` interface (whose query() returns the
9
+ // union). The concrete classes narrow via overload; these cover the interface-typed path.
10
+ export const isGig = (e) => e.kind === "gig";
11
+ export const isGenomeMutation = (e) => e.kind === "genome_mutation";
12
+ export const isGovernance = (e) => e.kind === "governance";
13
+ /**
14
+ * Resolve the ledger file. `COLTRANE_LEDGER_PATH` wins; otherwise `<root>/.coltrane/ledger.jsonl`.
15
+ *
16
+ * Genome-scoped, deliberately NOT `$HOME`-global like `defaultOutputsPersistDir` (#210): a
17
+ * `genome_hash` is only meaningful relative to a genome and `standard_slug` is not namespaced,
18
+ * so a global ledger would interleave rows from every genome the operator has ever run and
19
+ * `query({standard_slug})` would return unrelated genomes' runs as one history. Outputs
20
+ * tolerate a global root only because they are sharded into per-gig_id files.
21
+ * `.gitignore` already carries `.coltrane/`.
22
+ */
23
+ export function defaultLedgerPath(root) {
24
+ const override = process.env["COLTRANE_LEDGER_PATH"];
25
+ if (override && override.length > 0)
26
+ return override;
27
+ return join(root ?? process.cwd(), ".coltrane", "ledger.jsonl");
28
+ }
29
+ function isNonEmptyString(v) {
30
+ return typeof v === "string" && v.length > 0;
31
+ }
32
+ function requireHex(row, field, kind) {
33
+ const v = row[field];
34
+ if (typeof v !== "string" || !HEX64.test(v)) {
35
+ throw new LedgerError(`${kind} entry requires ${field} to be 64 lowercase hex (sha256); got ${JSON.stringify(v)}. ` +
36
+ "Non-emptiness was the v1 guard, and it is exactly what let 7 call sites write \"n/a\".");
37
+ }
38
+ }
39
+ /** Gig identity on a non-gig row is not "discouraged", it is invalid — that is what makes the
40
+ * sentinel unrepresentable rather than merely absent by convention. */
41
+ function rejectGigIdentity(row, kind) {
42
+ for (const field of ["genome_hash", "run_fingerprint"]) {
43
+ if (row[field] !== undefined) {
44
+ throw new LedgerError(`${kind} entry must not carry ${field} — reproducibility identity is gig-only. ` +
45
+ "A promotion is not a run.");
46
+ }
47
+ }
48
+ }
49
+ /**
50
+ * THE shared validator. Both implementations call this; the duplicated guard triplet it
51
+ * replaces (v1 `src/ledger.ts:56-58` and `:102-104`) is how the MemoryLedger/FileLedger
52
+ * immutability divergence in #214 crept in unnoticed.
53
+ */
54
+ export function validateEntry(entry) {
55
+ const row = entry;
56
+ const kind = row["kind"];
57
+ if (kind !== "gig" && kind !== "genome_mutation" && kind !== "governance") {
58
+ throw new LedgerError(`ledger entry requires kind ∈ {gig, genome_mutation, governance}; got ${JSON.stringify(kind)}`);
59
+ }
60
+ if (!isNonEmptyString(row["entry_id"]))
61
+ throw new LedgerError("ledger entry requires entry_id");
62
+ if (!isNonEmptyString(row["started_at"]))
63
+ throw new LedgerError("ledger entry requires started_at");
64
+ if (!isNonEmptyString(row["finished_at"]))
65
+ throw new LedgerError("ledger entry requires finished_at");
66
+ if (!Array.isArray(row["output_hashes"]))
67
+ throw new LedgerError("ledger entry requires output_hashes");
68
+ if (kind === "gig") {
69
+ if (!isNonEmptyString(row["gig_id"]))
70
+ throw new LedgerError("gig entry requires gig_id");
71
+ if (!isNonEmptyString(row["standard_slug"]))
72
+ throw new LedgerError("gig entry requires standard_slug");
73
+ requireHex(row, "genome_hash", "gig");
74
+ requireHex(row, "run_fingerprint", "gig");
75
+ return;
76
+ }
77
+ if (!isNonEmptyString(row["event"]))
78
+ throw new LedgerError(`${kind} entry requires event`);
79
+ if (!isNonEmptyString(row["subject_slug"])) {
80
+ throw new LedgerError(`${kind} entry requires subject_slug — WHICH entity the event was about. ` +
81
+ "v1 recorded a bare UUID and no subject at all.");
82
+ }
83
+ rejectGigIdentity(row, kind);
84
+ if (kind === "genome_mutation") {
85
+ requireHex(row, "content_hash", "genome_mutation");
86
+ requireHex(row, "effective_hash", "genome_mutation");
87
+ }
88
+ }
89
+ /** Deep copy, so neither implementation hands out a live reference (#214). */
90
+ function freezeCopy(entry) {
91
+ return structuredClone(entry);
92
+ }
93
+ function matches(entry, filter) {
94
+ const e = entry;
95
+ if (filter.kind && e["kind"] !== filter.kind)
96
+ return false;
97
+ if (filter.event && e["event"] !== filter.event)
98
+ return false;
99
+ if (filter.subject_slug && e["subject_slug"] !== filter.subject_slug)
100
+ return false;
101
+ if (filter.subject_gig_id && e["subject_gig_id"] !== filter.subject_gig_id)
102
+ return false;
103
+ if (filter.gig_id && e["gig_id"] !== filter.gig_id)
104
+ return false;
105
+ if (filter.standard_slug && e["standard_slug"] !== filter.standard_slug)
106
+ return false;
107
+ if (filter.genome_hash && e["genome_hash"] !== filter.genome_hash)
108
+ return false;
109
+ if (filter.effective_hash && e["effective_hash"] !== filter.effective_hash)
110
+ return false;
111
+ if (filter.after && String(e["started_at"]) < filter.after)
112
+ return false;
113
+ if (filter.before && String(e["started_at"]) > filter.before)
114
+ return false;
115
+ return true;
116
+ }
117
+ // ── v1 read-side upgrade ────────────────────────────────────────────────────
118
+ // v1 rows are upgraded to the v2 VIEW on read. The file is NEVER rewritten: an append-only
119
+ // ledger that silently self-heals is indistinguishable from one that was tampered with.
120
+ /** v1 governance rows keyed `standard_slug` to the MCP tool name. */
121
+ const V1_GOVERNANCE_EVENTS = new Set([
122
+ "charter_suggest_update", "proposal_create", "gig_abort", "tool_register",
123
+ "agent_promote", "standard_promote", "skill_promote",
124
+ "session_review_write", "learning_synthesize",
125
+ ]);
126
+ const V1_MUTATION_EVENTS = new Set([
127
+ "agent_define", "agent_evolve", "standard_compose",
128
+ "type_register", "type_extend", "skill_define",
129
+ ]);
130
+ function upgradeV1(row) {
131
+ const event = typeof row["standard_slug"] === "string" ? row["standard_slug"] : "";
132
+ const gig_id = typeof row["gig_id"] === "string" ? row["gig_id"] : "";
133
+ const started_at = typeof row["started_at"] === "string" ? row["started_at"] : "";
134
+ // NOTE: `principal` is deliberately left undefined here. A v1 row genuinely has no
135
+ // principal — the field did not exist when it was written — and inventing one (from a
136
+ // process owner, an env var, "unknown") would fabricate provenance, which is exactly the
137
+ // dishonesty `legacy: true` exists to prevent. Absent means absent.
138
+ const base = {
139
+ schema_version: LEDGER_SCHEMA_VERSION,
140
+ entry_id: gig_id,
141
+ output_hashes: Array.isArray(row["output_hashes"]) ? row["output_hashes"] : [],
142
+ started_at,
143
+ finished_at: typeof row["finished_at"] === "string" ? row["finished_at"] : started_at,
144
+ legacy: true,
145
+ };
146
+ if (V1_GOVERNANCE_EVENTS.has(event)) {
147
+ // `abort:<gid>` is the only v1 governance namespace whose subject is recoverable. The
148
+ // rest genuinely recorded nothing — leaving subject_slug absent is the honest result, and
149
+ // `legacy: true` is what says so.
150
+ const subject_gig_id = gig_id.startsWith("abort:") ? gig_id.slice("abort:".length) : undefined;
151
+ return {
152
+ ...base, kind: "governance", event,
153
+ ...(subject_gig_id ? { subject_gig_id } : {}),
154
+ };
155
+ }
156
+ if (V1_MUTATION_EVENTS.has(event)) {
157
+ const gh = row["genome_hash"];
158
+ const oh = base.output_hashes;
159
+ return {
160
+ ...base, kind: "genome_mutation", event,
161
+ ...(typeof gh === "string" && HEX64.test(gh) ? { effective_hash: gh } : {}),
162
+ ...(typeof oh[0] === "string" && HEX64.test(oh[0]) ? { content_hash: oh[0] } : {}),
163
+ };
164
+ }
165
+ // A real run. Identity is carried forward verbatim — never fabricated, never "n/a".
166
+ const gh = row["genome_hash"];
167
+ const rf = row["run_fingerprint"];
168
+ return {
169
+ ...base, kind: "gig", gig_id,
170
+ standard_slug: event,
171
+ ...(typeof gh === "string" && gh !== "n/a" ? { genome_hash: gh } : {}),
172
+ ...(typeof rf === "string" && rf !== "n/a" ? { run_fingerprint: rf } : {}),
173
+ ...(row["usage"] ? { usage: row["usage"] } : {}),
174
+ };
175
+ }
176
+ /** Parse one JSONL line into a v2 row view, or explain why it cannot be. */
177
+ function parseLine(line) {
178
+ let parsed;
179
+ try {
180
+ parsed = JSON.parse(line);
181
+ }
182
+ catch (e) {
183
+ return { reason: `unparseable JSON: ${e.message}` };
184
+ }
185
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
186
+ // `42` and `null` parse fine and would otherwise be handed to execution_history_read as
187
+ // an "execution" — src/ledger.ts:79 was an unchecked cast.
188
+ return { reason: `line is ${parsed === null ? "null" : typeof parsed}, not a ledger row` };
189
+ }
190
+ const row = parsed;
191
+ if (row["kind"] === undefined && row["schema_version"] === undefined) {
192
+ return { entry: upgradeV1(row) };
193
+ }
194
+ return { entry: row };
195
+ }
196
+ // Both implementations expose their methods as bound arrow properties rather than prototype
197
+ // methods. `deps.ledger.query` is routinely passed around and destructured, and a detached
198
+ // `const q = ledger.query; q(...)` would otherwise throw on `this` — a footgun with no upside
199
+ // for an object that is always used as a service handle, never as a prototype.
200
+ export class FileLedger {
201
+ path;
202
+ constructor(path) {
203
+ this.path = path;
204
+ // Bound so a detached `const q = ledger.query; q(...)` works. `deps.ledger` is a service
205
+ // handle that gets passed around and destructured, never used as a prototype.
206
+ this.append = this.append.bind(this);
207
+ this.query = this.query.bind(this);
208
+ this.count = this.count.bind(this);
209
+ this.integrity = this.integrity.bind(this);
210
+ // NOTE: no eager mkdir. bootstrapServerDeps() with no root resolves to process.cwd(), so
211
+ // constructing the production ledger must not seed `.coltrane/` into the developer's
212
+ // checkout just because something built a ServerDeps. The directory is created on the
213
+ // first append instead.
214
+ }
215
+ append(entry) {
216
+ validateEntry(entry);
217
+ try {
218
+ mkdirSync(dirname(this.path), { recursive: true });
219
+ appendFileSync(this.path, JSON.stringify(entry) + "\n");
220
+ }
221
+ catch (e) {
222
+ // Wrap raw fs failures (EACCES / EPERM / EROFS / ENOSPC) in a typed
223
+ // LedgerError so callers see a structured error, not a leaking SystemError.
224
+ // The append is stateless — once the path is writable again, a retry on the
225
+ // same instance succeeds (no cached fd to reset).
226
+ const sys = e;
227
+ const err = new LedgerError(`failed to append to ledger at ${this.path}: ${sys.message}`);
228
+ err.cause = e;
229
+ if (sys.code !== undefined)
230
+ err.code = sys.code;
231
+ throw err;
232
+ }
233
+ }
234
+ /** Single read pass shared by query / count / integrity, so the three can never disagree
235
+ * about what the file contains (v1 `count()` never parsed, so it reported a healthy total
236
+ * for a ledger `query()` could not open). */
237
+ read() {
238
+ const entries = [];
239
+ const corrupt = [];
240
+ if (!existsSync(this.path))
241
+ return { entries, corrupt };
242
+ const lines = readFileSync(this.path, "utf-8").split("\n");
243
+ for (let i = 0; i < lines.length; i++) {
244
+ const raw = lines[i];
245
+ // `.trim()`, not `.length > 0` — a lone `\r` from a CRLF file is length 1 and would
246
+ // otherwise reach JSON.parse (contrast the v1 filter).
247
+ const line = raw.trim();
248
+ if (line.length === 0)
249
+ continue;
250
+ const { entry, reason } = parseLine(line);
251
+ if (entry)
252
+ entries.push(entry);
253
+ else
254
+ corrupt.push({ line_no: i + 1, reason: reason ?? "unreadable", preview: line.slice(0, 120) });
255
+ }
256
+ return { entries, corrupt };
257
+ }
258
+ query(filter = {}) {
259
+ return this.read().entries.filter((e) => matches(e, filter));
260
+ }
261
+ count(filter = {}) {
262
+ return this.read().entries.filter((e) => matches(e, filter)).length;
263
+ }
264
+ /**
265
+ * Skip-and-REPORT. A silent skip (the src/outputs.ts:180-184 shape) is the wrong remedy for
266
+ * an audit trail: it lets a single corrupted byte delete a row with no trace. `query()`
267
+ * keeps serving the intact rows; this is how an operator learns the ledger is damaged.
268
+ */
269
+ integrity() {
270
+ const { entries, corrupt } = this.read();
271
+ return { ok: corrupt.length === 0, path: this.path, entries: entries.length, corrupt };
272
+ }
273
+ }
274
+ export class MemoryLedger {
275
+ entries = [];
276
+ constructor() {
277
+ this.append = this.append.bind(this);
278
+ this.query = this.query.bind(this);
279
+ this.count = this.count.bind(this);
280
+ // #255 — bound like its siblings. The class comment promises BOTH implementations expose
281
+ // bound methods so a detached `const { integrity } = ledger` cannot throw; FileLedger
282
+ // binds it and this did not, so destructuring it here died on `this.entries`.
283
+ this.integrity = this.integrity.bind(this);
284
+ }
285
+ append(entry) {
286
+ validateEntry(entry);
287
+ // Clone IN: v1 pushed the caller's object, so a caller that reused or mutated an entry
288
+ // after append() silently rewrote sealed history (#214).
289
+ this.entries.push(freezeCopy(entry));
290
+ }
291
+ query(filter = {}) {
292
+ // Clone OUT: v1 returned live references, so `ledger.query()[0].genome_hash = "forged"`
293
+ // rewrote history in place. FileLedger was immune only by accident of serialization —
294
+ // the two implementations of one interface had different immutability semantics.
295
+ return this.entries.filter((e) => matches(e, filter)).map(freezeCopy);
296
+ }
297
+ count(filter = {}) {
298
+ return this.entries.filter((e) => matches(e, filter)).length;
299
+ }
300
+ /** Nothing is parsed from bytes here, so there is no torn-line failure mode to report.
301
+ * `path` is empty because there is no file — not because we failed to find one. */
302
+ integrity() {
303
+ return { ok: true, path: "", entries: this.entries.length, corrupt: [] };
304
+ }
305
+ }
306
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { type Agent, type AgentDef, type Standard, type PhaseDef } from "./composition.js";
2
+ import { type SkillOutput, type EvalOutput, type DomainTypeOutput } from "./genome_schema.js";
3
+ export interface CoreTypeRecord {
4
+ slug: string;
5
+ primitive: string;
6
+ description: string;
7
+ schema: object;
8
+ }
9
+ export type DomainTypeRecord = DomainTypeOutput;
10
+ export type AgentFileDef = AgentDef;
11
+ export interface StandardFileDef {
12
+ slug: string;
13
+ domain: string;
14
+ agent_slugs: readonly string[];
15
+ phases: readonly PhaseDef[];
16
+ eval_slugs?: readonly string[];
17
+ input_types?: readonly string[];
18
+ output_types?: readonly string[];
19
+ max_examine_rounds?: number;
20
+ description?: string;
21
+ }
22
+ export type SkillRecord = SkillOutput & {
23
+ package_dir?: string;
24
+ code_hash?: string | null;
25
+ text?: string;
26
+ body?: string;
27
+ };
28
+ export type EvalRecord = EvalOutput;
29
+ export interface LoadError {
30
+ readonly kind: "domain_type" | "agent" | "standard" | "skill" | "eval" | "manifest";
31
+ readonly path: string;
32
+ readonly slug: string | null;
33
+ readonly error: string;
34
+ }
35
+ export interface LoadedGenome {
36
+ core_types: ReadonlyMap<string, CoreTypeRecord>;
37
+ domain_types: ReadonlyMap<string, DomainTypeRecord>;
38
+ agents: ReadonlyMap<string, Agent>;
39
+ standards: Map<string, Standard>;
40
+ skills: Map<string, SkillRecord>;
41
+ evals: Map<string, EvalRecord>;
42
+ load_errors: LoadError[];
43
+ provenance?: ReadonlyMap<string, string>;
44
+ }
45
+ export declare class GenomeLoadError extends Error {
46
+ }
47
+ export declare function loadGenome(root: string, opts?: {
48
+ inheritedAgents?: ReadonlyMap<string, Agent>;
49
+ /** Set by loadLayeredGenome: defer the dangling-skill-binding post-pass to after the
50
+ * fold, so a base agent binding a skill the consumer layer supplies isn't false-flagged. */
51
+ deferSkillBindingCheck?: boolean;
52
+ }): LoadedGenome;
53
+ /**
54
+ * Resolve a LAYERED genome from a stack of roots, lowest → highest (genome extension
55
+ * Phase 2 — docs/genome-extension.md). Each root is loaded as a normal genome, then
56
+ * folded so a higher layer's definitions OVERRIDE a lower layer's by slug, per class.
57
+ * A consumer extends a base by passing [baseRoot, consumerRoot]: it inherits the base,
58
+ * adds its own, and overrides where it specializes. `provenance` records which layer
59
+ * supplied each effective definition. core_types are the immutable 6 (every layer
60
+ * provides them, seeded or on-disk); the top layer's are used.
61
+ */
62
+ export declare function loadLayeredGenome(roots: readonly string[]): LoadedGenome;
63
+ /**
64
+ * Manifest-aware genome load (genome extension Phase 2 — opt-in). A genome root may
65
+ * declare the base(s) it extends in a `genome.json` manifest: `{ "extends": [<path>] }`
66
+ * (absolute, or relative to that root). resolveGenome walks the extends chain, flattens
67
+ * it to a layer stack (bases first, this root last, deduped + cycle-guarded), and resolves
68
+ * it via loadLayeredGenome. No manifest → a plain single-root load. This is what the
69
+ * running server (bootstrapServerDeps) calls, so a downstream consumer's declared base
70
+ * is honored automatically.
71
+ */
72
+ export declare function resolveGenome(root: string): LoadedGenome;
73
+ /**
74
+ * Genome cascade check (genome extension Phase 3 — docs/genome-extension.md). Given a
75
+ * consumer genome and two base versions (`fromBase` it currently validates against,
76
+ * `toBase` a candidate), report what in the CONSUMER layer breaks when the base advances
77
+ * — e.g. a consumer standard that composes a base player the new base removed/renamed.
78
+ *
79
+ * `broken` = consumer-layer load_errors present against toBase but NOT fromBase (the
80
+ * base change broke them). `healed` = the inverse (informational). Lets a consumer
81
+ * decide whether to adopt a new base before pinning to it.
82
+ */
83
+ export interface CascadeReport {
84
+ broken: LoadError[];
85
+ healed: LoadError[];
86
+ }
87
+ export declare function genomeCascadeCheck(consumerRoot: string, fromBase: string, toBase: string): CascadeReport;