@lorekit/cli 1.30.3 → 1.31.0

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.
package/README.md CHANGED
@@ -47,7 +47,7 @@ Linux, and Windows (npm creates the `lorekit` shim on every platform).
47
47
  Sets up the full memory loop — the same three parts as the Claude plugin,
48
48
  without needing a marketplace:
49
49
 
50
- 1. **Skills** (`lorekit-memory` + `lorekit-setup`) — the model-invoked authoring judgment and the self-improvement loop authoring counterpart.
50
+ 1. **Skills** (`lorekit-memory` + `lorekit-setup` + `lorekit-groom`) — the model-invoked runtime read/write loop, the self-improvement loop authoring counterpart, and the store-grooming maintenance counterpart.
51
51
  2. **MCP server** (`lorekit`) — the connection to your lessons, merged into the
52
52
  MCP config (preserving any other servers).
53
53
  3. **Hooks** — the *deterministic* layer: lessons injected on every
@@ -751,7 +751,7 @@ also returns their headroom against the plan's memory cap.
751
751
 
752
752
  ## What the skills do
753
753
 
754
- `install` scaffolds two skills:
754
+ `install` scaffolds three skills:
755
755
 
756
756
  The **`lorekit-memory`** skill teaches an agent to:
757
757
 
@@ -770,6 +770,14 @@ to wire a self-improvement loop into one of *your own* skills or workflows — t
770
770
  two-tier model, the lesson bucket convention, and the entrenchment guards. See
771
771
  its `SKILL.md` and `rules/self-improvement-loops.md`.
772
772
 
773
+ The **`lorekit-groom`** skill is the maintenance counterpart: it teaches an agent
774
+ to run a grooming pass over an accumulated store — survey (`stats` / `scopes`),
775
+ lint, dedupe & merge near-duplicates, set expiry (TTL) on time-bound lessons, and
776
+ prune or archive obsolete ones. It always analyses read-only and proposes a plan
777
+ before mutating (archive is preferred over hard-delete), because the store is
778
+ shared and a merge or delete is permanent for every agent. See its `SKILL.md`,
779
+ `rules/grooming-pass.md`, and `references/merge-and-expiry.md`.
780
+
773
781
  The **skills** are model-invoked (the agent chooses to use them). For a
774
782
  **deterministic** guarantee — lessons injected on every session start, a nudge
775
783
  on every tool failure — use the framework plugins in [`plugins/`](../../plugins/),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lorekit/cli",
3
- "version": "1.30.3",
3
+ "version": "1.31.0",
4
4
  "description": "Install the LoreKit shared-memory skill and run health checks for the LoreKit MCP server.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: lorekit-groom
3
+ description: >
4
+ Grooms and maintains an accumulated LoreKit memory store — the cleanup
5
+ counterpart to lorekit-memory (which reads and records single lessons). It
6
+ finds and merges near-duplicate lessons, lints out low-quality ones, sets
7
+ expiry (TTL) on time-bound lessons, and prunes or archives obsolete ones,
8
+ ALWAYS analysing read-only and proposing a plan before any change (nothing
9
+ is deleted or merged without confirmation, and archive is preferred over
10
+ hard-delete). Reach for this whenever a lesson/memory store has grown noisy,
11
+ large, or stale and needs tidying — not for reading or writing one lesson.
12
+ Triggers on "groom my memories", "clean up my lessons", "dedupe the memory
13
+ store", "merge duplicate lessons", "too many memories", "my lorekit is a
14
+ mess", "consolidate lessons", "add expiry dates to old lessons", "prune stale
15
+ branch lessons", "lint my memories", "/lorekit-groom".
16
+ user-invocable: true
17
+ argument-hint: '[scope-hint]'
18
+ license: MIT
19
+ metadata:
20
+ author: mthines
21
+ version: '1.0.0'
22
+ workflow_type: shared-memory-grooming-and-consolidation
23
+ tags:
24
+ - lorekit
25
+ - persistent-memory
26
+ - shared-memory
27
+ - mcp
28
+ - lessons
29
+ - grooming
30
+ - dedupe
31
+ - lint
32
+ - maintenance
33
+ ---
34
+
35
+ # LoreKit Groom
36
+
37
+ Keep a shared memory store healthy as it grows.
38
+
39
+ A memory store that is never tended slowly rots: the same lesson gets written
40
+ three times in slightly different words, a stub with an empty value sits next to
41
+ a real one, a branch-specific gotcha outlives the branch by a year. Noise like
42
+ that is not harmless — it drowns the signal every future read depends on, so the
43
+ next agent scrolls past ten near-identical lines instead of acting on one clear
44
+ one.
45
+
46
+ This skill runs a **grooming pass** over the lessons for a scope: survey → lint →
47
+ dedupe & merge → set expiry → prune → verify. It is the maintenance counterpart
48
+ to the other two LoreKit skills:
49
+
50
+ | Skill | Job |
51
+ |-------|-----|
52
+ | `lorekit-memory` | Runtime: read scoped lessons on a task, write one on failure |
53
+ | `lorekit-setup` | Authoring: wire a self-improvement loop into a host |
54
+ | **`lorekit-groom`** | **Maintenance: consolidate and clean an accumulated store** |
55
+
56
+ ---
57
+
58
+ ## The one rule that governs everything: propose, then confirm
59
+
60
+ Grooming edits a **shared, persistent** store — a lesson you merge or delete is
61
+ gone for every agent on every machine, not just this session. So the entire pass
62
+ is read-only until a human says otherwise:
63
+
64
+ 1. **Analyse read-only.** Every survey step below is a read command. Run them
65
+ first and build the full picture before touching anything.
66
+ 2. **Propose a concrete plan.** Show exactly what you intend to do — which
67
+ lessons merge into which, what gets an expiry, what gets archived — with the
68
+ actual keys and values, grouped so a human can scan it in one screen.
69
+ 3. **Only mutate after confirmation.** Wait for the go-ahead, then apply. Prefer
70
+ **archive** (reversible) over hard-delete; reserve permanent deletion for
71
+ genuine junk and only with explicit sign-off.
72
+
73
+ Never batch-delete on a similarity score alone — the dedupe heuristic is a
74
+ word-overlap guess, not a semantic judge (see the toolbox note below). It finds
75
+ *candidates for a human's eye*, and merging is a judgement call about meaning.
76
+
77
+ If you are asked to "just clean it up" without oversight, still surface the plan
78
+ once and get a single confirmation for the batch — that is the floor, not a
79
+ step to skip.
80
+
81
+ ---
82
+
83
+ ## The grooming pass
84
+
85
+ Follow [rules/grooming-pass.md](./rules/grooming-pass.md) for the full playbook.
86
+ The short version is six phases; the first four are pure analysis.
87
+
88
+ 1. **Survey** — size the problem. `lorekit stats` (counts per scope + store) and
89
+ `lorekit scopes` (store-wide inventory: every scope with its lesson count)
90
+ show where the mass is. Pick the noisiest scope to start.
91
+ 2. **Lint** — `lorekit lint --json` flags structurally bad lessons (empty /
92
+ whitespace / suspiciously short / untrimmed values, empty keys, malformed
93
+ scopes). These are the cheapest wins: fix or drop them first.
94
+ 3. **Dedupe** — `lorekit dedupe --json` clusters near-duplicate lessons. Start at
95
+ a high `--threshold` (e.g. `0.85`) for confident duplicates, then lower it to
96
+ surface looser paraphrases. Use `lorekit show <scope::key>` to read each
97
+ cluster member's full value before deciding.
98
+ 4. **Plan** — turn the findings into a proposed set of merges, expiries, and
99
+ removals. This is where propose-then-confirm happens.
100
+ 5. **Apply** (after confirmation) — merge, expire, and prune. See the toolbox.
101
+ 6. **Verify** — re-run `lorekit lint` (should exit 0) and `lorekit dedupe` (no
102
+ clusters at your threshold) and `lorekit stats` (a lower count). Green means
103
+ the pass landed.
104
+
105
+ ---
106
+
107
+ ## The toolbox
108
+
109
+ Grooming spans two surfaces. **Analysis is the CLI** — its read commands
110
+ (`lint`, `dedupe`, `stats`, `scopes`, `show`, `list`, `search`, `tree`, `diff`)
111
+ survey the store far more richly than the MCP tools do, across both the offline
112
+ and remote stores at once. **Mutation is the `memory.*` MCP tools** — and
113
+ crucially, *removal* is MCP-only: there is no `lorekit delete` command, so
114
+ archiving and deleting always go through `memory.delete` / `memory.archive`.
115
+
116
+ | Job | How | Surface |
117
+ |-----|-----|---------|
118
+ | Count lessons per scope/store | `lorekit stats [--scope <s>]` | CLI (read) |
119
+ | Inventory every scope + lesson count | `lorekit scopes` | CLI (read) |
120
+ | Find low-quality lessons | `lorekit lint --json` | CLI (read) |
121
+ | Find near-duplicate clusters | `lorekit dedupe --json [--threshold <n>]` | CLI (read) |
122
+ | Read one lesson in full | `lorekit show <scope::key> [--json]` | CLI (read) |
123
+ | Compare offline vs remote | `lorekit diff` | CLI (read) |
124
+ | Write the merged/consolidated lesson | `memory.write` (or `lorekit write`) | MCP / CLI |
125
+ | Set / clear an expiry | `memory.write { ttl_days }` / `{ clear_ttl: true }` | MCP / CLI (`--ttl-days` / `--clear-ttl`) |
126
+ | Archive a lesson (reversible) | `memory.archive` (or `memory.delete`) | **MCP only** |
127
+ | Hard-delete a lesson (permanent) | `memory.delete { force: true }` | **MCP only** |
128
+
129
+ > **`dedupe` is a heuristic, not a semantic judge.** It clusters on Jaccard
130
+ > word-token overlap, so it can both miss reworded duplicates *and* group
131
+ > coincidental ones. Treat every cluster as a candidate to read and decide on,
132
+ > never as an instruction to merge.
133
+
134
+ > **If the `memory.*` MCP tools are not connected**, analysis still works
135
+ > (the CLI reads and `lorekit write --ttl-days` sets expiries), but you cannot
136
+ > archive or delete. Say so once, complete everything you can, and hand the
137
+ > removal list to the human rather than silently skipping it.
138
+
139
+ Merging, expiry tiers, and the archive-vs-delete call each have real judgement
140
+ in them — the details, with examples, live in
141
+ [references/merge-and-expiry.md](./references/merge-and-expiry.md). Read it
142
+ before your first merge or TTL decision in a pass.
143
+
144
+ ---
145
+
146
+ ## Scope in one line
147
+
148
+ Lessons are partitioned by a canonical scope string (`::` is the only separator):
149
+
150
+ ```text
151
+ global universal principles
152
+ project::{name} monorepo-wide
153
+ repo::{owner}/{repo} this repository's codebase
154
+ branch::{owner}/{repo}::{branch} short-lived, this branch only
155
+ ```
156
+
157
+ Scope drives two grooming decisions: **branch-scoped lessons are the prime
158
+ candidates for expiry** (a branch is short-lived, its lessons usually are too),
159
+ and **a merge lands in the narrowest scope that still covers all its members**.
160
+ Both are spelled out in the reference file.
161
+
162
+ ---
163
+
164
+ ## Setup
165
+
166
+ Grooming uses the same install as the rest of LoreKit:
167
+
168
+ ```bash
169
+ npx @lorekit/cli install
170
+ npx @lorekit/cli doctor
171
+ ```
172
+
173
+ `doctor` confirms the store backend (`remote`, `local`, or `off`) and token
174
+ permission. Removal needs a token with **write** permission (`lk_rw_*` or
175
+ `lk_wo_*`); a read-only token can survey and propose but not apply. If a mutate
176
+ call fails with an authorization error, report it and stop — do not retry.
@@ -0,0 +1,123 @@
1
+ # Merge, expiry, and removal — the judgement calls
2
+
3
+ The mechanical parts of grooming (survey, lint, dedupe) are commands. The parts
4
+ that need thought are: how to synthesise a merged lesson, where it should live,
5
+ how long a lesson should last, and whether a stale lesson should be archived or
6
+ deleted. This file is the reference for those four decisions. Read it before the
7
+ first merge or TTL choice in a pass.
8
+
9
+ ## Table of contents
10
+
11
+ 1. [Synthesising a merged lesson](#1-synthesising-a-merged-lesson)
12
+ 2. [Choosing the merged lesson's scope](#2-choosing-the-merged-lessons-scope)
13
+ 3. [Choosing the key](#3-choosing-the-key)
14
+ 4. [Expiry tiers (TTL)](#4-expiry-tiers-ttl)
15
+ 5. [Archive vs. hard-delete](#5-archive-vs-hard-delete)
16
+
17
+ ---
18
+
19
+ ## 1. Synthesising a merged lesson
20
+
21
+ A merge is not a concatenation. Three lessons that say the same thing become
22
+ **one lesson that says it best** — otherwise you have replaced three near-copies
23
+ with one long lumpy one and gained nothing.
24
+
25
+ - **Keep the observation, drop the repetition.** Write the single clearest
26
+ statement of the shared point. If two members add genuinely different detail
27
+ (one names the failing command, another names the fix), fold both facts into
28
+ one lesson; if they only reword each other, keep the sharpest phrasing.
29
+ - **Stay an observation, not a rule.** LoreKit lessons are advisory ("migrations
30
+ that skip an explicit transaction have left the schema half-applied here"), not
31
+ commandments ("ALWAYS wrap migrations"). Merging is a chance to soften a member
32
+ that drifted into a rigid MUST.
33
+ - **Preserve the union of tags and the richest provenance.** Carry every source's
34
+ tags onto the merged lesson so it stays as findable as the originals. Keep the
35
+ most complete origin (repo / branch / commit / PR) among the members.
36
+ - **Prefer updating a survivor over minting a new key.** If one member is already
37
+ well-named and well-scoped, write the merged value onto *its* `scope::key`
38
+ (an in-place update) and delete the others. That keeps any external links to
39
+ that key alive. Mint a fresh key only when no member's key fits the merged
40
+ meaning.
41
+
42
+ **Example**
43
+
44
+ ```text
45
+ Sources:
46
+ - "wrap every migration in a transaction"
47
+ - "schema changes need a transaction or they half-apply on error"
48
+ - "migrations must be atomic"
49
+ Merged value:
50
+ "Migrations here half-apply on error unless wrapped in an explicit
51
+ transaction — a failed step otherwise leaves the schema partly changed."
52
+ ```
53
+
54
+ The merged version keeps the *why* (half-apply on error) that only one source
55
+ had, and states it as an observation.
56
+
57
+ ## 2. Choosing the merged lesson's scope
58
+
59
+ Merge into the **narrowest scope that still correctly covers every member**.
60
+
61
+ - All members share a scope → merge stays in that scope.
62
+ - Members span scopes (e.g. two `branch::…` and one `repo::…` saying the same
63
+ thing) → the lesson is really about the broader scope. Merge up to the
64
+ narrowest scope that is still true for all of them — usually `repo::` when a
65
+ branch lesson turned out to be a repo-wide truth. Broadening scope is itself a
66
+ useful grooming outcome: a durable lesson trapped on a dead branch is nearly
67
+ invisible.
68
+ - Never merge *down* into a scope narrower than some members — that hides the
69
+ lesson from contexts where it applies.
70
+
71
+ Precedence check: bare `lorekit tree` shows which scope's lesson wins when keys
72
+ collide across scopes. Run it without `--scope` — that flag narrows the
73
+ resolution to a single scope, which by construction cannot show a collision.
74
+ Use it to confirm a merged lesson will actually surface where you intend.
75
+
76
+ ## 3. Choosing the key
77
+
78
+ - Reuse a good survivor's key when one exists (see §1 — keeps links alive).
79
+ - Otherwise write a short, specific, hyphenated key that names the *observation*,
80
+ not the symptom: `db-migrations-need-explicit-tx`, not `migration-bug` or
81
+ `note-3`. A key is how a future agent recognises the lesson at a glance in a
82
+ list, so vague keys are their own kind of noise.
83
+
84
+ ## 4. Expiry tiers (TTL)
85
+
86
+ `ttl_days` (1–365) auto-expires a lesson that many days after the write, after
87
+ which it is hidden from reads. Set it via `memory.write { ttl_days }` or
88
+ `lorekit write --ttl-days <n>`; clear it with `{ clear_ttl: true }` /
89
+ `--clear-ttl` to make a lesson permanent again.
90
+
91
+ Match the TTL to how long the lesson's *truth* lasts, not to how old it is:
92
+
93
+ | Lesson kind | Guidance |
94
+ |-------------|----------|
95
+ | `branch::` — branch-specific gotcha | Short. The branch is short-lived; 14–30 days usually outlasts it. Prime expiry candidates. |
96
+ | Version- or dependency-pinned ("works around the bug in lib X 2.3") | Medium (30–90d), or archive once the pin is gone. |
97
+ | Repo- or project-wide architectural truth | Usually **permanent** — no TTL. Expiring durable knowledge is how a store forgets the things worth keeping. |
98
+ | `global` principle | Permanent. |
99
+
100
+ The instinct to worry about is expiring something durable. When unsure whether a
101
+ lesson's truth is time-bound, leave it permanent and flag it in the plan rather
102
+ than quietly attaching a TTL — a lesson that silently vanishes is worse than one
103
+ that lingers.
104
+
105
+ ## 5. Archive vs. hard-delete
106
+
107
+ Two removal paths, and the default is the reversible one.
108
+
109
+ - **Archive** (`memory.archive`, or `memory.delete` without `force`) —
110
+ soft-removes: hidden from reads but restorable. This is the default for
111
+ anything that is *stale* rather than *junk*: superseded workarounds, lessons
112
+ about a since-deleted subsystem, a merge's source lessons. If a future run
113
+ might ever want it back, archive.
114
+ - **Hard-delete** (`memory.delete { force: true }`) — permanent, no recovery.
115
+ Reserve it for genuine junk: lint casualties with no meaning (empty values,
116
+ placeholder keys), test detritus, accidental writes. Only with explicit
117
+ human sign-off in the plan.
118
+
119
+ When a lesson came from another agent or teammate (check its tags / source),
120
+ lean further toward archive — deleting someone else's recorded knowledge outright
121
+ is a heavier call than tidying your own.
122
+
123
+ Rule of thumb: **if you would hesitate to lose it forever, archive it.**
@@ -0,0 +1,148 @@
1
+ # The grooming pass — playbook
2
+
3
+ A single, repeatable pass over the lessons for a scope. The first four phases are
4
+ read-only; nothing is mutated until a human has seen and approved the plan.
5
+
6
+ Work **one scope at a time**. A whole-store pass in a single breath produces a
7
+ wall of proposed changes no one can review; a scope at a time keeps each
8
+ confirmation small enough to actually read.
9
+
10
+ ---
11
+
12
+ ## Phase 1 — Survey (read-only)
13
+
14
+ Size the problem before touching it, so you groom where the mass actually is
15
+ rather than wherever you happened to look first.
16
+
17
+ ```bash
18
+ lorekit stats # counts per scope and per store — where the mass is
19
+ lorekit scopes # every scope in the store + its lesson count
20
+ ```
21
+
22
+ `scopes` is the one command that is store-wide rather than cwd-scoped, so it is
23
+ how you notice a `branch::…` scope you had forgotten about, or a scope with
24
+ hundreds of lessons that dwarfs the rest. Neither command reports a
25
+ last-activity date — the inventory is counts only — so judge staleness from the
26
+ lessons themselves once you narrow in (`lorekit list --scope <scope>` tags each
27
+ one with its `updated` date). Read both, then pick the noisiest scope as the
28
+ target for this pass and narrow to it with `--scope <scope>` from here on.
29
+
30
+ ## Phase 2 — Lint (read-only)
31
+
32
+ ```bash
33
+ lorekit lint --json --scope <scope>
34
+ ```
35
+
36
+ Findings are structural, not semantic — each names its rule:
37
+
38
+ - **empty-value / short-value / untrimmed-value** — the lesson carries little or
39
+ no signal, or has stray leading/trailing whitespace.
40
+ - **empty-key** — no key to address it by.
41
+ - **malformed-scope** — the scope string is invalid.
42
+
43
+ These are the cheapest wins and the least controversial, so clear them first.
44
+ For each: either **fix it in place** (rewrite a too-short value into a real
45
+ observation, trim whitespace — a `memory.write` to the same `scope`+`key`
46
+ updates in place) or, if the lesson is genuinely empty of meaning, **queue it for
47
+ removal** in the plan. `lint` exits non-zero while findings remain, which also
48
+ makes it a clean CI gate — a passing `lint` is your Phase 6 proof.
49
+
50
+ ## Phase 3 — Dedupe (read-only)
51
+
52
+ ```bash
53
+ lorekit dedupe --json --scope <scope> --threshold 0.85
54
+ ```
55
+
56
+ Each cluster is a set of lessons whose values overlap heavily by word tokens.
57
+ Start high (`0.85`) to see the confident duplicates, then re-run lower (`0.75`,
58
+ `0.7`) to surface looser paraphrases — but the lower you go, the more the
59
+ clusters are coincidental overlaps rather than true duplicates, so read more
60
+ carefully.
61
+
62
+ For every cluster you intend to act on, read the members in full first:
63
+
64
+ ```bash
65
+ lorekit show <scope::key> --json
66
+ ```
67
+
68
+ You are deciding whether these lessons *mean* the same thing, which the score
69
+ cannot tell you. Only clusters that survive that read become merges in the plan.
70
+
71
+ ## Phase 4 — Build and propose the plan
72
+
73
+ Turn Phases 2–3 into one concrete, scannable proposal. Group it by action and
74
+ show the real content, because a human approving a shared-store change needs to
75
+ see what actually changes, not a count:
76
+
77
+ ```text
78
+ MERGE (3 → 1) in repo::acme/api
79
+ keep/new key: db-migrations-need-explicit-tx
80
+ merged from:
81
+ - repo::acme/api::migrations-wrap-in-transaction "wrap every migration in a tx…"
82
+ - repo::acme/api::tx-around-schema-changes "schema changes need a transaction…"
83
+ - repo::acme/api::migration-atomicity "migrations must be atomic…"
84
+ proposed value: "<the synthesised lesson>"
85
+
86
+ EXPIRE (set TTL)
87
+ - branch::acme/api::feat-x::stub-endpoint-shape → ttl_days: 14 (branch-scoped, short-lived)
88
+
89
+ ARCHIVE (reversible)
90
+ - repo::acme/api::old-node-14-workaround (node 14 dropped; superseded)
91
+
92
+ DELETE (permanent — junk only)
93
+ - repo::acme/api::asdf (empty value, no key meaning)
94
+ ```
95
+
96
+ Then stop and get confirmation. See
97
+ [references/merge-and-expiry.md](../references/merge-and-expiry.md) for how to
98
+ synthesise a merged value, choose its scope and key, pick a TTL tier, and decide
99
+ archive vs delete — those are the judgement calls, and getting them right is the
100
+ whole point of doing this by hand rather than by script.
101
+
102
+ ## Phase 5 — Apply (only after confirmation)
103
+
104
+ Apply in an order that never loses information, because the store is the only
105
+ record — there is no undo for a hard delete:
106
+
107
+ 1. **Fixes and merges first — write before you remove.** Write the corrected or
108
+ merged lesson (`memory.write`, or `lorekit write`). Confirm it landed
109
+ (`lorekit show <scope::key>`) *before* removing any source lesson, so a
110
+ failure mid-way leaves the originals intact rather than a gap.
111
+ 2. **Expiries.** `memory.write { scope, key, ttl_days }` on the lessons that get
112
+ a TTL, or `{ clear_ttl: true }` to make one permanent again. Same key updates
113
+ in place — no new lesson is created.
114
+ 3. **Removals last.** Archive (`memory.archive`, reversible) for anything a
115
+ future run might still want; `memory.delete { force: true }` (permanent) only
116
+ for the junk explicitly approved for deletion. Remove the merge sources here,
117
+ once their replacement is confirmed written.
118
+
119
+ Preserve `tags` and provenance when you rewrite a lesson — carry the union of the
120
+ sources' tags onto a merge so the consolidated lesson stays as findable as the
121
+ originals were.
122
+
123
+ ## Phase 6 — Verify (read-only)
124
+
125
+ ```bash
126
+ lorekit lint --scope <scope> # expect exit 0 — clean
127
+ lorekit dedupe --scope <scope> --threshold 0.85 # expect no clusters
128
+ lorekit stats --scope <scope> # expect a lower count than Phase 1
129
+ ```
130
+
131
+ Report the before/after: lessons removed, clusters merged, expiries set, and the
132
+ new count. Then either move to the next scope or close out the pass.
133
+
134
+ ---
135
+
136
+ ## Guardrails
137
+
138
+ - **Read before you remove.** Never delete a merge source until its replacement
139
+ is written and confirmed.
140
+ - **Archive beats delete.** Prefer the reversible path unless the lesson is
141
+ provably junk (a lint casualty) and the human approved permanent removal.
142
+ - **The score is a hint, not a verdict.** A dedupe cluster is a candidate to
143
+ read, not a merge to execute.
144
+ - **One scope, one confirmation.** Keep each proposed batch small enough to
145
+ actually review.
146
+ - **Someone else's lesson deserves more caution.** A lesson tagged from another
147
+ agent or a teammate is not automatically yours to delete — when in doubt,
148
+ archive rather than hard-delete, and flag it in the plan.
package/src/config.mjs CHANGED
@@ -12,8 +12,10 @@ export const SKILL_SOURCE = path.join(PKG_ROOT, 'skill', SKILL_NAME);
12
12
  // Every skill the CLI ships. `lorekit-memory` is the operational read/write
13
13
  // loop (kept first as the primary — `SKILL_NAME`/`SKILL_SOURCE` above alias it
14
14
  // for back-compat); `lorekit-setup` is the authoring skill that wires a
15
- // self-improvement loop into a host. install/uninstall/doctor iterate this list.
16
- export const SKILLS = ['lorekit-memory', 'lorekit-setup'].map((name) => ({
15
+ // self-improvement loop into a host; `lorekit-groom` is the maintenance skill
16
+ // that dedupes/lints/merges/expires an accumulated store. install/uninstall/
17
+ // doctor iterate this list.
18
+ export const SKILLS = ['lorekit-memory', 'lorekit-setup', 'lorekit-groom'].map((name) => ({
17
19
  name,
18
20
  source: path.join(PKG_ROOT, 'skill', name),
19
21
  }));