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
@@ -28364,6 +28364,7 @@ var PASSTHROUGH_COMMANDS = [
28364
28364
  "extract",
28365
28365
  "health",
28366
28366
  "improve",
28367
+ "improve-judge",
28367
28368
  "improve-report",
28368
28369
  "import",
28369
28370
  "index",
@@ -34782,25 +34783,21 @@ var coerce = {
34782
34783
  };
34783
34784
  var NEVER = INVALID;
34784
34785
  // src/integrations/harnesses/ids.ts
34785
- var OPENCODE_INFERENCE = ["temperature", "maxTokens", "contextLength", "enableThinking", "reasoningEffort"];
34786
34786
  var HARNESS_ID_TABLE = [
34787
- { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true, inference: OPENCODE_INFERENCE },
34788
- { id: "claude", agentDispatch: true, enforcesModelWorkTools: true, inference: ["reasoningEffort"] },
34789
- { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true, inference: OPENCODE_INFERENCE },
34790
- { id: "codex", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34791
- { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34792
- { id: "pi", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34793
- { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34794
- { id: "aider", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34795
- { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false, inference: [] },
34796
- { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false, inference: [] }
34787
+ { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true },
34788
+ { id: "claude", agentDispatch: true, enforcesModelWorkTools: true },
34789
+ { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true },
34790
+ { id: "codex", agentDispatch: true, enforcesModelWorkTools: false },
34791
+ { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false },
34792
+ { id: "pi", agentDispatch: true, enforcesModelWorkTools: false },
34793
+ { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false },
34794
+ { id: "aider", agentDispatch: true, enforcesModelWorkTools: false },
34795
+ { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false },
34796
+ { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false }
34797
34797
  ];
34798
34798
  var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
34799
34799
  var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
34800
34800
  var HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
34801
- function harnessInferenceKeys(platform) {
34802
- return HARNESS_ID_TABLE.find((h) => h.id === platform)?.inference ?? [];
34803
- }
34804
34801
 
34805
34802
  // src/core/extra-params.ts
34806
34803
  var EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
@@ -35105,13 +35102,6 @@ var LlmEngineSchema = exports_external.object({
35105
35102
  });
35106
35103
  }
35107
35104
  });
35108
- var AGENT_INFERENCE_KEYS = [
35109
- "temperature",
35110
- "maxTokens",
35111
- "contextLength",
35112
- "enableThinking",
35113
- "reasoningEffort"
35114
- ];
35115
35105
  var AgentEngineSchema = exports_external.object({
35116
35106
  kind: exports_external.literal("agent"),
35117
35107
  platform: AgentPlatformSchema.refine((platform) => HARNESS_AGENT_DISPATCH_IDS.has(platform), {
@@ -35122,27 +35112,25 @@ var AgentEngineSchema = exports_external.object({
35122
35112
  workspace: nonEmptyString.optional(),
35123
35113
  model: nonEmptyString.optional(),
35124
35114
  timeoutMs: timeoutMsField,
35125
- llmEngine: engineName.optional(),
35126
- temperature: exports_external.number().finite().optional(),
35127
- maxTokens: positiveInt.optional(),
35128
- contextLength: positiveInt.optional(),
35129
- enableThinking: exports_external.boolean().optional(),
35130
- reasoningEffort: nonEmptyString.optional()
35115
+ llmEngine: engineName.optional()
35131
35116
  }).passthrough().superRefine((value, ctx) => {
35132
- for (const key of ["provider", "endpoint", "apiKey", "apiKeyFile", "concurrency", "extraParams", "modelAliases"]) {
35117
+ for (const key of [
35118
+ "provider",
35119
+ "endpoint",
35120
+ "apiKey",
35121
+ "apiKeyFile",
35122
+ "temperature",
35123
+ "maxTokens",
35124
+ "concurrency",
35125
+ "extraParams",
35126
+ "contextLength",
35127
+ "enableThinking",
35128
+ "reasoningEffort",
35129
+ "modelAliases"
35130
+ ]) {
35133
35131
  if (key in value)
35134
35132
  ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an agent engine` });
35135
35133
  }
35136
- const translated = harnessInferenceKeys(value.platform);
35137
- for (const key of AGENT_INFERENCE_KEYS) {
35138
- if (key in value && !translated.includes(key)) {
35139
- ctx.addIssue({
35140
- code: exports_external.ZodIssueCode.custom,
35141
- path: [key],
35142
- 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"}`
35143
- });
35144
- }
35145
- }
35146
35134
  if (value.platform !== "opencode-sdk" && value.llmEngine !== undefined) {
35147
35135
  ctx.addIssue({
35148
35136
  code: exports_external.ZodIssueCode.custom,
@@ -35206,6 +35194,11 @@ var clsField = exports_external.object({
35206
35194
  }).passthrough().optional();
35207
35195
  var fidelityCheckField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35208
35196
  var lowValueFilterField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35197
+ var defectFilterField = exports_external.object({
35198
+ placeholders: exports_external.array(nonEmptyString).optional(),
35199
+ metaCommentary: exports_external.array(nonEmptyString).optional(),
35200
+ frontmatterKeys: exports_external.array(nonEmptyString).optional()
35201
+ }).passthrough().optional();
35209
35202
  var extractTriageGateField = exports_external.object({
35210
35203
  enabled: exports_external.boolean().optional(),
35211
35204
  minScore: exports_external.number().min(0).optional()
@@ -35228,7 +35221,8 @@ var REFLECT_PROCESS_FIELDS = {
35228
35221
  excludeRefPrefixes: excludeRefPrefixesField,
35229
35222
  limit: processLimitField,
35230
35223
  qualityGate: qualityGateField,
35231
- lowValueFilter: lowValueFilterField
35224
+ lowValueFilter: lowValueFilterField,
35225
+ defectFilter: defectFilterField
35232
35226
  };
35233
35227
  var DISTILL_PROCESS_FIELDS = {
35234
35228
  allowedTypes: allowedTypesField,
@@ -36950,6 +36944,10 @@ var ENV_PASSTHROUGH_REDACTION_POLICY = {
36950
36944
  OPENCODE_CONFIG: "path",
36951
36945
  CLAUDE_CONFIG: "path",
36952
36946
  CODEX_CONFIG: "path",
36947
+ XDG_CONFIG_HOME: "path",
36948
+ XDG_DATA_HOME: "path",
36949
+ XDG_CACHE_HOME: "path",
36950
+ XDG_STATE_HOME: "path",
36953
36951
  AWS_PROFILE: "identifier",
36954
36952
  AWS_REGION: "identifier",
36955
36953
  LLM_MODEL: "identifier",
@@ -39002,10 +39000,7 @@ import { createHash as createHash3 } from "crypto";
39002
39000
 
39003
39001
  // src/execution/source.ts
39004
39002
  var EXECUTION_SOURCE_SCHEMA_VERSION = 1;
39005
- var MODEL_WORK_TOOLS = Object.freeze(["read", "edit", "akm search", "akm show"]);
39006
- function isModelWorkTools(tools) {
39007
- return Array.isArray(tools) && tools.length === MODEL_WORK_TOOLS.length && tools.every((tool, index) => tool === MODEL_WORK_TOOLS[index]);
39008
- }
39003
+ var MODEL_WORK_POLICY_ID = "model-work";
39009
39004
  function requireRecord(value, path18) {
39010
39005
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
39011
39006
  throw new TypeError(`${path18} must be an object`);
@@ -51040,8 +51035,9 @@ function extensionFields(request) {
51040
51035
  ];
51041
51036
  }
51042
51037
  function createAgentRequestLowerer(options) {
51043
- return (profile, request) => {
51044
- const supportedInference = new Set(typeof options.inference === "function" ? options.inference(profile, request) : options.inference ?? []);
51038
+ const supportedInference = new Set(options.inference ?? []);
51039
+ return (_profile, request) => {
51040
+ const modelWork = request.authorization.policy?.id === MODEL_WORK_POLICY_ID;
51045
51041
  const notices = [];
51046
51042
  const skip = (field) => {
51047
51043
  notices.push(untranslated(options.adapter, field));
@@ -51082,18 +51078,18 @@ function createAgentRequestLowerer(options) {
51082
51078
  if (Object.hasOwn(request, "inference")) {
51083
51079
  dispatch.inference = request.inference ?? null;
51084
51080
  for (const key of Object.keys(request.inference ?? {}).sort()) {
51085
- if (!supportedInference.has(key))
51081
+ if (!(modelWork && supportedInference.has(key)))
51086
51082
  skip(`inference.${key}`);
51087
51083
  }
51088
51084
  }
51089
- if (isModelWorkTools(request.tools)) {
51090
- if (!options.modelWorkTools) {
51085
+ if (modelWork) {
51086
+ if (!HARNESS_MODEL_WORK_IDS.has(options.adapter)) {
51091
51087
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the model-work tool policy.`, "INVALID_CONFIG_FILE");
51092
51088
  }
51093
51089
  if (dispatch.agent) {
51094
51090
  throw new ConfigError(`The ${options.adapter} transport cannot run native agent ${JSON.stringify(dispatch.agent)} under the model-work tool policy.`, "INVALID_CONFIG_FILE");
51095
51091
  }
51096
- dispatch.tools = request.tools;
51092
+ dispatch.modelWork = true;
51097
51093
  } else if (request.tools !== undefined) {
51098
51094
  if (hasToolSelection(request.tools) && !translatesTools(options.tools, request.tools)) {
51099
51095
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the resolved tool policy.`, "INVALID_CONFIG_FILE");
@@ -51289,12 +51285,10 @@ var claudeBuilder = {
51289
51285
  adapter: "claude",
51290
51286
  personaChannel: "native",
51291
51287
  nativeAgentSelector: true,
51292
- tools: "all",
51293
- modelWorkTools: true,
51294
- inference: ["reasoningEffort"]
51288
+ tools: "all"
51295
51289
  }),
51296
51290
  build(profile, req) {
51297
- const modelWork = isModelWorkTools(req.tools);
51291
+ const modelWork = req.modelWork === true;
51298
51292
  const args = modelWork ? [...MODEL_WORK_CLAUDE_FLAGS] : [...profile.args];
51299
51293
  if (req.agent) {
51300
51294
  args.push("--agent", req.agent);
@@ -51310,10 +51304,7 @@ var claudeBuilder = {
51310
51304
  if (model)
51311
51305
  args.push("--model", model);
51312
51306
  }
51313
- const effort = req.inference?.reasoningEffort;
51314
- if (typeof effort === "string" && effort.length > 0)
51315
- args.push("--effort", effort);
51316
- if (req.tools && !modelWork) {
51307
+ if (req.tools) {
51317
51308
  args.push("--allowedTools", normalizeTools(req.tools));
51318
51309
  }
51319
51310
  if (req.schema) {
@@ -51771,6 +51762,170 @@ var codexResultExtractor = (result) => {
51771
51762
  return sessionId === undefined ? { text } : { text, sessionId };
51772
51763
  };
51773
51764
 
51765
+ // src/integrations/harnesses/codex/session-log.ts
51766
+ import fs36 from "fs";
51767
+ import os5 from "os";
51768
+ import path43 from "path";
51769
+ function codexSessionsDir() {
51770
+ return path43.join(process.env.CODEX_HOME || path43.join(os5.homedir(), ".codex"), "sessions");
51771
+ }
51772
+ var META_PEEK_BYTES = 128 * 1024;
51773
+ 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;
51774
+ function parseSessionMeta(entry) {
51775
+ const e = entry;
51776
+ if (e?.type !== "session_meta" || !e.payload)
51777
+ return;
51778
+ const { timestamp, cwd, source } = e.payload;
51779
+ const startedAt = typeof timestamp === "string" ? Date.parse(timestamp) : Number.NaN;
51780
+ return {
51781
+ ...Number.isNaN(startedAt) ? {} : { startedAt },
51782
+ ...typeof cwd === "string" ? { cwd } : {},
51783
+ isAgent: typeof source === "object" && source !== null && (("subagent" in source) || ("internal" in source))
51784
+ };
51785
+ }
51786
+ function blockText(blocks, keep = () => true) {
51787
+ if (typeof blocks === "string")
51788
+ return blocks;
51789
+ if (!Array.isArray(blocks))
51790
+ return "";
51791
+ const parts = [];
51792
+ for (const block of blocks) {
51793
+ const text = block?.text;
51794
+ if (typeof text === "string" && keep(text))
51795
+ parts.push(text);
51796
+ }
51797
+ return parts.join(`
51798
+ `);
51799
+ }
51800
+ function toolInputText(input) {
51801
+ let args = input;
51802
+ if (typeof input === "string") {
51803
+ try {
51804
+ args = JSON.parse(input);
51805
+ } catch {
51806
+ return input;
51807
+ }
51808
+ }
51809
+ const fields = args && typeof args === "object" ? args : {};
51810
+ const cmd = fields.cmd ?? fields.command;
51811
+ if (typeof cmd === "string")
51812
+ return cmd;
51813
+ if (Array.isArray(cmd))
51814
+ return cmd.join(" ");
51815
+ return typeof input === "string" ? input : JSON.stringify(input) ?? "";
51816
+ }
51817
+ function parseCodexRecord(entry, sessionId, filePath, fallbackTsMs) {
51818
+ const e = entry;
51819
+ const item = e?.type === "response_item" ? e.payload : undefined;
51820
+ if (!item)
51821
+ return;
51822
+ const toolName2 = typeof item.name === "string" ? item.name : "tool";
51823
+ let role = "assistant";
51824
+ let text;
51825
+ switch (item.type) {
51826
+ case "message":
51827
+ if (item.role !== "user" && item.role !== "assistant")
51828
+ return;
51829
+ role = item.role;
51830
+ text = blockText(item.content, item.role === "user" ? (t) => !INJECTED_CONTEXT_RE.test(t) : undefined);
51831
+ break;
51832
+ case "function_call":
51833
+ text = `[tool:${toolName2}] ${toolInputText(item.arguments)}`;
51834
+ break;
51835
+ case "custom_tool_call":
51836
+ text = `[tool:${toolName2}] ${typeof item.input === "string" ? item.input : ""}`;
51837
+ break;
51838
+ case "local_shell_call":
51839
+ text = `[tool:shell] ${toolInputText(item.action)}`;
51840
+ break;
51841
+ case "function_call_output":
51842
+ case "custom_tool_call_output": {
51843
+ role = "tool";
51844
+ const output = blockText(item.output);
51845
+ text = output ? `[tool_result] ${output}` : "";
51846
+ break;
51847
+ }
51848
+ default:
51849
+ return;
51850
+ }
51851
+ if (!text.trim())
51852
+ return;
51853
+ const ts = typeof e?.timestamp === "string" ? Date.parse(e.timestamp) || fallbackTsMs : fallbackTsMs;
51854
+ return { harness: "codex", text, ts, sessionId, role, filePath };
51855
+ }
51856
+
51857
+ class CodexProvider extends AbstractSessionLogProvider {
51858
+ name = "codex";
51859
+ availabilityRoot() {
51860
+ return codexSessionsDir();
51861
+ }
51862
+ listSessions(input = {}) {
51863
+ return this.listSessionsFromFiles({
51864
+ sinceMs: input.sinceMs ?? 0,
51865
+ enumerate: () => this.walkFiles(input.location ?? codexSessionsDir(), (name) => /^rollout-.+\.jsonl$/.test(name)),
51866
+ summarize: (rolloutPath, stat) => {
51867
+ const meta = this.#peekMeta(rolloutPath);
51868
+ if (meta?.isAgent)
51869
+ return;
51870
+ return this.sessionRef({
51871
+ sessionId: path43.basename(rolloutPath, ".jsonl").slice(-36),
51872
+ filePath: rolloutPath,
51873
+ startedAt: meta?.startedAt ?? stat.ctimeMs,
51874
+ endedAt: stat.mtimeMs,
51875
+ projectHint: meta?.cwd
51876
+ });
51877
+ }
51878
+ });
51879
+ }
51880
+ readSession(ref) {
51881
+ const stat = fs36.statSync(ref.filePath);
51882
+ const events = [];
51883
+ const inlineRefs = [];
51884
+ let meta;
51885
+ for (const line of fs36.readFileSync(ref.filePath, "utf8").split(`
51886
+ `).filter(Boolean)) {
51887
+ let entry;
51888
+ try {
51889
+ entry = JSON.parse(line);
51890
+ } catch {
51891
+ continue;
51892
+ }
51893
+ meta ??= parseSessionMeta(entry);
51894
+ const parsed = parseCodexRecord(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
51895
+ if (!parsed)
51896
+ continue;
51897
+ events.push(parsed);
51898
+ inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
51899
+ }
51900
+ return {
51901
+ ref: this.sessionRef({
51902
+ sessionId: ref.sessionId,
51903
+ filePath: ref.filePath,
51904
+ startedAt: meta?.startedAt ?? events[0]?.ts ?? stat.ctimeMs,
51905
+ endedAt: events[events.length - 1]?.ts ?? stat.mtimeMs,
51906
+ projectHint: meta?.cwd
51907
+ }),
51908
+ events,
51909
+ inlineRefs
51910
+ };
51911
+ }
51912
+ #peekMeta(filePath) {
51913
+ try {
51914
+ const fd = fs36.openSync(filePath, "r");
51915
+ try {
51916
+ const head = Buffer.alloc(META_PEEK_BYTES);
51917
+ const firstLine = head.toString("utf8", 0, fs36.readSync(fd, head, 0, head.length, 0)).split(`
51918
+ `, 1)[0] ?? "";
51919
+ return parseSessionMeta(JSON.parse(firstLine));
51920
+ } finally {
51921
+ fs36.closeSync(fd);
51922
+ }
51923
+ } catch {
51924
+ return;
51925
+ }
51926
+ }
51927
+ }
51928
+
51774
51929
  // src/integrations/harnesses/codex/index.ts
51775
51930
  class CodexHarness extends BaseHarness {
51776
51931
  id = "codex";
@@ -51778,7 +51933,9 @@ class CodexHarness extends BaseHarness {
51778
51933
  agentBuilder = codexBuilder;
51779
51934
  resultExtractor = codexResultExtractor;
51780
51935
  presenceEnv = ["CODEX_SANDBOX"];
51936
+ sessionLogProvider = () => new CodexProvider;
51781
51937
  capabilities = caps({
51938
+ sessionLogs: true,
51782
51939
  agentDispatch: true,
51783
51940
  detection: true
51784
51941
  });
@@ -52075,101 +52232,87 @@ class GeminiHarness extends BaseHarness {
52075
52232
  }
52076
52233
 
52077
52234
  // src/integrations/harnesses/opencode/model-config.ts
52235
+ var MODEL_WORK_AGENT_INFERENCE = ["temperature", "reasoningEffort", "enableThinking"];
52078
52236
  var isPositiveInteger = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
52079
- function carriedInference(inference) {
52080
- const carried = {};
52237
+ function opencodeInferenceConfig(inference, modelWork) {
52081
52238
  const { temperature, reasoningEffort, enableThinking, maxTokens, contextLength } = inference ?? {};
52239
+ const options = {};
52082
52240
  if (typeof temperature === "number" && Number.isFinite(temperature))
52083
- carried.temperature = temperature;
52241
+ options.temperature = temperature;
52084
52242
  if (typeof reasoningEffort === "string" && reasoningEffort.length > 0)
52085
- carried.reasoningEffort = reasoningEffort;
52086
- if (typeof enableThinking === "boolean")
52087
- carried.enableThinking = enableThinking;
52088
- const limit = isPositiveInteger(maxTokens) && isPositiveInteger(contextLength);
52089
- if (limit)
52090
- carried.limit = { context: contextLength, output: maxTokens };
52091
- const keys = [
52092
- ["temperature", carried.temperature !== undefined, temperature],
52093
- ["reasoningEffort", carried.reasoningEffort !== undefined, reasoningEffort],
52094
- ["enableThinking", carried.enableThinking !== undefined, enableThinking],
52095
- ["maxTokens", limit, maxTokens],
52096
- ["contextLength", limit, contextLength]
52097
- ].filter(([, isCarried, value]) => isCarried || value === null).map(([key]) => key);
52098
- return { carried, keys };
52099
- }
52100
- function splitOpencodeModel(model) {
52101
- const slash = model.indexOf("/");
52102
- if (slash <= 0 || slash === model.length - 1)
52103
- return;
52104
- return { providerID: model.slice(0, slash), modelID: model.slice(slash + 1) };
52105
- }
52106
- function opencodeCarriedKeys(attachable, inference, modelWork) {
52107
- const { keys } = carriedInference(inference);
52108
- if (attachable)
52109
- return keys;
52110
- return modelWork ? keys.filter((key) => key !== "maxTokens" && key !== "contextLength") : [];
52111
- }
52112
- function opencodeInferenceConfig(inference, modelWork) {
52113
- const { carried } = carriedInference(inference);
52114
- const options = {};
52115
- if (carried.temperature !== undefined)
52116
- options.temperature = carried.temperature;
52117
- if (carried.reasoningEffort !== undefined)
52118
- options.reasoningEffort = carried.reasoningEffort;
52119
- if (carried.enableThinking !== undefined) {
52120
- options.chat_template_kwargs = { enable_thinking: carried.enableThinking };
52121
- options.enable_thinking = carried.enableThinking;
52243
+ options.reasoningEffort = reasoningEffort;
52244
+ if (typeof enableThinking === "boolean") {
52245
+ options.chat_template_kwargs = { enable_thinking: enableThinking };
52246
+ options.enable_thinking = enableThinking;
52122
52247
  }
52123
52248
  const hasOptions = Object.keys(options).length > 0;
52124
52249
  return {
52125
52250
  entry: {
52126
52251
  ...hasOptions && !modelWork ? { options } : {},
52127
- ...carried.limit ? { limit: { ...carried.limit } } : {}
52252
+ ...isPositiveInteger(maxTokens) && isPositiveInteger(contextLength) ? { limit: { context: contextLength, output: maxTokens } } : {}
52128
52253
  },
52129
52254
  ...hasOptions && modelWork ? { agentOptions: options } : {}
52130
52255
  };
52131
52256
  }
52132
- function opencodeModelConfig(model, entry) {
52133
- const target = model === undefined ? undefined : splitOpencodeModel(model);
52134
- if (!target || Object.keys(entry).length === 0)
52135
- return;
52136
- return { provider: { [target.providerID]: { models: { [target.modelID]: entry } } } };
52137
- }
52138
52257
 
52139
52258
  // src/integrations/harnesses/opencode/model-work-agent.ts
52259
+ import path44 from "path";
52140
52260
  var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52141
- var MODEL_WORK_STEPS = 8;
52142
52261
  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.";
52143
- var MODEL_WORK_PERMISSION = {
52144
- "*": "deny",
52145
- read: "allow",
52146
- edit: "allow",
52147
- external_directory: "deny",
52148
- bash: "deny",
52149
- doom_loop: "deny",
52150
- glob: "deny",
52151
- grep: "deny",
52152
- list: "deny",
52153
- lsp: "deny",
52154
- question: "deny",
52155
- skill: "deny",
52156
- task: "deny",
52157
- todowrite: "deny",
52158
- webfetch: "deny",
52159
- websearch: "deny"
52160
- };
52262
+ function modelWorkPermission(stash) {
52263
+ return {
52264
+ "*": "deny",
52265
+ read: "allow",
52266
+ grep: "allow",
52267
+ glob: "allow",
52268
+ edit: { "*": "allow", ...stash ? { [`${stash.slice(1)}/*`]: "deny" } : {} },
52269
+ external_directory: {
52270
+ ...stash ? { [`${stash}/*`]: "allow" } : {},
52271
+ "~/.local/share/opencode/tool-output/*": "deny"
52272
+ },
52273
+ akm_search: "allow",
52274
+ akm_show: "allow",
52275
+ akm_feedback: "deny",
52276
+ akm_remember: "deny",
52277
+ akm_curate: "deny",
52278
+ bash: "deny",
52279
+ doom_loop: "deny",
52280
+ list: "deny",
52281
+ lsp: "deny",
52282
+ question: "deny",
52283
+ skill: "deny",
52284
+ task: "deny",
52285
+ todowrite: "deny",
52286
+ webfetch: "deny",
52287
+ websearch: "deny"
52288
+ };
52289
+ }
52290
+ function modelWorkPluginEnv() {
52291
+ return {
52292
+ AKM_AUTO_CURATE: "0",
52293
+ AKM_AUTO_LEARNING: "0",
52294
+ AKM_AUTO_SKILL_PROPOSALS: "0",
52295
+ AKM_WRITE_GATE: "off",
52296
+ XDG_STATE_HOME: path44.join(getStateDir(), "opencode-model-work"),
52297
+ ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52298
+ };
52299
+ }
52161
52300
  function modelWorkOpencodeConfig(options) {
52301
+ let stash;
52302
+ try {
52303
+ stash = resolveStashDir();
52304
+ } catch {}
52305
+ const permission = modelWorkPermission(stash);
52162
52306
  return {
52163
- permission: { ...MODEL_WORK_PERMISSION },
52307
+ permission: { ...permission },
52164
52308
  compaction: { auto: false },
52165
52309
  agent: {
52166
52310
  [MODEL_WORK_OPENCODE_AGENT]: {
52167
52311
  mode: "primary",
52168
52312
  description: "akm unattended model work: read and edit inside its working directory only.",
52169
52313
  prompt: MODEL_WORK_PROMPT,
52170
- steps: MODEL_WORK_STEPS,
52171
52314
  ...options ? { options } : {},
52172
- permission: { ...MODEL_WORK_PERMISSION }
52315
+ permission: { ...permission }
52173
52316
  }
52174
52317
  }
52175
52318
  };
@@ -52184,18 +52327,12 @@ var opencodeBuilder = {
52184
52327
  personaChannel: "prompt",
52185
52328
  nativeAgentSelector: true,
52186
52329
  tools: "none",
52187
- modelWorkTools: true,
52188
- inference: (profile, request) => {
52189
- const model = request.model?.resolved ?? modelFromArgs(profile.args);
52190
- return opencodeCarriedKeys(model !== undefined && splitOpencodeModel(model) !== undefined, request.inference, isModelWorkTools(request.tools));
52191
- }
52330
+ inference: MODEL_WORK_AGENT_INFERENCE
52192
52331
  }),
52193
52332
  build(profile, req) {
52194
- const model = req.model ?? modelFromArgs(profile.args);
52195
- const modelWork = isModelWorkTools(req.tools);
52196
- const { entry, agentOptions } = opencodeInferenceConfig(req.inference, modelWork);
52197
- const modelConfig = opencodeModelConfig(model, entry);
52198
- if (modelWork) {
52333
+ if (req.modelWork) {
52334
+ const model = req.model ?? modelFromArgs(profile.args);
52335
+ const { agentOptions } = opencodeInferenceConfig(req.inference, true);
52199
52336
  return {
52200
52337
  argv: [
52201
52338
  profile.bin,
@@ -52206,7 +52343,10 @@ var opencodeBuilder = {
52206
52343
  "--",
52207
52344
  req.prompt
52208
52345
  ],
52209
- env: { OPENCODE_CONFIG_CONTENT: JSON.stringify({ ...modelWorkOpencodeConfig(agentOptions), ...modelConfig }) }
52346
+ env: {
52347
+ ...modelWorkPluginEnv(),
52348
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(modelWorkOpencodeConfig(agentOptions))
52349
+ }
52210
52350
  };
52211
52351
  }
52212
52352
  const args = req.model ? [] : [...profile.args];
@@ -52231,23 +52371,20 @@ var opencodeBuilder = {
52231
52371
  }
52232
52372
  args.push("--");
52233
52373
  args.push(req.prompt);
52234
- return {
52235
- argv: [profile.bin, ...args],
52236
- ...modelConfig ? { env: { OPENCODE_CONFIG_CONTENT: JSON.stringify(modelConfig) } } : {}
52237
- };
52374
+ return { argv: [profile.bin, ...args] };
52238
52375
  }
52239
52376
  };
52240
52377
 
52241
52378
  // src/integrations/harnesses/opencode/session-log.ts
52242
- import fs37 from "fs";
52243
- import os6 from "os";
52244
- import path44 from "path";
52379
+ import fs38 from "fs";
52380
+ import os7 from "os";
52381
+ import path46 from "path";
52245
52382
 
52246
52383
  // src/storage/sqlite-read-snapshot.ts
52247
52384
  import { spawnSync as spawnSync5 } from "child_process";
52248
- import fs36 from "fs";
52249
- import os5 from "os";
52250
- import path43 from "path";
52385
+ import fs37 from "fs";
52386
+ import os6 from "os";
52387
+ import path45 from "path";
52251
52388
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52252
52389
  var SNAPSHOT_BACKOFF_MS = 25;
52253
52390
 
@@ -52259,7 +52396,7 @@ class SqliteReadSnapshotUnavailableError extends Error {
52259
52396
  }
52260
52397
  function pathExists(filePath) {
52261
52398
  try {
52262
- fs36.lstatSync(filePath);
52399
+ fs37.lstatSync(filePath);
52263
52400
  return true;
52264
52401
  } catch (error2) {
52265
52402
  if (error2.code === "ENOENT")
@@ -52269,7 +52406,7 @@ function pathExists(filePath) {
52269
52406
  }
52270
52407
  function fileFingerprint(filePath) {
52271
52408
  try {
52272
- const stat = fs36.statSync(filePath, { bigint: true });
52409
+ const stat = fs37.statSync(filePath, { bigint: true });
52273
52410
  return { size: stat.size, mtimeNs: stat.mtimeNs, ctimeNs: stat.ctimeNs };
52274
52411
  } catch (error2) {
52275
52412
  if (error2.code === "ENOENT")
@@ -52291,7 +52428,7 @@ function fingerprintsEqual(left, right) {
52291
52428
  }
52292
52429
  function copyFileOutsideThisProcess(source, destination) {
52293
52430
  if (process.platform === "win32") {
52294
- fs36.copyFileSync(source, destination);
52431
+ fs37.copyFileSync(source, destination);
52295
52432
  return;
52296
52433
  }
52297
52434
  const result = spawnSync5("cp", ["--", source, destination], {
@@ -52312,8 +52449,8 @@ function copyFileOutsideThisProcess(source, destination) {
52312
52449
  function openSqliteReadSnapshot(dbPath) {
52313
52450
  if (!pathExists(dbPath))
52314
52451
  return;
52315
- const snapshotDir = fs36.mkdtempSync(path43.join(os5.tmpdir(), "akm-sqlite-read-"));
52316
- const snapshotPath = path43.join(snapshotDir, "snapshot.db");
52452
+ const snapshotDir = fs37.mkdtempSync(path45.join(os6.tmpdir(), "akm-sqlite-read-"));
52453
+ const snapshotPath = path45.join(snapshotDir, "snapshot.db");
52317
52454
  let db;
52318
52455
  try {
52319
52456
  let copied = false;
@@ -52328,7 +52465,7 @@ function openSqliteReadSnapshot(dbPath) {
52328
52465
  if (before.wal)
52329
52466
  copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
52330
52467
  else
52331
- fs36.rmSync(`${snapshotPath}-wal`, { force: true });
52468
+ fs37.rmSync(`${snapshotPath}-wal`, { force: true });
52332
52469
  const after = databaseFingerprint(dbPath);
52333
52470
  if (fingerprintsEqual(before, after) && !pathExists(`${dbPath}-journal`)) {
52334
52471
  copied = true;
@@ -52356,14 +52493,14 @@ function openSqliteReadSnapshot(dbPath) {
52356
52493
  closeSnapshot();
52357
52494
  } catch {}
52358
52495
  try {
52359
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52496
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52360
52497
  } catch {}
52361
52498
  return;
52362
52499
  }
52363
52500
  try {
52364
52501
  closeSnapshot();
52365
52502
  } finally {
52366
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52503
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52367
52504
  }
52368
52505
  };
52369
52506
  const cleanupOnExit = () => cleanup(true);
@@ -52374,7 +52511,7 @@ function openSqliteReadSnapshot(dbPath) {
52374
52511
  try {
52375
52512
  db?.close();
52376
52513
  } finally {
52377
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52514
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52378
52515
  }
52379
52516
  throw error2;
52380
52517
  }
@@ -52383,9 +52520,9 @@ function openSqliteReadSnapshot(dbPath) {
52383
52520
  // src/integrations/harnesses/opencode/session-log.ts
52384
52521
  function getOpenCodeBaseDir() {
52385
52522
  if (process.platform === "darwin") {
52386
- return path44.join(os6.homedir(), "Library", "Application Support", "opencode");
52523
+ return path46.join(os7.homedir(), "Library", "Application Support", "opencode");
52387
52524
  }
52388
- return path44.join(os6.homedir(), ".local", "share", "opencode");
52525
+ return path46.join(os7.homedir(), ".local", "share", "opencode");
52389
52526
  }
52390
52527
  var OPENCODE_DB_FILENAME = "opencode.db";
52391
52528
 
@@ -52396,13 +52533,13 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52396
52533
  return this.#dbPath(this.#baseDir);
52397
52534
  }
52398
52535
  #dbPath(base) {
52399
- return path44.join(base, OPENCODE_DB_FILENAME);
52536
+ return path46.join(base, OPENCODE_DB_FILENAME);
52400
52537
  }
52401
52538
  listSessions(input = {}) {
52402
52539
  const base = input.location ?? this.#baseDir;
52403
52540
  const sinceMs = input.sinceMs ?? 0;
52404
52541
  const dbPath = this.#dbPath(base);
52405
- if (!fs37.existsSync(dbPath))
52542
+ if (!fs38.existsSync(dbPath))
52406
52543
  return [];
52407
52544
  return this.#listSessionsFromDb(dbPath, sinceMs, input.isolatedSnapshot ?? false);
52408
52545
  }
@@ -52534,8 +52671,7 @@ class OpencodeSdkHarness extends BaseHarness {
52534
52671
  personaChannel: "native",
52535
52672
  nativeAgentSelector: true,
52536
52673
  tools: "sdk",
52537
- modelWorkTools: true,
52538
- inference: (_profile, request) => opencodeCarriedKeys(Boolean(request.model?.resolved), request.inference, isModelWorkTools(request.tools))
52674
+ inference: MODEL_WORK_AGENT_INFERENCE
52539
52675
  })
52540
52676
  };
52541
52677
  capabilities = caps({
@@ -52812,11 +52948,6 @@ var VALID_HARNESS_IDS2 = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
52812
52948
  var SESSION_LOG_HARNESSES = HARNESS_REGISTRY.filter(isSessionLogHarness);
52813
52949
  var AGENT_DISPATCH_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.agentDispatch);
52814
52950
 
52815
- // src/integrations/agent/model-map.ts
52816
- var ENGINE_KEY_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
52817
- var RESERVED_MAP_KEYS = new Set(["__proto__", "constructor", "prototype", "tostring"]);
52818
- var PROFILE_FIELD_KEYS = new Set(["model", "inference", "engine"]);
52819
-
52820
52951
  // src/core/spawn-env.ts
52821
52952
  var COMMON_SPAWN_ENV_PASSTHROUGH = [
52822
52953
  "HOME",
@@ -52828,6 +52959,12 @@ var COMMON_SPAWN_ENV_PASSTHROUGH = [
52828
52959
  "TMPDIR",
52829
52960
  "AKM_EVENT_SOURCE"
52830
52961
  ];
52962
+ var XDG_BASE_DIR_ENV_PASSTHROUGH = [
52963
+ "XDG_CONFIG_HOME",
52964
+ "XDG_DATA_HOME",
52965
+ "XDG_CACHE_HOME",
52966
+ "XDG_STATE_HOME"
52967
+ ];
52831
52968
  var supplementedPaths = new Map;
52832
52969
 
52833
52970
  // src/integrations/agent/profiles.ts
@@ -52838,7 +52975,7 @@ var BUILTINS = {
52838
52975
  bin: "opencode",
52839
52976
  args: ["run"],
52840
52977
  stdio: "interactive",
52841
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
52978
+ envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG", ...XDG_BASE_DIR_ENV_PASSTHROUGH],
52842
52979
  parseOutput: "text"
52843
52980
  },
52844
52981
  claude: {
@@ -52918,6 +53055,11 @@ var FALLBACK_ANNOUNCEMENT = `No engine is configured; falling back to \`${FALLBA
52918
53055
  var NO_ENGINE_MESSAGE_SUFFIX = `has no selected engine, and no usable \`${OPENCODE_SDK_SERVER_BIN}\` binary was found to fall back to.`;
52919
53056
  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`) \u2014 akm falls back to it automatically.";
52920
53057
 
53058
+ // src/integrations/agent/model-map.ts
53059
+ var ENGINE_KEY_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
53060
+ var RESERVED_MAP_KEYS = new Set(["__proto__", "constructor", "prototype", "tostring"]);
53061
+ var PROFILE_FIELD_KEYS = new Set(["model", "inference", "engine"]);
53062
+
52921
53063
  // src/storage/repositories/improve-ledger-repository.ts
52922
53064
  var LEDGER_REJECTION_WINDOW_DAYS = Object.freeze({
52923
53065
  reflect: 14,
@@ -53269,8 +53411,8 @@ Commands:
53269
53411
  `;
53270
53412
 
53271
53413
  // scripts/akm-migrate/migrate/dead-residue.ts
53272
- import fs38 from "fs";
53273
- import path45 from "path";
53414
+ import fs39 from "fs";
53415
+ import path47 from "path";
53274
53416
  var DEAD_RESIDUE_PATHS = [
53275
53417
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53276
53418
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53287,43 +53429,43 @@ function dirSizeBytes(target) {
53287
53429
  let total = 0;
53288
53430
  let entries;
53289
53431
  try {
53290
- entries = fs38.readdirSync(target, { withFileTypes: true });
53432
+ entries = fs39.readdirSync(target, { withFileTypes: true });
53291
53433
  } catch {
53292
53434
  return 0;
53293
53435
  }
53294
53436
  for (const entry of entries) {
53295
- const entryPath = path45.join(target, entry.name);
53437
+ const entryPath = path47.join(target, entry.name);
53296
53438
  if (entry.isDirectory()) {
53297
53439
  total += dirSizeBytes(entryPath);
53298
53440
  } else if (entry.isFile()) {
53299
53441
  try {
53300
- total += fs38.statSync(entryPath).size;
53442
+ total += fs39.statSync(entryPath).size;
53301
53443
  } catch {}
53302
53444
  }
53303
53445
  }
53304
53446
  return total;
53305
53447
  }
53306
53448
  function sizeOf(target) {
53307
- const st = fs38.statSync(target);
53449
+ const st = fs39.statSync(target);
53308
53450
  return st.isDirectory() ? dirSizeBytes(target) : st.size;
53309
53451
  }
53310
53452
  function hostResidue() {
53311
53453
  const data = getDataDir();
53312
53454
  const state = getStateDir();
53313
- const configDir = path45.dirname(getConfigPath());
53455
+ const configDir = path47.dirname(getConfigPath());
53314
53456
  const named = [
53315
- { absolutePath: path45.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53316
- { absolutePath: path45.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53317
- { absolutePath: path45.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53318
- { absolutePath: path45.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53319
- { absolutePath: path45.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53320
- { absolutePath: path45.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53321
- { absolutePath: path45.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53457
+ { absolutePath: path47.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53458
+ { absolutePath: path47.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53459
+ { absolutePath: path47.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53460
+ { absolutePath: path47.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53461
+ { absolutePath: path47.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53462
+ { absolutePath: path47.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53463
+ { absolutePath: path47.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53322
53464
  ];
53323
53465
  const found = [];
53324
53466
  const claimed = new Set;
53325
53467
  for (const entry of named) {
53326
- if (claimed.has(entry.absolutePath) || !fs38.existsSync(entry.absolutePath))
53468
+ if (claimed.has(entry.absolutePath) || !fs39.existsSync(entry.absolutePath))
53327
53469
  continue;
53328
53470
  try {
53329
53471
  found.push({ ...entry, relativePath: entry.absolutePath, sizeBytes: sizeOf(entry.absolutePath) });
@@ -53347,13 +53489,13 @@ function hostResidue() {
53347
53489
  function findSidecars(root2, depth, skip) {
53348
53490
  let entries;
53349
53491
  try {
53350
- entries = fs38.readdirSync(root2, { withFileTypes: true });
53492
+ entries = fs39.readdirSync(root2, { withFileTypes: true });
53351
53493
  } catch {
53352
53494
  return [];
53353
53495
  }
53354
53496
  const found = [];
53355
53497
  for (const entry of entries) {
53356
- const entryPath = path45.join(root2, entry.name);
53498
+ const entryPath = path47.join(root2, entry.name);
53357
53499
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53358
53500
  found.push(entryPath);
53359
53501
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53366,10 +53508,10 @@ function findDeadResidueEntries(stashDir) {
53366
53508
  const host = hostResidue();
53367
53509
  if (stashDir === undefined)
53368
53510
  return host;
53369
- const akmDir = path45.join(stashDir, ".akm");
53511
+ const akmDir = path47.join(stashDir, ".akm");
53370
53512
  let names;
53371
53513
  try {
53372
- names = fs38.readdirSync(akmDir);
53514
+ names = fs39.readdirSync(akmDir);
53373
53515
  } catch {
53374
53516
  return [];
53375
53517
  }
@@ -53379,14 +53521,14 @@ function findDeadResidueEntries(stashDir) {
53379
53521
  for (const name of matches) {
53380
53522
  if (!names.includes(name))
53381
53523
  continue;
53382
- const absolutePath = path45.join(akmDir, name);
53524
+ const absolutePath = path47.join(akmDir, name);
53383
53525
  let sizeBytes;
53384
53526
  try {
53385
53527
  sizeBytes = sizeOf(absolutePath);
53386
53528
  } catch {
53387
53529
  continue;
53388
53530
  }
53389
- found.push({ relativePath: path45.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53531
+ found.push({ relativePath: path47.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53390
53532
  }
53391
53533
  }
53392
53534
  return found;
@@ -53395,7 +53537,7 @@ function removeDeadResidue(stashDir) {
53395
53537
  const entries = findDeadResidueEntries(stashDir);
53396
53538
  return entries.map((entry) => {
53397
53539
  try {
53398
- fs38.rmSync(entry.absolutePath, { recursive: true, force: true });
53540
+ fs39.rmSync(entry.absolutePath, { recursive: true, force: true });
53399
53541
  return { relativePath: entry.relativePath, sizeBytes: entry.sizeBytes, removed: true };
53400
53542
  } catch (error2) {
53401
53543
  return {
@@ -53410,18 +53552,18 @@ function removeDeadResidue(stashDir) {
53410
53552
 
53411
53553
  // scripts/akm-migrate/task-migrate.ts
53412
53554
  import { randomUUID as randomUUID3 } from "crypto";
53413
- import fs40 from "fs";
53414
- import os7 from "os";
53415
- import path48 from "path";
53555
+ import fs41 from "fs";
53556
+ import os8 from "os";
53557
+ import path50 from "path";
53416
53558
 
53417
53559
  // scripts/akm-migrate/migrate/task-files.ts
53418
53560
  import crypto4 from "crypto";
53419
- import fs39 from "fs";
53420
- import path47 from "path";
53561
+ import fs40 from "fs";
53562
+ import path49 from "path";
53421
53563
 
53422
53564
  // src/tasks/source/task-to-v4.ts
53423
53565
  import crypto3 from "crypto";
53424
- import path46 from "path";
53566
+ import path48 from "path";
53425
53567
 
53426
53568
  // src/tasks/task-id.ts
53427
53569
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54230,7 +54372,7 @@ function addSharedNonPromptOverrides(data, akm) {
54230
54372
  }
54231
54373
  function promptSourceKind(raw) {
54232
54374
  const trimmed = raw.trim();
54233
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path46.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54375
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path48.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54234
54376
  return "file";
54235
54377
  }
54236
54378
  try {
@@ -54334,7 +54476,7 @@ function planV2DataToV4(input, data) {
54334
54476
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54335
54477
  }
54336
54478
  try {
54337
- validateTaskId(path46.basename(input.filePath, ".yml"));
54479
+ validateTaskId(path48.basename(input.filePath, ".yml"));
54338
54480
  } catch (cause) {
54339
54481
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54340
54482
  }
@@ -54479,7 +54621,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54479
54621
  for (let index = 1;index < files.length; index += 1) {
54480
54622
  const previous = files[index - 1];
54481
54623
  const current = files[index];
54482
- if (previous && current && path46.resolve(previous.filePath) === path46.resolve(current.filePath)) {
54624
+ if (previous && current && path48.resolve(previous.filePath) === path48.resolve(current.filePath)) {
54483
54625
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54484
54626
  }
54485
54627
  }
@@ -54491,18 +54633,18 @@ function migrationError(detail) {
54491
54633
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54492
54634
  }
54493
54635
  function contained2(root2, candidate) {
54494
- const relative = path47.relative(root2, candidate);
54495
- return relative === "" || !relative.startsWith("..") && !path47.isAbsolute(relative);
54636
+ const relative = path49.relative(root2, candidate);
54637
+ return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
54496
54638
  }
54497
54639
  function realDirectory(filePath) {
54498
- const stat = fs39.lstatSync(filePath);
54640
+ const stat = fs40.lstatSync(filePath);
54499
54641
  if (stat.isSymbolicLink() || !stat.isDirectory())
54500
54642
  throw migrationError(`${filePath} must be a real directory.`);
54501
- return fs39.realpathSync(filePath);
54643
+ return fs40.realpathSync(filePath);
54502
54644
  }
54503
54645
  function isWritable(filePath) {
54504
54646
  try {
54505
- fs39.accessSync(filePath, fs39.constants.W_OK);
54647
+ fs40.accessSync(filePath, fs40.constants.W_OK);
54506
54648
  return true;
54507
54649
  } catch {
54508
54650
  return false;
@@ -54515,12 +54657,12 @@ function walkTasks(root2, tasksDir, out) {
54515
54657
  throw migrationError(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
54516
54658
  }
54517
54659
  const visit2 = (directory) => {
54518
- const physicalDirectory = fs39.realpathSync(directory);
54660
+ const physicalDirectory = fs40.realpathSync(directory);
54519
54661
  if (!contained2(physicalRoot, physicalDirectory)) {
54520
54662
  throw migrationError(`${directory} resolves outside bundle ${root2.bundleId}.`);
54521
54663
  }
54522
- for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54523
- const candidate = path47.join(directory, entry.name);
54664
+ for (const entry of fs40.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54665
+ const candidate = path49.join(directory, entry.name);
54524
54666
  if (entry.isSymbolicLink())
54525
54667
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54526
54668
  if (entry.isDirectory()) {
@@ -54529,11 +54671,11 @@ function walkTasks(root2, tasksDir, out) {
54529
54671
  }
54530
54672
  if (!entry.isFile() || !entry.name.endsWith(".yml"))
54531
54673
  continue;
54532
- const stat = fs39.lstatSync(candidate);
54674
+ const stat = fs40.lstatSync(candidate);
54533
54675
  const mode = stat.mode & 511;
54534
54676
  out.push({
54535
54677
  filePath: candidate,
54536
- bytes: fs39.readFileSync(candidate),
54678
+ bytes: fs40.readFileSync(candidate),
54537
54679
  mode,
54538
54680
  writable: root2.writable,
54539
54681
  onDiskWritable: isWritable(candidate) && isWritable(directory) && (mode & 146) !== 0,
@@ -54546,9 +54688,9 @@ function walkTasks(root2, tasksDir, out) {
54546
54688
  function inspectTaskFiles(roots) {
54547
54689
  const files = [];
54548
54690
  for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54549
- const tasksDir = root2.layout === "akm-task" ? root2.root : path47.join(root2.root, "tasks");
54691
+ const tasksDir = root2.layout === "akm-task" ? root2.root : path49.join(root2.root, "tasks");
54550
54692
  try {
54551
- const stat = fs39.lstatSync(tasksDir);
54693
+ const stat = fs40.lstatSync(tasksDir);
54552
54694
  if (stat.isSymbolicLink())
54553
54695
  throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
54554
54696
  if (!stat.isDirectory())
@@ -54566,18 +54708,18 @@ function planTaskFilesMigration(inputs) {
54566
54708
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54567
54709
  }
54568
54710
  function taskFileBackupPath(backupRoot, filePath) {
54569
- const digest = crypto4.createHash("sha256").update(path47.resolve(filePath)).digest("hex").slice(0, 16);
54570
- return path47.join(backupRoot, "files", `${digest}-${path47.basename(filePath)}`);
54711
+ const digest = crypto4.createHash("sha256").update(path49.resolve(filePath)).digest("hex").slice(0, 16);
54712
+ return path49.join(backupRoot, "files", `${digest}-${path49.basename(filePath)}`);
54571
54713
  }
54572
54714
  function fsyncDirectory(directory) {
54573
54715
  if (process.platform === "win32")
54574
54716
  return;
54575
54717
  try {
54576
- const fd = fs39.openSync(directory, "r");
54718
+ const fd = fs40.openSync(directory, "r");
54577
54719
  try {
54578
- fs39.fsyncSync(fd);
54720
+ fs40.fsyncSync(fd);
54579
54721
  } finally {
54580
- fs39.closeSync(fd);
54722
+ fs40.closeSync(fd);
54581
54723
  }
54582
54724
  } catch (cause) {
54583
54725
  const code = cause.code;
@@ -54586,25 +54728,25 @@ function fsyncDirectory(directory) {
54586
54728
  }
54587
54729
  }
54588
54730
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54589
- fs39.mkdirSync(path47.dirname(filePath), { recursive: true });
54590
- const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54731
+ fs40.mkdirSync(path49.dirname(filePath), { recursive: true });
54732
+ const fd = fs40.openSync(filePath, exclusive ? "wx" : "w", mode);
54591
54733
  try {
54592
- fs39.writeFileSync(fd, bytes);
54593
- fs39.fsyncSync(fd);
54734
+ fs40.writeFileSync(fd, bytes);
54735
+ fs40.fsyncSync(fd);
54594
54736
  } finally {
54595
- fs39.closeSync(fd);
54737
+ fs40.closeSync(fd);
54596
54738
  }
54597
- fs39.chmodSync(filePath, mode);
54598
- fsyncDirectory(path47.dirname(filePath));
54739
+ fs40.chmodSync(filePath, mode);
54740
+ fsyncDirectory(path49.dirname(filePath));
54599
54741
  }
54600
54742
  function replaceAtomically(filePath, bytes, mode) {
54601
- const temporary = path47.join(path47.dirname(filePath), `.${path47.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54743
+ const temporary = path49.join(path49.dirname(filePath), `.${path49.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54602
54744
  try {
54603
54745
  writeDurable(temporary, bytes, mode, true);
54604
- fs39.renameSync(temporary, filePath);
54605
- fsyncDirectory(path47.dirname(filePath));
54746
+ fs40.renameSync(temporary, filePath);
54747
+ fsyncDirectory(path49.dirname(filePath));
54606
54748
  } finally {
54607
- fs39.rmSync(temporary, { force: true });
54749
+ fs40.rmSync(temporary, { force: true });
54608
54750
  }
54609
54751
  }
54610
54752
  function applyTaskFilesPlan(plan, options) {
@@ -54627,7 +54769,7 @@ function applyTaskFilesPlan(plan, options) {
54627
54769
  }
54628
54770
  } catch (cause) {
54629
54771
  for (const change of [...replaced].reverse()) {
54630
- replaceAtomically(change.filePath, fs39.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54772
+ replaceAtomically(change.filePath, fs40.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54631
54773
  }
54632
54774
  throw cause;
54633
54775
  }
@@ -54637,14 +54779,14 @@ function applyTaskFilesPlan(plan, options) {
54637
54779
  // scripts/akm-migrate/task-migrate.ts
54638
54780
  function expandTilde(value) {
54639
54781
  if (value === "~")
54640
- return os7.homedir();
54782
+ return os8.homedir();
54641
54783
  if (value.startsWith("~/") || value.startsWith("~\\"))
54642
- return path48.join(os7.homedir(), value.slice(2));
54784
+ return path50.join(os8.homedir(), value.slice(2));
54643
54785
  return value;
54644
54786
  }
54645
54787
  function existingDirectory(target) {
54646
54788
  try {
54647
- return fs40.statSync(target).isDirectory();
54789
+ return fs41.statSync(target).isDirectory();
54648
54790
  } catch (cause) {
54649
54791
  if (cause.code === "ENOENT")
54650
54792
  return false;
@@ -54665,14 +54807,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54665
54807
  const source = sources.get(bundleId);
54666
54808
  if (!source)
54667
54809
  continue;
54668
- const configuredRoot = source.type === "filesystem" && source.path ? path48.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54810
+ const configuredRoot = source.type === "filesystem" && source.path ? path50.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54669
54811
  if (!configuredRoot || !existingDirectory(configuredRoot))
54670
54812
  continue;
54671
- const bundleRoot = path48.resolve(configuredRoot);
54813
+ const bundleRoot = path50.resolve(configuredRoot);
54672
54814
  const component = bundleComponentConfig(bundle);
54673
- const componentRoot = path48.resolve(bundleRoot, component?.root ?? ".");
54674
- const relative = path48.relative(bundleRoot, componentRoot);
54675
- if (relative === ".." || relative.startsWith(`..${path48.sep}`) || path48.isAbsolute(relative)) {
54815
+ const componentRoot = path50.resolve(bundleRoot, component?.root ?? ".");
54816
+ const relative = path50.relative(bundleRoot, componentRoot);
54817
+ if (relative === ".." || relative.startsWith(`..${path50.sep}`) || path50.isAbsolute(relative)) {
54676
54818
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54677
54819
  }
54678
54820
  if (!existingDirectory(componentRoot))
@@ -54689,7 +54831,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54689
54831
  }
54690
54832
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54691
54833
  if (envStash && existingDirectory(envStash)) {
54692
- const stashRoot = path48.resolve(envStash);
54834
+ const stashRoot = path50.resolve(envStash);
54693
54835
  if (!rootsByPath.has(stashRoot)) {
54694
54836
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54695
54837
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54702,7 +54844,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54702
54844
  function taskRoot(bundleId, bundleRoot, componentRoot, configuredAdapter, writable) {
54703
54845
  const adapter = configuredAdapter ?? detectAdapterId(componentRoot, "");
54704
54846
  if (!configuredAdapter && adapter === "") {
54705
- const flatTasks = fs40.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54847
+ const flatTasks = fs41.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54706
54848
  if (flatTasks.length > 0) {
54707
54849
  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");
54708
54850
  }
@@ -54758,7 +54900,7 @@ function applyTaskFilesMigration() {
54758
54900
  const before = inspectCurrent();
54759
54901
  if (before.result.taskFiles.changed === 0)
54760
54902
  return before.result;
54761
- const backupPath = path48.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54903
+ const backupPath = path50.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54762
54904
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54763
54905
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54764
54906
  });