@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,254 @@
|
|
|
1
|
+
import { type ChartInput, type ChartOutput, type ChartEdgeOutput, type ChartApprovalGateOutput, type VenueOutput } from "./genome_schema.js";
|
|
2
|
+
import type { Agent, Standard } from "./composition.js";
|
|
3
|
+
import { type OutputRecord } from "./outputs.js";
|
|
4
|
+
import { type GigResult, type RunDeps } from "./runtime.js";
|
|
5
|
+
export type Chart = ChartOutput;
|
|
6
|
+
export type ChartMovement = Chart["movements"][number];
|
|
7
|
+
export type ChartEdge = ChartEdgeOutput;
|
|
8
|
+
export type ChartApprovalGate = ChartApprovalGateOutput;
|
|
9
|
+
/** The room a performance is held in. Its shape is `VenueSchema` (one Zod source); its only engine
|
|
10
|
+
* behaviour today is the ceiling rule below, which is why the type surfaces from this module. */
|
|
11
|
+
export type Venue = VenueOutput;
|
|
12
|
+
/** A movement with its standard RESOLVED — the composition's output, and what a run walks. */
|
|
13
|
+
export interface ResolvedMovement {
|
|
14
|
+
movement_id: string;
|
|
15
|
+
standard: Standard;
|
|
16
|
+
runtime_fills: Record<string, unknown>;
|
|
17
|
+
seatings: Chart["movements"][number]["seatings"];
|
|
18
|
+
}
|
|
19
|
+
/** How an edge was classified by R6. A `conditional` edge may legitimately carry nothing. */
|
|
20
|
+
export interface ClassifiedEdge {
|
|
21
|
+
from_movement: string;
|
|
22
|
+
to_movement: string;
|
|
23
|
+
output_type: string;
|
|
24
|
+
kind: "hard" | "conditional";
|
|
25
|
+
}
|
|
26
|
+
/** One refusal, located. Never a bare boolean: a chart is refused FOR something, at a place. */
|
|
27
|
+
export interface ChartViolation {
|
|
28
|
+
/** "R0".."R9" — the rule that fired, so a caller can act on the class of defect. */
|
|
29
|
+
rule: string;
|
|
30
|
+
detail: string;
|
|
31
|
+
movement_id?: string;
|
|
32
|
+
edge?: {
|
|
33
|
+
from_movement: string;
|
|
34
|
+
to_movement: string;
|
|
35
|
+
output_type: string;
|
|
36
|
+
};
|
|
37
|
+
gate_id?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Everything a performance needs, and nothing it has not been checked for. */
|
|
40
|
+
export interface ChartPlan {
|
|
41
|
+
chart: Chart;
|
|
42
|
+
movements: readonly ResolvedMovement[];
|
|
43
|
+
/** Topological order over edges ∪ gate ordering — the order `runChart` walks. */
|
|
44
|
+
order: readonly string[];
|
|
45
|
+
edges_classified: readonly ClassifiedEdge[];
|
|
46
|
+
chart_hash: string;
|
|
47
|
+
}
|
|
48
|
+
export type ChartComposition = (ChartPlan & {
|
|
49
|
+
ok: true;
|
|
50
|
+
violations: readonly ChartViolation[];
|
|
51
|
+
}) | {
|
|
52
|
+
ok: false;
|
|
53
|
+
violations: readonly ChartViolation[];
|
|
54
|
+
};
|
|
55
|
+
export interface ChartComposeInput {
|
|
56
|
+
chart: ChartInput;
|
|
57
|
+
/** The caller's genome. A movement's standard resolves here or the movement is a dead name. */
|
|
58
|
+
standards: ReadonlyMap<string, Standard>;
|
|
59
|
+
/** For R3: a seating names an agent, and an agent that does not exist is a dead seat. */
|
|
60
|
+
agents?: ReadonlyMap<string, Agent> | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* For R10: the rooms this caller knows. A chart that names a `venue` is composable ONLY against a
|
|
63
|
+
* map that holds it — an unresolvable ceiling is not an absent ceiling, so a caller who knows no
|
|
64
|
+
* venues cannot compose a chart that names one. A chart with no `venue` never consults this.
|
|
65
|
+
*/
|
|
66
|
+
venues?: ReadonlyMap<string, Venue> | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* The types the chart's DISPATCH PAYLOAD will carry — the third way an entry slot can be filled
|
|
69
|
+
* (R7), beside an incoming hard edge and a movement's `runtime_fills`.
|
|
70
|
+
*
|
|
71
|
+
* Declared at compose time on purpose. A payload is a dispatch-time fact, but "which types this
|
|
72
|
+
* performance is seeded with" is an authoring-time DECISION, exactly as a standard declares its
|
|
73
|
+
* `input_types` rather than discovering them at t=0. Absent = the chart declares no payload, and
|
|
74
|
+
* a required entry slot with no edge and no fill is a dead slot.
|
|
75
|
+
*/
|
|
76
|
+
payload_types?: readonly string[] | undefined;
|
|
77
|
+
}
|
|
78
|
+
/** One movement, no edges, no gates: the single-standard gig, wearing the chart's clothes. */
|
|
79
|
+
export declare function isDegenerateChart(chart: {
|
|
80
|
+
movements: readonly unknown[];
|
|
81
|
+
edges?: readonly unknown[];
|
|
82
|
+
approval_gates?: readonly unknown[];
|
|
83
|
+
}): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* The arrangement's identity.
|
|
86
|
+
*
|
|
87
|
+
* MOVEMENT lines (sorted by movement_id) fold `movement_id` with the movement's standard
|
|
88
|
+
* projection; EDGE lines (sorted) fold the endpoints, the type and the declared `optional` flag;
|
|
89
|
+
* GATE lines fold the arrangement's human seats. Declaration order therefore cannot move the hash,
|
|
90
|
+
* and the same standards arranged differently cannot share it.
|
|
91
|
+
*
|
|
92
|
+
* The standard projection is `genomeHash(standard)` ITSELF, deliberately: the spec asked for "the
|
|
93
|
+
* same field set genomeHash folds today", and the only way to guarantee those are the same bytes —
|
|
94
|
+
* now and after the next change to that field set — is to call the same function. It is also what
|
|
95
|
+
* makes the degenerate short-circuit below an exact identity rather than a coincidence.
|
|
96
|
+
*/
|
|
97
|
+
export declare function chartHash(plan: {
|
|
98
|
+
movements: readonly ResolvedMovement[];
|
|
99
|
+
chart: {
|
|
100
|
+
edges?: readonly ChartEdge[] | undefined;
|
|
101
|
+
approval_gates?: readonly ChartApprovalGate[] | undefined;
|
|
102
|
+
};
|
|
103
|
+
}): string;
|
|
104
|
+
/**
|
|
105
|
+
* Desugar a bare `standard_slug` into the chart it always was.
|
|
106
|
+
*
|
|
107
|
+
* `chart_slug == movement_id == standard_slug`, no edges, no gates, and the dispatch payload
|
|
108
|
+
* becomes the movement's `runtime_fills`. Every existing caller path is preserved because a
|
|
109
|
+
* single-standard gig IS this chart.
|
|
110
|
+
*/
|
|
111
|
+
export declare function degenerateChart(standard_slug: string, gig_input?: Record<string, unknown>): Chart;
|
|
112
|
+
/**
|
|
113
|
+
* The dispatch target refine: EXACTLY ONE of `standard_slug` / `chart_slug`.
|
|
114
|
+
*
|
|
115
|
+
* Both optional at the outer level (so no existing caller's shape breaks) and refined to
|
|
116
|
+
* exactly-one, because "a standard AND a chart" names two performances and "neither" names none.
|
|
117
|
+
*/
|
|
118
|
+
export declare function dispatchTarget(args: {
|
|
119
|
+
standard_slug?: string | undefined;
|
|
120
|
+
chart_slug?: string | undefined;
|
|
121
|
+
}): {
|
|
122
|
+
ok: true;
|
|
123
|
+
kind: "standard" | "chart";
|
|
124
|
+
slug: string;
|
|
125
|
+
} | {
|
|
126
|
+
ok: false;
|
|
127
|
+
error: string;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* The effective tool set of one agent in one room: its OWN grants, intersected with the room's
|
|
131
|
+
* equipment. Grants are returned as the agent declared them (scoping intact) and matched on their
|
|
132
|
+
* BASE name, because that is how every other grant resolution in the engine matches — a room that
|
|
133
|
+
* holds `Bash` holds `Bash(npx vitest run:*)`.
|
|
134
|
+
*
|
|
135
|
+
* The direction is the whole point: this can only ever return a subset of `agent.allowed_tools`. A
|
|
136
|
+
* tool present in the room and absent from the charter does not appear, so a venue cannot hand a
|
|
137
|
+
* player authority its charter never claimed.
|
|
138
|
+
*/
|
|
139
|
+
export declare function venueEffectiveTools(agent: Agent, venue: Venue): string[];
|
|
140
|
+
/**
|
|
141
|
+
* The types a chart's SOURCE movements are seeded with — the honest answer to R7 at load time.
|
|
142
|
+
*
|
|
143
|
+
* R7 refuses a movement whose required outside input has no provider: no incoming hard edge, no
|
|
144
|
+
* `runtime_fills` entry, and not declared on the dispatch payload. The payload is a dispatch-time
|
|
145
|
+
* fact, so a LOADER cannot know it — and a loader that passed nothing would make every chart whose
|
|
146
|
+
* first movement declares a gig contract unloadable, which is not a defect in the chart.
|
|
147
|
+
*
|
|
148
|
+
* So the load-time answer is this: a movement with NO incoming edge is a boundary movement, seeded
|
|
149
|
+
* from outside the arrangement, and its standard's own `input_types` — the standard's declaration
|
|
150
|
+
* that these types enter from elsewhere (#177) — are what the payload is expected to carry. An
|
|
151
|
+
* INTERIOR movement gets nothing from here, so the dead slot R7 exists for (movement B needs a type
|
|
152
|
+
* and nothing upstream produces it) still fires at load.
|
|
153
|
+
*
|
|
154
|
+
* The strict check happens where the payload is a fact: `gig_dispatch` re-composes the chart with
|
|
155
|
+
* the real payload's keys, so a dispatch that does not actually carry the seed is refused there.
|
|
156
|
+
*/
|
|
157
|
+
export declare function chartEntrySeedTypes(chart: Chart, standards: ReadonlyMap<string, Standard>): string[];
|
|
158
|
+
export declare function composeChart(input: ChartComposeInput): ChartComposition;
|
|
159
|
+
/** The chart's own checkpoint: which movements completed, and what the performance has spent. */
|
|
160
|
+
export declare function chartCheckpointId(gig_id: string): string;
|
|
161
|
+
/**
|
|
162
|
+
* A movement's gig id.
|
|
163
|
+
*
|
|
164
|
+
* The degenerate chart's movement runs under the chart's own id, unchanged — same outputs file,
|
|
165
|
+
* same checkpoint, same ledger row id a single-standard dispatch always had. A real arrangement
|
|
166
|
+
* gives each movement its own id, so one movement's checkpoint, header and row cannot be another's.
|
|
167
|
+
*
|
|
168
|
+
* The spec left open whether the movements of one chart should instead SHARE a gig id, so that
|
|
169
|
+
* `OutputStore.trace` — scoped to a single gig — would walk the whole performance. That question
|
|
170
|
+
* is now ANSWERED THE OTHER WAY: the ids stay separate (a movement keeps its own checkpoint,
|
|
171
|
+
* header and row) and the STORE learned the id scheme instead. `performanceRoot` reads a
|
|
172
|
+
* performance off a movement's gig id, so `trace` walks the whole arrangement and LABELS each
|
|
173
|
+
* node with the movement it lived in. The composition is the one owner of how the id is built;
|
|
174
|
+
* the store is the one owner of how it is read back apart.
|
|
175
|
+
*/
|
|
176
|
+
export declare function movementGigId(plan: {
|
|
177
|
+
chart: Chart;
|
|
178
|
+
}, gig_id: string, movement_id: string): string;
|
|
179
|
+
/** Where a movement's own checkpoint lives. Equal to the gig id, as `runGig` expects. */
|
|
180
|
+
export declare function movementCheckpointId(plan: {
|
|
181
|
+
chart: Chart;
|
|
182
|
+
}, gig_id: string, movement_id: string): string;
|
|
183
|
+
export interface ChartMovementRun {
|
|
184
|
+
movement_id: string;
|
|
185
|
+
standard_slug: string;
|
|
186
|
+
gig_id: string;
|
|
187
|
+
/** `skipped` = restored from the chart checkpoint; it played in an earlier attempt. */
|
|
188
|
+
status: "complete" | "skipped" | "awaiting_approval" | "budget_exhausted";
|
|
189
|
+
result?: GigResult;
|
|
190
|
+
/** What this movement handed on: its sealed outputs, or the ones a resume restored. */
|
|
191
|
+
outputs: readonly OutputRecord[];
|
|
192
|
+
/** Real settled model spend for this movement. 0 when no invoker reported cost. */
|
|
193
|
+
spent_usd: number;
|
|
194
|
+
}
|
|
195
|
+
export interface ChartResult {
|
|
196
|
+
chart_slug: string;
|
|
197
|
+
chart_hash: string;
|
|
198
|
+
gig_id: string;
|
|
199
|
+
status: "complete" | "awaiting_approval" | "budget_exhausted";
|
|
200
|
+
movements: readonly ChartMovementRun[];
|
|
201
|
+
/**
|
|
202
|
+
* Present iff parked: WHOSE seat the performance is waiting on, and where.
|
|
203
|
+
*
|
|
204
|
+
* `gate_id` is present for an ARRANGEMENT-level gate (approved through `approvals[gate_id]`) and
|
|
205
|
+
* absent when a movement parked at its own within-movement human chair (`approvals[role]`). The
|
|
206
|
+
* two are different offices and the reply says which, rather than calling a chair role a gate id.
|
|
207
|
+
*/
|
|
208
|
+
awaiting?: {
|
|
209
|
+
movement_id: string;
|
|
210
|
+
chair: string;
|
|
211
|
+
gate_id?: string;
|
|
212
|
+
phase?: string;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Gate approvals that STAND for this performance — a yes is a record, not a message.
|
|
216
|
+
*
|
|
217
|
+
* Includes an approval sealed in an earlier attempt and restored here, because the fact an
|
|
218
|
+
* operator needs is "this gate is answered", and re-sealing it on every resume would put two
|
|
219
|
+
* yeses in the chain for one decision.
|
|
220
|
+
*/
|
|
221
|
+
gates_approved?: ReadonlyArray<{
|
|
222
|
+
gate_id: string;
|
|
223
|
+
chair: string;
|
|
224
|
+
approved_by: string;
|
|
225
|
+
output_id: string;
|
|
226
|
+
}>;
|
|
227
|
+
/** Cumulative real spend across every movement of this performance. */
|
|
228
|
+
spent_usd: number;
|
|
229
|
+
/** Present when the chart declares an envelope. Names the boundary a refusal happened at. */
|
|
230
|
+
budget?: {
|
|
231
|
+
total_usd: number;
|
|
232
|
+
spent_usd: number;
|
|
233
|
+
exhausted_at_movement?: string;
|
|
234
|
+
};
|
|
235
|
+
/** Present when this run resumed an earlier attempt at the same performance. */
|
|
236
|
+
resumed?: {
|
|
237
|
+
movements: string[];
|
|
238
|
+
outputs: number;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Perform the chart: walk the movements in topological order, one `runGig` each.
|
|
243
|
+
*
|
|
244
|
+
* The boundaries are where everything interesting happens, because a boundary is the last place a
|
|
245
|
+
* stop is free:
|
|
246
|
+
* - the incoming edges' carriers are gathered and handed to the sink as SEALED RECORDS (so its
|
|
247
|
+
* provenance reaches back across the boundary, rather than a payload copy that says it came
|
|
248
|
+
* from nowhere),
|
|
249
|
+
* - an approval gate parks the performance — checkpointed, drained as `awaiting_approval`,
|
|
250
|
+
* nothing hollow sealed — exactly as an in-standard human chair does,
|
|
251
|
+
* - the budget envelope is compared against real settled spend BEFORE the next movement starts,
|
|
252
|
+
* - and the movement that just finished is recorded, so a resume never re-derives it.
|
|
253
|
+
*/
|
|
254
|
+
export declare function runChart(plan: ChartPlan, chartInput: Record<string, unknown>, deps: RunDeps): Promise<ChartResult>;
|