akm-cli 0.9.6 → 0.9.8-beta.1

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 (135) hide show
  1. package/CHANGELOG.md +408 -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.js +2 -21
  8. package/dist/commands/health/checks.js +0 -25
  9. package/dist/commands/health/improve-metrics.js +8 -34
  10. package/dist/commands/health/windows.js +0 -4
  11. package/dist/commands/health.js +1 -35
  12. package/dist/commands/improve/consolidate/eligibility.js +11 -5
  13. package/dist/commands/improve/extract.js +36 -32
  14. package/dist/commands/improve/improve-cli.js +1 -1
  15. package/dist/commands/improve/improve-strategies.js +0 -4
  16. package/dist/commands/improve/memory/memory-belief.js +15 -5
  17. package/dist/commands/improve/memory/memory-contradiction-detect.js +16 -25
  18. package/dist/commands/improve/memory/memory-improve.js +9 -20
  19. package/dist/commands/improve/preparation.js +53 -37
  20. package/dist/commands/improve/reflect.js +14 -18
  21. package/dist/commands/lint/base-linter.js +182 -19
  22. package/dist/commands/lint/index.js +21 -9
  23. package/dist/commands/migrate/config-extra-params.js +61 -0
  24. package/dist/commands/migrate/dead-residue.js +113 -0
  25. package/dist/commands/migrate/stale-txn.js +49 -0
  26. package/dist/commands/migrate-cli.js +42 -1
  27. package/dist/commands/proposal/proposal.js +1 -21
  28. package/dist/commands/proposal/repository.js +0 -4
  29. package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -6
  30. package/dist/commands/read/curate.js +51 -18
  31. package/dist/commands/read/search-cli.js +24 -1
  32. package/dist/commands/read/show.js +2 -1
  33. package/dist/commands/sources/installed-stashes.js +5 -1
  34. package/dist/commands/sources/self-update.js +38 -1
  35. package/dist/commands/sources/sources-cli.js +17 -1
  36. package/dist/commands/tasks/tasks.js +0 -8
  37. package/dist/commands/url-checker.js +20 -28
  38. package/dist/core/adapter/adapters/agent-skills-adapter.js +2 -6
  39. package/dist/core/adapter/adapters/akm-adapter.js +2 -3
  40. package/dist/core/adapter/adapters/akm-lint.js +2 -20
  41. package/dist/core/adapter/adapters/akm-task-adapter.js +2 -6
  42. package/dist/core/adapter/adapters/akm-workflow-adapter.js +2 -6
  43. package/dist/core/adapter/adapters/dotenv-adapter.js +2 -22
  44. package/dist/core/adapter/adapters/generic-files-adapter.js +3 -9
  45. package/dist/core/adapter/adapters/llm-wiki-adapter.js +2 -6
  46. package/dist/core/adapter/adapters/okf-adapter.js +7 -18
  47. package/dist/core/adapter/adapters/shared.js +2 -0
  48. package/dist/core/adapter/adapters/tool-dir-shared.js +3 -9
  49. package/dist/core/adapter/adapters/website-snapshot-adapter.js +2 -6
  50. package/dist/core/adapter/validate-context.js +1 -3
  51. package/dist/core/asset/asset-placement.js +14 -5
  52. package/dist/core/asset/frontmatter.js +212 -0
  53. package/dist/core/asset/memory-archive.js +97 -0
  54. package/dist/core/common.js +66 -2
  55. package/dist/core/config/config-walker.js +6 -10
  56. package/dist/core/config/config.js +11 -8
  57. package/dist/core/config/engine-semantics.js +0 -2
  58. package/dist/core/extra-params.js +17 -13
  59. package/dist/core/improve-result.js +1 -3
  60. package/dist/core/json-schema.js +9 -11
  61. package/dist/core/state/migrations.js +52 -2
  62. package/dist/core/state-db.js +2 -1
  63. package/dist/execution/executable-identity.js +1 -3
  64. package/dist/execution/guarded-source.js +1 -6
  65. package/dist/indexer/bundle-identity-guard.js +6 -1
  66. package/dist/indexer/db/graph-db.js +139 -154
  67. package/dist/indexer/ensure-index.js +11 -19
  68. package/dist/indexer/graph/graph-boost.js +23 -34
  69. package/dist/indexer/graph/graph-extraction.js +12 -2
  70. package/dist/indexer/indexer.js +1 -1
  71. package/dist/indexer/lookup/adapter-concept-owner.js +12 -9
  72. package/dist/indexer/passes/memory-inference.js +7 -2
  73. package/dist/indexer/scan/drain-dir.js +2 -4
  74. package/dist/indexer/search/db-search.js +3 -3
  75. package/dist/indexer/search/fts-query.js +10 -15
  76. package/dist/indexer/search/search-source.js +0 -13
  77. package/dist/indexer/usage/usage-events.js +9 -1
  78. package/dist/indexer/walk/walker.js +11 -6
  79. package/dist/integrations/harnesses/claude/result-extractor.js +30 -15
  80. package/dist/integrations/harnesses/codex/result-extractor.js +43 -6
  81. package/dist/integrations/harnesses/copilot/result-extractor.js +39 -12
  82. package/dist/integrations/harnesses/gemini/result-extractor.js +40 -12
  83. package/dist/integrations/harnesses/index.js +0 -4
  84. package/dist/integrations/harnesses/openhands/result-extractor.js +51 -19
  85. package/dist/integrations/harnesses/pi/result-extractor.js +45 -12
  86. package/dist/integrations/lockfile.js +0 -14
  87. package/dist/integrations/session-logs/index.js +0 -81
  88. package/dist/llm/client.js +0 -12
  89. package/dist/llm/memory-infer.js +1 -3
  90. package/dist/llm/usage-telemetry.js +1 -3
  91. package/dist/registry/create-provider-registry.js +4 -0
  92. package/dist/registry/factory.js +4 -0
  93. package/dist/registry/resolve.js +23 -8
  94. package/dist/runtime.js +0 -12
  95. package/dist/scripts/akm-migrate-node.js +155 -251
  96. package/dist/scripts/akm-migrate.js +155 -251
  97. package/dist/setup/setup.js +6 -12
  98. package/dist/sources/providers/git-install.js +7 -2
  99. package/dist/sources/providers/tar-utils.js +1 -7
  100. package/dist/sources/snapshot-fetchers/content-extract.js +0 -17
  101. package/dist/sources/snapshot-fetchers/website-ingest.js +126 -0
  102. package/dist/storage/managed-db.js +20 -7
  103. package/dist/storage/repositories/events-repository.js +0 -81
  104. package/dist/storage/repositories/index-connection.js +45 -3
  105. package/dist/storage/repositories/index-entries-repository.js +0 -17
  106. package/dist/storage/repositories/index-fts-repository.js +24 -30
  107. package/dist/storage/repositories/index-utility-repository.js +0 -57
  108. package/dist/storage/repositories/index-vec-repository.js +25 -27
  109. package/dist/storage/repositories/task-history-repository.js +9 -3
  110. package/dist/tasks/backends/cron.js +49 -9
  111. package/dist/tasks/backends/launchd.js +8 -18
  112. package/dist/tasks/resolve-akm-bin.js +17 -2
  113. package/dist/tasks/run/task-history.js +21 -31
  114. package/dist/tasks/scheduler-invocation.js +8 -1
  115. package/dist/tasks/scheduler-sync.js +1 -6
  116. package/dist/tasks/source/bounded-document.js +1 -14
  117. package/dist/tasks/source/parse-task-source.js +23 -9
  118. package/dist/workflows/exec/child-workflow.js +1 -1
  119. package/dist/workflows/exec/native-executor.js +2 -2
  120. package/dist/workflows/exec/step-work.js +5 -17
  121. package/dist/workflows/exec/worktree.js +40 -6
  122. package/dist/workflows/freeze/task-bindings.js +2 -4
  123. package/dist/workflows/ir/compile.js +3 -14
  124. package/dist/workflows/ir/schema-v4.js +4 -6
  125. package/dist/workflows/ir/schema.js +2 -5
  126. package/dist/workflows/parser.js +23 -26
  127. package/dist/workflows/source-files.js +8 -13
  128. package/dist/workflows/source-ir/schema.js +1 -19
  129. package/docs/migration/v0.9.0-troubleshooting.md +12 -2
  130. package/docs/reference/cli.md +7 -1
  131. package/docs/reference/workflow-schema.md +24 -0
  132. package/package.json +2 -5
  133. package/dist/assets/improve-strategies/frequent.json +0 -15
  134. package/dist/assets/improve-strategies/memory-focus.json +0 -15
  135. package/dist/workflows/source-ir/compare.js +0 -17
@@ -9453,6 +9453,12 @@ function stripJsonComments(text) {
9453
9453
  }
9454
9454
  return result;
9455
9455
  }
9456
+ function toPosix(input) {
9457
+ return input.replace(/\\/g, "/");
9458
+ }
9459
+ function compareCodePoints(left, right) {
9460
+ return left < right ? -1 : left > right ? 1 : 0;
9461
+ }
9456
9462
  function isContainedRelativePath(value) {
9457
9463
  if (value === "" || value.startsWith("/") || value.startsWith("\\") || value.startsWith("~"))
9458
9464
  return false;
@@ -9505,6 +9511,40 @@ function asNonEmptyString(value) {
9505
9511
  const trimmed = value.trim();
9506
9512
  return trimmed.length > 0 ? trimmed : undefined;
9507
9513
  }
9514
+ var ENV_ASSIGN_LINE_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
9515
+ function scanEnvKeyNames(text) {
9516
+ const keys = [];
9517
+ const seen = new Set;
9518
+ for (const line of text.split(/\r?\n/)) {
9519
+ const m = line.match(ENV_ASSIGN_LINE_RE);
9520
+ if (!m)
9521
+ continue;
9522
+ const key = m[1];
9523
+ if (!key)
9524
+ continue;
9525
+ if (seen.has(key))
9526
+ continue;
9527
+ seen.add(key);
9528
+ keys.push(key);
9529
+ }
9530
+ return keys;
9531
+ }
9532
+ function wellFormedUnicode(value) {
9533
+ for (let index = 0;index < value.length; index += 1) {
9534
+ const code = value.charCodeAt(index);
9535
+ if (code >= 55296 && code <= 56319) {
9536
+ const next = value.charCodeAt(index + 1);
9537
+ if (!(next >= 56320 && next <= 57343))
9538
+ return false;
9539
+ index += 1;
9540
+ } else if (code >= 56320 && code <= 57343)
9541
+ return false;
9542
+ }
9543
+ return true;
9544
+ }
9545
+ function isRecord(value) {
9546
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9547
+ }
9508
9548
  function isProcessAlive(pid) {
9509
9549
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
9510
9550
  return false;
@@ -11524,6 +11564,7 @@ var SCRIPT_EXTENSIONS = new Set([
11524
11564
  ".kts"
11525
11565
  ]);
11526
11566
  var WORKFLOW_EXTENSIONS = [".md", ".yml"];
11567
+ var DERIVED_SUFFIX = ".derived";
11527
11568
  var KNOWN_TYPES = [
11528
11569
  "skill",
11529
11570
  "command",
@@ -11546,9 +11587,6 @@ function isKnownType(type) {
11546
11587
  var DEPRECATED_REJECTED_TYPES = new Set(["tool", "vault"]);
11547
11588
 
11548
11589
  // src/core/asset/asset-placement.ts
11549
- function toPosix(input) {
11550
- return input.replace(/\\/g, "/");
11551
- }
11552
11590
  var workflowSpec = {
11553
11591
  isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path5.extname(fileName).toLowerCase()),
11554
11592
  toCanonicalName: (typeRoot, filePath) => {
@@ -11684,6 +11722,9 @@ function assetPathForName(assetType, typeRoot, name) {
11684
11722
  }
11685
11723
  function assetPathCandidatesForName(assetType, typeRoot, name) {
11686
11724
  const primary = assetPathForName(assetType, typeRoot, name);
11725
+ if (assetType === "memory" && !name.endsWith(DERIVED_SUFFIX)) {
11726
+ return [primary, assetPathForName(assetType, typeRoot, `${name}${DERIVED_SUFFIX}`)];
11727
+ }
11687
11728
  if (assetType !== "env")
11688
11729
  return [primary];
11689
11730
  const base = name === "default" ? "" : name.endsWith("/default") ? name.slice(0, -"default".length) : undefined;
@@ -12646,6 +12687,7 @@ function readTags(value) {
12646
12687
  const tags = value.filter((tag) => typeof tag === "string" && tag.trim().length > 0);
12647
12688
  return tags.length > 0 ? tags : undefined;
12648
12689
  }
12690
+ var RESERVED_FILES = new Set(["index.md", "log.md"]);
12649
12691
  function checkMissingUpdated(data, frontmatterText) {
12650
12692
  return frontmatterText !== null && !("updated" in data);
12651
12693
  }
@@ -12783,12 +12825,8 @@ var NAME_MAX = 64;
12783
12825
  var DESCRIPTION_MAX = 1024;
12784
12826
  var RESERVED_NAME_WORDS = ["anthropic", "claude"];
12785
12827
  var NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
12786
- var MAX_CONTENT_CHARS = 1e5;
12787
- function toPosix2(p) {
12788
- return p.replace(/\\/g, "/");
12789
- }
12790
12828
  function skillPackage(relPath) {
12791
- const posix = toPosix2(relPath);
12829
+ const posix = toPosix(relPath);
12792
12830
  const segs = posix.split("/").filter((s) => s.length > 0);
12793
12831
  if (segs.length < 2 || segs[segs.length - 1] !== SKILL_MANIFEST)
12794
12832
  return null;
@@ -12817,7 +12855,7 @@ function recognize(c, file) {
12817
12855
  adapterId: "agent-skills",
12818
12856
  type: "skill",
12819
12857
  name,
12820
- content: body.length > MAX_CONTENT_CHARS ? body.slice(0, MAX_CONTENT_CHARS) : body
12858
+ content: body
12821
12859
  };
12822
12860
  if (description !== undefined)
12823
12861
  doc.description = description;
@@ -12905,7 +12943,7 @@ async function validate(_c, changes, ctx) {
12905
12943
  if (seenDirs.has(pkg.conceptId))
12906
12944
  continue;
12907
12945
  seenDirs.add(pkg.conceptId);
12908
- diagnostics.push(...skillFieldDiagnostics(toPosix2(change.path), pkg.dirName, parseFrontmatter(raw).data));
12946
+ diagnostics.push(...skillFieldDiagnostics(toPosix(change.path), pkg.dirName, parseFrontmatter(raw).data));
12909
12947
  }
12910
12948
  diagnostics.push(...await missingManifestDiagnostics(ctx));
12911
12949
  return diagnostics;
@@ -14764,24 +14802,6 @@ import path14 from "path";
14764
14802
 
14765
14803
  // src/commands/env/env.ts
14766
14804
  var import_dotenv = __toESM(require_main(), 1);
14767
- var ASSIGN_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
14768
- function scanEnvKeyNames(text) {
14769
- const keys = [];
14770
- const seen = new Set;
14771
- for (const line of text.split(/\r?\n/)) {
14772
- const m = line.match(ASSIGN_RE);
14773
- if (!m)
14774
- continue;
14775
- const key = m[1];
14776
- if (!key)
14777
- continue;
14778
- if (seen.has(key))
14779
- continue;
14780
- seen.add(key);
14781
- keys.push(key);
14782
- }
14783
- return keys;
14784
- }
14785
14805
 
14786
14806
  // src/commands/lint/env-key-rules.ts
14787
14807
  var DANGEROUS_ENV_KEYS = new Set([
@@ -14919,19 +14939,6 @@ function own2(value, key) {
14919
14939
  function utf8Bytes2(value) {
14920
14940
  return new TextEncoder().encode(value).byteLength;
14921
14941
  }
14922
- function wellFormedUnicode(value) {
14923
- for (let index = 0;index < value.length; index += 1) {
14924
- const code = value.charCodeAt(index);
14925
- if (code >= 55296 && code <= 56319) {
14926
- const next = value.charCodeAt(index + 1);
14927
- if (!(next >= 56320 && next <= 57343))
14928
- return false;
14929
- index += 1;
14930
- } else if (code >= 56320 && code <= 57343)
14931
- return false;
14932
- }
14933
- return true;
14934
- }
14935
14942
  function sourceError(ctx, fieldPath, detail) {
14936
14943
  const dotted = fieldPath.length === 0 ? "$" : fieldPath.reduce((display, segment) => typeof segment === "number" ? `${display}[${segment}]` : display.length > 0 ? `${display}.${segment}` : segment, "");
14937
14944
  const line = ctx.lineAt?.(fieldPath);
@@ -15343,9 +15350,6 @@ function pointerFor(path10) {
15343
15350
  function pushIssue(issues, path10, keyword, kind, message) {
15344
15351
  issues.push({ path: [...path10], pointer: pointerFor(path10), keyword, kind, message });
15345
15352
  }
15346
- function isPlainObject(value) {
15347
- return typeof value === "object" && value !== null && !Array.isArray(value);
15348
- }
15349
15353
  function isSupportedEnumValue(value) {
15350
15354
  return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
15351
15355
  }
@@ -15395,7 +15399,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15395
15399
  continue;
15396
15400
  }
15397
15401
  branches.forEach((branch, index) => {
15398
- if (isPlainObject(branch)) {
15402
+ if (isRecord(branch)) {
15399
15403
  checkDefinitionNode(branch, [...path10, keyword, index], issues, depth + 1);
15400
15404
  } else {
15401
15405
  pushIssue(issues, [...path10, keyword, index], keyword, "malformed", `"${keyword}[${index}]" must be a schema object`);
@@ -15403,7 +15407,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15403
15407
  });
15404
15408
  }
15405
15409
  if (schema.not !== undefined) {
15406
- if (isPlainObject(schema.not)) {
15410
+ if (isRecord(schema.not)) {
15407
15411
  checkDefinitionNode(schema.not, [...path10, "not"], issues, depth + 1);
15408
15412
  } else {
15409
15413
  pushIssue(issues, [...path10, "not"], "not", "malformed", `"not" must be a schema object`);
@@ -15415,11 +15419,11 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15415
15419
  }
15416
15420
  }
15417
15421
  if (schema.properties !== undefined) {
15418
- if (!isPlainObject(schema.properties)) {
15422
+ if (!isRecord(schema.properties)) {
15419
15423
  pushIssue(issues, [...path10, "properties"], "properties", "malformed", `"properties" must be an object mapping property names to schemas`);
15420
15424
  } else {
15421
15425
  for (const [key, propSchema] of Object.entries(schema.properties)) {
15422
- if (isPlainObject(propSchema)) {
15426
+ if (isRecord(propSchema)) {
15423
15427
  checkDefinitionNode(propSchema, [...path10, "properties", key], issues, depth + 1);
15424
15428
  } else {
15425
15429
  pushIssue(issues, [...path10, "properties", key], "properties", "malformed", `property ${JSON.stringify(key)} must be a schema object`);
@@ -15428,7 +15432,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15428
15432
  }
15429
15433
  }
15430
15434
  if (schema.items !== undefined) {
15431
- if (isPlainObject(schema.items)) {
15435
+ if (isRecord(schema.items)) {
15432
15436
  checkDefinitionNode(schema.items, [...path10, "items"], issues, depth + 1);
15433
15437
  } else if (Array.isArray(schema.items)) {
15434
15438
  pushIssue(issues, [...path10, "items"], "items", "unsupported", `tuple-form "items" (an array of schemas) is not enforced by the workflow schema subset \u2014 use a single schema object`);
@@ -15437,7 +15441,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15437
15441
  }
15438
15442
  }
15439
15443
  if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== "boolean") {
15440
- if (isPlainObject(schema.additionalProperties)) {
15444
+ if (isRecord(schema.additionalProperties)) {
15441
15445
  pushIssue(issues, [...path10, "additionalProperties"], "additionalProperties", "unsupported", `schema-form "additionalProperties" is not enforced by the workflow schema subset \u2014 only "additionalProperties: false" is`);
15442
15446
  } else {
15443
15447
  pushIssue(issues, [...path10, "additionalProperties"], "additionalProperties", "malformed", `"additionalProperties" must be a boolean (only "false" is enforced)`);
@@ -15486,7 +15490,7 @@ function combinatorBranches(schema, keyword) {
15486
15490
  const raw = schema[keyword];
15487
15491
  if (!Array.isArray(raw))
15488
15492
  return [];
15489
- return raw.filter(isPlainObject);
15493
+ return raw.filter(isRecord);
15490
15494
  }
15491
15495
  function summarizeBranchFailures(failures) {
15492
15496
  const shown = failures.slice(0, 3).map((f) => `${f.index + 1}: ${f.errors[0] ?? "no match"}`);
@@ -15518,7 +15522,7 @@ function validateCombinators(value, schema, path10, ctx) {
15518
15522
  }
15519
15523
  }
15520
15524
  const not = schema.not;
15521
- if (isPlainObject(not) && branchErrors(value, not, path10, ctx).length === 0) {
15525
+ if (isRecord(not) && branchErrors(value, not, path10, ctx).length === 0) {
15522
15526
  ctx.errors.push(`${path10}: value must not match the "not" schema`);
15523
15527
  }
15524
15528
  }
@@ -16274,20 +16278,17 @@ function formatExtraParamsIssue(label, issue) {
16274
16278
  const suffix = issue.path.map((part) => typeof part === "number" ? `[${part}]` : `.${part}`).join("");
16275
16279
  return `${label}${suffix} ${issue.message}`;
16276
16280
  }
16277
- function isPlainObject2(value) {
16278
- return typeof value === "object" && value !== null && !Array.isArray(value);
16279
- }
16280
16281
  function liftLegacyEngineExtraParams(raw) {
16281
16282
  const lifted = [];
16282
16283
  const conflicts = [];
16283
16284
  const rawEngines = raw.engines;
16284
- if (!isPlainObject2(rawEngines)) {
16285
+ if (!isRecord(rawEngines)) {
16285
16286
  return { config: raw, lifted, conflicts };
16286
16287
  }
16287
16288
  const engines = {};
16288
16289
  let anyEngineChanged = false;
16289
16290
  for (const [name, engineValue] of Object.entries(rawEngines)) {
16290
- if (!isPlainObject2(engineValue) || !isPlainObject2(engineValue.extraParams)) {
16291
+ if (!isRecord(engineValue) || !isRecord(engineValue.extraParams)) {
16291
16292
  engines[name] = engineValue;
16292
16293
  continue;
16293
16294
  }
@@ -17528,6 +17529,9 @@ function peekTaskSourceVersion(root) {
17528
17529
  return typeof value === "number" ? value : undefined;
17529
17530
  }
17530
17531
  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`.";
17532
+ function unmigratableVersionError(filePath, version, reason, detail) {
17533
+ 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.");
17534
+ }
17531
17535
  function unsupportedVersionError(filePath, version) {
17532
17536
  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);
17533
17537
  }
@@ -17547,12 +17551,12 @@ function planInMemoryV4Bytes(version, yaml, filePath, workspaceRoot) {
17547
17551
  } else {
17548
17552
  const v3Outcome = planTaskToV3File(baseInput);
17549
17553
  if (v3Outcome.status !== "changed")
17550
- return;
17554
+ return { reason: v3Outcome.reason, detail: v3Outcome.detail };
17551
17555
  v3Bytes = v3Outcome.after;
17552
17556
  }
17553
17557
  const v4Outcome = planTaskToV4File({ ...baseInput, bytes: v3Bytes });
17554
17558
  if (v4Outcome.status !== "changed")
17555
- return;
17559
+ return { reason: v4Outcome.reason, detail: v4Outcome.detail };
17556
17560
  return v4Outcome.after.toString("utf8");
17557
17561
  }
17558
17562
  function parseTaskSource(input) {
@@ -17560,16 +17564,17 @@ function parseTaskSource(input) {
17560
17564
  const version = peekTaskSourceVersion(root);
17561
17565
  if (version !== undefined && version !== TASK_SOURCE_V4_VERSION) {
17562
17566
  if (version === 2 || version === 3) {
17563
- const v4Yaml = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17564
- if (v4Yaml !== undefined) {
17567
+ const shimmed = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17568
+ if (typeof shimmed === "string") {
17565
17569
  const v4 = parseTaskSourceV4({
17566
- yaml: v4Yaml,
17570
+ yaml: shimmed,
17567
17571
  filePath: input.filePath,
17568
17572
  ...input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}
17569
17573
  });
17570
17574
  warn(`akm: task ${input.filePath} uses schema v${version} \u2014 auto-read as v4; run \`akm migrate apply\` to rewrite it and silence this`);
17571
17575
  return Object.freeze({ version: 4, v4 });
17572
17576
  }
17577
+ throw unmigratableVersionError(input.filePath, version, shimmed.reason, shimmed.detail);
17573
17578
  }
17574
17579
  throw unsupportedVersionError(input.filePath, version);
17575
17580
  }
@@ -17803,11 +17808,6 @@ function sourceStepRef(source) {
17803
17808
  // src/workflows/source-ir/schema.ts
17804
17809
  import { types as utilTypes2 } from "util";
17805
17810
 
17806
- // src/workflows/source-ir/compare.ts
17807
- function compareWorkflowSourceCodePoints(left, right) {
17808
- return left < right ? -1 : left > right ? 1 : 0;
17809
- }
17810
-
17811
17811
  // src/workflows/source-ir/semantics.ts
17812
17812
  import fs7 from "fs";
17813
17813
  import path12 from "path";
@@ -18446,9 +18446,6 @@ function validateStep(value, jobId, index, stepIds, options) {
18446
18446
  extensions(step.extensions, `step ${id} extensions`);
18447
18447
  span(step.source, `step ${id} source`);
18448
18448
  }
18449
- function compareCodePoints(left, right) {
18450
- return compareWorkflowSourceCodePoints(left, right);
18451
- }
18452
18449
  function validateExec(value, location, options) {
18453
18450
  if (value === undefined)
18454
18451
  return;
@@ -18754,7 +18751,7 @@ function snapshotValue(value, depth, location, state) {
18754
18751
  return value;
18755
18752
  }
18756
18753
  if (typeof value === "string") {
18757
- if (!wellFormedUnicode2(value))
18754
+ if (!wellFormedUnicode(value))
18758
18755
  fail2(`${location} must contain well-formed Unicode`);
18759
18756
  countJsonBytes(state, JSON.stringify(value));
18760
18757
  return value;
@@ -18818,7 +18815,7 @@ function snapshotObject(value, depth, location, state) {
18818
18815
  for (const [index, key] of ownKeys.entries()) {
18819
18816
  if (typeof key === "symbol")
18820
18817
  fail2(`${location} contains symbol keys`);
18821
- if (!wellFormedUnicode2(key))
18818
+ if (!wellFormedUnicode(key))
18822
18819
  fail2(`${location} contains an ill-formed key`);
18823
18820
  if (UNSAFE_KEYS.has(key))
18824
18821
  fail2(`${location} contains unsafe key ${key}`);
@@ -18847,20 +18844,6 @@ function countJsonBytes(state, token) {
18847
18844
  if (state.bytes > WORKFLOW_SOURCE_IR_MAX_BYTES)
18848
18845
  fail2("source IR exceeds the byte limit");
18849
18846
  }
18850
- function wellFormedUnicode2(value) {
18851
- for (let index = 0;index < value.length; index++) {
18852
- const code = value.charCodeAt(index);
18853
- if (code >= 55296 && code <= 56319) {
18854
- const next = value.charCodeAt(index + 1);
18855
- if (!(next >= 56320 && next <= 57343))
18856
- return false;
18857
- index++;
18858
- } else if (code >= 56320 && code <= 57343) {
18859
- return false;
18860
- }
18861
- }
18862
- return true;
18863
- }
18864
18847
  function record(value, location) {
18865
18848
  if (value === null || typeof value !== "object" || Array.isArray(value))
18866
18849
  fail2(`${location} must be an object`);
@@ -19005,14 +18988,11 @@ function compileWorkflowPlan(input, title, resolvedUnits = new Map) {
19005
18988
  }
19006
18989
  function sortedOutputs(outputs) {
19007
18990
  const sorted = {};
19008
- for (const name of Object.keys(outputs).sort(compareCodePoints2)) {
18991
+ for (const name of Object.keys(outputs).sort(compareCodePoints)) {
19009
18992
  sorted[name] = outputs[name];
19010
18993
  }
19011
18994
  return sorted;
19012
18995
  }
19013
- function compareCodePoints2(left, right) {
19014
- return left < right ? -1 : left > right ? 1 : 0;
19015
- }
19016
18996
  function compileStep(step, sequenceIndex, defaults, resolved) {
19017
18997
  const gate = {
19018
18998
  kind: "gate",
@@ -19139,12 +19119,6 @@ function collectWorkflowWarnings(input) {
19139
19119
  message: `Step "${step.id}" declares \`gate.max_loops: ${maxLoops}\` on an \`exec\` step \u2014 it runs its command ` + `ONCE. A gate loop re-executes the step so it can address the judge's feedback, and a frozen argv cannot ` + `read that feedback; looping would only repeat the command's side effects. The gate still evaluates and ` + `can still fail the step.`
19140
19120
  });
19141
19121
  }
19142
- if ((step.map || step.route === undefined) && step.output === undefined) {
19143
- warnings.push({
19144
- line: step.source.start,
19145
- message: `Step "${step.id}" declares no \`output:\` schema \u2014 its unit results are carried as an untyped ` + `artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`
19146
- });
19147
- }
19148
19122
  if (declaredParams) {
19149
19123
  const declaredList = [...declaredParams].join(", ");
19150
19124
  const scan = (text, label) => {
@@ -19358,7 +19332,7 @@ function parseWorkflow(markdown, source) {
19358
19332
  };
19359
19333
  if (root === null || root === undefined)
19360
19334
  root = {};
19361
- if (!isPlainRecord(root)) {
19335
+ if (!isRecord(root)) {
19362
19336
  return {
19363
19337
  ok: false,
19364
19338
  errors: [{ line: 2, message: `Workflow frontmatter must be a YAML mapping (key: value pairs).` }]
@@ -19539,7 +19513,7 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
19539
19513
  checkActorStamp(ctx, root.verified, ["verified"], `"verified"`);
19540
19514
  }
19541
19515
  }
19542
- if (root.provenance !== undefined && !isPlainRecord(root.provenance)) {
19516
+ if (root.provenance !== undefined && !isRecord(root.provenance)) {
19543
19517
  ctx.err(["provenance"], `Workflow frontmatter "provenance" must be a mapping.`);
19544
19518
  }
19545
19519
  if (root.status !== undefined && (typeof root.status !== "string" || !LIFECYCLE_STATUSES.has(root.status))) {
@@ -19552,7 +19526,7 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
19552
19526
  function checkActorStamp(ctx, value, path13, label) {
19553
19527
  if (value === undefined)
19554
19528
  return;
19555
- if (!isPlainRecord(value)) {
19529
+ if (!isRecord(value)) {
19556
19530
  ctx.err(path13, `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
19557
19531
  return;
19558
19532
  }
@@ -19583,7 +19557,7 @@ function checkXrefs2(ctx, value, fmEndLine) {
19583
19557
  function parseParams(ctx, raw) {
19584
19558
  if (raw === undefined)
19585
19559
  return;
19586
- if (!isPlainRecord(raw)) {
19560
+ if (!isRecord(raw)) {
19587
19561
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19588
19562
  return;
19589
19563
  }
@@ -19593,7 +19567,7 @@ function parseParams(ctx, raw) {
19593
19567
  ctx.err(["params", paramName], `Param name "${paramName}" is invalid. Use letters, digits, and underscores, starting with a letter or underscore, so "params.${paramName}" can address it.`);
19594
19568
  continue;
19595
19569
  }
19596
- if (!isPlainRecord(value)) {
19570
+ if (!isRecord(value)) {
19597
19571
  ctx.err(["params", paramName], `Param "${paramName}" must be a JSON Schema object (e.g. { type: string }).`);
19598
19572
  continue;
19599
19573
  }
@@ -19608,7 +19582,7 @@ function parseParams(ctx, raw) {
19608
19582
  function parseOutputs(ctx, raw) {
19609
19583
  if (raw === undefined)
19610
19584
  return;
19611
- if (!isPlainRecord(raw)) {
19585
+ if (!isRecord(raw)) {
19612
19586
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19613
19587
  return;
19614
19588
  }
@@ -19619,7 +19593,7 @@ function parseOutputs(ctx, raw) {
19619
19593
  ctx.err(path13, `Output name "${outputName}" is invalid. Use letters, digits, and underscores, starting with a letter or ` + `underscore, so "steps.<child>.output.${outputName}" can address it.`);
19620
19594
  continue;
19621
19595
  }
19622
- if (!isPlainRecord(value)) {
19596
+ if (!isRecord(value)) {
19623
19597
  ctx.err(path13, `Output "${outputName}" must be a mapping with "from" (and optional "schema").`);
19624
19598
  continue;
19625
19599
  }
@@ -19639,7 +19613,7 @@ function parseOutputs(ctx, raw) {
19639
19613
  }
19640
19614
  const entry = { from: value.from };
19641
19615
  if (value.schema !== undefined) {
19642
- if (!isPlainRecord(value.schema)) {
19616
+ if (!isRecord(value.schema)) {
19643
19617
  ctx.err([...path13, "schema"], `Output "${outputName}" "schema" must be a JSON Schema object.`);
19644
19618
  } else {
19645
19619
  if (jsonBytes(value.schema) > WORKFLOW_MAX_SCHEMA_BYTES) {
@@ -19657,7 +19631,7 @@ function parseDefaults(ctx, raw) {
19657
19631
  if (raw === undefined)
19658
19632
  return;
19659
19633
  const path13 = ["defaults"];
19660
- if (!isPlainRecord(raw)) {
19634
+ if (!isRecord(raw)) {
19661
19635
  ctx.err(path13, `"defaults" must be a mapping with any of: ${DEFAULTS_KEYS.join(", ")}.`);
19662
19636
  return;
19663
19637
  }
@@ -19689,7 +19663,7 @@ function parseBudget(ctx, raw) {
19689
19663
  if (raw === undefined)
19690
19664
  return;
19691
19665
  const path13 = ["budget"];
19692
- if (!isPlainRecord(raw)) {
19666
+ if (!isRecord(raw)) {
19693
19667
  ctx.err(path13, `"budget" must be a mapping with any of: ${BUDGET_KEYS.join(", ")}.`);
19694
19668
  return;
19695
19669
  }
@@ -19718,7 +19692,7 @@ function parseSteps(ctx, raw) {
19718
19692
  }
19719
19693
  const idIndex = new Map;
19720
19694
  raw.forEach((rawStep, index) => {
19721
- if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
19695
+ if (isRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
19722
19696
  idIndex.set(rawStep.id, index);
19723
19697
  }
19724
19698
  });
@@ -19727,7 +19701,7 @@ function parseSteps(ctx, raw) {
19727
19701
  const routeChecks = [];
19728
19702
  raw.forEach((rawStep, index) => {
19729
19703
  const path13 = ["steps", index];
19730
- if (!isPlainRecord(rawStep)) {
19704
+ if (!isRecord(rawStep)) {
19731
19705
  ctx.err(path13, `Step ${index + 1} must be a mapping with an "id".`);
19732
19706
  return;
19733
19707
  }
@@ -19801,7 +19775,7 @@ function parseSteps(ctx, raw) {
19801
19775
  return steps;
19802
19776
  }
19803
19777
  function parseUnit(ctx, raw, path13, stepLabel) {
19804
- if (!isPlainRecord(raw)) {
19778
+ if (!isRecord(raw)) {
19805
19779
  ctx.err(path13, `${stepLabel} "unit" must be a mapping (a dispatch-override bag).`);
19806
19780
  return;
19807
19781
  }
@@ -19862,7 +19836,7 @@ function parseUnit(ctx, raw, path13, stepLabel) {
19862
19836
  return unit;
19863
19837
  }
19864
19838
  function parseExec(ctx, raw, path13, stepLabel) {
19865
- if (!isPlainRecord(raw)) {
19839
+ if (!isRecord(raw)) {
19866
19840
  ctx.err(path13, `${stepLabel} "exec" must be a mapping with a "command" argv list.`);
19867
19841
  return;
19868
19842
  }
@@ -19946,7 +19920,7 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
19946
19920
  return value;
19947
19921
  }
19948
19922
  function parseMap(ctx, raw, path13, stepLabel) {
19949
- if (!isPlainRecord(raw)) {
19923
+ if (!isRecord(raw)) {
19950
19924
  ctx.err(path13, `${stepLabel} "map" must be a mapping with an "over" key.`);
19951
19925
  return;
19952
19926
  }
@@ -19978,7 +19952,7 @@ function parseMap(ctx, raw, path13, stepLabel) {
19978
19952
  return map;
19979
19953
  }
19980
19954
  function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
19981
- if (!isPlainRecord(raw)) {
19955
+ if (!isRecord(raw)) {
19982
19956
  ctx.err(path13, `${stepLabel} "route" must be a mapping with "input" and "when" keys.`);
19983
19957
  return;
19984
19958
  }
@@ -19998,7 +19972,7 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
19998
19972
  const seenMatches = new Map;
19999
19973
  raw.when.forEach((branch, i) => {
20000
19974
  const branchPath = [...whenPath, i];
20001
- if (!isPlainRecord(branch)) {
19975
+ if (!isRecord(branch)) {
20002
19976
  ctx.err(branchPath, `${stepLabel} "when[${i}]" must be a mapping: { match, step }.`);
20003
19977
  return;
20004
19978
  }
@@ -20069,7 +20043,7 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20069
20043
  return out.length > 0 ? out : undefined;
20070
20044
  }
20071
20045
  function parseGate(ctx, raw, path13, stepLabel) {
20072
- if (!isPlainRecord(raw)) {
20046
+ if (!isRecord(raw)) {
20073
20047
  ctx.err(path13, `${stepLabel} "gate" must be a mapping with any of: ${GATE_KEYS.join(", ")}.`);
20074
20048
  return;
20075
20049
  }
@@ -20099,7 +20073,7 @@ function parseEngineName(ctx, raw, path13, label) {
20099
20073
  function parseRetry(ctx, raw, path13, stepLabel) {
20100
20074
  if (raw === undefined)
20101
20075
  return;
20102
- if (!isPlainRecord(raw)) {
20076
+ if (!isRecord(raw)) {
20103
20077
  ctx.err(path13, `${stepLabel} "retry" must be a mapping: { max: <n>, on: [<failure_reason>, \u2026] }.`);
20104
20078
  return;
20105
20079
  }
@@ -20172,7 +20146,7 @@ function parseEnumField(ctx, raw, path13, label, allowed) {
20172
20146
  function parseLlmOverrides(ctx, raw, path13, label) {
20173
20147
  if (raw === undefined)
20174
20148
  return;
20175
- if (!isPlainRecord(raw)) {
20149
+ if (!isRecord(raw)) {
20176
20150
  ctx.err(path13, `${label} must be a mapping of LLM invocation overrides.`);
20177
20151
  return;
20178
20152
  }
@@ -20206,7 +20180,7 @@ function parseLlmOverrides(ctx, raw, path13, label) {
20206
20180
  ctx.err([...path13, "supports_json_schema"], `${label}.supports_json_schema must be a boolean.`);
20207
20181
  }
20208
20182
  if (raw.extra_params !== undefined) {
20209
- if (!isPlainRecord(raw.extra_params)) {
20183
+ if (!isRecord(raw.extra_params)) {
20210
20184
  ctx.err([...path13, "extra_params"], `${label}.extra_params must be a JSON object.`);
20211
20185
  } else {
20212
20186
  const issues = validateExtraParams(raw.extra_params);
@@ -20244,7 +20218,7 @@ function parseLlmOverrides(ctx, raw, path13, label) {
20244
20218
  function parseSchemaObject(ctx, raw, path13, label) {
20245
20219
  if (raw === undefined)
20246
20220
  return;
20247
- if (!isPlainRecord(raw)) {
20221
+ if (!isRecord(raw)) {
20248
20222
  ctx.err(path13, `${label} must be a JSON Schema object (e.g. { type: object, properties: { \u2026 } }).`);
20249
20223
  return;
20250
20224
  }
@@ -20276,9 +20250,6 @@ function checkUnknownKeys(ctx, obj, path13, allowed, label) {
20276
20250
  }
20277
20251
  }
20278
20252
  }
20279
- function isPlainRecord(value) {
20280
- return typeof value === "object" && value !== null && !Array.isArray(value);
20281
- }
20282
20253
  function describeError(cause) {
20283
20254
  return cause instanceof Error ? cause.message : String(cause);
20284
20255
  }
@@ -21159,22 +21130,6 @@ function nameOrTypeDiagnostics(relPath, data, frontmatter, allowedTypes) {
21159
21130
  }
21160
21131
  return [];
21161
21132
  }
21162
- var ASSIGN_RE2 = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
21163
- function scanKeys(text) {
21164
- const keys2 = [];
21165
- const seen = new Set;
21166
- for (const line of text.split(/\r?\n/)) {
21167
- const m = line.match(ASSIGN_RE2);
21168
- if (!m)
21169
- continue;
21170
- const key = m[1];
21171
- if (seen.has(key))
21172
- continue;
21173
- seen.add(key);
21174
- keys2.push(key);
21175
- }
21176
- return keys2;
21177
- }
21178
21133
  function collectSuppressedKeys(raw) {
21179
21134
  const suppressed = new Set;
21180
21135
  const lines = raw.split(/\r?\n/);
@@ -21198,7 +21153,7 @@ function dangerousEnvKeyDiagnostics(type, relPath, raw) {
21198
21153
  if (!baseNameWithExt.endsWith(".env"))
21199
21154
  return [];
21200
21155
  const ref = conceptIdForStashFile(type, ".", relPath);
21201
- const keys2 = scanKeys(raw);
21156
+ const keys2 = scanEnvKeyNames(raw);
21202
21157
  const suppressed = collectSuppressedKeys(raw);
21203
21158
  const diagnostics = [];
21204
21159
  for (const key of keys2) {
@@ -21648,7 +21603,6 @@ function applyFoldedMetadata(entry, folded) {
21648
21603
  }
21649
21604
 
21650
21605
  // src/core/adapter/adapters/akm-adapter.ts
21651
- var RESERVED_FILES = new Set(["index.md", "log.md"]);
21652
21606
  function isReservedFileName(name) {
21653
21607
  return RESERVED_FILES.has(name.toLowerCase());
21654
21608
  }
@@ -21984,14 +21938,10 @@ import fs9 from "fs";
21984
21938
  import path16 from "path";
21985
21939
  var COMPONENT_ID2 = "main";
21986
21940
  var TASK_EXT = TASK_EXTENSION;
21987
- var MAX_CONTENT_CHARS2 = 1e5;
21988
- function toPosix3(p) {
21989
- return p.replace(/\\/g, "/");
21990
- }
21991
21941
  function recognize3(c, file) {
21992
21942
  if (file.ext !== TASK_EXT)
21993
21943
  return null;
21994
- const conceptId = toPosix3(file.relPath).replace(/\.yml$/i, "");
21944
+ const conceptId = toPosix(file.relPath).replace(/\.yml$/i, "");
21995
21945
  const name = conceptId.split("/").pop() ?? conceptId;
21996
21946
  const raw = file.content();
21997
21947
  return {
@@ -22004,7 +21954,7 @@ function recognize3(c, file) {
22004
21954
  adapterId: "akm-task",
22005
21955
  type: "task",
22006
21956
  name,
22007
- content: raw.length > MAX_CONTENT_CHARS2 ? raw.slice(0, MAX_CONTENT_CHARS2) : raw
21957
+ content: raw
22008
21958
  };
22009
21959
  }
22010
21960
  async function validate3(c, changes, ctx) {
@@ -22018,7 +21968,7 @@ async function validate3(c, changes, ctx) {
22018
21968
  const ext = path16.extname(change.path).toLowerCase();
22019
21969
  if (ext !== TASK_EXT && ext !== TASK_NEAR_MISS_EXTENSION)
22020
21970
  continue;
22021
- const relPath = toPosix3(change.path);
21971
+ const relPath = toPosix(change.path);
22022
21972
  if (ext === TASK_NEAR_MISS_EXTENSION) {
22023
21973
  diagnostics.push({
22024
21974
  file: relPath,
@@ -22048,14 +21998,14 @@ var akmTaskAdapter = {
22048
21998
  recognize: recognize3,
22049
21999
  validate: validate3,
22050
22000
  readCandidates(c, conceptId) {
22051
- const posix = toPosix3(conceptId).replace(/\.ya?ml$/i, "");
22001
+ const posix = toPosix(conceptId).replace(/\.ya?ml$/i, "");
22052
22002
  return [
22053
22003
  { path: path16.join(c.root, `${posix}.yml`), conceptId: posix },
22054
22004
  { path: path16.join(c.root, `${posix}.yaml`), conceptId: posix }
22055
22005
  ];
22056
22006
  },
22057
22007
  placeNew(c, conceptId) {
22058
- const posix = toPosix3(conceptId);
22008
+ const posix = toPosix(conceptId);
22059
22009
  return path16.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
22060
22010
  },
22061
22011
  directoryList() {
@@ -22091,12 +22041,8 @@ import fs10 from "fs";
22091
22041
  import path17 from "path";
22092
22042
  var COMPONENT_ID3 = "main";
22093
22043
  var WORKFLOW_EXTS = new Set([".md", ".yml"]);
22094
- var MAX_CONTENT_CHARS3 = 1e5;
22095
- function toPosix4(p) {
22096
- return p.replace(/\\/g, "/");
22097
- }
22098
22044
  function conceptIdOf(relPath) {
22099
- return toPosix4(relPath).replace(/\.(?:md|yml)$/i, "");
22045
+ return toPosix(relPath).replace(/\.(?:md|yml)$/i, "");
22100
22046
  }
22101
22047
  function isReservedDocFile(fileName) {
22102
22048
  return fileName.toLowerCase() === "readme.md";
@@ -22130,7 +22076,7 @@ function recognize4(c, file) {
22130
22076
  adapterId: "akm-workflow",
22131
22077
  type: "workflow",
22132
22078
  name,
22133
- content: body.length > MAX_CONTENT_CHARS3 ? body.slice(0, MAX_CONTENT_CHARS3) : body
22079
+ content: body
22134
22080
  };
22135
22081
  if (description !== undefined)
22136
22082
  doc.description = description;
@@ -22149,7 +22095,7 @@ async function validate4(c, changes, ctx) {
22149
22095
  const ext = path17.extname(change.path).toLowerCase();
22150
22096
  if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(path17.basename(change.path)))
22151
22097
  continue;
22152
- const relPath = toPosix4(change.path);
22098
+ const relPath = toPosix(change.path);
22153
22099
  if (ext === ".yml") {
22154
22100
  diagnostics.push(...workflowYamlSourceDiagnostics(relPath, raw, relPath, c.root).errors);
22155
22101
  continue;
@@ -22199,7 +22145,7 @@ var akmWorkflowAdapter = {
22199
22145
  recognize: recognize4,
22200
22146
  validate: validate4,
22201
22147
  readCandidates(c, conceptId) {
22202
- const posix = toPosix4(conceptId);
22148
+ const posix = toPosix(conceptId);
22203
22149
  const canonical = posix.replace(/\.(?:md|yml)$/i, "");
22204
22150
  return /\.(?:md|yml)$/i.test(posix) ? [{ path: path17.join(c.root, posix), conceptId: canonical }] : [
22205
22151
  { path: path17.join(c.root, `${posix}.md`), conceptId: canonical },
@@ -22207,7 +22153,7 @@ var akmWorkflowAdapter = {
22207
22153
  ];
22208
22154
  },
22209
22155
  placeNew(c, conceptId) {
22210
- const posix = toPosix4(conceptId);
22156
+ const posix = toPosix(conceptId);
22211
22157
  if (/\.(?:md|yml)$/i.test(posix))
22212
22158
  return path17.join(c.root, posix);
22213
22159
  return path17.join(c.root, `${posix}.md`);
@@ -22232,20 +22178,15 @@ import path19 from "path";
22232
22178
 
22233
22179
  // src/core/adapter/adapters/tool-dir-shared.ts
22234
22180
  import path18 from "path";
22235
- var RESERVED_FILES2 = new Set(["index.md", "log.md"]);
22236
- var MAX_CONTENT_CHARS4 = 1e5;
22237
22181
  var CANONICAL_COMMAND_DIR = "commands";
22238
22182
  var CANONICAL_AGENT_DIR = "agents";
22239
22183
  var CANONICAL_SKILL_DIR = "skills";
22240
22184
  var SKILL_MANIFEST2 = "SKILL.md";
22241
- function toPosix5(p) {
22242
- return p.replace(/\\/g, "/");
22243
- }
22244
22185
  function isReserved(base3) {
22245
- return RESERVED_FILES2.has(base3.toLowerCase());
22186
+ return RESERVED_FILES.has(base3.toLowerCase());
22246
22187
  }
22247
22188
  function classify(relPath, layout) {
22248
- const posix = toPosix5(relPath);
22189
+ const posix = toPosix(relPath);
22249
22190
  const segs = posix.split("/").filter((s) => s.length > 0);
22250
22191
  if (segs.length === 0)
22251
22192
  return null;
@@ -22292,7 +22233,7 @@ function recognizeToolDir(layout, c, file) {
22292
22233
  adapterId: layout.adapterId,
22293
22234
  type: cls.type,
22294
22235
  name,
22295
- content: body.length > MAX_CONTENT_CHARS4 ? body.slice(0, MAX_CONTENT_CHARS4) : body
22236
+ content: body
22296
22237
  };
22297
22238
  if (cls.type === "instruction")
22298
22239
  doc.ownsPresentation = true;
@@ -22303,7 +22244,7 @@ function recognizeToolDir(layout, c, file) {
22303
22244
  return doc;
22304
22245
  }
22305
22246
  function placeNewToolDir(layout, c, conceptId) {
22306
- const posix = toPosix5(conceptId);
22247
+ const posix = toPosix(conceptId);
22307
22248
  if (posix === layout.instructionConceptId)
22308
22249
  return path18.join(c.root, layout.instructionFile);
22309
22250
  const segs = posix.split("/").filter((s) => s.length > 0);
@@ -22320,7 +22261,7 @@ function placeNewToolDir(layout, c, conceptId) {
22320
22261
  return path18.join(c.root, `${posix}.md`);
22321
22262
  }
22322
22263
  function readCandidatesToolDir(layout, c, conceptId) {
22323
- const posix = toPosix5(conceptId);
22264
+ const posix = toPosix(conceptId);
22324
22265
  if (posix === layout.instructionConceptId) {
22325
22266
  return [{ path: path18.join(c.root, layout.instructionFile), conceptId: posix }];
22326
22267
  }
@@ -22361,7 +22302,7 @@ async function validateToolDir(layout, c, changes, ctx) {
22361
22302
  const raw = change.after ?? await ctx.readFile(change.path);
22362
22303
  if (typeof raw !== "string")
22363
22304
  continue;
22364
- const relPath = toPosix5(change.path);
22305
+ const relPath = toPosix(change.path);
22365
22306
  diagnostics.push(...await skillDirectoryDiagnostics(relPath, seenSkillDirs, ctx, layout.skillDirs));
22366
22307
  const cls = classify(change.path, layout);
22367
22308
  if (cls === null)
@@ -22461,12 +22402,8 @@ var COMPONENT_ID4 = "main";
22461
22402
  var ENV_DIR = "env";
22462
22403
  var SECRETS_DIR = "secrets";
22463
22404
  var SECRET_SKIP_SUFFIXES = [".lock", ".sensitive"];
22464
- var ASSIGN_RE3 = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
22465
- function toPosix6(p) {
22466
- return p.replace(/\\/g, "/");
22467
- }
22468
22405
  function classify2(relPath) {
22469
- const posix = toPosix6(relPath);
22406
+ const posix = toPosix(relPath);
22470
22407
  const segs = posix.split("/").filter((s) => s.length > 0);
22471
22408
  if (segs.length < 2)
22472
22409
  return null;
@@ -22484,23 +22421,8 @@ function hasSensitiveMarker(absPath, type) {
22484
22421
  const marker = type === "env" ? absPath.replace(/\.env$/i, ".sensitive") : `${absPath}.sensitive`;
22485
22422
  return marker !== absPath && fs12.existsSync(marker);
22486
22423
  }
22487
- function scanKeyNames(raw) {
22488
- const keys2 = [];
22489
- const seen = new Set;
22490
- for (const line of raw.split(/\r?\n/)) {
22491
- const m = line.match(ASSIGN_RE3);
22492
- if (!m)
22493
- continue;
22494
- const key = m[1];
22495
- if (seen.has(key))
22496
- continue;
22497
- seen.add(key);
22498
- keys2.push(key);
22499
- }
22500
- return keys2;
22501
- }
22502
22424
  function conceptIdForPath(type, relativePath) {
22503
- const posix = toPosix6(relativePath);
22425
+ const posix = toPosix(relativePath);
22504
22426
  if (type === "secret")
22505
22427
  return posix;
22506
22428
  const stripped = posix.replace(/\.env$/i, "");
@@ -22512,12 +22434,12 @@ function recognize5(c, file) {
22512
22434
  return null;
22513
22435
  if (hasSensitiveMarker(file.absPath, type))
22514
22436
  return null;
22515
- const posix = toPosix6(file.relPath);
22437
+ const posix = toPosix(file.relPath);
22516
22438
  const raw = file.content();
22517
22439
  if (type === "env") {
22518
22440
  const conceptId = conceptIdForPath(type, posix);
22519
22441
  const name2 = (conceptId.split("/").pop() ?? conceptId) || "default";
22520
- const keys2 = scanKeyNames(raw);
22442
+ const keys2 = scanEnvKeyNames(raw);
22521
22443
  const doc = {
22522
22444
  ref: `${c.id}//${conceptId}`,
22523
22445
  bundle: c.id,
@@ -22557,7 +22479,7 @@ async function validate5(_c, changes, ctx) {
22557
22479
  const type = classify2(change.path);
22558
22480
  if (type === null)
22559
22481
  continue;
22560
- diagnostics.push(...dangerousEnvKeyDiagnostics(type, toPosix6(change.path), raw));
22482
+ diagnostics.push(...dangerousEnvKeyDiagnostics(type, toPosix(change.path), raw));
22561
22483
  }
22562
22484
  return diagnostics;
22563
22485
  }
@@ -22568,7 +22490,7 @@ var dotenvAdapter = {
22568
22490
  recognize: recognize5,
22569
22491
  validate: validate5,
22570
22492
  readCandidates(c, conceptId) {
22571
- const posix = toPosix6(conceptId);
22493
+ const posix = toPosix(conceptId);
22572
22494
  const slash = posix.indexOf("/");
22573
22495
  if (slash <= 0)
22574
22496
  return [];
@@ -22582,7 +22504,7 @@ var dotenvAdapter = {
22582
22504
  return expanded.map((candidatePath) => ({ path: candidatePath, conceptId: posix }));
22583
22505
  },
22584
22506
  placeNew(c, conceptId) {
22585
- const posix = toPosix6(conceptId);
22507
+ const posix = toPosix(conceptId);
22586
22508
  const slash = posix.indexOf("/");
22587
22509
  if (slash > 0) {
22588
22510
  const head = posix.slice(0, slash);
@@ -22617,13 +22539,8 @@ var dotenvAdapter = {
22617
22539
  import path21 from "path";
22618
22540
  var COMPONENT_ID5 = "main";
22619
22541
  var DOCUMENT_EXTENSIONS = new Set([".md", ".markdown", ".txt", ".text"]);
22620
- var RESERVED_FILES3 = new Set(["index.md", "log.md"]);
22621
- var MAX_CONTENT_CHARS5 = 1e5;
22622
- function toPosix7(p) {
22623
- return p.replace(/\\/g, "/");
22624
- }
22625
22542
  function isReserved2(base3) {
22626
- return RESERVED_FILES3.has(base3.toLowerCase());
22543
+ return RESERVED_FILES.has(base3.toLowerCase());
22627
22544
  }
22628
22545
  function classify3(ext) {
22629
22546
  if (SCRIPT_EXTENSIONS.has(ext))
@@ -22633,7 +22550,7 @@ function classify3(ext) {
22633
22550
  return "file";
22634
22551
  }
22635
22552
  function recognize6(c, file) {
22636
- const posix = toPosix7(file.relPath);
22553
+ const posix = toPosix(file.relPath);
22637
22554
  const base3 = posix.split("/").pop() ?? posix;
22638
22555
  if (isReserved2(base3))
22639
22556
  return null;
@@ -22653,7 +22570,7 @@ function recognize6(c, file) {
22653
22570
  adapterId: "generic-files",
22654
22571
  type,
22655
22572
  name,
22656
- content: body.length > MAX_CONTENT_CHARS5 ? body.slice(0, MAX_CONTENT_CHARS5) : body
22573
+ content: body
22657
22574
  };
22658
22575
  if (type !== "script")
22659
22576
  doc.ownsPresentation = true;
@@ -22673,7 +22590,7 @@ async function validate6(c, changes, ctx) {
22673
22590
  const raw = change.after ?? await ctx.readFile(change.path);
22674
22591
  if (typeof raw !== "string")
22675
22592
  continue;
22676
- diagnostics.push(...await runBaseValidateChecks(toPosix7(change.path), parseFrontmatter(raw), c.root, ctx));
22593
+ diagnostics.push(...await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx));
22677
22594
  }
22678
22595
  return diagnostics;
22679
22596
  }
@@ -22684,7 +22601,7 @@ var genericFilesAdapter = {
22684
22601
  recognize: recognize6,
22685
22602
  validate: validate6,
22686
22603
  readCandidates(c, conceptId) {
22687
- const posix = toPosix7(conceptId);
22604
+ const posix = toPosix(conceptId);
22688
22605
  const extension = path21.extname(posix).toLowerCase();
22689
22606
  const documentCandidates = [...DOCUMENT_EXTENSIONS].map((candidateExtension) => ({
22690
22607
  path: path21.join(c.root, `${posix}${candidateExtension}`),
@@ -22693,7 +22610,7 @@ var genericFilesAdapter = {
22693
22610
  return DOCUMENT_EXTENSIONS.has(extension) ? documentCandidates : [{ path: path21.join(c.root, posix), conceptId: posix }, ...documentCandidates];
22694
22611
  },
22695
22612
  placeNew(c, conceptId) {
22696
- const posix = toPosix7(conceptId);
22613
+ const posix = toPosix(conceptId);
22697
22614
  const hasExt = path21.extname(posix) !== "";
22698
22615
  return path21.join(c.root, hasExt ? posix : `${posix}.md`);
22699
22616
  },
@@ -22711,12 +22628,8 @@ var DEFAULT_PAGE_KIND = "note";
22711
22628
  var RESERVED_ROOT_FILES = new Set(["schema.md", "index.md", "log.md"]);
22712
22629
  var RAW_SUBDIR = "raw";
22713
22630
  var PAGES_SUBDIR = "pages";
22714
- var MAX_CONTENT_CHARS6 = 1e5;
22715
- function toPosix8(p) {
22716
- return p.replace(/\\/g, "/");
22717
- }
22718
22631
  function conceptIdOf2(relPath) {
22719
- return toPosix8(relPath).replace(/\.md$/i, "");
22632
+ return toPosix(relPath).replace(/\.md$/i, "");
22720
22633
  }
22721
22634
  function parseWikiFrontmatter(raw) {
22722
22635
  const out = { xrefs: [], sources: [] };
@@ -22748,13 +22661,13 @@ function parseWikiFrontmatter(raw) {
22748
22661
  return out;
22749
22662
  }
22750
22663
  function isReservedRootFile(relPath) {
22751
- const posix = toPosix8(relPath);
22664
+ const posix = toPosix(relPath);
22752
22665
  if (posix.includes("/"))
22753
22666
  return false;
22754
22667
  return RESERVED_ROOT_FILES.has(posix.toLowerCase());
22755
22668
  }
22756
22669
  function firstSegment(relPath) {
22757
- const posix = toPosix8(relPath);
22670
+ const posix = toPosix(relPath);
22758
22671
  const slash = posix.indexOf("/");
22759
22672
  return slash < 0 ? posix : posix.slice(0, slash);
22760
22673
  }
@@ -22766,7 +22679,7 @@ function resolveXref(xref, bundleId) {
22766
22679
  return target.length > 0 ? target : null;
22767
22680
  }
22768
22681
  function resolveBodyLinks(body, fileRelPath) {
22769
- const dir = path22.posix.dirname(toPosix8(fileRelPath));
22682
+ const dir = path22.posix.dirname(toPosix(fileRelPath));
22770
22683
  const linkRe = /\[[^\]]*\]\(([^)]+)\)/g;
22771
22684
  const out = [];
22772
22685
  const seen = new Set;
@@ -22843,7 +22756,7 @@ function resolveSources(fm) {
22843
22756
  function recognize7(c, file) {
22844
22757
  if (file.ext !== ".md")
22845
22758
  return null;
22846
- const relPath = toPosix8(file.relPath);
22759
+ const relPath = toPosix(file.relPath);
22847
22760
  if (isReservedRootFile(relPath))
22848
22761
  return null;
22849
22762
  const head = firstSegment(relPath);
@@ -22867,7 +22780,7 @@ function recognize7(c, file) {
22867
22780
  ownsPresentation: true,
22868
22781
  type: isRaw ? WIKI_SOURCE_TYPE : fm.pageKind ?? DEFAULT_PAGE_KIND,
22869
22782
  name: lastSegment,
22870
- content: body.length > MAX_CONTENT_CHARS6 ? body.slice(0, MAX_CONTENT_CHARS6) : body
22783
+ content: body
22871
22784
  };
22872
22785
  if (fm.description !== undefined)
22873
22786
  doc.description = fm.description;
@@ -22893,7 +22806,7 @@ async function validate7(c, changes, ctx) {
22893
22806
  const raw = change.after ?? await ctx.readFile(change.path);
22894
22807
  if (typeof raw !== "string")
22895
22808
  continue;
22896
- const relPath = toPosix8(change.path);
22809
+ const relPath = toPosix(change.path);
22897
22810
  if (isReservedRootFile(relPath))
22898
22811
  continue;
22899
22812
  const head = firstSegment(relPath);
@@ -22976,7 +22889,7 @@ var llmWikiAdapter = {
22976
22889
  recognize: recognize7,
22977
22890
  validate: validate7,
22978
22891
  readCandidates(c, conceptId) {
22979
- const canonical = toPosix8(conceptId).replace(/\.md$/i, "");
22892
+ const canonical = toPosix(conceptId).replace(/\.md$/i, "");
22980
22893
  return [{ path: path22.join(c.root, `${canonical}.md`), conceptId: canonical }];
22981
22894
  },
22982
22895
  placeNew(c, conceptId) {
@@ -23012,11 +22925,8 @@ var CONSUMED_FRONTMATTER_KEYS = [
23012
22925
  "stale_after",
23013
22926
  "okf_version"
23014
22927
  ];
23015
- function isPlainObject3(value) {
23016
- return value !== null && typeof value === "object" && !Array.isArray(value);
23017
- }
23018
22928
  function parseActorMapping(value) {
23019
- if (!isPlainObject3(value))
22929
+ if (!isRecord(value))
23020
22930
  return;
23021
22931
  const by = nonEmptyString(value.by);
23022
22932
  if (by === undefined)
@@ -23041,7 +22951,7 @@ function parseOkfSources(value) {
23041
22951
  return;
23042
22952
  const out = [];
23043
22953
  for (const item of value) {
23044
- if (!isPlainObject3(item))
22954
+ if (!isRecord(item))
23045
22955
  continue;
23046
22956
  const resource = nonEmptyString(item.resource);
23047
22957
  if (resource === undefined)
@@ -23069,16 +22979,11 @@ function parseOkfSources(value) {
23069
22979
  function parseLifecycleStatus(value) {
23070
22980
  return value === "draft" || value === "stable" || value === "deprecated" ? value : undefined;
23071
22981
  }
23072
- var RESERVED_FILES4 = new Set(["index.md", "log.md"]);
23073
- var MAX_CONTENT_CHARS7 = 1e5;
23074
- function toPosix9(p) {
23075
- return p.replace(/\\/g, "/");
23076
- }
23077
22982
  function isReservedFileName2(name) {
23078
- return RESERVED_FILES4.has(name.toLowerCase());
22983
+ return RESERVED_FILES.has(name.toLowerCase());
23079
22984
  }
23080
22985
  function resolveOkfLinks(body, fileRelPath) {
23081
- const dir = path23.posix.dirname(toPosix9(fileRelPath));
22986
+ const dir = path23.posix.dirname(toPosix(fileRelPath));
23082
22987
  const definitions = new Map;
23083
22988
  for (const match of body.matchAll(/^\s*\[([^\]]+)\]:\s*(\S+)/gm)) {
23084
22989
  definitions.set(match[1].trim().toLowerCase(), match[2]);
@@ -23136,7 +23041,7 @@ function recognize8(c, file) {
23136
23041
  return null;
23137
23042
  if (isReservedFileName2(file.fileName))
23138
23043
  return null;
23139
- const conceptId = toPosix9(file.relPath).replace(/\.md$/i, "");
23044
+ const conceptId = toPosix(file.relPath).replace(/\.md$/i, "");
23140
23045
  const raw = file.content();
23141
23046
  const parsed = parseFrontmatter(raw);
23142
23047
  const data = parsed.data;
@@ -23147,7 +23052,7 @@ function recognize8(c, file) {
23147
23052
  const description = nonEmptyString(data.description);
23148
23053
  const tags = readTags(data.tags);
23149
23054
  const links = resolveOkfLinks(body, file.relPath);
23150
- const generatedMapping = isPlainObject3(data.generated) ? data.generated : undefined;
23055
+ const generatedMapping = isRecord(data.generated) ? data.generated : undefined;
23151
23056
  const generatedAt = generatedMapping ? nonEmptyString(generatedMapping.at) : undefined;
23152
23057
  const generatedBy = generatedMapping ? nonEmptyString(generatedMapping.by) : undefined;
23153
23058
  const legacyTimestamp = nonEmptyString(data.timestamp);
@@ -23174,7 +23079,7 @@ function recognize8(c, file) {
23174
23079
  ownsPresentation: true,
23175
23080
  type,
23176
23081
  name,
23177
- content: body.length > MAX_CONTENT_CHARS7 ? body.slice(0, MAX_CONTENT_CHARS7) : body
23082
+ content: body
23178
23083
  };
23179
23084
  if (description !== undefined)
23180
23085
  doc.description = description;
@@ -23205,7 +23110,7 @@ async function validate8(c, changes, ctx) {
23205
23110
  const raw = change.after ?? await ctx.readFile(change.path);
23206
23111
  if (typeof raw !== "string")
23207
23112
  continue;
23208
- const relPath = toPosix9(change.path);
23113
+ const relPath = toPosix(change.path);
23209
23114
  const fileName = relPath.split("/").pop() ?? relPath;
23210
23115
  const reserved = isReservedFileName2(fileName);
23211
23116
  const parsed = parseFrontmatter(raw);
@@ -23329,10 +23234,6 @@ var COMPONENT_ID6 = "main";
23329
23234
  var PAGES_PREFIX = "stash/knowledge/";
23330
23235
  var MANIFEST_FILE = "manifest.json";
23331
23236
  var WEBSITE_TAG = "website";
23332
- var MAX_CONTENT_CHARS8 = 1e5;
23333
- function toPosix10(p) {
23334
- return p.replace(/\\/g, "/");
23335
- }
23336
23237
  function parseSnapshotFrontmatter(raw) {
23337
23238
  const out = { tags: [] };
23338
23239
  const block = parseFrontmatterBlock(raw);
@@ -23355,14 +23256,14 @@ function parseSnapshotFrontmatter(raw) {
23355
23256
  return out;
23356
23257
  }
23357
23258
  function isSnapshotPage(relPath) {
23358
- const posix = toPosix10(relPath);
23259
+ const posix = toPosix(relPath);
23359
23260
  return posix.startsWith(PAGES_PREFIX) && posix.toLowerCase().endsWith(".md");
23360
23261
  }
23361
23262
  function isReTypeGated(fm) {
23362
23263
  return fm.sourceUrl !== undefined || fm.tags.includes(WEBSITE_TAG);
23363
23264
  }
23364
23265
  function conceptIdOf3(relPath) {
23365
- return toPosix10(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, "");
23266
+ return toPosix(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, "");
23366
23267
  }
23367
23268
  function recognize9(c, file) {
23368
23269
  if (file.ext !== ".md" || !isSnapshotPage(file.relPath))
@@ -23385,7 +23286,7 @@ function recognize9(c, file) {
23385
23286
  ownsPresentation: true,
23386
23287
  type: "website",
23387
23288
  name,
23388
- content: body.length > MAX_CONTENT_CHARS8 ? body.slice(0, MAX_CONTENT_CHARS8) : body
23289
+ content: body
23389
23290
  };
23390
23291
  if (fm.description !== undefined)
23391
23292
  doc.description = fm.description;
@@ -23403,7 +23304,7 @@ async function validate9(c, changes, ctx) {
23403
23304
  continue;
23404
23305
  if (!isSnapshotPage(change.path))
23405
23306
  continue;
23406
- const base3 = await runBaseValidateChecks(toPosix10(change.path), parseFrontmatter(raw), c.root, ctx);
23307
+ const base3 = await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx);
23407
23308
  diagnostics.push(...base3.filter((d) => d.issue !== "missing-updated"));
23408
23309
  }
23409
23310
  return diagnostics;
@@ -23415,7 +23316,7 @@ var websiteSnapshotAdapter = {
23415
23316
  recognize: recognize9,
23416
23317
  validate: validate9,
23417
23318
  readCandidates(c, conceptId) {
23418
- const canonical = toPosix10(conceptId).replace(/\.md$/i, "");
23319
+ const canonical = toPosix(conceptId).replace(/\.md$/i, "");
23419
23320
  return [{ path: path25.join(c.root, PAGES_PREFIX, `${canonical}.md`), conceptId: canonical }];
23420
23321
  },
23421
23322
  looksLikeRoot(root) {
@@ -27912,9 +27813,7 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
27912
27813
  "default",
27913
27814
  "quick",
27914
27815
  "thorough",
27915
- "memory-focus",
27916
27816
  "graph-refresh",
27917
- "frequent",
27918
27817
  "consolidate",
27919
27818
  "catchup",
27920
27819
  "reflect-distill",
@@ -28807,7 +28706,7 @@ function upgradeConfigVersion(raw, sourcePath) {
28807
28706
 
28808
28707
  // src/core/config/deep-merge.ts
28809
28708
  var UNSAFE_KEYS3 = new Set(["__proto__", "constructor", "prototype"]);
28810
- function isPlainObject4(value) {
28709
+ function isPlainObject(value) {
28811
28710
  if (value === null || typeof value !== "object" || Array.isArray(value))
28812
28711
  return false;
28813
28712
  const prototype = Object.getPrototypeOf(value);
@@ -28816,7 +28715,7 @@ function isPlainObject4(value) {
28816
28715
  function copyConfigValue(value) {
28817
28716
  if (Array.isArray(value))
28818
28717
  return value.map(copyConfigValue);
28819
- if (!isPlainObject4(value))
28718
+ if (!isPlainObject(value))
28820
28719
  return value;
28821
28720
  const copy = {};
28822
28721
  for (const key of Object.keys(value)) {
@@ -28835,7 +28734,7 @@ function deepMergeConfig(base3, override) {
28835
28734
  if (next === undefined)
28836
28735
  continue;
28837
28736
  const current = result[key];
28838
- result[key] = isPlainObject4(current) && isPlainObject4(next) ? deepMergeConfig(current, next) : copyConfigValue(next);
28737
+ result[key] = isPlainObject(current) && isPlainObject(next) ? deepMergeConfig(current, next) : copyConfigValue(next);
28839
28738
  }
28840
28739
  return result;
28841
28740
  }
@@ -28896,8 +28795,8 @@ function loadUserConfig() {
28896
28795
  }
28897
28796
  function parseAndValidateConfigText(text, sourcePath) {
28898
28797
  const parsedRaw = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
28899
- const { config: raw, lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28900
28798
  const where = sourcePath ? ` at ${sourcePath}` : "";
28799
+ const { lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28901
28800
  if (conflicts.length > 0) {
28902
28801
  const lines = conflicts.map((c) => ` - engines.${c.engine}.extraParams.${c.key} (${JSON.stringify(c.extraParamsValue)}) conflicts with engines.${c.engine}.${c.field} (${JSON.stringify(c.fieldValue)})`).join(`
28903
28802
  `);
@@ -28907,11 +28806,13 @@ ${lines}
28907
28806
  Each extraParams key above has a first-class equivalent and akm will not guess which value you meant \u2014 remove the extraParams entry once the field carries the value you want.`, "INVALID_CONFIG_FILE");
28908
28807
  }
28909
28808
  if (lifted.length > 0) {
28910
- warn(`Config${where} uses deprecated extraParams keys with first-class equivalents; treating them as the first-class fields for this run (not written back to the file):
28809
+ throw new ConfigError(`Config${where} uses deprecated extraParams keys with first-class equivalents:
28911
28810
  - ${lifted.join(`
28912
- - `)}`);
28811
+ - `)}
28812
+
28813
+ Run \`akm migrate apply\` to rewrite the config file, or move the values onto the first-class fields yourself.`, "INVALID_CONFIG_FILE");
28913
28814
  }
28914
- const parsed = AkmConfigSchema.safeParse(raw);
28815
+ const parsed = AkmConfigSchema.safeParse(parsedRaw);
28915
28816
  if (!parsed.success) {
28916
28817
  const lines = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join(`
28917
28818
  `);
@@ -29206,6 +29107,9 @@ function createProviderRegistry() {
29206
29107
  resolve(type) {
29207
29108
  return map.get(type) ?? null;
29208
29109
  },
29110
+ unregister(type) {
29111
+ map.delete(type);
29112
+ },
29209
29113
  list() {
29210
29114
  return [...map.keys()];
29211
29115
  }