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
@@ -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;
@@ -11521,6 +11524,7 @@ var SCRIPT_EXTENSIONS = new Set([
11521
11524
  ".kts"
11522
11525
  ]);
11523
11526
  var WORKFLOW_EXTENSIONS = [".md", ".yml"];
11527
+ var DERIVED_SUFFIX = ".derived";
11524
11528
  var KNOWN_TYPES = [
11525
11529
  "skill",
11526
11530
  "command",
@@ -11681,6 +11685,9 @@ function assetPathForName(assetType, typeRoot, name) {
11681
11685
  }
11682
11686
  function assetPathCandidatesForName(assetType, typeRoot, name) {
11683
11687
  const primary = assetPathForName(assetType, typeRoot, name);
11688
+ if (assetType === "memory" && !name.endsWith(DERIVED_SUFFIX)) {
11689
+ return [primary, assetPathForName(assetType, typeRoot, `${name}${DERIVED_SUFFIX}`)];
11690
+ }
11684
11691
  if (assetType !== "env")
11685
11692
  return [primary];
11686
11693
  const base = name === "default" ? "" : name.endsWith("/default") ? name.slice(0, -"default".length) : undefined;
@@ -14879,25 +14886,13 @@ var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
14879
14886
  // src/workflows/resource-limits.ts
14880
14887
  var WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
14881
14888
  var WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
14882
- var WORKFLOW_MAX_STEPS = 256;
14883
- var WORKFLOW_MAX_PARAMS = 128;
14884
- var WORKFLOW_MAX_ROUTE_BRANCHES = 256;
14885
14889
  var WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
14886
14890
  var WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
14887
14891
  var WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
14888
- var WORKFLOW_MAX_MAP_EXPANSION = 1e4;
14889
- var WORKFLOW_MAX_INPUTS = 64;
14890
- var WORKFLOW_MAX_OUTPUTS = 64;
14891
14892
  var WORKFLOW_MAX_CONCURRENCY = 64;
14892
- var WORKFLOW_MAX_GATE_LOOPS = 100;
14893
- var WORKFLOW_MAX_RETRIES = 100;
14894
14893
  var WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
14895
14894
  var WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
14896
14895
  var WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
14897
- var WORKFLOW_MAX_EXEC_ARGV = 64;
14898
- var WORKFLOW_MAX_EXEC_ARG_BYTES = 4096;
14899
- var WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
14900
- var WORKFLOW_MAX_EXEC_PASS_ENV = 32;
14901
14896
  var WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
14902
14897
  var WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
14903
14898
  var EXEC_CONTEXT_LIMITS_POSIX = {
@@ -14915,13 +14910,13 @@ function jsonBytes(value) {
14915
14910
  var WORKFLOW_MAX_EMBEDDED_CHILD_PLAN_BYTES = 1024 * 1024;
14916
14911
 
14917
14912
  // src/tasks/source/bounded-document.ts
14918
- var TASK_V3_MAX_SOURCE_BYTES = 1024 * 1024;
14919
14913
  var TASK_V3_MAX_JSON_DEPTH = 64;
14920
14914
  var TASK_V3_MAX_JSON_NODES = 1e4;
14921
14915
  var TASK_V3_MAX_COLLECTION_ITEMS = 1024;
14922
14916
  var TASK_V3_MAX_OBJECT_KEYS = 256;
14923
14917
  var TASK_V3_MAX_STRING_BYTES = 256 * 1024;
14924
14918
  var TASK_V3_MAX_SCHEDULES = 64;
14919
+ var TASK_V3_MAX_REDACT_NAMES = 32;
14925
14920
  function own2(value, key) {
14926
14921
  return Object.hasOwn(value, key);
14927
14922
  }
@@ -15210,9 +15205,6 @@ function readBoundedTaskSourceYaml(input, options) {
15210
15205
  if (typeof input.yaml !== "string") {
15211
15206
  throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source must be a string.`, "TASK_SOURCE_INVALID");
15212
15207
  }
15213
- if (utf8Bytes2(input.yaml) > TASK_V3_MAX_SOURCE_BYTES) {
15214
- throw new UsageError(`Invalid ${sourceLabel} at ${input.filePath}: source exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) resource limit.`, "TASK_SOURCE_INVALID");
15215
- }
15216
15208
  const lineCounter2 = new $LineCounter;
15217
15209
  let document;
15218
15210
  try {
@@ -15972,7 +15964,7 @@ function parseExecutionControls(input, ctx) {
15972
15964
  out.timeout = parseTimeoutTopLevel(input.timeout, ctx);
15973
15965
  if (own2(input, "redact")) {
15974
15966
  const names = parseStringArray(input.redact, ctx, ["redact"], {
15975
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
15967
+ max: TASK_V3_MAX_REDACT_NAMES,
15976
15968
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
15977
15969
  });
15978
15970
  if (new Set(names).size !== names.length)
@@ -15986,8 +15978,8 @@ function parseExecutionControls(input, ctx) {
15986
15978
  out.maxSteps = input.maxSteps;
15987
15979
  }
15988
15980
  if (own2(input, "maxRetries")) {
15989
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
15990
- sourceError(ctx, ["maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
15981
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
15982
+ sourceError(ctx, ["maxRetries"], "must be a non-negative safe integer.");
15991
15983
  }
15992
15984
  out.maxRetries = input.maxRetries;
15993
15985
  }
@@ -16047,9 +16039,6 @@ function parseInputDeclaration(name, raw, ctx) {
16047
16039
  function parseInputDeclarations(value, ctx) {
16048
16040
  const input = asRecord(value, ctx, ["inputs"]);
16049
16041
  const names = Object.keys(input);
16050
- if (names.length > WORKFLOW_MAX_PARAMS) {
16051
- sourceError(ctx, ["inputs"], `accepts at most ${WORKFLOW_MAX_PARAMS} declared inputs.`);
16052
- }
16053
16042
  const result = {};
16054
16043
  for (const name of names) {
16055
16044
  if (!INPUT_NAME_PATTERN.test(name)) {
@@ -16482,7 +16471,7 @@ function parseAkm(value, ctx) {
16482
16471
  out.timeout = parseTimeout(input.timeout, ctx);
16483
16472
  if (own2(input, "redact")) {
16484
16473
  const names = parseStringArray(input.redact, ctx, ["akm", "redact"], {
16485
- max: WORKFLOW_MAX_EXEC_PASS_ENV,
16474
+ max: TASK_V3_MAX_REDACT_NAMES,
16486
16475
  pattern: WORKFLOW_ENV_VAR_NAME_PATTERN
16487
16476
  });
16488
16477
  if (new Set(names).size !== names.length)
@@ -16496,8 +16485,8 @@ function parseAkm(value, ctx) {
16496
16485
  out.maxSteps = input.maxSteps;
16497
16486
  }
16498
16487
  if (own2(input, "maxRetries")) {
16499
- if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0 || input.maxRetries > WORKFLOW_MAX_RETRIES) {
16500
- sourceError(ctx, ["akm", "maxRetries"], `must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
16488
+ if (!Number.isSafeInteger(input.maxRetries) || input.maxRetries < 0) {
16489
+ sourceError(ctx, ["akm", "maxRetries"], "must be a non-negative safe integer.");
16501
16490
  }
16502
16491
  out.maxRetries = input.maxRetries;
16503
16492
  }
@@ -16814,9 +16803,6 @@ function optionalString(value, label) {
16814
16803
  return exactString(value, label);
16815
16804
  }
16816
16805
  function parseLegacyTaskYaml(input) {
16817
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
16818
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
16819
- }
16820
16806
  let source;
16821
16807
  try {
16822
16808
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -16864,7 +16850,7 @@ function validateCommonV2(data) {
16864
16850
  }
16865
16851
  }
16866
16852
  if (data.redact !== undefined && data.redact !== null) {
16867
- 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))) {
16853
+ 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))) {
16868
16854
  throw new Error("redact must contain only bounded environment variable names");
16869
16855
  }
16870
16856
  }
@@ -16990,8 +16976,8 @@ function migratedObject(data) {
16990
16976
  akm.maxSteps = data.maxSteps;
16991
16977
  }
16992
16978
  if (data.maxRetries !== undefined && data.maxRetries !== null) {
16993
- if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0 || data.maxRetries > WORKFLOW_MAX_RETRIES) {
16994
- throw new Error(`maxRetries must be from 0 through ${WORKFLOW_MAX_RETRIES}`);
16979
+ if (!Number.isSafeInteger(data.maxRetries) || data.maxRetries < 0) {
16980
+ throw new Error("maxRetries must be a non-negative integer");
16995
16981
  }
16996
16982
  akm.maxRetries = data.maxRetries;
16997
16983
  }
@@ -17250,9 +17236,6 @@ function exactString2(value, label, nonempty = false) {
17250
17236
  return value;
17251
17237
  }
17252
17238
  function parseV3RawYaml(input) {
17253
- if (input.bytes.byteLength > TASK_V3_MAX_SOURCE_BYTES) {
17254
- throw new Error(`task YAML exceeds the 1 MiB (${TASK_V3_MAX_SOURCE_BYTES}-byte) source resource limit`);
17255
- }
17256
17239
  let source;
17257
17240
  try {
17258
17241
  source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input.bytes);
@@ -17549,6 +17532,9 @@ function peekTaskSourceVersion(root) {
17549
17532
  return typeof value === "number" ? value : undefined;
17550
17533
  }
17551
17534
  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`.";
17535
+ function unmigratableVersionError(filePath, version, reason, detail) {
17536
+ return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version} and needs a human decision before it can run \u2014 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.");
17537
+ }
17552
17538
  function unsupportedVersionError(filePath, version) {
17553
17539
  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);
17554
17540
  }
@@ -17568,12 +17554,12 @@ function planInMemoryV4Bytes(version, yaml, filePath, workspaceRoot) {
17568
17554
  } else {
17569
17555
  const v3Outcome = planTaskToV3File(baseInput);
17570
17556
  if (v3Outcome.status !== "changed")
17571
- return;
17557
+ return { reason: v3Outcome.reason, detail: v3Outcome.detail };
17572
17558
  v3Bytes = v3Outcome.after;
17573
17559
  }
17574
17560
  const v4Outcome = planTaskToV4File({ ...baseInput, bytes: v3Bytes });
17575
17561
  if (v4Outcome.status !== "changed")
17576
- return;
17562
+ return { reason: v4Outcome.reason, detail: v4Outcome.detail };
17577
17563
  return v4Outcome.after.toString("utf8");
17578
17564
  }
17579
17565
  function parseTaskSource(input) {
@@ -17581,16 +17567,17 @@ function parseTaskSource(input) {
17581
17567
  const version = peekTaskSourceVersion(root);
17582
17568
  if (version !== undefined && version !== TASK_SOURCE_V4_VERSION) {
17583
17569
  if (version === 2 || version === 3) {
17584
- const v4Yaml = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17585
- if (v4Yaml !== undefined) {
17570
+ const shimmed = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17571
+ if (typeof shimmed === "string") {
17586
17572
  const v4 = parseTaskSourceV4({
17587
- yaml: v4Yaml,
17573
+ yaml: shimmed,
17588
17574
  filePath: input.filePath,
17589
17575
  ...input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}
17590
17576
  });
17591
17577
  warn(`akm: task ${input.filePath} uses schema v${version} \u2014 auto-read as v4; run \`akm migrate apply\` to rewrite it and silence this`);
17592
17578
  return Object.freeze({ version: 4, v4 });
17593
17579
  }
17580
+ throw unmigratableVersionError(input.filePath, version, shimmed.reason, shimmed.detail);
17594
17581
  }
17595
17582
  throw unsupportedVersionError(input.filePath, version);
17596
17583
  }
@@ -18453,7 +18440,7 @@ function validateStep(value, jobId, index, stepIds, options) {
18453
18440
  }
18454
18441
  validateMap(step.map, `step ${id} map`);
18455
18442
  validateRoute(step.route, `step ${id} route`);
18456
- optionalStringList(step.inputs, `step ${id} inputs`, WORKFLOW_MAX_INPUTS);
18443
+ optionalStringList(step.inputs, `step ${id} inputs`, Infinity);
18457
18444
  if (Array.isArray(step.inputs)) {
18458
18445
  for (const [inputIndex, input] of step.inputs.entries())
18459
18446
  validateReference(input, `step ${id} inputs[${inputIndex}]`);
@@ -18475,12 +18462,7 @@ function validateExec(value, location, options) {
18475
18462
  return;
18476
18463
  const exec = record(value, location);
18477
18464
  keys(exec, ["command", "cwd", "passEnv"], location);
18478
- stringList(exec.command, `${location}.command`, WORKFLOW_MAX_EXEC_ARGV, false);
18479
- for (const [index, argument] of exec.command.entries()) {
18480
- if (utf8Bytes(argument) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
18481
- fail2(`${location}.command[${index}] exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes`);
18482
- }
18483
- }
18465
+ stringList(exec.command, `${location}.command`, Infinity, false);
18484
18466
  try {
18485
18467
  rejectNulInArgv(exec.command);
18486
18468
  } catch (cause) {
@@ -18488,9 +18470,6 @@ function validateExec(value, location, options) {
18488
18470
  }
18489
18471
  optionalString2(exec.cwd, `${location}.cwd`);
18490
18472
  if (exec.cwd !== undefined) {
18491
- if (exec.cwd.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
18492
- fail2(`${location}.cwd exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters`);
18493
- }
18494
18473
  try {
18495
18474
  exec.cwd = canonicalizeWorkflowWorkingDirectory(exec.cwd, options.workspaceRoot);
18496
18475
  } catch (cause) {
@@ -18498,7 +18477,7 @@ function validateExec(value, location, options) {
18498
18477
  }
18499
18478
  }
18500
18479
  if (exec.passEnv !== undefined) {
18501
- stringList(exec.passEnv, `${location}.passEnv`, WORKFLOW_MAX_EXEC_PASS_ENV, false);
18480
+ stringList(exec.passEnv, `${location}.passEnv`, Infinity, false);
18502
18481
  }
18503
18482
  if (Array.isArray(exec.passEnv)) {
18504
18483
  for (const name of exec.passEnv) {
@@ -18549,8 +18528,8 @@ function validateRetry(value, location) {
18549
18528
  return;
18550
18529
  const retry = record(value, location);
18551
18530
  keys(retry, ["max", "on"], location);
18552
- if (!Number.isSafeInteger(retry.max) || retry.max < 0 || retry.max > WORKFLOW_MAX_RETRIES) {
18553
- fail2(`${location}.max must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}`);
18531
+ if (!Number.isSafeInteger(retry.max) || retry.max < 0) {
18532
+ fail2(`${location}.max must be a non-negative integer`);
18554
18533
  }
18555
18534
  stringList(retry.on, `${location}.on`, PROGRAM_RETRY_REASONS.length, false);
18556
18535
  for (const reason of retry.on) {
@@ -18580,8 +18559,8 @@ function validateRoute(value, location) {
18580
18559
  keys(route, ["input", "branches", "defaultStepId"], location);
18581
18560
  nonEmptyString2(route.input, `${location}.input`);
18582
18561
  validateReference(route.input, `${location}.input`);
18583
- if (!Array.isArray(route.branches) || route.branches.length === 0 || route.branches.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
18584
- fail2(`${location}.branches must contain 1 through ${WORKFLOW_MAX_ROUTE_BRANCHES} entries`);
18562
+ if (!Array.isArray(route.branches) || route.branches.length === 0) {
18563
+ fail2(`${location}.branches must be a non-empty array`);
18585
18564
  }
18586
18565
  const matches = new Set;
18587
18566
  for (const [index, value2] of route.branches.entries()) {
@@ -18601,8 +18580,8 @@ function validateGate(value, location) {
18601
18580
  return;
18602
18581
  const gate = record(value, location);
18603
18582
  keys(gate, ["maxLoops", "rubric"], location);
18604
- if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1 || gate.maxLoops > WORKFLOW_MAX_GATE_LOOPS)) {
18605
- fail2(`${location}.maxLoops must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}`);
18583
+ if (gate.maxLoops !== undefined && (!Number.isSafeInteger(gate.maxLoops) || gate.maxLoops < 1)) {
18584
+ fail2(`${location}.maxLoops must be an integer of at least 1`);
18606
18585
  }
18607
18586
  optionalString2(gate.rubric, `${location}.rubric`);
18608
18587
  }
@@ -18635,8 +18614,8 @@ function validateParams(value) {
18635
18614
  if (value === undefined)
18636
18615
  return;
18637
18616
  const params = record(value, "params");
18638
- if (Object.keys(params).length === 0 || Object.keys(params).length > WORKFLOW_MAX_PARAMS) {
18639
- fail2(`params must contain 1 through ${WORKFLOW_MAX_PARAMS} entries`);
18617
+ if (Object.keys(params).length === 0) {
18618
+ fail2(`params must contain at least one entry`);
18640
18619
  }
18641
18620
  for (const [name, schema] of Object.entries(params)) {
18642
18621
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18648,8 +18627,8 @@ function validateOutputs(value) {
18648
18627
  if (value === undefined)
18649
18628
  return;
18650
18629
  const outputs = record(value, "outputs");
18651
- if (Object.keys(outputs).length === 0 || Object.keys(outputs).length > WORKFLOW_MAX_OUTPUTS) {
18652
- fail2(`outputs must contain 1 through ${WORKFLOW_MAX_OUTPUTS} entries`);
18630
+ if (Object.keys(outputs).length === 0) {
18631
+ fail2(`outputs must contain at least one entry`);
18653
18632
  }
18654
18633
  for (const [name, declaration] of Object.entries(outputs)) {
18655
18634
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
@@ -18672,9 +18651,6 @@ function validateBudget(value) {
18672
18651
  fail2(`budget.${key} must be a positive integer`);
18673
18652
  }
18674
18653
  }
18675
- if (typeof budget.maxUnits === "number" && budget.maxUnits > WORKFLOW_MAX_MAP_EXPANSION) {
18676
- fail2(`budget.maxUnits must be at most ${WORKFLOW_MAX_MAP_EXPANSION}`);
18677
- }
18678
18654
  }
18679
18655
  function validateLlm(value, location) {
18680
18656
  if (value === undefined)
@@ -19258,12 +19234,6 @@ function checkXrefs(value, line, errors2) {
19258
19234
  }
19259
19235
  }
19260
19236
  function checkResourceLimits(draft, errors2) {
19261
- if (draft.steps.length > WORKFLOW_MAX_STEPS) {
19262
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_STEPS} steps.` });
19263
- }
19264
- if (Object.keys(draft.params ?? {}).length > WORKFLOW_MAX_PARAMS) {
19265
- errors2.push({ line: 1, message: `Workflow must contain at most ${WORKFLOW_MAX_PARAMS} parameters.` });
19266
- }
19267
19237
  for (const step of draft.steps) {
19268
19238
  if (step.instructions && utf8Bytes(step.instructions.text) > WORKFLOW_MAX_INSTRUCTION_BYTES) {
19269
19239
  errors2.push({
@@ -19625,9 +19595,6 @@ function parseParams(ctx, raw) {
19625
19595
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19626
19596
  return;
19627
19597
  }
19628
- if (Object.keys(raw).length > WORKFLOW_MAX_PARAMS) {
19629
- ctx.err(["params"], `"params" must contain at most ${WORKFLOW_MAX_PARAMS} entries.`);
19630
- }
19631
19598
  const params = {};
19632
19599
  for (const [paramName, value] of Object.entries(raw)) {
19633
19600
  if (!INPUT_NAME_PATTERN.test(paramName)) {
@@ -19653,9 +19620,6 @@ function parseOutputs(ctx, raw) {
19653
19620
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19654
19621
  return;
19655
19622
  }
19656
- if (Object.keys(raw).length > WORKFLOW_MAX_OUTPUTS) {
19657
- ctx.err(["outputs"], `"outputs" must contain at most ${WORKFLOW_MAX_OUTPUTS} entries.`);
19658
- }
19659
19623
  const outputs = {};
19660
19624
  for (const [outputName, value] of Object.entries(raw)) {
19661
19625
  const path13 = ["outputs", outputName];
@@ -19747,10 +19711,10 @@ function parseBudget(ctx, raw) {
19747
19711
  }
19748
19712
  }
19749
19713
  if (raw.max_units !== undefined) {
19750
- if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1 && raw.max_units <= WORKFLOW_MAX_MAP_EXPANSION) {
19714
+ if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
19751
19715
  budget.maxUnits = raw.max_units;
19752
19716
  } else {
19753
- ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer from 1 through ${WORKFLOW_MAX_MAP_EXPANSION}.`);
19717
+ ctx.err([...path13, "max_units"], `"budget.max_units" must be an integer >= 1.`);
19754
19718
  }
19755
19719
  }
19756
19720
  return Object.keys(budget).length > 0 ? budget : undefined;
@@ -19760,9 +19724,6 @@ function parseSteps(ctx, raw) {
19760
19724
  ctx.err(["steps"], `"steps" is required and must be a list with at least one step.`);
19761
19725
  return [];
19762
19726
  }
19763
- if (raw.length > WORKFLOW_MAX_STEPS) {
19764
- ctx.err(["steps"], `"steps" must contain at most ${WORKFLOW_MAX_STEPS} entries.`);
19765
- }
19766
19727
  const idIndex = new Map;
19767
19728
  raw.forEach((rawStep, index) => {
19768
19729
  if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
@@ -19933,10 +19894,6 @@ function parseExecPassEnv(ctx, raw, path13, stepLabel) {
19933
19894
  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.`);
19934
19895
  return;
19935
19896
  }
19936
- if (raw.length > WORKFLOW_MAX_EXEC_PASS_ENV) {
19937
- 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.`);
19938
- return;
19939
- }
19940
19897
  const names = [];
19941
19898
  for (const [index, entry] of raw.entries()) {
19942
19899
  if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
@@ -19956,10 +19913,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
19956
19913
  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.`);
19957
19914
  return;
19958
19915
  }
19959
- if (raw.length > WORKFLOW_MAX_EXEC_ARGV) {
19960
- ctx.err(path13, `${stepLabel} "exec.command" must have at most ${WORKFLOW_MAX_EXEC_ARGV} entries.`);
19961
- return;
19962
- }
19963
19916
  const argv = [];
19964
19917
  for (const [index, entry] of raw.entries()) {
19965
19918
  if (typeof entry !== "string" || entry === "") {
@@ -19970,10 +19923,6 @@ function parseExecCommand(ctx, raw, path13, stepLabel) {
19970
19923
  ctx.err([...path13, index], `${stepLabel} "exec.command[${index}]" may not contain NUL bytes.`);
19971
19924
  return;
19972
19925
  }
19973
- if (utf8Bytes(entry) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
19974
- ctx.err(path13, `${stepLabel} "exec.command[${index}]" exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes.`);
19975
- return;
19976
- }
19977
19926
  argv.push(entry);
19978
19927
  }
19979
19928
  return argv;
@@ -19986,10 +19935,6 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
19986
19935
  return;
19987
19936
  }
19988
19937
  const value = raw.trim();
19989
- if (value.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
19990
- ctx.err(path13, `${stepLabel} "exec.cwd" exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters.`);
19991
- return;
19992
- }
19993
19938
  if (!isContainedRelativePath(value)) {
19994
19939
  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.`);
19995
19940
  return;
@@ -20023,10 +19968,10 @@ function parseMap(ctx, raw, path13, stepLabel) {
20023
19968
  }
20024
19969
  let concurrency;
20025
19970
  if (raw.concurrency !== undefined) {
20026
- if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0 && raw.concurrency <= WORKFLOW_MAX_CONCURRENCY) {
20027
- concurrency = raw.concurrency;
19971
+ if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
19972
+ concurrency = Math.min(raw.concurrency, WORKFLOW_MAX_CONCURRENCY);
20028
19973
  } else {
20029
- ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}.`);
19974
+ ctx.err([...path13, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
20030
19975
  }
20031
19976
  }
20032
19977
  const reducer = parseEnumField(ctx, raw.reducer, [...path13, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
@@ -20058,9 +20003,6 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20058
20003
  if (!Array.isArray(raw.when) || raw.when.length === 0) {
20059
20004
  ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
20060
20005
  } else {
20061
- if (raw.when.length > WORKFLOW_MAX_ROUTE_BRANCHES) {
20062
- ctx.err(whenPath, `${stepLabel} "when" must contain at most ${WORKFLOW_MAX_ROUTE_BRANCHES} branches.`);
20063
- }
20064
20006
  const seenMatches = new Map;
20065
20007
  raw.when.forEach((branch, i) => {
20066
20008
  const branchPath = [...whenPath, i];
@@ -20116,9 +20058,6 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20116
20058
  ctx.err(path13, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
20117
20059
  return;
20118
20060
  }
20119
- if (raw.length > WORKFLOW_MAX_INPUTS) {
20120
- ctx.err(path13, `${stepLabel} "inputs" must contain at most ${WORKFLOW_MAX_INPUTS} entries.`);
20121
- }
20122
20061
  const out = [];
20123
20062
  const seen = new Set;
20124
20063
  raw.forEach((entry, i) => {
@@ -20145,10 +20084,10 @@ function parseGate(ctx, raw, path13, stepLabel) {
20145
20084
  checkUnknownKeys(ctx, raw, path13, GATE_KEYS, `${stepLabel} "gate"`);
20146
20085
  const gate = {};
20147
20086
  if (raw.max_loops !== undefined) {
20148
- if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1 && raw.max_loops <= WORKFLOW_MAX_GATE_LOOPS) {
20087
+ if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
20149
20088
  gate.maxLoops = raw.max_loops;
20150
20089
  } else {
20151
- ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}.`);
20090
+ ctx.err([...path13, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer of at least 1.`);
20152
20091
  }
20153
20092
  }
20154
20093
  return gate;
@@ -20174,8 +20113,8 @@ function parseRetry(ctx, raw, path13, stepLabel) {
20174
20113
  }
20175
20114
  checkUnknownKeys(ctx, raw, path13, RETRY_KEYS, `${stepLabel} "retry"`);
20176
20115
  let ok = true;
20177
- if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0 && raw.max <= WORKFLOW_MAX_RETRIES)) {
20178
- ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
20116
+ if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
20117
+ ctx.err([...path13, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
20179
20118
  ok = false;
20180
20119
  }
20181
20120
  const on = [];
@@ -23763,7 +23702,7 @@ function withLockOperationMutex(lockPath, run) {
23763
23702
  db.exec("BEGIN IMMEDIATE");
23764
23703
  began = db.inTransaction;
23765
23704
  if (!began)
23766
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 2 ** attempt);
23705
+ sleepSync(2 ** attempt);
23767
23706
  }
23768
23707
  if (!began)
23769
23708
  throw new Error(`Could not acquire lock operation mutex for ${lockPath}.`);
@@ -23926,7 +23865,7 @@ function extractHolderPid(content) {
23926
23865
  // src/core/config/config-io.ts
23927
23866
  function readConfigText(configPath) {
23928
23867
  try {
23929
- return readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file");
23868
+ return readTextFile(configPath, "Config file");
23930
23869
  } catch (err) {
23931
23870
  if (err.code === "ENOENT")
23932
23871
  return;
@@ -27981,9 +27920,7 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
27981
27920
  "default",
27982
27921
  "quick",
27983
27922
  "thorough",
27984
- "memory-focus",
27985
27923
  "graph-refresh",
27986
- "frequent",
27987
27924
  "consolidate",
27988
27925
  "catchup",
27989
27926
  "reflect-distill",
@@ -28033,9 +27970,6 @@ var ExtraParamsSchema = exports_external.record(exports_external.unknown()).supe
28033
27970
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: issue.path, message: issue.message });
28034
27971
  }
28035
27972
  });
28036
- var LlmCapabilitiesSchema = exports_external.object({
28037
- structuredOutput: exports_external.boolean().optional()
28038
- }).passthrough();
28039
27973
  var LlmInvocationOverridesSchema = exports_external.object({
28040
27974
  temperature: exports_external.number().finite().optional(),
28041
27975
  maxTokens: positiveInt.optional(),
@@ -28091,15 +28025,13 @@ var LlmConnectionConfigSchema = exports_external.object({
28091
28025
  maxTokens: positiveInt.optional(),
28092
28026
  timeoutMs: timeoutMsField,
28093
28027
  concurrency: positiveInt.optional(),
28094
- capabilities: LlmCapabilitiesSchema.optional(),
28028
+ supportsJsonSchema: exports_external.boolean().optional(),
28095
28029
  extraParams: ExtraParamsSchema.optional(),
28096
28030
  contextLength: positiveInt.optional(),
28097
28031
  enableThinking: exports_external.boolean().optional(),
28098
28032
  reasoningEffort: nonEmptyString3.optional()
28099
28033
  }).passthrough();
28100
- var LlmProfileConfigSchema = LlmConnectionConfigSchema.extend({
28101
- supportsJsonSchema: exports_external.boolean().optional()
28102
- }).passthrough();
28034
+ var LlmProfileConfigSchema = LlmConnectionConfigSchema.passthrough();
28103
28035
  var AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
28104
28036
  var LlmEngineSchema = exports_external.object({
28105
28037
  kind: exports_external.literal("llm"),
@@ -28111,7 +28043,6 @@ var LlmEngineSchema = exports_external.object({
28111
28043
  maxTokens: positiveInt.optional(),
28112
28044
  timeoutMs: timeoutMsField,
28113
28045
  concurrency: positiveInt.optional(),
28114
- supportsJsonSchema: exports_external.boolean().optional(),
28115
28046
  extraParams: ExtraParamsSchema.optional(),
28116
28047
  contextLength: positiveInt.optional(),
28117
28048
  enableThinking: exports_external.boolean().optional(),
@@ -28141,7 +28072,6 @@ var AgentEngineSchema = exports_external.object({
28141
28072
  "temperature",
28142
28073
  "maxTokens",
28143
28074
  "concurrency",
28144
- "supportsJsonSchema",
28145
28075
  "extraParams",
28146
28076
  "contextLength",
28147
28077
  "enableThinking",
@@ -28507,7 +28437,7 @@ var SearchGraphBoostSchema = exports_external.object({
28507
28437
  hopBoostPerEntity: nonNegativeNumber.optional(),
28508
28438
  hopBoostCap: nonNegativeNumber.optional(),
28509
28439
  maxHops: positiveInt.max(3).optional(),
28510
- confidenceMode: exports_external.enum(["off", "blend", "multiply"]).default("blend").optional(),
28440
+ confidenceMode: exports_external.enum(["blend"]).default("blend").optional(),
28511
28441
  confidenceWeight: exports_external.number().finite().min(0).max(1).default(0.2).optional()
28512
28442
  }).passthrough();
28513
28443
  var SearchConfigSchema = exports_external.object({
@@ -29049,8 +28979,7 @@ function withMaintenanceStartBarrier(run) {
29049
28979
 
29050
28980
  // src/indexer/index-writer-lock.ts
29051
28981
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
29052
- var INDEX_WRITER_LOCK_STALE_AFTER_MS = 12 * 60 * 60 * 1000;
29053
- var DEFAULT_INDEX_WRITER_MAX_WAIT_MS = 10 * 60 * 1000;
28982
+ var DEFAULT_ASSET_MUTATION_MAX_WAIT_MS = 10 * 60 * 1000;
29054
28983
  var leaseContext = new AsyncLocalStorage2;
29055
28984
 
29056
28985
  // src/integrations/lockfile.ts
@@ -29848,9 +29777,14 @@ function existingDirectory(target) {
29848
29777
  throw cause;
29849
29778
  }
29850
29779
  }
29780
+ function reconcileDuplicateRoot(existing, candidate, sharedPath) {
29781
+ if (existing.writable === candidate.writable && existing.layout === candidate.layout)
29782
+ return;
29783
+ 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");
29784
+ }
29851
29785
  function taskRoots(config, resolutionBase = process.cwd()) {
29852
29786
  const sources = new Map((bundlesToSourceEntries(config) ?? []).map((source) => [source.name, source]));
29853
- const roots = [];
29787
+ const rootsByPath = new Map;
29854
29788
  for (const [bundleId, bundle] of Object.entries(config.bundles ?? {})) {
29855
29789
  if (bundle.enabled === false)
29856
29790
  continue;
@@ -29878,15 +29812,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
29878
29812
  }
29879
29813
  if (adapter !== "akm" && adapter !== "akm-task")
29880
29814
  continue;
29881
- roots.push({
29815
+ const candidate = {
29882
29816
  bundleId,
29883
29817
  root: componentRoot,
29884
29818
  bundleRoot,
29885
29819
  writable: component?.writable ?? resolveWritable(source),
29886
29820
  layout: adapter === "akm-task" ? "akm-task" : "akm-stash"
29887
- });
29821
+ };
29822
+ const existing = rootsByPath.get(componentRoot);
29823
+ if (existing) {
29824
+ reconcileDuplicateRoot(existing, candidate, componentRoot);
29825
+ continue;
29826
+ }
29827
+ rootsByPath.set(componentRoot, candidate);
29888
29828
  }
29889
- return roots;
29829
+ return [...rootsByPath.values()];
29890
29830
  }
29891
29831
  function summarize(plan) {
29892
29832
  const files = plan.files.map((file) => ({
@@ -7,11 +7,10 @@ export function readCurrentLlmEngine(config) {
7
7
  const engine = name ? config.engines?.[name] : undefined;
8
8
  if (!engine || engine.kind !== "llm")
9
9
  return undefined;
10
- const { kind: _kind, supportsJsonSchema, timeoutMs, ...connection } = engine;
10
+ const { kind: _kind, timeoutMs, ...connection } = engine;
11
11
  return {
12
12
  ...connection,
13
13
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
14
- ...(supportsJsonSchema !== undefined ? { capabilities: { structuredOutput: supportsJsonSchema } } : {}),
15
14
  };
16
15
  }
17
16
  export function readAgentEngineSelection(config) {
@@ -45,15 +44,13 @@ export function writeLlmEngine(config, llm) {
45
44
  const endpoint = llm.endpoint.endsWith("/chat/completions")
46
45
  ? llm.endpoint
47
46
  : `${llm.endpoint.replace(/\/$/, "")}/chat/completions`;
48
- const { capabilities, ...connection } = llm;
49
47
  return {
50
48
  engines: {
51
49
  ...(config.engines ?? {}),
52
50
  [name]: {
53
- ...connection,
51
+ ...llm,
54
52
  kind: "llm",
55
53
  endpoint,
56
- ...(capabilities?.structuredOutput !== undefined ? { supportsJsonSchema: capabilities.structuredOutput } : {}),
57
54
  },
58
55
  },
59
56
  defaults: { ...(config.defaults ?? {}), engine: config.defaults?.engine ?? name, llmEngine: name },
@@ -17,14 +17,6 @@ import { hasRegistryUrlCredentials } from "../core/registry-url.js";
17
17
  import { allowPrivateRegistryFixtureForTests, cancelRegistryResponse, fetchRegistryResponse, } from "../registry/network.js";
18
18
  import { parseRegistryRef } from "../registry/resolve.js";
19
19
  // ── Default selections ──────────────────────────────────────────────────────
20
- /**
21
- * Registry stash IDs that are pre-selected by default during setup.
22
- * IDs must match the `id` field in the official registry index and have a
23
- * matching target in AUTHENTICATED_DEFAULT_TARGETS.
24
- *
25
- * The target binding is intentionally separate from display metadata.
26
- */
27
- export const DEFAULT_SELECTED_STASH_IDS = ["itlackey/akm-stash"];
28
20
  const AUTHENTICATED_DEFAULT_TARGETS = {
29
21
  "itlackey/akm-stash": {
30
22
  installType: "git",