akm-cli 0.9.5 → 0.9.7

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 (130) hide show
  1. package/CHANGELOG.md +295 -0
  2. package/dist/assets/hints/cli-hints-full.md +3 -3
  3. package/dist/assets/improve-strategies/catchup.json +40 -11
  4. package/dist/assets/improve-strategies/thorough.json +45 -7
  5. package/dist/assets/tasks/improve/akm-improve-frequent.yml +2 -2
  6. package/dist/commands/agent/contribute-cli.js +11 -0
  7. package/dist/commands/env/env-cli.js +1 -2
  8. package/dist/commands/env/secret-cli.js +1 -5
  9. package/dist/commands/feedback-cli.js +0 -4
  10. package/dist/commands/health/checks.js +0 -32
  11. package/dist/commands/health/surfaces.js +2 -2
  12. package/dist/commands/health.js +6 -15
  13. package/dist/commands/improve/autonomy-gate.js +1 -1
  14. package/dist/commands/improve/consolidate.js +25 -26
  15. package/dist/commands/improve/distill.js +2 -2
  16. package/dist/commands/improve/extract.js +8 -1
  17. package/dist/commands/improve/improve-cli.js +1 -1
  18. package/dist/commands/improve/improve-strategies.js +0 -4
  19. package/dist/commands/improve/improve.js +3 -5
  20. package/dist/commands/improve/locks.js +13 -5
  21. package/dist/commands/improve/loop-stages.js +8 -9
  22. package/dist/commands/improve/memory/memory-contradiction-detect.js +1 -19
  23. package/dist/commands/improve/memory/memory-improve.js +2 -1
  24. package/dist/commands/improve/outcome-loop.js +0 -6
  25. package/dist/commands/improve/preparation.js +1 -1
  26. package/dist/commands/improve/reflect.js +21 -10
  27. package/dist/commands/lint/base-linter.js +141 -18
  28. package/dist/commands/lint/index.js +21 -10
  29. package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -7
  30. package/dist/commands/read/curate.js +47 -0
  31. package/dist/commands/read/search-cli.js +24 -1
  32. package/dist/commands/sources/bundle-config-ops.js +9 -4
  33. package/dist/commands/sources/info.js +14 -10
  34. package/dist/commands/tasks/tasks.js +12 -16
  35. package/dist/commands/workflow-cli.js +2 -2
  36. package/dist/core/asset/asset-placement.js +13 -2
  37. package/dist/core/asset/frontmatter.js +116 -0
  38. package/dist/core/asset/memory-archive.js +97 -0
  39. package/dist/core/common.js +61 -24
  40. package/dist/core/config/config-io.js +2 -2
  41. package/dist/core/config/config-sources.js +32 -2
  42. package/dist/core/config/config.js +1 -1
  43. package/dist/core/config/engine-semantics.js +0 -2
  44. package/dist/core/config/schema/engines.js +9 -7
  45. package/dist/core/config/schema/primitives.js +0 -5
  46. package/dist/core/config/schema/search.js +2 -1
  47. package/dist/core/file-lock.js +2 -1
  48. package/dist/core/maintenance-barrier.js +2 -14
  49. package/dist/core/paths.js +0 -3
  50. package/dist/core/redaction.js +2 -2
  51. package/dist/core/spawn-env.js +8 -12
  52. package/dist/core/state/migrations.js +1 -12
  53. package/dist/core/state-db.js +9 -27
  54. package/dist/core/write-source.js +12 -19
  55. package/dist/execution/directory-identity.js +36 -10
  56. package/dist/indexer/graph/graph-boost.js +0 -4
  57. package/dist/indexer/index-writer-lock.js +43 -24
  58. package/dist/indexer/index-written-assets.js +5 -6
  59. package/dist/indexer/indexer.js +2 -39
  60. package/dist/indexer/materialize-embeddings.js +85 -41
  61. package/dist/indexer/search/db-search.js +15 -48
  62. package/dist/indexer/search/ranking-contributors.js +0 -25
  63. package/dist/indexer/search/ranking.js +3 -13
  64. package/dist/integrations/agent/builder-shared.js +0 -25
  65. package/dist/integrations/agent/model-map.js +2 -60
  66. package/dist/integrations/harnesses/aider/agent-builder.js +1 -3
  67. package/dist/integrations/harnesses/amazonq/agent-builder.js +2 -7
  68. package/dist/integrations/harnesses/claude/agent-builder.js +1 -4
  69. package/dist/integrations/harnesses/codex/agent-builder.js +1 -4
  70. package/dist/integrations/harnesses/copilot/agent-builder.js +2 -6
  71. package/dist/integrations/harnesses/gemini/agent-builder.js +2 -7
  72. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -4
  73. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +2 -16
  74. package/dist/integrations/harnesses/openhands/agent-builder.js +1 -3
  75. package/dist/integrations/harnesses/pi/agent-builder.js +2 -4
  76. package/dist/integrations/session-logs/index.js +0 -9
  77. package/dist/llm/client.js +75 -42
  78. package/dist/llm/embedder.js +7 -3
  79. package/dist/llm/embedders/remote.js +141 -42
  80. package/dist/registry/network.js +5 -37
  81. package/dist/runtime.js +2 -10
  82. package/dist/scripts/akm-migrate-node.js +73 -133
  83. package/dist/scripts/akm-migrate.js +73 -133
  84. package/dist/setup/engine-config.js +2 -5
  85. package/dist/setup/registry-stash-loader.js +0 -8
  86. package/dist/setup/setup.js +9 -46
  87. package/dist/setup/steps/connection-shared.js +10 -13
  88. package/dist/sources/providers/git-install.js +1 -1
  89. package/dist/sources/snapshot-fetchers/website-ingest.js +126 -0
  90. package/dist/storage/engines/sqlite-migrations.js +20 -1
  91. package/dist/storage/repositories/index-connection.js +45 -3
  92. package/dist/storage/repositories/index-entries-repository.js +0 -15
  93. package/dist/tasks/backends/cron.js +49 -9
  94. package/dist/tasks/backends/launchd.js +15 -20
  95. package/dist/tasks/backends/schtasks.js +18 -8
  96. package/dist/tasks/resolve-akm-bin.js +17 -2
  97. package/dist/tasks/run/run-native-task.js +8 -6
  98. package/dist/tasks/scheduler-invocation.js +8 -1
  99. package/dist/tasks/source/bounded-document.js +2 -4
  100. package/dist/tasks/source/parse-task-source.js +23 -9
  101. package/dist/tasks/source/task-source-v3-frozen.js +5 -7
  102. package/dist/tasks/source/task-source-v4.js +5 -10
  103. package/dist/tasks/source/task-to-v3.js +5 -10
  104. package/dist/tasks/source/task-to-v4.js +1 -4
  105. package/dist/tasks/source-v3.js +6 -6
  106. package/dist/workflows/exec/native-executor.js +21 -31
  107. package/dist/workflows/exec/run-workflow.js +5 -6
  108. package/dist/workflows/exec/scheduler.js +3 -19
  109. package/dist/workflows/exec/step-work.js +1 -4
  110. package/dist/workflows/exec/unit-dispatch.js +2 -2
  111. package/dist/workflows/exec/worktree.js +1 -13
  112. package/dist/workflows/freeze/targets/child-workflow.js +2 -10
  113. package/dist/workflows/ir/plan-hash.js +4 -6
  114. package/dist/workflows/ir/schema-v4.js +0 -12
  115. package/dist/workflows/ir/schema.js +20 -31
  116. package/dist/workflows/parser.js +11 -52
  117. package/dist/workflows/renderer.js +2 -3
  118. package/dist/workflows/resource-limits.js +11 -41
  119. package/dist/workflows/runtime/runs.js +3 -4
  120. package/dist/workflows/source-ir/schema.js +14 -30
  121. package/dist/workflows/validator.js +1 -7
  122. package/docs/reference/cli.md +5 -1
  123. package/docs/reference/configuration.md +1 -1
  124. package/package.json +1 -1
  125. package/schemas/akm-config.json +4 -23
  126. package/schemas/akm-task.json +1 -2
  127. package/schemas/akm-workflow.json +1 -13
  128. package/dist/assets/improve-strategies/frequent.json +0 -15
  129. package/dist/assets/improve-strategies/memory-focus.json +0 -15
  130. 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;
@@ -11522,6 +11525,7 @@ var SCRIPT_EXTENSIONS = new Set([
11522
11525
  ".kts"
11523
11526
  ]);
11524
11527
  var WORKFLOW_EXTENSIONS = [".md", ".yml"];
11528
+ var DERIVED_SUFFIX = ".derived";
11525
11529
  var KNOWN_TYPES = [
11526
11530
  "skill",
11527
11531
  "command",
@@ -11682,6 +11686,9 @@ function assetPathForName(assetType, typeRoot, name) {
11682
11686
  }
11683
11687
  function assetPathCandidatesForName(assetType, typeRoot, name) {
11684
11688
  const primary = assetPathForName(assetType, typeRoot, name);
11689
+ if (assetType === "memory" && !name.endsWith(DERIVED_SUFFIX)) {
11690
+ return [primary, assetPathForName(assetType, typeRoot, `${name}${DERIVED_SUFFIX}`)];
11691
+ }
11685
11692
  if (assetType !== "env")
11686
11693
  return [primary];
11687
11694
  const base = name === "default" ? "" : name.endsWith("/default") ? name.slice(0, -"default".length) : undefined;
@@ -14957,25 +14964,13 @@ var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
14957
14964
  // src/workflows/resource-limits.ts
14958
14965
  var WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
14959
14966
  var WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
14960
- var WORKFLOW_MAX_STEPS = 256;
14961
- var WORKFLOW_MAX_PARAMS = 128;
14962
- var WORKFLOW_MAX_ROUTE_BRANCHES = 256;
14963
14967
  var WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
14964
14968
  var WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
14965
14969
  var WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
14966
- var WORKFLOW_MAX_MAP_EXPANSION = 1e4;
14967
- var WORKFLOW_MAX_INPUTS = 64;
14968
- var WORKFLOW_MAX_OUTPUTS = 64;
14969
14970
  var WORKFLOW_MAX_CONCURRENCY = 64;
14970
- var WORKFLOW_MAX_GATE_LOOPS = 100;
14971
- var WORKFLOW_MAX_RETRIES = 100;
14972
14971
  var WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
14973
14972
  var WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
14974
14973
  var WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
14975
- var WORKFLOW_MAX_EXEC_ARGV = 64;
14976
- var WORKFLOW_MAX_EXEC_ARG_BYTES = 4096;
14977
- var WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
14978
- var WORKFLOW_MAX_EXEC_PASS_ENV = 32;
14979
14974
  var WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
14980
14975
  var WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
14981
14976
  var EXEC_CONTEXT_LIMITS_POSIX = {
@@ -14993,13 +14988,13 @@ function jsonBytes(value) {
14993
14988
  var WORKFLOW_MAX_EMBEDDED_CHILD_PLAN_BYTES = 1024 * 1024;
14994
14989
 
14995
14990
  // src/tasks/source/bounded-document.ts
14996
- var TASK_V3_MAX_SOURCE_BYTES = 1024 * 1024;
14997
14991
  var TASK_V3_MAX_JSON_DEPTH = 64;
14998
14992
  var TASK_V3_MAX_JSON_NODES = 1e4;
14999
14993
  var TASK_V3_MAX_COLLECTION_ITEMS = 1024;
15000
14994
  var TASK_V3_MAX_OBJECT_KEYS = 256;
15001
14995
  var TASK_V3_MAX_STRING_BYTES = 256 * 1024;
15002
14996
  var TASK_V3_MAX_SCHEDULES = 64;
14997
+ var TASK_V3_MAX_REDACT_NAMES = 32;
15003
14998
  function own2(value, key) {
15004
14999
  return Object.hasOwn(value, key);
15005
15000
  }
@@ -15288,9 +15283,6 @@ function readBoundedTaskSourceYaml(input, options) {
15288
15283
  if (typeof input.yaml !== "string") {
15289
15284
  throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source must be a string.`, "TASK_SOURCE_INVALID");
15290
15285
  }
15291
- if (utf8Bytes2(input.yaml) > TASK_V3_MAX_SOURCE_BYTES) {
15292
- throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) resource limit.`, "TASK_SOURCE_INVALID");
15293
- }
15294
15286
  const lineCounter2 = new $LineCounter;
15295
15287
  let document;
15296
15288
  try {
@@ -16050,7 +16042,7 @@ function parseExecutionControls(input, ctx) {
16050
16042
  out.timeout = parseTimeoutTopLevel(input.timeout, ctx);
16051
16043
  if (own2(input, "redact")) {
16052
16044
  const names = parseStringArray(input.redact, ctx, ["redact"], {
16053
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16045
+ max: TASK_V3_MAX_REDACT_NAMES,
16054
16046
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16055
16047
  });
16056
16048
  if (new Set(names).size !== names.length)
@@ -16064,8 +16056,8 @@ function parseExecutionControls(input, ctx) {
16064
16056
  out.maxSteps = input.maxSteps;
16065
16057
  }
16066
16058
  if (own2(input, "maxRetries")) {
16067
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16068
- sourceError(ctx, ["maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16059
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16060
+ sourceError(ctx, ["maxRetries"], "must be a non-negative safe integer.");
16069
16061
  }
16070
16062
  out.maxRetries = input.maxRetries;
16071
16063
  }
@@ -16125,9 +16117,6 @@ function parseInputDeclaration(name, raw, ctx) {
16125
16117
  function parseInputDeclarations(value, ctx) {
16126
16118
  const input = asRecord(value, ctx, ["inputs"]);
16127
16119
  const names = Object.keys(input);
16128
- if (names.length > WORKFLOW_MAX_PARAMS) {
16129
- sourceError(ctx, ["inputs"], `accepts at most ${WORKFLOW_MAX_PARAMS} declared inputs.`);
16130
- }
16131
16120
  const result = {};
16132
16121
  for (const name of names) {
16133
16122
  if (!INPUT_NAME_PATTERN.test(name)) {
@@ -16560,7 +16549,7 @@ function parseAkm(value, ctx) {
16560
16549
  out.timeout = parseTimeout(input.timeout, ctx);
16561
16550
  if (own2(input, "redact")) {
16562
16551
  const names = parseStringArray(input.redact, ctx, ["akm", "redact"], {
16563
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16552
+ max: TASK_V3_MAX_REDACT_NAMES,
16564
16553
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16565
16554
  });
16566
16555
  if (new Set(names).size !== names.length)
@@ -16574,8 +16563,8 @@ function parseAkm(value, ctx) {
16574
16563
  out.maxSteps = input.maxSteps;
16575
16564
  }
16576
16565
  if (own2(input, "maxRetries")) {
16577
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16578
- sourceError(ctx, ["akm", "maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16566
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16567
+ sourceError(ctx, ["akm", "maxRetries"], "must be a non-negative safe integer.");
16579
16568
  }
16580
16569
  out.maxRetries = input.maxRetries;
16581
16570
  }
@@ -16892,9 +16881,6 @@ function optionalString(value, label) {
16892
16881
  return exactString(value, label);
16893
16882
  }
16894
16883
  function parseLegacyTaskYaml(input) {
16895
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
16896
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
16897
- }
16898
16884
  let source;
16899
16885
  try {
16900
16886
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -16942,7 +16928,7 @@ function validateCommonV2(data) {
16942
16928
  }
16943
16929
  }
16944
16930
  if (data.redact !== undefined && data.redact !== null) {
16945
- 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))) {
16931
+ 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))) {
16946
16932
  throw new Error("redact must contain only bounded environment variable names");
16947
16933
  }
16948
16934
  }
@@ -17068,8 +17054,8 @@ function migratedObject(data) {
17068
17054
  akm.maxSteps = data.maxSteps;
17069
17055
  }
17070
17056
  if (data.maxRetries !== undefined && data.maxRetries !== null) {
17071
- if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0 || data.maxRetries > WORKFLOW_MAX_RETRIES) {
17072
- throw new Error(`maxRetries must be from 0 through ${WORKFLOW_MAX_RETRIES}`);
17057
+ if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0) {
17058
+ throw new Error("maxRetries must be a non-negative integer");
17073
17059
  }
17074
17060
  akm.maxRetries = data.maxRetries;
17075
17061
  }
@@ -17328,9 +17314,6 @@ function exactString2(value, label, nonempty = false) {
17328
17314
  return value;
17329
17315
  }
17330
17316
  function parseV3RawYaml(input) {
17331
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
17332
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
17333
- }
17334
17317
  let source;
17335
17318
  try {
17336
17319
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -17627,6 +17610,9 @@ function peekTaskSourceVersion(root) {
17627
17610
  return typeof value === "number" ? value : undefined;
17628
17611
  }
17629
17612
  var TASK_MIGRATE_HINT = "Run `akm migrate apply --dry-run` to preview the task-v3 to task-source-v4 conversion, then run `akm migrate apply`.";
17613
+ function unmigratableVersionError(filePath, version, reason, detail) {
17614
+ return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version} and needs a human decision before it can run — the deterministic migrator cannot convert it automatically (${reason}${detail ? `: ${detail}` : ""}).`, "TASK_SCHEMA_VERSION_UNSUPPORTED", "Review the file and resolve the ambiguity by hand, then it will convert normally; `akm migrate status` reports the same reason.");
17615
+ }
17630
17616
  function unsupportedVersionError(filePath, version) {
17631
17617
  return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version}, which this release does not accept.`, "TASK_SCHEMA_VERSION_UNSUPPORTED", TASK_MIGRATE_HINT);
17632
17618
  }
@@ -17646,12 +17632,12 @@ function planInMemoryV4Bytes(version, yaml, filePath, workspaceRoot) {
17646
17632
  } else {
17647
17633
  const v3Outcome = planTaskToV3File(baseInput);
17648
17634
  if (v3Outcome.status !== "changed")
17649
- return;
17635
+ return { reason: v3Outcome.reason, detail: v3Outcome.detail };
17650
17636
  v3Bytes = v3Outcome.after;
17651
17637
  }
17652
17638
  const v4Outcome = planTaskToV4File({ ...baseInput, bytes: v3Bytes });
17653
17639
  if (v4Outcome.status !== "changed")
17654
- return;
17640
+ return { reason: v4Outcome.reason, detail: v4Outcome.detail };
17655
17641
  return v4Outcome.after.toString("utf8");
17656
17642
  }
17657
17643
  function parseTaskSource(input) {
@@ -17659,16 +17645,17 @@ function parseTaskSource(input) {
17659
17645
  const version = peekTaskSourceVersion(root);
17660
17646
  if (version !== undefined && version !== TASK_SOURCE_V4_VERSION) {
17661
17647
  if (version === 2 || version === 3) {
17662
- const v4Yaml = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17663
- if (v4Yaml !== undefined) {
17648
+ const shimmed = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17649
+ if (typeof shimmed === "string") {
17664
17650
  const v4 = parseTaskSourceV4({
17665
- yaml: v4Yaml,
17651
+ yaml: shimmed,
17666
17652
  filePath: input.filePath,
17667
17653
  ...input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}
17668
17654
  });
17669
17655
  warn(`akm: task ${input.filePath} uses schema v${version} — auto-read as v4; run \`akm migrate apply\` to rewrite it and silence this`);
17670
17656
  return Object.freeze({ version: 4, v4 });
17671
17657
  }
17658
+ throw unmigratableVersionError(input.filePath, version, shimmed.reason, shimmed.detail);
17672
17659
  }
17673
17660
  throw unsupportedVersionError(input.filePath, version);
17674
17661
  }
@@ -18531,7 +18518,7 @@ function validateStep(value, jobId, index, stepIds, options) {
18531
18518
  }
18532
18519
  validateMap(step.map, `step ${id} map`);
18533
18520
  validateRoute(step.route, `step ${id} route`);
18534
- optionalStringList(step.inputs, `step ${id} inputs`, WORKFLOW_MAX_INPUTS);
18521
+ optionalStringList(step.inputs, `step ${id} inputs`, Infinity);
18535
18522
  if (Array.isArray(step.inputs)) {
18536
18523
  for (const [inputIndex, input] of step.inputs.entries())
18537
18524
  validateReference(input, `step ${id} inputs[${inputIndex}]`);
@@ -18553,12 +18540,7 @@ function validateExec(value, location, options) {
18553
18540
  return;
18554
18541
  const exec = record(value, location);
18555
18542
  keys(exec, ["command", "cwd", "passEnv"], location);
18556
- stringList(exec.command, `${location}.command`, WORKFLOW_MAX_EXEC_ARGV, false);
18557
- for (const [index, argument] of exec.command.entries()) {
18558
- if (utf8Bytes(argument) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
18559
- fail2(`${location}.command[${index}] exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes`);
18560
- }
18561
- }
18543
+ stringList(exec.command, `${location}.command`, Infinity, false);
18562
18544
  try {
18563
18545
  rejectNulInArgv(exec.command);
18564
18546
  } catch (cause) {
@@ -18566,9 +18548,6 @@ function validateExec(value, location, options) {
18566
18548
  }
18567
18549
  optionalString2(exec.cwd, `${location}.cwd`);
18568
18550
  if (exec.cwd !== undefined) {
18569
- if (exec.cwd.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
18570
- fail2(`${location}.cwd exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters`);
18571
- }
18572
18551
  try {
18573
18552
  exec.cwd = canonicalizeWorkflowWorkingDirectory(exec.cwd, options.workspaceRoot);
18574
18553
  } catch (cause) {
@@ -18576,7 +18555,7 @@ function validateExec(value, location, options) {
18576
18555
  }
18577
18556
  }
18578
18557
  if (exec.passEnv !== undefined) {
18579
- stringList(exec.passEnv, `${location}.passEnv`, WORKFLOW_MAX_EXEC_PASS_ENV, false);
18558
+ stringList(exec.passEnv, `${location}.passEnv`, Infinity, false);
18580
18559
  }
18581
18560
  if (Array.isArray(exec.passEnv)) {
18582
18561
  for (const name of exec.passEnv) {
@@ -18627,8 +18606,8 @@ function validateRetry(value, location) {
18627
18606
  return;
18628
18607
  const retry = record(value, location);
18629
18608
  keys(retry, ["max", "on"], location);
18630
- if (!Number.isSafeInteger(retry.max) || retry.max < 0 || retry.max > WORKFLOW_MAX_RETRIES) {
18631
- fail2(`${location}.max must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}`);
18609
+ if (!Number.isSafeInteger(retry.max) || retry.max < 0) {
18610
+ fail2(`${location}.max must be a non-negative integer`);
18632
18611
  }
18633
18612
  stringList(retry.on, `${location}.on`, PROGRAM_RETRY_REASONS.length, false);
18634
18613
  for (const reason of retry.on) {
@@ -18658,8 +18637,8 @@ function validateRoute(value, location) {
18658
18637
  keys(route, ["input", "branches", "defaultStepId"], location);
18659
18638
  nonEmptyString2(route.input, `${location}.input`);
18660
18639
  validateReference(route.input, `${location}.input`);
18661
- if (!Array.isArray(route.branches) || route.branches.length === 0 || route.branches.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
18662
- fail2(`${location}.branches must contain 1 through ${WORKFLOW_MAX_ROUTE_BRANCHES} entries`);
18640
+ if (!Array.isArray(route.branches) || route.branches.length === 0) {
18641
+ fail2(`${location}.branches must be a non-empty array`);
18663
18642
  }
18664
18643
  const matches = new Set;
18665
18644
  for (const [index, value2] of route.branches.entries()) {
@@ -18679,8 +18658,8 @@ function validateGate(value, location) {
18679
18658
  return;
18680
18659
  const gate = record(value, location);
18681
18660
  keys(gate, ["maxLoops", "rubric"], location);
18682
- if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1 || gate.maxLoops > WORKFLOW_MAX_GATE_LOOPS)) {
18683
- fail2(`${location}.maxLoops must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}`);
18661
+ if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1)) {
18662
+ fail2(`${location}.maxLoops must be an integer of at least 1`);
18684
18663
  }
18685
18664
  optionalString2(gate.rubric, `${location}.rubric`);
18686
18665
  }
@@ -18713,8 +18692,8 @@ function validateParams(value) {
18713
18692
  if (value === undefined)
18714
18693
  return;
18715
18694
  const params = record(value, "params");
18716
- if (Object.keys(params).length === 0 || Object.keys(params).length > WORKFLOW_MAX_PARAMS) {
18717
- fail2(`params must contain 1 through ${WORKFLOW_MAX_PARAMS} entries`);
18695
+ if (Object.keys(params).length === 0) {
18696
+ fail2(`params must contain at least one entry`);
18718
18697
  }
18719
18698
  for (const [name, schema] of Object.entries(params)) {
18720
18699
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18726,8 +18705,8 @@ function validateOutputs(value) {
18726
18705
  if (value === undefined)
18727
18706
  return;
18728
18707
  const outputs = record(value, "outputs");
18729
- if (Object.keys(outputs).length === 0 || Object.keys(outputs).length > WORKFLOW_MAX_OUTPUTS) {
18730
- fail2(`outputs must contain 1 through ${WORKFLOW_MAX_OUTPUTS} entries`);
18708
+ if (Object.keys(outputs).length === 0) {
18709
+ fail2(`outputs must contain at least one entry`);
18731
18710
  }
18732
18711
  for (const [name, declaration] of Object.entries(outputs)) {
18733
18712
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18750,9 +18729,6 @@ function validateBudget(value) {
18750
18729
  fail2(`budget.${key} must be a positive integer`);
18751
18730
  }
18752
18731
  }
18753
- if (typeof budget.maxUnits === "number" && budget.maxUnits > WORKFLOW_MAX_MAP_EXPANSION) {
18754
- fail2(`budget.maxUnits must be at most ${WORKFLOW_MAX_MAP_EXPANSION}`);
18755
- }
18756
18732
  }
18757
18733
  function validateLlm(value, location) {
18758
18734
  if (value === undefined)
@@ -19336,12 +19312,6 @@ function checkXrefs(value, line, errors2) {
19336
19312
  }
19337
19313
  }
19338
19314
  function checkResourceLimits(draft, errors2) {
19339
- if (draft.steps.length > WORKFLOW_MAX_STEPS) {
19340
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_STEPS} steps.` });
19341
- }
19342
- if (Object.keys(draft.params ?? {}).length > WORKFLOW_MAX_PARAMS) {
19343
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_PARAMS} parameters.` });
19344
- }
19345
19315
  for (const step of draft.steps) {
19346
19316
  if (step.instructions && utf8Bytes(step.instructions.text) > WORKFLOW_MAX_INSTRUCTION_BYTES) {
19347
19317
  errors2.push({
@@ -19703,9 +19673,6 @@ function parseParams(ctx, raw) {
19703
19673
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19704
19674
  return;
19705
19675
  }
19706
- if (Object.keys(raw).length > WORKFLOW_MAX_PARAMS) {
19707
- ctx.err(["params"], `"params" must contain at most ${WORKFLOW_MAX_PARAMS} entries.`);
19708
- }
19709
19676
  const params = {};
19710
19677
  for (const [paramName, value] of Object.entries(raw)) {
19711
19678
  if (!INPUT_NAME_PATTERN.test(paramName)) {
@@ -19731,9 +19698,6 @@ function parseOutputs(ctx, raw) {
19731
19698
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19732
19699
  return;
19733
19700
  }
19734
- if (Object.keys(raw).length > WORKFLOW_MAX_OUTPUTS) {
19735
- ctx.err(["outputs"], `"outputs" must contain at most ${WORKFLOW_MAX_OUTPUTS} entries.`);
19736
- }
19737
19701
  const outputs = {};
19738
19702
  for (const [outputName, value] of Object.entries(raw)) {
19739
19703
  const path13 = ["outputs", outputName];
@@ -19825,10 +19789,10 @@ function parseBudget(ctx, raw) {
19825
19789
  }
19826
19790
  }
19827
19791
  if (raw.max_units !== undefined) {
19828
- if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1 && raw.max_units <= WORKFLOW_MAX_MAP_EXPANSION) {
19792
+ if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
19829
19793
  budget.maxUnits = raw.max_units;
19830
19794
  } else {
19831
- ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer from 1 through ${WORKFLOW_MAX_MAP_EXPANSION}.`);
19795
+ ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer >= 1.`);
19832
19796
  }
19833
19797
  }
19834
19798
  return Object.keys(budget).length > 0 ? budget : undefined;
@@ -19838,9 +19802,6 @@ function parseSteps(ctx, raw) {
19838
19802
  ctx.err(["steps"], `"steps" is required and must be a list with at least one step.`);
19839
19803
  return [];
19840
19804
  }
19841
- if (raw.length > WORKFLOW_MAX_STEPS) {
19842
- ctx.err(["steps"], `"steps" must contain at most ${WORKFLOW_MAX_STEPS} entries.`);
19843
- }
19844
19805
  const idIndex = new Map;
19845
19806
  raw.forEach((rawStep, index) => {
19846
19807
  if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
@@ -20011,10 +19972,6 @@ function parseExecPassEnv(ctx, raw, path13, stepLabel) {
20011
19972
  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.`);
20012
19973
  return;
20013
19974
  }
20014
- if (raw.length > WORKFLOW_MAX_EXEC_PASS_ENV) {
20015
- 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.`);
20016
- return;
20017
- }
20018
19975
  const names = [];
20019
19976
  for (const [index, entry] of raw.entries()) {
20020
19977
  if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
@@ -20034,10 +19991,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
20034
19991
  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.`);
20035
19992
  return;
20036
19993
  }
20037
- if (raw.length > WORKFLOW_MAX_EXEC_ARGV) {
20038
- ctx.err(path13, `${stepLabel} "exec.command" must have at most ${WORKFLOW_MAX_EXEC_ARGV} entries.`);
20039
- return;
20040
- }
20041
19994
  const argv = [];
20042
19995
  for (const [index, entry] of raw.entries()) {
20043
19996
  if (typeof entry !== "string" || entry === "") {
@@ -20048,10 +20001,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
20048
20001
  ctx.err([...path13, index], `${stepLabel} "exec.command[${index}]" may not contain NUL bytes.`);
20049
20002
  return;
20050
20003
  }
20051
- if (utf8Bytes(entry) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
20052
- ctx.err(path13, `${stepLabel} "exec.command[${index}]" exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes.`);
20053
- return;
20054
- }
20055
20004
  argv.push(entry);
20056
20005
  }
20057
20006
  return argv;
@@ -20064,10 +20013,6 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
20064
20013
  return;
20065
20014
  }
20066
20015
  const value = raw.trim();
20067
- if (value.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
20068
- ctx.err(path13, `${stepLabel} "exec.cwd" exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters.`);
20069
- return;
20070
- }
20071
20016
  if (!isContainedRelativePath(value)) {
20072
20017
  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.`);
20073
20018
  return;
@@ -20101,10 +20046,10 @@ function parseMap(ctx, raw, path13, stepLabel) {
20101
20046
  }
20102
20047
  let concurrency;
20103
20048
  if (raw.concurrency !== undefined) {
20104
- if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0 && raw.concurrency <= WORKFLOW_MAX_CONCURRENCY) {
20105
- concurrency = raw.concurrency;
20049
+ if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
20050
+ concurrency = Math.min(raw.concurrency, WORKFLOW_MAX_CONCURRENCY);
20106
20051
  } else {
20107
- ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}.`);
20052
+ ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
20108
20053
  }
20109
20054
  }
20110
20055
  const reducer = parseEnumField(ctx, raw.reducer, [...path13, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
@@ -20136,9 +20081,6 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20136
20081
  if (!Array.isArray(raw.when) || raw.when.length === 0) {
20137
20082
  ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
20138
20083
  } else {
20139
- if (raw.when.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
20140
- ctx.err(whenPath, `${stepLabel} "when" must contain at most ${WORKFLOW_MAX_ROUTE_BRANCHES} branches.`);
20141
- }
20142
20084
  const seenMatches = new Map;
20143
20085
  raw.when.forEach((branch, i) => {
20144
20086
  const branchPath = [...whenPath, i];
@@ -20194,9 +20136,6 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20194
20136
  ctx.err(path13, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
20195
20137
  return;
20196
20138
  }
20197
- if (raw.length > WORKFLOW_MAX_INPUTS) {
20198
- ctx.err(path13, `${stepLabel} "inputs" must contain at most ${WORKFLOW_MAX_INPUTS} entries.`);
20199
- }
20200
20139
  const out = [];
20201
20140
  const seen = new Set;
20202
20141
  raw.forEach((entry, i) => {
@@ -20223,10 +20162,10 @@ function parseGate(ctx, raw, path13, stepLabel) {
20223
20162
  checkUnknownKeys(ctx, raw, path13, GATE_KEYS, `${stepLabel} "gate"`);
20224
20163
  const gate = {};
20225
20164
  if (raw.max_loops !== undefined) {
20226
- if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1 && raw.max_loops <= WORKFLOW_MAX_GATE_LOOPS) {
20165
+ if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
20227
20166
  gate.maxLoops = raw.max_loops;
20228
20167
  } else {
20229
- ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}.`);
20168
+ ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer of at least 1.`);
20230
20169
  }
20231
20170
  }
20232
20171
  return gate;
@@ -20252,8 +20191,8 @@ function parseRetry(ctx, raw, path13, stepLabel) {
20252
20191
  }
20253
20192
  checkUnknownKeys(ctx, raw, path13, RETRY_KEYS, `${stepLabel} "retry"`);
20254
20193
  let ok = true;
20255
- if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0 && raw.max <= WORKFLOW_MAX_RETRIES)) {
20256
- ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
20194
+ if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
20195
+ ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
20257
20196
  ok = false;
20258
20197
  }
20259
20198
  const on = [];
@@ -23841,7 +23780,7 @@ function withLockOperationMutex(lockPath, run) {
23841
23780
  db.exec("BEGIN IMMEDIATE");
23842
23781
  began = db.inTransaction;
23843
23782
  if (!began)
23844
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2 ** attempt);
23783
+ sleepSync(2 ** attempt);
23845
23784
  }
23846
23785
  if (!began)
23847
23786
  throw new Error(`Could not acquire lock operation mutex for ${lockPath}.`);
@@ -24004,7 +23943,7 @@ function extractHolderPid(content) {
24004
23943
  // src/core/config/config-io.ts
24005
23944
  function readConfigText(configPath) {
24006
23945
  try {
24007
- return readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file");
23946
+ return readTextFile(configPath, "Config file");
24008
23947
  } catch (err) {
24009
23948
  if (err.code === "ENOENT")
24010
23949
  return;
@@ -28059,9 +27998,7 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
28059
27998
  "default",
28060
27999
  "quick",
28061
28000
  "thorough",
28062
- "memory-focus",
28063
28001
  "graph-refresh",
28064
- "frequent",
28065
28002
  "consolidate",
28066
28003
  "catchup",
28067
28004
  "reflect-distill",
@@ -28111,9 +28048,6 @@ var ExtraParamsSchema = exports_external.record(exports_external.unknown()).supe
28111
28048
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: issue.path, message: issue.message });
28112
28049
  }
28113
28050
  });
28114
- var LlmCapabilitiesSchema = exports_external.object({
28115
- structuredOutput: exports_external.boolean().optional()
28116
- }).passthrough();
28117
28051
  var LlmInvocationOverridesSchema = exports_external.object({
28118
28052
  temperature: exports_external.number().finite().optional(),
28119
28053
  maxTokens: positiveInt.optional(),
@@ -28169,15 +28103,13 @@ var LlmConnectionConfigSchema = exports_external.object({
28169
28103
  maxTokens: positiveInt.optional(),
28170
28104
  timeoutMs: timeoutMsField,
28171
28105
  concurrency: positiveInt.optional(),
28172
- capabilities: LlmCapabilitiesSchema.optional(),
28106
+ supportsJsonSchema: exports_external.boolean().optional(),
28173
28107
  extraParams: ExtraParamsSchema.optional(),
28174
28108
  contextLength: positiveInt.optional(),
28175
28109
  enableThinking: exports_external.boolean().optional(),
28176
28110
  reasoningEffort: nonEmptyString3.optional()
28177
28111
  }).passthrough();
28178
- var LlmProfileConfigSchema = LlmConnectionConfigSchema.extend({
28179
- supportsJsonSchema: exports_external.boolean().optional()
28180
- }).passthrough();
28112
+ var LlmProfileConfigSchema = LlmConnectionConfigSchema.passthrough();
28181
28113
  var AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
28182
28114
  var LlmEngineSchema = exports_external.object({
28183
28115
  kind: exports_external.literal("llm"),
@@ -28189,7 +28121,6 @@ var LlmEngineSchema = exports_external.object({
28189
28121
  maxTokens: positiveInt.optional(),
28190
28122
  timeoutMs: timeoutMsField,
28191
28123
  concurrency: positiveInt.optional(),
28192
- supportsJsonSchema: exports_external.boolean().optional(),
28193
28124
  extraParams: ExtraParamsSchema.optional(),
28194
28125
  contextLength: positiveInt.optional(),
28195
28126
  enableThinking: exports_external.boolean().optional(),
@@ -28219,7 +28150,6 @@ var AgentEngineSchema = exports_external.object({
28219
28150
  "temperature",
28220
28151
  "maxTokens",
28221
28152
  "concurrency",
28222
- "supportsJsonSchema",
28223
28153
  "extraParams",
28224
28154
  "contextLength",
28225
28155
  "enableThinking",
@@ -28585,7 +28515,7 @@ var SearchGraphBoostSchema = exports_external.object({
28585
28515
  hopBoostPerEntity: nonNegativeNumber.optional(),
28586
28516
  hopBoostCap: nonNegativeNumber.optional(),
28587
28517
  maxHops: positiveInt.max(3).optional(),
28588
- confidenceMode: exports_external.enum(["off", "blend", "multiply"]).default("blend").optional(),
28518
+ confidenceMode: exports_external.enum(["blend"]).default("blend").optional(),
28589
28519
  confidenceWeight: exports_external.number().finite().min(0).max(1).default(0.2).optional()
28590
28520
  }).passthrough();
28591
28521
  var SearchConfigSchema = exports_external.object({
@@ -29127,8 +29057,7 @@ function withMaintenanceStartBarrier(run) {
29127
29057
 
29128
29058
  // src/indexer/index-writer-lock.ts
29129
29059
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
29130
- var INDEX_WRITER_LOCK_STALE_AFTER_MS = 12 * 60 * 60 * 1000;
29131
- var DEFAULT_INDEX_WRITER_MAX_WAIT_MS = 10 * 60 * 1000;
29060
+ var DEFAULT_ASSET_MUTATION_MAX_WAIT_MS = 10 * 60 * 1000;
29132
29061
  var leaseContext = new AsyncLocalStorage2;
29133
29062
 
29134
29063
  // src/integrations/lockfile.ts
@@ -29926,9 +29855,14 @@ function existingDirectory(target) {
29926
29855
  throw cause;
29927
29856
  }
29928
29857
  }
29858
+ function reconcileDuplicateRoot(existing, candidate, sharedPath) {
29859
+ if (existing.writable === candidate.writable && existing.layout === candidate.layout)
29860
+ return;
29861
+ 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");
29862
+ }
29929
29863
  function taskRoots(config, resolutionBase = process.cwd()) {
29930
29864
  const sources = new Map((bundlesToSourceEntries(config) ?? []).map((source) => [source.name, source]));
29931
- const roots = [];
29865
+ const rootsByPath = new Map;
29932
29866
  for (const [bundleId, bundle] of Object.entries(config.bundles ?? {})) {
29933
29867
  if (bundle.enabled === false)
29934
29868
  continue;
@@ -29956,15 +29890,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
29956
29890
  }
29957
29891
  if (adapter !== "akm" && adapter !== "akm-task")
29958
29892
  continue;
29959
- roots.push({
29893
+ const candidate = {
29960
29894
  bundleId,
29961
29895
  root: componentRoot,
29962
29896
  bundleRoot,
29963
29897
  writable: component?.writable ?? resolveWritable(source),
29964
29898
  layout: adapter === "akm-task" ? "akm-task" : "akm-stash"
29965
- });
29899
+ };
29900
+ const existing = rootsByPath.get(componentRoot);
29901
+ if (existing) {
29902
+ reconcileDuplicateRoot(existing, candidate, componentRoot);
29903
+ continue;
29904
+ }
29905
+ rootsByPath.set(componentRoot, candidate);
29966
29906
  }
29967
- return roots;
29907
+ return [...rootsByPath.values()];
29968
29908
  }
29969
29909
  function summarize(plan) {
29970
29910
  const files = plan.files.map((file) => ({