akm-cli 0.7.4 → 0.8.0-rc.10

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 (300) hide show
  1. package/CHANGELOG.md +224 -1
  2. package/README.md +22 -6
  3. package/SECURITY.md +93 -0
  4. package/dist/cli/config-migrate.js +144 -0
  5. package/dist/cli/config-validate.js +39 -0
  6. package/dist/cli/confirm.js +73 -0
  7. package/dist/cli/parse-args.js +133 -0
  8. package/dist/cli/shared.js +129 -0
  9. package/dist/cli.js +2631 -1440
  10. package/dist/commands/add-cli.js +279 -0
  11. package/dist/commands/agent-dispatch.js +110 -0
  12. package/dist/commands/agent-support.js +68 -0
  13. package/dist/commands/completions.js +3 -0
  14. package/dist/commands/config-cli.js +130 -534
  15. package/dist/commands/consolidate.js +2122 -0
  16. package/dist/commands/curate.js +45 -3
  17. package/dist/commands/db-cli.js +23 -0
  18. package/dist/commands/distill-promotion-policy.js +660 -0
  19. package/dist/commands/distill.js +1081 -73
  20. package/dist/commands/env.js +213 -0
  21. package/dist/commands/eval-cases.js +43 -0
  22. package/dist/commands/events.js +15 -24
  23. package/dist/commands/extract-cli.js +127 -0
  24. package/dist/commands/extract-prompt.js +204 -0
  25. package/dist/commands/extract.js +477 -0
  26. package/dist/commands/feedback-cli.js +331 -0
  27. package/dist/commands/graph.js +477 -0
  28. package/dist/commands/health.js +1302 -0
  29. package/dist/commands/help/help-accept.md +12 -0
  30. package/dist/commands/help/help-improve.md +69 -0
  31. package/dist/commands/help/help-proposals.md +18 -0
  32. package/dist/commands/help/help-propose.md +17 -0
  33. package/dist/commands/help/help-reject.md +11 -0
  34. package/dist/commands/history.js +54 -46
  35. package/dist/commands/improve-auto-accept.js +97 -0
  36. package/dist/commands/improve-cli.js +217 -0
  37. package/dist/commands/improve-profiles.js +166 -0
  38. package/dist/commands/improve-result-file.js +167 -0
  39. package/dist/commands/improve.js +2373 -0
  40. package/dist/commands/info.js +5 -2
  41. package/dist/commands/init.js +50 -2
  42. package/dist/commands/installed-stashes.js +102 -139
  43. package/dist/commands/knowledge.js +136 -0
  44. package/dist/commands/lint/agent-linter.js +49 -0
  45. package/dist/commands/lint/base-linter.js +479 -0
  46. package/dist/commands/lint/command-linter.js +49 -0
  47. package/dist/commands/lint/default-linter.js +16 -0
  48. package/dist/commands/lint/env-key-rules.js +154 -0
  49. package/dist/commands/lint/index.js +196 -0
  50. package/dist/commands/lint/knowledge-linter.js +16 -0
  51. package/dist/commands/lint/markdown-insertion.js +343 -0
  52. package/dist/commands/lint/memory-linter.js +61 -0
  53. package/dist/commands/lint/registry.js +36 -0
  54. package/dist/commands/lint/skill-linter.js +45 -0
  55. package/dist/commands/lint/task-linter.js +50 -0
  56. package/dist/commands/lint/types.js +4 -0
  57. package/dist/commands/lint/workflow-linter.js +56 -0
  58. package/dist/commands/lint.js +4 -0
  59. package/dist/commands/migration-help.js +3 -0
  60. package/dist/commands/proposal.js +67 -12
  61. package/dist/commands/propose.js +120 -45
  62. package/dist/commands/reflect.js +1104 -60
  63. package/dist/commands/registry-cli.js +150 -0
  64. package/dist/commands/registry-search.js +5 -2
  65. package/dist/commands/remember-cli.js +257 -0
  66. package/dist/commands/remember.js +70 -7
  67. package/dist/commands/schema-repair.js +203 -0
  68. package/dist/commands/search.js +115 -14
  69. package/dist/commands/secret.js +173 -0
  70. package/dist/commands/self-update.js +3 -0
  71. package/dist/commands/show.js +158 -60
  72. package/dist/commands/source-add.js +17 -45
  73. package/dist/commands/source-clone.js +3 -0
  74. package/dist/commands/source-manage.js +14 -19
  75. package/dist/commands/tasks.js +437 -0
  76. package/dist/commands/url-checker.js +42 -0
  77. package/dist/core/action-contributors.js +28 -0
  78. package/dist/core/asset-ref.js +17 -2
  79. package/dist/core/asset-registry.js +12 -17
  80. package/dist/core/asset-serialize.js +88 -0
  81. package/dist/core/asset-spec.js +67 -1
  82. package/dist/core/common.js +182 -0
  83. package/dist/core/concurrent.js +25 -0
  84. package/dist/core/config-io.js +347 -0
  85. package/dist/core/config-migration.js +622 -0
  86. package/dist/core/config-schema.js +534 -0
  87. package/dist/core/config-sources.js +108 -0
  88. package/dist/core/config-types.js +4 -0
  89. package/dist/core/config-walker.js +337 -0
  90. package/dist/core/config.js +364 -968
  91. package/dist/core/errors.js +42 -20
  92. package/dist/core/events.js +105 -135
  93. package/dist/core/file-lock.js +104 -0
  94. package/dist/core/frontmatter.js +75 -8
  95. package/dist/core/lesson-lint.js +3 -0
  96. package/dist/core/markdown.js +20 -0
  97. package/dist/core/memory-belief.js +62 -0
  98. package/dist/core/memory-contradiction-detect.js +274 -0
  99. package/dist/core/memory-improve.js +806 -0
  100. package/dist/core/parse.js +158 -0
  101. package/dist/core/paths.js +280 -14
  102. package/dist/core/proposal-quality-validators.js +380 -0
  103. package/dist/core/proposal-validators.js +69 -0
  104. package/dist/core/proposals.js +512 -42
  105. package/dist/core/state-db.js +1068 -0
  106. package/dist/core/text-truncation.js +107 -0
  107. package/dist/core/time.js +54 -0
  108. package/dist/core/tty.js +59 -0
  109. package/dist/core/warn.js +64 -1
  110. package/dist/core/write-source.js +3 -0
  111. package/dist/indexer/db-backup.js +391 -0
  112. package/dist/indexer/db-search.js +198 -489
  113. package/dist/indexer/db.js +990 -108
  114. package/dist/indexer/ensure-index.js +136 -0
  115. package/dist/indexer/file-context.js +3 -0
  116. package/dist/indexer/graph-boost.js +376 -101
  117. package/dist/indexer/graph-db.js +391 -0
  118. package/dist/indexer/graph-dedup.js +95 -0
  119. package/dist/indexer/graph-extraction.js +550 -114
  120. package/dist/indexer/index-context.js +4 -0
  121. package/dist/indexer/indexer.js +547 -309
  122. package/dist/indexer/llm-cache.js +52 -0
  123. package/dist/indexer/manifest.js +3 -0
  124. package/dist/indexer/matchers.js +167 -160
  125. package/dist/indexer/memory-inference.js +152 -74
  126. package/dist/indexer/metadata-contributors.js +29 -0
  127. package/dist/indexer/metadata.js +275 -196
  128. package/dist/indexer/path-resolver.js +92 -0
  129. package/dist/indexer/project-context.js +192 -0
  130. package/dist/indexer/ranking-contributors.js +331 -0
  131. package/dist/indexer/ranking.js +81 -0
  132. package/dist/indexer/search-fields.js +5 -9
  133. package/dist/indexer/search-hit-enrichers.js +111 -0
  134. package/dist/indexer/search-source.js +44 -10
  135. package/dist/indexer/semantic-status.js +6 -17
  136. package/dist/indexer/staleness-detect.js +447 -0
  137. package/dist/indexer/usage-events.js +12 -9
  138. package/dist/indexer/walker.js +28 -0
  139. package/dist/integrations/agent/builders.js +135 -0
  140. package/dist/integrations/agent/config.js +122 -230
  141. package/dist/integrations/agent/detect.js +3 -0
  142. package/dist/integrations/agent/index.js +7 -13
  143. package/dist/integrations/agent/model-aliases.js +55 -0
  144. package/dist/integrations/agent/profiles.js +70 -5
  145. package/dist/integrations/agent/prompts.js +250 -36
  146. package/dist/integrations/agent/runner.js +151 -0
  147. package/dist/integrations/agent/sdk-runner.js +126 -0
  148. package/dist/integrations/agent/spawn.js +183 -35
  149. package/dist/integrations/github.js +3 -0
  150. package/dist/integrations/lockfile.js +32 -69
  151. package/dist/integrations/session-logs/index.js +69 -0
  152. package/dist/integrations/session-logs/inline-refs.js +35 -0
  153. package/dist/integrations/session-logs/pre-filter.js +152 -0
  154. package/dist/integrations/session-logs/providers/claude-code.js +282 -0
  155. package/dist/integrations/session-logs/providers/opencode.js +258 -0
  156. package/dist/integrations/session-logs/types.js +4 -0
  157. package/dist/llm/call-ai.js +62 -0
  158. package/dist/llm/client.js +79 -88
  159. package/dist/llm/embedder.js +20 -29
  160. package/dist/llm/embedders/cache.js +3 -7
  161. package/dist/llm/embedders/local.js +42 -1
  162. package/dist/llm/embedders/remote.js +20 -8
  163. package/dist/llm/embedders/types.js +3 -7
  164. package/dist/llm/feature-gate.js +95 -48
  165. package/dist/llm/graph-extract.js +676 -72
  166. package/dist/llm/index-passes.js +44 -29
  167. package/dist/llm/memory-infer.js +80 -71
  168. package/dist/llm/metadata-enhance.js +42 -29
  169. package/dist/llm/prompts/extract-session.md +80 -0
  170. package/dist/llm/prompts/graph-extract-user-prompt.md +35 -0
  171. package/dist/output/cli-hints-full.md +292 -0
  172. package/dist/output/cli-hints-short.md +66 -0
  173. package/dist/output/cli-hints.js +7 -311
  174. package/dist/output/context.js +60 -8
  175. package/dist/output/renderers.js +306 -258
  176. package/dist/output/shapes/curate.js +56 -0
  177. package/dist/output/shapes/distill.js +10 -0
  178. package/dist/output/shapes/env-list.js +19 -0
  179. package/dist/output/shapes/events.js +11 -0
  180. package/dist/output/shapes/helpers.js +424 -0
  181. package/dist/output/shapes/history.js +7 -0
  182. package/dist/output/shapes/passthrough.js +102 -0
  183. package/dist/output/shapes/proposal-accept.js +7 -0
  184. package/dist/output/shapes/proposal-diff.js +7 -0
  185. package/dist/output/shapes/proposal-list.js +7 -0
  186. package/dist/output/shapes/proposal-producer.js +11 -0
  187. package/dist/output/shapes/proposal-reject.js +7 -0
  188. package/dist/output/shapes/proposal-show.js +7 -0
  189. package/dist/output/shapes/registry-search.js +6 -0
  190. package/dist/output/shapes/registry.js +30 -0
  191. package/dist/output/shapes/search.js +6 -0
  192. package/dist/output/shapes/secret-list.js +19 -0
  193. package/dist/output/shapes/show.js +6 -0
  194. package/dist/output/shapes/vault-list.js +19 -0
  195. package/dist/output/shapes.js +51 -511
  196. package/dist/output/text/add.js +6 -0
  197. package/dist/output/text/clone.js +6 -0
  198. package/dist/output/text/config.js +6 -0
  199. package/dist/output/text/curate.js +6 -0
  200. package/dist/output/text/distill.js +7 -0
  201. package/dist/output/text/enable-disable.js +7 -0
  202. package/dist/output/text/events.js +10 -0
  203. package/dist/output/text/feedback.js +6 -0
  204. package/dist/output/text/helpers.js +1039 -0
  205. package/dist/output/text/history.js +7 -0
  206. package/dist/output/text/import.js +6 -0
  207. package/dist/output/text/index.js +6 -0
  208. package/dist/output/text/info.js +6 -0
  209. package/dist/output/text/init.js +6 -0
  210. package/dist/output/text/list.js +6 -0
  211. package/dist/output/text/proposal-producer.js +8 -0
  212. package/dist/output/text/proposal.js +11 -0
  213. package/dist/output/text/registry-commands.js +11 -0
  214. package/dist/output/text/registry.js +30 -0
  215. package/dist/output/text/remember.js +6 -0
  216. package/dist/output/text/remove.js +6 -0
  217. package/dist/output/text/save.js +6 -0
  218. package/dist/output/text/search.js +6 -0
  219. package/dist/output/text/show.js +6 -0
  220. package/dist/output/text/update.js +6 -0
  221. package/dist/output/text/upgrade.js +6 -0
  222. package/dist/output/text/vault.js +16 -0
  223. package/dist/output/text/wiki.js +15 -0
  224. package/dist/output/text/workflow.js +14 -0
  225. package/dist/output/text.js +44 -1093
  226. package/dist/registry/build-index.js +3 -0
  227. package/dist/registry/create-provider-registry.js +3 -0
  228. package/dist/registry/factory.js +4 -1
  229. package/dist/registry/origin-resolve.js +3 -0
  230. package/dist/registry/providers/index.js +3 -0
  231. package/dist/registry/providers/skills-sh.js +71 -50
  232. package/dist/registry/providers/static-index.js +53 -48
  233. package/dist/registry/providers/types.js +3 -24
  234. package/dist/registry/resolve.js +11 -16
  235. package/dist/registry/types.js +3 -0
  236. package/dist/scripts/migrate-storage.js +17750 -0
  237. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
  238. package/dist/scripts/migrations/v16-to-v17.js +141 -0
  239. package/dist/setup/detect.js +3 -0
  240. package/dist/setup/ripgrep-install.js +3 -0
  241. package/dist/setup/ripgrep-resolve.js +3 -0
  242. package/dist/setup/setup.js +775 -37
  243. package/dist/setup/steps.js +3 -15
  244. package/dist/sources/include.js +3 -0
  245. package/dist/sources/provider-factory.js +5 -12
  246. package/dist/sources/provider.js +3 -20
  247. package/dist/sources/providers/filesystem.js +19 -23
  248. package/dist/sources/providers/git.js +179 -20
  249. package/dist/sources/providers/index.js +3 -0
  250. package/dist/sources/providers/install-types.js +3 -13
  251. package/dist/sources/providers/npm.js +3 -4
  252. package/dist/sources/providers/provider-utils.js +3 -0
  253. package/dist/sources/providers/sync-from-ref.js +3 -11
  254. package/dist/sources/providers/tar-utils.js +3 -0
  255. package/dist/sources/providers/website.js +18 -22
  256. package/dist/sources/resolve.js +3 -0
  257. package/dist/sources/types.js +3 -0
  258. package/dist/sources/website-ingest.js +7 -0
  259. package/dist/tasks/backends/cron.js +203 -0
  260. package/dist/tasks/backends/exec-utils.js +28 -0
  261. package/dist/tasks/backends/index.js +24 -0
  262. package/dist/tasks/backends/launchd-template.xml +19 -0
  263. package/dist/tasks/backends/launchd.js +187 -0
  264. package/dist/tasks/backends/schtasks-template.xml +29 -0
  265. package/dist/tasks/backends/schtasks.js +215 -0
  266. package/dist/tasks/parser.js +211 -0
  267. package/dist/tasks/resolveAkmBin.js +87 -0
  268. package/dist/tasks/runner.js +458 -0
  269. package/dist/tasks/schedule.js +227 -0
  270. package/dist/tasks/schema.js +15 -0
  271. package/dist/tasks/validator.js +62 -0
  272. package/dist/version.js +3 -0
  273. package/dist/wiki/index-template.md +12 -0
  274. package/dist/wiki/ingest-workflow-template.md +54 -0
  275. package/dist/wiki/log-template.md +8 -0
  276. package/dist/wiki/schema-template.md +61 -0
  277. package/dist/wiki/wiki-templates.js +15 -0
  278. package/dist/wiki/wiki.js +13 -61
  279. package/dist/workflows/authoring.js +8 -25
  280. package/dist/workflows/cli.js +3 -0
  281. package/dist/workflows/db.js +141 -2
  282. package/dist/workflows/document-cache.js +3 -10
  283. package/dist/workflows/parser.js +3 -0
  284. package/dist/workflows/renderer.js +11 -3
  285. package/dist/workflows/runs.js +91 -89
  286. package/dist/workflows/schema.js +3 -0
  287. package/dist/workflows/scope-key.js +79 -0
  288. package/dist/workflows/validator.js +4 -8
  289. package/dist/workflows/workflow-template.md +24 -0
  290. package/docs/README.md +10 -2
  291. package/docs/data-and-telemetry.md +225 -0
  292. package/docs/migration/release-notes/0.7.0.md +1 -1
  293. package/docs/migration/release-notes/0.7.4.md +1 -1
  294. package/docs/migration/release-notes/0.7.5.md +20 -0
  295. package/docs/migration/release-notes/0.8.0.md +48 -0
  296. package/docs/migration/v0.7-to-v0.8.md +1307 -0
  297. package/package.json +29 -11
  298. package/dist/commands/install-audit.js +0 -381
  299. package/dist/commands/vault.js +0 -333
  300. package/dist/templates/wiki-templates.js +0 -100
@@ -0,0 +1,107 @@
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
+ /**
5
+ * Shared text-truncation heuristics used by `distill` and `consolidate`.
6
+ *
7
+ * Both commands need to recognise when an LLM-produced description string was
8
+ * sliced mid-sentence (typically the model hit its output budget). The two
9
+ * implementations historically maintained overlapping-but-not-identical
10
+ * vocabularies of hanging-connector words, which was a maintenance trap.
11
+ *
12
+ * This module is the single source of truth. `distill` continues to layer its
13
+ * own section-heading regex on top (those patterns are distill-specific and
14
+ * intentionally stay local to that module).
15
+ */
16
+ /**
17
+ * Words that, when ending a sentence, suggest the description was truncated
18
+ * mid-sentence. Prepositions, conjunctions, articles, and auxiliary verbs that
19
+ * almost always have *something* following them in well-formed prose.
20
+ *
21
+ * This is the UNION of the two prior vocabularies used by `distill` and
22
+ * `consolidate` — a superset of both, so behaviour is at least as strict as
23
+ * either previous check.
24
+ *
25
+ * Stored lowercased; callers must lower-case the last word before lookup.
26
+ */
27
+ export const TRUNCATION_TRAILING_WORDS = new Set([
28
+ "a",
29
+ "after",
30
+ "an",
31
+ "and",
32
+ "are",
33
+ "as",
34
+ "at",
35
+ "be",
36
+ "been",
37
+ "before",
38
+ "being",
39
+ "but",
40
+ "by",
41
+ "can",
42
+ "could",
43
+ "did",
44
+ "do",
45
+ "does",
46
+ "for",
47
+ "from",
48
+ "had",
49
+ "has",
50
+ "have",
51
+ "if",
52
+ "in",
53
+ "into",
54
+ "is",
55
+ "may",
56
+ "might",
57
+ "must",
58
+ "of",
59
+ "on",
60
+ "onto",
61
+ "or",
62
+ "per",
63
+ "shall",
64
+ "should",
65
+ "so",
66
+ "than",
67
+ "that",
68
+ "the",
69
+ "to",
70
+ "upon",
71
+ "via",
72
+ "was",
73
+ "were",
74
+ "when",
75
+ "which",
76
+ "while",
77
+ "will",
78
+ "with",
79
+ "would",
80
+ ]);
81
+ /**
82
+ * Returns a reason string when `description` looks truncated mid-sentence;
83
+ * returns `null` if the description appears complete.
84
+ *
85
+ * Heuristics:
86
+ * - Trailing `,`, `;`, `:`, or `+` (operator-style cutoff like `max-width:100% +`)
87
+ * - Trailing ellipsis (`...` or `…`)
88
+ * - Last word matches {@link TRUNCATION_TRAILING_WORDS}
89
+ *
90
+ * Does NOT detect section-heading fragments — that check is distill-specific
91
+ * and lives in `src/commands/distill.ts` (`HEADING_FRAGMENT_PATTERNS`).
92
+ */
93
+ export function detectTruncatedDescription(description) {
94
+ const trimmed = description.trim();
95
+ if (trimmed.length === 0)
96
+ return null; // empty handled elsewhere
97
+ if (/[,;:+]$/.test(trimmed))
98
+ return "ends with trailing punctuation/operator";
99
+ if (/\.{3,}$/.test(trimmed) || /…$/.test(trimmed))
100
+ return "ends with ellipsis";
101
+ const lastWord = trimmed.split(/\s+/).pop() ?? "";
102
+ const normalized = lastWord.toLowerCase();
103
+ if (TRUNCATION_TRAILING_WORDS.has(normalized)) {
104
+ return `ends with hanging connector "${lastWord}"`;
105
+ }
106
+ return null;
107
+ }
@@ -0,0 +1,54 @@
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
+ /**
5
+ * Shared time and date utilities.
6
+ *
7
+ * Centralises parsing of user-facing `--since` values so that all consumers
8
+ * interpret the same set of formats (ISO-8601, epoch ms, plain date strings)
9
+ * consistently without private re-implementations drifting apart.
10
+ */
11
+ import { UsageError } from "./errors";
12
+ // ── Since-flag parsing ───────────────────────────────────────────────────────
13
+ /**
14
+ * Parse a user-supplied `--since` value and return an ISO-8601 timestamp
15
+ * string (e.g. `"2026-01-15T10:30:00.000Z"`).
16
+ *
17
+ * Accepted input formats:
18
+ * - ISO-8601 timestamp (preferred): `"2026-04-01T00:00:00Z"`
19
+ * - Plain date: `"2026-04-01"` (interpreted as start-of-day UTC)
20
+ * - Epoch milliseconds (pure digit string): `"1744329600000"`
21
+ * - Any other value parseable by `new Date()`
22
+ *
23
+ * Callers that need a different wire format (e.g. SQLite `"YYYY-MM-DD HH:MM:SS"`)
24
+ * should convert the returned ISO string themselves.
25
+ *
26
+ * @throws {UsageError} when `since` is empty or cannot be parsed as a date.
27
+ */
28
+ export function parseSinceToIso(since) {
29
+ const trimmed = since.trim();
30
+ if (!trimmed) {
31
+ throw new UsageError("--since cannot be empty.", "INVALID_FLAG_VALUE");
32
+ }
33
+ // Pure-digit input → epoch milliseconds
34
+ if (/^\d+$/.test(trimmed)) {
35
+ const ms = Number.parseInt(trimmed, 10);
36
+ const d = new Date(ms);
37
+ if (Number.isNaN(d.getTime())) {
38
+ throw new UsageError(`Invalid --since value: ${since}`, "INVALID_FLAG_VALUE");
39
+ }
40
+ return d.toISOString();
41
+ }
42
+ const parsed = new Date(trimmed);
43
+ if (Number.isNaN(parsed.getTime())) {
44
+ throw new UsageError(`Invalid --since value: ${since}. Expected ISO timestamp (e.g. 2026-04-01T00:00:00Z) or epoch ms.`, "INVALID_FLAG_VALUE");
45
+ }
46
+ return parsed.toISOString();
47
+ }
48
+ /**
49
+ * Convert an ISO-8601 timestamp string to the SQLite datetime format
50
+ * `"YYYY-MM-DD HH:MM:SS"` used by `datetime('now')`.
51
+ */
52
+ export function isoToSqlite(iso) {
53
+ return iso.replace("T", " ").replace(/\.\d+Z$/, "");
54
+ }
@@ -0,0 +1,59 @@
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
+ /**
5
+ * Terminal-glyph and color gating helpers (#486).
6
+ *
7
+ * Honor the [NO_COLOR](https://no-color.org/) convention — when NO_COLOR is
8
+ * present in the environment (with any value, including empty), the CLI
9
+ * suppresses both ANSI color codes AND decorative emoji glyphs. Emoji often
10
+ * render as garbage in non-Unicode terminals or get logged as literal bytes
11
+ * when output is piped to text aggregators, so we treat them as a subset of
12
+ * "color" decoration.
13
+ *
14
+ * Detection is also automatic on non-TTY stderr (output piped or redirected
15
+ * to a file), where decorative glyphs add nothing.
16
+ */
17
+ /**
18
+ * Returns true when decorative glyphs and color codes should be emitted.
19
+ * False when NO_COLOR is set or stderr is not a TTY (unless FORCE_COLOR
20
+ * overrides per the de-facto Node convention).
21
+ */
22
+ export function shouldDecorate() {
23
+ if (process.env.NO_COLOR !== undefined)
24
+ return false;
25
+ if (process.env.FORCE_COLOR !== undefined && process.env.FORCE_COLOR !== "" && process.env.FORCE_COLOR !== "0") {
26
+ return true;
27
+ }
28
+ return process.stderr.isTTY === true;
29
+ }
30
+ // Map known decorative emoji to plain ASCII fallbacks. Anything not listed
31
+ // is still removed by the catch-all sweep below when decoration is off.
32
+ const EMOJI_FALLBACKS = [
33
+ [/\u{1F44B}\s*/gu, ""], // wave (with trailing space)
34
+ [/✓/g, "[ok]"],
35
+ [/✗/g, "[x]"],
36
+ [/✘/g, "[x]"],
37
+ [/⚠️?/g, "[!]"],
38
+ [/\u{1F4DA}\s*/gu, ""], // books
39
+ ];
40
+ /**
41
+ * If decoration is disabled, replace known emoji with ASCII fallbacks and
42
+ * strip any remaining pictograph code points. If decoration is enabled,
43
+ * return the input unchanged.
44
+ */
45
+ export function plainize(text) {
46
+ if (shouldDecorate())
47
+ return text;
48
+ let out = text;
49
+ for (const [pattern, repl] of EMOJI_FALLBACKS) {
50
+ out = out.replace(pattern, repl);
51
+ }
52
+ // Catch-all for unmapped pictographs. Future-proof when new emoji are added
53
+ // to call sites without updating the explicit map.
54
+ out = out.replace(/[\u{1F300}-\u{1FAFF}]/gu, "");
55
+ // Collapse runs of whitespace introduced by emoji removal, but preserve
56
+ // intentional leading indentation. Only collapses interior runs.
57
+ out = out.replace(/(\S)[ \t]{2,}/g, "$1 ");
58
+ return out;
59
+ }
package/dist/core/warn.js CHANGED
@@ -1,12 +1,22 @@
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/.
1
4
  /**
2
- * Module-level quiet/verbose flags for stderr warning gating.
5
+ * Module-level quiet/verbose flags and optional file sink for stderr output.
3
6
  *
4
7
  * `quiet` is controlled by the CLI `--quiet`/`-q` flag.
5
8
  * `verbose` is controlled by the CLI `--verbose` flag, with `AKM_VERBOSE`
6
9
  * (env var) winning regardless: env > flag > default (false).
10
+ *
11
+ * Call `setLogFile(path)` to tee all warn/error/info output to a file in
12
+ * addition to stderr. The file sink is written even when `--quiet` suppresses
13
+ * console output, so logs remain available for post-run inspection.
7
14
  */
15
+ import fs from "node:fs";
16
+ import path from "node:path";
8
17
  let quiet = false;
9
18
  let verbose = false;
19
+ let logFilePath;
10
20
  export function setQuiet(value) {
11
21
  quiet = value;
12
22
  }
@@ -51,15 +61,68 @@ export function isVerbose() {
51
61
  return false;
52
62
  return verbose;
53
63
  }
64
+ /**
65
+ * Direct all warn/error/info output to `filePath` in addition to stderr.
66
+ * The directory is created if it does not exist. Pass `undefined` to disable.
67
+ * The file is written even when `--quiet` suppresses console output.
68
+ */
69
+ export function setLogFile(filePath) {
70
+ logFilePath = filePath;
71
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
72
+ }
73
+ export function clearLogFile() {
74
+ logFilePath = undefined;
75
+ }
76
+ export function getLogFile() {
77
+ return logFilePath;
78
+ }
79
+ function appendToLogFile(level, args) {
80
+ if (!logFilePath)
81
+ return;
82
+ const ts = new Date().toISOString();
83
+ const msg = args.map((a) => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
84
+ try {
85
+ fs.appendFileSync(logFilePath, `[${ts}] [${level}] ${msg}\n`);
86
+ }
87
+ catch (e) {
88
+ // Log file write failed — emit directly to stderr so the message is not lost.
89
+ process.stderr.write(`[akm:warn] log-file write failed (${logFilePath}): ${e}\n`);
90
+ process.stderr.write(`[${ts}] [${level}] ${msg}\n`);
91
+ }
92
+ }
93
+ /**
94
+ * Emit an info/progress line to stderr unless --quiet is active.
95
+ * Always written to the log file if one is active.
96
+ * Use for progress counters and status lines (replaces console.error used for progress).
97
+ */
98
+ export function info(...args) {
99
+ appendToLogFile("INFO", args);
100
+ if (!quiet) {
101
+ console.warn(...args);
102
+ }
103
+ }
54
104
  /**
55
105
  * Emit a warning to stderr unless --quiet is active.
106
+ * Always written to the log file if one is active.
56
107
  * Drop-in replacement for console.warn() across the codebase.
57
108
  */
58
109
  export function warn(...args) {
110
+ appendToLogFile("WARN", args);
59
111
  if (!quiet) {
60
112
  console.warn(...args);
61
113
  }
62
114
  }
115
+ /**
116
+ * Emit an error to stderr unless --quiet is active.
117
+ * Always written to the log file if one is active.
118
+ * Drop-in replacement for console.error() used for diagnostic failures.
119
+ */
120
+ export function error(...args) {
121
+ appendToLogFile("ERROR", args);
122
+ if (!quiet) {
123
+ console.error(...args);
124
+ }
125
+ }
63
126
  /**
64
127
  * Emit a warning only when verbose output is requested. Use for noisy
65
128
  * per-item diagnostics that should be replaced by a one-line summary at
@@ -1,3 +1,6 @@
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/.
1
4
  /**
2
5
  * write-source — the only place in the codebase that branches on `source.kind`.
3
6
  *