@eir-labs/coltrane 0.5.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/agents/bill.json +59 -0
- package/agents/deploy-agent.json +68 -0
- package/agents/deploy-scout.json +40 -0
- package/agents/john.json +42 -0
- package/agents/miles.json +44 -0
- package/charts/software-delivery-v1.json +9 -0
- package/charts/software-delivery-v2.json +39 -0
- package/dist/src/bifrost_invoker.js +5 -3
- package/dist/src/bifrost_invoker.js.map +1 -1
- package/dist/src/canonical_form.d.ts +23 -0
- package/dist/src/canonical_form.js +53 -0
- package/dist/src/canonical_form.js.map +1 -1
- package/dist/src/chart.d.ts +254 -0
- package/dist/src/chart.js +897 -0
- package/dist/src/chart.js.map +1 -0
- package/dist/src/claude_invoker.d.ts +20 -3
- package/dist/src/claude_invoker.js +30 -5
- package/dist/src/claude_invoker.js.map +1 -1
- package/dist/src/cli.d.ts +19 -4
- package/dist/src/cli.js +132 -9
- package/dist/src/cli.js.map +1 -1
- package/dist/src/composition.d.ts +24 -0
- package/dist/src/composition.js +50 -5
- package/dist/src/composition.js.map +1 -1
- package/dist/src/conduct_daemon.d.ts +59 -0
- package/dist/src/conduct_daemon.js +178 -0
- package/dist/src/conduct_daemon.js.map +1 -0
- package/dist/src/genome_schema.d.ts +1476 -146
- package/dist/src/genome_schema.js +438 -32
- package/dist/src/genome_schema.js.map +1 -1
- package/dist/src/genome_store.d.ts +79 -0
- package/dist/src/genome_store.js +503 -0
- package/dist/src/genome_store.js.map +1 -0
- package/dist/src/gig_tracker.d.ts +11 -1
- package/dist/src/gig_tracker.js +5 -0
- package/dist/src/gig_tracker.js.map +1 -1
- package/dist/src/hosted_tools.d.ts +23 -0
- package/dist/src/hosted_tools.js +170 -0
- package/dist/src/hosted_tools.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/ledger.d.ts +22 -0
- package/dist/src/ledger.js +4 -0
- package/dist/src/ledger.js.map +1 -1
- package/dist/src/loader.d.ts +9 -1
- package/dist/src/loader.js +105 -5
- package/dist/src/loader.js.map +1 -1
- package/dist/src/mcp.js +52 -5
- package/dist/src/mcp.js.map +1 -1
- package/dist/src/output_mirror.d.ts +70 -0
- package/dist/src/output_mirror.js +381 -0
- package/dist/src/output_mirror.js.map +1 -0
- package/dist/src/outputs.d.ts +77 -1
- package/dist/src/outputs.js +179 -37
- package/dist/src/outputs.js.map +1 -1
- package/dist/src/play_worker.d.ts +24 -0
- package/dist/src/play_worker.js +49 -0
- package/dist/src/play_worker.js.map +1 -0
- package/dist/src/registry.d.ts +2 -0
- package/dist/src/registry.js +63 -33
- package/dist/src/registry.js.map +1 -1
- package/dist/src/reuse.d.ts +56 -0
- package/dist/src/reuse.js +0 -0
- package/dist/src/reuse.js.map +1 -1
- package/dist/src/runtime.d.ts +91 -2
- package/dist/src/runtime.js +236 -18
- package/dist/src/runtime.js.map +1 -1
- package/dist/src/seal_drill.d.ts +32 -0
- package/dist/src/seal_drill.js +138 -0
- package/dist/src/seal_drill.js.map +1 -0
- package/dist/src/server.d.ts +39 -1
- package/dist/src/server.js +760 -68
- package/dist/src/server.js.map +1 -1
- package/dist/src/skill_subprocess.js +12 -4
- package/dist/src/skill_subprocess.js.map +1 -1
- package/dist/src/supabase_genome.d.ts +28 -0
- package/dist/src/supabase_genome.js +49 -0
- package/dist/src/supabase_genome.js.map +1 -0
- package/dist/src/tool_surface.d.ts +5 -0
- package/dist/src/tool_surface.js +15 -0
- package/dist/src/tool_surface.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/worker.d.ts +182 -0
- package/dist/src/worker.js +609 -0
- package/dist/src/worker.js.map +1 -0
- package/domain_types/branch-state.json +21 -0
- package/domain_types/change-context.json +39 -0
- package/domain_types/change-decision.json +36 -0
- package/domain_types/change-plan.json +47 -0
- package/domain_types/change-request.json +24 -0
- package/domain_types/change-set.json +46 -0
- package/domain_types/change-verdict.json +26 -0
- package/domain_types/deploy-verdict.json +23 -0
- package/domain_types/design-brief.json +37 -0
- package/domain_types/design-concept.json +36 -0
- package/domain_types/design-definition.json +37 -0
- package/domain_types/design-question.json +23 -0
- package/domain_types/design-verdict.json +27 -0
- package/domain_types/preview-deployment.json +32 -0
- package/institutions/quartet.json +344 -0
- package/package.json +21 -3
- package/skills/vercel-api/fixtures/error.json +10 -0
- package/skills/vercel-api/fixtures/ready.json +10 -0
- package/skills/vercel-api/fixtures/unsettled.json +10 -0
- package/skills/vercel-api/meta.json +10 -0
- package/skills/vercel-api/skill.mjs +63 -0
- package/standards/preview-deploy-v1.json +89 -0
- package/standards/product-design-v1.json +122 -0
- package/standards/promote-v1.json +41 -0
- package/standards/software-change-v1.json +147 -0
- package/venues/ci-deploy-room-v1.json +28 -0
- package/venues/empty-room-v1.json +19 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// Two-tier output persistence + retrieval — the reliable local mirror MCP traverses.
|
|
2
|
+
//
|
|
3
|
+
// The bug this closes: a CLI-dispatched gig sealed outputs to disk, but the payloads were not
|
|
4
|
+
// reliably retrievable through the MCP surface. This module makes every sealed output land in a
|
|
5
|
+
// content-addressed local store under `.coltrane/` (gitignored) that MCP reads seamlessly with
|
|
6
|
+
// NO remote configured, and — only when an append credential is present — ALSO drains the same
|
|
7
|
+
// record to a remote row + artifact store.
|
|
8
|
+
//
|
|
9
|
+
// Two tiers, by design:
|
|
10
|
+
// • TIER 1 — a compact, queryable METADATA row, ALWAYS. id, gig_id, agent, phase, primitive,
|
|
11
|
+
// domain_type, content_sha, a short preview, a storage_ref, cost/tokens, created_at. This
|
|
12
|
+
// alone supports high-level traversal (`output_query`/`output_trace`) without loading a
|
|
13
|
+
// single payload.
|
|
14
|
+
// • TIER 2 — the full PAYLOAD, as a content-addressed artifact, fetched only on the deeper
|
|
15
|
+
// second pass (`readPayload`, or `output_query { include_data:true }`).
|
|
16
|
+
//
|
|
17
|
+
// OSS stays pure: with no drain credential in the environment, ONLY the local tier runs and no
|
|
18
|
+
// new npm dependency is touched (the remote row goes over `fetch`; the optional Postgres path is
|
|
19
|
+
// a guarded dynamic import that is never reached unless a PG connection string is set).
|
|
20
|
+
import * as fs from "node:fs";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
const ARTIFACT_SUBDIR = path.join("outputs", "artifacts");
|
|
23
|
+
const META_SUBDIR = path.join("outputs", "meta");
|
|
24
|
+
// Where the local mirror lives. `COLTRANE_MIRROR_DIR` overrides (tests, sandboxes); otherwise
|
|
25
|
+
// `<genomeRoot>/.coltrane` — beside the ledger, gitignored, so a CLI and an MCP server rooted at
|
|
26
|
+
// the same repo share one store and MCP retrieval traverses exactly what the CLI sealed.
|
|
27
|
+
export function defaultMirrorDir(root) {
|
|
28
|
+
const override = process.env["COLTRANE_MIRROR_DIR"];
|
|
29
|
+
if (override && override.length > 0)
|
|
30
|
+
return override;
|
|
31
|
+
return path.join(root ?? process.cwd(), ".coltrane");
|
|
32
|
+
}
|
|
33
|
+
function ensureDir(dir) {
|
|
34
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
function appendJsonl(file, row) {
|
|
37
|
+
ensureDir(path.dirname(file));
|
|
38
|
+
fs.appendFileSync(file, JSON.stringify(row) + "\n", "utf8");
|
|
39
|
+
}
|
|
40
|
+
// A short, deterministic summary of the payload for the Tier-1 row. Never throws.
|
|
41
|
+
export function outputPreview(data) {
|
|
42
|
+
try {
|
|
43
|
+
const s = JSON.stringify(data);
|
|
44
|
+
return s.length <= 200 ? s : s.slice(0, 197) + "...";
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const makePreview = outputPreview;
|
|
51
|
+
/** The repo-relative artifact path for a content_sha — the Tier-1 row's local `storage_ref`. */
|
|
52
|
+
export function mirrorStorageRef(content_sha) {
|
|
53
|
+
return path.join(ARTIFACT_SUBDIR, `${content_sha.replace(/[^0-9a-zA-Z._-]/g, "_")}.json`);
|
|
54
|
+
}
|
|
55
|
+
function metaOf(rec, storage_ref) {
|
|
56
|
+
return {
|
|
57
|
+
id: rec.id,
|
|
58
|
+
gig_id: rec.gig_id,
|
|
59
|
+
agent_slug: rec.agent_slug,
|
|
60
|
+
from_role: rec.from_role,
|
|
61
|
+
phase: rec.phase,
|
|
62
|
+
primitive: rec.primitive,
|
|
63
|
+
core_type: rec.core_type,
|
|
64
|
+
domain_type: rec.domain_type,
|
|
65
|
+
domain_type_version: rec.domain_type_version,
|
|
66
|
+
domain: rec.domain,
|
|
67
|
+
content_sha: rec.content_sha,
|
|
68
|
+
input_refs: rec.input_refs,
|
|
69
|
+
input_shas: rec.input_shas,
|
|
70
|
+
cost_usd: rec.cost_usd,
|
|
71
|
+
tokens_used: rec.tokens_used,
|
|
72
|
+
duration_ms: rec.duration_ms,
|
|
73
|
+
model: rec.model,
|
|
74
|
+
model_tier: rec.model_tier,
|
|
75
|
+
created_at: rec.created_at,
|
|
76
|
+
preview: makePreview(rec.data),
|
|
77
|
+
storage_ref,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function readJsonlRows(file) {
|
|
81
|
+
if (!fs.existsSync(file))
|
|
82
|
+
return [];
|
|
83
|
+
const rows = [];
|
|
84
|
+
for (const line of fs.readFileSync(file, "utf8").split("\n")) {
|
|
85
|
+
const t = line.trim();
|
|
86
|
+
if (!t)
|
|
87
|
+
continue;
|
|
88
|
+
try {
|
|
89
|
+
rows.push(JSON.parse(t));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Forgiving read (a torn append should not take the whole traversal offline). The
|
|
93
|
+
// store's own `integrity()` is the surface that REPORTS damage; here we keep serving.
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return rows;
|
|
97
|
+
}
|
|
98
|
+
export function createOutputMirror(mirrorRoot) {
|
|
99
|
+
const artifactsDir = path.join(mirrorRoot, ARTIFACT_SUBDIR);
|
|
100
|
+
const metaDir = path.join(mirrorRoot, META_SUBDIR);
|
|
101
|
+
function artifactPath(content_sha) {
|
|
102
|
+
// Content-addressed: a filename-safe form of the sha. Two byte-identical payloads dedupe.
|
|
103
|
+
const safe = content_sha.replace(/[^0-9a-zA-Z._-]/g, "_");
|
|
104
|
+
return path.join(artifactsDir, `${safe}.json`);
|
|
105
|
+
}
|
|
106
|
+
const storageRef = mirrorStorageRef;
|
|
107
|
+
function writeArtifact(rec) {
|
|
108
|
+
const file = artifactPath(rec.content_sha);
|
|
109
|
+
// Content-addressed → if it already exists, the bytes are identical; skip the rewrite.
|
|
110
|
+
if (fs.existsSync(file))
|
|
111
|
+
return;
|
|
112
|
+
ensureDir(path.dirname(file));
|
|
113
|
+
fs.writeFileSync(file, JSON.stringify({ content_sha: rec.content_sha, id: rec.id, data: rec.data }), "utf8");
|
|
114
|
+
}
|
|
115
|
+
function metaFile(gig_id) {
|
|
116
|
+
return path.join(metaDir, `${gig_id}.jsonl`);
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
root: mirrorRoot,
|
|
120
|
+
persist(rec) {
|
|
121
|
+
const ref = storageRef(rec.content_sha);
|
|
122
|
+
// TIER 2 first, so the Tier-1 row never points at an artifact that is not there yet.
|
|
123
|
+
writeArtifact(rec);
|
|
124
|
+
// TIER 1 — the always-on compact row.
|
|
125
|
+
appendJsonl(metaFile(rec.gig_id), metaOf(rec, ref));
|
|
126
|
+
// REMOTE, credential-gated. Fire-and-forget: a finished gig is not failed because a
|
|
127
|
+
// remote append could not be reached. OSS with no credential never enters this path.
|
|
128
|
+
if (remoteConfigured()) {
|
|
129
|
+
void drainRemote(rec).catch((e) => {
|
|
130
|
+
if (process.env["COLTRANE_DRAIN_DEBUG"]) {
|
|
131
|
+
console.warn(`[output_mirror] remote drain failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
queryMeta(filter) {
|
|
137
|
+
// A FRESH read every call — this is what makes a long-lived MCP server see a gig sealed by
|
|
138
|
+
// a separate CLI process. No `fullyHydrated`-style latch lives here on purpose.
|
|
139
|
+
if (!fs.existsSync(metaDir))
|
|
140
|
+
return [];
|
|
141
|
+
const gigId = filter?.gig_id;
|
|
142
|
+
const files = gigId
|
|
143
|
+
? [metaFile(gigId)]
|
|
144
|
+
: fs.readdirSync(metaDir).filter((f) => f.endsWith(".jsonl")).map((f) => path.join(metaDir, f));
|
|
145
|
+
const out = [];
|
|
146
|
+
for (const file of files)
|
|
147
|
+
out.push(...readJsonlRows(file));
|
|
148
|
+
return out;
|
|
149
|
+
},
|
|
150
|
+
readPayload(sel) {
|
|
151
|
+
let content_sha = sel.content_sha;
|
|
152
|
+
let meta;
|
|
153
|
+
if (!content_sha && sel.id) {
|
|
154
|
+
// Resolve id → content_sha via the Tier-1 rows (fresh scan).
|
|
155
|
+
meta = this.queryMeta().find((m) => m.id === sel.id);
|
|
156
|
+
content_sha = meta?.content_sha;
|
|
157
|
+
}
|
|
158
|
+
else if (content_sha) {
|
|
159
|
+
meta = this.queryMeta().find((m) => m.content_sha === content_sha);
|
|
160
|
+
}
|
|
161
|
+
if (!content_sha)
|
|
162
|
+
return undefined;
|
|
163
|
+
const file = artifactPath(content_sha);
|
|
164
|
+
if (fs.existsSync(file)) {
|
|
165
|
+
try {
|
|
166
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
167
|
+
return { meta, data: parsed.data };
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return { meta };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Local miss — the artifact may live only in the remote store (a mirror pulled from a peer).
|
|
174
|
+
// Best-effort remote fetch when configured; otherwise nothing to return.
|
|
175
|
+
return meta ? { meta } : undefined;
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// ── REMOTE TIER — append-only, credential-gated. Never a service_role key (see the TODO). ──────
|
|
180
|
+
//
|
|
181
|
+
// Two credential shapes are accepted, whichever is present drives the write:
|
|
182
|
+
// (a) COLTRANE_DRAIN_KEY — a per-consumer ISSUED, scoped append key. The Tier-1 row is POSTed
|
|
183
|
+
// to PostgREST (`coltrane_outputs`) and the Tier-2 payload uploaded to Storage, both with
|
|
184
|
+
// this key. Uses `fetch` only — no new npm dependency.
|
|
185
|
+
// (b) COLTRANE_DRAIN_PG — a Postgres connection string for a scoped append role. The row is
|
|
186
|
+
// written over a direct `pg` connection (a guarded dynamic import; `pg` is NOT a declared
|
|
187
|
+
// dependency, so this path is unreachable — and harmless — unless the operator both sets
|
|
188
|
+
// the env AND installs the driver).
|
|
189
|
+
//
|
|
190
|
+
// COLTRANE_DRAIN_URL is the PostgREST + Storage project base URL (deployment-supplied, no host
|
|
191
|
+
// baked in here) for the (a) REST paths. COLTRANE_DRAIN_BUCKET names the Storage bucket
|
|
192
|
+
// (default "coltrane-artifacts").
|
|
193
|
+
function remoteConfigured() {
|
|
194
|
+
return Boolean(process.env["COLTRANE_DRAIN_KEY"] || process.env["COLTRANE_DRAIN_PG"]);
|
|
195
|
+
}
|
|
196
|
+
function drainBody(rec) {
|
|
197
|
+
const body = {
|
|
198
|
+
id: rec.id,
|
|
199
|
+
gig_id: rec.gig_id,
|
|
200
|
+
agent_slug: rec.agent_slug,
|
|
201
|
+
phase: rec.phase,
|
|
202
|
+
primitive: rec.primitive,
|
|
203
|
+
core_type: rec.core_type,
|
|
204
|
+
domain_type: rec.domain_type,
|
|
205
|
+
domain_type_version: rec.domain_type_version,
|
|
206
|
+
domain: rec.domain,
|
|
207
|
+
content_sha: rec.content_sha,
|
|
208
|
+
data: rec.data,
|
|
209
|
+
input_shas: rec.input_shas,
|
|
210
|
+
cost_usd: rec.cost_usd,
|
|
211
|
+
tokens_used: rec.tokens_used,
|
|
212
|
+
duration_ms: rec.duration_ms,
|
|
213
|
+
created_at: rec.created_at,
|
|
214
|
+
};
|
|
215
|
+
return body;
|
|
216
|
+
}
|
|
217
|
+
async function drainRemote(rec) {
|
|
218
|
+
const key = process.env["COLTRANE_DRAIN_KEY"];
|
|
219
|
+
if (key) {
|
|
220
|
+
await drainViaPostgrest(rec, key);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const pgConn = process.env["COLTRANE_DRAIN_PG"];
|
|
224
|
+
if (pgConn) {
|
|
225
|
+
await drainViaPg(rec, pgConn);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function drainViaPostgrest(rec, key) {
|
|
230
|
+
const base = (process.env["COLTRANE_DRAIN_URL"] ?? "").replace(/\/$/, "");
|
|
231
|
+
if (!base)
|
|
232
|
+
throw new Error("COLTRANE_DRAIN_KEY is set but COLTRANE_DRAIN_URL (project base) is missing");
|
|
233
|
+
// TIER 1 — the metadata+data row into `coltrane_outputs` (columns already exist in the schema).
|
|
234
|
+
const rowRes = await fetch(`${base}/rest/v1/coltrane_outputs`, {
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers: {
|
|
237
|
+
apikey: key,
|
|
238
|
+
Authorization: `Bearer ${key}`,
|
|
239
|
+
"Content-Type": "application/json",
|
|
240
|
+
Prefer: "resolution=merge-duplicates,return=minimal",
|
|
241
|
+
},
|
|
242
|
+
body: JSON.stringify(drainBody(rec)),
|
|
243
|
+
});
|
|
244
|
+
if (!rowRes.ok)
|
|
245
|
+
throw new Error(`coltrane_outputs POST ${rowRes.status}`);
|
|
246
|
+
// TIER 2 — the payload artifact into Storage, content-addressed by sha (idempotent upsert).
|
|
247
|
+
const bucket = process.env["COLTRANE_DRAIN_BUCKET"] ?? "coltrane-artifacts";
|
|
248
|
+
const objectPath = `${rec.gig_id}/${rec.content_sha}.json`;
|
|
249
|
+
const artRes = await fetch(`${base}/storage/v1/object/${bucket}/${objectPath}`, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
headers: {
|
|
252
|
+
apikey: key,
|
|
253
|
+
Authorization: `Bearer ${key}`,
|
|
254
|
+
"Content-Type": "application/json",
|
|
255
|
+
"x-upsert": "true",
|
|
256
|
+
},
|
|
257
|
+
body: JSON.stringify({ content_sha: rec.content_sha, id: rec.id, data: rec.data }),
|
|
258
|
+
});
|
|
259
|
+
// A duplicate object (already uploaded for this sha) is success, not failure.
|
|
260
|
+
if (!artRes.ok && artRes.status !== 409)
|
|
261
|
+
throw new Error(`storage POST ${artRes.status}`);
|
|
262
|
+
}
|
|
263
|
+
async function drainViaPg(rec, conn) {
|
|
264
|
+
// Guarded dynamic import — `pg` is intentionally NOT a declared dependency, so the string is
|
|
265
|
+
// indirected to keep tsc from resolving it, and any failure to load surfaces as a drain error
|
|
266
|
+
// (fire-and-forget at the call site) rather than a hard crash.
|
|
267
|
+
const moduleName = "pg";
|
|
268
|
+
let pg;
|
|
269
|
+
try {
|
|
270
|
+
pg = await import(moduleName);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
throw new Error("COLTRANE_DRAIN_PG is set but the 'pg' driver is not installed — install it in the consuming " +
|
|
274
|
+
"deployment, or use COLTRANE_DRAIN_KEY (PostgREST) instead. OSS ships no pg dependency.");
|
|
275
|
+
}
|
|
276
|
+
const Client = pg.Client;
|
|
277
|
+
if (!Client)
|
|
278
|
+
throw new Error("'pg' loaded but exposes no Client");
|
|
279
|
+
const client = new Client({ connectionString: conn });
|
|
280
|
+
await client.connect();
|
|
281
|
+
try {
|
|
282
|
+
const b = drainBody(rec);
|
|
283
|
+
await client.query(`insert into coltrane_outputs
|
|
284
|
+
(id, gig_id, agent_slug, phase, primitive, domain_type, domain_type_version, domain, content_sha, data, input_shas, cost_usd, tokens_used, duration_ms, created_at)
|
|
285
|
+
values ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
|
286
|
+
on conflict (id) do nothing`, [
|
|
287
|
+
b["id"], b["gig_id"], b["agent_slug"], b["phase"], b["primitive"], b["domain_type"],
|
|
288
|
+
b["domain_type_version"], b["domain"], b["content_sha"], JSON.stringify(b["data"]),
|
|
289
|
+
b["input_shas"], b["cost_usd"], b["tokens_used"], b["duration_ms"], b["created_at"],
|
|
290
|
+
]);
|
|
291
|
+
}
|
|
292
|
+
finally {
|
|
293
|
+
await client.end();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/** The sink row, derived entirely from the run's own record (engine "complete" → sink "completed"). */
|
|
297
|
+
export function gigHeaderBody(rec) {
|
|
298
|
+
const started = rec.started_at ? Date.parse(rec.started_at) : NaN;
|
|
299
|
+
const finished = rec.finished_at ? Date.parse(rec.finished_at) : NaN;
|
|
300
|
+
const duration = Number.isFinite(started) && Number.isFinite(finished) ? finished - started : null;
|
|
301
|
+
const tokens = rec.usage && (rec.usage.input_tokens !== undefined || rec.usage.output_tokens !== undefined)
|
|
302
|
+
? (rec.usage.input_tokens ?? 0) + (rec.usage.output_tokens ?? 0)
|
|
303
|
+
: null;
|
|
304
|
+
const manifest = {};
|
|
305
|
+
if (rec.outputs_count !== undefined)
|
|
306
|
+
manifest["output_count"] = rec.outputs_count;
|
|
307
|
+
if (rec.error !== undefined)
|
|
308
|
+
manifest["error"] = rec.error;
|
|
309
|
+
return {
|
|
310
|
+
id: rec.gig_id,
|
|
311
|
+
standard_slug: rec.standard_slug,
|
|
312
|
+
status: rec.status === "complete" ? "completed" : rec.status,
|
|
313
|
+
genome_hash: rec.genome_hash ?? null,
|
|
314
|
+
run_fingerprint: rec.run_fingerprint ?? null,
|
|
315
|
+
started_at: rec.started_at ?? null,
|
|
316
|
+
completed_at: rec.finished_at ?? null,
|
|
317
|
+
total_cost_usd: rec.usage?.total_cost_usd ?? null,
|
|
318
|
+
total_tokens: tokens,
|
|
319
|
+
total_duration_ms: duration,
|
|
320
|
+
manifest,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/** Drain the header. Silent no-op when no drain credential is configured. */
|
|
324
|
+
export async function drainGigHeader(rec) {
|
|
325
|
+
if (!remoteConfigured())
|
|
326
|
+
return;
|
|
327
|
+
const key = process.env["COLTRANE_DRAIN_KEY"];
|
|
328
|
+
if (key) {
|
|
329
|
+
const base = (process.env["COLTRANE_DRAIN_URL"] ?? "").replace(/\/$/, "");
|
|
330
|
+
if (!base)
|
|
331
|
+
throw new Error("COLTRANE_DRAIN_KEY is set but COLTRANE_DRAIN_URL (drain service base) is missing");
|
|
332
|
+
const res = await fetch(`${base}/rest/v1/coltrane_gigs`, {
|
|
333
|
+
method: "POST",
|
|
334
|
+
headers: {
|
|
335
|
+
apikey: key,
|
|
336
|
+
Authorization: `Bearer ${key}`,
|
|
337
|
+
"Content-Type": "application/json",
|
|
338
|
+
Prefer: "resolution=merge-duplicates,return=minimal",
|
|
339
|
+
},
|
|
340
|
+
body: JSON.stringify(gigHeaderBody(rec)),
|
|
341
|
+
});
|
|
342
|
+
if (!res.ok)
|
|
343
|
+
throw new Error(`coltrane_gigs POST ${res.status}`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const pgConn = process.env["COLTRANE_DRAIN_PG"];
|
|
347
|
+
if (pgConn) {
|
|
348
|
+
const moduleName = "pg";
|
|
349
|
+
const pg = (await import(moduleName));
|
|
350
|
+
if (!pg.Client)
|
|
351
|
+
throw new Error("'pg' loaded but exposes no Client");
|
|
352
|
+
const client = new pg.Client({ connectionString: pgConn });
|
|
353
|
+
await client.connect();
|
|
354
|
+
try {
|
|
355
|
+
const b = gigHeaderBody(rec);
|
|
356
|
+
await client.query(`insert into coltrane_gigs (id, standard_slug, status, genome_hash, run_fingerprint, started_at, completed_at, total_cost_usd, total_tokens, total_duration_ms, manifest)
|
|
357
|
+
values ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
|
|
358
|
+
on conflict (id) do update set
|
|
359
|
+
standard_slug = excluded.standard_slug, status = excluded.status,
|
|
360
|
+
genome_hash = excluded.genome_hash, run_fingerprint = excluded.run_fingerprint,
|
|
361
|
+
started_at = excluded.started_at, completed_at = excluded.completed_at,
|
|
362
|
+
total_cost_usd = excluded.total_cost_usd, total_tokens = excluded.total_tokens,
|
|
363
|
+
total_duration_ms = excluded.total_duration_ms, manifest = excluded.manifest`, [
|
|
364
|
+
b["id"], b["standard_slug"], b["status"], b["genome_hash"], b["run_fingerprint"],
|
|
365
|
+
b["started_at"], b["completed_at"], b["total_cost_usd"], b["total_tokens"],
|
|
366
|
+
b["total_duration_ms"], JSON.stringify(b["manifest"]),
|
|
367
|
+
]);
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
await client.end();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// TODO(scoped-credential): the remote tier expects an APPEND-ONLY credential — either a
|
|
375
|
+
// per-consumer issued key (COLTRANE_DRAIN_KEY) whose grant is exactly "insert a coltrane_outputs
|
|
376
|
+
// row + upload an artifact object" and nothing else, or a Postgres role (COLTRANE_DRAIN_PG)
|
|
377
|
+
// scoped to INSERT on coltrane_outputs only. A service_role key MUST NOT be used here. Issuing
|
|
378
|
+
// that scoped credential (a Supabase RLS insert policy for the key's role, and a Storage bucket
|
|
379
|
+
// policy allowing upsert to the artifacts bucket) is deployment work that lives outside this OSS
|
|
380
|
+
// repo; this module only consumes whichever env credential is present.
|
|
381
|
+
//# sourceMappingURL=output_mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output_mirror.js","sourceRoot":"","sources":["../../src/output_mirror.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,EAAE;AACF,8FAA8F;AAC9F,gGAAgG;AAChG,+FAA+F;AAC/F,+FAA+F;AAC/F,2CAA2C;AAC3C,EAAE;AACF,wBAAwB;AACxB,+FAA+F;AAC/F,8FAA8F;AAC9F,4FAA4F;AAC5F,sBAAsB;AACtB,6FAA6F;AAC7F,4EAA4E;AAC5E,EAAE;AACF,+FAA+F;AAC/F,iGAAiG;AACjG,wFAAwF;AACxF,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AA0ClC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAEjD,8FAA8F;AAC9F,iGAAiG;AACjG,yFAAyF;AACzF,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACpD,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,GAAY;IAC7C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AAC9D,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AACD,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,MAAM,CAAC,GAAiB,EAAE,WAAmB;IACpD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;QAC5C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAC9B,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAI,IAAY;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,IAAI,GAAQ,EAAE,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAM,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,kFAAkF;YAClF,sFAAsF;QACxF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAEnD,SAAS,YAAY,CAAC,WAAmB;QACvC,0FAA0F;QAC1F,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,UAAU,GAAG,gBAAgB,CAAC;IAEpC,SAAS,aAAa,CAAC,GAAiB;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3C,uFAAuF;QACvF,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO;QAChC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9B,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/G,CAAC;IAED,SAAS,QAAQ,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO;QACL,IAAI,EAAE,UAAU;QAEhB,OAAO,CAAC,GAAG;YACT,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACxC,qFAAqF;YACrF,aAAa,CAAC,GAAG,CAAC,CAAC;YACnB,sCAAsC;YACtC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACpD,oFAAoF;YACpF,qFAAqF;YACrF,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBACvB,KAAK,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChC,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC;wBACxC,OAAO,CAAC,IAAI,CAAC,wCAAwC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACrG,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,SAAS,CAAC,MAAM;YACd,2FAA2F;YAC3F,gFAAgF;YAChF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,EAAE,MAAM,CAAC;YAC7B,MAAM,KAAK,GAAG,KAAK;gBACjB,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBACnB,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAClG,MAAM,GAAG,GAAiB,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,aAAa,CAAa,IAAI,CAAC,CAAC,CAAC;YACvE,OAAO,GAAG,CAAC;QACb,CAAC;QAED,WAAW,CAAC,GAAG;YACb,IAAI,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;YAClC,IAAI,IAA4B,CAAC;YACjC,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBAC3B,6DAA6D;gBAC7D,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrD,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC;YAClC,CAAC;iBAAM,IAAI,WAAW,EAAE,CAAC;gBACvB,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,CAAC,WAAW;gBAAE,OAAO,SAAS,CAAC;YACnC,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;YACvC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAuC,CAAC;oBAC/F,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,IAAI,EAAE,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,6FAA6F;YAC7F,yEAAyE;YACzE,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,EAAE;AACF,6EAA6E;AAC7E,iGAAiG;AACjG,gGAAgG;AAChG,6DAA6D;AAC7D,gGAAgG;AAChG,gGAAgG;AAChG,+FAA+F;AAC/F,0CAA0C;AAC1C,EAAE;AACF,+FAA+F;AAC/F,wFAAwF;AACxF,kCAAkC;AAClC,SAAS,gBAAgB;IACvB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,SAAS,CAAC,GAAiB;IAClC,MAAM,IAAI,GAA4B;QACpC,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;QAC5C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAiB;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC9C,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAiB,EAAE,GAAW;IAC7D,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IACzG,gGAAgG;IAChG,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,2BAA2B,EAAE;QAC7D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,MAAM,EAAE,GAAG;YACX,aAAa,EAAE,UAAU,GAAG,EAAE;YAC9B,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,4CAA4C;SACrD;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;KACrC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,4FAA4F;IAC5F,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,oBAAoB,CAAC;IAC5E,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,OAAO,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,sBAAsB,MAAM,IAAI,UAAU,EAAE,EAAE;QAC9E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,MAAM,EAAE,GAAG;YACX,aAAa,EAAE,UAAU,GAAG,EAAE;YAC9B,cAAc,EAAE,kBAAkB;YAClC,UAAU,EAAE,MAAM;SACnB;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;KACnF,CAAC,CAAC;IACH,8EAA8E;IAC9E,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAiB,EAAE,IAAY;IACvD,6FAA6F;IAC7F,8FAA8F;IAC9F,+DAA+D;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC;IACxB,IAAI,EAAW,CAAC;IAChB,IAAI,CAAC;QACH,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,8FAA8F;YAC5F,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAI,EAAqE,CAAC,MAAM,CAAC;IAC7F,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,MAAM,CAAC,KAAK,CAChB;;;mCAG6B,EAC7B;YACE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC;YACnF,CAAC,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAClF,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC;SACpF,CACF,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AA8BD,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,GAAoB;IAChD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACrE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACnG,MAAM,MAAM,GACV,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC;QAC1F,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QAChE,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS;QAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC;IAClF,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS;QAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;IAC3D,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,MAAM;QACd,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM;QAC5D,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,IAAI;QACpC,eAAe,EAAE,GAAG,CAAC,eAAe,IAAI,IAAI;QAC5C,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,IAAI;QAClC,YAAY,EAAE,GAAG,CAAC,WAAW,IAAI,IAAI;QACrC,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,cAAc,IAAI,IAAI;QACjD,YAAY,EAAE,MAAM;QACpB,iBAAiB,EAAE,QAAQ;QAC3B,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAoB;IACvD,IAAI,CAAC,gBAAgB,EAAE;QAAE,OAAO;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC9C,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;QAC/G,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,wBAAwB,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,MAAM,EAAE,GAAG;gBACX,aAAa,EAAE,UAAU,GAAG,EAAE;gBAC9B,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,4CAA4C;aACrD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;SACzC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAmE,CAAC;QACxG,IAAI,CAAC,EAAE,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,MAAM,CAAC,KAAK,CAChB;;;;;;;wFAOgF,EAChF;gBACE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,iBAAiB,CAAC;gBAChF,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC;gBAC1E,CAAC,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;aACtD,CACF,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,iGAAiG;AACjG,4FAA4F;AAC5F,+FAA+F;AAC/F,gGAAgG;AAChG,iGAAiG;AACjG,uEAAuE"}
|
package/dist/src/outputs.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Registry } from "./registry.js";
|
|
2
|
+
import type { OutputMirror } from "./output_mirror.js";
|
|
2
3
|
export declare const REF_RELATIONS: readonly ["derived_from", "validates", "challenges", "refines", "triggers", "contains"];
|
|
3
4
|
export type RefRelation = (typeof REF_RELATIONS)[number];
|
|
4
5
|
export interface OutputRecord {
|
|
@@ -96,6 +97,61 @@ export interface OutputWrite {
|
|
|
96
97
|
cache_key: string;
|
|
97
98
|
} | undefined;
|
|
98
99
|
}
|
|
100
|
+
/** The infix that separates a performance root from a movement id. Carries dots on BOTH sides so
|
|
101
|
+
* it cannot occur in a bare uuid, and `.m` alone cannot be mistaken for it. */
|
|
102
|
+
export declare const MOVEMENT_ID_INFIX = ".m.";
|
|
103
|
+
/** A movement's gig id, from the performance's id and the movement's. */
|
|
104
|
+
export declare function composeMovementGigId(gig_id: string, movement_id: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* The performance a gig id belongs to. A plain gig id is its own root.
|
|
107
|
+
*
|
|
108
|
+
* Split at the FIRST infix, not the last: `composeChart`'s R1 admits `[A-Za-z0-9._-]+` for a
|
|
109
|
+
* movement_id, so a movement may itself contain `.m.` — and only a first-occurrence split puts
|
|
110
|
+
* two siblings of one performance under the same root.
|
|
111
|
+
*/
|
|
112
|
+
export declare function performanceRoot(gig_id: string): string;
|
|
113
|
+
/** Which movement a gig id names, or undefined when it names none (a plain gig, or a
|
|
114
|
+
* degenerate chart, whose one movement runs under the performance's own id). */
|
|
115
|
+
export declare function movementOfGigId(gig_id: string): string | undefined;
|
|
116
|
+
/** Which way `trace` walks. `upstream` (the default) is the ancestor closure. */
|
|
117
|
+
export type TraceDirection = "upstream" | "downstream" | "both";
|
|
118
|
+
/**
|
|
119
|
+
* Where a traced record LIVED. Present only when there is something to say: a record sealed under
|
|
120
|
+
* a plain gig id, reached from a seed in that same gig, carries none of these — which is what
|
|
121
|
+
* keeps a single-standard gig's trace byte-identical to what it was before charts existed.
|
|
122
|
+
*/
|
|
123
|
+
export interface TraceLabels {
|
|
124
|
+
/** The movement whose gig sealed this record. Absent when its gig id names no movement. */
|
|
125
|
+
movement?: string | undefined;
|
|
126
|
+
/** The performance this record's gig belongs to. Absent when its gig id names no movement. */
|
|
127
|
+
performance_gig_id?: string | undefined;
|
|
128
|
+
/** Set when this node's gig_id differs from the seed's — the walk CROSSED a boundary to reach
|
|
129
|
+
* it. Crossing is never silent: a consumer reads it off the node. */
|
|
130
|
+
crossed?: true | undefined;
|
|
131
|
+
/** Never set. The discriminant against `TraceMissingNode`. */
|
|
132
|
+
missing?: undefined;
|
|
133
|
+
}
|
|
134
|
+
/** A record the walk resolved, labelled with where it lived. */
|
|
135
|
+
export type TraceRecordNode = OutputRecord & TraceLabels;
|
|
136
|
+
/**
|
|
137
|
+
* A reference the chain makes and this store cannot resolve — the upstream movement drained
|
|
138
|
+
* remotely and was never local, or a row was lost.
|
|
139
|
+
*
|
|
140
|
+
* It is a NAMED terminal, never a dropped edge. Silently skipping it is the #248 defect exactly:
|
|
141
|
+
* the engine would report a SHORTER CHAIN as if it were the whole chain. The `content_sha` comes
|
|
142
|
+
* from the referring record's `input_shas` — engine-stamped at seal time, which is why the hole
|
|
143
|
+
* can be named rather than guessed at. It is `""` only when the reference carries no sha at all
|
|
144
|
+
* (a hand-authored `output_refs` edge, which records no hash).
|
|
145
|
+
*/
|
|
146
|
+
export interface TraceMissingNode {
|
|
147
|
+
/** The output id the chain referenced. */
|
|
148
|
+
id: string;
|
|
149
|
+
content_sha: string;
|
|
150
|
+
missing: true;
|
|
151
|
+
/** The record that referenced it — so an operator knows where the hole is. */
|
|
152
|
+
referenced_by: string;
|
|
153
|
+
}
|
|
154
|
+
export type TraceNode = TraceRecordNode | TraceMissingNode;
|
|
99
155
|
export interface OutputRef {
|
|
100
156
|
id: string;
|
|
101
157
|
from_output_id: string;
|
|
@@ -155,9 +211,28 @@ export interface OutputStore {
|
|
|
155
211
|
all(): readonly OutputRecord[];
|
|
156
212
|
addRef(from_output_id: string, to_output_id: string, relation: RefRelation, primitive: string): OutputRef;
|
|
157
213
|
refs(): readonly OutputRef[];
|
|
214
|
+
/**
|
|
215
|
+
* E6: walk the provenance graph from a seed record. Returns the reachable closure, cycle-safe,
|
|
216
|
+
* EXCLUDING the seed itself.
|
|
217
|
+
*
|
|
218
|
+
* `direction` — `upstream` (the default) follows `input_refs` plus `derived_from`/`refines`
|
|
219
|
+
* edges to the ancestors; `downstream` follows the reverse of `input_refs` to the descendants;
|
|
220
|
+
* `both` is their union, each node once.
|
|
221
|
+
*
|
|
222
|
+
* `max_depth` caps the walk at N hops from the seed. `0` returns nothing.
|
|
223
|
+
*
|
|
224
|
+
* SCOPE — the PERFORMANCE, not one gig and not the whole store. A movement's gig id is
|
|
225
|
+
* `<performance>.m.<movement>`, so the walk follows an edge into any gig of the same
|
|
226
|
+
* performance and LABELS the node with where it lived (`TraceLabels`). It refuses an edge into
|
|
227
|
+
* an unrelated gig: a hand-authored reference between two performances is out of family, and
|
|
228
|
+
* surfacing it would be the cross-gig leak PR #85 closed.
|
|
229
|
+
*
|
|
230
|
+
* A reference this store cannot resolve is returned as a `TraceMissingNode`, never dropped.
|
|
231
|
+
*/
|
|
158
232
|
trace(id: string, opts?: {
|
|
159
233
|
max_depth?: number;
|
|
160
|
-
|
|
234
|
+
direction?: TraceDirection;
|
|
235
|
+
}): TraceNode[];
|
|
161
236
|
findings(): Finding[];
|
|
162
237
|
coreTypeOf(typeSlug: string): string | null;
|
|
163
238
|
/**
|
|
@@ -194,6 +269,7 @@ export interface OutputStore {
|
|
|
194
269
|
}
|
|
195
270
|
export interface OutputStoreOptions {
|
|
196
271
|
persistDir?: string | undefined;
|
|
272
|
+
mirror?: OutputMirror | undefined;
|
|
197
273
|
}
|
|
198
274
|
export declare function defaultOutputsPersistDir(): string;
|
|
199
275
|
export declare function createOutputStore(registry: Registry, options?: OutputStoreOptions): OutputStore;
|