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
@@ -9379,8 +9379,6 @@ function getRegistryIndexCacheDir() {
9379
9379
  }
9380
9380
 
9381
9381
  // src/core/common.ts
9382
- var MAX_CONFIG_FILE_BYTES = 1024 * 1024;
9383
- var MAX_LOCAL_METADATA_BYTES = 1024 * 1024;
9384
9382
  var MAX_LOCK_METADATA_BYTES = 64 * 1024;
9385
9383
  function readTextFileDescriptorWithLimit(fd, maxBytes, label = "File", displayPath = "(open file)") {
9386
9384
  const stat = fs.fstatSync(fd);
@@ -9402,10 +9400,13 @@ function readTextFileDescriptorWithLimit(fd, maxBytes, label = "File", displayPa
9402
9400
  }
9403
9401
  return buffer.subarray(0, total).toString("utf8");
9404
9402
  }
9405
- function readTextFileWithLimit(filePath, maxBytes, label = "File") {
9403
+ function readTextFile(filePath, label = "File") {
9406
9404
  const fd = fs.openSync(filePath, "r");
9407
9405
  try {
9408
- return readTextFileDescriptorWithLimit(fd, maxBytes, label, filePath);
9406
+ const stat = fs.fstatSync(fd);
9407
+ if (!stat.isFile())
9408
+ throw new ConfigError(`${label} is not a regular file: ${filePath}.`, "INVALID_CONFIG_FILE");
9409
+ return fs.readFileSync(fd, "utf8");
9409
9410
  } finally {
9410
9411
  fs.closeSync(fd);
9411
9412
  }
@@ -9505,6 +9506,8 @@ function asNonEmptyString(value) {
9505
9506
  return trimmed.length > 0 ? trimmed : undefined;
9506
9507
  }
9507
9508
  function isProcessAlive(pid) {
9509
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
9510
+ return false;
9508
9511
  try {
9509
9512
  process.kill(pid, 0);
9510
9513
  return true;
@@ -10066,11 +10069,13 @@ function makeStampHandler(command) {
10066
10069
  if (typeof result !== "object" || Array.isArray(result))
10067
10070
  return result;
10068
10071
  const obj = result;
10069
- if (obj.shape === undefined)
10070
- obj.shape = command;
10071
- if (obj.schemaVersion === undefined)
10072
- obj.schemaVersion = 1;
10073
- return obj;
10072
+ if (obj.shape !== undefined && obj.schemaVersion !== undefined)
10073
+ return obj;
10074
+ return {
10075
+ ...obj,
10076
+ shape: obj.shape ?? command,
10077
+ schemaVersion: obj.schemaVersion ?? 1
10078
+ };
10074
10079
  };
10075
10080
  }
10076
10081
  var PASSTHROUGH_COMMANDS = [
@@ -10110,6 +10115,7 @@ var PASSTHROUGH_COMMANDS = [
10110
10115
  "task-doctor",
10111
10116
  "task-explain",
10112
10117
  "task-history",
10118
+ "task-prune",
10113
10119
  "task-run",
10114
10120
  "task-sync",
10115
10121
  "task-sync-dry-run",
@@ -12946,8 +12952,17 @@ import path8 from "path";
12946
12952
  // src/core/warn.ts
12947
12953
  import fs4 from "fs";
12948
12954
  var quiet = false;
12955
+ var verbose = false;
12949
12956
  var logFilePath;
12950
12957
  var sinkOverride;
12958
+ function isVerbose() {
12959
+ const env = process.env.AKM_VERBOSE?.trim().toLowerCase();
12960
+ if (env === "1" || env === "true" || env === "yes" || env === "on")
12961
+ return true;
12962
+ if (env === "0" || env === "false" || env === "no" || env === "off")
12963
+ return false;
12964
+ return verbose;
12965
+ }
12951
12966
  function appendToLogFile(level, args) {
12952
12967
  if (!logFilePath)
12953
12968
  return;
@@ -12973,6 +12988,15 @@ function warn(...args) {
12973
12988
  console.warn(...args);
12974
12989
  }
12975
12990
  }
12991
+ function warnVerbose(...args) {
12992
+ if (sinkOverride) {
12993
+ sinkOverride("warnVerbose", args);
12994
+ return;
12995
+ }
12996
+ if (isVerbose()) {
12997
+ warn(...args);
12998
+ }
12999
+ }
12976
13000
 
12977
13001
  // src/indexer/passes/metadata.ts
12978
13002
  var SCOPE_KEYS = ["user", "agent", "run", "channel"];
@@ -13688,7 +13712,7 @@ function stripMarkdownLinkDestinations(text, nesting = 0) {
13688
13712
  }
13689
13713
  return visible;
13690
13714
  }
13691
- function projectMarkdownContent(body) {
13715
+ function projectMarkdownContent(body, truncationInfo) {
13692
13716
  const lines = body.split(/\r?\n/);
13693
13717
  const innerBlock = findInnerFrontmatterBlock(lines);
13694
13718
  const start = innerBlock && isFrontmatterShaped(lines, innerBlock) ? innerBlock.close + 1 : 0;
@@ -13734,6 +13758,8 @@ function projectMarkdownContent(body) {
13734
13758
  const text = projected.join(" ").replace(/\s+/g, " ").trim();
13735
13759
  if (!text)
13736
13760
  return;
13761
+ if (truncationInfo)
13762
+ truncationInfo.truncated = text.length > MARKDOWN_CONTENT_MAX_CHARS;
13737
13763
  return truncateUnicodeSafe(text, MARKDOWN_CONTENT_MAX_CHARS);
13738
13764
  }
13739
13765
  function applyPreContributorFields(entry, file, ctx, pkgMeta) {
@@ -13757,9 +13783,15 @@ function applyPreContributorFields(entry, file, ctx, pkgMeta) {
13757
13783
  applyWikiFrontmatter(entry, parsed.data);
13758
13784
  applyProvenanceFrontmatter(entry, parsed.data);
13759
13785
  if (entry.type !== "env" && entry.type !== "session" && !hasSessionMemoryMarker(parsed.data, parsed.content)) {
13760
- const contentProjection = projectMarkdownContent(parsed.content);
13761
- if (contentProjection)
13786
+ const truncationInfo = { truncated: false };
13787
+ const contentProjection = projectMarkdownContent(parsed.content, truncationInfo);
13788
+ if (contentProjection) {
13762
13789
  entry.content = contentProjection;
13790
+ if (truncationInfo.truncated) {
13791
+ entry.contentTruncated = true;
13792
+ warnVerbose(`${file}: indexed content truncated to ${MARKDOWN_CONTENT_MAX_CHARS} chars`);
13793
+ }
13794
+ }
13763
13795
  }
13764
13796
  if (entry.type === "command") {
13765
13797
  const cmdParams = extractCommandParameters(parsed.content);
@@ -14850,25 +14882,13 @@ var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
14850
14882
  // src/workflows/resource-limits.ts
14851
14883
  var WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
14852
14884
  var WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
14853
- var WORKFLOW_MAX_STEPS = 256;
14854
- var WORKFLOW_MAX_PARAMS = 128;
14855
- var WORKFLOW_MAX_ROUTE_BRANCHES = 256;
14856
14885
  var WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
14857
14886
  var WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
14858
14887
  var WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
14859
- var WORKFLOW_MAX_MAP_EXPANSION = 1e4;
14860
- var WORKFLOW_MAX_INPUTS = 64;
14861
- var WORKFLOW_MAX_OUTPUTS = 64;
14862
14888
  var WORKFLOW_MAX_CONCURRENCY = 64;
14863
- var WORKFLOW_MAX_GATE_LOOPS = 100;
14864
- var WORKFLOW_MAX_RETRIES = 100;
14865
14889
  var WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
14866
14890
  var WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
14867
14891
  var WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
14868
- var WORKFLOW_MAX_EXEC_ARGV = 64;
14869
- var WORKFLOW_MAX_EXEC_ARG_BYTES = 4096;
14870
- var WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
14871
- var WORKFLOW_MAX_EXEC_PASS_ENV = 32;
14872
14892
  var WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
14873
14893
  var WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
14874
14894
  var EXEC_CONTEXT_LIMITS_POSIX = {
@@ -14886,13 +14906,13 @@ function jsonBytes(value) {
14886
14906
  var WORKFLOW_MAX_EMBEDDED_CHILD_PLAN_BYTES = 1024 * 1024;
14887
14907
 
14888
14908
  // src/tasks/source/bounded-document.ts
14889
- var TASK_V3_MAX_SOURCE_BYTES = 1024 * 1024;
14890
14909
  var TASK_V3_MAX_JSON_DEPTH = 64;
14891
14910
  var TASK_V3_MAX_JSON_NODES = 1e4;
14892
14911
  var TASK_V3_MAX_COLLECTION_ITEMS = 1024;
14893
14912
  var TASK_V3_MAX_OBJECT_KEYS = 256;
14894
14913
  var TASK_V3_MAX_STRING_BYTES = 256 * 1024;
14895
14914
  var TASK_V3_MAX_SCHEDULES = 64;
14915
+ var TASK_V3_MAX_REDACT_NAMES = 32;
14896
14916
  function own2(value, key) {
14897
14917
  return Object.hasOwn(value, key);
14898
14918
  }
@@ -15181,9 +15201,6 @@ function readBoundedTaskSourceYaml(input, options) {
15181
15201
  if (typeof input.yaml !== "string") {
15182
15202
  throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source must be a string.`, "TASK_SOURCE_INVALID");
15183
15203
  }
15184
- if (utf8Bytes2(input.yaml) > TASK_V3_MAX_SOURCE_BYTES) {
15185
- throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) resource limit.`, "TASK_SOURCE_INVALID");
15186
- }
15187
15204
  const lineCounter2 = new $LineCounter;
15188
15205
  let document;
15189
15206
  try {
@@ -15943,7 +15960,7 @@ function parseExecutionControls(input, ctx) {
15943
15960
  out.timeout = parseTimeoutTopLevel(input.timeout, ctx);
15944
15961
  if (own2(input, "redact")) {
15945
15962
  const names = parseStringArray(input.redact, ctx, ["redact"], {
15946
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
15963
+ max: TASK_V3_MAX_REDACT_NAMES,
15947
15964
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
15948
15965
  });
15949
15966
  if (new Set(names).size !== names.length)
@@ -15957,8 +15974,8 @@ function parseExecutionControls(input, ctx) {
15957
15974
  out.maxSteps = input.maxSteps;
15958
15975
  }
15959
15976
  if (own2(input, "maxRetries")) {
15960
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
15961
- sourceError(ctx, ["maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
15977
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
15978
+ sourceError(ctx, ["maxRetries"], "must be a non-negative safe integer.");
15962
15979
  }
15963
15980
  out.maxRetries = input.maxRetries;
15964
15981
  }
@@ -16018,9 +16035,6 @@ function parseInputDeclaration(name, raw, ctx) {
16018
16035
  function parseInputDeclarations(value, ctx) {
16019
16036
  const input = asRecord(value, ctx, ["inputs"]);
16020
16037
  const names = Object.keys(input);
16021
- if (names.length > WORKFLOW_MAX_PARAMS) {
16022
- sourceError(ctx, ["inputs"], `accepts at most ${WORKFLOW_MAX_PARAMS} declared inputs.`);
16023
- }
16024
16038
  const result = {};
16025
16039
  for (const name of names) {
16026
16040
  if (!INPUT_NAME_PATTERN.test(name)) {
@@ -16453,7 +16467,7 @@ function parseAkm(value, ctx) {
16453
16467
  out.timeout = parseTimeout(input.timeout, ctx);
16454
16468
  if (own2(input, "redact")) {
16455
16469
  const names = parseStringArray(input.redact, ctx, ["akm", "redact"], {
16456
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16470
+ max: TASK_V3_MAX_REDACT_NAMES,
16457
16471
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16458
16472
  });
16459
16473
  if (new Set(names).size !== names.length)
@@ -16467,8 +16481,8 @@ function parseAkm(value, ctx) {
16467
16481
  out.maxSteps = input.maxSteps;
16468
16482
  }
16469
16483
  if (own2(input, "maxRetries")) {
16470
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16471
- sourceError(ctx, ["akm", "maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16484
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16485
+ sourceError(ctx, ["akm", "maxRetries"], "must be a non-negative safe integer.");
16472
16486
  }
16473
16487
  out.maxRetries = input.maxRetries;
16474
16488
  }
@@ -16722,6 +16736,16 @@ var SHELL_ASSIGNMENT_WORD = /^[A-Za-z_][A-Za-z0-9_]*=/;
16722
16736
  function shellStableV2Executable(executable) {
16723
16737
  return executable === "akm" || executable.includes("/");
16724
16738
  }
16739
+ function skipEnvAssignmentPrefix(tokens) {
16740
+ if (tokens[0] !== "env")
16741
+ return { tokens, envWrapped: false };
16742
+ let index = 1;
16743
+ while (index < tokens.length && SHELL_ASSIGNMENT_WORD.test(tokens[index]))
16744
+ index += 1;
16745
+ if (index >= tokens.length)
16746
+ return { tokens, envWrapped: false };
16747
+ return { tokens: tokens.slice(index), envWrapped: true };
16748
+ }
16725
16749
  var KNOWN_PROMPT_REF_FAMILIES = new Set([
16726
16750
  "agents",
16727
16751
  "commands",
@@ -16742,11 +16766,6 @@ function hash(bytes) {
16742
16766
  return crypto.createHash("sha256").update(bytes).digest("hex");
16743
16767
  }
16744
16768
  function base(input) {
16745
- const inspectionIdentity = input.inspectionIdentity ? Object.freeze({
16746
- file: Object.freeze({ ...input.inspectionIdentity.file }),
16747
- root: Object.freeze({ ...input.inspectionIdentity.root }),
16748
- ...input.inspectionIdentity.bundleRoot ? { bundleRoot: Object.freeze({ ...input.inspectionIdentity.bundleRoot }) } : {}
16749
- }) : undefined;
16750
16769
  return {
16751
16770
  filePath: input.filePath,
16752
16771
  before: Buffer.from(input.bytes),
@@ -16754,8 +16773,7 @@ function base(input) {
16754
16773
  mode: input.mode,
16755
16774
  writable: input.writable,
16756
16775
  ...input.onDiskWritable !== undefined ? { onDiskWritable: input.onDiskWritable } : {},
16757
- ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {},
16758
- ...inspectionIdentity ? { inspectionIdentity } : {}
16776
+ ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {}
16759
16777
  };
16760
16778
  }
16761
16779
  function blocked(input, reason, detail) {
@@ -16781,9 +16799,6 @@ function optionalString(value, label) {
16781
16799
  return exactString(value, label);
16782
16800
  }
16783
16801
  function parseLegacyTaskYaml(input) {
16784
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
16785
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
16786
- }
16787
16802
  let source;
16788
16803
  try {
16789
16804
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -16831,7 +16846,7 @@ function validateCommonV2(data) {
16831
16846
  }
16832
16847
  }
16833
16848
  if (data.redact !== undefined && data.redact !== null) {
16834
- 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))) {
16849
+ 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))) {
16835
16850
  throw new Error("redact must contain only bounded environment variable names");
16836
16851
  }
16837
16852
  }
@@ -16957,8 +16972,8 @@ function migratedObject(data) {
16957
16972
  akm.maxSteps = data.maxSteps;
16958
16973
  }
16959
16974
  if (data.maxRetries !== undefined && data.maxRetries !== null) {
16960
- if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0 || data.maxRetries > WORKFLOW_MAX_RETRIES) {
16961
- throw new Error(`maxRetries must be from 0 through ${WORKFLOW_MAX_RETRIES}`);
16975
+ if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0) {
16976
+ throw new Error("maxRetries must be a non-negative integer");
16962
16977
  }
16963
16978
  akm.maxRetries = data.maxRetries;
16964
16979
  }
@@ -16991,8 +17006,9 @@ function migratedObject(data) {
16991
17006
  if (tokens.length === 0 || tokens.some((token) => !SAFE_V2_COMMAND_TOKEN.test(token))) {
16992
17007
  return "shell-operators-change-v2-literal-argv-semantics";
16993
17008
  }
16994
- const executable = tokens[0];
16995
- if (SHELL_ASSIGNMENT_WORD.test(executable) || !shellStableV2Executable(executable)) {
17009
+ const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(tokens);
17010
+ const executable = targetTokens[0];
17011
+ if (SHELL_ASSIGNMENT_WORD.test(executable) || !envWrapped && !shellStableV2Executable(executable)) {
16996
17012
  return "shell-command-resolution-changes-v2-literal-argv-semantics";
16997
17013
  }
16998
17014
  output.run = tokens.join(" ");
@@ -17186,11 +17202,6 @@ function causeMessage(cause) {
17186
17202
  return cause instanceof Error ? cause.message : String(cause);
17187
17203
  }
17188
17204
  function base2(input) {
17189
- const inspectionIdentity = input.inspectionIdentity ? Object.freeze({
17190
- file: Object.freeze({ ...input.inspectionIdentity.file }),
17191
- root: Object.freeze({ ...input.inspectionIdentity.root }),
17192
- ...input.inspectionIdentity.bundleRoot ? { bundleRoot: Object.freeze({ ...input.inspectionIdentity.bundleRoot }) } : {}
17193
- }) : undefined;
17194
17205
  return {
17195
17206
  filePath: input.filePath,
17196
17207
  before: Buffer.from(input.bytes),
@@ -17198,8 +17209,7 @@ function base2(input) {
17198
17209
  mode: input.mode,
17199
17210
  writable: input.writable,
17200
17211
  ...input.onDiskWritable !== undefined ? { onDiskWritable: input.onDiskWritable } : {},
17201
- ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {},
17202
- ...inspectionIdentity ? { inspectionIdentity } : {}
17212
+ ...input.containmentRoot ? { containmentRoot: input.containmentRoot } : {}
17203
17213
  };
17204
17214
  }
17205
17215
  function blocked2(input, reason, detail) {
@@ -17222,9 +17232,6 @@ function exactString2(value, label, nonempty = false) {
17222
17232
  return value;
17223
17233
  }
17224
17234
  function parseV3RawYaml(input) {
17225
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
17226
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
17227
- }
17228
17235
  let source;
17229
17236
  try {
17230
17237
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -18425,7 +18432,7 @@ function validateStep(value, jobId, index, stepIds, options) {
18425
18432
  }
18426
18433
  validateMap(step.map, `step ${id} map`);
18427
18434
  validateRoute(step.route, `step ${id} route`);
18428
- optionalStringList(step.inputs, `step ${id} inputs`, WORKFLOW_MAX_INPUTS);
18435
+ optionalStringList(step.inputs, `step ${id} inputs`, Infinity);
18429
18436
  if (Array.isArray(step.inputs)) {
18430
18437
  for (const [inputIndex, input] of step.inputs.entries())
18431
18438
  validateReference(input, `step ${id} inputs[${inputIndex}]`);
@@ -18447,12 +18454,7 @@ function validateExec(value, location, options) {
18447
18454
  return;
18448
18455
  const exec = record(value, location);
18449
18456
  keys(exec, ["command", "cwd", "passEnv"], location);
18450
- stringList(exec.command, `${location}.command`, WORKFLOW_MAX_EXEC_ARGV, false);
18451
- for (const [index, argument] of exec.command.entries()) {
18452
- if (utf8Bytes(argument) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
18453
- fail2(`${location}.command[${index}] exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes`);
18454
- }
18455
- }
18457
+ stringList(exec.command, `${location}.command`, Infinity, false);
18456
18458
  try {
18457
18459
  rejectNulInArgv(exec.command);
18458
18460
  } catch (cause) {
@@ -18460,9 +18462,6 @@ function validateExec(value, location, options) {
18460
18462
  }
18461
18463
  optionalString2(exec.cwd, `${location}.cwd`);
18462
18464
  if (exec.cwd !== undefined) {
18463
- if (exec.cwd.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
18464
- fail2(`${location}.cwd exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters`);
18465
- }
18466
18465
  try {
18467
18466
  exec.cwd = canonicalizeWorkflowWorkingDirectory(exec.cwd, options.workspaceRoot);
18468
18467
  } catch (cause) {
@@ -18470,7 +18469,7 @@ function validateExec(value, location, options) {
18470
18469
  }
18471
18470
  }
18472
18471
  if (exec.passEnv !== undefined) {
18473
- stringList(exec.passEnv, `${location}.passEnv`, WORKFLOW_MAX_EXEC_PASS_ENV, false);
18472
+ stringList(exec.passEnv, `${location}.passEnv`, Infinity, false);
18474
18473
  }
18475
18474
  if (Array.isArray(exec.passEnv)) {
18476
18475
  for (const name of exec.passEnv) {
@@ -18521,8 +18520,8 @@ function validateRetry(value, location) {
18521
18520
  return;
18522
18521
  const retry = record(value, location);
18523
18522
  keys(retry, ["max", "on"], location);
18524
- if (!Number.isSafeInteger(retry.max) || retry.max < 0 || retry.max > WORKFLOW_MAX_RETRIES) {
18525
- fail2(`${location}.max must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}`);
18523
+ if (!Number.isSafeInteger(retry.max) || retry.max < 0) {
18524
+ fail2(`${location}.max must be a non-negative integer`);
18526
18525
  }
18527
18526
  stringList(retry.on, `${location}.on`, PROGRAM_RETRY_REASONS.length, false);
18528
18527
  for (const reason of retry.on) {
@@ -18552,8 +18551,8 @@ function validateRoute(value, location) {
18552
18551
  keys(route, ["input", "branches", "defaultStepId"], location);
18553
18552
  nonEmptyString2(route.input, `${location}.input`);
18554
18553
  validateReference(route.input, `${location}.input`);
18555
- if (!Array.isArray(route.branches) || route.branches.length === 0 || route.branches.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
18556
- fail2(`${location}.branches must contain 1 through ${WORKFLOW_MAX_ROUTE_BRANCHES} entries`);
18554
+ if (!Array.isArray(route.branches) || route.branches.length === 0) {
18555
+ fail2(`${location}.branches must be a non-empty array`);
18557
18556
  }
18558
18557
  const matches = new Set;
18559
18558
  for (const [index, value2] of route.branches.entries()) {
@@ -18573,8 +18572,8 @@ function validateGate(value, location) {
18573
18572
  return;
18574
18573
  const gate = record(value, location);
18575
18574
  keys(gate, ["maxLoops", "rubric"], location);
18576
- if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1 || gate.maxLoops > WORKFLOW_MAX_GATE_LOOPS)) {
18577
- fail2(`${location}.maxLoops must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}`);
18575
+ if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1)) {
18576
+ fail2(`${location}.maxLoops must be an integer of at least 1`);
18578
18577
  }
18579
18578
  optionalString2(gate.rubric, `${location}.rubric`);
18580
18579
  }
@@ -18607,8 +18606,8 @@ function validateParams(value) {
18607
18606
  if (value === undefined)
18608
18607
  return;
18609
18608
  const params = record(value, "params");
18610
- if (Object.keys(params).length === 0 || Object.keys(params).length > WORKFLOW_MAX_PARAMS) {
18611
- fail2(`params must contain 1 through ${WORKFLOW_MAX_PARAMS} entries`);
18609
+ if (Object.keys(params).length === 0) {
18610
+ fail2(`params must contain at least one entry`);
18612
18611
  }
18613
18612
  for (const [name, schema] of Object.entries(params)) {
18614
18613
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18620,8 +18619,8 @@ function validateOutputs(value) {
18620
18619
  if (value === undefined)
18621
18620
  return;
18622
18621
  const outputs = record(value, "outputs");
18623
- if (Object.keys(outputs).length === 0 || Object.keys(outputs).length > WORKFLOW_MAX_OUTPUTS) {
18624
- fail2(`outputs must contain 1 through ${WORKFLOW_MAX_OUTPUTS} entries`);
18622
+ if (Object.keys(outputs).length === 0) {
18623
+ fail2(`outputs must contain at least one entry`);
18625
18624
  }
18626
18625
  for (const [name, declaration] of Object.entries(outputs)) {
18627
18626
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18644,9 +18643,6 @@ function validateBudget(value) {
18644
18643
  fail2(`budget.${key} must be a positive integer`);
18645
18644
  }
18646
18645
  }
18647
- if (typeof budget.maxUnits === "number" && budget.maxUnits > WORKFLOW_MAX_MAP_EXPANSION) {
18648
- fail2(`budget.maxUnits must be at most ${WORKFLOW_MAX_MAP_EXPANSION}`);
18649
- }
18650
18646
  }
18651
18647
  function validateLlm(value, location) {
18652
18648
  if (value === undefined)
@@ -19230,12 +19226,6 @@ function checkXrefs(value, line, errors2) {
19230
19226
  }
19231
19227
  }
19232
19228
  function checkResourceLimits(draft, errors2) {
19233
- if (draft.steps.length > WORKFLOW_MAX_STEPS) {
19234
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_STEPS} steps.` });
19235
- }
19236
- if (Object.keys(draft.params ?? {}).length > WORKFLOW_MAX_PARAMS) {
19237
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_PARAMS} parameters.` });
19238
- }
19239
19229
  for (const step of draft.steps) {
19240
19230
  if (step.instructions && utf8Bytes(step.instructions.text) > WORKFLOW_MAX_INSTRUCTION_BYTES) {
19241
19231
  errors2.push({
@@ -19597,9 +19587,6 @@ function parseParams(ctx, raw) {
19597
19587
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19598
19588
  return;
19599
19589
  }
19600
- if (Object.keys(raw).length > WORKFLOW_MAX_PARAMS) {
19601
- ctx.err(["params"], `"params" must contain at most ${WORKFLOW_MAX_PARAMS} entries.`);
19602
- }
19603
19590
  const params = {};
19604
19591
  for (const [paramName, value] of Object.entries(raw)) {
19605
19592
  if (!INPUT_NAME_PATTERN.test(paramName)) {
@@ -19625,9 +19612,6 @@ function parseOutputs(ctx, raw) {
19625
19612
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19626
19613
  return;
19627
19614
  }
19628
- if (Object.keys(raw).length > WORKFLOW_MAX_OUTPUTS) {
19629
- ctx.err(["outputs"], `"outputs" must contain at most ${WORKFLOW_MAX_OUTPUTS} entries.`);
19630
- }
19631
19615
  const outputs = {};
19632
19616
  for (const [outputName, value] of Object.entries(raw)) {
19633
19617
  const path13 = ["outputs", outputName];
@@ -19719,10 +19703,10 @@ function parseBudget(ctx, raw) {
19719
19703
  }
19720
19704
  }
19721
19705
  if (raw.max_units !== undefined) {
19722
- if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1 && raw.max_units <= WORKFLOW_MAX_MAP_EXPANSION) {
19706
+ if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
19723
19707
  budget.maxUnits = raw.max_units;
19724
19708
  } else {
19725
- ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer from 1 through ${WORKFLOW_MAX_MAP_EXPANSION}.`);
19709
+ ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer >= 1.`);
19726
19710
  }
19727
19711
  }
19728
19712
  return Object.keys(budget).length > 0 ? budget : undefined;
@@ -19732,9 +19716,6 @@ function parseSteps(ctx, raw) {
19732
19716
  ctx.err(["steps"], `"steps" is required and must be a list with at least one step.`);
19733
19717
  return [];
19734
19718
  }
19735
- if (raw.length > WORKFLOW_MAX_STEPS) {
19736
- ctx.err(["steps"], `"steps" must contain at most ${WORKFLOW_MAX_STEPS} entries.`);
19737
- }
19738
19719
  const idIndex = new Map;
19739
19720
  raw.forEach((rawStep, index) => {
19740
19721
  if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
@@ -19905,10 +19886,6 @@ function parseExecPassEnv(ctx, raw, path13, stepLabel) {
19905
19886
  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 \u2014 use "env:" bindings for those.`);
19906
19887
  return;
19907
19888
  }
19908
- if (raw.length > WORKFLOW_MAX_EXEC_PASS_ENV) {
19909
- 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.`);
19910
- return;
19911
- }
19912
19889
  const names = [];
19913
19890
  for (const [index, entry] of raw.entries()) {
19914
19891
  if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
@@ -19928,10 +19905,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
19928
19905
  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 \u2014 the command is spawned directly, never through a shell.`);
19929
19906
  return;
19930
19907
  }
19931
- if (raw.length > WORKFLOW_MAX_EXEC_ARGV) {
19932
- ctx.err(path13, `${stepLabel} "exec.command" must have at most ${WORKFLOW_MAX_EXEC_ARGV} entries.`);
19933
- return;
19934
- }
19935
19908
  const argv = [];
19936
19909
  for (const [index, entry] of raw.entries()) {
19937
19910
  if (typeof entry !== "string" || entry === "") {
@@ -19942,10 +19915,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
19942
19915
  ctx.err([...path13, index], `${stepLabel} "exec.command[${index}]" may not contain NUL bytes.`);
19943
19916
  return;
19944
19917
  }
19945
- if (utf8Bytes(entry) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
19946
- ctx.err(path13, `${stepLabel} "exec.command[${index}]" exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes.`);
19947
- return;
19948
- }
19949
19918
  argv.push(entry);
19950
19919
  }
19951
19920
  return argv;
@@ -19958,10 +19927,6 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
19958
19927
  return;
19959
19928
  }
19960
19929
  const value = raw.trim();
19961
- if (value.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
19962
- ctx.err(path13, `${stepLabel} "exec.cwd" exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters.`);
19963
- return;
19964
- }
19965
19930
  if (!isContainedRelativePath(value)) {
19966
19931
  ctx.err(path13, `${stepLabel} "exec.cwd" (${JSON.stringify(value)}) must be a RELATIVE path inside the unit's working ` + `directory \u2014 absolute paths, Windows drive letters, "~", and ".." segments are rejected.`);
19967
19932
  return;
@@ -19995,10 +19960,10 @@ function parseMap(ctx, raw, path13, stepLabel) {
19995
19960
  }
19996
19961
  let concurrency;
19997
19962
  if (raw.concurrency !== undefined) {
19998
- if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0 && raw.concurrency <= WORKFLOW_MAX_CONCURRENCY) {
19999
- concurrency = raw.concurrency;
19963
+ if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
19964
+ concurrency = Math.min(raw.concurrency, WORKFLOW_MAX_CONCURRENCY);
20000
19965
  } else {
20001
- ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}.`);
19966
+ ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
20002
19967
  }
20003
19968
  }
20004
19969
  const reducer = parseEnumField(ctx, raw.reducer, [...path13, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
@@ -20030,9 +19995,6 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20030
19995
  if (!Array.isArray(raw.when) || raw.when.length === 0) {
20031
19996
  ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
20032
19997
  } else {
20033
- if (raw.when.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
20034
- ctx.err(whenPath, `${stepLabel} "when" must contain at most ${WORKFLOW_MAX_ROUTE_BRANCHES} branches.`);
20035
- }
20036
19998
  const seenMatches = new Map;
20037
19999
  raw.when.forEach((branch, i) => {
20038
20000
  const branchPath = [...whenPath, i];
@@ -20088,9 +20050,6 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20088
20050
  ctx.err(path13, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
20089
20051
  return;
20090
20052
  }
20091
- if (raw.length > WORKFLOW_MAX_INPUTS) {
20092
- ctx.err(path13, `${stepLabel} "inputs" must contain at most ${WORKFLOW_MAX_INPUTS} entries.`);
20093
- }
20094
20053
  const out = [];
20095
20054
  const seen = new Set;
20096
20055
  raw.forEach((entry, i) => {
@@ -20117,10 +20076,10 @@ function parseGate(ctx, raw, path13, stepLabel) {
20117
20076
  checkUnknownKeys(ctx, raw, path13, GATE_KEYS, `${stepLabel} "gate"`);
20118
20077
  const gate = {};
20119
20078
  if (raw.max_loops !== undefined) {
20120
- if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1 && raw.max_loops <= WORKFLOW_MAX_GATE_LOOPS) {
20079
+ if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
20121
20080
  gate.maxLoops = raw.max_loops;
20122
20081
  } else {
20123
- ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}.`);
20082
+ ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer of at least 1.`);
20124
20083
  }
20125
20084
  }
20126
20085
  return gate;
@@ -20146,8 +20105,8 @@ function parseRetry(ctx, raw, path13, stepLabel) {
20146
20105
  }
20147
20106
  checkUnknownKeys(ctx, raw, path13, RETRY_KEYS, `${stepLabel} "retry"`);
20148
20107
  let ok = true;
20149
- if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0 && raw.max <= WORKFLOW_MAX_RETRIES)) {
20150
- ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
20108
+ if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
20109
+ ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
20151
20110
  ok = false;
20152
20111
  }
20153
20112
  const on = [];
@@ -21764,6 +21723,8 @@ function indexDocumentFromEntry(entry, base3, rendererName) {
21764
21723
  doc.tags = entry.tags;
21765
21724
  if (entry.content !== undefined)
21766
21725
  doc.content = entry.content;
21726
+ if (entry.contentTruncated !== undefined)
21727
+ doc.contentTruncated = entry.contentTruncated;
21767
21728
  if (entry.aliases !== undefined)
21768
21729
  doc.aliases = entry.aliases;
21769
21730
  if (entry.searchHints !== undefined)
@@ -23733,7 +23694,7 @@ function withLockOperationMutex(lockPath, run) {
23733
23694
  db.exec("BEGIN IMMEDIATE");
23734
23695
  began = db.inTransaction;
23735
23696
  if (!began)
23736
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2 ** attempt);
23697
+ sleepSync(2 ** attempt);
23737
23698
  }
23738
23699
  if (!began)
23739
23700
  throw new Error(`Could not acquire lock operation mutex for ${lockPath}.`);
@@ -23896,7 +23857,7 @@ function extractHolderPid(content) {
23896
23857
  // src/core/config/config-io.ts
23897
23858
  function readConfigText(configPath) {
23898
23859
  try {
23899
- return readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file");
23860
+ return readTextFile(configPath, "Config file");
23900
23861
  } catch (err) {
23901
23862
  if (err.code === "ENOENT")
23902
23863
  return;
@@ -28003,9 +27964,6 @@ var ExtraParamsSchema = exports_external.record(exports_external.unknown()).supe
28003
27964
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: issue.path, message: issue.message });
28004
27965
  }
28005
27966
  });
28006
- var LlmCapabilitiesSchema = exports_external.object({
28007
- structuredOutput: exports_external.boolean().optional()
28008
- }).passthrough();
28009
27967
  var LlmInvocationOverridesSchema = exports_external.object({
28010
27968
  temperature: exports_external.number().finite().optional(),
28011
27969
  maxTokens: positiveInt.optional(),
@@ -28061,15 +28019,13 @@ var LlmConnectionConfigSchema = exports_external.object({
28061
28019
  maxTokens: positiveInt.optional(),
28062
28020
  timeoutMs: timeoutMsField,
28063
28021
  concurrency: positiveInt.optional(),
28064
- capabilities: LlmCapabilitiesSchema.optional(),
28022
+ supportsJsonSchema: exports_external.boolean().optional(),
28065
28023
  extraParams: ExtraParamsSchema.optional(),
28066
28024
  contextLength: positiveInt.optional(),
28067
28025
  enableThinking: exports_external.boolean().optional(),
28068
28026
  reasoningEffort: nonEmptyString3.optional()
28069
28027
  }).passthrough();
28070
- var LlmProfileConfigSchema = LlmConnectionConfigSchema.extend({
28071
- supportsJsonSchema: exports_external.boolean().optional()
28072
- }).passthrough();
28028
+ var LlmProfileConfigSchema = LlmConnectionConfigSchema.passthrough();
28073
28029
  var AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
28074
28030
  var LlmEngineSchema = exports_external.object({
28075
28031
  kind: exports_external.literal("llm"),
@@ -28081,7 +28037,6 @@ var LlmEngineSchema = exports_external.object({
28081
28037
  maxTokens: positiveInt.optional(),
28082
28038
  timeoutMs: timeoutMsField,
28083
28039
  concurrency: positiveInt.optional(),
28084
- supportsJsonSchema: exports_external.boolean().optional(),
28085
28040
  extraParams: ExtraParamsSchema.optional(),
28086
28041
  contextLength: positiveInt.optional(),
28087
28042
  enableThinking: exports_external.boolean().optional(),
@@ -28111,7 +28066,6 @@ var AgentEngineSchema = exports_external.object({
28111
28066
  "temperature",
28112
28067
  "maxTokens",
28113
28068
  "concurrency",
28114
- "supportsJsonSchema",
28115
28069
  "extraParams",
28116
28070
  "contextLength",
28117
28071
  "enableThinking",
@@ -28477,7 +28431,7 @@ var SearchGraphBoostSchema = exports_external.object({
28477
28431
  hopBoostPerEntity: nonNegativeNumber.optional(),
28478
28432
  hopBoostCap: nonNegativeNumber.optional(),
28479
28433
  maxHops: positiveInt.max(3).optional(),
28480
- confidenceMode: exports_external.enum(["off", "blend", "multiply"]).default("blend").optional(),
28434
+ confidenceMode: exports_external.enum(["blend"]).default("blend").optional(),
28481
28435
  confidenceWeight: exports_external.number().finite().min(0).max(1).default(0.2).optional()
28482
28436
  }).passthrough();
28483
28437
  var SearchConfigSchema = exports_external.object({
@@ -28814,6 +28768,43 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
28814
28768
  }
28815
28769
  });
28816
28770
 
28771
+ // src/core/config/config-version-shim.ts
28772
+ var KNOWN_OLD_CONFIG_VERSIONS = ["0.0.1"];
28773
+ function isKnownOldConfigVersion(value) {
28774
+ return typeof value === "string" && KNOWN_OLD_CONFIG_VERSIONS.includes(value);
28775
+ }
28776
+ function upgradeFrom080(raw) {
28777
+ const { defaultEngine, defaults, ...rest } = raw;
28778
+ if (typeof defaultEngine !== "string" || defaultEngine.length === 0) {
28779
+ return { ...rest, ...defaults !== undefined ? { defaults } : {}, configVersion: CURRENT_CONFIG_VERSION };
28780
+ }
28781
+ const existingDefaults = defaults !== null && typeof defaults === "object" ? defaults : {};
28782
+ return {
28783
+ ...rest,
28784
+ configVersion: CURRENT_CONFIG_VERSION,
28785
+ defaults: { llmEngine: defaultEngine, ...existingDefaults }
28786
+ };
28787
+ }
28788
+ var CONFIG_VERSION_UPGRADES = {
28789
+ "0.0.1": upgradeFrom080
28790
+ };
28791
+ function unsupportedConfigVersionError(rawVersion, sourcePath) {
28792
+ const where = sourcePath ? ` at ${sourcePath}` : "";
28793
+ const supported = [CURRENT_CONFIG_VERSION, ...KNOWN_OLD_CONFIG_VERSIONS].map((v) => `"${v}"`).join(", ");
28794
+ 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.");
28795
+ }
28796
+ function upgradeConfigVersion(raw, sourcePath) {
28797
+ const version = raw.configVersion;
28798
+ if (version === CURRENT_CONFIG_VERSION)
28799
+ return raw;
28800
+ if (isKnownOldConfigVersion(version)) {
28801
+ const upgraded = CONFIG_VERSION_UPGRADES[version](raw);
28802
+ warn(`Config${sourcePath ? ` at ${sourcePath}` : ""} uses configVersion "${version}" \u2014 auto-upgraded to ${CURRENT_CONFIG_VERSION} in memory; the next config write (e.g. \`akm config set\`) persists this and silences the warning.`);
28803
+ return upgraded;
28804
+ }
28805
+ throw unsupportedConfigVersionError(version, sourcePath);
28806
+ }
28807
+
28817
28808
  // src/core/config/deep-merge.ts
28818
28809
  var UNSAFE_KEYS3 = new Set(["__proto__", "constructor", "prototype"]);
28819
28810
  function isPlainObject4(value) {
@@ -28904,10 +28895,7 @@ function loadUserConfig() {
28904
28895
  return finalConfig;
28905
28896
  }
28906
28897
  function parseAndValidateConfigText(text, sourcePath) {
28907
- const parsedRaw = parseConfigText(text, sourcePath);
28908
- if (parsedRaw.configVersion !== CURRENT_CONFIG_VERSION) {
28909
- 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.");
28910
- }
28898
+ const parsedRaw = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
28911
28899
  const { config: raw, lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28912
28900
  const where = sourcePath ? ` at ${sourcePath}` : "";
28913
28901
  if (conflicts.length > 0) {
@@ -28985,8 +28973,7 @@ function withMaintenanceStartBarrier(run) {
28985
28973
 
28986
28974
  // src/indexer/index-writer-lock.ts
28987
28975
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
28988
- var INDEX_WRITER_LOCK_STALE_AFTER_MS = 12 * 60 * 60 * 1000;
28989
- var DEFAULT_INDEX_WRITER_MAX_WAIT_MS = 10 * 60 * 1000;
28976
+ var DEFAULT_ASSET_MUTATION_MAX_WAIT_MS = 10 * 60 * 1000;
28990
28977
  var leaseContext = new AsyncLocalStorage2;
28991
28978
 
28992
28979
  // src/integrations/lockfile.ts
@@ -29460,32 +29447,18 @@ function contained2(root, candidate) {
29460
29447
  const relative = path31.relative(root, candidate);
29461
29448
  return relative === "" || !relative.startsWith("..") && !path31.isAbsolute(relative);
29462
29449
  }
29463
- function identity3(filePath, kind) {
29464
- const stat = fs26.lstatSync(filePath, { bigint: true });
29465
- const valid = kind === "file" ? stat.isFile() : stat.isDirectory();
29466
- if (stat.isSymbolicLink() || !valid)
29467
- throw migrationError(`${filePath} must be a real ${kind}.`);
29468
- if (kind === "file" && stat.nlink !== 1n)
29469
- throw migrationError(`${filePath} must not be hard-linked.`);
29470
- return Object.freeze({
29471
- realPath: fs26.realpathSync(filePath),
29472
- device: stat.dev.toString(),
29473
- inode: stat.ino.toString(),
29474
- linkCount: stat.nlink.toString(),
29475
- changeTimeNs: stat.ctimeNs.toString()
29476
- });
29477
- }
29478
- function sameIdentity2(left, right) {
29479
- return left.realPath === right.realPath && left.device === right.device && left.inode === right.inode && left.linkCount === right.linkCount && left.changeTimeNs === right.changeTimeNs;
29450
+ function realDirectory(filePath) {
29451
+ const stat = fs26.lstatSync(filePath);
29452
+ if (stat.isSymbolicLink() || !stat.isDirectory())
29453
+ throw migrationError(`${filePath} must be a real directory.`);
29454
+ return fs26.realpathSync(filePath);
29480
29455
  }
29481
29456
  function snapshot(filePath) {
29482
- const before = identity3(filePath, "file");
29483
29457
  const stat = fs26.lstatSync(filePath);
29458
+ if (stat.isSymbolicLink() || !stat.isFile())
29459
+ throw migrationError(`${filePath} must be a real file.`);
29484
29460
  const bytes = fs26.readFileSync(filePath);
29485
- const after = identity3(filePath, "file");
29486
- if (!sameIdentity2(before, after))
29487
- throw migrationError(`${filePath} changed while it was read.`);
29488
- return Object.freeze({ bytes, mode: stat.mode & 511, identity: after });
29461
+ return Object.freeze({ bytes, mode: stat.mode & 511 });
29489
29462
  }
29490
29463
  function writable(filePath) {
29491
29464
  try {
@@ -29496,10 +29469,9 @@ function writable(filePath) {
29496
29469
  }
29497
29470
  }
29498
29471
  function walkTasks(root, tasksDir, out) {
29499
- const rootIdentity = identity3(root.root, "directory");
29500
- const bundleIdentity = identity3(root.bundleRoot ?? root.root, "directory");
29501
- const physicalRoot = rootIdentity.realPath;
29502
- if (!contained2(bundleIdentity.realPath, physicalRoot)) {
29472
+ const physicalRoot = realDirectory(root.root);
29473
+ const physicalBundleRoot = realDirectory(root.bundleRoot ?? root.root);
29474
+ if (!contained2(physicalBundleRoot, physicalRoot)) {
29503
29475
  throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
29504
29476
  }
29505
29477
  const visit2 = (directory) => {
@@ -29525,12 +29497,7 @@ function walkTasks(root, tasksDir, out) {
29525
29497
  mode: current.mode,
29526
29498
  writable: root.writable,
29527
29499
  onDiskWritable: writable(candidate) && writable(parent) && (current.mode & 146) !== 0,
29528
- containmentRoot: physicalRoot,
29529
- inspectionIdentity: Object.freeze({
29530
- file: current.identity,
29531
- root: rootIdentity,
29532
- bundleRoot: bundleIdentity
29533
- })
29500
+ containmentRoot: physicalRoot
29534
29501
  });
29535
29502
  }
29536
29503
  };
@@ -29594,17 +29561,9 @@ function assertUnchanged(change) {
29594
29561
  if (!current.bytes.equals(change.before) || current.mode !== change.mode) {
29595
29562
  throw migrationError(`${change.filePath} changed after preview; no task files were replaced.`);
29596
29563
  }
29597
- const planned = change.inspectionIdentity?.file;
29598
- if (planned && !sameIdentity2(planned, current.identity)) {
29599
- throw migrationError(`${change.filePath} identity changed after preview; no task files were replaced.`);
29600
- }
29601
29564
  return current;
29602
29565
  }
29603
29566
  function applyTaskToV3MigrationPlan(plan, options) {
29604
- const blocked3 = plan.files.filter((file) => file.status === "blocked");
29605
- if (blocked3.length > 0) {
29606
- throw migrationError(`plan is blocked: ${blocked3.map((file) => `${file.filePath} (${file.reason})`).join(", ")}. No files were written.`);
29607
- }
29608
29567
  const changes = plan.files.filter((file) => file.status === "changed");
29609
29568
  for (const change of changes) {
29610
29569
  assertUnchanged(change);
@@ -29647,32 +29606,18 @@ function contained3(root, candidate) {
29647
29606
  const relative = path32.relative(root, candidate);
29648
29607
  return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
29649
29608
  }
29650
- function identity4(filePath, kind) {
29651
- const stat = fs27.lstatSync(filePath, { bigint: true });
29652
- const valid = kind === "file" ? stat.isFile() : stat.isDirectory();
29653
- if (stat.isSymbolicLink() || !valid)
29654
- throw migrationError2(`${filePath} must be a real ${kind}.`);
29655
- if (kind === "file" && stat.nlink !== 1n)
29656
- throw migrationError2(`${filePath} must not be hard-linked.`);
29657
- return Object.freeze({
29658
- realPath: fs27.realpathSync(filePath),
29659
- device: stat.dev.toString(),
29660
- inode: stat.ino.toString(),
29661
- linkCount: stat.nlink.toString(),
29662
- changeTimeNs: stat.ctimeNs.toString()
29663
- });
29664
- }
29665
- function sameIdentity3(left, right) {
29666
- return left.realPath === right.realPath && left.device === right.device && left.inode === right.inode && left.linkCount === right.linkCount && left.changeTimeNs === right.changeTimeNs;
29609
+ function realDirectory2(filePath) {
29610
+ const stat = fs27.lstatSync(filePath);
29611
+ if (stat.isSymbolicLink() || !stat.isDirectory())
29612
+ throw migrationError2(`${filePath} must be a real directory.`);
29613
+ return fs27.realpathSync(filePath);
29667
29614
  }
29668
29615
  function snapshot2(filePath) {
29669
- const before = identity4(filePath, "file");
29670
29616
  const stat = fs27.lstatSync(filePath);
29617
+ if (stat.isSymbolicLink() || !stat.isFile())
29618
+ throw migrationError2(`${filePath} must be a real file.`);
29671
29619
  const bytes = fs27.readFileSync(filePath);
29672
- const after = identity4(filePath, "file");
29673
- if (!sameIdentity3(before, after))
29674
- throw migrationError2(`${filePath} changed while it was read.`);
29675
- return Object.freeze({ bytes, mode: stat.mode & 511, identity: after });
29620
+ return Object.freeze({ bytes, mode: stat.mode & 511 });
29676
29621
  }
29677
29622
  function writable2(filePath) {
29678
29623
  try {
@@ -29683,10 +29628,9 @@ function writable2(filePath) {
29683
29628
  }
29684
29629
  }
29685
29630
  function walkTasks2(root, tasksDir, out) {
29686
- const rootIdentity = identity4(root.root, "directory");
29687
- const bundleIdentity = identity4(root.bundleRoot ?? root.root, "directory");
29688
- const physicalRoot = rootIdentity.realPath;
29689
- if (!contained3(bundleIdentity.realPath, physicalRoot)) {
29631
+ const physicalRoot = realDirectory2(root.root);
29632
+ const physicalBundleRoot = realDirectory2(root.bundleRoot ?? root.root);
29633
+ if (!contained3(physicalBundleRoot, physicalRoot)) {
29690
29634
  throw migrationError2(`${root.root} resolves outside bundle ${root.bundleId}.`);
29691
29635
  }
29692
29636
  const visit2 = (directory) => {
@@ -29712,12 +29656,7 @@ function walkTasks2(root, tasksDir, out) {
29712
29656
  mode: current.mode,
29713
29657
  writable: root.writable,
29714
29658
  onDiskWritable: writable2(candidate) && writable2(parent) && (current.mode & 146) !== 0,
29715
- containmentRoot: physicalRoot,
29716
- inspectionIdentity: Object.freeze({
29717
- file: current.identity,
29718
- root: rootIdentity,
29719
- bundleRoot: bundleIdentity
29720
- })
29659
+ containmentRoot: physicalRoot
29721
29660
  });
29722
29661
  }
29723
29662
  };
@@ -29781,17 +29720,9 @@ function assertUnchanged2(change) {
29781
29720
  if (!current.bytes.equals(change.before) || current.mode !== change.mode) {
29782
29721
  throw migrationError2(`${change.filePath} changed after preview; no task files were replaced.`);
29783
29722
  }
29784
- const planned = change.inspectionIdentity?.file;
29785
- if (planned && !sameIdentity3(planned, current.identity)) {
29786
- throw migrationError2(`${change.filePath} identity changed after preview; no task files were replaced.`);
29787
- }
29788
29723
  return current;
29789
29724
  }
29790
29725
  function applyTaskToV4MigrationPlan(plan, options) {
29791
- const blocked3 = plan.files.filter((file) => file.status === "blocked");
29792
- if (blocked3.length > 0) {
29793
- throw migrationError2(`plan is blocked: ${blocked3.map((file) => `${file.filePath} (${file.reason})`).join(", ")}. No files were written.`);
29794
- }
29795
29726
  const changes = plan.files.filter((file) => file.status === "changed");
29796
29727
  for (const change of changes) {
29797
29728
  assertUnchanged2(change);
@@ -29840,9 +29771,14 @@ function existingDirectory(target) {
29840
29771
  throw cause;
29841
29772
  }
29842
29773
  }
29774
+ function reconcileDuplicateRoot(existing, candidate, sharedPath) {
29775
+ if (existing.writable === candidate.writable && existing.layout === candidate.layout)
29776
+ return;
29777
+ 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 \u2014 run `akm bundle list` to see both.", "INVALID_CONFIG_FILE");
29778
+ }
29843
29779
  function taskRoots(config, resolutionBase = process.cwd()) {
29844
29780
  const sources = new Map((bundlesToSourceEntries(config) ?? []).map((source) => [source.name, source]));
29845
- const roots = [];
29781
+ const rootsByPath = new Map;
29846
29782
  for (const [bundleId, bundle] of Object.entries(config.bundles ?? {})) {
29847
29783
  if (bundle.enabled === false)
29848
29784
  continue;
@@ -29870,15 +29806,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
29870
29806
  }
29871
29807
  if (adapter !== "akm" && adapter !== "akm-task")
29872
29808
  continue;
29873
- roots.push({
29809
+ const candidate = {
29874
29810
  bundleId,
29875
29811
  root: componentRoot,
29876
29812
  bundleRoot,
29877
29813
  writable: component?.writable ?? resolveWritable(source),
29878
29814
  layout: adapter === "akm-task" ? "akm-task" : "akm-stash"
29879
- });
29815
+ };
29816
+ const existing = rootsByPath.get(componentRoot);
29817
+ if (existing) {
29818
+ reconcileDuplicateRoot(existing, candidate, componentRoot);
29819
+ continue;
29820
+ }
29821
+ rootsByPath.set(componentRoot, candidate);
29880
29822
  }
29881
- return roots;
29823
+ return [...rootsByPath.values()];
29882
29824
  }
29883
29825
  function summarize(plan) {
29884
29826
  const files = plan.files.map((file) => ({
@@ -29935,12 +29877,12 @@ async function runMigrationApply(options = {}) {
29935
29877
  }
29936
29878
  const result = withConfigLock(() => withMaintenanceStartBarrier(() => {
29937
29879
  const before = inspectCurrentTaskPlan();
29938
- if (before.result.status !== "ready")
29880
+ if (before.result.taskV3Migration.changed === 0)
29939
29881
  return before.result;
29940
29882
  const backupPath = path33.join(getDataDir(), "backups", "task-v3", `${Date.now()}-${randomUUID2()}`);
29941
29883
  const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
29942
29884
  const after = inspectCurrentTaskPlan().result;
29943
- if (after.status !== "current") {
29885
+ if (after.taskV3Migration.changed > 0) {
29944
29886
  throw new ConfigError("Task migration did not converge to task v3.", "INVALID_CONFIG_FILE");
29945
29887
  }
29946
29888
  return { ...after, backupPath, applied: applied.changed.length };
@@ -29998,12 +29940,12 @@ async function runTaskV4MigrationApply(options = {}) {
29998
29940
  }
29999
29941
  const result = withConfigLock(() => withMaintenanceStartBarrier(() => {
30000
29942
  const before = inspectCurrentTaskV4Plan();
30001
- if (before.result.status !== "ready")
29943
+ if (before.result.taskV4Migration.changed === 0)
30002
29944
  return before.result;
30003
29945
  const backupPath = path33.join(getDataDir(), "backups", "task-v4", `${Date.now()}-${randomUUID2()}`);
30004
29946
  const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
30005
29947
  const after = inspectCurrentTaskV4Plan().result;
30006
- if (after.status !== "current") {
29948
+ if (after.taskV4Migration.changed > 0) {
30007
29949
  throw new ConfigError("Task migration did not converge to task source v4.", "INVALID_CONFIG_FILE");
30008
29950
  }
30009
29951
  return { ...after, backupPath, applied: applied.changed.length };