akm-cli 0.9.4 → 0.9.6

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 (123) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/dist/commands/env/env-cli.js +1 -2
  3. package/dist/commands/env/secret-cli.js +1 -5
  4. package/dist/commands/feedback-cli.js +0 -4
  5. package/dist/commands/health/checks.js +0 -32
  6. package/dist/commands/health/surfaces.js +2 -2
  7. package/dist/commands/health.js +6 -15
  8. package/dist/commands/improve/anti-collapse.js +4 -91
  9. package/dist/commands/improve/autonomy-gate.js +1 -1
  10. package/dist/commands/improve/consolidate.js +25 -26
  11. package/dist/commands/improve/distill.js +2 -2
  12. package/dist/commands/improve/extract.js +8 -1
  13. package/dist/commands/improve/improve.js +3 -5
  14. package/dist/commands/improve/locks.js +13 -5
  15. package/dist/commands/improve/loop-stages.js +8 -9
  16. package/dist/commands/improve/memory/memory-contradiction-detect.js +1 -19
  17. package/dist/commands/improve/outcome-loop.js +0 -6
  18. package/dist/commands/improve/reflect.js +20 -9
  19. package/dist/commands/lint/index.js +4 -6
  20. package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -7
  21. package/dist/commands/proposal/validators/proposal-validators.js +12 -0
  22. package/dist/commands/read/search.js +14 -24
  23. package/dist/commands/sources/bundle-config-ops.js +9 -4
  24. package/dist/commands/sources/info.js +14 -10
  25. package/dist/commands/tasks/tasks-cli.js +56 -3
  26. package/dist/commands/tasks/tasks.js +101 -18
  27. package/dist/commands/workflow-cli.js +2 -2
  28. package/dist/core/adapter/adapters/akm-adapter.js +2 -0
  29. package/dist/core/common.js +61 -24
  30. package/dist/core/config/config-io.js +2 -2
  31. package/dist/core/config/config-sources.js +32 -2
  32. package/dist/core/config/config-version-shim.js +101 -0
  33. package/dist/core/config/config.js +7 -7
  34. package/dist/core/config/schema/engines.js +9 -7
  35. package/dist/core/config/schema/primitives.js +0 -5
  36. package/dist/core/config/schema/search.js +2 -1
  37. package/dist/core/file-lock.js +2 -1
  38. package/dist/core/improve-result.js +35 -14
  39. package/dist/core/maintenance-barrier.js +2 -14
  40. package/dist/core/paths.js +0 -3
  41. package/dist/core/redaction.js +2 -2
  42. package/dist/core/spawn-env.js +8 -12
  43. package/dist/core/state/migrations.js +1 -12
  44. package/dist/core/state-db.js +9 -27
  45. package/dist/core/write-source.js +12 -19
  46. package/dist/execution/directory-identity.js +36 -10
  47. package/dist/execution/guarded-source.js +0 -10
  48. package/dist/indexer/graph/graph-boost.js +0 -4
  49. package/dist/indexer/index-writer-lock.js +43 -24
  50. package/dist/indexer/index-written-assets.js +5 -6
  51. package/dist/indexer/indexer.js +2 -39
  52. package/dist/indexer/materialize-embeddings.js +85 -41
  53. package/dist/indexer/passes/metadata.js +12 -4
  54. package/dist/indexer/scan/doc-to-entry.js +2 -0
  55. package/dist/indexer/search/db-search.js +15 -48
  56. package/dist/indexer/search/ranking-contributors.js +0 -25
  57. package/dist/indexer/search/ranking.js +3 -13
  58. package/dist/indexer/search/search-fields.js +16 -1
  59. package/dist/integrations/agent/builder-shared.js +0 -25
  60. package/dist/integrations/agent/model-map.js +2 -60
  61. package/dist/integrations/harnesses/aider/agent-builder.js +1 -3
  62. package/dist/integrations/harnesses/amazonq/agent-builder.js +2 -7
  63. package/dist/integrations/harnesses/claude/agent-builder.js +1 -4
  64. package/dist/integrations/harnesses/codex/agent-builder.js +1 -4
  65. package/dist/integrations/harnesses/copilot/agent-builder.js +2 -6
  66. package/dist/integrations/harnesses/gemini/agent-builder.js +2 -7
  67. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -4
  68. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +2 -16
  69. package/dist/integrations/harnesses/openhands/agent-builder.js +1 -3
  70. package/dist/integrations/harnesses/pi/agent-builder.js +2 -4
  71. package/dist/integrations/session-logs/index.js +0 -9
  72. package/dist/llm/client.js +75 -42
  73. package/dist/llm/embedder.js +7 -3
  74. package/dist/llm/embedders/remote.js +141 -42
  75. package/dist/output/shapes/passthrough.js +17 -5
  76. package/dist/registry/network.js +5 -37
  77. package/dist/runtime.js +2 -10
  78. package/dist/scripts/akm-migrate-node.js +180 -238
  79. package/dist/scripts/akm-migrate.js +180 -238
  80. package/dist/setup/engine-config.js +2 -5
  81. package/dist/setup/registry-stash-loader.js +0 -8
  82. package/dist/setup/setup.js +9 -46
  83. package/dist/setup/steps/connection-shared.js +10 -13
  84. package/dist/sources/providers/git-install.js +1 -1
  85. package/dist/storage/engines/sqlite-migrations.js +20 -1
  86. package/dist/storage/repositories/index-entries-repository.js +0 -15
  87. package/dist/storage/repositories/proposals-repository.js +32 -6
  88. package/dist/tasks/backends/launchd.js +15 -20
  89. package/dist/tasks/backends/schtasks.js +18 -8
  90. package/dist/tasks/run/run-native-task.js +8 -6
  91. package/dist/tasks/scheduler-binding.js +15 -5
  92. package/dist/tasks/scheduler-sync-preview.js +4 -2
  93. package/dist/tasks/scheduler-sync.js +77 -42
  94. package/dist/tasks/source/bounded-document.js +2 -4
  95. package/dist/tasks/source/task-source-v3-frozen.js +5 -7
  96. package/dist/tasks/source/task-source-v4.js +5 -10
  97. package/dist/tasks/source/task-to-v3.js +29 -22
  98. package/dist/tasks/source/task-to-v4.js +1 -14
  99. package/dist/tasks/source-v3.js +6 -6
  100. package/dist/workflows/exec/native-executor.js +21 -31
  101. package/dist/workflows/exec/run-workflow.js +5 -6
  102. package/dist/workflows/exec/scheduler.js +3 -19
  103. package/dist/workflows/exec/step-work.js +1 -4
  104. package/dist/workflows/exec/unit-dispatch.js +2 -2
  105. package/dist/workflows/exec/worktree.js +1 -13
  106. package/dist/workflows/freeze/targets/child-workflow.js +2 -10
  107. package/dist/workflows/ir/plan-hash.js +4 -6
  108. package/dist/workflows/ir/schema-v4.js +0 -12
  109. package/dist/workflows/ir/schema.js +20 -31
  110. package/dist/workflows/parser.js +11 -52
  111. package/dist/workflows/renderer.js +2 -3
  112. package/dist/workflows/resource-limits.js +11 -41
  113. package/dist/workflows/runtime/runs.js +3 -4
  114. package/dist/workflows/source-ir/schema.js +14 -30
  115. package/dist/workflows/validator.js +1 -7
  116. package/docs/reference/cli.md +25 -3
  117. package/docs/reference/configuration.md +28 -7
  118. package/docs/reference/tasks.md +10 -0
  119. package/package.json +1 -1
  120. package/schemas/akm-config.json +4 -23
  121. package/schemas/akm-task.json +1 -2
  122. package/schemas/akm-workflow.json +1 -13
  123. package/dist/indexer/search/semantic-status.js +0 -142
@@ -9380,8 +9380,6 @@ function getRegistryIndexCacheDir() {
9380
9380
  }
9381
9381
 
9382
9382
  // src/core/common.ts
9383
- var MAX_CONFIG_FILE_BYTES = 1024 * 1024;
9384
- var MAX_LOCAL_METADATA_BYTES = 1024 * 1024;
9385
9383
  var MAX_LOCK_METADATA_BYTES = 64 * 1024;
9386
9384
  function readTextFileDescriptorWithLimit(fd, maxBytes, label = "File", displayPath = "(open file)") {
9387
9385
  const stat = fs.fstatSync(fd);
@@ -9403,10 +9401,13 @@ function readTextFileDescriptorWithLimit(fd, maxBytes, label = "File", displayPa
9403
9401
  }
9404
9402
  return buffer.subarray(0, total).toString("utf8");
9405
9403
  }
9406
- function readTextFileWithLimit(filePath, maxBytes, label = "File") {
9404
+ function readTextFile(filePath, label = "File") {
9407
9405
  const fd = fs.openSync(filePath, "r");
9408
9406
  try {
9409
- return readTextFileDescriptorWithLimit(fd, maxBytes, label, filePath);
9407
+ const stat = fs.fstatSync(fd);
9408
+ if (!stat.isFile())
9409
+ throw new ConfigError(`${label} is not a regular file: ${filePath}.`, "INVALID_CONFIG_FILE");
9410
+ return fs.readFileSync(fd, "utf8");
9410
9411
  } finally {
9411
9412
  fs.closeSync(fd);
9412
9413
  }
@@ -9506,6 +9507,8 @@ function asNonEmptyString(value) {
9506
9507
  return trimmed.length > 0 ? trimmed : undefined;
9507
9508
  }
9508
9509
  function isProcessAlive(pid) {
9510
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
9511
+ return false;
9509
9512
  try {
9510
9513
  process.kill(pid, 0);
9511
9514
  return true;
@@ -10067,11 +10070,13 @@ function makeStampHandler(command) {
10067
10070
  if (typeof result !== "object" || Array.isArray(result))
10068
10071
  return result;
10069
10072
  const obj = result;
10070
- if (obj.shape === undefined)
10071
- obj.shape = command;
10072
- if (obj.schemaVersion === undefined)
10073
- obj.schemaVersion = 1;
10074
- return obj;
10073
+ if (obj.shape !== undefined && obj.schemaVersion !== undefined)
10074
+ return obj;
10075
+ return {
10076
+ ...obj,
10077
+ shape: obj.shape ?? command,
10078
+ schemaVersion: obj.schemaVersion ?? 1
10079
+ };
10075
10080
  };
10076
10081
  }
10077
10082
  var PASSTHROUGH_COMMANDS = [
@@ -10111,6 +10116,7 @@ var PASSTHROUGH_COMMANDS = [
10111
10116
  "task-doctor",
10112
10117
  "task-explain",
10113
10118
  "task-history",
10119
+ "task-prune",
10114
10120
  "task-run",
10115
10121
  "task-sync",
10116
10122
  "task-sync-dry-run",
@@ -13024,8 +13030,17 @@ import path8 from "node:path";
13024
13030
  // src/core/warn.ts
13025
13031
  import fs4 from "node:fs";
13026
13032
  var quiet = false;
13033
+ var verbose = false;
13027
13034
  var logFilePath;
13028
13035
  var sinkOverride;
13036
+ function isVerbose() {
13037
+ const env = process.env.AKM_VERBOSE?.trim().toLowerCase();
13038
+ if (env === "1" || env === "true" || env === "yes" || env === "on")
13039
+ return true;
13040
+ if (env === "0" || env === "false" || env === "no" || env === "off")
13041
+ return false;
13042
+ return verbose;
13043
+ }
13029
13044
  function appendToLogFile(level, args) {
13030
13045
  if (!logFilePath)
13031
13046
  return;
@@ -13051,6 +13066,15 @@ function warn(...args) {
13051
13066
  console.warn(...args);
13052
13067
  }
13053
13068
  }
13069
+ function warnVerbose(...args) {
13070
+ if (sinkOverride) {
13071
+ sinkOverride("warnVerbose", args);
13072
+ return;
13073
+ }
13074
+ if (isVerbose()) {
13075
+ warn(...args);
13076
+ }
13077
+ }
13054
13078
 
13055
13079
  // src/indexer/passes/metadata.ts
13056
13080
  var SCOPE_KEYS = ["user", "agent", "run", "channel"];
@@ -13766,7 +13790,7 @@ function stripMarkdownLinkDestinations(text, nesting = 0) {
13766
13790
  }
13767
13791
  return visible;
13768
13792
  }
13769
- function projectMarkdownContent(body) {
13793
+ function projectMarkdownContent(body, truncationInfo) {
13770
13794
  const lines = body.split(/\r?\n/);
13771
13795
  const innerBlock = findInnerFrontmatterBlock(lines);
13772
13796
  const start = innerBlock && isFrontmatterShaped(lines, innerBlock) ? innerBlock.close + 1 : 0;
@@ -13812,6 +13836,8 @@ function projectMarkdownContent(body) {
13812
13836
  const text = projected.join(" ").replace(/\s+/g, " ").trim();
13813
13837
  if (!text)
13814
13838
  return;
13839
+ if (truncationInfo)
13840
+ truncationInfo.truncated = text.length > MARKDOWN_CONTENT_MAX_CHARS;
13815
13841
  return truncateUnicodeSafe(text, MARKDOWN_CONTENT_MAX_CHARS);
13816
13842
  }
13817
13843
  function applyPreContributorFields(entry, file, ctx, pkgMeta) {
@@ -13835,9 +13861,15 @@ function applyPreContributorFields(entry, file, ctx, pkgMeta) {
13835
13861
  applyWikiFrontmatter(entry, parsed.data);
13836
13862
  applyProvenanceFrontmatter(entry, parsed.data);
13837
13863
  if (entry.type !== "env" && entry.type !== "session" && !hasSessionMemoryMarker(parsed.data, parsed.content)) {
13838
- const contentProjection = projectMarkdownContent(parsed.content);
13839
- if (contentProjection)
13864
+ const truncationInfo = { truncated: false };
13865
+ const contentProjection = projectMarkdownContent(parsed.content, truncationInfo);
13866
+ if (contentProjection) {
13840
13867
  entry.content = contentProjection;
13868
+ if (truncationInfo.truncated) {
13869
+ entry.contentTruncated = true;
13870
+ warnVerbose(`${file}: indexed content truncated to ${MARKDOWN_CONTENT_MAX_CHARS} chars`);
13871
+ }
13872
+ }
13841
13873
  }
13842
13874
  if (entry.type === "command") {
13843
13875
  const cmdParams = extractCommandParameters(parsed.content);
@@ -14928,25 +14960,13 @@ var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
14928
14960
  // src/workflows/resource-limits.ts
14929
14961
  var WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
14930
14962
  var WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
14931
- var WORKFLOW_MAX_STEPS = 256;
14932
- var WORKFLOW_MAX_PARAMS = 128;
14933
- var WORKFLOW_MAX_ROUTE_BRANCHES = 256;
14934
14963
  var WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
14935
14964
  var WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
14936
14965
  var WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
14937
- var WORKFLOW_MAX_MAP_EXPANSION = 1e4;
14938
- var WORKFLOW_MAX_INPUTS = 64;
14939
- var WORKFLOW_MAX_OUTPUTS = 64;
14940
14966
  var WORKFLOW_MAX_CONCURRENCY = 64;
14941
- var WORKFLOW_MAX_GATE_LOOPS = 100;
14942
- var WORKFLOW_MAX_RETRIES = 100;
14943
14967
  var WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
14944
14968
  var WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
14945
14969
  var WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
14946
- var WORKFLOW_MAX_EXEC_ARGV = 64;
14947
- var WORKFLOW_MAX_EXEC_ARG_BYTES = 4096;
14948
- var WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
14949
- var WORKFLOW_MAX_EXEC_PASS_ENV = 32;
14950
14970
  var WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
14951
14971
  var WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
14952
14972
  var EXEC_CONTEXT_LIMITS_POSIX = {
@@ -14964,13 +14984,13 @@ function jsonBytes(value) {
14964
14984
  var WORKFLOW_MAX_EMBEDDED_CHILD_PLAN_BYTES = 1024 * 1024;
14965
14985
 
14966
14986
  // src/tasks/source/bounded-document.ts
14967
- var TASK_V3_MAX_SOURCE_BYTES = 1024 * 1024;
14968
14987
  var TASK_V3_MAX_JSON_DEPTH = 64;
14969
14988
  var TASK_V3_MAX_JSON_NODES = 1e4;
14970
14989
  var TASK_V3_MAX_COLLECTION_ITEMS = 1024;
14971
14990
  var TASK_V3_MAX_OBJECT_KEYS = 256;
14972
14991
  var TASK_V3_MAX_STRING_BYTES = 256 * 1024;
14973
14992
  var TASK_V3_MAX_SCHEDULES = 64;
14993
+ var TASK_V3_MAX_REDACT_NAMES = 32;
14974
14994
  function own2(value, key) {
14975
14995
  return Object.hasOwn(value, key);
14976
14996
  }
@@ -15259,9 +15279,6 @@ function readBoundedTaskSourceYaml(input, options) {
15259
15279
  if (typeof input.yaml !== "string") {
15260
15280
  throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source must be a string.`, "TASK_SOURCE_INVALID");
15261
15281
  }
15262
- if (utf8Bytes2(input.yaml) > TASK_V3_MAX_SOURCE_BYTES) {
15263
- throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) resource limit.`, "TASK_SOURCE_INVALID");
15264
- }
15265
15282
  const lineCounter2 = new $LineCounter;
15266
15283
  let document;
15267
15284
  try {
@@ -16021,7 +16038,7 @@ function parseExecutionControls(input, ctx) {
16021
16038
  out.timeout = parseTimeoutTopLevel(input.timeout, ctx);
16022
16039
  if (own2(input, "redact")) {
16023
16040
  const names = parseStringArray(input.redact, ctx, ["redact"], {
16024
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16041
+ max: TASK_V3_MAX_REDACT_NAMES,
16025
16042
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16026
16043
  });
16027
16044
  if (new Set(names).size !== names.length)
@@ -16035,8 +16052,8 @@ function parseExecutionControls(input, ctx) {
16035
16052
  out.maxSteps = input.maxSteps;
16036
16053
  }
16037
16054
  if (own2(input, "maxRetries")) {
16038
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16039
- sourceError(ctx, ["maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16055
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16056
+ sourceError(ctx, ["maxRetries"], "must be a non-negative safe integer.");
16040
16057
  }
16041
16058
  out.maxRetries = input.maxRetries;
16042
16059
  }
@@ -16096,9 +16113,6 @@ function parseInputDeclaration(name, raw, ctx) {
16096
16113
  function parseInputDeclarations(value, ctx) {
16097
16114
  const input = asRecord(value, ctx, ["inputs"]);
16098
16115
  const names = Object.keys(input);
16099
- if (names.length > WORKFLOW_MAX_PARAMS) {
16100
- sourceError(ctx, ["inputs"], `accepts at most ${WORKFLOW_MAX_PARAMS} declared inputs.`);
16101
- }
16102
16116
  const result = {};
16103
16117
  for (const name of names) {
16104
16118
  if (!INPUT_NAME_PATTERN.test(name)) {
@@ -16531,7 +16545,7 @@ function parseAkm(value, ctx) {
16531
16545
  out.timeout = parseTimeout(input.timeout, ctx);
16532
16546
  if (own2(input, "redact")) {
16533
16547
  const names = parseStringArray(input.redact, ctx, ["akm", "redact"], {
16534
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16548
+ max: TASK_V3_MAX_REDACT_NAMES,
16535
16549
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16536
16550
  });
16537
16551
  if (new Set(names).size !== names.length)
@@ -16545,8 +16559,8 @@ function parseAkm(value, ctx) {
16545
16559
  out.maxSteps = input.maxSteps;
16546
16560
  }
16547
16561
  if (own2(input, "maxRetries")) {
16548
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16549
- sourceError(ctx, ["akm", "maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16562
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16563
+ sourceError(ctx, ["akm", "maxRetries"], "must be a non-negative safe integer.");
16550
16564
  }
16551
16565
  out.maxRetries = input.maxRetries;
16552
16566
  }
@@ -16800,6 +16814,16 @@ var SHELL_ASSIGNMENT_WORD = /^[A-Za-z_][A-Za-z0-9_]*=/;
16800
16814
  function shellStableV2Executable(executable) {
16801
16815
  return executable === "akm" || executable.includes("/");
16802
16816
  }
16817
+ function skipEnvAssignmentPrefix(tokens) {
16818
+ if (tokens[0] !== "env")
16819
+ return { tokens, envWrapped: false };
16820
+ let index = 1;
16821
+ while (index < tokens.length && SHELL_ASSIGNMENT_WORD.test(tokens[index]))
16822
+ index += 1;
16823
+ if (index >= tokens.length)
16824
+ return { tokens, envWrapped: false };
16825
+ return { tokens: tokens.slice(index), envWrapped: true };
16826
+ }
16803
16827
  var KNOWN_PROMPT_REF_FAMILIES = new Set([
16804
16828
  "agents",
16805
16829
  "commands",
@@ -16820,11 +16844,6 @@ function hash(bytes) {
16820
16844
  return crypto.createHash("sha256").update(bytes).digest("hex");
16821
16845
  }
16822
16846
  function base(input) {
16823
- const inspectionIdentity = input.inspectionIdentity ? Object.freeze({
16824
- file: Object.freeze({ ...input.inspectionIdentity.file }),
16825
- root: Object.freeze({ ...input.inspectionIdentity.root }),
16826
- ...input.inspectionIdentity.bundleRoot ? { bundleRoot: Object.freeze({ ...input.inspectionIdentity.bundleRoot }) } : {}
16827
- }) : undefined;
16828
16847
  return {
16829
16848
  filePath: input.filePath,
16830
16849
  before: Buffer.from(input.bytes),
@@ -16832,8 +16851,7 @@ function base(input) {
16832
16851
  mode: input.mode,
16833
16852
  writable: input.writable,
16834
16853
  ...input.onDiskWritable !== undefined ? { onDiskWritable: input.onDiskWritable } : {},
16835
- ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {},
16836
- ...inspectionIdentity ? { inspectionIdentity } : {}
16854
+ ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {}
16837
16855
  };
16838
16856
  }
16839
16857
  function blocked(input, reason, detail) {
@@ -16859,9 +16877,6 @@ function optionalString(value, label) {
16859
16877
  return exactString(value, label);
16860
16878
  }
16861
16879
  function parseLegacyTaskYaml(input) {
16862
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
16863
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
16864
- }
16865
16880
  let source;
16866
16881
  try {
16867
16882
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -16909,7 +16924,7 @@ function validateCommonV2(data) {
16909
16924
  }
16910
16925
  }
16911
16926
  if (data.redact !== undefined && data.redact !== null) {
16912
- if (!Array.isArray(data.redact) || data.redact.length > WORKFLOW_MAX_EXEC_PASS_ENV || data.redact.some((entry) => typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry))) {
16927
+ if (!Array.isArray(data.redact) || data.redact.length > TASK_V3_MAX_REDACT_NAMES || data.redact.some((entry) => typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry))) {
16913
16928
  throw new Error("redact must contain only bounded environment variable names");
16914
16929
  }
16915
16930
  }
@@ -17035,8 +17050,8 @@ function migratedObject(data) {
17035
17050
  akm.maxSteps = data.maxSteps;
17036
17051
  }
17037
17052
  if (data.maxRetries !== undefined && data.maxRetries !== null) {
17038
- if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0 || data.maxRetries > WORKFLOW_MAX_RETRIES) {
17039
- throw new Error(`maxRetries must be from 0 through ${WORKFLOW_MAX_RETRIES}`);
17053
+ if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0) {
17054
+ throw new Error("maxRetries must be a non-negative integer");
17040
17055
  }
17041
17056
  akm.maxRetries = data.maxRetries;
17042
17057
  }
@@ -17069,8 +17084,9 @@ function migratedObject(data) {
17069
17084
  if (tokens.length === 0 || tokens.some((token) => !SAFE_V2_COMMAND_TOKEN.test(token))) {
17070
17085
  return "shell-operators-change-v2-literal-argv-semantics";
17071
17086
  }
17072
- const executable = tokens[0];
17073
- if (SHELL_ASSIGNMENT_WORD.test(executable) || !shellStableV2Executable(executable)) {
17087
+ const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(tokens);
17088
+ const executable = targetTokens[0];
17089
+ if (SHELL_ASSIGNMENT_WORD.test(executable) || !envWrapped && !shellStableV2Executable(executable)) {
17074
17090
  return "shell-command-resolution-changes-v2-literal-argv-semantics";
17075
17091
  }
17076
17092
  output.run = tokens.join(" ");
@@ -17264,11 +17280,6 @@ function causeMessage(cause) {
17264
17280
  return cause instanceof Error ? cause.message : String(cause);
17265
17281
  }
17266
17282
  function base2(input) {
17267
- const inspectionIdentity = input.inspectionIdentity ? Object.freeze({
17268
- file: Object.freeze({ ...input.inspectionIdentity.file }),
17269
- root: Object.freeze({ ...input.inspectionIdentity.root }),
17270
- ...input.inspectionIdentity.bundleRoot ? { bundleRoot: Object.freeze({ ...input.inspectionIdentity.bundleRoot }) } : {}
17271
- }) : undefined;
17272
17283
  return {
17273
17284
  filePath: input.filePath,
17274
17285
  before: Buffer.from(input.bytes),
@@ -17276,8 +17287,7 @@ function base2(input) {
17276
17287
  mode: input.mode,
17277
17288
  writable: input.writable,
17278
17289
  ...input.onDiskWritable !== undefined ? { onDiskWritable: input.onDiskWritable } : {},
17279
- ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {},
17280
- ...inspectionIdentity ? { inspectionIdentity } : {}
17290
+ ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {}
17281
17291
  };
17282
17292
  }
17283
17293
  function blocked2(input, reason, detail) {
@@ -17300,9 +17310,6 @@ function exactString2(value, label, nonempty = false) {
17300
17310
  return value;
17301
17311
  }
17302
17312
  function parseV3RawYaml(input) {
17303
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
17304
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
17305
- }
17306
17313
  let source;
17307
17314
  try {
17308
17315
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -18503,7 +18510,7 @@ function validateStep(value, jobId, index, stepIds, options) {
18503
18510
  }
18504
18511
  validateMap(step.map, `step ${id} map`);
18505
18512
  validateRoute(step.route, `step ${id} route`);
18506
- optionalStringList(step.inputs, `step ${id} inputs`, WORKFLOW_MAX_INPUTS);
18513
+ optionalStringList(step.inputs, `step ${id} inputs`, Infinity);
18507
18514
  if (Array.isArray(step.inputs)) {
18508
18515
  for (const [inputIndex, input] of step.inputs.entries())
18509
18516
  validateReference(input, `step ${id} inputs[${inputIndex}]`);
@@ -18525,12 +18532,7 @@ function validateExec(value, location, options) {
18525
18532
  return;
18526
18533
  const exec = record(value, location);
18527
18534
  keys(exec, ["command", "cwd", "passEnv"], location);
18528
- stringList(exec.command, `${location}.command`, WORKFLOW_MAX_EXEC_ARGV, false);
18529
- for (const [index, argument] of exec.command.entries()) {
18530
- if (utf8Bytes(argument) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
18531
- fail2(`${location}.command[${index}] exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes`);
18532
- }
18533
- }
18535
+ stringList(exec.command, `${location}.command`, Infinity, false);
18534
18536
  try {
18535
18537
  rejectNulInArgv(exec.command);
18536
18538
  } catch (cause) {
@@ -18538,9 +18540,6 @@ function validateExec(value, location, options) {
18538
18540
  }
18539
18541
  optionalString2(exec.cwd, `${location}.cwd`);
18540
18542
  if (exec.cwd !== undefined) {
18541
- if (exec.cwd.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
18542
- fail2(`${location}.cwd exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters`);
18543
- }
18544
18543
  try {
18545
18544
  exec.cwd = canonicalizeWorkflowWorkingDirectory(exec.cwd, options.workspaceRoot);
18546
18545
  } catch (cause) {
@@ -18548,7 +18547,7 @@ function validateExec(value, location, options) {
18548
18547
  }
18549
18548
  }
18550
18549
  if (exec.passEnv !== undefined) {
18551
- stringList(exec.passEnv, `${location}.passEnv`, WORKFLOW_MAX_EXEC_PASS_ENV, false);
18550
+ stringList(exec.passEnv, `${location}.passEnv`, Infinity, false);
18552
18551
  }
18553
18552
  if (Array.isArray(exec.passEnv)) {
18554
18553
  for (const name of exec.passEnv) {
@@ -18599,8 +18598,8 @@ function validateRetry(value, location) {
18599
18598
  return;
18600
18599
  const retry = record(value, location);
18601
18600
  keys(retry, ["max", "on"], location);
18602
- if (!Number.isSafeInteger(retry.max) || retry.max < 0 || retry.max > WORKFLOW_MAX_RETRIES) {
18603
- fail2(`${location}.max must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}`);
18601
+ if (!Number.isSafeInteger(retry.max) || retry.max < 0) {
18602
+ fail2(`${location}.max must be a non-negative integer`);
18604
18603
  }
18605
18604
  stringList(retry.on, `${location}.on`, PROGRAM_RETRY_REASONS.length, false);
18606
18605
  for (const reason of retry.on) {
@@ -18630,8 +18629,8 @@ function validateRoute(value, location) {
18630
18629
  keys(route, ["input", "branches", "defaultStepId"], location);
18631
18630
  nonEmptyString2(route.input, `${location}.input`);
18632
18631
  validateReference(route.input, `${location}.input`);
18633
- if (!Array.isArray(route.branches) || route.branches.length === 0 || route.branches.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
18634
- fail2(`${location}.branches must contain 1 through ${WORKFLOW_MAX_ROUTE_BRANCHES} entries`);
18632
+ if (!Array.isArray(route.branches) || route.branches.length === 0) {
18633
+ fail2(`${location}.branches must be a non-empty array`);
18635
18634
  }
18636
18635
  const matches = new Set;
18637
18636
  for (const [index, value2] of route.branches.entries()) {
@@ -18651,8 +18650,8 @@ function validateGate(value, location) {
18651
18650
  return;
18652
18651
  const gate = record(value, location);
18653
18652
  keys(gate, ["maxLoops", "rubric"], location);
18654
- if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1 || gate.maxLoops > WORKFLOW_MAX_GATE_LOOPS)) {
18655
- fail2(`${location}.maxLoops must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}`);
18653
+ if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1)) {
18654
+ fail2(`${location}.maxLoops must be an integer of at least 1`);
18656
18655
  }
18657
18656
  optionalString2(gate.rubric, `${location}.rubric`);
18658
18657
  }
@@ -18685,8 +18684,8 @@ function validateParams(value) {
18685
18684
  if (value === undefined)
18686
18685
  return;
18687
18686
  const params = record(value, "params");
18688
- if (Object.keys(params).length === 0 || Object.keys(params).length > WORKFLOW_MAX_PARAMS) {
18689
- fail2(`params must contain 1 through ${WORKFLOW_MAX_PARAMS} entries`);
18687
+ if (Object.keys(params).length === 0) {
18688
+ fail2(`params must contain at least one entry`);
18690
18689
  }
18691
18690
  for (const [name, schema] of Object.entries(params)) {
18692
18691
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18698,8 +18697,8 @@ function validateOutputs(value) {
18698
18697
  if (value === undefined)
18699
18698
  return;
18700
18699
  const outputs = record(value, "outputs");
18701
- if (Object.keys(outputs).length === 0 || Object.keys(outputs).length > WORKFLOW_MAX_OUTPUTS) {
18702
- fail2(`outputs must contain 1 through ${WORKFLOW_MAX_OUTPUTS} entries`);
18700
+ if (Object.keys(outputs).length === 0) {
18701
+ fail2(`outputs must contain at least one entry`);
18703
18702
  }
18704
18703
  for (const [name, declaration] of Object.entries(outputs)) {
18705
18704
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18722,9 +18721,6 @@ function validateBudget(value) {
18722
18721
  fail2(`budget.${key} must be a positive integer`);
18723
18722
  }
18724
18723
  }
18725
- if (typeof budget.maxUnits === "number" && budget.maxUnits > WORKFLOW_MAX_MAP_EXPANSION) {
18726
- fail2(`budget.maxUnits must be at most ${WORKFLOW_MAX_MAP_EXPANSION}`);
18727
- }
18728
18724
  }
18729
18725
  function validateLlm(value, location) {
18730
18726
  if (value === undefined)
@@ -19308,12 +19304,6 @@ function checkXrefs(value, line, errors2) {
19308
19304
  }
19309
19305
  }
19310
19306
  function checkResourceLimits(draft, errors2) {
19311
- if (draft.steps.length > WORKFLOW_MAX_STEPS) {
19312
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_STEPS} steps.` });
19313
- }
19314
- if (Object.keys(draft.params ?? {}).length > WORKFLOW_MAX_PARAMS) {
19315
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_PARAMS} parameters.` });
19316
- }
19317
19307
  for (const step of draft.steps) {
19318
19308
  if (step.instructions && utf8Bytes(step.instructions.text) > WORKFLOW_MAX_INSTRUCTION_BYTES) {
19319
19309
  errors2.push({
@@ -19675,9 +19665,6 @@ function parseParams(ctx, raw) {
19675
19665
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19676
19666
  return;
19677
19667
  }
19678
- if (Object.keys(raw).length > WORKFLOW_MAX_PARAMS) {
19679
- ctx.err(["params"], `"params" must contain at most ${WORKFLOW_MAX_PARAMS} entries.`);
19680
- }
19681
19668
  const params = {};
19682
19669
  for (const [paramName, value] of Object.entries(raw)) {
19683
19670
  if (!INPUT_NAME_PATTERN.test(paramName)) {
@@ -19703,9 +19690,6 @@ function parseOutputs(ctx, raw) {
19703
19690
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19704
19691
  return;
19705
19692
  }
19706
- if (Object.keys(raw).length > WORKFLOW_MAX_OUTPUTS) {
19707
- ctx.err(["outputs"], `"outputs" must contain at most ${WORKFLOW_MAX_OUTPUTS} entries.`);
19708
- }
19709
19693
  const outputs = {};
19710
19694
  for (const [outputName, value] of Object.entries(raw)) {
19711
19695
  const path13 = ["outputs", outputName];
@@ -19797,10 +19781,10 @@ function parseBudget(ctx, raw) {
19797
19781
  }
19798
19782
  }
19799
19783
  if (raw.max_units !== undefined) {
19800
- if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1 && raw.max_units <= WORKFLOW_MAX_MAP_EXPANSION) {
19784
+ if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
19801
19785
  budget.maxUnits = raw.max_units;
19802
19786
  } else {
19803
- ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer from 1 through ${WORKFLOW_MAX_MAP_EXPANSION}.`);
19787
+ ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer >= 1.`);
19804
19788
  }
19805
19789
  }
19806
19790
  return Object.keys(budget).length > 0 ? budget : undefined;
@@ -19810,9 +19794,6 @@ function parseSteps(ctx, raw) {
19810
19794
  ctx.err(["steps"], `"steps" is required and must be a list with at least one step.`);
19811
19795
  return [];
19812
19796
  }
19813
- if (raw.length > WORKFLOW_MAX_STEPS) {
19814
- ctx.err(["steps"], `"steps" must contain at most ${WORKFLOW_MAX_STEPS} entries.`);
19815
- }
19816
19797
  const idIndex = new Map;
19817
19798
  raw.forEach((rawStep, index) => {
19818
19799
  if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
@@ -19983,10 +19964,6 @@ function parseExecPassEnv(ctx, raw, path13, stepLabel) {
19983
19964
  ctx.err(path13, `${stepLabel} "exec.pass_env" must be a non-empty list of environment variable NAMES to copy through from ` + `akm's own environment, e.g. pass_env: [CARGO_HOME]. Values never appear here — use "env:" bindings for those.`);
19984
19965
  return;
19985
19966
  }
19986
- if (raw.length > WORKFLOW_MAX_EXEC_PASS_ENV) {
19987
- ctx.err(path13, `${stepLabel} "exec.pass_env" must have at most ${WORKFLOW_MAX_EXEC_PASS_ENV} entries. A command needing ` + `more than that should use explicit named "env:" bindings instead.`);
19988
- return;
19989
- }
19990
19967
  const names = [];
19991
19968
  for (const [index, entry] of raw.entries()) {
19992
19969
  if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
@@ -20006,10 +19983,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
20006
19983
  ctx.err(path13, `${stepLabel} "exec" requires "command": a non-empty argv list, e.g. command: ["bun", "run", "test:unit"]. ` + `A single shell string is not accepted — the command is spawned directly, never through a shell.`);
20007
19984
  return;
20008
19985
  }
20009
- if (raw.length > WORKFLOW_MAX_EXEC_ARGV) {
20010
- ctx.err(path13, `${stepLabel} "exec.command" must have at most ${WORKFLOW_MAX_EXEC_ARGV} entries.`);
20011
- return;
20012
- }
20013
19986
  const argv = [];
20014
19987
  for (const [index, entry] of raw.entries()) {
20015
19988
  if (typeof entry !== "string" || entry === "") {
@@ -20020,10 +19993,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
20020
19993
  ctx.err([...path13, index], `${stepLabel} "exec.command[${index}]" may not contain NUL bytes.`);
20021
19994
  return;
20022
19995
  }
20023
- if (utf8Bytes(entry) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
20024
- ctx.err(path13, `${stepLabel} "exec.command[${index}]" exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes.`);
20025
- return;
20026
- }
20027
19996
  argv.push(entry);
20028
19997
  }
20029
19998
  return argv;
@@ -20036,10 +20005,6 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
20036
20005
  return;
20037
20006
  }
20038
20007
  const value = raw.trim();
20039
- if (value.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
20040
- ctx.err(path13, `${stepLabel} "exec.cwd" exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters.`);
20041
- return;
20042
- }
20043
20008
  if (!isContainedRelativePath(value)) {
20044
20009
  ctx.err(path13, `${stepLabel} "exec.cwd" (${JSON.stringify(value)}) must be a RELATIVE path inside the unit's working ` + `directory — absolute paths, Windows drive letters, "~", and ".." segments are rejected.`);
20045
20010
  return;
@@ -20073,10 +20038,10 @@ function parseMap(ctx, raw, path13, stepLabel) {
20073
20038
  }
20074
20039
  let concurrency;
20075
20040
  if (raw.concurrency !== undefined) {
20076
- if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0 && raw.concurrency <= WORKFLOW_MAX_CONCURRENCY) {
20077
- concurrency = raw.concurrency;
20041
+ if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
20042
+ concurrency = Math.min(raw.concurrency, WORKFLOW_MAX_CONCURRENCY);
20078
20043
  } else {
20079
- ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}.`);
20044
+ ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
20080
20045
  }
20081
20046
  }
20082
20047
  const reducer = parseEnumField(ctx, raw.reducer, [...path13, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
@@ -20108,9 +20073,6 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20108
20073
  if (!Array.isArray(raw.when) || raw.when.length === 0) {
20109
20074
  ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
20110
20075
  } else {
20111
- if (raw.when.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
20112
- ctx.err(whenPath, `${stepLabel} "when" must contain at most ${WORKFLOW_MAX_ROUTE_BRANCHES} branches.`);
20113
- }
20114
20076
  const seenMatches = new Map;
20115
20077
  raw.when.forEach((branch, i) => {
20116
20078
  const branchPath = [...whenPath, i];
@@ -20166,9 +20128,6 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20166
20128
  ctx.err(path13, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
20167
20129
  return;
20168
20130
  }
20169
- if (raw.length > WORKFLOW_MAX_INPUTS) {
20170
- ctx.err(path13, `${stepLabel} "inputs" must contain at most ${WORKFLOW_MAX_INPUTS} entries.`);
20171
- }
20172
20131
  const out = [];
20173
20132
  const seen = new Set;
20174
20133
  raw.forEach((entry, i) => {
@@ -20195,10 +20154,10 @@ function parseGate(ctx, raw, path13, stepLabel) {
20195
20154
  checkUnknownKeys(ctx, raw, path13, GATE_KEYS, `${stepLabel} "gate"`);
20196
20155
  const gate = {};
20197
20156
  if (raw.max_loops !== undefined) {
20198
- if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1 && raw.max_loops <= WORKFLOW_MAX_GATE_LOOPS) {
20157
+ if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
20199
20158
  gate.maxLoops = raw.max_loops;
20200
20159
  } else {
20201
- ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}.`);
20160
+ ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer of at least 1.`);
20202
20161
  }
20203
20162
  }
20204
20163
  return gate;
@@ -20224,8 +20183,8 @@ function parseRetry(ctx, raw, path13, stepLabel) {
20224
20183
  }
20225
20184
  checkUnknownKeys(ctx, raw, path13, RETRY_KEYS, `${stepLabel} "retry"`);
20226
20185
  let ok = true;
20227
- if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0 && raw.max <= WORKFLOW_MAX_RETRIES)) {
20228
- ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
20186
+ if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
20187
+ ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
20229
20188
  ok = false;
20230
20189
  }
20231
20190
  const on = [];
@@ -21842,6 +21801,8 @@ function indexDocumentFromEntry(entry, base3, rendererName) {
21842
21801
  doc.tags = entry.tags;
21843
21802
  if (entry.content !== undefined)
21844
21803
  doc.content = entry.content;
21804
+ if (entry.contentTruncated !== undefined)
21805
+ doc.contentTruncated = entry.contentTruncated;
21845
21806
  if (entry.aliases !== undefined)
21846
21807
  doc.aliases = entry.aliases;
21847
21808
  if (entry.searchHints !== undefined)
@@ -23811,7 +23772,7 @@ function withLockOperationMutex(lockPath, run) {
23811
23772
  db.exec("BEGIN IMMEDIATE");
23812
23773
  began = db.inTransaction;
23813
23774
  if (!began)
23814
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2 ** attempt);
23775
+ sleepSync(2 ** attempt);
23815
23776
  }
23816
23777
  if (!began)
23817
23778
  throw new Error(`Could not acquire lock operation mutex for ${lockPath}.`);
@@ -23974,7 +23935,7 @@ function extractHolderPid(content) {
23974
23935
  // src/core/config/config-io.ts
23975
23936
  function readConfigText(configPath) {
23976
23937
  try {
23977
- return readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file");
23938
+ return readTextFile(configPath, "Config file");
23978
23939
  } catch (err) {
23979
23940
  if (err.code === "ENOENT")
23980
23941
  return;
@@ -28081,9 +28042,6 @@ var ExtraParamsSchema = exports_external.record(exports_external.unknown()).supe
28081
28042
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: issue.path, message: issue.message });
28082
28043
  }
28083
28044
  });
28084
- var LlmCapabilitiesSchema = exports_external.object({
28085
- structuredOutput: exports_external.boolean().optional()
28086
- }).passthrough();
28087
28045
  var LlmInvocationOverridesSchema = exports_external.object({
28088
28046
  temperature: exports_external.number().finite().optional(),
28089
28047
  maxTokens: positiveInt.optional(),
@@ -28139,15 +28097,13 @@ var LlmConnectionConfigSchema = exports_external.object({
28139
28097
  maxTokens: positiveInt.optional(),
28140
28098
  timeoutMs: timeoutMsField,
28141
28099
  concurrency: positiveInt.optional(),
28142
- capabilities: LlmCapabilitiesSchema.optional(),
28100
+ supportsJsonSchema: exports_external.boolean().optional(),
28143
28101
  extraParams: ExtraParamsSchema.optional(),
28144
28102
  contextLength: positiveInt.optional(),
28145
28103
  enableThinking: exports_external.boolean().optional(),
28146
28104
  reasoningEffort: nonEmptyString3.optional()
28147
28105
  }).passthrough();
28148
- var LlmProfileConfigSchema = LlmConnectionConfigSchema.extend({
28149
- supportsJsonSchema: exports_external.boolean().optional()
28150
- }).passthrough();
28106
+ var LlmProfileConfigSchema = LlmConnectionConfigSchema.passthrough();
28151
28107
  var AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
28152
28108
  var LlmEngineSchema = exports_external.object({
28153
28109
  kind: exports_external.literal("llm"),
@@ -28159,7 +28115,6 @@ var LlmEngineSchema = exports_external.object({
28159
28115
  maxTokens: positiveInt.optional(),
28160
28116
  timeoutMs: timeoutMsField,
28161
28117
  concurrency: positiveInt.optional(),
28162
- supportsJsonSchema: exports_external.boolean().optional(),
28163
28118
  extraParams: ExtraParamsSchema.optional(),
28164
28119
  contextLength: positiveInt.optional(),
28165
28120
  enableThinking: exports_external.boolean().optional(),
@@ -28189,7 +28144,6 @@ var AgentEngineSchema = exports_external.object({
28189
28144
  "temperature",
28190
28145
  "maxTokens",
28191
28146
  "concurrency",
28192
- "supportsJsonSchema",
28193
28147
  "extraParams",
28194
28148
  "contextLength",
28195
28149
  "enableThinking",
@@ -28555,7 +28509,7 @@ var SearchGraphBoostSchema = exports_external.object({
28555
28509
  hopBoostPerEntity: nonNegativeNumber.optional(),
28556
28510
  hopBoostCap: nonNegativeNumber.optional(),
28557
28511
  maxHops: positiveInt.max(3).optional(),
28558
- confidenceMode: exports_external.enum(["off", "blend", "multiply"]).default("blend").optional(),
28512
+ confidenceMode: exports_external.enum(["blend"]).default("blend").optional(),
28559
28513
  confidenceWeight: exports_external.number().finite().min(0).max(1).default(0.2).optional()
28560
28514
  }).passthrough();
28561
28515
  var SearchConfigSchema = exports_external.object({
@@ -28892,6 +28846,43 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
28892
28846
  }
28893
28847
  });
28894
28848
 
28849
+ // src/core/config/config-version-shim.ts
28850
+ var KNOWN_OLD_CONFIG_VERSIONS = ["0.0.1"];
28851
+ function isKnownOldConfigVersion(value) {
28852
+ return typeof value === "string" && KNOWN_OLD_CONFIG_VERSIONS.includes(value);
28853
+ }
28854
+ function upgradeFrom080(raw) {
28855
+ const { defaultEngine, defaults, ...rest } = raw;
28856
+ if (typeof defaultEngine !== "string" || defaultEngine.length === 0) {
28857
+ return { ...rest, ...defaults !== undefined ? { defaults } : {}, configVersion: CURRENT_CONFIG_VERSION };
28858
+ }
28859
+ const existingDefaults = defaults !== null && typeof defaults === "object" ? defaults : {};
28860
+ return {
28861
+ ...rest,
28862
+ configVersion: CURRENT_CONFIG_VERSION,
28863
+ defaults: { llmEngine: defaultEngine, ...existingDefaults }
28864
+ };
28865
+ }
28866
+ var CONFIG_VERSION_UPGRADES = {
28867
+ "0.0.1": upgradeFrom080
28868
+ };
28869
+ function unsupportedConfigVersionError(rawVersion, sourcePath) {
28870
+ const where = sourcePath ? ` at ${sourcePath}` : "";
28871
+ const supported = [CURRENT_CONFIG_VERSION, ...KNOWN_OLD_CONFIG_VERSIONS].map((v) => `"${v}"`).join(", ");
28872
+ return new ConfigError(`Unsupported configVersion${where}: got ${JSON.stringify(rawVersion)}, expected one of ${supported}.`, "UNSUPPORTED_CONFIG_VERSION", "Recreate engines and improve.strategies manually for AKM 0.9.0; profile-based configuration is not translated automatically.");
28873
+ }
28874
+ function upgradeConfigVersion(raw, sourcePath) {
28875
+ const version = raw.configVersion;
28876
+ if (version === CURRENT_CONFIG_VERSION)
28877
+ return raw;
28878
+ if (isKnownOldConfigVersion(version)) {
28879
+ const upgraded = CONFIG_VERSION_UPGRADES[version](raw);
28880
+ warn(`Config${sourcePath ? ` at ${sourcePath}` : ""} uses configVersion "${version}" — auto-upgraded to ${CURRENT_CONFIG_VERSION} in memory; the next config write (e.g. \`akm config set\`) persists this and silences the warning.`);
28881
+ return upgraded;
28882
+ }
28883
+ throw unsupportedConfigVersionError(version, sourcePath);
28884
+ }
28885
+
28895
28886
  // src/core/config/deep-merge.ts
28896
28887
  var UNSAFE_KEYS3 = new Set(["__proto__", "constructor", "prototype"]);
28897
28888
  function isPlainObject4(value) {
@@ -28982,10 +28973,7 @@ function loadUserConfig() {
28982
28973
  return finalConfig;
28983
28974
  }
28984
28975
  function parseAndValidateConfigText(text, sourcePath) {
28985
- const parsedRaw = parseConfigText(text, sourcePath);
28986
- if (parsedRaw.configVersion !== CURRENT_CONFIG_VERSION) {
28987
- throw new ConfigError(`Unsupported configVersion${sourcePath ? ` at ${sourcePath}` : ""}: expected "${CURRENT_CONFIG_VERSION}".`, "UNSUPPORTED_CONFIG_VERSION", "Recreate engines and improve.strategies manually for AKM 0.9.0; profile-based configuration is not translated automatically.");
28988
- }
28976
+ const parsedRaw = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
28989
28977
  const { config: raw, lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28990
28978
  const where = sourcePath ? ` at ${sourcePath}` : "";
28991
28979
  if (conflicts.length > 0) {
@@ -29063,8 +29051,7 @@ function withMaintenanceStartBarrier(run) {
29063
29051
 
29064
29052
  // src/indexer/index-writer-lock.ts
29065
29053
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
29066
- var INDEX_WRITER_LOCK_STALE_AFTER_MS = 12 * 60 * 60 * 1000;
29067
- var DEFAULT_INDEX_WRITER_MAX_WAIT_MS = 10 * 60 * 1000;
29054
+ var DEFAULT_ASSET_MUTATION_MAX_WAIT_MS = 10 * 60 * 1000;
29068
29055
  var leaseContext = new AsyncLocalStorage2;
29069
29056
 
29070
29057
  // src/integrations/lockfile.ts
@@ -29538,32 +29525,18 @@ function contained2(root, candidate) {
29538
29525
  const relative = path31.relative(root, candidate);
29539
29526
  return relative === "" || !relative.startsWith("..") && !path31.isAbsolute(relative);
29540
29527
  }
29541
- function identity3(filePath, kind) {
29542
- const stat = fs26.lstatSync(filePath, { bigint: true });
29543
- const valid = kind === "file" ? stat.isFile() : stat.isDirectory();
29544
- if (stat.isSymbolicLink() || !valid)
29545
- throw migrationError(`${filePath} must be a real ${kind}.`);
29546
- if (kind === "file" && stat.nlink !== 1n)
29547
- throw migrationError(`${filePath} must not be hard-linked.`);
29548
- return Object.freeze({
29549
- realPath: fs26.realpathSync(filePath),
29550
- device: stat.dev.toString(),
29551
- inode: stat.ino.toString(),
29552
- linkCount: stat.nlink.toString(),
29553
- changeTimeNs: stat.ctimeNs.toString()
29554
- });
29555
- }
29556
- function sameIdentity2(left, right) {
29557
- return left.realPath === right.realPath && left.device === right.device && left.inode === right.inode && left.linkCount === right.linkCount && left.changeTimeNs === right.changeTimeNs;
29528
+ function realDirectory(filePath) {
29529
+ const stat = fs26.lstatSync(filePath);
29530
+ if (stat.isSymbolicLink() || !stat.isDirectory())
29531
+ throw migrationError(`${filePath} must be a real directory.`);
29532
+ return fs26.realpathSync(filePath);
29558
29533
  }
29559
29534
  function snapshot(filePath) {
29560
- const before = identity3(filePath, "file");
29561
29535
  const stat = fs26.lstatSync(filePath);
29536
+ if (stat.isSymbolicLink() || !stat.isFile())
29537
+ throw migrationError(`${filePath} must be a real file.`);
29562
29538
  const bytes = fs26.readFileSync(filePath);
29563
- const after = identity3(filePath, "file");
29564
- if (!sameIdentity2(before, after))
29565
- throw migrationError(`${filePath} changed while it was read.`);
29566
- return Object.freeze({ bytes, mode: stat.mode & 511, identity: after });
29539
+ return Object.freeze({ bytes, mode: stat.mode & 511 });
29567
29540
  }
29568
29541
  function writable(filePath) {
29569
29542
  try {
@@ -29574,10 +29547,9 @@ function writable(filePath) {
29574
29547
  }
29575
29548
  }
29576
29549
  function walkTasks(root, tasksDir, out) {
29577
- const rootIdentity = identity3(root.root, "directory");
29578
- const bundleIdentity = identity3(root.bundleRoot ?? root.root, "directory");
29579
- const physicalRoot = rootIdentity.realPath;
29580
- if (!contained2(bundleIdentity.realPath, physicalRoot)) {
29550
+ const physicalRoot = realDirectory(root.root);
29551
+ const physicalBundleRoot = realDirectory(root.bundleRoot ?? root.root);
29552
+ if (!contained2(physicalBundleRoot, physicalRoot)) {
29581
29553
  throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
29582
29554
  }
29583
29555
  const visit2 = (directory) => {
@@ -29603,12 +29575,7 @@ function walkTasks(root, tasksDir, out) {
29603
29575
  mode: current.mode,
29604
29576
  writable: root.writable,
29605
29577
  onDiskWritable: writable(candidate) && writable(parent) && (current.mode & 146) !== 0,
29606
- containmentRoot: physicalRoot,
29607
- inspectionIdentity: Object.freeze({
29608
- file: current.identity,
29609
- root: rootIdentity,
29610
- bundleRoot: bundleIdentity
29611
- })
29578
+ containmentRoot: physicalRoot
29612
29579
  });
29613
29580
  }
29614
29581
  };
@@ -29672,17 +29639,9 @@ function assertUnchanged(change) {
29672
29639
  if (!current.bytes.equals(change.before) || current.mode !== change.mode) {
29673
29640
  throw migrationError(`${change.filePath} changed after preview; no task files were replaced.`);
29674
29641
  }
29675
- const planned = change.inspectionIdentity?.file;
29676
- if (planned && !sameIdentity2(planned, current.identity)) {
29677
- throw migrationError(`${change.filePath} identity changed after preview; no task files were replaced.`);
29678
- }
29679
29642
  return current;
29680
29643
  }
29681
29644
  function applyTaskToV3MigrationPlan(plan, options) {
29682
- const blocked3 = plan.files.filter((file) => file.status === "blocked");
29683
- if (blocked3.length > 0) {
29684
- throw migrationError(`plan is blocked: ${blocked3.map((file) => `${file.filePath} (${file.reason})`).join(", ")}. No files were written.`);
29685
- }
29686
29645
  const changes = plan.files.filter((file) => file.status === "changed");
29687
29646
  for (const change of changes) {
29688
29647
  assertUnchanged(change);
@@ -29725,32 +29684,18 @@ function contained3(root, candidate) {
29725
29684
  const relative = path32.relative(root, candidate);
29726
29685
  return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
29727
29686
  }
29728
- function identity4(filePath, kind) {
29729
- const stat = fs27.lstatSync(filePath, { bigint: true });
29730
- const valid = kind === "file" ? stat.isFile() : stat.isDirectory();
29731
- if (stat.isSymbolicLink() || !valid)
29732
- throw migrationError2(`${filePath} must be a real ${kind}.`);
29733
- if (kind === "file" && stat.nlink !== 1n)
29734
- throw migrationError2(`${filePath} must not be hard-linked.`);
29735
- return Object.freeze({
29736
- realPath: fs27.realpathSync(filePath),
29737
- device: stat.dev.toString(),
29738
- inode: stat.ino.toString(),
29739
- linkCount: stat.nlink.toString(),
29740
- changeTimeNs: stat.ctimeNs.toString()
29741
- });
29742
- }
29743
- function sameIdentity3(left, right) {
29744
- return left.realPath === right.realPath && left.device === right.device && left.inode === right.inode && left.linkCount === right.linkCount && left.changeTimeNs === right.changeTimeNs;
29687
+ function realDirectory2(filePath) {
29688
+ const stat = fs27.lstatSync(filePath);
29689
+ if (stat.isSymbolicLink() || !stat.isDirectory())
29690
+ throw migrationError2(`${filePath} must be a real directory.`);
29691
+ return fs27.realpathSync(filePath);
29745
29692
  }
29746
29693
  function snapshot2(filePath) {
29747
- const before = identity4(filePath, "file");
29748
29694
  const stat = fs27.lstatSync(filePath);
29695
+ if (stat.isSymbolicLink() || !stat.isFile())
29696
+ throw migrationError2(`${filePath} must be a real file.`);
29749
29697
  const bytes = fs27.readFileSync(filePath);
29750
- const after = identity4(filePath, "file");
29751
- if (!sameIdentity3(before, after))
29752
- throw migrationError2(`${filePath} changed while it was read.`);
29753
- return Object.freeze({ bytes, mode: stat.mode & 511, identity: after });
29698
+ return Object.freeze({ bytes, mode: stat.mode & 511 });
29754
29699
  }
29755
29700
  function writable2(filePath) {
29756
29701
  try {
@@ -29761,10 +29706,9 @@ function writable2(filePath) {
29761
29706
  }
29762
29707
  }
29763
29708
  function walkTasks2(root, tasksDir, out) {
29764
- const rootIdentity = identity4(root.root, "directory");
29765
- const bundleIdentity = identity4(root.bundleRoot ?? root.root, "directory");
29766
- const physicalRoot = rootIdentity.realPath;
29767
- if (!contained3(bundleIdentity.realPath, physicalRoot)) {
29709
+ const physicalRoot = realDirectory2(root.root);
29710
+ const physicalBundleRoot = realDirectory2(root.bundleRoot ?? root.root);
29711
+ if (!contained3(physicalBundleRoot, physicalRoot)) {
29768
29712
  throw migrationError2(`${root.root} resolves outside bundle ${root.bundleId}.`);
29769
29713
  }
29770
29714
  const visit2 = (directory) => {
@@ -29790,12 +29734,7 @@ function walkTasks2(root, tasksDir, out) {
29790
29734
  mode: current.mode,
29791
29735
  writable: root.writable,
29792
29736
  onDiskWritable: writable2(candidate) && writable2(parent) && (current.mode & 146) !== 0,
29793
- containmentRoot: physicalRoot,
29794
- inspectionIdentity: Object.freeze({
29795
- file: current.identity,
29796
- root: rootIdentity,
29797
- bundleRoot: bundleIdentity
29798
- })
29737
+ containmentRoot: physicalRoot
29799
29738
  });
29800
29739
  }
29801
29740
  };
@@ -29859,17 +29798,9 @@ function assertUnchanged2(change) {
29859
29798
  if (!current.bytes.equals(change.before) || current.mode !== change.mode) {
29860
29799
  throw migrationError2(`${change.filePath} changed after preview; no task files were replaced.`);
29861
29800
  }
29862
- const planned = change.inspectionIdentity?.file;
29863
- if (planned && !sameIdentity3(planned, current.identity)) {
29864
- throw migrationError2(`${change.filePath} identity changed after preview; no task files were replaced.`);
29865
- }
29866
29801
  return current;
29867
29802
  }
29868
29803
  function applyTaskToV4MigrationPlan(plan, options) {
29869
- const blocked3 = plan.files.filter((file) => file.status === "blocked");
29870
- if (blocked3.length > 0) {
29871
- throw migrationError2(`plan is blocked: ${blocked3.map((file) => `${file.filePath} (${file.reason})`).join(", ")}. No files were written.`);
29872
- }
29873
29804
  const changes = plan.files.filter((file) => file.status === "changed");
29874
29805
  for (const change of changes) {
29875
29806
  assertUnchanged2(change);
@@ -29918,9 +29849,14 @@ function existingDirectory(target) {
29918
29849
  throw cause;
29919
29850
  }
29920
29851
  }
29852
+ function reconcileDuplicateRoot(existing, candidate, sharedPath) {
29853
+ if (existing.writable === candidate.writable && existing.layout === candidate.layout)
29854
+ return;
29855
+ throw new ConfigError(`Bundles "${existing.bundleId}" and "${candidate.bundleId}" both resolve to the same directory ` + `(${sharedPath}) but disagree on writable/adapter settings. Two bundle ids configured for one ` + "directory must have matching settings, or one of them removed — run `akm bundle list` to see both.", "INVALID_CONFIG_FILE");
29856
+ }
29921
29857
  function taskRoots(config, resolutionBase = process.cwd()) {
29922
29858
  const sources = new Map((bundlesToSourceEntries(config) ?? []).map((source) => [source.name, source]));
29923
- const roots = [];
29859
+ const rootsByPath = new Map;
29924
29860
  for (const [bundleId, bundle] of Object.entries(config.bundles ?? {})) {
29925
29861
  if (bundle.enabled === false)
29926
29862
  continue;
@@ -29948,15 +29884,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
29948
29884
  }
29949
29885
  if (adapter !== "akm" && adapter !== "akm-task")
29950
29886
  continue;
29951
- roots.push({
29887
+ const candidate = {
29952
29888
  bundleId,
29953
29889
  root: componentRoot,
29954
29890
  bundleRoot,
29955
29891
  writable: component?.writable ?? resolveWritable(source),
29956
29892
  layout: adapter === "akm-task" ? "akm-task" : "akm-stash"
29957
- });
29893
+ };
29894
+ const existing = rootsByPath.get(componentRoot);
29895
+ if (existing) {
29896
+ reconcileDuplicateRoot(existing, candidate, componentRoot);
29897
+ continue;
29898
+ }
29899
+ rootsByPath.set(componentRoot, candidate);
29958
29900
  }
29959
- return roots;
29901
+ return [...rootsByPath.values()];
29960
29902
  }
29961
29903
  function summarize(plan) {
29962
29904
  const files = plan.files.map((file) => ({
@@ -30013,12 +29955,12 @@ async function runMigrationApply(options = {}) {
30013
29955
  }
30014
29956
  const result = withConfigLock(() => withMaintenanceStartBarrier(() => {
30015
29957
  const before = inspectCurrentTaskPlan();
30016
- if (before.result.status !== "ready")
29958
+ if (before.result.taskV3Migration.changed === 0)
30017
29959
  return before.result;
30018
29960
  const backupPath = path33.join(getDataDir(), "backups", "task-v3", `${Date.now()}-${randomUUID2()}`);
30019
29961
  const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
30020
29962
  const after = inspectCurrentTaskPlan().result;
30021
- if (after.status !== "current") {
29963
+ if (after.taskV3Migration.changed > 0) {
30022
29964
  throw new ConfigError("Task migration did not converge to task v3.", "INVALID_CONFIG_FILE");
30023
29965
  }
30024
29966
  return { ...after, backupPath, applied: applied.changed.length };
@@ -30076,12 +30018,12 @@ async function runTaskV4MigrationApply(options = {}) {
30076
30018
  }
30077
30019
  const result = withConfigLock(() => withMaintenanceStartBarrier(() => {
30078
30020
  const before = inspectCurrentTaskV4Plan();
30079
- if (before.result.status !== "ready")
30021
+ if (before.result.taskV4Migration.changed === 0)
30080
30022
  return before.result;
30081
30023
  const backupPath = path33.join(getDataDir(), "backups", "task-v4", `${Date.now()}-${randomUUID2()}`);
30082
30024
  const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
30083
30025
  const after = inspectCurrentTaskV4Plan().result;
30084
- if (after.status !== "current") {
30026
+ if (after.taskV4Migration.changed > 0) {
30085
30027
  throw new ConfigError("Task migration did not converge to task source v4.", "INVALID_CONFIG_FILE");
30086
30028
  }
30087
30029
  return { ...after, backupPath, applied: applied.changed.length };