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
@@ -9454,6 +9454,12 @@ function stripJsonComments(text) {
9454
9454
  }
9455
9455
  return result;
9456
9456
  }
9457
+ function toPosix(input) {
9458
+ return input.replace(/\\/g, "/");
9459
+ }
9460
+ function compareCodePoints(left, right) {
9461
+ return left < right ? -1 : left > right ? 1 : 0;
9462
+ }
9457
9463
  function isContainedRelativePath(value) {
9458
9464
  if (value === "" || value.startsWith("/") || value.startsWith("\\") || value.startsWith("~"))
9459
9465
  return false;
@@ -9506,6 +9512,40 @@ function asNonEmptyString(value) {
9506
9512
  const trimmed = value.trim();
9507
9513
  return trimmed.length > 0 ? trimmed : undefined;
9508
9514
  }
9515
+ var ENV_ASSIGN_LINE_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
9516
+ function scanEnvKeyNames(text) {
9517
+ const keys = [];
9518
+ const seen = new Set;
9519
+ for (const line of text.split(/\r?\n/)) {
9520
+ const m = line.match(ENV_ASSIGN_LINE_RE);
9521
+ if (!m)
9522
+ continue;
9523
+ const key = m[1];
9524
+ if (!key)
9525
+ continue;
9526
+ if (seen.has(key))
9527
+ continue;
9528
+ seen.add(key);
9529
+ keys.push(key);
9530
+ }
9531
+ return keys;
9532
+ }
9533
+ function wellFormedUnicode(value) {
9534
+ for (let index = 0;index < value.length; index += 1) {
9535
+ const code = value.charCodeAt(index);
9536
+ if (code >= 55296 && code <= 56319) {
9537
+ const next = value.charCodeAt(index + 1);
9538
+ if (!(next >= 56320 && next <= 57343))
9539
+ return false;
9540
+ index += 1;
9541
+ } else if (code >= 56320 && code <= 57343)
9542
+ return false;
9543
+ }
9544
+ return true;
9545
+ }
9546
+ function isRecord(value) {
9547
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9548
+ }
9509
9549
  function isProcessAlive(pid) {
9510
9550
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
9511
9551
  return false;
@@ -11525,6 +11565,7 @@ var SCRIPT_EXTENSIONS = new Set([
11525
11565
  ".kts"
11526
11566
  ]);
11527
11567
  var WORKFLOW_EXTENSIONS = [".md", ".yml"];
11568
+ var DERIVED_SUFFIX = ".derived";
11528
11569
  var KNOWN_TYPES = [
11529
11570
  "skill",
11530
11571
  "command",
@@ -11547,9 +11588,6 @@ function isKnownType(type) {
11547
11588
  var DEPRECATED_REJECTED_TYPES = new Set(["tool", "vault"]);
11548
11589
 
11549
11590
  // src/core/asset/asset-placement.ts
11550
- function toPosix(input) {
11551
- return input.replace(/\\/g, "/");
11552
- }
11553
11591
  var workflowSpec = {
11554
11592
  isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path5.extname(fileName).toLowerCase()),
11555
11593
  toCanonicalName: (typeRoot, filePath) => {
@@ -11685,6 +11723,9 @@ function assetPathForName(assetType, typeRoot, name) {
11685
11723
  }
11686
11724
  function assetPathCandidatesForName(assetType, typeRoot, name) {
11687
11725
  const primary = assetPathForName(assetType, typeRoot, name);
11726
+ if (assetType === "memory" && !name.endsWith(DERIVED_SUFFIX)) {
11727
+ return [primary, assetPathForName(assetType, typeRoot, `${name}${DERIVED_SUFFIX}`)];
11728
+ }
11688
11729
  if (assetType !== "env")
11689
11730
  return [primary];
11690
11731
  const base = name === "default" ? "" : name.endsWith("/default") ? name.slice(0, -"default".length) : undefined;
@@ -12724,6 +12765,7 @@ function readTags(value) {
12724
12765
  const tags = value.filter((tag) => typeof tag === "string" && tag.trim().length > 0);
12725
12766
  return tags.length > 0 ? tags : undefined;
12726
12767
  }
12768
+ var RESERVED_FILES = new Set(["index.md", "log.md"]);
12727
12769
  function checkMissingUpdated(data, frontmatterText) {
12728
12770
  return frontmatterText !== null && !("updated" in data);
12729
12771
  }
@@ -12861,12 +12903,8 @@ var NAME_MAX = 64;
12861
12903
  var DESCRIPTION_MAX = 1024;
12862
12904
  var RESERVED_NAME_WORDS = ["anthropic", "claude"];
12863
12905
  var NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
12864
- var MAX_CONTENT_CHARS = 1e5;
12865
- function toPosix2(p) {
12866
- return p.replace(/\\/g, "/");
12867
- }
12868
12906
  function skillPackage(relPath) {
12869
- const posix = toPosix2(relPath);
12907
+ const posix = toPosix(relPath);
12870
12908
  const segs = posix.split("/").filter((s) => s.length > 0);
12871
12909
  if (segs.length < 2 || segs[segs.length - 1] !== SKILL_MANIFEST)
12872
12910
  return null;
@@ -12895,7 +12933,7 @@ function recognize(c, file) {
12895
12933
  adapterId: "agent-skills",
12896
12934
  type: "skill",
12897
12935
  name,
12898
- content: body.length > MAX_CONTENT_CHARS ? body.slice(0, MAX_CONTENT_CHARS) : body
12936
+ content: body
12899
12937
  };
12900
12938
  if (description !== undefined)
12901
12939
  doc.description = description;
@@ -12983,7 +13021,7 @@ async function validate(_c, changes, ctx) {
12983
13021
  if (seenDirs.has(pkg.conceptId))
12984
13022
  continue;
12985
13023
  seenDirs.add(pkg.conceptId);
12986
- diagnostics.push(...skillFieldDiagnostics(toPosix2(change.path), pkg.dirName, parseFrontmatter(raw).data));
13024
+ diagnostics.push(...skillFieldDiagnostics(toPosix(change.path), pkg.dirName, parseFrontmatter(raw).data));
12987
13025
  }
12988
13026
  diagnostics.push(...await missingManifestDiagnostics(ctx));
12989
13027
  return diagnostics;
@@ -14842,24 +14880,6 @@ import path14 from "node:path";
14842
14880
 
14843
14881
  // src/commands/env/env.ts
14844
14882
  var import_dotenv = __toESM(require_main(), 1);
14845
- var ASSIGN_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
14846
- function scanEnvKeyNames(text) {
14847
- const keys = [];
14848
- const seen = new Set;
14849
- for (const line of text.split(/\r?\n/)) {
14850
- const m = line.match(ASSIGN_RE);
14851
- if (!m)
14852
- continue;
14853
- const key = m[1];
14854
- if (!key)
14855
- continue;
14856
- if (seen.has(key))
14857
- continue;
14858
- seen.add(key);
14859
- keys.push(key);
14860
- }
14861
- return keys;
14862
- }
14863
14883
 
14864
14884
  // src/commands/lint/env-key-rules.ts
14865
14885
  var DANGEROUS_ENV_KEYS = new Set([
@@ -14997,19 +15017,6 @@ function own2(value, key) {
14997
15017
  function utf8Bytes2(value) {
14998
15018
  return new TextEncoder().encode(value).byteLength;
14999
15019
  }
15000
- function wellFormedUnicode(value) {
15001
- for (let index = 0;index < value.length; index += 1) {
15002
- const code = value.charCodeAt(index);
15003
- if (code >= 55296 && code <= 56319) {
15004
- const next = value.charCodeAt(index + 1);
15005
- if (!(next >= 56320 && next <= 57343))
15006
- return false;
15007
- index += 1;
15008
- } else if (code >= 56320 && code <= 57343)
15009
- return false;
15010
- }
15011
- return true;
15012
- }
15013
15020
  function sourceError(ctx, fieldPath, detail) {
15014
15021
  const dotted = fieldPath.length === 0 ? "$" : fieldPath.reduce((display, segment) => typeof segment === "number" ? `${display}[${segment}]` : display.length > 0 ? `${display}.${segment}` : segment, "");
15015
15022
  const line = ctx.lineAt?.(fieldPath);
@@ -15421,9 +15428,6 @@ function pointerFor(path10) {
15421
15428
  function pushIssue(issues, path10, keyword, kind, message) {
15422
15429
  issues.push({ path: [...path10], pointer: pointerFor(path10), keyword, kind, message });
15423
15430
  }
15424
- function isPlainObject(value) {
15425
- return typeof value === "object" && value !== null && !Array.isArray(value);
15426
- }
15427
15431
  function isSupportedEnumValue(value) {
15428
15432
  return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
15429
15433
  }
@@ -15473,7 +15477,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15473
15477
  continue;
15474
15478
  }
15475
15479
  branches.forEach((branch, index) => {
15476
- if (isPlainObject(branch)) {
15480
+ if (isRecord(branch)) {
15477
15481
  checkDefinitionNode(branch, [...path10, keyword, index], issues, depth + 1);
15478
15482
  } else {
15479
15483
  pushIssue(issues, [...path10, keyword, index], keyword, "malformed", `"${keyword}[${index}]" must be a schema object`);
@@ -15481,7 +15485,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15481
15485
  });
15482
15486
  }
15483
15487
  if (schema.not !== undefined) {
15484
- if (isPlainObject(schema.not)) {
15488
+ if (isRecord(schema.not)) {
15485
15489
  checkDefinitionNode(schema.not, [...path10, "not"], issues, depth + 1);
15486
15490
  } else {
15487
15491
  pushIssue(issues, [...path10, "not"], "not", "malformed", `"not" must be a schema object`);
@@ -15493,11 +15497,11 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15493
15497
  }
15494
15498
  }
15495
15499
  if (schema.properties !== undefined) {
15496
- if (!isPlainObject(schema.properties)) {
15500
+ if (!isRecord(schema.properties)) {
15497
15501
  pushIssue(issues, [...path10, "properties"], "properties", "malformed", `"properties" must be an object mapping property names to schemas`);
15498
15502
  } else {
15499
15503
  for (const [key, propSchema] of Object.entries(schema.properties)) {
15500
- if (isPlainObject(propSchema)) {
15504
+ if (isRecord(propSchema)) {
15501
15505
  checkDefinitionNode(propSchema, [...path10, "properties", key], issues, depth + 1);
15502
15506
  } else {
15503
15507
  pushIssue(issues, [...path10, "properties", key], "properties", "malformed", `property ${JSON.stringify(key)} must be a schema object`);
@@ -15506,7 +15510,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15506
15510
  }
15507
15511
  }
15508
15512
  if (schema.items !== undefined) {
15509
- if (isPlainObject(schema.items)) {
15513
+ if (isRecord(schema.items)) {
15510
15514
  checkDefinitionNode(schema.items, [...path10, "items"], issues, depth + 1);
15511
15515
  } else if (Array.isArray(schema.items)) {
15512
15516
  pushIssue(issues, [...path10, "items"], "items", "unsupported", `tuple-form "items" (an array of schemas) is not enforced by the workflow schema subset — use a single schema object`);
@@ -15515,7 +15519,7 @@ function checkDefinitionNode(schema, path10, issues, depth) {
15515
15519
  }
15516
15520
  }
15517
15521
  if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== "boolean") {
15518
- if (isPlainObject(schema.additionalProperties)) {
15522
+ if (isRecord(schema.additionalProperties)) {
15519
15523
  pushIssue(issues, [...path10, "additionalProperties"], "additionalProperties", "unsupported", `schema-form "additionalProperties" is not enforced by the workflow schema subset — only "additionalProperties: false" is`);
15520
15524
  } else {
15521
15525
  pushIssue(issues, [...path10, "additionalProperties"], "additionalProperties", "malformed", `"additionalProperties" must be a boolean (only "false" is enforced)`);
@@ -15564,7 +15568,7 @@ function combinatorBranches(schema, keyword) {
15564
15568
  const raw = schema[keyword];
15565
15569
  if (!Array.isArray(raw))
15566
15570
  return [];
15567
- return raw.filter(isPlainObject);
15571
+ return raw.filter(isRecord);
15568
15572
  }
15569
15573
  function summarizeBranchFailures(failures) {
15570
15574
  const shown = failures.slice(0, 3).map((f) => `${f.index + 1}: ${f.errors[0] ?? "no match"}`);
@@ -15596,7 +15600,7 @@ function validateCombinators(value, schema, path10, ctx) {
15596
15600
  }
15597
15601
  }
15598
15602
  const not = schema.not;
15599
- if (isPlainObject(not) && branchErrors(value, not, path10, ctx).length === 0) {
15603
+ if (isRecord(not) && branchErrors(value, not, path10, ctx).length === 0) {
15600
15604
  ctx.errors.push(`${path10}: value must not match the "not" schema`);
15601
15605
  }
15602
15606
  }
@@ -16352,20 +16356,17 @@ function formatExtraParamsIssue(label, issue) {
16352
16356
  const suffix = issue.path.map((part) => typeof part === "number" ? `[${part}]` : `.${part}`).join("");
16353
16357
  return `${label}${suffix} ${issue.message}`;
16354
16358
  }
16355
- function isPlainObject2(value) {
16356
- return typeof value === "object" && value !== null && !Array.isArray(value);
16357
- }
16358
16359
  function liftLegacyEngineExtraParams(raw) {
16359
16360
  const lifted = [];
16360
16361
  const conflicts = [];
16361
16362
  const rawEngines = raw.engines;
16362
- if (!isPlainObject2(rawEngines)) {
16363
+ if (!isRecord(rawEngines)) {
16363
16364
  return { config: raw, lifted, conflicts };
16364
16365
  }
16365
16366
  const engines = {};
16366
16367
  let anyEngineChanged = false;
16367
16368
  for (const [name, engineValue] of Object.entries(rawEngines)) {
16368
- if (!isPlainObject2(engineValue) || !isPlainObject2(engineValue.extraParams)) {
16369
+ if (!isRecord(engineValue) || !isRecord(engineValue.extraParams)) {
16369
16370
  engines[name] = engineValue;
16370
16371
  continue;
16371
16372
  }
@@ -17606,6 +17607,9 @@ function peekTaskSourceVersion(root) {
17606
17607
  return typeof value === "number" ? value : undefined;
17607
17608
  }
17608
17609
  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`.";
17610
+ function unmigratableVersionError(filePath, version, reason, detail) {
17611
+ return new UsageError(`TASK_SCHEMA_VERSION_UNSUPPORTED: Task at ${filePath} uses task schema version ${version} and needs a human decision before it can run — the deterministic migrator cannot convert it automatically (${reason}${detail ? `: ${detail}` : ""}).`, "TASK_SCHEMA_VERSION_UNSUPPORTED", "Review the file and resolve the ambiguity by hand, then it will convert normally; `akm migrate status` reports the same reason.");
17612
+ }
17609
17613
  function unsupportedVersionError(filePath, version) {
17610
17614
  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);
17611
17615
  }
@@ -17625,12 +17629,12 @@ function planInMemoryV4Bytes(version, yaml, filePath, workspaceRoot) {
17625
17629
  } else {
17626
17630
  const v3Outcome = planTaskToV3File(baseInput);
17627
17631
  if (v3Outcome.status !== "changed")
17628
- return;
17632
+ return { reason: v3Outcome.reason, detail: v3Outcome.detail };
17629
17633
  v3Bytes = v3Outcome.after;
17630
17634
  }
17631
17635
  const v4Outcome = planTaskToV4File({ ...baseInput, bytes: v3Bytes });
17632
17636
  if (v4Outcome.status !== "changed")
17633
- return;
17637
+ return { reason: v4Outcome.reason, detail: v4Outcome.detail };
17634
17638
  return v4Outcome.after.toString("utf8");
17635
17639
  }
17636
17640
  function parseTaskSource(input) {
@@ -17638,16 +17642,17 @@ function parseTaskSource(input) {
17638
17642
  const version = peekTaskSourceVersion(root);
17639
17643
  if (version !== undefined && version !== TASK_SOURCE_V4_VERSION) {
17640
17644
  if (version === 2 || version === 3) {
17641
- const v4Yaml = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17642
- if (v4Yaml !== undefined) {
17645
+ const shimmed = planInMemoryV4Bytes(version, input.yaml, input.filePath, input.workspaceRoot);
17646
+ if (typeof shimmed === "string") {
17643
17647
  const v4 = parseTaskSourceV4({
17644
- yaml: v4Yaml,
17648
+ yaml: shimmed,
17645
17649
  filePath: input.filePath,
17646
17650
  ...input.workspaceRoot ? { workspaceRoot: input.workspaceRoot } : {}
17647
17651
  });
17648
17652
  warn(`akm: task ${input.filePath} uses schema v${version} — auto-read as v4; run \`akm migrate apply\` to rewrite it and silence this`);
17649
17653
  return Object.freeze({ version: 4, v4 });
17650
17654
  }
17655
+ throw unmigratableVersionError(input.filePath, version, shimmed.reason, shimmed.detail);
17651
17656
  }
17652
17657
  throw unsupportedVersionError(input.filePath, version);
17653
17658
  }
@@ -17881,11 +17886,6 @@ function sourceStepRef(source) {
17881
17886
  // src/workflows/source-ir/schema.ts
17882
17887
  import { types as utilTypes2 } from "node:util";
17883
17888
 
17884
- // src/workflows/source-ir/compare.ts
17885
- function compareWorkflowSourceCodePoints(left, right) {
17886
- return left < right ? -1 : left > right ? 1 : 0;
17887
- }
17888
-
17889
17889
  // src/workflows/source-ir/semantics.ts
17890
17890
  import fs7 from "node:fs";
17891
17891
  import path12 from "node:path";
@@ -18524,9 +18524,6 @@ function validateStep(value, jobId, index, stepIds, options) {
18524
18524
  extensions(step.extensions, `step ${id} extensions`);
18525
18525
  span(step.source, `step ${id} source`);
18526
18526
  }
18527
- function compareCodePoints(left, right) {
18528
- return compareWorkflowSourceCodePoints(left, right);
18529
- }
18530
18527
  function validateExec(value, location, options) {
18531
18528
  if (value === undefined)
18532
18529
  return;
@@ -18832,7 +18829,7 @@ function snapshotValue(value, depth, location, state) {
18832
18829
  return value;
18833
18830
  }
18834
18831
  if (typeof value === "string") {
18835
- if (!wellFormedUnicode2(value))
18832
+ if (!wellFormedUnicode(value))
18836
18833
  fail2(`${location} must contain well-formed Unicode`);
18837
18834
  countJsonBytes(state, JSON.stringify(value));
18838
18835
  return value;
@@ -18896,7 +18893,7 @@ function snapshotObject(value, depth, location, state) {
18896
18893
  for (const [index, key] of ownKeys.entries()) {
18897
18894
  if (typeof key === "symbol")
18898
18895
  fail2(`${location} contains symbol keys`);
18899
- if (!wellFormedUnicode2(key))
18896
+ if (!wellFormedUnicode(key))
18900
18897
  fail2(`${location} contains an ill-formed key`);
18901
18898
  if (UNSAFE_KEYS.has(key))
18902
18899
  fail2(`${location} contains unsafe key ${key}`);
@@ -18925,20 +18922,6 @@ function countJsonBytes(state, token) {
18925
18922
  if (state.bytes > WORKFLOW_SOURCE_IR_MAX_BYTES)
18926
18923
  fail2("source IR exceeds the byte limit");
18927
18924
  }
18928
- function wellFormedUnicode2(value) {
18929
- for (let index = 0;index < value.length; index++) {
18930
- const code = value.charCodeAt(index);
18931
- if (code >= 55296 && code <= 56319) {
18932
- const next = value.charCodeAt(index + 1);
18933
- if (!(next >= 56320 && next <= 57343))
18934
- return false;
18935
- index++;
18936
- } else if (code >= 56320 && code <= 57343) {
18937
- return false;
18938
- }
18939
- }
18940
- return true;
18941
- }
18942
18925
  function record(value, location) {
18943
18926
  if (value === null || typeof value !== "object" || Array.isArray(value))
18944
18927
  fail2(`${location} must be an object`);
@@ -19083,14 +19066,11 @@ function compileWorkflowPlan(input, title, resolvedUnits = new Map) {
19083
19066
  }
19084
19067
  function sortedOutputs(outputs) {
19085
19068
  const sorted = {};
19086
- for (const name of Object.keys(outputs).sort(compareCodePoints2)) {
19069
+ for (const name of Object.keys(outputs).sort(compareCodePoints)) {
19087
19070
  sorted[name] = outputs[name];
19088
19071
  }
19089
19072
  return sorted;
19090
19073
  }
19091
- function compareCodePoints2(left, right) {
19092
- return left < right ? -1 : left > right ? 1 : 0;
19093
- }
19094
19074
  function compileStep(step, sequenceIndex, defaults, resolved) {
19095
19075
  const gate = {
19096
19076
  kind: "gate",
@@ -19217,12 +19197,6 @@ function collectWorkflowWarnings(input) {
19217
19197
  message: `Step "${step.id}" declares \`gate.max_loops: ${maxLoops}\` on an \`exec\` step — 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.`
19218
19198
  });
19219
19199
  }
19220
- if ((step.map || step.route === undefined) && step.output === undefined) {
19221
- warnings.push({
19222
- line: step.source.start,
19223
- message: `Step "${step.id}" declares no \`output:\` schema — its unit results are carried as an untyped ` + `artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`
19224
- });
19225
- }
19226
19200
  if (declaredParams) {
19227
19201
  const declaredList = [...declaredParams].join(", ");
19228
19202
  const scan = (text, label) => {
@@ -19436,7 +19410,7 @@ function parseWorkflow(markdown, source) {
19436
19410
  };
19437
19411
  if (root === null || root === undefined)
19438
19412
  root = {};
19439
- if (!isPlainRecord(root)) {
19413
+ if (!isRecord(root)) {
19440
19414
  return {
19441
19415
  ok: false,
19442
19416
  errors: [{ line: 2, message: `Workflow frontmatter must be a YAML mapping (key: value pairs).` }]
@@ -19617,7 +19591,7 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
19617
19591
  checkActorStamp(ctx, root.verified, ["verified"], `"verified"`);
19618
19592
  }
19619
19593
  }
19620
- if (root.provenance !== undefined && !isPlainRecord(root.provenance)) {
19594
+ if (root.provenance !== undefined && !isRecord(root.provenance)) {
19621
19595
  ctx.err(["provenance"], `Workflow frontmatter "provenance" must be a mapping.`);
19622
19596
  }
19623
19597
  if (root.status !== undefined && (typeof root.status !== "string" || !LIFECYCLE_STATUSES.has(root.status))) {
@@ -19630,7 +19604,7 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
19630
19604
  function checkActorStamp(ctx, value, path13, label) {
19631
19605
  if (value === undefined)
19632
19606
  return;
19633
- if (!isPlainRecord(value)) {
19607
+ if (!isRecord(value)) {
19634
19608
  ctx.err(path13, `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
19635
19609
  return;
19636
19610
  }
@@ -19661,7 +19635,7 @@ function checkXrefs2(ctx, value, fmEndLine) {
19661
19635
  function parseParams(ctx, raw) {
19662
19636
  if (raw === undefined)
19663
19637
  return;
19664
- if (!isPlainRecord(raw)) {
19638
+ if (!isRecord(raw)) {
19665
19639
  ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
19666
19640
  return;
19667
19641
  }
@@ -19671,7 +19645,7 @@ function parseParams(ctx, raw) {
19671
19645
  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.`);
19672
19646
  continue;
19673
19647
  }
19674
- if (!isPlainRecord(value)) {
19648
+ if (!isRecord(value)) {
19675
19649
  ctx.err(["params", paramName], `Param "${paramName}" must be a JSON Schema object (e.g. { type: string }).`);
19676
19650
  continue;
19677
19651
  }
@@ -19686,7 +19660,7 @@ function parseParams(ctx, raw) {
19686
19660
  function parseOutputs(ctx, raw) {
19687
19661
  if (raw === undefined)
19688
19662
  return;
19689
- if (!isPlainRecord(raw)) {
19663
+ if (!isRecord(raw)) {
19690
19664
  ctx.err(["outputs"], `"outputs" must be a mapping of output name to { from, schema? } (e.g. report: { from: steps.summarize.output }).`);
19691
19665
  return;
19692
19666
  }
@@ -19697,7 +19671,7 @@ function parseOutputs(ctx, raw) {
19697
19671
  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.`);
19698
19672
  continue;
19699
19673
  }
19700
- if (!isPlainRecord(value)) {
19674
+ if (!isRecord(value)) {
19701
19675
  ctx.err(path13, `Output "${outputName}" must be a mapping with "from" (and optional "schema").`);
19702
19676
  continue;
19703
19677
  }
@@ -19717,7 +19691,7 @@ function parseOutputs(ctx, raw) {
19717
19691
  }
19718
19692
  const entry = { from: value.from };
19719
19693
  if (value.schema !== undefined) {
19720
- if (!isPlainRecord(value.schema)) {
19694
+ if (!isRecord(value.schema)) {
19721
19695
  ctx.err([...path13, "schema"], `Output "${outputName}" "schema" must be a JSON Schema object.`);
19722
19696
  } else {
19723
19697
  if (jsonBytes(value.schema) > WORKFLOW_MAX_SCHEMA_BYTES) {
@@ -19735,7 +19709,7 @@ function parseDefaults(ctx, raw) {
19735
19709
  if (raw === undefined)
19736
19710
  return;
19737
19711
  const path13 = ["defaults"];
19738
- if (!isPlainRecord(raw)) {
19712
+ if (!isRecord(raw)) {
19739
19713
  ctx.err(path13, `"defaults" must be a mapping with any of: ${DEFAULTS_KEYS.join(", ")}.`);
19740
19714
  return;
19741
19715
  }
@@ -19767,7 +19741,7 @@ function parseBudget(ctx, raw) {
19767
19741
  if (raw === undefined)
19768
19742
  return;
19769
19743
  const path13 = ["budget"];
19770
- if (!isPlainRecord(raw)) {
19744
+ if (!isRecord(raw)) {
19771
19745
  ctx.err(path13, `"budget" must be a mapping with any of: ${BUDGET_KEYS.join(", ")}.`);
19772
19746
  return;
19773
19747
  }
@@ -19796,7 +19770,7 @@ function parseSteps(ctx, raw) {
19796
19770
  }
19797
19771
  const idIndex = new Map;
19798
19772
  raw.forEach((rawStep, index) => {
19799
- if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
19773
+ if (isRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
19800
19774
  idIndex.set(rawStep.id, index);
19801
19775
  }
19802
19776
  });
@@ -19805,7 +19779,7 @@ function parseSteps(ctx, raw) {
19805
19779
  const routeChecks = [];
19806
19780
  raw.forEach((rawStep, index) => {
19807
19781
  const path13 = ["steps", index];
19808
- if (!isPlainRecord(rawStep)) {
19782
+ if (!isRecord(rawStep)) {
19809
19783
  ctx.err(path13, `Step ${index + 1} must be a mapping with an "id".`);
19810
19784
  return;
19811
19785
  }
@@ -19879,7 +19853,7 @@ function parseSteps(ctx, raw) {
19879
19853
  return steps;
19880
19854
  }
19881
19855
  function parseUnit(ctx, raw, path13, stepLabel) {
19882
- if (!isPlainRecord(raw)) {
19856
+ if (!isRecord(raw)) {
19883
19857
  ctx.err(path13, `${stepLabel} "unit" must be a mapping (a dispatch-override bag).`);
19884
19858
  return;
19885
19859
  }
@@ -19940,7 +19914,7 @@ function parseUnit(ctx, raw, path13, stepLabel) {
19940
19914
  return unit;
19941
19915
  }
19942
19916
  function parseExec(ctx, raw, path13, stepLabel) {
19943
- if (!isPlainRecord(raw)) {
19917
+ if (!isRecord(raw)) {
19944
19918
  ctx.err(path13, `${stepLabel} "exec" must be a mapping with a "command" argv list.`);
19945
19919
  return;
19946
19920
  }
@@ -20024,7 +19998,7 @@ function parseExecCwd(ctx, raw, path13, stepLabel) {
20024
19998
  return value;
20025
19999
  }
20026
20000
  function parseMap(ctx, raw, path13, stepLabel) {
20027
- if (!isPlainRecord(raw)) {
20001
+ if (!isRecord(raw)) {
20028
20002
  ctx.err(path13, `${stepLabel} "map" must be a mapping with an "over" key.`);
20029
20003
  return;
20030
20004
  }
@@ -20056,7 +20030,7 @@ function parseMap(ctx, raw, path13, stepLabel) {
20056
20030
  return map;
20057
20031
  }
20058
20032
  function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20059
- if (!isPlainRecord(raw)) {
20033
+ if (!isRecord(raw)) {
20060
20034
  ctx.err(path13, `${stepLabel} "route" must be a mapping with "input" and "when" keys.`);
20061
20035
  return;
20062
20036
  }
@@ -20076,7 +20050,7 @@ function parseRoute(ctx, raw, path13, stepLabel, stepIndex, routeChecks) {
20076
20050
  const seenMatches = new Map;
20077
20051
  raw.when.forEach((branch, i) => {
20078
20052
  const branchPath = [...whenPath, i];
20079
- if (!isPlainRecord(branch)) {
20053
+ if (!isRecord(branch)) {
20080
20054
  ctx.err(branchPath, `${stepLabel} "when[${i}]" must be a mapping: { match, step }.`);
20081
20055
  return;
20082
20056
  }
@@ -20147,7 +20121,7 @@ function parseInputs(ctx, raw, path13, stepLabel) {
20147
20121
  return out.length > 0 ? out : undefined;
20148
20122
  }
20149
20123
  function parseGate(ctx, raw, path13, stepLabel) {
20150
- if (!isPlainRecord(raw)) {
20124
+ if (!isRecord(raw)) {
20151
20125
  ctx.err(path13, `${stepLabel} "gate" must be a mapping with any of: ${GATE_KEYS.join(", ")}.`);
20152
20126
  return;
20153
20127
  }
@@ -20177,7 +20151,7 @@ function parseEngineName(ctx, raw, path13, label) {
20177
20151
  function parseRetry(ctx, raw, path13, stepLabel) {
20178
20152
  if (raw === undefined)
20179
20153
  return;
20180
- if (!isPlainRecord(raw)) {
20154
+ if (!isRecord(raw)) {
20181
20155
  ctx.err(path13, `${stepLabel} "retry" must be a mapping: { max: <n>, on: [<failure_reason>, …] }.`);
20182
20156
  return;
20183
20157
  }
@@ -20250,7 +20224,7 @@ function parseEnumField(ctx, raw, path13, label, allowed) {
20250
20224
  function parseLlmOverrides(ctx, raw, path13, label) {
20251
20225
  if (raw === undefined)
20252
20226
  return;
20253
- if (!isPlainRecord(raw)) {
20227
+ if (!isRecord(raw)) {
20254
20228
  ctx.err(path13, `${label} must be a mapping of LLM invocation overrides.`);
20255
20229
  return;
20256
20230
  }
@@ -20284,7 +20258,7 @@ function parseLlmOverrides(ctx, raw, path13, label) {
20284
20258
  ctx.err([...path13, "supports_json_schema"], `${label}.supports_json_schema must be a boolean.`);
20285
20259
  }
20286
20260
  if (raw.extra_params !== undefined) {
20287
- if (!isPlainRecord(raw.extra_params)) {
20261
+ if (!isRecord(raw.extra_params)) {
20288
20262
  ctx.err([...path13, "extra_params"], `${label}.extra_params must be a JSON object.`);
20289
20263
  } else {
20290
20264
  const issues = validateExtraParams(raw.extra_params);
@@ -20322,7 +20296,7 @@ function parseLlmOverrides(ctx, raw, path13, label) {
20322
20296
  function parseSchemaObject(ctx, raw, path13, label) {
20323
20297
  if (raw === undefined)
20324
20298
  return;
20325
- if (!isPlainRecord(raw)) {
20299
+ if (!isRecord(raw)) {
20326
20300
  ctx.err(path13, `${label} must be a JSON Schema object (e.g. { type: object, properties: { … } }).`);
20327
20301
  return;
20328
20302
  }
@@ -20354,9 +20328,6 @@ function checkUnknownKeys(ctx, obj, path13, allowed, label) {
20354
20328
  }
20355
20329
  }
20356
20330
  }
20357
- function isPlainRecord(value) {
20358
- return typeof value === "object" && value !== null && !Array.isArray(value);
20359
- }
20360
20331
  function describeError(cause) {
20361
20332
  return cause instanceof Error ? cause.message : String(cause);
20362
20333
  }
@@ -21237,22 +21208,6 @@ function nameOrTypeDiagnostics(relPath, data, frontmatter, allowedTypes) {
21237
21208
  }
21238
21209
  return [];
21239
21210
  }
21240
- var ASSIGN_RE2 = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
21241
- function scanKeys(text) {
21242
- const keys2 = [];
21243
- const seen = new Set;
21244
- for (const line of text.split(/\r?\n/)) {
21245
- const m = line.match(ASSIGN_RE2);
21246
- if (!m)
21247
- continue;
21248
- const key = m[1];
21249
- if (seen.has(key))
21250
- continue;
21251
- seen.add(key);
21252
- keys2.push(key);
21253
- }
21254
- return keys2;
21255
- }
21256
21211
  function collectSuppressedKeys(raw) {
21257
21212
  const suppressed = new Set;
21258
21213
  const lines = raw.split(/\r?\n/);
@@ -21276,7 +21231,7 @@ function dangerousEnvKeyDiagnostics(type, relPath, raw) {
21276
21231
  if (!baseNameWithExt.endsWith(".env"))
21277
21232
  return [];
21278
21233
  const ref = conceptIdForStashFile(type, ".", relPath);
21279
- const keys2 = scanKeys(raw);
21234
+ const keys2 = scanEnvKeyNames(raw);
21280
21235
  const suppressed = collectSuppressedKeys(raw);
21281
21236
  const diagnostics = [];
21282
21237
  for (const key of keys2) {
@@ -21726,7 +21681,6 @@ function applyFoldedMetadata(entry, folded) {
21726
21681
  }
21727
21682
 
21728
21683
  // src/core/adapter/adapters/akm-adapter.ts
21729
- var RESERVED_FILES = new Set(["index.md", "log.md"]);
21730
21684
  function isReservedFileName(name) {
21731
21685
  return RESERVED_FILES.has(name.toLowerCase());
21732
21686
  }
@@ -22062,14 +22016,10 @@ import fs9 from "node:fs";
22062
22016
  import path16 from "node:path";
22063
22017
  var COMPONENT_ID2 = "main";
22064
22018
  var TASK_EXT = TASK_EXTENSION;
22065
- var MAX_CONTENT_CHARS2 = 1e5;
22066
- function toPosix3(p) {
22067
- return p.replace(/\\/g, "/");
22068
- }
22069
22019
  function recognize3(c, file) {
22070
22020
  if (file.ext !== TASK_EXT)
22071
22021
  return null;
22072
- const conceptId = toPosix3(file.relPath).replace(/\.yml$/i, "");
22022
+ const conceptId = toPosix(file.relPath).replace(/\.yml$/i, "");
22073
22023
  const name = conceptId.split("/").pop() ?? conceptId;
22074
22024
  const raw = file.content();
22075
22025
  return {
@@ -22082,7 +22032,7 @@ function recognize3(c, file) {
22082
22032
  adapterId: "akm-task",
22083
22033
  type: "task",
22084
22034
  name,
22085
- content: raw.length > MAX_CONTENT_CHARS2 ? raw.slice(0, MAX_CONTENT_CHARS2) : raw
22035
+ content: raw
22086
22036
  };
22087
22037
  }
22088
22038
  async function validate3(c, changes, ctx) {
@@ -22096,7 +22046,7 @@ async function validate3(c, changes, ctx) {
22096
22046
  const ext = path16.extname(change.path).toLowerCase();
22097
22047
  if (ext !== TASK_EXT && ext !== TASK_NEAR_MISS_EXTENSION)
22098
22048
  continue;
22099
- const relPath = toPosix3(change.path);
22049
+ const relPath = toPosix(change.path);
22100
22050
  if (ext === TASK_NEAR_MISS_EXTENSION) {
22101
22051
  diagnostics.push({
22102
22052
  file: relPath,
@@ -22126,14 +22076,14 @@ var akmTaskAdapter = {
22126
22076
  recognize: recognize3,
22127
22077
  validate: validate3,
22128
22078
  readCandidates(c, conceptId) {
22129
- const posix = toPosix3(conceptId).replace(/\.ya?ml$/i, "");
22079
+ const posix = toPosix(conceptId).replace(/\.ya?ml$/i, "");
22130
22080
  return [
22131
22081
  { path: path16.join(c.root, `${posix}.yml`), conceptId: posix },
22132
22082
  { path: path16.join(c.root, `${posix}.yaml`), conceptId: posix }
22133
22083
  ];
22134
22084
  },
22135
22085
  placeNew(c, conceptId) {
22136
- const posix = toPosix3(conceptId);
22086
+ const posix = toPosix(conceptId);
22137
22087
  return path16.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
22138
22088
  },
22139
22089
  directoryList() {
@@ -22169,12 +22119,8 @@ import fs10 from "node:fs";
22169
22119
  import path17 from "node:path";
22170
22120
  var COMPONENT_ID3 = "main";
22171
22121
  var WORKFLOW_EXTS = new Set([".md", ".yml"]);
22172
- var MAX_CONTENT_CHARS3 = 1e5;
22173
- function toPosix4(p) {
22174
- return p.replace(/\\/g, "/");
22175
- }
22176
22122
  function conceptIdOf(relPath) {
22177
- return toPosix4(relPath).replace(/\.(?:md|yml)$/i, "");
22123
+ return toPosix(relPath).replace(/\.(?:md|yml)$/i, "");
22178
22124
  }
22179
22125
  function isReservedDocFile(fileName) {
22180
22126
  return fileName.toLowerCase() === "readme.md";
@@ -22208,7 +22154,7 @@ function recognize4(c, file) {
22208
22154
  adapterId: "akm-workflow",
22209
22155
  type: "workflow",
22210
22156
  name,
22211
- content: body.length > MAX_CONTENT_CHARS3 ? body.slice(0, MAX_CONTENT_CHARS3) : body
22157
+ content: body
22212
22158
  };
22213
22159
  if (description !== undefined)
22214
22160
  doc.description = description;
@@ -22227,7 +22173,7 @@ async function validate4(c, changes, ctx) {
22227
22173
  const ext = path17.extname(change.path).toLowerCase();
22228
22174
  if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(path17.basename(change.path)))
22229
22175
  continue;
22230
- const relPath = toPosix4(change.path);
22176
+ const relPath = toPosix(change.path);
22231
22177
  if (ext === ".yml") {
22232
22178
  diagnostics.push(...workflowYamlSourceDiagnostics(relPath, raw, relPath, c.root).errors);
22233
22179
  continue;
@@ -22277,7 +22223,7 @@ var akmWorkflowAdapter = {
22277
22223
  recognize: recognize4,
22278
22224
  validate: validate4,
22279
22225
  readCandidates(c, conceptId) {
22280
- const posix = toPosix4(conceptId);
22226
+ const posix = toPosix(conceptId);
22281
22227
  const canonical = posix.replace(/\.(?:md|yml)$/i, "");
22282
22228
  return /\.(?:md|yml)$/i.test(posix) ? [{ path: path17.join(c.root, posix), conceptId: canonical }] : [
22283
22229
  { path: path17.join(c.root, `${posix}.md`), conceptId: canonical },
@@ -22285,7 +22231,7 @@ var akmWorkflowAdapter = {
22285
22231
  ];
22286
22232
  },
22287
22233
  placeNew(c, conceptId) {
22288
- const posix = toPosix4(conceptId);
22234
+ const posix = toPosix(conceptId);
22289
22235
  if (/\.(?:md|yml)$/i.test(posix))
22290
22236
  return path17.join(c.root, posix);
22291
22237
  return path17.join(c.root, `${posix}.md`);
@@ -22310,20 +22256,15 @@ import path19 from "node:path";
22310
22256
 
22311
22257
  // src/core/adapter/adapters/tool-dir-shared.ts
22312
22258
  import path18 from "node:path";
22313
- var RESERVED_FILES2 = new Set(["index.md", "log.md"]);
22314
- var MAX_CONTENT_CHARS4 = 1e5;
22315
22259
  var CANONICAL_COMMAND_DIR = "commands";
22316
22260
  var CANONICAL_AGENT_DIR = "agents";
22317
22261
  var CANONICAL_SKILL_DIR = "skills";
22318
22262
  var SKILL_MANIFEST2 = "SKILL.md";
22319
- function toPosix5(p) {
22320
- return p.replace(/\\/g, "/");
22321
- }
22322
22263
  function isReserved(base3) {
22323
- return RESERVED_FILES2.has(base3.toLowerCase());
22264
+ return RESERVED_FILES.has(base3.toLowerCase());
22324
22265
  }
22325
22266
  function classify(relPath, layout) {
22326
- const posix = toPosix5(relPath);
22267
+ const posix = toPosix(relPath);
22327
22268
  const segs = posix.split("/").filter((s) => s.length > 0);
22328
22269
  if (segs.length === 0)
22329
22270
  return null;
@@ -22370,7 +22311,7 @@ function recognizeToolDir(layout, c, file) {
22370
22311
  adapterId: layout.adapterId,
22371
22312
  type: cls.type,
22372
22313
  name,
22373
- content: body.length > MAX_CONTENT_CHARS4 ? body.slice(0, MAX_CONTENT_CHARS4) : body
22314
+ content: body
22374
22315
  };
22375
22316
  if (cls.type === "instruction")
22376
22317
  doc.ownsPresentation = true;
@@ -22381,7 +22322,7 @@ function recognizeToolDir(layout, c, file) {
22381
22322
  return doc;
22382
22323
  }
22383
22324
  function placeNewToolDir(layout, c, conceptId) {
22384
- const posix = toPosix5(conceptId);
22325
+ const posix = toPosix(conceptId);
22385
22326
  if (posix === layout.instructionConceptId)
22386
22327
  return path18.join(c.root, layout.instructionFile);
22387
22328
  const segs = posix.split("/").filter((s) => s.length > 0);
@@ -22398,7 +22339,7 @@ function placeNewToolDir(layout, c, conceptId) {
22398
22339
  return path18.join(c.root, `${posix}.md`);
22399
22340
  }
22400
22341
  function readCandidatesToolDir(layout, c, conceptId) {
22401
- const posix = toPosix5(conceptId);
22342
+ const posix = toPosix(conceptId);
22402
22343
  if (posix === layout.instructionConceptId) {
22403
22344
  return [{ path: path18.join(c.root, layout.instructionFile), conceptId: posix }];
22404
22345
  }
@@ -22439,7 +22380,7 @@ async function validateToolDir(layout, c, changes, ctx) {
22439
22380
  const raw = change.after ?? await ctx.readFile(change.path);
22440
22381
  if (typeof raw !== "string")
22441
22382
  continue;
22442
- const relPath = toPosix5(change.path);
22383
+ const relPath = toPosix(change.path);
22443
22384
  diagnostics.push(...await skillDirectoryDiagnostics(relPath, seenSkillDirs, ctx, layout.skillDirs));
22444
22385
  const cls = classify(change.path, layout);
22445
22386
  if (cls === null)
@@ -22539,12 +22480,8 @@ var COMPONENT_ID4 = "main";
22539
22480
  var ENV_DIR = "env";
22540
22481
  var SECRETS_DIR = "secrets";
22541
22482
  var SECRET_SKIP_SUFFIXES = [".lock", ".sensitive"];
22542
- var ASSIGN_RE3 = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
22543
- function toPosix6(p) {
22544
- return p.replace(/\\/g, "/");
22545
- }
22546
22483
  function classify2(relPath) {
22547
- const posix = toPosix6(relPath);
22484
+ const posix = toPosix(relPath);
22548
22485
  const segs = posix.split("/").filter((s) => s.length > 0);
22549
22486
  if (segs.length < 2)
22550
22487
  return null;
@@ -22562,23 +22499,8 @@ function hasSensitiveMarker(absPath, type) {
22562
22499
  const marker = type === "env" ? absPath.replace(/\.env$/i, ".sensitive") : `${absPath}.sensitive`;
22563
22500
  return marker !== absPath && fs12.existsSync(marker);
22564
22501
  }
22565
- function scanKeyNames(raw) {
22566
- const keys2 = [];
22567
- const seen = new Set;
22568
- for (const line of raw.split(/\r?\n/)) {
22569
- const m = line.match(ASSIGN_RE3);
22570
- if (!m)
22571
- continue;
22572
- const key = m[1];
22573
- if (seen.has(key))
22574
- continue;
22575
- seen.add(key);
22576
- keys2.push(key);
22577
- }
22578
- return keys2;
22579
- }
22580
22502
  function conceptIdForPath(type, relativePath) {
22581
- const posix = toPosix6(relativePath);
22503
+ const posix = toPosix(relativePath);
22582
22504
  if (type === "secret")
22583
22505
  return posix;
22584
22506
  const stripped = posix.replace(/\.env$/i, "");
@@ -22590,12 +22512,12 @@ function recognize5(c, file) {
22590
22512
  return null;
22591
22513
  if (hasSensitiveMarker(file.absPath, type))
22592
22514
  return null;
22593
- const posix = toPosix6(file.relPath);
22515
+ const posix = toPosix(file.relPath);
22594
22516
  const raw = file.content();
22595
22517
  if (type === "env") {
22596
22518
  const conceptId = conceptIdForPath(type, posix);
22597
22519
  const name2 = (conceptId.split("/").pop() ?? conceptId) || "default";
22598
- const keys2 = scanKeyNames(raw);
22520
+ const keys2 = scanEnvKeyNames(raw);
22599
22521
  const doc = {
22600
22522
  ref: `${c.id}//${conceptId}`,
22601
22523
  bundle: c.id,
@@ -22635,7 +22557,7 @@ async function validate5(_c, changes, ctx) {
22635
22557
  const type = classify2(change.path);
22636
22558
  if (type === null)
22637
22559
  continue;
22638
- diagnostics.push(...dangerousEnvKeyDiagnostics(type, toPosix6(change.path), raw));
22560
+ diagnostics.push(...dangerousEnvKeyDiagnostics(type, toPosix(change.path), raw));
22639
22561
  }
22640
22562
  return diagnostics;
22641
22563
  }
@@ -22646,7 +22568,7 @@ var dotenvAdapter = {
22646
22568
  recognize: recognize5,
22647
22569
  validate: validate5,
22648
22570
  readCandidates(c, conceptId) {
22649
- const posix = toPosix6(conceptId);
22571
+ const posix = toPosix(conceptId);
22650
22572
  const slash = posix.indexOf("/");
22651
22573
  if (slash <= 0)
22652
22574
  return [];
@@ -22660,7 +22582,7 @@ var dotenvAdapter = {
22660
22582
  return expanded.map((candidatePath) => ({ path: candidatePath, conceptId: posix }));
22661
22583
  },
22662
22584
  placeNew(c, conceptId) {
22663
- const posix = toPosix6(conceptId);
22585
+ const posix = toPosix(conceptId);
22664
22586
  const slash = posix.indexOf("/");
22665
22587
  if (slash > 0) {
22666
22588
  const head = posix.slice(0, slash);
@@ -22695,13 +22617,8 @@ var dotenvAdapter = {
22695
22617
  import path21 from "node:path";
22696
22618
  var COMPONENT_ID5 = "main";
22697
22619
  var DOCUMENT_EXTENSIONS = new Set([".md", ".markdown", ".txt", ".text"]);
22698
- var RESERVED_FILES3 = new Set(["index.md", "log.md"]);
22699
- var MAX_CONTENT_CHARS5 = 1e5;
22700
- function toPosix7(p) {
22701
- return p.replace(/\\/g, "/");
22702
- }
22703
22620
  function isReserved2(base3) {
22704
- return RESERVED_FILES3.has(base3.toLowerCase());
22621
+ return RESERVED_FILES.has(base3.toLowerCase());
22705
22622
  }
22706
22623
  function classify3(ext) {
22707
22624
  if (SCRIPT_EXTENSIONS.has(ext))
@@ -22711,7 +22628,7 @@ function classify3(ext) {
22711
22628
  return "file";
22712
22629
  }
22713
22630
  function recognize6(c, file) {
22714
- const posix = toPosix7(file.relPath);
22631
+ const posix = toPosix(file.relPath);
22715
22632
  const base3 = posix.split("/").pop() ?? posix;
22716
22633
  if (isReserved2(base3))
22717
22634
  return null;
@@ -22731,7 +22648,7 @@ function recognize6(c, file) {
22731
22648
  adapterId: "generic-files",
22732
22649
  type,
22733
22650
  name,
22734
- content: body.length > MAX_CONTENT_CHARS5 ? body.slice(0, MAX_CONTENT_CHARS5) : body
22651
+ content: body
22735
22652
  };
22736
22653
  if (type !== "script")
22737
22654
  doc.ownsPresentation = true;
@@ -22751,7 +22668,7 @@ async function validate6(c, changes, ctx) {
22751
22668
  const raw = change.after ?? await ctx.readFile(change.path);
22752
22669
  if (typeof raw !== "string")
22753
22670
  continue;
22754
- diagnostics.push(...await runBaseValidateChecks(toPosix7(change.path), parseFrontmatter(raw), c.root, ctx));
22671
+ diagnostics.push(...await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx));
22755
22672
  }
22756
22673
  return diagnostics;
22757
22674
  }
@@ -22762,7 +22679,7 @@ var genericFilesAdapter = {
22762
22679
  recognize: recognize6,
22763
22680
  validate: validate6,
22764
22681
  readCandidates(c, conceptId) {
22765
- const posix = toPosix7(conceptId);
22682
+ const posix = toPosix(conceptId);
22766
22683
  const extension = path21.extname(posix).toLowerCase();
22767
22684
  const documentCandidates = [...DOCUMENT_EXTENSIONS].map((candidateExtension) => ({
22768
22685
  path: path21.join(c.root, `${posix}${candidateExtension}`),
@@ -22771,7 +22688,7 @@ var genericFilesAdapter = {
22771
22688
  return DOCUMENT_EXTENSIONS.has(extension) ? documentCandidates : [{ path: path21.join(c.root, posix), conceptId: posix }, ...documentCandidates];
22772
22689
  },
22773
22690
  placeNew(c, conceptId) {
22774
- const posix = toPosix7(conceptId);
22691
+ const posix = toPosix(conceptId);
22775
22692
  const hasExt = path21.extname(posix) !== "";
22776
22693
  return path21.join(c.root, hasExt ? posix : `${posix}.md`);
22777
22694
  },
@@ -22789,12 +22706,8 @@ var DEFAULT_PAGE_KIND = "note";
22789
22706
  var RESERVED_ROOT_FILES = new Set(["schema.md", "index.md", "log.md"]);
22790
22707
  var RAW_SUBDIR = "raw";
22791
22708
  var PAGES_SUBDIR = "pages";
22792
- var MAX_CONTENT_CHARS6 = 1e5;
22793
- function toPosix8(p) {
22794
- return p.replace(/\\/g, "/");
22795
- }
22796
22709
  function conceptIdOf2(relPath) {
22797
- return toPosix8(relPath).replace(/\.md$/i, "");
22710
+ return toPosix(relPath).replace(/\.md$/i, "");
22798
22711
  }
22799
22712
  function parseWikiFrontmatter(raw) {
22800
22713
  const out = { xrefs: [], sources: [] };
@@ -22826,13 +22739,13 @@ function parseWikiFrontmatter(raw) {
22826
22739
  return out;
22827
22740
  }
22828
22741
  function isReservedRootFile(relPath) {
22829
- const posix = toPosix8(relPath);
22742
+ const posix = toPosix(relPath);
22830
22743
  if (posix.includes("/"))
22831
22744
  return false;
22832
22745
  return RESERVED_ROOT_FILES.has(posix.toLowerCase());
22833
22746
  }
22834
22747
  function firstSegment(relPath) {
22835
- const posix = toPosix8(relPath);
22748
+ const posix = toPosix(relPath);
22836
22749
  const slash = posix.indexOf("/");
22837
22750
  return slash < 0 ? posix : posix.slice(0, slash);
22838
22751
  }
@@ -22844,7 +22757,7 @@ function resolveXref(xref, bundleId) {
22844
22757
  return target.length > 0 ? target : null;
22845
22758
  }
22846
22759
  function resolveBodyLinks(body, fileRelPath) {
22847
- const dir = path22.posix.dirname(toPosix8(fileRelPath));
22760
+ const dir = path22.posix.dirname(toPosix(fileRelPath));
22848
22761
  const linkRe = /\[[^\]]*\]\(([^)]+)\)/g;
22849
22762
  const out = [];
22850
22763
  const seen = new Set;
@@ -22921,7 +22834,7 @@ function resolveSources(fm) {
22921
22834
  function recognize7(c, file) {
22922
22835
  if (file.ext !== ".md")
22923
22836
  return null;
22924
- const relPath = toPosix8(file.relPath);
22837
+ const relPath = toPosix(file.relPath);
22925
22838
  if (isReservedRootFile(relPath))
22926
22839
  return null;
22927
22840
  const head = firstSegment(relPath);
@@ -22945,7 +22858,7 @@ function recognize7(c, file) {
22945
22858
  ownsPresentation: true,
22946
22859
  type: isRaw ? WIKI_SOURCE_TYPE : fm.pageKind ?? DEFAULT_PAGE_KIND,
22947
22860
  name: lastSegment,
22948
- content: body.length > MAX_CONTENT_CHARS6 ? body.slice(0, MAX_CONTENT_CHARS6) : body
22861
+ content: body
22949
22862
  };
22950
22863
  if (fm.description !== undefined)
22951
22864
  doc.description = fm.description;
@@ -22971,7 +22884,7 @@ async function validate7(c, changes, ctx) {
22971
22884
  const raw = change.after ?? await ctx.readFile(change.path);
22972
22885
  if (typeof raw !== "string")
22973
22886
  continue;
22974
- const relPath = toPosix8(change.path);
22887
+ const relPath = toPosix(change.path);
22975
22888
  if (isReservedRootFile(relPath))
22976
22889
  continue;
22977
22890
  const head = firstSegment(relPath);
@@ -23054,7 +22967,7 @@ var llmWikiAdapter = {
23054
22967
  recognize: recognize7,
23055
22968
  validate: validate7,
23056
22969
  readCandidates(c, conceptId) {
23057
- const canonical = toPosix8(conceptId).replace(/\.md$/i, "");
22970
+ const canonical = toPosix(conceptId).replace(/\.md$/i, "");
23058
22971
  return [{ path: path22.join(c.root, `${canonical}.md`), conceptId: canonical }];
23059
22972
  },
23060
22973
  placeNew(c, conceptId) {
@@ -23090,11 +23003,8 @@ var CONSUMED_FRONTMATTER_KEYS = [
23090
23003
  "stale_after",
23091
23004
  "okf_version"
23092
23005
  ];
23093
- function isPlainObject3(value) {
23094
- return value !== null && typeof value === "object" && !Array.isArray(value);
23095
- }
23096
23006
  function parseActorMapping(value) {
23097
- if (!isPlainObject3(value))
23007
+ if (!isRecord(value))
23098
23008
  return;
23099
23009
  const by = nonEmptyString(value.by);
23100
23010
  if (by === undefined)
@@ -23119,7 +23029,7 @@ function parseOkfSources(value) {
23119
23029
  return;
23120
23030
  const out = [];
23121
23031
  for (const item of value) {
23122
- if (!isPlainObject3(item))
23032
+ if (!isRecord(item))
23123
23033
  continue;
23124
23034
  const resource = nonEmptyString(item.resource);
23125
23035
  if (resource === undefined)
@@ -23147,16 +23057,11 @@ function parseOkfSources(value) {
23147
23057
  function parseLifecycleStatus(value) {
23148
23058
  return value === "draft" || value === "stable" || value === "deprecated" ? value : undefined;
23149
23059
  }
23150
- var RESERVED_FILES4 = new Set(["index.md", "log.md"]);
23151
- var MAX_CONTENT_CHARS7 = 1e5;
23152
- function toPosix9(p) {
23153
- return p.replace(/\\/g, "/");
23154
- }
23155
23060
  function isReservedFileName2(name) {
23156
- return RESERVED_FILES4.has(name.toLowerCase());
23061
+ return RESERVED_FILES.has(name.toLowerCase());
23157
23062
  }
23158
23063
  function resolveOkfLinks(body, fileRelPath) {
23159
- const dir = path23.posix.dirname(toPosix9(fileRelPath));
23064
+ const dir = path23.posix.dirname(toPosix(fileRelPath));
23160
23065
  const definitions = new Map;
23161
23066
  for (const match of body.matchAll(/^\s*\[([^\]]+)\]:\s*(\S+)/gm)) {
23162
23067
  definitions.set(match[1].trim().toLowerCase(), match[2]);
@@ -23214,7 +23119,7 @@ function recognize8(c, file) {
23214
23119
  return null;
23215
23120
  if (isReservedFileName2(file.fileName))
23216
23121
  return null;
23217
- const conceptId = toPosix9(file.relPath).replace(/\.md$/i, "");
23122
+ const conceptId = toPosix(file.relPath).replace(/\.md$/i, "");
23218
23123
  const raw = file.content();
23219
23124
  const parsed = parseFrontmatter(raw);
23220
23125
  const data = parsed.data;
@@ -23225,7 +23130,7 @@ function recognize8(c, file) {
23225
23130
  const description = nonEmptyString(data.description);
23226
23131
  const tags = readTags(data.tags);
23227
23132
  const links = resolveOkfLinks(body, file.relPath);
23228
- const generatedMapping = isPlainObject3(data.generated) ? data.generated : undefined;
23133
+ const generatedMapping = isRecord(data.generated) ? data.generated : undefined;
23229
23134
  const generatedAt = generatedMapping ? nonEmptyString(generatedMapping.at) : undefined;
23230
23135
  const generatedBy = generatedMapping ? nonEmptyString(generatedMapping.by) : undefined;
23231
23136
  const legacyTimestamp = nonEmptyString(data.timestamp);
@@ -23252,7 +23157,7 @@ function recognize8(c, file) {
23252
23157
  ownsPresentation: true,
23253
23158
  type,
23254
23159
  name,
23255
- content: body.length > MAX_CONTENT_CHARS7 ? body.slice(0, MAX_CONTENT_CHARS7) : body
23160
+ content: body
23256
23161
  };
23257
23162
  if (description !== undefined)
23258
23163
  doc.description = description;
@@ -23283,7 +23188,7 @@ async function validate8(c, changes, ctx) {
23283
23188
  const raw = change.after ?? await ctx.readFile(change.path);
23284
23189
  if (typeof raw !== "string")
23285
23190
  continue;
23286
- const relPath = toPosix9(change.path);
23191
+ const relPath = toPosix(change.path);
23287
23192
  const fileName = relPath.split("/").pop() ?? relPath;
23288
23193
  const reserved = isReservedFileName2(fileName);
23289
23194
  const parsed = parseFrontmatter(raw);
@@ -23407,10 +23312,6 @@ var COMPONENT_ID6 = "main";
23407
23312
  var PAGES_PREFIX = "stash/knowledge/";
23408
23313
  var MANIFEST_FILE = "manifest.json";
23409
23314
  var WEBSITE_TAG = "website";
23410
- var MAX_CONTENT_CHARS8 = 1e5;
23411
- function toPosix10(p) {
23412
- return p.replace(/\\/g, "/");
23413
- }
23414
23315
  function parseSnapshotFrontmatter(raw) {
23415
23316
  const out = { tags: [] };
23416
23317
  const block = parseFrontmatterBlock(raw);
@@ -23433,14 +23334,14 @@ function parseSnapshotFrontmatter(raw) {
23433
23334
  return out;
23434
23335
  }
23435
23336
  function isSnapshotPage(relPath) {
23436
- const posix = toPosix10(relPath);
23337
+ const posix = toPosix(relPath);
23437
23338
  return posix.startsWith(PAGES_PREFIX) && posix.toLowerCase().endsWith(".md");
23438
23339
  }
23439
23340
  function isReTypeGated(fm) {
23440
23341
  return fm.sourceUrl !== undefined || fm.tags.includes(WEBSITE_TAG);
23441
23342
  }
23442
23343
  function conceptIdOf3(relPath) {
23443
- return toPosix10(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, "");
23344
+ return toPosix(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, "");
23444
23345
  }
23445
23346
  function recognize9(c, file) {
23446
23347
  if (file.ext !== ".md" || !isSnapshotPage(file.relPath))
@@ -23463,7 +23364,7 @@ function recognize9(c, file) {
23463
23364
  ownsPresentation: true,
23464
23365
  type: "website",
23465
23366
  name,
23466
- content: body.length > MAX_CONTENT_CHARS8 ? body.slice(0, MAX_CONTENT_CHARS8) : body
23367
+ content: body
23467
23368
  };
23468
23369
  if (fm.description !== undefined)
23469
23370
  doc.description = fm.description;
@@ -23481,7 +23382,7 @@ async function validate9(c, changes, ctx) {
23481
23382
  continue;
23482
23383
  if (!isSnapshotPage(change.path))
23483
23384
  continue;
23484
- const base3 = await runBaseValidateChecks(toPosix10(change.path), parseFrontmatter(raw), c.root, ctx);
23385
+ const base3 = await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx);
23485
23386
  diagnostics.push(...base3.filter((d) => d.issue !== "missing-updated"));
23486
23387
  }
23487
23388
  return diagnostics;
@@ -23493,7 +23394,7 @@ var websiteSnapshotAdapter = {
23493
23394
  recognize: recognize9,
23494
23395
  validate: validate9,
23495
23396
  readCandidates(c, conceptId) {
23496
- const canonical = toPosix10(conceptId).replace(/\.md$/i, "");
23397
+ const canonical = toPosix(conceptId).replace(/\.md$/i, "");
23497
23398
  return [{ path: path25.join(c.root, PAGES_PREFIX, `${canonical}.md`), conceptId: canonical }];
23498
23399
  },
23499
23400
  looksLikeRoot(root) {
@@ -27990,9 +27891,7 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
27990
27891
  "default",
27991
27892
  "quick",
27992
27893
  "thorough",
27993
- "memory-focus",
27994
27894
  "graph-refresh",
27995
- "frequent",
27996
27895
  "consolidate",
27997
27896
  "catchup",
27998
27897
  "reflect-distill",
@@ -28885,7 +28784,7 @@ function upgradeConfigVersion(raw, sourcePath) {
28885
28784
 
28886
28785
  // src/core/config/deep-merge.ts
28887
28786
  var UNSAFE_KEYS3 = new Set(["__proto__", "constructor", "prototype"]);
28888
- function isPlainObject4(value) {
28787
+ function isPlainObject(value) {
28889
28788
  if (value === null || typeof value !== "object" || Array.isArray(value))
28890
28789
  return false;
28891
28790
  const prototype = Object.getPrototypeOf(value);
@@ -28894,7 +28793,7 @@ function isPlainObject4(value) {
28894
28793
  function copyConfigValue(value) {
28895
28794
  if (Array.isArray(value))
28896
28795
  return value.map(copyConfigValue);
28897
- if (!isPlainObject4(value))
28796
+ if (!isPlainObject(value))
28898
28797
  return value;
28899
28798
  const copy = {};
28900
28799
  for (const key of Object.keys(value)) {
@@ -28913,7 +28812,7 @@ function deepMergeConfig(base3, override) {
28913
28812
  if (next === undefined)
28914
28813
  continue;
28915
28814
  const current = result[key];
28916
- result[key] = isPlainObject4(current) && isPlainObject4(next) ? deepMergeConfig(current, next) : copyConfigValue(next);
28815
+ result[key] = isPlainObject(current) && isPlainObject(next) ? deepMergeConfig(current, next) : copyConfigValue(next);
28917
28816
  }
28918
28817
  return result;
28919
28818
  }
@@ -28974,8 +28873,8 @@ function loadUserConfig() {
28974
28873
  }
28975
28874
  function parseAndValidateConfigText(text, sourcePath) {
28976
28875
  const parsedRaw = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
28977
- const { config: raw, lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28978
28876
  const where = sourcePath ? ` at ${sourcePath}` : "";
28877
+ const { lifted, conflicts } = liftLegacyEngineExtraParams(parsedRaw);
28979
28878
  if (conflicts.length > 0) {
28980
28879
  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(`
28981
28880
  `);
@@ -28985,11 +28884,13 @@ ${lines}
28985
28884
  Each extraParams key above has a first-class equivalent and akm will not guess which value you meant — remove the extraParams entry once the field carries the value you want.`, "INVALID_CONFIG_FILE");
28986
28885
  }
28987
28886
  if (lifted.length > 0) {
28988
- 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):
28887
+ throw new ConfigError(`Config${where} uses deprecated extraParams keys with first-class equivalents:
28989
28888
  - ${lifted.join(`
28990
- - `)}`);
28889
+ - `)}
28890
+
28891
+ Run \`akm migrate apply\` to rewrite the config file, or move the values onto the first-class fields yourself.`, "INVALID_CONFIG_FILE");
28991
28892
  }
28992
- const parsed = AkmConfigSchema.safeParse(raw);
28893
+ const parsed = AkmConfigSchema.safeParse(parsedRaw);
28993
28894
  if (!parsed.success) {
28994
28895
  const lines = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join(`
28995
28896
  `);
@@ -29284,6 +29185,9 @@ function createProviderRegistry() {
29284
29185
  resolve(type) {
29285
29186
  return map.get(type) ?? null;
29286
29187
  },
29188
+ unregister(type) {
29189
+ map.delete(type);
29190
+ },
29287
29191
  list() {
29288
29192
  return [...map.keys()];
29289
29193
  }