@eir-labs/coltrane 0.10.0 → 0.12.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/agents/bandleader.json +54 -0
- package/agents/bill.json +4 -2
- package/agents/change-verifier.json +2 -1
- package/agents/code-implementer.json +7 -4
- package/agents/john.json +5 -3
- package/agents/lineage-scout-external.json +19 -6
- package/agents/lineage-scribe.json +20 -9
- package/agents/lineage-weaver.json +26 -11
- package/agents/miles.json +2 -1
- package/agents/players/bandleader.md +70 -0
- package/agents/pr-publisher.json +4 -2
- package/agents/red-spec-drafter.json +12 -6
- package/agents/room-prober.json +29 -0
- package/agents/source-walker.json +1 -1
- package/charts/room-probe-chart-v1.json +14 -0
- package/charts/worker-contract-docker-v2.json +135 -0
- package/charts/worker-contract-v3.json +206 -0
- package/dist/src/boundary_check.d.ts +18 -0
- package/dist/src/boundary_check.js +70 -0
- package/dist/src/boundary_check.js.map +1 -0
- package/dist/src/boundary_scan.d.ts +62 -0
- package/dist/src/boundary_scan.js +93 -0
- package/dist/src/boundary_scan.js.map +1 -0
- package/dist/src/chart.js +34 -1
- package/dist/src/chart.js.map +1 -1
- package/dist/src/claude_invoker.d.ts +2 -13
- package/dist/src/claude_invoker.js +242 -18
- package/dist/src/claude_invoker.js.map +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +115 -27
- package/dist/src/cli.js.map +1 -1
- package/dist/src/drain_preflight.d.ts +33 -0
- package/dist/src/drain_preflight.js +97 -0
- package/dist/src/drain_preflight.js.map +1 -0
- package/dist/src/genome_schema.d.ts +390 -9
- package/dist/src/genome_schema.js +163 -8
- package/dist/src/genome_schema.js.map +1 -1
- package/dist/src/genome_store.js +9 -0
- package/dist/src/genome_store.js.map +1 -1
- package/dist/src/genome_writer.d.ts +1 -1
- package/dist/src/genome_writer.js +10 -2
- package/dist/src/genome_writer.js.map +1 -1
- package/dist/src/gig_conformance.d.ts +66 -0
- package/dist/src/gig_conformance.js +153 -0
- package/dist/src/gig_conformance.js.map +1 -0
- package/dist/src/gig_tracker.js +8 -0
- package/dist/src/gig_tracker.js.map +1 -1
- package/dist/src/grounding.d.ts +44 -0
- package/dist/src/grounding.js +127 -0
- package/dist/src/grounding.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/institution_loader.d.ts +29 -5
- package/dist/src/institution_loader.js +67 -6
- package/dist/src/institution_loader.js.map +1 -1
- package/dist/src/lineage_adoption.d.ts +82 -0
- package/dist/src/lineage_adoption.js +82 -0
- package/dist/src/lineage_adoption.js.map +1 -0
- package/dist/src/lineage_persist.d.ts +34 -0
- package/dist/src/lineage_persist.js +60 -0
- package/dist/src/lineage_persist.js.map +1 -0
- package/dist/src/loader.d.ts +13 -0
- package/dist/src/loader.js +43 -2
- package/dist/src/loader.js.map +1 -1
- package/dist/src/local_queue.d.ts +105 -0
- package/dist/src/local_queue.js +380 -0
- package/dist/src/local_queue.js.map +1 -0
- package/dist/src/mcp.js +37 -4
- package/dist/src/mcp.js.map +1 -1
- package/dist/src/org_hire.d.ts +23 -0
- package/dist/src/org_hire.js +42 -0
- package/dist/src/org_hire.js.map +1 -0
- package/dist/src/outputs.d.ts +17 -0
- package/dist/src/outputs.js +86 -1
- package/dist/src/outputs.js.map +1 -1
- package/dist/src/player_to_claude_code.js +26 -2
- package/dist/src/player_to_claude_code.js.map +1 -1
- package/dist/src/registry.d.ts +3 -1
- package/dist/src/registry.js +43 -3
- package/dist/src/registry.js.map +1 -1
- package/dist/src/repo_index.d.ts +58 -0
- package/dist/src/repo_index.js +232 -0
- package/dist/src/repo_index.js.map +1 -0
- package/dist/src/residency.d.ts +149 -0
- package/dist/src/residency.js +283 -0
- package/dist/src/residency.js.map +1 -0
- package/dist/src/reuse.d.ts +44 -4
- package/dist/src/reuse.js +0 -0
- package/dist/src/reuse.js.map +1 -1
- package/dist/src/runtime.d.ts +82 -0
- package/dist/src/runtime.js +254 -25
- package/dist/src/runtime.js.map +1 -1
- package/dist/src/server.d.ts +37 -0
- package/dist/src/server.js +422 -11
- package/dist/src/server.js.map +1 -1
- package/dist/src/server_relay.d.ts +40 -2
- package/dist/src/server_relay.js +186 -19
- package/dist/src/server_relay.js.map +1 -1
- package/dist/src/tool_providers.d.ts +27 -0
- package/dist/src/tool_providers.js +48 -0
- package/dist/src/tool_providers.js.map +1 -1
- package/dist/src/venue_credential.d.ts +41 -0
- package/dist/src/venue_credential.js +57 -0
- package/dist/src/venue_credential.js.map +1 -0
- package/dist/src/venue_realize.d.ts +23 -0
- package/dist/src/venue_realize.js +43 -3
- package/dist/src/venue_realize.js.map +1 -1
- package/dist/src/venue_realizer.d.ts +224 -0
- package/dist/src/venue_realizer.js +889 -0
- package/dist/src/venue_realizer.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 +57 -0
- package/dist/src/worker.js +155 -24
- package/dist/src/worker.js.map +1 -1
- package/dist/src/worker_env.d.ts +79 -0
- package/dist/src/worker_env.js +322 -0
- package/dist/src/worker_env.js.map +1 -0
- package/dist/src/workspace.d.ts +12 -1
- package/dist/src/workspace.js +10 -3
- package/dist/src/workspace.js.map +1 -1
- package/domain_types/change-context.json +59 -13
- package/domain_types/lineage-adoption-target.json +22 -0
- package/domain_types/lineage-map.json +7 -2
- package/domain_types/lineage-record.json +55 -5
- package/domain_types/prior-art-hit.json +16 -1
- package/domain_types/red-spec.json +5 -3
- package/domain_types/woodshed-record.json +149 -0
- package/evals/gist-present.json +7 -0
- package/institutions/coltrane.json +178 -6
- package/package.json +6 -3
- package/skills/non-vacuity-probe/fixtures/fixture-001.json +17 -0
- package/skills/non-vacuity-probe/meta.json +12 -0
- package/skills/non-vacuity-probe/skill.md +27 -0
- package/skills/non-vacuity-probe/skill.mjs +81 -0
- package/standards/lineage-adopt-v0.json +37 -0
- package/standards/room-probe-v1.json +28 -0
- package/standards/software-change-pr-v1.json +15 -15
- package/standards/software-change-red-first-v0.json +183 -0
- package/standards/spec-review-and-sequence-v0.json +112 -0
- package/standards/studio-session-v0.json +101 -0
- package/tours/coltrane.json +72 -0
- package/venues/engine-room-v1.json +32 -0
|
@@ -35,6 +35,43 @@ const refuse = (code, detail) => ({
|
|
|
35
35
|
tornDown: () => true,
|
|
36
36
|
teardown: () => { },
|
|
37
37
|
});
|
|
38
|
+
/**
|
|
39
|
+
* The env keys a seat may carry from the ambient environment — the minimum a process needs to
|
|
40
|
+
* EXECUTE: PATH so the OS can locate its binary, HOME so the binary can resolve its own config. An
|
|
41
|
+
* explicit ALLOWLIST, not a deny-list: a key absent from this list never reaches the seat, so a
|
|
42
|
+
* credential added to the container later is excluded by default rather than by anyone remembering
|
|
43
|
+
* to strip it. This is the deny-by-default posture held unconditionally — it does not depend on the
|
|
44
|
+
* completeness of any strip-list (`withoutBoxCredentials`'s `BOX_CREDENTIAL_ENV` is a floor for the
|
|
45
|
+
* paths that never reach here, not the control).
|
|
46
|
+
*
|
|
47
|
+
* Why it is not `[]`: the seat env was `{}` (deny EVERYTHING), which is airtight but unspawnable —
|
|
48
|
+
* a `claude -p` child with no PATH cannot find its binary and dies with `spawn claude ENOENT`
|
|
49
|
+
* (measured, gig 87cffa2c), so no venue-confined seat ever ran. `['PATH','HOME']` is the
|
|
50
|
+
* minimum-viable widening: enough to start, no credential material.
|
|
51
|
+
*
|
|
52
|
+
* Why USER is admitted: on a macOS host with no `~/.claude/.credentials.json`, Claude auth is
|
|
53
|
+
* keychain-backed (a `Claude Code-credentials` keychain entry), and the keychain lookup needs USER
|
|
54
|
+
* to resolve the account. Measured: `claude -p` under {PATH,HOME} exits 1 with 'Not logged in ·
|
|
55
|
+
* Please run /login'; under {PATH,HOME,USER} it exits 0 and reaches the MCP server (gig 4506b567).
|
|
56
|
+
* On a Linux drain, credentials are file-based under HOME, so PATH+HOME already suffices and this
|
|
57
|
+
* key is inert. USER is a USERNAME, not a credential — admitting it carries no secret material, so
|
|
58
|
+
* the deny-by-default posture is unweakened; the allowlist grows by exactly one non-secret key.
|
|
59
|
+
*/
|
|
60
|
+
export const SEAT_ENV_ALLOWLIST = ["PATH", "HOME", "USER"];
|
|
61
|
+
/**
|
|
62
|
+
* Build a seat's env as the allowlisted subset of the ambient environment. Only keys in
|
|
63
|
+
* `SEAT_ENV_ALLOWLIST` that are present with a defined value are carried; every other key — every
|
|
64
|
+
* credential, every undeclared ambient var — is omitted. Never inherits `ambientEnv` wholesale.
|
|
65
|
+
*/
|
|
66
|
+
function seatEnv(ambientEnv) {
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const key of SEAT_ENV_ALLOWLIST) {
|
|
69
|
+
const value = ambientEnv[key];
|
|
70
|
+
if (value !== undefined)
|
|
71
|
+
out[key] = value;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
38
75
|
/**
|
|
39
76
|
* Realize a Venue contract into an enforced, observable performance space.
|
|
40
77
|
*
|
|
@@ -86,9 +123,12 @@ export function realize(venue, opts) {
|
|
|
86
123
|
if (grants.length > 0 && effective_tools.length === 0) {
|
|
87
124
|
return refuse("ceiling-empty", `agent "${seat.agent.slug}" grants [${grants.join(", ")}] but none lie within venue "${venue.slug}" equipment — the room narrows it to nothing`);
|
|
88
125
|
}
|
|
89
|
-
// env is
|
|
90
|
-
//
|
|
91
|
-
|
|
126
|
+
// env is the ALLOWLISTED subset of the ambient environment (SEAT_ENV_ALLOWLIST): the minimum a
|
|
127
|
+
// process needs to EXECUTE, and nothing else. `env: {}` was the stricter posture but it is
|
|
128
|
+
// UNSPAWNABLE — a child with no PATH dies with `spawn claude ENOENT` (measured, gig 87cffa2c),
|
|
129
|
+
// so no venue-confined seat ever started. Every credential and undeclared ambient var stays out
|
|
130
|
+
// by default; this widening only admits PATH/HOME.
|
|
131
|
+
seats.push({ agent_slug: seat.agent.slug, effective_tools, env: seatEnv(opts.ambientEnv) });
|
|
92
132
|
}
|
|
93
133
|
// The room is sound. Build the observable realization with per-call isolation and idempotent
|
|
94
134
|
// teardown. `torn` is closed over this call alone, so tearing one gig's room down cannot touch
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"venue_realize.js","sourceRoot":"","sources":["../../src/venue_realize.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"venue_realize.js","sourceRoot":"","sources":["../../src/venue_realize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { DEVICE_CLASSES } from "./genome_schema.js";
|
|
2
|
+
import { prepareWorkspace } from "./workspace.js";
|
|
3
|
+
/** The workspace preparer the room populates its tree through. It IS the drain's `prepareWorkspace`
|
|
4
|
+
* (src/workspace.ts) — one mechanism, not two — and defaults to exactly that. Injectable ONLY so a
|
|
5
|
+
* law can observe the routing without a live git endpoint, the same seam shape `run` already uses for
|
|
6
|
+
* docker; the default is the real shared function, so production population and drain population are
|
|
7
|
+
* the identical clone path. */
|
|
8
|
+
export type WorkspacePreparer = typeof prepareWorkspace;
|
|
9
|
+
export { DEVICE_CLASSES };
|
|
10
|
+
/** Credentials reach the room ONLY through here: bound at realization time from `credential_names`,
|
|
11
|
+
* a subset of the venue's `credential_surface`. Injected the way the engine already injects one. */
|
|
12
|
+
export type CredentialResolver = (names: readonly string[]) => Promise<Record<string, string>>;
|
|
13
|
+
/** How the containerized realizer reaches `docker`. Real by default; see dockerComposeRealizer. */
|
|
14
|
+
export type ComposeRunner = (args: readonly string[], timeoutMs: number) => void;
|
|
15
|
+
/** The properties a realizer may CLAIM — and may only claim if it can actually keep them. */
|
|
16
|
+
export type VenueGuarantee = "withholds_capabilities" | "isolated_filesystem" | "network_policy_doors" | "reproducible_tool_surface" | "per_chair_isolation";
|
|
17
|
+
/** One thing a realizer created, LABELLED with both the gig it belongs to and the instance that made
|
|
18
|
+
* it — an unlabelled artifact is indistinguishable from something a human made on purpose, so
|
|
19
|
+
* nothing may safely collect it. */
|
|
20
|
+
export interface RealizedArtifact {
|
|
21
|
+
kind: string;
|
|
22
|
+
id: string;
|
|
23
|
+
labels: {
|
|
24
|
+
gig_id: string;
|
|
25
|
+
instance: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** A ceiling on what survives outside the per-gig lifecycle. The point is that a bound EXISTS. */
|
|
29
|
+
export interface RetentionPolicy {
|
|
30
|
+
max_cached_build_artifacts: number;
|
|
31
|
+
max_unreferenced_environments: number;
|
|
32
|
+
cadence: string;
|
|
33
|
+
}
|
|
34
|
+
/** WHERE a room is stood up. Absent endpoint = the worker's own machine. The device map lives here,
|
|
35
|
+
* not in the contract: which nodes `serial` means, and which group owns them, are the machine's
|
|
36
|
+
* facts rather than the room's. */
|
|
37
|
+
export interface RealizationHost {
|
|
38
|
+
endpoint?: string;
|
|
39
|
+
architecture: string;
|
|
40
|
+
devices: Readonly<Record<string, {
|
|
41
|
+
nodes: readonly string[];
|
|
42
|
+
group: string;
|
|
43
|
+
}>>;
|
|
44
|
+
/** Per gig, against a live lease — never held at boot. See src/workspace.ts:60-89. */
|
|
45
|
+
credential?: (args: {
|
|
46
|
+
gigId: string;
|
|
47
|
+
}) => Promise<string>;
|
|
48
|
+
}
|
|
49
|
+
export interface RealizationHandle {
|
|
50
|
+
state: string;
|
|
51
|
+
mcpServerConfigs: Readonly<Record<string, unknown>>;
|
|
52
|
+
configPath: string;
|
|
53
|
+
artifacts: readonly RealizedArtifact[];
|
|
54
|
+
teardown(): Promise<void> | void;
|
|
55
|
+
tornDown(): boolean;
|
|
56
|
+
/** Present ONLY when the room is SEAT-BEARING — its venue selects a `floor` image (Dockerfile.floor)
|
|
57
|
+
* that carries the toolchain and the agent binary, the deliberate opposite of the production-only
|
|
58
|
+
* room image. It names the room's own container and the per-realization workspace, so the invoker
|
|
59
|
+
* can run the chair as `docker exec -i -w <workspace> <container> claude …` INSIDE the room. Absent
|
|
60
|
+
* on the production room image and on the local-process realizer: the seat runs on the host. */
|
|
61
|
+
seat?: {
|
|
62
|
+
container: string;
|
|
63
|
+
workspace: string;
|
|
64
|
+
} | undefined;
|
|
65
|
+
}
|
|
66
|
+
export interface RealizeOpts {
|
|
67
|
+
gigId: string;
|
|
68
|
+
engineServers?: Readonly<Record<string, unknown>>;
|
|
69
|
+
probe?: (s: {
|
|
70
|
+
slug: string;
|
|
71
|
+
}) => Promise<string[]>;
|
|
72
|
+
host?: RealizationHost;
|
|
73
|
+
chairs?: number;
|
|
74
|
+
/** WHERE the room's tree comes from — the repository named by the RUN, supplied by the realization
|
|
75
|
+
* caller, NEVER a venue field and NEVER read from the host's cwd. A venue is one AT-REST room that
|
|
76
|
+
* serves many repositories, so the repository is a per-RUN fact, threaded in here from
|
|
77
|
+
* `RunDeps.repoUrl` (an explicit dispatch field, or the claim's governed `repo_url`). Present → the
|
|
78
|
+
* room's workspace is populated (through `prepareWorkspace`) with a clone of this repository, so a
|
|
79
|
+
* seat inside the room has a tree to edit. Absent → the workspace stays the empty room, and no git
|
|
80
|
+
* credential is minted. Inferring an ambient source is the exact failure this explicit field
|
|
81
|
+
* forecloses. */
|
|
82
|
+
repoUrl?: string;
|
|
83
|
+
/** The per-gig git-credential plumbing `prepareWorkspace` requires, supplied by the realization
|
|
84
|
+
* caller alongside `repoUrl` — never derived from ambient process state. The minted token only ever
|
|
85
|
+
* rides `cloneInto`'s GIT_CONFIG_* env, never a host file, so token-never-on-disk is preserved. */
|
|
86
|
+
drainKey?: string;
|
|
87
|
+
instance?: string;
|
|
88
|
+
gitCredentialsEndpoint?: string;
|
|
89
|
+
}
|
|
90
|
+
/** The seam. The engine ships the interface, the state machine, the probe and the drift guard; a
|
|
91
|
+
* deployment supplies the implementations it has. Two implementations or it is not a seam. */
|
|
92
|
+
export interface VenueRealizer {
|
|
93
|
+
readonly substrate: string;
|
|
94
|
+
readonly guarantees: readonly VenueGuarantee[];
|
|
95
|
+
available(): boolean;
|
|
96
|
+
readonly retention: RetentionPolicy;
|
|
97
|
+
realize(venue: unknown, credentialResolver: CredentialResolver, opts: RealizeOpts): Promise<RealizationHandle>;
|
|
98
|
+
sweep(opts: {
|
|
99
|
+
liveGigs: readonly string[];
|
|
100
|
+
}): Promise<readonly RealizedArtifact[]>;
|
|
101
|
+
}
|
|
102
|
+
/** A substrate no available realizer provides is a REFUSAL, never a downgrade — the whole reason
|
|
103
|
+
* this gap is written down. Names what was required and what this host can actually provide. */
|
|
104
|
+
export declare class VenueSubstrateUnavailable extends Error {
|
|
105
|
+
readonly required: string;
|
|
106
|
+
readonly available: readonly string[];
|
|
107
|
+
constructor(required: string, available: readonly string[]);
|
|
108
|
+
}
|
|
109
|
+
/** A HOST cannot host this venue: a device class it does not provide, an architecture it is not.
|
|
110
|
+
* Distinct from a substrate refusal — the fix is a different machine, not a different runtime. */
|
|
111
|
+
export declare class VenueHostUnsuitable extends Error {
|
|
112
|
+
constructor(message: string);
|
|
113
|
+
}
|
|
114
|
+
/** A realization would exceed the venue's declared concurrency ceiling. */
|
|
115
|
+
export declare class VenueConcurrencyRefused extends Error {
|
|
116
|
+
constructor(message: string);
|
|
117
|
+
}
|
|
118
|
+
/** Input would render a setting the contract may not ask for. Carries `forbidden` so the refusal
|
|
119
|
+
* names the value, and `field` so it names where it arrived — "invalid venue" sends the author back
|
|
120
|
+
* to read the whole contract. */
|
|
121
|
+
export declare class VenueRenderRefusal extends Error {
|
|
122
|
+
readonly forbidden: string;
|
|
123
|
+
readonly field: string | undefined;
|
|
124
|
+
constructor(args: {
|
|
125
|
+
forbidden: string;
|
|
126
|
+
field?: string;
|
|
127
|
+
message?: string;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** Gap 2's bidirectional probe, direction one: a tool the CONTRACT grants that the server does not
|
|
131
|
+
* actually advertise. "Granted but unprovided" caught at realization instead of at first use. Carries
|
|
132
|
+
* the bare tool and the server so the refusal names both — the remediation is to add the tool to the
|
|
133
|
+
* server or drop the grant, which is a different fix from a server that is too wide. */
|
|
134
|
+
export declare class VenueRealizationError extends Error {
|
|
135
|
+
readonly state: string;
|
|
136
|
+
readonly missingGrant: string;
|
|
137
|
+
readonly serverSlug: string;
|
|
138
|
+
constructor(args: {
|
|
139
|
+
state: string;
|
|
140
|
+
missingGrant: string;
|
|
141
|
+
serverSlug: string;
|
|
142
|
+
message?: string;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/** Gap 2's bidirectional probe, direction two: the server advertises MORE than the contract declared.
|
|
146
|
+
* A ceiling the thing beneath it can quietly exceed is not a ceiling — the exact intersection R10
|
|
147
|
+
* enforces at compose time. NON-OVERLAPPING fields with `VenueRealizationError` on purpose: the two
|
|
148
|
+
* mismatches demand different remediation, and one merged error would make the direction ambiguous. */
|
|
149
|
+
export declare class VenueContractViolation extends Error {
|
|
150
|
+
readonly state: string;
|
|
151
|
+
readonly extraTool: string;
|
|
152
|
+
readonly serverSlug: string;
|
|
153
|
+
constructor(args: {
|
|
154
|
+
state: string;
|
|
155
|
+
extraTool: string;
|
|
156
|
+
serverSlug: string;
|
|
157
|
+
message?: string;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/** The CLOSED allowlist of contract fields the renderer may substitute. Exact, not a floor: a field
|
|
161
|
+
* not on this list contributes nothing to the render whatever it is called, and widening the list
|
|
162
|
+
* is a line someone changes on purpose. */
|
|
163
|
+
export declare const COMPOSE_SUBSTITUTABLE_FIELDS: readonly ["credential_names", "doors", "installs", "mcp_servers", "slug"];
|
|
164
|
+
/** The identity of the environment built from a venue — a function of the parsed contract's content,
|
|
165
|
+
* so the same contract is the same environment and a changed one is a different environment. */
|
|
166
|
+
export declare function environmentIdentity(venue: unknown): string;
|
|
167
|
+
/** The identity of the shared floor a venue composes over. Two venues declaring the same floor
|
|
168
|
+
* resolve to the SAME floor identity — the precondition for sharing at all. */
|
|
169
|
+
export declare function floorIdentity(venue: unknown): string;
|
|
170
|
+
/** Renders the runtime configuration from a PARSED venue. Never from raw input: re-parsing through
|
|
171
|
+
* `VenueSchema` (which is `.strict()`) is the enforcement point, so an unparsed object carrying an
|
|
172
|
+
* extra key is refused at the door rather than trusted to have been parsed by every future caller. */
|
|
173
|
+
export declare function renderComposeConfig(venue: unknown, opts: {
|
|
174
|
+
gigId: string;
|
|
175
|
+
realizationDir: string;
|
|
176
|
+
host?: RealizationHost;
|
|
177
|
+
}): Record<string, unknown>;
|
|
178
|
+
/** Picks the realizer a venue requires from those a deployment supplies. A required substrate no
|
|
179
|
+
* AVAILABLE realizer provides is a `VenueSubstrateUnavailable`, never a downgrade. A venue naming no
|
|
180
|
+
* substrate is realizable by whatever the deployment supplies — deny-by-default is on capability,
|
|
181
|
+
* not on portability. */
|
|
182
|
+
export declare function selectRealizer(venue: unknown, realizers: readonly VenueRealizer[]): VenueRealizer;
|
|
183
|
+
/** THE ONE OWNER OF THE COMPOSE PROJECT NAME — and therefore of the room's container name.
|
|
184
|
+
*
|
|
185
|
+
* These two facts must agree or the realization is dead on arrival: the name compose gives the
|
|
186
|
+
* container, and the name the emitted MCP transport execs into. They were derived in two places
|
|
187
|
+
* from two different inputs (the realization directory here, the gig id at the call site) and a
|
|
188
|
+
* comment asserted they matched. A restatement is not an agreement; when the directory was not
|
|
189
|
+
* named `gig-<id8>` the transport pointed at a container that never existed, and every law still
|
|
190
|
+
* passed because every law read the emitted string rather than running it.
|
|
191
|
+
*
|
|
192
|
+
* So there is one derivation and both callers go through it. `-room-1` is docker compose's own
|
|
193
|
+
* default container name for the `room` service of this project. */
|
|
194
|
+
export declare function composeProjectName(realizationDir: string): string;
|
|
195
|
+
export declare function roomContainerName(realizationDir: string): string;
|
|
196
|
+
/** The container docker compose names for a declared SERVER service — same `{project}-{service}-1`
|
|
197
|
+
* default as the room, with the server's slug as the service. The credential-delivery step copies
|
|
198
|
+
* each server's own classes into this container, mirroring where the prior compose file-secret was
|
|
199
|
+
* mounted, so a server that reads /run/secrets/<class> is unchanged by the delivery move. */
|
|
200
|
+
export declare function serverContainerName(realizationDir: string, slug: string): string;
|
|
201
|
+
/** The Gap 2 entry: builds the spawn's MCP environment STRICTLY from the venue contract, verifies it
|
|
202
|
+
* in both directions before anything is committed, and writes the per-gig config the spawn is pointed
|
|
203
|
+
* at. The map is the venue's declared servers plus the engine entries and NOTHING the venue did not
|
|
204
|
+
* declare — the ambient `.mcp.json` `readMcpServerConfigs` builds at bootstrap is never read here,
|
|
205
|
+
* neither to add a server nor to override one, because a drain's cwd is an untrusted clone and a clone
|
|
206
|
+
* that can declare MCP servers for the seat reading it is command execution under the seat. The
|
|
207
|
+
* realized map is precisely what a tool grant is failed closed against, so preflight and spawn read
|
|
208
|
+
* one stable object rather than two copies that agree today. */
|
|
209
|
+
export declare function realizeVenue(venue: unknown, credentialResolver: CredentialResolver, opts: RealizeOpts): Promise<RealizationHandle>;
|
|
210
|
+
/** The baseline. Runs seats as subprocesses of a host that holds the git binary, the remote and the
|
|
211
|
+
* network — so it CANNOT withhold capabilities and CANNOT enforce `doors` at a network boundary,
|
|
212
|
+
* and it claims neither. src/workspace.ts:44-56 is already candid that process-level protection is
|
|
213
|
+
* not a security control and must not be described as one, so claiming those guarantees would be a
|
|
214
|
+
* false contract a caller would rely on. Must work on a host with no container runtime and no
|
|
215
|
+
* daemon installed. */
|
|
216
|
+
export declare function localProcessRealizer(): VenueRealizer;
|
|
217
|
+
/** The containerized realizer. Names a real boundary and may claim the guarantees it provides. MUST
|
|
218
|
+
* NOT throw on construction — the out-of-scope laws call `.realize()` with mocks, and a construction
|
|
219
|
+
* throw would contaminate the seam family's shared setup. Host suitability (architecture, device
|
|
220
|
+
* classes) and the concurrency ceiling are answered BEFORE probing anything. */
|
|
221
|
+
export declare function dockerComposeRealizer(opts?: {
|
|
222
|
+
run?: ComposeRunner;
|
|
223
|
+
prepareWorkspace?: WorkspacePreparer;
|
|
224
|
+
}): VenueRealizer;
|