akm-cli 0.9.0-rc.1 → 0.9.0-rc.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 (228) hide show
  1. package/CHANGELOG.md +223 -9
  2. package/SECURITY.md +23 -24
  3. package/dist/assets/help/help-improve.md +10 -10
  4. package/dist/assets/hints/cli-hints-full.md +44 -10
  5. package/dist/assets/hints/cli-hints-short.md +6 -2
  6. package/dist/assets/{profiles → improve-strategies}/default.json +1 -0
  7. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +1 -1
  8. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +2 -3
  9. package/dist/assets/{profiles → improve-strategies}/reflect-distill.json +3 -4
  10. package/dist/assets/stash-skeleton/README.md +28 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +6 -0
  12. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +6 -0
  13. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +12 -1
  14. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +11 -1
  15. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +9 -0
  17. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +7 -0
  18. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +7 -0
  19. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +6 -0
  20. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +98 -0
  21. package/dist/assets/stash-skeleton/facts/conventions/domains.md +63 -0
  22. package/dist/assets/stash-skeleton/facts/conventions/organization.md +127 -0
  23. package/dist/assets/tasks/core/backup.yml +1 -0
  24. package/dist/assets/tasks/core/extract.yml +1 -0
  25. package/dist/assets/tasks/core/improve.yml +1 -0
  26. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  27. package/dist/assets/tasks/core/sync.yml +1 -0
  28. package/dist/assets/tasks/core/version-check.yml +1 -0
  29. package/dist/assets/tasks/graph-refresh-weekly.yml +4 -4
  30. package/dist/assets/templates/html/health.html +5 -1
  31. package/dist/cli/config-migrate.js +31 -138
  32. package/dist/cli/config-validate.js +10 -8
  33. package/dist/cli.js +48 -14
  34. package/dist/commands/agent/agent-dispatch.js +17 -16
  35. package/dist/commands/agent/agent-support.js +0 -24
  36. package/dist/commands/agent/contribute-cli.js +5 -15
  37. package/dist/commands/backup-cli.js +54 -0
  38. package/dist/commands/config-cli.js +45 -159
  39. package/dist/commands/env/secret.js +8 -5
  40. package/dist/commands/health/checks.js +130 -83
  41. package/dist/commands/health/html-report.js +4 -0
  42. package/dist/commands/health/improve-metrics.js +30 -32
  43. package/dist/commands/health/llm-usage.js +19 -19
  44. package/dist/commands/health/md-report.js +4 -0
  45. package/dist/commands/health/metrics.js +2 -1
  46. package/dist/commands/health/surfaces.js +5 -4
  47. package/dist/commands/health.js +1 -1
  48. package/dist/commands/improve/consolidate/chunking.js +2 -2
  49. package/dist/commands/improve/consolidate.js +28 -25
  50. package/dist/commands/improve/distill/promote-memory.js +5 -12
  51. package/dist/commands/improve/distill/quality-gate.js +5 -7
  52. package/dist/commands/improve/distill.js +16 -5
  53. package/dist/commands/improve/eligibility.js +22 -12
  54. package/dist/commands/improve/extract-cli.js +47 -19
  55. package/dist/commands/improve/extract.js +110 -62
  56. package/dist/commands/improve/improve-cli.js +38 -16
  57. package/dist/commands/improve/improve-result-file.js +30 -24
  58. package/dist/commands/improve/improve-strategies.js +137 -0
  59. package/dist/commands/improve/improve.js +60 -30
  60. package/dist/commands/improve/locks.js +66 -45
  61. package/dist/commands/improve/loop-stages.js +75 -33
  62. package/dist/commands/improve/memory/memory-belief.js +79 -7
  63. package/dist/commands/improve/memory/memory-contradiction-detect.js +12 -4
  64. package/dist/commands/improve/preparation.js +71 -73
  65. package/dist/commands/improve/procedural.js +3 -2
  66. package/dist/commands/improve/recombine.js +2 -1
  67. package/dist/commands/improve/reflect.js +119 -214
  68. package/dist/commands/improve/shared.js +11 -5
  69. package/dist/commands/lint/base-linter.js +152 -42
  70. package/dist/commands/mv-cli.js +809 -0
  71. package/dist/commands/proposal/proposal-cli.js +18 -8
  72. package/dist/commands/proposal/propose.js +64 -69
  73. package/dist/commands/read/knowledge.js +436 -4
  74. package/dist/commands/read/remember-cli.js +39 -2
  75. package/dist/commands/read/search-cli.js +6 -1
  76. package/dist/commands/registry-cli.js +29 -14
  77. package/dist/commands/remember.js +2 -0
  78. package/dist/commands/sources/init.js +13 -14
  79. package/dist/commands/sources/schema-repair.js +2 -4
  80. package/dist/commands/sources/source-add.js +62 -73
  81. package/dist/commands/sources/source-manage.js +50 -46
  82. package/dist/commands/sources/stash-cli.js +41 -4
  83. package/dist/commands/tasks/default-tasks.js +12 -12
  84. package/dist/commands/tasks/tasks-cli.js +7 -3
  85. package/dist/commands/tasks/tasks.js +113 -18
  86. package/dist/commands/wiki-cli.js +9 -10
  87. package/dist/core/asset/frontmatter.js +12 -2
  88. package/dist/core/common.js +5 -3
  89. package/dist/core/config/config-io.js +28 -17
  90. package/dist/core/config/config-schema.js +358 -66
  91. package/dist/core/config/config-types.js +3 -3
  92. package/dist/core/config/config-version.js +29 -0
  93. package/dist/core/config/config-walker.js +98 -27
  94. package/dist/core/config/config.js +132 -266
  95. package/dist/core/config/deep-merge.js +41 -0
  96. package/dist/core/config/engine-semantics.js +32 -0
  97. package/dist/core/errors.js +2 -2
  98. package/dist/core/extra-params.js +61 -0
  99. package/dist/core/file-lock.js +201 -56
  100. package/dist/core/improve-result.js +178 -0
  101. package/dist/core/maintenance-barrier.js +119 -0
  102. package/dist/core/migration-backup.js +416 -0
  103. package/dist/core/paths.js +3 -0
  104. package/dist/core/redaction.js +358 -0
  105. package/dist/core/state/migrations.js +17 -2
  106. package/dist/core/state-db.js +44 -1
  107. package/dist/indexer/db/db.js +116 -1
  108. package/dist/indexer/graph/graph-extraction.js +28 -16
  109. package/dist/indexer/index-writer-lock.js +31 -24
  110. package/dist/indexer/index-written-assets.js +15 -6
  111. package/dist/indexer/indexer.js +47 -2
  112. package/dist/indexer/passes/memory-inference.js +10 -6
  113. package/dist/indexer/passes/metadata.js +250 -0
  114. package/dist/indexer/search/db-search.js +111 -44
  115. package/dist/indexer/search/fts-query.js +41 -0
  116. package/dist/indexer/search/ranking-contributors.js +48 -0
  117. package/dist/indexer/search/ranking.js +36 -23
  118. package/dist/indexer/search/search-fields.js +11 -1
  119. package/dist/integrations/agent/builder-shared.js +7 -0
  120. package/dist/integrations/agent/builders.js +5 -52
  121. package/dist/integrations/agent/config.js +3 -143
  122. package/dist/integrations/agent/detect.js +17 -2
  123. package/dist/integrations/agent/engine-resolution.js +202 -0
  124. package/dist/integrations/agent/index.js +1 -2
  125. package/dist/integrations/agent/model-aliases.js +7 -2
  126. package/dist/integrations/agent/profiles.js +6 -99
  127. package/dist/integrations/agent/runner-dispatch.js +76 -13
  128. package/dist/integrations/agent/runner.js +76 -207
  129. package/dist/integrations/agent/spawn.js +4 -6
  130. package/dist/integrations/harnesses/aider/agent-builder.js +2 -3
  131. package/dist/integrations/harnesses/aider/index.js +0 -1
  132. package/dist/integrations/harnesses/amazonq/agent-builder.js +2 -3
  133. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  134. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  135. package/dist/integrations/harnesses/claude/index.js +0 -2
  136. package/dist/integrations/harnesses/codex/agent-builder.js +2 -3
  137. package/dist/integrations/harnesses/codex/index.js +0 -1
  138. package/dist/integrations/harnesses/copilot/agent-builder.js +2 -3
  139. package/dist/integrations/harnesses/copilot/index.js +0 -1
  140. package/dist/integrations/harnesses/gemini/agent-builder.js +2 -3
  141. package/dist/integrations/harnesses/gemini/index.js +0 -1
  142. package/dist/integrations/harnesses/index.js +1 -24
  143. package/dist/integrations/harnesses/opencode/agent-builder.js +2 -3
  144. package/dist/integrations/harnesses/opencode/index.js +0 -6
  145. package/dist/integrations/harnesses/opencode-sdk/harness.js +1 -6
  146. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
  147. package/dist/integrations/harnesses/openhands/agent-builder.js +2 -3
  148. package/dist/integrations/harnesses/openhands/index.js +0 -1
  149. package/dist/integrations/harnesses/pi/agent-builder.js +2 -3
  150. package/dist/integrations/harnesses/pi/index.js +0 -1
  151. package/dist/integrations/harnesses/types.js +1 -32
  152. package/dist/integrations/lockfile.js +32 -21
  153. package/dist/llm/client.js +48 -14
  154. package/dist/llm/feature-gate.js +15 -47
  155. package/dist/llm/graph-extract.js +1 -1
  156. package/dist/llm/index-passes.js +8 -42
  157. package/dist/llm/memory-infer-impl.js +1 -1
  158. package/dist/llm/usage-persist.js +4 -0
  159. package/dist/llm/usage-telemetry.js +35 -5
  160. package/dist/output/shapes/helpers.js +2 -1
  161. package/dist/output/shapes/passthrough.js +2 -0
  162. package/dist/output/text/helpers.js +3 -1
  163. package/dist/schemas/akm-config.json +11013 -8600
  164. package/dist/schemas/akm-task.json +87 -0
  165. package/dist/schemas/akm-workflow.json +57 -13
  166. package/dist/scripts/migrate-storage.js +8591 -509
  167. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +8623 -484
  168. package/dist/setup/detected-engines.js +142 -0
  169. package/dist/setup/engine-config.js +89 -0
  170. package/dist/setup/setup.js +236 -132
  171. package/dist/setup/steps/connection.js +61 -32
  172. package/dist/setup/steps/platforms.js +4 -4
  173. package/dist/setup/steps.js +3 -2
  174. package/dist/storage/database.js +13 -1
  175. package/dist/storage/engines/sqlite-migrations.js +1 -0
  176. package/dist/storage/repositories/improve-runs-repository.js +5 -5
  177. package/dist/storage/repositories/task-history-repository.js +78 -0
  178. package/dist/storage/repositories/workflow-runs-repository.js +9 -8
  179. package/dist/tasks/parser.js +138 -52
  180. package/dist/tasks/runner.js +71 -75
  181. package/dist/tasks/schema.js +1 -1
  182. package/dist/tasks/validator.js +11 -6
  183. package/dist/wiki/wiki.js +9 -8
  184. package/dist/workflows/authoring/workflow-program-template.yaml +3 -3
  185. package/dist/workflows/concurrency-policy.js +15 -0
  186. package/dist/workflows/db.js +65 -13
  187. package/dist/workflows/exec/brief.js +18 -24
  188. package/dist/workflows/exec/frozen-judge.js +47 -0
  189. package/dist/workflows/exec/native-executor.js +124 -65
  190. package/dist/workflows/exec/report.js +93 -33
  191. package/dist/workflows/exec/run-workflow.js +38 -25
  192. package/dist/workflows/exec/scheduler.js +12 -41
  193. package/dist/workflows/exec/step-work.js +91 -35
  194. package/dist/workflows/ir/compile.js +13 -26
  195. package/dist/workflows/ir/freeze.js +243 -0
  196. package/dist/workflows/ir/plan-hash.js +40 -5
  197. package/dist/workflows/ir/schema.js +542 -1
  198. package/dist/workflows/parser.js +7 -0
  199. package/dist/workflows/program/parser.js +132 -23
  200. package/dist/workflows/program/project.js +3 -4
  201. package/dist/workflows/program/schema.js +2 -2
  202. package/dist/workflows/resource-limits.js +20 -0
  203. package/dist/workflows/runtime/plan-classifier.js +187 -0
  204. package/dist/workflows/runtime/runs.js +54 -47
  205. package/dist/workflows/runtime/workflow-asset-loader.js +0 -22
  206. package/dist/workflows/validator.js +25 -0
  207. package/docs/data-and-telemetry.md +2 -2
  208. package/docs/migration/release-notes/0.6.0.md +1 -1
  209. package/docs/migration/release-notes/0.7.0.md +5 -4
  210. package/docs/migration/v0.8-to-v0.9.md +401 -0
  211. package/package.json +4 -2
  212. package/schemas/akm-config.json +16638 -0
  213. package/schemas/akm-task.json +87 -0
  214. package/schemas/akm-workflow.json +372 -0
  215. package/dist/commands/improve/improve-profiles.js +0 -168
  216. package/dist/core/config/config-migration.js +0 -602
  217. package/dist/core/deep-merge.js +0 -38
  218. package/dist/llm/call-ai.js +0 -62
  219. package/dist/setup/legacy-config.js +0 -106
  220. package/docs/README.md +0 -104
  221. /package/dist/assets/{profiles → improve-strategies}/catchup.json +0 -0
  222. /package/dist/assets/{profiles → improve-strategies}/consolidate.json +0 -0
  223. /package/dist/assets/{profiles → improve-strategies}/frequent.json +0 -0
  224. /package/dist/assets/{profiles → improve-strategies}/memory-focus.json +0 -0
  225. /package/dist/assets/{profiles → improve-strategies}/quick.json +0 -0
  226. /package/dist/assets/{profiles → improve-strategies}/recombine-only.json +0 -0
  227. /package/dist/assets/{profiles → improve-strategies}/synthesize.json +0 -0
  228. /package/dist/assets/{profiles → improve-strategies}/thorough.json +0 -0
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://itlackey.github.io/akm/schemas/akm-task.json",
4
+ "title": "AKM Scheduled Task",
5
+ "description": "Strict version-2 YAML task definition. Exactly one target is required.",
6
+ "type": "object",
7
+ "required": ["version", "schedule"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": { "const": 2 },
11
+ "name": { "type": "string" },
12
+ "description": { "type": "string" },
13
+ "when_to_use": { "type": "string" },
14
+ "tags": { "type": "array", "items": { "type": "string", "minLength": 1 } },
15
+ "schedule": { "type": "string", "minLength": 1 },
16
+ "enabled": { "type": "boolean" },
17
+ "workflow": { "type": "string", "minLength": 1 },
18
+ "prompt": { "type": "string", "minLength": 1 },
19
+ "command": {
20
+ "oneOf": [
21
+ { "type": "string", "minLength": 1 },
22
+ { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }
23
+ ]
24
+ },
25
+ "params": { "type": "object" },
26
+ "engine": { "type": "string", "minLength": 1 },
27
+ "model": { "type": "string", "minLength": 1 },
28
+ "timeoutMs": { "type": ["integer", "null"], "minimum": 1 },
29
+ "llm": { "$ref": "#/definitions/llm" }
30
+ },
31
+ "oneOf": [
32
+ {
33
+ "required": ["workflow"],
34
+ "not": { "anyOf": [{ "required": ["prompt"] }, { "required": ["command"] }, { "required": ["engine"] }, { "required": ["model"] }, { "required": ["timeoutMs"] }, { "required": ["llm"] }] }
35
+ },
36
+ {
37
+ "required": ["prompt"],
38
+ "not": { "anyOf": [{ "required": ["workflow"] }, { "required": ["command"] }, { "required": ["params"] }] }
39
+ },
40
+ {
41
+ "required": ["command"],
42
+ "not": { "anyOf": [{ "required": ["workflow"] }, { "required": ["prompt"] }, { "required": ["params"] }, { "required": ["engine"] }, { "required": ["model"] }, { "required": ["llm"] }] }
43
+ }
44
+ ],
45
+ "definitions": {
46
+ "llm": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "temperature": { "type": "number" },
51
+ "maxTokens": { "type": "integer", "minimum": 1 },
52
+ "supportsJsonSchema": { "type": "boolean" },
53
+ "extraParams": { "$ref": "#/definitions/extraParams" },
54
+ "contextLength": { "type": "integer", "minimum": 1 },
55
+ "enableThinking": { "type": "boolean" }
56
+ }
57
+ },
58
+ "extraParams": {
59
+ "type": "object",
60
+ "description": "Provider-specific request fields. Top-level AKM-owned fields are forbidden; credential-shaped keys are forbidden recursively after lowercase/non-alphanumeric normalization.",
61
+ "propertyNames": {
62
+ "not": {
63
+ "enum": ["model", "messages", "temperature", "maxtokens", "responseformat", "stream", "streamoptions", "enablethinking", "authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
64
+ }
65
+ },
66
+ "additionalProperties": { "$ref": "#/definitions/extraParamValue" },
67
+ "x-akm-protectedTopLevelNormalizedKeys": ["model", "messages", "temperature", "maxtokens", "responseformat", "stream", "streamoptions", "enablethinking"],
68
+ "x-akm-recursivelyForbiddenNormalizedKeys": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
69
+ },
70
+ "extraParamValue": {
71
+ "anyOf": [
72
+ { "type": ["string", "number", "boolean", "null"] },
73
+ { "type": "array", "items": { "$ref": "#/definitions/extraParamValue" } },
74
+ {
75
+ "type": "object",
76
+ "propertyNames": {
77
+ "not": {
78
+ "enum": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
79
+ }
80
+ },
81
+ "additionalProperties": { "$ref": "#/definitions/extraParamValue" },
82
+ "x-akm-recursivelyForbiddenNormalizedKeys": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
83
+ }
84
+ ]
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,372 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://itlackey.github.io/akm/schemas/akm-workflow.json",
4
+ "title": "AKM Workflow Program",
5
+ "description": "YAML workflow program for the akm CLI (Agent Knowledge Management). Files live under workflows/ with extension .yaml or .yml. Hand-authored alongside src/workflows/program/schema.ts; the enum vocabularies and patterns here are pinned against the TypeScript constants by tests/workflows/program-parser.test.ts — update both together.",
6
+ "type": "object",
7
+ "required": ["version", "name", "steps"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": {
11
+ "const": 2,
12
+ "description": "Workflow program format version. Only 2 is valid."
13
+ },
14
+ "name": {
15
+ "type": "string",
16
+ "minLength": 1,
17
+ "description": "Workflow name."
18
+ },
19
+ "description": {
20
+ "type": "string",
21
+ "description": "Optional human-readable description."
22
+ },
23
+ "params": {
24
+ "type": "object",
25
+ "maxProperties": 128,
26
+ "description": "Run parameters: param name -> JSON Schema declaration. Names must be ${{ params.<name> }}-addressable identifiers.",
27
+ "propertyNames": {
28
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
29
+ },
30
+ "additionalProperties": {
31
+ "$ref": "#/definitions/jsonSchemaObject"
32
+ }
33
+ },
34
+ "defaults": {
35
+ "$ref": "#/definitions/defaults"
36
+ },
37
+ "budget": {
38
+ "$ref": "#/definitions/budget"
39
+ },
40
+ "steps": {
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "maxItems": 256,
44
+ "items": {
45
+ "$ref": "#/definitions/step"
46
+ }
47
+ }
48
+ },
49
+ "definitions": {
50
+ "identifier": {
51
+ "type": "string",
52
+ "pattern": "^[A-Za-z_][A-Za-z0-9_-]*$",
53
+ "description": "Step id: a letter or underscore first, then letters, digits, underscores, or dashes (no dots, no leading digit). This is exactly the ${{ steps.<id>.output }}-addressable grammar; dots are reserved for the .output path separator and the engine's internal <stepId>.gate node id."
54
+ },
55
+ "timeout": {
56
+ "description": "Duration: \"<n>ms\" | \"<n>s\" | \"<n>m\" | \"none\" (bare integers are milliseconds).",
57
+ "oneOf": [
58
+ {
59
+ "type": "string",
60
+ "pattern": "^([0-9]+(ms|s|m)?|none)$"
61
+ },
62
+ {
63
+ "type": "integer",
64
+ "minimum": 1
65
+ }
66
+ ]
67
+ },
68
+ "onError": {
69
+ "description": "Failure policy: fail the step on the first unit failure (default), or record failures and let the gate decide.",
70
+ "enum": ["fail", "continue"]
71
+ },
72
+ "llm": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "properties": {
76
+ "temperature": { "type": "number" },
77
+ "max_tokens": { "type": "integer", "minimum": 1 },
78
+ "supports_json_schema": { "type": "boolean" },
79
+ "extra_params": { "$ref": "#/definitions/extraParams" },
80
+ "context_length": { "type": "integer", "minimum": 1 },
81
+ "enable_thinking": { "type": "boolean" }
82
+ }
83
+ },
84
+ "extraParams": {
85
+ "type": "object",
86
+ "description": "Provider-specific request fields. Top-level AKM-owned fields are forbidden; credential-shaped keys are forbidden recursively after lowercase/non-alphanumeric normalization.",
87
+ "propertyNames": {
88
+ "not": {
89
+ "enum": ["model", "messages", "temperature", "maxtokens", "responseformat", "stream", "streamoptions", "enablethinking", "authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
90
+ }
91
+ },
92
+ "additionalProperties": { "$ref": "#/definitions/extraParamValue" },
93
+ "x-akm-protectedTopLevelNormalizedKeys": ["model", "messages", "temperature", "maxtokens", "responseformat", "stream", "streamoptions", "enablethinking"],
94
+ "x-akm-recursivelyForbiddenNormalizedKeys": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
95
+ },
96
+ "extraParamValue": {
97
+ "anyOf": [
98
+ { "type": ["string", "number", "boolean", "null"] },
99
+ { "type": "array", "items": { "$ref": "#/definitions/extraParamValue" } },
100
+ {
101
+ "type": "object",
102
+ "propertyNames": {
103
+ "not": {
104
+ "enum": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
105
+ }
106
+ },
107
+ "additionalProperties": { "$ref": "#/definitions/extraParamValue" },
108
+ "x-akm-recursivelyForbiddenNormalizedKeys": ["authorization", "headers", "apikey", "token", "password", "secret", "cookie", "setcookie"]
109
+ }
110
+ ]
111
+ },
112
+ "reducer": {
113
+ "description": "How a map step folds per-item unit results into the step artifact.",
114
+ "enum": ["collect", "vote"]
115
+ },
116
+ "isolation": {
117
+ "description": "Filesystem isolation for file-mutating units (enforcement lands in R2).",
118
+ "enum": ["none", "worktree"]
119
+ },
120
+ "failureReason": {
121
+ "description": "Persisted AgentFailureReason taxonomy (src/integrations/agent/spawn.ts).",
122
+ "enum": [
123
+ "timeout",
124
+ "spawn_failed",
125
+ "non_zero_exit",
126
+ "parse_error",
127
+ "cooldown",
128
+ "llm_rate_limit",
129
+ "llm_content_filter",
130
+ "llm_invalid_json",
131
+ "content_policy_reject",
132
+ "unsupported_type",
133
+ "no_change",
134
+ "aborted"
135
+ ]
136
+ },
137
+ "jsonSchemaObject": {
138
+ "type": "object",
139
+ "description": "A JSON Schema declaration (validated as a schema by the compiler, not here)."
140
+ },
141
+ "retry": {
142
+ "type": "object",
143
+ "description": "Bounded retry on transient failures, keyed on the persisted failure_reason taxonomy.",
144
+ "required": ["max", "on"],
145
+ "additionalProperties": false,
146
+ "properties": {
147
+ "max": {
148
+ "type": "integer",
149
+ "minimum": 0,
150
+ "description": "Maximum retry attempts per unit."
151
+ },
152
+ "on": {
153
+ "type": "array",
154
+ "minItems": 1,
155
+ "items": {
156
+ "$ref": "#/definitions/failureReason"
157
+ }
158
+ }
159
+ }
160
+ },
161
+ "budget": {
162
+ "type": "object",
163
+ "description": "Run-level budget ceilings, enforced by the engine per run (journal-seeded). Hitting a ceiling fails the step hard, regardless of on_error.",
164
+ "additionalProperties": false,
165
+ "properties": {
166
+ "max_tokens": {
167
+ "type": "integer",
168
+ "minimum": 1,
169
+ "description": "Ceiling on total reported token usage across the run (seeded from journaled unit rows)."
170
+ },
171
+ "max_units": {
172
+ "type": "integer",
173
+ "minimum": 1,
174
+ "maximum": 10000,
175
+ "description": "Ceiling on total dispatched units across the run (seeded from journaled unit rows)."
176
+ }
177
+ }
178
+ },
179
+ "defaults": {
180
+ "type": "object",
181
+ "description": "Run-level defaults, overridable per unit.",
182
+ "additionalProperties": false,
183
+ "properties": {
184
+ "engine": {
185
+ "type": "string",
186
+ "minLength": 1
187
+ },
188
+ "model": {
189
+ "type": "string",
190
+ "minLength": 1,
191
+ "description": "Model alias (tier) or exact id; resolved per-harness at dispatch."
192
+ },
193
+ "timeout": {
194
+ "$ref": "#/definitions/timeout"
195
+ },
196
+ "on_error": {
197
+ "$ref": "#/definitions/onError"
198
+ },
199
+ "llm": {
200
+ "$ref": "#/definitions/llm"
201
+ }
202
+ }
203
+ },
204
+ "unit": {
205
+ "type": "object",
206
+ "description": "A single dispatchable unit: instructions plus dispatch overrides.",
207
+ "required": ["instructions"],
208
+ "additionalProperties": false,
209
+ "properties": {
210
+ "engine": {
211
+ "type": "string",
212
+ "minLength": 1,
213
+ "description": "Named engine selected at workflow start."
214
+ },
215
+ "model": {
216
+ "type": "string",
217
+ "minLength": 1
218
+ },
219
+ "llm": {
220
+ "$ref": "#/definitions/llm"
221
+ },
222
+ "timeout": {
223
+ "$ref": "#/definitions/timeout"
224
+ },
225
+ "retry": {
226
+ "$ref": "#/definitions/retry"
227
+ },
228
+ "on_error": {
229
+ "$ref": "#/definitions/onError"
230
+ },
231
+ "instructions": {
232
+ "type": "string",
233
+ "minLength": 1,
234
+ "description": "Instruction template. ${{ … }} expressions are parsed against the closed grammar: params.<name> | steps.<id>.output.<path> | item | item_index."
235
+ },
236
+ "output": {
237
+ "$ref": "#/definitions/jsonSchemaObject"
238
+ },
239
+ "env": {
240
+ "type": "array",
241
+ "items": {
242
+ "type": "string",
243
+ "minLength": 1
244
+ },
245
+ "description": "Env asset refs injected into the dispatched unit env."
246
+ },
247
+ "isolation": {
248
+ "$ref": "#/definitions/isolation"
249
+ }
250
+ }
251
+ },
252
+ "map": {
253
+ "type": "object",
254
+ "description": "Fan the unit template out over an expression-addressed item list.",
255
+ "required": ["over", "unit"],
256
+ "additionalProperties": false,
257
+ "properties": {
258
+ "over": {
259
+ "type": "string",
260
+ "minLength": 1,
261
+ "description": "${{ … }} expression naming the producer of the item list (e.g. ${{ steps.discover.output.files }})."
262
+ },
263
+ "concurrency": {
264
+ "type": "integer",
265
+ "minimum": 1,
266
+ "description": "Max concurrent units for this step; capped by the engine's global limit."
267
+ },
268
+ "reducer": {
269
+ "$ref": "#/definitions/reducer"
270
+ },
271
+ "unit": {
272
+ "$ref": "#/definitions/unit"
273
+ }
274
+ }
275
+ },
276
+ "route": {
277
+ "type": "object",
278
+ "description": "Route on an explicit ${{ … }} input to a LATER step. Targets must come after the routing step.",
279
+ "required": ["input", "when"],
280
+ "additionalProperties": false,
281
+ "properties": {
282
+ "input": {
283
+ "type": "string",
284
+ "minLength": 1,
285
+ "description": "${{ … }} expression naming the value to route on."
286
+ },
287
+ "when": {
288
+ "type": "object",
289
+ "minProperties": 1,
290
+ "maxProperties": 256,
291
+ "description": "Match value -> target step id.",
292
+ "additionalProperties": {
293
+ "$ref": "#/definitions/identifier"
294
+ }
295
+ },
296
+ "default": {
297
+ "$ref": "#/definitions/identifier"
298
+ }
299
+ }
300
+ },
301
+ "gate": {
302
+ "type": "object",
303
+ "description": "Completion gate criteria judged against the step artifact.",
304
+ "required": ["criteria"],
305
+ "additionalProperties": false,
306
+ "properties": {
307
+ "criteria": {
308
+ "type": "array",
309
+ "minItems": 1,
310
+ "items": {
311
+ "type": "string",
312
+ "minLength": 1
313
+ }
314
+ },
315
+ "max_loops": {
316
+ "type": "integer",
317
+ "minimum": 1,
318
+ "description": "Evaluator-optimizer loop bound (execution lands in R2)."
319
+ },
320
+ "required": {
321
+ "type": "boolean",
322
+ "description": "When true, the gate must be judged: if no summary-validation judge is available (offline / misconfigured LLM), the step BLOCKS for a human instead of failing open and silently passing. Absent = fail-open default. The engine's --require-gates flag applies this to every criteria-bearing gate for one invocation."
323
+ }
324
+ }
325
+ },
326
+ "step": {
327
+ "type": "object",
328
+ "description": "One step of the gated spine. Exactly one of unit | map | route.",
329
+ "required": ["id"],
330
+ "additionalProperties": false,
331
+ "properties": {
332
+ "id": {
333
+ "$ref": "#/definitions/identifier"
334
+ },
335
+ "title": {
336
+ "type": "string",
337
+ "minLength": 1
338
+ },
339
+ "unit": {
340
+ "$ref": "#/definitions/unit"
341
+ },
342
+ "map": {
343
+ "$ref": "#/definitions/map"
344
+ },
345
+ "route": {
346
+ "$ref": "#/definitions/route"
347
+ },
348
+ "output": {
349
+ "$ref": "#/definitions/jsonSchemaObject"
350
+ },
351
+ "gate": {
352
+ "$ref": "#/definitions/gate"
353
+ }
354
+ },
355
+ "allOf": [
356
+ {
357
+ "oneOf": [
358
+ {
359
+ "required": ["unit"]
360
+ },
361
+ {
362
+ "required": ["map"]
363
+ },
364
+ {
365
+ "required": ["route"]
366
+ }
367
+ ]
368
+ }
369
+ ]
370
+ }
371
+ }
372
+ }
@@ -1,168 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import profileCatchup from "../../assets/profiles/catchup.json" with { type: "json" };
5
- import profileConsolidate from "../../assets/profiles/consolidate.json" with { type: "json" };
6
- import profileDefault from "../../assets/profiles/default.json" with { type: "json" };
7
- import profileFrequent from "../../assets/profiles/frequent.json" with { type: "json" };
8
- import profileGraphRefresh from "../../assets/profiles/graph-refresh.json" with { type: "json" };
9
- import profileMemoryFocus from "../../assets/profiles/memory-focus.json" with { type: "json" };
10
- import profileProactiveMaintenance from "../../assets/profiles/proactive-maintenance.json" with { type: "json" };
11
- import profileQuick from "../../assets/profiles/quick.json" with { type: "json" };
12
- import profileRecombineOnly from "../../assets/profiles/recombine-only.json" with { type: "json" };
13
- import profileReflectDistill from "../../assets/profiles/reflect-distill.json" with { type: "json" };
14
- import profileSynthesize from "../../assets/profiles/synthesize.json" with { type: "json" };
15
- import profileThorough from "../../assets/profiles/thorough.json" with { type: "json" };
16
- import { parseAssetRef } from "../../core/asset/asset-ref.js";
17
- import { ConfigError } from "../../core/errors.js";
18
- /** Profile name used as the final fallback when nothing else resolves. */
19
- const FALLBACK_PROFILE_NAME = "default";
20
- // Built-in default allowed types per process
21
- export const DEFAULT_ALLOWED_TYPES = {
22
- reflect: ["agent", "command", "knowledge", "lesson", "memory", "skill", "wiki", "workflow"],
23
- distill: ["memory"],
24
- consolidate: ["memory"],
25
- };
26
- // Built-in profiles are loaded from embedded JSON files in src/assets/profiles/.
27
- // To add a new profile: create a new .json file there, import it above, and add
28
- // it to this map. No code change needed beyond those two steps.
29
- const BUILTIN_PROFILES = {
30
- default: profileDefault,
31
- quick: profileQuick,
32
- thorough: profileThorough,
33
- "memory-focus": profileMemoryFocus,
34
- "graph-refresh": profileGraphRefresh,
35
- frequent: profileFrequent,
36
- consolidate: profileConsolidate,
37
- catchup: profileCatchup,
38
- synthesize: profileSynthesize,
39
- "reflect-distill": profileReflectDistill,
40
- "proactive-maintenance": profileProactiveMaintenance,
41
- "recombine-only": profileRecombineOnly,
42
- };
43
- /**
44
- * Default enabled-state for known improve processes when neither the user
45
- * profile nor the built-in default profile specifies an override.
46
- *
47
- * These mirror the legacy `LlmFeatureFlags` defaults so callers that bypass
48
- * the profile system (rare — most run through `resolveImproveProfile`) get
49
- * the same answer.
50
- */
51
- const IMPROVE_PROCESS_DEFAULTS = {
52
- reflect: true,
53
- distill: true,
54
- consolidate: true,
55
- memoryInference: true,
56
- graphExtraction: true,
57
- validation: false,
58
- // session-extraction reads native session files from claude-code / opencode
59
- // and queues durable-insight proposals. Default on — opt out via
60
- // profiles.improve.default.processes.extract.enabled: false.
61
- extract: true,
62
- // proposal-queue triage drains the standing backlog. Opt-in (default off),
63
- // like `validation` — needs an explicit `enabled: true`.
64
- triage: false,
65
- // Layer 2 proactive-maintenance selector. Opt-in (default off) — surfaces
66
- // stale high-value assets on a schedule. Enable per-profile with an explicit
67
- // `processes.proactiveMaintenance.enabled: true`.
68
- proactiveMaintenance: false,
69
- // #609 recombine / synthesize pass — whole-corpus cross-episodic
70
- // generalization. Opt-in (default off); enable per-profile with an explicit
71
- // `processes.recombine.enabled: true`.
72
- recombine: false,
73
- // #615 procedural-compilation pass — detects recurring successful ordered
74
- // action sequences and compiles them into workflow proposals. Opt-in (default
75
- // off); enable per-profile with an explicit `processes.procedural.enabled: true`.
76
- procedural: false,
77
- };
78
- /**
79
- * Compute the effective enabled-state for a named improve process.
80
- *
81
- * Resolution order: explicit `profile.processes.<name>.enabled` (boolean) →
82
- * the built-in {@link IMPROVE_PROCESS_DEFAULTS} fallback → `false`.
83
- */
84
- export function resolveProcessEnabled(processName, profile) {
85
- const processes = profile.processes;
86
- const entry = processes?.[processName];
87
- if (entry && typeof entry.enabled === "boolean")
88
- return entry.enabled;
89
- return IMPROVE_PROCESS_DEFAULTS[processName] ?? false;
90
- }
91
- function deepMerge(base, override) {
92
- if (typeof base !== "object" || base === null)
93
- return override ?? base;
94
- const result = { ...base };
95
- for (const key of Object.keys(override)) {
96
- const ov = override[key];
97
- // Treat `null` the same as `undefined` so user overrides never wipe a
98
- // built-in field with `null`. The on-disk parser already strips nulls,
99
- // but the programmatic API exposes this path and callers occasionally
100
- // pass JSON-shaped objects with explicit nulls.
101
- if (ov !== undefined && ov !== null) {
102
- const bv = base[key];
103
- if (typeof bv === "object" && bv !== null && typeof ov === "object" && ov !== null && !Array.isArray(bv)) {
104
- result[key] = deepMerge(bv, ov);
105
- }
106
- else {
107
- result[key] = ov;
108
- }
109
- }
110
- }
111
- return result;
112
- }
113
- export function resolveImproveProfile(name, config) {
114
- const requestedName = name ??
115
- (typeof config.defaults?.improve === "string" ? config.defaults.improve : undefined) ??
116
- FALLBACK_PROFILE_NAME;
117
- const hasBuiltin = requestedName in BUILTIN_PROFILES;
118
- const hasUserDefined = !!config.profiles?.improve?.[requestedName];
119
- // An unknown profile name is a HARD error. Silently falling back to the
120
- // default (proactive-off) profile is the −96% incident class: a cron pinned
121
- // to `--profile reflect-distill` ran the default for weeks because the name
122
- // only existed in one host's config and the resolver swallowed the miss.
123
- if (!hasBuiltin && !hasUserDefined) {
124
- const valid = [
125
- ...new Set([...Object.keys(BUILTIN_PROFILES), ...Object.keys(config.profiles?.improve ?? {})]),
126
- ].sort();
127
- throw new ConfigError(`Improve profile "${requestedName}" not found. Valid profiles: ${valid.join(", ")}.`, "UNKNOWN_IMPROVE_PROFILE");
128
- }
129
- const builtin = BUILTIN_PROFILES[requestedName] ?? BUILTIN_PROFILES[FALLBACK_PROFILE_NAME];
130
- const userOverride = config.profiles?.improve?.[requestedName] ?? {};
131
- return deepMerge(builtin, userOverride);
132
- }
133
- export function shouldSkipRef(ref, processName, profile) {
134
- const cfg = profile.processes?.[processName];
135
- // Check if the process itself is disabled
136
- if (cfg?.enabled === false)
137
- return { skip: true, reason: "process-disabled" };
138
- const parsed = parseAssetRef(ref);
139
- const allowed = cfg?.allowedTypes ?? DEFAULT_ALLOWED_TYPES[processName];
140
- if (!allowed.includes(parsed.type))
141
- return { skip: true, reason: "type-filter" };
142
- // Hardcoded: wiki raw directories are never processed by any improve process.
143
- if (parsed.type === "wiki" && parsed.name.split("/")[1] === "raw") {
144
- return { skip: true, reason: "raw-wiki" };
145
- }
146
- return { skip: false, reason: "" };
147
- }
148
- /**
149
- * Planner-level pre-filter: return `true` when every per-ref improve pass that
150
- * participates in the in-loop dispatch (today: `reflect` and `distill`) would
151
- * refuse this ref under the active profile. Such refs cannot produce any work
152
- * downstream — they only generate synthetic skip actions and inflate
153
- * `plannedRefs` by a constant factor per cron run.
154
- *
155
- * Companion to `shouldSkipRef`. The 2026-05-27 planner/profile/metrics deep
156
- * analysis (`/tmp/akm-health-investigations/planner-profile-metrics-deep-analysis.md`)
157
- * documents the 99.07% synthetic-skip emission rate this pre-filter eliminates.
158
- *
159
- * NOTE: passes that operate on their own candidate set (consolidate,
160
- * memoryInference, graphExtraction) are deliberately excluded — they do not
161
- * iterate `plannedRefs` per-ref, so a ref being profile-incompatible at the
162
- * reflect+distill layer says nothing about their work.
163
- */
164
- export function isProfileFilteredForAllPasses(ref, profile) {
165
- const reflectSkip = shouldSkipRef(ref, "reflect", profile);
166
- const distillSkip = shouldSkipRef(ref, "distill", profile);
167
- return reflectSkip.skip && distillSkip.skip;
168
- }