holycodex 0.15.0-dev.29.1 → 0.15.1-dev.35.1

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.
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env bun
2
- import { $ as EffortSchema, $t as scoped$2, At as filter, B as SPECIALIST_OUTCOME_VERSION, Bt as positive, Ct as Record, Dt as Unknown, Et as Union, Ft as maxLength, G as parseCliEnvelope, Gt as fail, H as SpecialistOutcomeV2Schema, Ht as _void, It as minItems, J as canonicalJson, Jt as orElseSucceed, K as specialistOutcomeFromCapabilityResult, Kt as gen, L as lookupPlan, Lt as minLength, Mt as greaterThanOrEqualTo, N as WorkflowRuntimeError, Nt as int, Ot as declare, Pt as maxItems, Q as DelegationModeSchema, Qt as runSync, R as lookupRoute, Rt as optional, S as isWorkflowFailure, St as Number$, Tt as Struct, U as normalizeSpecialistOutcome, Ut as acquireRelease, V as SpecialistOutcomeSchema, Vt as is, W as parseCapabilityResultV2, Wt as async, X as domainSeparatedSha256, Xt as raceFirst, Y as canonicalJsonUtf8, Yt as provide$2, Z as sha256DomainDigest, Zt as runPromise, _t as decodeUnknown, a as runExecutionPlan, an as mapError$2, at as ServiceTierSchema, bt as Literal, c as loadNativeWorkflowSource, cn as succeed$1, ct as createSha256Digest, d as CompileOptionsSchema, dn as isRight, dt as CapabilityNameSchema, en as succeed$2, et as PlanNameSchema, fn as CLI_SCHEMA_VERSION, ft as OPTIONAL_CAPABILITY_NAMES, gt as resolveOptionalCapabilitySelections, h as hydrateWorkflowPlanIR, ht as pluginIdsForOptionalCapabilities, i as makeCapacityService, in as fromEffect, it as RouteKeySchema, jt as greaterThan, kt as decodeUnknownEither, ln as Tag, lt as createTrustId, mt as migrateOptionalCapabilitySelections, n as evaluateWorkflowCompatibility, nn as tryPromise, nt as RoleSkillProfileSchema, on as provide$1, ot as lookupRoleDefinition, p as compileWorkflow, pn as STATE_SCHEMA_EPOCH, pt as capabilityHealth, q as canonicalIdentityUtf8, qt as mapError$3, rn as try_, rt as RoleTaskSchema, sn as scoped$1, st as createProjectId, tn as sync, tt as RoleSchema, un as isLeft, ut as CAPABILITY_REGISTRY, vt as Array$, wt as String$, xt as Null, yt as Boolean$, z as resolvePlanSelection, zt as pattern } from "./src-DamQOFzF.js";
2
+ import { $ as DelegationModeSchema, $t as runSync, At as decodeUnknownEither, B as resolvePlanSelection, Bt as pattern, Ct as Number$, Dt as Union, Et as Struct, Ft as maxItems, G as parseCapabilityResultV2, Gt as async, H as SpecialistOutcomeSchema, Ht as is, It as maxLength, J as canonicalIdentityUtf8, Jt as mapError$3, K as parseCliEnvelope, Kt as fail, Lt as minItems, Mt as greaterThan, Nt as greaterThanOrEqualTo, Ot as Unknown, P as WorkflowRuntimeError, Pt as int, Q as sha256DomainDigest, Qt as runPromise, R as lookupPlan, Rt as minLength, S as isWorkflowFailure, St as Null, Tt as String$, U as SpecialistOutcomeV2Schema, Ut as _void, V as SPECIALIST_OUTCOME_VERSION, Vt as positive, W as normalizeSpecialistOutcome, Wt as acquireRelease, X as canonicalJsonUtf8, Xt as provide$2, Y as canonicalJson, Yt as orElseSucceed, Z as domainSeparatedSha256, Zt as raceFirst, _t as resolveOptionalCapabilitySelections, a as runExecutionPlan, an as fromEffect, at as RouteKeySchema, bt as Boolean$, c as loadNativeWorkflowSource, cn as scoped$1, ct as createProjectId, d as CompileOptionsSchema, dn as isLeft, dt as CAPABILITY_REGISTRY, en as scoped$2, et as EffortSchema, fn as isRight, ft as CapabilityNameSchema, gt as pluginIdsForOptionalCapabilities, h as hydrateWorkflowPlanIR, ht as migrateOptionalCapabilitySelections, i as makeCapacityService, in as try_, it as RoleTaskSchema, jt as filter, kt as declare, ln as succeed$1, lt as createSha256Digest, mn as STATE_SCHEMA_EPOCH, mt as capabilityHealth, n as evaluateWorkflowCompatibility, nn as sync, nt as RoleSchema, on as mapError$2, ot as ServiceTierSchema, p as compileWorkflow, pn as CLI_SCHEMA_VERSION, pt as OPTIONAL_CAPABILITY_NAMES, q as specialistOutcomeFromCapabilityResult, qt as gen, rn as tryPromise, rt as RoleSkillProfileSchema, sn as provide$1, st as lookupRoleDefinition, tn as succeed$2, tt as PlanNameSchema, un as Tag, ut as createTrustId, vt as decodeUnknown, wt as Record, xt as Literal, yt as Array$, z as lookupRoute, zt as optional } from "./src-BmUZJGuC.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { copyFile, cp, link, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
5
5
  import { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
- import { execFileSync, spawn, spawnSync } from "node:child_process";
8
- import { createHash } from "node:crypto";
9
- import { homedir, tmpdir } from "node:os";
7
+ import { spawn, spawnSync } from "node:child_process";
8
+ import { createHash, randomBytes } from "node:crypto";
10
9
  import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
10
+ import { homedir, tmpdir } from "node:os";
11
11
  import { AsyncLocalStorage } from "node:async_hooks";
12
12
  import { connect } from "node:net";
13
13
  import { execPath } from "node:process";
@@ -159,6 +159,7 @@ const VALUE_OPTIONS = /* @__PURE__ */ new Set([
159
159
  "scope",
160
160
  "run-id",
161
161
  "session-id",
162
+ "name",
162
163
  "official-plugin",
163
164
  "task",
164
165
  "autonomy",
@@ -307,6 +308,14 @@ function positionalRange(command) {
307
308
  min: 1,
308
309
  max: 2
309
310
  };
311
+ case "workflow create": return {
312
+ min: 1,
313
+ max: 2
314
+ };
315
+ case "workflow check": return {
316
+ min: 1,
317
+ max: 1
318
+ };
310
319
  case "workflow show":
311
320
  case "workflow inspect":
312
321
  case "workflow pause":
@@ -398,6 +407,14 @@ function commandOptions(command) {
398
407
  "trusted",
399
408
  "compat-quickjs"
400
409
  ]);
410
+ case "workflow create": return /* @__PURE__ */ new Set([
411
+ ...common,
412
+ "name",
413
+ "session-id",
414
+ "trusted",
415
+ "task"
416
+ ]);
417
+ case "workflow check": return /* @__PURE__ */ new Set([...common, "trusted"]);
401
418
  case "workflow resume": return /* @__PURE__ */ new Set([
402
419
  ...common,
403
420
  "trusted",
@@ -441,7 +458,6 @@ function optionalChoiceOptions() {
441
458
  const VERSION_PATTERN = /^0\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/u;
442
459
  const EPOCH_PATTERN = /^[a-z][a-z0-9._:-]{0,63}$/u;
443
460
  const PLUGIN_NAME_PATTERN = /^[a-z][a-z0-9._-]{1,63}$/u;
444
- const SKILL_NAME_PATTERN = /^[a-z][a-z0-9-]{0,63}$/u;
445
461
  const DIGEST_PATTERN = /^[0-9a-f]{64}$/u;
446
462
  const SOURCE_MANIFEST_PATH = ".codex-plugin/plugin.json";
447
463
  const PAYLOAD_MANIFEST_PATH = ".codex-plugin/payload.json";
@@ -600,7 +616,6 @@ function comparePathText(left, right) {
600
616
  //#endregion
601
617
  //#region packages/plugin/src/schemas.ts
602
618
  const PluginNameSchema$1 = String$.pipe(pattern(PLUGIN_NAME_PATTERN));
603
- const SkillNameSchema = String$.pipe(pattern(SKILL_NAME_PATTERN));
604
619
  const VersionSchema$1 = String$.pipe(pattern(VERSION_PATTERN));
605
620
  const SchemaEpochSchema = String$.pipe(pattern(EPOCH_PATTERN));
606
621
  const DigestSchema$2 = String$.pipe(pattern(DIGEST_PATTERN));
@@ -613,9 +628,21 @@ const PathSchema = String$.pipe(filter((value) => {
613
628
  }
614
629
  }));
615
630
  const DescriptionSchema = String$.pipe(filter((value) => value.length > 0 && value.length <= 300));
616
- const SkillNamesSchema = Array$(SkillNameSchema);
617
- const AssetPathsSchema = Array$(PathSchema);
618
- const CapabilityAssetPathsSchema = Array$(PathSchema);
631
+ const SkillRootSchema = Literal("skills", "./skills", "skills/");
632
+ const AuthorSchema = Struct({
633
+ name: String$.pipe(minLength(1)),
634
+ email: optional(String$),
635
+ url: optional(String$)
636
+ });
637
+ const InterfaceSchema = Struct({
638
+ displayName: String$.pipe(minLength(1)),
639
+ shortDescription: String$.pipe(minLength(1)),
640
+ longDescription: String$.pipe(minLength(1)),
641
+ developerName: String$.pipe(minLength(1)),
642
+ category: String$.pipe(minLength(1)),
643
+ capabilities: Array$(String$.pipe(minLength(1))),
644
+ defaultPrompt: Array$(String$.pipe(minLength(1)))
645
+ });
619
646
  const PonytailMetadataSchema = Struct({
620
647
  name: Literal("ponytail"),
621
648
  version: Literal("4.9.0"),
@@ -630,24 +657,27 @@ const PonytailMetadataSchema = Struct({
630
657
  });
631
658
  const SourceManifestSchema = Struct({
632
659
  name: PluginNameSchema$1,
660
+ version: VersionSchema$1,
633
661
  description: DescriptionSchema,
662
+ author: AuthorSchema,
663
+ homepage: optional(String$),
664
+ repository: optional(String$),
634
665
  license: optional(String$),
635
- skills: optional(SkillNamesSchema),
636
- assets: optional(AssetPathsSchema),
637
- hooks: optional(CapabilityAssetPathsSchema),
638
- rules: optional(CapabilityAssetPathsSchema),
639
- compaction: optional(CapabilityAssetPathsSchema)
666
+ keywords: optional(Array$(String$.pipe(minLength(1)))),
667
+ skills: SkillRootSchema,
668
+ interface: InterfaceSchema
640
669
  });
641
670
  const GeneratedManifestSchema = Struct({
642
671
  name: PluginNameSchema$1,
643
672
  version: VersionSchema$1,
644
673
  description: DescriptionSchema,
674
+ author: AuthorSchema,
675
+ homepage: optional(String$),
676
+ repository: optional(String$),
645
677
  license: optional(String$),
646
- skills: optional(SkillNamesSchema),
647
- assets: optional(AssetPathsSchema),
648
- hooks: optional(CapabilityAssetPathsSchema),
649
- rules: optional(CapabilityAssetPathsSchema),
650
- compaction: optional(CapabilityAssetPathsSchema)
678
+ keywords: optional(Array$(String$.pipe(minLength(1)))),
679
+ skills: SkillRootSchema,
680
+ interface: InterfaceSchema
651
681
  });
652
682
  const PayloadFileSchema = Struct({
653
683
  path: PathSchema,
@@ -705,6 +735,7 @@ async function readSourceManifest(root) {
705
735
  const parsed = decodeSchema(SourceManifestSchema, input);
706
736
  if (parsed === void 0) throw pluginError("manifest_invalid", "The source plugin manifest is invalid.", { summary: "Effect Schema rejected the source manifest." });
707
737
  if (containsMcpDeclaration(input)) throw pluginError("manifest_invalid", "Plugin source manifests cannot declare external servers.");
738
+ if (typeof input === "object" && input !== null && !Array.isArray(input) && Object.keys(input).some((key) => !OFFICIAL_MANIFEST_KEYS.has(key))) throw pluginError("manifest_invalid", "The source plugin manifest contains unsupported fields.");
708
739
  validateManifestDeclarations(parsed);
709
740
  return parsed;
710
741
  }
@@ -739,41 +770,37 @@ async function readPayloadManifest(root) {
739
770
  return parsed;
740
771
  }
741
772
  function validateManifestDeclarations(manifest) {
742
- const skills = manifest.skills ?? [];
743
- const assets = manifest.assets ?? [];
744
- const hooks = manifest.hooks ?? [];
745
- const rules = manifest.rules ?? [];
746
- const compaction = manifest.compaction ?? [];
747
- const declared = [
748
- ...assets,
749
- ...hooks,
750
- ...rules,
751
- ...compaction
752
- ];
753
- if (new Set(skills).size !== skills.length || new Set(declared).size !== declared.length) throw pluginError("manifest_invalid", "Manifest asset declarations must be unique.");
754
- const seen = /* @__PURE__ */ new Set();
755
- for (const asset of declared) {
756
- const normalized = normalizeRelativePath(asset);
757
- if (normalized === ".codex-plugin/plugin.json" || normalized === ".codex-plugin/payload.json") throw pluginError("manifest_invalid", "Generated metadata paths are reserved.", { path: normalized });
758
- if (seen.has(normalized)) throw pluginError("manifest_invalid", "Manifest asset declarations must be canonical.", { path: normalized });
759
- seen.add(normalized);
760
- }
773
+ if (manifest.skills !== "skills" && manifest.skills !== "./skills" && manifest.skills !== "skills/") throw pluginError("manifest_invalid", "The plugin skills path must resolve to `skills`.");
761
774
  }
762
- function declaredSourcePaths(manifest) {
775
+ function declaredSourcePaths(_manifest, candidates = []) {
763
776
  const paths = /* @__PURE__ */ new Set([SOURCE_MANIFEST_PATH]);
764
- for (const asset of manifest.assets ?? []) paths.add(normalizeRelativePath(asset));
765
- for (const skill of manifest.skills ?? []) {
766
- paths.add(`skills/${skill}/SKILL.md`);
767
- paths.add(`skills/${skill}/agents/openai.yaml`);
768
- }
769
- for (const path of [
770
- ...manifest.assets ?? [],
771
- ...manifest.hooks ?? [],
772
- ...manifest.rules ?? [],
773
- ...manifest.compaction ?? []
774
- ]) paths.add(normalizeRelativePath(path));
777
+ for (const candidate of candidates) {
778
+ const normalized = normalizeRelativePath(candidate);
779
+ if (isPayloadAssetPath(normalized)) paths.add(normalized);
780
+ }
775
781
  return paths;
776
782
  }
783
+ const OFFICIAL_MANIFEST_KEYS = /* @__PURE__ */ new Set([
784
+ "name",
785
+ "version",
786
+ "description",
787
+ "author",
788
+ "homepage",
789
+ "repository",
790
+ "license",
791
+ "keywords",
792
+ "skills",
793
+ "interface"
794
+ ]);
795
+ function isPayloadAssetPath(path) {
796
+ return [
797
+ "agents/",
798
+ "skills/",
799
+ "hooks/",
800
+ "rules/",
801
+ "compaction/"
802
+ ].some((prefix) => path.startsWith(prefix));
803
+ }
777
804
  function isUsableDirectoryText(value) {
778
805
  return value.length > 0 && !value.includes("\0");
779
806
  }
@@ -794,7 +821,7 @@ async function verifyPayload(input) {
794
821
  const generatedManifest = await readGeneratedManifest(root);
795
822
  if (generatedManifest.version !== payloadManifest.version) throw pluginError("payload_invalid", "Generated metadata versions do not match.");
796
823
  if (payloadManifest.identity.epoch !== payloadManifest.schema_epoch) throw pluginError("payload_invalid", "Payload identity epoch does not match metadata.");
797
- const declaredPaths = [...declaredSourcePaths(generatedManifest)].sort(comparePathText);
824
+ const declaredPaths = [...declaredSourcePaths(generatedManifest, payloadManifest.files.map((file) => file.path))].sort(comparePathText);
798
825
  const manifestPaths = payloadManifest.files.map((file) => file.path);
799
826
  if (declaredPaths.length !== manifestPaths.length || declaredPaths.some((path, index) => path !== manifestPaths[index])) throw pluginError("payload_invalid", "Generated metadata and the payload file manifest disagree.");
800
827
  const expectedPaths = /* @__PURE__ */ new Set([...payloadManifest.files.map((file) => file.path), PAYLOAD_MANIFEST_PATH]);
@@ -814,7 +841,7 @@ async function verifyPayload(input) {
814
841
  if (bytes.byteLength > 1048576 || totalSize > 8388608) throw pluginError("payload_invalid", "The payload exceeds the size limit.");
815
842
  fileBytes.set(file.path, bytes);
816
843
  }
817
- if (generatedManifest.skills?.includes("ponytail") === true) await verifyPonytailMetadata(async (path) => {
844
+ if (payloadManifest.files.some((file) => file.path === "skills/ponytail/SKILL.md")) await verifyPonytailMetadata(async (path) => {
818
845
  const bytes = fileBytes.get(path);
819
846
  if (bytes === void 0) throw pluginError("payload_invalid", "A Ponytail metadata input is missing.", { path });
820
847
  return bytes;
@@ -896,11 +923,13 @@ async function validateSource(input = pluginSourceRoot) {
896
923
  const walkedFiles = [];
897
924
  await walkSource(root, "", walkedFiles);
898
925
  const manifest = await readSourceManifest(root);
899
- const declaredPaths = declaredSourcePaths(manifest);
926
+ const declaredPaths = declaredSourcePaths(manifest, walkedFiles);
900
927
  const walkedSet = new Set(walkedFiles);
928
+ const skillDirectories = new Set(walkedFiles.map((path) => /^skills\/([^/]+)\//u.exec(path)?.[1]).filter((name) => name !== void 0));
929
+ for (const skill of skillDirectories) if (!walkedSet.has(`skills/${skill}/SKILL.md`)) throw pluginError("source_invalid", "A skill directory is missing SKILL.md.", { skill });
901
930
  for (const declaredPath of declaredPaths) if (!walkedSet.has(declaredPath)) throw pluginError("source_invalid", "A manifest-declared asset is missing.", { path: declaredPath });
902
931
  for (const walkedPath of walkedFiles) if (!declaredPaths.has(walkedPath)) throw pluginError("source_invalid", "The plugin source contains an undeclared file.", { path: walkedPath });
903
- if (manifest.skills?.includes("ponytail") === true) await verifyPonytailMetadata((path) => readSourceFile(root, path), "source_invalid");
932
+ if (walkedFiles.includes("skills/ponytail/SKILL.md")) await verifyPonytailMetadata((path) => readSourceFile(root, path), "source_invalid");
904
933
  const files = [];
905
934
  let totalSize = 0;
906
935
  for (const path of [...walkedSet].sort()) {
@@ -958,14 +987,17 @@ function createGeneratedManifest(source, version) {
958
987
  const manifest = {
959
988
  name: source.name,
960
989
  version,
961
- description: source.description
962
- };
963
- if (source["license"] !== void 0) manifest["license"] = source["license"];
964
- if (source["skills"] !== void 0) manifest["skills"] = [...source["skills"]];
965
- if (source["assets"] !== void 0) manifest["assets"] = [...source["assets"]];
966
- if (source["hooks"] !== void 0) manifest["hooks"] = [...source["hooks"]];
967
- if (source["rules"] !== void 0) manifest["rules"] = [...source["rules"]];
968
- if (source["compaction"] !== void 0) manifest["compaction"] = [...source["compaction"]];
990
+ description: source.description,
991
+ author: source.author,
992
+ skills: source.skills,
993
+ interface: source.interface
994
+ };
995
+ for (const key of [
996
+ "license",
997
+ "homepage",
998
+ "repository",
999
+ "keywords"
1000
+ ]) if (source[key] !== void 0) manifest[key] = source[key];
969
1001
  const parsed = decodeSchema(GeneratedManifestSchema, manifest);
970
1002
  if (parsed === void 0) throw pluginError("manifest_invalid", "Generated plugin metadata is invalid.", { summary: "Effect Schema rejected the generated plugin metadata." });
971
1003
  return parsed;
@@ -2220,6 +2252,9 @@ const SemanticAssignmentPacketSchema = Struct({
2220
2252
  security: SecurityPolicySchema,
2221
2253
  compatibility: CompatibilityPacketSchema,
2222
2254
  skill_profile: Union(RoleSkillProfileSchema, Null),
2255
+ /** Runtime metadata supplied by the host; never hardcode release or platform values here. */
2256
+ canonical_version: optional(TextSchema),
2257
+ platform: optional(Literal("win32", "posix")),
2223
2258
  capability_input: optional(JsonObjectSchema$2),
2224
2259
  retained_context: optional(RetainedContextSchema)
2225
2260
  });
@@ -2239,8 +2274,10 @@ function compileSpecialistAssignment(packet) {
2239
2274
  `Assignment ID: ${packet.assignment.id}`,
2240
2275
  `Objective: ${packet.assignment.objective}`,
2241
2276
  `Role/task: ${packet.assignment.role_task.role}/${packet.assignment.role_task.task}`,
2277
+ ...packet.canonical_version === void 0 ? [] : [`Canonical version: ${packet.canonical_version}`],
2242
2278
  `Authority: ${packet.assignment.authority}`
2243
2279
  ];
2280
+ if (packet.platform === "win32") lines.push("Use C:/Program Files/Git/bin/bash.exe for every shell command.");
2244
2281
  const retained = completeRetainedContext(packet.retained_context);
2245
2282
  if (packet.skill_profile !== null && retained === void 0) {
2246
2283
  lines.push(`Skill reference: ${packet.skill_profile.reference}`);
@@ -2256,7 +2293,7 @@ function compileSpecialistAssignment(packet) {
2256
2293
  if (value !== void 0 && value.length > 0) lines.push(`${label}: ${value.join("; ")}`);
2257
2294
  }
2258
2295
  lines.push(`Outcome protocol: ${SPECIALIST_OUTCOME_VERSION}; terminal shapes: completed {protocol_version,route,evidence,status,summary}; blocked {protocol_version,route,evidence,status,reason,needs_root_decision}; partial {protocol_version,route,evidence,status,summary,completed,remaining,needs_root_decision}; failed {protocol_version,route,evidence,status,error}.`);
2259
- lines.push("Boundary: Do not delegate or broaden scope; return material choices to Root.");
2296
+ lines.push("Boundary: Stay within the assigned scope and return material choices to Root.");
2260
2297
  return lines.join("\n");
2261
2298
  }
2262
2299
  const ExecutionBackendSchema = Literal("app-server-v1-fallback", "app-server-v2", "host-capability");
@@ -5508,11 +5545,11 @@ function executeCodexOperation(context, definition, pending, active, input) {
5508
5545
  },
5509
5546
  input: {
5510
5547
  name: "json",
5511
- decode: (value) => value
5548
+ decode: (value) => asJsonValue(value, "operation input")
5512
5549
  },
5513
5550
  output: {
5514
5551
  name: "json",
5515
- decode: (value) => value
5552
+ decode: (value) => asJsonValue(value, "operation output")
5516
5553
  },
5517
5554
  metadata: { id: input.operationId },
5518
5555
  route: input.route
@@ -5521,7 +5558,7 @@ function executeCodexOperation(context, definition, pending, active, input) {
5521
5558
  if (codex === void 0) return fail(workflowFailure("execution", "The workflow host Codex AgentExecution capability is unavailable."));
5522
5559
  return gen(function* () {
5523
5560
  const route = yield* resolvePlanRoute(definition, input.route);
5524
- const packet = yield* makeSemanticPacket(definition, pending, assignment, route);
5561
+ const packet = yield* makeSemanticPacket(context, definition, pending, assignment, route);
5525
5562
  return (yield* validateSemanticOutcome(yield* codex.execute(packet).pipe(mapError$3((cause) => codexFailure(cause, assignment))), assignment, roleTaskForRoute(route))).outcome;
5526
5563
  });
5527
5564
  }
@@ -5537,7 +5574,7 @@ function executeCodexAssignment(context, definition, pending, active, agent, ass
5537
5574
  } catch (cause) {
5538
5575
  return yield* fail(workflowFailure(cause instanceof CostAccountingError ? cause.code : "estimate_unavailable", "The workflow assignment has no conservative pricing estimate.", { cause }));
5539
5576
  }
5540
- const packet = yield* makeSemanticPacket(definition, pending, assignment, routeDefinition);
5577
+ const packet = yield* makeSemanticPacket(context, definition, pending, assignment, routeDefinition);
5541
5578
  const normalizedInput = normalizeSemanticAssignment(packet);
5542
5579
  const authorityDigest = yield* tryPromise({
5543
5580
  try: () => authorityScopeDigest(packet.assignment.authority, packet.assignment.scope),
@@ -5666,7 +5703,7 @@ function resolvePlanRoute(definition, route) {
5666
5703
  const selected = lookupRoute(definition.identity.plan, route);
5667
5704
  return selected.ok ? succeed$2(selected.value) : fail(workflowFailure("validation", "The assignment route is unavailable."));
5668
5705
  }
5669
- function makeSemanticPacket(definition, pending, assignment, route, retainedContext) {
5706
+ function makeSemanticPacket(context, definition, pending, assignment, route, retainedContext) {
5670
5707
  return try_({
5671
5708
  try: () => {
5672
5709
  const payload = asJsonValue(assignment.payload, "workflow assignment payload");
@@ -5732,6 +5769,8 @@ function makeSemanticPacket(definition, pending, assignment, route, retainedCont
5732
5769
  prefer_multi_agent_v2: false,
5733
5770
  require_multi_agent_v2: false
5734
5771
  },
5772
+ ...context.canonicalVersion === void 0 ? {} : { canonical_version: context.canonicalVersion },
5773
+ platform: context.platform,
5735
5774
  skill_profile: role.skill_profile,
5736
5775
  ...capability === void 0 ? {} : { capability_input: options },
5737
5776
  ...retainedContext === void 0 ? {} : { retained_context: retainedContext }
@@ -5819,7 +5858,7 @@ function roleTaskForRoute(route) {
5819
5858
  function readFanOut(assignment) {
5820
5859
  const payload = assignment.payload;
5821
5860
  if (typeof payload === "object" && payload !== null && !Array.isArray(payload)) {
5822
- const options = "options" in payload ? payload.options : void 0;
5861
+ const options = "options" in payload ? payload["options"] : void 0;
5823
5862
  if (typeof options === "object" && options !== null && !Array.isArray(options)) return optionInteger(jsonObject(options, "assignment options"), "fan_out", 1);
5824
5863
  }
5825
5864
  return 1;
@@ -6512,11 +6551,11 @@ async function handleOperation(context, definition, plan, active, operation) {
6512
6551
  },
6513
6552
  input: {
6514
6553
  name: "json",
6515
- decode: (value) => value
6554
+ decode: (value) => asJsonValue(value, "operation input")
6516
6555
  },
6517
6556
  output: {
6518
6557
  name: "json",
6519
- decode: (value) => value
6558
+ decode: (value) => asJsonValue(value, "operation output")
6520
6559
  },
6521
6560
  metadata: { id: operationId },
6522
6561
  route
@@ -6981,6 +7020,8 @@ var WorkflowHost = class {
6981
7020
  approvalPolicy: assertIdentifier(options.approvalPolicy ?? "never", "approval policy"),
6982
7021
  sandboxPolicy: assertIdentifier(options.sandboxPolicy, "sandbox policy"),
6983
7022
  codexCapabilityDigest: assertDigest(options.codexCapabilityDigest, "Codex capability digest"),
7023
+ canonicalVersion: options.canonicalVersion,
7024
+ platform: options.platform ?? "posix",
6984
7025
  telemetry: options.telemetry,
6985
7026
  refinementsEnabled: options.refinementsEnabled ?? false,
6986
7027
  pending: /* @__PURE__ */ new Map(),
@@ -7143,7 +7184,7 @@ function resolveInstallerPaths(options = {}, environment = process.env) {
7143
7184
  payloadRoot: marketplacePlugins,
7144
7185
  stagingRoot: join(safeMarketplaceRoot, "plugins", ".holycodex-staging"),
7145
7186
  runsRoot: join(stateRoot, "runs"),
7146
- generatedWorkflowsRoot: join(stateRoot, "workflows")
7187
+ generatedWorkflowsRoot: join(safeCodexHome, "workflows")
7147
7188
  };
7148
7189
  }
7149
7190
  var PathBoundaryError = class extends Error {
@@ -7370,12 +7411,23 @@ var LockError = class extends Error {
7370
7411
  //#endregion
7371
7412
  //#region packages/cli/src/marketplace.ts
7372
7413
  const MarketplaceSchema = JsonObjectSchema$3;
7373
- const MarketplaceEntrySchema = JsonObjectSchema$3;
7414
+ const MarketplaceEntrySchema = declare((value) => {
7415
+ const parsed = decodeSchema$1(JsonObjectSchema$3, value);
7416
+ return parsed !== void 0 && typeof parsed["name"] === "string";
7417
+ });
7418
+ const MarketplaceNameSchema = Literal("holycodex");
7374
7419
  const MANAGED_MARKETPLACE_OWNER = "holycodex";
7375
7420
  const MANAGED_MARKETPLACE_CATEGORY = "Development";
7376
7421
  const MANAGED_INSTALL_POLICY = "AVAILABLE";
7377
7422
  const MANAGED_AUTH_POLICY = "ON_INSTALL";
7378
7423
  async function readMarketplace(path) {
7424
+ return (await readMarketplaceInternal(path, false)).document;
7425
+ }
7426
+ /** Reads the official document and repairs only the previous HolyCodex shape in memory. */
7427
+ async function readMarketplaceForInstall(path) {
7428
+ return await readMarketplaceInternal(path, true);
7429
+ }
7430
+ async function readMarketplaceInternal(path, allowLegacyRepair) {
7379
7431
  await assertNoSymlink(path).catch((error) => {
7380
7432
  if (!isFsCode(error, "ENOENT")) throw error;
7381
7433
  });
@@ -7384,18 +7436,88 @@ async function readMarketplace(path) {
7384
7436
  document = await readJsonObject(path);
7385
7437
  } catch (error) {
7386
7438
  if (!isFsCode(error, "ENOENT")) throw error;
7387
- return { plugins: [] };
7439
+ return {
7440
+ document: emptyMarketplace(),
7441
+ repaired: false
7442
+ };
7388
7443
  }
7389
7444
  const parsed = decodeSchema$1(MarketplaceSchema, document);
7390
- if (parsed === void 0) throw new MarketplaceError("marketplace_invalid", "The marketplace file is not a JSON object.");
7391
- const rawPlugins = parsed["plugins"];
7392
- if (rawPlugins !== void 0 && (!Array.isArray(rawPlugins) || rawPlugins.some((item) => decodeSchema$1(MarketplaceEntrySchema, item) === void 0))) throw new MarketplaceError("marketplace_invalid", "The marketplace plugins list is invalid.");
7393
- const plugins = Array.isArray(rawPlugins) ? rawPlugins.filter((item) => decodeSchema$1(MarketplaceEntrySchema, item) !== void 0) : [];
7445
+ if (parsed !== void 0) {
7446
+ const official = parseOfficialMarketplace(parsed);
7447
+ if (official !== void 0) return {
7448
+ document: official,
7449
+ repaired: false
7450
+ };
7451
+ }
7452
+ if (allowLegacyRepair) {
7453
+ const repaired = repairLegacyMarketplace(document);
7454
+ if (repaired !== void 0) return {
7455
+ document: repaired,
7456
+ repaired: true
7457
+ };
7458
+ }
7459
+ throw new MarketplaceError("marketplace_invalid", "The marketplace file is not a valid Codex marketplace.");
7460
+ }
7461
+ function parseOfficialMarketplace(document) {
7462
+ if (decodeSchema$1(MarketplaceNameSchema, document["name"]) === void 0) return void 0;
7463
+ const rawPlugins = document["plugins"];
7464
+ if (!Array.isArray(rawPlugins)) return void 0;
7465
+ const plugins = [];
7466
+ for (const item of rawPlugins) {
7467
+ const plugin = decodeSchema$1(MarketplaceEntrySchema, item);
7468
+ if (plugin === void 0) return void 0;
7469
+ plugins.push(plugin);
7470
+ }
7471
+ return {
7472
+ ...document,
7473
+ name: MANAGED_MARKETPLACE_OWNER,
7474
+ plugins
7475
+ };
7476
+ }
7477
+ function repairLegacyMarketplace(document) {
7478
+ const rawPlugins = document["plugins"];
7479
+ if (!Array.isArray(rawPlugins)) return void 0;
7480
+ const plugins = [];
7481
+ for (const item of rawPlugins) {
7482
+ if (!isJsonObject$1(item)) return void 0;
7483
+ if (isLegacyManagedEntry(item)) {
7484
+ const source = item["source"];
7485
+ if (typeof source !== "string" || source.length === 0) return void 0;
7486
+ plugins.push(repairLegacyEntry(item));
7487
+ } else plugins.push(item);
7488
+ }
7394
7489
  return {
7395
- ...parsed,
7490
+ ...document,
7491
+ name: MANAGED_MARKETPLACE_OWNER,
7492
+ interface: isJsonObject$1(document["interface"]) ? document["interface"] : { displayName: "HolyCodex" },
7396
7493
  plugins
7397
7494
  };
7398
7495
  }
7496
+ function repairLegacyEntry(entry) {
7497
+ const source = entry["source"];
7498
+ return {
7499
+ name: MANAGED_MARKETPLACE_OWNER,
7500
+ source: {
7501
+ source: "local",
7502
+ path: typeof source === "string" ? source : ""
7503
+ },
7504
+ policy: {
7505
+ installation: MANAGED_INSTALL_POLICY,
7506
+ authentication: MANAGED_AUTH_POLICY
7507
+ },
7508
+ category: MANAGED_MARKETPLACE_CATEGORY
7509
+ };
7510
+ }
7511
+ function isLegacyManagedEntry(value) {
7512
+ return isJsonObject$1(value) && (value["name"] === "holycodex" || isJsonObject$1(value["owner"]) && value["owner"]["name"] === "holycodex");
7513
+ }
7514
+ function emptyMarketplace() {
7515
+ return {
7516
+ name: MANAGED_MARKETPLACE_OWNER,
7517
+ interface: { displayName: "HolyCodex" },
7518
+ plugins: []
7519
+ };
7520
+ }
7399
7521
  async function writeMarketplace(path, document) {
7400
7522
  await ensureOwnedDirectory(dirname(path));
7401
7523
  await writeAtomicJson(path, document);
@@ -7403,21 +7525,15 @@ async function writeMarketplace(path, document) {
7403
7525
  function managedMarketplaceEntry(record) {
7404
7526
  return {
7405
7527
  name: "holycodex",
7406
- source: record.relative_path,
7407
- version: record.version,
7408
- category: MANAGED_MARKETPLACE_CATEGORY,
7409
- install: MANAGED_INSTALL_POLICY,
7410
- auth: MANAGED_AUTH_POLICY,
7411
- owner: {
7412
- name: MANAGED_MARKETPLACE_OWNER,
7413
- schema: record.schema_epoch
7528
+ source: {
7529
+ source: "local",
7530
+ path: record.relative_path
7414
7531
  },
7415
- cache: { identity: {
7416
- version: record.version,
7417
- digest: record.digest,
7418
- epoch: record.epoch,
7419
- artifact_id: record.artifact_id
7420
- } }
7532
+ policy: {
7533
+ installation: MANAGED_INSTALL_POLICY,
7534
+ authentication: MANAGED_AUTH_POLICY
7535
+ },
7536
+ category: MANAGED_MARKETPLACE_CATEGORY
7421
7537
  };
7422
7538
  }
7423
7539
  function marketplaceWithManagedEntry(document, record) {
@@ -7454,12 +7570,8 @@ function pickManagedFields(entry) {
7454
7570
  for (const key of [
7455
7571
  "name",
7456
7572
  "source",
7457
- "version",
7458
- "category",
7459
- "install",
7460
- "auth",
7461
- "owner",
7462
- "cache"
7573
+ "policy",
7574
+ "category"
7463
7575
  ]) {
7464
7576
  const value = entry[key];
7465
7577
  if (value !== void 0) result[key] = value;
@@ -8262,9 +8374,13 @@ async function installHolyCodex(request = {}, options = {}, environment = proces
8262
8374
  try {
8263
8375
  await writeAtomicJson(paths.activeRecord, asJsonValue$1(record));
8264
8376
  await appendJournal(paths, runId, "active-written", { artifact_id: artifactId }, now);
8265
- const nextMarketplace = marketplaceWithManagedEntry(await readMarketplace(paths.marketplaceFile), record);
8377
+ const marketplace = await readMarketplaceForInstall(paths.marketplaceFile);
8378
+ const nextMarketplace = marketplaceWithManagedEntry(marketplace.document, record);
8266
8379
  await writeMarketplace(paths.marketplaceFile, nextMarketplace);
8267
- await appendJournal(paths, runId, "marketplace-written", { artifact_id: artifactId }, now);
8380
+ await appendJournal(paths, runId, "marketplace-written", {
8381
+ artifact_id: artifactId,
8382
+ legacy_repaired: marketplace.repaired ? 1 : 0
8383
+ }, now);
8268
8384
  await verifyActivation(paths, record);
8269
8385
  await appendJournal(paths, runId, "activation-verified", { artifact_id: artifactId }, now);
8270
8386
  } catch (error) {
@@ -8758,7 +8874,7 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
8758
8874
  if (validated.stdin === void 0) childStdin.end();
8759
8875
  else childStdin.end(validated.stdin);
8760
8876
  } catch (error) {
8761
- finish(null, null, errorMessage$1(error), errorCode(error));
8877
+ finish(null, null, errorMessage(error), errorCode(error));
8762
8878
  }
8763
8879
  });
8764
8880
  }
@@ -8847,7 +8963,7 @@ function processErrorResult(error) {
8847
8963
  timedOut: false,
8848
8964
  aborted: false,
8849
8965
  outputTruncated: false,
8850
- error: errorMessage$1(error),
8966
+ error: errorMessage(error),
8851
8967
  ...errorCode(error) === void 0 ? {} : { errorCode: errorCode(error) }
8852
8968
  };
8853
8969
  }
@@ -8894,7 +9010,7 @@ function emptyOutput() {
8894
9010
  function outputText(state) {
8895
9011
  return state.truncated ? `${state.head}${TRUNCATED_MARKER}${state.tail}` : state.head;
8896
9012
  }
8897
- function errorMessage$1(error) {
9013
+ function errorMessage(error) {
8898
9014
  return error instanceof Error ? error.message : String(error);
8899
9015
  }
8900
9016
  function errorCode(error) {
@@ -9378,7 +9494,7 @@ const GENERATED_WORKFLOW_MAX_SESSION_ID_BYTES = 96;
9378
9494
  const GENERATED_WORKFLOW_MAX_NAME_BYTES = 64;
9379
9495
  const SafeSegmentSchema = String$.pipe(pattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/u));
9380
9496
  const SafeWorkflowNameSchema = String$.pipe(pattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u));
9381
- const ShortHashSchema = String$.pipe(pattern(/^[0-9a-f]{16}$/u));
9497
+ const ShortHashSchema = String$.pipe(pattern(/^[0-9a-f]{4}$/u));
9382
9498
  const NativeWorkflowIdentitySchema = Struct({
9383
9499
  source_sha256: DigestSchema$3,
9384
9500
  ir_sha256: DigestSchema$3,
@@ -9432,46 +9548,55 @@ var GeneratedWorkflowStore = class {
9432
9548
  await this.ensureOwnedDirectory(sessionDirectory);
9433
9549
  await this.assertCaseSafeDirectory(sessionDirectory, name);
9434
9550
  const sourceSha256 = sha256(bytes);
9435
- const shortHash = await shortWorkflowHash(ownerSessionId, name, sourceSha256);
9436
- const fileName = `${name}-${shortHash}.ts`;
9437
- const sourcePath = join(sessionDirectory, fileName);
9438
- const metadataPath = `${sourcePath}.metadata.json`;
9439
- const existing = await this.readMetadataIfPresent(metadataPath);
9440
9551
  const now = this.now();
9441
- if (existing !== void 0) {
9442
- if (existing.owner_session_id !== ownerSessionId || existing.safe_name !== name || existing.short_hash !== shortHash || existing.source_path !== sourcePath) throw new GeneratedWorkflowStoreError("collision", "The generated workflow name collides with different persisted metadata.");
9443
- const existingBytes = await this.readOwnedBytes(sourcePath);
9444
- if (sha256(existingBytes) !== sourceSha256) throw new GeneratedWorkflowStoreError("collision", "The generated workflow short hash collides with different source bytes.");
9552
+ for (let attempt = 0; attempt < 16; attempt += 1) {
9553
+ const shortHash = await shortWorkflowHash(ownerSessionId, name, sourceSha256, attempt);
9554
+ const fileName = `${name}-${shortHash}.ts`;
9555
+ const sourcePath = join(sessionDirectory, fileName);
9556
+ const metadataPath = `${sourcePath}.metadata.json`;
9557
+ const existing = await this.readMetadataIfPresent(metadataPath);
9558
+ if (existing !== void 0) {
9559
+ const existingBytes = await this.readOwnedBytes(sourcePath);
9560
+ if (sha256(existingBytes) !== sourceSha256) continue;
9561
+ if (existing.owner_session_id !== ownerSessionId || existing.safe_name !== name || existing.short_hash !== shortHash || existing.source_path !== sourcePath) throw new GeneratedWorkflowStoreError("collision", "The generated workflow name collides with different persisted metadata.");
9562
+ return {
9563
+ metadata: await this.writeMetadata({
9564
+ ...existing,
9565
+ last_access_at: now.toISOString(),
9566
+ expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
9567
+ active: true
9568
+ }),
9569
+ source: new TextDecoder().decode(existingBytes)
9570
+ };
9571
+ }
9572
+ try {
9573
+ await this.readOwnedBytes(sourcePath);
9574
+ continue;
9575
+ } catch (error) {
9576
+ if (!isMissingPath(error)) throw error;
9577
+ }
9578
+ await this.writeAtomicBytes(sourcePath, bytes);
9579
+ const metadata = await this.writeMetadata({
9580
+ schema_epoch: GENERATED_WORKFLOW_SCHEMA_EPOCH,
9581
+ naming_version: GENERATED_WORKFLOW_NAMING_VERSION,
9582
+ owner_session_id: ownerSessionId,
9583
+ safe_name: name,
9584
+ short_hash: shortHash,
9585
+ source_sha256: sourceSha256,
9586
+ source_path: sourcePath,
9587
+ created_at: now.toISOString(),
9588
+ last_access_at: now.toISOString(),
9589
+ expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
9590
+ active: true
9591
+ });
9592
+ const verified = await this.readOwnedBytes(sourcePath);
9593
+ if (sha256(verified) !== sourceSha256) throw new GeneratedWorkflowStoreError("integrity_uncertain", "The generated workflow failed post-write digest verification.");
9445
9594
  return {
9446
- metadata: await this.writeMetadata({
9447
- ...existing,
9448
- last_access_at: now.toISOString(),
9449
- expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
9450
- active: true
9451
- }),
9452
- source: new TextDecoder().decode(existingBytes)
9595
+ metadata,
9596
+ source: new TextDecoder().decode(verified)
9453
9597
  };
9454
9598
  }
9455
- await this.writeAtomicBytes(sourcePath, bytes);
9456
- const metadata = await this.writeMetadata({
9457
- schema_epoch: GENERATED_WORKFLOW_SCHEMA_EPOCH,
9458
- naming_version: GENERATED_WORKFLOW_NAMING_VERSION,
9459
- owner_session_id: ownerSessionId,
9460
- safe_name: name,
9461
- short_hash: shortHash,
9462
- source_sha256: sourceSha256,
9463
- source_path: sourcePath,
9464
- created_at: now.toISOString(),
9465
- last_access_at: now.toISOString(),
9466
- expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
9467
- active: true
9468
- });
9469
- const verified = await this.readOwnedBytes(sourcePath);
9470
- if (sha256(verified) !== sourceSha256) throw new GeneratedWorkflowStoreError("integrity_uncertain", "The generated workflow failed post-write digest verification.");
9471
- return {
9472
- metadata,
9473
- source: new TextDecoder().decode(verified)
9474
- };
9599
+ throw new GeneratedWorkflowStoreError("collision", "The generated workflow short hash collided with different source bytes.");
9475
9600
  }
9476
9601
  async read(sourcePath) {
9477
9602
  const normalized = this.assertOwnedSourcePath(sourcePath);
@@ -9505,7 +9630,7 @@ var GeneratedWorkflowStore = class {
9505
9630
  const directory = join(this.root, ownerSessionId);
9506
9631
  await this.assertOwnedPath(directory, true);
9507
9632
  const entries = await this.readOwnedDirectory(directory).catch((error) => {
9508
- if (isFsCode(error, "ENOENT")) return [];
9633
+ if (isMissingPath(error)) return [];
9509
9634
  throw error;
9510
9635
  });
9511
9636
  for (const entry of entries) {
@@ -9532,7 +9657,7 @@ var GeneratedWorkflowStore = class {
9532
9657
  await this.assertTree(directory);
9533
9658
  await this.requireBoundary().removeOwnedDirectory(this.root, directory);
9534
9659
  } catch (error) {
9535
- if (isFsCode(error, "ENOENT")) return;
9660
+ if (isMissingPath(error)) return;
9536
9661
  if (error instanceof GeneratedWorkflowStoreError) throw error;
9537
9662
  throw new GeneratedWorkflowStoreError("storage_failure", "The generated workflow session could not be removed.", error);
9538
9663
  }
@@ -9548,7 +9673,7 @@ var GeneratedWorkflowStore = class {
9548
9673
  await this.assertOwnedPath(directory, false);
9549
9674
  return true;
9550
9675
  } catch (error) {
9551
- if (isFsCode(error, "ENOENT")) return false;
9676
+ if (isMissingPath(error)) return false;
9552
9677
  throw error;
9553
9678
  }
9554
9679
  }
@@ -9587,7 +9712,7 @@ var GeneratedWorkflowStore = class {
9587
9712
  if (!preview) await this.requireBoundary().removeOwnedDirectory(this.root, directory);
9588
9713
  removed.push(directory);
9589
9714
  } catch (error) {
9590
- if (isFsCode(error, "ENOENT")) continue;
9715
+ if (isMissingPath(error)) continue;
9591
9716
  uncertain.push(directory);
9592
9717
  }
9593
9718
  }
@@ -9644,7 +9769,7 @@ var GeneratedWorkflowStore = class {
9644
9769
  try {
9645
9770
  return await this.readMetadata(path);
9646
9771
  } catch (error) {
9647
- if (isFsCode(error, "ENOENT")) return void 0;
9772
+ if (isMissingPath(error)) return void 0;
9648
9773
  throw error;
9649
9774
  }
9650
9775
  }
@@ -9654,7 +9779,7 @@ var GeneratedWorkflowStore = class {
9654
9779
  try {
9655
9780
  parsed = JSON.parse(new TextDecoder().decode(await this.requireBoundary().readOwnedFile(this.root, path)));
9656
9781
  } catch (error) {
9657
- if (isFsCode(error, "ENOENT")) throw error;
9782
+ if (isMissingPath(error)) throw error;
9658
9783
  throw new GeneratedWorkflowStoreError("malformed_metadata", "Generated workflow metadata is not valid JSON.", error);
9659
9784
  }
9660
9785
  const metadata = decodeSchema$1(GeneratedWorkflowMetadataSchema, parsed);
@@ -9720,16 +9845,15 @@ function assertSafeWorkflowName(value) {
9720
9845
  if (parsed === void 0 || value === "." || value === "..") throw new GeneratedWorkflowStoreError("invalid_name", "The generated workflow name is not filesystem-safe.");
9721
9846
  return parsed;
9722
9847
  }
9723
- async function shortWorkflowHash(sessionId, safeName, sourceSha256) {
9848
+ async function shortWorkflowHash(sessionId, safeName, sourceSha256, attempt = 0) {
9724
9849
  assertSafeSessionId(sessionId);
9725
9850
  assertSafeWorkflowName(safeName);
9726
9851
  if (decodeSchema$1(DigestSchema$3, sourceSha256) === void 0) throw new GeneratedWorkflowStoreError("invalid_input", "The source digest is invalid.");
9727
- return (await domainSeparatedSha256("holycodex-generated-workflow-name-v1", [new TextEncoder().encode(canonicalJson({
9728
- version: GENERATED_WORKFLOW_NAMING_VERSION,
9729
- session_id: sessionId,
9730
- safe_name: safeName,
9731
- source_sha256: sourceSha256
9732
- }))])).slice(0, 16);
9852
+ if (!Number.isSafeInteger(attempt) || attempt < 0 || attempt > 15) throw new GeneratedWorkflowStoreError("invalid_input", "The workflow hash attempt is invalid.");
9853
+ return randomBytes(2).toString("hex");
9854
+ }
9855
+ function isMissingPath(error) {
9856
+ return isFsCode(error, "ENOENT") || isFsCode(error, "not_found");
9733
9857
  }
9734
9858
  function sha256(bytes) {
9735
9859
  return createHash("sha256").update(bytes).digest("hex");
@@ -9997,7 +10121,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
9997
10121
  const target = join(paths.generatedWorkflowsRoot, sessionId);
9998
10122
  if (!pathWithin(paths.generatedWorkflowsRoot, target)) throw new CleanupError("cleanup_failed", "The workflow session path escaped the owned root.");
9999
10123
  try {
10000
- const store = new GeneratedWorkflowStore(paths.stateRoot, {
10124
+ const store = new GeneratedWorkflowStore(paths.codexHome, {
10001
10125
  now: () => now,
10002
10126
  ...options.generatedWorkflowBoundary === void 0 ? {} : { boundary: options.generatedWorkflowBoundary }
10003
10127
  });
@@ -10063,10 +10187,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
10063
10187
  reasons
10064
10188
  };
10065
10189
  }
10066
- const marketplace = await readMarketplace(paths.marketplaceFile).catch((error) => {
10067
- if (isFsCode(error, "ENOENT")) return { plugins: [] };
10068
- throw error;
10069
- });
10190
+ const marketplace = await readMarketplace(paths.marketplaceFile);
10070
10191
  const managed = active ? findManagedEntry(marketplace) : void 0;
10071
10192
  if (active && managed && managedEntryMatches(managed, active)) {
10072
10193
  const next = {
@@ -10096,7 +10217,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
10096
10217
  }
10097
10218
  async function removeExpiredGeneratedWorkflows(paths, preview, removed, preserved, now, cutoff, boundary) {
10098
10219
  try {
10099
- const result = await new GeneratedWorkflowStore(paths.stateRoot, {
10220
+ const result = await new GeneratedWorkflowStore(paths.codexHome, {
10100
10221
  now: () => now,
10101
10222
  ttlMs: Math.max(1, now.getTime() - cutoff),
10102
10223
  ...boundary === void 0 ? {} : { boundary }
@@ -13517,9 +13638,8 @@ var GitBashError = class extends Error {
13517
13638
  //#endregion
13518
13639
  //#region packages/git-bash/src/git-bash-resolver.ts
13519
13640
  const GIT_BASH_ENV_KEY = "HOLYCODEX_GIT_BASH_PATH";
13520
- const PROGRAM_FILES_GIT_BASH = "C:\\Program Files\\Git\\bin\\bash.exe";
13521
- const PROGRAM_FILES_X86_GIT_BASH = "C:\\Program Files (x86)\\Git\\bin\\bash.exe";
13522
- const DEFAULT_INSTALL_HINT = `Git Bash required. Install: winget install --id Git.Git -e --source winget\nCustom path: set ${GIT_BASH_ENV_KEY}=C:\\path\\to\\bash.exe`;
13641
+ const GIT_BASH_EXECUTABLE_PATH = "C:\\Program Files\\Git\\bin\\bash.exe";
13642
+ const DEFAULT_INSTALL_HINT = `Git Bash is required at ${GIT_BASH_EXECUTABLE_PATH}. Install: winget install --id Git.Git -e --source winget`;
13523
13643
  const EnvironmentShapeSchema$1 = Record({
13524
13644
  key: String$,
13525
13645
  value: Unknown
@@ -13537,54 +13657,22 @@ function resolveGitBash(input) {
13537
13657
  if (configured !== void 0 && configured.length > 0) {
13538
13658
  checkedPaths.push(configured);
13539
13659
  const normalized = normalizeGitBashExecutablePath(configured, input.platform);
13540
- if (normalized !== null && available(input, configured, normalized)) return found(normalized, "env", checkedPaths);
13660
+ if (normalized !== null && isRequiredGitBashExecutablePath(normalized, input.platform) && available(input, configured, normalized)) return found(normalized, "env", checkedPaths);
13541
13661
  return missing(checkedPaths, `${GIT_BASH_ENV_KEY} is configured but invalid or unavailable; refusing fallback.\n${DEFAULT_INSTALL_HINT}`);
13542
13662
  }
13543
- const fixedCandidates = [{
13544
- path: PROGRAM_FILES_GIT_BASH,
13545
- source: "program-files"
13546
- }, {
13547
- path: PROGRAM_FILES_X86_GIT_BASH,
13548
- source: "program-files-x86"
13549
- }];
13550
- for (const candidate of fixedCandidates) {
13551
- checkedPaths.push(candidate.path);
13552
- const normalized = normalizeGitBashExecutablePath(candidate.path, input.platform);
13553
- if (normalized !== null && available(input, candidate.path, normalized)) return found(normalized, candidate.source, checkedPaths);
13554
- }
13555
- let pathCandidates;
13556
- try {
13557
- pathCandidates = validateWhereOutput(input.where("bash"));
13558
- } catch (error) {
13559
- return missing(checkedPaths, `${DEFAULT_INSTALL_HINT}\nPATH lookup failed: ${errorMessage(error)}`);
13560
- }
13561
- const seen = /* @__PURE__ */ new Set();
13562
- for (const raw of pathCandidates) {
13563
- const candidate = raw.trim();
13564
- if (candidate.length === 0) continue;
13565
- checkedPaths.push(candidate);
13566
- const normalized = normalizeGitBashExecutablePath(candidate, input.platform);
13567
- if (normalized === null) continue;
13568
- const key = normalized.toLowerCase();
13569
- if (seen.has(key)) continue;
13570
- seen.add(key);
13571
- if (available(input, candidate, normalized)) return found(normalized, "path", checkedPaths);
13572
- }
13663
+ checkedPaths.push(GIT_BASH_EXECUTABLE_PATH);
13664
+ const normalized = normalizeGitBashExecutablePath(GIT_BASH_EXECUTABLE_PATH, input.platform);
13665
+ if (normalized !== null && available(input, "C:\\Program Files\\Git\\bin\\bash.exe", normalized)) return found(normalized, "program-files", checkedPaths);
13573
13666
  return missing(checkedPaths);
13574
13667
  }
13575
13668
  /** Resolves Git Bash using the current process and injectable platform seams. */
13576
13669
  function resolveGitBashForCurrentProcess(input = {}) {
13577
- const platform = input.platform ?? process.platform;
13578
- const environment = input.env ?? process.env;
13579
13670
  return resolveGitBash({
13580
- platform,
13581
- env: environment,
13671
+ platform: input.platform ?? process.platform,
13672
+ env: input.env ?? process.env,
13582
13673
  exists: input.exists ?? defaultExists,
13583
13674
  inspect: input.inspect ?? (input.exists === void 0 ? defaultInspect : (path) => safeExists(input.exists, path) ? "file" : "missing"),
13584
- where: input.where ?? ((command) => {
13585
- if (platform !== "win32") return [];
13586
- return whereGitBash(command, environment);
13587
- })
13675
+ where: input.where ?? (() => [])
13588
13676
  });
13589
13677
  }
13590
13678
  /** Normalizes and validates an explicit Git Bash executable path without resolving links. */
@@ -13600,6 +13688,11 @@ function normalizeGitBashExecutablePath(value, platform) {
13600
13688
  if (platform === "win32" && isRejectedWindowsAlias(normalized)) return null;
13601
13689
  return normalized;
13602
13690
  }
13691
+ function isRequiredGitBashExecutablePath(path, platform) {
13692
+ const normalized = normalizeGitBashExecutablePath(path, platform);
13693
+ if (normalized === null) return false;
13694
+ return platform !== "win32" || normalized.toLowerCase() === "C:\\Program Files\\Git\\bin\\bash.exe".toLowerCase();
13695
+ }
13603
13696
  /** Checks a candidate without following symbolic links or reparse aliases. */
13604
13697
  function isSafeGitBashExecutablePath(path) {
13605
13698
  try {
@@ -13623,11 +13716,6 @@ function validateResolverInput(input) {
13623
13716
  }
13624
13717
  return Object.freeze(environment);
13625
13718
  }
13626
- function validateWhereOutput(value) {
13627
- const decoded = decodeUnknownEither(Array$(String$), { onExcessProperty: "error" })(value);
13628
- if (isLeft(decoded)) throw new GitBashError("unavailable", "The Windows PATH lookup returned invalid candidates.", {}, { cause: decoded.left });
13629
- return decoded.right;
13630
- }
13631
13719
  function available(input, raw, normalized) {
13632
13720
  if ((input.inspect === void 0 ? "file" : safeInspect(input.inspect, normalized)) !== "file") return false;
13633
13721
  return safeExists(input.exists, normalized) || raw !== normalized && safeExists(input.exists, raw);
@@ -13652,32 +13740,6 @@ function defaultExists(path) {
13652
13740
  function defaultInspect(path) {
13653
13741
  return isSafeGitBashExecutablePath(path) ? "file" : "missing";
13654
13742
  }
13655
- function whereGitBash(command, environment) {
13656
- try {
13657
- const output = execFileSync("where.exe", [command], {
13658
- encoding: "utf8",
13659
- windowsHide: true,
13660
- env: whereEnvironment(environment)
13661
- });
13662
- return String(output).split(/\r?\n/u).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
13663
- } catch {
13664
- return [];
13665
- }
13666
- }
13667
- function whereEnvironment(input) {
13668
- const entries = Object.entries(input);
13669
- const exactPath = entries.find(([key, value]) => key === "PATH" && value !== void 0);
13670
- const fallbackPath = [...entries].reverse().find(([key, value]) => key.toLowerCase() === "path" && value !== void 0);
13671
- const pathEntry = exactPath ?? fallbackPath;
13672
- const environment = {};
13673
- for (const [key, value] of entries) {
13674
- const normalizedKey = key.toLowerCase();
13675
- if (normalizedKey === "path" || normalizedKey === "original_path" || value === void 0) continue;
13676
- environment[key] = value;
13677
- }
13678
- if (pathEntry !== void 0) environment["PATH"] = pathEntry[1];
13679
- return environment;
13680
- }
13681
13743
  function isRejectedWindowsAlias(path) {
13682
13744
  const normalized = path.toLowerCase().replaceAll("/", "\\");
13683
13745
  return normalized.includes("\\windows\\system32\\") || normalized.split("\\").includes("windowsapps");
@@ -13697,9 +13759,6 @@ function missing(checkedPaths, installHint = DEFAULT_INSTALL_HINT) {
13697
13759
  installHint
13698
13760
  });
13699
13761
  }
13700
- function errorMessage(error) {
13701
- return error instanceof Error ? error.message : String(error);
13702
- }
13703
13762
  //#endregion
13704
13763
  //#region packages/git-bash/src/runner.ts
13705
13764
  const DEFAULT_MAX_OUTPUT_CHARS = 262144;
@@ -13721,6 +13780,7 @@ async function runGitBashCommand(input) {
13721
13780
  const validated = validateRunInput(input);
13722
13781
  const normalizedBashPath = normalizeGitBashExecutablePath(validated.bashPath, platform);
13723
13782
  if (normalizedBashPath === null) throw new GitBashError("invalid_input", "Git Bash executable path must be absolute, traversal-free, and name bash.");
13783
+ if (!isRequiredGitBashExecutablePath(normalizedBashPath, platform)) throw new GitBashError("invalid_input", "Windows Git Bash must be C:/Program Files/Git/bin/bash.exe.");
13724
13784
  const safeExecutable = validated.isSafeExecutable ?? isSafeGitBashExecutablePath;
13725
13785
  let executableIsSafe = false;
13726
13786
  try {
@@ -13815,12 +13875,37 @@ function isAbortSignal(value) {
13815
13875
  //#region packages/cli/src/workflow.ts
13816
13876
  const MAX_WORKFLOW_SOURCE_BYTES = 1048576;
13817
13877
  async function executeWorkflowCommand(parsed, context) {
13818
- const service = context.workflowService ?? await createDefaultWorkflowService(context, parsed);
13878
+ const service = parsed.command === "workflow create" || parsed.command === "workflow check" ? context.workflowService ?? {} : context.workflowService ?? await createDefaultWorkflowService(context, parsed);
13819
13879
  switch (parsed.command) {
13880
+ case "workflow create": {
13881
+ const source = await readWorkflowSource(parsed.positionals[0] ?? "", parsed.positionals[1], parsed, context);
13882
+ (await loadNativeWorkflowSource({ source: source.source })).dispose();
13883
+ const sessionId = optionString$1(parsed, "session-id") ?? context.workflowSessionId;
13884
+ const name = optionString$1(parsed, "name") ?? context.workflowName;
13885
+ const materialized = await materializeGeneratedWorkflow(source, {
13886
+ ...context,
13887
+ ...sessionId === void 0 ? {} : { workflowSessionId: sessionId },
13888
+ ...name === void 0 ? {} : { workflowName: name }
13889
+ });
13890
+ await materialized.store.setSessionActivity(materialized.sessionId, false);
13891
+ return asJsonValue$1((await materialized.store.read(materialized.source.path ?? "")).metadata);
13892
+ }
13893
+ case "workflow check": {
13894
+ const source = await readWorkflowSource(parsed.positionals[0] ?? "", void 0, parsed, context);
13895
+ const workflow = await loadNativeWorkflow(source);
13896
+ try {
13897
+ return asJsonValue$1({
13898
+ valid: true,
13899
+ execution_mode: "native",
13900
+ source_path: source.path
13901
+ });
13902
+ } finally {
13903
+ workflow.dispose();
13904
+ }
13905
+ }
13820
13906
  case "workflow run": {
13821
13907
  let workflow = await readWorkflowSource(parsed.positionals[0] ?? "", parsed.positionals[1], parsed, context);
13822
- const compatibility = parsed.options["compat-quickjs"] === true;
13823
- const nativeRequested = context.workflowService === void 0 && !compatibility;
13908
+ const nativeRequested = context.workflowService === void 0;
13824
13909
  const generatedStore = context.workflowService === void 0 && workflow.path === null ? await materializeGeneratedWorkflow(workflow, context) : void 0;
13825
13910
  if (generatedStore !== void 0) workflow = generatedStore.source;
13826
13911
  let nativeWorkflow;
@@ -13848,8 +13933,7 @@ async function executeWorkflowCommand(parsed, context) {
13848
13933
  source: workflow.source,
13849
13934
  args: workflow.args,
13850
13935
  ...generatedStore === void 0 || workflow.path === null ? {} : { sourcePath: workflow.path },
13851
- ...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow },
13852
- ...compatibility ? { compatibility: true } : {}
13936
+ ...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
13853
13937
  }));
13854
13938
  } finally {
13855
13939
  nativeWorkflow?.dispose();
@@ -13863,8 +13947,7 @@ async function executeWorkflowCommand(parsed, context) {
13863
13947
  const runId = requiredPosition(parsed, 0, "run id");
13864
13948
  let workflow = await readWorkflowSource(requiredPosition(parsed, 1, "workflow source"), parsed.positionals[2], parsed, context);
13865
13949
  await assertResumeInputIdentity(service, runId, workflow);
13866
- const compatibility = parsed.options["compat-quickjs"] === true;
13867
- const nativeRequested = context.workflowService === void 0 && !compatibility;
13950
+ const nativeRequested = context.workflowService === void 0;
13868
13951
  const generatedStore = context.workflowService === void 0 && workflow.path === null ? await materializeGeneratedWorkflow(workflow, context) : void 0;
13869
13952
  if (generatedStore !== void 0) workflow = generatedStore.source;
13870
13953
  let nativeWorkflow;
@@ -13876,8 +13959,7 @@ async function executeWorkflowCommand(parsed, context) {
13876
13959
  source: workflow.source,
13877
13960
  args: workflow.args,
13878
13961
  ...generatedStore === void 0 || workflow.path === null ? {} : { sourcePath: workflow.path },
13879
- ...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow },
13880
- ...compatibility ? { compatibility: true } : {}
13962
+ ...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
13881
13963
  }));
13882
13964
  } finally {
13883
13965
  nativeWorkflow?.dispose();
@@ -13890,8 +13972,7 @@ async function executeWorkflowCommand(parsed, context) {
13890
13972
  return asJsonValue$1(await requireCapability(service.continuation, "continuation")({
13891
13973
  runId,
13892
13974
  source: workflow.source,
13893
- args: workflow.args,
13894
- ...parsed.options["compat-quickjs"] === true ? { compatibility: true } : {}
13975
+ args: workflow.args
13895
13976
  }));
13896
13977
  }
13897
13978
  case "workflow goal": return asJsonValue$1(await requireCapability(service.goal, "goal")(requiredPosition(parsed, 0, "run id"), requiredPosition(parsed, 1, "goal summary")));
@@ -13936,7 +14017,7 @@ async function readWorkflowSource(reference, argumentText, parsed, context) {
13936
14017
  }
13937
14018
  if (reference.length === 0 || extname(reference) !== ".ts") throw new WorkflowCommandError("invalid_argument", "Workflow source must be a TypeScript file or stdin.");
13938
14019
  const path = resolve(context.cwd ?? process.cwd(), reference);
13939
- const generatedStore = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).stateRoot, {
14020
+ const generatedStore = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).codexHome, {
13940
14021
  ...context.now === void 0 ? {} : { now: context.now },
13941
14022
  ...context.generatedWorkflowBoundary === void 0 ? {} : { boundary: context.generatedWorkflowBoundary }
13942
14023
  });
@@ -13966,7 +14047,7 @@ async function readWorkflowSource(reference, argumentText, parsed, context) {
13966
14047
  }
13967
14048
  /** Load a file-backed native workflow through the bounded runtime source boundary. */
13968
14049
  async function loadNativeWorkflow(source) {
13969
- if (source.path === null) throw new WorkflowCommandError("invalid_argument", "Native workflows require a trusted TypeScript file; use --compat-quickjs with stdin.");
14050
+ if (source.path === null) throw new WorkflowCommandError("invalid_argument", "Workflows require a trusted TypeScript file; use workflow create for generated sources.");
13970
14051
  try {
13971
14052
  return await loadNativeWorkflowSource({ source: source.source });
13972
14053
  } catch (error) {
@@ -13987,7 +14068,7 @@ function defaultObjective(path, reference) {
13987
14068
  async function materializeGeneratedWorkflow(source, context) {
13988
14069
  const sessionId = context.workflowSessionId;
13989
14070
  if (sessionId === void 0) throw new WorkflowCommandError("invalid_argument", "Generated workflow storage requires an explicit caller session identity.");
13990
- const store = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).stateRoot, {
14071
+ const store = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).codexHome, {
13991
14072
  ...context.now === void 0 ? {} : { now: context.now },
13992
14073
  ...context.generatedWorkflowBoundary === void 0 ? {} : { boundary: context.generatedWorkflowBoundary }
13993
14074
  });
@@ -14080,7 +14161,9 @@ async function createDefaultWorkflowService(context, parsed) {
14080
14161
  maxCalls: planDefinition.value.budget.maxCalls,
14081
14162
  costMax: planDefinition.value.budget.costMax
14082
14163
  },
14083
- refinementsEnabled: true
14164
+ refinementsEnabled: true,
14165
+ canonicalVersion: await readCanonicalVersion(),
14166
+ platform: process.platform === "win32" ? "win32" : "posix"
14084
14167
  });
14085
14168
  return {
14086
14169
  create: async (input) => await host.create({
@@ -14111,22 +14194,28 @@ async function createDefaultWorkflowService(context, parsed) {
14111
14194
  stop: async (runId) => await host.stop(runId),
14112
14195
  stopAgent: async (runId, callId) => await host.stopAgent(runId, callId),
14113
14196
  save: async (scope, name, source) => await saveWorkflow(stateRoot, scope, name, source, cwd, context.now ?? (() => /* @__PURE__ */ new Date())),
14114
- invoke: async (scope, name, args, useCompatibility = false) => {
14197
+ invoke: async (scope, name, args, _compatibilityAlias = false) => {
14115
14198
  const saved = await readSavedWorkflow(stateRoot, scope, name, cwd);
14116
- if (!useCompatibility) throw new WorkflowCommandError("invalid_argument", "Saved native workflows require a file-backed module; invoke with --compat-quickjs for stored source.");
14117
- const created = await host.create({
14118
- source: saved.source,
14119
- args,
14120
- objective: `workflow:${saved.name}`,
14121
- plan,
14122
- serviceTier,
14123
- expectedConcurrency: maxSubagents
14124
- });
14125
- return asJsonValue$1(await host.run({
14126
- runId: created.run_id,
14127
- source: saved.source,
14128
- args
14129
- }));
14199
+ const workflow = await loadNativeWorkflowSource({ source: saved.source });
14200
+ try {
14201
+ const created = await host.create({
14202
+ source: saved.source,
14203
+ args,
14204
+ objective: `workflow:${saved.name}`,
14205
+ plan,
14206
+ serviceTier,
14207
+ expectedConcurrency: maxSubagents,
14208
+ workflow
14209
+ });
14210
+ return asJsonValue$1(await host.run({
14211
+ runId: created.run_id,
14212
+ source: saved.source,
14213
+ args,
14214
+ workflow
14215
+ }));
14216
+ } finally {
14217
+ workflow.dispose();
14218
+ }
14130
14219
  },
14131
14220
  refinements: {
14132
14221
  list: async () => await listRefinements(stateRoot),
@@ -14145,10 +14234,7 @@ async function createDefaultWorkflowService(context, parsed) {
14145
14234
  };
14146
14235
  }
14147
14236
  function resolveWorkflowInstallerPaths(installer, environment) {
14148
- return resolveInstallerPaths({ paths: {
14149
- codexHome: installer?.paths?.codexHome ?? environment?.["CODEX_HOME"] ?? resolve(process.cwd(), ".codex"),
14150
- marketplaceRoot: installer?.paths?.marketplaceRoot ?? environment?.["HOLYCODEX_MARKETPLACE_ROOT"] ?? resolve(process.cwd(), ".marketplace")
14151
- } }, environment);
14237
+ return resolveInstallerPaths(installer, environment);
14152
14238
  }
14153
14239
  async function invokeWorkflowCapability(capability, options, context) {
14154
14240
  if (decodeSchema$1(CapabilityNameSchema, capability) === void 0) throw new WorkflowCommandError("invalid_argument", "The capability name is invalid.");
@@ -14809,10 +14895,9 @@ Options:
14809
14895
  --json Emit one validated JSON envelope.
14810
14896
  --no-tui Disable prompts and interactive UI behavior.
14811
14897
 
14812
- Workflow execution is native Effect workflow-module execution by default. A
14813
- trusted TypeScript file must export a default workflow.wait(...) value. The
14814
- explicit --compat-quickjs flag selects the compatibility-only string evaluator;
14815
- stdin requires that flag and an explicit --task objective.
14898
+ Workflow execution uses one capability-denied QuickJS TypeScript evaluator. A
14899
+ trusted TypeScript file must export a default workflow.wait(...) value. Use
14900
+ workflow create for generated sources; stdin requires an explicit --task objective.
14816
14901
 
14817
14902
  Optional Work, Web, Security, Computer Use, LSP, LSP setup, and Git Bash
14818
14903
  providers are independently capability-gated. Missing providers fail closed;
@@ -14822,6 +14907,8 @@ const WORKFLOW_HELP = `Workflow commands
14822
14907
 
14823
14908
  Usage:
14824
14909
  holycodex workflow run <file.ts|-> [args.json] [options]
14910
+ holycodex workflow create <file.ts|-> [args.json] [--name <name>] [--session-id <id>]
14911
+ holycodex workflow check <file.ts> [options]
14825
14912
  holycodex workflow list [options]
14826
14913
  holycodex workflow show <run-id> [options]
14827
14914
  holycodex workflow inspect <run-id> [--follow] [options]
@@ -14841,12 +14928,12 @@ Options:
14841
14928
  --autonomy <mode> Select manual, assisted, or autonomous execution.
14842
14929
  --max-subagents <n> Bound specialist concurrency.
14843
14930
  --trusted Assert the caller has established project trust.
14844
- --compat-quickjs Explicitly select the string/QuickJS compatibility path.
14845
- --task <objective> Required for native-unsupported stdin compatibility runs.
14931
+ --compat-quickjs Deprecated one-release alias; the same evaluator is used.
14932
+ --task <objective> Required when workflow source is read from stdin.
14846
14933
  --json, --no-tui Select machine/non-interactive output behavior.
14847
14934
 
14848
- Native workflow files must export a default workflow.wait(...) value. The
14849
- compatibility evaluator is never selected implicitly; use --compat-quickjs.
14935
+ Workflow files must export a default workflow.wait(...) value. workflow check
14936
+ performs type, import, schema, and security validation without host effects.
14850
14937
  `;
14851
14938
  const INSTALL_HELP = `Install HolyCodex into the owned scope.
14852
14939
 
@@ -14883,6 +14970,8 @@ function helpText(topic) {
14883
14970
  case "version": return VERSION_HELP;
14884
14971
  case "workflow":
14885
14972
  case "workflow run":
14973
+ case "workflow create":
14974
+ case "workflow check":
14886
14975
  case "workflow list":
14887
14976
  case "workflow show":
14888
14977
  case "workflow inspect":
@@ -15263,14 +15352,68 @@ function isJsonObject(value) {
15263
15352
  }
15264
15353
  function emitProgress(context, json, message) {
15265
15354
  if (json || parsedVerbose(context) === false) return;
15266
- context.io?.writeStderr?.(`${message}\n`);
15355
+ context.io?.writeStderr?.(`${renderProgress(message, {
15356
+ stderrIsTTY: context.io?.stderrIsTTY,
15357
+ env: context.env
15358
+ })}\n`);
15267
15359
  }
15268
15360
  function parsedVerbose(context) {
15269
15361
  return context.io?.stderrIsTTY === true || context.io?.stderrIsTTY === void 0;
15270
15362
  }
15271
- function renderHuman(result) {
15272
- if (result.envelope.ok) return `${result.envelope.command}: ok\n${JSON.stringify(result.envelope.data, null, 2)}\n`;
15273
- return `${result.envelope.command}: error ${result.envelope.error.code}\n${result.envelope.error.message}\n`;
15363
+ function renderHuman(result, options = {}) {
15364
+ const color = colorEnabled(options);
15365
+ if (result.envelope.ok) return `${paint("✔", "green", color)} ${result.envelope.command}\n${renderData(result.envelope.data, color)}`;
15366
+ const error = result.envelope.error;
15367
+ const hint = actionableHint(error.code, result.envelope.command);
15368
+ return [
15369
+ `${paint("✖", "red", color)} ${result.envelope.command}`,
15370
+ ` ${paint(error.code, "red", color)}: ${error.message}`,
15371
+ ...renderDetails(error.details, color),
15372
+ ...hint === void 0 ? [] : [` hint: ${hint}`],
15373
+ ""
15374
+ ].join("\n");
15375
+ }
15376
+ function renderProgress(message, options = {}) {
15377
+ return `${paint("•", "cyan", colorEnabled({
15378
+ ...options,
15379
+ stream: "stderr"
15380
+ }))} ${message}`;
15381
+ }
15382
+ function renderData(data, color) {
15383
+ if (typeof data !== "object" || data === null || Array.isArray(data)) return ` ${paint(formatValue(data), "dim", color)}\n`;
15384
+ const entries = Object.entries(data);
15385
+ if (entries.length === 0) return "";
15386
+ const width = Math.max(...entries.map(([key]) => key.length));
15387
+ return `${entries.map(([key, value]) => ` ${key.padEnd(width)}: ${formatValue(value)}`).join("\n")}\n`;
15388
+ }
15389
+ function renderDetails(details, color) {
15390
+ return Object.entries(details).map(([key, value]) => ` ${key}: ${paint(formatValue(value), "dim", color)}`);
15391
+ }
15392
+ function formatValue(value) {
15393
+ if (typeof value === "string") return value;
15394
+ if (value === null || typeof value === "number" || typeof value === "boolean") return String(value);
15395
+ return JSON.stringify(value);
15396
+ }
15397
+ function actionableHint(code, command) {
15398
+ if (code === "invalid_argument" || code === "unknown_command") return `holycodex ${command.split(" ")[0] ?? "help"} --help`;
15399
+ if (code === "non_tty_confirmation_required") return "rerun with --yes or use an interactive terminal";
15400
+ if (code === "capability_denied") return "run `holycodex doctor` to inspect capability availability";
15401
+ }
15402
+ function colorEnabled(options) {
15403
+ const env = options.env ?? {};
15404
+ if (env["NO_COLOR"] !== void 0 || env["TERM"] === "dumb") return false;
15405
+ if (env["FORCE_COLOR"] !== void 0 && env["FORCE_COLOR"] !== "0") return true;
15406
+ if (env["CI"] !== void 0 && env["CI"] !== "false") return false;
15407
+ return (options.stream === "stderr" ? options.stderrIsTTY : options.stdoutIsTTY) === true;
15408
+ }
15409
+ function paint(value, color, enabled) {
15410
+ if (!enabled) return value;
15411
+ return `\u001b[${{
15412
+ red: "31",
15413
+ green: "32",
15414
+ cyan: "36",
15415
+ dim: "2"
15416
+ }[color]}m${value}\u001b[0m`;
15274
15417
  }
15275
15418
  var CliCommandError = class extends Error {
15276
15419
  code;
@@ -15305,8 +15448,18 @@ async function runBinary(argv = Bun.argv.slice(2), binaryIo = processIo()) {
15305
15448
  if (helpRequested(argv) && !jsonRequested(argv)) context.io?.writeStdout?.(helpText(helpTopic(argv)));
15306
15449
  else if (argv[0] === "help" && !jsonRequested(argv)) context.io?.writeStdout?.(helpText(helpTopic(argv)));
15307
15450
  else if (jsonRequested(argv)) context.io?.writeStdout?.(`${JSON.stringify(result.envelope)}\n`);
15308
- else if (result.envelope.ok) context.io?.writeStdout?.(renderHuman(result));
15309
- else context.io?.writeStderr?.(renderHuman(result));
15451
+ else if (result.envelope.ok) context.io?.writeStdout?.(renderHuman(result, {
15452
+ stdoutIsTTY: context.io?.stdoutIsTTY,
15453
+ stderrIsTTY: context.io?.stderrIsTTY,
15454
+ env: context.env,
15455
+ stream: "stdout"
15456
+ }));
15457
+ else context.io?.writeStderr?.(renderHuman(result, {
15458
+ stdoutIsTTY: context.io?.stderrIsTTY,
15459
+ stderrIsTTY: context.io?.stderrIsTTY,
15460
+ env: context.env,
15461
+ stream: "stderr"
15462
+ }));
15310
15463
  return result.exitCode;
15311
15464
  }
15312
15465
  function processIo() {
@@ -15331,4 +15484,4 @@ async function* stdinChunks() {
15331
15484
  if (tail.length > 0) yield tail;
15332
15485
  }
15333
15486
  //#endregion
15334
- export { acquireInstallLock as $, installHolyCodex as A, WorkflowStoreError as B, GENERATED_WORKFLOW_SCHEMA_EPOCH as C, assertSafeWorkflowName as D, assertSafeSessionId as E, MIGRATION_RECORD_NAME as F, readCanonicalVersion as G, OfficialPluginManagerError as H, inspectLegacyState as I, managedEntryMatches as J, updateCanonicalVersion as K, migrateLegacyState as L, verifyActivation as M, LEGACY_SCHEMA_EPOCH as N, shortWorkflowHash as O, MIGRATED_STATE_NAME as P, LockError as Q, readMigratedInstallerSelections as R, GENERATED_WORKFLOW_NAMING_VERSION as S, GeneratedWorkflowStoreError as T, publicManifestPath as U, CodexOfficialPluginManager as V, readCanonicalBaseVersion as W, readMarketplace as X, managedMarketplaceEntry as Y, writeMarketplace as Z, doctorHolyCodex as _, helpRequested as a, ArgumentError as at, GENERATED_WORKFLOW_MAX_SESSION_ID_BYTES as b, WorkflowCommandError as c, CapabilityStateRecordSchema as ct, invokeWorkflowCapability as d, PathBoundaryError as et, loadNativeWorkflow as f, cleanupHolyCodex as g, CleanupError as h, runCli as i, resolveInstallerPaths as it, readActiveInstallRecord as j, InstallerError as k, createDefaultWorkflowService as l, InstallRecordSchema as lt, readWorkflowSource as m, executeCommand as n, assertRootText as nt, helpText as o, parseArgv as ot, optionalArgs as p, MarketplaceError as q, renderHuman as r, pathWithin as rt, helpTopic as s, CapabilityInstallStateSchema as st, runBinary as t, STATE_SCHEMA as tt, executeWorkflowCommand as u, GENERATED_WORKFLOW_DEFAULT_TTL_MS as v, GeneratedWorkflowStore as w, GENERATED_WORKFLOW_MAX_SOURCE_BYTES as x, GENERATED_WORKFLOW_MAX_NAME_BYTES as y, RefinementStoreError as z };
15487
+ export { writeMarketplace as $, InstallerError as A, RefinementStoreError as B, GENERATED_WORKFLOW_NAMING_VERSION as C, assertSafeSessionId as D, GeneratedWorkflowStoreError as E, MIGRATED_STATE_NAME as F, readCanonicalBaseVersion as G, CodexOfficialPluginManager as H, MIGRATION_RECORD_NAME as I, MarketplaceError as J, readCanonicalVersion as K, inspectLegacyState as L, readActiveInstallRecord as M, verifyActivation as N, assertSafeWorkflowName as O, LEGACY_SCHEMA_EPOCH as P, readMarketplaceForInstall as Q, migrateLegacyState as R, GENERATED_WORKFLOW_MAX_SOURCE_BYTES as S, GeneratedWorkflowStore as T, OfficialPluginManagerError as U, WorkflowStoreError as V, publicManifestPath as W, managedMarketplaceEntry as X, managedEntryMatches as Y, readMarketplace as Z, cleanupHolyCodex as _, runCli as a, pathWithin as at, GENERATED_WORKFLOW_MAX_NAME_BYTES as b, helpTopic as c, parseArgv as ct, executeWorkflowCommand as d, InstallRecordSchema as dt, LockError as et, invokeWorkflowCapability as f, CleanupError as g, readWorkflowSource as h, renderProgress as i, assertRootText as it, installHolyCodex as j, shortWorkflowHash as k, WorkflowCommandError as l, CapabilityInstallStateSchema as lt, optionalArgs as m, executeCommand as n, PathBoundaryError as nt, helpRequested as o, resolveInstallerPaths as ot, loadNativeWorkflow as p, updateCanonicalVersion as q, renderHuman as r, STATE_SCHEMA as rt, helpText as s, ArgumentError as st, runBinary as t, acquireInstallLock as tt, createDefaultWorkflowService as u, CapabilityStateRecordSchema as ut, doctorHolyCodex as v, GENERATED_WORKFLOW_SCHEMA_EPOCH as w, GENERATED_WORKFLOW_MAX_SESSION_ID_BYTES as x, GENERATED_WORKFLOW_DEFAULT_TTL_MS as y, readMigratedInstallerSelections as z };