@almadar/shell-node 0.1.0 → 1.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.
@@ -6,9 +6,9 @@ import { tmpdir } from 'os';
6
6
  import { relative, resolve, isAbsolute, sep, join } from 'path';
7
7
  import { z } from 'zod';
8
8
  import { createLogger } from '@almadar/logger';
9
+ import { decodeProveReport, decodeOsGrantsReport, decodeValidationJsonOutput, isStepRefusal, decodeStepRefusal, decodePlayedStep } from '@almadar/core/kernel-wire';
9
10
  import { resolveOrbBinary, discoverBehaviorPackages } from '@almadar/core/behavior-package';
10
- import { EventPayloadSchema, SExprSchema, CatalogEntrySchema, formatTraitValueLiteral, BehaviorDescriptionSchema, mergeCallSiteConfigOverrides, isRoutePage, defaultPage, importsOf, dependencyGraphOf, DescribeTargetSchema, CatalogScopeSchema, parseProgram, ProgramInspectionSchema, TraitDescriptionSchema } from '@almadar/core';
11
- import { composeAppFromFiles, orbitalImportResolver, atomTraitResolver, organismOrderResolver } from '@almadar/core/builders';
11
+ import { EventPayloadSchema, CatalogEntrySchema, formatTraitValueLiteral, BehaviorDescriptionSchema, importsOf, dependencyGraphOf, DescribeTargetSchema, CatalogScopeSchema, parseProgram, ProgramInspectionSchema, TraitDescriptionSchema } from '@almadar/core';
12
12
 
13
13
  var log = createLogger("almadar:integrations:program");
14
14
  function runOrb(args, opts) {
@@ -44,6 +44,17 @@ function parseJson(schema, run, what) {
44
44
  if (!parsed.success) throw new Error(`${what}: unexpected orb output: ${parsed.error.message}`);
45
45
  return parsed.data;
46
46
  }
47
+ function decodeJson(decode, run, what) {
48
+ if (run.code !== 0) throw new Error(`${what}: orb exited ${run.code}: ${run.stderr.trim()}`);
49
+ try {
50
+ return decode(JSON.parse(run.stdout));
51
+ } catch (error) {
52
+ throw new Error(`${what}: unexpected orb output: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ }
55
+ function issueOf(finding) {
56
+ return { code: finding.code, message: finding.message, path: finding.path, ...finding.line !== void 0 ? { line: finding.line } : {}, ...finding.column !== void 0 ? { column: finding.column } : {} };
57
+ }
47
58
  function withTempFile(name, content, use) {
48
59
  const dir = mkdtempSync(join(tmpdir(), "almadar-program-"));
49
60
  const path = join(dir, name);
@@ -57,33 +68,33 @@ function withProjectFile(cwd, name, content, use) {
57
68
  }
58
69
  async function behaviorCatalog(scope, opts, options = {}) {
59
70
  const exposure = (scope.exposure ?? []).flatMap((e) => ["--exposure", e]);
60
- const noVectors = options.vectors === false ? ["--no-vectors"] : [];
61
- const run = await runOrb(["behaviors", "catalog", "--json", ...noVectors, ...scope.paths, ...exposure], opts);
71
+ const noTraits = options.traits === false ? ["--no-traits"] : [];
72
+ const run = await runOrb(["behaviors", "catalog", "--json", ...noTraits, ...scope.paths, ...exposure], opts);
62
73
  return parseJson(CatalogEntrySchema.array(), run, "behavior/catalog");
63
74
  }
64
75
  function behaviorCatalogSync(scope, opts) {
65
76
  const exposure = (scope.exposure ?? []).flatMap((e) => ["--exposure", e]);
66
77
  return parseJson(CatalogEntrySchema.array(), runOrbSync(["behaviors", "catalog", "--json", ...scope.paths, ...exposure], opts), "behavior/catalog");
67
78
  }
68
- async function behaviorDescribe(value, opts, options = {}) {
69
- const knobVectors = options.knobVectors === true ? ["--knob-vectors"] : [];
79
+ async function behaviorDescribe(value, opts) {
70
80
  if ("trait" in value) {
71
- const run = await runOrb(["behaviors", "describe", "--json", ...knobVectors, formatTraitValueLiteral(value)], opts);
81
+ const run = await runOrb(["behaviors", "describe", "--json", formatTraitValueLiteral(value)], opts);
72
82
  return parseJson(TraitDescriptionSchema, run, "behavior/describe");
73
83
  }
74
84
  const spec = "orbital" in value ? `${value.behavior}.orbitals.${value.orbital}` : value.behavior;
75
- return parseJson(BehaviorDescriptionSchema, await runOrb(["behaviors", "describe", "--json", ...knobVectors, spec], opts), "behavior/describe");
85
+ return parseJson(BehaviorDescriptionSchema, await runOrb(["behaviors", "describe", "--json", spec], opts), "behavior/describe");
76
86
  }
77
- function booleanOption(op, raw, key) {
87
+ function booleanOptions(op, raw, keys) {
78
88
  const options = raw ?? {};
79
89
  if (options === null || typeof options !== "object" || Array.isArray(options)) return `${op}: options must be an object`;
80
- let value;
90
+ const out = {};
81
91
  for (const [k, v] of Object.entries(options)) {
82
- if (k !== key) return `${op}: unsupported option "${k}"`;
83
- if (typeof v !== "boolean") return `${op}: ${key} must be a boolean`;
84
- value = v;
92
+ const key = keys.find((known) => known === k);
93
+ if (key === void 0) return `${op}: unsupported option "${k}"`;
94
+ if (typeof v !== "boolean") return `${op}: ${k} must be a boolean`;
95
+ out[key] = v;
85
96
  }
86
- return value === void 0 ? {} : { value };
97
+ return out;
87
98
  }
88
99
  async function behaviorSource(value, opts) {
89
100
  const run = await runOrb(["behaviors", "source", "--json", value.behavior], opts);
@@ -102,8 +113,8 @@ async function programReadOutcome(text, opts) {
102
113
  if (run.code !== 0) return fail(`program/read: orb exited ${run.code}: ${run.stderr.trim()}`);
103
114
  const parsed = ProgramParser.safeParse(JSON.parse(run.stdout));
104
115
  if (parsed.success) return { ok: true, result: parsed.data };
105
- const report = parseJson(ValidateReportSchema, await runOrb(["validate", "--json", "--deny-warnings", path], opts), "program/read");
106
- const issues = [...report.errors ?? [], ...report.warnings ?? []];
116
+ const report = decodeJson(decodeValidationJsonOutput, await runOrb(["validate", "--json", "--deny-warnings", path], opts), "program/read");
117
+ const issues = [...report.errors ?? [], ...report.warnings ?? []].map(issueOf);
107
118
  if (issues.length === 0) return fail(`program/read: not a program: ${parsed.error.message}`);
108
119
  return { ok: false, error: `program/read: ${issues.length} validation issue(s): ${issues.map((e) => e.message).join("; ")}`, errors: issues };
109
120
  });
@@ -129,18 +140,6 @@ function programPrint(program, opts) {
129
140
  return run.stdout;
130
141
  });
131
142
  }
132
- var IssueSchema = z.object({
133
- code: z.string(),
134
- message: z.string(),
135
- path: z.string().optional(),
136
- line: z.number().optional(),
137
- column: z.number().optional()
138
- });
139
- var ValidateReportSchema = z.object({
140
- valid: z.boolean(),
141
- errors: z.array(IssueSchema).optional(),
142
- warnings: z.array(IssueSchema).optional()
143
- });
144
143
  function workspaceAccessError(behavior, opts, context) {
145
144
  const host = installedWorkspaceHost();
146
145
  if (host === null || !behavior.startsWith("./")) return void 0;
@@ -169,9 +168,9 @@ async function stampAndValidate(program, opts, dir, caller) {
169
168
  return { ok: false, errors: [{ code: "PROGRAM_STAMP_FAILED", message: stamp.stderr.trim() }] };
170
169
  }
171
170
  const validateArgs = ["validate", "--json", "--deny-warnings", ...opts.final === true ? ["--final"] : [], stamped];
172
- const report = parseJson(ValidateReportSchema, await runOrb(validateArgs, opts), caller);
173
- const errors = report.errors ?? [];
174
- const warnings = report.warnings ?? [];
171
+ const report = decodeJson(decodeValidationJsonOutput, await runOrb(validateArgs, opts), caller);
172
+ const errors = (report.errors ?? []).map(issueOf);
173
+ const warnings = (report.warnings ?? []).map(issueOf);
175
174
  return { ok: true, stamped, errors, warnings, valid: report.valid && errors.length === 0 && warnings.length === 0 };
176
175
  }
177
176
  async function programValidate(program, opts) {
@@ -183,6 +182,17 @@ async function programValidate(program, opts) {
183
182
  rmSync(dir, { recursive: true, force: true });
184
183
  }
185
184
  }
185
+ async function programProve(target, opts) {
186
+ if ("path" in target) return decodeJson(decodeProveReport, await runOrb(["prove", target.path], opts), "program/prove");
187
+ if (!PROGRAM_NAME.test(target.program.name)) throw new Error(`program/prove: program name "${target.program.name}" is not a file name`);
188
+ return withTempFile(`${target.program.name}.orb`, JSON.stringify(target.program), async (file) => decodeJson(decodeProveReport, await runOrb(["prove", file], opts), "program/prove"));
189
+ }
190
+ async function programOsGrants(target, opts) {
191
+ const flags = opts.final === true ? ["--final"] : [];
192
+ if ("path" in target) return decodeJson(decodeOsGrantsReport, await runOrb(["os-grants", target.path, ...flags], opts), "program/os-grants");
193
+ if (!PROGRAM_NAME.test(target.program.name)) throw new Error(`program/os-grants: program name "${target.program.name}" is not a file name`);
194
+ return withTempFile(`${target.program.name}.orb`, JSON.stringify(target.program), async (file) => decodeJson(decodeOsGrantsReport, await runOrb(["os-grants", file, ...flags], opts), "program/os-grants"));
195
+ }
186
196
  async function programEval(program, opts) {
187
197
  const dir = mkdtempSync(join(tmpdir(), "almadar-eval-"));
188
198
  try {
@@ -224,92 +234,24 @@ async function programEval(program, opts) {
224
234
  }
225
235
  }
226
236
  var LAYOUT_STRATEGIES = ["sidebar", "tabs", "dashboard", "wizard-flow", "single"];
227
- function importSource(orbital) {
228
- const ref = orbital.reference?.ref;
229
- if (ref === void 0) return void 0;
230
- const [alias, kind, name] = ref.split(".");
231
- if (kind !== "orbitals" || name === void 0) return void 0;
232
- const use = (orbital.uses ?? []).find((u) => u.as === alias);
233
- return use === void 0 ? void 0 : { from: use.from, orbital: name };
234
- }
235
- var behaviorName = (from) => from.split("/").pop() ?? from;
236
237
  async function programCompose(programs, options, opts) {
237
- const sources = /* @__PURE__ */ new Set();
238
- for (const program of programs) {
239
- for (const orbital of program.orbitals) for (const use of orbital.uses ?? []) sources.add(use.from);
240
- }
241
- const loaded = /* @__PURE__ */ new Map();
242
- for (const from of sources) loaded.set(behaviorName(from), await behaviorSource({ behavior: from }, opts));
243
- const load = (name) => loaded.get(name) ?? null;
244
- const byName = /* @__PURE__ */ new Map();
245
- for (const program of programs) for (const orbital of program.orbitals) byName.set(orbital.name, orbital);
246
- const catalogOrbitalOf = (name) => {
247
- const orbital = byName.get(name);
248
- const source = orbital === void 0 ? void 0 : importSource(orbital);
249
- return source === void 0 ? void 0 : { organism: behaviorName(source.from), orbital: source.orbital };
250
- };
251
- const composed = composeAppFromFiles(programs, {
252
- appName: options.appName,
253
- ...options.layout !== void 0 ? { layoutStrategy: options.layout } : {},
254
- organismOf: (name) => catalogOrbitalOf(name)?.organism,
255
- organismOrderOf: organismOrderResolver(catalogOrbitalOf, load),
256
- atomTraitOf: atomTraitResolver(load),
257
- importedOrbitalOf: orbitalImportResolver(load),
258
- importedProgramOf: (orbital) => {
259
- const source = importSource(orbital);
260
- return source === void 0 ? void 0 : load(behaviorName(source.from)) ?? void 0;
261
- }
262
- });
263
- return options.theme !== void 0 ? { ...composed.schema, theme: options.theme } : composed.schema;
264
- }
265
- async function mountTraitValue(value, opts, context) {
266
- const denied = workspaceAccessError(value.behavior, opts, context);
267
- if (denied !== void 0) return { ok: false, error: denied };
268
- let source;
238
+ const dir = mkdtempSync(join(tmpdir(), "almadar-compose-"));
269
239
  try {
270
- source = await behaviorSource(value, opts);
271
- } catch (error) {
272
- return { ok: false, error: error instanceof Error ? error.message : String(error) };
273
- }
274
- const owner = source.orbitals.find(
275
- (o) => o.traits.some((t) => typeof t === "object" && !("ref" in t) && t.name === value.trait)
276
- );
277
- if (owner === void 0) {
278
- return { ok: false, error: `behavior "${value.behavior}" declares no inline trait "${value.trait}"` };
240
+ const files = programs.map((program, index) => {
241
+ const file = join(dir, `${index}.orb`);
242
+ writeFileSync(file, JSON.stringify(program));
243
+ return file;
244
+ });
245
+ const flags = [
246
+ "--app-name",
247
+ options.appName,
248
+ ...options.layout !== void 0 ? ["--layout", options.layout] : [],
249
+ ...options.theme !== void 0 ? ["--theme", options.theme] : []
250
+ ];
251
+ return parseJson(ProgramParser, await runOrb(["compose", ...flags, ...files], opts), "program/compose");
252
+ } finally {
253
+ rmSync(dir, { recursive: true, force: true });
279
254
  }
280
- const { behavior, trait, config, ...rest } = value;
281
- const overrides = config !== void 0 ? { ...rest, config: mergeCallSiteConfigOverrides({}, config) } : rest;
282
- const projectRelative = behavior.startsWith("./");
283
- const page = (owner.pages ?? []).find((p) => typeof p === "object" && "path" in p && isRoutePage(p) && (p.traits ?? []).some((t) => (typeof t === "string" ? t : "ref" in t ? t.ref : t.name) === trait));
284
- const wrapper = {
285
- name: `Mount${trait}`,
286
- orbitals: [
287
- {
288
- name: "Mounted",
289
- entity: `Bound.orbitals.${owner.name}.entity`,
290
- reference: {
291
- ref: `Bound.orbitals.${owner.name}`,
292
- only: [trait],
293
- ...Object.keys(overrides).length > 0 ? { traits: { [trait]: overrides } } : {}
294
- },
295
- traits: [],
296
- pages: [],
297
- uses: [{ as: "Bound", from: behavior }]
298
- }
299
- ]
300
- };
301
- const check = async (path) => {
302
- const report = parseJson(ValidateReportSchema, await runOrb(["validate", "--json", "--deny-warnings", path], opts), "mount");
303
- const issues = [...report.errors ?? [], ...report.warnings ?? []];
304
- if (!report.valid || issues.length > 0) {
305
- return { ok: false, error: `trait value ${formatTraitValueLiteral(value)} does not validate where it is bound`, errors: issues };
306
- }
307
- const schema = parseJson(ProgramParser, await runOrb(["resolve", path], opts), "mount");
308
- const pagePath = page !== void 0 && typeof page === "object" && "path" in page ? page.path : void 0;
309
- return { ok: true, mounted: { schema, orbital: "Mounted", trait: `Mounted${trait}`, ...pagePath !== void 0 ? { pagePath } : {} } };
310
- };
311
- const text = JSON.stringify(wrapper);
312
- return projectRelative ? withProjectFile(opts.cwd, "mount.orb", text, check) : withTempFile("mount.orb", text, check);
313
255
  }
314
256
  var WHICH_LINE = /^(\/\S+\.(?:orb|lolo)) \((.+)\)$/;
315
257
  async function behaviorFile(behavior, opts) {
@@ -323,21 +265,6 @@ async function behaviorFile(behavior, opts) {
323
265
  if (run.code !== 0 || match === null) return { error: `behavior "${behavior}" is not installed${run.stderr.trim() ? `: ${run.stderr.trim()}` : ""}` };
324
266
  return match[1];
325
267
  }
326
- async function mountBehaviorValue(value, opts, context) {
327
- const denied = workspaceAccessError(value.behavior, opts, context);
328
- if (denied !== void 0) return { ok: false, error: denied };
329
- const file = await behaviorFile(value.behavior, opts);
330
- if (typeof file !== "string") return { ok: false, error: file.error };
331
- const report = parseJson(ValidateReportSchema, await runOrb(["validate", "--json", "--deny-warnings", file], opts), "mount");
332
- const issues = [...report.errors ?? [], ...report.warnings ?? []];
333
- if (!report.valid || issues.length > 0) {
334
- return { ok: false, error: `behavior ${value.behavior} does not validate`, errors: issues };
335
- }
336
- const schema = parseJson(ProgramParser, await runOrb(["resolve", file], opts), "mount");
337
- const firstPage = defaultPage(schema)?.page.path;
338
- if (firstPage === void 0) return { ok: false, error: `behavior ${value.behavior} has no page to open` };
339
- return { ok: true, mounted: { schema, firstPage } };
340
- }
341
268
  async function programResolve(path, opts) {
342
269
  return parseJson(ProgramParser, await runOrb(["resolve", path], opts), "program/resolve");
343
270
  }
@@ -395,57 +322,26 @@ var StepRequestSchema = z.object({
395
322
  config: EventPayloadSchema.optional(),
396
323
  now: z.number().optional(),
397
324
  settleMs: z.number().optional(),
398
- viewer: EventPayloadSchema.nullable().optional()
325
+ identity: z.object({ subject: z.string(), claims: EventPayloadSchema }).optional()
399
326
  });
400
- var StepOutcomeSchema = z.object({
401
- orbital: z.string(),
402
- trait: z.string(),
403
- event: z.string(),
404
- executed: z.boolean(),
405
- previousState: z.string(),
406
- newState: z.string(),
407
- emits: z.array(z.object({ event: z.string(), payload: EventPayloadSchema.nullable() })),
408
- firedArm: z.number().int().nullable(),
409
- guards: z.array(z.object({ arm: z.number().int(), guard: SExprSchema, passed: z.boolean(), error: z.string().optional() })),
410
- effects: z.array(z.object({ type: z.string(), args: z.array(SExprSchema), status: z.enum(["executed", "failed", "skipped"]), error: z.string().optional() }))
411
- });
412
- var StepReportSchema = z.union([
413
- z.object({ success: z.literal(true), steps: z.array(z.object({ outcomes: z.array(StepOutcomeSchema), entityAfter: EventPayloadSchema.nullable() })) }),
414
- z.object({ success: z.literal(false), error: z.string() })
415
- ]);
416
- function effectsOf(effects) {
417
- return effects.map((e) => ({ type: e.type, args: e.args, status: e.status, ...e.error !== void 0 ? { error: e.error } : {} }));
327
+ function decodePlayedSteps(printed) {
328
+ if (!Array.isArray(printed)) throw new Error("program/step: expected an array of played steps");
329
+ return printed.map((step) => decodePlayedStep(step));
418
330
  }
419
- function emittedOf(emits, step) {
420
- return emits.map((e) => ({ type: e.event, ...e.payload !== null ? { payload: e.payload } : {}, timestamp: step }));
331
+ function decodePlayedOutput(run) {
332
+ if (run.code !== 0) throw new Error(`program/step: orb exited ${run.code}: ${run.stderr.trim()}`);
333
+ try {
334
+ const printed = JSON.parse(run.stdout);
335
+ return isStepRefusal(printed) ? decodeStepRefusal(printed) : decodePlayedSteps(printed);
336
+ } catch (error) {
337
+ throw new Error(`program/step: unexpected orb output: ${error instanceof Error ? error.message : String(error)}`);
338
+ }
421
339
  }
422
340
  async function programStep(program, requests, opts, live = false) {
423
- const steps = requests.map((r) => ({ trait: r.trait, event: r.event, payload: r.payload, from: r.from, ...r.entity !== void 0 ? { entity: r.entity } : {}, ...r.config !== void 0 ? { config: r.config } : {}, ...r.now !== void 0 ? { now: r.now } : {}, ...r.settleMs !== void 0 ? { settleMs: r.settleMs } : {}, ...r.viewer !== void 0 ? { viewer: r.viewer } : {} }));
341
+ const steps = requests.map((r) => ({ orbital: r.orbital, trait: r.trait, event: r.event, payload: r.payload, from: r.from, ...r.entity !== void 0 ? { entity: r.entity } : {}, ...r.config !== void 0 ? { config: r.config } : {}, ...r.now !== void 0 ? { now: r.now } : {}, ...r.settleMs !== void 0 ? { settleMs: r.settleMs } : {}, ...r.identity !== void 0 ? { identity: r.identity } : {} }));
424
342
  return withTempFile("program.orb", JSON.stringify(program), async (path) => {
425
- const run = await runOrb(["execute", path, "--steps", JSON.stringify(steps), ...live ? ["--live"] : []], opts);
426
- const report = parseJson(StepReportSchema, run, "program/step");
427
- if (!report.success) return { error: report.error };
428
- const results = [];
429
- for (const [i, request] of requests.entries()) {
430
- const moved = report.steps[i]?.outcomes ?? [];
431
- const outcome = moved.find((o) => o.trait === request.trait);
432
- if (outcome === void 0) return { error: `trait "${request.trait}" did not run` };
433
- const firedGuarded = outcome.firedArm !== null && outcome.guards.some((g) => g.arm === outcome.firedArm);
434
- results.push({ ...request, result: {
435
- trait: outcome.trait,
436
- event: request.event,
437
- transitionFired: outcome.executed,
438
- guard: firedGuarded ? "pass" : outcome.firedArm === null && outcome.guards.length > 0 ? "fail" : "none",
439
- ...outcome.firedArm !== null ? { firedArm: outcome.firedArm } : {},
440
- state: { before: outcome.previousState, after: outcome.newState },
441
- effects: effectsOf(outcome.effects),
442
- emitted: emittedOf(outcome.emits, i),
443
- guards: outcome.guards.map((g) => ({ arm: g.arm, guard: g.guard, passed: g.passed, trace: [], ...g.error !== void 0 ? { error: g.error } : {} })),
444
- entityAfter: report.steps[i]?.entityAfter ?? null,
445
- outcomes: moved.map((o) => ({ orbital: o.orbital, trait: o.trait, event: o.event, from: o.previousState, to: o.newState, arm: o.firedArm, fired: o.executed, effects: effectsOf(o.effects), emitted: emittedOf(o.emits, i) }))
446
- } });
447
- }
448
- return results;
343
+ const run = await runOrb(["execute", path, "--steps", JSON.stringify(steps), "--played", ...live ? ["--live"] : []], opts);
344
+ return decodePlayedOutput(run);
449
345
  });
450
346
  }
451
347
  function fail(error) {
@@ -465,18 +361,18 @@ async function runProgramEffect(op, args, opts, context) {
465
361
  case "behavior/catalog": {
466
362
  const scope = CatalogScopeSchema.safeParse(args[0]);
467
363
  if (!scope.success) return fail(`behavior/catalog: ${issuesOf(scope.error)}`);
468
- const vectors = booleanOption(op, args[1], "vectors");
469
- if (typeof vectors === "string") return fail(vectors);
470
- return { ok: true, result: await behaviorCatalog(scope.data, opts, vectors.value === void 0 ? {} : { vectors: vectors.value }) };
364
+ const options = booleanOptions(op, args[1], ["traits"]);
365
+ if (typeof options === "string") return fail(options);
366
+ return { ok: true, result: await behaviorCatalog(scope.data, opts, options.traits === void 0 ? {} : { traits: options.traits }) };
471
367
  }
472
368
  case "behavior/describe": {
473
369
  const value = DescribeTargetSchema.safeParse(args[0]);
474
370
  if (!value.success) return fail(`${op}: ${issuesOf(value.error)}`);
475
- const knobVectors = booleanOption(op, args[1], "knobVectors");
476
- if (typeof knobVectors === "string") return fail(knobVectors);
371
+ const none = booleanOptions(op, args[1], []);
372
+ if (typeof none === "string") return fail(none);
477
373
  const denied = workspaceAccessError(value.data.behavior, opts, context);
478
374
  if (denied !== void 0) return fail(`${op}: ${denied}`);
479
- return { ok: true, result: await behaviorDescribe(value.data, opts, knobVectors.value === void 0 ? {} : { knobVectors: knobVectors.value }) };
375
+ return { ok: true, result: await behaviorDescribe(value.data, opts) };
480
376
  }
481
377
  case "behavior/source": {
482
378
  const value = DescribeTargetSchema.safeParse(args[0]);
@@ -564,6 +460,35 @@ async function runProgramEffect(op, args, opts, context) {
564
460
  }
565
461
  return { ok: true, result: await programValidate(program, { ...opts, ...prior !== void 0 ? { prior } : {}, ...final !== void 0 ? { final } : {} }) };
566
462
  }
463
+ case "program/prove": {
464
+ const options = args[1] ?? {};
465
+ if (options === null || typeof options !== "object" || Array.isArray(options)) return fail("program/prove: options must be an object");
466
+ for (const key of Object.keys(options)) if (key !== "path") return fail(`program/prove: unsupported option "${key}"`);
467
+ const path = options["path"];
468
+ if (path !== void 0) {
469
+ if (typeof path !== "string" || !isAbsolute(path)) return fail("program/prove: path must be an absolute path");
470
+ return { ok: true, result: await programProve({ path }, opts) };
471
+ }
472
+ const program = programArg(op, args[0]);
473
+ if (typeof program === "string") return fail(program);
474
+ return { ok: true, result: await programProve({ program }, opts) };
475
+ }
476
+ case "program/os-grants": {
477
+ const options = args[1] ?? {};
478
+ if (options === null || typeof options !== "object" || Array.isArray(options)) return fail("program/os-grants: options must be an object");
479
+ for (const key of Object.keys(options)) if (key !== "path" && key !== "final") return fail(`program/os-grants: unsupported option "${key}"`);
480
+ const final = options["final"];
481
+ if (final !== void 0 && typeof final !== "boolean") return fail("program/os-grants: final must be a boolean");
482
+ const pass = final === true ? { final } : {};
483
+ const path = options["path"];
484
+ if (path !== void 0) {
485
+ if (typeof path !== "string" || !isAbsolute(path)) return fail("program/os-grants: path must be an absolute path");
486
+ return { ok: true, result: await programOsGrants({ path }, { ...opts, ...pass }) };
487
+ }
488
+ const program = programArg(op, args[0]);
489
+ if (typeof program === "string") return fail(program);
490
+ return { ok: true, result: await programOsGrants({ program }, { ...opts, ...pass }) };
491
+ }
567
492
  case "program/eval": {
568
493
  const program = programArg(op, args[0]);
569
494
  if (typeof program === "string") return fail(program);
@@ -595,4 +520,4 @@ async function runProgramEffect(op, args, opts, context) {
595
520
  }
596
521
  }
597
522
 
598
- export { behaviorCatalog, behaviorCatalogSync, behaviorDependencies, behaviorDescribe, behaviorResolve, behaviorSource, mountBehaviorValue, mountTraitValue, programCompose, programEval, programPrint, programRead, programResolve, programResolveSchema, programStep, programValidate, runProgramEffect, workspaceAccessError };
523
+ export { behaviorCatalog, behaviorCatalogSync, behaviorDependencies, behaviorDescribe, behaviorResolve, behaviorSource, programCompose, programEval, programOsGrants, programPrint, programProve, programRead, programResolve, programResolveSchema, programStep, programValidate, runProgramEffect, workspaceAccessError };
@@ -15,9 +15,6 @@ function nativeMemoryOf(kernel) {
15
15
  if (!hasMemoryStore(kernel)) throw new Error("this kernel module exports no MemoryStore; install a kernel build that carries it");
16
16
  return new NativeMemoryPersistenceAdapter(new kernel.MemoryStore());
17
17
  }
18
- async function loadKernelModule(kernelDir, options) {
19
- return loadKernel(kernelDir, options);
20
- }
21
18
  var initialised = /* @__PURE__ */ new WeakSet();
22
19
  function initOnce(loaded, wasm, languageFrom) {
23
20
  if (initialised.has(loaded)) return loaded;
@@ -27,17 +24,10 @@ function initOnce(loaded, wasm, languageFrom) {
27
24
  initialised.add(loaded);
28
25
  return loaded;
29
26
  }
30
- function initKernelSync(languageFrom) {
31
- initOnce(installedModule, readFileSync(createRequire(import.meta.url).resolve("@almadar/kernel/kernel.wasm")), languageFrom);
32
- return installedModule;
33
- }
34
27
  async function loadInstalledKernel(languageFrom) {
35
- return initKernelSync(languageFrom);
28
+ return initOnce(installedModule, readFileSync(createRequire(import.meta.url).resolve("@almadar/kernel/kernel.wasm")), languageFrom);
36
29
  }
37
- async function loadHttpKernel(kernelDir, options) {
38
- return loadKernel(kernelDir, options);
39
- }
40
- async function loadKernel(kernelDir, options) {
30
+ async function loadKernelModule(kernelDir, options) {
41
31
  const loaded = await import(pathToFileURL(join(kernelDir, "pkg/orbital_wasm.js")).href);
42
32
  return initOnce(loaded, initialised.has(loaded) ? void 0 : readFileSync(join(kernelDir, "pkg/orbital_wasm_bg.wasm")), options.languageFrom);
43
33
  }
@@ -60,4 +50,4 @@ async function loadNativeKernelModule(addonPath, options) {
60
50
  return initOnce(loaded, void 0, options.languageFrom);
61
51
  }
62
52
 
63
- export { initKernelSync, loadHttpKernel, loadInstalledKernel, loadKernelModule, loadNativeKernelModule, nativeMemoryOf, resolveNativeAddon };
53
+ export { loadInstalledKernel, loadKernelModule, loadNativeKernelModule, nativeMemoryOf, resolveNativeAddon };