@smartergpt/lexrunner 2.0.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/BRAND.md +14 -0
  2. package/CHANGELOG.md +49 -0
  3. package/GOVERNANCE.md +18 -0
  4. package/LICENSE.md +201 -110
  5. package/NOTICE.md +12 -1
  6. package/README.mcp.md +5 -1
  7. package/README.md +48 -35
  8. package/dist/{api-QBPBKYOC.js → api-UIWVFU7M.js} +1 -1
  9. package/dist/{audit-SKMMC2U4.js → audit-HVB2HJPU.js} +2 -2
  10. package/dist/{autopilot-3OHEUTHD.js → autopilot-7PX6YG55.js} +2 -2
  11. package/dist/{chunk-6PZDSWCG.js → chunk-37UC53OG.js} +2 -2
  12. package/dist/{chunk-ARDKZW7F.js → chunk-M6AAYMHH.js} +363 -293
  13. package/dist/{chunk-V3BU2VDU.js → chunk-PDDULIDL.js} +13 -1
  14. package/dist/cli.cjs +3672 -2774
  15. package/dist/cli.d.ts +201 -24
  16. package/dist/cli.js +1073 -275
  17. package/dist/{commandValidator-LVEMJTZP.js → commandValidator-XFVNCZXX.js} +1 -1
  18. package/dist/{constraints-2ZK5FJFA.js → constraints-LE2MW5NS.js} +1 -1
  19. package/dist/errors/index.js +1 -1
  20. package/dist/frames/index.js +1 -1
  21. package/dist/{gateMapping-R3RJYKMS.js → gateMapping-V4DTL5WD.js} +1 -1
  22. package/dist/hooks/events.js +1 -1
  23. package/dist/{jsonEnvelope-K2U5CWKU.js → jsonEnvelope-MXJM5ZQH.js} +1 -1
  24. package/dist/{mergeTreeSimulator-QCFSOU25.js → mergeTreeSimulator-GWZ77NF2.js} +1 -1
  25. package/dist/package-schemas/behavior-rule.js +1 -1
  26. package/dist/package-schemas/execution-plan-v1.js +1 -1
  27. package/dist/package-schemas/gates.js +1 -1
  28. package/dist/package-schemas/runner-scope.js +1 -1
  29. package/dist/package-schemas/runner-stack.js +1 -1
  30. package/dist/{planDiff-IHLFNZUT.js → planDiff-4D3AERAW.js} +1 -1
  31. package/dist/{planHistory-GLRI356L.js → planHistory-VPV4WDPW.js} +1 -1
  32. package/dist/{planReview-UUMCGZJ6.js → planReview-FV6INFLQ.js} +1 -1
  33. package/dist/{planViewer-TRSQVMH4.js → planViewer-WOV6A2HZ.js} +1 -1
  34. package/dist/{sarif-2C6RKOUX.js → sarif-QXVE3LYD.js} +1 -1
  35. package/dist/sdk/index.d.ts +5 -5
  36. package/dist/sdk/index.js +1 -1
  37. package/dist/{security-OE4VLUFK.js → security-W7TOUXSB.js} +1 -1
  38. package/dist/{signing-KLZYZZMP.js → signing-WGVPHJGG.js} +1 -1
  39. package/dist/{verify-3UVMA62I.js → verify-Y34CJAKB.js} +1 -1
  40. package/package.json +8 -6
  41. package/schemas/plan.schema.json +203 -73
package/dist/cli.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  finalizeAudit,
25
25
  initAuditEmitter,
26
26
  redactSecrets
27
- } from "./chunk-6PZDSWCG.js";
27
+ } from "./chunk-37UC53OG.js";
28
28
  import "./chunk-6KK5JFFE.js";
29
29
  import {
30
30
  simulateBatchMerges
@@ -32,6 +32,7 @@ import {
32
32
  import {
33
33
  AutopilotConfigError,
34
34
  FileAnalyzer,
35
+ FrozenGitInputs,
35
36
  GATE_EXECUTION_RECEIPT_SCHEMA_VERSION,
36
37
  GitHubAuthError,
37
38
  GitHubClientImpl,
@@ -75,6 +76,7 @@ import {
75
76
  readRunLog,
76
77
  readRunState,
77
78
  removeIndexEntry,
79
+ repositoryIdentity,
78
80
  resolveProfile,
79
81
  resolveSpawnExecutable,
80
82
  runEnvironmentQualityCheck,
@@ -83,7 +85,7 @@ import {
83
85
  validateWriteOperation,
84
86
  verifyToolchainPins,
85
87
  writeRunState
86
- } from "./chunk-ARDKZW7F.js";
88
+ } from "./chunk-M6AAYMHH.js";
87
89
  import {
88
90
  ExecutionState,
89
91
  generateMarkdownSummary,
@@ -135,9 +137,13 @@ import "./chunk-AXOAVRTU.js";
135
137
  import {
136
138
  __esm,
137
139
  __export,
140
+ __privateAdd,
141
+ __privateGet,
142
+ __privateMethod,
143
+ __privateSet,
138
144
  __require,
139
145
  __toCommonJS
140
- } from "./chunk-V3BU2VDU.js";
146
+ } from "./chunk-PDDULIDL.js";
141
147
 
142
148
  // src/metrics/export.ts
143
149
  var export_exports = {};
@@ -470,7 +476,7 @@ import "dotenv/config";
470
476
  // package.json
471
477
  var package_default = {
472
478
  name: "@smartergpt/lexrunner",
473
- version: "2.0.2",
479
+ version: "2.2.0",
474
480
  type: "module",
475
481
  engines: {
476
482
  node: ">=24"
@@ -480,13 +486,13 @@ var package_default = {
480
486
  description: "Fan-out tasks as multiple PRs in parallel, then build a merge pyramid from the blocks. Compute dependency order, run gates locally, and merge cleanly.",
481
487
  repository: {
482
488
  type: "git",
483
- url: "git+https://github.com/Guffawaffle/lexrunner.git"
489
+ url: "git+https://github.com/SmarterGPT/lexrunner.git"
484
490
  },
485
491
  publishConfig: {
486
- access: "restricted",
492
+ access: "public",
487
493
  registry: "https://registry.npmjs.org/"
488
494
  },
489
- license: "SEE LICENSE IN LICENSE.md",
495
+ license: "Apache-2.0",
490
496
  files: [
491
497
  "dist/",
492
498
  "schemas/",
@@ -495,7 +501,9 @@ var package_default = {
495
501
  "README.mcp.md",
496
502
  "CHANGELOG.md",
497
503
  "NOTICE.md",
498
- "LICENSE.md"
504
+ "LICENSE.md",
505
+ "GOVERNANCE.md",
506
+ "BRAND.md"
499
507
  ],
500
508
  bin: {
501
509
  lexrunner: "dist/cli.js",
@@ -571,7 +579,7 @@ var package_default = {
571
579
  "docs:surface:check": "node scripts/render-doc-surfaces.mjs --check",
572
580
  "dogfood:ecosystem": "tsx scripts/dogfood-ecosystem.ts",
573
581
  test: "vitest run",
574
- "test:git": "vitest run -c vitest.git.config.ts tests/release-prepare.spec.ts tests/promptsResolver.spec.ts tests/e2e-comprehensive.test.ts tests/autopilot-e2e-level3-4.spec.ts tests/deterministic-build.test.ts tests/e2e-merge-resume.spec.ts",
582
+ "test:git": "vitest run -c vitest.git.config.ts tests/release-prepare.spec.ts tests/promptsResolver.spec.ts tests/e2e-comprehensive.test.ts tests/autopilot-e2e-level3-4.spec.ts tests/deterministic-build.test.ts tests/e2e-merge-resume.spec.ts tests/e2e-frozen-git-inputs.spec.ts",
575
583
  "test:isolation": "node scripts/verify-parallel-isolation.mjs",
576
584
  "test:cli:slow": "vitest run -c vitest.slow-cli.config.ts",
577
585
  benchmark: "vitest bench -c vitest.benchmark.config.ts",
@@ -649,7 +657,7 @@ var package_default = {
649
657
  // src/cli.ts
650
658
  import { Command as Command6, CommanderError } from "commander";
651
659
  import { fileURLToPath as fileURLToPath6 } from "url";
652
- import { resolve as resolve14 } from "path";
660
+ import { resolve as resolve15 } from "path";
653
661
  import chalk11 from "chalk";
654
662
 
655
663
  // src/core/inputs.ts
@@ -1106,8 +1114,8 @@ function generateSnapshot(plan, inputs) {
1106
1114
  }
1107
1115
  function getPackageVersion() {
1108
1116
  try {
1109
- const fs50 = __require("fs");
1110
- const packageJson = JSON.parse(fs50.readFileSync("package.json", "utf8"));
1117
+ const fs51 = __require("fs");
1118
+ const packageJson = JSON.parse(fs51.readFileSync("package.json", "utf8"));
1111
1119
  return packageJson.version || "unknown";
1112
1120
  } catch {
1113
1121
  return "unknown";
@@ -2432,10 +2440,10 @@ async function promptGitHubToken() {
2432
2440
  input: process.stdin,
2433
2441
  output: process.stdout
2434
2442
  });
2435
- return new Promise((resolve15) => {
2443
+ return new Promise((resolve16) => {
2436
2444
  rl.question("GitHub token (optional, press Enter to skip): ", (answer) => {
2437
2445
  rl.close();
2438
- resolve15(answer.trim());
2446
+ resolve16(answer.trim());
2439
2447
  });
2440
2448
  });
2441
2449
  }
@@ -2638,13 +2646,41 @@ function installUnhandledRejectionHandler() {
2638
2646
  unhandledRejectionHandlerInstalled = true;
2639
2647
  }
2640
2648
 
2649
+ // src/core/standardGateCommands.ts
2650
+ function getStandardGateCommand(gateName) {
2651
+ const commands = {
2652
+ lint: "npm run lint",
2653
+ test: "npm test",
2654
+ unit: "npm test",
2655
+ typecheck: "npm run typecheck",
2656
+ build: "npm run build",
2657
+ format: "npm run format"
2658
+ };
2659
+ if (!Object.prototype.hasOwnProperty.call(commands, gateName)) {
2660
+ throw new Error(
2661
+ `No executable command is defined for gate ${JSON.stringify(gateName)}. Author an explicit gate run command in a manual plan, or select a supported standard gate.`
2662
+ );
2663
+ }
2664
+ return commands[gateName];
2665
+ }
2666
+
2641
2667
  // src/core/githubPlan.ts
2642
2668
  var STANDARD_TEST_GATE_TIMEOUT_MS = 5 * 60 * 1e3;
2643
2669
  async function generatePlanFromGitHub(client, options = {}) {
2644
2670
  const repoInfo = await client.validateRepository();
2645
2671
  const target = options.target || repoInfo.defaultBranch;
2672
+ const targetCommit = await client.getBranchHead(target);
2673
+ const gitInputs = {
2674
+ schemaVersion: "1.0.0",
2675
+ repository: `${repoInfo.url.replace(/\/$/, "").replace(/\.git$/, "")}.git`,
2676
+ checkoutRemote: "origin",
2677
+ acquisition: options.gitAcquisition ?? "fetch",
2678
+ target: { ref: `refs/heads/${target}`, commit: targetCommit },
2679
+ sources: []
2680
+ };
2646
2681
  const prs = await client.listOpenPRs({
2647
2682
  state: "open",
2683
+ base: target,
2648
2684
  labels: options.labels,
2649
2685
  // If no specific query, find PRs with stack labels or open PRs
2650
2686
  ...options.query ? { query: options.query } : {}
@@ -2655,8 +2691,9 @@ async function generatePlanFromGitHub(client, options = {}) {
2655
2691
  const finalPRs = excludePRs.length > 0 ? filteredPRs.filter((pr) => !excludePRs.includes(pr.number)) : filteredPRs;
2656
2692
  if (finalPRs.length === 0) {
2657
2693
  const emptyPlan = {
2658
- schemaVersion: "1.0.0",
2694
+ schemaVersion: "1.0.1",
2659
2695
  target,
2696
+ gitInputs,
2660
2697
  items: []
2661
2698
  };
2662
2699
  if (options.policy) {
@@ -2670,15 +2707,28 @@ async function generatePlanFromGitHub(client, options = {}) {
2670
2707
  mergeRule: { type: "strict-required" }
2671
2708
  };
2672
2709
  }
2673
- return emptyPlan;
2710
+ return Plan.parse(emptyPlan);
2674
2711
  }
2675
2712
  const prDetails = await Promise.all(finalPRs.map((pr) => client.getPRDetails(pr.number)));
2676
- const planItems = prDetails.map((pr) => transformPRToPlanItem(pr, options));
2713
+ if (prDetails.some((pr) => pr.base.ref !== target)) {
2714
+ throw new Error(
2715
+ "Selected PR targets a different branch; refresh discovery for the intended target"
2716
+ );
2717
+ }
2718
+ const planItems = prDetails.map(
2719
+ (pr) => transformPRToPlanItem(pr, options, `${repoInfo.owner}/${repoInfo.repo}`)
2720
+ );
2721
+ gitInputs.sources = prDetails.map((pr) => ({
2722
+ item: `PR-${pr.number}`,
2723
+ ref: `refs/pull/${pr.number}/head`,
2724
+ commit: pr.head.sha
2725
+ })).sort((a, b) => a.item.localeCompare(b.item));
2677
2726
  planItems.sort((a, b) => a.name.localeCompare(b.name));
2678
2727
  validateGitHubDependencies(planItems, prDetails);
2679
2728
  const plan = {
2680
- schemaVersion: "1.0.0",
2729
+ schemaVersion: "1.0.1",
2681
2730
  target,
2731
+ gitInputs,
2682
2732
  items: planItems
2683
2733
  };
2684
2734
  if (options.policy) {
@@ -2692,12 +2742,18 @@ async function generatePlanFromGitHub(client, options = {}) {
2692
2742
  mergeRule: { type: "strict-required" }
2693
2743
  };
2694
2744
  }
2695
- return plan;
2745
+ return Plan.parse(plan);
2696
2746
  }
2697
- function transformPRToPlanItem(pr, options) {
2747
+ function transformPRToPlanItem(pr, options, repository) {
2698
2748
  const name = `PR-${pr.number}`;
2699
2749
  const deps = pr.dependencies.filter((dep) => {
2700
- return dep.includes("#");
2750
+ const match = /^(?:([^#]+))?#([1-9][0-9]*)$/.exec(dep);
2751
+ if (!match || match[1] && match[1].toLowerCase() !== repository.toLowerCase()) {
2752
+ throw new Error(
2753
+ `Dependency ${JSON.stringify(dep)} is outside this single-repository plan; declare a valid repository-bound dependency`
2754
+ );
2755
+ }
2756
+ return true;
2701
2757
  }).map((dep) => {
2702
2758
  const prNumber = dep.includes("#") ? dep.split("#")[1] : dep;
2703
2759
  return `PR-${prNumber}`;
@@ -2732,47 +2788,7 @@ function createStandardGate(gateName, pr) {
2732
2788
  runtime: "local",
2733
2789
  artifacts: []
2734
2790
  };
2735
- switch (gateName) {
2736
- case "lint":
2737
- return {
2738
- ...baseGate,
2739
- run: "npm run lint",
2740
- artifacts: ["lint-results.txt"]
2741
- };
2742
- case "test":
2743
- case "unit":
2744
- return {
2745
- ...baseGate,
2746
- run: "npm test",
2747
- artifacts: ["test-results.xml", "coverage/"],
2748
- timeoutMs: STANDARD_TEST_GATE_TIMEOUT_MS
2749
- };
2750
- case "typecheck":
2751
- return {
2752
- ...baseGate,
2753
- run: "npm run typecheck",
2754
- artifacts: ["typecheck-results.txt"]
2755
- };
2756
- case "build":
2757
- return {
2758
- ...baseGate,
2759
- run: "npm run build",
2760
- artifacts: ["dist/", "build-log.txt"]
2761
- };
2762
- default:
2763
- return baseGate;
2764
- }
2765
- }
2766
- function getStandardGateCommand(gateName) {
2767
- const standardCommands = {
2768
- lint: "npm run lint",
2769
- test: "npm test",
2770
- unit: "npm test",
2771
- typecheck: "npm run typecheck",
2772
- build: "npm run build",
2773
- format: "npm run format"
2774
- };
2775
- return standardCommands[gateName] || `echo "Running ${gateName} gate"`;
2791
+ return gateName === "test" || gateName === "unit" ? { ...baseGate, timeoutMs: STANDARD_TEST_GATE_TIMEOUT_MS } : baseGate;
2776
2792
  }
2777
2793
  function validateGitHubDependencies(planItems, prDetails) {
2778
2794
  const itemNames = new Set(planItems.map((item) => item.name));
@@ -2922,7 +2938,7 @@ function generateGatesForMultiRepoPR(pr, options) {
2922
2938
  for (const gateName of requiredGates) {
2923
2939
  gates.push({
2924
2940
  name: gateName,
2925
- run: getGateCommand(gateName),
2941
+ run: getStandardGateCommand(gateName),
2926
2942
  env: {
2927
2943
  PR_NUMBER: pr.number.toString(),
2928
2944
  PR_BRANCH: pr.head.ref,
@@ -2931,33 +2947,13 @@ function generateGatesForMultiRepoPR(pr, options) {
2931
2947
  REPO_NAME: pr.repoName
2932
2948
  },
2933
2949
  runtime: "local",
2934
- artifacts: getGateArtifacts(gateName),
2950
+ artifacts: [],
2935
2951
  ...isStandardTestGate(gateName) ? { timeoutMs: STANDARD_TEST_GATE_TIMEOUT_MS2 } : {}
2936
2952
  });
2937
2953
  }
2938
2954
  gates.sort((a, b) => a.name.localeCompare(b.name));
2939
2955
  return gates;
2940
2956
  }
2941
- function getGateCommand(gateName) {
2942
- const commands = {
2943
- lint: "npm run lint",
2944
- test: "npm test",
2945
- unit: "npm test",
2946
- typecheck: "npm run typecheck",
2947
- build: "npm run build"
2948
- };
2949
- return commands[gateName] || `echo "Running ${gateName}"`;
2950
- }
2951
- function getGateArtifacts(gateName) {
2952
- const artifacts = {
2953
- lint: ["lint-results.txt"],
2954
- test: ["test-results.xml", "coverage/"],
2955
- unit: ["test-results.xml", "coverage/"],
2956
- typecheck: ["typecheck-results.txt"],
2957
- build: ["dist/"]
2958
- };
2959
- return artifacts[gateName] || [];
2960
- }
2961
2957
  function isStandardTestGate(gateName) {
2962
2958
  return gateName === "test" || gateName === "unit";
2963
2959
  }
@@ -3404,8 +3400,8 @@ function containedRegularFile(root, candidate) {
3404
3400
  }
3405
3401
  }
3406
3402
  function isContained(root, candidate) {
3407
- const relative3 = path8.relative(path8.resolve(root), path8.resolve(candidate));
3408
- return relative3 !== ".." && !relative3.startsWith(`..${path8.sep}`) && !path8.isAbsolute(relative3);
3403
+ const relative5 = path8.relative(path8.resolve(root), path8.resolve(candidate));
3404
+ return relative5 !== ".." && !relative5.startsWith(`..${path8.sep}`) && !path8.isAbsolute(relative5);
3409
3405
  }
3410
3406
  function evidenceError(code, message) {
3411
3407
  return new GateEvidenceServiceError(code, message);
@@ -3485,6 +3481,7 @@ var IntegrationStatusQueryService = class {
3485
3481
  schemaVersion: validated.schemaVersion,
3486
3482
  target: bounded(validated.target),
3487
3483
  itemCount: validated.items.length,
3484
+ gitInputBinding: validated.gitInputs ? "frozen" : "legacy-unbound",
3488
3485
  ...validated.policy ? { policy: validated.policy } : {}
3489
3486
  },
3490
3487
  mergeSummary: evaluator.getMergeSummary(),
@@ -4528,7 +4525,7 @@ function registerGateImportChecksCommand(program2) {
4528
4525
  version: "1.0.0",
4529
4526
  mappings: []
4530
4527
  };
4531
- const { DEFAULT_GATE_MAPPINGS } = await import("./gateMapping-R3RJYKMS.js");
4528
+ const { DEFAULT_GATE_MAPPINGS } = await import("./gateMapping-V4DTL5WD.js");
4532
4529
  mappingConfig.mappings = DEFAULT_GATE_MAPPINGS;
4533
4530
  }
4534
4531
  let githubClient;
@@ -4841,11 +4838,11 @@ function isTestFile(file) {
4841
4838
  }
4842
4839
  function directOwnerCandidates(file) {
4843
4840
  if (!file.startsWith("src/") || !/\.[cm]?tsx?$/.test(file)) return [];
4844
- const relative3 = file.replace(/^src\//, "").replace(/\.[cm]?tsx?$/, "");
4845
- const basename4 = path12.posix.basename(relative3);
4841
+ const relative5 = file.replace(/^src\//, "").replace(/\.[cm]?tsx?$/, "");
4842
+ const basename4 = path12.posix.basename(relative5);
4846
4843
  return [
4847
- `tests/${relative3}.spec.ts`,
4848
- `tests/${relative3}.test.ts`,
4844
+ `tests/${relative5}.spec.ts`,
4845
+ `tests/${relative5}.test.ts`,
4849
4846
  `tests/${basename4}.spec.ts`,
4850
4847
  `tests/${basename4}.test.ts`
4851
4848
  ];
@@ -6071,10 +6068,10 @@ async function readInput(inputPath) {
6071
6068
  }
6072
6069
  return fs17.readFileSync(inputPath, "utf-8");
6073
6070
  } else {
6074
- return new Promise((resolve15, reject) => {
6071
+ return new Promise((resolve16, reject) => {
6075
6072
  const chunks = [];
6076
6073
  process.stdin.on("data", (chunk) => chunks.push(chunk));
6077
- process.stdin.on("end", () => resolve15(Buffer.concat(chunks).toString("utf-8")));
6074
+ process.stdin.on("end", () => resolve16(Buffer.concat(chunks).toString("utf-8")));
6078
6075
  process.stdin.on("error", reject);
6079
6076
  });
6080
6077
  }
@@ -6711,20 +6708,20 @@ async function registerSecurityCommands(program2) {
6711
6708
  program2.command("security").description("Security operations: token rotation, secrets scanning, validation").addCommand(
6712
6709
  new Command3("check-rotation").description("Check if secrets need rotation based on age").argument("[secrets...]", "Secret IDs to check (without LEX_PR_ prefix)", ["GITHUB_TOKEN"]).option("--max-age <days>", "Maximum age in days before rotation needed", "90").option("--format <format>", "Output format: text or json", "text").option("--no-color", "Disable ANSI colors in text output").action(
6713
6710
  async (secretIds, opts) => {
6714
- const { checkRotation } = await import("./security-OE4VLUFK.js");
6711
+ const { checkRotation } = await import("./security-W7TOUXSB.js");
6715
6712
  const result = await checkRotation(secretIds, parseInt(opts.maxAge));
6716
6713
  outputSecurityResult("check-rotation", result, opts.format, opts.color !== false);
6717
6714
  }
6718
6715
  )
6719
6716
  ).addCommand(
6720
6717
  new Command3("scan-plan").description("Scan plan file for accidentally exposed secrets").argument("[plan-file]", "Path to plan file", "plan.json").option("--format <format>", "Output format: text or json", "text").option("--no-color", "Disable ANSI colors in text output").action(async (planFile, opts) => {
6721
- const { scanPlan } = await import("./security-OE4VLUFK.js");
6718
+ const { scanPlan } = await import("./security-W7TOUXSB.js");
6722
6719
  const result = await scanPlan(planFile);
6723
6720
  outputSecurityResult("scan-plan", result, opts.format, opts.color !== false);
6724
6721
  })
6725
6722
  ).addCommand(
6726
6723
  new Command3("validate-secrets").description("Validate that required secrets are present").argument("<secrets...>", "Required secret IDs (without LEX_PR_ prefix)").option("--format <format>", "Output format: text or json", "text").option("--no-color", "Disable ANSI colors in text output").action(async (secretIds, opts) => {
6727
- const { validateSecrets } = await import("./security-OE4VLUFK.js");
6724
+ const { validateSecrets } = await import("./security-W7TOUXSB.js");
6728
6725
  const result = await validateSecrets(secretIds);
6729
6726
  outputSecurityResult("validate-secrets", result, opts.format, opts.color !== false);
6730
6727
  })
@@ -6765,7 +6762,7 @@ function outputAuditResult(command, result, format, color) {
6765
6762
  async function registerAuditCommands(program2) {
6766
6763
  program2.command("audit").description("Audit operations: signature verification, manifest validation").addCommand(
6767
6764
  new Command4("verify").description("Verify audit manifest signature").argument("[manifest-file]", "Path to audit manifest file", "audit-manifest.json").option("--format <format>", "Output format: text or json", "text").option("--no-color", "Disable ANSI colors in text output").action(async (manifestFile, opts) => {
6768
- const { verifyCommand } = await import("./verify-3UVMA62I.js");
6765
+ const { verifyCommand } = await import("./verify-Y34CJAKB.js");
6769
6766
  const result = await verifyCommand(manifestFile);
6770
6767
  outputAuditResult("verify", result, opts.format, opts.color !== false);
6771
6768
  })
@@ -8387,8 +8384,8 @@ Details:`);
8387
8384
  if (opts.json || deps.jsonModeActive()) {
8388
8385
  const output = JSON.stringify(plan, null, 2);
8389
8386
  if (opts.output) {
8390
- const fs50 = await import("fs/promises");
8391
- await fs50.writeFile(opts.output, output, "utf-8");
8387
+ const fs51 = await import("fs/promises");
8388
+ await fs51.writeFile(opts.output, output, "utf-8");
8392
8389
  console.log(`Plan written to: ${opts.output}`);
8393
8390
  } else {
8394
8391
  console.log(output);
@@ -8411,8 +8408,8 @@ Details:`);
8411
8408
  console.log(` ${phase}: ${count}`);
8412
8409
  }
8413
8410
  if (opts.output) {
8414
- const fs50 = await import("fs/promises");
8415
- await fs50.writeFile(opts.output, JSON.stringify(plan, null, 2), "utf-8");
8411
+ const fs51 = await import("fs/promises");
8412
+ await fs51.writeFile(opts.output, JSON.stringify(plan, null, 2), "utf-8");
8416
8413
  console.log(`
8417
8414
  Plan written to: ${opts.output}`);
8418
8415
  }
@@ -8664,8 +8661,8 @@ function registerHarvestCommand(fanoutCommand) {
8664
8661
  });
8665
8662
  const output = JSON.stringify(harvestBundle, null, 2);
8666
8663
  if (opts.output) {
8667
- const fs50 = await import("fs/promises");
8668
- await fs50.writeFile(opts.output, output, "utf-8");
8664
+ const fs51 = await import("fs/promises");
8665
+ await fs51.writeFile(opts.output, output, "utf-8");
8669
8666
  console.error(`\u2713 Harvest bundle written to ${opts.output}`);
8670
8667
  console.error(` ${harvestBundle.bundle.pullRequests.length} PRs`);
8671
8668
  console.error(` ${harvestBundle.bundle.issues.length} issues`);
@@ -9054,10 +9051,10 @@ function analyzeBundle(harvest) {
9054
9051
  function registerAnalyzeCommand(fanoutCommand) {
9055
9052
  fanoutCommand.command("analyze").description("D1: Analyze harvest bundle into facts pool (deterministic)").option("--input <file>", "Path to harvest bundle JSON file (default: stdin)").option("--json", "Output JSON format (default)").option("--output <file>", "Write output to file").action(async (opts) => {
9056
9053
  try {
9057
- const fs50 = await import("fs/promises");
9054
+ const fs51 = await import("fs/promises");
9058
9055
  let content;
9059
9056
  if (opts.input) {
9060
- content = await fs50.readFile(opts.input, "utf-8");
9057
+ content = await fs51.readFile(opts.input, "utf-8");
9061
9058
  } else {
9062
9059
  const chunks = [];
9063
9060
  for await (const chunk of process.stdin) {
@@ -9099,7 +9096,7 @@ function registerAnalyzeCommand(fanoutCommand) {
9099
9096
  const analysisPool = analyzeBundle(harvest);
9100
9097
  const output = JSON.stringify(analysisPool, null, 2);
9101
9098
  if (opts.output) {
9102
- await fs50.writeFile(opts.output, output, "utf-8");
9099
+ await fs51.writeFile(opts.output, output, "utf-8");
9103
9100
  console.error(`\u2713 Analysis pool written to ${opts.output}`);
9104
9101
  console.error(` ${analysisPool.pool.entities.length} entities`);
9105
9102
  console.error(` ${analysisPool.pool.relations.length} relations`);
@@ -9196,9 +9193,9 @@ var DEFAULT_FANOUT_TEMPLATES_PATHS = [
9196
9193
  "fanout-templates.yml"
9197
9194
  ];
9198
9195
  var FanoutTemplatesLoadError = class extends Error {
9199
- constructor(message, path59, cause) {
9196
+ constructor(message, path60, cause) {
9200
9197
  super(message);
9201
- this.path = path59;
9198
+ this.path = path60;
9202
9199
  this.cause = cause;
9203
9200
  this.name = "FanoutTemplatesLoadError";
9204
9201
  }
@@ -9529,7 +9526,7 @@ function registerFanoutCommands(weaveCommand) {
9529
9526
  }
9530
9527
  });
9531
9528
  fanout.command("validate").description("Validate fanout templates file").option("-f, --file <path>", "Path to templates file").action(async (options) => {
9532
- const fs50 = await import("fs/promises");
9529
+ const fs51 = await import("fs/promises");
9533
9530
  try {
9534
9531
  let filePath;
9535
9532
  if (options.file) {
@@ -9542,7 +9539,7 @@ function registerFanoutCommands(weaveCommand) {
9542
9539
  }
9543
9540
  filePath = result2.path;
9544
9541
  }
9545
- const content = await fs50.readFile(filePath, "utf-8");
9542
+ const content = await fs51.readFile(filePath, "utf-8");
9546
9543
  const result = validateFanoutTemplatesContent(content);
9547
9544
  if (result.valid) {
9548
9545
  console.log(`\u2713 Valid: ${filePath}`);
@@ -10013,6 +10010,70 @@ import { join as join15 } from "path";
10013
10010
  import { simpleGit as simpleGit2 } from "simple-git";
10014
10011
  import { ulid } from "ulid";
10015
10012
 
10013
+ // src/git/frozen-inputs.ts
10014
+ var FrozenGitInputError = class extends Error {
10015
+ constructor(message) {
10016
+ super(message);
10017
+ this.name = "FrozenGitInputError";
10018
+ }
10019
+ };
10020
+ async function verifyFrozenGitInputs(git2, value) {
10021
+ const inputs = FrozenGitInputs.parse(value);
10022
+ let remote;
10023
+ try {
10024
+ remote = (await git2.raw(["remote", "get-url", inputs.checkoutRemote])).trim();
10025
+ if (repositoryIdentity(remote) !== repositoryIdentity(inputs.repository)) throw new Error();
10026
+ } catch {
10027
+ throw new FrozenGitInputError(
10028
+ "Checkout repository does not match gitInputs; use the declared checkout"
10029
+ );
10030
+ }
10031
+ const resolve16 = async (input) => {
10032
+ let ref = input.ref;
10033
+ if (inputs.acquisition === "fetch") {
10034
+ ref = `refs/lexrunner/inputs/${sha256(Buffer.from(`${inputs.repository}
10035
+ ${input.ref}
10036
+ ${input.commit}`))}`;
10037
+ try {
10038
+ await git2.raw([
10039
+ "fetch",
10040
+ "--no-tags",
10041
+ "--no-recurse-submodules",
10042
+ "--no-write-fetch-head",
10043
+ "--",
10044
+ inputs.repository,
10045
+ `+${input.ref}:${ref}`
10046
+ ]);
10047
+ } catch {
10048
+ throw new FrozenGitInputError(
10049
+ `Declared acquisition failed for ${input.ref}; restore access and retry without changing frozen expectations`
10050
+ );
10051
+ }
10052
+ }
10053
+ let observed;
10054
+ try {
10055
+ observed = (await git2.raw(["rev-parse", "--verify", ref])).trim();
10056
+ } catch {
10057
+ throw new FrozenGitInputError(
10058
+ `Declared ref ${input.ref} is unavailable; explicitly acquire it or create a new plan permitting fetch`
10059
+ );
10060
+ }
10061
+ if (observed !== input.commit) {
10062
+ throw new FrozenGitInputError(
10063
+ `Stale Git input ${input.ref}; reassess and generate a new plan instead of replacing its expected commit`
10064
+ );
10065
+ }
10066
+ if ((await git2.raw(["cat-file", "-t", input.commit])).trim() !== "commit") {
10067
+ throw new FrozenGitInputError(`Declared input ${input.ref} is not a commit object`);
10068
+ }
10069
+ return observed;
10070
+ };
10071
+ const targetHeadSha = await resolve16(inputs.target);
10072
+ const sourceHeads = /* @__PURE__ */ Object.create(null);
10073
+ for (const source of inputs.sources) sourceHeads[source.item] = await resolve16(source);
10074
+ return { targetHeadSha, sourceHeads };
10075
+ }
10076
+
10016
10077
  // src/weave/resume-service.ts
10017
10078
  import { z as z7 } from "zod";
10018
10079
  async function resumePersistedWeave(input) {
@@ -10161,6 +10222,15 @@ function validateResumeJournal(checkpoint) {
10161
10222
  };
10162
10223
  }
10163
10224
  const ids = /* @__PURE__ */ new Set();
10225
+ const inputs = parsedPlan.data.gitInputs;
10226
+ if (inputs && journal.repository.integrationBranch !== `weave/resume-${checkpoint.runId.toLowerCase()}`) {
10227
+ return { valid: false, reason: "checkpoint integration branch does not match its bound run" };
10228
+ }
10229
+ if (inputs && (inputs.target.commit !== journal.repository.targetHeadSha || inputs.sources.some(
10230
+ (source) => source.commit !== journal.repository.sourceHeads[source.item]
10231
+ ))) {
10232
+ return { valid: false, reason: "checkpoint commits do not match the plan's frozen Git inputs" };
10233
+ }
10164
10234
  let seenIncomplete = false;
10165
10235
  for (const operation of journal.operations) {
10166
10236
  if (!operation.id || ids.has(operation.id)) {
@@ -10326,11 +10396,22 @@ async function createLocalResumeCheckpoint(input) {
10326
10396
  const runId = input.runId ?? ulid();
10327
10397
  const at = input.now ?? (/* @__PURE__ */ new Date()).toISOString();
10328
10398
  const levels = computeMergeOrder(input.plan);
10329
- const sourceHeads = {};
10330
- for (const item of input.plan.items) {
10331
- sourceHeads[item.name] = await exactRefHead(git2, item.name);
10399
+ Plan.parse(input.plan);
10400
+ const sourceHeads = /* @__PURE__ */ Object.create(null);
10401
+ let targetHeadSha;
10402
+ if (input.plan.gitInputs) {
10403
+ const status = await git2.status();
10404
+ if (status.files.some(isUnexpectedBoundChange)) {
10405
+ throw new Error("Working tree must be clean before acquiring frozen Git inputs");
10406
+ }
10407
+ const verified = await verifyFrozenGitInputs(git2, input.plan.gitInputs);
10408
+ Object.assign(sourceHeads, verified.sourceHeads);
10409
+ targetHeadSha = verified.targetHeadSha;
10410
+ } else {
10411
+ for (const item of input.plan.items)
10412
+ sourceHeads[item.name] = await exactRefHead(git2, item.name);
10413
+ targetHeadSha = await exactRefHead(git2, input.plan.target);
10332
10414
  }
10333
- const targetHeadSha = await exactRefHead(git2, input.plan.target);
10334
10415
  const integrationBranch = `weave/resume-${runId.toLowerCase()}`;
10335
10416
  const operations = planResumeOperations(input.plan);
10336
10417
  const planHash = sha256(Buffer.from(canonicalJSONStringify(input.plan)));
@@ -10352,7 +10433,7 @@ async function createLocalResumeCheckpoint(input) {
10352
10433
  lastUpdatedAt: at,
10353
10434
  metadata: {
10354
10435
  target: input.plan.target,
10355
- warnings: [],
10436
+ warnings: input.plan.gitInputs ? [] : ["Legacy unbound plan: Git heads are selected at preparation, not frozen at synthesis"],
10356
10437
  resume: createResumeJournal({
10357
10438
  operations,
10358
10439
  target: input.plan.target,
@@ -10374,23 +10455,34 @@ var LocalWeaveResumeDriver = class {
10374
10455
  if (!journal) return { valid: false, reason: "resume journal is missing" };
10375
10456
  try {
10376
10457
  const status = await this.git.status();
10377
- const unexpectedChanges = status.files.filter((file) => !isRunnerStatePath(file.path));
10458
+ const unexpectedChanges = status.files.filter(
10459
+ checkpoint.plan.gitInputs ? isUnexpectedBoundChange : (file) => !isRunnerStatePath(file.path)
10460
+ );
10378
10461
  if (unexpectedChanges.length > 0) {
10379
10462
  return {
10380
10463
  valid: false,
10381
10464
  reason: "working tree is not clean; resolve or abort the interrupted operation first"
10382
10465
  };
10383
10466
  }
10384
- const targetHead = await exactRefHead(this.git, journal.repository.target);
10385
- if (targetHead !== journal.repository.targetHeadSha) {
10386
- return { valid: false, reason: "target branch changed after the checkpoint was created" };
10387
- }
10388
- for (const [name, expected] of Object.entries(journal.repository.sourceHeads)) {
10389
- if (await exactRefHead(this.git, name) !== expected) {
10390
- return {
10391
- valid: false,
10392
- reason: `source branch ${name} changed after checkpoint creation`
10393
- };
10467
+ if (checkpoint.plan.gitInputs) {
10468
+ const verified = await verifyFrozenGitInputs(this.git, checkpoint.plan.gitInputs);
10469
+ if (verified.targetHeadSha !== journal.repository.targetHeadSha || Object.entries(verified.sourceHeads).some(
10470
+ ([name, commit]) => journal.repository.sourceHeads[name] !== commit
10471
+ )) {
10472
+ return { valid: false, reason: "Journal commit evidence differs from frozen Git inputs" };
10473
+ }
10474
+ } else {
10475
+ const targetHead = await exactRefHead(this.git, journal.repository.target);
10476
+ if (targetHead !== journal.repository.targetHeadSha) {
10477
+ return { valid: false, reason: "target branch changed after the checkpoint was created" };
10478
+ }
10479
+ for (const [name, expected] of Object.entries(journal.repository.sourceHeads)) {
10480
+ if (await exactRefHead(this.git, name) !== expected) {
10481
+ return {
10482
+ valid: false,
10483
+ reason: `source branch ${name} changed after checkpoint creation`
10484
+ };
10485
+ }
10394
10486
  }
10395
10487
  }
10396
10488
  const integrationHead = await localBranchHead(this.git, journal.repository.integrationBranch);
@@ -10441,29 +10533,66 @@ var LocalWeaveResumeDriver = class {
10441
10533
  }
10442
10534
  async execute(operation, checkpoint) {
10443
10535
  const journal = checkpoint.metadata.resume;
10536
+ const bound4 = !!checkpoint.plan.gitInputs;
10537
+ const expectedIntegration = lastCompletedMergeSha(journal.operations) ?? journal.repository.targetHeadSha;
10538
+ if (bound4) {
10539
+ const stateError = await this.boundStateError();
10540
+ if (stateError) return { completed: false, reason: stateError };
10541
+ const integrationHead = await localBranchHead(this.git, journal.repository.integrationBranch);
10542
+ if (integrationHead && integrationHead !== expectedIntegration || !integrationHead && lastCompletedMergeSha(journal.operations)) {
10543
+ return {
10544
+ completed: false,
10545
+ reason: "Frozen integration branch changed before operation; preserve and inspect it"
10546
+ };
10547
+ }
10548
+ }
10444
10549
  await this.ensureIntegrationBranch(
10445
10550
  journal.repository.integrationBranch,
10446
10551
  journal.repository.targetHeadSha
10447
10552
  );
10448
10553
  if (operation.phase === "merge") {
10449
10554
  await this.git.checkout(journal.repository.integrationBranch);
10555
+ if (bound4) {
10556
+ const stateError = await this.boundStateError(expectedIntegration);
10557
+ if (stateError) return { completed: false, reason: stateError };
10558
+ }
10450
10559
  const item = checkpoint.plan.items.find((candidate) => candidate.name === operation.item);
10451
10560
  if (!item) return { completed: false, reason: "plan item is missing" };
10452
10561
  const result2 = await this.operations.executeMergeOperation({
10453
10562
  item,
10454
10563
  targetBranch: journal.repository.integrationBranch,
10455
- strategy: "merge-weave"
10564
+ strategy: "merge-weave",
10565
+ ...checkpoint.plan.gitInputs ? { sourceCommit: journal.repository.sourceHeads[operation.item] } : {}
10456
10566
  });
10567
+ if (bound4 && result2.success && result2.sha) {
10568
+ const stateError = await this.boundStateError(result2.sha);
10569
+ if (stateError) return { completed: false, reason: stateError };
10570
+ }
10457
10571
  return result2.success && result2.sha ? { completed: true, externalId: result2.sha } : { completed: false, reason: result2.message ?? "merge failed" };
10458
10572
  }
10459
10573
  const gate = gateForOperation(checkpoint.plan, operation);
10460
10574
  if (!gate) return { completed: false, reason: "gate definition is missing" };
10461
10575
  if (operation.phase === "gate") {
10462
- await this.git.checkout(`origin/${operation.item}`).catch(() => this.git.checkout(operation.item));
10576
+ if (checkpoint.plan.gitInputs) {
10577
+ await this.git.checkout(["--detach", journal.repository.sourceHeads[operation.item]]);
10578
+ } else {
10579
+ await this.git.checkout(`origin/${operation.item}`).catch(() => this.git.checkout(operation.item));
10580
+ }
10463
10581
  } else {
10464
10582
  await this.git.checkout(journal.repository.integrationBranch);
10465
10583
  }
10466
- const artifactDir = join15(this.workingDir, ".lexrunner", "runs", checkpoint.runId, "gates");
10584
+ const expectedGateHead = operation.phase === "gate" ? journal.repository.sourceHeads[operation.item] : expectedIntegration;
10585
+ if (bound4) {
10586
+ const stateError = await this.boundStateError(expectedGateHead);
10587
+ if (stateError) return { completed: false, reason: stateError };
10588
+ }
10589
+ const artifactDir = join15(
10590
+ this.workingDir,
10591
+ ".lexrunner",
10592
+ "runs",
10593
+ checkpoint.runId,
10594
+ operation.phase
10595
+ );
10467
10596
  await mkdir2(artifactDir, { recursive: true });
10468
10597
  const policy = Policy.parse(checkpoint.plan.policy ?? {});
10469
10598
  const result = await executeGate(
@@ -10475,12 +10604,38 @@ var LocalWeaveResumeDriver = class {
10475
10604
  false,
10476
10605
  this.workingDir
10477
10606
  );
10478
- return result.status === "pass" ? { completed: true, externalId: `${gate.name}:${result.lastAttempt ?? "pass"}` } : { completed: false, reason: result.stderr || `gate ${gate.name} failed` };
10607
+ if (bound4) {
10608
+ const stateError = await this.boundStateError(expectedGateHead);
10609
+ if (stateError) return { completed: false, reason: stateError };
10610
+ if (await localBranchHead(this.git, journal.repository.integrationBranch) !== expectedIntegration) {
10611
+ return {
10612
+ completed: false,
10613
+ reason: "Gate changed the frozen integration branch; preserve and inspect it"
10614
+ };
10615
+ }
10616
+ }
10617
+ const receipt = result.artifacts?.find(
10618
+ (path60) => /gate-execution-receipt\.attempt-\d+\.json$/.test(path60)
10619
+ );
10620
+ return result.status === "pass" ? {
10621
+ completed: true,
10622
+ externalId: receipt ?? `${gate.name}:${result.lastAttempt ?? "pass"}`
10623
+ } : { completed: false, reason: result.stderr || `gate ${gate.name} failed` };
10479
10624
  }
10480
10625
  async ensureIntegrationBranch(branch, targetHeadSha) {
10481
10626
  if (await localBranchHead(this.git, branch)) return;
10482
10627
  await this.git.checkoutBranch(branch, targetHeadSha);
10483
10628
  }
10629
+ async boundStateError(expectedHead) {
10630
+ if (expectedHead && (await this.git.revparse(["HEAD"])).trim() !== expectedHead) {
10631
+ return "Frozen checkout HEAD changed during the operation; preserve and inspect the new commit";
10632
+ }
10633
+ const status = await this.git.status();
10634
+ if (status.files.some(isUnexpectedBoundChange)) {
10635
+ return "Frozen checkout index or working tree changed; preserve and inspect the modifications before continuing";
10636
+ }
10637
+ return null;
10638
+ }
10484
10639
  };
10485
10640
  function gateForOperation(plan, operation) {
10486
10641
  const parts = operation.id.split(":");
@@ -10523,8 +10678,11 @@ function lastCompletedMergeSha(operations) {
10523
10678
  (operation) => operation.phase === "merge" && operation.status === "completed" && operation.result?.externalId
10524
10679
  )?.result?.externalId;
10525
10680
  }
10526
- function isRunnerStatePath(path59) {
10527
- return path59 === ".lexrunner" || path59.startsWith(".lexrunner/") || path59 === "weave-lock.json" || path59.endsWith("/weave-lock.json");
10681
+ function isRunnerStatePath(path60) {
10682
+ return path60 === ".lexrunner" || path60.startsWith(".lexrunner/") || path60 === "weave-lock.json" || path60.endsWith("/weave-lock.json");
10683
+ }
10684
+ function isUnexpectedBoundChange(file) {
10685
+ return !(file.index === "?" && file.working_dir === "?" && isRunnerStatePath(file.path));
10528
10686
  }
10529
10687
 
10530
10688
  // src/commands/weave.ts
@@ -10532,6 +10690,7 @@ import fs22 from "fs";
10532
10690
  import path15 from "path";
10533
10691
 
10534
10692
  // src/application/merge-application-service.ts
10693
+ import { join as join16 } from "path";
10535
10694
  var MAX_OPERATIONS = 256;
10536
10695
  var MAX_LABEL_BYTES2 = 512;
10537
10696
  var MAX_RESULT_BYTES2 = 256 * 1024;
@@ -10558,6 +10717,7 @@ var MergeApplicationService = class {
10558
10717
  ok: true,
10559
10718
  status: "preview",
10560
10719
  totalItems: input.plan.items.length,
10720
+ gitInputBinding: input.plan.gitInputs ? "frozen" : "legacy-unbound",
10561
10721
  levels,
10562
10722
  maxParallelism: levels.length === 0 ? 0 : Math.max(...levels.map((level) => level.length)),
10563
10723
  artifactRefs: []
@@ -10579,10 +10739,10 @@ var MergeApplicationService = class {
10579
10739
  let runId;
10580
10740
  try {
10581
10741
  runId = await this.runtime.prepare(input.plan, input.workingDir);
10582
- } catch {
10742
+ } catch (error) {
10583
10743
  throw new MergeApplicationServiceError(
10584
10744
  "MERGE_STALE_INPUT",
10585
- "Merge input could not be bound to current source and target heads"
10745
+ error instanceof FrozenGitInputError ? error.message : "Merge input could not be bound to current source and target heads"
10586
10746
  );
10587
10747
  }
10588
10748
  return this.executePrepared({ plan: input.plan, workingDir: input.workingDir, runId });
@@ -10612,6 +10772,7 @@ var MergeApplicationService = class {
10612
10772
  ok: completed,
10613
10773
  status: execution.result.ok ? execution.result.outcome : "failed",
10614
10774
  totalItems: input.plan.items.length,
10775
+ gitInputBinding: input.plan.gitInputs ? "frozen" : "legacy-unbound",
10615
10776
  runId: bound2(input.runId),
10616
10777
  operations: execution.operations.map((operation) => ({
10617
10778
  id: bound2(operation.id),
@@ -10632,15 +10793,22 @@ var LocalMergeApplicationRuntime = class {
10632
10793
  }
10633
10794
  async prepare(plan, workingDir) {
10634
10795
  const checkpoint = await createLocalResumeCheckpoint({ plan, workingDir });
10635
- await saveCheckpoint(checkpoint, { skipCleanup: true });
10796
+ await saveCheckpoint(checkpoint, {
10797
+ checkpointDir: join16(workingDir, ".lexrunner", "checkpoints"),
10798
+ skipCleanup: true
10799
+ });
10636
10800
  return checkpoint.runId;
10637
10801
  }
10638
10802
  async resume(runId, workingDir) {
10639
10803
  const result = await resumePersistedWeave({
10640
10804
  runId,
10805
+ checkpointDir: join16(workingDir, ".lexrunner", "checkpoints"),
10641
10806
  driver: new LocalWeaveResumeDriver(workingDir)
10642
10807
  });
10643
- const checkpoint = await loadCheckpoint(runId, { validatePlanHash: false });
10808
+ const checkpoint = await loadCheckpoint(runId, {
10809
+ checkpointDir: join16(workingDir, ".lexrunner", "checkpoints"),
10810
+ validatePlanHash: false
10811
+ });
10644
10812
  return { result, operations: checkpoint.metadata?.resume?.operations ?? [] };
10645
10813
  }
10646
10814
  };
@@ -10936,7 +11104,7 @@ async function runWeaveApply(opts, deps) {
10936
11104
  if (json2) {
10937
11105
  const output = { ...preview.summary };
10938
11106
  if (showConstraints) {
10939
- const { previewConstraints: previewConstraints2 } = await import("./constraints-2ZK5FJFA.js");
11107
+ const { previewConstraints: previewConstraints2 } = await import("./constraints-LE2MW5NS.js");
10940
11108
  output.constraints = await previewConstraints2(plan);
10941
11109
  }
10942
11110
  console.log(canonicalJSONStringify(output));
@@ -10946,13 +11114,17 @@ async function runWeaveApply(opts, deps) {
10946
11114
  \u{1F50D} Merge-Weave Dry Run
10947
11115
  `);
10948
11116
  if (showConstraints) {
10949
- const { previewConstraints: previewConstraints2, formatConstraintPreview: formatConstraintPreview2 } = await import("./constraints-2ZK5FJFA.js");
11117
+ const { previewConstraints: previewConstraints2, formatConstraintPreview: formatConstraintPreview2 } = await import("./constraints-LE2MW5NS.js");
10950
11118
  console.log(formatConstraintPreview2(await previewConstraints2(plan)));
10951
11119
  }
10952
11120
  console.log(`Plan: ${opts.plan}`);
10953
11121
  console.log(`Items: ${plan.items.length}`);
10954
11122
  console.log(`Target: ${plan.target}
10955
11123
  `);
11124
+ console.log(
11125
+ `Git inputs: ${preview.summary.gitInputBinding}${plan.gitInputs ? `; acquisition: ${plan.gitInputs.acquisition}` : ""}
11126
+ `
11127
+ );
10956
11128
  console.log("\u{1F4E6} Execution Plan\n");
10957
11129
  console.log("Execution Order (topological):\n");
10958
11130
  levels.forEach((level, index) => {
@@ -10976,7 +11148,7 @@ async function runWeaveApply(opts, deps) {
10976
11148
  console.log(`Items: ${plan.items.length}
10977
11149
  `);
10978
11150
  }
10979
- if (!opts.skipGates) {
11151
+ if (!opts.skipGates && !(opts.execute && plan.gitInputs)) {
10980
11152
  if (!json2) console.log("Running gates...\n");
10981
11153
  const executionState = new ExecutionState(plan);
10982
11154
  const gatesDir = path15.join(process.cwd(), ".smartergpt", "runner", "gates");
@@ -11142,7 +11314,7 @@ function registerPlanDiffCommand(program2, deps) {
11142
11314
  const plan2Content = fs24.readFileSync(plan2Path, "utf-8");
11143
11315
  const plan1 = loadPlan(plan1Content);
11144
11316
  const plan2 = loadPlan(plan2Content);
11145
- const { comparePlans, formatPlanDiff } = await import("./planDiff-IHLFNZUT.js");
11317
+ const { comparePlans, formatPlanDiff } = await import("./planDiff-4D3AERAW.js");
11146
11318
  const diff = comparePlans(plan1, plan2);
11147
11319
  if (opts.json || deps.jsonModeActive()) {
11148
11320
  writeJsonOutput(diff);
@@ -11626,12 +11798,12 @@ ${prefix} Plan validation failed: ${error.message}`);
11626
11798
  }
11627
11799
  fs25.mkdirSync(outDir, { recursive: true });
11628
11800
  const planPath = path16.join(outDir, "plan.json");
11629
- const snapshotPath = path16.join(outDir, "snapshot.md");
11801
+ const snapshotPath2 = path16.join(outDir, "snapshot.md");
11630
11802
  fs25.writeFileSync(planPath, planJSON);
11631
- fs25.writeFileSync(snapshotPath, snapshot);
11803
+ fs25.writeFileSync(snapshotPath2, snapshot);
11632
11804
  console.log(`\u2713 Generated plan artifacts:`);
11633
11805
  console.log(` \u{1F4C1} ${planPath}`);
11634
- console.log(` \u{1F4C1} ${snapshotPath}`);
11806
+ console.log(` \u{1F4C1} ${snapshotPath2}`);
11635
11807
  console.log("");
11636
11808
  console.log(generatePlanSummary(validatedPlan));
11637
11809
  return;
@@ -11772,7 +11944,7 @@ function registerAutopilotCommand(program2, deps) {
11772
11944
  argv: process.argv.slice(2)
11773
11945
  });
11774
11946
  }
11775
- const { AutopilotLevel0, AutopilotLevel1, AutopilotLevel2: AutopilotLevel22 } = await import("./autopilot-3OHEUTHD.js");
11947
+ const { AutopilotLevel0, AutopilotLevel1, AutopilotLevel2: AutopilotLevel22 } = await import("./autopilot-7PX6YG55.js");
11776
11948
  const context = {
11777
11949
  plan,
11778
11950
  profilePath: profile.path,
@@ -11820,7 +11992,7 @@ function registerAutopilotCommand(program2, deps) {
11820
11992
  // src/application/gate-execution-service.ts
11821
11993
  import { randomUUID as randomUUID4 } from "crypto";
11822
11994
  import { mkdirSync as mkdirSync12 } from "fs";
11823
- import { join as join18, resolve as resolve9 } from "path";
11995
+ import { join as join19, resolve as resolve9 } from "path";
11824
11996
  var MAX_ITEMS = 256;
11825
11997
  var MAX_GATES_PER_ITEM = 64;
11826
11998
  var MAX_LABEL_BYTES3 = 512;
@@ -11923,7 +12095,7 @@ var GateExecutionService = class {
11923
12095
  function prepareOwnedArtifactDirectory(requestedRoot) {
11924
12096
  const root = resolve9(bounded2(requestedRoot, MAX_ARTIFACT_REF_BYTES));
11925
12097
  mkdirSync12(root, { recursive: true });
11926
- const runDirectory = join18(root, `gate-run-${Date.now()}-${randomUUID4()}`);
12098
+ const runDirectory = join19(root, `gate-run-${Date.now()}-${randomUUID4()}`);
11927
12099
  mkdirSync12(runDirectory);
11928
12100
  return runDirectory;
11929
12101
  }
@@ -12797,7 +12969,7 @@ import * as fs28 from "fs";
12797
12969
  import * as path18 from "path";
12798
12970
  async function finalizeAuditGuard(emitter, status) {
12799
12971
  try {
12800
- const { finalizeAudit: finalizeAudit2 } = await import("./audit-SKMMC2U4.js");
12972
+ const { finalizeAudit: finalizeAudit2 } = await import("./audit-HVB2HJPU.js");
12801
12973
  await finalizeAudit2(emitter, status);
12802
12974
  } catch (e) {
12803
12975
  if (e instanceof Error && typeof e.message === "string" && e.message.startsWith("HIPAA:")) {
@@ -13363,8 +13535,8 @@ function registerPlanReviewCommand(program2, deps) {
13363
13535
  }
13364
13536
  const planContent = fs29.readFileSync(planFile, "utf-8");
13365
13537
  const plan = loadPlan(planContent);
13366
- const { reviewPlan } = await import("./planReview-UUMCGZJ6.js");
13367
- const { savePlanVersion, getPlanHistoryPath } = await import("./planHistory-GLRI356L.js");
13538
+ const { reviewPlan } = await import("./planReview-FV6INFLQ.js");
13539
+ const { savePlanVersion, getPlanHistoryPath } = await import("./planHistory-VPV4WDPW.js");
13368
13540
  const result = await reviewPlan({
13369
13541
  plan,
13370
13542
  interactive: !opts.nonInteractive,
@@ -14064,7 +14236,7 @@ async function predictConflicts(options) {
14064
14236
  const pr2Head = prHeads.get(edge.to);
14065
14237
  if (pr1Head && pr2Head) {
14066
14238
  const key = `${edge.from}-${edge.to}`;
14067
- const result = await import("./mergeTreeSimulator-QCFSOU25.js").then(
14239
+ const result = await import("./mergeTreeSimulator-GWZ77NF2.js").then(
14068
14240
  (m) => m.simulateMerge(baseBranch, pr1Head, pr2Head, workingDir)
14069
14241
  );
14070
14242
  mergeTreeSimulation[key] = result;
@@ -14140,7 +14312,7 @@ function generateRecommendations(misBatches, mergeTreeSimulation) {
14140
14312
 
14141
14313
  // src/orchestration/agentAssigner.ts
14142
14314
  function sleep(ms) {
14143
- return new Promise((resolve15) => setTimeout(resolve15, ms));
14315
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
14144
14316
  }
14145
14317
  async function assignAgentWithRetry(issueNumber, repo, assignFn, maxRetries = 4) {
14146
14318
  let retries = 0;
@@ -14759,8 +14931,8 @@ function registerGenerateDeliverablesCommand(program2) {
14759
14931
  console.log(`\u2705 Created: ${path23.join(outputDir, "GATE5_cleanup.md")}`);
14760
14932
  console.log(`\u2705 Created: ${path23.join(outputDir, "SUMMARY.md")}`);
14761
14933
  console.log("");
14762
- const fs50 = await import("fs");
14763
- const planHashContent = fs50.readFileSync(path23.join(outputDir, "plan-hash.txt"), "utf-8");
14934
+ const fs51 = await import("fs");
14935
+ const planHashContent = fs51.readFileSync(path23.join(outputDir, "plan-hash.txt"), "utf-8");
14764
14936
  const planHashMatch = planHashContent.match(/SHA256: ([a-f0-9]+)/);
14765
14937
  if (planHashMatch) {
14766
14938
  console.log(`Plan hash: ${planHashMatch[1]}`);
@@ -15551,7 +15723,7 @@ function formatMonitor(monitor) {
15551
15723
  async function runCheck(opts) {
15552
15724
  let githubAPI = await createGitHubAPI();
15553
15725
  if (opts.owner && opts.repo) {
15554
- const { GitHubAPI: GitHubAPI2 } = await import("./api-QBPBKYOC.js");
15726
+ const { GitHubAPI: GitHubAPI2 } = await import("./api-UIWVFU7M.js");
15555
15727
  githubAPI = new GitHubAPI2({
15556
15728
  owner: opts.owner,
15557
15729
  repo: opts.repo,
@@ -16762,9 +16934,9 @@ async function promptInteractive(defaults) {
16762
16934
  output: process.stdout
16763
16935
  });
16764
16936
  const question = (prompt) => {
16765
- return new Promise((resolve15) => {
16937
+ return new Promise((resolve16) => {
16766
16938
  rl.question(prompt, (answer) => {
16767
- resolve15(answer.trim());
16939
+ resolve16(answer.trim());
16768
16940
  });
16769
16941
  });
16770
16942
  };
@@ -18621,8 +18793,8 @@ Total: ${entries.length} counter-examples (${entries.filter((e) => e.shouldLearn
18621
18793
  counterExamples.command("export").description("Export counter-examples for analysis").option("--format <format>", "Export format (json|csv)", "json").option("--base-dir <dir>", "Base directory for lexrunner", process.cwd()).option("--output <file>", "Output file (prints to stdout if not specified)").action(async (options) => {
18622
18794
  const output = exportCounterExamples(options.format, options.baseDir);
18623
18795
  if (options.output) {
18624
- const fs50 = await import("fs");
18625
- fs50.writeFileSync(options.output, output, "utf-8");
18796
+ const fs51 = await import("fs");
18797
+ fs51.writeFileSync(options.output, output, "utf-8");
18626
18798
  console.log(chalk9.green(`\u2713 Exported counter-examples to ${options.output}`));
18627
18799
  } else {
18628
18800
  console.log(output);
@@ -19202,7 +19374,7 @@ function nativePathsOverlap(runtimePlatform, left, right, comparison) {
19202
19374
  if (api.parse(normalizedLeft).root !== api.parse(normalizedRight).root) return false;
19203
19375
  const relativeLeft = api.relative(normalizedLeft, normalizedRight);
19204
19376
  const relativeRight = api.relative(normalizedRight, normalizedLeft);
19205
- const isDescendant = (relative3) => relative3.length > 0 && relative3 !== ".." && !relative3.startsWith(`..${api.sep}`);
19377
+ const isDescendant = (relative5) => relative5.length > 0 && relative5 !== ".." && !relative5.startsWith(`..${api.sep}`);
19206
19378
  return isDescendant(relativeLeft) || isDescendant(relativeRight);
19207
19379
  }
19208
19380
  function digestBinding(runtime) {
@@ -20547,8 +20719,8 @@ function parseGitStatusPorcelainV1Z(input) {
20547
20719
  }
20548
20720
  const indexStatus = field[0];
20549
20721
  const worktreeStatus = field[1];
20550
- const path59 = field.slice(3);
20551
- if (path59.length === 0) {
20722
+ const path60 = field.slice(3);
20723
+ if (path60.length === 0) {
20552
20724
  throw new Error("Malformed git status porcelain: path is empty");
20553
20725
  }
20554
20726
  const renameOrCopy = [indexStatus, worktreeStatus].find(
@@ -20566,7 +20738,7 @@ function parseGitStatusPorcelainV1Z(input) {
20566
20738
  records.push({
20567
20739
  indexStatus,
20568
20740
  worktreeStatus,
20569
- path: path59,
20741
+ path: path60,
20570
20742
  ...originalPath === void 0 ? {} : { originalPath },
20571
20743
  kind
20572
20744
  });
@@ -21018,8 +21190,8 @@ function copyIssues(result, context) {
21018
21190
  context.addIssue({ code: "custom", path: issue.path, message: issue.message });
21019
21191
  }
21020
21192
  }
21021
- function addIssue(context, path59, message) {
21022
- context.addIssue({ code: "custom", path: path59, message });
21193
+ function addIssue(context, path60, message) {
21194
+ context.addIssue({ code: "custom", path: path60, message });
21023
21195
  }
21024
21196
 
21025
21197
  // src/workspaces/linux-workspace-boundary.ts
@@ -22060,8 +22232,8 @@ var NodeGitWorktreeBroker = class {
22060
22232
  "The worktree root was replaced after broker initialization"
22061
22233
  );
22062
22234
  }
22063
- const relative3 = path34.relative(this.worktreeRoot, path34.resolve(target.worktreePath));
22064
- const components = relative3.split(path34.sep);
22235
+ const relative5 = path34.relative(this.worktreeRoot, path34.resolve(target.worktreePath));
22236
+ const components = relative5.split(path34.sep);
22065
22237
  const targetName = components.pop();
22066
22238
  if (!targetName) {
22067
22239
  throw new DirectoryBoundaryError("invalid_path", "The worktree target has no basename");
@@ -22265,8 +22437,8 @@ var NodeGitWorktreeBroker = class {
22265
22437
  );
22266
22438
  }
22267
22439
  const normalized = path34.resolve(gitDirectoryPath);
22268
- const relative3 = path34.relative(this.repositoryGitIdentity.path, normalized);
22269
- if (!relative3 || relative3 === ".." || relative3.startsWith(`..${path34.sep}`)) {
22440
+ const relative5 = path34.relative(this.repositoryGitIdentity.path, normalized);
22441
+ if (!relative5 || relative5 === ".." || relative5.startsWith(`..${path34.sep}`)) {
22270
22442
  return this.failure(
22271
22443
  operation,
22272
22444
  "containment_violation",
@@ -22275,7 +22447,7 @@ var NodeGitWorktreeBroker = class {
22275
22447
  }
22276
22448
  let current = null;
22277
22449
  try {
22278
- for (const component of relative3.split(path34.sep)) {
22450
+ for (const component of relative5.split(path34.sep)) {
22279
22451
  const child = await boundary.lease.openChild(
22280
22452
  current ?? boundary.repositoryGit,
22281
22453
  component,
@@ -22329,8 +22501,8 @@ var NodeGitWorktreeBroker = class {
22329
22501
  const normalizedRoot = path34.resolve(root);
22330
22502
  const comparedCandidate = this.pathComparison === "case-insensitive" ? normalizedCandidate.toLocaleLowerCase("en-US") : normalizedCandidate;
22331
22503
  const comparedRoot = this.pathComparison === "case-insensitive" ? normalizedRoot.toLocaleLowerCase("en-US") : normalizedRoot;
22332
- const relative3 = path34.relative(comparedRoot, comparedCandidate);
22333
- return relative3.length > 0 && relative3 !== ".." && !relative3.startsWith(`..${path34.sep}`);
22504
+ const relative5 = path34.relative(comparedRoot, comparedCandidate);
22505
+ return relative5.length > 0 && relative5 !== ".." && !relative5.startsWith(`..${path34.sep}`);
22334
22506
  }
22335
22507
  async git(boundary, operation, args, cwd, options, allowedNonzeroExitCodes = [], evidence) {
22336
22508
  const result = await boundary.lease.runProcess({
@@ -22435,7 +22607,7 @@ function nativePathsOverlap2(left, right, comparison) {
22435
22607
  if (normalizedLeft === normalizedRight) return true;
22436
22608
  const relativeLeft = path34.relative(normalizedLeft, normalizedRight);
22437
22609
  const relativeRight = path34.relative(normalizedRight, normalizedLeft);
22438
- const isDescendant = (relative3) => relative3.length > 0 && relative3 !== ".." && !relative3.startsWith(`..${path34.sep}`);
22610
+ const isDescendant = (relative5) => relative5.length > 0 && relative5 !== ".." && !relative5.startsWith(`..${path34.sep}`);
22439
22611
  return isDescendant(relativeLeft) || isDescendant(relativeRight);
22440
22612
  }
22441
22613
  function branchName(ref) {
@@ -23478,7 +23650,7 @@ var NativeWslProjectionEngine = class {
23478
23650
  "native publication target became occupied"
23479
23651
  );
23480
23652
  }
23481
- const repositoryIdentity = identityOf(staging.repository);
23653
+ const repositoryIdentity2 = identityOf(staging.repository);
23482
23654
  const allocationIdentity = identityOf(staging.allocation);
23483
23655
  staging.repository.close();
23484
23656
  staging.repository = void 0;
@@ -23491,7 +23663,7 @@ var NativeWslProjectionEngine = class {
23491
23663
  staging.repositoryPublished = true;
23492
23664
  assertPublishedIdentity(
23493
23665
  path35.join(boundary.projectionRoot.path, projectionId),
23494
- repositoryIdentity,
23666
+ repositoryIdentity2,
23495
23667
  "native projection"
23496
23668
  );
23497
23669
  await rename(
@@ -24377,11 +24549,11 @@ function loadNativeWslProjectionSelection(repositoryRoot, expectedSelectionDiges
24377
24549
  if (!/^sha256:[a-f0-9]{64}$/u.test(expectedSelectionDigest)) {
24378
24550
  throw new Error("Projection selection authority is invalid");
24379
24551
  }
24380
- const repositoryIdentity = captureDirectoryIdentity(
24552
+ const repositoryIdentity2 = captureDirectoryIdentity(
24381
24553
  repositoryRoot,
24382
24554
  "native projection repository"
24383
24555
  );
24384
- const repository = reopenDirectoryIdentity(repositoryIdentity, "native projection repository");
24556
+ const repository = reopenDirectoryIdentity(repositoryIdentity2, "native projection repository");
24385
24557
  let gitDirectory;
24386
24558
  try {
24387
24559
  gitDirectory = openChildDirectory(repository, ".git", "native projection Git directory");
@@ -24975,24 +25147,24 @@ var AcceptanceCriterion = z19.object({
24975
25147
  function isMachineLocalAbsolutePath(value) {
24976
25148
  return /(?:^|\s)\/(?!\/)[^\s]*/.test(value) || /(?:^|\s)~\/[^\s]*/.test(value) || /(?:^|\s)\\\\[^\s]*/.test(value) || /(?:^|\s)[a-z]:[\\/][^\s]*/i.test(value) || /(?:^|\s)file:/i.test(value);
24977
25149
  }
24978
- function rejectMachineLocalPaths(value, ctx, path59 = []) {
25150
+ function rejectMachineLocalPaths(value, ctx, path60 = []) {
24979
25151
  if (typeof value === "string") {
24980
25152
  if (isMachineLocalAbsolutePath(value)) {
24981
25153
  ctx.addIssue({
24982
25154
  code: "custom",
24983
- path: path59,
25155
+ path: path60,
24984
25156
  message: "AgentTaskPacket_v1 must not contain machine-local absolute paths"
24985
25157
  });
24986
25158
  }
24987
25159
  return;
24988
25160
  }
24989
25161
  if (Array.isArray(value)) {
24990
- value.forEach((item, index) => rejectMachineLocalPaths(item, ctx, [...path59, index]));
25162
+ value.forEach((item, index) => rejectMachineLocalPaths(item, ctx, [...path60, index]));
24991
25163
  return;
24992
25164
  }
24993
25165
  if (value !== null && typeof value === "object") {
24994
25166
  for (const [key, item] of Object.entries(value)) {
24995
- rejectMachineLocalPaths(item, ctx, [...path59, key]);
25167
+ rejectMachineLocalPaths(item, ctx, [...path60, key]);
24996
25168
  }
24997
25169
  }
24998
25170
  }
@@ -27166,10 +27338,10 @@ function captureBoundIdentities(input) {
27166
27338
  worktree: captureDirectoryIdentity(input.worktreePath, "execution mapping worktree")
27167
27339
  };
27168
27340
  }
27169
- function verifiedRoot(runtimeId, path59, identity) {
27341
+ function verifiedRoot(runtimeId, path60, identity) {
27170
27342
  return {
27171
27343
  runtime_id: runtimeId,
27172
- path: path59,
27344
+ path: path60,
27173
27345
  verification: "directory_identity",
27174
27346
  directory_identity: identityClaim2(identity)
27175
27347
  };
@@ -27288,8 +27460,8 @@ async function requireDirectoryWithin(directory, root, field) {
27288
27460
  realpath(directory),
27289
27461
  realpath(root)
27290
27462
  ]);
27291
- const relative3 = path36.relative(resolvedRoot, resolvedDirectory);
27292
- if (relative3 === ".." || relative3.startsWith(`..${path36.sep}`) || path36.isAbsolute(relative3)) {
27463
+ const relative5 = path36.relative(resolvedRoot, resolvedDirectory);
27464
+ if (relative5 === ".." || relative5.startsWith(`..${path36.sep}`) || path36.isAbsolute(relative5)) {
27293
27465
  throw new Error(`${field} must resolve within its authorized root`);
27294
27466
  }
27295
27467
  }
@@ -32481,8 +32653,8 @@ async function requireDirectoryWithin2(directory, root, field) {
32481
32653
  realpath2(directory),
32482
32654
  realpath2(root)
32483
32655
  ]);
32484
- const relative3 = path37.relative(resolvedRoot, resolvedDirectory);
32485
- if (relative3 === ".." || relative3.startsWith(`..${path37.sep}`) || path37.isAbsolute(relative3)) {
32656
+ const relative5 = path37.relative(resolvedRoot, resolvedDirectory);
32657
+ if (relative5 === ".." || relative5.startsWith(`..${path37.sep}`) || path37.isAbsolute(relative5)) {
32486
32658
  throw new Error(`${field} must resolve within the authorized worktree`);
32487
32659
  }
32488
32660
  }
@@ -35259,10 +35431,10 @@ var WorkerSessionDelegationBinding_v1 = z29.object({
35259
35431
  function decisionReceiptMatchesOffer(receipt, offer, offerHash) {
35260
35432
  return receipt.delegation_id === offer.delegation_id && receipt.attempt_id === offer.attempt_id && receipt.offer_hash === offerHash && receipt.worker_thread_id === offer.worker.thread_id && receipt.transcript_start_hash === offer.transcript_start_hash && Date.parse(receipt.decided_at) >= Date.parse(offer.offered_at);
35261
35433
  }
35262
- function requireTimeOrder(earlier, later, path59, context, equalAllowed = true) {
35434
+ function requireTimeOrder(earlier, later, path60, context, equalAllowed = true) {
35263
35435
  const ordered = equalAllowed ? Date.parse(earlier) <= Date.parse(later) : Date.parse(earlier) < Date.parse(later);
35264
35436
  if (!ordered) {
35265
- context.addIssue({ code: "custom", path: [path59], message: `${path59} is out of order` });
35437
+ context.addIssue({ code: "custom", path: [path60], message: `${path60} is out of order` });
35266
35438
  }
35267
35439
  }
35268
35440
 
@@ -36372,12 +36544,12 @@ function grantWithinRequirements(grant, requirements) {
36372
36544
  );
36373
36545
  return grant.authorized_model_provider === requirements.authorized_model_provider && grant.source_disclosure_allowed === requirements.source_disclosure_allowed && grant.max_duration_ms <= requirements.max_duration_ms && grant.max_output_bytes <= requirements.max_output_bytes && grant.controls.every((control) => required2.get(control.control) === control.minimum_strength) && grant.tools.length <= 1;
36374
36546
  }
36375
- function requireExactControls(controls, context, path59) {
36547
+ function requireExactControls(controls, context, path60) {
36376
36548
  const actual = new Set(controls.map((control) => control.control));
36377
36549
  if (actual.size !== GovernedControlId.options.length || GovernedControlId.options.some((control) => !actual.has(control))) {
36378
36550
  context.addIssue({
36379
36551
  code: "custom",
36380
- path: path59,
36552
+ path: path60,
36381
36553
  message: "every governed denial control must appear exactly once"
36382
36554
  });
36383
36555
  }
@@ -37327,10 +37499,10 @@ function requireAbsent(value, fields, context) {
37327
37499
  function addStateIssue(message, context) {
37328
37500
  context.addIssue({ code: "custom", path: ["status"], message });
37329
37501
  }
37330
- function requireOrdered(earlier, later, path59, context, equalAllowed = true) {
37502
+ function requireOrdered(earlier, later, path60, context, equalAllowed = true) {
37331
37503
  const ordered = equalAllowed ? Date.parse(earlier) <= Date.parse(later) : Date.parse(earlier) < Date.parse(later);
37332
37504
  if (!ordered) {
37333
- context.addIssue({ code: "custom", path: [path59], message: `${path59} is out of order` });
37505
+ context.addIssue({ code: "custom", path: [path60], message: `${path60} is out of order` });
37334
37506
  }
37335
37507
  }
37336
37508
 
@@ -39050,8 +39222,8 @@ function normalizeInstant4(value) {
39050
39222
  return new Date(timestamp).toISOString();
39051
39223
  }
39052
39224
  function assertDescendant(parent, candidate) {
39053
- const relative3 = path46.relative(path46.resolve(parent), path46.resolve(candidate));
39054
- if (relative3.startsWith("..") || path46.isAbsolute(relative3)) {
39225
+ const relative5 = path46.relative(path46.resolve(parent), path46.resolve(candidate));
39226
+ if (relative5.startsWith("..") || path46.isAbsolute(relative5)) {
39055
39227
  throw new LocalProtectedEvidenceVerificationError("container_invalid");
39056
39228
  }
39057
39229
  }
@@ -39206,14 +39378,14 @@ var WindowsProtectedEvidenceAuthority = class {
39206
39378
  this.child = null;
39207
39379
  child?.stdin.end();
39208
39380
  if (child && child.exitCode === null) {
39209
- await new Promise((resolve15) => {
39381
+ await new Promise((resolve16) => {
39210
39382
  const timeout = setTimeout(() => {
39211
39383
  child.kill();
39212
- resolve15();
39384
+ resolve16();
39213
39385
  }, 5e3);
39214
39386
  child.once("close", () => {
39215
39387
  clearTimeout(timeout);
39216
- resolve15();
39388
+ resolve16();
39217
39389
  });
39218
39390
  });
39219
39391
  }
@@ -39224,8 +39396,8 @@ var WindowsProtectedEvidenceAuthority = class {
39224
39396
  const child = this.ensureChild();
39225
39397
  const id = this.nextId;
39226
39398
  this.nextId += 1;
39227
- return new Promise((resolve15, reject) => {
39228
- this.pending.set(id, { resolve: resolve15, reject });
39399
+ return new Promise((resolve16, reject) => {
39400
+ this.pending.set(id, { resolve: resolve16, reject });
39229
39401
  child.stdin.write(`${JSON.stringify({ id, op: operation, path: target })}
39230
39402
  `, (error) => {
39231
39403
  if (!error) return;
@@ -39877,7 +40049,7 @@ var repositoryCorpusHeaderBody = z41.object({
39877
40049
  var GovernedRepositoryCorpusHeader_v1 = repositoryCorpusHeaderBody.superRefine(
39878
40050
  (value, context) => {
39879
40051
  const paths = value.entries.map((entry) => entry.path);
39880
- if (new Set(paths).size !== paths.length || paths.some((path59, index) => index > 0 && path59 <= paths[index - 1])) {
40052
+ if (new Set(paths).size !== paths.length || paths.some((path60, index) => index > 0 && path60 <= paths[index - 1])) {
39881
40053
  context.addIssue({
39882
40054
  code: "custom",
39883
40055
  path: ["entries"],
@@ -40304,7 +40476,7 @@ function sanitizedWslEnvironment() {
40304
40476
  return environment;
40305
40477
  }
40306
40478
  function waitForExit(child, timeoutMs) {
40307
- return new Promise((resolve15, reject) => {
40479
+ return new Promise((resolve16, reject) => {
40308
40480
  const timeout = setTimeout(() => {
40309
40481
  child.kill();
40310
40482
  reject(new Error("WSL2 provider control request timed out"));
@@ -40315,7 +40487,7 @@ function waitForExit(child, timeoutMs) {
40315
40487
  });
40316
40488
  child.once("close", (code) => {
40317
40489
  clearTimeout(timeout);
40318
- resolve15(code);
40490
+ resolve16(code);
40319
40491
  });
40320
40492
  });
40321
40493
  }
@@ -41430,8 +41602,8 @@ var LocalProtectedEvidenceStore = class {
41430
41602
  exclusive(operation) {
41431
41603
  const previous = this.queue;
41432
41604
  let release;
41433
- this.queue = new Promise((resolve15) => {
41434
- release = resolve15;
41605
+ this.queue = new Promise((resolve16) => {
41606
+ release = resolve16;
41435
41607
  });
41436
41608
  return previous.then(operation).finally(release);
41437
41609
  }
@@ -41594,8 +41766,8 @@ function sameToken(expected, candidate) {
41594
41766
  return left.length === right.length && timingSafeEqual(left, right);
41595
41767
  }
41596
41768
  function assertDescendant2(root, candidate) {
41597
- const relative3 = path50.relative(root, candidate);
41598
- if (!relative3 || relative3.startsWith("..") || path50.isAbsolute(relative3)) {
41769
+ const relative5 = path50.relative(root, candidate);
41770
+ if (!relative5 || relative5.startsWith("..") || path50.isAbsolute(relative5)) {
41599
41771
  throw new Error("protected evidence deletion target escaped its root");
41600
41772
  }
41601
41773
  }
@@ -42443,11 +42615,11 @@ async function launchDetachedSupervisor(input) {
42443
42615
  env: sanitizedSupervisorEnvironment()
42444
42616
  }
42445
42617
  );
42446
- return await new Promise((resolve15) => {
42447
- child.once("error", () => resolve15(false));
42618
+ return await new Promise((resolve16) => {
42619
+ child.once("error", () => resolve16(false));
42448
42620
  child.once("spawn", () => {
42449
42621
  child.unref();
42450
- resolve15(true);
42622
+ resolve16(true);
42451
42623
  });
42452
42624
  });
42453
42625
  } catch {
@@ -43193,10 +43365,10 @@ function commandPath(command) {
43193
43365
  }
43194
43366
  return components.join(" ");
43195
43367
  }
43196
- function aliasWarning(path59) {
43197
- const policy = POLICY_BY_PATH.get(path59);
43368
+ function aliasWarning(path60) {
43369
+ const policy = POLICY_BY_PATH.get(path60);
43198
43370
  if (!policy) return null;
43199
- return policy.disposition === "deprecated" ? `[lexrunner] deprecated alias "${path59}"; use "${policy.replacement}"; removal: ${policy.removeIn}.` : `[lexrunner] compatibility alias "${path59}"; use "${policy.replacement}"; supported through 2.x and reviewed at 3.0.0.`;
43371
+ return policy.disposition === "deprecated" ? `[lexrunner] deprecated alias "${path60}"; use "${policy.replacement}"; removal: ${policy.removeIn}.` : `[lexrunner] compatibility alias "${path60}"; use "${policy.replacement}"; supported through 2.x and reviewed at 3.0.0.`;
43200
43372
  }
43201
43373
  function emitAliasWarning(command, write = (message) => process.stderr.write(message)) {
43202
43374
  const warning = aliasWarning(commandPath(command));
@@ -43302,8 +43474,8 @@ async function searchAttributions(query, runId) {
43302
43474
  }
43303
43475
 
43304
43476
  // src/cli.ts
43305
- import * as fs49 from "fs";
43306
- import * as path58 from "path";
43477
+ import * as fs50 from "fs";
43478
+ import * as path59 from "path";
43307
43479
 
43308
43480
  // src/runs/enforcement.ts
43309
43481
  import { z as z45 } from "zod";
@@ -44411,7 +44583,7 @@ function createRunManager(baseDirOrOptions) {
44411
44583
 
44412
44584
  // src/runs/coordinated-manager.ts
44413
44585
  import { existsSync as existsSync24, readFileSync as readFileSync32, renameSync as renameSync3, writeFileSync as writeFileSync19 } from "fs";
44414
- import { join as join32 } from "path";
44586
+ import { join as join33 } from "path";
44415
44587
 
44416
44588
  // src/runs/agent-work-supervisor.ts
44417
44589
  import { z as z48 } from "zod";
@@ -44725,8 +44897,8 @@ async function executeAgentWorkPreparation(input) {
44725
44897
  function passed(results, id) {
44726
44898
  return results.some((result) => result.id === id && result.outcome === "passed");
44727
44899
  }
44728
- async function containedExistingDirectory(root, relative3) {
44729
- const candidate = relative3 ? path55.resolve(root, relative3) : root;
44900
+ async function containedExistingDirectory(root, relative5) {
44901
+ const candidate = relative5 ? path55.resolve(root, relative5) : root;
44730
44902
  const resolved = await realpath6(candidate);
44731
44903
  const relation = path55.relative(root, resolved);
44732
44904
  if (relation === ".." || relation.startsWith(`..${path55.sep}`) || path55.isAbsolute(relation)) {
@@ -44809,7 +44981,7 @@ var workspaceFilesystemEntry = z49.discriminatedUnion("kind", [
44809
44981
  }).strict()
44810
44982
  ]);
44811
44983
  function requireStrictlyOrderedPaths(values, context, field) {
44812
- if (values.some(({ path: path59 }, index) => index > 0 && path59 <= values[index - 1].path)) {
44984
+ if (values.some(({ path: path60 }, index) => index > 0 && path60 <= values[index - 1].path)) {
44813
44985
  context.addIssue({
44814
44986
  code: "custom",
44815
44987
  path: [field],
@@ -44829,7 +45001,7 @@ var completeGitIdentity = z49.object({
44829
45001
  kind: z49.enum(["absent", "present"]),
44830
45002
  paths: z49.array(boundedRelativePath).max(4096)
44831
45003
  }).strict().superRefine((identity, context) => {
44832
- if (identity.paths.some((path59, index) => index > 0 && path59 <= identity.paths[index - 1]) || identity.kind === "absent" && identity.paths.length !== 0 || identity.kind === "present" && identity.paths.length === 0) {
45004
+ if (identity.paths.some((path60, index) => index > 0 && path60 <= identity.paths[index - 1]) || identity.kind === "absent" && identity.paths.length !== 0 || identity.kind === "present" && identity.paths.length === 0) {
44833
45005
  context.addIssue({
44834
45006
  code: "custom",
44835
45007
  path: ["paths"],
@@ -45139,7 +45311,7 @@ var GovernedWorkspaceMutationRecoveryReceipt_v1 = z49.object({
45139
45311
  });
45140
45312
  }
45141
45313
  if (receipt.changed_paths.some(
45142
- (path59, index) => index > 0 && path59 <= receipt.changed_paths[index - 1]
45314
+ (path60, index) => index > 0 && path60 <= receipt.changed_paths[index - 1]
45143
45315
  )) {
45144
45316
  context.addIssue({
45145
45317
  code: "custom",
@@ -45974,15 +46146,15 @@ var AttemptAwaitableSupervisor = class {
45974
46146
  0,
45975
46147
  Date.parse(record.observer_lease.expires_at) - Date.parse(this.now()) + 1
45976
46148
  );
45977
- let resolve15;
46149
+ let resolve16;
45978
46150
  const completion = new Promise((resolvePromise) => {
45979
- resolve15 = resolvePromise;
46151
+ resolve16 = resolvePromise;
45980
46152
  });
45981
46153
  const timer = setTimeout(() => {
45982
46154
  this.leaseExpiryWakeups.delete(record.awaitable_id);
45983
- void this.attach(record.awaitable_id).finally(resolve15);
46155
+ void this.attach(record.awaitable_id).finally(resolve16);
45984
46156
  }, delayMs);
45985
- this.leaseExpiryWakeups.set(record.awaitable_id, { timer, completion, resolve: resolve15 });
46157
+ this.leaseExpiryWakeups.set(record.awaitable_id, { timer, completion, resolve: resolve16 });
45986
46158
  }
45987
46159
  clearLeaseExpiryWakeup(awaitableId) {
45988
46160
  const wakeup = this.leaseExpiryWakeups.get(awaitableId);
@@ -46087,14 +46259,14 @@ function normalizeRetryDelay(value, name) {
46087
46259
  }
46088
46260
  function waitForRetry(delayMs, signal) {
46089
46261
  if (signal.aborted) return Promise.resolve(false);
46090
- return new Promise((resolve15) => {
46262
+ return new Promise((resolve16) => {
46091
46263
  const timer = setTimeout(() => {
46092
46264
  signal.removeEventListener("abort", onAbort);
46093
- resolve15(true);
46265
+ resolve16(true);
46094
46266
  }, delayMs);
46095
46267
  const onAbort = () => {
46096
46268
  clearTimeout(timer);
46097
- resolve15(false);
46269
+ resolve16(false);
46098
46270
  };
46099
46271
  signal.addEventListener("abort", onAbort, { once: true });
46100
46272
  });
@@ -49611,8 +49783,135 @@ function normalizeInstant8(value) {
49611
49783
  // src/application/plan-artifact-service.ts
49612
49784
  import * as fs48 from "fs";
49613
49785
  import * as path57 from "path";
49614
- var MAX_PLAN_REFERENCE_BYTES = 4096;
49615
- var MAX_PLAN_BYTES = 4 * 1024 * 1024;
49786
+ import { isDeepStrictEqual } from "util";
49787
+
49788
+ // src/application/execution-plan-artifact.ts
49789
+ import { createHash as createHash13 } from "crypto";
49790
+ import { z as z54 } from "zod";
49791
+ var EXECUTION_PLAN_ARTIFACT_CONTRACT = "lexrunner.execution-plan-artifact.v1";
49792
+ var PLAN_ARTIFACT_REFERENCE_CONTRACT = "lexrunner.plan-artifact-reference.v1";
49793
+ var EXECUTION_PLAN_CANONICALIZATION_PROFILE = "lexrunner.execution-plan.canonical-json.v1";
49794
+ var EXECUTION_PLAN_HASH_PROFILE = "lexrunner.execution-plan-artifact.sha256.v1";
49795
+ var EXECUTION_PLAN_HASH_DOMAIN = "lexrunner:execution-plan-artifact:v1\0";
49796
+ var MAX_PLAN_ARTIFACT_BYTES = 4 * 1024 * 1024;
49797
+ var MAX_PLAN_RETRIEVAL_REFERENCE_BYTES = 4096;
49798
+ var MAX_SCOPE_LABEL_BYTES = 512;
49799
+ var Sha256Digest = z54.string().regex(/^sha256:[a-f0-9]{64}$/);
49800
+ var BoundedScopeLabel = z54.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_SCOPE_LABEL_BYTES, {
49801
+ message: "Scope label exceeds the transport limit"
49802
+ });
49803
+ var BoundedIdentityLabel = z54.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_SCOPE_LABEL_BYTES, {
49804
+ message: "Identity label exceeds the transport limit"
49805
+ });
49806
+ var PlanArtifactScope_v1Schema = z54.object({
49807
+ tenant: BoundedScopeLabel,
49808
+ workspace: BoundedScopeLabel,
49809
+ repository: BoundedScopeLabel,
49810
+ refNamespace: BoundedScopeLabel,
49811
+ policy: BoundedScopeLabel
49812
+ }).strict();
49813
+ var ExecutionPlanArtifactIdentity_v1Schema = z54.object({
49814
+ contract: z54.literal(EXECUTION_PLAN_ARTIFACT_CONTRACT),
49815
+ kind: z54.literal("execution-plan"),
49816
+ planSchema: z54.literal("lexrunner.execution-plan"),
49817
+ planSchemaVersion: BoundedIdentityLabel,
49818
+ canonicalizationProfile: z54.literal(EXECUTION_PLAN_CANONICALIZATION_PROFILE),
49819
+ hashProfile: z54.literal(EXECUTION_PLAN_HASH_PROFILE),
49820
+ digestAlgorithm: z54.literal("sha256"),
49821
+ digest: Sha256Digest,
49822
+ canonicalByteLength: z54.number().int().nonnegative().max(MAX_PLAN_ARTIFACT_BYTES),
49823
+ target: BoundedIdentityLabel,
49824
+ summary: z54.object({
49825
+ itemCount: z54.number().int().nonnegative().max(256),
49826
+ gateCount: z54.number().int().nonnegative().max(256 * 64)
49827
+ }).strict()
49828
+ }).strict();
49829
+ var ExecutionPlanArtifact_v1Schema = z54.object({
49830
+ identity: ExecutionPlanArtifactIdentity_v1Schema,
49831
+ canonicalBytes: z54.string()
49832
+ }).strict().superRefine((artifact, context) => {
49833
+ const byteLength = Buffer.byteLength(artifact.canonicalBytes, "utf8");
49834
+ if (byteLength > MAX_PLAN_ARTIFACT_BYTES) {
49835
+ context.addIssue({
49836
+ code: "custom",
49837
+ path: ["canonicalBytes"],
49838
+ message: "Canonical plan bytes exceed the artifact limit"
49839
+ });
49840
+ }
49841
+ if (byteLength !== artifact.identity.canonicalByteLength) {
49842
+ context.addIssue({
49843
+ code: "custom",
49844
+ path: ["identity", "canonicalByteLength"],
49845
+ message: "Canonical plan byte length does not match the artifact identity"
49846
+ });
49847
+ }
49848
+ if (computeExecutionPlanArtifactDigest(artifact.canonicalBytes) !== artifact.identity.digest) {
49849
+ context.addIssue({
49850
+ code: "custom",
49851
+ path: ["identity", "digest"],
49852
+ message: "Canonical plan digest does not match the artifact identity"
49853
+ });
49854
+ }
49855
+ try {
49856
+ const plan = loadPlan(artifact.canonicalBytes);
49857
+ if (canonicalJSONStringify(plan) !== artifact.canonicalBytes) {
49858
+ context.addIssue({
49859
+ code: "custom",
49860
+ path: ["canonicalBytes"],
49861
+ message: "Plan bytes are not in the declared canonical form"
49862
+ });
49863
+ }
49864
+ const gateCount = plan.items.reduce((count, item) => count + item.gates.length, 0);
49865
+ if (artifact.identity.planSchemaVersion !== plan.schemaVersion || artifact.identity.target !== plan.target || artifact.identity.summary.itemCount !== plan.items.length || artifact.identity.summary.gateCount !== gateCount) {
49866
+ context.addIssue({
49867
+ code: "custom",
49868
+ path: ["identity"],
49869
+ message: "Plan semantics do not match the artifact identity"
49870
+ });
49871
+ }
49872
+ } catch {
49873
+ context.addIssue({
49874
+ code: "custom",
49875
+ path: ["canonicalBytes"],
49876
+ message: "Canonical bytes do not contain a valid execution plan"
49877
+ });
49878
+ }
49879
+ });
49880
+ var PlanArtifactReference_v1Schema = z54.object({
49881
+ contract: z54.literal(PLAN_ARTIFACT_REFERENCE_CONTRACT),
49882
+ artifact: ExecutionPlanArtifactIdentity_v1Schema,
49883
+ expectedDigest: Sha256Digest,
49884
+ expectedCanonicalByteLength: z54.number().int().nonnegative().max(MAX_PLAN_ARTIFACT_BYTES),
49885
+ retrieval: z54.object({
49886
+ kind: z54.enum(["file", "registered"]),
49887
+ reference: z54.string().min(1).refine(
49888
+ (value) => !value.includes("\0") && Buffer.byteLength(value, "utf8") <= MAX_PLAN_RETRIEVAL_REFERENCE_BYTES,
49889
+ { message: "Retrieval reference is invalid or exceeds the transport limit" }
49890
+ )
49891
+ }).strict(),
49892
+ scope: PlanArtifactScope_v1Schema.optional()
49893
+ }).strict().superRefine((reference, context) => {
49894
+ if (reference.expectedDigest !== reference.artifact.digest) {
49895
+ context.addIssue({
49896
+ code: "custom",
49897
+ path: ["expectedDigest"],
49898
+ message: "Expected digest does not match the embedded artifact identity"
49899
+ });
49900
+ }
49901
+ if (reference.expectedCanonicalByteLength !== reference.artifact.canonicalByteLength) {
49902
+ context.addIssue({
49903
+ code: "custom",
49904
+ path: ["expectedCanonicalByteLength"],
49905
+ message: "Expected byte length does not match the embedded artifact identity"
49906
+ });
49907
+ }
49908
+ });
49909
+ function computeExecutionPlanArtifactDigest(canonicalBytes2) {
49910
+ const digest = createHash13("sha256").update(EXECUTION_PLAN_HASH_DOMAIN, "utf8").update(canonicalBytes2, "utf8").digest("hex");
49911
+ return `sha256:${digest}`;
49912
+ }
49913
+
49914
+ // src/application/plan-artifact-service.ts
49616
49915
  var MAX_PLAN_ITEMS = 256;
49617
49916
  var MAX_GATES_PER_ITEM2 = 64;
49618
49917
  var MAX_IDENTITY_LABEL_BYTES = 512;
@@ -49624,16 +49923,41 @@ var PlanArtifactServiceError = class extends Error {
49624
49923
  this.name = "PlanArtifactServiceError";
49625
49924
  }
49626
49925
  };
49926
+ var _hooks;
49627
49927
  var PlanArtifactService = class {
49928
+ constructor(options = {}) {
49929
+ __privateAdd(this, _hooks);
49930
+ __privateSet(this, _hooks, options.importHooks ?? {});
49931
+ }
49628
49932
  resolve(input = {}) {
49629
49933
  const workingDir = path57.resolve(input.workingDir ?? process.cwd());
49934
+ const scope = parseScope(input.scope);
49935
+ if (input.planReference !== void 0 && input.planFile !== void 0) {
49936
+ throw new PlanArtifactServiceError(
49937
+ "PLAN_REFERENCE_INVALID",
49938
+ "Provide either an immutable plan reference or an explicit plan path, not both",
49939
+ "explicit"
49940
+ );
49941
+ }
49942
+ if (input.planReference !== void 0 && input.scope !== void 0) {
49943
+ throw new PlanArtifactServiceError(
49944
+ "PLAN_REFERENCE_INVALID",
49945
+ "A separately supplied scope cannot override an immutable plan reference",
49946
+ "explicit"
49947
+ );
49948
+ }
49949
+ if (input.planReference !== void 0) {
49950
+ const reference = parseReference(input.planReference);
49951
+ const explicitPath = resolveExplicitReference(reference.retrieval.reference, workingDir);
49952
+ return readArtifact(explicitPath, "explicit", __privateGet(this, _hooks), reference);
49953
+ }
49630
49954
  if (input.planFile !== void 0) {
49631
49955
  const explicitPath = resolveExplicitReference(input.planFile, workingDir);
49632
- return readArtifact(explicitPath, "explicit");
49956
+ return readArtifact(explicitPath, "explicit", __privateGet(this, _hooks), void 0, scope);
49633
49957
  }
49634
49958
  const repositoryPlan = path57.join(workingDir, "plan.json");
49635
- if (isRegularFile(repositoryPlan)) {
49636
- return readArtifact(repositoryPlan, "repository-root");
49959
+ if (pathEntryExists(repositoryPlan)) {
49960
+ return readArtifact(repositoryPlan, "repository-root", __privateGet(this, _hooks), void 0, scope);
49637
49961
  }
49638
49962
  let profilePlan;
49639
49963
  try {
@@ -49641,8 +49965,8 @@ var PlanArtifactService = class {
49641
49965
  profilePlan = path57.join(profile.path, "runner", "plan.json");
49642
49966
  } catch {
49643
49967
  }
49644
- if (profilePlan && isRegularFile(profilePlan)) {
49645
- return readArtifact(profilePlan, "profile-runner");
49968
+ if (profilePlan && pathEntryExists(profilePlan)) {
49969
+ return readArtifact(profilePlan, "profile-runner", __privateGet(this, _hooks), void 0, scope);
49646
49970
  }
49647
49971
  throw new PlanArtifactServiceError(
49648
49972
  "PLAN_NOT_FOUND",
@@ -49650,46 +49974,85 @@ var PlanArtifactService = class {
49650
49974
  );
49651
49975
  }
49652
49976
  };
49653
- function resolveExplicitReference(reference, workingDir) {
49654
- if (reference.length === 0 || reference.includes("\0") || Buffer.byteLength(reference, "utf8") > MAX_PLAN_REFERENCE_BYTES) {
49977
+ _hooks = new WeakMap();
49978
+ function parseReference(reference) {
49979
+ const parsed = PlanArtifactReference_v1Schema.safeParse(reference);
49980
+ if (!parsed.success) {
49655
49981
  throw new PlanArtifactServiceError(
49656
49982
  "PLAN_REFERENCE_INVALID",
49657
- "The explicit plan reference is empty, overlong, or contains an invalid character",
49983
+ "The immutable plan reference does not satisfy the bounded transport contract",
49658
49984
  "explicit"
49659
49985
  );
49660
49986
  }
49661
- return path57.isAbsolute(reference) ? path57.normalize(reference) : path57.resolve(workingDir, reference);
49987
+ return parsed.data;
49662
49988
  }
49663
- function readArtifact(filePath, source) {
49664
- let stat11;
49665
- try {
49666
- stat11 = fs48.statSync(filePath);
49667
- } catch {
49989
+ function parseScope(scope) {
49990
+ if (scope === void 0) return void 0;
49991
+ const parsed = PlanArtifactScope_v1Schema.safeParse(scope);
49992
+ if (!parsed.success) {
49668
49993
  throw new PlanArtifactServiceError(
49669
- "PLAN_NOT_FOUND",
49670
- "The referenced integration plan does not exist",
49671
- source
49994
+ "PLAN_REFERENCE_INVALID",
49995
+ "The plan scope does not satisfy the bounded transport contract",
49996
+ "explicit"
49672
49997
  );
49673
49998
  }
49674
- if (!stat11.isFile() || stat11.size > MAX_PLAN_BYTES) {
49999
+ return parsed.data;
50000
+ }
50001
+ function resolveExplicitReference(reference, workingDir) {
50002
+ if (reference.length === 0 || reference.includes("\0") || Buffer.byteLength(reference, "utf8") > MAX_PLAN_RETRIEVAL_REFERENCE_BYTES) {
49675
50003
  throw new PlanArtifactServiceError(
49676
- "PLAN_UNREADABLE",
49677
- "The referenced integration plan is not a readable bounded file",
50004
+ "PLAN_REFERENCE_INVALID",
50005
+ "The explicit plan reference is empty, overlong, or contains an invalid character",
50006
+ "explicit"
50007
+ );
50008
+ }
50009
+ return path57.isAbsolute(reference) ? path57.normalize(reference) : path57.resolve(workingDir, reference);
50010
+ }
50011
+ function readArtifact(filePath, source, hooks, expected, scope) {
50012
+ const content = readPortableRaceDetectedFile(filePath, source, hooks);
50013
+ const plan = loadPlan(content);
50014
+ assertBoundedArtifact(plan, source);
50015
+ const canonicalBytes2 = canonicalJSONStringify(plan);
50016
+ const canonicalByteLength = Buffer.byteLength(canonicalBytes2, "utf8");
50017
+ if (canonicalByteLength > MAX_PLAN_ARTIFACT_BYTES) {
50018
+ throw new PlanArtifactServiceError(
50019
+ "PLAN_ARTIFACT_LIMIT_EXCEEDED",
50020
+ "The canonical integration plan exceeds the artifact byte limit",
49678
50021
  source
49679
50022
  );
49680
50023
  }
49681
- let content;
49682
- try {
49683
- content = fs48.readFileSync(filePath, "utf8");
49684
- } catch {
50024
+ const artifactIdentity = {
50025
+ contract: EXECUTION_PLAN_ARTIFACT_CONTRACT,
50026
+ kind: "execution-plan",
50027
+ planSchema: "lexrunner.execution-plan",
50028
+ planSchemaVersion: plan.schemaVersion,
50029
+ canonicalizationProfile: EXECUTION_PLAN_CANONICALIZATION_PROFILE,
50030
+ hashProfile: EXECUTION_PLAN_HASH_PROFILE,
50031
+ digestAlgorithm: "sha256",
50032
+ digest: computeExecutionPlanArtifactDigest(canonicalBytes2),
50033
+ canonicalByteLength,
50034
+ target: plan.target,
50035
+ summary: {
50036
+ itemCount: plan.items.length,
50037
+ gateCount: plan.items.reduce((count, item) => count + item.gates.length, 0)
50038
+ }
50039
+ };
50040
+ const artifact = { identity: artifactIdentity, canonicalBytes: canonicalBytes2 };
50041
+ if (expected && !isDeepStrictEqual(expected.artifact, artifactIdentity)) {
49685
50042
  throw new PlanArtifactServiceError(
49686
- "PLAN_UNREADABLE",
49687
- "The referenced integration plan could not be read",
50043
+ "PLAN_REFERENCE_MISMATCH",
50044
+ "The retrieved integration plan does not match the immutable reference",
49688
50045
  source
49689
50046
  );
49690
50047
  }
49691
- const plan = loadPlan(content);
49692
- assertBoundedArtifact(plan, source);
50048
+ const reference = expected ?? parseReference({
50049
+ contract: PLAN_ARTIFACT_REFERENCE_CONTRACT,
50050
+ artifact: artifactIdentity,
50051
+ expectedDigest: artifactIdentity.digest,
50052
+ expectedCanonicalByteLength: artifactIdentity.canonicalByteLength,
50053
+ retrieval: { kind: "file", reference: filePath },
50054
+ ...scope ? { scope } : {}
50055
+ });
49693
50056
  return {
49694
50057
  plan,
49695
50058
  identity: {
@@ -49701,10 +50064,167 @@ function readArtifact(filePath, source) {
49701
50064
  target: plan.target,
49702
50065
  itemCount: plan.items.length
49703
50066
  },
50067
+ artifact,
50068
+ reference,
50069
+ acquisition: {
50070
+ contract: "lexrunner.plan-artifact-acquisition.v1",
50071
+ assurance: "portable-race-detection",
50072
+ authority: "unverified"
50073
+ },
49704
50074
  source,
49705
50075
  filePath
49706
50076
  };
49707
50077
  }
50078
+ function readPortableRaceDetectedFile(filePath, source, hooks) {
50079
+ const initialPath = snapshotPath(filePath, source);
50080
+ hooks.afterInitialPathSnapshot?.();
50081
+ const noFollow = typeof fs48.constants.O_NOFOLLOW === "number" ? fs48.constants.O_NOFOLLOW : 0;
50082
+ let descriptor;
50083
+ try {
50084
+ descriptor = fs48.openSync(filePath, fs48.constants.O_RDONLY | noFollow);
50085
+ } catch (error) {
50086
+ throw importError(error, source);
50087
+ }
50088
+ let bytes;
50089
+ try {
50090
+ const before = fs48.fstatSync(descriptor, { bigint: true });
50091
+ assertOpenedIdentity(initialPath[initialPath.length - 1].stats, before, source);
50092
+ hooks.afterOpen?.();
50093
+ if (before.size > BigInt(MAX_PLAN_ARTIFACT_BYTES)) {
50094
+ throw new PlanArtifactServiceError(
50095
+ "PLAN_ARTIFACT_LIMIT_EXCEEDED",
50096
+ "The referenced integration plan exceeds the artifact byte limit",
50097
+ source
50098
+ );
50099
+ }
50100
+ bytes = readAtMost(descriptor, MAX_PLAN_ARTIFACT_BYTES + 1);
50101
+ hooks.afterRead?.();
50102
+ const after = fs48.fstatSync(descriptor, { bigint: true });
50103
+ assertStableOpenedFile(before, after, bytes.length, source);
50104
+ } finally {
50105
+ fs48.closeSync(descriptor);
50106
+ }
50107
+ hooks.beforeFinalPathSnapshot?.();
50108
+ const finalPath = snapshotPath(filePath, source);
50109
+ assertStablePath(initialPath, finalPath, source);
50110
+ try {
50111
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
50112
+ } catch {
50113
+ throw new PlanArtifactServiceError(
50114
+ "PLAN_UNREADABLE",
50115
+ "The referenced integration plan is not valid UTF-8",
50116
+ source
50117
+ );
50118
+ }
50119
+ }
50120
+ function snapshotPath(filePath, source) {
50121
+ const absolute = path57.resolve(filePath);
50122
+ const root = path57.parse(absolute).root;
50123
+ const relative5 = path57.relative(root, absolute);
50124
+ const segments = relative5.length === 0 ? [] : relative5.split(path57.sep);
50125
+ const candidates = [root];
50126
+ let current = root;
50127
+ for (const segment of segments) {
50128
+ current = path57.join(current, segment);
50129
+ candidates.push(current);
50130
+ }
50131
+ return candidates.map((candidate, index) => {
50132
+ let stats;
50133
+ try {
50134
+ stats = fs48.lstatSync(candidate, { bigint: true });
50135
+ } catch (error) {
50136
+ throw importError(error, source);
50137
+ }
50138
+ const leaf = index === candidates.length - 1;
50139
+ if (stats.isSymbolicLink()) {
50140
+ throw new PlanArtifactServiceError(
50141
+ "PLAN_FILESYSTEM_UNSAFE",
50142
+ "The integration plan path contains an unsafe filesystem object",
50143
+ source
50144
+ );
50145
+ }
50146
+ if (leaf ? !stats.isFile() : !stats.isDirectory()) {
50147
+ throw new PlanArtifactServiceError(
50148
+ "PLAN_UNREADABLE",
50149
+ "The referenced integration plan is not a readable bounded file",
50150
+ source
50151
+ );
50152
+ }
50153
+ if (leaf && stats.nlink !== 1n) {
50154
+ throw new PlanArtifactServiceError(
50155
+ "PLAN_FILESYSTEM_UNSAFE",
50156
+ "The integration plan file has an ambiguous filesystem identity",
50157
+ source
50158
+ );
50159
+ }
50160
+ return { stats, leaf };
50161
+ });
50162
+ }
50163
+ function assertOpenedIdentity(pathStats, openedStats, source) {
50164
+ if (!openedStats.isFile() || openedStats.nlink !== 1n || !sameObject(pathStats, openedStats) || pathStats.size !== openedStats.size || pathStats.mtimeNs !== openedStats.mtimeNs || pathStats.ctimeNs !== openedStats.ctimeNs) {
50165
+ throw new PlanArtifactServiceError(
50166
+ "PLAN_FILESYSTEM_UNSAFE",
50167
+ "The integration plan filesystem identity changed during acquisition",
50168
+ source
50169
+ );
50170
+ }
50171
+ }
50172
+ function assertStableOpenedFile(before, after, bytesRead, source) {
50173
+ if (bytesRead > MAX_PLAN_ARTIFACT_BYTES) {
50174
+ throw new PlanArtifactServiceError(
50175
+ "PLAN_ARTIFACT_LIMIT_EXCEEDED",
50176
+ "The referenced integration plan exceeds the artifact byte limit",
50177
+ source
50178
+ );
50179
+ }
50180
+ if (!after.isFile() || after.nlink !== 1n || !sameObject(before, after) || before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs || BigInt(bytesRead) !== before.size) {
50181
+ throw new PlanArtifactServiceError(
50182
+ "PLAN_FILESYSTEM_UNSAFE",
50183
+ "The integration plan changed while its bytes were being acquired",
50184
+ source
50185
+ );
50186
+ }
50187
+ }
50188
+ function assertStablePath(before, after, source) {
50189
+ if (before.length !== after.length || before.some((entry, index) => {
50190
+ const current = after[index];
50191
+ return !current || entry.leaf !== current.leaf || !sameObject(entry.stats, current.stats) || entry.leaf && (entry.stats.size !== current.stats.size || entry.stats.mtimeNs !== current.stats.mtimeNs || entry.stats.ctimeNs !== current.stats.ctimeNs || current.stats.nlink !== 1n);
50192
+ })) {
50193
+ throw new PlanArtifactServiceError(
50194
+ "PLAN_FILESYSTEM_UNSAFE",
50195
+ "The integration plan path changed while its bytes were being acquired",
50196
+ source
50197
+ );
50198
+ }
50199
+ }
50200
+ function sameObject(left, right) {
50201
+ return left.dev === right.dev && left.ino === right.ino && left.mode === right.mode;
50202
+ }
50203
+ function readAtMost(descriptor, maximumBytes) {
50204
+ const buffer = Buffer.allocUnsafe(maximumBytes);
50205
+ let offset = 0;
50206
+ while (offset < maximumBytes) {
50207
+ const count = fs48.readSync(descriptor, buffer, offset, maximumBytes - offset, null);
50208
+ if (count === 0) break;
50209
+ offset += count;
50210
+ }
50211
+ return buffer.subarray(0, offset);
50212
+ }
50213
+ function importError(error, source) {
50214
+ const code = error?.code;
50215
+ if (code === "ENOENT" || code === "ENOTDIR") {
50216
+ return new PlanArtifactServiceError(
50217
+ "PLAN_NOT_FOUND",
50218
+ "The referenced integration plan does not exist",
50219
+ source
50220
+ );
50221
+ }
50222
+ return new PlanArtifactServiceError(
50223
+ "PLAN_UNREADABLE",
50224
+ "The referenced integration plan could not be safely read",
50225
+ source
50226
+ );
50227
+ }
49708
50228
  function assertBoundedArtifact(plan, source) {
49709
50229
  const labels = [
49710
50230
  plan.schemaVersion,
@@ -49719,11 +50239,277 @@ function assertBoundedArtifact(plan, source) {
49719
50239
  );
49720
50240
  }
49721
50241
  }
49722
- function isRegularFile(filePath) {
50242
+ function pathEntryExists(filePath) {
49723
50243
  try {
49724
- return fs48.statSync(filePath).isFile();
49725
- } catch {
49726
- return false;
50244
+ fs48.lstatSync(filePath);
50245
+ return true;
50246
+ } catch (error) {
50247
+ const code = error?.code;
50248
+ if (code === "ENOENT" || code === "ENOTDIR") return false;
50249
+ return true;
50250
+ }
50251
+ }
50252
+
50253
+ // src/application/plan-artifact-registration-service.ts
50254
+ import * as fs49 from "fs";
50255
+ import * as path58 from "path";
50256
+ import { randomUUID as randomUUID9 } from "crypto";
50257
+ var PlanArtifactRegistrationError = class extends Error {
50258
+ constructor(code, message) {
50259
+ super(message);
50260
+ this.code = code;
50261
+ this.name = "PlanArtifactRegistrationError";
50262
+ }
50263
+ };
50264
+ var _PlanArtifactRegistrationService_instances, verifyExisting_fn;
50265
+ var PlanArtifactRegistrationService = class {
50266
+ constructor() {
50267
+ __privateAdd(this, _PlanArtifactRegistrationService_instances);
50268
+ }
50269
+ register(input) {
50270
+ const parsed = ExecutionPlanArtifact_v1Schema.safeParse(input.artifact);
50271
+ if (!parsed.success) {
50272
+ throw new PlanArtifactRegistrationError(
50273
+ "PLAN_REGISTRATION_INVALID",
50274
+ "The plan artifact does not satisfy the immutable artifact contract"
50275
+ );
50276
+ }
50277
+ const artifact = parsed.data;
50278
+ const scope = parseScope2(input.scope);
50279
+ const storeDirectory = validateStoreReference(input.storeDirectory);
50280
+ prepareControlledStore(storeDirectory);
50281
+ const digestName = `${artifact.identity.digest.slice("sha256:".length)}.json`;
50282
+ const artifactPath = path58.join(storeDirectory, digestName);
50283
+ const reference = createRegisteredReference(artifact, artifactPath, scope);
50284
+ if (pathEntryExists2(artifactPath)) {
50285
+ return __privateMethod(this, _PlanArtifactRegistrationService_instances, verifyExisting_fn).call(this, artifact, reference, false);
50286
+ }
50287
+ const temporaryPath = path58.join(storeDirectory, `.plan-${randomUUID9()}.tmp`);
50288
+ let temporaryCreated = false;
50289
+ try {
50290
+ const descriptor = fs49.openSync(
50291
+ temporaryPath,
50292
+ fs49.constants.O_WRONLY | fs49.constants.O_CREAT | fs49.constants.O_EXCL,
50293
+ 384
50294
+ );
50295
+ temporaryCreated = true;
50296
+ try {
50297
+ writeAll(descriptor, Buffer.from(artifact.canonicalBytes, "utf8"));
50298
+ fs49.fsyncSync(descriptor);
50299
+ } finally {
50300
+ fs49.closeSync(descriptor);
50301
+ }
50302
+ try {
50303
+ fs49.linkSync(temporaryPath, artifactPath);
50304
+ } catch (error) {
50305
+ if (!pathEntryExists2(artifactPath)) throw error;
50306
+ return __privateMethod(this, _PlanArtifactRegistrationService_instances, verifyExisting_fn).call(this, artifact, reference, false);
50307
+ }
50308
+ try {
50309
+ fs49.unlinkSync(temporaryPath);
50310
+ } catch (error) {
50311
+ if (error.code !== "ENOENT") throw error;
50312
+ }
50313
+ temporaryCreated = false;
50314
+ flushDirectoryWhenSupported(storeDirectory);
50315
+ assertStoreDirectory(storeDirectory);
50316
+ return __privateMethod(this, _PlanArtifactRegistrationService_instances, verifyExisting_fn).call(this, artifact, reference, true);
50317
+ } catch (error) {
50318
+ if (error instanceof PlanArtifactRegistrationError) throw error;
50319
+ throw new PlanArtifactRegistrationError(
50320
+ "PLAN_REGISTRATION_UNSAFE",
50321
+ "The plan artifact could not be published without replacing existing bytes"
50322
+ );
50323
+ } finally {
50324
+ if (temporaryCreated) {
50325
+ try {
50326
+ fs49.unlinkSync(temporaryPath);
50327
+ } catch {
50328
+ }
50329
+ }
50330
+ }
50331
+ }
50332
+ };
50333
+ _PlanArtifactRegistrationService_instances = new WeakSet();
50334
+ verifyExisting_fn = function(artifact, reference, created) {
50335
+ try {
50336
+ waitForConcurrentPublisher(reference.retrieval.reference);
50337
+ const resolved = new PlanArtifactService().resolve({ planReference: reference });
50338
+ if (resolved.artifact.canonicalBytes !== artifact.canonicalBytes) {
50339
+ throw new PlanArtifactRegistrationError(
50340
+ "PLAN_REGISTRATION_CONFLICT",
50341
+ "The content-addressed plan object conflicts with the requested artifact"
50342
+ );
50343
+ }
50344
+ return {
50345
+ artifact: resolved.artifact,
50346
+ reference,
50347
+ created,
50348
+ storage: { assurance: "service-no-replace-verified", authority: "unverified" }
50349
+ };
50350
+ } catch (error) {
50351
+ if (error instanceof PlanArtifactRegistrationError) throw error;
50352
+ if (error instanceof PlanArtifactServiceError && error.code === "PLAN_REFERENCE_MISMATCH") {
50353
+ throw new PlanArtifactRegistrationError(
50354
+ "PLAN_REGISTRATION_CONFLICT",
50355
+ "The content-addressed plan object conflicts with the requested artifact"
50356
+ );
50357
+ }
50358
+ throw new PlanArtifactRegistrationError(
50359
+ "PLAN_REGISTRATION_VERIFY_FAILED",
50360
+ "The persisted plan artifact could not be reread and verified"
50361
+ );
50362
+ }
50363
+ };
50364
+ function createRegisteredReference(artifact, artifactPath, scope) {
50365
+ if (Buffer.byteLength(artifactPath, "utf8") > 4096) {
50366
+ throw new PlanArtifactRegistrationError(
50367
+ "PLAN_REGISTRATION_INVALID",
50368
+ "The artifact store cannot produce a bounded retrieval reference"
50369
+ );
50370
+ }
50371
+ const reference = {
50372
+ contract: PLAN_ARTIFACT_REFERENCE_CONTRACT,
50373
+ artifact: artifact.identity,
50374
+ expectedDigest: artifact.identity.digest,
50375
+ expectedCanonicalByteLength: artifact.identity.canonicalByteLength,
50376
+ retrieval: { kind: "registered", reference: artifactPath },
50377
+ ...scope ? { scope } : {}
50378
+ };
50379
+ const parsed = PlanArtifactReference_v1Schema.safeParse(reference);
50380
+ if (!parsed.success) {
50381
+ throw new PlanArtifactRegistrationError(
50382
+ "PLAN_REGISTRATION_INVALID",
50383
+ "The registered artifact reference does not satisfy the bounded transport contract"
50384
+ );
50385
+ }
50386
+ return parsed.data;
50387
+ }
50388
+ function parseScope2(scope) {
50389
+ if (scope === void 0) return void 0;
50390
+ const parsed = PlanArtifactScope_v1Schema.safeParse(scope);
50391
+ if (!parsed.success) {
50392
+ throw new PlanArtifactRegistrationError(
50393
+ "PLAN_REGISTRATION_INVALID",
50394
+ "The plan scope does not satisfy the bounded transport contract"
50395
+ );
50396
+ }
50397
+ return parsed.data;
50398
+ }
50399
+ function validateStoreReference(reference) {
50400
+ if (reference.length === 0 || reference.includes("\0") || Buffer.byteLength(reference, "utf8") > 4096) {
50401
+ throw new PlanArtifactRegistrationError(
50402
+ "PLAN_REGISTRATION_INVALID",
50403
+ "The artifact store reference is invalid or exceeds its bound"
50404
+ );
50405
+ }
50406
+ return path58.resolve(reference);
50407
+ }
50408
+ function prepareControlledStore(storeDirectory) {
50409
+ const root = path58.parse(storeDirectory).root;
50410
+ const segments = path58.relative(root, storeDirectory).split(path58.sep).filter(Boolean);
50411
+ let current = root;
50412
+ for (const segment of segments) {
50413
+ current = path58.join(current, segment);
50414
+ try {
50415
+ const stats = fs49.lstatSync(current);
50416
+ if (stats.isSymbolicLink() || !stats.isDirectory()) {
50417
+ throw new PlanArtifactRegistrationError(
50418
+ "PLAN_REGISTRATION_UNSAFE",
50419
+ "The artifact store contains an unsafe filesystem object"
50420
+ );
50421
+ }
50422
+ } catch (error) {
50423
+ if (error instanceof PlanArtifactRegistrationError) throw error;
50424
+ if (error.code !== "ENOENT") {
50425
+ throw new PlanArtifactRegistrationError(
50426
+ "PLAN_REGISTRATION_UNSAFE",
50427
+ "The artifact store identity is unavailable"
50428
+ );
50429
+ }
50430
+ try {
50431
+ fs49.mkdirSync(current, { mode: 448 });
50432
+ } catch (mkdirError) {
50433
+ if (mkdirError.code !== "EEXIST") {
50434
+ throw new PlanArtifactRegistrationError(
50435
+ "PLAN_REGISTRATION_UNSAFE",
50436
+ "The artifact store could not be prepared"
50437
+ );
50438
+ }
50439
+ }
50440
+ const created = fs49.lstatSync(current);
50441
+ if (created.isSymbolicLink() || !created.isDirectory()) {
50442
+ throw new PlanArtifactRegistrationError(
50443
+ "PLAN_REGISTRATION_UNSAFE",
50444
+ "The artifact store contains an unsafe filesystem object"
50445
+ );
50446
+ }
50447
+ }
50448
+ }
50449
+ assertStoreDirectory(storeDirectory);
50450
+ }
50451
+ function assertStoreDirectory(storeDirectory) {
50452
+ const root = path58.parse(storeDirectory).root;
50453
+ const segments = path58.relative(root, storeDirectory).split(path58.sep).filter(Boolean);
50454
+ let current = root;
50455
+ for (const segment of segments) {
50456
+ current = path58.join(current, segment);
50457
+ let stats;
50458
+ try {
50459
+ stats = fs49.lstatSync(current);
50460
+ } catch {
50461
+ throw new PlanArtifactRegistrationError(
50462
+ "PLAN_REGISTRATION_UNSAFE",
50463
+ "The artifact store identity is unavailable"
50464
+ );
50465
+ }
50466
+ if (stats.isSymbolicLink() || !stats.isDirectory()) {
50467
+ throw new PlanArtifactRegistrationError(
50468
+ "PLAN_REGISTRATION_UNSAFE",
50469
+ "The artifact store contains an unsafe filesystem object"
50470
+ );
50471
+ }
50472
+ }
50473
+ }
50474
+ function writeAll(descriptor, bytes) {
50475
+ let offset = 0;
50476
+ while (offset < bytes.length) {
50477
+ offset += fs49.writeSync(descriptor, bytes, offset, bytes.length - offset, null);
50478
+ }
50479
+ }
50480
+ function flushDirectoryWhenSupported(directory) {
50481
+ let descriptor;
50482
+ try {
50483
+ descriptor = fs49.openSync(directory, fs49.constants.O_RDONLY);
50484
+ fs49.fsyncSync(descriptor);
50485
+ } catch (error) {
50486
+ const code = error?.code;
50487
+ if (process.platform !== "win32" || code !== "EISDIR" && code !== "EPERM") throw error;
50488
+ } finally {
50489
+ if (descriptor !== void 0) fs49.closeSync(descriptor);
50490
+ }
50491
+ }
50492
+ function pathEntryExists2(filePath) {
50493
+ try {
50494
+ fs49.lstatSync(filePath);
50495
+ return true;
50496
+ } catch (error) {
50497
+ const code = error?.code;
50498
+ return code !== "ENOENT" && code !== "ENOTDIR";
50499
+ }
50500
+ }
50501
+ function waitForConcurrentPublisher(artifactPath) {
50502
+ const deadline = Date.now() + 500;
50503
+ const signal = new Int32Array(new SharedArrayBuffer(4));
50504
+ while (Date.now() < deadline) {
50505
+ let stats;
50506
+ try {
50507
+ stats = fs49.lstatSync(artifactPath);
50508
+ } catch {
50509
+ return;
50510
+ }
50511
+ if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink <= 1) return;
50512
+ Atomics.wait(signal, 0, 0, 10);
49727
50513
  }
49728
50514
  }
49729
50515
 
@@ -50282,7 +51068,7 @@ workspaceCmd.command("init").description("Initialize lexrunner workspace with in
50282
51068
  force: opts.force
50283
51069
  });
50284
51070
  if (isJsonMode) {
50285
- const { writeSuccessEnvelope } = await import("./jsonEnvelope-K2U5CWKU.js");
51071
+ const { writeSuccessEnvelope } = await import("./jsonEnvelope-MXJM5ZQH.js");
50286
51072
  writeSuccessEnvelope("lex-pr workspace init", initialized);
50287
51073
  } else {
50288
51074
  console.log(
@@ -50302,7 +51088,7 @@ workspaceCmd.command("init").description("Initialize lexrunner workspace with in
50302
51088
  policyTemplate: opts.policyTemplate
50303
51089
  });
50304
51090
  if (isJsonMode) {
50305
- const { writeSuccessEnvelope, writeErrorEnvelope } = await import("./jsonEnvelope-K2U5CWKU.js");
51091
+ const { writeSuccessEnvelope, writeErrorEnvelope } = await import("./jsonEnvelope-MXJM5ZQH.js");
50306
51092
  if (result.success) {
50307
51093
  writeSuccessEnvelope("lex-pr workspace init", {
50308
51094
  profileDir: result.profileDir,
@@ -50330,7 +51116,7 @@ workspaceCmd.command("init").description("Initialize lexrunner workspace with in
50330
51116
  throw error;
50331
51117
  }
50332
51118
  if (isJsonMode) {
50333
- const { writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-K2U5CWKU.js");
51119
+ const { writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-MXJM5ZQH.js");
50334
51120
  if (error instanceof WorkspaceConfigServiceError) {
50335
51121
  writeErrorEnvelope("lex-pr workspace init", {
50336
51122
  code: error.code,
@@ -50427,7 +51213,7 @@ program.command("init").description("Initialize lexrunner workspace with interac
50427
51213
  jsonMode: isJsonMode
50428
51214
  });
50429
51215
  if (isJsonMode) {
50430
- const { writeSuccessEnvelope, writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-K2U5CWKU.js");
51216
+ const { writeSuccessEnvelope, writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-MXJM5ZQH.js");
50431
51217
  if (result.success) {
50432
51218
  writeSuccessEnvelope("lex-pr init", {
50433
51219
  profileDir: result.profileDir,
@@ -50455,7 +51241,7 @@ program.command("init").description("Initialize lexrunner workspace with interac
50455
51241
  throw error;
50456
51242
  }
50457
51243
  if (isJsonMode) {
50458
- const { writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-K2U5CWKU.js");
51244
+ const { writeErrorEnvelope, errorToJsonError } = await import("./jsonEnvelope-MXJM5ZQH.js");
50459
51245
  if (error instanceof WriteProtectionError) {
50460
51246
  writeErrorEnvelope("lex-pr init", {
50461
51247
  code: "EWRITE_PROTECTED",
@@ -50651,8 +51437,8 @@ program.command("view").description("Interactive plan viewer with navigation and
50651
51437
  throwExit(1);
50652
51438
  }
50653
51439
  try {
50654
- const { InteractivePlanViewer } = await import("./planViewer-TRSQVMH4.js");
50655
- const planContent = fs49.readFileSync(planFile, "utf-8");
51440
+ const { InteractivePlanViewer } = await import("./planViewer-WOV6A2HZ.js");
51441
+ const planContent = fs50.readFileSync(planFile, "utf-8");
50656
51442
  const plan = loadPlan(planContent);
50657
51443
  const viewer = new InteractivePlanViewer(plan, {
50658
51444
  filter: opts.filter,
@@ -50668,7 +51454,7 @@ program.command("view").description("Interactive plan viewer with navigation and
50668
51454
  program.command("deliverables:list").description("List all autopilot deliverables with metadata").option("--profile-dir <dir>", "Profile directory (default: .smartergpt)").option("--json", "Output JSON format").action(async (opts) => {
50669
51455
  try {
50670
51456
  const profile = resolveProfile(opts.profileDir);
50671
- const { DeliverablesManager } = await import("./autopilot-3OHEUTHD.js");
51457
+ const { DeliverablesManager } = await import("./autopilot-7PX6YG55.js");
50672
51458
  const manager = new DeliverablesManager(profile.path);
50673
51459
  const deliverables = await manager.listDeliverables();
50674
51460
  if (opts.json) {
@@ -50694,7 +51480,7 @@ program.command("deliverables:list").description("List all autopilot deliverable
50694
51480
  });
50695
51481
  const latest = manager.getLatestPath();
50696
51482
  if (latest) {
50697
- console.log(`\u{1F4CD} Latest: ${path58.basename(latest)}`);
51483
+ console.log(`\u{1F4CD} Latest: ${path59.basename(latest)}`);
50698
51484
  }
50699
51485
  }
50700
51486
  } catch (error) {
@@ -50707,7 +51493,7 @@ program.command("deliverables:list").description("List all autopilot deliverable
50707
51493
  program.command("deliverables:cleanup").description("Clean up old deliverables based on retention policy").option("--profile-dir <dir>", "Profile directory (default: .smartergpt)").option("--max-age <days>", "Maximum age in days (deletes older deliverables)").option("--max-count <count>", "Maximum number of deliverables to keep").option("--keep-latest", "Always keep the latest deliverables (default: true)", true).option("--dry-run", "Preview cleanup without deleting").option("--json", "Output JSON format").action(async (opts) => {
50708
51494
  try {
50709
51495
  const profile = resolveProfile(opts.profileDir);
50710
- const { DeliverablesManager } = await import("./autopilot-3OHEUTHD.js");
51496
+ const { DeliverablesManager } = await import("./autopilot-7PX6YG55.js");
50711
51497
  const manager = new DeliverablesManager(profile.path);
50712
51498
  const policy = {
50713
51499
  maxAge: opts.maxAge ? parseInt(opts.maxAge) : void 0,
@@ -50768,8 +51554,8 @@ program.command("deliverables:cleanup").description("Clean up old deliverables b
50768
51554
  console.log(`Freed space: ${(result.freedSpace / 1024).toFixed(2)} KB`);
50769
51555
  if (result.removed.length > 0) {
50770
51556
  console.log("\nRemoved:");
50771
- result.removed.forEach((path59) => {
50772
- console.log(` - ${path59}`);
51557
+ result.removed.forEach((path60) => {
51558
+ console.log(` - ${path60}`);
50773
51559
  });
50774
51560
  }
50775
51561
  }
@@ -50840,8 +51626,8 @@ var isDirectExec = (() => {
50840
51626
  try {
50841
51627
  if (typeof import.meta === "undefined") return false;
50842
51628
  if (!process.argv[1] || !import.meta.url) return false;
50843
- const invokedPath = fs49.realpathSync(resolve14(process.argv[1]));
50844
- const modulePath = fs49.realpathSync(fileURLToPath6(import.meta.url));
51629
+ const invokedPath = fs50.realpathSync(resolve15(process.argv[1]));
51630
+ const modulePath = fs50.realpathSync(fileURLToPath6(import.meta.url));
50845
51631
  return invokedPath === modulePath;
50846
51632
  } catch {
50847
51633
  return false;
@@ -50911,11 +51697,17 @@ export {
50911
51697
  ConfigurationQueryService,
50912
51698
  ControllerLease_v1,
50913
51699
  DiscoveryQueryService,
51700
+ EXECUTION_PLAN_ARTIFACT_CONTRACT,
51701
+ EXECUTION_PLAN_CANONICALIZATION_PROFILE,
51702
+ EXECUTION_PLAN_HASH_DOMAIN,
51703
+ EXECUTION_PLAN_HASH_PROFILE,
50914
51704
  EngineVerificationCheckSource_v2,
50915
51705
  EngineVerificationDeterminism_v2,
50916
51706
  EngineVerificationTrustGapReason_v2,
50917
51707
  ExecutionEnvelope_v1,
50918
51708
  ExecutionEnvironmentOS,
51709
+ ExecutionPlanArtifactIdentity_v1Schema,
51710
+ ExecutionPlanArtifact_v1Schema,
50919
51711
  ExecutionState,
50920
51712
  ExternalAwaitOutcome_v1,
50921
51713
  ExternalAwaitableDescriptor_v1,
@@ -50971,6 +51763,11 @@ export {
50971
51763
  NativeWslProjectionSelection_v1,
50972
51764
  NativeWslProjectionStatusRequestJsonSchema,
50973
51765
  NativeWslSourceObservation_v1,
51766
+ PLAN_ARTIFACT_REFERENCE_CONTRACT,
51767
+ PlanArtifactReference_v1Schema,
51768
+ PlanArtifactRegistrationError,
51769
+ PlanArtifactRegistrationService,
51770
+ PlanArtifactScope_v1Schema,
50974
51771
  PlanArtifactService,
50975
51772
  PlanArtifactServiceError,
50976
51773
  PlanCreationService,
@@ -51000,6 +51797,7 @@ export {
51000
51797
  completionForAttemptAwaitable,
51001
51798
  computeAgentEngineVerificationV2Hash,
51002
51799
  computeAgentTaskPacketHash,
51800
+ computeExecutionPlanArtifactDigest,
51003
51801
  computeFanInEvidenceSetHash,
51004
51802
  computeMergeOrder,
51005
51803
  containsAttemptAwaitableCredentialValue,