@sublang/slc 0.1.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 (137) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +192 -0
  3. package/dist/app.d.ts +85 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +233 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/artifacts.d.ts +61 -0
  8. package/dist/artifacts.d.ts.map +1 -0
  9. package/dist/artifacts.js +97 -0
  10. package/dist/artifacts.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +26 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/cligent-agent.d.ts +11 -0
  16. package/dist/cligent-agent.d.ts.map +1 -0
  17. package/dist/cligent-agent.js +66 -0
  18. package/dist/cligent-agent.js.map +1 -0
  19. package/dist/compiled-executor.d.ts +42 -0
  20. package/dist/compiled-executor.d.ts.map +1 -0
  21. package/dist/compiled-executor.js +433 -0
  22. package/dist/compiled-executor.js.map +1 -0
  23. package/dist/config-file.d.ts +52 -0
  24. package/dist/config-file.d.ts.map +1 -0
  25. package/dist/config-file.js +159 -0
  26. package/dist/config-file.js.map +1 -0
  27. package/dist/config.d.ts +82 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +161 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/entry-module.d.ts +22 -0
  32. package/dist/entry-module.d.ts.map +1 -0
  33. package/dist/entry-module.js +216 -0
  34. package/dist/entry-module.js.map +1 -0
  35. package/dist/execution.d.ts +71 -0
  36. package/dist/execution.d.ts.map +1 -0
  37. package/dist/execution.js +207 -0
  38. package/dist/execution.js.map +1 -0
  39. package/dist/file-capability.d.ts +46 -0
  40. package/dist/file-capability.d.ts.map +1 -0
  41. package/dist/file-capability.js +234 -0
  42. package/dist/file-capability.js.map +1 -0
  43. package/dist/file-grants.d.ts +79 -0
  44. package/dist/file-grants.d.ts.map +1 -0
  45. package/dist/file-grants.js +133 -0
  46. package/dist/file-grants.js.map +1 -0
  47. package/dist/hash.d.ts +14 -0
  48. package/dist/hash.d.ts.map +1 -0
  49. package/dist/hash.js +34 -0
  50. package/dist/hash.js.map +1 -0
  51. package/dist/index.d.ts +20 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +22 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/interpreter.d.ts +48 -0
  56. package/dist/interpreter.d.ts.map +1 -0
  57. package/dist/interpreter.js +118 -0
  58. package/dist/interpreter.js.map +1 -0
  59. package/dist/invocation.d.ts +64 -0
  60. package/dist/invocation.d.ts.map +1 -0
  61. package/dist/invocation.js +148 -0
  62. package/dist/invocation.js.map +1 -0
  63. package/dist/link.d.ts +63 -0
  64. package/dist/link.d.ts.map +1 -0
  65. package/dist/link.js +172 -0
  66. package/dist/link.js.map +1 -0
  67. package/dist/markdown.d.ts +12 -0
  68. package/dist/markdown.d.ts.map +1 -0
  69. package/dist/markdown.js +63 -0
  70. package/dist/markdown.js.map +1 -0
  71. package/dist/normalize.md +68 -0
  72. package/dist/phase-runner.d.ts +64 -0
  73. package/dist/phase-runner.d.ts.map +1 -0
  74. package/dist/phase-runner.js +322 -0
  75. package/dist/phase-runner.js.map +1 -0
  76. package/dist/phase.d.ts +62 -0
  77. package/dist/phase.d.ts.map +1 -0
  78. package/dist/phase.js +111 -0
  79. package/dist/phase.js.map +1 -0
  80. package/dist/pin-closure.d.ts +19 -0
  81. package/dist/pin-closure.d.ts.map +1 -0
  82. package/dist/pin-closure.js +110 -0
  83. package/dist/pin-closure.js.map +1 -0
  84. package/dist/pin-currency.d.ts +55 -0
  85. package/dist/pin-currency.d.ts.map +1 -0
  86. package/dist/pin-currency.js +435 -0
  87. package/dist/pin-currency.js.map +1 -0
  88. package/dist/pin-generate.d.ts +46 -0
  89. package/dist/pin-generate.d.ts.map +1 -0
  90. package/dist/pin-generate.js +131 -0
  91. package/dist/pin-generate.js.map +1 -0
  92. package/dist/pin-paths.d.ts +11 -0
  93. package/dist/pin-paths.d.ts.map +1 -0
  94. package/dist/pin-paths.js +108 -0
  95. package/dist/pin-paths.js.map +1 -0
  96. package/dist/pins.d.ts +84 -0
  97. package/dist/pins.d.ts.map +1 -0
  98. package/dist/pins.js +265 -0
  99. package/dist/pins.js.map +1 -0
  100. package/dist/pipeline.d.ts +61 -0
  101. package/dist/pipeline.d.ts.map +1 -0
  102. package/dist/pipeline.js +147 -0
  103. package/dist/pipeline.js.map +1 -0
  104. package/dist/playbook-contract.d.ts +194 -0
  105. package/dist/playbook-contract.d.ts.map +1 -0
  106. package/dist/playbook-contract.js +180 -0
  107. package/dist/playbook-contract.js.map +1 -0
  108. package/dist/playbook-ports.d.ts +53 -0
  109. package/dist/playbook-ports.d.ts.map +1 -0
  110. package/dist/playbook-ports.js +217 -0
  111. package/dist/playbook-ports.js.map +1 -0
  112. package/dist/resolver.d.ts +68 -0
  113. package/dist/resolver.d.ts.map +1 -0
  114. package/dist/resolver.js +133 -0
  115. package/dist/resolver.js.map +1 -0
  116. package/dist/runner.d.ts +45 -0
  117. package/dist/runner.d.ts.map +1 -0
  118. package/dist/runner.js +506 -0
  119. package/dist/runner.js.map +1 -0
  120. package/dist/runtime-package.d.ts +7 -0
  121. package/dist/runtime-package.d.ts.map +1 -0
  122. package/dist/runtime-package.js +132 -0
  123. package/dist/runtime-package.js.map +1 -0
  124. package/dist/slc.config.template.yaml +5 -0
  125. package/dist/verify-coverage.d.ts +99 -0
  126. package/dist/verify-coverage.d.ts.map +1 -0
  127. package/dist/verify-coverage.js +1949 -0
  128. package/dist/verify-coverage.js.map +1 -0
  129. package/dist/verify-support.d.ts +10 -0
  130. package/dist/verify-support.d.ts.map +1 -0
  131. package/dist/verify-support.js +52 -0
  132. package/dist/verify-support.js.map +1 -0
  133. package/dist/verify.d.ts +393 -0
  134. package/dist/verify.d.ts.map +1 -0
  135. package/dist/verify.js +1790 -0
  136. package/dist/verify.js.map +1 -0
  137. package/package.json +76 -0
@@ -0,0 +1,433 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
+ /**
4
+ * Compiled phase execution: load a `playbook` artifact and drive it host-side
5
+ * (PHEXEC-23, PHEXEC-24, PHEXEC-25; DR-005).
6
+ *
7
+ * {@link loadPlaybookRuntime} imports a compiled `playbook` module and returns
8
+ * its `createPlaybookRuntime` factory. {@link createCompiledExecutor} adapts it
9
+ * to the DR-003 {@link PhaseExecutor} boundary: per run it builds the
10
+ * Cligent-backed Playbook ports, constructs the runtime, drives one
11
+ * non-interactive turn (`init` -> `handleBossInput` -> `dispose`), and maps a
12
+ * structured result when present or the bounded legacy host-observable outcome
13
+ * otherwise. The pin-selected contract profile chooses the exact legacy,
14
+ * traced-session, or composed-session init shape without a retry heuristic
15
+ * (DR-010, DR-011). The host-only `drainDiagnostics` stays host-side;
16
+ * human status and non-trace operational telemetry become diagnostics. Like
17
+ * interpreted execution, a compiled phase writes through its agents
18
+ * (`callPlayer`) and relies on the DR-003 generic checks, which defend the
19
+ * protected inputs (not the full write scope); `slc` adds no host-side
20
+ * write-scope enforcement.
21
+ *
22
+ * The turn is seeded per the PHEXEC-29 contract ({@link seedPhaseTurn}), and a
23
+ * transformation-performing direct Captain call additionally carries the host
24
+ * workspace contract ({@link composeWorkspaceContract}; PHEXEC-34) so the
25
+ * host-agnostic artifact's Captain learns the request's absolute paths; the
26
+ * result is derived in {@link drivePhase} from the structured runtime boundary
27
+ * or, for a void-result legacy runtime, the host-observable output delta.
28
+ * See specs/dev/phase-execution.md.
29
+ */
30
+ import { createHash, randomUUID } from 'node:crypto';
31
+ import { readFile, stat } from 'node:fs/promises';
32
+ import { basename, resolve } from 'node:path';
33
+ import { pathToFileURL } from 'node:url';
34
+ import { composeWorkspaceContract, mapPhaseResult, seedPhaseTurn, } from './phase-runner.js';
35
+ import { isPlaybookRunResult, } from './playbook-contract.js';
36
+ import { createPlaybookPorts } from './playbook-ports.js';
37
+ /**
38
+ * Imports a compiled `playbook` module and returns its runtime factory
39
+ * (PHEXEC-23).
40
+ *
41
+ * @throws when the module has no callable `createPlaybookRuntime` default export.
42
+ */
43
+ export async function loadPlaybookRuntime(artifactPath) {
44
+ const module = await import(pathToFileURL(resolve(artifactPath)).href);
45
+ const create = module.default;
46
+ if (typeof create !== 'function') {
47
+ throw new Error(`compiled artifact "${artifactPath}" has no createPlaybookRuntime default export`);
48
+ }
49
+ return create;
50
+ }
51
+ /**
52
+ * Adapts a compiled `playbook` artifact to the {@link PhaseExecutor} boundary
53
+ * (PHEXEC-24, PHEXEC-25): build the Cligent-backed Playbook ports, load and
54
+ * construct the runtime, drive one non-interactive root-session turn, and map
55
+ * the outcome, appending drained status and non-trace operational telemetry.
56
+ */
57
+ export function createCompiledExecutor(opts) {
58
+ const load = opts.loadFactory ?? loadPlaybookRuntime;
59
+ return {
60
+ async run(request, signal) {
61
+ let lastFsmState;
62
+ const input = phaseInput(request, opts.runRoot);
63
+ const adapter = createPlaybookPorts({
64
+ player: opts.player,
65
+ judge: opts.judge,
66
+ models: opts.models,
67
+ defaultModel: opts.defaultModel,
68
+ cwd: opts.cwd,
69
+ // The host owns the workspace: a transformation-performing Captain's
70
+ // transported prompt carries the request's absolute paths and
71
+ // write-scope rules (PHEXEC-34).
72
+ captainWorkspace: composeWorkspaceContract(input),
73
+ });
74
+ // Hand the runtime only Playbook's ports — never the host-only
75
+ // drainDiagnostics, nor a file capability (DR-005, PHEXEC-23).
76
+ const ports = {
77
+ callPlayer: adapter.callPlayer,
78
+ callCaptain: adapter.callCaptain,
79
+ callJudge: adapter.callJudge,
80
+ callPlaybook: adapter.callPlaybook,
81
+ emitStatus: adapter.emitStatus,
82
+ emitTelemetry: async (event) => {
83
+ const state = fsmTransitionTarget(event);
84
+ if (state !== undefined)
85
+ lastFsmState = state;
86
+ await adapter.emitTelemetry(event);
87
+ },
88
+ };
89
+ const runtimeContract = opts.runtimeContract ?? 'legacy';
90
+ const identity = phaseSessionIdentity({
91
+ sessionId: (opts.createSessionId ?? randomUUID)(),
92
+ playbookId: opts.playbookId ?? playbookIdFromArtifact(opts.artifactPath),
93
+ });
94
+ const driven = await drivePhase(load, opts.artifactPath, ports, input, signal, identity, runtimeContract);
95
+ const result = mapVoidContractFailedState(driven, lastFsmState, runtimeContract !== 'composed-v2');
96
+ const mapped = mapPhaseResult(result);
97
+ return {
98
+ status: mapped.status,
99
+ diagnostics: [...mapped.diagnostics, ...adapter.drainDiagnostics()],
100
+ };
101
+ },
102
+ };
103
+ }
104
+ /** Returns the destination carried by Playbook's standard FSM telemetry. */
105
+ function fsmTransitionTarget(event) {
106
+ if (event.topic !== 'playbook.fsm.state' ||
107
+ typeof event.payload !== 'object' ||
108
+ event.payload === null ||
109
+ !('to' in event.payload) ||
110
+ typeof event.payload.to !== 'string') {
111
+ return undefined;
112
+ }
113
+ return event.payload.to;
114
+ }
115
+ /** DR-005 maps a quiescent `failed` FSM state to an executor error. */
116
+ function mapVoidContractFailedState(result, lastFsmState, voidContract) {
117
+ if (!voidContract || result.status === 'error' || lastFsmState !== 'failed') {
118
+ return result;
119
+ }
120
+ return {
121
+ status: 'error',
122
+ diagnostics: ['compiled runtime reached the failed quiescent state'],
123
+ };
124
+ }
125
+ /**
126
+ * Loads, constructs, and drives one non-interactive turn. Structured results
127
+ * are authoritative; a void legacy result retains DR-010's output-delta and
128
+ * host-observed failed-state mapping.
129
+ */
130
+ async function drivePhase(load, artifactPath, ports, input, signal, identity, runtimeContract) {
131
+ let runtime;
132
+ try {
133
+ const factory = await load(artifactPath);
134
+ runtime = factory({});
135
+ }
136
+ catch (error) {
137
+ return {
138
+ status: 'error',
139
+ diagnostics: [`compiled artifact failed to load: ${messageOf(error)}`],
140
+ };
141
+ }
142
+ // Snapshot the output before the turn so a pre-existing stale artifact is not
143
+ // mistaken for fresh output the turn produced.
144
+ const outputPath = input.kind === 'compile' ? input.target : input.linked;
145
+ const before = await outputState(outputPath);
146
+ const initValue = runtimeInitValue(runtimeContract, identity, ports);
147
+ let runResult;
148
+ try {
149
+ await callRuntimeInit(runtime, initValue);
150
+ runResult = await callRuntimeTurn(runtime, seedPhaseTurn(input), signal);
151
+ }
152
+ catch (error) {
153
+ const disposal = await disposeRuntime(runtime);
154
+ return {
155
+ status: 'error',
156
+ diagnostics: [
157
+ signal.aborted
158
+ ? 'compiled run aborted'
159
+ : `compiled run failed: ${messageOf(error)}`,
160
+ ...(disposal === undefined
161
+ ? []
162
+ : [`compiled runtime disposal also failed: ${messageOf(disposal)}`]),
163
+ ],
164
+ };
165
+ }
166
+ const disposal = await disposeRuntime(runtime);
167
+ if (disposal !== undefined) {
168
+ return {
169
+ status: 'error',
170
+ diagnostics: [`compiled runtime disposal failed: ${messageOf(disposal)}`],
171
+ };
172
+ }
173
+ if (signal.aborted) {
174
+ return {
175
+ status: 'error',
176
+ diagnostics: ['compiled run aborted'],
177
+ };
178
+ }
179
+ const after = await outputState(outputPath);
180
+ const produced = outputWasProduced(before, after);
181
+ return mapRuntimeOutcome(runResult, produced, runtimeContract);
182
+ }
183
+ async function disposeRuntime(runtime) {
184
+ try {
185
+ await runtime.dispose();
186
+ return undefined;
187
+ }
188
+ catch (error) {
189
+ return error;
190
+ }
191
+ }
192
+ function rootSession(identity, ports) {
193
+ return {
194
+ sessionId: identity.sessionId,
195
+ playbookId: identity.playbookId,
196
+ rootSessionId: identity.sessionId,
197
+ depth: 0,
198
+ ports: composedPorts(ports),
199
+ };
200
+ }
201
+ function legacyPorts(ports) {
202
+ return {
203
+ callPlayer: ports.callPlayer,
204
+ callJudge: ports.callJudge,
205
+ emitStatus: ports.emitStatus,
206
+ emitTelemetry: ports.emitTelemetry,
207
+ };
208
+ }
209
+ function sessionV1Ports(ports) {
210
+ return {
211
+ callPlayer: (playerId, prompt, signal, options) => ports.callPlayer(playerId, prompt, signal, requirePlayerCallOptions(options)),
212
+ callJudge: ports.callJudge,
213
+ emitStatus: ports.emitStatus,
214
+ emitTelemetry: ports.emitTelemetry,
215
+ };
216
+ }
217
+ function composedPorts(ports) {
218
+ return {
219
+ callPlayer: (playerId, prompt, signal, options) => preserveControlPlaneRejection('callPlayer', signal, () => ports.callPlayer(playerId, prompt, signal, requirePlayerCallOptions(options))),
220
+ callCaptain: (prompt, signal, options) => preserveControlPlaneRejection('callCaptain', signal, () => ports.callCaptain(prompt, signal, options)),
221
+ callJudge: (prompt, signal) => preserveControlPlaneRejection('callJudge', signal, () => ports.callJudge(prompt, signal)),
222
+ callPlaybook: (request, signal) => preserveControlPlaneRejection('callPlaybook', signal, () => ports.callPlaybook(request, signal)),
223
+ emitStatus: (message, data) => preserveControlPlaneRejection('emitStatus', undefined, () => ports.emitStatus(message, data)),
224
+ emitTelemetry: (event) => preserveControlPlaneRejection('emitTelemetry', undefined, () => ports.emitTelemetry(event)),
225
+ };
226
+ }
227
+ /**
228
+ * Keeps nullish host-port rejections visible to immutable composed runtimes.
229
+ * Playbook 2.0.0 latches control-plane failures with nullish coalescing, so a
230
+ * rejection without a value could otherwise be mistaken for an authored FSM
231
+ * failure. Preserve a causally identical abort reason, but give every other
232
+ * nullish rejection a stable Error identity before it crosses the boundary.
233
+ */
234
+ async function preserveControlPlaneRejection(port, signal, call) {
235
+ try {
236
+ return await call();
237
+ }
238
+ catch (error) {
239
+ if (error !== undefined && error !== null) {
240
+ throw error;
241
+ }
242
+ if (signal?.aborted === true && error === signal.reason) {
243
+ throw error;
244
+ }
245
+ throw new Error(`compiled composed-v2 ${port} port rejected without an error`, { cause: error });
246
+ }
247
+ }
248
+ function requirePlayerCallOptions(value) {
249
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
250
+ throw new TypeError('session runtime callPlayer requires explicit PlayerCallOptions');
251
+ }
252
+ const descriptor = Object.getOwnPropertyDescriptor(value, 'resume');
253
+ if (descriptor === undefined ||
254
+ !Object.prototype.hasOwnProperty.call(descriptor, 'value') ||
255
+ (descriptor.value !== false && typeof descriptor.value !== 'string')) {
256
+ throw new TypeError('session runtime callPlayer options.resume must be false or a string');
257
+ }
258
+ return { resume: descriptor.value };
259
+ }
260
+ function runtimeInitValue(contract, identity, ports) {
261
+ switch (contract) {
262
+ case 'legacy':
263
+ return legacyPorts(ports);
264
+ case 'session-v1':
265
+ return {
266
+ sessionId: identity.sessionId,
267
+ playbookId: identity.playbookId,
268
+ ports: sessionV1Ports(ports),
269
+ };
270
+ case 'composed-v2':
271
+ return rootSession(identity, ports);
272
+ }
273
+ }
274
+ async function callRuntimeInit(runtime, value) {
275
+ const init = runtime.init;
276
+ await init.call(runtime, value);
277
+ }
278
+ async function callRuntimeTurn(runtime, text, signal) {
279
+ const handle = runtime.handleBossInput;
280
+ return handle.call(runtime, { text, signal });
281
+ }
282
+ function mapRuntimeOutcome(result, produced, contract) {
283
+ if (contract !== 'composed-v2') {
284
+ return result === undefined
285
+ ? legacyOutputResult(produced)
286
+ : {
287
+ status: 'error',
288
+ diagnostics: [
289
+ `compiled ${contract} runtime returned an unexpected structured result`,
290
+ ],
291
+ };
292
+ }
293
+ if (result === undefined) {
294
+ return {
295
+ status: 'error',
296
+ diagnostics: ['compiled composed-v2 runtime returned no run result'],
297
+ };
298
+ }
299
+ if (!isPlaybookRunResult(result)) {
300
+ return {
301
+ status: 'error',
302
+ diagnostics: ['compiled runtime returned an invalid run result'],
303
+ };
304
+ }
305
+ return structuredOutputResult(result, produced);
306
+ }
307
+ function phaseSessionIdentity(identity) {
308
+ if (identity.sessionId.trim().length === 0) {
309
+ throw new Error('compiled runtime session id must be non-empty');
310
+ }
311
+ if (identity.playbookId.trim().length === 0) {
312
+ throw new Error('compiled runtime playbook id must be non-empty');
313
+ }
314
+ return identity;
315
+ }
316
+ function legacyOutputResult(produced) {
317
+ return produced
318
+ ? { status: 'ok', diagnostics: [] }
319
+ : {
320
+ status: 'blocked',
321
+ diagnostics: [
322
+ 'compiled phase produced no output (parked for Boss input)',
323
+ ],
324
+ };
325
+ }
326
+ function structuredOutputResult(result, produced) {
327
+ switch (result.outcome) {
328
+ case 'quiescent':
329
+ case 'terminal':
330
+ return produced
331
+ ? { status: 'ok', diagnostics: [] }
332
+ : {
333
+ status: 'blocked',
334
+ diagnostics: [
335
+ `compiled runtime ${result.outcome} without producing output`,
336
+ ],
337
+ };
338
+ case 'no-action':
339
+ return {
340
+ status: 'blocked',
341
+ diagnostics: ['compiled runtime accepted no phase action'],
342
+ };
343
+ case 'failed':
344
+ case 'aborted':
345
+ return {
346
+ status: 'error',
347
+ diagnostics: [
348
+ `compiled runtime ${result.outcome}${result.error ? `: ${result.error.message}` : ''}`,
349
+ ],
350
+ };
351
+ case 'suspended':
352
+ return {
353
+ status: 'error',
354
+ diagnostics: [
355
+ `compiled runtime suspended for unsupported nested playbook call ${result.pendingCall.callId}`,
356
+ ],
357
+ };
358
+ }
359
+ }
360
+ function playbookIdFromArtifact(artifactPath) {
361
+ const name = basename(artifactPath);
362
+ return name.endsWith('.playbook.ts')
363
+ ? name.slice(0, -'.playbook.ts'.length)
364
+ : name.replace(/\.[^.]+$/, '');
365
+ }
366
+ /**
367
+ * A point-in-time output view. Content and file identity supplement timestamps,
368
+ * so an atomic replacement or preserved mtime still counts as produced output.
369
+ */
370
+ async function outputState(path) {
371
+ try {
372
+ const info = await stat(path);
373
+ const identity = {
374
+ dev: info.dev,
375
+ ino: info.ino,
376
+ mode: info.mode,
377
+ size: info.size,
378
+ mtimeMs: info.mtimeMs,
379
+ ctimeMs: info.ctimeMs,
380
+ };
381
+ if (!info.isFile())
382
+ return { kind: 'other', ...identity };
383
+ const digest = createHash('sha256')
384
+ .update(await readFile(path))
385
+ .digest('hex');
386
+ return { kind: 'file', digest, ...identity };
387
+ }
388
+ catch {
389
+ return { kind: 'missing' };
390
+ }
391
+ }
392
+ function outputWasProduced(before, after) {
393
+ if (after.kind !== 'file')
394
+ return false;
395
+ if (before.kind !== 'file')
396
+ return true;
397
+ return (before.digest !== after.digest ||
398
+ before.dev !== after.dev ||
399
+ before.ino !== after.ino ||
400
+ before.mode !== after.mode ||
401
+ before.size !== after.size ||
402
+ before.mtimeMs !== after.mtimeMs ||
403
+ before.ctimeMs !== after.ctimeMs);
404
+ }
405
+ /**
406
+ * Maps an {@link ExecuteRequest} to the {@link PhaseInput} the seed carries,
407
+ * resolving its workspace paths against the run root to absolute host paths the
408
+ * runtime's agents can act on (DR-005).
409
+ */
410
+ function phaseInput(request, runRoot) {
411
+ const abs = (path) => resolve(runRoot, path);
412
+ if (request.kind === 'compile') {
413
+ return {
414
+ kind: 'compile',
415
+ source: abs(request.source),
416
+ target: abs(request.target),
417
+ };
418
+ }
419
+ return {
420
+ kind: 'link',
421
+ objects: request.objects.map(abs),
422
+ linkTarget: abs(request.linkTarget),
423
+ options: optionsRecord(request.options),
424
+ linked: abs(request.linked),
425
+ };
426
+ }
427
+ function optionsRecord(options) {
428
+ return Object.fromEntries(options.map((option) => [option.name, option.value]));
429
+ }
430
+ function messageOf(error) {
431
+ return error instanceof Error ? error.message : String(error);
432
+ }
433
+ //# sourceMappingURL=compiled-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiled-executor.js","sourceRoot":"","sources":["../src/compiled-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /** Config-file basename discovered in the working directory (DR-006). */
2
+ export declare const CONFIG_FILE = "slc.config.yaml";
3
+ /** Config-file path under the user config home (DR-006). */
4
+ export declare const HOME_CONFIG: string;
5
+ /** Partial cligent-invocation selection loaded from a config file (DR-006). */
6
+ export interface FileConfig {
7
+ agent?: string;
8
+ model?: string;
9
+ effort?: string;
10
+ pipelinePath?: string[];
11
+ }
12
+ /**
13
+ * A loaded config file: the parsed {@link FileConfig} plus the resolved file
14
+ * path, or `path: undefined` on a discovery miss (no file loaded).
15
+ */
16
+ export interface LoadedFileConfig {
17
+ path?: string;
18
+ config: FileConfig;
19
+ }
20
+ /** Injectable IO for {@link loadConfigFile}; all fields default to the process. */
21
+ export interface LoadConfigFileOptions {
22
+ cwd?: string;
23
+ /** Explicit `--config <path>`: disables discovery and errors when absent (CLI-20, CLI-21). */
24
+ configPath?: string;
25
+ /** User config home; defaults to `${XDG_CONFIG_HOME:-~/.config}`. Injectable for tests. */
26
+ configHome?: string;
27
+ /** Environment for resolving `XDG_CONFIG_HOME`; defaults to `process.env`. */
28
+ env?: Record<string, string | undefined>;
29
+ /** Called with the created path when a discovery miss seeds the user config (DR-015, CLI-30). */
30
+ onSeed?: (path: string) => void;
31
+ }
32
+ /** Machine-readable reason a config file was rejected (CLI-21). */
33
+ export type ConfigFileErrorCode = 'config-not-found' | 'config-parse' | 'config-invalid';
34
+ /** Raised when an explicit `--config` file is missing, malformed, or invalid (CLI-21). */
35
+ export declare class ConfigFileError extends Error {
36
+ readonly code: ConfigFileErrorCode;
37
+ constructor(code: ConfigFileErrorCode, message: string);
38
+ }
39
+ /**
40
+ * Loads the slc config file (DR-006, CLI-20, CLI-21).
41
+ *
42
+ * Resolves the file via an explicit `--config` path or cwd/home discovery,
43
+ * parses and validates it, and returns the partial selection plus the resolved
44
+ * path. A discovery miss returns `{ config: {} }` so the caller falls through to
45
+ * the environment and built-in defaults.
46
+ *
47
+ * @throws {ConfigFileError} when an explicit `--config` path is absent
48
+ * (`config-not-found`), the file is unreadable or malformed YAML
49
+ * (`config-parse`), or it violates the flat schema (`config-invalid`).
50
+ */
51
+ export declare function loadConfigFile(options?: LoadConfigFileOptions): Promise<LoadedFileConfig>;
52
+ //# sourceMappingURL=config-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"AA2BA,yEAAyE;AACzE,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,4DAA4D;AAC5D,eAAO,MAAM,WAAW,QAA6B,CAAC;AAOtD,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,iGAAiG;IACjG,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,mEAAmE;AACnE,MAAM,MAAM,mBAAmB,GAC3B,kBAAkB,GAClB,cAAc,GACd,gBAAgB,CAAC;AAErB,0FAA0F;AAC1F,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;gBAEvB,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM;CAKvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAQ3B"}
@@ -0,0 +1,159 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
+ /**
4
+ * Config-file loader for the `slc` bin (DR-006, CLI-20, CLI-21).
5
+ *
6
+ * Discovers and parses the optional YAML config file that supplies the
7
+ * cligent-invocation defaults — `agent`, `model`, `effort`, and `pipelinePath` — which the
8
+ * environment then overrides (DR-006). Discovery reads `slc.config.yaml` in the
9
+ * working directory, then `${XDG_CONFIG_HOME:-~/.config}/slc/config.yaml`; an
10
+ * explicit `--config` path disables discovery and is an error when absent, while
11
+ * a discovery miss returns an empty result that falls through to the environment
12
+ * and defaults. The loader validates a flat schema and rejects unknown keys and
13
+ * mistyped values; the supported-agent check stays with `resolveAgentSelection`
14
+ * so the agent set keeps a single source of truth. Relative `pipelinePath`
15
+ * entries are returned verbatim and resolved against the cwd downstream
16
+ * (CLI-6). See specs/dev/cli.md.
17
+ */
18
+ import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
19
+ import { readFile } from 'node:fs/promises';
20
+ import { homedir } from 'node:os';
21
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { parse } from 'yaml';
24
+ /** Config-file basename discovered in the working directory (DR-006). */
25
+ export const CONFIG_FILE = 'slc.config.yaml';
26
+ /** Config-file path under the user config home (DR-006). */
27
+ export const HOME_CONFIG = join('slc', 'config.yaml');
28
+ /** Bundled starter template seeded into the user config home on a discovery miss (DR-015). */
29
+ const TEMPLATE_PATH = fileURLToPath(new URL('./slc.config.template.yaml', import.meta.url));
30
+ /** Raised when an explicit `--config` file is missing, malformed, or invalid (CLI-21). */
31
+ export class ConfigFileError extends Error {
32
+ code;
33
+ constructor(code, message) {
34
+ super(message);
35
+ this.name = 'ConfigFileError';
36
+ this.code = code;
37
+ }
38
+ }
39
+ /**
40
+ * Loads the slc config file (DR-006, CLI-20, CLI-21).
41
+ *
42
+ * Resolves the file via an explicit `--config` path or cwd/home discovery,
43
+ * parses and validates it, and returns the partial selection plus the resolved
44
+ * path. A discovery miss returns `{ config: {} }` so the caller falls through to
45
+ * the environment and built-in defaults.
46
+ *
47
+ * @throws {ConfigFileError} when an explicit `--config` path is absent
48
+ * (`config-not-found`), the file is unreadable or malformed YAML
49
+ * (`config-parse`), or it violates the flat schema (`config-invalid`).
50
+ */
51
+ export async function loadConfigFile(options = {}) {
52
+ const cwd = options.cwd ?? process.cwd();
53
+ const path = resolveConfigPath(options, cwd);
54
+ if (path === undefined) {
55
+ return { config: {} };
56
+ }
57
+ const config = await readConfigFile(path);
58
+ return { path, config };
59
+ }
60
+ function resolveConfigPath(options, cwd) {
61
+ if (options.configPath !== undefined) {
62
+ const explicit = isAbsolute(options.configPath)
63
+ ? options.configPath
64
+ : resolve(cwd, options.configPath);
65
+ if (!existsSync(explicit)) {
66
+ throw new ConfigFileError('config-not-found', `--config file not found: ${options.configPath}`);
67
+ }
68
+ return explicit;
69
+ }
70
+ const cwdConfig = resolve(cwd, CONFIG_FILE);
71
+ if (existsSync(cwdConfig)) {
72
+ return cwdConfig;
73
+ }
74
+ const homeConfig = join(configHome(options), HOME_CONFIG);
75
+ if (existsSync(homeConfig)) {
76
+ return homeConfig;
77
+ }
78
+ // First run: neither discovered file exists, so seed the user config from
79
+ // the bundled starter and load it (DR-015, CLI-30).
80
+ mkdirSync(dirname(homeConfig), { recursive: true });
81
+ copyFileSync(TEMPLATE_PATH, homeConfig);
82
+ options.onSeed?.(homeConfig);
83
+ return homeConfig;
84
+ }
85
+ function configHome(options) {
86
+ if (options.configHome !== undefined) {
87
+ return options.configHome;
88
+ }
89
+ const env = options.env ?? process.env;
90
+ const xdg = (env.XDG_CONFIG_HOME ?? '').trim();
91
+ return xdg !== '' ? xdg : join(homedir(), '.config');
92
+ }
93
+ async function readConfigFile(path) {
94
+ let source;
95
+ try {
96
+ source = await readFile(path, 'utf8');
97
+ }
98
+ catch (error) {
99
+ throw new ConfigFileError('config-parse', `Failed to read config file ${path}: ${messageOf(error)}`);
100
+ }
101
+ let raw;
102
+ try {
103
+ raw = parse(source);
104
+ }
105
+ catch (error) {
106
+ throw new ConfigFileError('config-parse', `Failed to parse config file ${path}: ${messageOf(error)}`);
107
+ }
108
+ return normalizeFileConfig(raw, path);
109
+ }
110
+ const ALLOWED_KEYS = new Set(['agent', 'model', 'effort', 'pipelinePath']);
111
+ function normalizeFileConfig(value, path) {
112
+ if (value === null || value === undefined) {
113
+ return {};
114
+ }
115
+ if (typeof value !== 'object' || Array.isArray(value)) {
116
+ throw new ConfigFileError('config-invalid', `Config file ${path} must contain a mapping of keys to values`);
117
+ }
118
+ const input = value;
119
+ for (const key of Object.keys(input)) {
120
+ if (!ALLOWED_KEYS.has(key)) {
121
+ throw new ConfigFileError('config-invalid', `Unknown config key "${key}" in ${path}; allowed keys: agent, model, effort, pipelinePath`);
122
+ }
123
+ }
124
+ const config = {};
125
+ if (input.agent !== undefined) {
126
+ config.agent = requireString(input.agent, 'agent', path);
127
+ }
128
+ if (input.model !== undefined) {
129
+ config.model = requireString(input.model, 'model', path);
130
+ }
131
+ if (input.effort !== undefined) {
132
+ config.effort = requireString(input.effort, 'effort', path);
133
+ }
134
+ if (input.pipelinePath !== undefined) {
135
+ config.pipelinePath = requireStringArray(input.pipelinePath, 'pipelinePath', path);
136
+ }
137
+ return config;
138
+ }
139
+ function requireString(value, key, path) {
140
+ if (typeof value !== 'string' || value.trim() === '') {
141
+ throw new ConfigFileError('config-invalid', `Config key "${key}" in ${path} must be a non-empty string`);
142
+ }
143
+ return value;
144
+ }
145
+ function requireStringArray(value, key, path) {
146
+ if (!Array.isArray(value)) {
147
+ throw new ConfigFileError('config-invalid', `Config key "${key}" in ${path} must be a sequence of strings`);
148
+ }
149
+ return value.map((entry, index) => {
150
+ if (typeof entry !== 'string' || entry.trim() === '') {
151
+ throw new ConfigFileError('config-invalid', `Config key "${key}[${index}]" in ${path} must be a non-empty string`);
152
+ }
153
+ return entry;
154
+ });
155
+ }
156
+ function messageOf(error) {
157
+ return error instanceof Error ? error.message : String(error);
158
+ }
159
+ //# sourceMappingURL=config-file.js.map