akm-cli 0.9.0-rc.2 → 0.9.0-rc.4

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 (115) hide show
  1. package/CHANGELOG.md +40 -12
  2. package/README.md +7 -8
  3. package/SECURITY.md +5 -3
  4. package/dist/akm +44 -33
  5. package/dist/akm-migrate-storage +44 -33
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/improve-strategies/catchup.json +3 -1
  8. package/dist/assets/improve-strategies/consolidate.json +3 -1
  9. package/dist/assets/improve-strategies/frequent.json +3 -1
  10. package/dist/assets/improve-strategies/graph-refresh.json +3 -1
  11. package/dist/assets/improve-strategies/memory-focus.json +4 -1
  12. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -0
  13. package/dist/assets/improve-strategies/quick.json +3 -1
  14. package/dist/assets/improve-strategies/recombine-only.json +2 -0
  15. package/dist/assets/improve-strategies/reflect-distill.json +1 -0
  16. package/dist/assets/improve-strategies/synthesize.json +2 -0
  17. package/dist/assets/tasks/core/backup.yml +2 -2
  18. package/dist/cli/config-migrate.js +554 -26
  19. package/dist/cli.js +28 -11
  20. package/dist/commands/backup-cli.js +6 -4
  21. package/dist/commands/config-cli.js +10 -3
  22. package/dist/commands/feedback-cli.js +24 -7
  23. package/dist/commands/health/checks.js +94 -15
  24. package/dist/commands/health/html-report.js +23 -2
  25. package/dist/commands/health/improve-metrics.js +45 -6
  26. package/dist/commands/health/md-report.js +10 -1
  27. package/dist/commands/health/surfaces.js +2 -1
  28. package/dist/commands/health/windows.js +1 -1
  29. package/dist/commands/health.js +1 -1
  30. package/dist/commands/improve/anti-collapse.js +3 -3
  31. package/dist/commands/improve/collapse-detector.js +5 -5
  32. package/dist/commands/improve/consolidate.js +123 -66
  33. package/dist/commands/improve/distill/promote-memory.js +8 -6
  34. package/dist/commands/improve/distill/quality-gate.js +1 -1
  35. package/dist/commands/improve/distill-guards.js +1 -1
  36. package/dist/commands/improve/distill-promotion-policy.js +32 -26
  37. package/dist/commands/improve/distill.js +52 -36
  38. package/dist/commands/improve/eligibility.js +9 -8
  39. package/dist/commands/improve/extract-prompt.js +2 -2
  40. package/dist/commands/improve/extract.js +43 -11
  41. package/dist/commands/improve/improve-auto-accept.js +14 -28
  42. package/dist/commands/improve/improve-cli.js +4 -2
  43. package/dist/commands/improve/improve-strategies.js +2 -1
  44. package/dist/commands/improve/improve.js +49 -8
  45. package/dist/commands/improve/loop-stages.js +11 -6
  46. package/dist/commands/improve/preparation.js +51 -17
  47. package/dist/commands/improve/procedural.js +10 -6
  48. package/dist/commands/improve/recombine.js +31 -7
  49. package/dist/commands/improve/reflect.js +24 -14
  50. package/dist/commands/improve/salience.js +5 -1
  51. package/dist/commands/improve/source-identity.js +43 -0
  52. package/dist/commands/migrate-cli.js +36 -0
  53. package/dist/commands/mv-cli.js +647 -258
  54. package/dist/commands/proposal/drain.js +16 -4
  55. package/dist/commands/proposal/proposal-cli.js +3 -2
  56. package/dist/commands/proposal/proposal.js +16 -55
  57. package/dist/commands/proposal/repository.js +664 -58
  58. package/dist/commands/read/curate.js +4 -2
  59. package/dist/commands/read/knowledge.js +4 -1
  60. package/dist/commands/read/search.js +6 -2
  61. package/dist/commands/read/show.js +8 -7
  62. package/dist/commands/sources/self-update.js +156 -112
  63. package/dist/commands/sources/sources-cli.js +7 -2
  64. package/dist/commands/tasks/default-tasks.js +5 -5
  65. package/dist/commands/tasks/tasks-cli.js +7 -3
  66. package/dist/commands/tasks/tasks.js +261 -68
  67. package/dist/core/common.js +36 -3
  68. package/dist/core/config/config-io.js +2 -2
  69. package/dist/core/config/config-schema.js +15 -3
  70. package/dist/core/config/config.js +14 -13
  71. package/dist/core/file-lock.js +2 -2
  72. package/dist/core/improve-result.js +87 -7
  73. package/dist/core/migration-backup.js +816 -171
  74. package/dist/core/migration-operation.js +44 -0
  75. package/dist/core/state/migrations.js +4 -7
  76. package/dist/core/state-db.js +23 -7
  77. package/dist/core/write-source.js +86 -18
  78. package/dist/indexer/db/db.js +109 -53
  79. package/dist/indexer/index-writer-lock.js +38 -37
  80. package/dist/indexer/index-written-assets.js +73 -56
  81. package/dist/indexer/indexer.js +5 -1
  82. package/dist/indexer/search/search-source.js +2 -2
  83. package/dist/indexer/usage/usage-events.js +8 -2
  84. package/dist/integrations/agent/engine-resolution.js +14 -7
  85. package/dist/scripts/migrate-storage.js +887 -992
  86. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +494 -574
  87. package/dist/setup/detected-engines.js +7 -13
  88. package/dist/setup/engine-config.js +14 -4
  89. package/dist/setup/setup.js +1 -1
  90. package/dist/setup/steps/connection.js +1 -1
  91. package/dist/setup/steps/tasks.js +1 -1
  92. package/dist/sources/providers/git-stash.js +58 -21
  93. package/dist/sources/providers/git.js +1 -1
  94. package/dist/storage/engines/sqlite-migrations.js +138 -3
  95. package/dist/storage/repositories/events-repository.js +24 -0
  96. package/dist/storage/repositories/proposals-repository.js +14 -0
  97. package/dist/storage/repositories/task-history-repository.js +30 -3
  98. package/dist/tasks/backends/cron.js +71 -38
  99. package/dist/tasks/backends/exec-utils.js +55 -3
  100. package/dist/tasks/backends/launchd.js +241 -50
  101. package/dist/tasks/backends/schtasks.js +434 -59
  102. package/dist/tasks/command-executable.js +93 -0
  103. package/dist/tasks/embedded.js +2 -0
  104. package/dist/tasks/parser.js +142 -6
  105. package/dist/tasks/resolve-akm-bin.js +19 -4
  106. package/dist/tasks/runner.js +258 -93
  107. package/dist/tasks/schedule.js +108 -19
  108. package/dist/tasks/scheduler-invocation.js +86 -0
  109. package/dist/tasks/task-id.js +37 -0
  110. package/dist/workflows/db.js +24 -13
  111. package/dist/workflows/validator.js +24 -2
  112. package/docs/README.md +103 -0
  113. package/docs/migration/release-notes/0.9.0.md +28 -9
  114. package/docs/migration/v0.8-to-v0.9.md +186 -26
  115. package/package.json +2 -3
@@ -5,7 +5,7 @@ import { randomUUID } from "node:crypto";
5
5
  import fs from "node:fs";
6
6
  import path from "node:path";
7
7
  import { openDatabase } from "../storage/database.js";
8
- import { isProcessAlive } from "./common.js";
8
+ import { isProcessAlive, MAX_LOCK_METADATA_BYTES, readTextFileDescriptorWithLimit } from "./common.js";
9
9
  function readLockSnapshot(lockPath) {
10
10
  let fd;
11
11
  try {
@@ -17,7 +17,7 @@ function readLockSnapshot(lockPath) {
17
17
  throw err;
18
18
  }
19
19
  try {
20
- const rawContent = fs.readFileSync(fd, "utf8");
20
+ const rawContent = readTextFileDescriptorWithLimit(fd, MAX_LOCK_METADATA_BYTES, "Lock metadata", lockPath);
21
21
  const stat = fs.fstatSync(fd);
22
22
  return {
23
23
  rawContent,
@@ -44,8 +44,26 @@ const COMMON_FIELDS = [
44
44
  "sync",
45
45
  "terminated",
46
46
  ];
47
- const V1_FIELDS = new Set([...COMMON_FIELDS, "profile", "profileFilteredRefs"]);
47
+ const V1_FIELDS = new Set([...COMMON_FIELDS, "profile", "profileFilteredRefs", "stalenessDetection"]);
48
48
  const V2_FIELDS = new Set([...COMMON_FIELDS, "strategy", "strategyFilteredRefs"]);
49
+ const STALENESS_DETECTION_FIELDS = new Set([
50
+ "considered",
51
+ "deprecated",
52
+ "confirmed",
53
+ "skipped",
54
+ "durationMs",
55
+ "warnings",
56
+ ]);
57
+ const INTERRUPTED_V1_FIELDS = new Set([
58
+ "schemaVersion",
59
+ "ok",
60
+ "profile",
61
+ "scope",
62
+ "dryRun",
63
+ "plannedRefs",
64
+ "actions",
65
+ "terminated",
66
+ ]);
49
67
  function fail(message) {
50
68
  throw new Error(`invalid improve-result envelope: ${message}`);
51
69
  }
@@ -57,6 +75,33 @@ function requireExactFields(value, allowed) {
57
75
  if (unknown.length > 0)
58
76
  fail(`unknown field${unknown.length === 1 ? "" : "s"}: ${unknown.sort().join(", ")}`);
59
77
  }
78
+ function isKnownInterruptedV1Partial(value) {
79
+ if (Object.keys(value).some((key) => !INTERRUPTED_V1_FIELDS.has(key)))
80
+ return false;
81
+ if (value.ok !== false || typeof value.dryRun !== "boolean")
82
+ return false;
83
+ if (value.profile !== undefined && typeof value.profile !== "string")
84
+ return false;
85
+ if (!Array.isArray(value.plannedRefs) || value.plannedRefs.length !== 0)
86
+ return false;
87
+ if (!Array.isArray(value.actions) || value.actions.length !== 0)
88
+ return false;
89
+ if (!isRecord(value.scope))
90
+ return false;
91
+ if (Object.keys(value.scope).some((key) => key !== "mode" && key !== "value"))
92
+ return false;
93
+ if (value.scope.mode !== "all" && value.scope.mode !== "type" && value.scope.mode !== "ref")
94
+ return false;
95
+ if (value.scope.value !== undefined && typeof value.scope.value !== "string")
96
+ return false;
97
+ if (!isRecord(value.terminated))
98
+ return false;
99
+ if (Object.keys(value.terminated).some((key) => !["reason", "at", "errorMessage"].includes(key)))
100
+ return false;
101
+ if (typeof value.terminated.reason !== "string" || typeof value.terminated.at !== "string")
102
+ return false;
103
+ return value.terminated.errorMessage === undefined || typeof value.terminated.errorMessage === "string";
104
+ }
60
105
  function validateCommon(value) {
61
106
  if (typeof value.ok !== "boolean")
62
107
  fail("ok must be a boolean");
@@ -131,6 +176,32 @@ function validateCommon(value) {
131
176
  if (value[field] !== undefined && !isRecord(value[field]))
132
177
  fail(`${field} must be an object`);
133
178
  }
179
+ if (isRecord(value.terminated)) {
180
+ requireExactFields(value.terminated, new Set(["reason", "at", "errorMessage"]));
181
+ if (typeof value.terminated.reason !== "string" || typeof value.terminated.at !== "string") {
182
+ fail("terminated.reason and terminated.at must be strings");
183
+ }
184
+ if (value.terminated.errorMessage !== undefined && typeof value.terminated.errorMessage !== "string") {
185
+ fail("terminated.errorMessage must be a string when present");
186
+ }
187
+ }
188
+ }
189
+ function validateV1StalenessDetection(value) {
190
+ if (value === undefined)
191
+ return;
192
+ if (!isRecord(value))
193
+ fail("stalenessDetection must be an object");
194
+ const unknown = Object.keys(value).filter((key) => !STALENESS_DETECTION_FIELDS.has(key));
195
+ if (unknown.length > 0) {
196
+ fail(`stalenessDetection has unknown field${unknown.length === 1 ? "" : "s"}: ${unknown.sort().join(", ")}`);
197
+ }
198
+ for (const field of ["considered", "deprecated", "confirmed", "skipped", "durationMs"]) {
199
+ if (typeof value[field] !== "number")
200
+ fail(`stalenessDetection.${field} must be a number`);
201
+ }
202
+ if (!Array.isArray(value.warnings) || value.warnings.some((warning) => typeof warning !== "string")) {
203
+ fail("stalenessDetection.warnings must be an array of strings");
204
+ }
134
205
  }
135
206
  /** Decode the persisted public v1/v2 contract without guessing across versions. */
136
207
  export function decodeImproveResult(input) {
@@ -146,17 +217,25 @@ export function decodeImproveResult(input) {
146
217
  if (!isRecord(parsed))
147
218
  fail("root must be an object");
148
219
  if (parsed.schemaVersion === 1) {
149
- requireExactFields(parsed, V1_FIELDS);
150
- validateCommon(parsed);
151
- if (parsed.profile !== undefined && typeof parsed.profile !== "string")
220
+ let normalized = parsed;
221
+ let normalizedLegacyPartial = false;
222
+ if (normalized.memorySummary === undefined && isKnownInterruptedV1Partial(normalized)) {
223
+ normalized = { ...normalized, memorySummary: { eligible: 0, derived: 0 } };
224
+ normalizedLegacyPartial = true;
225
+ }
226
+ requireExactFields(normalized, V1_FIELDS);
227
+ validateCommon(normalized);
228
+ validateV1StalenessDetection(normalized.stalenessDetection);
229
+ if (normalized.profile !== undefined && typeof normalized.profile !== "string")
152
230
  fail("profile must be a string");
153
- if (parsed.profileFilteredRefs !== undefined && !Array.isArray(parsed.profileFilteredRefs)) {
231
+ if (normalized.profileFilteredRefs !== undefined && !Array.isArray(normalized.profileFilteredRefs)) {
154
232
  fail("profileFilteredRefs must be an array");
155
233
  }
156
234
  return {
157
- envelope: parsed,
235
+ envelope: normalized,
158
236
  strategy: null,
159
- legacyProfile: typeof parsed.profile === "string" ? parsed.profile : null,
237
+ legacyProfile: typeof normalized.profile === "string" ? normalized.profile : null,
238
+ normalizedLegacyPartial,
160
239
  };
161
240
  }
162
241
  if (parsed.schemaVersion === 2) {
@@ -172,6 +251,7 @@ export function decodeImproveResult(input) {
172
251
  envelope: parsed,
173
252
  strategy: parsed.strategy,
174
253
  legacyProfile: null,
254
+ normalizedLegacyPartial: false,
175
255
  };
176
256
  }
177
257
  fail(`unsupported schemaVersion: ${String(parsed.schemaVersion)}`);