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
@@ -28236,16 +28236,16 @@ var BUILTIN_IMPROVE_STRATEGY_NAMES = [
28236
28236
  "reflect-distill",
28237
28237
  "proactive-maintenance"
28238
28238
  ];
28239
- var IMPROVE_PROCESS_ENGINE_CAPABILITIES = {
28240
- reflect: "llm",
28241
- distill: "llm",
28242
- consolidate: "llm",
28243
- memoryInference: "llm",
28244
- extract: "llm",
28245
- validation: "llm",
28246
- triage: "runner",
28247
- proactiveMaintenance: null
28248
- };
28239
+ var IMPROVE_ENGINE_PROCESSES = [
28240
+ "reflect",
28241
+ "distill",
28242
+ "consolidate",
28243
+ "memoryInference",
28244
+ "extract",
28245
+ "validation",
28246
+ "triage"
28247
+ ];
28248
+ var IMPROVE_PROCESS_NAMES = [...IMPROVE_ENGINE_PROCESSES, "proactiveMaintenance"];
28249
28249
 
28250
28250
  // src/core/improve-result.ts
28251
28251
  var COMMON_FIELDS = [
@@ -29036,6 +29036,7 @@ var PASSTHROUGH_COMMANDS = [
29036
29036
  "extract",
29037
29037
  "health",
29038
29038
  "improve",
29039
+ "improve-judge",
29039
29040
  "improve-report",
29040
29041
  "import",
29041
29042
  "index",
@@ -35453,6 +35454,23 @@ var coerce = {
35453
35454
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
35454
35455
  };
35455
35456
  var NEVER = INVALID;
35457
+ // src/integrations/harnesses/ids.ts
35458
+ var HARNESS_ID_TABLE = [
35459
+ { id: "opencode", agentDispatch: true, enforcesModelWorkTools: true },
35460
+ { id: "claude", agentDispatch: true, enforcesModelWorkTools: true },
35461
+ { id: "opencode-sdk", agentDispatch: true, enforcesModelWorkTools: true },
35462
+ { id: "codex", agentDispatch: true, enforcesModelWorkTools: false },
35463
+ { id: "copilot", agentDispatch: true, enforcesModelWorkTools: false },
35464
+ { id: "pi", agentDispatch: true, enforcesModelWorkTools: false },
35465
+ { id: "gemini", agentDispatch: true, enforcesModelWorkTools: false },
35466
+ { id: "aider", agentDispatch: true, enforcesModelWorkTools: false },
35467
+ { id: "amazonq", agentDispatch: true, enforcesModelWorkTools: false },
35468
+ { id: "openhands", agentDispatch: true, enforcesModelWorkTools: false }
35469
+ ];
35470
+ var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
35471
+ var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
35472
+ var HARNESS_MODEL_WORK_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.enforcesModelWorkTools).map((h) => h.id));
35473
+
35456
35474
  // src/core/extra-params.ts
35457
35475
  var EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
35458
35476
  "model",
@@ -35682,22 +35700,6 @@ var EmbeddingConnectionConfigSchema = exports_external.object({
35682
35700
  concurrency: positiveInt.max(16).optional()
35683
35701
  }).passthrough();
35684
35702
 
35685
- // src/integrations/harnesses/ids.ts
35686
- var HARNESS_ID_TABLE = [
35687
- { id: "opencode", agentDispatch: true },
35688
- { id: "claude", agentDispatch: true },
35689
- { id: "opencode-sdk", agentDispatch: true },
35690
- { id: "codex", agentDispatch: true },
35691
- { id: "copilot", agentDispatch: true },
35692
- { id: "pi", agentDispatch: true },
35693
- { id: "gemini", agentDispatch: true },
35694
- { id: "aider", agentDispatch: true },
35695
- { id: "amazonq", agentDispatch: true },
35696
- { id: "openhands", agentDispatch: true }
35697
- ];
35698
- var VALID_HARNESS_IDS = Object.freeze(HARNESS_ID_TABLE.map((h) => h.id));
35699
- var HARNESS_AGENT_DISPATCH_IDS = new Set(HARNESS_ID_TABLE.filter((h) => h.agentDispatch).map((h) => h.id));
35700
-
35701
35703
  // src/execution/limits.ts
35702
35704
  var EXECUTION_MAX_TIMEOUT_MS = 2 ** 31 - 1;
35703
35705
 
@@ -35864,6 +35866,11 @@ var clsField = exports_external.object({
35864
35866
  }).passthrough().optional();
35865
35867
  var fidelityCheckField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35866
35868
  var lowValueFilterField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
35869
+ var defectFilterField = exports_external.object({
35870
+ placeholders: exports_external.array(nonEmptyString).optional(),
35871
+ metaCommentary: exports_external.array(nonEmptyString).optional(),
35872
+ frontmatterKeys: exports_external.array(nonEmptyString).optional()
35873
+ }).passthrough().optional();
35867
35874
  var extractTriageGateField = exports_external.object({
35868
35875
  enabled: exports_external.boolean().optional(),
35869
35876
  minScore: exports_external.number().min(0).optional()
@@ -35886,7 +35893,8 @@ var REFLECT_PROCESS_FIELDS = {
35886
35893
  excludeRefPrefixes: excludeRefPrefixesField,
35887
35894
  limit: processLimitField,
35888
35895
  qualityGate: qualityGateField,
35889
- lowValueFilter: lowValueFilterField
35896
+ lowValueFilter: lowValueFilterField,
35897
+ defectFilter: defectFilterField
35890
35898
  };
35891
35899
  var DISTILL_PROCESS_FIELDS = {
35892
35900
  allowedTypes: allowedTypesField,
@@ -35973,7 +35981,7 @@ var ImproveProfileProcessesSchema = exports_external.object({
35973
35981
  });
35974
35982
  }
35975
35983
  for (const [name, process2] of Object.entries(val)) {
35976
- if (!(name in IMPROVE_PROCESS_ENGINE_CAPABILITIES) && !RETIRED_PROCESS_NAMES.has(name) && process2 !== null && typeof process2 === "object" && process2.enabled === true) {
35984
+ if (!IMPROVE_PROCESS_NAMES.includes(name) && !RETIRED_PROCESS_NAMES.has(name) && process2 !== null && typeof process2 === "object" && process2.enabled === true) {
35977
35985
  ctx.addIssue({
35978
35986
  code: exports_external.ZodIssueCode.custom,
35979
35987
  path: [name],
@@ -36399,13 +36407,27 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
36399
36407
  message: "engine does not name a configured engine"
36400
36408
  });
36401
36409
  }
36402
- const defaultLlm = config.defaults?.llmEngine;
36403
- if (defaultLlm && config.engines?.[defaultLlm]?.kind !== "llm") {
36404
- ctx.addIssue({
36405
- code: exports_external.ZodIssueCode.custom,
36406
- path: ["defaults", "llmEngine"],
36407
- message: "llmEngine must name an LLM engine"
36408
- });
36410
+ const confining = [...HARNESS_MODEL_WORK_IDS];
36411
+ const confiningPlatforms = `${confining.slice(0, -1).join(", ")} or ${confining.at(-1)}`;
36412
+ const modelWorkEngine = (name, path12) => {
36413
+ if (!name)
36414
+ return;
36415
+ const engine = config.engines?.[name];
36416
+ if (!engine) {
36417
+ ctx.addIssue({ code: exports_external.ZodIssueCode.custom, path: path12, message: "engine does not name a configured engine" });
36418
+ } else if (engine.kind !== "llm" && !HARNESS_MODEL_WORK_IDS.has(engine.platform)) {
36419
+ ctx.addIssue({
36420
+ code: exports_external.ZodIssueCode.custom,
36421
+ path: path12,
36422
+ 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}.`
36423
+ });
36424
+ }
36425
+ };
36426
+ modelWorkEngine(config.defaults?.llmEngine, ["defaults", "llmEngine"]);
36427
+ for (const [passName, pass] of Object.entries(config.index ?? {})) {
36428
+ const engine = pass?.engine;
36429
+ if (typeof engine === "string")
36430
+ modelWorkEngine(engine, ["index", passName, "engine"]);
36409
36431
  }
36410
36432
  const workflowJudge = config.workflow?.judgeEngine;
36411
36433
  if (workflowJudge && !config.engines?.[workflowJudge]) {
@@ -36424,64 +36446,24 @@ var AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
36424
36446
  });
36425
36447
  }
36426
36448
  for (const [strategyName, strategy] of Object.entries(config.improve?.strategies ?? {})) {
36427
- const strategyEngine = strategy.engine;
36428
- if (strategyEngine) {
36429
- const engine = config.engines?.[strategyEngine];
36430
- if (!engine || engine.kind !== "llm") {
36431
- ctx.addIssue({
36432
- code: exports_external.ZodIssueCode.custom,
36433
- path: ["improve", "strategies", strategyName, "engine"],
36434
- message: engine ? "strategy engine must be an LLM engine" : "engine does not name a configured engine"
36435
- });
36436
- }
36437
- }
36449
+ const strategyPath = ["improve", "strategies", strategyName];
36450
+ modelWorkEngine(strategy.engine, [...strategyPath, "engine"]);
36438
36451
  for (const [processName, process2] of Object.entries(strategy.processes ?? {})) {
36439
36452
  const processConfig = process2;
36440
- const capability = IMPROVE_PROCESS_ENGINE_CAPABILITIES[processName];
36441
- if (processConfig.engine && capability === null) {
36453
+ const processPath = [...strategyPath, "processes", processName];
36454
+ if (processConfig.engine && !IMPROVE_ENGINE_PROCESSES.includes(processName)) {
36442
36455
  ctx.addIssue({
36443
36456
  code: exports_external.ZodIssueCode.custom,
36444
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
36457
+ path: [...processPath, "engine"],
36445
36458
  message: `${processName} does not dispatch an engine`
36446
36459
  });
36447
36460
  } else {
36448
- const processEngine = processConfig.engine ?? strategyEngine;
36449
- if (processEngine && capability === "llm") {
36450
- const engine = config.engines?.[processEngine];
36451
- if (!engine || engine.kind !== "llm") {
36452
- ctx.addIssue({
36453
- code: exports_external.ZodIssueCode.custom,
36454
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
36455
- message: engine ? `${processName} requires an LLM engine` : "engine does not name a configured engine"
36456
- });
36457
- }
36458
- } else if (processConfig.engine && capability === "runner" && !config.engines?.[processConfig.engine]) {
36459
- ctx.addIssue({
36460
- code: exports_external.ZodIssueCode.custom,
36461
- path: ["improve", "strategies", strategyName, "processes", processName, "engine"],
36462
- message: "engine does not name a configured engine"
36463
- });
36464
- }
36461
+ modelWorkEngine(processConfig.engine, [...processPath, "engine"]);
36465
36462
  }
36466
- const judgmentEngine = processConfig.judgment?.engine;
36467
- if (processConfig.judgment?.enabled === true && judgmentEngine) {
36468
- const engine = config.engines?.[judgmentEngine];
36469
- if (!engine) {
36470
- ctx.addIssue({
36471
- code: exports_external.ZodIssueCode.custom,
36472
- path: ["improve", "strategies", strategyName, "processes", processName, "judgment", "engine"],
36473
- message: "engine does not name a configured engine"
36474
- });
36475
- }
36476
- }
36477
- const gateEngine = processConfig.qualityGate?.engine;
36478
- if (gateEngine && config.engines?.[gateEngine]?.kind !== "llm") {
36479
- ctx.addIssue({
36480
- code: exports_external.ZodIssueCode.custom,
36481
- path: ["improve", "strategies", strategyName, "processes", processName, "qualityGate", "engine"],
36482
- message: config.engines?.[gateEngine] ? "a quality-gate judge must be an LLM engine" : "engine does not name a configured engine"
36483
- });
36463
+ if (processConfig.judgment?.enabled === true) {
36464
+ modelWorkEngine(processConfig.judgment.engine, [...processPath, "judgment", "engine"]);
36484
36465
  }
36466
+ modelWorkEngine(processConfig.qualityGate?.engine, [...processPath, "qualityGate", "engine"]);
36485
36467
  }
36486
36468
  }
36487
36469
  if (config.defaultWriteTarget !== undefined) {
@@ -37634,6 +37616,10 @@ var ENV_PASSTHROUGH_REDACTION_POLICY = {
37634
37616
  OPENCODE_CONFIG: "path",
37635
37617
  CLAUDE_CONFIG: "path",
37636
37618
  CODEX_CONFIG: "path",
37619
+ XDG_CONFIG_HOME: "path",
37620
+ XDG_DATA_HOME: "path",
37621
+ XDG_CACHE_HOME: "path",
37622
+ XDG_STATE_HOME: "path",
37637
37623
  AWS_PROFILE: "identifier",
37638
37624
  AWS_REGION: "identifier",
37639
37625
  LLM_MODEL: "identifier",
@@ -39686,6 +39672,7 @@ import { createHash as createHash3 } from "node:crypto";
39686
39672
 
39687
39673
  // src/execution/source.ts
39688
39674
  var EXECUTION_SOURCE_SCHEMA_VERSION = 1;
39675
+ var MODEL_WORK_POLICY_ID = "model-work";
39689
39676
  function requireRecord(value, path18) {
39690
39677
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
39691
39678
  throw new TypeError(`${path18} must be an object`);
@@ -50946,6 +50933,17 @@ class BaseHarness {
50946
50933
  function resolveDispatchModel(request, _profile, _platform) {
50947
50934
  return request.model;
50948
50935
  }
50936
+ function modelFromArgs(args) {
50937
+ let model;
50938
+ for (let index = 0;index < args.length; index += 1) {
50939
+ const arg = args[index];
50940
+ if (arg === "--model")
50941
+ model = args[index + 1];
50942
+ else if (arg?.startsWith("--model="))
50943
+ model = arg.slice("--model=".length);
50944
+ }
50945
+ return model;
50946
+ }
50949
50947
  function normalizeTools(tools) {
50950
50948
  if (typeof tools === "string")
50951
50949
  return tools;
@@ -50954,6 +50952,14 @@ function normalizeTools(tools) {
50954
50952
  return JSON.stringify(tools);
50955
50953
  }
50956
50954
 
50955
+ // src/core/structured.ts
50956
+ function withSchemaInstruction(prompt, schema) {
50957
+ return `${prompt}
50958
+
50959
+ Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
50960
+ ${JSON.stringify(schema)}`;
50961
+ }
50962
+
50957
50963
  // src/integrations/agent/conversation-fallback.ts
50958
50964
  var CONVERSATION_FALLBACK_BEGIN = "<AKM_CONVERSATION_JSON>";
50959
50965
  var CONVERSATION_FALLBACK_END = "</AKM_CONVERSATION_JSON>";
@@ -51036,6 +51042,7 @@ function extensionFields(request) {
51036
51042
  function createAgentRequestLowerer(options) {
51037
51043
  const supportedInference = new Set(options.inference ?? []);
51038
51044
  return (_profile, request) => {
51045
+ const modelWork = request.authorization.policy?.id === MODEL_WORK_POLICY_ID;
51039
51046
  const notices = [];
51040
51047
  const skip = (field) => {
51041
51048
  notices.push(untranslated(options.adapter, field));
@@ -51066,24 +51073,29 @@ function createAgentRequestLowerer(options) {
51066
51073
  }
51067
51074
  dispatch.agent = request.agent;
51068
51075
  }
51076
+ if (request.outputSchema) {
51077
+ prompt = withSchemaInstruction(prompt, request.outputSchema);
51078
+ dispatch.schema = request.outputSchema;
51079
+ }
51069
51080
  dispatch.prompt = prompt;
51070
51081
  if (request.model)
51071
51082
  dispatch.model = request.model.resolved;
51072
51083
  if (Object.hasOwn(request, "inference")) {
51073
51084
  dispatch.inference = request.inference ?? null;
51074
51085
  for (const key of Object.keys(request.inference ?? {}).sort()) {
51075
- if (!supportedInference.has(key))
51086
+ if (!(modelWork && supportedInference.has(key)))
51076
51087
  skip(`inference.${key}`);
51077
51088
  }
51078
- if (typeof request.inference?.effort === "string")
51079
- dispatch.effort = request.inference.effort;
51080
- }
51081
- if (request.outputSchema) {
51082
- if (!options.outputSchema)
51083
- skip("outputSchema");
51084
- dispatch.schema = request.outputSchema;
51085
51089
  }
51086
- if (request.tools !== undefined) {
51090
+ if (modelWork) {
51091
+ if (!HARNESS_MODEL_WORK_IDS.has(options.adapter)) {
51092
+ throw new ConfigError(`The ${options.adapter} transport cannot enforce the model-work tool policy.`, "INVALID_CONFIG_FILE");
51093
+ }
51094
+ if (dispatch.agent) {
51095
+ throw new ConfigError(`The ${options.adapter} transport cannot run native agent ${JSON.stringify(dispatch.agent)} under the model-work tool policy.`, "INVALID_CONFIG_FILE");
51096
+ }
51097
+ dispatch.modelWork = true;
51098
+ } else if (request.tools !== undefined) {
51087
51099
  if (hasToolSelection(request.tools) && !translatesTools(options.tools, request.tools)) {
51088
51100
  throw new ConfigError(`The ${options.adapter} transport cannot enforce the resolved tool policy.`, "INVALID_CONFIG_FILE");
51089
51101
  }
@@ -51105,10 +51117,6 @@ function buildMessagePayload(req) {
51105
51117
  if (req.systemPrompt)
51106
51118
  sections.push(req.systemPrompt);
51107
51119
  sections.push(req.prompt);
51108
- if (req.schema) {
51109
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51110
- ${JSON.stringify(req.schema)}`);
51111
- }
51112
51120
  return sections.join(`
51113
51121
 
51114
51122
  `);
@@ -51119,8 +51127,7 @@ var aiderBuilder = {
51119
51127
  lower: createAgentRequestLowerer({
51120
51128
  adapter: AIDER_PLATFORM,
51121
51129
  personaChannel: "prompt",
51122
- tools: "none",
51123
- outputSchema: true
51130
+ tools: "none"
51124
51131
  }),
51125
51132
  build(profile, req) {
51126
51133
  const args = [...profile.args];
@@ -51170,8 +51177,6 @@ class AiderHarness extends BaseHarness {
51170
51177
  displayName = "Aider";
51171
51178
  agentBuilder = aiderBuilder;
51172
51179
  resultExtractor = aiderResultExtractor;
51173
- pattern = "local-runner";
51174
- structuredOutput = "none";
51175
51180
  capabilities = caps({
51176
51181
  agentDispatch: true,
51177
51182
  detection: true
@@ -51194,10 +51199,6 @@ function buildPromptPayload(req) {
51194
51199
  if (req.systemPrompt)
51195
51200
  sections.push(req.systemPrompt);
51196
51201
  sections.push(req.prompt);
51197
- if (req.schema) {
51198
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51199
- ${JSON.stringify(req.schema)}`);
51200
- }
51201
51202
  return sections.join(`
51202
51203
 
51203
51204
  `);
@@ -51208,8 +51209,7 @@ var amazonqBuilder = {
51208
51209
  lower: createAgentRequestLowerer({
51209
51210
  adapter: AMAZONQ_PLATFORM,
51210
51211
  personaChannel: "prompt",
51211
- tools: "flat",
51212
- outputSchema: true
51212
+ tools: "flat"
51213
51213
  }),
51214
51214
  build(profile, req) {
51215
51215
  const extra = profile.args[0] === "chat" ? profile.args.slice(1) : [...profile.args];
@@ -51266,8 +51266,6 @@ class AmazonqHarness extends BaseHarness {
51266
51266
  displayName = "Amazon Q Developer CLI";
51267
51267
  agentBuilder = amazonqBuilder;
51268
51268
  resultExtractor = amazonqResultExtractor;
51269
- pattern = "local-runner";
51270
- structuredOutput = "none";
51271
51269
  capabilities = caps({
51272
51270
  agentDispatch: true,
51273
51271
  detection: true
@@ -51275,14 +51273,16 @@ class AmazonqHarness extends BaseHarness {
51275
51273
  }
51276
51274
 
51277
51275
  // src/integrations/harnesses/claude/agent-builder.ts
51278
- function buildPromptPayload2(req) {
51279
- if (!req.schema)
51280
- return req.prompt;
51281
- return `${req.prompt}
51282
-
51283
- Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51284
- ${JSON.stringify(req.schema)}`;
51285
- }
51276
+ var MODEL_WORK_CLAUDE_FLAGS = Object.freeze([
51277
+ "--restricted",
51278
+ "--strict-mcp-config",
51279
+ "--tools",
51280
+ "Read,Edit,Bash",
51281
+ "--allowedTools",
51282
+ "Read,Edit,Bash(akm search *),Bash(akm show *)",
51283
+ "--permission-mode",
51284
+ "dontAsk"
51285
+ ]);
51286
51286
  var claudeBuilder = {
51287
51287
  platform: "claude",
51288
51288
  personaChannel: "native",
@@ -51290,11 +51290,11 @@ var claudeBuilder = {
51290
51290
  adapter: "claude",
51291
51291
  personaChannel: "native",
51292
51292
  nativeAgentSelector: true,
51293
- tools: "all",
51294
- outputSchema: true
51293
+ tools: "all"
51295
51294
  }),
51296
51295
  build(profile, req) {
51297
- const args = [...profile.args];
51296
+ const modelWork = req.modelWork === true;
51297
+ const args = modelWork ? [...MODEL_WORK_CLAUDE_FLAGS] : [...profile.args];
51298
51298
  if (req.agent) {
51299
51299
  args.push("--agent", req.agent);
51300
51300
  }
@@ -51304,6 +51304,10 @@ var claudeBuilder = {
51304
51304
  if (req.model) {
51305
51305
  const resolved = resolveDispatchModel(req, profile, "claude");
51306
51306
  args.push("--model", resolved);
51307
+ } else if (modelWork) {
51308
+ const model = modelFromArgs(profile.args);
51309
+ if (model)
51310
+ args.push("--model", model);
51307
51311
  }
51308
51312
  if (req.tools) {
51309
51313
  args.push("--allowedTools", normalizeTools(req.tools));
@@ -51313,7 +51317,7 @@ var claudeBuilder = {
51313
51317
  }
51314
51318
  args.push("--print");
51315
51319
  args.push("--");
51316
- args.push(buildPromptPayload2(req));
51320
+ args.push(req.prompt);
51317
51321
  return { argv: [profile.bin, ...args] };
51318
51322
  }
51319
51323
  };
@@ -51648,8 +51652,6 @@ class ClaudeHarness extends BaseHarness {
51648
51652
  setupDetectionDir = ".claude";
51649
51653
  agentBuilder = claudeBuilder;
51650
51654
  resultExtractor = claudeResultExtractor;
51651
- pattern = "in-harness";
51652
- structuredOutput = "native-json";
51653
51655
  identityEnv = ["CLAUDE_SESSION_ID"];
51654
51656
  sessionLogProvider = () => new ClaudeCodeProvider;
51655
51657
  capabilities = caps({
@@ -51684,8 +51686,7 @@ var codexBuilder = {
51684
51686
  lower: createAgentRequestLowerer({
51685
51687
  adapter: "codex",
51686
51688
  personaChannel: "prompt",
51687
- tools: "none",
51688
- outputSchema: true
51689
+ tools: "none"
51689
51690
  }),
51690
51691
  build(profile, req) {
51691
51692
  const extra = profile.args[0] === "exec" ? profile.args.slice(1) : [...profile.args];
@@ -51772,8 +51773,6 @@ class CodexHarness extends BaseHarness {
51772
51773
  displayName = "OpenAI Codex CLI";
51773
51774
  agentBuilder = codexBuilder;
51774
51775
  resultExtractor = codexResultExtractor;
51775
- pattern = "local-runner";
51776
- structuredOutput = "native-schema";
51777
51776
  presenceEnv = ["CODEX_SANDBOX"];
51778
51777
  capabilities = caps({
51779
51778
  agentDispatch: true,
@@ -51792,15 +51791,11 @@ function toolPolicyEntries2(tools) {
51792
51791
  }
51793
51792
  return;
51794
51793
  }
51795
- function buildPromptPayload3(req) {
51794
+ function buildPromptPayload2(req) {
51796
51795
  const sections = [];
51797
51796
  if (req.systemPrompt)
51798
51797
  sections.push(req.systemPrompt);
51799
51798
  sections.push(req.prompt);
51800
- if (req.schema) {
51801
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51802
- ${JSON.stringify(req.schema)}`);
51803
- }
51804
51799
  return sections.join(`
51805
51800
 
51806
51801
  `);
@@ -51811,8 +51806,7 @@ var copilotBuilder = {
51811
51806
  lower: createAgentRequestLowerer({
51812
51807
  adapter: COPILOT_PLATFORM,
51813
51808
  personaChannel: "prompt",
51814
- tools: "flat",
51815
- outputSchema: true
51809
+ tools: "flat"
51816
51810
  }),
51817
51811
  build(profile, req) {
51818
51812
  const args = [...profile.args];
@@ -51831,7 +51825,7 @@ var copilotBuilder = {
51831
51825
  if (req.schema) {
51832
51826
  args.push("--output-format", "json");
51833
51827
  }
51834
- args.push("-p", buildPromptPayload3(req));
51828
+ args.push("-p", buildPromptPayload2(req));
51835
51829
  return { argv: [profile.bin, ...args] };
51836
51830
  }
51837
51831
  };
@@ -51929,8 +51923,6 @@ class CopilotHarness extends BaseHarness {
51929
51923
  displayName = "GitHub Copilot CLI";
51930
51924
  agentBuilder = copilotBuilder;
51931
51925
  resultExtractor = copilotResultExtractor;
51932
- pattern = "local-runner";
51933
- structuredOutput = "native-json";
51934
51926
  identityEnv = ["COPILOT_SESSION_ID"];
51935
51927
  capabilities = caps({
51936
51928
  agentDispatch: true,
@@ -51949,15 +51941,11 @@ function toolPolicyEntries3(tools) {
51949
51941
  }
51950
51942
  return;
51951
51943
  }
51952
- function buildPromptPayload4(req) {
51944
+ function buildPromptPayload3(req) {
51953
51945
  const sections = [];
51954
51946
  if (req.systemPrompt)
51955
51947
  sections.push(req.systemPrompt);
51956
51948
  sections.push(req.prompt);
51957
- if (req.schema) {
51958
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
51959
- ${JSON.stringify(req.schema)}`);
51960
- }
51961
51949
  return sections.join(`
51962
51950
 
51963
51951
  `);
@@ -51968,8 +51956,7 @@ var geminiBuilder = {
51968
51956
  lower: createAgentRequestLowerer({
51969
51957
  adapter: GEMINI_PLATFORM,
51970
51958
  personaChannel: "prompt",
51971
- tools: "flat",
51972
- outputSchema: true
51959
+ tools: "flat"
51973
51960
  }),
51974
51961
  build(profile, req) {
51975
51962
  const args = [...profile.args];
@@ -51985,7 +51972,7 @@ var geminiBuilder = {
51985
51972
  if (req.schema) {
51986
51973
  args.push("--output-format", "json");
51987
51974
  }
51988
- args.push("-p", buildPromptPayload4(req));
51975
+ args.push("-p", buildPromptPayload3(req));
51989
51976
  return { argv: [profile.bin, ...args] };
51990
51977
  }
51991
51978
  };
@@ -52076,8 +52063,6 @@ class GeminiHarness extends BaseHarness {
52076
52063
  displayName = "Gemini CLI";
52077
52064
  agentBuilder = geminiBuilder;
52078
52065
  resultExtractor = geminiResultExtractor;
52079
- pattern = "local-runner";
52080
- structuredOutput = "native-json";
52081
52066
  presenceEnv = ["GEMINI_CLI"];
52082
52067
  capabilities = caps({
52083
52068
  agentDispatch: true,
@@ -52085,18 +52070,124 @@ class GeminiHarness extends BaseHarness {
52085
52070
  });
52086
52071
  }
52087
52072
 
52073
+ // src/integrations/harnesses/opencode/model-config.ts
52074
+ var MODEL_WORK_AGENT_INFERENCE = ["temperature", "reasoningEffort", "enableThinking"];
52075
+ var isPositiveInteger = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
52076
+ function opencodeInferenceConfig(inference, modelWork) {
52077
+ const { temperature, reasoningEffort, enableThinking, maxTokens, contextLength } = inference ?? {};
52078
+ const options = {};
52079
+ if (typeof temperature === "number" && Number.isFinite(temperature))
52080
+ options.temperature = temperature;
52081
+ if (typeof reasoningEffort === "string" && reasoningEffort.length > 0)
52082
+ options.reasoningEffort = reasoningEffort;
52083
+ if (typeof enableThinking === "boolean") {
52084
+ options.chat_template_kwargs = { enable_thinking: enableThinking };
52085
+ options.enable_thinking = enableThinking;
52086
+ }
52087
+ const hasOptions = Object.keys(options).length > 0;
52088
+ return {
52089
+ entry: {
52090
+ ...hasOptions && !modelWork ? { options } : {},
52091
+ ...isPositiveInteger(maxTokens) && isPositiveInteger(contextLength) ? { limit: { context: contextLength, output: maxTokens } } : {}
52092
+ },
52093
+ ...hasOptions && modelWork ? { agentOptions: options } : {}
52094
+ };
52095
+ }
52096
+
52097
+ // src/integrations/harnesses/opencode/model-work-agent.ts
52098
+ import path43 from "node:path";
52099
+ var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52100
+ 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.";
52101
+ function modelWorkPermission(stash) {
52102
+ return {
52103
+ "*": "deny",
52104
+ read: "allow",
52105
+ grep: "allow",
52106
+ glob: "allow",
52107
+ edit: { "*": "allow", ...stash ? { [`${stash.slice(1)}/*`]: "deny" } : {} },
52108
+ external_directory: {
52109
+ ...stash ? { [`${stash}/*`]: "allow" } : {},
52110
+ "~/.local/share/opencode/tool-output/*": "deny"
52111
+ },
52112
+ akm_search: "allow",
52113
+ akm_show: "allow",
52114
+ akm_feedback: "deny",
52115
+ akm_remember: "deny",
52116
+ akm_curate: "deny",
52117
+ bash: "deny",
52118
+ doom_loop: "deny",
52119
+ list: "deny",
52120
+ lsp: "deny",
52121
+ question: "deny",
52122
+ skill: "deny",
52123
+ task: "deny",
52124
+ todowrite: "deny",
52125
+ webfetch: "deny",
52126
+ websearch: "deny"
52127
+ };
52128
+ }
52129
+ function modelWorkPluginEnv() {
52130
+ return {
52131
+ AKM_AUTO_CURATE: "0",
52132
+ AKM_AUTO_LEARNING: "0",
52133
+ AKM_AUTO_SKILL_PROPOSALS: "0",
52134
+ AKM_WRITE_GATE: "off",
52135
+ XDG_STATE_HOME: path43.join(getStateDir(), "opencode-model-work"),
52136
+ ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52137
+ };
52138
+ }
52139
+ function modelWorkOpencodeConfig(options) {
52140
+ let stash;
52141
+ try {
52142
+ stash = resolveStashDir();
52143
+ } catch {}
52144
+ const permission = modelWorkPermission(stash);
52145
+ return {
52146
+ permission: { ...permission },
52147
+ compaction: { auto: false },
52148
+ agent: {
52149
+ [MODEL_WORK_OPENCODE_AGENT]: {
52150
+ mode: "primary",
52151
+ description: "akm unattended model work: read and edit inside its working directory only.",
52152
+ prompt: MODEL_WORK_PROMPT,
52153
+ ...options ? { options } : {},
52154
+ permission: { ...permission }
52155
+ }
52156
+ }
52157
+ };
52158
+ }
52159
+
52088
52160
  // src/integrations/harnesses/opencode/agent-builder.ts
52089
52161
  var opencodeBuilder = {
52090
52162
  platform: "opencode",
52091
- personaChannel: "native",
52163
+ personaChannel: "prompt",
52092
52164
  lower: createAgentRequestLowerer({
52093
52165
  adapter: "opencode",
52094
- personaChannel: "native",
52166
+ personaChannel: "prompt",
52095
52167
  nativeAgentSelector: true,
52096
52168
  tools: "none",
52097
- outputSchema: false
52169
+ inference: MODEL_WORK_AGENT_INFERENCE
52098
52170
  }),
52099
52171
  build(profile, req) {
52172
+ if (req.modelWork) {
52173
+ const model = req.model ?? modelFromArgs(profile.args);
52174
+ const { agentOptions } = opencodeInferenceConfig(req.inference, true);
52175
+ return {
52176
+ argv: [
52177
+ profile.bin,
52178
+ "run",
52179
+ "--agent",
52180
+ MODEL_WORK_OPENCODE_AGENT,
52181
+ ...model ? ["--model", model] : [],
52182
+ "--",
52183
+ req.prompt
52184
+ ],
52185
+ env: {
52186
+ ...modelWorkPluginEnv(),
52187
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(modelWorkOpencodeConfig(agentOptions))
52188
+ }
52189
+ };
52190
+ }
52100
52191
  const args = req.model ? [] : [...profile.args];
52101
52192
  if (req.model) {
52102
52193
  for (let index = 0;index < profile.args.length; index += 1) {
@@ -52110,9 +52201,6 @@ var opencodeBuilder = {
52110
52201
  }
52111
52202
  }
52112
52203
  }
52113
- if (req.systemPrompt) {
52114
- args.push("--system-prompt", req.systemPrompt);
52115
- }
52116
52204
  if (req.agent) {
52117
52205
  args.push("--agent", req.agent);
52118
52206
  }
@@ -52129,13 +52217,13 @@ var opencodeBuilder = {
52129
52217
  // src/integrations/harnesses/opencode/session-log.ts
52130
52218
  import fs37 from "node:fs";
52131
52219
  import os6 from "node:os";
52132
- import path44 from "node:path";
52220
+ import path45 from "node:path";
52133
52221
 
52134
52222
  // src/storage/sqlite-read-snapshot.ts
52135
52223
  import { spawnSync as spawnSync5 } from "node:child_process";
52136
52224
  import fs36 from "node:fs";
52137
52225
  import os5 from "node:os";
52138
- import path43 from "node:path";
52226
+ import path44 from "node:path";
52139
52227
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52140
52228
  var SNAPSHOT_BACKOFF_MS = 25;
52141
52229
 
@@ -52200,8 +52288,8 @@ function copyFileOutsideThisProcess(source, destination) {
52200
52288
  function openSqliteReadSnapshot(dbPath) {
52201
52289
  if (!pathExists(dbPath))
52202
52290
  return;
52203
- const snapshotDir = fs36.mkdtempSync(path43.join(os5.tmpdir(), "akm-sqlite-read-"));
52204
- const snapshotPath = path43.join(snapshotDir, "snapshot.db");
52291
+ const snapshotDir = fs36.mkdtempSync(path44.join(os5.tmpdir(), "akm-sqlite-read-"));
52292
+ const snapshotPath = path44.join(snapshotDir, "snapshot.db");
52205
52293
  let db;
52206
52294
  try {
52207
52295
  let copied = false;
@@ -52271,9 +52359,9 @@ function openSqliteReadSnapshot(dbPath) {
52271
52359
  // src/integrations/harnesses/opencode/session-log.ts
52272
52360
  function getOpenCodeBaseDir() {
52273
52361
  if (process.platform === "darwin") {
52274
- return path44.join(os6.homedir(), "Library", "Application Support", "opencode");
52362
+ return path45.join(os6.homedir(), "Library", "Application Support", "opencode");
52275
52363
  }
52276
- return path44.join(os6.homedir(), ".local", "share", "opencode");
52364
+ return path45.join(os6.homedir(), ".local", "share", "opencode");
52277
52365
  }
52278
52366
  var OPENCODE_DB_FILENAME = "opencode.db";
52279
52367
 
@@ -52284,7 +52372,7 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52284
52372
  return this.#dbPath(this.#baseDir);
52285
52373
  }
52286
52374
  #dbPath(base) {
52287
- return path44.join(base, OPENCODE_DB_FILENAME);
52375
+ return path45.join(base, OPENCODE_DB_FILENAME);
52288
52376
  }
52289
52377
  listSessions(input = {}) {
52290
52378
  const base = input.location ?? this.#baseDir;
@@ -52400,8 +52488,6 @@ class OpencodeHarness extends BaseHarness {
52400
52488
  displayName = "OpenCode";
52401
52489
  setupDetectionDir = ".config/opencode";
52402
52490
  agentBuilder = opencodeBuilder;
52403
- pattern = "local-runner";
52404
- structuredOutput = "none";
52405
52491
  identityEnv = ["OPENCODE_SESSION_ID"];
52406
52492
  sessionLogProvider = () => new OpenCodeProvider;
52407
52493
  capabilities = caps({
@@ -52416,8 +52502,6 @@ class OpencodeHarness extends BaseHarness {
52416
52502
  class OpencodeSdkHarness extends BaseHarness {
52417
52503
  id = "opencode-sdk";
52418
52504
  displayName = "OpenCode SDK";
52419
- pattern = "local-runner";
52420
- structuredOutput = "native-json";
52421
52505
  executionLowerer = {
52422
52506
  platform: "opencode-sdk",
52423
52507
  personaChannel: "native",
@@ -52426,7 +52510,7 @@ class OpencodeSdkHarness extends BaseHarness {
52426
52510
  personaChannel: "native",
52427
52511
  nativeAgentSelector: true,
52428
52512
  tools: "sdk",
52429
- outputSchema: false
52513
+ inference: MODEL_WORK_AGENT_INFERENCE
52430
52514
  })
52431
52515
  };
52432
52516
  capabilities = caps({
@@ -52443,10 +52527,6 @@ function buildTaskPayload(req) {
52443
52527
  if (req.systemPrompt)
52444
52528
  sections.push(req.systemPrompt);
52445
52529
  sections.push(req.prompt);
52446
- if (req.schema) {
52447
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
52448
- ${JSON.stringify(req.schema)}`);
52449
- }
52450
52530
  return sections.join(`
52451
52531
 
52452
52532
  `);
@@ -52457,8 +52537,7 @@ var openhandsBuilder = {
52457
52537
  lower: createAgentRequestLowerer({
52458
52538
  adapter: OPENHANDS_PLATFORM,
52459
52539
  personaChannel: "prompt",
52460
- tools: "none",
52461
- outputSchema: true
52540
+ tools: "none"
52462
52541
  }),
52463
52542
  build(profile, req) {
52464
52543
  const args = [...profile.args];
@@ -52542,8 +52621,6 @@ class OpenhandsHarness extends BaseHarness {
52542
52621
  displayName = "OpenHands";
52543
52622
  agentBuilder = openhandsBuilder;
52544
52623
  resultExtractor = openhandsResultExtractor;
52545
- pattern = "local-runner";
52546
- structuredOutput = "native-json";
52547
52624
  capabilities = caps({
52548
52625
  agentDispatch: true,
52549
52626
  detection: true
@@ -52552,24 +52629,13 @@ class OpenhandsHarness extends BaseHarness {
52552
52629
 
52553
52630
  // src/integrations/harnesses/pi/agent-builder.ts
52554
52631
  var PI_PLATFORM = "pi";
52555
- function buildPromptPayload5(req) {
52556
- const sections = [req.prompt];
52557
- if (req.schema) {
52558
- sections.push(`Respond with ONLY a JSON value matching this JSON Schema (no prose, no code fences):
52559
- ${JSON.stringify(req.schema)}`);
52560
- }
52561
- return sections.join(`
52562
-
52563
- `);
52564
- }
52565
52632
  var piBuilder = {
52566
52633
  platform: PI_PLATFORM,
52567
52634
  personaChannel: "native",
52568
52635
  lower: createAgentRequestLowerer({
52569
52636
  adapter: PI_PLATFORM,
52570
52637
  personaChannel: "native",
52571
- tools: "none",
52572
- outputSchema: true
52638
+ tools: "none"
52573
52639
  }),
52574
52640
  build(profile, req) {
52575
52641
  const args = [...profile.args];
@@ -52585,7 +52651,7 @@ var piBuilder = {
52585
52651
  }
52586
52652
  args.push("-p");
52587
52653
  args.push("--");
52588
- args.push(buildPromptPayload5(req));
52654
+ args.push(req.prompt);
52589
52655
  return { argv: [profile.bin, ...args] };
52590
52656
  }
52591
52657
  };
@@ -52687,8 +52753,6 @@ class PiHarness extends BaseHarness {
52687
52753
  displayName = "Pi";
52688
52754
  agentBuilder = piBuilder;
52689
52755
  resultExtractor = piResultExtractor;
52690
- pattern = "local-runner";
52691
- structuredOutput = "native-json";
52692
52756
  identityEnv = ["PI_SESSION_ID"];
52693
52757
  capabilities = caps({
52694
52758
  agentDispatch: true,
@@ -52734,6 +52798,12 @@ var COMMON_SPAWN_ENV_PASSTHROUGH = [
52734
52798
  "TMPDIR",
52735
52799
  "AKM_EVENT_SOURCE"
52736
52800
  ];
52801
+ var XDG_BASE_DIR_ENV_PASSTHROUGH = [
52802
+ "XDG_CONFIG_HOME",
52803
+ "XDG_DATA_HOME",
52804
+ "XDG_CACHE_HOME",
52805
+ "XDG_STATE_HOME"
52806
+ ];
52737
52807
  var supplementedPaths = new Map;
52738
52808
 
52739
52809
  // src/integrations/agent/profiles.ts
@@ -52744,7 +52814,7 @@ var BUILTINS = {
52744
52814
  bin: "opencode",
52745
52815
  args: ["run"],
52746
52816
  stdio: "interactive",
52747
- envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
52817
+ envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG", ...XDG_BASE_DIR_ENV_PASSTHROUGH],
52748
52818
  parseOutput: "text"
52749
52819
  },
52750
52820
  claude: {
@@ -52855,9 +52925,9 @@ var BUILTIN_STRATEGIES = {
52855
52925
  if (BUILTIN_IMPROVE_STRATEGY_NAMES.some((name) => !(name in BUILTIN_STRATEGIES))) {
52856
52926
  throw new Error("Built-in improve strategy names are out of sync with their assets");
52857
52927
  }
52928
+ var MODEL_CALLING_PROCESSES = new Set(IMPROVE_ENGINE_PROCESSES.filter((name) => name !== "triage"));
52858
52929
 
52859
52930
  // src/commands/improve/improve-usage-report.ts
52860
- var LLM_BACKED_PROCESSES = new Set(Object.keys(IMPROVE_PROCESS_ENGINE_CAPABILITIES).filter((name) => IMPROVE_PROCESS_ENGINE_CAPABILITIES[name] === "llm"));
52861
52931
  function renderFixedWidthTable(headers, rows) {
52862
52932
  const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
52863
52933
  const renderRow = (cells) => cells.map((cell, index) => cell.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
@@ -53218,7 +53288,7 @@ Commands:
53218
53288
 
53219
53289
  // scripts/akm-migrate/migrate/dead-residue.ts
53220
53290
  import fs38 from "node:fs";
53221
- import path45 from "node:path";
53291
+ import path46 from "node:path";
53222
53292
  var DEAD_RESIDUE_PATHS = [
53223
53293
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53224
53294
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53240,7 +53310,7 @@ function dirSizeBytes(target) {
53240
53310
  return 0;
53241
53311
  }
53242
53312
  for (const entry of entries) {
53243
- const entryPath = path45.join(target, entry.name);
53313
+ const entryPath = path46.join(target, entry.name);
53244
53314
  if (entry.isDirectory()) {
53245
53315
  total += dirSizeBytes(entryPath);
53246
53316
  } else if (entry.isFile()) {
@@ -53258,15 +53328,15 @@ function sizeOf(target) {
53258
53328
  function hostResidue() {
53259
53329
  const data = getDataDir();
53260
53330
  const state = getStateDir();
53261
- const configDir = path45.dirname(getConfigPath());
53331
+ const configDir = path46.dirname(getConfigPath());
53262
53332
  const named = [
53263
- { absolutePath: path45.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53264
- { absolutePath: path45.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53265
- { absolutePath: path45.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53266
- { absolutePath: path45.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53267
- { absolutePath: path45.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53268
- { absolutePath: path45.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53269
- { absolutePath: path45.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53333
+ { absolutePath: path46.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53334
+ { absolutePath: path46.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53335
+ { absolutePath: path46.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53336
+ { absolutePath: path46.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53337
+ { absolutePath: path46.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53338
+ { absolutePath: path46.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53339
+ { absolutePath: path46.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53270
53340
  ];
53271
53341
  const found = [];
53272
53342
  const claimed = new Set;
@@ -53301,7 +53371,7 @@ function findSidecars(root, depth, skip) {
53301
53371
  }
53302
53372
  const found = [];
53303
53373
  for (const entry of entries) {
53304
- const entryPath = path45.join(root, entry.name);
53374
+ const entryPath = path46.join(root, entry.name);
53305
53375
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53306
53376
  found.push(entryPath);
53307
53377
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53314,7 +53384,7 @@ function findDeadResidueEntries(stashDir) {
53314
53384
  const host = hostResidue();
53315
53385
  if (stashDir === undefined)
53316
53386
  return host;
53317
- const akmDir = path45.join(stashDir, ".akm");
53387
+ const akmDir = path46.join(stashDir, ".akm");
53318
53388
  let names;
53319
53389
  try {
53320
53390
  names = fs38.readdirSync(akmDir);
@@ -53327,14 +53397,14 @@ function findDeadResidueEntries(stashDir) {
53327
53397
  for (const name of matches) {
53328
53398
  if (!names.includes(name))
53329
53399
  continue;
53330
- const absolutePath = path45.join(akmDir, name);
53400
+ const absolutePath = path46.join(akmDir, name);
53331
53401
  let sizeBytes;
53332
53402
  try {
53333
53403
  sizeBytes = sizeOf(absolutePath);
53334
53404
  } catch {
53335
53405
  continue;
53336
53406
  }
53337
- found.push({ relativePath: path45.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53407
+ found.push({ relativePath: path46.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53338
53408
  }
53339
53409
  }
53340
53410
  return found;
@@ -53360,16 +53430,16 @@ function removeDeadResidue(stashDir) {
53360
53430
  import { randomUUID as randomUUID3 } from "node:crypto";
53361
53431
  import fs40 from "node:fs";
53362
53432
  import os7 from "node:os";
53363
- import path48 from "node:path";
53433
+ import path49 from "node:path";
53364
53434
 
53365
53435
  // scripts/akm-migrate/migrate/task-files.ts
53366
53436
  import crypto4 from "node:crypto";
53367
53437
  import fs39 from "node:fs";
53368
- import path47 from "node:path";
53438
+ import path48 from "node:path";
53369
53439
 
53370
53440
  // src/tasks/source/task-to-v4.ts
53371
53441
  import crypto3 from "node:crypto";
53372
- import path46 from "node:path";
53442
+ import path47 from "node:path";
53373
53443
 
53374
53444
  // src/tasks/task-id.ts
53375
53445
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54178,7 +54248,7 @@ function addSharedNonPromptOverrides(data, akm) {
54178
54248
  }
54179
54249
  function promptSourceKind(raw) {
54180
54250
  const trimmed = raw.trim();
54181
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path46.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54251
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path47.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54182
54252
  return "file";
54183
54253
  }
54184
54254
  try {
@@ -54282,7 +54352,7 @@ function planV2DataToV4(input, data) {
54282
54352
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54283
54353
  }
54284
54354
  try {
54285
- validateTaskId(path46.basename(input.filePath, ".yml"));
54355
+ validateTaskId(path47.basename(input.filePath, ".yml"));
54286
54356
  } catch (cause) {
54287
54357
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54288
54358
  }
@@ -54427,7 +54497,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54427
54497
  for (let index = 1;index < files.length; index += 1) {
54428
54498
  const previous = files[index - 1];
54429
54499
  const current = files[index];
54430
- if (previous && current && path46.resolve(previous.filePath) === path46.resolve(current.filePath)) {
54500
+ if (previous && current && path47.resolve(previous.filePath) === path47.resolve(current.filePath)) {
54431
54501
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54432
54502
  }
54433
54503
  }
@@ -54439,8 +54509,8 @@ function migrationError(detail) {
54439
54509
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54440
54510
  }
54441
54511
  function contained2(root, candidate) {
54442
- const relative = path47.relative(root, candidate);
54443
- return relative === "" || !relative.startsWith("..") && !path47.isAbsolute(relative);
54512
+ const relative = path48.relative(root, candidate);
54513
+ return relative === "" || !relative.startsWith("..") && !path48.isAbsolute(relative);
54444
54514
  }
54445
54515
  function realDirectory(filePath) {
54446
54516
  const stat = fs39.lstatSync(filePath);
@@ -54468,7 +54538,7 @@ function walkTasks(root, tasksDir, out) {
54468
54538
  throw migrationError(`${directory} resolves outside bundle ${root.bundleId}.`);
54469
54539
  }
54470
54540
  for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54471
- const candidate = path47.join(directory, entry.name);
54541
+ const candidate = path48.join(directory, entry.name);
54472
54542
  if (entry.isSymbolicLink())
54473
54543
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54474
54544
  if (entry.isDirectory()) {
@@ -54494,7 +54564,7 @@ function walkTasks(root, tasksDir, out) {
54494
54564
  function inspectTaskFiles(roots) {
54495
54565
  const files = [];
54496
54566
  for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54497
- const tasksDir = root.layout === "akm-task" ? root.root : path47.join(root.root, "tasks");
54567
+ const tasksDir = root.layout === "akm-task" ? root.root : path48.join(root.root, "tasks");
54498
54568
  try {
54499
54569
  const stat = fs39.lstatSync(tasksDir);
54500
54570
  if (stat.isSymbolicLink())
@@ -54514,8 +54584,8 @@ function planTaskFilesMigration(inputs) {
54514
54584
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54515
54585
  }
54516
54586
  function taskFileBackupPath(backupRoot, filePath) {
54517
- const digest = crypto4.createHash("sha256").update(path47.resolve(filePath)).digest("hex").slice(0, 16);
54518
- return path47.join(backupRoot, "files", `${digest}-${path47.basename(filePath)}`);
54587
+ const digest = crypto4.createHash("sha256").update(path48.resolve(filePath)).digest("hex").slice(0, 16);
54588
+ return path48.join(backupRoot, "files", `${digest}-${path48.basename(filePath)}`);
54519
54589
  }
54520
54590
  function fsyncDirectory(directory) {
54521
54591
  if (process.platform === "win32")
@@ -54534,7 +54604,7 @@ function fsyncDirectory(directory) {
54534
54604
  }
54535
54605
  }
54536
54606
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54537
- fs39.mkdirSync(path47.dirname(filePath), { recursive: true });
54607
+ fs39.mkdirSync(path48.dirname(filePath), { recursive: true });
54538
54608
  const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54539
54609
  try {
54540
54610
  fs39.writeFileSync(fd, bytes);
@@ -54543,14 +54613,14 @@ function writeDurable(filePath, bytes, mode, exclusive = false) {
54543
54613
  fs39.closeSync(fd);
54544
54614
  }
54545
54615
  fs39.chmodSync(filePath, mode);
54546
- fsyncDirectory(path47.dirname(filePath));
54616
+ fsyncDirectory(path48.dirname(filePath));
54547
54617
  }
54548
54618
  function replaceAtomically(filePath, bytes, mode) {
54549
- const temporary = path47.join(path47.dirname(filePath), `.${path47.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54619
+ const temporary = path48.join(path48.dirname(filePath), `.${path48.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54550
54620
  try {
54551
54621
  writeDurable(temporary, bytes, mode, true);
54552
54622
  fs39.renameSync(temporary, filePath);
54553
- fsyncDirectory(path47.dirname(filePath));
54623
+ fsyncDirectory(path48.dirname(filePath));
54554
54624
  } finally {
54555
54625
  fs39.rmSync(temporary, { force: true });
54556
54626
  }
@@ -54587,7 +54657,7 @@ function expandTilde(value) {
54587
54657
  if (value === "~")
54588
54658
  return os7.homedir();
54589
54659
  if (value.startsWith("~/") || value.startsWith("~\\"))
54590
- return path48.join(os7.homedir(), value.slice(2));
54660
+ return path49.join(os7.homedir(), value.slice(2));
54591
54661
  return value;
54592
54662
  }
54593
54663
  function existingDirectory(target) {
@@ -54613,14 +54683,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54613
54683
  const source = sources.get(bundleId);
54614
54684
  if (!source)
54615
54685
  continue;
54616
- const configuredRoot = source.type === "filesystem" && source.path ? path48.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54686
+ const configuredRoot = source.type === "filesystem" && source.path ? path49.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54617
54687
  if (!configuredRoot || !existingDirectory(configuredRoot))
54618
54688
  continue;
54619
- const bundleRoot = path48.resolve(configuredRoot);
54689
+ const bundleRoot = path49.resolve(configuredRoot);
54620
54690
  const component = bundleComponentConfig(bundle);
54621
- const componentRoot = path48.resolve(bundleRoot, component?.root ?? ".");
54622
- const relative = path48.relative(bundleRoot, componentRoot);
54623
- if (relative === ".." || relative.startsWith(`..${path48.sep}`) || path48.isAbsolute(relative)) {
54691
+ const componentRoot = path49.resolve(bundleRoot, component?.root ?? ".");
54692
+ const relative = path49.relative(bundleRoot, componentRoot);
54693
+ if (relative === ".." || relative.startsWith(`..${path49.sep}`) || path49.isAbsolute(relative)) {
54624
54694
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54625
54695
  }
54626
54696
  if (!existingDirectory(componentRoot))
@@ -54637,7 +54707,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54637
54707
  }
54638
54708
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54639
54709
  if (envStash && existingDirectory(envStash)) {
54640
- const stashRoot = path48.resolve(envStash);
54710
+ const stashRoot = path49.resolve(envStash);
54641
54711
  if (!rootsByPath.has(stashRoot)) {
54642
54712
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54643
54713
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54706,7 +54776,7 @@ function applyTaskFilesMigration() {
54706
54776
  const before = inspectCurrent();
54707
54777
  if (before.result.taskFiles.changed === 0)
54708
54778
  return before.result;
54709
- const backupPath = path48.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54779
+ const backupPath = path49.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54710
54780
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54711
54781
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54712
54782
  });