From 15d404b1471e7fdd5ed12513c404a73b6a4d7cf7 Mon Sep 17 00:00:00 2001 From: Diego Oliveira Date: Fri, 31 Jul 2026 12:18:41 -0300 Subject: [PATCH] feat(memory): introduce gated learning capture and enhance documentation - Added the `/agent-memory learn` command for capturing gated learnings and pitfalls, allowing users to document insights directly into `learnings.md` or `learnings-.md`. - Updated `CHANGELOG.md` to reflect the new learning capture feature and its associated policies. - Revised `README.md` to include details on the new command and its usage, emphasizing the importance of confirming entries before writing. - Enhanced `instructions.md` and `index.md` to clarify the learning/pitfall entry format and the topic-split convention. - Introduced a new `learn.md` reference file detailing the command's syntax, boundaries, and steps for capturing learnings. - Improved documentation across various files to ensure consistency and clarity regarding memory management and learning capture processes. --- CHANGELOG.md | 7 ++ README.md | 5 +- skills/README.md | 2 +- skills/agent-memory/SKILL.md | 13 ++-- skills/agent-memory/references/bootstrap.md | 18 ++--- skills/agent-memory/references/consolidate.md | 9 ++- skills/agent-memory/references/learn.md | 67 +++++++++++++++++++ skills/agent-memory/references/lint.md | 8 ++- skills/agent-memory/references/sync.md | 6 +- skills/agent-memory/references/update.md | 4 +- skills/agent-memory/vendor/README.md | 24 +++---- skills/agent-memory/vendor/memory/index.md | 2 +- .../vendor/memory/instructions.md | 48 +++++++++---- tests/reference-first-contract.sh | 59 ++++++++++++++-- 14 files changed, 214 insertions(+), 58 deletions(-) create mode 100644 skills/agent-memory/references/learn.md diff --git a/CHANGELOG.md b/CHANGELOG.md index de1bca0..7e1c70a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ Migration details for `/agent-memory update` live in [`skills/agent-memory/vendo ## [Unreleased] +### Added + +- `/agent-memory learn [>topic] ` — gated capture of one learning/pitfall into `learnings.md` or `learnings-.md` (confirm; no `--auto`); conflict/dirty guards, slug sanitizing, deterministic target routing, and duplicate-rule skip. +- Topic-split convention for learnings (`learnings-.md`) with optional `when editing:` scope hints in `index.md` — normative match contract in `instructions.md` (_Always load_). +- H2 learning/pitfall entry format (aligned with decisions), legacy one-liner kept valid, duplicate rule across formats, and writing guidance (generalize; prefer correct patterns). + ### Security - OpenCode plugin: refuse symlink hook scripts, confine resolved paths under `.opencode/hooks`, and validate session/conversation binding IDs before env/stdin. @@ -16,6 +22,7 @@ Migration details for `/agent-memory update` live in [`skills/agent-memory/vendo ### Changed - `instructions.md` slimmed for always-load: permission boundaries, numbered precedence, task-organized sections, observable turn closure, and formats linked to templates (`TEMPLATE.md`, `log.md`, `decisions.md`) instead of duplicated inventories. +- Learning/pitfall format and topic-split / scope-hint policy documented in `instructions.md` and `index.md`; `bootstrap` / `sync` / `lint` / `consolidate` aligned. - CLI build publishes `bin/cli.js` without minify for supply-chain auditability. ## [0.1.0] - 2026-07-27 diff --git a/README.md b/README.md index 45cf1de..6730397 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Memory lives at `.agents/memory/` and separates **canonical project sources** fr | `decisions.md` | Decision **pointers** (or local fallback when no ADR system). | | `log.md` | Recent **semantic** session deltas (append at the bottom). | -Optional on demand: `learnings.md` — evidenced learnings/pitfalls with no better source. Do **not** create parallel vision/architecture/patterns/domains copies; link the project's own docs instead. +Optional on demand: `learnings.md` or `learnings-.md` — evidenced learnings/pitfalls with no better source; optional `when editing:` hints in `index.md`. Capture explicitly with `/agent-memory learn`. Do **not** create parallel vision/architecture/patterns/domains copies; link the project's own docs instead. -**Workflow:** before a task, agents read `index.md`, `current.md`, and their branch's `active-work` file when it exists; **primary write** is in-turn (resume fields + semantic `log.md` outcomes); **catch-up** at checkpoints via `/agent-memory sync` (or follow the skill's `references/sync.md` without invoking the skill); periodically `/agent-memory consolidate` to promote useful facts and prune closed-session noise. Hooks store ephemeral path/session evidence in `.hook-sync-state` only — never Markdown. +**Workflow:** before a task, agents read `index.md`, `current.md`, and their branch's `active-work` file when it exists (plus any recall file whose `when editing:` hint matches task paths — contract in `instructions.md`); **primary write** is in-turn (resume fields + semantic `log.md` outcomes); **catch-up** at checkpoints via `/agent-memory sync` (or follow the skill's `references/sync.md` without invoking the skill); `/agent-memory learn` to capture a gated learning now; periodically `/agent-memory consolidate` to promote useful facts and prune closed-session noise. Hooks store ephemeral path/session evidence in `.hook-sync-state` only — never Markdown. Full method: [`skills/agent-memory/vendor/README.md`](./skills/agent-memory/vendor/README.md) and [`instructions.md`](./skills/agent-memory/vendor/memory/instructions.md). @@ -81,6 +81,7 @@ Use `init ` when you already know the agent. | `/agent-memory bootstrap` | Inventory canonical sources and gaps; populate pointers. | | `/agent-memory sync` | Refresh `current.md` / active-work / `log.md` / `index.md`. | | `/agent-memory lint` | Broken links, orphans, duplication, stale branches, consistency. | +| `/agent-memory learn` | Capture one gated learning/pitfall (`learn [>topic] `). | | `/agent-memory consolidate` | Promote useful facts; prune closed-session noise (guided). | ## Hooks diff --git a/skills/README.md b/skills/README.md index cae48b0..c863008 100644 --- a/skills/README.md +++ b/skills/README.md @@ -6,6 +6,6 @@ Skills that operate the [Agent Memory](./agent-memory/vendor/README.md) method. Manual-only skill that orchestrates the local recall layer. See [`agent-memory/SKILL.md`](./agent-memory/SKILL.md) for routing and [`agent-memory/vendor/memory/instructions.md`](./agent-memory/vendor/memory/instructions.md) for the method. -Commands: `init`, `install hooks`, `update`, `bootstrap`, `sync`, `lint`, `consolidate`, `help`. +Commands: `init`, `install hooks`, `update`, `bootstrap`, `sync`, `lint`, `consolidate`, `learn`, `help`. `init` wires harness-native instruction files (`.cursor/rules/*.mdc`, `.github/instructions/*.instructions.md`, or `AGENTS.md` / `CLAUDE.md` / `GEMINI.md`). Hooks are user-installed separately. diff --git a/skills/agent-memory/SKILL.md b/skills/agent-memory/SKILL.md index 9bc64fa..152ed39 100644 --- a/skills/agent-memory/SKILL.md +++ b/skills/agent-memory/SKILL.md @@ -19,8 +19,10 @@ description: >- (check the memory for broken links, orphans, duplication, and consistency; accepts `--fix` to also delete stale per-branch `active-work` files), `consolidate` (guided promotion/pruning of closed-session noise — no `--auto`), - or `help` (list the commands and how to use them). Never trigger automatically; - this skill must be invoked on demand only. + `learn` (capture one gated learning/pitfall into `learnings.md` or + `learnings-.md` — no `--auto`), or `help` (list the commands and how + to use them). Never trigger automatically; this skill must be invoked on + demand only. metadata: invocation: manual version: "0.1.0" @@ -87,6 +89,7 @@ Read the subcommand from the invocation, load **only** the matching reference, a | `sync` | Refresh `current.md` / active-work / `log.md` / `index.md` from repo state. | `references/sync.md` | | `lint` | Check the memory for structural and consistency problems. | `references/lint.md` | | `consolidate` | Guided promotion/pruning of closed-session noise (confirm each diff; no `--auto`). | `references/consolidate.md` | +| `learn` | Capture one gated learning/pitfall into `learnings.md` or a topic split (confirm; no `--auto`). | `references/learn.md` | | `help` | List the commands and how to use them. | _Help_ section below | If no subcommand is given, or it is not one of those above, run `help` (below) and stop. Do not guess the user's intent. @@ -107,6 +110,7 @@ For `/agent-memory help` (and for any empty or unknown invocation), output the f | Command | Does | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/agent-memory help` | Show this guide. | | `/agent-memory init` | Create `.agents/memory/`; auto-detect harnesses and write the native instruction file (`.mdc`, `.instructions.md`, or agent `*.md`), or `init ` for one. | | `/agent-memory install hooks` | Print how to install or refresh hooks for one harness — `cursor`, `claude`, `codex`, `opencode`, `copilot`, `gemini` (memory must exist). | | `/agent-memory bootstrap` | Inventory canonical sources and gaps (up to 3 subagents); populate pointers — not doc copies. | @@ -114,7 +118,7 @@ For `/agent-memory help` (and for any empty or unknown invocation), output the f | `/agent-memory sync` | Refresh `current.md` / active-work / `log.md` / `index.md` from repo state. `--auto` applies all diffs without per-file prompts. | | `/agent-memory lint` | Check for broken links, orphans, duplication, stale branches, and consistency. `--fix` also deletes stale per-branch `active-work` files. | | `/agent-memory consolidate` | Promote useful facts and prune closed-session noise (guided; confirm each diff; no `--auto`). | -| `/agent-memory help` | Show this guide. | +| `/agent-memory learn` | Capture one gated learning/pitfall (`learn [>topic] `). Confirm before write; no `--auto`. | **Getting started** @@ -122,6 +126,7 @@ For `/agent-memory help` (and for any empty or unknown invocation), output the f - Memory exists but hooks missing or stale? Run `install hooks ` for instructions, or re-run the installer from the release tag. - Keeping the memory current? Write resume fields + semantic `log.md` in the turn (primary); run `sync` at checkpoints for catch-up (or follow `references/sync.md` without invoking the skill). Use `sync --auto` for low-friction routine flushes. - Pruning noise? Run `consolidate` periodically (guided; never automatic). +- Capture a lesson now? Run `learn [>topic] ` (retention gate; confirm). - Already set up? Use `lint` to check health (`lint --fix` also removes stale per-branch files), `update` to upgrade memory scaffolding, then refresh hooks with the user-run installer if needed. Method & conventions: `.agents/memory/instructions.md` @@ -130,7 +135,7 @@ Method & conventions: `.agents/memory/instructions.md` ## Shared rules (apply to every command) -- **Never modify project memory content** — `current.md`, `active-work/*`, `decisions.md`, `log.md`, `learnings.md`, legacy `domains/*` / `features/*`, and other user-authored recall — unless a command explicitly says so, and only after the user confirms. Never edit project docs/ADRs outside `.agents/memory/`. +- **Never modify project memory content** — `current.md`, `active-work/*`, `decisions.md`, `log.md`, `learnings.md`, `learnings-*.md`, legacy `domains/*` / `features/*`, and other user-authored recall — unless a command explicitly says so, and only after the user confirms. **Exception:** primary write in-turn and `bootstrap` follow `instructions.md` directly (gated learnings/decisions are written when discovered, without this skill's per-entry confirmation); per-diff confirmation applies to `/agent-memory learn`, `consolidate`, and `lint --fix` edits. Never edit project docs/ADRs outside `.agents/memory/`. - Run memory/orchestration steps inside the user's current agent. **Do not download, clone, or execute hook installers** — only print instructions for the user to run. - If the host ignores `allowed-tools` granularity: still **never** run `git clone`, `git fetch`, `git pull`, or any network fetch for this skill. - All paths are relative to the target project root unless stated otherwise (vendor paths are relative to this skill directory). diff --git a/skills/agent-memory/references/bootstrap.md b/skills/agent-memory/references/bootstrap.md index 418a69d..03f5423 100644 --- a/skills/agent-memory/references/bootstrap.md +++ b/skills/agent-memory/references/bootstrap.md @@ -15,14 +15,14 @@ Analyze the project and populate the memory as a **source inventory + gaps** — 4. **Synthesize and write (inventory-first, skip empties).** Wait for all three, then fill memory **without copying docs**: - | Source | Writes to | - | ------------ | ----------------------------------------------------------- | - | A (sources) | `index.md` → _Canonical project sources_ (few entry points) | - | A (ADRs) | `decisions.md` — optional single pointer to ADR index/dir | - | | when a decision system exists and is useful for continuity | - | B + C (gaps) | `learnings.md` — **only** stable, evidenced, undocumented | - | | facts that pass the gate in `instructions.md` | - | synthesis | `log.md` — one bootstrap session entry | + | Source | Writes to | + | ------------ | ------------------------------------------------------------- | + | A (sources) | `index.md` → _Canonical project sources_ (few entry points) | + | A (ADRs) | `decisions.md` — optional single pointer to ADR index/dir | + | | when a decision system exists and is useful for continuity | + | B + C (gaps) | `learnings.md` (or a clear `learnings-.md`) — **only** | + | | stable, evidenced, undocumented facts that pass the gate | + | synthesis | `log.md` — one bootstrap session entry | Rules: - Do **not** create `vision.md`, `architecture.md`, `patterns.md`, `mistakes.md`, `known-issues.md`, `domains/*`, or `features/*`. @@ -30,7 +30,7 @@ Analyze the project and populate the memory as a **source inventory + gaps** — - Leave `current.md` with empty placeholders if there is no active work — do not invent milestones, Done lists, or roadmaps. - Leave `active-work/` with only its `TEMPLATE.md`. - Do **not** invent decisions — only point at an existing ADR index/dir when helpful, or leave `decisions.md` empty. - - Create `learnings.md` only when at least one fact passes the gate (reusable, undocumented, non-obvious, evidenced, no secrets). Use `[learning]` or `[pitfall]` tags per `instructions.md`. Mark facts that should become official docs with `pending-doc`. Link `learnings.md` from `index.md` when created. + - Create `learnings.md` (or a topic split) only when at least one fact passes the gate (reusable, undocumented, non-obvious, evidenced, no secrets). Use the H2 learning/pitfall format in `instructions.md`. Mark facts that should become official docs with `pending-doc`. Link every new learnings file from `index.md` (optional `when editing:` when paths are clear). Prefer one `learnings.md` on first bootstrap unless a single theme dominates. - Append to `log.md` using the per-session format in `instructions.md`, e.g. `## [YYYY-MM-DD] [docs] bootstrap source inventory` with bullets listing sources indexed / learnings created / gaps reported. - Keep every `index.md` source line to: link + what it owns + when to read. diff --git a/skills/agent-memory/references/consolidate.md b/skills/agent-memory/references/consolidate.md index ca4809d..dd10642 100644 --- a/skills/agent-memory/references/consolidate.md +++ b/skills/agent-memory/references/consolidate.md @@ -37,7 +37,9 @@ Guided, conservative promotion and pruning of memory. Turns closed-session noise 4. **Classify each candidate.** Propose one action per item: - **Reference** — replace body with a pointer to a canonical source; update `index.md` if needed. - **Decision** — add/replace pointer in `decisions.md` (or local fallback if no ADR system); mark superseded entries instead of deleting them. - - **Learning / pitfall** — promote to `learnings.md` with evidence + use trigger (+ `invalidate when` when useful). + - **Learning / pitfall** — promote to `learnings.md` or an existing `learnings-.md` using the H2 format in `instructions.md` (evidence + use when + verified + invalidate when). Prefer an existing topic split when the theme matches; otherwise `learnings.md`. Apply the duplicate rule from `instructions.md` — skip when the insight already exists in the target file (H2 or legacy one-liner). + - **Split** — when `learnings.md` is large or thematically clustered, propose moving entries into `learnings-.md` and updating `index.md` (optional `when editing:` hints). Convert moved entries to the H2 form as part of the move (do not move raw one-liners unless the user declines conversion). Confirm; never auto-split. + - **Merge** — when a topic split is tiny or redundant with another, propose merging back into `learnings.md` or a sibling split; same H2 conversion and duplicate rule (confirm). - **Current** — keep in `current.md` / active-work because still active. - **Discard** — remove because transient, reconstructible from Git, or duplicated (including legacy path bullets and empty headings). - **Defer** — preserve when unsure or waiting on external doc promotion (`pending-doc`). @@ -45,14 +47,15 @@ Guided, conservative promotion and pruning of memory. Turns closed-session noise 5. **Show the classification plan** to the user (table or grouped list). Do not write yet. 6. **Apply in safe order** — confirm each diff (approve / skip / abort): - 1. Additions/promotions first: `decisions.md`, `learnings.md`, `current.md` (shared blockers only if still active), `index.md`. - 2. Only after a promotion is **approved**, propose removing its origin from `log.md` or a legacy file body. If promotion is declined, **keep** the origin. + 1. Additions/promotions first: `decisions.md`, `learnings.md` / `learnings-*.md`, `current.md` (shared blockers only if still active), `index.md` (including new/updated learnings links and `when editing:` hints). + 2. Only after a promotion is **approved**, propose removing its origin from `log.md` or a legacy file body. If promotion is declined, **keep** the origin. Apply approved split/merge moves only after the destination write is confirmed. 3. Propose removal of legacy path-only bullets, empty closed-session headings, and legacy _Touched files_ sections (Git available; evidence reconstructible). 4. Propose deleting stale `active-work/.md` one-by-one, or with an explicit "delete all stale" approval. Never delete `TEMPLATE.md`. 5. For legacy mirrors: prefer converting to pointers / learnings over delete; deleting a legacy file is sensitive and must be confirmed. 7. **Report.** Summarize separately: - **promoted** — decision or learning/pitfall bodies added; + - **split / merged** — learnings moved between `learnings.md` and topic splits; - **referenced** — pointers to canonical sources (no body copy); - **superseded** — prior decisions marked with `Superseded by:`; - **discarded** — transient / reconstructible / duplicated removed; diff --git a/skills/agent-memory/references/learn.md b/skills/agent-memory/references/learn.md new file mode 100644 index 0000000..f773c04 --- /dev/null +++ b/skills/agent-memory/references/learn.md @@ -0,0 +1,67 @@ +# `/agent-memory learn` + +Capture one gated learning or pitfall into Workspace Memory. Applies the retention gate in `instructions.md`, writes the canonical H2 entry, and links the file from `index.md` when needed. Confirm before writing. Does **not** accept `--auto`. + +## Syntax + +```text +/agent-memory learn [>topic] +``` + +- `>topic` — optional. Target a topic split (`learnings-.md`). The slug is sanitized like branch names (lowercase; every character outside `[a-z0-9-]` → `-`; collapse repeats); the resulting slug is shown in the confirmation diff. Stop only when the sanitized slug is empty or collides with an existing split of a different theme. +- `` — required. Free text from the user and/or the current session; the agent turns it into a generalized, actionable Insight. + +Examples: + +- `/agent-memory learn OpenCode spawn must go through safe-script before execFileSync` +- `/agent-memory learn >hooks hooks never write Markdown under .agents/memory` + +## Boundary + +- **May create/edit** `learnings.md`, `learnings-.md`, and the matching link line in `index.md` (with confirmation). +- **Must not** edit `current.md`, `active-work/*`, `decisions.md`, `log.md`, `instructions.md`, or anything outside `.agents/memory/`. +- **Must not** copy docs into memory or invent evidence. +- Skill stays manual-only — never auto-trigger learn. + +## Steps + +1. **Guard.** If `.agents/memory/` does not exist, stop and suggest `/agent-memory init`. If any target file (`learnings.md`, the resolved `learnings-.md`, or `index.md`) has unresolved merge conflict markers, **stop**. If those files have uncommitted changes, warn and require confirmation before proposing diffs — never silently overwrite pre-existing edits. + +2. **Parse input.** Extract optional `>topic` and the lesson clue. If the clue is empty, stop and show usage. Sanitize `>topic` to the slug form above and use it for the filename. + +3. **Apply the retention gate** (`instructions.md` → _Retention gate and lifecycle_). Walk the gate explicitly. If any step fails (not reusable, already in a canonical source, task-only state, decision not learning, unevidenced, secrets), **stop**: report which step failed and what to do instead (e.g. active-work, `decisions.md`, pointer-only, or skip). Do not write a learning that failed the gate. + +4. **Choose the target file.** + - With `>topic`: the sanitized `learnings-.md` (create if missing). + - Without topic: default `learnings.md`. If the clue explicitly names an existing split's slug, or exactly one existing split unambiguously owns the theme, propose that file in the confirmation diff. If more than one split could own it, **stop** and ask the user for `>topic` — do not guess. + - Never write under `domains/*` or `features/*`. + +5. **Dedupe.** Read the target file first. Skip and report the existing entry — without writing — when the duplicate rule in `instructions.md` matches: same normalized topic + equivalent Insight in an H2 entry, or a legacy one-liner covering the same insight. When a legacy one-liner duplicates the lesson, offer to convert it to H2 in the same confirmed diff instead of appending. + +6. **Draft the entry** in the canonical H2 form from `instructions.md`: + + ```md + ## [YYYY-MM-DD] [learning|pitfall] Short topic + + - Insight: reusable pattern (prefer what to do; generalize beyond this incident). + - Evidence: path|link + - Use when: trigger + - Verified: YYYY-MM-DD + - Invalidate when: condition + ``` + + Use today's date for the heading and `Verified`. Choose `learning` or `pitfall`. Add `- pending-doc` only when the fact belongs in official docs. + +7. **Draft the `index.md` line.** When the file is new or unlisted, add the link. When the file is already listed **without** a `when editing:` hint and the evidence makes paths obvious, propose updating that existing line in place (never a second entry). Hints are allowed on any learnings link per `instructions.md` → _Always load_; never invent globs without path evidence. + +8. **Show the proposal** (entry + `index.md` change if any) as a diff. Confirm: approve / skip / abort. On skip or abort, write nothing. + +9. **Apply.** Append the entry at the **bottom** of the target file (oldest first). Create the file with a short H1 (`# Learnings` or `# learnings`) only when creating. Update `index.md` _Recall files_ when needed. + +10. **Report.** File written, topic tag, whether `index.md` changed (and whether a hint was added/updated), and one line on when to load it next (`when editing` or on-demand). + +## Notes + +- Align with writing guidance in `instructions.md`: generalize; prefer correct patterns over “don’t” lists. +- Primary write in-turn may still append learnings without this command; `learn` is the explicit capture path when the user wants a gated write now. +- `/agent-memory consolidate` remains the path for promoting closed-session log noise into learnings and for proposing topic splits/merges. diff --git a/skills/agent-memory/references/lint.md b/skills/agent-memory/references/lint.md index 5c47074..a7d57f5 100644 --- a/skills/agent-memory/references/lint.md +++ b/skills/agent-memory/references/lint.md @@ -159,7 +159,7 @@ Check `.agents/memory/` for structural and consistency problems. Report findings - each `active-work/*.md` (except TEMPLATE) > 60 → warn bloat. - `index.md` > 100 → warn bloat. - `log.md` > 30 session headings (`^## \[`) → suggest consolidate. - - `decisions.md` or `learnings.md` > 200 → suggest topic splits (do not auto-split). + - `decisions.md` or any `learnings.md` / `learnings-*.md` > 200 → suggest topic splits or consolidate merge (do not auto-split). 4. **Semantic checks (judgment — report as warnings to review).** These need reading, not grepping; surface them for the user to confirm rather than auto-fixing: - **Stale `current.md`** — does _In progress_ still match open active-work? @@ -168,7 +168,9 @@ Check `.agents/memory/` for structural and consistency problems. Report findings - **Duplication** — paraphrased facts also in AGENTS/README/docs/ADR (exact long-line overlap is handled deterministically above). - **Local decision with ADR** — local fallback body that should be a pointer. - **Superseded without link** — `Status: superseded` without `Superseded by:`, or a newer decision that should mark an older one superseded. - - **Learning/pitfall without evidence / use trigger / verified.** + - **Learning/pitfall without evidence / use trigger / verified** — missing fields on H2 entries or legacy one-liners. + - **Legacy learning one-liner** — `- [YYYY-MM-DD] [learning|pitfall] …` without an H2 heading; suggest migrating to the H2 form when editing (do not auto-rewrite). + - **Invalid or stale `when editing:`** — per the contract in `instructions.md` → _Always load_: glob that matches no repo path, non-repo-root-relative glob, or a topic split with no hint when evidence paths are obvious. Cross-cutting `learnings.md` without a hint is fine. - **Stale `pending-doc` learnings.** - **Contradictions** — memory vs canonical source or code. - **Legacy path-only bullets / empty headings / Touched files** — candidates for consolidate. @@ -178,7 +180,7 @@ Check `.agents/memory/` for structural and consistency problems. Report findings 5. **Report.** Group findings as **errors** (broken links, missing required headings, orphans, stale per-branch files) and **warnings** (semantic, budgets, legacy). For each, name the file and the problem. -6. **Fix offer.** Offer to fix only safe issues (e.g. remove a dead link, add an orphan recall file to `index.md`). Any fix that edits user content (`current.md`, `decisions.md`, `learnings.md`, …) must be confirmed first — show the diff. For stale `current.md` / active-work / `log.md`, suggest `/agent-memory sync` rather than editing by hand. For promotion/pruning / converting legacy mirrors / removing path-only bullets, suggest `/agent-memory consolidate` — **do not** do that work in `lint --fix`. +6. **Fix offer.** Offer to fix only safe issues (e.g. remove a dead link, add an orphan recall file to `index.md`). Any fix that edits user content (`current.md`, `decisions.md`, `learnings.md`, `learnings-*.md`, …) must be confirmed first — show the diff. For stale `current.md` / active-work / `log.md`, suggest `/agent-memory sync` rather than editing by hand. For promotion/pruning / converting legacy mirrors / removing path-only bullets / learnings split-merge, suggest `/agent-memory consolidate` — **do not** do that work in `lint --fix`. For capturing a new gated learning now, suggest `/agent-memory learn`. `--fix` — with this flag, also offer to **delete stale per-branch `active-work/.md` files** (files whose branch no longer exists) and, for **delegation-canary** findings (step 2), offer to remove the redundant block from `CLAUDE.md`/`GEMINI.md` that delegate via `@AGENTS.md` (each removal sensitive — show diff, confirm). Each deletion is still confirmed one by one (it removes a file, so it is sensitive) unless combined with an explicit "delete all stale" approval. `--fix` never deletes anything other than stale `active-work` files, never touches `TEMPLATE.md`, never deletes legacy mirror files. Delegation-canary block removal edits only the agent-memory delimiters in `CLAUDE.md`/`GEMINI.md` (with confirmation). diff --git a/skills/agent-memory/references/sync.md b/skills/agent-memory/references/sync.md index ede2051..a270fc3 100644 --- a/skills/agent-memory/references/sync.md +++ b/skills/agent-memory/references/sync.md @@ -13,7 +13,7 @@ Use sync at any checkpoint: end of a task, before a commit, before context compa ## Boundary -Sync writes only to: `current.md`, `active-work/.md`, `log.md`, and `index.md` (recall-file links and newly relevant canonical source links when evidence exists). It **never** touches `decisions.md`, `learnings.md`, `instructions.md`, or any file outside `.agents/memory/`. It never deletes anything except replacing placeholder lines inside the four target files. It never copies documentation, never invents roadmaps, and never re-indexes the whole docs tree. +Sync writes only to: `current.md`, `active-work/.md`, `log.md`, and `index.md` (recall-file links and newly relevant canonical source links when evidence exists). It **never** touches `decisions.md`, `learnings.md`, `learnings-*.md`, `instructions.md`, or any file outside `.agents/memory/`. It never deletes anything except replacing placeholder lines inside the four target files. It never copies documentation, never invents roadmaps, and never re-indexes the whole docs tree. On `index.md`, existing `when editing:` hints are preserved verbatim (details in the steps below). Hooks never write Markdown. They may populate `.hook-sync-state` (gitignored) with session id, branch, touched paths, and `last_processed_head`. Sync may **read** that state as evidence, then write semantic resume fields and log outcomes. The split is the same on every harness — see `instructions.md` → _Harness parity — memory contract_. @@ -49,11 +49,11 @@ Hooks never write Markdown. They may populate `.hook-sync-state` (gitignored) wi - **`active-work/.md`** — fill/refresh _Task_, _Progress_ (facts only), _Next step_, _Validation_ (command + expected result), _Assumptions / open questions_, _Blockers_, _Rejected approaches_, and _References_ (path/link + why). Update `Checkpoint: YYYY-MM-DD @ ` from `git rev-parse --short HEAD`. Do **not** write path-only _Touched files_ sections. Overwrite only fields the evidence supports. - **`log.md`** — maintain **one heading per session** only when there is a useful outcome: `## [YYYY-MM-DD] [session-id] [type] short outcome` with `-` semantic bullets. Never write path bullets or `changed N files…`. Refine type/summary; dedupe. Oldest first / newest at bottom. Do not reopen or summarize closed sessions. Skip the file entirely when there is no semantic outcome. - **`current.md`** — refresh _In progress_ (list each open `active-work/*.md` with a one-line branch goal). Aggregate _Blockers / attention_ only for shared impediments. Update _Handoff_ only from an explicit instruction/plan. Do **not** maintain Done, milestone, or roadmap sections. - - **`index.md`** — for every existing recall file (`learnings.md`, topic splits, etc.) not yet listed, add a link. Remove links to deleted recall files. Add a **canonical source** link only when that source was created or became newly relevant this session — do not re-discover the whole docs tree. + - **`index.md`** — for every existing recall file (`learnings.md`, topic splits, etc.) not yet listed, add a link. Remove links to deleted recall files. When touching `index.md`, never remove or reformat `when editing:` hints on existing lines; when adding a newly listed orphan, write the minimal link without inventing a hint (hint creation belongs to `/agent-memory learn` / `consolidate` with path evidence). Add a **canonical source** link only when that source was created or became newly relevant this session — do not re-discover the whole docs tree. 6. **Apply approved diffs** only, with `Edit`/`Write` scoped to `.agents/memory/**`. Skip anything the user declined. -7. **Report.** List each file: updated, skipped, or unchanged — and one line on what the next agent should read to continue (the branch's active-work file plus `current.md`). If a decision or learning/pitfall trigger fired, remind the agent to update `decisions.md` / `learnings.md` (or the external ADR/doc) — sync does not write those files. Suggest `/agent-memory consolidate` when `log.md` has accumulated closed-session noise. +7. **Report.** List each file: updated, skipped, or unchanged — and one line on what the next agent should read to continue (the branch's active-work file plus `current.md`). If a decision or learning/pitfall trigger fired, remind the agent to update `decisions.md` / `learnings.md` (or run `/agent-memory learn`) — sync does not write those files. Suggest `/agent-memory consolidate` when `log.md` has accumulated closed-session noise. ## Notes diff --git a/skills/agent-memory/references/update.md b/skills/agent-memory/references/update.md index b812389..0e698be 100644 --- a/skills/agent-memory/references/update.md +++ b/skills/agent-memory/references/update.md @@ -4,7 +4,7 @@ Migrate an existing `.agents/memory/` to the latest structure from this skill's ## Boundary (read before doing anything) -- **Project memory (NEVER touch):** `current.md`, `active-work/*`, `decisions.md`, `log.md`, `learnings.md`, legacy `domains/*` / `features/*`, and any other user-authored recall content. +- **Project memory (NEVER touch):** `current.md`, `active-work/*`, `decisions.md`, `log.md`, `learnings.md`, `learnings-*.md`, legacy `domains/*` / `features/*`, and any other user-authored recall content. - **Scaffolding (may change, see rules):** `instructions.md`, the structural sections of `index.md`, the `.version` file, brand-new core files, and the agent-memory block in harness instruction files. - **Outside the block (NEVER touch):** any content in instruction files outside the agent-memory delimiters (`` … ``, or legacy plain tags). For `.cursor/rules/agent-memory.mdc`, preserve YAML frontmatter — refresh only the delimited body. @@ -37,7 +37,7 @@ The exact block `init` writes and `update` refreshes is defined in [`references/ - `current.md` structural cleanup from `UPDATE.md` (e.g. 0.0.14 removal of legacy `Version / milestone` / `Done` / `Next steps`) — preserve `## In progress` and any still-useful bullets the user wants kept. - `active-work/*.md` and `TEMPLATE.md` from 0.1.0 — add missing resume sections (`Next step`, `Validation`, `Assumptions / open questions`, `Rejected approaches`, `References`, `Checkpoint:`); offer removal of legacy `## Touched files` (sensitive — show diff, confirm). Preserve existing semantic content. - `log.md` / `decisions.md` scaffolding from 0.1.0 — refresh format docs only; preserve entries; do not invent headings. Legacy path-only bullets and empty closed-session headings are consolidate candidates (confirm). - - Any change to a file that can hold user content — including `index.md` (merge structural sections; **preserve** the user's _Canonical project sources_ and _Recall files_ lists, including `learnings.md` / topic splits). Legacy Domains/Features sections are not auto-preserved — convert them to pointers via `lint` / `consolidate`. + - Any change to a file that can hold user content — including `index.md` (merge structural sections; **preserve** the user's _Canonical project sources_ and _Recall files_ lists, including `learnings.md` / topic splits and any `when editing:` scope hints on existing learnings link lines). Legacy Domains/Features sections are not auto-preserved — convert them to pointers via `lint` / `consolidate`. - Any rename, move, or deletion. - **Skip superseded items** — e.g. do **not** agent-merge `.cursor/hooks.json` for `afterFileEdit` when `UPDATE.md` marks that 0.0.10 sensitive step as superseded (hooks refresh is user-run installer only). - Present each sensitive change as a unified diff and ask the user to approve, skip, or abort. Apply only what is approved. diff --git a/skills/agent-memory/vendor/README.md b/skills/agent-memory/vendor/README.md index 9582621..cf36694 100644 --- a/skills/agent-memory/vendor/README.md +++ b/skills/agent-memory/vendor/README.md @@ -16,21 +16,21 @@ Any project where AI agents do meaningful work across multiple sessions, and whe Agents **read AND write** the memory. Full workflow and multi-developer rules: [`memory/instructions.md`](./memory/instructions.md) (canonical method file). -Short version: before a task read `index.md`, `current.md`, and the branch `active-work` when it exists; **primary write** is in-turn (resume fields + semantic `log.md`); **catch-up** via `/agent-memory sync` (or follow `references/sync.md` without the skill); periodically `/agent-memory consolidate`. Hooks write only `.hook-sync-state` — never Markdown. +Short version: before a task read `index.md`, `current.md`, and the branch `active-work` when it exists (plus recall files matching `when editing:`); **primary write** is in-turn (resume fields + semantic `log.md`); **catch-up** via `/agent-memory sync` (or follow `references/sync.md` without the skill); `/agent-memory learn` for gated capture; periodically `/agent-memory consolidate`. Hooks write only `.hook-sync-state` — never Markdown. ## What's inside (`.agents/memory/`) -| File | Role | -| ----------------- | ------------------------------------------------------- | -| `instructions.md` | Canonical method (read first). | -| `index.md` | Map of canonical sources + recall files. | -| `current.md` | Shared active state (in progress / blockers handoff). | -| `active-work/` | Per-branch resume scratchpad (create when resumable). | -| `decisions.md` | Decision pointers or local fallback ADRs. | -| `log.md` | Recent semantic session deltas. | -| `.gitignore` | Ignores hook-local state. | +| File | Role | +| ----------------- | ----------------------------------------------------- | +| `instructions.md` | Canonical method (read first). | +| `index.md` | Map of canonical sources + recall files. | +| `current.md` | Shared active state (in progress / blockers handoff). | +| `active-work/` | Per-branch resume scratchpad (create when resumable). | +| `decisions.md` | Decision pointers or local fallback ADRs. | +| `log.md` | Recent semantic session deltas. | +| `.gitignore` | Ignores hook-local state. | -Optional on demand: `learnings.md`. Do not create parallel vision/architecture copies — link project docs instead. +Optional on demand: `learnings.md` / `learnings-.md` (optional `when editing:` in `index.md`). Do not create parallel vision/architecture copies — link project docs instead. ## Install @@ -43,7 +43,7 @@ Install the `agent-memory` skill ([skills.sh](https://www.skills.sh/diegoos/agen /agent-memory init # one harness (directory must exist) /agent-memory bootstrap # optional inventory /agent-memory install hooks # print hook install commands -/agent-memory update | sync | consolidate +/agent-memory update | sync | learn | consolidate ``` Hooks are **user-installed** (skill only prints commands) — see the [hooks README](https://github.com/diegoos/agent-memory/blob/0.1.0/hooks/README.md). diff --git a/skills/agent-memory/vendor/memory/index.md b/skills/agent-memory/vendor/memory/index.md index e61bc01..9f424f1 100644 --- a/skills/agent-memory/vendor/memory/index.md +++ b/skills/agent-memory/vendor/memory/index.md @@ -17,6 +17,6 @@ Keep aligned with useful entry points only (what they own + when to read). `/age - [decisions.md](./decisions.md) — decision pointers or local fallback. - [log.md](./log.md) — recent semantic session deltas. -- `learnings.md` — optional; create when the gate in `instructions.md` passes, then link here. Supports `learning` and `pitfall` entries. +- `learnings.md` — optional; create when the gate in `instructions.md` passes, then link here. Topic splits: `learnings-.md` (same gate). Any learnings link may carry a `when editing:` hint — syntax and match rule in `instructions.md` → _Always load_. Shape: `- [learnings-.md](./learnings-.md) — when editing: ; what it covers.` (shape only — add globs from evidence, never copy placeholder globs into a real memory). Older installs may still have legacy mirror files — convert via `lint` / `consolidate`; do not recreate. diff --git a/skills/agent-memory/vendor/memory/instructions.md b/skills/agent-memory/vendor/memory/instructions.md index f8a36c0..1a6a7b4 100644 --- a/skills/agent-memory/vendor/memory/instructions.md +++ b/skills/agent-memory/vendor/memory/instructions.md @@ -4,18 +4,20 @@ Workspace Memory in `.agents/memory/` is a Git-versioned **recall layer**, not a ## Always load -Harness context must load this file. Before every task, read `index.md` and `current.md`. Read the branch `active-work` file when it exists. Follow canonical sources in `index.md`; load `decisions.md`, `log.md`, and optional recall only when needed. Keep always-loaded files short: one fact per bullet, update before create, link instead of copy. Hot path: `index.md` + `current.md` + branch `active-work` (when present). `decisions.md`, `log.md`, and `learnings.md` are on-demand. +Harness context must load this file. Before every task, read `index.md` and `current.md`. Read the branch `active-work` file when it exists. Follow canonical sources in `index.md`; load `decisions.md`, `log.md`, and optional recall only when needed. When a learnings link in `index.md` carries a `when editing:` hint that matches the current task (contract below), read that file. Keep always-loaded files short: one fact per bullet, update before create, link instead of copy. Hot path: `index.md` + `current.md` + branch `active-work` (when present). `decisions.md`, `log.md`, `learnings.md`, and `learnings-*.md` are on-demand unless a `when editing:` hint matched. + +**`when editing:` contract** — syntax on an `index.md` recall line: `- [file](./file) — when editing: glob[, glob…]; description.` Globs are repo-root-relative, gitignore-style (`**` spans directories; `*` within one segment; no negation). Match rule: load the file when any task path — files in the current diff, files mentioned in the task, or paths in branch active-work _References_ — matches at least one glob (glob against the normalized repo-relative path). Comma-separated, trim spaces. Agents never write hints without path evidence; lint flags stale globs. ## Permission boundaries -| Mode | Scope | -| ---------------- | ---------------------------------------------------------------------------------------------------------------------- | -| READ | `.agents/memory/**` and canonical sources listed in `index.md` | -| WRITE | Versioned Markdown under `.agents/memory/` — **agent only** | -| NEVER | Hooks/plugin create or edit Markdown; invent progress or log bullets; copy docs into memory | -| HUMAN_CHECKPOINT | `/agent-memory consolidate` (promote/prune); resolve conflicting appends in `decisions.md` / `log.md` / `learnings.md` | +| Mode | Scope | +| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| READ | `.agents/memory/**` and canonical sources listed in `index.md` | +| WRITE | Versioned Markdown under `.agents/memory/` — **agent only** | +| NEVER | Hooks/plugin create or edit Markdown; invent progress or log bullets; copy docs into memory | +| HUMAN_CHECKPOINT | `/agent-memory consolidate` (promote/prune); `/agent-memory learn` (gated learning capture); resolve conflicting appends in `decisions.md` / `log.md` / `learnings.md` / `learnings-*.md` | -Multi-dev: edit only your `active-work/` (delete on merge); change `current.md` with the PR that changes shared active state; keep `decisions.md` / `learnings.md` / working `log.md` oldest-first and append-oriented — on conflict keep both valid contributions and mark supersession; prune closed log only via consolidate in a dedicated change (never the current session). +Multi-dev: edit only your `active-work/` (delete on merge); change `current.md` with the PR that changes shared active state; keep `decisions.md` / `learnings.md` / `learnings-*.md` / working `log.md` oldest-first and append-oriented — on conflict keep both valid contributions and mark supersession; prune closed log only via consolidate in a dedicated change (never the current session). ## Precedence @@ -34,7 +36,7 @@ No global source of truth — authority follows the fact: - Implemented behavior → code, tests, manifests, config - Temporary execution state → `current.md`, `active-work/.md` - Recent activity → `log.md` -- Reusable knowledge with no better source → on-demand `learnings.md` +- Reusable knowledge with no better source → on-demand `learnings.md` or `learnings-.md` ## Retention gate and lifecycle @@ -44,7 +46,7 @@ Before recording: 2. Already in a canonical source? → store only `link + delta/relevance` (optional `relevant when:` / `verified: YYYY-MM-DD` for code/config inferences). 3. Current-task state only? → branch `active-work`; shared active state → `current.md`. 4. Non-trivial decision? → pointer to the project decision system; local fallback in `decisions.md` only when none exists. Formats in `decisions.md`. -5. Stable, non-obvious, evidenced, undocumented, secret-free learning or pitfall? → `learnings.md`. +5. Stable, non-obvious, evidenced, undocumented, secret-free learning or pitfall? → `learnings.md` or a topic split (below). Prefer `/agent-memory learn` when capturing explicitly. 6. Transient, Git-reconstructible, or unevidenced? → do not make durable. Lifecycle: `active-work → log → canonical pointer | decision | learning | discard`. Record decisions/learnings when discovered; never remove durable knowledge without reason. Delete branch active-work on merge. Only manual `/agent-memory consolidate` may promote or prune closed sessions — never hooks, never mid-session automation, never the current session. Legacy mirrors may exist; do not create, auto-delete, or prefer them over canonical sources. Lint/consolidate may propose pointer conversion. @@ -53,7 +55,25 @@ Minimum pointer line: `- [topic] useful delta — source: [doc](../../path); rel **Log** — one `## [YYYY-MM-DD] [session-id] [type] short outcome` per session with useful outcomes (oldest first); semantic bullets only; never path lists, empty headings, or transcripts. Details and types in `log.md`. -**Learning / pitfall** — create `learnings.md` only when the gate passes, link from `index.md`, one line: `- [YYYY-MM-DD] [learning|pitfall] [topic] insight — evidence: path|link; use when: trigger; verified: YYYY-MM-DD; invalidate when: condition.` Append `pending-doc` when it belongs in official docs; keep until that source exists, then pointer or remove via consolidate. Code/config inferences need evidence + date. +**Learning / pitfall** — create a learnings file only when the gate passes, then link it from `index.md`. Write generalized, actionable patterns (prefer what to do over lists of “don’t”); extract the reusable lesson from the incident. Canonical entry (H2, oldest first): + +```md +## [YYYY-MM-DD] [learning|pitfall] Short topic + +- Insight: reusable pattern in one or two sentences. +- Evidence: path|link +- Use when: trigger +- Verified: YYYY-MM-DD +- Invalidate when: condition +``` + +Append a `- pending-doc` bullet when it belongs in official docs; keep until that source exists, then pointer or remove via consolidate. Code/config inferences need evidence + date. + +**Legacy one-liner** (pre-H2 installs): `- [YYYY-MM-DD] [learning|pitfall] [topic] insight — evidence: …; use when: …; verified: …` — still valid; do not rewrite in bulk. Migrate to H2 only when editing that entry or when consolidate moves it. + +**Duplicate rule** — never record the same lesson twice across formats: skip a new entry when an existing H2 has the same normalized topic and equivalent Insight, or when a legacy one-liner covers the same insight (same evidence/use-when, minor wording aside). Applies to in-turn writes, `/agent-memory learn`, and consolidate promotions. + +**Topic splits** — use `learnings.md` for cross-cutting lessons. When a theme has several entries (or lint warns `learnings.md` > 200 lines), split into `learnings-.md` where `` is a lowercase slug `[a-z0-9]+(-[a-z0-9]+)*`. Do not create `domains/*` or `features/*`. Link every learnings file from `index.md`; any learnings link may carry a `when editing:` hint (contract in _Always load_) — most useful on path-specific splits. Consolidate may propose split or merge (convert moved entries to H2); never auto-split without confirmation. ## When starting or resuming work @@ -61,7 +81,7 @@ Create `active-work/.md` only when work is resumable: Next step and Vali ## Workflow -**Primary write path (agent, in the turn):** when a turn produces durable progress, before stopping: update branch `active-work` resume fields (facts vs hypotheses, Next step, Validation) **and** append a semantic `log.md` outcome — or skip both only when the retention gate says the turn left nothing durable. Record decisions and gated learnings when discovered; align `index.md` when entry points change. Do not defer meaning to a later sync — hooks only accumulate evidence. +**Primary write path (agent, in the turn):** when a turn produces durable progress, before stopping: update branch `active-work` resume fields (facts vs hypotheses, Next step, Validation) **and** append a semantic `log.md` outcome — or skip both only when the retention gate says the turn left nothing durable. Record decisions and gated learnings when discovered (or via `/agent-memory learn`); align `index.md` when entry points change. Do not defer meaning to a later sync — hooks only accumulate evidence. **Catch-up (`/agent-memory sync`):** at end of turn / before compact / before commit / end of session, or when picking work back up — consistency pass over `current.md`, branch active-work, `log.md`, and `index.md`. It may read `.hook-sync-state` and `git` as evidence but never invents progress or log bullets without meaning. Update `current.md` only when shared active state changed; _Handoff_ must be explicit/evidenced. Sync never replaces decision/learning duties or copies docs. You may follow the skill's `references/sync.md` steps and edit those four files directly without invoking the skill command. @@ -71,8 +91,8 @@ Every supported harness targets the same memory shape. **Context layer** injects **Hooks own ephemeral evidence only:** session id binding; branch cache; session-cumulative touched paths; `last_processed_head` / commit range markers. Hooks never create or edit Markdown under `.agents/memory/`. -**Agent owns all versioned Markdown:** create/refine active-work and shared state; semantic log outcomes; resume fields (see `active-work/TEMPLATE.md`); source/recall links; decisions; gated learnings/pitfalls. Meaning is written in-turn (primary); sync is catch-up. Without hooks, use the same checkpoints and supply both evidence (from `git`) and meaning — via `/agent-memory sync` or by following `references/sync.md` directly. +**Agent owns all versioned Markdown:** create/refine active-work and shared state; semantic log outcomes; resume fields (see `active-work/TEMPLATE.md`); source/recall links; decisions; gated learnings/pitfalls (`learnings.md` / `learnings-*.md`, including `/agent-memory learn`). Meaning is written in-turn (primary); sync is catch-up. Without hooks, use the same checkpoints and supply both evidence (from `git`) and meaning — via `/agent-memory sync` or by following `references/sync.md` directly. ## Memory lint boundaries -Run `/agent-memory lint` on request or review. It checks structure, wiring, staleness, links, duplication, legacy mirrors, unsupported learnings, empty log headings, missing resume sections, Checkpoint freshness vs HEAD (`stale-resume`), and pending hook path evidence (`evidence-pending`); it warns rather than adjudicating product truth or deleting user content. Soft line/heading budgets and auto-fix limits live in the skill's `lint` reference — consolidation handles promotion/pruning, not `lint --fix`. +Run `/agent-memory lint` on request or review. It checks structure, wiring, staleness, links, duplication, legacy mirrors, unsupported learnings (including legacy one-liners and topic-split / `when editing:` hints), empty log headings, missing resume sections, Checkpoint freshness vs HEAD (`stale-resume`), and pending hook path evidence (`evidence-pending`); it warns rather than adjudicating product truth or deleting user content. Soft line/heading budgets and auto-fix limits live in the skill's `lint` reference — consolidation handles promotion/pruning and learnings split/merge, not `lint --fix`. diff --git a/tests/reference-first-contract.sh b/tests/reference-first-contract.sh index 12251d1..dee36e7 100755 --- a/tests/reference-first-contract.sh +++ b/tests/reference-first-contract.sh @@ -94,10 +94,15 @@ assert_contains "$instructions" '**Catch-up (`/agent-memory sync`):**' \ assert_contains "$instructions" 'without invoking the skill command' \ "sync may be followed without skill invoke" assert_contains "$instructions" '## Memory lint boundaries' "lint boundaries summary" -assert_contains "$instructions" \ - '- [YYYY-MM-DD] [learning|pitfall] [topic] insight — evidence: path|link; use when: trigger; verified: YYYY-MM-DD; invalidate when: condition.' \ - "learning/pitfall entry format" +assert_contains "$instructions" '## [YYYY-MM-DD] [learning|pitfall] Short topic' \ + "learning/pitfall H2 entry format" +assert_contains "$instructions" '- Insight: reusable pattern in one or two sentences.' \ + "learning Insight field" +assert_contains "$instructions" 'learnings-.md' "topic split convention" +assert_contains "$instructions" 'when editing:' "scope hint convention" +assert_contains "$instructions" 'prefer what to do' "learning writing guidance" assert_contains "$instructions" 'pending-doc' "pending-doc lifecycle" +assert_contains "$instructions" '/agent-memory learn' "learn command named in method" assert_absent "$instructions" 'Soft warning budgets:' \ "soft budgets stay in lint reference, not always-load" @@ -112,13 +117,15 @@ assert_contains "$update" 'Ensure `.agents/memory/.gitignore` exists' \ "update ensures .gitignore" assert_contains "$update" 'do **not** rely on directory listings' \ "update does not rely on Glob for .gitignore" +assert_contains "$update" '`when editing:` scope hints' \ + "update preserves when-editing hints on index merge" assert_contains "$lint" '.agents/memory/.gitignore' "lint checks .gitignore" # --- Bootstrap --- assert_contains "$bootstrap" 'A — Source inventory.' "bootstrap inventories sources" assert_contains "$bootstrap" 'never paste' "bootstrap does not copy bodies" assert_contains "$bootstrap" 'Do **not** create `vision.md`' "bootstrap forbids vision mirrors" -assert_contains "$bootstrap" '[learning]' "bootstrap mentions learning tag" +assert_contains "$bootstrap" 'H2 learning/pitfall format' "bootstrap uses H2 learning format" # --- Lint --- assert_contains "$lint" 'Legacy mirrors' "lint identifies mirrors" @@ -130,6 +137,8 @@ assert_contains "$lint" 'legacy-path-bullet' "lint checks legacy path bullets" assert_contains "$lint" 'Soft budgets (warnings only)' "soft budgets live in lint" assert_contains "$lint" 'stale-resume:' "lint checks checkpoint freshness vs HEAD" assert_contains "$lint" 'evidence-pending:' "lint checks pending hook path evidence" +assert_contains "$lint" 'Legacy learning one-liner' "lint warns on legacy learning one-liners" +assert_contains "$lint" 'when editing:' "lint mentions scope hints" # --- Sync --- assert_contains "$sync" 'Sync writes only to:' "sync four-file boundary" @@ -138,6 +147,7 @@ for target in 'current.md' 'active-work/.md' 'log.md' 'index.md'; do done assert_contains "$sync" 'It **never** touches `decisions.md`, `learnings.md`,' \ "sync excludes durable recall" +assert_contains "$sync" 'learnings-*.md' "sync excludes topic splits" assert_contains "$sync" 'Hooks never write Markdown' "sync documents ephemeral hooks" assert_contains "$sync" '_Validation_' "sync fills Validation" assert_contains "$sync" '_Workflow_' "sync links live Workflow section" @@ -156,6 +166,47 @@ assert_before "$consolidate" \ "consolidate promotes before pruning" assert_contains "$consolidate" 'Legacy `## Touched files`' \ "consolidate cleans legacy Touched files" +assert_contains "$consolidate" '**Split**' "consolidate can propose topic splits" +assert_contains "$consolidate" 'learnings-.md' "consolidate targets topic splits" + +# --- Learn --- +learn="$repo_root/skills/agent-memory/references/learn.md" +assert_contains "$learn" 'retention gate' "learn applies retention gate" +assert_contains "$learn" 'learnings-.md' "learn supports topic splits" +assert_contains "$learn" 'Does **not** accept `--auto`' "learn has no auto" +assert_contains "$learn" 'when editing:' "learn may set scope hints" +assert_contains "$learn" 'merge conflict markers' "learn guards on conflicts" +assert_contains "$learn" 'uncommitted changes' "learn warns on dirty memory" +assert_contains "$learn" 'sanitized' "learn sanitizes topic slug" +assert_contains "$learn" 'do not guess' "learn does not guess ambiguous target" +assert_contains "$learn" 'already listed **without** a `when editing:` hint' \ + "learn updates existing index line" +assert_contains "$learn" '## [YYYY-MM-DD] [learning|pitfall] Short topic' \ + "learn uses canonical H2 entry" +skill="$repo_root/skills/agent-memory/SKILL.md" +assert_contains "$skill" '`learn`' "SKILL routes learn" +assert_contains "$skill" 'references/learn.md' "SKILL points at learn reference" +assert_contains "$skill" '| `/agent-memory learn`' "SKILL help lists learn" +assert_contains "$skill" '**Exception:** primary write in-turn' \ + "SKILL allows in-turn gated capture" +index="$repo_root/skills/agent-memory/vendor/memory/index.md" +assert_contains "$index" 'when editing:' "index documents scope hints" +assert_contains "$index" 'learnings-.md' "index documents topic splits" +assert_contains "$index" 'shape only' "index example marked as shape placeholder" +assert_absent "$index" 'learnings-hooks.md' \ + "index skeleton has no repo-specific example file" +assert_contains "$instructions" 'gitignore-style' \ + "when-editing glob dialect pinned" +assert_contains "$instructions" 'Match rule: load the file when any task path' \ + "when-editing match rule pinned" +assert_contains "$instructions" '**Duplicate rule**' "duplicate rule in SoT" +assert_contains "$instructions" '**Legacy one-liner**' "legacy one-liner documented in SoT" +assert_contains "$sync" 'never remove or reformat `when editing:` hints' \ + "sync preserves existing hints" +assert_contains "$consolidate" 'duplicate rule' \ + "consolidate applies duplicate rule" +assert_contains "$consolidate" 'Convert moved entries to the H2 form' \ + "consolidate converts on split" # --- Context layer stays short --- assert_contains "$agent_block" 'Read `.agents/memory/instructions.md`' \