akm-cli 0.9.24 → 0.9.25-alpha.2

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 (84) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/cli.js +1 -1
  3. package/dist/commands/health/checks.js +10 -11
  4. package/dist/commands/improve/consolidate/pair-pass.js +4 -2
  5. package/dist/commands/improve/consolidate.js +10 -4
  6. package/dist/commands/improve/execution.js +4 -11
  7. package/dist/commands/improve/extract-prompt.js +4 -4
  8. package/dist/commands/improve/extract.js +11 -13
  9. package/dist/commands/improve/improve-cli.js +65 -34
  10. package/dist/commands/improve/improve-strategies.js +49 -43
  11. package/dist/commands/improve/improve-usage-report.js +8 -17
  12. package/dist/commands/improve/loop-stages.js +3 -0
  13. package/dist/commands/improve/preparation.js +3 -1
  14. package/dist/commands/improve/reflect-noise.js +125 -0
  15. package/dist/commands/improve/reflect.js +105 -172
  16. package/dist/commands/improve/retrieval-gate.js +7 -2
  17. package/dist/commands/improve/stage.js +67 -24
  18. package/dist/commands/proposal/drain.js +11 -2
  19. package/dist/commands/proposal/proposal-cli.js +1 -5
  20. package/dist/commands/proposal/propose-cli.js +2 -2
  21. package/dist/commands/proposal/propose.js +72 -84
  22. package/dist/commands/proposal/validators/proposal-quality-validators.js +4 -2
  23. package/dist/commands/read/search-cli.js +0 -38
  24. package/dist/commands/remember.js +3 -3
  25. package/dist/commands/sources/schema-repair.js +1 -1
  26. package/dist/core/config/config-schema.js +37 -60
  27. package/dist/core/config/engine-semantics.js +15 -11
  28. package/dist/core/config/schema/improve-processes.js +18 -2
  29. package/dist/core/improve-result.js +3 -3
  30. package/dist/core/redaction.js +4 -0
  31. package/dist/core/spawn-env.js +25 -0
  32. package/dist/core/structured.js +11 -1
  33. package/dist/execution/source.js +10 -0
  34. package/dist/indexer/passes/memory-inference.js +2 -1
  35. package/dist/integrations/agent/builder-shared.js +15 -0
  36. package/dist/integrations/agent/config.js +1 -1
  37. package/dist/integrations/agent/engine-resolution.js +13 -31
  38. package/dist/integrations/agent/execution.js +48 -22
  39. package/dist/integrations/agent/index.js +1 -1
  40. package/dist/integrations/agent/profiles.js +2 -2
  41. package/dist/integrations/agent/prompts.js +55 -114
  42. package/dist/integrations/agent/request-lowering.js +21 -8
  43. package/dist/integrations/agent/runner-dispatch.js +96 -3
  44. package/dist/integrations/agent/runner.js +8 -2
  45. package/dist/integrations/harnesses/aider/agent-builder.js +10 -23
  46. package/dist/integrations/harnesses/aider/index.js +0 -5
  47. package/dist/integrations/harnesses/amazonq/agent-builder.js +9 -21
  48. package/dist/integrations/harnesses/amazonq/index.js +0 -5
  49. package/dist/integrations/harnesses/claude/agent-builder.js +47 -36
  50. package/dist/integrations/harnesses/claude/index.js +0 -14
  51. package/dist/integrations/harnesses/codex/agent-builder.js +3 -4
  52. package/dist/integrations/harnesses/codex/index.js +0 -4
  53. package/dist/integrations/harnesses/copilot/agent-builder.js +4 -13
  54. package/dist/integrations/harnesses/copilot/index.js +2 -7
  55. package/dist/integrations/harnesses/gemini/agent-builder.js +4 -13
  56. package/dist/integrations/harnesses/gemini/index.js +0 -5
  57. package/dist/integrations/harnesses/ids.js +12 -10
  58. package/dist/integrations/harnesses/opencode/agent-builder.js +41 -9
  59. package/dist/integrations/harnesses/opencode/index.js +0 -8
  60. package/dist/integrations/harnesses/opencode/model-config.js +33 -0
  61. package/dist/integrations/harnesses/opencode/model-work-agent.js +115 -0
  62. package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -7
  63. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +114 -28
  64. package/dist/integrations/harnesses/openhands/agent-builder.js +7 -21
  65. package/dist/integrations/harnesses/openhands/index.js +0 -5
  66. package/dist/integrations/harnesses/pi/agent-builder.js +7 -21
  67. package/dist/integrations/harnesses/pi/index.js +0 -5
  68. package/dist/llm/client.js +5 -0
  69. package/dist/llm/feature-gate.js +12 -9
  70. package/dist/llm/index-passes.js +2 -5
  71. package/dist/llm/memory-infer.js +6 -5
  72. package/dist/llm/structured-call.js +33 -11
  73. package/dist/output/shapes/passthrough.js +1 -0
  74. package/dist/scripts/akm-migrate-node.js +298 -228
  75. package/dist/scripts/akm-migrate.js +298 -228
  76. package/dist/workflows/exec/step-work.js +6 -5
  77. package/dist/workflows/exec/unit-dispatch.js +4 -13
  78. package/dist/workflows/freeze/step-values.js +1 -1
  79. package/docs/reference/cli.md +41 -18
  80. package/docs/reference/configuration.md +165 -12
  81. package/docs/reference/data-and-telemetry.md +2 -3
  82. package/docs/reference/workflow-schema.md +10 -9
  83. package/package.json +1 -1
  84. package/schemas/akm-config.json +108 -0
@@ -27564,16 +27564,16 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
27564
27564
  "reflect-distill",
27565
27565
  "proactive-maintenance"
27566
27566
  ];
27567
- var IMPROVE_PROCESS_ENGINE_CAPABILITIES = {
27568
- reflect: "llm",
27569
- distill: "llm",
27570
- consolidate: "llm",
27571
- memoryInference: "llm",
27572
- extract: "llm",
27573
- validation: "llm",
27574
- triage: "runner",
27575
- proactiveMaintenance: null
27576
- };
27567
+ var IMPROVE_ENGINE_PROCESSES = [
27568
+ "reflect",
27569
+ "distill",
27570
+ "consolidate",
27571
+ "memoryInference",
27572
+ "extract",
27573
+ "validation",
27574
+ "triage"
27575
+ ];
27576
+ var IMPROVE_PROCESS_NAMES = [...IMPROVE_ENGINE_PROCESSES, "proactiveMaintenance"];
27577
27577
 
27578
27578
  // src/core/improve-result.ts
27579
27579
  var COMMON_FIELDS = [
@@ -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",
@@ -34781,6 +34782,23 @@ var coerce = {
34781
34782
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
34782
34783
  };
34783
34784
  var NEVER = INVALID;
34785
+ // src/integrations/harnesses/ids.ts
34786
+ var HARNESS_ID_TABLE = [
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
+ ];
34798
+ var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
34799
+ var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
34800
+ var HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
34801
+
34784
34802
  // src/core/extra-params.ts
34785
34803
  var EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
34786
34804
  "model",
@@ -35010,22 +35028,6 @@ var EmbeddingConnectionConfigSchema = exports_external.object({
35010
35028
  concurrency: positiveInt.max(16).optional()
35011
35029
  }).passthrough();
35012
35030
 
35013
- // src/integrations/harnesses/ids.ts
35014
- var HARNESS_ID_TABLE = [
35015
- { id: "opencode", agentDispatch: true },
35016
- { id: "claude", agentDispatch: true },
35017
- { id: "opencode-sdk", agentDispatch: true },
35018
- { id: "codex", agentDispatch: true },
35019
- { id: "copilot", agentDispatch: true },
35020
- { id: "pi", agentDispatch: true },
35021
- { id: "gemini", agentDispatch: true },
35022
- { id: "aider", agentDispatch: true },
35023
- { id: "amazonq", agentDispatch: true },
35024
- { id: "openhands", agentDispatch: true }
35025
- ];
35026
- var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
35027
- var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
35028
-
35029
35031
  // src/execution/limits.ts
35030
35032
  var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
35031
35033
 
@@ -35192,6 +35194,11 @@ var clsField = exports_external.object({
35192
35194
  }).passthrough().optional();
35193
35195
  var fidelityCheckField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35194
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();
35195
35202
  var extractTriageGateField = exports_external.object({
35196
35203
  enabled: exports_external.boolean().optional(),
35197
35204
  minScore: exports_external.number().min(0).optional()
@@ -35214,7 +35221,8 @@ var REFLECT_PROCESS_FIELDS = {
35214
35221
  excludeRefPrefixes: excludeRefPrefixesField,
35215
35222
  limit: processLimitField,
35216
35223
  qualityGate: qualityGateField,
35217
- lowValueFilter: lowValueFilterField
35224
+ lowValueFilter: lowValueFilterField,
35225
+ defectFilter: defectFilterField
35218
35226
  };
35219
35227
  var DISTILL_PROCESS_FIELDS = {
35220
35228
  allowedTypes: allowedTypesField,
@@ -35301,7 +35309,7 @@ var ImproveProfileProcessesSchema = exports_external.object({
35301
35309
  });
35302
35310
  }
35303
35311
  for (const [name, process2] of Object.entries(val)) {
35304
- if (!(name in IMPROVE_PROCESS_ENGINE_CAPABILITIES) && !RETIRED_PROCESS_NAMES.has(name) && process2 !== null && typeof process2 === "object" && process2.enabled === true) {
35312
+ if (!IMPROVE_PROCESS_NAMES.includes(name) && !RETIRED_PROCESS_NAMES.has(name) && process2 !== null && typeof process2 === "object" && process2.enabled === true) {
35305
35313
  ctx.addIssue({
35306
35314
  code: exports_external.ZodIssueCode.custom,
35307
35315
  path: [name],
@@ -35727,13 +35735,27 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
35727
35735
  message: "engine does not name a configured engine"
35728
35736
  });
35729
35737
  }
35730
- const defaultLlm = config.defaults?.llmEngine;
35731
- if (defaultLlm && config.engines?.[defaultLlm]?.kind !== "llm") {
35732
- ctx.addIssue({
35733
- code: exports_external.ZodIssueCode.custom,
35734
- path: ["defaults", "llmEngine"],
35735
- message: "llmEngine must name an LLM engine"
35736
- });
35738
+ const confining = [...HARNESS_MODEL_WORK_IDS];
35739
+ const confiningPlatforms = `${confining.slice(0, -1).join(", ")} or ${confining.at(-1)}`;
35740
+ const modelWorkEngine = (name, path12) => {
35741
+ if (!name)
35742
+ return;
35743
+ const engine = config.engines?.[name];
35744
+ if (!engine) {
35745
+ ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: path12, message: "engine does not name a configured engine" });
35746
+ } else if (engine.kind !== "llm" && !HARNESS_MODEL_WORK_IDS.has(engine.platform)) {
35747
+ ctx.addIssue({
35748
+ code: exports_external.ZodIssueCode.custom,
35749
+ path: path12,
35750
+ message: `engine "${name}" (platform ${engine.platform}) cannot confine the model-work tool policy, which unattended model work requires. Use an LLM engine, or an agent engine on ${confiningPlatforms}.`
35751
+ });
35752
+ }
35753
+ };
35754
+ modelWorkEngine(config.defaults?.llmEngine, ["defaults", "llmEngine"]);
35755
+ for (const [passName, pass] of Object.entries(config.index ?? {})) {
35756
+ const engine = pass?.engine;
35757
+ if (typeof engine === "string")
35758
+ modelWorkEngine(engine, ["index", passName, "engine"]);
35737
35759
  }
35738
35760
  const workflowJudge = config.workflow?.judgeEngine;
35739
35761
  if (workflowJudge && !config.engines?.[workflowJudge]) {
@@ -35752,64 +35774,24 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
35752
35774
  });
35753
35775
  }
35754
35776
  for (const [strategyName, strategy] of Object.entries(config.improve?.strategies ?? {})) {
35755
- const strategyEngine = strategy.engine;
35756
- if (strategyEngine) {
35757
- const engine = config.engines?.[strategyEngine];
35758
- if (!engine || engine.kind !== "llm") {
35759
- ctx.addIssue({
35760
- code: exports_external.ZodIssueCode.custom,
35761
- path: ["improve", "strategies", strategyName, "engine"],
35762
- message: engine ? "strategy engine must be an LLM engine" : "engine does not name a configured engine"
35763
- });
35764
- }
35765
- }
35777
+ const strategyPath = ["improve", "strategies", strategyName];
35778
+ modelWorkEngine(strategy.engine, [...strategyPath, "engine"]);
35766
35779
  for (const [processName, process2] of Object.entries(strategy.processes ?? {})) {
35767
35780
  const processConfig = process2;
35768
- const capability = IMPROVE_PROCESS_ENGINE_CAPABILITIES[processName];
35769
- if (processConfig.engine && capability === null) {
35781
+ const processPath = [...strategyPath, "processes", processName];
35782
+ if (processConfig.engine && !IMPROVE_ENGINE_PROCESSES.includes(processName)) {
35770
35783
  ctx.addIssue({
35771
35784
  code: exports_external.ZodIssueCode.custom,
35772
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
35785
+ path: [...processPath, "engine"],
35773
35786
  message: `${processName} does not dispatch an engine`
35774
35787
  });
35775
35788
  } else {
35776
- const processEngine = processConfig.engine ?? strategyEngine;
35777
- if (processEngine && capability === "llm") {
35778
- const engine = config.engines?.[processEngine];
35779
- if (!engine || engine.kind !== "llm") {
35780
- ctx.addIssue({
35781
- code: exports_external.ZodIssueCode.custom,
35782
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
35783
- message: engine ? `${processName} requires an LLM engine` : "engine does not name a configured engine"
35784
- });
35785
- }
35786
- } else if (processConfig.engine && capability === "runner" && !config.engines?.[processConfig.engine]) {
35787
- ctx.addIssue({
35788
- code: exports_external.ZodIssueCode.custom,
35789
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
35790
- message: "engine does not name a configured engine"
35791
- });
35792
- }
35789
+ modelWorkEngine(processConfig.engine, [...processPath, "engine"]);
35793
35790
  }
35794
- const judgmentEngine = processConfig.judgment?.engine;
35795
- if (processConfig.judgment?.enabled === true && judgmentEngine) {
35796
- const engine = config.engines?.[judgmentEngine];
35797
- if (!engine) {
35798
- ctx.addIssue({
35799
- code: exports_external.ZodIssueCode.custom,
35800
- path: ["improve", "strategies", strategyName, "processes", processName, "judgment", "engine"],
35801
- message: "engine does not name a configured engine"
35802
- });
35803
- }
35804
- }
35805
- const gateEngine = processConfig.qualityGate?.engine;
35806
- if (gateEngine && config.engines?.[gateEngine]?.kind !== "llm") {
35807
- ctx.addIssue({
35808
- code: exports_external.ZodIssueCode.custom,
35809
- path: ["improve", "strategies", strategyName, "processes", processName, "qualityGate", "engine"],
35810
- message: config.engines?.[gateEngine] ? "a quality-gate judge must be an LLM engine" : "engine does not name a configured engine"
35811
- });
35791
+ if (processConfig.judgment?.enabled === true) {
35792
+ modelWorkEngine(processConfig.judgment.engine, [...processPath, "judgment", "engine"]);
35812
35793
  }
35794
+ modelWorkEngine(processConfig.qualityGate?.engine, [...processPath, "qualityGate", "engine"]);
35813
35795
  }
35814
35796
  }
35815
35797
  if (config.defaultWriteTarget !== undefined) {
@@ -36962,6 +36944,10 @@ var ENV_PASSTHROUGH_REDACTION_POLICY = {
36962
36944
  OPENCODE_CONFIG: "path",
36963
36945
  CLAUDE_CONFIG: "path",
36964
36946
  CODEX_CONFIG: "path",
36947
+ XDG_CONFIG_HOME: "path",
36948
+ XDG_DATA_HOME: "path",
36949
+ XDG_CACHE_HOME: "path",
36950
+ XDG_STATE_HOME: "path",
36965
36951
  AWS_PROFILE: "identifier",
36966
36952
  AWS_REGION: "identifier",
36967
36953
  LLM_MODEL: "identifier",
@@ -39014,6 +39000,7 @@ import { createHash as createHash3 } from "crypto";
39014
39000
 
39015
39001
  // src/execution/source.ts
39016
39002
  var EXECUTION_SOURCE_SCHEMA_VERSION = 1;
39003
+ var MODEL_WORK_POLICY_ID = "model-work";
39017
39004
  function requireRecord(value, path18) {
39018
39005
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
39019
39006
  throw new TypeError(`${path18} must be an object`);
@@ -50941,6 +50928,17 @@ class BaseHarness {
50941
50928
  function resolveDispatchModel(request, _profile, _platform) {
50942
50929
  return request.model;
50943
50930
  }
50931
+ function modelFromArgs(args) {
50932
+ let model;
50933
+ for (let index = 0;index < args.length; index += 1) {
50934
+ const arg = args[index];
50935
+ if (arg === "--model")
50936
+ model = args[index + 1];
50937
+ else if (arg?.startsWith("--model="))
50938
+ model = arg.slice("--model=".length);
50939
+ }
50940
+ return model;
50941
+ }
50944
50942
  function normalizeTools(tools) {
50945
50943
  if (typeof tools === "string")
50946
50944
  return tools;
@@ -50949,6 +50947,14 @@ function normalizeTools(tools) {
50949
50947
  return JSON.stringify(tools);
50950
50948
  }
50951
50949
 
50950
+ // src/core/structured.ts
50951
+ function withSchemaInstruction(prompt, schema) {
50952
+ return `${prompt}
50953
+
50954
+ Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
50955
+ ${JSON.stringify(schema)}`;
50956
+ }
50957
+
50952
50958
  // src/integrations/agent/conversation-fallback.ts
50953
50959
  var CONVERSATION_FALLBACK_BEGIN = "<AKM_CONVERSATION_JSON>";
50954
50960
  var CONVERSATION_FALLBACK_END = "</AKM_CONVERSATION_JSON>";
@@ -51031,6 +51037,7 @@ function extensionFields(request) {
51031
51037
  function createAgentRequestLowerer(options) {
51032
51038
  const supportedInference = new Set(options.inference ?? []);
51033
51039
  return (_profile, request) => {
51040
+ const modelWork = request.authorization.policy?.id === MODEL_WORK_POLICY_ID;
51034
51041
  const notices = [];
51035
51042
  const skip = (field) => {
51036
51043
  notices.push(untranslated(options.adapter, field));
@@ -51061,24 +51068,29 @@ function createAgentRequestLowerer(options) {
51061
51068
  }
51062
51069
  dispatch.agent = request.agent;
51063
51070
  }
51071
+ if (request.outputSchema) {
51072
+ prompt = withSchemaInstruction(prompt, request.outputSchema);
51073
+ dispatch.schema = request.outputSchema;
51074
+ }
51064
51075
  dispatch.prompt = prompt;
51065
51076
  if (request.model)
51066
51077
  dispatch.model = request.model.resolved;
51067
51078
  if (Object.hasOwn(request, "inference")) {
51068
51079
  dispatch.inference = request.inference ?? null;
51069
51080
  for (const key of Object.keys(request.inference ?? {}).sort()) {
51070
- if (!supportedInference.has(key))
51081
+ if (!(modelWork && supportedInference.has(key)))
51071
51082
  skip(`inference.${key}`);
51072
51083
  }
51073
- if (typeof request.inference?.effort === "string")
51074
- dispatch.effort = request.inference.effort;
51075
- }
51076
- if (request.outputSchema) {
51077
- if (!options.outputSchema)
51078
- skip("outputSchema");
51079
- dispatch.schema = request.outputSchema;
51080
51084
  }
51081
- if (request.tools !== undefined) {
51085
+ if (modelWork) {
51086
+ if (!HARNESS_MODEL_WORK_IDS.has(options.adapter)) {
51087
+ throw new ConfigError(`The ${options.adapter} transport cannot enforce the model-work tool policy.`, "INVALID_CONFIG_FILE");
51088
+ }
51089
+ if (dispatch.agent) {
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");
51091
+ }
51092
+ dispatch.modelWork = true;
51093
+ } else if (request.tools !== undefined) {
51082
51094
  if (hasToolSelection(request.tools) && !translatesTools(options.tools, request.tools)) {
51083
51095
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the resolved tool policy.`, "INVALID_CONFIG_FILE");
51084
51096
  }
@@ -51100,10 +51112,6 @@ function buildMessagePayload(req) {
51100
51112
  if (req.systemPrompt)
51101
51113
  sections.push(req.systemPrompt);
51102
51114
  sections.push(req.prompt);
51103
- if (req.schema) {
51104
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51105
- ${JSON.stringify(req.schema)}`);
51106
- }
51107
51115
  return sections.join(`
51108
51116
 
51109
51117
  `);
@@ -51114,8 +51122,7 @@ var aiderBuilder = {
51114
51122
  lower: createAgentRequestLowerer({
51115
51123
  adapter: AIDER_PLATFORM,
51116
51124
  personaChannel: "prompt",
51117
- tools: "none",
51118
- outputSchema: true
51125
+ tools: "none"
51119
51126
  }),
51120
51127
  build(profile, req) {
51121
51128
  const args = [...profile.args];
@@ -51165,8 +51172,6 @@ class AiderHarness extends BaseHarness {
51165
51172
  displayName = "Aider";
51166
51173
  agentBuilder = aiderBuilder;
51167
51174
  resultExtractor = aiderResultExtractor;
51168
- pattern = "local-runner";
51169
- structuredOutput = "none";
51170
51175
  capabilities = caps({
51171
51176
  agentDispatch: true,
51172
51177
  detection: true
@@ -51189,10 +51194,6 @@ function buildPromptPayload(req) {
51189
51194
  if (req.systemPrompt)
51190
51195
  sections.push(req.systemPrompt);
51191
51196
  sections.push(req.prompt);
51192
- if (req.schema) {
51193
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51194
- ${JSON.stringify(req.schema)}`);
51195
- }
51196
51197
  return sections.join(`
51197
51198
 
51198
51199
  `);
@@ -51203,8 +51204,7 @@ var amazonqBuilder = {
51203
51204
  lower: createAgentRequestLowerer({
51204
51205
  adapter: AMAZONQ_PLATFORM,
51205
51206
  personaChannel: "prompt",
51206
- tools: "flat",
51207
- outputSchema: true
51207
+ tools: "flat"
51208
51208
  }),
51209
51209
  build(profile, req) {
51210
51210
  const extra = profile.args[0] === "chat" ? profile.args.slice(1) : [...profile.args];
@@ -51261,8 +51261,6 @@ class AmazonqHarness extends BaseHarness {
51261
51261
  displayName = "Amazon Q Developer CLI";
51262
51262
  agentBuilder = amazonqBuilder;
51263
51263
  resultExtractor = amazonqResultExtractor;
51264
- pattern = "local-runner";
51265
- structuredOutput = "none";
51266
51264
  capabilities = caps({
51267
51265
  agentDispatch: true,
51268
51266
  detection: true
@@ -51270,14 +51268,16 @@ class AmazonqHarness extends BaseHarness {
51270
51268
  }
51271
51269
 
51272
51270
  // src/integrations/harnesses/claude/agent-builder.ts
51273
- function buildPromptPayload2(req) {
51274
- if (!req.schema)
51275
- return req.prompt;
51276
- return `${req.prompt}
51277
-
51278
- Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51279
- ${JSON.stringify(req.schema)}`;
51280
- }
51271
+ var MODEL_WORK_CLAUDE_FLAGS = Object.freeze([
51272
+ "--restricted",
51273
+ "--strict-mcp-config",
51274
+ "--tools",
51275
+ "Read,Edit,Bash",
51276
+ "--allowedTools",
51277
+ "Read,Edit,Bash(akm search *),Bash(akm show *)",
51278
+ "--permission-mode",
51279
+ "dontAsk"
51280
+ ]);
51281
51281
  var claudeBuilder = {
51282
51282
  platform: "claude",
51283
51283
  personaChannel: "native",
@@ -51285,11 +51285,11 @@ var claudeBuilder = {
51285
51285
  adapter: "claude",
51286
51286
  personaChannel: "native",
51287
51287
  nativeAgentSelector: true,
51288
- tools: "all",
51289
- outputSchema: true
51288
+ tools: "all"
51290
51289
  }),
51291
51290
  build(profile, req) {
51292
- const args = [...profile.args];
51291
+ const modelWork = req.modelWork === true;
51292
+ const args = modelWork ? [...MODEL_WORK_CLAUDE_FLAGS] : [...profile.args];
51293
51293
  if (req.agent) {
51294
51294
  args.push("--agent", req.agent);
51295
51295
  }
@@ -51299,6 +51299,10 @@ var claudeBuilder = {
51299
51299
  if (req.model) {
51300
51300
  const resolved = resolveDispatchModel(req, profile, "claude");
51301
51301
  args.push("--model", resolved);
51302
+ } else if (modelWork) {
51303
+ const model = modelFromArgs(profile.args);
51304
+ if (model)
51305
+ args.push("--model", model);
51302
51306
  }
51303
51307
  if (req.tools) {
51304
51308
  args.push("--allowedTools", normalizeTools(req.tools));
@@ -51308,7 +51312,7 @@ var claudeBuilder = {
51308
51312
  }
51309
51313
  args.push("--print");
51310
51314
  args.push("--");
51311
- args.push(buildPromptPayload2(req));
51315
+ args.push(req.prompt);
51312
51316
  return { argv: [profile.bin, ...args] };
51313
51317
  }
51314
51318
  };
@@ -51643,8 +51647,6 @@ class ClaudeHarness extends BaseHarness {
51643
51647
  setupDetectionDir = ".claude";
51644
51648
  agentBuilder = claudeBuilder;
51645
51649
  resultExtractor = claudeResultExtractor;
51646
- pattern = "in-harness";
51647
- structuredOutput = "native-json";
51648
51650
  identityEnv = ["CLAUDE_SESSION_ID"];
51649
51651
  sessionLogProvider = () => new ClaudeCodeProvider;
51650
51652
  capabilities = caps({
@@ -51679,8 +51681,7 @@ var codexBuilder = {
51679
51681
  lower: createAgentRequestLowerer({
51680
51682
  adapter: "codex",
51681
51683
  personaChannel: "prompt",
51682
- tools: "none",
51683
- outputSchema: true
51684
+ tools: "none"
51684
51685
  }),
51685
51686
  build(profile, req) {
51686
51687
  const extra = profile.args[0] === "exec" ? profile.args.slice(1) : [...profile.args];
@@ -51767,8 +51768,6 @@ class CodexHarness extends BaseHarness {
51767
51768
  displayName = "OpenAI Codex CLI";
51768
51769
  agentBuilder = codexBuilder;
51769
51770
  resultExtractor = codexResultExtractor;
51770
- pattern = "local-runner";
51771
- structuredOutput = "native-schema";
51772
51771
  presenceEnv = ["CODEX_SANDBOX"];
51773
51772
  capabilities = caps({
51774
51773
  agentDispatch: true,
@@ -51787,15 +51786,11 @@ function toolPolicyEntries2(tools) {
51787
51786
  }
51788
51787
  return;
51789
51788
  }
51790
- function buildPromptPayload3(req) {
51789
+ function buildPromptPayload2(req) {
51791
51790
  const sections = [];
51792
51791
  if (req.systemPrompt)
51793
51792
  sections.push(req.systemPrompt);
51794
51793
  sections.push(req.prompt);
51795
- if (req.schema) {
51796
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51797
- ${JSON.stringify(req.schema)}`);
51798
- }
51799
51794
  return sections.join(`
51800
51795
 
51801
51796
  `);
@@ -51806,8 +51801,7 @@ var copilotBuilder = {
51806
51801
  lower: createAgentRequestLowerer({
51807
51802
  adapter: COPILOT_PLATFORM,
51808
51803
  personaChannel: "prompt",
51809
- tools: "flat",
51810
- outputSchema: true
51804
+ tools: "flat"
51811
51805
  }),
51812
51806
  build(profile, req) {
51813
51807
  const args = [...profile.args];
@@ -51826,7 +51820,7 @@ var copilotBuilder = {
51826
51820
  if (req.schema) {
51827
51821
  args.push("--output-format", "json");
51828
51822
  }
51829
- args.push("-p", buildPromptPayload3(req));
51823
+ args.push("-p", buildPromptPayload2(req));
51830
51824
  return { argv: [profile.bin, ...args] };
51831
51825
  }
51832
51826
  };
@@ -51924,8 +51918,6 @@ class CopilotHarness extends BaseHarness {
51924
51918
  displayName = "GitHub Copilot CLI";
51925
51919
  agentBuilder = copilotBuilder;
51926
51920
  resultExtractor = copilotResultExtractor;
51927
- pattern = "local-runner";
51928
- structuredOutput = "native-json";
51929
51921
  identityEnv = ["COPILOT_SESSION_ID"];
51930
51922
  capabilities = caps({
51931
51923
  agentDispatch: true,
@@ -51944,15 +51936,11 @@ function toolPolicyEntries3(tools) {
51944
51936
  }
51945
51937
  return;
51946
51938
  }
51947
- function buildPromptPayload4(req) {
51939
+ function buildPromptPayload3(req) {
51948
51940
  const sections = [];
51949
51941
  if (req.systemPrompt)
51950
51942
  sections.push(req.systemPrompt);
51951
51943
  sections.push(req.prompt);
51952
- if (req.schema) {
51953
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51954
- ${JSON.stringify(req.schema)}`);
51955
- }
51956
51944
  return sections.join(`
51957
51945
 
51958
51946
  `);
@@ -51963,8 +51951,7 @@ var geminiBuilder = {
51963
51951
  lower: createAgentRequestLowerer({
51964
51952
  adapter: GEMINI_PLATFORM,
51965
51953
  personaChannel: "prompt",
51966
- tools: "flat",
51967
- outputSchema: true
51954
+ tools: "flat"
51968
51955
  }),
51969
51956
  build(profile, req) {
51970
51957
  const args = [...profile.args];
@@ -51980,7 +51967,7 @@ var geminiBuilder = {
51980
51967
  if (req.schema) {
51981
51968
  args.push("--output-format", "json");
51982
51969
  }
51983
- args.push("-p", buildPromptPayload4(req));
51970
+ args.push("-p", buildPromptPayload3(req));
51984
51971
  return { argv: [profile.bin, ...args] };
51985
51972
  }
51986
51973
  };
@@ -52071,8 +52058,6 @@ class GeminiHarness extends BaseHarness {
52071
52058
  displayName = "Gemini CLI";
52072
52059
  agentBuilder = geminiBuilder;
52073
52060
  resultExtractor = geminiResultExtractor;
52074
- pattern = "local-runner";
52075
- structuredOutput = "native-json";
52076
52061
  presenceEnv = ["GEMINI_CLI"];
52077
52062
  capabilities = caps({
52078
52063
  agentDispatch: true,
@@ -52080,18 +52065,124 @@ class GeminiHarness extends BaseHarness {
52080
52065
  });
52081
52066
  }
52082
52067
 
52068
+ // src/integrations/harnesses/opencode/model-config.ts
52069
+ var MODEL_WORK_AGENT_INFERENCE = ["temperature", "reasoningEffort", "enableThinking"];
52070
+ var isPositiveInteger = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
52071
+ function opencodeInferenceConfig(inference, modelWork) {
52072
+ const { temperature, reasoningEffort, enableThinking, maxTokens, contextLength } = inference ?? {};
52073
+ const options = {};
52074
+ if (typeof temperature === "number" && Number.isFinite(temperature))
52075
+ options.temperature = temperature;
52076
+ if (typeof reasoningEffort === "string" && reasoningEffort.length > 0)
52077
+ options.reasoningEffort = reasoningEffort;
52078
+ if (typeof enableThinking === "boolean") {
52079
+ options.chat_template_kwargs = { enable_thinking: enableThinking };
52080
+ options.enable_thinking = enableThinking;
52081
+ }
52082
+ const hasOptions = Object.keys(options).length > 0;
52083
+ return {
52084
+ entry: {
52085
+ ...hasOptions && !modelWork ? { options } : {},
52086
+ ...isPositiveInteger(maxTokens) && isPositiveInteger(contextLength) ? { limit: { context: contextLength, output: maxTokens } } : {}
52087
+ },
52088
+ ...hasOptions && modelWork ? { agentOptions: options } : {}
52089
+ };
52090
+ }
52091
+
52092
+ // src/integrations/harnesses/opencode/model-work-agent.ts
52093
+ import path43 from "path";
52094
+ var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52095
+ 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.";
52096
+ function modelWorkPermission(stash) {
52097
+ return {
52098
+ "*": "deny",
52099
+ read: "allow",
52100
+ grep: "allow",
52101
+ glob: "allow",
52102
+ edit: { "*": "allow", ...stash ? { [`${stash.slice(1)}/*`]: "deny" } : {} },
52103
+ external_directory: {
52104
+ ...stash ? { [`${stash}/*`]: "allow" } : {},
52105
+ "~/.local/share/opencode/tool-output/*": "deny"
52106
+ },
52107
+ akm_search: "allow",
52108
+ akm_show: "allow",
52109
+ akm_feedback: "deny",
52110
+ akm_remember: "deny",
52111
+ akm_curate: "deny",
52112
+ bash: "deny",
52113
+ doom_loop: "deny",
52114
+ list: "deny",
52115
+ lsp: "deny",
52116
+ question: "deny",
52117
+ skill: "deny",
52118
+ task: "deny",
52119
+ todowrite: "deny",
52120
+ webfetch: "deny",
52121
+ websearch: "deny"
52122
+ };
52123
+ }
52124
+ function modelWorkPluginEnv() {
52125
+ return {
52126
+ AKM_AUTO_CURATE: "0",
52127
+ AKM_AUTO_LEARNING: "0",
52128
+ AKM_AUTO_SKILL_PROPOSALS: "0",
52129
+ AKM_WRITE_GATE: "off",
52130
+ XDG_STATE_HOME: path43.join(getStateDir(), "opencode-model-work"),
52131
+ ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52132
+ };
52133
+ }
52134
+ function modelWorkOpencodeConfig(options) {
52135
+ let stash;
52136
+ try {
52137
+ stash = resolveStashDir();
52138
+ } catch {}
52139
+ const permission = modelWorkPermission(stash);
52140
+ return {
52141
+ permission: { ...permission },
52142
+ compaction: { auto: false },
52143
+ agent: {
52144
+ [MODEL_WORK_OPENCODE_AGENT]: {
52145
+ mode: "primary",
52146
+ description: "akm unattended model work: read and edit inside its working directory only.",
52147
+ prompt: MODEL_WORK_PROMPT,
52148
+ ...options ? { options } : {},
52149
+ permission: { ...permission }
52150
+ }
52151
+ }
52152
+ };
52153
+ }
52154
+
52083
52155
  // src/integrations/harnesses/opencode/agent-builder.ts
52084
52156
  var opencodeBuilder = {
52085
52157
  platform: "opencode",
52086
- personaChannel: "native",
52158
+ personaChannel: "prompt",
52087
52159
  lower: createAgentRequestLowerer({
52088
52160
  adapter: "opencode",
52089
- personaChannel: "native",
52161
+ personaChannel: "prompt",
52090
52162
  nativeAgentSelector: true,
52091
52163
  tools: "none",
52092
- outputSchema: false
52164
+ inference: MODEL_WORK_AGENT_INFERENCE
52093
52165
  }),
52094
52166
  build(profile, req) {
52167
+ if (req.modelWork) {
52168
+ const model = req.model ?? modelFromArgs(profile.args);
52169
+ const { agentOptions } = opencodeInferenceConfig(req.inference, true);
52170
+ return {
52171
+ argv: [
52172
+ profile.bin,
52173
+ "run",
52174
+ "--agent",
52175
+ MODEL_WORK_OPENCODE_AGENT,
52176
+ ...model ? ["--model", model] : [],
52177
+ "--",
52178
+ req.prompt
52179
+ ],
52180
+ env: {
52181
+ ...modelWorkPluginEnv(),
52182
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(modelWorkOpencodeConfig(agentOptions))
52183
+ }
52184
+ };
52185
+ }
52095
52186
  const args = req.model ? [] : [...profile.args];
52096
52187
  if (req.model) {
52097
52188
  for (let index = 0;index < profile.args.length; index += 1) {
@@ -52105,9 +52196,6 @@ var opencodeBuilder = {
52105
52196
  }
52106
52197
  }
52107
52198
  }
52108
- if (req.systemPrompt) {
52109
- args.push("--system-prompt", req.systemPrompt);
52110
- }
52111
52199
  if (req.agent) {
52112
52200
  args.push("--agent", req.agent);
52113
52201
  }
@@ -52124,13 +52212,13 @@ var opencodeBuilder = {
52124
52212
  // src/integrations/harnesses/opencode/session-log.ts
52125
52213
  import fs37 from "fs";
52126
52214
  import os6 from "os";
52127
- import path44 from "path";
52215
+ import path45 from "path";
52128
52216
 
52129
52217
  // src/storage/sqlite-read-snapshot.ts
52130
52218
  import { spawnSync as spawnSync5 } from "child_process";
52131
52219
  import fs36 from "fs";
52132
52220
  import os5 from "os";
52133
- import path43 from "path";
52221
+ import path44 from "path";
52134
52222
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52135
52223
  var SNAPSHOT_BACKOFF_MS = 25;
52136
52224
 
@@ -52195,8 +52283,8 @@ function copyFileOutsideThisProcess(source, destination) {
52195
52283
  function openSqliteReadSnapshot(dbPath) {
52196
52284
  if (!pathExists(dbPath))
52197
52285
  return;
52198
- const snapshotDir = fs36.mkdtempSync(path43.join(os5.tmpdir(), "akm-sqlite-read-"));
52199
- const snapshotPath = path43.join(snapshotDir, "snapshot.db");
52286
+ const snapshotDir = fs36.mkdtempSync(path44.join(os5.tmpdir(), "akm-sqlite-read-"));
52287
+ const snapshotPath = path44.join(snapshotDir, "snapshot.db");
52200
52288
  let db;
52201
52289
  try {
52202
52290
  let copied = false;
@@ -52266,9 +52354,9 @@ function openSqliteReadSnapshot(dbPath) {
52266
52354
  // src/integrations/harnesses/opencode/session-log.ts
52267
52355
  function getOpenCodeBaseDir() {
52268
52356
  if (process.platform === "darwin") {
52269
- return path44.join(os6.homedir(), "Library", "Application Support", "opencode");
52357
+ return path45.join(os6.homedir(), "Library", "Application Support", "opencode");
52270
52358
  }
52271
- return path44.join(os6.homedir(), ".local", "share", "opencode");
52359
+ return path45.join(os6.homedir(), ".local", "share", "opencode");
52272
52360
  }
52273
52361
  var OPENCODE_DB_FILENAME = "opencode.db";
52274
52362
 
@@ -52279,7 +52367,7 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52279
52367
  return this.#dbPath(this.#baseDir);
52280
52368
  }
52281
52369
  #dbPath(base) {
52282
- return path44.join(base, OPENCODE_DB_FILENAME);
52370
+ return path45.join(base, OPENCODE_DB_FILENAME);
52283
52371
  }
52284
52372
  listSessions(input = {}) {
52285
52373
  const base = input.location ?? this.#baseDir;
@@ -52395,8 +52483,6 @@ class OpencodeHarness extends BaseHarness {
52395
52483
  displayName = "OpenCode";
52396
52484
  setupDetectionDir = ".config/opencode";
52397
52485
  agentBuilder = opencodeBuilder;
52398
- pattern = "local-runner";
52399
- structuredOutput = "none";
52400
52486
  identityEnv = ["OPENCODE_SESSION_ID"];
52401
52487
  sessionLogProvider = () => new OpenCodeProvider;
52402
52488
  capabilities = caps({
@@ -52411,8 +52497,6 @@ class OpencodeHarness extends BaseHarness {
52411
52497
  class OpencodeSdkHarness extends BaseHarness {
52412
52498
  id = "opencode-sdk";
52413
52499
  displayName = "OpenCode SDK";
52414
- pattern = "local-runner";
52415
- structuredOutput = "native-json";
52416
52500
  executionLowerer = {
52417
52501
  platform: "opencode-sdk",
52418
52502
  personaChannel: "native",
@@ -52421,7 +52505,7 @@ class OpencodeSdkHarness extends BaseHarness {
52421
52505
  personaChannel: "native",
52422
52506
  nativeAgentSelector: true,
52423
52507
  tools: "sdk",
52424
- outputSchema: false
52508
+ inference: MODEL_WORK_AGENT_INFERENCE
52425
52509
  })
52426
52510
  };
52427
52511
  capabilities = caps({
@@ -52438,10 +52522,6 @@ function buildTaskPayload(req) {
52438
52522
  if (req.systemPrompt)
52439
52523
  sections.push(req.systemPrompt);
52440
52524
  sections.push(req.prompt);
52441
- if (req.schema) {
52442
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
52443
- ${JSON.stringify(req.schema)}`);
52444
- }
52445
52525
  return sections.join(`
52446
52526
 
52447
52527
  `);
@@ -52452,8 +52532,7 @@ var openhandsBuilder = {
52452
52532
  lower: createAgentRequestLowerer({
52453
52533
  adapter: OPENHANDS_PLATFORM,
52454
52534
  personaChannel: "prompt",
52455
- tools: "none",
52456
- outputSchema: true
52535
+ tools: "none"
52457
52536
  }),
52458
52537
  build(profile, req) {
52459
52538
  const args = [...profile.args];
@@ -52537,8 +52616,6 @@ class OpenhandsHarness extends BaseHarness {
52537
52616
  displayName = "OpenHands";
52538
52617
  agentBuilder = openhandsBuilder;
52539
52618
  resultExtractor = openhandsResultExtractor;
52540
- pattern = "local-runner";
52541
- structuredOutput = "native-json";
52542
52619
  capabilities = caps({
52543
52620
  agentDispatch: true,
52544
52621
  detection: true
@@ -52547,24 +52624,13 @@ class OpenhandsHarness extends BaseHarness {
52547
52624
 
52548
52625
  // src/integrations/harnesses/pi/agent-builder.ts
52549
52626
  var PI_PLATFORM = "pi";
52550
- function buildPromptPayload5(req) {
52551
- const sections = [req.prompt];
52552
- if (req.schema) {
52553
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
52554
- ${JSON.stringify(req.schema)}`);
52555
- }
52556
- return sections.join(`
52557
-
52558
- `);
52559
- }
52560
52627
  var piBuilder = {
52561
52628
  platform: PI_PLATFORM,
52562
52629
  personaChannel: "native",
52563
52630
  lower: createAgentRequestLowerer({
52564
52631
  adapter: PI_PLATFORM,
52565
52632
  personaChannel: "native",
52566
- tools: "none",
52567
- outputSchema: true
52633
+ tools: "none"
52568
52634
  }),
52569
52635
  build(profile, req) {
52570
52636
  const args = [...profile.args];
@@ -52580,7 +52646,7 @@ var piBuilder = {
52580
52646
  }
52581
52647
  args.push("-p");
52582
52648
  args.push("--");
52583
- args.push(buildPromptPayload5(req));
52649
+ args.push(req.prompt);
52584
52650
  return { argv: [profile.bin, ...args] };
52585
52651
  }
52586
52652
  };
@@ -52682,8 +52748,6 @@ class PiHarness extends BaseHarness {
52682
52748
  displayName = "Pi";
52683
52749
  agentBuilder = piBuilder;
52684
52750
  resultExtractor = piResultExtractor;
52685
- pattern = "local-runner";
52686
- structuredOutput = "native-json";
52687
52751
  identityEnv = ["PI_SESSION_ID"];
52688
52752
  capabilities = caps({
52689
52753
  agentDispatch: true,
@@ -52729,6 +52793,12 @@ var COMMON_SPAWN_ENV_PASSTHROUGH = [
52729
52793
  "TMPDIR",
52730
52794
  "AKM_EVENT_SOURCE"
52731
52795
  ];
52796
+ var XDG_BASE_DIR_ENV_PASSTHROUGH = [
52797
+ "XDG_CONFIG_HOME",
52798
+ "XDG_DATA_HOME",
52799
+ "XDG_CACHE_HOME",
52800
+ "XDG_STATE_HOME"
52801
+ ];
52732
52802
  var supplementedPaths = new Map;
52733
52803
 
52734
52804
  // src/integrations/agent/profiles.ts
@@ -52739,7 +52809,7 @@ var BUILTINS = {
52739
52809
  bin: "opencode",
52740
52810
  args: ["run"],
52741
52811
  stdio: "interactive",
52742
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
52812
+ envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG", ...XDG_BASE_DIR_ENV_PASSTHROUGH],
52743
52813
  parseOutput: "text"
52744
52814
  },
52745
52815
  claude: {
@@ -52850,9 +52920,9 @@ var BUILTIN_STRATEGIES = {
52850
52920
  if (BUILTIN_IMPROVE_STRATEGY_NAMES.some((name) => !(name in BUILTIN_STRATEGIES))) {
52851
52921
  throw new Error("Built-in improve strategy names are out of sync with their assets");
52852
52922
  }
52923
+ var MODEL_CALLING_PROCESSES = new Set(IMPROVE_ENGINE_PROCESSES.filter((name) => name !== "triage"));
52853
52924
 
52854
52925
  // src/commands/improve/improve-usage-report.ts
52855
- var LLM_BACKED_PROCESSES = new Set(Object.keys(IMPROVE_PROCESS_ENGINE_CAPABILITIES).filter((name) => IMPROVE_PROCESS_ENGINE_CAPABILITIES[name] === "llm"));
52856
52926
  function renderFixedWidthTable(headers, rows) {
52857
52927
  const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
52858
52928
  const renderRow = (cells) => cells.map((cell, index) => cell.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
@@ -53176,7 +53246,7 @@ Commands:
53176
53246
 
53177
53247
  // scripts/akm-migrate/migrate/dead-residue.ts
53178
53248
  import fs38 from "fs";
53179
- import path45 from "path";
53249
+ import path46 from "path";
53180
53250
  var DEAD_RESIDUE_PATHS = [
53181
53251
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53182
53252
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53198,7 +53268,7 @@ function dirSizeBytes(target) {
53198
53268
  return 0;
53199
53269
  }
53200
53270
  for (const entry of entries) {
53201
- const entryPath = path45.join(target, entry.name);
53271
+ const entryPath = path46.join(target, entry.name);
53202
53272
  if (entry.isDirectory()) {
53203
53273
  total += dirSizeBytes(entryPath);
53204
53274
  } else if (entry.isFile()) {
@@ -53216,15 +53286,15 @@ function sizeOf(target) {
53216
53286
  function hostResidue() {
53217
53287
  const data = getDataDir();
53218
53288
  const state = getStateDir();
53219
- const configDir = path45.dirname(getConfigPath());
53289
+ const configDir = path46.dirname(getConfigPath());
53220
53290
  const named = [
53221
- { absolutePath: path45.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53222
- { absolutePath: path45.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53223
- { absolutePath: path45.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53224
- { absolutePath: path45.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53225
- { absolutePath: path45.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53226
- { absolutePath: path45.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53227
- { absolutePath: path45.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53291
+ { absolutePath: path46.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53292
+ { absolutePath: path46.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53293
+ { absolutePath: path46.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53294
+ { absolutePath: path46.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53295
+ { absolutePath: path46.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53296
+ { absolutePath: path46.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53297
+ { absolutePath: path46.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53228
53298
  ];
53229
53299
  const found = [];
53230
53300
  const claimed = new Set;
@@ -53259,7 +53329,7 @@ function findSidecars(root2, depth, skip) {
53259
53329
  }
53260
53330
  const found = [];
53261
53331
  for (const entry of entries) {
53262
- const entryPath = path45.join(root2, entry.name);
53332
+ const entryPath = path46.join(root2, entry.name);
53263
53333
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53264
53334
  found.push(entryPath);
53265
53335
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53272,7 +53342,7 @@ function findDeadResidueEntries(stashDir) {
53272
53342
  const host = hostResidue();
53273
53343
  if (stashDir === undefined)
53274
53344
  return host;
53275
- const akmDir = path45.join(stashDir, ".akm");
53345
+ const akmDir = path46.join(stashDir, ".akm");
53276
53346
  let names;
53277
53347
  try {
53278
53348
  names = fs38.readdirSync(akmDir);
@@ -53285,14 +53355,14 @@ function findDeadResidueEntries(stashDir) {
53285
53355
  for (const name of matches) {
53286
53356
  if (!names.includes(name))
53287
53357
  continue;
53288
- const absolutePath = path45.join(akmDir, name);
53358
+ const absolutePath = path46.join(akmDir, name);
53289
53359
  let sizeBytes;
53290
53360
  try {
53291
53361
  sizeBytes = sizeOf(absolutePath);
53292
53362
  } catch {
53293
53363
  continue;
53294
53364
  }
53295
- found.push({ relativePath: path45.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53365
+ found.push({ relativePath: path46.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53296
53366
  }
53297
53367
  }
53298
53368
  return found;
@@ -53318,16 +53388,16 @@ function removeDeadResidue(stashDir) {
53318
53388
  import { randomUUID as randomUUID3 } from "crypto";
53319
53389
  import fs40 from "fs";
53320
53390
  import os7 from "os";
53321
- import path48 from "path";
53391
+ import path49 from "path";
53322
53392
 
53323
53393
  // scripts/akm-migrate/migrate/task-files.ts
53324
53394
  import crypto4 from "crypto";
53325
53395
  import fs39 from "fs";
53326
- import path47 from "path";
53396
+ import path48 from "path";
53327
53397
 
53328
53398
  // src/tasks/source/task-to-v4.ts
53329
53399
  import crypto3 from "crypto";
53330
- import path46 from "path";
53400
+ import path47 from "path";
53331
53401
 
53332
53402
  // src/tasks/task-id.ts
53333
53403
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54136,7 +54206,7 @@ function addSharedNonPromptOverrides(data, akm) {
54136
54206
  }
54137
54207
  function promptSourceKind(raw) {
54138
54208
  const trimmed = raw.trim();
54139
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path46.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54209
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path47.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54140
54210
  return "file";
54141
54211
  }
54142
54212
  try {
@@ -54240,7 +54310,7 @@ function planV2DataToV4(input, data) {
54240
54310
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54241
54311
  }
54242
54312
  try {
54243
- validateTaskId(path46.basename(input.filePath, ".yml"));
54313
+ validateTaskId(path47.basename(input.filePath, ".yml"));
54244
54314
  } catch (cause) {
54245
54315
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54246
54316
  }
@@ -54385,7 +54455,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54385
54455
  for (let index = 1;index < files.length; index += 1) {
54386
54456
  const previous = files[index - 1];
54387
54457
  const current = files[index];
54388
- if (previous && current && path46.resolve(previous.filePath) === path46.resolve(current.filePath)) {
54458
+ if (previous && current && path47.resolve(previous.filePath) === path47.resolve(current.filePath)) {
54389
54459
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54390
54460
  }
54391
54461
  }
@@ -54397,8 +54467,8 @@ function migrationError(detail) {
54397
54467
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54398
54468
  }
54399
54469
  function contained2(root2, candidate) {
54400
- const relative = path47.relative(root2, candidate);
54401
- return relative === "" || !relative.startsWith("..") && !path47.isAbsolute(relative);
54470
+ const relative = path48.relative(root2, candidate);
54471
+ return relative === "" || !relative.startsWith("..") && !path48.isAbsolute(relative);
54402
54472
  }
54403
54473
  function realDirectory(filePath) {
54404
54474
  const stat = fs39.lstatSync(filePath);
@@ -54426,7 +54496,7 @@ function walkTasks(root2, tasksDir, out) {
54426
54496
  throw migrationError(`${directory} resolves outside bundle ${root2.bundleId}.`);
54427
54497
  }
54428
54498
  for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54429
- const candidate = path47.join(directory, entry.name);
54499
+ const candidate = path48.join(directory, entry.name);
54430
54500
  if (entry.isSymbolicLink())
54431
54501
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54432
54502
  if (entry.isDirectory()) {
@@ -54452,7 +54522,7 @@ function walkTasks(root2, tasksDir, out) {
54452
54522
  function inspectTaskFiles(roots) {
54453
54523
  const files = [];
54454
54524
  for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54455
- const tasksDir = root2.layout === "akm-task" ? root2.root : path47.join(root2.root, "tasks");
54525
+ const tasksDir = root2.layout === "akm-task" ? root2.root : path48.join(root2.root, "tasks");
54456
54526
  try {
54457
54527
  const stat = fs39.lstatSync(tasksDir);
54458
54528
  if (stat.isSymbolicLink())
@@ -54472,8 +54542,8 @@ function planTaskFilesMigration(inputs) {
54472
54542
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54473
54543
  }
54474
54544
  function taskFileBackupPath(backupRoot, filePath) {
54475
- const digest = crypto4.createHash("sha256").update(path47.resolve(filePath)).digest("hex").slice(0, 16);
54476
- return path47.join(backupRoot, "files", `${digest}-${path47.basename(filePath)}`);
54545
+ const digest = crypto4.createHash("sha256").update(path48.resolve(filePath)).digest("hex").slice(0, 16);
54546
+ return path48.join(backupRoot, "files", `${digest}-${path48.basename(filePath)}`);
54477
54547
  }
54478
54548
  function fsyncDirectory(directory) {
54479
54549
  if (process.platform === "win32")
@@ -54492,7 +54562,7 @@ function fsyncDirectory(directory) {
54492
54562
  }
54493
54563
  }
54494
54564
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54495
- fs39.mkdirSync(path47.dirname(filePath), { recursive: true });
54565
+ fs39.mkdirSync(path48.dirname(filePath), { recursive: true });
54496
54566
  const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54497
54567
  try {
54498
54568
  fs39.writeFileSync(fd, bytes);
@@ -54501,14 +54571,14 @@ function writeDurable(filePath, bytes, mode, exclusive = false) {
54501
54571
  fs39.closeSync(fd);
54502
54572
  }
54503
54573
  fs39.chmodSync(filePath, mode);
54504
- fsyncDirectory(path47.dirname(filePath));
54574
+ fsyncDirectory(path48.dirname(filePath));
54505
54575
  }
54506
54576
  function replaceAtomically(filePath, bytes, mode) {
54507
- const temporary = path47.join(path47.dirname(filePath), `.${path47.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54577
+ const temporary = path48.join(path48.dirname(filePath), `.${path48.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54508
54578
  try {
54509
54579
  writeDurable(temporary, bytes, mode, true);
54510
54580
  fs39.renameSync(temporary, filePath);
54511
- fsyncDirectory(path47.dirname(filePath));
54581
+ fsyncDirectory(path48.dirname(filePath));
54512
54582
  } finally {
54513
54583
  fs39.rmSync(temporary, { force: true });
54514
54584
  }
@@ -54545,7 +54615,7 @@ function expandTilde(value) {
54545
54615
  if (value === "~")
54546
54616
  return os7.homedir();
54547
54617
  if (value.startsWith("~/") || value.startsWith("~\\"))
54548
- return path48.join(os7.homedir(), value.slice(2));
54618
+ return path49.join(os7.homedir(), value.slice(2));
54549
54619
  return value;
54550
54620
  }
54551
54621
  function existingDirectory(target) {
@@ -54571,14 +54641,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54571
54641
  const source = sources.get(bundleId);
54572
54642
  if (!source)
54573
54643
  continue;
54574
- const configuredRoot = source.type === "filesystem" && source.path ? path48.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54644
+ const configuredRoot = source.type === "filesystem" && source.path ? path49.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54575
54645
  if (!configuredRoot || !existingDirectory(configuredRoot))
54576
54646
  continue;
54577
- const bundleRoot = path48.resolve(configuredRoot);
54647
+ const bundleRoot = path49.resolve(configuredRoot);
54578
54648
  const component = bundleComponentConfig(bundle);
54579
- const componentRoot = path48.resolve(bundleRoot, component?.root ?? ".");
54580
- const relative = path48.relative(bundleRoot, componentRoot);
54581
- if (relative === ".." || relative.startsWith(`..${path48.sep}`) || path48.isAbsolute(relative)) {
54649
+ const componentRoot = path49.resolve(bundleRoot, component?.root ?? ".");
54650
+ const relative = path49.relative(bundleRoot, componentRoot);
54651
+ if (relative === ".." || relative.startsWith(`..${path49.sep}`) || path49.isAbsolute(relative)) {
54582
54652
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54583
54653
  }
54584
54654
  if (!existingDirectory(componentRoot))
@@ -54595,7 +54665,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54595
54665
  }
54596
54666
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54597
54667
  if (envStash && existingDirectory(envStash)) {
54598
- const stashRoot = path48.resolve(envStash);
54668
+ const stashRoot = path49.resolve(envStash);
54599
54669
  if (!rootsByPath.has(stashRoot)) {
54600
54670
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54601
54671
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54664,7 +54734,7 @@ function applyTaskFilesMigration() {
54664
54734
  const before = inspectCurrent();
54665
54735
  if (before.result.taskFiles.changed === 0)
54666
54736
  return before.result;
54667
- const backupPath = path48.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54737
+ const backupPath = path49.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54668
54738
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54669
54739
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54670
54740
  });