@eir-labs/coltrane 0.9.4 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/agents/bandleader.json +54 -0
  2. package/agents/bill.json +4 -2
  3. package/agents/change-verifier.json +2 -1
  4. package/agents/code-implementer.json +7 -4
  5. package/agents/john.json +5 -3
  6. package/agents/lineage-scout-external.json +19 -6
  7. package/agents/lineage-scribe.json +20 -9
  8. package/agents/lineage-weaver.json +26 -11
  9. package/agents/miles.json +2 -1
  10. package/agents/players/bandleader.md +70 -0
  11. package/agents/pr-publisher.json +4 -2
  12. package/agents/red-spec-drafter.json +12 -6
  13. package/agents/room-prober.json +29 -0
  14. package/agents/source-walker.json +1 -1
  15. package/charts/room-probe-chart-v1.json +14 -0
  16. package/charts/worker-contract-docker-v2.json +135 -0
  17. package/charts/worker-contract-v3.json +206 -0
  18. package/dist/src/boundary_check.d.ts +18 -0
  19. package/dist/src/boundary_check.js +70 -0
  20. package/dist/src/boundary_check.js.map +1 -0
  21. package/dist/src/boundary_scan.d.ts +62 -0
  22. package/dist/src/boundary_scan.js +93 -0
  23. package/dist/src/boundary_scan.js.map +1 -0
  24. package/dist/src/chart.js +34 -1
  25. package/dist/src/chart.js.map +1 -1
  26. package/dist/src/claude_invoker.d.ts +2 -1
  27. package/dist/src/claude_invoker.js +150 -17
  28. package/dist/src/claude_invoker.js.map +1 -1
  29. package/dist/src/cli.d.ts +1 -1
  30. package/dist/src/cli.js +61 -26
  31. package/dist/src/cli.js.map +1 -1
  32. package/dist/src/drain_preflight.d.ts +33 -0
  33. package/dist/src/drain_preflight.js +97 -0
  34. package/dist/src/drain_preflight.js.map +1 -0
  35. package/dist/src/genome_schema.d.ts +390 -9
  36. package/dist/src/genome_schema.js +163 -8
  37. package/dist/src/genome_schema.js.map +1 -1
  38. package/dist/src/genome_store.js +9 -0
  39. package/dist/src/genome_store.js.map +1 -1
  40. package/dist/src/genome_writer.d.ts +1 -1
  41. package/dist/src/genome_writer.js +10 -2
  42. package/dist/src/genome_writer.js.map +1 -1
  43. package/dist/src/gig_conformance.d.ts +66 -0
  44. package/dist/src/gig_conformance.js +153 -0
  45. package/dist/src/gig_conformance.js.map +1 -0
  46. package/dist/src/gig_tracker.js +8 -0
  47. package/dist/src/gig_tracker.js.map +1 -1
  48. package/dist/src/grounding.d.ts +44 -0
  49. package/dist/src/grounding.js +127 -0
  50. package/dist/src/grounding.js.map +1 -0
  51. package/dist/src/index.d.ts +1 -0
  52. package/dist/src/index.js +1 -0
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/institution_loader.d.ts +29 -5
  55. package/dist/src/institution_loader.js +67 -6
  56. package/dist/src/institution_loader.js.map +1 -1
  57. package/dist/src/lineage_adoption.d.ts +82 -0
  58. package/dist/src/lineage_adoption.js +82 -0
  59. package/dist/src/lineage_adoption.js.map +1 -0
  60. package/dist/src/lineage_persist.d.ts +34 -0
  61. package/dist/src/lineage_persist.js +60 -0
  62. package/dist/src/lineage_persist.js.map +1 -0
  63. package/dist/src/loader.d.ts +13 -0
  64. package/dist/src/loader.js +43 -2
  65. package/dist/src/loader.js.map +1 -1
  66. package/dist/src/mcp.js +37 -4
  67. package/dist/src/mcp.js.map +1 -1
  68. package/dist/src/org_hire.d.ts +23 -0
  69. package/dist/src/org_hire.js +42 -0
  70. package/dist/src/org_hire.js.map +1 -0
  71. package/dist/src/output_mirror.js +98 -59
  72. package/dist/src/output_mirror.js.map +1 -1
  73. package/dist/src/outputs.d.ts +17 -0
  74. package/dist/src/outputs.js +86 -1
  75. package/dist/src/outputs.js.map +1 -1
  76. package/dist/src/player_to_claude_code.js +26 -2
  77. package/dist/src/player_to_claude_code.js.map +1 -1
  78. package/dist/src/registry.d.ts +3 -1
  79. package/dist/src/registry.js +43 -3
  80. package/dist/src/registry.js.map +1 -1
  81. package/dist/src/repo_index.d.ts +58 -0
  82. package/dist/src/repo_index.js +232 -0
  83. package/dist/src/repo_index.js.map +1 -0
  84. package/dist/src/reuse.d.ts +44 -4
  85. package/dist/src/reuse.js +0 -0
  86. package/dist/src/reuse.js.map +1 -1
  87. package/dist/src/runtime.d.ts +82 -0
  88. package/dist/src/runtime.js +254 -25
  89. package/dist/src/runtime.js.map +1 -1
  90. package/dist/src/server.d.ts +37 -0
  91. package/dist/src/server.js +422 -11
  92. package/dist/src/server.js.map +1 -1
  93. package/dist/src/server_relay.d.ts +40 -2
  94. package/dist/src/server_relay.js +186 -19
  95. package/dist/src/server_relay.js.map +1 -1
  96. package/dist/src/tool_providers.d.ts +27 -0
  97. package/dist/src/tool_providers.js +48 -0
  98. package/dist/src/tool_providers.js.map +1 -1
  99. package/dist/src/venue_credential.d.ts +41 -0
  100. package/dist/src/venue_credential.js +57 -0
  101. package/dist/src/venue_credential.js.map +1 -0
  102. package/dist/src/venue_realize.d.ts +23 -0
  103. package/dist/src/venue_realize.js +43 -3
  104. package/dist/src/venue_realize.js.map +1 -1
  105. package/dist/src/venue_realizer.d.ts +224 -0
  106. package/dist/src/venue_realizer.js +889 -0
  107. package/dist/src/venue_realizer.js.map +1 -0
  108. package/dist/src/version.d.ts +1 -1
  109. package/dist/src/version.js +1 -1
  110. package/dist/src/version.js.map +1 -1
  111. package/dist/src/worker.d.ts +37 -0
  112. package/dist/src/worker.js +127 -24
  113. package/dist/src/worker.js.map +1 -1
  114. package/dist/src/worker_env.d.ts +79 -0
  115. package/dist/src/worker_env.js +322 -0
  116. package/dist/src/worker_env.js.map +1 -0
  117. package/dist/src/workspace.d.ts +12 -1
  118. package/dist/src/workspace.js +10 -3
  119. package/dist/src/workspace.js.map +1 -1
  120. package/domain_types/change-context.json +59 -13
  121. package/domain_types/lineage-adoption-target.json +22 -0
  122. package/domain_types/lineage-map.json +7 -2
  123. package/domain_types/lineage-record.json +55 -5
  124. package/domain_types/prior-art-hit.json +16 -1
  125. package/domain_types/red-spec.json +5 -3
  126. package/domain_types/woodshed-record.json +149 -0
  127. package/evals/gist-present.json +7 -0
  128. package/institutions/coltrane.json +178 -6
  129. package/package.json +6 -3
  130. package/skills/non-vacuity-probe/fixtures/fixture-001.json +17 -0
  131. package/skills/non-vacuity-probe/meta.json +12 -0
  132. package/skills/non-vacuity-probe/skill.md +27 -0
  133. package/skills/non-vacuity-probe/skill.mjs +81 -0
  134. package/standards/lineage-adopt-v0.json +37 -0
  135. package/standards/room-probe-v1.json +28 -0
  136. package/standards/software-change-pr-v1.json +15 -15
  137. package/standards/software-change-red-first-v0.json +183 -0
  138. package/standards/spec-review-and-sequence-v0.json +112 -0
  139. package/standards/studio-session-v0.json +101 -0
  140. package/tours/coltrane.json +72 -0
  141. package/venues/engine-room-v1.json +32 -0
@@ -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 a default-deny map: nothing from the ambient environment leaks into a seat. No test
90
- // pins seat.env values; the strictest posture is the safe one until a spec names otherwise.
91
- seats.push({ agent_slug: seat.agent.slug, effective_tools, env: {} });
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":"AAAA,iGAAiG;AACjG,EAAE;AACF,iGAAiG;AACjG,mGAAmG;AACnG,mGAAmG;AACnG,qGAAqG;AACrG,mGAAmG;AACnG,kGAAkG;AAClG,oFAAoF;AACpF,EAAE;AACF,gGAAgG;AAChG,kGAAkG;AAClG,4FAA4F;AAC5F,mGAAmG;AACnG,gGAAgG;AAChG,+EAA+E;AAC/E,OAAO,EAAE,mBAAmB,EAAc,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAkFjD;;qGAEqG;AACrG,IAAI,cAAc,GAAG,CAAC,CAAC;AAEvB;;;;+DAI+D;AAC/D,MAAM,MAAM,GAAG,CAAC,IAAiB,EAAE,MAAc,EAAsB,EAAE,CAAC,CAAC;IACzE,EAAE,EAAE,KAAK;IACT,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;IACrB,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK;IACtB,gBAAgB,EAAE,eAAe;IACjC,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;IACpB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;CACnB,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAY,EAAE,IAAiB;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;IAE3C,gGAAgG;IAChG,gGAAgG;IAChG,iGAAiG;IACjG,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACrB,OAAO,MAAM,CAAC,eAAe,EAAE,UAAU,KAAK,CAAC,IAAI,iEAAiE,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,yFAAyF;IACzF,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,mGAAmG;IACnG,gFAAgF;IAChF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,MAAM,CACX,yBAAyB,EACzB,UAAU,KAAK,CAAC,IAAI,kBAAkB,GAAG,6CAA6C,CACvF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iGAAiG;IACjG,6FAA6F;IAC7F,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CACX,mBAAmB,EACnB,UAAU,KAAK,CAAC,IAAI,qBAAqB,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,6BAA6B,CACzI,CAAC;IACJ,CAAC;IAED,+FAA+F;IAC/F,gGAAgG;IAChG,sFAAsF;IACtF,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC;QAC9C,MAAM,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,MAAM,CACX,eAAe,EACf,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,aAAa,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,KAAK,CAAC,IAAI,8CAA8C,CAChJ,CAAC;QACJ,CAAC;QACD,6FAA6F;QAC7F,4FAA4F;QAC5F,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,6FAA6F;IAC7F,+FAA+F;IAC/F,aAAa;IACb,MAAM,gBAAgB,GAAG,SAAS,KAAK,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,cAAc,EAAE,CAAC;IACrF,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,CAAC,eAAe,KAAK,SAAS;QAC3C,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,EAAE;QACtF,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;IAEzC,MAAM,EAAE,GAAkB;QACxB,EAAE,EAAE,IAAI;QACR,KAAK;QACL,uBAAuB,EAAE,CAAC,GAAG,kBAAkB,CAAC;QAChD,QAAQ,EAAE,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACnE,SAAS,EAAE,CAAC,MAAc,EAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAChE,gBAAgB;QAChB,SAAS;QACT,QAAQ,EAAE,GAAY,EAAE,CAAC,IAAI;QAC7B,QAAQ,EAAE,GAAS,EAAE;YACnB,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjG,CAAC;IACF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,IAAkD;IAElD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,eAAe,EAAE,sCAAsC,IAAI,8BAA8B,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"venue_realize.js","sourceRoot":"","sources":["../../src/venue_realize.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,EAAE;AACF,iGAAiG;AACjG,mGAAmG;AACnG,mGAAmG;AACnG,qGAAqG;AACrG,mGAAmG;AACnG,kGAAkG;AAClG,oFAAoF;AACpF,EAAE;AACF,gGAAgG;AAChG,kGAAkG;AAClG,4FAA4F;AAC5F,mGAAmG;AACnG,gGAAgG;AAChG,+EAA+E;AAC/E,OAAO,EAAE,mBAAmB,EAAc,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAkFjD;;qGAEqG;AACrG,IAAI,cAAc,GAAG,CAAC,CAAC;AAEvB;;;;+DAI+D;AAC/D,MAAM,MAAM,GAAG,CAAC,IAAiB,EAAE,MAAc,EAAsB,EAAE,CAAC,CAAC;IACzE,EAAE,EAAE,KAAK;IACT,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;IACrB,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK;IACtB,gBAAgB,EAAE,eAAe;IACjC,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;IACpB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;CACnB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAEpE;;;;GAIG;AACH,SAAS,OAAO,CAAC,UAAkC;IACjD,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,KAAY,EAAE,IAAiB;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;IAE3C,gGAAgG;IAChG,gGAAgG;IAChG,iGAAiG;IACjG,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACrB,OAAO,MAAM,CAAC,eAAe,EAAE,UAAU,KAAK,CAAC,IAAI,iEAAiE,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,yFAAyF;IACzF,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,mGAAmG;IACnG,gFAAgF;IAChF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,MAAM,CACX,yBAAyB,EACzB,UAAU,KAAK,CAAC,IAAI,kBAAkB,GAAG,6CAA6C,CACvF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iGAAiG;IACjG,6FAA6F;IAC7F,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CACX,mBAAmB,EACnB,UAAU,KAAK,CAAC,IAAI,qBAAqB,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,6BAA6B,CACzI,CAAC;IACJ,CAAC;IAED,+FAA+F;IAC/F,gGAAgG;IAChG,sFAAsF;IACtF,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC;QAC9C,MAAM,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,MAAM,CACX,eAAe,EACf,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,aAAa,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,KAAK,CAAC,IAAI,8CAA8C,CAChJ,CAAC;QACJ,CAAC;QACD,+FAA+F;QAC/F,2FAA2F;QAC3F,+FAA+F;QAC/F,gGAAgG;QAChG,mDAAmD;QACnD,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,6FAA6F;IAC7F,+FAA+F;IAC/F,aAAa;IACb,MAAM,gBAAgB,GAAG,SAAS,KAAK,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,cAAc,EAAE,CAAC;IACrF,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,CAAC,eAAe,KAAK,SAAS;QAC3C,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,EAAE;QACtF,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;IAEzC,MAAM,EAAE,GAAkB;QACxB,EAAE,EAAE,IAAI;QACR,KAAK;QACL,uBAAuB,EAAE,CAAC,GAAG,kBAAkB,CAAC;QAChD,QAAQ,EAAE,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACnE,SAAS,EAAE,CAAC,MAAc,EAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAChE,gBAAgB;QAChB,SAAS;QACT,QAAQ,EAAE,GAAY,EAAE,CAAC,IAAI;QAC7B,QAAQ,EAAE,GAAS,EAAE;YACnB,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjG,CAAC;IACF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,IAAkD;IAElD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,eAAe,EAAE,sCAAsC,IAAI,8BAA8B,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC"}
@@ -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;