akm-cli 0.9.25-alpha.1 → 0.9.25-alpha.3

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 (68) hide show
  1. package/CHANGELOG.md +243 -280
  2. package/dist/assets/prompts/reflect-feedback-framing.md +1 -1
  3. package/dist/assets/prompts/reflect-llm-framed-contract.md +2 -9
  4. package/dist/assets/prompts/reflect-llm-schema-contract.md +1 -3
  5. package/dist/assets/prompts/reflect-output-repair.md +1 -1
  6. package/dist/cli.js +1 -1
  7. package/dist/commands/improve/consolidate/pair-pass.js +1 -0
  8. package/dist/commands/improve/consolidate.js +7 -2
  9. package/dist/commands/improve/execution.js +2 -3
  10. package/dist/commands/improve/extract-cli.js +3 -2
  11. package/dist/commands/improve/extract.js +2 -1
  12. package/dist/commands/improve/improve-cli.js +33 -1
  13. package/dist/commands/improve/loop-stages.js +3 -0
  14. package/dist/commands/improve/reflect-noise.js +125 -0
  15. package/dist/commands/improve/reflect.js +150 -333
  16. package/dist/commands/improve/retrieval-gate.js +7 -2
  17. package/dist/commands/improve/session-asset.js +6 -0
  18. package/dist/commands/improve/stage.js +31 -39
  19. package/dist/commands/proposal/drain.js +4 -7
  20. package/dist/commands/proposal/propose.js +2 -11
  21. package/dist/commands/proposal/validators/proposal-quality-validators.js +11 -5
  22. package/dist/commands/proposal/validators/proposal-validators.js +4 -5
  23. package/dist/commands/read/search-cli.js +0 -38
  24. package/dist/core/asset/asset-serialize.js +1 -1
  25. package/dist/core/config/schema/engines.js +15 -33
  26. package/dist/core/config/schema/improve-processes.js +16 -0
  27. package/dist/core/content-safety.js +0 -24
  28. package/dist/core/redaction.js +4 -0
  29. package/dist/core/spawn-env.js +25 -0
  30. package/dist/core/structured.js +1 -1
  31. package/dist/execution/source.js +8 -12
  32. package/dist/integrations/agent/config.js +1 -3
  33. package/dist/integrations/agent/engine-resolution.js +0 -3
  34. package/dist/integrations/agent/execution.js +14 -13
  35. package/dist/integrations/agent/index.js +1 -1
  36. package/dist/integrations/agent/model-map.js +15 -16
  37. package/dist/integrations/agent/profiles.js +2 -2
  38. package/dist/integrations/agent/prompts.js +51 -127
  39. package/dist/integrations/agent/request-lowering.js +9 -7
  40. package/dist/integrations/agent/runner-dispatch.js +25 -31
  41. package/dist/integrations/harnesses/aider/agent-builder.js +1 -2
  42. package/dist/integrations/harnesses/amazonq/agent-builder.js +1 -2
  43. package/dist/integrations/harnesses/claude/agent-builder.js +4 -16
  44. package/dist/integrations/harnesses/codex/agent-builder.js +1 -2
  45. package/dist/integrations/harnesses/codex/index.js +6 -11
  46. package/dist/integrations/harnesses/codex/session-log.js +211 -0
  47. package/dist/integrations/harnesses/ids.js +10 -16
  48. package/dist/integrations/harnesses/opencode/agent-builder.js +14 -24
  49. package/dist/integrations/harnesses/opencode/model-config.js +15 -62
  50. package/dist/integrations/harnesses/opencode/model-work-agent.js +71 -36
  51. package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -6
  52. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +32 -90
  53. package/dist/integrations/harnesses/openhands/agent-builder.js +1 -2
  54. package/dist/integrations/harnesses/pi/agent-builder.js +1 -2
  55. package/dist/integrations/harnesses/types.js +3 -3
  56. package/dist/llm/feature-gate.js +2 -5
  57. package/dist/llm/index-passes.js +2 -2
  58. package/dist/llm/structured-call.js +5 -5
  59. package/dist/output/shapes/passthrough.js +1 -0
  60. package/dist/scripts/akm-migrate-node.js +381 -239
  61. package/dist/scripts/akm-migrate.js +381 -239
  62. package/dist/workflows/exec/unit-dispatch.js +4 -13
  63. package/docs/reference/cli.md +29 -16
  64. package/docs/reference/configuration.md +79 -85
  65. package/docs/reference/data-and-telemetry.md +2 -3
  66. package/docs/reference/workflow-schema.md +6 -9
  67. package/package.json +1 -1
  68. package/schemas/akm-config.json +108 -36
@@ -29036,6 +29036,7 @@ var PASSTHROUGH_COMMANDS = [
29036
29036
  "extract",
29037
29037
  "health",
29038
29038
  "improve",
29039
+ "improve-judge",
29039
29040
  "improve-report",
29040
29041
  "import",
29041
29042
  "index",
@@ -35454,25 +35455,21 @@ var coerce = {
35454
35455
  };
35455
35456
  var NEVER = INVALID;
35456
35457
  // src/integrations/harnesses/ids.ts
35457
- var OPENCODE_INFERENCE = ["temperature", "maxTokens", "contextLength", "enableThinking", "reasoningEffort"];
35458
35458
  var HARNESS_ID_TABLE = [
35459
- { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true, inference: OPENCODE_INFERENCE },
35460
- { id: "claude", agentDispatch: true, enforcesModelWorkTools: true, inference: ["reasoningEffort"] },
35461
- { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true, inference: OPENCODE_INFERENCE },
35462
- { id: "codex", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35463
- { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35464
- { id: "pi", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35465
- { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35466
- { id: "aider", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35467
- { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
35468
- { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false, inference: [] }
35459
+ { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true },
35460
+ { id: "claude", agentDispatch: true, enforcesModelWorkTools: true },
35461
+ { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true },
35462
+ { id: "codex", agentDispatch: true, enforcesModelWorkTools: false },
35463
+ { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false },
35464
+ { id: "pi", agentDispatch: true, enforcesModelWorkTools: false },
35465
+ { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false },
35466
+ { id: "aider", agentDispatch: true, enforcesModelWorkTools: false },
35467
+ { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false },
35468
+ { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false }
35469
35469
  ];
35470
35470
  var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
35471
35471
  var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
35472
35472
  var HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
35473
- function harnessInferenceKeys(platform) {
35474
- return HARNESS_ID_TABLE.find((h) => h.id === platform)?.inference ?? [];
35475
- }
35476
35473
 
35477
35474
  // src/core/extra-params.ts
35478
35475
  var EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
@@ -35777,13 +35774,6 @@ var LlmEngineSchema = exports_external.object({
35777
35774
  });
35778
35775
  }
35779
35776
  });
35780
- var AGENT_INFERENCE_KEYS = [
35781
- "temperature",
35782
- "maxTokens",
35783
- "contextLength",
35784
- "enableThinking",
35785
- "reasoningEffort"
35786
- ];
35787
35777
  var AgentEngineSchema = exports_external.object({
35788
35778
  kind: exports_external.literal("agent"),
35789
35779
  platform: AgentPlatformSchema.refine((platform) => HARNESS_AGENT_DISPATCH_IDS.has(platform), {
@@ -35794,27 +35784,25 @@ var AgentEngineSchema = exports_external.object({
35794
35784
  workspace: nonEmptyString.optional(),
35795
35785
  model: nonEmptyString.optional(),
35796
35786
  timeoutMs: timeoutMsField,
35797
- llmEngine: engineName.optional(),
35798
- temperature: exports_external.number().finite().optional(),
35799
- maxTokens: positiveInt.optional(),
35800
- contextLength: positiveInt.optional(),
35801
- enableThinking: exports_external.boolean().optional(),
35802
- reasoningEffort: nonEmptyString.optional()
35787
+ llmEngine: engineName.optional()
35803
35788
  }).passthrough().superRefine((value, ctx) => {
35804
- for (const key of ["provider", "endpoint", "apiKey", "apiKeyFile", "concurrency", "extraParams", "modelAliases"]) {
35789
+ for (const key of [
35790
+ "provider",
35791
+ "endpoint",
35792
+ "apiKey",
35793
+ "apiKeyFile",
35794
+ "temperature",
35795
+ "maxTokens",
35796
+ "concurrency",
35797
+ "extraParams",
35798
+ "contextLength",
35799
+ "enableThinking",
35800
+ "reasoningEffort",
35801
+ "modelAliases"
35802
+ ]) {
35805
35803
  if (key in value)
35806
35804
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an agent engine` });
35807
35805
  }
35808
- const translated = harnessInferenceKeys(value.platform);
35809
- for (const key of AGENT_INFERENCE_KEYS) {
35810
- if (key in value && !translated.includes(key)) {
35811
- ctx.addIssue({
35812
- code: exports_external.ZodIssueCode.custom,
35813
- path: [key],
35814
- message: `${key} is not valid on a ${value.platform} engine: ${translated.length > 0 ? `the platform translates only ${translated.join(", ")}` : "the platform translates no inference fields"}`
35815
- });
35816
- }
35817
- }
35818
35806
  if (value.platform !== "opencode-sdk" && value.llmEngine !== undefined) {
35819
35807
  ctx.addIssue({
35820
35808
  code: exports_external.ZodIssueCode.custom,
@@ -35878,6 +35866,11 @@ var clsField = exports_external.object({
35878
35866
  }).passthrough().optional();
35879
35867
  var fidelityCheckField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35880
35868
  var lowValueFilterField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35869
+ var defectFilterField = exports_external.object({
35870
+ placeholders: exports_external.array(nonEmptyString).optional(),
35871
+ metaCommentary: exports_external.array(nonEmptyString).optional(),
35872
+ frontmatterKeys: exports_external.array(nonEmptyString).optional()
35873
+ }).passthrough().optional();
35881
35874
  var extractTriageGateField = exports_external.object({
35882
35875
  enabled: exports_external.boolean().optional(),
35883
35876
  minScore: exports_external.number().min(0).optional()
@@ -35900,7 +35893,8 @@ var REFLECT_PROCESS_FIELDS = {
35900
35893
  excludeRefPrefixes: excludeRefPrefixesField,
35901
35894
  limit: processLimitField,
35902
35895
  qualityGate: qualityGateField,
35903
- lowValueFilter: lowValueFilterField
35896
+ lowValueFilter: lowValueFilterField,
35897
+ defectFilter: defectFilterField
35904
35898
  };
35905
35899
  var DISTILL_PROCESS_FIELDS = {
35906
35900
  allowedTypes: allowedTypesField,
@@ -37622,6 +37616,10 @@ var ENV_PASSTHROUGH_REDACTION_POLICY = {
37622
37616
  OPENCODE_CONFIG: "path",
37623
37617
  CLAUDE_CONFIG: "path",
37624
37618
  CODEX_CONFIG: "path",
37619
+ XDG_CONFIG_HOME: "path",
37620
+ XDG_DATA_HOME: "path",
37621
+ XDG_CACHE_HOME: "path",
37622
+ XDG_STATE_HOME: "path",
37625
37623
  AWS_PROFILE: "identifier",
37626
37624
  AWS_REGION: "identifier",
37627
37625
  LLM_MODEL: "identifier",
@@ -39674,10 +39672,7 @@ import { createHash as createHash3 } from "node:crypto";
39674
39672
 
39675
39673
  // src/execution/source.ts
39676
39674
  var EXECUTION_SOURCE_SCHEMA_VERSION = 1;
39677
- var MODEL_WORK_TOOLS = Object.freeze(["read", "edit", "akm search", "akm show"]);
39678
- function isModelWorkTools(tools) {
39679
- return Array.isArray(tools) && tools.length === MODEL_WORK_TOOLS.length && tools.every((tool, index) => tool === MODEL_WORK_TOOLS[index]);
39680
- }
39675
+ var MODEL_WORK_POLICY_ID = "model-work";
39681
39676
  function requireRecord(value, path18) {
39682
39677
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
39683
39678
  throw new TypeError(`${path18} must be an object`);
@@ -51045,8 +51040,9 @@ function extensionFields(request) {
51045
51040
  ];
51046
51041
  }
51047
51042
  function createAgentRequestLowerer(options) {
51048
- return (profile, request) => {
51049
- const supportedInference = new Set(typeof options.inference === "function" ? options.inference(profile, request) : options.inference ?? []);
51043
+ const supportedInference = new Set(options.inference ?? []);
51044
+ return (_profile, request) => {
51045
+ const modelWork = request.authorization.policy?.id === MODEL_WORK_POLICY_ID;
51050
51046
  const notices = [];
51051
51047
  const skip = (field) => {
51052
51048
  notices.push(untranslated(options.adapter, field));
@@ -51087,18 +51083,18 @@ function createAgentRequestLowerer(options) {
51087
51083
  if (Object.hasOwn(request, "inference")) {
51088
51084
  dispatch.inference = request.inference ?? null;
51089
51085
  for (const key of Object.keys(request.inference ?? {}).sort()) {
51090
- if (!supportedInference.has(key))
51086
+ if (!(modelWork && supportedInference.has(key)))
51091
51087
  skip(`inference.${key}`);
51092
51088
  }
51093
51089
  }
51094
- if (isModelWorkTools(request.tools)) {
51095
- if (!options.modelWorkTools) {
51090
+ if (modelWork) {
51091
+ if (!HARNESS_MODEL_WORK_IDS.has(options.adapter)) {
51096
51092
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the model-work tool policy.`, "INVALID_CONFIG_FILE");
51097
51093
  }
51098
51094
  if (dispatch.agent) {
51099
51095
  throw new ConfigError(`The ${options.adapter} transport cannot run native agent ${JSON.stringify(dispatch.agent)} under the model-work tool policy.`, "INVALID_CONFIG_FILE");
51100
51096
  }
51101
- dispatch.tools = request.tools;
51097
+ dispatch.modelWork = true;
51102
51098
  } else if (request.tools !== undefined) {
51103
51099
  if (hasToolSelection(request.tools) && !translatesTools(options.tools, request.tools)) {
51104
51100
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the resolved tool policy.`, "INVALID_CONFIG_FILE");
@@ -51294,12 +51290,10 @@ var claudeBuilder = {
51294
51290
  adapter: "claude",
51295
51291
  personaChannel: "native",
51296
51292
  nativeAgentSelector: true,
51297
- tools: "all",
51298
- modelWorkTools: true,
51299
- inference: ["reasoningEffort"]
51293
+ tools: "all"
51300
51294
  }),
51301
51295
  build(profile, req) {
51302
- const modelWork = isModelWorkTools(req.tools);
51296
+ const modelWork = req.modelWork === true;
51303
51297
  const args = modelWork ? [...MODEL_WORK_CLAUDE_FLAGS] : [...profile.args];
51304
51298
  if (req.agent) {
51305
51299
  args.push("--agent", req.agent);
@@ -51315,10 +51309,7 @@ var claudeBuilder = {
51315
51309
  if (model)
51316
51310
  args.push("--model", model);
51317
51311
  }
51318
- const effort = req.inference?.reasoningEffort;
51319
- if (typeof effort === "string" && effort.length > 0)
51320
- args.push("--effort", effort);
51321
- if (req.tools && !modelWork) {
51312
+ if (req.tools) {
51322
51313
  args.push("--allowedTools", normalizeTools(req.tools));
51323
51314
  }
51324
51315
  if (req.schema) {
@@ -51776,6 +51767,170 @@ var codexResultExtractor = (result) => {
51776
51767
  return sessionId === undefined ? { text } : { text, sessionId };
51777
51768
  };
51778
51769
 
51770
+ // src/integrations/harnesses/codex/session-log.ts
51771
+ import fs36 from "node:fs";
51772
+ import os5 from "node:os";
51773
+ import path43 from "node:path";
51774
+ function codexSessionsDir() {
51775
+ return path43.join(process.env.CODEX_HOME || path43.join(os5.homedir(), ".codex"), "sessions");
51776
+ }
51777
+ var META_PEEK_BYTES = 128 * 1024;
51778
+ var INJECTED_CONTEXT_RE = /^\s*(?:# AGENTS\.md instructions[\s\S]*<\/INSTRUCTIONS>|<(environment_context|user_instructions|recommended_plugins|skill|turn_aborted)>[\s\S]*<\/\1>)\s*$/i;
51779
+ function parseSessionMeta(entry) {
51780
+ const e = entry;
51781
+ if (e?.type !== "session_meta" || !e.payload)
51782
+ return;
51783
+ const { timestamp, cwd, source } = e.payload;
51784
+ const startedAt = typeof timestamp === "string" ? Date.parse(timestamp) : Number.NaN;
51785
+ return {
51786
+ ...Number.isNaN(startedAt) ? {} : { startedAt },
51787
+ ...typeof cwd === "string" ? { cwd } : {},
51788
+ isAgent: typeof source === "object" && source !== null && (("subagent" in source) || ("internal" in source))
51789
+ };
51790
+ }
51791
+ function blockText(blocks, keep = () => true) {
51792
+ if (typeof blocks === "string")
51793
+ return blocks;
51794
+ if (!Array.isArray(blocks))
51795
+ return "";
51796
+ const parts = [];
51797
+ for (const block of blocks) {
51798
+ const text = block?.text;
51799
+ if (typeof text === "string" && keep(text))
51800
+ parts.push(text);
51801
+ }
51802
+ return parts.join(`
51803
+ `);
51804
+ }
51805
+ function toolInputText(input) {
51806
+ let args = input;
51807
+ if (typeof input === "string") {
51808
+ try {
51809
+ args = JSON.parse(input);
51810
+ } catch {
51811
+ return input;
51812
+ }
51813
+ }
51814
+ const fields = args && typeof args === "object" ? args : {};
51815
+ const cmd = fields.cmd ?? fields.command;
51816
+ if (typeof cmd === "string")
51817
+ return cmd;
51818
+ if (Array.isArray(cmd))
51819
+ return cmd.join(" ");
51820
+ return typeof input === "string" ? input : JSON.stringify(input) ?? "";
51821
+ }
51822
+ function parseCodexRecord(entry, sessionId, filePath, fallbackTsMs) {
51823
+ const e = entry;
51824
+ const item = e?.type === "response_item" ? e.payload : undefined;
51825
+ if (!item)
51826
+ return;
51827
+ const toolName2 = typeof item.name === "string" ? item.name : "tool";
51828
+ let role = "assistant";
51829
+ let text;
51830
+ switch (item.type) {
51831
+ case "message":
51832
+ if (item.role !== "user" && item.role !== "assistant")
51833
+ return;
51834
+ role = item.role;
51835
+ text = blockText(item.content, item.role === "user" ? (t) => !INJECTED_CONTEXT_RE.test(t) : undefined);
51836
+ break;
51837
+ case "function_call":
51838
+ text = `[tool:${toolName2}] ${toolInputText(item.arguments)}`;
51839
+ break;
51840
+ case "custom_tool_call":
51841
+ text = `[tool:${toolName2}] ${typeof item.input === "string" ? item.input : ""}`;
51842
+ break;
51843
+ case "local_shell_call":
51844
+ text = `[tool:shell] ${toolInputText(item.action)}`;
51845
+ break;
51846
+ case "function_call_output":
51847
+ case "custom_tool_call_output": {
51848
+ role = "tool";
51849
+ const output = blockText(item.output);
51850
+ text = output ? `[tool_result] ${output}` : "";
51851
+ break;
51852
+ }
51853
+ default:
51854
+ return;
51855
+ }
51856
+ if (!text.trim())
51857
+ return;
51858
+ const ts = typeof e?.timestamp === "string" ? Date.parse(e.timestamp) || fallbackTsMs : fallbackTsMs;
51859
+ return { harness: "codex", text, ts, sessionId, role, filePath };
51860
+ }
51861
+
51862
+ class CodexProvider extends AbstractSessionLogProvider {
51863
+ name = "codex";
51864
+ availabilityRoot() {
51865
+ return codexSessionsDir();
51866
+ }
51867
+ listSessions(input = {}) {
51868
+ return this.listSessionsFromFiles({
51869
+ sinceMs: input.sinceMs ?? 0,
51870
+ enumerate: () => this.walkFiles(input.location ?? codexSessionsDir(), (name) => /^rollout-.+\.jsonl$/.test(name)),
51871
+ summarize: (rolloutPath, stat) => {
51872
+ const meta = this.#peekMeta(rolloutPath);
51873
+ if (meta?.isAgent)
51874
+ return;
51875
+ return this.sessionRef({
51876
+ sessionId: path43.basename(rolloutPath, ".jsonl").slice(-36),
51877
+ filePath: rolloutPath,
51878
+ startedAt: meta?.startedAt ?? stat.ctimeMs,
51879
+ endedAt: stat.mtimeMs,
51880
+ projectHint: meta?.cwd
51881
+ });
51882
+ }
51883
+ });
51884
+ }
51885
+ readSession(ref) {
51886
+ const stat = fs36.statSync(ref.filePath);
51887
+ const events = [];
51888
+ const inlineRefs = [];
51889
+ let meta;
51890
+ for (const line of fs36.readFileSync(ref.filePath, "utf8").split(`
51891
+ `).filter(Boolean)) {
51892
+ let entry;
51893
+ try {
51894
+ entry = JSON.parse(line);
51895
+ } catch {
51896
+ continue;
51897
+ }
51898
+ meta ??= parseSessionMeta(entry);
51899
+ const parsed = parseCodexRecord(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
51900
+ if (!parsed)
51901
+ continue;
51902
+ events.push(parsed);
51903
+ inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
51904
+ }
51905
+ return {
51906
+ ref: this.sessionRef({
51907
+ sessionId: ref.sessionId,
51908
+ filePath: ref.filePath,
51909
+ startedAt: meta?.startedAt ?? events[0]?.ts ?? stat.ctimeMs,
51910
+ endedAt: events[events.length - 1]?.ts ?? stat.mtimeMs,
51911
+ projectHint: meta?.cwd
51912
+ }),
51913
+ events,
51914
+ inlineRefs
51915
+ };
51916
+ }
51917
+ #peekMeta(filePath) {
51918
+ try {
51919
+ const fd = fs36.openSync(filePath, "r");
51920
+ try {
51921
+ const head = Buffer.alloc(META_PEEK_BYTES);
51922
+ const firstLine = head.toString("utf8", 0, fs36.readSync(fd, head, 0, head.length, 0)).split(`
51923
+ `, 1)[0] ?? "";
51924
+ return parseSessionMeta(JSON.parse(firstLine));
51925
+ } finally {
51926
+ fs36.closeSync(fd);
51927
+ }
51928
+ } catch {
51929
+ return;
51930
+ }
51931
+ }
51932
+ }
51933
+
51779
51934
  // src/integrations/harnesses/codex/index.ts
51780
51935
  class CodexHarness extends BaseHarness {
51781
51936
  id = "codex";
@@ -51783,7 +51938,9 @@ class CodexHarness extends BaseHarness {
51783
51938
  agentBuilder = codexBuilder;
51784
51939
  resultExtractor = codexResultExtractor;
51785
51940
  presenceEnv = ["CODEX_SANDBOX"];
51941
+ sessionLogProvider = () => new CodexProvider;
51786
51942
  capabilities = caps({
51943
+ sessionLogs: true,
51787
51944
  agentDispatch: true,
51788
51945
  detection: true
51789
51946
  });
@@ -52080,101 +52237,87 @@ class GeminiHarness extends BaseHarness {
52080
52237
  }
52081
52238
 
52082
52239
  // src/integrations/harnesses/opencode/model-config.ts
52240
+ var MODEL_WORK_AGENT_INFERENCE = ["temperature", "reasoningEffort", "enableThinking"];
52083
52241
  var isPositiveInteger = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
52084
- function carriedInference(inference) {
52085
- const carried = {};
52242
+ function opencodeInferenceConfig(inference, modelWork) {
52086
52243
  const { temperature, reasoningEffort, enableThinking, maxTokens, contextLength } = inference ?? {};
52244
+ const options = {};
52087
52245
  if (typeof temperature === "number" && Number.isFinite(temperature))
52088
- carried.temperature = temperature;
52246
+ options.temperature = temperature;
52089
52247
  if (typeof reasoningEffort === "string" && reasoningEffort.length > 0)
52090
- carried.reasoningEffort = reasoningEffort;
52091
- if (typeof enableThinking === "boolean")
52092
- carried.enableThinking = enableThinking;
52093
- const limit = isPositiveInteger(maxTokens) && isPositiveInteger(contextLength);
52094
- if (limit)
52095
- carried.limit = { context: contextLength, output: maxTokens };
52096
- const keys = [
52097
- ["temperature", carried.temperature !== undefined, temperature],
52098
- ["reasoningEffort", carried.reasoningEffort !== undefined, reasoningEffort],
52099
- ["enableThinking", carried.enableThinking !== undefined, enableThinking],
52100
- ["maxTokens", limit, maxTokens],
52101
- ["contextLength", limit, contextLength]
52102
- ].filter(([, isCarried, value]) => isCarried || value === null).map(([key]) => key);
52103
- return { carried, keys };
52104
- }
52105
- function splitOpencodeModel(model) {
52106
- const slash = model.indexOf("/");
52107
- if (slash <= 0 || slash === model.length - 1)
52108
- return;
52109
- return { providerID: model.slice(0, slash), modelID: model.slice(slash + 1) };
52110
- }
52111
- function opencodeCarriedKeys(attachable, inference, modelWork) {
52112
- const { keys } = carriedInference(inference);
52113
- if (attachable)
52114
- return keys;
52115
- return modelWork ? keys.filter((key) => key !== "maxTokens" && key !== "contextLength") : [];
52116
- }
52117
- function opencodeInferenceConfig(inference, modelWork) {
52118
- const { carried } = carriedInference(inference);
52119
- const options = {};
52120
- if (carried.temperature !== undefined)
52121
- options.temperature = carried.temperature;
52122
- if (carried.reasoningEffort !== undefined)
52123
- options.reasoningEffort = carried.reasoningEffort;
52124
- if (carried.enableThinking !== undefined) {
52125
- options.chat_template_kwargs = { enable_thinking: carried.enableThinking };
52126
- options.enable_thinking = carried.enableThinking;
52248
+ options.reasoningEffort = reasoningEffort;
52249
+ if (typeof enableThinking === "boolean") {
52250
+ options.chat_template_kwargs = { enable_thinking: enableThinking };
52251
+ options.enable_thinking = enableThinking;
52127
52252
  }
52128
52253
  const hasOptions = Object.keys(options).length > 0;
52129
52254
  return {
52130
52255
  entry: {
52131
52256
  ...hasOptions && !modelWork ? { options } : {},
52132
- ...carried.limit ? { limit: { ...carried.limit } } : {}
52257
+ ...isPositiveInteger(maxTokens) && isPositiveInteger(contextLength) ? { limit: { context: contextLength, output: maxTokens } } : {}
52133
52258
  },
52134
52259
  ...hasOptions && modelWork ? { agentOptions: options } : {}
52135
52260
  };
52136
52261
  }
52137
- function opencodeModelConfig(model, entry) {
52138
- const target = model === undefined ? undefined : splitOpencodeModel(model);
52139
- if (!target || Object.keys(entry).length === 0)
52140
- return;
52141
- return { provider: { [target.providerID]: { models: { [target.modelID]: entry } } } };
52142
- }
52143
52262
 
52144
52263
  // src/integrations/harnesses/opencode/model-work-agent.ts
52264
+ import path44 from "node:path";
52145
52265
  var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52146
- var MODEL_WORK_STEPS = 8;
52147
52266
  var MODEL_WORK_PROMPT = "You do one bounded task for akm. Use tools only to check what the task needs, never repeat a tool call, and reply with exactly what the task asks for.";
52148
- var MODEL_WORK_PERMISSION = {
52149
- "*": "deny",
52150
- read: "allow",
52151
- edit: "allow",
52152
- external_directory: "deny",
52153
- bash: "deny",
52154
- doom_loop: "deny",
52155
- glob: "deny",
52156
- grep: "deny",
52157
- list: "deny",
52158
- lsp: "deny",
52159
- question: "deny",
52160
- skill: "deny",
52161
- task: "deny",
52162
- todowrite: "deny",
52163
- webfetch: "deny",
52164
- websearch: "deny"
52165
- };
52267
+ function modelWorkPermission(stash) {
52268
+ return {
52269
+ "*": "deny",
52270
+ read: "allow",
52271
+ grep: "allow",
52272
+ glob: "allow",
52273
+ edit: { "*": "allow", ...stash ? { [`${stash.slice(1)}/*`]: "deny" } : {} },
52274
+ external_directory: {
52275
+ ...stash ? { [`${stash}/*`]: "allow" } : {},
52276
+ "~/.local/share/opencode/tool-output/*": "deny"
52277
+ },
52278
+ akm_search: "allow",
52279
+ akm_show: "allow",
52280
+ akm_feedback: "deny",
52281
+ akm_remember: "deny",
52282
+ akm_curate: "deny",
52283
+ bash: "deny",
52284
+ doom_loop: "deny",
52285
+ list: "deny",
52286
+ lsp: "deny",
52287
+ question: "deny",
52288
+ skill: "deny",
52289
+ task: "deny",
52290
+ todowrite: "deny",
52291
+ webfetch: "deny",
52292
+ websearch: "deny"
52293
+ };
52294
+ }
52295
+ function modelWorkPluginEnv() {
52296
+ return {
52297
+ AKM_AUTO_CURATE: "0",
52298
+ AKM_AUTO_LEARNING: "0",
52299
+ AKM_AUTO_SKILL_PROPOSALS: "0",
52300
+ AKM_WRITE_GATE: "off",
52301
+ XDG_STATE_HOME: path44.join(getStateDir(), "opencode-model-work"),
52302
+ ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52303
+ };
52304
+ }
52166
52305
  function modelWorkOpencodeConfig(options) {
52306
+ let stash;
52307
+ try {
52308
+ stash = resolveStashDir();
52309
+ } catch {}
52310
+ const permission = modelWorkPermission(stash);
52167
52311
  return {
52168
- permission: { ...MODEL_WORK_PERMISSION },
52312
+ permission: { ...permission },
52169
52313
  compaction: { auto: false },
52170
52314
  agent: {
52171
52315
  [MODEL_WORK_OPENCODE_AGENT]: {
52172
52316
  mode: "primary",
52173
52317
  description: "akm unattended model work: read and edit inside its working directory only.",
52174
52318
  prompt: MODEL_WORK_PROMPT,
52175
- steps: MODEL_WORK_STEPS,
52176
52319
  ...options ? { options } : {},
52177
- permission: { ...MODEL_WORK_PERMISSION }
52320
+ permission: { ...permission }
52178
52321
  }
52179
52322
  }
52180
52323
  };
@@ -52189,18 +52332,12 @@ var opencodeBuilder = {
52189
52332
  personaChannel: "prompt",
52190
52333
  nativeAgentSelector: true,
52191
52334
  tools: "none",
52192
- modelWorkTools: true,
52193
- inference: (profile, request) => {
52194
- const model = request.model?.resolved ?? modelFromArgs(profile.args);
52195
- return opencodeCarriedKeys(model !== undefined && splitOpencodeModel(model) !== undefined, request.inference, isModelWorkTools(request.tools));
52196
- }
52335
+ inference: MODEL_WORK_AGENT_INFERENCE
52197
52336
  }),
52198
52337
  build(profile, req) {
52199
- const model = req.model ?? modelFromArgs(profile.args);
52200
- const modelWork = isModelWorkTools(req.tools);
52201
- const { entry, agentOptions } = opencodeInferenceConfig(req.inference, modelWork);
52202
- const modelConfig = opencodeModelConfig(model, entry);
52203
- if (modelWork) {
52338
+ if (req.modelWork) {
52339
+ const model = req.model ?? modelFromArgs(profile.args);
52340
+ const { agentOptions } = opencodeInferenceConfig(req.inference, true);
52204
52341
  return {
52205
52342
  argv: [
52206
52343
  profile.bin,
@@ -52211,7 +52348,10 @@ var opencodeBuilder = {
52211
52348
  "--",
52212
52349
  req.prompt
52213
52350
  ],
52214
- env: { OPENCODE_CONFIG_CONTENT: JSON.stringify({ ...modelWorkOpencodeConfig(agentOptions), ...modelConfig }) }
52351
+ env: {
52352
+ ...modelWorkPluginEnv(),
52353
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(modelWorkOpencodeConfig(agentOptions))
52354
+ }
52215
52355
  };
52216
52356
  }
52217
52357
  const args = req.model ? [] : [...profile.args];
@@ -52236,23 +52376,20 @@ var opencodeBuilder = {
52236
52376
  }
52237
52377
  args.push("--");
52238
52378
  args.push(req.prompt);
52239
- return {
52240
- argv: [profile.bin, ...args],
52241
- ...modelConfig ? { env: { OPENCODE_CONFIG_CONTENT: JSON.stringify(modelConfig) } } : {}
52242
- };
52379
+ return { argv: [profile.bin, ...args] };
52243
52380
  }
52244
52381
  };
52245
52382
 
52246
52383
  // src/integrations/harnesses/opencode/session-log.ts
52247
- import fs37 from "node:fs";
52248
- import os6 from "node:os";
52249
- import path44 from "node:path";
52384
+ import fs38 from "node:fs";
52385
+ import os7 from "node:os";
52386
+ import path46 from "node:path";
52250
52387
 
52251
52388
  // src/storage/sqlite-read-snapshot.ts
52252
52389
  import { spawnSync as spawnSync5 } from "node:child_process";
52253
- import fs36 from "node:fs";
52254
- import os5 from "node:os";
52255
- import path43 from "node:path";
52390
+ import fs37 from "node:fs";
52391
+ import os6 from "node:os";
52392
+ import path45 from "node:path";
52256
52393
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52257
52394
  var SNAPSHOT_BACKOFF_MS = 25;
52258
52395
 
@@ -52264,7 +52401,7 @@ class SqliteReadSnapshotUnavailableError extends Error {
52264
52401
  }
52265
52402
  function pathExists(filePath) {
52266
52403
  try {
52267
- fs36.lstatSync(filePath);
52404
+ fs37.lstatSync(filePath);
52268
52405
  return true;
52269
52406
  } catch (error2) {
52270
52407
  if (error2.code === "ENOENT")
@@ -52274,7 +52411,7 @@ function pathExists(filePath) {
52274
52411
  }
52275
52412
  function fileFingerprint(filePath) {
52276
52413
  try {
52277
- const stat = fs36.statSync(filePath, { bigint: true });
52414
+ const stat = fs37.statSync(filePath, { bigint: true });
52278
52415
  return { size: stat.size, mtimeNs: stat.mtimeNs, ctimeNs: stat.ctimeNs };
52279
52416
  } catch (error2) {
52280
52417
  if (error2.code === "ENOENT")
@@ -52296,7 +52433,7 @@ function fingerprintsEqual(left, right) {
52296
52433
  }
52297
52434
  function copyFileOutsideThisProcess(source, destination) {
52298
52435
  if (process.platform === "win32") {
52299
- fs36.copyFileSync(source, destination);
52436
+ fs37.copyFileSync(source, destination);
52300
52437
  return;
52301
52438
  }
52302
52439
  const result = spawnSync5("cp", ["--", source, destination], {
@@ -52317,8 +52454,8 @@ function copyFileOutsideThisProcess(source, destination) {
52317
52454
  function openSqliteReadSnapshot(dbPath) {
52318
52455
  if (!pathExists(dbPath))
52319
52456
  return;
52320
- const snapshotDir = fs36.mkdtempSync(path43.join(os5.tmpdir(), "akm-sqlite-read-"));
52321
- const snapshotPath = path43.join(snapshotDir, "snapshot.db");
52457
+ const snapshotDir = fs37.mkdtempSync(path45.join(os6.tmpdir(), "akm-sqlite-read-"));
52458
+ const snapshotPath = path45.join(snapshotDir, "snapshot.db");
52322
52459
  let db;
52323
52460
  try {
52324
52461
  let copied = false;
@@ -52333,7 +52470,7 @@ function openSqliteReadSnapshot(dbPath) {
52333
52470
  if (before.wal)
52334
52471
  copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
52335
52472
  else
52336
- fs36.rmSync(`${snapshotPath}-wal`, { force: true });
52473
+ fs37.rmSync(`${snapshotPath}-wal`, { force: true });
52337
52474
  const after = databaseFingerprint(dbPath);
52338
52475
  if (fingerprintsEqual(before, after) && !pathExists(`${dbPath}-journal`)) {
52339
52476
  copied = true;
@@ -52361,14 +52498,14 @@ function openSqliteReadSnapshot(dbPath) {
52361
52498
  closeSnapshot();
52362
52499
  } catch {}
52363
52500
  try {
52364
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52501
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52365
52502
  } catch {}
52366
52503
  return;
52367
52504
  }
52368
52505
  try {
52369
52506
  closeSnapshot();
52370
52507
  } finally {
52371
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52508
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52372
52509
  }
52373
52510
  };
52374
52511
  const cleanupOnExit = () => cleanup(true);
@@ -52379,7 +52516,7 @@ function openSqliteReadSnapshot(dbPath) {
52379
52516
  try {
52380
52517
  db?.close();
52381
52518
  } finally {
52382
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52519
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52383
52520
  }
52384
52521
  throw error2;
52385
52522
  }
@@ -52388,9 +52525,9 @@ function openSqliteReadSnapshot(dbPath) {
52388
52525
  // src/integrations/harnesses/opencode/session-log.ts
52389
52526
  function getOpenCodeBaseDir() {
52390
52527
  if (process.platform === "darwin") {
52391
- return path44.join(os6.homedir(), "Library", "Application Support", "opencode");
52528
+ return path46.join(os7.homedir(), "Library", "Application Support", "opencode");
52392
52529
  }
52393
- return path44.join(os6.homedir(), ".local", "share", "opencode");
52530
+ return path46.join(os7.homedir(), ".local", "share", "opencode");
52394
52531
  }
52395
52532
  var OPENCODE_DB_FILENAME = "opencode.db";
52396
52533
 
@@ -52401,13 +52538,13 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52401
52538
  return this.#dbPath(this.#baseDir);
52402
52539
  }
52403
52540
  #dbPath(base) {
52404
- return path44.join(base, OPENCODE_DB_FILENAME);
52541
+ return path46.join(base, OPENCODE_DB_FILENAME);
52405
52542
  }
52406
52543
  listSessions(input = {}) {
52407
52544
  const base = input.location ?? this.#baseDir;
52408
52545
  const sinceMs = input.sinceMs ?? 0;
52409
52546
  const dbPath = this.#dbPath(base);
52410
- if (!fs37.existsSync(dbPath))
52547
+ if (!fs38.existsSync(dbPath))
52411
52548
  return [];
52412
52549
  return this.#listSessionsFromDb(dbPath, sinceMs, input.isolatedSnapshot ?? false);
52413
52550
  }
@@ -52539,8 +52676,7 @@ class OpencodeSdkHarness extends BaseHarness {
52539
52676
  personaChannel: "native",
52540
52677
  nativeAgentSelector: true,
52541
52678
  tools: "sdk",
52542
- modelWorkTools: true,
52543
- inference: (_profile, request) => opencodeCarriedKeys(Boolean(request.model?.resolved), request.inference, isModelWorkTools(request.tools))
52679
+ inference: MODEL_WORK_AGENT_INFERENCE
52544
52680
  })
52545
52681
  };
52546
52682
  capabilities = caps({
@@ -52817,11 +52953,6 @@ var VALID_HARNESS_IDS2 = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
52817
52953
  var SESSION_LOG_HARNESSES = HARNESS_REGISTRY.filter(isSessionLogHarness);
52818
52954
  var AGENT_DISPATCH_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.agentDispatch);
52819
52955
 
52820
- // src/integrations/agent/model-map.ts
52821
- var ENGINE_KEY_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
52822
- var RESERVED_MAP_KEYS = new Set(["__proto__", "constructor", "prototype", "tostring"]);
52823
- var PROFILE_FIELD_KEYS = new Set(["model", "inference", "engine"]);
52824
-
52825
52956
  // src/core/spawn-env.ts
52826
52957
  var COMMON_SPAWN_ENV_PASSTHROUGH = [
52827
52958
  "HOME",
@@ -52833,6 +52964,12 @@ var COMMON_SPAWN_ENV_PASSTHROUGH = [
52833
52964
  "TMPDIR",
52834
52965
  "AKM_EVENT_SOURCE"
52835
52966
  ];
52967
+ var XDG_BASE_DIR_ENV_PASSTHROUGH = [
52968
+ "XDG_CONFIG_HOME",
52969
+ "XDG_DATA_HOME",
52970
+ "XDG_CACHE_HOME",
52971
+ "XDG_STATE_HOME"
52972
+ ];
52836
52973
  var supplementedPaths = new Map;
52837
52974
 
52838
52975
  // src/integrations/agent/profiles.ts
@@ -52843,7 +52980,7 @@ var BUILTINS = {
52843
52980
  bin: "opencode",
52844
52981
  args: ["run"],
52845
52982
  stdio: "interactive",
52846
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
52983
+ envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG", ...XDG_BASE_DIR_ENV_PASSTHROUGH],
52847
52984
  parseOutput: "text"
52848
52985
  },
52849
52986
  claude: {
@@ -52923,6 +53060,11 @@ var FALLBACK_ANNOUNCEMENT = `No engine is configured; falling back to \`${FALLBA
52923
53060
  var NO_ENGINE_MESSAGE_SUFFIX = `has no selected engine, and no usable \`${OPENCODE_SDK_SERVER_BIN}\` binary was found to fall back to.`;
52924
53061
  var NO_ENGINE_REMEDY = "Run `akm setup` to detect an installed agent, or set one explicitly: " + '`akm config set engines.claude \'{"kind":"agent","platform":"claude"}\'` ' + "then `akm config set defaults.engine claude`. " + `Installing the \`${OPENCODE_SDK_SERVER_BIN}\` binary also works ` + "(`npm i -g opencode-ai`) — akm falls back to it automatically.";
52925
53062
 
53063
+ // src/integrations/agent/model-map.ts
53064
+ var ENGINE_KEY_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
53065
+ var RESERVED_MAP_KEYS = new Set(["__proto__", "constructor", "prototype", "tostring"]);
53066
+ var PROFILE_FIELD_KEYS = new Set(["model", "inference", "engine"]);
53067
+
52926
53068
  // src/storage/repositories/improve-ledger-repository.ts
52927
53069
  var LEDGER_REJECTION_WINDOW_DAYS = Object.freeze({
52928
53070
  reflect: 14,
@@ -53311,8 +53453,8 @@ Commands:
53311
53453
  `;
53312
53454
 
53313
53455
  // scripts/akm-migrate/migrate/dead-residue.ts
53314
- import fs38 from "node:fs";
53315
- import path45 from "node:path";
53456
+ import fs39 from "node:fs";
53457
+ import path47 from "node:path";
53316
53458
  var DEAD_RESIDUE_PATHS = [
53317
53459
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53318
53460
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53329,43 +53471,43 @@ function dirSizeBytes(target) {
53329
53471
  let total = 0;
53330
53472
  let entries;
53331
53473
  try {
53332
- entries = fs38.readdirSync(target, { withFileTypes: true });
53474
+ entries = fs39.readdirSync(target, { withFileTypes: true });
53333
53475
  } catch {
53334
53476
  return 0;
53335
53477
  }
53336
53478
  for (const entry of entries) {
53337
- const entryPath = path45.join(target, entry.name);
53479
+ const entryPath = path47.join(target, entry.name);
53338
53480
  if (entry.isDirectory()) {
53339
53481
  total += dirSizeBytes(entryPath);
53340
53482
  } else if (entry.isFile()) {
53341
53483
  try {
53342
- total += fs38.statSync(entryPath).size;
53484
+ total += fs39.statSync(entryPath).size;
53343
53485
  } catch {}
53344
53486
  }
53345
53487
  }
53346
53488
  return total;
53347
53489
  }
53348
53490
  function sizeOf(target) {
53349
- const st = fs38.statSync(target);
53491
+ const st = fs39.statSync(target);
53350
53492
  return st.isDirectory() ? dirSizeBytes(target) : st.size;
53351
53493
  }
53352
53494
  function hostResidue() {
53353
53495
  const data = getDataDir();
53354
53496
  const state = getStateDir();
53355
- const configDir = path45.dirname(getConfigPath());
53497
+ const configDir = path47.dirname(getConfigPath());
53356
53498
  const named = [
53357
- { absolutePath: path45.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53358
- { absolutePath: path45.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53359
- { absolutePath: path45.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53360
- { absolutePath: path45.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53361
- { absolutePath: path45.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53362
- { absolutePath: path45.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53363
- { absolutePath: path45.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53499
+ { absolutePath: path47.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53500
+ { absolutePath: path47.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53501
+ { absolutePath: path47.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53502
+ { absolutePath: path47.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53503
+ { absolutePath: path47.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53504
+ { absolutePath: path47.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53505
+ { absolutePath: path47.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53364
53506
  ];
53365
53507
  const found = [];
53366
53508
  const claimed = new Set;
53367
53509
  for (const entry of named) {
53368
- if (claimed.has(entry.absolutePath) || !fs38.existsSync(entry.absolutePath))
53510
+ if (claimed.has(entry.absolutePath) || !fs39.existsSync(entry.absolutePath))
53369
53511
  continue;
53370
53512
  try {
53371
53513
  found.push({ ...entry, relativePath: entry.absolutePath, sizeBytes: sizeOf(entry.absolutePath) });
@@ -53389,13 +53531,13 @@ function hostResidue() {
53389
53531
  function findSidecars(root, depth, skip) {
53390
53532
  let entries;
53391
53533
  try {
53392
- entries = fs38.readdirSync(root, { withFileTypes: true });
53534
+ entries = fs39.readdirSync(root, { withFileTypes: true });
53393
53535
  } catch {
53394
53536
  return [];
53395
53537
  }
53396
53538
  const found = [];
53397
53539
  for (const entry of entries) {
53398
- const entryPath = path45.join(root, entry.name);
53540
+ const entryPath = path47.join(root, entry.name);
53399
53541
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53400
53542
  found.push(entryPath);
53401
53543
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53408,10 +53550,10 @@ function findDeadResidueEntries(stashDir) {
53408
53550
  const host = hostResidue();
53409
53551
  if (stashDir === undefined)
53410
53552
  return host;
53411
- const akmDir = path45.join(stashDir, ".akm");
53553
+ const akmDir = path47.join(stashDir, ".akm");
53412
53554
  let names;
53413
53555
  try {
53414
- names = fs38.readdirSync(akmDir);
53556
+ names = fs39.readdirSync(akmDir);
53415
53557
  } catch {
53416
53558
  return [];
53417
53559
  }
@@ -53421,14 +53563,14 @@ function findDeadResidueEntries(stashDir) {
53421
53563
  for (const name of matches) {
53422
53564
  if (!names.includes(name))
53423
53565
  continue;
53424
- const absolutePath = path45.join(akmDir, name);
53566
+ const absolutePath = path47.join(akmDir, name);
53425
53567
  let sizeBytes;
53426
53568
  try {
53427
53569
  sizeBytes = sizeOf(absolutePath);
53428
53570
  } catch {
53429
53571
  continue;
53430
53572
  }
53431
- found.push({ relativePath: path45.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53573
+ found.push({ relativePath: path47.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53432
53574
  }
53433
53575
  }
53434
53576
  return found;
@@ -53437,7 +53579,7 @@ function removeDeadResidue(stashDir) {
53437
53579
  const entries = findDeadResidueEntries(stashDir);
53438
53580
  return entries.map((entry) => {
53439
53581
  try {
53440
- fs38.rmSync(entry.absolutePath, { recursive: true, force: true });
53582
+ fs39.rmSync(entry.absolutePath, { recursive: true, force: true });
53441
53583
  return { relativePath: entry.relativePath, sizeBytes: entry.sizeBytes, removed: true };
53442
53584
  } catch (error2) {
53443
53585
  return {
@@ -53452,18 +53594,18 @@ function removeDeadResidue(stashDir) {
53452
53594
 
53453
53595
  // scripts/akm-migrate/task-migrate.ts
53454
53596
  import { randomUUID as randomUUID3 } from "node:crypto";
53455
- import fs40 from "node:fs";
53456
- import os7 from "node:os";
53457
- import path48 from "node:path";
53597
+ import fs41 from "node:fs";
53598
+ import os8 from "node:os";
53599
+ import path50 from "node:path";
53458
53600
 
53459
53601
  // scripts/akm-migrate/migrate/task-files.ts
53460
53602
  import crypto4 from "node:crypto";
53461
- import fs39 from "node:fs";
53462
- import path47 from "node:path";
53603
+ import fs40 from "node:fs";
53604
+ import path49 from "node:path";
53463
53605
 
53464
53606
  // src/tasks/source/task-to-v4.ts
53465
53607
  import crypto3 from "node:crypto";
53466
- import path46 from "node:path";
53608
+ import path48 from "node:path";
53467
53609
 
53468
53610
  // src/tasks/task-id.ts
53469
53611
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54272,7 +54414,7 @@ function addSharedNonPromptOverrides(data, akm) {
54272
54414
  }
54273
54415
  function promptSourceKind(raw) {
54274
54416
  const trimmed = raw.trim();
54275
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path46.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54417
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path48.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54276
54418
  return "file";
54277
54419
  }
54278
54420
  try {
@@ -54376,7 +54518,7 @@ function planV2DataToV4(input, data) {
54376
54518
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54377
54519
  }
54378
54520
  try {
54379
- validateTaskId(path46.basename(input.filePath, ".yml"));
54521
+ validateTaskId(path48.basename(input.filePath, ".yml"));
54380
54522
  } catch (cause) {
54381
54523
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54382
54524
  }
@@ -54521,7 +54663,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54521
54663
  for (let index = 1;index < files.length; index += 1) {
54522
54664
  const previous = files[index - 1];
54523
54665
  const current = files[index];
54524
- if (previous && current && path46.resolve(previous.filePath) === path46.resolve(current.filePath)) {
54666
+ if (previous && current && path48.resolve(previous.filePath) === path48.resolve(current.filePath)) {
54525
54667
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54526
54668
  }
54527
54669
  }
@@ -54533,18 +54675,18 @@ function migrationError(detail) {
54533
54675
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54534
54676
  }
54535
54677
  function contained2(root, candidate) {
54536
- const relative = path47.relative(root, candidate);
54537
- return relative === "" || !relative.startsWith("..") && !path47.isAbsolute(relative);
54678
+ const relative = path49.relative(root, candidate);
54679
+ return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
54538
54680
  }
54539
54681
  function realDirectory(filePath) {
54540
- const stat = fs39.lstatSync(filePath);
54682
+ const stat = fs40.lstatSync(filePath);
54541
54683
  if (stat.isSymbolicLink() || !stat.isDirectory())
54542
54684
  throw migrationError(`${filePath} must be a real directory.`);
54543
- return fs39.realpathSync(filePath);
54685
+ return fs40.realpathSync(filePath);
54544
54686
  }
54545
54687
  function isWritable(filePath) {
54546
54688
  try {
54547
- fs39.accessSync(filePath, fs39.constants.W_OK);
54689
+ fs40.accessSync(filePath, fs40.constants.W_OK);
54548
54690
  return true;
54549
54691
  } catch {
54550
54692
  return false;
@@ -54557,12 +54699,12 @@ function walkTasks(root, tasksDir, out) {
54557
54699
  throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
54558
54700
  }
54559
54701
  const visit2 = (directory) => {
54560
- const physicalDirectory = fs39.realpathSync(directory);
54702
+ const physicalDirectory = fs40.realpathSync(directory);
54561
54703
  if (!contained2(physicalRoot, physicalDirectory)) {
54562
54704
  throw migrationError(`${directory} resolves outside bundle ${root.bundleId}.`);
54563
54705
  }
54564
- for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54565
- const candidate = path47.join(directory, entry.name);
54706
+ for (const entry of fs40.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54707
+ const candidate = path49.join(directory, entry.name);
54566
54708
  if (entry.isSymbolicLink())
54567
54709
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54568
54710
  if (entry.isDirectory()) {
@@ -54571,11 +54713,11 @@ function walkTasks(root, tasksDir, out) {
54571
54713
  }
54572
54714
  if (!entry.isFile() || !entry.name.endsWith(".yml"))
54573
54715
  continue;
54574
- const stat = fs39.lstatSync(candidate);
54716
+ const stat = fs40.lstatSync(candidate);
54575
54717
  const mode = stat.mode & 511;
54576
54718
  out.push({
54577
54719
  filePath: candidate,
54578
- bytes: fs39.readFileSync(candidate),
54720
+ bytes: fs40.readFileSync(candidate),
54579
54721
  mode,
54580
54722
  writable: root.writable,
54581
54723
  onDiskWritable: isWritable(candidate) && isWritable(directory) && (mode & 146) !== 0,
@@ -54588,9 +54730,9 @@ function walkTasks(root, tasksDir, out) {
54588
54730
  function inspectTaskFiles(roots) {
54589
54731
  const files = [];
54590
54732
  for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54591
- const tasksDir = root.layout === "akm-task" ? root.root : path47.join(root.root, "tasks");
54733
+ const tasksDir = root.layout === "akm-task" ? root.root : path49.join(root.root, "tasks");
54592
54734
  try {
54593
- const stat = fs39.lstatSync(tasksDir);
54735
+ const stat = fs40.lstatSync(tasksDir);
54594
54736
  if (stat.isSymbolicLink())
54595
54737
  throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
54596
54738
  if (!stat.isDirectory())
@@ -54608,18 +54750,18 @@ function planTaskFilesMigration(inputs) {
54608
54750
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54609
54751
  }
54610
54752
  function taskFileBackupPath(backupRoot, filePath) {
54611
- const digest = crypto4.createHash("sha256").update(path47.resolve(filePath)).digest("hex").slice(0, 16);
54612
- return path47.join(backupRoot, "files", `${digest}-${path47.basename(filePath)}`);
54753
+ const digest = crypto4.createHash("sha256").update(path49.resolve(filePath)).digest("hex").slice(0, 16);
54754
+ return path49.join(backupRoot, "files", `${digest}-${path49.basename(filePath)}`);
54613
54755
  }
54614
54756
  function fsyncDirectory(directory) {
54615
54757
  if (process.platform === "win32")
54616
54758
  return;
54617
54759
  try {
54618
- const fd = fs39.openSync(directory, "r");
54760
+ const fd = fs40.openSync(directory, "r");
54619
54761
  try {
54620
- fs39.fsyncSync(fd);
54762
+ fs40.fsyncSync(fd);
54621
54763
  } finally {
54622
- fs39.closeSync(fd);
54764
+ fs40.closeSync(fd);
54623
54765
  }
54624
54766
  } catch (cause) {
54625
54767
  const code = cause.code;
@@ -54628,25 +54770,25 @@ function fsyncDirectory(directory) {
54628
54770
  }
54629
54771
  }
54630
54772
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54631
- fs39.mkdirSync(path47.dirname(filePath), { recursive: true });
54632
- const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54773
+ fs40.mkdirSync(path49.dirname(filePath), { recursive: true });
54774
+ const fd = fs40.openSync(filePath, exclusive ? "wx" : "w", mode);
54633
54775
  try {
54634
- fs39.writeFileSync(fd, bytes);
54635
- fs39.fsyncSync(fd);
54776
+ fs40.writeFileSync(fd, bytes);
54777
+ fs40.fsyncSync(fd);
54636
54778
  } finally {
54637
- fs39.closeSync(fd);
54779
+ fs40.closeSync(fd);
54638
54780
  }
54639
- fs39.chmodSync(filePath, mode);
54640
- fsyncDirectory(path47.dirname(filePath));
54781
+ fs40.chmodSync(filePath, mode);
54782
+ fsyncDirectory(path49.dirname(filePath));
54641
54783
  }
54642
54784
  function replaceAtomically(filePath, bytes, mode) {
54643
- const temporary = path47.join(path47.dirname(filePath), `.${path47.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54785
+ const temporary = path49.join(path49.dirname(filePath), `.${path49.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54644
54786
  try {
54645
54787
  writeDurable(temporary, bytes, mode, true);
54646
- fs39.renameSync(temporary, filePath);
54647
- fsyncDirectory(path47.dirname(filePath));
54788
+ fs40.renameSync(temporary, filePath);
54789
+ fsyncDirectory(path49.dirname(filePath));
54648
54790
  } finally {
54649
- fs39.rmSync(temporary, { force: true });
54791
+ fs40.rmSync(temporary, { force: true });
54650
54792
  }
54651
54793
  }
54652
54794
  function applyTaskFilesPlan(plan, options) {
@@ -54669,7 +54811,7 @@ function applyTaskFilesPlan(plan, options) {
54669
54811
  }
54670
54812
  } catch (cause) {
54671
54813
  for (const change of [...replaced].reverse()) {
54672
- replaceAtomically(change.filePath, fs39.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54814
+ replaceAtomically(change.filePath, fs40.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54673
54815
  }
54674
54816
  throw cause;
54675
54817
  }
@@ -54679,14 +54821,14 @@ function applyTaskFilesPlan(plan, options) {
54679
54821
  // scripts/akm-migrate/task-migrate.ts
54680
54822
  function expandTilde(value) {
54681
54823
  if (value === "~")
54682
- return os7.homedir();
54824
+ return os8.homedir();
54683
54825
  if (value.startsWith("~/") || value.startsWith("~\\"))
54684
- return path48.join(os7.homedir(), value.slice(2));
54826
+ return path50.join(os8.homedir(), value.slice(2));
54685
54827
  return value;
54686
54828
  }
54687
54829
  function existingDirectory(target) {
54688
54830
  try {
54689
- return fs40.statSync(target).isDirectory();
54831
+ return fs41.statSync(target).isDirectory();
54690
54832
  } catch (cause) {
54691
54833
  if (cause.code === "ENOENT")
54692
54834
  return false;
@@ -54707,14 +54849,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54707
54849
  const source = sources.get(bundleId);
54708
54850
  if (!source)
54709
54851
  continue;
54710
- const configuredRoot = source.type === "filesystem" && source.path ? path48.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54852
+ const configuredRoot = source.type === "filesystem" && source.path ? path50.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54711
54853
  if (!configuredRoot || !existingDirectory(configuredRoot))
54712
54854
  continue;
54713
- const bundleRoot = path48.resolve(configuredRoot);
54855
+ const bundleRoot = path50.resolve(configuredRoot);
54714
54856
  const component = bundleComponentConfig(bundle);
54715
- const componentRoot = path48.resolve(bundleRoot, component?.root ?? ".");
54716
- const relative = path48.relative(bundleRoot, componentRoot);
54717
- if (relative === ".." || relative.startsWith(`..${path48.sep}`) || path48.isAbsolute(relative)) {
54857
+ const componentRoot = path50.resolve(bundleRoot, component?.root ?? ".");
54858
+ const relative = path50.relative(bundleRoot, componentRoot);
54859
+ if (relative === ".." || relative.startsWith(`..${path50.sep}`) || path50.isAbsolute(relative)) {
54718
54860
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54719
54861
  }
54720
54862
  if (!existingDirectory(componentRoot))
@@ -54731,7 +54873,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54731
54873
  }
54732
54874
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54733
54875
  if (envStash && existingDirectory(envStash)) {
54734
- const stashRoot = path48.resolve(envStash);
54876
+ const stashRoot = path50.resolve(envStash);
54735
54877
  if (!rootsByPath.has(stashRoot)) {
54736
54878
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54737
54879
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54744,7 +54886,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54744
54886
  function taskRoot(bundleId, bundleRoot, componentRoot, configuredAdapter, writable) {
54745
54887
  const adapter = configuredAdapter ?? detectAdapterId(componentRoot, "");
54746
54888
  if (!configuredAdapter && adapter === "") {
54747
- const flatTasks = fs40.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54889
+ const flatTasks = fs41.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54748
54890
  if (flatTasks.length > 0) {
54749
54891
  throw new ConfigError(`Task migration cannot classify top-level task file(s) ${flatTasks.join(", ")} in bundle ${bundleId}; configure adapter "akm-task" or move them under tasks/.`, "INVALID_CONFIG_FILE");
54750
54892
  }
@@ -54800,7 +54942,7 @@ function applyTaskFilesMigration() {
54800
54942
  const before = inspectCurrent();
54801
54943
  if (before.result.taskFiles.changed === 0)
54802
54944
  return before.result;
54803
- const backupPath = path48.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54945
+ const backupPath = path50.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54804
54946
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54805
54947
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54806
54948
  });