akm-cli 0.9.6 → 0.9.7

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 (31) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/dist/assets/hints/cli-hints-full.md +3 -3
  3. package/dist/assets/improve-strategies/catchup.json +40 -11
  4. package/dist/assets/improve-strategies/thorough.json +45 -7
  5. package/dist/assets/tasks/improve/akm-improve-frequent.yml +2 -2
  6. package/dist/commands/agent/contribute-cli.js +11 -0
  7. package/dist/commands/improve/improve-cli.js +1 -1
  8. package/dist/commands/improve/improve-strategies.js +0 -4
  9. package/dist/commands/improve/memory/memory-improve.js +2 -1
  10. package/dist/commands/improve/preparation.js +1 -1
  11. package/dist/commands/improve/reflect.js +1 -1
  12. package/dist/commands/lint/base-linter.js +141 -18
  13. package/dist/commands/lint/index.js +17 -4
  14. package/dist/commands/read/curate.js +47 -0
  15. package/dist/commands/read/search-cli.js +24 -1
  16. package/dist/core/asset/asset-placement.js +13 -2
  17. package/dist/core/asset/frontmatter.js +116 -0
  18. package/dist/core/asset/memory-archive.js +97 -0
  19. package/dist/core/config/engine-semantics.js +0 -2
  20. package/dist/scripts/akm-migrate-node.js +13 -7
  21. package/dist/scripts/akm-migrate.js +13 -7
  22. package/dist/sources/snapshot-fetchers/website-ingest.js +126 -0
  23. package/dist/storage/repositories/index-connection.js +45 -3
  24. package/dist/tasks/backends/cron.js +49 -9
  25. package/dist/tasks/resolve-akm-bin.js +17 -2
  26. package/dist/tasks/scheduler-invocation.js +8 -1
  27. package/dist/tasks/source/parse-task-source.js +23 -9
  28. package/docs/reference/cli.md +5 -1
  29. package/package.json +1 -1
  30. package/dist/assets/improve-strategies/frequent.json +0 -15
  31. package/dist/assets/improve-strategies/memory-focus.json +0 -15
package/CHANGELOG.md CHANGED
@@ -4,6 +4,196 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [0.9.7] - 2026-08-31
8
+
9
+ ### Added
10
+
11
+ - **`akm curate --pack <tokens>` (#746).** Packs the ranked stash hits' full
12
+ content into a single token-budgeted blob instead of returning refs the
13
+ caller has to follow up on with N separate `akm show` calls. Content is
14
+ resolved through the same path `akm show` uses, so a `ref#fragment` hit
15
+ packs just that section. Drops whole assets from the tail of the ranked
16
+ list first; only a single highest-rank hit that alone exceeds the budget
17
+ is truncated. Registry hits are never packed — that separation stays
18
+ opt-in and there is no flag to override it. Named `--pack` rather than
19
+ `--budget` because the workflow asset schema already uses `budget` for
20
+ run-cost caps.
21
+
22
+ - **`llms.txt`-aware website ingestion (#749).** `akm bundle add` against an
23
+ origin root now probes `<origin>/llms.txt` first and, when present, uses
24
+ that author-curated link list as the crawl frontier instead of discovering
25
+ links by parsing HTML. Each linked page still flows through the same
26
+ robots-compliant, host-guarded, content-extracting fetch as before, so
27
+ ingested pages stay individually addressable. Off-origin manifest entries
28
+ are dropped. The probe is restricted to origin-root URLs, so adding a
29
+ specific page still fetches that page. Sites without the file fall through
30
+ to the existing crawler unchanged. `llms-full.txt` is deliberately not
31
+ read: its `## <path>` separators are ambiguous against real page content.
32
+
33
+ ### Changed
34
+
35
+ - **The improve-strategy presets were reviewed as a set (#878).** The
36
+ investigation first believed `thorough` silently ran without validation;
37
+ that was wrong — every strategy deep-merges onto `default` before
38
+ resolving, so the old asset behaved correctly. What was real: `thorough`
39
+ was the only preset of ten relying on that invisible inheritance instead
40
+ of an explicit process matrix, and its triage used `applyMode: "queue"`
41
+ while its description promised to "drain the backlog" — queue mode never
42
+ promotes, so nothing drained. `catchup` had the same inertness:
43
+ `maxAcceptsPerRun: 100` under queue mode, a key the promote loop never
44
+ reads.
45
+
46
+ Both now use the same judged-promotion pattern as `reflect-distill` and
47
+ `proactive-maintenance`: `applyMode: "promote"`, `judgment: true`, a
48
+ per-run accept cap (`thorough` 25, `catchup` 100), and `maxDiffLines:
49
+ 200`. The autonomy gate demotes promote back to queue unless
50
+ `experimental.improveAutonomy` is enabled, so by default both still
51
+ review-only; with autonomy on, they actually drain. `thorough` now
52
+ carries default's full explicit matrix, and a regression test pins
53
+ "everything default enables, thorough enables identically, plus triage."
54
+
55
+ ### Fixed
56
+
57
+ - **Pruning a memory no longer leaves dangling belief edges (#884).**
58
+ `analyzeMemoryCleanup` archives a pruned memory rather than deleting it —
59
+ the file moves under `.akm/memory-cleanup/archive/` beside a `cleanup.md`
60
+ audit record naming its `ref` and `originalPath`. Ref resolution only ever
61
+ looked at the memory's original location, so once #882 made
62
+ `contradictedBy`/`supersededBy` validatable, every memory pointing at a
63
+ pruned one began reporting `missing-ref`. `refExistsInAnyStash` now resolves
64
+ the archive tombstone, so a belief edge to an archived memory is satisfied
65
+ instead of dangling. Existence only: `resolveRefPathInStash` still ignores
66
+ the archive, because it returns a path callers mutate (`--supersedes`
67
+ demotion) and an archived file must never be written to. The contradiction
68
+ an edge records is preserved rather than erased, which a bare edge-scrub
69
+ would have destroyed.
70
+
71
+ A ref whose target has neither a file nor a tombstone was removed by
72
+ something other than prune — a hand `git rm`, or a pre-fix release — and is
73
+ genuinely dangling. Clearing those deletes user assertions, so it is opt-in
74
+ behind `akm lint --prune-dangling-edges` and is deliberately NOT folded into
75
+ `--fix`: every other auto-fix repairs a malformed file, whereas this one
76
+ edits well-formed files to drop a claim about the belief graph. The repair
77
+ is scoped to the `supersededBy`/`contradictedBy` channels — a stale `xrefs`
78
+ entry is an ordinary broken link that the author may want to re-target, not
79
+ delete — and preserves comments, key order, and surviving list entries. It
80
+ clears the same `writable: false` gate `--fix` does.
81
+
82
+ Known limitation: if a memory's only edge on a channel is dropped, a
83
+ `beliefState:` naming that channel is left without a supporting edge.
84
+ Choosing a demotion target is a belief-semantics decision this fix does not
85
+ make. No occurrences existed in the stash that surfaced #884.
86
+
87
+ - **A corrupt `index.db` now rebuilds instead of failing the command
88
+ (#865).** `src/core/state-db.ts` documented that "a corrupt index is
89
+ recovered by deleting it and re-running `akm index`" — that recovery was
90
+ never implemented. Real on-disk corruption surfaced a raw `SQLITE_CORRUPT`
91
+ and exited 70, and the existing inline-reindex fallback could not help
92
+ because it reopened the same corrupt file. `openIndexDatabase` now detects
93
+ corruption, removes the file and its `-wal`/`-shm` sidecars, and retries
94
+ the open once. Scoped to `index.db`, which is fully regenerable from the
95
+ stash; `state.db` is never touched.
96
+
97
+ - **`akm task sync` accepts an immutable package-local install (#868).** An
98
+ image-baked akm pinned at a path outside the npm global root was refused
99
+ outright, and `--rebind` then warned on every sync that the pinned binary
100
+ was "mutable, unproven" — the opposite of true, training operators to
101
+ ignore a recurring warning. The npm-global check was only ever a proxy for
102
+ "this binary won't change out from under the scheduler"; that property is
103
+ now tested directly, so a launcher this process cannot write to (a
104
+ read-only mount) is eligible without `--rebind` and without the warning.
105
+ Writable `npx`/project-`node_modules` installs remain ineligible, which is
106
+ the case the original check existed for. No new config knob.
107
+
108
+ - **`TASK_SCHEMA_VERSION_UNSUPPORTED` names the actual blocker (#869).** For
109
+ a v2/v3 file the message is only reached after the read-time shim has
110
+ already tried and failed to convert it — meaning a human decision is
111
+ required — yet it pointed at `akm migrate apply`, which would report the
112
+ identical block for that same file. The blocked `reason`/`detail` were
113
+ already computed and then discarded; they are now surfaced, so the error
114
+ names the specific reason (e.g.
115
+ `shell-command-resolution-changes-v2-literal-argv-semantics`) and says a
116
+ decision is needed rather than sending the operator to a command that
117
+ cannot help.
118
+
119
+ Also verified as already fixed and left alone: cross-bundle scoping (a
120
+ blocked file in one bundle does not prevent conversion in another —
121
+ resolved by #866) and `env`-prefixed command conversion (resolved by
122
+ #867).
123
+
124
+ - **`akm task sync` no longer dead-ends on pre-0.9.2 crontab rows (#881).**
125
+ Rows written by v0.9.0/v0.9.1 carry no `--scheduler-context` marker, so
126
+ `extractCronInvocation` could not parse them. Sync therefore saw the task
127
+ as absent, tried to install it, and collided with the row that was still
128
+ physically present — permanently blocking sync for every task on any
129
+ install upgrading past v0.9.2. Such a row is now recognized and
130
+ reconciled. The fallback fires only when the marker is entirely absent
131
+ and only inside akm's own `# akm:task … BEGIN/END` sentinels, so a row
132
+ carrying the marker that fails to parse for any other reason is never
133
+ reinterpreted, and no ownership or cardinality assertion changed.
134
+
135
+ - **`akm lint` validates `type:slug` xrefs instead of silently skipping
136
+ them (#882).** `typeNameFromConceptId` returns `undefined` for the colon
137
+ grammar, so `classifyConceptRef` treated those refs as "not a local ref"
138
+ and dropped them before validation — roughly half the xref channel on a
139
+ real corpus. Zero `missing-ref` findings read as "every reference is
140
+ healthy" when half had never been examined. akm still writes this
141
+ grammar today (`memory-contradiction-detect.ts` emits `contradictedBy:`
142
+ as `memory:<name>`), so it is a live channel, not legacy residue; it is
143
+ now accepted as a fallback in lint only, leaving the parser and write
144
+ paths on the single conceptId grammar.
145
+
146
+ - **Refs to derived memories resolve (#882).** `assetPathCandidatesForName`
147
+ only ever offered `<name>.md`, so any ref to a memory stored as
148
+ `<name>.derived.md` failed to resolve — affecting the conceptId grammar
149
+ equally, and invisible until the above fix made these refs validatable.
150
+ `.derived` is a provenance marker on the same identity, not part of the
151
+ name, so `<name>.derived.md` is now a secondary candidate with plain
152
+ `<name>.md` still taking precedence when both exist. Fixed at the
153
+ resolution primitive, so write-time `--xref`/`--supersedes` validation
154
+ benefits as well.
155
+
156
+ ### Removed
157
+
158
+ - **The `frequent` and `memory-focus` improve strategies.** Zero recorded
159
+ invocations, and both were mid-points of other presets (`frequent` ≈
160
+ `reflect-distill` without distill or triage; `memory-focus` a subset of
161
+ `frequent`). The shipped hourly task template now uses `reflect-distill`
162
+ — matching what real deployments had already switched to by hand. Any
163
+ removed combination remains expressible via `improve.strategies` in
164
+ config. One caveat: a user-config strategy *named* `frequent` or
165
+ `memory-focus` previously merged over the built-in of the same name; it
166
+ now merges over `default` only, so a partial override that relied on the
167
+ built-in's values will resolve differently and should be made explicit.
168
+
169
+ ### Testing
170
+
171
+ - **The previous-release corpus covers more than task sources (#880).**
172
+ Added fixtures for the synthesized `AKM_BUNDLE_DIR` duplicate-`stash`
173
+ bundle shape that caused #870, the retired 0.8 `stashDir`/`sources[]`/
174
+ `installed[]` config keys, and a downstream consumer's `config.json` plus
175
+ four task-source-v4 files. The 0.8 fixture deliberately asserts the
176
+ opposite of the others: those keys are hard-rejected by design, so it
177
+ guards that the rejection stays loud and actionable rather than silently
178
+ loading. Every fixture was proven to catch a regression by breaking the
179
+ guarantee, observing the failure, and reverting.
180
+
181
+ - Pinned current handling of truncated LLM responses (`finishReason:
182
+ "length"`) as a regression test (#865). No distinct classification or
183
+ retry was added: the underlying truncation was already resolved by
184
+ `reasoningEffort`, and threading the finish reason through four layers to
185
+ earn one diagnostic label was not justified.
186
+
187
+ ### Not shipped
188
+
189
+ - **Orphan-asset detection for `akm health` (#750)** was implemented and
190
+ then backed out after measurement. Against a live 23,859-entry index it
191
+ flagged 16,609 of 16,615 in-scope assets (99.96%) and took 135 s. The
192
+ corpus is not densely cross-linked — 1,591 distinct xref tokens exist in
193
+ total — so the check has no signal to give. The broken-ref half of #750
194
+ had already shipped previously. Moved to Backlog; see #882 for the
195
+ resolver defect the investigation exposed.
196
+
7
197
  ## [0.9.6] - 2026-08-31
8
198
 
9
199
  The deletion release: **net −2,100 lines**, almost all of it machinery that
@@ -245,8 +245,8 @@ akm improve --no-push # commit but skip push for this ru
245
245
  akm improve --sync # force sync even on strategies that disable it
246
246
  ```
247
247
 
248
- Strategy sync defaults: `catchup`, `consolidate`, `default`, `frequent`,
249
- `graph-refresh`, `memory-focus`, `quick`, and `thorough` auto-commit + push;
248
+ Strategy sync defaults: `catchup`, `consolidate`, `default`,
249
+ `graph-refresh`, `quick`, and `thorough` auto-commit + push;
250
250
  `proactive-maintenance` and `reflect-distill` skip sync entirely. Override
251
251
  with `--sync` / `--no-sync` flags.
252
252
 
@@ -355,7 +355,7 @@ scheduler (cron / launchd / schtasks). The file is the source of truth:
355
355
  file plus one `sync` is a complete workflow.
356
356
 
357
357
  ```sh
358
- akm task add nightly-improve --schedule "@daily" --command "akm improve --strategy frequent"
358
+ akm task add nightly-improve --schedule "@daily" --command "akm improve --strategy default"
359
359
  akm task add briefing --schedule "0 9 * * *" --prompt "Draft the morning briefing" # Inline command task
360
360
  akm task sync # Reconcile task files with the OS scheduler
361
361
  akm task sync --rebind # Also re-pin the scheduler's akm binary/spelling
@@ -1,15 +1,44 @@
1
1
  {
2
- "description": "Manual catch-up consolidation + triage drain with no interval minimum.",
2
+ "description": "Manual catch-up \u2014 consolidation plus a judged triage drain (up to 100 accepts) with no interval minimum. Auto-accepts only when improve autonomy is enabled; otherwise proposals queue for review.",
3
3
  "processes": {
4
- "reflect": { "enabled": false },
5
- "distill": { "enabled": false },
6
- "consolidate": { "enabled": true, "allowedTypes": ["memory"], "maxChunkSize": 50, "minPoolSize": 0 },
7
- "memoryInference": { "enabled": false },
8
- "graphExtraction": { "enabled": false },
9
- "extract": { "enabled": false },
10
- "triage": { "enabled": true, "applyMode": "queue", "policy": "personal-stash", "maxAcceptsPerRun": 100 },
11
- "validation": { "enabled": false },
12
- "proactiveMaintenance": { "enabled": false }
4
+ "reflect": {
5
+ "enabled": false
6
+ },
7
+ "distill": {
8
+ "enabled": false
9
+ },
10
+ "consolidate": {
11
+ "enabled": true,
12
+ "allowedTypes": ["memory"],
13
+ "maxChunkSize": 50,
14
+ "minPoolSize": 0
15
+ },
16
+ "memoryInference": {
17
+ "enabled": false
18
+ },
19
+ "graphExtraction": {
20
+ "enabled": false
21
+ },
22
+ "extract": {
23
+ "enabled": false
24
+ },
25
+ "triage": {
26
+ "enabled": true,
27
+ "applyMode": "promote",
28
+ "policy": "personal-stash",
29
+ "maxAcceptsPerRun": 100,
30
+ "judgment": true,
31
+ "maxDiffLines": 200
32
+ },
33
+ "validation": {
34
+ "enabled": false
35
+ },
36
+ "proactiveMaintenance": {
37
+ "enabled": false
38
+ }
13
39
  },
14
- "sync": { "enabled": true, "push": true }
40
+ "sync": {
41
+ "enabled": true,
42
+ "push": true
43
+ }
15
44
  }
@@ -1,15 +1,53 @@
1
1
  {
2
- "description": "Like default, plus the triage process (drains the pending-proposal backlog).",
2
+ "description": "Everything default runs, plus a judged triage drain of the pending-proposal backlog (up to 25 accepts per run). Auto-accepts only when improve autonomy is enabled; otherwise proposals queue for review. Identical tuning to default; improve-stage extract and proactive maintenance stay off.",
3
3
  "processes": {
4
4
  "reflect": {
5
5
  "enabled": true,
6
+ "limit": 25,
6
7
  "allowedTypes": ["agent", "command", "knowledge", "lesson", "memory", "skill", "workflow"]
7
8
  },
8
- "distill": { "enabled": true, "allowedTypes": ["memory"] },
9
- "consolidate": { "enabled": true, "allowedTypes": ["memory"] },
10
- "memoryInference": { "enabled": true },
11
- "graphExtraction": { "enabled": true },
12
- "triage": { "enabled": true, "applyMode": "queue" }
9
+ "distill": {
10
+ "enabled": true,
11
+ "allowedTypes": ["memory"],
12
+ "requirePlannedRefs": true
13
+ },
14
+ "consolidate": {
15
+ "enabled": true,
16
+ "allowedTypes": ["memory"],
17
+ "minPoolSize": 500
18
+ },
19
+ "memoryInference": {
20
+ "enabled": true
21
+ },
22
+ "graphExtraction": {
23
+ "enabled": true
24
+ },
25
+ "extract": {
26
+ "enabled": false,
27
+ "triage": {
28
+ "enabled": true,
29
+ "minScore": 2
30
+ }
31
+ },
32
+ "validation": {
33
+ "enabled": true
34
+ },
35
+ "proactiveMaintenance": {
36
+ "enabled": false,
37
+ "dueDays": 30,
38
+ "maxPerRun": 15
39
+ },
40
+ "triage": {
41
+ "enabled": true,
42
+ "applyMode": "promote",
43
+ "policy": "personal-stash",
44
+ "maxAcceptsPerRun": 25,
45
+ "maxDiffLines": 200,
46
+ "judgment": true
47
+ }
13
48
  },
14
- "sync": { "enabled": true, "push": true }
49
+ "sync": {
50
+ "enabled": true,
51
+ "push": true
52
+ }
15
53
  }
@@ -1,4 +1,4 @@
1
1
  version: 4
2
- run: akm improve --strategy frequent --skip-if-locked
3
- description: Frequent inference pass (hourly at :40; improve-stage extract off)
2
+ run: akm improve --strategy reflect-distill --skip-if-locked
3
+ description: Frequent learning pass (hourly at :40) reflect, distill, memory inference, judged triage
4
4
  schedule: "40 * * * *"
@@ -139,6 +139,16 @@ export const lintCommand = defineCommand({
139
139
  description: "Exit non-zero when summary.flagged > 0 (CI-friendly). Default: exit 0 regardless of findings.",
140
140
  default: false,
141
141
  },
142
+ // #884: NOT folded into `--fix`. Every other auto-fix repairs a structural
143
+ // defect in the file it edits; this one DELETES an assertion the user (or
144
+ // the improve pipeline) made about the belief graph, and it does so in
145
+ // files that are themselves perfectly well-formed. That is a data decision,
146
+ // so it stays opt-in behind its own flag even when `--fix` is present.
147
+ "prune-dangling-edges": {
148
+ type: "boolean",
149
+ description: "Opt-in repair: drop supersededBy/contradictedBy entries whose target has neither a file nor a prune tombstone. Modifies memories — review the plain `akm lint` report first.",
150
+ default: false,
151
+ },
142
152
  type: {
143
153
  type: "string",
144
154
  description: "Only lint assets of this type (e.g. workflows, tasks, memories). akm bundles only — every other adapter validates the whole bundle and warns that the flag had no effect.",
@@ -151,6 +161,7 @@ export const lintCommand = defineCommand({
151
161
  fix: args.fix === true || getHyphenatedBoolean(args, "auto-fix"),
152
162
  dir: getStringArg(args, "dir"),
153
163
  typeFilter: getStringArg(args, "type"),
164
+ pruneDanglingEdges: getHyphenatedBoolean(args, "prune-dangling-edges"),
154
165
  });
155
166
  output("lint", result);
156
167
  if (args["fail-on-flagged"] && result.summary.flagged > 0) {
@@ -114,7 +114,7 @@ export const improveCommand = defineCommand({
114
114
  },
115
115
  strategy: {
116
116
  type: "string",
117
- description: "Named improve strategy from improve.strategies or built-in strategies (catchup, consolidate, default, frequent, graph-refresh, memory-focus, proactive-maintenance, quick, reflect-distill, thorough). Controls which sub-processes run and which asset types are processed.",
117
+ description: "Named improve strategy from improve.strategies or built-in strategies (catchup, consolidate, default, graph-refresh, proactive-maintenance, quick, reflect-distill, thorough). Controls which sub-processes run and which asset types are processed.",
118
118
  },
119
119
  sync: {
120
120
  type: "boolean",
@@ -4,9 +4,7 @@
4
4
  import catchup from "../../assets/improve-strategies/catchup.json" with { type: "json" };
5
5
  import consolidate from "../../assets/improve-strategies/consolidate.json" with { type: "json" };
6
6
  import defaultStrategy from "../../assets/improve-strategies/default.json" with { type: "json" };
7
- import frequent from "../../assets/improve-strategies/frequent.json" with { type: "json" };
8
7
  import graphRefresh from "../../assets/improve-strategies/graph-refresh.json" with { type: "json" };
9
- import memoryFocus from "../../assets/improve-strategies/memory-focus.json" with { type: "json" };
10
8
  import proactiveMaintenance from "../../assets/improve-strategies/proactive-maintenance.json" with { type: "json" };
11
9
  import quick from "../../assets/improve-strategies/quick.json" with { type: "json" };
12
10
  import reflectDistill from "../../assets/improve-strategies/reflect-distill.json" with { type: "json" };
@@ -45,9 +43,7 @@ const BUILTIN_STRATEGIES = {
45
43
  default: defaultStrategy,
46
44
  quick,
47
45
  thorough,
48
- "memory-focus": memoryFocus,
49
46
  "graph-refresh": graphRefresh,
50
- frequent,
51
47
  consolidate,
52
48
  catchup,
53
49
  "reflect-distill": reflectDistill,
@@ -5,6 +5,7 @@ import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { assembleAsset } from "../../../core/asset/asset-serialize.js";
7
7
  import { mutateFrontmatter, parseFrontmatter } from "../../../core/asset/frontmatter.js";
8
+ import { MEMORY_ARCHIVE_REL } from "../../../core/asset/memory-archive.js";
8
9
  import { conceptIdFromTypeName } from "../../../core/asset/resolve-ref.js";
9
10
  import { asNonEmptyString, groupBy, stringArray } from "../../../core/common.js";
10
11
  import { DERIVED_SUFFIX } from "../../../core/recognition-util.js";
@@ -553,7 +554,7 @@ function priorBeliefStateForArchive(candidate) {
553
554
  }
554
555
  function createArchiveDir(stashDir, ref, archivedAt) {
555
556
  const baseName = `${archivedAt.replace(/[:.]/g, "-")}-${sanitizeRef(ref)}`;
556
- const root = path.join(stashDir, ".akm", "memory-cleanup", "archive");
557
+ const root = path.join(stashDir, MEMORY_ARCHIVE_REL);
557
558
  fs.mkdirSync(root, { recursive: true });
558
559
  let attempt = 0;
559
560
  while (true) {
@@ -760,7 +760,7 @@ async function runPreparationPrelude(args) {
760
760
  };
761
761
  }
762
762
  export async function runImprovePreparationStage(args) {
763
- const { scope, options, plannedRefs, primaryStashDir, eventsCtx, initialCleanupWarnings, improveProfile, resolvedPlan, planOnly = options.dryRun === true, } = args;
763
+ const { scope, options, primaryStashDir, eventsCtx, initialCleanupWarnings, improveProfile, resolvedPlan, planOnly = options.dryRun === true, } = args;
764
764
  const actions = [];
765
765
  const cleanupWarnings = initialCleanupWarnings ? [...initialCleanupWarnings] : [];
766
766
  const { memoryIndexHealth, consolidationPass, extractPlan, extractResults, appliedCleanup, postCleanupRefs, cleanupGate, validationFailures, validationFailureRefs, schemaRepairs, } = await runPreparationPrelude({ ...args, planOnly, actions, cleanupWarnings });
@@ -790,7 +790,7 @@ function parseDirectReflectOutput(raw, mode, targetRef) {
790
790
  export async function runReflectViaLlm(opts) {
791
791
  const start = Date.now();
792
792
  let repairAttempts = 0;
793
- const connection = opts.runner.connection;
793
+ const _connection = opts.runner.connection;
794
794
  const messages = [{ role: "user", content: opts.prompt ?? "" }];
795
795
  const configuredTimeout = Object.hasOwn(opts, "timeoutMs")
796
796
  ? (opts.timeoutMs ?? null)