@eir-labs/coltrane 0.20.0 → 0.22.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.
package/dist/src/cli.d.ts CHANGED
@@ -31,7 +31,7 @@ export interface CliIO {
31
31
  /** Injected for tests. Production reads stdin for `--input -`. */
32
32
  stdin?: () => string;
33
33
  }
34
- export declare const USAGE = "coltrane 0.20.0\n\n coltrane validate load the genome; exit non-zero on load errors\n coltrane dispatch <standard> run a standard\n coltrane monitor <gig-id> report a gig's progress\n coltrane logs <gig-id> per-chair logs for a gig\n coltrane abort <gig-id> stop a running gig\n coltrane trace <output-id> walk an output's provenance\n coltrane simulate <standard> cost/shape a standard without running it\n coltrane health engine + store health\n coltrane serve run the MCP server on stdio\n coltrane enqueue <standard> queue a gig on the LOCAL file queue (no store, no key)\n (env: COLTRANE_QUEUE_DIR \u2014 its absence is the whole\n difference between local and hosted)\n coltrane work claim one queued gig from the org store and run it\n coltrane work --check report whether this box's drain environment is configured\n and exit without claiming (0 ready, 1 not ready)\n (env: COLTRANE_STORE_URL, COLTRANE_STORE_ANON,\n COLTRANE_AGENT_TOKEN; results drain via\n COLTRANE_DRAIN_URL + COLTRANE_DRAIN_KEY;\n checkpoints under COLTRANE_WORKER_CHECKPOINTS,\n default ~/.coltrane/worker-checkpoints;\n exit 0 complete or parked, 1 failed, 3 queue empty)\n\nOptions\n --input <json|@file|-> dispatch payload; @file reads a file, - reads stdin\n --depth <skim|standard|deep> tighten the per-chair turn cap\n --budget <dollars> per-gig ceiling; the run stops when it is gone\n --reuse allow chair-level reuse of prior sealed outputs\n --resume <gig-id> continue a gig that died mid-pipeline\n --approve <role>=<json|@file> a human chair's verdict; repeat once per chair\n --as <name> who is approving; sealed as the verdict's author\n --wait block until the run finishes\n --follow poll until the gig reaches a terminal state\n --direction <upstream|downstream|both> for trace\n --json print the raw result to stdout\n --genome <path> genome root (default: $COLTRANE_GENOME or cwd)\n --help, --version\n\nA dispatch that reaches a chair a HUMAN holds parks: it names the waiting chair and exits 0,\nbecause a gig waiting on a person is not a failed gig. Approve it on the resume \u2014\n\n coltrane dispatch <standard> --resume <gig> \\\n --approve approve=@verdict.json --as eugene\n\n--input is NOT required on an approve-only resume: when every remaining chair is human the\ncheckpoint's recorded payload stands and the omission inherits it. If you DO pass --input it is\nchecked against the checkpoint, and a disagreement still refuses the resume.\n";
34
+ export declare const USAGE = "coltrane 0.22.0\n\n coltrane validate load the genome; exit non-zero on load errors\n coltrane dispatch <standard> run a standard\n coltrane monitor <gig-id> report a gig's progress\n coltrane logs <gig-id> per-chair logs for a gig\n coltrane abort <gig-id> stop a running gig\n coltrane trace <output-id> walk an output's provenance\n coltrane simulate <standard> cost/shape a standard without running it\n coltrane health engine + store health\n coltrane serve run the MCP server on stdio\n coltrane enqueue <standard> queue a gig on the LOCAL file queue (no store, no key)\n (env: COLTRANE_QUEUE_DIR \u2014 its absence is the whole\n difference between local and hosted)\n coltrane work claim one queued gig from the org store and run it\n coltrane work --check report whether this box's drain environment is configured\n and exit without claiming (0 ready, 1 not ready)\n (env: COLTRANE_STORE_URL, COLTRANE_STORE_ANON,\n COLTRANE_AGENT_TOKEN; results drain via\n COLTRANE_DRAIN_URL + COLTRANE_DRAIN_KEY;\n checkpoints under COLTRANE_WORKER_CHECKPOINTS,\n default ~/.coltrane/worker-checkpoints;\n exit 0 complete or parked, 1 failed, 3 queue empty)\n\nOptions\n --input <json|@file|-> dispatch payload; @file reads a file, - reads stdin\n --depth <skim|standard|deep> tighten the per-chair turn cap\n --budget <dollars> per-gig ceiling; the run stops when it is gone\n --reuse allow chair-level reuse of prior sealed outputs\n --resume <gig-id> continue a gig that died mid-pipeline\n --approve <role>=<json|@file> a human chair's verdict; repeat once per chair\n --as <name> who is approving; sealed as the verdict's author\n --wait block until the run finishes\n --follow poll until the gig reaches a terminal state\n --direction <upstream|downstream|both> for trace\n --json print the raw result to stdout\n --genome <path> genome root (default: $COLTRANE_GENOME or cwd)\n --help, --version\n\nA dispatch that reaches a chair a HUMAN holds parks: it names the waiting chair and exits 0,\nbecause a gig waiting on a person is not a failed gig. Approve it on the resume \u2014\n\n coltrane dispatch <standard> --resume <gig> \\\n --approve approve=@verdict.json --as eugene\n\n--input is NOT required on an approve-only resume: when every remaining chair is human the\ncheckpoint's recorded payload stands and the omission inherits it. If you DO pass --input it is\nchecked against the checkpoint, and a disagreement still refuses the resume.\n";
35
35
  interface Parsed {
36
36
  cmd: string | undefined;
37
37
  positional: string[];
@@ -0,0 +1,67 @@
1
+ /**
2
+ * THE CHAIR-PLACEMENT SEAM — the engine defines the question; a deployment answers it.
3
+ *
4
+ * WHY THIS SHAPE. The Envoy orientation (2026-08-21) states it directly: "Coltrane (OSS) exposes the
5
+ * chair-placement seam; Envoy (deployment) plugs into it… the same shape as the venue-realizer seam:
6
+ * an interface the engine defines and enforces, an implementation the deployment supplies." So the
7
+ * resolution — who may sit here, and with what history — deliberately does NOT live in this repo.
8
+ * The engine owns the MOMENT and the REFUSAL; the resolver owns the answer.
9
+ *
10
+ * WHAT IT UNBLOCKS. Three things are loaded into the genome today and read by nothing, because there
11
+ * has been no moment at which anything is asked:
12
+ * · an institutional chair's `supplies` — the quartet writes a house-style nothing consumes
13
+ * · `technique_evidence` — "why this player in this chair", 0 readers
14
+ * · `contract_caps` — the chair-authorisation narrowing rule, 0 readers
15
+ * Each is an answer waiting for a question. This is the question.
16
+ *
17
+ * OPTIONAL BY ABSENCE, CLOSED BY REFUSAL. A deployment that supplies no resolver runs exactly as
18
+ * before — every existing standard and gig is untouched, which is what makes this safe to land ahead
19
+ * of any consumer. A deployment that supplies one can REFUSE a seating, and a refusal stops the
20
+ * chair. A refusal that were logged and ignored would make the seam decoration.
21
+ */
22
+ /** Who is being placed, where, and under what. Everything the engine knows at the moment a chair is
23
+ * taken — deliberately no more: what else bears on the decision is the resolver's business. */
24
+ export interface PlacementRequest {
25
+ /** The agent being seated. */
26
+ readonly agent_slug: string;
27
+ /** The chair's role within the standard. */
28
+ readonly role: string;
29
+ /** The standard the chair belongs to. */
30
+ readonly standard_slug: string;
31
+ /** The phase the chair runs in. */
32
+ readonly phase: string;
33
+ /** The gig this placement is for. */
34
+ readonly gig_id: string;
35
+ /** What the chair's contract says this seat consumes and produces — enough for a resolver to ask
36
+ * "can it do what this chair assigns" without reaching back into the genome itself. */
37
+ readonly input_contract: readonly string[];
38
+ readonly output_contract: readonly string[];
39
+ }
40
+ /**
41
+ * The answer. `admitted: false` REFUSES the seating and stops the chair.
42
+ *
43
+ * `hydration` is the other half of placement — Envoy's "carry the chain into the chair". Whatever the
44
+ * resolver returns reaches the invocation as `ctx.hydration`, on exactly the wire an institutional
45
+ * chair's `supplies` would use. A resolver that admits without hydrating is valid; the field is
46
+ * optional because validation and hydration are separable and a deployment may want only the first.
47
+ */
48
+ export interface PlacementDecision {
49
+ readonly admitted: boolean;
50
+ /** Why refused. Carried into the error so an operator learns the reason, not merely that it failed. */
51
+ readonly reason?: string | undefined;
52
+ /** Slot name → value, delivered to the seated agent. */
53
+ readonly hydration?: Record<string, unknown> | undefined;
54
+ }
55
+ /** What a deployment supplies. One method: the engine asks at the moment a chair is taken. */
56
+ export interface PlacementResolver {
57
+ place(request: PlacementRequest): Promise<PlacementDecision>;
58
+ }
59
+ /**
60
+ * A refused seating. Distinct from every other chair failure because the chair never ran — nothing
61
+ * was spent, and the reason belongs to the institution rather than to the work.
62
+ */
63
+ export declare class PlacementRefused extends Error {
64
+ readonly agent_slug: string;
65
+ readonly role: string;
66
+ constructor(agent_slug: string, role: string, reason: string);
67
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * THE CHAIR-PLACEMENT SEAM — the engine defines the question; a deployment answers it.
3
+ *
4
+ * WHY THIS SHAPE. The Envoy orientation (2026-08-21) states it directly: "Coltrane (OSS) exposes the
5
+ * chair-placement seam; Envoy (deployment) plugs into it… the same shape as the venue-realizer seam:
6
+ * an interface the engine defines and enforces, an implementation the deployment supplies." So the
7
+ * resolution — who may sit here, and with what history — deliberately does NOT live in this repo.
8
+ * The engine owns the MOMENT and the REFUSAL; the resolver owns the answer.
9
+ *
10
+ * WHAT IT UNBLOCKS. Three things are loaded into the genome today and read by nothing, because there
11
+ * has been no moment at which anything is asked:
12
+ * · an institutional chair's `supplies` — the quartet writes a house-style nothing consumes
13
+ * · `technique_evidence` — "why this player in this chair", 0 readers
14
+ * · `contract_caps` — the chair-authorisation narrowing rule, 0 readers
15
+ * Each is an answer waiting for a question. This is the question.
16
+ *
17
+ * OPTIONAL BY ABSENCE, CLOSED BY REFUSAL. A deployment that supplies no resolver runs exactly as
18
+ * before — every existing standard and gig is untouched, which is what makes this safe to land ahead
19
+ * of any consumer. A deployment that supplies one can REFUSE a seating, and a refusal stops the
20
+ * chair. A refusal that were logged and ignored would make the seam decoration.
21
+ */
22
+ /**
23
+ * A refused seating. Distinct from every other chair failure because the chair never ran — nothing
24
+ * was spent, and the reason belongs to the institution rather than to the work.
25
+ */
26
+ export class PlacementRefused extends Error {
27
+ agent_slug;
28
+ role;
29
+ constructor(agent_slug, role, reason) {
30
+ super(`placement refused — agent "${agent_slug}" may not take chair "${role}": ${reason}`);
31
+ this.name = "PlacementRefused";
32
+ this.agent_slug = agent_slug;
33
+ this.role = role;
34
+ }
35
+ }
36
+ //# sourceMappingURL=placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement.js","sourceRoot":"","sources":["../../src/placement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0CH;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,UAAU,CAAS;IACnB,IAAI,CAAS;IACtB,YAAY,UAAkB,EAAE,IAAY,EAAE,MAAc;QAC1D,KAAK,CAAC,8BAA8B,UAAU,yBAAyB,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import type { LoadedInstitution } from "./institution_loader.js";
2
+ import type { PlacementResolver } from "./placement.js";
3
+ /**
4
+ * A PlacementResolver backed by the genome's own `institutions/*.json`.
5
+ *
6
+ * WHY THIS IS IN OSS, given the seam exists for a deployment to fill. The precedent is this repo's:
7
+ * the venue seam defines `VenueRealizer` AND ships `dockerComposeRealizer()`; `GenomeStore` has three
8
+ * backings behind one port. This is the file backing of the placement port — the parallel to Envoy's
9
+ * store-backed resolver, not a competitor to it. Envoy answers from `coltrane_chair_assignment`; this
10
+ * answers from the files a clone already has.
11
+ *
12
+ * WHAT IT CLOSES. `institutions/quartet.json`'s structure-builder chair supplies a real `house-style`,
13
+ * and bill's carried `structure-conformance` skill tells its agent to "read the constraints supplied
14
+ * in the `house-style` slot". Nothing ever delivered it, because until the placement seam there was
15
+ * no moment at which anything was asked. This is the first thing to answer.
16
+ *
17
+ * THE SEMANTIC, and it is the whole design decision:
18
+ *
19
+ * SILENCE ADMITS — an institution that says nothing about an agent does not refuse it.
20
+ * CONTRADICTION REFUSES — an institution that seats a DIFFERENT agent in that role does.
21
+ *
22
+ * Refusing every unwitnessed seating would break the shipped genome: no standard outside the quartet
23
+ * carries assignments at all. Absence of a record is not a finding — it is a genome that has not been
24
+ * populated yet, and treating it as a refusal would make the feature unusable on the day it landed.
25
+ * A contradiction is different: the institution HAS spoken about this chair and named someone else.
26
+ */
27
+ export declare function institutionPlacementResolver(institutions: ReadonlyMap<string, LoadedInstitution>): PlacementResolver;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * A PlacementResolver backed by the genome's own `institutions/*.json`.
3
+ *
4
+ * WHY THIS IS IN OSS, given the seam exists for a deployment to fill. The precedent is this repo's:
5
+ * the venue seam defines `VenueRealizer` AND ships `dockerComposeRealizer()`; `GenomeStore` has three
6
+ * backings behind one port. This is the file backing of the placement port — the parallel to Envoy's
7
+ * store-backed resolver, not a competitor to it. Envoy answers from `coltrane_chair_assignment`; this
8
+ * answers from the files a clone already has.
9
+ *
10
+ * WHAT IT CLOSES. `institutions/quartet.json`'s structure-builder chair supplies a real `house-style`,
11
+ * and bill's carried `structure-conformance` skill tells its agent to "read the constraints supplied
12
+ * in the `house-style` slot". Nothing ever delivered it, because until the placement seam there was
13
+ * no moment at which anything was asked. This is the first thing to answer.
14
+ *
15
+ * THE SEMANTIC, and it is the whole design decision:
16
+ *
17
+ * SILENCE ADMITS — an institution that says nothing about an agent does not refuse it.
18
+ * CONTRADICTION REFUSES — an institution that seats a DIFFERENT agent in that role does.
19
+ *
20
+ * Refusing every unwitnessed seating would break the shipped genome: no standard outside the quartet
21
+ * carries assignments at all. Absence of a record is not a finding — it is a genome that has not been
22
+ * populated yet, and treating it as a refusal would make the feature unusable on the day it landed.
23
+ * A contradiction is different: the institution HAS spoken about this chair and named someone else.
24
+ */
25
+ export function institutionPlacementResolver(institutions) {
26
+ return {
27
+ place: async (request) => resolve(institutions, request),
28
+ };
29
+ }
30
+ function resolve(institutions, request) {
31
+ for (const inst of institutions.values()) {
32
+ // The document is typed by the loader (InstitutionDocumentSections); read it as such rather than
33
+ // casting to a bag of unknowns, so a section that changes shape breaks here at compile time.
34
+ const chairs = inst.document.chairs ?? [];
35
+ const seats = inst.document.assignments ?? [];
36
+ // The chair this role names, in this institution. A role no chair carries is silence.
37
+ const chair = chairs.find((c) => c.role === request.role);
38
+ if (!chair)
39
+ continue;
40
+ // Who the institution seats there. An unseated chair is also silence — the office exists and
41
+ // nobody has been placed in it, which is not a statement about the agent being placed now.
42
+ const seat = seats.find((s) => s.chair_id === chair.id);
43
+ if (!seat)
44
+ continue;
45
+ if (seat.agent_slug !== request.agent_slug) {
46
+ return {
47
+ admitted: false,
48
+ reason: `institution "${inst.slug}" seats "${seat.agent_slug}" in chair "${request.role}", ` +
49
+ `not "${request.agent_slug}"`,
50
+ };
51
+ }
52
+ // Seated, and it is this agent. Carry the chair's supplies — the institution's data entering at
53
+ // the seat, which is the wire this whole surface was waiting for.
54
+ const supplies = chair.supplies && Object.keys(chair.supplies).length > 0
55
+ ? { ...chair.supplies }
56
+ : undefined;
57
+ return supplies ? { admitted: true, hydration: supplies } : { admitted: true };
58
+ }
59
+ // No institution had anything to say about this role. Silence admits.
60
+ return { admitted: true };
61
+ }
62
+ //# sourceMappingURL=placement_institutions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement_institutions.js","sourceRoot":"","sources":["../../src/placement_institutions.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,4BAA4B,CAC1C,YAAoD;IAEpD,OAAO;QACL,KAAK,EAAE,KAAK,EAAE,OAAyB,EAA8B,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;KACvG,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CACd,YAAoD,EACpD,OAAyB;IAEzB,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,iGAAiG;QACjG,6FAA6F;QAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC;QAE9C,sFAAsF;QACtF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,6FAA6F;QAC7F,2FAA2F;QAC3F,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;YAC3C,OAAO;gBACL,QAAQ,EAAE,KAAK;gBACf,MAAM,EACJ,gBAAgB,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,UAAU,eAAe,OAAO,CAAC,IAAI,KAAK;oBACpF,QAAQ,OAAO,CAAC,UAAU,GAAG;aAChC,CAAC;QACJ,CAAC;QAED,gGAAgG;QAChG,kEAAkE;QAClE,MAAM,QAAQ,GACZ,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;YACtD,CAAC,CAAC,EAAE,GAAI,KAAK,CAAC,QAAoC,EAAE;YACpD,CAAC,CAAC,SAAS,CAAC;QAChB,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjF,CAAC;IACD,sEAAsE;IACtE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
@@ -98,7 +98,7 @@ export declare function resolveWorkingRepo(claim: {
98
98
  * seed_outputs, chart, checkpoints) are NOT here: each call site spreads its own onto this result. The
99
99
  * assembler unifies exactly the wires that diverged and no more.
100
100
  */
101
- export type AssembleRunDepsArgs = Pick<RunDeps, "outputs" | "ledger" | "invoke" | "model_version" | "skills" | "skill_dirs" | "evals" | "budget" | "toolProviders" | "venue" | "venues" | "venueRealizer"> & {
101
+ export type AssembleRunDepsArgs = Pick<RunDeps, "outputs" | "ledger" | "invoke" | "model_version" | "skills" | "skill_dirs" | "evals" | "budget" | "toolProviders" | "venue" | "venues" | "venueRealizer" | "placementResolver"> & {
102
102
  /**
103
103
  * The enforcement environment, supplied per door: {} on the drain, the bootstrap map on the server
104
104
  * (which is itself `Record | undefined`). REQUIRED — the property may hold undefined but may never be
@@ -120,6 +120,7 @@ export function assembleRunDeps(args) {
120
120
  ...(args.venue ? { venue: args.venue } : {}),
121
121
  ...(args.venues ? { venues: args.venues } : {}),
122
122
  ...(args.venueRealizer ? { venueRealizer: args.venueRealizer } : {}),
123
+ ...(args.placementResolver ? { placementResolver: args.placementResolver } : {}),
123
124
  ...(args.repoUrl ? { repoUrl: args.repoUrl } : {}),
124
125
  };
125
126
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run_deps.js","sourceRoot":"","sources":["../../src/run_deps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run_deps.js","sourceRoot":"","sources":["../../src/run_deps.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import { type CheckpointStore, type ReuseStore, type PriorBudgetState } from "./
8
8
  import type { OutputStore, OutputRecord } from "./outputs.js";
9
9
  import { type GigConformanceResult } from "./gig_conformance.js";
10
10
  import { type Ledger, type GigUsage } from "./ledger.js";
11
+ import { type PlacementResolver } from "./placement.js";
11
12
  import type { Depth } from "./pricing.js";
12
13
  import type { SkillRecord, EvalRecord } from "./loader.js";
13
14
  export interface AgentInvocationContext {
@@ -341,6 +342,17 @@ export interface RunDeps {
341
342
  * and tests supply the daemon-free substitute (a realizer with an injected `run` seam).
342
343
  */
343
344
  venueRealizer?: VenueRealizer | undefined;
345
+ /**
346
+ * THE CHAIR-PLACEMENT SEAM. Asked at the moment a chair is taken: may this agent be here, can it do
347
+ * what this chair assigns, and with what history. Absent → every placement is admitted and the run
348
+ * is byte-identical to before, which is what makes the seam safe to ship ahead of any consumer.
349
+ *
350
+ * The engine owns the MOMENT and the REFUSAL; the deployment owns the answer. Per the Envoy
351
+ * orientation: "Coltrane (OSS) exposes the chair-placement seam; Envoy (deployment) plugs into it
352
+ * … the same shape as the venue-realizer seam." So institutions, assignments and technique_evidence
353
+ * are read by the RESOLVER, not by this engine — which is why none of them appear here.
354
+ */
355
+ placementResolver?: PlacementResolver | undefined;
344
356
  /**
345
357
  * How the substrate realizer binds credentials into the room. Passed as the required positional
346
358
  * `credentialResolver` argument to `venueRealizer.realize()`. Absent → `async () => ({})`, an empty
@@ -25,6 +25,7 @@ import { producersSha, reuseCacheKey, checkReuseEntry, runIdentityMismatch, chec
25
25
  import { checkGigConformance } from "./gig_conformance.js";
26
26
  import { drainGigHeader } from "./output_mirror.js";
27
27
  import { LEDGER_SCHEMA_VERSION } from "./ledger.js";
28
+ import { PlacementRefused } from "./placement.js";
28
29
  import { COLTRANE_VERSION } from "./version.js";
29
30
  /**
30
31
  * #236 — settled spend used to be discarded on every failed gig: `usage` was written only on
@@ -1743,12 +1744,47 @@ export async function runGig(standard, gigInput, deps) {
1743
1744
  reserveSettled = true;
1744
1745
  };
1745
1746
  try {
1747
+ // ── THE PLACEMENT SEAM ────────────────────────────────────────────────────────────────────
1748
+ // Asked BEFORE the chair is invoked, so a refused seating costs nothing. The engine owns the
1749
+ // moment and the refusal; the deployment owns the answer (Envoy). Absent resolver → admitted,
1750
+ // and the run is byte-identical to before.
1751
+ //
1752
+ // A resolver that THROWS refuses. Absent must mean DECLINE: treating an unreachable resolver as
1753
+ // admission would make an outage look like an open door, which is the failure direction this
1754
+ // engine refuses everywhere else.
1755
+ let placedHydration;
1756
+ if (deps.placementResolver) {
1757
+ let decision;
1758
+ try {
1759
+ decision = await deps.placementResolver.place({
1760
+ agent_slug: agent.slug,
1761
+ role: chair.role,
1762
+ standard_slug: standard.slug,
1763
+ phase: phaseName,
1764
+ gig_id,
1765
+ input_contract: [...(chair.input_contract ?? [])],
1766
+ output_contract: [...(chair.output_contract ?? [])],
1767
+ });
1768
+ }
1769
+ catch (e) {
1770
+ throw new PlacementRefused(agent.slug, chair.role, `the placement resolver failed, so no admission was given: ${e instanceof Error ? e.message : String(e)}`);
1771
+ }
1772
+ if (!decision.admitted) {
1773
+ throw new PlacementRefused(agent.slug, chair.role, decision.reason ?? "no reason given");
1774
+ }
1775
+ placedHydration = decision.hydration;
1776
+ }
1746
1777
  data = await deps.invoke({
1747
1778
  agent, phase: phaseName, gig_id, inputs, gig_input: gigInput, skills,
1748
1779
  missing_skills: p.missing_skills, // #241 — what did NOT resolve, so the prompt can't assert it
1749
1780
  // THE SEAT IS WHERE THE INSTITUTION'S DATA ENTERS. Validated at compose time (the dead-slot
1750
1781
  // refusal) and, until now, dropped on the floor immediately afterwards.
1751
- ...(p.chair.supplies ? { hydration: p.chair.supplies } : {}),
1782
+ // The seat's own supplies, then whatever the placement resolver carried in — Envoy's
1783
+ // "carry the chain into the chair". The resolver wins on a key collision: it answers with
1784
+ // the institution's live record, where the standard's chair carries an authored default.
1785
+ ...(p.chair.supplies || placedHydration
1786
+ ? { hydration: { ...(p.chair.supplies ?? {}), ...(placedHydration ?? {}) } }
1787
+ : {}),
1752
1788
  output_types: output_specs.map((s) => s.domain_type), // #174 — the chair's promised subset
1753
1789
  // #250 level 2 + #237 — the cancellation signal and the run's depth reach the invocation
1754
1790
  // itself, so an invoker can kill its child and shape what it asks the model for.