backlot 0.4.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 (64) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +106 -0
  3. package/dist/cli/client.d.ts +22 -0
  4. package/dist/cli/client.js +83 -0
  5. package/dist/cli/client.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.js +308 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/core/events.d.ts +10 -0
  10. package/dist/core/events.js +42 -0
  11. package/dist/core/events.js.map +1 -0
  12. package/dist/core/journal.d.ts +80 -0
  13. package/dist/core/journal.js +186 -0
  14. package/dist/core/journal.js.map +1 -0
  15. package/dist/core/manifest.d.ts +76 -0
  16. package/dist/core/manifest.js +46 -0
  17. package/dist/core/manifest.js.map +1 -0
  18. package/dist/core/paths.d.ts +17 -0
  19. package/dist/core/paths.js +32 -0
  20. package/dist/core/paths.js.map +1 -0
  21. package/dist/core/policy.d.ts +15 -0
  22. package/dist/core/policy.js +45 -0
  23. package/dist/core/policy.js.map +1 -0
  24. package/dist/core/ports.d.ts +3 -0
  25. package/dist/core/ports.js +22 -0
  26. package/dist/core/ports.js.map +1 -0
  27. package/dist/core/retention.d.ts +19 -0
  28. package/dist/core/retention.js +101 -0
  29. package/dist/core/retention.js.map +1 -0
  30. package/dist/core/sync.d.ts +15 -0
  31. package/dist/core/sync.js +150 -0
  32. package/dist/core/sync.js.map +1 -0
  33. package/dist/core/types.d.ts +82 -0
  34. package/dist/core/types.js +6 -0
  35. package/dist/core/types.js.map +1 -0
  36. package/dist/core/upkeep.d.ts +11 -0
  37. package/dist/core/upkeep.js +47 -0
  38. package/dist/core/upkeep.js.map +1 -0
  39. package/dist/core/util.d.ts +36 -0
  40. package/dist/core/util.js +100 -0
  41. package/dist/core/util.js.map +1 -0
  42. package/dist/daemon/engine.d.ts +284 -0
  43. package/dist/daemon/engine.js +858 -0
  44. package/dist/daemon/engine.js.map +1 -0
  45. package/dist/daemon/index.d.ts +2 -0
  46. package/dist/daemon/index.js +183 -0
  47. package/dist/daemon/index.js.map +1 -0
  48. package/dist/daemon/supervisor.d.ts +36 -0
  49. package/dist/daemon/supervisor.js +189 -0
  50. package/dist/daemon/supervisor.js.map +1 -0
  51. package/dist/drivers/datastore-sqlite.d.ts +27 -0
  52. package/dist/drivers/datastore-sqlite.js +83 -0
  53. package/dist/drivers/datastore-sqlite.js.map +1 -0
  54. package/dist/drivers/datastores.d.ts +22 -0
  55. package/dist/drivers/datastores.js +190 -0
  56. package/dist/drivers/datastores.js.map +1 -0
  57. package/dist/drivers/types.d.ts +71 -0
  58. package/dist/drivers/types.js +14 -0
  59. package/dist/drivers/types.js.map +1 -0
  60. package/dist/mcp/index.d.ts +2 -0
  61. package/dist/mcp/index.js +144 -0
  62. package/dist/mcp/index.js.map +1 -0
  63. package/package.json +57 -0
  64. package/schema/stack.schema.json +172 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datastore-sqlite.js","sourceRoot":"","sources":["../../src/drivers/datastore-sqlite.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAQhE,MAAM,OAAO,eAAe;IAEP;IACA;IACA;IAHnB,YACmB,IAAY,EACZ,IAAmB,EACnB,OAAe;QAFf,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAe;QACnB,YAAO,GAAP,OAAO,CAAQ;IAC/B,CAAC;IAEJ,IAAI,YAAY;QACd,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,kEAAkE;IAClE,GAAG,CAAC,OAAe;QACjB,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,oDAAoD;IACtD,CAAC;IAEO,OAAO,CAAC,MAAc;QAC5B,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IAEO,YAAY,CAAC,MAAc;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAEO,SAAS,CAAC,OAAe,EAAE,MAAc,EAAE,MAAc;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,WAAW,CAAC,YAAY,EAAE,cAAc,IAAI,CAAC,IAAI,0BAA0B,EAAE,WAAW,CAAC,CAAC;QAC9G,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;gBACpG,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,CACJ,IAAI,WAAW,CAAC,YAAY,EAAE,oBAAoB,IAAI,CAAC,IAAI,aAAa,MAAM,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAC9H,CAAC;gBACJ,CAAC;;oBAAM,OAAO,EAAE,CAAC;YACnB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,OAAe,EAAE,MAAc;QAC3D,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,kCAAkC;YAChF,CAAC;YACD,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,8CAA8C;QAC3E,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,gFAAgF;IAChF,MAAM;QACJ,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAAmB,EAAE,OAAe;IAC9E,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,WAAW,CACnB,aAAa,EACb,qBAAqB,IAAI,CAAC,MAAM,0EAA0E,EAC1G,WAAW,CACZ,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { DatastoreSpec } from '../core/manifest.js';
2
+ export interface DsHandle {
3
+ envId: string;
4
+ envTree: string;
5
+ dataDir: string;
6
+ }
7
+ export interface DsDriver {
8
+ readonly name: string;
9
+ /** The ns for an environment: sqlite = file path; server = SQL-safe db name. */
10
+ ns(h: DsHandle): string;
11
+ /** The connection string services/checks receive. */
12
+ url(h: DsHandle): string;
13
+ /** infra-error (never code blame) when the external server is unreachable. */
14
+ probe(): Promise<void>;
15
+ /** Create/restore the namespace at the preset. force = recreate even if present. */
16
+ ensure(h: DsHandle, preset: string, force: boolean, exists: boolean): Promise<void>;
17
+ /** Best-effort removal (recycle). */
18
+ drop(h: DsHandle): Promise<void>;
19
+ /** @rebake-template: invalidate baked templates. */
20
+ rebake(): void;
21
+ }
22
+ export declare function makeDatastore(name: string, spec: DatastoreSpec, stackId: string): DsDriver;
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Datastore drivers (see docs/driver-spec.md).
3
+ *
4
+ * Two families:
5
+ * - sqlite: fully engine-native — the ns IS a file; template restore is a copy.
6
+ * - command (postgres/mssql/mysql/redis): ALL mechanics are repo-declared
7
+ * commands ({{ns}}/{{preset}}/{{template}} resolved by the engine). backlot
8
+ * embeds no database clients — the anti-scope ("orchestrate, don't
9
+ * reimplement") applied to data.
10
+ *
11
+ * Template model: bake once per seed-content hash into a template ns, then
12
+ * restore per environment (postgres: `createdb -T`; mssql: the repo's
13
+ * backup/restore script). Templates are machine-global and immutable-keyed
14
+ * (decision 0006/0008).
15
+ */
16
+ import { copyFileSync, mkdirSync, rmSync, existsSync, writeFileSync, constants as fsConstants } from 'node:fs';
17
+ import { join } from 'node:path';
18
+ import { execFile } from 'node:child_process';
19
+ import { connect } from 'node:net';
20
+ import { templatesRoot } from '../core/paths.js';
21
+ import { sha256, template, BrokerError } from '../core/util.js';
22
+ const sh = (cmd, cwd, errCtx) => new Promise((resolve, reject) => {
23
+ execFile('sh', ['-c', cmd], { cwd, maxBuffer: 16 * 1024 * 1024 }, (err, _out, stderr) => {
24
+ if (err)
25
+ reject(new BrokerError('work-error', errCtx, 'datastore', String(stderr).slice(0, 800)));
26
+ else
27
+ resolve();
28
+ });
29
+ });
30
+ const shQuiet = (cmd, cwd) => new Promise((resolve) => {
31
+ execFile('sh', ['-c', cmd], { cwd, maxBuffer: 16 * 1024 * 1024 }, () => resolve());
32
+ });
33
+ // ---------------------------------------------------------------- sqlite
34
+ class SqliteDs {
35
+ name;
36
+ spec;
37
+ stackId;
38
+ constructor(name, spec, stackId) {
39
+ this.name = name;
40
+ this.spec = spec;
41
+ this.stackId = stackId;
42
+ }
43
+ ns(h) {
44
+ // The datastore KEY becomes a filename; a key with `/` or `..` must not
45
+ // escape dataDir (the command-family sibling already sanitizes — this
46
+ // closes the same hole here). Reject rather than mangle so a bad key is loud.
47
+ if (/[/\\]|\.\./.test(this.name)) {
48
+ throw new BrokerError('work-error', `sqlite datastore key '${this.name}' must not contain '/', '\\', or '..'`, 'manifest');
49
+ }
50
+ return join(h.dataDir, `${this.name}.db`);
51
+ }
52
+ url(h) {
53
+ return this.ns(h);
54
+ }
55
+ async probe() {
56
+ /* in-process — nothing external */
57
+ }
58
+ tplPath(preset) {
59
+ const dir = join(templatesRoot(), this.stackId);
60
+ mkdirSync(dir, { recursive: true });
61
+ return join(dir, `${this.name}-${preset}@${sha256(this.spec.create ?? '').slice(0, 12)}.db`);
62
+ }
63
+ async runCreate(envTree, ns, preset) {
64
+ if (!this.spec.create)
65
+ throw new BrokerError('work-error', `datastore '${this.name}' has no create: command`, 'datastore');
66
+ await sh(template(this.spec.create, { ns, preset }), envTree, `seed failed for '${this.name}' preset '${preset}'`);
67
+ }
68
+ async ensure(h, preset, force, exists) {
69
+ mkdirSync(h.dataDir, { recursive: true });
70
+ const dbPath = this.ns(h);
71
+ if (exists && !force && existsSync(dbPath))
72
+ return;
73
+ if (this.spec.template === true) {
74
+ const tpl = this.tplPath(preset);
75
+ if (!existsSync(tpl))
76
+ await this.runCreate(h.envTree, tpl, preset); // bake once
77
+ copyFileSync(tpl, dbPath, fsConstants.COPYFILE_FICLONE); // restore = CoW clone where the fs supports it
78
+ }
79
+ else {
80
+ await this.runCreate(h.envTree, dbPath, preset);
81
+ }
82
+ }
83
+ async drop(h) {
84
+ rmSync(this.ns(h), { force: true });
85
+ }
86
+ rebake() {
87
+ rmSync(join(templatesRoot(), this.stackId), { recursive: true, force: true });
88
+ }
89
+ }
90
+ // ---------------------------------------------------------------- command family
91
+ class CommandDs {
92
+ name;
93
+ spec;
94
+ stackId;
95
+ constructor(name, spec, stackId) {
96
+ this.name = name;
97
+ this.spec = spec;
98
+ this.stackId = stackId;
99
+ if (!spec.url) {
100
+ throw new BrokerError('work-error', `datastore '${name}' (driver ${spec.driver}) needs a url: template with {{ns}}`, 'manifest');
101
+ }
102
+ }
103
+ get capabilities() {
104
+ return { template: Boolean(this.spec.template_restore), ephemeral: this.spec.ephemeral === true };
105
+ }
106
+ ns(h) {
107
+ return `backlot_${h.envId}`.replace(/[^A-Za-z0-9_]/g, '_');
108
+ }
109
+ url(h) {
110
+ return template(this.spec.url, { ns: this.ns(h) });
111
+ }
112
+ async probe() {
113
+ if (!this.spec.probe)
114
+ return;
115
+ const [host, portStr] = this.spec.probe.split(':');
116
+ const port = Number(portStr);
117
+ await new Promise((resolve, reject) => {
118
+ const sock = connect({ host: host || 'localhost', port, timeout: 3000 });
119
+ sock.once('connect', () => {
120
+ sock.end();
121
+ resolve();
122
+ });
123
+ const fail = () => reject(new BrokerError('infra-error', `datastore '${this.name}' unreachable at ${this.spec.probe} — is the server running?`, 'datastore'));
124
+ sock.once('error', fail);
125
+ sock.once('timeout', fail);
126
+ });
127
+ }
128
+ templateNs(preset) {
129
+ return `backlot_tpl_${this.stackId}_${preset}_${sha256(this.spec.create ?? '').slice(0, 8)}`.replace(/[^A-Za-z0-9_]/g, '_');
130
+ }
131
+ bakedMarker(preset) {
132
+ const dir = join(templatesRoot(), this.stackId);
133
+ mkdirSync(dir, { recursive: true });
134
+ return join(dir, `${this.name}-${preset}@${sha256(this.spec.create ?? '').slice(0, 12)}.baked`);
135
+ }
136
+ async ensure(h, preset, force, exists) {
137
+ const nsE = this.ns(h);
138
+ if (this.spec.ephemeral) {
139
+ // Ephemeral (redis-class): no presets, no templates — reset = the drop:
140
+ // command as a flush; create (optional) runs only on first bind.
141
+ if (force && exists && this.spec.drop)
142
+ await shQuiet(template(this.spec.drop, { ns: nsE }), h.envTree);
143
+ if (!exists && this.spec.create) {
144
+ await sh(template(this.spec.create, { ns: nsE, preset }), h.envTree, `create failed for ephemeral '${this.name}'`);
145
+ }
146
+ return;
147
+ }
148
+ if (exists && !force)
149
+ return;
150
+ if (!this.spec.create)
151
+ throw new BrokerError('work-error', `datastore '${this.name}' has no create: command`, 'datastore');
152
+ const ns = this.ns(h);
153
+ if (this.spec.drop)
154
+ await shQuiet(template(this.spec.drop, { ns }), h.envTree); // clean slate, best-effort
155
+ if (this.spec.template_restore) {
156
+ const tpl = this.templateNs(preset);
157
+ if (!existsSync(this.bakedMarker(preset))) {
158
+ await shQuiet(this.spec.drop ? template(this.spec.drop, { ns: tpl }) : 'true', h.envTree);
159
+ await sh(template(this.spec.create, { ns: tpl, preset }), h.envTree, `template bake failed for '${this.name}' preset '${preset}'`);
160
+ writeFileSync(this.bakedMarker(preset), tpl);
161
+ }
162
+ await sh(template(this.spec.template_restore, { template: tpl, ns }), h.envTree, `template restore failed for '${this.name}' preset '${preset}'`);
163
+ }
164
+ else {
165
+ await sh(template(this.spec.create, { ns, preset }), h.envTree, `seed failed for '${this.name}' preset '${preset}'`);
166
+ }
167
+ }
168
+ async drop(h) {
169
+ if (this.spec.drop)
170
+ await shQuiet(template(this.spec.drop, { ns: this.ns(h) }), h.envTree);
171
+ }
172
+ rebake() {
173
+ rmSync(join(templatesRoot(), this.stackId), { recursive: true, force: true });
174
+ }
175
+ }
176
+ // ---------------------------------------------------------------- factory
177
+ export function makeDatastore(name, spec, stackId) {
178
+ switch (spec.driver) {
179
+ case 'sqlite':
180
+ return new SqliteDs(name, spec, stackId);
181
+ case 'postgres':
182
+ case 'mssql':
183
+ case 'mysql':
184
+ case 'redis':
185
+ return new CommandDs(name, spec, stackId);
186
+ default:
187
+ throw new BrokerError('work-error', `unknown datastore driver '${spec.driver}'`, 'manifest');
188
+ }
189
+ }
190
+ //# sourceMappingURL=datastores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datastores.js","sourceRoot":"","sources":["../../src/drivers/datastores.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * DESIGN TARGET — NOT YET WIRED. These are the FROZEN-FOR-0.3 shapes for the
3
+ * remote SUBSTRATE seam, which the engine does not yet call (v0.4 hardcodes
4
+ * local process supervision). The LIVE datastore seam is `DsDriver` in
5
+ * ./datastores.ts, not this file. Do not import these types expecting the
6
+ * engine to honor them; they exist so the substrate interface is designed
7
+ * before it is built (see docs/driver-spec.md).
8
+ *
9
+ * Drivers own TRANSPORT and STORAGE mechanics; the engine owns all POLICY
10
+ * (pooling, leases, hygiene, upkeep, sync, error taxonomy). A driver that
11
+ * wants policy is a design bug.
12
+ */
13
+ export interface ExecOptions {
14
+ cwd?: string;
15
+ env?: Record<string, string>;
16
+ /** Remote substrates must support detached (submit-and-poll) execution. */
17
+ detach?: boolean;
18
+ timeoutMs?: number;
19
+ }
20
+ export interface ExecResult {
21
+ exitCode: number;
22
+ stdout: string;
23
+ stderr: string;
24
+ /** Set when detach:true — poll/reattach handle, journaled on the box. */
25
+ jobId?: string;
26
+ }
27
+ export interface EnvHandle {
28
+ id: string;
29
+ /** Filesystem root of the environment's tree (local path or remote path). */
30
+ root: string;
31
+ substrate: string;
32
+ }
33
+ export interface SubstrateCapabilities {
34
+ pause: boolean;
35
+ checkpoint: boolean;
36
+ }
37
+ export interface SubstrateDriver {
38
+ readonly name: string;
39
+ readonly capabilities: SubstrateCapabilities;
40
+ /** Idempotent per env id. */
41
+ provision(envId: string): Promise<EnvHandle>;
42
+ exec(env: EnvHandle, cmd: string[], opts?: ExecOptions): Promise<ExecResult>;
43
+ /** A git remote/path the sync layer can fetch/push through. */
44
+ gitEndpoint(env: EnvHandle): Promise<string>;
45
+ /** Consumer-reachable URL for a port inside the environment. */
46
+ expose(env: EnvHandle, port: number): Promise<string>;
47
+ destroy(env: EnvHandle): Promise<void>;
48
+ pause?(env: EnvHandle): Promise<void>;
49
+ resume?(env: EnvHandle): Promise<void>;
50
+ checkpoint?(env: EnvHandle, key: string): Promise<void>;
51
+ restore?(key: string, envId: string): Promise<EnvHandle>;
52
+ /** Adopt-or-reap discovery of instances the local journal forgot (remote). */
53
+ reconcile?(): Promise<EnvHandle[]>;
54
+ }
55
+ export interface DatastoreCapabilities {
56
+ template: boolean;
57
+ /** Reset-data degenerates to flush; presets are meaningless. */
58
+ ephemeral: boolean;
59
+ }
60
+ export interface DatastoreDriver {
61
+ readonly name: string;
62
+ readonly capabilities: DatastoreCapabilities;
63
+ /** infra-error (never code blame) when the external server is unreachable. */
64
+ probe(): Promise<void>;
65
+ create(ns: string, preset: string): Promise<void>;
66
+ /** Must refuse namespaces outside backlot's own pattern. */
67
+ drop(ns: string): Promise<void>;
68
+ url(ns: string): string;
69
+ templateBake?(preset: string, seedHash: string): Promise<void>;
70
+ templateRestore?(ns: string, preset: string, seedHash: string): Promise<void>;
71
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * DESIGN TARGET — NOT YET WIRED. These are the FROZEN-FOR-0.3 shapes for the
3
+ * remote SUBSTRATE seam, which the engine does not yet call (v0.4 hardcodes
4
+ * local process supervision). The LIVE datastore seam is `DsDriver` in
5
+ * ./datastores.ts, not this file. Do not import these types expecting the
6
+ * engine to honor them; they exist so the substrate interface is designed
7
+ * before it is built (see docs/driver-spec.md).
8
+ *
9
+ * Drivers own TRANSPORT and STORAGE mechanics; the engine owns all POLICY
10
+ * (pooling, leases, hygiene, upkeep, sync, error taxonomy). A driver that
11
+ * wants policy is a design bug.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/drivers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Minimal MCP (Model Context Protocol) server over stdio — a THIN adapter on
4
+ * the same daemon RPC the CLI uses (decision 0014: never a second
5
+ * implementation). Newline-delimited JSON-RPC 2.0; implements initialize,
6
+ * tools/list, tools/call. Start with: backlot-mcp (or node dist/mcp/index.js)
7
+ *
8
+ * Every tool result is the same JSON the CLI's --json emits, as text content.
9
+ */
10
+ import { createInterface } from 'node:readline';
11
+ import { ensureDaemon, rpc } from '../cli/client.js';
12
+ const PROTOCOL = '2025-06-18';
13
+ const cwdProp = {
14
+ cwd: { type: 'string', description: 'Worktree directory (a stack.yaml is found upward from here). REQUIRED — the MCP server has no meaningful cwd of its own.' },
15
+ };
16
+ const TOOLS = [
17
+ {
18
+ name: 'backlot_up',
19
+ description: 'Lease a warm environment for this worktree: sync, upkeep, seed, start services. Returns the context blob (URLs, logins, connection strings).',
20
+ inputSchema: { type: 'object', properties: { ...cwdProp, hygiene: { type: 'string', enum: ['reuse', 'reset-data', 'pristine'] } }, required: ['cwd'] },
21
+ verb: 'up',
22
+ },
23
+ {
24
+ name: 'backlot_run',
25
+ description: 'Run a named check from stack.yaml against a fresh binding: verdict with ok/exitCode/failure taxonomy (work-error = your code, env-error = environment, infra-error = external), artifacts dir, outputs_changed.',
26
+ inputSchema: { type: 'object', properties: { ...cwdProp, check: { type: 'string' }, hygiene: { type: 'string', enum: ['reuse', 'reset-data', 'pristine'] } }, required: ['cwd', 'check'] },
27
+ verb: 'run',
28
+ },
29
+ {
30
+ name: 'backlot_ctx',
31
+ description: 'The current lease context: service URLs, logins, token command, datastore connection strings, artifacts dir, recent service events.',
32
+ inputSchema: { type: 'object', properties: { ...cwdProp }, required: ['cwd'] },
33
+ verb: 'ctx',
34
+ },
35
+ {
36
+ name: 'backlot_sync',
37
+ description: 'Project the worktree state (including dirty/untracked files) into the leased environment; services restart only if the source changed.',
38
+ inputSchema: { type: 'object', properties: { ...cwdProp }, required: ['cwd'] },
39
+ verb: 'sync',
40
+ },
41
+ {
42
+ name: 'backlot_exec',
43
+ description: 'Run a shell command inside the leased environment tree (BACKLOT_URL_*/BACKLOT_DS_* env injected).',
44
+ inputSchema: { type: 'object', properties: { ...cwdProp, cmd: { type: 'string' } }, required: ['cwd', 'cmd'] },
45
+ verb: 'exec',
46
+ },
47
+ {
48
+ name: 'backlot_logs',
49
+ description: 'Tail a supervised service log from the leased environment.',
50
+ inputSchema: { type: 'object', properties: { ...cwdProp, service: { type: 'string' }, lines: { type: 'number' } }, required: ['cwd', 'service'] },
51
+ verb: 'logs',
52
+ },
53
+ {
54
+ name: 'backlot_reset_data',
55
+ description: 'Restore the data template on the current lease (replay a repro against pristine data). URLs stay stable.',
56
+ inputSchema: { type: 'object', properties: { ...cwdProp }, required: ['cwd'] },
57
+ verb: 'reset-data',
58
+ },
59
+ {
60
+ name: 'backlot_pull',
61
+ description: 'Copy the environment\'s changed declared outputs (regenerated lockfiles, generated clients) back into the worktree — the only sanctioned write-back.',
62
+ inputSchema: { type: 'object', properties: { ...cwdProp }, required: ['cwd'] },
63
+ verb: 'pull',
64
+ },
65
+ {
66
+ name: 'backlot_token',
67
+ description: 'Mint an auth token via the stack\'s auth.token hook (resolves {{role}}). Returns {token, role}.',
68
+ inputSchema: { type: 'object', properties: { ...cwdProp, role: { type: 'string', description: 'Role to mint for (default admin).' } }, required: ['cwd'] },
69
+ verb: 'token',
70
+ },
71
+ {
72
+ name: 'backlot_release',
73
+ description: 'Release the current lease; the environment returns to the pool warm.',
74
+ inputSchema: { type: 'object', properties: { ...cwdProp }, required: ['cwd'] },
75
+ verb: 'release',
76
+ },
77
+ {
78
+ name: 'backlot_status',
79
+ description: 'Pool overview: environments, states, leases, recent daemon events.',
80
+ inputSchema: { type: 'object', properties: {} },
81
+ verb: 'status',
82
+ },
83
+ {
84
+ name: 'backlot_doctor',
85
+ description: 'Active health check of the pool: pid divergence, stuck-recycling envs, plus recent events.',
86
+ inputSchema: { type: 'object', properties: {} },
87
+ verb: 'doctor',
88
+ },
89
+ ];
90
+ function respond(id, result) {
91
+ process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id, result }) + '\n');
92
+ }
93
+ function respondError(id, code, message) {
94
+ process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } }) + '\n');
95
+ }
96
+ const rl = createInterface({ input: process.stdin });
97
+ rl.on('line', (line) => {
98
+ void (async () => {
99
+ if (!line.trim())
100
+ return;
101
+ let msg;
102
+ try {
103
+ msg = JSON.parse(line);
104
+ }
105
+ catch {
106
+ return respondError(null, -32700, 'parse error');
107
+ }
108
+ const { id, method, params } = msg;
109
+ try {
110
+ switch (method) {
111
+ case 'initialize':
112
+ return respond(id, {
113
+ protocolVersion: PROTOCOL,
114
+ capabilities: { tools: {} },
115
+ serverInfo: { name: 'backlot', version: '0.4.0' },
116
+ });
117
+ case 'notifications/initialized':
118
+ return; // notification — no response
119
+ case 'ping':
120
+ return respond(id, {});
121
+ case 'tools/list':
122
+ return respond(id, { tools: TOOLS.map(({ name, description, inputSchema }) => ({ name, description, inputSchema })) });
123
+ case 'tools/call': {
124
+ const toolName = String(params?.name);
125
+ const tool = TOOLS.find((t) => t.name === toolName);
126
+ if (!tool)
127
+ return respondError(id, -32602, `unknown tool '${toolName}'`);
128
+ const args = (params?.arguments ?? {});
129
+ await ensureDaemon();
130
+ const res = await rpc(tool.verb, args);
131
+ const text = JSON.stringify(res.ok ? res.data : { error: res.error });
132
+ return respond(id, { content: [{ type: 'text', text }], isError: !res.ok });
133
+ }
134
+ default:
135
+ if (id !== undefined)
136
+ return respondError(id, -32601, `method '${method}' not found`);
137
+ }
138
+ }
139
+ catch (err) {
140
+ return respondError(id, -32603, String(err.message ?? err));
141
+ }
142
+ })();
143
+ });
144
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "backlot",
3
+ "version": "0.4.0",
4
+ "description": "The repo-aware environment broker: puts a working, seeded, provable instance of your web application in front of coding agents and humans \u2014 warm pools, leases, bind-by-sync. Brokers environments; never provides them.",
5
+ "keywords": [
6
+ "environment",
7
+ "broker",
8
+ "dev-environment",
9
+ "coding-agents",
10
+ "e2e",
11
+ "preview",
12
+ "warm-pool",
13
+ "sandbox",
14
+ "harness",
15
+ "mcp"
16
+ ],
17
+ "license": "Apache-2.0",
18
+ "type": "module",
19
+ "engines": {
20
+ "node": ">=22.5.0"
21
+ },
22
+ "bin": {
23
+ "backlot": "./dist/cli/index.js",
24
+ "backlot-mcp": "./dist/mcp/index.js"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "schema",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.json",
34
+ "typecheck": "tsc -p tsconfig.json --noEmit",
35
+ "test": "vitest run",
36
+ "lint": "eslint src",
37
+ "pretest": "npm run build"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^22.10.0",
41
+ "typescript": "^5.7.0",
42
+ "vitest": "^3.0.0"
43
+ },
44
+ "dependencies": {
45
+ "ajv": "^8.17.0",
46
+ "yaml": "^2.6.0"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/ChristianKohlberg/backlot.git"
51
+ },
52
+ "homepage": "https://github.com/ChristianKohlberg/backlot#readme",
53
+ "bugs": {
54
+ "url": "https://github.com/ChristianKohlberg/backlot/issues"
55
+ },
56
+ "author": "Christian Kohlberg"
57
+ }