akm-cli 0.8.6 → 0.8.14

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 (324) hide show
  1. package/CHANGELOG.md +442 -0
  2. package/dist/assets/help/help-proposals.md +1 -2
  3. package/dist/assets/hints/cli-hints-full.md +34 -19
  4. package/dist/assets/hints/cli-hints-short.md +1 -1
  5. package/dist/assets/profiles/catchup.json +13 -0
  6. package/dist/assets/profiles/consolidate.json +13 -0
  7. package/dist/assets/profiles/frequent.json +13 -0
  8. package/dist/assets/tasks/core/backup.yml +4 -0
  9. package/dist/assets/tasks/core/extract.yml +4 -0
  10. package/dist/assets/tasks/core/improve.yml +4 -0
  11. package/dist/assets/tasks/core/index-refresh.yml +4 -0
  12. package/dist/assets/tasks/core/sync.yml +4 -0
  13. package/dist/assets/tasks/core/update-stashes.yml +4 -0
  14. package/dist/assets/tasks/core/version-check.yml +4 -0
  15. package/dist/assets/templates/html/default.html +78 -0
  16. package/dist/assets/templates/html/health.html +560 -0
  17. package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
  18. package/dist/cli/config-migrate.js +6 -6
  19. package/dist/cli/config-validate.js +4 -4
  20. package/dist/cli/confirm.js +3 -3
  21. package/dist/cli/parse-args.js +1 -1
  22. package/dist/cli/shared.js +72 -19
  23. package/dist/cli-node.mjs +26 -0
  24. package/dist/cli.js +206 -3866
  25. package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
  26. package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
  27. package/dist/commands/agent/contribute-cli.js +200 -0
  28. package/dist/commands/completions.js +1 -1
  29. package/dist/commands/config-cli.js +230 -3
  30. package/dist/commands/db-cli.js +2 -2
  31. package/dist/commands/env/env-cli.js +529 -0
  32. package/dist/commands/env/env.js +410 -0
  33. package/dist/commands/env/secret-cli.js +259 -0
  34. package/dist/commands/{secret.js → env/secret.js} +6 -47
  35. package/dist/commands/events.js +4 -4
  36. package/dist/commands/feedback-cli.js +18 -34
  37. package/dist/commands/graph/graph-cli.js +132 -0
  38. package/dist/commands/{graph.js → graph/graph.js} +22 -16
  39. package/dist/commands/health/checks.js +279 -0
  40. package/dist/commands/health/html-report.js +448 -0
  41. package/dist/commands/health.js +189 -266
  42. package/dist/commands/{consolidate.js → improve/consolidate.js} +63 -38
  43. package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
  44. package/dist/commands/{distill.js → improve/distill.js} +39 -18
  45. package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
  46. package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
  47. package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
  48. package/dist/commands/{extract.js → improve/extract.js} +221 -26
  49. package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +30 -4
  50. package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
  51. package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
  52. package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
  53. package/dist/commands/{improve.js → improve/improve.js} +672 -292
  54. package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
  55. package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
  56. package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
  57. package/dist/commands/improve/reflect-noise.js +0 -0
  58. package/dist/commands/{reflect.js → improve/reflect.js} +58 -28
  59. package/dist/commands/improve/session-asset.js +248 -0
  60. package/dist/commands/lint/agent-linter.js +1 -1
  61. package/dist/commands/lint/base-linter.js +55 -37
  62. package/dist/commands/lint/command-linter.js +1 -1
  63. package/dist/commands/lint/default-linter.js +1 -1
  64. package/dist/commands/lint/env-key-rules.js +1 -1
  65. package/dist/commands/lint/index.js +19 -25
  66. package/dist/commands/lint/knowledge-linter.js +1 -1
  67. package/dist/commands/lint/memory-linter.js +1 -1
  68. package/dist/commands/lint/registry.js +8 -8
  69. package/dist/commands/lint/skill-linter.js +1 -1
  70. package/dist/commands/lint/task-linter.js +1 -1
  71. package/dist/commands/lint/workflow-linter.js +1 -1
  72. package/dist/commands/lint.js +1 -1
  73. package/dist/commands/observability-cli.js +244 -0
  74. package/dist/commands/proposal/drain-policies.js +3 -3
  75. package/dist/commands/proposal/drain.js +87 -15
  76. package/dist/commands/proposal/proposal-cli.js +490 -0
  77. package/dist/commands/{proposal.js → proposal/proposal.js} +17 -6
  78. package/dist/commands/{propose.js → proposal/propose.js} +11 -11
  79. package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
  80. package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
  81. package/dist/{core → commands/proposal/validators}/proposals.js +374 -345
  82. package/dist/commands/{curate.js → read/curate.js} +7 -7
  83. package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
  84. package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
  85. package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
  86. package/dist/commands/read/search-cli.js +207 -0
  87. package/dist/commands/{search.js → read/search.js} +22 -27
  88. package/dist/commands/{show.js → read/show.js} +31 -45
  89. package/dist/commands/registry-cli.js +8 -8
  90. package/dist/commands/remember.js +14 -10
  91. package/dist/commands/sources/add-cli.js +293 -0
  92. package/dist/commands/{history.js → sources/history.js} +27 -25
  93. package/dist/commands/{info.js → sources/info.js} +6 -6
  94. package/dist/commands/{init.js → sources/init.js} +6 -6
  95. package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
  96. package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
  97. package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
  98. package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
  99. package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
  100. package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
  101. package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
  102. package/dist/commands/sources/sources-cli.js +305 -0
  103. package/dist/commands/sources/stash-cli.js +219 -0
  104. package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
  105. package/dist/commands/tasks/default-tasks.js +173 -0
  106. package/dist/commands/tasks/tasks-cli.js +210 -0
  107. package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
  108. package/dist/commands/wiki-cli.js +307 -0
  109. package/dist/commands/workflow-cli.js +329 -0
  110. package/dist/core/action-contributors.js +1 -1
  111. package/dist/core/assert.js +40 -0
  112. package/dist/core/asset/asset-create.js +54 -0
  113. package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
  114. package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
  115. package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
  116. package/dist/core/{markdown.js → asset/markdown.js} +1 -1
  117. package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
  118. package/dist/core/best-effort.js +64 -0
  119. package/dist/core/common.js +32 -18
  120. package/dist/core/{config-io.js → config/config-io.js} +29 -19
  121. package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
  122. package/dist/core/{config-schema.js → config/config-schema.js} +50 -7
  123. package/dist/core/config/config-types.js +16 -0
  124. package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
  125. package/dist/core/{config.js → config/config.js} +10 -8
  126. package/dist/core/env-secret-ref.js +90 -0
  127. package/dist/core/errors.js +13 -3
  128. package/dist/core/events.js +27 -4
  129. package/dist/core/file-lock.js +1 -1
  130. package/dist/core/improve-types.js +48 -0
  131. package/dist/core/lesson-lint.js +2 -2
  132. package/dist/core/logs-db.js +304 -0
  133. package/dist/core/paths.js +2 -2
  134. package/dist/core/ripgrep/install.js +2 -2
  135. package/dist/core/ripgrep/resolve.js +2 -2
  136. package/dist/core/state-db.js +195 -60
  137. package/dist/core/text-truncation.js +148 -0
  138. package/dist/core/time.js +1 -1
  139. package/dist/core/write-source.js +98 -85
  140. package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
  141. package/dist/indexer/{db.js → db/db.js} +128 -118
  142. package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
  143. package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
  144. package/dist/indexer/ensure-index.js +4 -4
  145. package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
  146. package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
  147. package/dist/indexer/indexer.js +37 -30
  148. package/dist/indexer/init.js +54 -0
  149. package/dist/indexer/manifest.js +10 -10
  150. package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +141 -33
  151. package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
  152. package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
  153. package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
  154. package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
  155. package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
  156. package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
  157. package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
  158. package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
  159. package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
  160. package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
  161. package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
  162. package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
  163. package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
  164. package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
  165. package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
  166. package/dist/indexer/{walker.js → walk/walker.js} +4 -3
  167. package/dist/integrations/agent/builder-shared.js +39 -0
  168. package/dist/integrations/agent/builders.js +14 -81
  169. package/dist/integrations/agent/config.js +6 -4
  170. package/dist/integrations/agent/detect.js +1 -1
  171. package/dist/integrations/agent/index.js +23 -8
  172. package/dist/integrations/agent/prompts.js +2 -3
  173. package/dist/integrations/agent/runner.js +22 -3
  174. package/dist/integrations/agent/spawn.js +9 -10
  175. package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
  176. package/dist/integrations/harnesses/claude/config-import.js +70 -0
  177. package/dist/integrations/harnesses/claude/index.js +64 -0
  178. package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +32 -5
  179. package/dist/integrations/harnesses/index.js +144 -0
  180. package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
  181. package/dist/integrations/harnesses/opencode/config-import.js +82 -0
  182. package/dist/integrations/harnesses/opencode/index.js +59 -0
  183. package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
  184. package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
  185. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
  186. package/dist/integrations/harnesses/types.js +43 -0
  187. package/dist/integrations/lockfile.js +7 -16
  188. package/dist/integrations/session-logs/index.js +82 -9
  189. package/dist/llm/call-ai.js +4 -4
  190. package/dist/llm/client.js +146 -6
  191. package/dist/llm/embedder.js +6 -6
  192. package/dist/llm/embedders/local.js +9 -22
  193. package/dist/llm/embedders/remote.js +2 -2
  194. package/dist/llm/embedders/types.js +1 -1
  195. package/dist/llm/graph-extract.js +31 -12
  196. package/dist/llm/index-passes.js +1 -1
  197. package/dist/llm/memory-infer.js +12 -5
  198. package/dist/llm/metadata-enhance.js +2 -2
  199. package/dist/llm/usage-persist.js +77 -0
  200. package/dist/llm/usage-telemetry.js +103 -0
  201. package/dist/output/context.js +9 -46
  202. package/dist/output/html-render.js +73 -0
  203. package/dist/output/renderers.js +88 -58
  204. package/dist/output/shapes/curate.js +7 -3
  205. package/dist/output/shapes/distill.js +7 -3
  206. package/dist/output/shapes/env-list.js +18 -16
  207. package/dist/output/shapes/events.js +5 -4
  208. package/dist/output/shapes/helpers.js +19 -5
  209. package/dist/output/shapes/history.js +7 -3
  210. package/dist/output/shapes/passthrough.js +8 -11
  211. package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
  212. package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
  213. package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
  214. package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
  215. package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
  216. package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
  217. package/dist/output/shapes/registry-search.js +7 -3
  218. package/dist/output/shapes/registry.js +12 -0
  219. package/dist/output/shapes/search.js +7 -3
  220. package/dist/output/shapes/secret-list.js +18 -16
  221. package/dist/output/shapes/show.js +7 -3
  222. package/dist/output/shapes.js +55 -30
  223. package/dist/output/text/add.js +2 -3
  224. package/dist/output/text/clone.js +2 -3
  225. package/dist/output/text/config.js +2 -3
  226. package/dist/output/text/curate.js +4 -3
  227. package/dist/output/text/distill.js +2 -3
  228. package/dist/output/text/enable-disable.js +5 -4
  229. package/dist/output/text/env.js +13 -0
  230. package/dist/output/text/events.js +5 -4
  231. package/dist/output/text/feedback.js +4 -3
  232. package/dist/output/text/helpers.js +123 -40
  233. package/dist/output/text/history.js +2 -3
  234. package/dist/output/text/import.js +2 -3
  235. package/dist/output/text/index.js +2 -3
  236. package/dist/output/text/info.js +2 -3
  237. package/dist/output/text/init.js +2 -3
  238. package/dist/output/text/list.js +2 -3
  239. package/dist/output/text/proposal/producer.js +9 -0
  240. package/dist/output/text/proposal/proposal.js +13 -0
  241. package/dist/output/text/registry-commands.js +8 -7
  242. package/dist/output/text/registry.js +12 -0
  243. package/dist/output/text/remember.js +4 -3
  244. package/dist/output/text/remove.js +2 -3
  245. package/dist/output/text/save.js +2 -3
  246. package/dist/output/text/search.js +4 -3
  247. package/dist/output/text/show.js +4 -3
  248. package/dist/output/text/update.js +2 -3
  249. package/dist/output/text/upgrade.js +2 -3
  250. package/dist/output/text/wiki.js +12 -11
  251. package/dist/output/text/workflow.js +12 -10
  252. package/dist/output/text.js +66 -32
  253. package/dist/registry/build-index.js +11 -10
  254. package/dist/registry/factory.js +1 -1
  255. package/dist/registry/origin-resolve.js +1 -1
  256. package/dist/registry/providers/index.js +2 -2
  257. package/dist/registry/providers/skills-sh.js +91 -72
  258. package/dist/registry/providers/static-index.js +75 -52
  259. package/dist/registry/resolve.js +3 -3
  260. package/dist/runtime.js +242 -0
  261. package/dist/scripts/migrate-storage.js +1654 -683
  262. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +254 -168
  263. package/dist/setup/detect.js +311 -9
  264. package/dist/setup/harness-config-import.js +6 -120
  265. package/dist/setup/setup.js +454 -43
  266. package/dist/sources/include.js +1 -1
  267. package/dist/sources/provider-factory.js +2 -2
  268. package/dist/sources/providers/filesystem.js +3 -3
  269. package/dist/sources/providers/git.js +9 -9
  270. package/dist/sources/providers/index.js +4 -4
  271. package/dist/sources/providers/npm.js +6 -6
  272. package/dist/sources/providers/provider-utils.js +13 -20
  273. package/dist/sources/providers/sync-from-ref.js +5 -5
  274. package/dist/sources/providers/tar-utils.js +2 -2
  275. package/dist/sources/providers/website.js +2 -2
  276. package/dist/sources/resolve.js +5 -5
  277. package/dist/sources/website-ingest.js +5 -5
  278. package/dist/storage/database.js +102 -0
  279. package/dist/storage/engines/sqlite-migrations.js +42 -0
  280. package/dist/storage/locations.js +25 -0
  281. package/dist/storage/repositories/index-db.js +43 -0
  282. package/dist/storage/repositories/workflow-runs-repository.js +141 -0
  283. package/dist/tasks/backends/cron.js +4 -4
  284. package/dist/tasks/backends/exec-utils.js +32 -0
  285. package/dist/tasks/backends/index.js +3 -3
  286. package/dist/tasks/backends/launchd.js +7 -14
  287. package/dist/tasks/backends/schtasks.js +7 -16
  288. package/dist/tasks/embedded.js +71 -0
  289. package/dist/tasks/parser.js +2 -2
  290. package/dist/tasks/resolveAkmBin.js +1 -1
  291. package/dist/tasks/runner.js +127 -31
  292. package/dist/tasks/schedule.js +1 -1
  293. package/dist/tasks/validator.js +7 -7
  294. package/dist/text-import-hook.mjs +51 -0
  295. package/dist/version.js +2 -1
  296. package/dist/wiki/wiki.js +7 -7
  297. package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
  298. package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
  299. package/dist/workflows/cli.js +1 -1
  300. package/dist/workflows/db.js +54 -32
  301. package/dist/workflows/parser.js +4 -4
  302. package/dist/workflows/renderer.js +5 -5
  303. package/dist/workflows/runtime/agent-identity.js +56 -0
  304. package/dist/workflows/runtime/checkin.js +57 -0
  305. package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
  306. package/dist/workflows/validate-summary.js +82 -0
  307. package/docs/README.md +1 -1
  308. package/docs/data-and-telemetry.md +6 -6
  309. package/package.json +17 -8
  310. package/dist/commands/add-cli.js +0 -279
  311. package/dist/commands/env.js +0 -213
  312. package/dist/integrations/agent/sdk-runner.js +0 -126
  313. package/dist/output/shapes/vault-list.js +0 -19
  314. package/dist/output/text/proposal-producer.js +0 -8
  315. package/dist/output/text/proposal.js +0 -12
  316. package/dist/output/text/vault.js +0 -16
  317. /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
  318. /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
  319. /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
  320. /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
  321. /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
  322. /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
  323. /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
  324. /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
@@ -135,29 +135,6 @@ export function formatRegistryBuildIndexPlain(r) {
135
135
  const version = typeof r.version === "number" ? `v${r.version}` : "";
136
136
  return `Wrote registry index ${version} (${total} kits) → ${outPath}`.replace(/\s+/g, " ").trim();
137
137
  }
138
- export function formatVaultListPlain(r) {
139
- // Multi-vault listing: { vaults: [{ ref, path, keys }, ...] }
140
- const vaults = Array.isArray(r.vaults) ? r.vaults : [];
141
- if (vaults.length === 0) {
142
- return "No vaults. Create one with `akm vault create <name>` then `akm vault set vault:<name> KEY=VALUE`.";
143
- }
144
- const lines = [];
145
- for (const v of vaults) {
146
- const ref = String(v.ref ?? "?");
147
- const keys = Array.isArray(v.keys) ? v.keys.map(String) : [];
148
- if (lines.length > 0)
149
- lines.push("");
150
- lines.push(`## ${ref}`);
151
- if (keys.length === 0) {
152
- lines.push("- (no keys)");
153
- continue;
154
- }
155
- for (const key of keys) {
156
- lines.push(`- ${key}`);
157
- }
158
- }
159
- return lines.join("\n");
160
- }
161
138
  export function formatEnvListPlain(r) {
162
139
  // Multi-env listing: { envs: [{ ref, path, keys }, ...] }
163
140
  const envs = Array.isArray(r.envs) ? r.envs : [];
@@ -191,6 +168,20 @@ export function formatEnvRemovePlain(r) {
191
168
  const removed = r.removed === true;
192
169
  return removed ? `Removed env ${String(r.ref ?? "?")}` : `Env ${String(r.ref ?? "?")} was not present`;
193
170
  }
171
+ export function formatEnvSetPlain(r) {
172
+ return `Set ${String(r.key ?? "?")} in env ${String(r.ref ?? "?")} (value not displayed)`;
173
+ }
174
+ export function formatEnvUnsetPlain(r) {
175
+ const removed = Array.isArray(r.removed) ? r.removed.map(String) : [];
176
+ const missing = Array.isArray(r.missing) ? r.missing.map(String) : [];
177
+ const ref = String(r.ref ?? "?");
178
+ const parts = [];
179
+ if (removed.length > 0)
180
+ parts.push(`Removed ${removed.join(", ")} from env ${ref}`);
181
+ if (missing.length > 0)
182
+ parts.push(`Not present in env ${ref}: ${missing.join(", ")}`);
183
+ return parts.join("\n") || `No keys changed in env ${ref}`;
184
+ }
194
185
  export function formatWikiRegisterPlain(r) {
195
186
  const name = String(r.name ?? r.wiki ?? "?");
196
187
  const ref = String(r.ref ?? r.path ?? r.url ?? "?");
@@ -205,6 +196,25 @@ export function formatWorkflowValidatePlain(r) {
205
196
  const stepCount = typeof r.stepCount === "number" ? r.stepCount : 0;
206
197
  return `workflow validate: ok — ${title || pathValue} (${stepCount} step(s))`;
207
198
  }
199
+ /**
200
+ * Plain-text rendering for a step-completion that was rejected by the
201
+ * summary-validation gate (#506): the step stays pending and the agent gets
202
+ * corrective feedback on what to finish/fix.
203
+ */
204
+ export function formatWorkflowCompleteRejectedPlain(r) {
205
+ const stepId = String(r.stepId ?? "?");
206
+ const feedback = typeof r.feedback === "string" ? r.feedback : "";
207
+ const missing = Array.isArray(r.missing) ? r.missing.map((m) => String(m)) : [];
208
+ const lines = [`workflow complete: rejected — step "${stepId}" does not meet its completion criteria`];
209
+ if (feedback)
210
+ lines.push(` feedback: ${feedback}`);
211
+ if (missing.length > 0) {
212
+ lines.push(" outstanding:");
213
+ for (const m of missing)
214
+ lines.push(` - ${m}`);
215
+ }
216
+ return lines.join("\n");
217
+ }
208
218
  export function formatProposalProducerPlain(command, r) {
209
219
  if (r.ok === false) {
210
220
  const reason = String(r.reason ?? "unknown");
@@ -225,6 +235,50 @@ export function formatProposalProducerPlain(command, r) {
225
235
  const status = String(proposal.status ?? "pending");
226
236
  return `${command}: queued proposal ${id} (${ref}) [${status}]`;
227
237
  }
238
+ /**
239
+ * Render a one-line gate-decision summary for the proposal list / show surfaces
240
+ * (#577), e.g. `gate=deferred:below-threshold (0.72 < 0.90)`. Returns the empty
241
+ * string for a missing or malformed decision so legacy proposals render cleanly.
242
+ */
243
+ export function formatGateDecisionSummary(raw) {
244
+ if (typeof raw !== "object" || raw === null)
245
+ return "";
246
+ const d = raw;
247
+ const outcome = typeof d.outcome === "string" ? d.outcome : undefined;
248
+ if (!outcome)
249
+ return "";
250
+ const reason = typeof d.reason === "string" && d.reason.length > 0 ? `:${d.reason}` : "";
251
+ const cmp = formatGateThresholdComparison(d);
252
+ return `gate=${outcome}${reason}${cmp ? ` (${cmp})` : ""}`;
253
+ }
254
+ /**
255
+ * Reconstruct the threshold comparison the gate applied, when both sides are
256
+ * present (e.g. confidence 0.72 vs. autoAccept 0.90 → "0.72 < 0.90"). Returns
257
+ * the empty string when the decision lacks the operands.
258
+ */
259
+ function formatGateThresholdComparison(d) {
260
+ const thresholds = (typeof d.thresholds === "object" && d.thresholds !== null ? d.thresholds : {});
261
+ const confidence = typeof d.confidence === "number" ? d.confidence : undefined;
262
+ const autoAccept = typeof thresholds.autoAccept === "number" ? thresholds.autoAccept : undefined;
263
+ if (confidence !== undefined && autoAccept !== undefined) {
264
+ const op = confidence >= autoAccept ? ">=" : "<";
265
+ return `${confidence.toFixed(2)} ${op} ${autoAccept.toFixed(2)}`;
266
+ }
267
+ // Drain bands: when the measured value is present, render the full comparison
268
+ // ("210 > 200" / "1 < 5"); otherwise fall back to the bound alone (#577).
269
+ const measured = typeof d.measured === "number" ? d.measured : undefined;
270
+ if (typeof thresholds.maxDiffLines === "number") {
271
+ return measured !== undefined
272
+ ? `${measured} > ${thresholds.maxDiffLines}`
273
+ : `maxDiffLines=${thresholds.maxDiffLines}`;
274
+ }
275
+ if (typeof thresholds.minContentLines === "number") {
276
+ return measured !== undefined
277
+ ? `${measured} < ${thresholds.minContentLines}`
278
+ : `minContentLines=${thresholds.minContentLines}`;
279
+ }
280
+ return "";
281
+ }
228
282
  export function formatProposalListPlain(r) {
229
283
  const proposals = Array.isArray(r.proposals) ? r.proposals : [];
230
284
  const total = typeof r.totalCount === "number" ? r.totalCount : proposals.length;
@@ -238,7 +292,11 @@ export function formatProposalListPlain(r) {
238
292
  const status = String(p.status ?? "?");
239
293
  const source = String(p.source ?? "?");
240
294
  const created = String(p.createdAt ?? "?");
241
- lines.push(`${id} [${status}] ${ref} source=${source} ${created}`);
295
+ // #577: surface the gate verdict inline so the queue explains itself
296
+ // ("deferred: below-threshold"). Legacy proposals carry no gateDecision.
297
+ const gate = formatGateDecisionSummary(p.gateDecision);
298
+ const gateSuffix = gate ? ` ${gate}` : "";
299
+ lines.push(`${id} [${status}] ${ref} source=${source} ${created}${gateSuffix}`);
242
300
  }
243
301
  return lines.join("\n").trimEnd();
244
302
  }
@@ -255,6 +313,26 @@ export function formatProposalShowPlain(r) {
255
313
  lines.push(`createdAt: ${String(p.createdAt)}`);
256
314
  if (p.updatedAt)
257
315
  lines.push(`updatedAt: ${String(p.updatedAt)}`);
316
+ if (typeof p.confidence === "number")
317
+ lines.push(`confidence: ${p.confidence.toFixed(2)}`);
318
+ // #577: gate decision (auto-accepted / deferred / auto-rejected + reason +
319
+ // thresholds). Absent on legacy proposals — render "unknown" so the field is
320
+ // always present and the operator never sees a silent gap.
321
+ const gate = p.gateDecision;
322
+ if (gate && typeof gate.outcome === "string") {
323
+ lines.push(`gate.decision: ${String(gate.outcome)}`);
324
+ lines.push(`gate.reason: ${gate.reason ? String(gate.reason) : "unknown"}`);
325
+ const cmp = formatGateThresholdComparison(gate);
326
+ if (cmp)
327
+ lines.push(`gate.thresholds: ${cmp}`);
328
+ if (gate.gate)
329
+ lines.push(`gate.by: ${String(gate.gate)}`);
330
+ if (gate.decidedAt)
331
+ lines.push(`gate.decidedAt: ${String(gate.decidedAt)}`);
332
+ }
333
+ else {
334
+ lines.push("gate.decision: unknown");
335
+ }
258
336
  const review = p.review;
259
337
  if (review) {
260
338
  lines.push(`review.outcome: ${String(review.outcome ?? "?")}`);
@@ -265,12 +343,29 @@ export function formatProposalShowPlain(r) {
265
343
  }
266
344
  const validation = r.validation;
267
345
  if (validation) {
268
- const ok = validation.ok === true;
269
346
  const findings = Array.isArray(validation.findings) ? validation.findings : [];
347
+ // Partition findings by severity. `severity: "warn"` findings are
348
+ // non-blocking (the validator reports `ok: true` for a warn-only proposal),
349
+ // so they must read as advisory — a distinct icon/label from blocking errors.
350
+ const warnings = findings.filter((f) => f.severity === "warn");
351
+ const errors = findings.filter((f) => f.severity !== "warn");
270
352
  lines.push("");
271
- lines.push(`validation: ${ok ? "ok" : `${findings.length} finding(s)`}`);
272
- for (const f of findings) {
273
- lines.push(` - [${String(f.kind)}] ${String(f.message)}`);
353
+ if (errors.length > 0) {
354
+ const warnSuffix = warnings.length > 0 ? `, ${warnings.length} warning(s)` : "";
355
+ lines.push(`✗ invalid (${errors.length} error(s)${warnSuffix})`);
356
+ }
357
+ else if (warnings.length > 0) {
358
+ lines.push(`✓ valid (${warnings.length} warning(s))`);
359
+ }
360
+ else {
361
+ lines.push("✓ valid");
362
+ }
363
+ // Errors first (blocking), then warnings (advisory, non-blocking).
364
+ for (const f of errors) {
365
+ lines.push(` ✗ error [${String(f.kind)}] ${String(f.message)}`);
366
+ }
367
+ for (const f of warnings) {
368
+ lines.push(` ⚠ warning [${String(f.kind)}] ${String(f.message)} (non-blocking)`);
274
369
  }
275
370
  }
276
371
  const payload = p.payload;
@@ -1035,18 +1130,6 @@ export function formatWorkflowCreatePlain(r) {
1035
1130
  }
1036
1131
  return null;
1037
1132
  }
1038
- export function formatVaultCreatePlain(r) {
1039
- return `Created vault ${String(r.ref ?? "?")} at ${String(r.path ?? "?")}`;
1040
- }
1041
- export function formatVaultSetPlain(r) {
1042
- return `Set ${String(r.key ?? "?")} in ${String(r.ref ?? "?")} (value not displayed)`;
1043
- }
1044
- export function formatVaultUnsetPlain(r) {
1045
- const removed = r.removed === true;
1046
- return removed
1047
- ? `Removed ${String(r.key ?? "?")} from ${String(r.ref ?? "?")}`
1048
- : `Key ${String(r.key ?? "?")} was not present in ${String(r.ref ?? "?")}`;
1049
- }
1050
1133
  export function formatWorkflowResumePlain(r) {
1051
1134
  return formatWorkflowStatusPlain(r) ?? `Resumed workflow run ${String(r.id ?? r.runId ?? "?")}`;
1052
1135
  }
@@ -2,6 +2,5 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  // Output text formatter for `akm history` — paired with the shape in shapes/history.ts.
5
- import { formatHistoryPlain } from "./helpers";
6
- import { registerTextFormatter } from "./registry";
7
- registerTextFormatter("history", (r) => formatHistoryPlain(r));
5
+ import { formatHistoryPlain } from "./helpers.js";
6
+ export const historyFormatters = [{ command: "history", handler: (r) => formatHistoryPlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatImportPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("import", (r) => formatImportPlain(r));
4
+ import { formatImportPlain } from "./helpers.js";
5
+ export const importFormatters = [{ command: "import", handler: (r) => formatImportPlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatIndexPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("index", (r) => formatIndexPlain(r));
4
+ import { formatIndexPlain } from "./helpers.js";
5
+ export const indexFormatters = [{ command: "index", handler: (r) => formatIndexPlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatInfoPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("info", (r) => formatInfoPlain(r));
4
+ import { formatInfoPlain } from "./helpers.js";
5
+ export const infoFormatters = [{ command: "info", handler: (r) => formatInfoPlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatInitPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("init", (r) => formatInitPlain(r));
4
+ import { formatInitPlain } from "./helpers.js";
5
+ export const initFormatters = [{ command: "init", handler: (r) => formatInitPlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatListPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("list", (r) => formatListPlain(r));
4
+ import { formatListPlain } from "./helpers.js";
5
+ export const listFormatters = [{ command: "list", handler: (r) => formatListPlain(r) }];
@@ -0,0 +1,9 @@
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
+ // Output text formatters for `akm reflect` / `akm propose` (#226).
5
+ import { formatProposalProducerPlain } from "../helpers.js";
6
+ export const proposalProducerFormatters = [
7
+ { command: "reflect", handler: (r) => formatProposalProducerPlain("reflect", r) },
8
+ { command: "propose", handler: (r) => formatProposalProducerPlain("propose", r) },
9
+ ];
@@ -0,0 +1,13 @@
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
+ // Output text formatters for `akm proposal *` (#225).
5
+ import { formatProposalAcceptPlain, formatProposalDiffPlain, formatProposalDrainPlain, formatProposalListPlain, formatProposalRejectPlain, formatProposalShowPlain, } from "../helpers.js";
6
+ export const proposalFormatters = [
7
+ { command: "proposal-list", handler: (r) => formatProposalListPlain(r) },
8
+ { command: "proposal-show", handler: (r) => formatProposalShowPlain(r) },
9
+ { command: "proposal-accept", handler: (r) => formatProposalAcceptPlain(r) },
10
+ { command: "proposal-reject", handler: (r) => formatProposalRejectPlain(r) },
11
+ { command: "proposal-diff", handler: (r) => formatProposalDiffPlain(r) },
12
+ { command: "proposal-drain", handler: (r) => formatProposalDrainPlain(r) },
13
+ ];
@@ -2,10 +2,11 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  // Output text formatters for `akm registry *` commands.
5
- import { formatRegistryAddPlain, formatRegistryBuildIndexPlain, formatRegistryListPlain, formatRegistryRemovePlain, formatRegistrySearchPlain, } from "./helpers";
6
- import { registerTextFormatter } from "./registry";
7
- registerTextFormatter("registry-list", (r) => formatRegistryListPlain(r));
8
- registerTextFormatter("registry-add", (r) => formatRegistryAddPlain(r));
9
- registerTextFormatter("registry-remove", (r) => formatRegistryRemovePlain(r));
10
- registerTextFormatter("registry-search", (r, detail) => formatRegistrySearchPlain(r, detail));
11
- registerTextFormatter("registry-build-index", (r) => formatRegistryBuildIndexPlain(r));
5
+ import { formatRegistryAddPlain, formatRegistryBuildIndexPlain, formatRegistryListPlain, formatRegistryRemovePlain, formatRegistrySearchPlain, } from "./helpers.js";
6
+ export const registryCommandFormatters = [
7
+ { command: "registry-list", handler: (r) => formatRegistryListPlain(r) },
8
+ { command: "registry-add", handler: (r) => formatRegistryAddPlain(r) },
9
+ { command: "registry-remove", handler: (r) => formatRegistryRemovePlain(r) },
10
+ { command: "registry-search", handler: (r, detail) => formatRegistrySearchPlain(r, detail) },
11
+ { command: "registry-build-index", handler: (r) => formatRegistryBuildIndexPlain(r) },
12
+ ];
@@ -15,6 +15,18 @@ const TEXT_FORMATTER_REGISTRY = new Map();
15
15
  export function registerTextFormatter(command, handler) {
16
16
  TEXT_FORMATTER_REGISTRY.set(command, handler);
17
17
  }
18
+ /**
19
+ * Register a batch of {@link TextFormatterEntry} definitions in iteration order.
20
+ *
21
+ * This is the explicit-assembly entry point used by `text.ts`: the built-in
22
+ * formatter set is registered by iterating a single explicit list exactly once,
23
+ * with no reliance on module import order.
24
+ */
25
+ export function registerTextFormatters(entries) {
26
+ for (const { command, handler } of entries) {
27
+ TEXT_FORMATTER_REGISTRY.set(command, handler);
28
+ }
29
+ }
18
30
  /**
19
31
  * Remove a previously-registered text formatter. Test-only utility.
20
32
  */
@@ -1,6 +1,7 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatRememberPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("remember", (r) => formatRememberPlain(r));
4
+ import { formatRememberPlain } from "./helpers.js";
5
+ export const rememberFormatters = [
6
+ { command: "remember", handler: (r) => formatRememberPlain(r) },
7
+ ];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatRemovePlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("remove", (r) => formatRemovePlain(r));
4
+ import { formatRemovePlain } from "./helpers.js";
5
+ export const removeFormatters = [{ command: "remove", handler: (r) => formatRemovePlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatSavePlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("save", (r) => formatSavePlain(r));
4
+ import { formatSavePlain } from "./helpers.js";
5
+ export const saveFormatters = [{ command: "save", handler: (r) => formatSavePlain(r) }];
@@ -1,6 +1,7 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatSearchPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("search", (r, detail) => formatSearchPlain(r, detail));
4
+ import { formatSearchPlain } from "./helpers.js";
5
+ export const searchFormatters = [
6
+ { command: "search", handler: (r, detail) => formatSearchPlain(r, detail) },
7
+ ];
@@ -1,6 +1,7 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatShowPlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("show", (r, detail) => formatShowPlain(r, detail));
4
+ import { formatShowPlain } from "./helpers.js";
5
+ export const showFormatters = [
6
+ { command: "show", handler: (r, detail) => formatShowPlain(r, detail) },
7
+ ];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatUpdatePlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("update", (r) => formatUpdatePlain(r));
4
+ import { formatUpdatePlain } from "./helpers.js";
5
+ export const updateFormatters = [{ command: "update", handler: (r) => formatUpdatePlain(r) }];
@@ -1,6 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { formatUpgradePlain } from "./helpers";
5
- import { registerTextFormatter } from "./registry";
6
- registerTextFormatter("upgrade", (r) => formatUpgradePlain(r));
4
+ import { formatUpgradePlain } from "./helpers.js";
5
+ export const upgradeFormatters = [{ command: "upgrade", handler: (r) => formatUpgradePlain(r) }];
@@ -2,14 +2,15 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  // Output text formatters for all `akm wiki *` commands.
5
- import { formatWikiCreatePlain, formatWikiIngestPlain, formatWikiLintPlain, formatWikiListPlain, formatWikiPagesPlain, formatWikiRegisterPlain, formatWikiRemovePlain, formatWikiShowPlain, formatWikiStashPlain, } from "./helpers";
6
- import { registerTextFormatter } from "./registry";
7
- registerTextFormatter("wiki-list", (r) => formatWikiListPlain(r));
8
- registerTextFormatter("wiki-show", (r) => formatWikiShowPlain(r));
9
- registerTextFormatter("wiki-create", (r) => formatWikiCreatePlain(r));
10
- registerTextFormatter("wiki-remove", (r) => formatWikiRemovePlain(r));
11
- registerTextFormatter("wiki-pages", (r) => formatWikiPagesPlain(r));
12
- registerTextFormatter("wiki-stash", (r) => formatWikiStashPlain(r));
13
- registerTextFormatter("wiki-lint", (r) => formatWikiLintPlain(r));
14
- registerTextFormatter("wiki-ingest", (r) => formatWikiIngestPlain(r));
15
- registerTextFormatter("wiki-register", (r) => formatWikiRegisterPlain(r));
5
+ import { formatWikiCreatePlain, formatWikiIngestPlain, formatWikiLintPlain, formatWikiListPlain, formatWikiPagesPlain, formatWikiRegisterPlain, formatWikiRemovePlain, formatWikiShowPlain, formatWikiStashPlain, } from "./helpers.js";
6
+ export const wikiFormatters = [
7
+ { command: "wiki-list", handler: (r) => formatWikiListPlain(r) },
8
+ { command: "wiki-show", handler: (r) => formatWikiShowPlain(r) },
9
+ { command: "wiki-create", handler: (r) => formatWikiCreatePlain(r) },
10
+ { command: "wiki-remove", handler: (r) => formatWikiRemovePlain(r) },
11
+ { command: "wiki-pages", handler: (r) => formatWikiPagesPlain(r) },
12
+ { command: "wiki-stash", handler: (r) => formatWikiStashPlain(r) },
13
+ { command: "wiki-lint", handler: (r) => formatWikiLintPlain(r) },
14
+ { command: "wiki-ingest", handler: (r) => formatWikiIngestPlain(r) },
15
+ { command: "wiki-register", handler: (r) => formatWikiRegisterPlain(r) },
16
+ ];
@@ -2,13 +2,15 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  // Output text formatters for all `akm workflow *` commands.
5
- import { formatWorkflowCreatePlain, formatWorkflowListPlain, formatWorkflowNextPlain, formatWorkflowResumePlain, formatWorkflowStatusPlain, formatWorkflowValidatePlain, } from "./helpers";
6
- import { registerTextFormatter } from "./registry";
7
- registerTextFormatter("workflow-start", (r) => formatWorkflowStatusPlain(r));
8
- registerTextFormatter("workflow-status", (r) => formatWorkflowStatusPlain(r));
9
- registerTextFormatter("workflow-complete", (r) => formatWorkflowStatusPlain(r));
10
- registerTextFormatter("workflow-next", (r) => formatWorkflowNextPlain(r));
11
- registerTextFormatter("workflow-list", (r) => formatWorkflowListPlain(r));
12
- registerTextFormatter("workflow-create", (r) => formatWorkflowCreatePlain(r));
13
- registerTextFormatter("workflow-validate", (r) => formatWorkflowValidatePlain(r));
14
- registerTextFormatter("workflow-resume", (r) => formatWorkflowResumePlain(r));
5
+ import { formatWorkflowCompleteRejectedPlain, formatWorkflowCreatePlain, formatWorkflowListPlain, formatWorkflowNextPlain, formatWorkflowResumePlain, formatWorkflowStatusPlain, formatWorkflowValidatePlain, } from "./helpers.js";
6
+ export const workflowFormatters = [
7
+ { command: "workflow-start", handler: (r) => formatWorkflowStatusPlain(r) },
8
+ { command: "workflow-status", handler: (r) => formatWorkflowStatusPlain(r) },
9
+ { command: "workflow-complete", handler: (r) => formatWorkflowStatusPlain(r) },
10
+ { command: "workflow-complete-rejected", handler: (r) => formatWorkflowCompleteRejectedPlain(r) },
11
+ { command: "workflow-next", handler: (r) => formatWorkflowNextPlain(r) },
12
+ { command: "workflow-list", handler: (r) => formatWorkflowListPlain(r) },
13
+ { command: "workflow-create", handler: (r) => formatWorkflowCreatePlain(r) },
14
+ { command: "workflow-validate", handler: (r) => formatWorkflowValidatePlain(r) },
15
+ { command: "workflow-resume", handler: (r) => formatWorkflowResumePlain(r) },
16
+ ];
@@ -1,41 +1,75 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { getTextFormatterHandler } from "./text/registry";
4
+ import { addFormatters } from "./text/add.js";
5
+ import { cloneFormatters } from "./text/clone.js";
6
+ import { configFormatters } from "./text/config.js";
7
+ import { curateFormatters } from "./text/curate.js";
8
+ import { distillFormatters } from "./text/distill.js";
9
+ import { enableDisableFormatters } from "./text/enable-disable.js";
10
+ import { envFormatters } from "./text/env.js";
11
+ import { eventsFormatters } from "./text/events.js";
12
+ import { feedbackFormatters } from "./text/feedback.js";
13
+ import { historyFormatters } from "./text/history.js";
14
+ import { importFormatters } from "./text/import.js";
15
+ import { indexFormatters } from "./text/index.js";
16
+ import { infoFormatters } from "./text/info.js";
17
+ import { initFormatters } from "./text/init.js";
18
+ import { listFormatters } from "./text/list.js";
19
+ import { proposalProducerFormatters } from "./text/proposal/producer.js";
20
+ import { proposalFormatters } from "./text/proposal/proposal.js";
21
+ import { getTextFormatterHandler, registerTextFormatters } from "./text/registry.js";
22
+ import { registryCommandFormatters } from "./text/registry-commands.js";
23
+ import { rememberFormatters } from "./text/remember.js";
24
+ import { removeFormatters } from "./text/remove.js";
25
+ import { saveFormatters } from "./text/save.js";
26
+ import { searchFormatters } from "./text/search.js";
27
+ import { showFormatters } from "./text/show.js";
28
+ import { updateFormatters } from "./text/update.js";
29
+ import { upgradeFormatters } from "./text/upgrade.js";
30
+ import { wikiFormatters } from "./text/wiki.js";
31
+ import { workflowFormatters } from "./text/workflow.js";
5
32
  // Re-export helpers so existing imports from `text.ts` keep working.
6
- export { formatAddPlain, formatClonePlain, formatConfigPlain, formatCuratePlain, formatDistillPlain, formatEventLine, formatEventsPlain, formatFeedbackPlain, formatHistoryPlain, formatImportPlain, formatIndexPlain, formatInfoPlain, formatInitPlain, formatListPlain, formatProposalAcceptPlain, formatProposalDiffPlain, formatProposalListPlain, formatProposalProducerPlain, formatProposalRejectPlain, formatProposalShowPlain, formatRegistryAddPlain, formatRegistryBuildIndexPlain, formatRegistryListPlain, formatRegistryRemovePlain, formatRegistrySearchPlain, formatRememberPlain, formatRemovePlain, formatSavePlain, formatSearchPlain, formatShowPlain, formatToggleComponentPlain, formatUpdatePlain, formatUpgradePlain, formatVaultCreatePlain, formatVaultListPlain, formatVaultSetPlain, formatVaultUnsetPlain, formatWikiCreatePlain, formatWikiIngestPlain, formatWikiLintPlain, formatWikiListPlain, formatWikiPagesPlain, formatWikiRegisterPlain, formatWikiRemovePlain, formatWikiShowPlain, formatWikiStashPlain, formatWorkflowCreatePlain, formatWorkflowListPlain, formatWorkflowNextPlain, formatWorkflowResumePlain, formatWorkflowStatusPlain, formatWorkflowValidatePlain, } from "./text/helpers";
33
+ export { formatAddPlain, formatClonePlain, formatConfigPlain, formatCuratePlain, formatDistillPlain, formatEventLine, formatEventsPlain, formatFeedbackPlain, formatHistoryPlain, formatImportPlain, formatIndexPlain, formatInfoPlain, formatInitPlain, formatListPlain, formatProposalAcceptPlain, formatProposalDiffPlain, formatProposalListPlain, formatProposalProducerPlain, formatProposalRejectPlain, formatProposalShowPlain, formatRegistryAddPlain, formatRegistryBuildIndexPlain, formatRegistryListPlain, formatRegistryRemovePlain, formatRegistrySearchPlain, formatRememberPlain, formatRemovePlain, formatSavePlain, formatSearchPlain, formatShowPlain, formatToggleComponentPlain, formatUpdatePlain, formatUpgradePlain, formatWikiCreatePlain, formatWikiIngestPlain, formatWikiLintPlain, formatWikiListPlain, formatWikiPagesPlain, formatWikiRegisterPlain, formatWikiRemovePlain, formatWikiShowPlain, formatWikiStashPlain, formatWorkflowCreatePlain, formatWorkflowListPlain, formatWorkflowNextPlain, formatWorkflowResumePlain, formatWorkflowStatusPlain, formatWorkflowValidatePlain, } from "./text/helpers.js";
7
34
  // Re-export registry API so callers can use this module as the single entry
8
35
  // point (backward compat).
9
- export { deregisterTextFormatter, registerTextFormatter } from "./text/registry";
10
- // ── Per-command text formatter modules (self-register at import time) ─────────
11
- // Importing these modules triggers their `registerTextFormatter(...)` calls.
12
- import "./text/init";
13
- import "./text/index";
14
- import "./text/show";
15
- import "./text/search";
16
- import "./text/curate";
17
- import "./text/wiki";
18
- import "./text/workflow";
19
- import "./text/list";
20
- import "./text/add";
21
- import "./text/remove";
22
- import "./text/update";
23
- import "./text/upgrade";
24
- import "./text/clone";
25
- import "./text/history";
26
- import "./text/events";
27
- import "./text/proposal";
28
- import "./text/proposal-producer";
29
- import "./text/distill";
30
- import "./text/info";
31
- import "./text/config";
32
- import "./text/feedback";
33
- import "./text/remember";
34
- import "./text/import";
35
- import "./text/save";
36
- import "./text/enable-disable";
37
- import "./text/registry-commands";
38
- import "./text/vault";
36
+ export { deregisterTextFormatter, registerTextFormatter } from "./text/registry.js";
37
+ // ── Explicit built-in formatter assembly ──────────────────────────────────────
38
+ // Each entry below is a pure exported `TextFormatterEntry[]` from a per-command
39
+ // module. The set is registered ONCE, deterministically, with no reliance on
40
+ // import order. Removing a module from this list removes its registration —
41
+ // and because each name is referenced statically, a deleted export fails to
42
+ // compile instead of silently disappearing at runtime.
43
+ const BUILT_IN_TEXT_FORMATTERS = [
44
+ ...initFormatters,
45
+ ...indexFormatters,
46
+ ...showFormatters,
47
+ ...searchFormatters,
48
+ ...curateFormatters,
49
+ ...wikiFormatters,
50
+ ...workflowFormatters,
51
+ ...listFormatters,
52
+ ...addFormatters,
53
+ ...removeFormatters,
54
+ ...updateFormatters,
55
+ ...upgradeFormatters,
56
+ ...cloneFormatters,
57
+ ...historyFormatters,
58
+ ...eventsFormatters,
59
+ ...proposalFormatters,
60
+ ...proposalProducerFormatters,
61
+ ...distillFormatters,
62
+ ...infoFormatters,
63
+ ...configFormatters,
64
+ ...feedbackFormatters,
65
+ ...rememberFormatters,
66
+ ...importFormatters,
67
+ ...saveFormatters,
68
+ ...enableDisableFormatters,
69
+ ...registryCommandFormatters,
70
+ ...envFormatters,
71
+ ];
72
+ registerTextFormatters(BUILT_IN_TEXT_FORMATTERS);
39
73
  // ── JSONL output (unchanged — not part of the formatPlain dispatch) ───────────
40
74
  export function outputJsonl(command, shaped) {
41
75
  if (command === "search" || command === "registry-search") {