@eir-labs/coltrane 0.9.4 → 0.11.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 (141) hide show
  1. package/agents/bandleader.json +54 -0
  2. package/agents/bill.json +4 -2
  3. package/agents/change-verifier.json +2 -1
  4. package/agents/code-implementer.json +7 -4
  5. package/agents/john.json +5 -3
  6. package/agents/lineage-scout-external.json +19 -6
  7. package/agents/lineage-scribe.json +20 -9
  8. package/agents/lineage-weaver.json +26 -11
  9. package/agents/miles.json +2 -1
  10. package/agents/players/bandleader.md +70 -0
  11. package/agents/pr-publisher.json +4 -2
  12. package/agents/red-spec-drafter.json +12 -6
  13. package/agents/room-prober.json +29 -0
  14. package/agents/source-walker.json +1 -1
  15. package/charts/room-probe-chart-v1.json +14 -0
  16. package/charts/worker-contract-docker-v2.json +135 -0
  17. package/charts/worker-contract-v3.json +206 -0
  18. package/dist/src/boundary_check.d.ts +18 -0
  19. package/dist/src/boundary_check.js +70 -0
  20. package/dist/src/boundary_check.js.map +1 -0
  21. package/dist/src/boundary_scan.d.ts +62 -0
  22. package/dist/src/boundary_scan.js +93 -0
  23. package/dist/src/boundary_scan.js.map +1 -0
  24. package/dist/src/chart.js +34 -1
  25. package/dist/src/chart.js.map +1 -1
  26. package/dist/src/claude_invoker.d.ts +2 -1
  27. package/dist/src/claude_invoker.js +150 -17
  28. package/dist/src/claude_invoker.js.map +1 -1
  29. package/dist/src/cli.d.ts +1 -1
  30. package/dist/src/cli.js +61 -26
  31. package/dist/src/cli.js.map +1 -1
  32. package/dist/src/drain_preflight.d.ts +33 -0
  33. package/dist/src/drain_preflight.js +97 -0
  34. package/dist/src/drain_preflight.js.map +1 -0
  35. package/dist/src/genome_schema.d.ts +390 -9
  36. package/dist/src/genome_schema.js +163 -8
  37. package/dist/src/genome_schema.js.map +1 -1
  38. package/dist/src/genome_store.js +9 -0
  39. package/dist/src/genome_store.js.map +1 -1
  40. package/dist/src/genome_writer.d.ts +1 -1
  41. package/dist/src/genome_writer.js +10 -2
  42. package/dist/src/genome_writer.js.map +1 -1
  43. package/dist/src/gig_conformance.d.ts +66 -0
  44. package/dist/src/gig_conformance.js +153 -0
  45. package/dist/src/gig_conformance.js.map +1 -0
  46. package/dist/src/gig_tracker.js +8 -0
  47. package/dist/src/gig_tracker.js.map +1 -1
  48. package/dist/src/grounding.d.ts +44 -0
  49. package/dist/src/grounding.js +127 -0
  50. package/dist/src/grounding.js.map +1 -0
  51. package/dist/src/index.d.ts +1 -0
  52. package/dist/src/index.js +1 -0
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/institution_loader.d.ts +29 -5
  55. package/dist/src/institution_loader.js +67 -6
  56. package/dist/src/institution_loader.js.map +1 -1
  57. package/dist/src/lineage_adoption.d.ts +82 -0
  58. package/dist/src/lineage_adoption.js +82 -0
  59. package/dist/src/lineage_adoption.js.map +1 -0
  60. package/dist/src/lineage_persist.d.ts +34 -0
  61. package/dist/src/lineage_persist.js +60 -0
  62. package/dist/src/lineage_persist.js.map +1 -0
  63. package/dist/src/loader.d.ts +13 -0
  64. package/dist/src/loader.js +43 -2
  65. package/dist/src/loader.js.map +1 -1
  66. package/dist/src/mcp.js +37 -4
  67. package/dist/src/mcp.js.map +1 -1
  68. package/dist/src/org_hire.d.ts +23 -0
  69. package/dist/src/org_hire.js +42 -0
  70. package/dist/src/org_hire.js.map +1 -0
  71. package/dist/src/output_mirror.js +98 -59
  72. package/dist/src/output_mirror.js.map +1 -1
  73. package/dist/src/outputs.d.ts +17 -0
  74. package/dist/src/outputs.js +86 -1
  75. package/dist/src/outputs.js.map +1 -1
  76. package/dist/src/player_to_claude_code.js +26 -2
  77. package/dist/src/player_to_claude_code.js.map +1 -1
  78. package/dist/src/registry.d.ts +3 -1
  79. package/dist/src/registry.js +43 -3
  80. package/dist/src/registry.js.map +1 -1
  81. package/dist/src/repo_index.d.ts +58 -0
  82. package/dist/src/repo_index.js +232 -0
  83. package/dist/src/repo_index.js.map +1 -0
  84. package/dist/src/reuse.d.ts +44 -4
  85. package/dist/src/reuse.js +0 -0
  86. package/dist/src/reuse.js.map +1 -1
  87. package/dist/src/runtime.d.ts +82 -0
  88. package/dist/src/runtime.js +254 -25
  89. package/dist/src/runtime.js.map +1 -1
  90. package/dist/src/server.d.ts +37 -0
  91. package/dist/src/server.js +422 -11
  92. package/dist/src/server.js.map +1 -1
  93. package/dist/src/server_relay.d.ts +40 -2
  94. package/dist/src/server_relay.js +186 -19
  95. package/dist/src/server_relay.js.map +1 -1
  96. package/dist/src/tool_providers.d.ts +27 -0
  97. package/dist/src/tool_providers.js +48 -0
  98. package/dist/src/tool_providers.js.map +1 -1
  99. package/dist/src/venue_credential.d.ts +41 -0
  100. package/dist/src/venue_credential.js +57 -0
  101. package/dist/src/venue_credential.js.map +1 -0
  102. package/dist/src/venue_realize.d.ts +23 -0
  103. package/dist/src/venue_realize.js +43 -3
  104. package/dist/src/venue_realize.js.map +1 -1
  105. package/dist/src/venue_realizer.d.ts +224 -0
  106. package/dist/src/venue_realizer.js +889 -0
  107. package/dist/src/venue_realizer.js.map +1 -0
  108. package/dist/src/version.d.ts +1 -1
  109. package/dist/src/version.js +1 -1
  110. package/dist/src/version.js.map +1 -1
  111. package/dist/src/worker.d.ts +37 -0
  112. package/dist/src/worker.js +127 -24
  113. package/dist/src/worker.js.map +1 -1
  114. package/dist/src/worker_env.d.ts +79 -0
  115. package/dist/src/worker_env.js +322 -0
  116. package/dist/src/worker_env.js.map +1 -0
  117. package/dist/src/workspace.d.ts +12 -1
  118. package/dist/src/workspace.js +10 -3
  119. package/dist/src/workspace.js.map +1 -1
  120. package/domain_types/change-context.json +59 -13
  121. package/domain_types/lineage-adoption-target.json +22 -0
  122. package/domain_types/lineage-map.json +7 -2
  123. package/domain_types/lineage-record.json +55 -5
  124. package/domain_types/prior-art-hit.json +16 -1
  125. package/domain_types/red-spec.json +5 -3
  126. package/domain_types/woodshed-record.json +149 -0
  127. package/evals/gist-present.json +7 -0
  128. package/institutions/coltrane.json +178 -6
  129. package/package.json +6 -3
  130. package/skills/non-vacuity-probe/fixtures/fixture-001.json +17 -0
  131. package/skills/non-vacuity-probe/meta.json +12 -0
  132. package/skills/non-vacuity-probe/skill.md +27 -0
  133. package/skills/non-vacuity-probe/skill.mjs +81 -0
  134. package/standards/lineage-adopt-v0.json +37 -0
  135. package/standards/room-probe-v1.json +28 -0
  136. package/standards/software-change-pr-v1.json +15 -15
  137. package/standards/software-change-red-first-v0.json +183 -0
  138. package/standards/spec-review-and-sequence-v0.json +112 -0
  139. package/standards/studio-session-v0.json +101 -0
  140. package/tours/coltrane.json +72 -0
  141. package/venues/engine-room-v1.json +32 -0
@@ -0,0 +1,322 @@
1
+ // The worker environment contract, written down in ONE place — the fix for Gap 3 of
2
+ // SPEC-worker-contract.md.
3
+ //
4
+ // ONE VARIABLE, THREE READERS, TWO MEANINGS. `COLTRANE_DRAIN_URL` was read by callers that did not
5
+ // agree on what host it named — two treated it as the database's PostgREST base, one as the
6
+ // Coltrane service origin. Pointed at the database, rows wrote and the artifact 401'd forever;
7
+ // repointed at the service, provisioning broke against a 307. Every fix moved the failure because
8
+ // the variable had never named one thing.
9
+ //
10
+ // This module pins the general form of the fix rather than that instance of it:
11
+ // * one variable names one host; two hosts are two variables (`WORKER_ENV_CONTRACT`);
12
+ // * `COLTRANE_SERVICE_URL` is canonical and `COLTRANE_DRAIN_URL` survives only as a normalized
13
+ // legacy alias — a role name is not a host name, which is how one variable came to hold both;
14
+ // * a legacy shape NORMALIZES, never appends (`normalizeWorkerEnv`) — appending is what produced
15
+ // `/rest/v1/rest/v1`;
16
+ // * a misconfigured worker refuses at STARTUP in its own voice (`assertWorkerEnv`), rather than
17
+ // learning it is pointed at the wrong host from a status code at its first write.
18
+ //
19
+ // The contract enumerates every variable the worker path reads. `tests/spec_worker_environment.test.ts`
20
+ // scans the real source of the WORKER_PATH files and fails if any `process.env["…"]` read is absent
21
+ // from this table — so the table is a declaration the code is held to, not a comment. This file
22
+ // therefore reads NO environment itself; its three functions take the environment as an argument.
23
+ /**
24
+ * THE ENUMERATED TABLE. Every environment variable the worker path reads appears here exactly once,
25
+ * as a `name` or as one entry's `legacy_names`. Exactly one always-required url names each host
26
+ * (store, service); no name is listed twice; no legacy alias is also someone's canonical name.
27
+ */
28
+ export const WORKER_ENV_CONTRACT = [
29
+ {
30
+ name: "COLTRANE_STORE_URL",
31
+ host: "store",
32
+ role: "url",
33
+ required: "always",
34
+ meaning: "The PostgREST base URL of the store — the database host that persists gigs, outputs and ledger rows and that the claim path reads directly.",
35
+ },
36
+ {
37
+ name: "COLTRANE_STORE_ANON",
38
+ host: "none",
39
+ role: "credential",
40
+ required: "always",
41
+ meaning: "The store's public anon API key, presented to the store on the claim path as its `apikey`; it is not a write credential.",
42
+ },
43
+ {
44
+ name: "COLTRANE_SERVICE_URL",
45
+ host: "service",
46
+ role: "url",
47
+ required: "always",
48
+ meaning: "The origin of the Coltrane service that brokers drain writes and boot-time provisioning — names the service host, and never the managed database.",
49
+ legacy_names: ["COLTRANE_DRAIN_URL"],
50
+ },
51
+ {
52
+ name: "COLTRANE_DRAIN_KEY",
53
+ host: "none",
54
+ role: "credential",
55
+ required: "venue",
56
+ meaning: "The venue's org-scoped `cdk_` drain credential authorizing output writes through the service on behalf of the whole instance.",
57
+ },
58
+ {
59
+ name: "COLTRANE_AGENT_TOKEN",
60
+ host: "none",
61
+ role: "credential",
62
+ required: "player",
63
+ meaning: "A single agent's own `ctk_` bearer token, identifying the player to the store in player mode instead of a shared venue key.",
64
+ },
65
+ {
66
+ name: "COLTRANE_INSTANCE",
67
+ host: "none",
68
+ role: "identity",
69
+ required: "conditional",
70
+ meaning: "The name this worker box answers to, stamped on every drain write so the store can gate the write against a live lease; absent for an unleased local run.",
71
+ legacy_names: ["FLY_APP_NAME"],
72
+ },
73
+ {
74
+ name: "COLTRANE_DRAIN_PG",
75
+ host: "none",
76
+ role: "credential",
77
+ required: "never",
78
+ meaning: "Legacy direct-Postgres connection string for the drain — a fallback sink reached only when no service drain key is configured.",
79
+ },
80
+ {
81
+ name: "COLTRANE_DRAIN_BUCKET",
82
+ host: "none",
83
+ role: "tuning",
84
+ required: "never",
85
+ meaning: "Name of the storage bucket that drain artifacts are written into; defaults to `coltrane-artifacts` when unset.",
86
+ },
87
+ {
88
+ name: "COLTRANE_DRAIN_OPENING",
89
+ host: "none",
90
+ role: "tuning",
91
+ required: "never",
92
+ meaning: "Milliseconds the drain waits for a gig's opening header before proceeding; tunes drain startup latency.",
93
+ },
94
+ {
95
+ name: "COLTRANE_MIRROR_DIR",
96
+ host: "none",
97
+ role: "tuning",
98
+ required: "never",
99
+ meaning: "Local directory the output mirror writes a copy of every sealed artifact into for offline inspection.",
100
+ },
101
+ {
102
+ name: "COLTRANE_GIT_CREDENTIALS_URL",
103
+ host: "none",
104
+ role: "tuning",
105
+ required: "never",
106
+ meaning: "Endpoint the worker asks for a short-lived git credential when cloning a lease's repository; unset outside a leased drain.",
107
+ },
108
+ {
109
+ name: "COLTRANE_MODEL",
110
+ host: "none",
111
+ role: "tuning",
112
+ required: "never",
113
+ meaning: "Overrides the model version a chair invokes and is recorded on outputs as the model that produced them.",
114
+ },
115
+ {
116
+ name: "COLTRANE_CHAIR_TIMEOUT_MS",
117
+ host: "none",
118
+ role: "tuning",
119
+ required: "never",
120
+ meaning: "Per-chair wall-clock timeout in milliseconds before a running chair invocation is abandoned.",
121
+ },
122
+ {
123
+ name: "COLTRANE_GIG_TIMEOUT_MS",
124
+ host: "none",
125
+ role: "tuning",
126
+ required: "never",
127
+ meaning: "Overall wall-clock timeout in milliseconds for a single gig before the worker abandons it.",
128
+ },
129
+ {
130
+ name: "COLTRANE_WORKER_CHECKPOINTS",
131
+ host: "none",
132
+ role: "tuning",
133
+ required: "never",
134
+ meaning: "Overrides the worker's checkpoint cadence, controlling how often in-progress run state is persisted to disk.",
135
+ },
136
+ {
137
+ name: "COLTRANE_WORKER_STATE_TTL_DAYS",
138
+ host: "none",
139
+ role: "tuning",
140
+ required: "never",
141
+ meaning: "Days a worker retains persisted run state before it is considered stale and eligible for pruning.",
142
+ },
143
+ {
144
+ name: "COLTRANE_TOOL_PROVIDERS",
145
+ host: "none",
146
+ role: "tuning",
147
+ required: "never",
148
+ meaning: "Comma-separated list of tool providers the worker is permitted to load, narrowing the tool surface a chair may reach.",
149
+ },
150
+ ];
151
+ /** The canonical service-url entry — the one host the legacy `COLTRANE_DRAIN_URL` normalizes onto. */
152
+ const SERVICE_URL = "COLTRANE_SERVICE_URL";
153
+ /** The canonical store-url entry — the database host, which must never be the same as the service. */
154
+ const STORE_URL = "COLTRANE_STORE_URL";
155
+ /** The legacy role-name that once held both meanings; now a normalized alias of the service url. */
156
+ const DRAIN_URL = "COLTRANE_DRAIN_URL";
157
+ /** The managed database's host shape. A service url naming this is the defect in its purest form. */
158
+ const MANAGED_DB_HOST = /(^|\.)supabase\.(co|in|net)$/i;
159
+ /** Parseable as an http(s) URL — the shape a `role: "url"` variable must have. */
160
+ function isHttpUrl(value) {
161
+ try {
162
+ const u = new URL(value);
163
+ return u.protocol === "http:" || u.protocol === "https:";
164
+ }
165
+ catch {
166
+ return false;
167
+ }
168
+ }
169
+ /** The host a url addresses, or "" when it does not parse — for comparing two urls' hosts. */
170
+ function urlHost(value) {
171
+ try {
172
+ return new URL(value).host.toLowerCase();
173
+ }
174
+ catch {
175
+ return "";
176
+ }
177
+ }
178
+ /**
179
+ * Strip the legacy `/rest/v1` suffix an origin may carry from when it named a database. Mirrors
180
+ * `src/output_mirror.ts:317-320`: build from the ORIGIN, so a suffix that survives a redeploy can
181
+ * never be appended-to and produce `/rest/v1/rest/v1`.
182
+ */
183
+ function serviceOrigin(value) {
184
+ return value.replace(/\/+$/, "").replace(/\/rest\/v1$/, "");
185
+ }
186
+ /**
187
+ * Normalize a worker environment onto its canonical shape — it NORMALIZES, it never appends.
188
+ *
189
+ * * strips a legacy `/rest/v1` path suffix from the service url rather than building on top of it;
190
+ * * maps the legacy name (`COLTRANE_DRAIN_URL`) onto the canonical `COLTRANE_SERVICE_URL`;
191
+ * * treats the hosting provider's app name (`FLY_APP_NAME`) as a legacy alias of `COLTRANE_INSTANCE`;
192
+ * * is IDEMPOTENT — applying it to its own output changes nothing.
193
+ *
194
+ * The legacy keys are dropped from the output: a normalized environment carries only canonical
195
+ * names, which is what makes re-application a no-op.
196
+ */
197
+ export function normalizeWorkerEnv(env) {
198
+ const out = {};
199
+ for (const [k, v] of Object.entries(env)) {
200
+ if (v !== undefined)
201
+ out[k] = v;
202
+ }
203
+ // A legacy name fills the canonical one only when the canonical is not already set, then is
204
+ // dropped — mapping, not appending.
205
+ const legacyService = out[DRAIN_URL];
206
+ if (legacyService !== undefined && out[SERVICE_URL] === undefined) {
207
+ out[SERVICE_URL] = legacyService;
208
+ }
209
+ delete out[DRAIN_URL];
210
+ const legacyInstance = out["FLY_APP_NAME"];
211
+ if (legacyInstance !== undefined && out["COLTRANE_INSTANCE"] === undefined) {
212
+ out["COLTRANE_INSTANCE"] = legacyInstance;
213
+ }
214
+ delete out["FLY_APP_NAME"];
215
+ const service = out[SERVICE_URL];
216
+ if (service !== undefined) {
217
+ out[SERVICE_URL] = serviceOrigin(service);
218
+ }
219
+ return out;
220
+ }
221
+ /**
222
+ * Which credential mode a worker is in — the SINGLE derivation of it (Gap 4). Both the CLI door and
223
+ * the claim path ask this one function instead of each recomputing `drainKey && instance`; the
224
+ * answer carries the fields the answer needs, so no call site re-reads the environment to fill them
225
+ * in, and its refusal (`why`) is the refusal the CLI prints. It is the only place that decides.
226
+ *
227
+ * Reads the RAW environment for the same reason `assertWorkerEnv` does: the instance may arrive
228
+ * under the legacy `FLY_APP_NAME` alias, and normalizing first would drop that alias, so a
229
+ * venue-key-without-instance could no longer be told apart from a properly named venue.
230
+ *
231
+ * Precedence, and the reasons:
232
+ * * A drain key present makes this a venue box. With an instance it is venue mode; WITHOUT one it
233
+ * REFUSES — even when a player token is sitting right there. A half-configured venue that quietly
234
+ * ran as a player would claim a different set of gigs under a different identity, and the operator
235
+ * would see a queue that merely looked empty. Venue therefore wins over player, and its own
236
+ * misconfiguration is a refusal, not a downgrade.
237
+ * * A player token alone is player mode.
238
+ * * Neither credential is a refusal that names BOTH doors, because either one would work.
239
+ */
240
+ export function workerCredentialMode(env) {
241
+ const drainKey = env["COLTRANE_DRAIN_KEY"];
242
+ const agentToken = env["COLTRANE_AGENT_TOKEN"];
243
+ const instance = env["COLTRANE_INSTANCE"] ?? env["FLY_APP_NAME"];
244
+ if (drainKey) {
245
+ if (instance)
246
+ return { mode: "venue", drainKey, instance };
247
+ return {
248
+ mode: "none",
249
+ why: "COLTRANE_DRAIN_KEY is set but no instance is named — the key is bound to one venue and the " +
250
+ "store cannot tell which. Set COLTRANE_INSTANCE (or FLY_APP_NAME) so the drain key can be presented.",
251
+ };
252
+ }
253
+ if (agentToken)
254
+ return { mode: "player", agentToken };
255
+ return {
256
+ mode: "none",
257
+ why: "work needs a credential: EITHER a venue drain key (COLTRANE_DRAIN_KEY with COLTRANE_INSTANCE " +
258
+ "or FLY_APP_NAME) OR a player token (COLTRANE_AGENT_TOKEN). A drain should hold the venue " +
259
+ "credential: it claims any gig dispatched to its org and runs each as that gig's own acting_for.",
260
+ };
261
+ }
262
+ /**
263
+ * Refuse a misconfigured worker at STARTUP, naming the offending variable in the error — never
264
+ * silently picking a winner, and never learning it from a status code at the first write.
265
+ *
266
+ * Reads the RAW environment. The legacy-alias contradiction check in particular must NOT normalize
267
+ * first: normalizing collapses `COLTRANE_DRAIN_URL` onto `COLTRANE_SERVICE_URL`, leaving nothing to
268
+ * contradict — so the check would pass on exactly the environment it exists to refuse.
269
+ */
270
+ export function assertWorkerEnv(env) {
271
+ // (a) Every always-required variable must be present. A legacy alias satisfies its canonical.
272
+ for (const v of WORKER_ENV_CONTRACT) {
273
+ if (v.required !== "always")
274
+ continue;
275
+ const present = env[v.name] ?? (v.legacy_names ?? []).map((n) => env[n]).find((x) => x != null && x !== "");
276
+ if (present == null || present === "") {
277
+ throw new Error(`${v.name} is required but absent — ${v.meaning}`);
278
+ }
279
+ }
280
+ // (b) Every url-role variable that is present must actually be a url. Checked before any host
281
+ // comparison so the parsing below is safe.
282
+ for (const v of WORKER_ENV_CONTRACT) {
283
+ if (v.role !== "url")
284
+ continue;
285
+ const value = env[v.name] ?? (v.legacy_names ?? []).map((n) => env[n]).find((x) => x != null);
286
+ if (value != null && value !== "" && !isHttpUrl(value)) {
287
+ throw new Error(`${v.name} is a url but does not parse as one: ${value}`);
288
+ }
289
+ }
290
+ const serviceRaw = env[SERVICE_URL] ?? env[DRAIN_URL];
291
+ const storeRaw = env[STORE_URL];
292
+ // (c) The service url must not name the managed database — checked BEFORE the first request, the
293
+ // diagnostic moved from output_mirror.ts to startup where it belongs.
294
+ if (serviceRaw != null && serviceRaw !== "" && MANAGED_DB_HOST.test(urlHost(serviceRaw))) {
295
+ throw new Error(`${SERVICE_URL} names the managed database (${serviceRaw}). It must name the Coltrane service, ` +
296
+ "which brokers both halves of a write; a drain key is not a project credential and Storage will refuse it.");
297
+ }
298
+ // (d) The store and the service must not name the same host — the general form of "pointed at the
299
+ // database", detectable without knowing which of the two is wrong.
300
+ if (serviceRaw != null &&
301
+ serviceRaw !== "" &&
302
+ storeRaw != null &&
303
+ storeRaw !== "" &&
304
+ urlHost(serviceRaw) !== "" &&
305
+ urlHost(serviceRaw) === urlHost(storeRaw)) {
306
+ throw new Error(`${STORE_URL} and ${SERVICE_URL} name the same host (${urlHost(serviceRaw)}) — a store and a ` +
307
+ "service are two hosts, and one url pointed at both is how three readers came to disagree.");
308
+ }
309
+ // (e) A legacy alias that CONTRADICTS the canonical name refuses, naming both — read raw, because
310
+ // normalization would erase the disagreement. Agreement is the ordinary post-redeploy case.
311
+ const drainRaw = env[DRAIN_URL];
312
+ const serviceCanonical = env[SERVICE_URL];
313
+ if (drainRaw != null &&
314
+ drainRaw !== "" &&
315
+ serviceCanonical != null &&
316
+ serviceCanonical !== "" &&
317
+ serviceOrigin(drainRaw) !== serviceOrigin(serviceCanonical)) {
318
+ throw new Error(`${DRAIN_URL} (${drainRaw}) disagrees with ${SERVICE_URL} (${serviceCanonical}). ${DRAIN_URL} is a ` +
319
+ `legacy alias of ${SERVICE_URL}; set one, or make them agree.`);
320
+ }
321
+ }
322
+ //# sourceMappingURL=worker_env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker_env.js","sourceRoot":"","sources":["../../src/worker_env.ts"],"names":[],"mappings":"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"}
@@ -69,8 +69,15 @@ export declare function fetchGitCredential(endpoint: string, drainKey: string, i
69
69
  * The helper is supplied through GIT_CONFIG_* rather than `-c`, because `git clone -c k=v` writes k
70
70
  * into the NEW clone's .git/config — see the note at the call site. Scoped to `https://github.com`
71
71
  * so a URL naming any other host is never offered the token.
72
+ *
73
+ * `targetDir`, when given, is WHERE the clone lands — a caller-supplied directory instead of this
74
+ * function's own throwaway tmpdir. It is the one addition a venue room needs over the drain: the room
75
+ * clones into `<realizationDir>/workspace` (the seat's cwd, subsumed by the realizer's own teardown)
76
+ * rather than a detached tmpdir. Everything else — the token-never-on-disk GIT_CONFIG_* path, cleanup,
77
+ * revoke — is IDENTICAL, because a room's working tree and the drain's must be the same thing prepared
78
+ * the same way. Omitted (the drain's call) keeps the original mkdtempSync behaviour byte-for-byte.
72
79
  */
73
- export declare function cloneInto(repoUrl: string, token: string): PreparedWorkspace;
80
+ export declare function cloneInto(repoUrl: string, token: string, targetDir?: string): PreparedWorkspace;
74
81
  /**
75
82
  * Everything above, for one claimed gig — or null when the claim names no repository.
76
83
  *
@@ -86,4 +93,8 @@ export declare function prepareWorkspace(opts: {
86
93
  drainKey: string | undefined;
87
94
  instance: string | undefined;
88
95
  endpoint: string | undefined;
96
+ /** Where the clone lands. Omitted (the drain) → cloneInto's own throwaway tmpdir. Supplied (a venue
97
+ * room) → `<realizationDir>/workspace`, so the seat's cwd is the room's tree and the realizer's
98
+ * existing teardown subsumes the clone. The credential path is unchanged either way. */
99
+ target?: string | undefined;
89
100
  }): Promise<PreparedWorkspace | null>;
@@ -64,9 +64,16 @@ export async function fetchGitCredential(endpoint, drainKey, instance, gigId) {
64
64
  * The helper is supplied through GIT_CONFIG_* rather than `-c`, because `git clone -c k=v` writes k
65
65
  * into the NEW clone's .git/config — see the note at the call site. Scoped to `https://github.com`
66
66
  * so a URL naming any other host is never offered the token.
67
+ *
68
+ * `targetDir`, when given, is WHERE the clone lands — a caller-supplied directory instead of this
69
+ * function's own throwaway tmpdir. It is the one addition a venue room needs over the drain: the room
70
+ * clones into `<realizationDir>/workspace` (the seat's cwd, subsumed by the realizer's own teardown)
71
+ * rather than a detached tmpdir. Everything else — the token-never-on-disk GIT_CONFIG_* path, cleanup,
72
+ * revoke — is IDENTICAL, because a room's working tree and the drain's must be the same thing prepared
73
+ * the same way. Omitted (the drain's call) keeps the original mkdtempSync behaviour byte-for-byte.
67
74
  */
68
- export function cloneInto(repoUrl, token) {
69
- const dir = mkdtempSync(join(tmpdir(), "coltrane-gig-"));
75
+ export function cloneInto(repoUrl, token, targetDir) {
76
+ const dir = targetDir ?? mkdtempSync(join(tmpdir(), "coltrane-gig-"));
70
77
  const cleanup = () => {
71
78
  try {
72
79
  rmSync(dir, { recursive: true, force: true });
@@ -136,6 +143,6 @@ export async function prepareWorkspace(opts) {
136
143
  `nowhere to obtain a credential scoped to this gig`);
137
144
  }
138
145
  const cred = await fetchGitCredential(opts.endpoint, opts.drainKey, opts.instance, opts.gigId);
139
- return cloneInto(opts.repoUrl, cred.token);
146
+ return cloneInto(opts.repoUrl, cred.token, opts.target);
140
147
  }
141
148
  //# sourceMappingURL=workspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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"}
@@ -1,32 +1,78 @@
1
1
  {
2
2
  "slug": "change-context",
3
- "version": 1,
3
+ "version": 2,
4
4
  "extends": "Interpretation",
5
5
  "domain": "software-change",
6
6
  "status": "active",
7
- "description": "The exhaustive read of the material a change lands in, produced before any decision is taken. Records what is present AND what is absent: unknowns is required because an incomplete reading that omits its gaps is indistinguishable from a complete one, and every downstream seat would treat it as complete.",
8
7
  "schema": {
9
8
  "type": "object",
10
9
  "properties": {
11
- "repository": { "type": "string", "description": "Repository or working-tree the reading covers." },
12
- "boundary": { "type": "array", "items": { "type": "string" }, "description": "The declared extent of the read: paths and artefacts inside it, and those deliberately outside it." },
13
- "entry_points": { "type": "array", "items": { "type": "string" }, "description": "Where control or data enters the region under change." },
14
- "relevant_files": {
10
+ "repository": {
11
+ "type": "string",
12
+ "description": "Repository or working-tree the reading covers."
13
+ },
14
+ "boundary": {
15
+ "type": "array",
16
+ "items": {
17
+ "type": "string"
18
+ },
19
+ "description": "The declared extent of the read: paths and artefacts inside it, and those deliberately outside it."
20
+ },
21
+ "entry_points": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "string"
25
+ },
26
+ "description": "Where control or data enters the region under change."
27
+ },
28
+ "relevant_files": {
15
29
  "type": "array",
16
30
  "description": "Each file the change plausibly touches, with the reason it is relevant and the locator the reading came from.",
17
31
  "items": {
18
32
  "type": "object",
19
33
  "properties": {
20
- "path": { "type": "string" },
21
- "why": { "type": "string" },
22
- "locator": { "type": "string", "description": "Tool plus path or query that produced this finding." }
34
+ "path": {
35
+ "type": "string"
36
+ },
37
+ "why": {
38
+ "type": "string"
39
+ },
40
+ "locator": {
41
+ "type": "string",
42
+ "description": "Tool plus path or query that produced this finding."
43
+ }
23
44
  },
24
- "required": ["path", "why"]
45
+ "required": [
46
+ "path",
47
+ "why"
48
+ ]
25
49
  }
26
50
  },
27
- "existing_tests": { "type": "array", "items": { "type": "string" }, "description": "Checks that already cover the region — the baseline a later verdict is measured against." },
28
- "conventions_observed": { "type": "array", "items": { "type": "string" }, "description": "Prevailing patterns the change is expected to hold to." },
29
- "unknowns": { "type": "array", "items": { "type": "string" }, "description": "Questions the material does not answer and paths that could not be reached. Required: the honest bound of the read." }
51
+ "existing_tests": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "string"
55
+ },
56
+ "description": "Checks that already cover the region — the baseline a later verdict is measured against."
57
+ },
58
+ "conventions_observed": {
59
+ "type": "array",
60
+ "items": {
61
+ "type": "string"
62
+ },
63
+ "description": "Prevailing patterns the change is expected to hold to."
64
+ },
65
+ "unknowns": {
66
+ "type": "array",
67
+ "items": {
68
+ "type": "string"
69
+ },
70
+ "description": "Questions the material does not answer and paths that could not be reached. Required: the honest bound of the read."
71
+ },
72
+ "index_revision": {
73
+ "type": "string",
74
+ "description": "The source revision the MECHANICAL half of this reading was compiled against — the tree state src/repo_index.ts walked. Present when a compiler produced those fields, absent when a human or a model read the code directly. It is what makes the freshness gate possible (#424 I16): a change-context whose index_revision no longer matches the current source describes a tree that has moved, and is refused rather than used. Structure compiled from a stale tree is not merely old, it is WRONG in the specific way that is hardest to notice — the shape is right, the file:line locators are plausible, and every one of them points at the wrong place. OPTIONAL by construction: a change-context may come from any of four interchangeable producers (a reader, the compiler, a prior standard, a human) and only the compiler has a revision to report, so requiring it would make the type unsatisfiable for the three that read code directly — which is the producer-agnosticism I11 pins."
75
+ }
30
76
  }
31
77
  },
32
78
  "required_fields": [
@@ -0,0 +1,22 @@
1
+ {
2
+ "slug": "lineage-adoption-target",
3
+ "version": 1,
4
+ "extends": "Signal",
5
+ "domain": "lineage",
6
+ "status": "active",
7
+ "description": "WHICH INSTITUTION an approved lineage-record grounds. Both lineage-record and lineage-verdict promise an attachment neither carries: the record says that on approval it 'becomes first-class lineage attached to an institution, inherited by every agent seated there', and the verdict says a passing verdict 'promotes the record to first-class institutional lineage' — yet neither holds an institution_slug, so a sealed adoption named no target and the caller had to know it out of band. The attachment is not a property of the LINEAGE: the same record can ground two institutions and nothing about its ancestry changes when it does. It is not a property of the APPROVAL either: the approver judges whether the evidence is sound, which is a question about grounding rather than about attachment. It is a property of the ADOPTION ACT. One record, approved once, may be adopted into two institutions by two separate acts, each with its own approver and its own seal. Carrying it here rather than on either sealed type also means no shared type changes shape, and lineage-adopt-v0's chair is already an ENTRY chair, so the target arrives the same way the record does — in the dispatch payload.",
8
+ "schema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "institution_slug": {
12
+ "type": "string",
13
+ "description": "The institution this adoption grounds. Must resolve against the loaded genome; an unresolved slug is a dead name and fails closed rather than adopting into nothing."
14
+ },
15
+ "note": {
16
+ "type": "string",
17
+ "description": "Optional. Why THIS institution, when a record could ground more than one. Recorded beside the act rather than inferred from it later."
18
+ }
19
+ }
20
+ },
21
+ "required_fields": ["source", "institution_slug"]
22
+ }
@@ -21,9 +21,14 @@
21
21
  "enum": ["descends-from", "aligns-with", "diverges-from", "supersedes", "informed-by"]
22
22
  },
23
23
  "grounding_internal": { "type": "string" },
24
- "grounding_external": { "type": "string" }
24
+ "grounding_external": { "type": "string" },
25
+ "strength": {
26
+ "type": "string",
27
+ "enum": ["dereferenceable-both-sides", "structural-correspondence", "conceptual-analogy"],
28
+ "$comment": "The weaver DRAWS the grounding strength; the scribe carries it through unchanged into the lineage-record. Ordinal, closed vocabulary — see domain_types/lineage-record.json for the orthogonality note against CitationSchema.evidence_grade (src/genome_schema.ts:293-309)."
29
+ }
25
30
  },
26
- "required": ["internal_ref", "external_ref", "relation", "grounding_internal", "grounding_external"]
31
+ "required": ["internal_ref", "external_ref", "relation", "grounding_internal", "grounding_external", "strength"]
27
32
  }
28
33
  }
29
34
  }
@@ -1,16 +1,66 @@
1
1
  {
2
2
  "slug": "lineage-record",
3
- "version": 1,
3
+ "version": 2,
4
4
  "extends": "Artifact",
5
5
  "domain": "lineage",
6
6
  "status": "active",
7
- "description": "The formal, publishable lineage: the identified external body, our internal inventory, the established connections between them, the gap, and the alignment recommendation — grounded citation by citation. On human approval this record becomes first-class lineage attached to an institution, inherited by every agent seated there.",
7
+ "description": "The formal, publishable lineage: the identified external body, our internal inventory, the established connections between them, the gap, and the alignment recommendation — grounded citation by citation. Held to the SAME bar the lineage-map weaver already meets one phase upstream: every connection carries the map edge's full shape plus a closed-vocabulary per-edge grounding strength, external bodies carry a closed reached|not-reached status, and inventory entries carry a checkable reference. On human approval this record becomes first-class lineage attached to an institution, inherited by every agent seated there.",
8
8
  "schema": {
9
9
  "type": "object",
10
10
  "properties": {
11
- "external_body": { "type": "array" },
12
- "internal_inventory": { "type": "array" },
13
- "connections": { "type": "array" },
11
+ "external_body": {
12
+ "type": "array",
13
+ "items": {
14
+ "type": "object",
15
+ "properties": {
16
+ "source": { "type": "string" },
17
+ "status": {
18
+ "type": "string",
19
+ "enum": ["reached", "not-reached"]
20
+ },
21
+ "note": { "type": "string" }
22
+ },
23
+ "required": ["source", "status"],
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "internal_inventory": {
28
+ "type": "array",
29
+ "items": {
30
+ "type": "object",
31
+ "properties": {
32
+ "reference": { "type": "string" },
33
+ "kind": { "type": "string" },
34
+ "summary": { "type": "string" }
35
+ },
36
+ "required": ["reference"],
37
+ "additionalProperties": false
38
+ }
39
+ },
40
+ "connections": {
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "items": {
44
+ "type": "object",
45
+ "properties": {
46
+ "internal_ref": { "type": "string" },
47
+ "external_ref": { "type": "string" },
48
+ "relation": {
49
+ "type": "string",
50
+ "enum": ["descends-from", "aligns-with", "diverges-from", "supersedes", "informed-by"]
51
+ },
52
+ "grounding_internal": { "type": "string" },
53
+ "grounding_external": { "type": "string" },
54
+ "strength": {
55
+ "type": "string",
56
+ "enum": ["dereferenceable-both-sides", "structural-correspondence", "conceptual-analogy"],
57
+ "$comment": "Per-edge grounding strength: HOW firmly this connection is drawn, ordinal from dereferenceable-both-sides (strongest) to conceptual-analogy (weakest). It is ORTHOGONAL to CitationSchema.evidence_grade (src/genome_schema.ts:293-309), which grades the source's fetch status (archive|attestation) and is never laundered upward. Both endpoints can be archive-grade while the edge between them is a loose conceptual-analogy. Do NOT collapse strength into evidence_grade — that obvious future 'simplification' would destroy the distinction between a citation-grounded edge and a loose structural or conceptual one."
58
+ }
59
+ },
60
+ "required": ["internal_ref", "external_ref", "relation", "grounding_internal", "grounding_external", "strength"],
61
+ "additionalProperties": false
62
+ }
63
+ },
14
64
  "gap": { "type": "string" },
15
65
  "alignment_recommendation": { "type": "string" }
16
66
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "slug": "prior-art-hit",
3
- "version": 1,
3
+ "version": 2,
4
4
  "extends": "Signal",
5
5
  "domain": "patent-triage",
6
6
  "status": "active",
@@ -41,6 +41,21 @@
41
41
  "caveat": {
42
42
  "type": "string"
43
43
  }
44
+ },
45
+ "if": {
46
+ "properties": {
47
+ "verified": {
48
+ "const": true
49
+ }
50
+ },
51
+ "required": [
52
+ "verified"
53
+ ]
54
+ },
55
+ "then": {
56
+ "required": [
57
+ "verification_method"
58
+ ]
44
59
  }
45
60
  },
46
61
  "required_fields": [