diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/headless-runs.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/headless-runs.md new file mode 100644 index 00000000..e0827717 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/headless-runs.md @@ -0,0 +1,43 @@ +# Headless runs + +Both hosts served this branch, synced with `scripts/dev-sync.sh aidd-context` (v2.3.2). Before the sync, both caches held 2.2.0 and its five old actions, so an unsynced run would have tested the released skill and passed for the wrong reason. + +Every claim below was read off disk, never off the model's report. + +## Claude, existing repo with code and no memory + +Picked `claude`. Detected `core`, `api` (`express` + `src/routes/`), `database` (`pg` + `src/db.js`). + +- 9 memory files, all flat in `aidd_docs/memory/`. No subfolder. +- `CLAUDE.md` had no `## Memory Management`. The section was appended, the block filled with all 9 files. +- The hand-written line in `CLAUDE.md` survived. +- `AGENTS.md` was never created. Only the picked tool was touched. + +The review fanned out to one `aidd-dev:checker` per file and earned its keep: it found that `pg` is declared but imported nowhere, and that `src/db.js` is required by no caller. The first draft's architecture diagram had drawn `Routes → Db → Postgres`, three edges that do not exist in the code. The reviewers, none of whom wrote the file they read, caught what the writer could not see. + +## Claude, a repo whose memory was already nested + +The fixture carried `memory/core/project-brief.md` and `memory/internal/architecture.md`, the client bug. + +Scan stopped at the confirmation gate, as designed, so nothing was written. What it said before stopping is the proof the destinations table fired: + +> `core/` is a template-selection folder, not a path. This is a misplaced generated file. Its flat home `aidd_docs/memory/project-brief.md` does not exist, so nothing is loading it today. + +It planned to write the flat file, carry the nested file's content into it, leave the orphan in place, and report it. That matches the decision: prevent and surface, never auto-remediate. + +## Codex, hand-written `AGENTS.md` carrying no block + +Picked `codex`. Same fixture shape as the Claude run. + +- 9 memory files, all flat. +- `AGENTS.md` had no block at all. The action inserted the section and the block, then the script filled it. +- The hand-written line survived. +- `CLAUDE.md` was never created. +- The script was called as `update_memory.js codex`, so the picked-tool argument reached it. + +Codex spawned nine independent reviewers of its own. + +## What stays unproven + +- **The no-subagent fallback never ran.** Both hosts have subagents, so `review-protocol.md`'s degrade path is untested. It is defensive code, not verified behavior. Do not report it as working. +- **The interactive contract is untested.** Every run pre-answered the tool pick and the capability confirmation in the prompt. The blocking ask itself was exercised only once, in the nested-drift run, where scan correctly refused to proceed. diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-1.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-1.md new file mode 100644 index 00000000..19c5dc88 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-1.md @@ -0,0 +1,69 @@ +--- +status: done +--- + + + +# Instruction: Router and scan + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +plugins/aidd-context/skills/02-project-memory/ +├── SKILL.md ✏️ router: mermaid scan->generate->sync, 3-action table, rules, ref/asset lists +├── actions/ +│ └── 01-scan.md ✅ detect tools + capabilities, user picks tools, confirms capabilities +└── references/ + ├── tools.md ✅ tool | detected-when | context-file (merges detection signals + the AI map) + └── capability-signals.md ✏️ keep the table, strip prose to one-line intents +``` + +## Tasks to do + +### `1)` Rewrite SKILL.md as a router + +> The always-on description and the smallest body that routes. + +1. Frontmatter: `name`, a `description` under ~45 tokens naming the journey not the mechanism, `argument-hint: scan | generate | sync`. +2. Body: a linear mermaid `scan --> generate --> sync`, then a 3-row action table (verb, one-line does). +3. Carry the load-bearing line: run in order, read the action's file in `actions/` before running it. +4. Keep the transversal Memory rules and Action rules, one idea per line, no semicolons. +5. Carry no reference or asset list: the actions point at them with `@`, and onboard proves the list is pure duplication. + +### `2)` Write actions/01-scan.md + +> Detect, ask, confirm. Read only, one prompt. + +1. Detect the tools present per `references/tools.md` (detected-when column). +2. Show the detected tools, let the user pick one or several, wait for the pick, never default to all. +3. Detect the capabilities per `references/capability-signals.md`, each with its repo evidence. +4. Show each capability with evidence, let the user confirm, add, or drop, block on the answer. +5. Output: the confirmed tool set and confirmed capability set, rendered nowhere. + +### `3)` Write references/tools.md + +> One table keyed by tool, serving scan and sync. + +1. Columns: tool, detected-when (its own dir or a file only it reads), context-file (where the block lives). +2. Rows: claude, codex, cursor, opencode, copilot, matching the current mapping paths. +3. A note: a shared `AGENTS.md` is a wiring target, never a detection signal. + +### `4)` Trim references/capability-signals.md + +> Keep the capability/definition/evidence/folder table, cut the surrounding prose to intents. + +1. Reduce the two prose paragraphs to the load-bearing rules only (a capability holds on a concrete fact, no inferred domain, every fire shown with evidence). +2. Leave the table and the template folders untouched. + +## Test acceptance criteria + + + +| Task | Acceptance criteria | +| ---- | --------------------------------------------------------------------------------------- | +| 1 | SKILL.md holds a mermaid, a 3-row table, the read-the-action-file line, and a sub-45-token description. | +| 2 | scan detects tools, offers a multi-pick, and confirms capabilities with evidence, rendering no memory. | +| 3 | tools.md maps every listed tool to a detected-when signal and a context-file path. | +| 4 | capability-signals.md keeps its table and carries no prose beyond the holding rules. | diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-2.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-2.md new file mode 100644 index 00000000..75c4d3a2 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-2.md @@ -0,0 +1,60 @@ +--- +status: done +--- + + + +# Instruction: Generate with forced paths + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +plugins/aidd-context/skills/02-project-memory/ +├── actions/ +│ └── 02-generate.md ✅ scaffold aidd_docs/, fill memory to forced flat paths, review +└── references/ + ├── memory-destinations.md ✅ template path -> exact flat output path + └── review-protocol.md ✅ independent checker fan-out, fresh-context degrade +``` + +## Tasks to do + +### `1)` Write actions/02-generate.md + +> One action: scaffold, fill, review. Small file, each step one line pointing at a ref. + +1. Scaffold: create `aidd_docs/` with its three docs and `memory/{internal,external}` from `@../assets/`, preserving user edits. +2. Select: take `core/` plus each confirmed capability's folder from scan. +3. Fill: for each template, write to its forced path in `references/memory-destinations.md`, capturing the macro and non-derivable facts, never repeating a fact, pointing to code over a copy. +4. Enforce: every core file lands flat in `aidd_docs/memory/`, never under `core/`, `internal/`, or any subfolder. +5. Review: run `references/review-protocol.md`, apply confirmed fixes. +6. Output: the memory bank, flat, plus the review report. + +### `2)` Write references/memory-destinations.md + +> The table that kills the nesting bug. Data, not inference. + +1. One row per template: source `templates/memory//.md`, destination `aidd_docs/memory/.md`. +2. State the invariant: the template folder is a capability gate only, never part of the output path. +3. State that `internal/` and `external/` hold user notes, never a generated core file. + +### `3)` Write references/review-protocol.md + +> Independent review that works, with a stated fallback. + +1. Fan out one `aidd-dev:checker` subagent per memory file (or per small group), each verifying cross-file consistency, duplication, and accuracy against the code. +2. Collect findings, apply the safe confirmed fixes, flag the rest for a human. +3. Degrade: where the host cannot spawn subagents, run a single fresh-context review pass over all files, and say so in the report. + +## Test acceptance criteria + + + +| Task | Acceptance criteria | +| ---- | ------------------------------------------------------------------------------------------ | +| 1 | generate scaffolds the docs, fills the selected templates, and ends with a review, in one action file. | +| 2 | memory-destinations.md maps every template to a flat `aidd_docs/memory/.md` path with no subfolder. | +| 3 | review-protocol.md fans out to independent checkers and names the fresh-context fallback. | +| 4 | A generate run writes every core file flat, none under `core/` or `internal/`. | diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-3.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-3.md new file mode 100644 index 00000000..1a9bd2c8 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-3.md @@ -0,0 +1,64 @@ +--- +status: done +--- + + + +# Instruction: Sync that adapts + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +plugins/aidd-context/ +├── hooks/ +│ └── update_memory.js ✏️ accept an optional picked-tool list, fill only those; no-arg keeps fill-all-present +└── skills/02-project-memory/ + ├── actions/ + │ └── 03-sync.md ✅ create the context file when missing, upsert the block, run the fill script + └── references/ + └── memory-block.md ✏️ keep the upsert cases, add the create-when-missing case for a picked tool +``` + +## Tasks to do + +### `1)` Write actions/03-sync.md + +> The wiring. Owns the context file end to end. + +1. For each tool picked in scan, resolve its context-file path per `references/tools.md`. +2. Create the file when missing: copy `@../assets/AGENTS.md`, set the tool's title, per `references/memory-block.md`. +3. Upsert the empty `` block into every picked tool's file. +4. Run the fill script `hooks/update_memory.js`, passing the picked tools, to fill each block with the memory-file references. +5. Guard: on a non-zero exit, print the error and stop, telling the user to check that `aidd_docs/memory/` holds a `.md` file and that `node` is available. +6. Output: each picked tool's context file, present, wired, and filled. + +### `2)` Make update_memory.js respect the picked tools + +> Fill only what the user chose, without breaking the auto hook. + +1. Accept an optional tool list (CLI args), map each to its context file, fill only those. +2. No argument: keep today's behavior, fill every target file already present. +3. Keep the hook wiring unchanged, the hook calls it with no argument. +4. Never insert a block: a file without `` is skipped, both no-arg and with-args. Block insertion stays the sync action's job. + +### `3)` Update references/memory-block.md + +> Add the create case, keep the rest. + +1. Keep the existing upsert cases (absent, no section, section-no-block, block-present). +2. State that a tool picked in scan whose context file does not exist gets the file created from the template, not skipped. +3. Note that the fill script only fills an existing block: it creates neither the file nor the block, so both are the action's job before the script runs. +4. State the boundary: a blockless existing file (e.g. a hand-written `AGENTS.md`) is only given a block when its tool is picked; the auto hook never inserts one. + +## Test acceptance criteria + + + +| Task | Acceptance criteria | +| ---- | ------------------------------------------------------------------------------------------ | +| 1 | sync creates a missing context file for a picked tool, upserts the block, and runs the fill script. | +| 2 | Passing only claude fills `CLAUDE.md` and leaves a pre-existing `AGENTS.md` block untouched; no-arg fills all present. | +| 3 | memory-block.md documents the create-when-missing case and the script's update-only limit. | +| 4 | A non-zero script exit stops with a message, never a silent partial sync. | diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-4.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-4.md new file mode 100644 index 00000000..1ba3fddc --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/phase-4.md @@ -0,0 +1,65 @@ +--- +status: done +--- + + + +# Instruction: Cutover and headless verify + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +plugins/aidd-context/skills/02-project-memory/ +├── SKILL.md ✏️ ref and asset lists point at the new files only +├── actions/ +│ ├── 01-init-context-file.md ❌ absorbed into 03-sync +│ ├── 02-scaffold-docs.md ❌ absorbed into 02-generate +│ ├── 03-generate-memory.md ❌ replaced by 02-generate +│ ├── 04-review-memory.md ❌ absorbed into 02-generate +│ └── 05-sync-memory.md ❌ replaced by 03-sync +└── references/ + └── mapping-ai-context-file.md ❌ merged into tools.md +``` + +## Tasks to do + +### `1)` Remove the superseded files + +> Delete only what the new three actions fully absorb. + +1. Delete the five old action files. +2. Delete `references/mapping-ai-context-file.md`, its content now in `tools.md`. +3. Grep the skill for any dangling `@` reference to a deleted file, fix or remove it. + +### `2)` Verify the skill is internally whole + +> No broken link, no orphaned rule. + +1. Run the repo link checker, expect zero broken links. +2. Confirm every action file is reachable from SKILL.md and reads only refs that exist. +3. Confirm no runtime instruction lives only in an authoring contract (the onboard lesson). + +### `3)` Headless sweep on both hosts + +> Prove it runs, not just that it reads. + +1. Build fixtures: an existing repo with a stack and no memory, a repo whose tool wrote memory into `internal/`, and one for Codex whose `AGENTS.md` carries no block. +2. Sync this checkout into both tools' caches with `scripts/dev-sync.sh`, so the run tests the branch and not the released version. +3. Run `02-project-memory` headless on Claude across the fixtures, capture each output. +4. Run the same on Codex, capture its output. +5. Assert on disk, never on the report: core files flat, the picked tool's block filled, an unpicked tool's file untouched. +6. Record which review path ran. Both hosts have subagents today, so the no-subagent fallback stays unexercised and must not be reported as verified. + +## Test acceptance criteria + + + +| Task | Acceptance criteria | +| ---- | ------------------------------------------------------------------------------------------ | +| 1 | The five old actions and `mapping-ai-context-file.md` are gone, no reference dangles. | +| 2 | The link checker reports zero broken links across the skill. | +| 3 | Claude and Codex both run the three-action flow end to end, each output naming scan, generate, and sync. | +| 4 | Disk shows core memory flat, the picked tool's block filled, and an unpicked tool's file untouched. | +| 5 | The review ran with reviewers that did not write what they read, and the report names them. | diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/plan.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/plan.md new file mode 100644 index 00000000..32909453 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/plan.md @@ -0,0 +1,42 @@ +--- +objective: "02-project-memory is a three-action skill (scan, generate, sync) on the onboard anatomy, writing every core memory file flat and wiring the block into each chosen tool's context file, created when missing." +status: implemented +--- + + + +# Plan: Rebuild 02-project-memory on the onboard anatomy + +## Overview + +| Field | Value | +| ---------- | -------------------------------------------------------------------------------------- | +| **Goal** | Collapse the five-action memory skill to three, token-lean, with forced flat paths and an independent review. | +| **Source** | Brainstorm this session, grounded in the onboard rebuild and the current skill's files. | + +## Phases + +| # | Phase | File | +| --- | --------------------------- | ---------------------------- | +| 1 | Router and scan | [`phase-1.md`](./phase-1.md) | +| 2 | Generate with forced paths | [`phase-2.md`](./phase-2.md) | +| 3 | Sync that adapts | [`phase-3.md`](./phase-3.md) | +| 4 | Cutover and headless verify | [`phase-4.md`](./phase-4.md) | + +## Decisions + + + +| Decision | Why | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | +| Three actions `scan → generate → sync`, linear, each idempotent | Five actions were four trivial ones and a pipeline; onboard proved small SKILL.md plus small actions. | +| `sync` owns the tool context file: creates it when missing, then fills | The user's "project-memory adapts" — no separate init skill; the config file's absence is not a veto once the tool is picked. | +| A forced template-to-path table, flat destinations only | Codex and Copilot nested core files into `core/` or `internal/`, demoting them out of the always-loaded tier. Make the path data, not inference. | +| Review is a fan-out to independent `aidd-dev:checker` subagents | The user requires an independent review that works, not a self-check. | +| Review degrades to a fresh-context pass where the host has no subagents | Same portability lesson as onboard's orphaned rule: a runtime capability the host lacks must have a stated fallback. | +| Merge tool detection and the context-file map into one `tools.md` | Both are keyed by tool; one table inside the skill is DRY. Duplication with onboard stays, tables independent. | +| Memory templates under `assets/templates/` are untouched | They are user-facing content; telegraphing them degrades what the reader reads. | +| `update_memory.js` takes an optional picked-tool list, no-arg unchanged | sync must fill only the tools the user picked; the same script also runs as an auto hook with no such context, so the tool list is optional and absence keeps today's fill-all-present behavior. | +| `skill-authoring.md` stays untouched on this branch | Same standing constraint as the onboard rework; the authoring contract is a separate ticket. | +| Nesting is prevented and surfaced, never auto-remediated | A file already nested by an older run is the user's file now. Generate writes the flat one, reports the orphan, and deletes nothing. Silently moving a file the user may have edited is worse than the drift. | +| The Codex review self-pass is accepted, not treated as a defect | `codex exec` headless spawns no real subagents, so the review degrades to one honest self-pass and says so. Claude fans out real independent checkers. The skill behaves as designed on both; the asymmetry is a platform limit, accepted by the user. | diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/session-report.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/session-report.md new file mode 100644 index 00000000..f4b2b18c --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/session-report.md @@ -0,0 +1,71 @@ +# Project-memory rebuild — session report + +Branch `feat/project-memory-rebuild`, off `origin/next`. Nothing pushed. Eight commits landed; a second pass (file-by-file review, mermaid, smoke test) is uncommitted. + +## What changed, in one line + +The five-action memory skill became three (`scan → generate → sync`) on the onboard anatomy: each action asks its own question when the answer is used, every memory file lands flat where a table says, and an independent review runs before anything is trusted. + +## The shape + +``` +scan ──▶ generate ──▶ sync (set up or refresh) + ▲ + re-wire ───┘ (a tool needs wiring, memory already there) +``` + +- **scan** reads the project, confirms the capabilities. Stops if there is nothing to remember. +- **generate** scaffolds `aidd_docs/`, writes each memory file to its forced flat path, reviews with independent agents, reports. +- **sync** picks the tools, creates or wires each tool's context file, fills the block with the script. + +Files: `SKILL.md` + 3 actions + 6 references + 5 assets + 22 memory templates. `references/memory-block.md` deleted (its shape lives in the asset, its fill in the script). + +## The eight committed changes + +1. Router: three actions, mermaid, load-bearing "read the action file" line. +2. generate writes to a forced template→path table — the client nesting bug fixed at the root. +3. sync wires only the picked tools; the script takes a tool list, still stages nothing when the skill calls it. +4. The five old actions and the AI map retired; catalogs fixed. +5. Each action asks its own question: tool pick moved scan→sync, so sync runs alone; scan gained the empty-project guard. +6. A memory file on an older template shape is reported, never rewritten. +7. Memory-content rules moved to `references/memory-rules.md`, loaded by generate, never by sync. +8. No neighbour plugin named; tests state observables, not restated rules. + +## The uncommitted second pass + +A file-by-file review with the user, then mermaid, then the smoke test. + +- **SKILL.md** — description recentred on the project (architecture, conventions, decisions), active verb, no dash. Mermaid shows both entries (set up / re-wire). Number column dropped (the flow branches). Transversal rules gained "create or revise, keeping the user's edits; delete only when asked". +- **01-scan** — Ground/Find/Ask/Confirm, a stop sub-bullet for the empty project, observable tests. +- **02-generate** — Output one line; Write and Prune split coherently (Write owns selected files, Prune owns orphans); Review and Fix separated; report shaped by `assets/report.md`; tests grouped always / by-case. +- **03-sync** — Require guard, tool pick, upsert folded to reference the asset shape, reconcile-on-drift offer, guard trimmed, observable tests. +- **references** — `tools.md` two rules only; `capability-signals.md` one framing line + table, files column dropped (lived in destinations), `monorepo` removed (codebase-map's job); `memory-destinations.md` a pure mapping; `memory-rules.md` "A memory file:" properties; `review-protocol.md` a numbered protocol addressed to the reviewer, expanded to catch dead commands, invented rationale, and omissions; `structure.md` new, the scaffold tree. +- **assets** — `report.md` new (the generate report shape). `templates/memory/README.md` load model as a mermaid, maintenance rules aligned with `memory-rules.md`, orphan 200-line dropped. +- **mermaid** — `database` ER (a restated schema) replaced by an optional domain diagram; `auth` and `deployment` gained an optional, gated flow diagram; every diagram gated "only when non-trivial, never a derivable schema or tree". +- **script** — `updateMarkers` anchors on the close then the nearest open, so a marker quoted in prose above the block no longer splices out the text between. + +## Defects found and fixed this session + +- Ten adversarial audit agents: the review protocol's generic "breach of memory-rules" subsumed its own specific flags; the dedup check needed file contents but the reviewer only reads names. Both reframed. +- File-by-file review: cross-plugin coupling in the review protocol, an AImemory-rules dup with the README, a database ER that restated the schema, tests that restated rules. +- Smoke test: `update_memory.js` had no test and the runner is not wired to CI (a repo-level gap, ticketed, not this rework). + +## Verified in execution — 31/31 on disk, both hosts + +See `smoke-test.md`. Ten fixtures, every claim read off disk. Ground-stop, full flow, bare-AGENTS insert, standalone sync, Require-stop, drift-report, Prune flag+offer+decline, shared-AGENTS, reconcile-offer, gated mermaids. + +## The one asymmetry — review by host + +- **Claude** fans out real independent `aidd-dev:checker` reviewers (9 on F2, 4 on F10) that caught stub-overstatement and duplication and fixed them. The prerogative is met. +- **Codex** self-passes: "ran without subagents, one fresh pass; no fixes needed." `codex exec` headless does not spawn real subagents; an earlier run that named reviewers was persona role-play, not fan-out. The skill degrades as designed and reports it, but Codex gets a self-review, not an independent one. + +Content and structure are sound on both. Independent review is real only on Claude. Accepting the Codex self-pass, or requiring independent review on every host, is a product call. + +## Not proven + +- Accepting a Prune removal or a reconcile: headless offers but cannot answer; only the decline path is proven. + +## Deferred, needs a ticket + +- Wire `node --test` into CI, then unit-test `update_memory.js` (`updateMarkers`, `resolveTargets`). +- `skill-authoring.md` sanctions (nested refs, inline `@`, mermaid for loops, router format) — untouched on this branch by standing constraint. diff --git a/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/smoke-test.md b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/smoke-test.md new file mode 100644 index 00000000..36c72e07 --- /dev/null +++ b/aidd_docs/tasks/2026_07/2026_07_13_project-memory-rebuild/smoke-test.md @@ -0,0 +1,34 @@ +# Smoke test — the reworked skill + +Ten fixtures, both hosts synced to this branch first (`dev-sync.sh`). Every claim read off disk, never off a report. `smoke-setup.sh` and `smoke-assert.sh` in the job tmp. + +| # | Fixture | Host | Proves | Result | +| - | ------- | ---- | ------ | ------ | +| F1 | greenfield | Claude | scan Ground stops, writes nothing | pass | +| F2 | existing + code | Claude | full flow, flat memory, no placeholder, block filled, hand line kept, unpicked tool untouched, nothing staged | pass | +| F3 | existing, bare AGENTS | Codex | full flow, section+block inserted, hand line kept | pass | +| F4 | memory + claude, add codex | Claude | sync alone wires codex, claude stays wired, memory byte-identical | pass | +| F5 | no memory | Claude | sync Require stops before writing | pass | +| F6 | architecture missing a section | Claude | drift reported, never injected | pass | +| F7 | dropped capability | Claude | generate ran, Prune flagged and offered removal, declined, kept | pass | +| F8 | shared AGENTS (codex+cursor) | Codex | pick codex wires the shared file once | pass | +| F9 | context file on old template | Claude | reconcile offered vs the asset, nothing applied without an answer | pass | +| F10 | auth + deployment | Claude | gated mermaids filled, no TODO left in any diagram | pass | + +Disk assertions: 31 pass, 0 fail. + +## Two re-runs + +- **F7** first stalled at the confirmation gate (the prompt said "confirm" without "proceed"). Re-run with "and proceed": generate ran, created the four missing core files, Prune flagged `api`/`database`, offered removal, kept both on the decline. The flag-offer-consent path is proven. +- **F9** first did not offer: the block already matched so sync short-circuited, and "seeded from an older template" was too vague to detect. Fixed the sync instruction to "if its AIDD structure differs from `@../assets/AGENTS.md`, offer to reconcile". Re-run: it detected the missing `## Behavior/Communication/Action` sections and the stray `OLD-INSTRUCTION` line, and offered options. Nothing applied without an answer. + +## Review, by host — the one asymmetry + +- **Claude fans out for real.** F2: nine independent `aidd-dev:checker` reviewers, one per file; they flagged stub-overstatement and cross-file duplication, and the fixes were applied. F10: four parallel checkers. The prerogative is met. +- **Codex self-passes.** F3 (twice): "ran without subagents, one fresh pass per memory file; no fixes needed." `codex exec` headless does not spawn real subagents. An earlier Codex run that named reviewers (Peirce, Singer, Darwin, ...) was one pass role-playing personas, not real fan-out. The skill degrades as designed and says so, but Codex gets a self-review, not an independent one. + +Content and structure are sound on both hosts. The independent review is real only on Claude. Whether the Codex self-pass is acceptable, or independent review is a hard requirement on every host, is a product decision. + +## Still not proven + +- **Accepting a Prune removal or a reconcile.** Headless can offer but cannot answer, so only the decline path is proven. Accepting is manual. diff --git a/docs/CATALOG.md b/docs/CATALOG.md index 1a046c9d..ac2e9286 100644 --- a/docs/CATALOG.md +++ b/docs/CATALOG.md @@ -18,9 +18,9 @@ Bootstrap, project init, context-artifact generation, diagrams, learning, and ex | Skill | Role | Actions | | ---------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| `00-onboard` | Scan the project into a diagnostic of what's set up and missing, then run the recommended next commands | `01-scan`, `02-report`, `03-run` | +| `00-onboard` | Guide the project's journey through AIDD, from first setup to shipping a feature | `01-scan`, `02-assess`, `03-present`, `04-run` | | `01-bootstrap` | Imagine and validate a new SaaS architecture, output an `INSTALL.md` | `01-gather-needs`, `02-propose-candidates`, `03-audit-candidates`, `04-pick-and-design`, `05-write-install-md` | -| `02-project-memory` | Initialize or refresh the memory bank and AI context files | `01-init-context-file`, `02-scaffold-docs`, `03-generate-memory`, `04-review-memory`, `05-sync-memory` | +| `02-project-memory` | Give the AI a memory of the project, wired into the tools you use | `01-scan`, `02-generate`, `03-sync` | | `03-context-generate` | Router that dispatches an artifact-generation request to the dedicated generator below | delegates to `04`–`08` (and plugins / marketplaces) | | `04-skill-generate` | Generate a router-based skill across the host AI tool(s) | `01-capture-intent`, `02-decompose-actions`, `03-draft-skill`, `04-write-actions`, `05-validate` | | `05-rule-generate` | Generate a coding rule that governs editor and agent behavior | `01-capture-rule`, `02-write-rule`, `03-validate` | diff --git a/plugins/aidd-context/CATALOG.md b/plugins/aidd-context/CATALOG.md index 5ed76aa5..9e207eab 100644 --- a/plugins/aidd-context/CATALOG.md +++ b/plugins/aidd-context/CATALOG.md @@ -71,19 +71,21 @@ Auto-generated index of skills, agents, references and assets shipped by the `ai | Group | File | Description | |-------|------|---| -| `actions` | [01-init-context-file.md](skills/02-project-memory/actions/01-init-context-file.md) | - | -| `actions` | [02-scaffold-docs.md](skills/02-project-memory/actions/02-scaffold-docs.md) | - | -| `actions` | [03-generate-memory.md](skills/02-project-memory/actions/03-generate-memory.md) | - | -| `actions` | [04-review-memory.md](skills/02-project-memory/actions/04-review-memory.md) | - | -| `actions` | [05-sync-memory.md](skills/02-project-memory/actions/05-sync-memory.md) | - | +| `actions` | [01-scan.md](skills/02-project-memory/actions/01-scan.md) | - | +| `actions` | [02-generate.md](skills/02-project-memory/actions/02-generate.md) | - | +| `actions` | [03-sync.md](skills/02-project-memory/actions/03-sync.md) | - | | `assets` | [AGENTS.md](skills/02-project-memory/assets/AGENTS.md) | - | | `assets` | [CONTRIBUTING.md](skills/02-project-memory/assets/CONTRIBUTING.md) | - | | `assets` | [GUIDELINES.md](skills/02-project-memory/assets/GUIDELINES.md) | - | | `assets` | [README.md](skills/02-project-memory/assets/README.md) | - | +| `assets` | [report.md](skills/02-project-memory/assets/report.md) | - | | `references` | [capability-signals.md](skills/02-project-memory/references/capability-signals.md) | - | -| `references` | [mapping-ai-context-file.md](skills/02-project-memory/references/mapping-ai-context-file.md) | - | -| `references` | [memory-block.md](skills/02-project-memory/references/memory-block.md) | - | -| `-` | [SKILL.md](skills/02-project-memory/SKILL.md) | `Initialize or refresh the project memory bank. Use when the user wants to set up or regenerate the project's memory files. Not for updating one memory file after it exists or editing a single rule directly.` | +| `references` | [memory-destinations.md](skills/02-project-memory/references/memory-destinations.md) | - | +| `references` | [memory-rules.md](skills/02-project-memory/references/memory-rules.md) | - | +| `references` | [review-protocol.md](skills/02-project-memory/references/review-protocol.md) | - | +| `references` | [structure.md](skills/02-project-memory/references/structure.md) | - | +| `references` | [tools.md](skills/02-project-memory/references/tools.md) | - | +| `-` | [SKILL.md](skills/02-project-memory/SKILL.md) | `Build the project's memory of its architecture, conventions, and decisions, and wire it into the tools you use. Use to set up or refresh project memory. Not for editing one existing memory file.` | #### `skills/03-context-generate` diff --git a/plugins/aidd-context/hooks/update_memory.js b/plugins/aidd-context/hooks/update_memory.js index 4f46ffe0..f6db0c9e 100644 --- a/plugins/aidd-context/hooks/update_memory.js +++ b/plugins/aidd-context/hooks/update_memory.js @@ -10,6 +10,17 @@ * Reference syntax for the always-loaded tier: * CLAUDE.md / AGENTS.md -> @aidd_docs/memory/file.md * .github/copilot-instructions -> [aidd_docs/memory/file.md](../aidd_docs/memory/file.md) + * + * Usage: + * node update_memory.js every context file already present + * node update_memory.js claude codex only those tools' context files + * + * The auto hook calls it with no argument. The project-memory skill passes the + * tools the user picked, so a context file the user did not choose is left + * alone even when it exists. + * + * It only ever fills a block that is already there. Creating the file, or the + * block inside it, is the skill's job. */ // ── Constants ───────────────────────────────────────────────────── @@ -34,6 +45,15 @@ const TARGET_FILES = [ { path: ".github/copilot-instructions.md", syntax: "link" }, ]; +// Which context file each tool reads. Mirrors the skill's references/tools.md. +const TOOL_FILES = { + claude: "CLAUDE.md", + codex: "AGENTS.md", + cursor: "AGENTS.md", + opencode: "AGENTS.md", + copilot: ".github/copilot-instructions.md", +}; + // ── Helpers ─────────────────────────────────────────────────────── function memoryPath(path, ...parts) { @@ -102,10 +122,14 @@ function buildBlockContent(rootFiles, onDemandFiles, syntax) { } // Replace the text between an open and close marker, leaving the rest intact. +// Anchor on the close, then take the nearest open before it: a bare marker +// quoted in hand-written prose above the real block must not become the cut +// point and splice out everything between it and the block. function updateMarkers(content, open, close, innerContent) { - const openIdx = content.indexOf(open); const closeIdx = content.indexOf(close); - if (openIdx === -1 || closeIdx === -1 || closeIdx < openIdx) return null; + if (closeIdx === -1) return null; + const openIdx = content.lastIndexOf(open, closeIdx); + if (openIdx === -1) return null; return content.slice(0, openIdx + open.length) + innerContent + content.slice(closeIdx); } @@ -132,6 +156,23 @@ function buildToc(rootFiles, onDemandFiles, path) { return `\n${lines.join("\n")}\n`; } +// The context files to fill. No tool named: every target already present, which +// is what the auto hook wants. Tools named: only theirs, so an AGENTS.md the +// user never picked keeps its block untouched. +function resolveTargets(tools) { + if (tools.length === 0) return TARGET_FILES; + + const unknown = tools.filter((t) => !(t in TOOL_FILES)); + if (unknown.length > 0) { + const known = Object.keys(TOOL_FILES).join(", "); + console.error(`update_memory: unknown tool ${unknown.join(", ")} (known: ${known})`); + process.exit(1); + } + + const wanted = new Set(tools.map((t) => TOOL_FILES[t])); + return TARGET_FILES.filter((target) => wanted.has(target.path)); +} + function gitAdd(childProcess, files) { try { childProcess.execSync(`git add ${files.map((f) => `"${f}"`).join(" ")}`, { @@ -151,11 +192,14 @@ function gitAdd(childProcess, files) { if (!fs.existsSync(DOCS_DIR)) process.exit(0); + const tools = process.argv.slice(2).map((arg) => arg.toLowerCase()); + const targets = resolveTargets(tools); + const rootFiles = scanRootFiles(fs, path); const onDemandFiles = ON_DEMAND_DIRS.flatMap((sub) => scanSubdir(fs, path, sub)); const changed = []; - for (const target of TARGET_FILES) { + for (const target of targets) { const original = readTextOrNull(fs, target.path); if (original === null) continue; @@ -180,5 +224,9 @@ function gitAdd(childProcess, files) { } } - if (changed.length > 0) gitAdd(childProcess, changed); + // Stage only when running as the auto hook, which owns no other change. Called + // by the skill, generate has just written files this script knows nothing about, + // so staging its own two would leave a partial index that reads like the whole + // change. The skill reports instead, and the user stages what they mean to commit. + if (changed.length > 0 && tools.length === 0) gitAdd(childProcess, changed); })(); diff --git a/plugins/aidd-context/skills/02-project-memory/SKILL.md b/plugins/aidd-context/skills/02-project-memory/SKILL.md index d2128db8..bb317952 100644 --- a/plugins/aidd-context/skills/02-project-memory/SKILL.md +++ b/plugins/aidd-context/skills/02-project-memory/SKILL.md @@ -1,50 +1,30 @@ --- name: 02-project-memory -description: Initialize or refresh the project memory bank. Use when the user wants to set up or regenerate the project's memory files. Not for updating one memory file after it exists or editing a single rule directly. -argument-hint: init-context-file | scaffold-docs | generate-memory | review-memory | sync-memory +description: Build the project's memory of its architecture, conventions, and decisions, and wire it into the tools you use. Use to set up or refresh project memory. Not for editing one existing memory file. +argument-hint: setup | refresh | rewire --- # Project Memory -Bootstraps the project's context layer: the AI context files with a memory block, the `aidd_docs/` structure, and the memory bank. +```mermaid +flowchart LR + build([setup or refresh]) --> scan --> generate --> sync + rewire([rewire only]) --> sync +``` ## Actions -| # | Action | Role | Input | -| --- | ------------------- | --------------------------------------------------- | ----------------- | -| 01 | `init-context-file` | Resolve the tools, then upsert the memory block | project root | -| 02 | `scaffold-docs` | Create the `aidd_docs/` folder structure | project root | -| 03 | `generate-memory` | Detect the capabilities, generate the memory files | the memory dir | -| 04 | `review-memory` | Review the memory files for consistency | the memory dir | -| 05 | `sync-memory` | Fill the memory block in every context file | the context files | +Run the flow above. No argument, `setup`, or `refresh` starts at scan. `rewire` runs sync alone. Read an action's file in `actions/` before running it. -Run the actions in order, `01 → 05`, and run each action's `## Test` before the next. Before running an action, read its file in `actions/`, not only the table or assets. +| Action | Does | +| -------- | -------------------------- | +| scan | read the project | +| generate | write the memory | +| sync | pick the tools, wire it in | -## Memory rules +## Transversal rules -Govern the content of every memory file. - -- Capture the macro and the non-derivable: decisions, conventions, gotchas, the why. Never restate a schema or a file tree. Point to the code over a copy. -- One fact, one file: define it in its home, elsewhere reference it. Naming a shared lib in its own concern is fine. -- Keep each file small. Short bullets, code in backticks, no version in a tech name (`React`, not `React 19`). -- Reflect the current state only. Drop an unused section, never leave a placeholder. - -## Action rules - -Govern how every action runs. - -- Read an asset or reference relative to this skill. If one can't be read, stop and say so, never invent. +- If a referenced file cannot be read, stop and say so. Never invent its content. - Ask before anything ambiguous. Never default silently. +- Create or revise a file, keeping the user's edits. Delete one only when the user asks. - End with a short report of what changed. - -## References - -- `references/mapping-ai-context-file.md`: the per-tool context-file path. -- `references/memory-block.md`: the context-file memory block and its upsert cases. -- `references/capability-signals.md`: the capabilities, their signals, and the concerns each gates. - -## Assets - -- `assets/AGENTS.md`: the context-file template. -- `assets/README.md`, `assets/GUIDELINES.md`, `assets/CONTRIBUTING.md`: the `aidd_docs/` doc templates. -- `assets/templates/memory/`: the memory templates, one folder per capability (`core` always, the rest gated by signal). diff --git a/plugins/aidd-context/skills/02-project-memory/actions/01-init-context-file.md b/plugins/aidd-context/skills/02-project-memory/actions/01-init-context-file.md deleted file mode 100644 index f8836a6d..00000000 --- a/plugins/aidd-context/skills/02-project-memory/actions/01-init-context-file.md +++ /dev/null @@ -1,21 +0,0 @@ -# 01 - Init context file - -Ensure each target tool's AI context file carries the project memory block. - -## Input - -The project root. - -## Output - -One context file per confirmed tool, each carrying an empty `` block. - -## Process - -1. **Detect.** Find the context files already present, by the per-tool paths in `@../references/mapping-ai-context-file.md`. Only those paths qualify; any other file is user content, off-limits. -2. **Resolve tools.** On a re-run, the tools present are the confirmed set, skip the prompt. Otherwise propose the detected tools plus the full list and ask which the user uses; wait for an explicit pick, never default to all. -3. **Upsert.** For each confirmed tool, write the memory block into its context file per `@../references/memory-block.md`. - -## Test - -- Every confirmed tool's context file exists and contains a `` block. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/01-scan.md b/plugins/aidd-context/skills/02-project-memory/actions/01-scan.md new file mode 100644 index 00000000..57658613 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/actions/01-scan.md @@ -0,0 +1,25 @@ +# 01 - Scan + +Read the project. + +## Input + +The project root. + +## Output + +The confirmed capabilities, printed nowhere. + +## Process + +1. **Ground.** Look for something to remember: source code, or anything written about what the project is. + - Nothing there: stop, say so, send the user to create something first. +2. **Find.** Detect the project's capabilities per `@../references/capability-signals.md`, each with its repo evidence. +3. **Ask.** Show each capability with its evidence. Ask the user to add or drop one. Wait for the answer. +4. **Confirm.** Keep the confirmed set in context for generate. + +## Test + +- The run changes no file: `git status --porcelain` reads the same after as before. +- A capability reaches the confirmed set only when a file or dependency for it exists in the repo. +- On a repo with no code and nothing describing it, the run stops at Ground and hands nothing to generate. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/02-generate.md b/plugins/aidd-context/skills/02-project-memory/actions/02-generate.md new file mode 100644 index 00000000..63fac9dd --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/actions/02-generate.md @@ -0,0 +1,33 @@ +# 02 - Generate + +Write the memory the project deserves. + +## Input + +The confirmed capabilities from `01-scan`. + +## Output + +The written memory bank, and a report of what changed. + +## Process + +1. **Scaffold.** Create the tree in `@../references/structure.md`. +2. **Select.** Take the rows to write from `@../references/memory-destinations.md`. +3. **Write.** Write each selected row to its destination, against `@../references/memory-rules.md`. + - The destination is the one the table names. Never derive a path. + - Absent file: fill the template, strip its guidance comment. + - Existing file: revise it in place. + - Report a template section the file now lacks when the project has something for it. Never inject it. +4. **Prune.** A file on disk whose capability is no longer selected: flag it, offer to remove it, delete only on the user's word. +5. **Review.** Have each memory file reviewed against `@../references/review-protocol.md` by an independent agent, a checker agent if the project has one, in parallel. Without subagents, make one fresh pass per file yourself, and say so in the report. +6. **Fix.** Apply the safe findings. On a duplicated fact, keep its home and drop the copy. +7. **Report.** Fill `@../assets/report.md`. + +## Test + +- `find aidd_docs/memory -mindepth 2 -name '*.md'` returns nothing outside `internal/` and `external/`. +- Every `core` destination and every `@../references/structure.md` path exists at its exact place. +- `internal/` and `external/` exist, each with a `.gitkeep` and no memory file. +- No `TODO` or `` remains in a written file. +- A line the user added survives a re-run, and a flagged missing section is never injected. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/02-scaffold-docs.md b/plugins/aidd-context/skills/02-project-memory/actions/02-scaffold-docs.md deleted file mode 100644 index c573beb6..00000000 --- a/plugins/aidd-context/skills/02-project-memory/actions/02-scaffold-docs.md +++ /dev/null @@ -1,22 +0,0 @@ -# 02 - Scaffold docs - -Create the `aidd_docs/` structure: root docs, empty memory subdirectories, and the project recipe directory. - -## Input - -The project root. - -## Output - -`aidd_docs/` with `README.md`, `GUIDELINES.md`, `CONTRIBUTING.md`, `memory/README.md`, `memory/{internal,external}/.gitkeep`, and `recipes/.gitkeep`. - -## Process - -1. **Docs.** Write each of `README.md`, `GUIDELINES.md`, `CONTRIBUTING.md` from its `@../assets/` template if absent, else update in place preserving the user's edits. -2. **Memory dirs.** Ensure `aidd_docs/memory/internal/` and `aidd_docs/memory/external/` exist, each with a `.gitkeep`. -3. **Recipe dir.** Ensure `aidd_docs/recipes/` exists with a `.gitkeep`; recipe files created by cook live there. -4. **Memory readme.** Write `aidd_docs/memory/README.md` from `@../assets/templates/memory/README.md` if absent; leave an existing one. - -## Test - -- `aidd_docs/` holds the three docs, `memory/README.md`, both memory subdirectories with their `.gitkeep`, and `recipes/.gitkeep`. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/03-generate-memory.md b/plugins/aidd-context/skills/02-project-memory/actions/03-generate-memory.md deleted file mode 100644 index 0e719f72..00000000 --- a/plugins/aidd-context/skills/02-project-memory/actions/03-generate-memory.md +++ /dev/null @@ -1,23 +0,0 @@ -# 03 - Generate memory - -Detect the project's capabilities, then fill the matching memory templates from the codebase. - -## Input - -The `aidd_docs/memory/` directory and the project root. - -## Output - -The `core/` memory files plus each detected capability's folder, filled and written flat to `aidd_docs/memory/`. - -## Process - -1. **Detect.** Find the project's capabilities (`@../references/capability-signals.md`): a capability holds when a concrete repo fact matches its definition, never an inferred domain. In a monorepo, scan every workspace. -2. **Confirm.** Show each capability with its evidence and the templates it selects. Ask the user to confirm, add, or drop one. Block on the answer. -3. **Select.** Take `core/` plus each confirmed capability's folder. On an existing `aidd_docs/memory/`: update a concern from current reality (keep the user's edits), create a missing one, leave-but-flag one whose capability is gone (never delete). -4. **Fill.** For each template, knowing what earlier ones captured (never repeat a fact, point to its file): capture the macro, non-derivable facts (exclude AIDD's scaffold, point to code over a copy), fill its sections, drop an empty one, strip the guidance comment, never copy verbatim. -5. **Write.** One file per template, named by its basename, flat in `aidd_docs/memory/`. Never nest, rename, or consolidate. - -## Test - -- `aidd_docs/memory/` holds the core files plus one file per confirmed capability's concern, each named after a template. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/03-sync.md b/plugins/aidd-context/skills/02-project-memory/actions/03-sync.md new file mode 100644 index 00000000..14640934 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/actions/03-sync.md @@ -0,0 +1,33 @@ +# 03 - Sync + +Wire the memory into the tools the user picks. + +## Input + +The memory bank in `aidd_docs/memory/`. + +## Output + +Each picked tool's context file, carrying the filled block. + +## Process + +1. **Require.** Stop unless `aidd_docs/memory/` holds a `.md` file. Send the user to generate first. +2. **Detect.** Find the AI tools present per `@../references/tools.md`. +3. **Pick.** Show every tool, the detected ones ticked. Let the user pick one or several. Wait for the pick. +4. **Upsert.** Ensure each picked tool's context file carries the block, shaped like `@../assets/AGENTS.md`. + - Absent file: create it from that template. + - Existing file: add only the missing `## Memory Management` section or block, leaving the rest untouched. + - If its AIDD structure differs from `@../assets/AGENTS.md`, offer to reconcile it, applying only what the user approves. + - Touch no file a picked tool does not resolve to. +5. **Fill.** Run `hooks/update_memory.js` from the project root, naming the picked tools. +6. **Guard.** On a non-zero script exit, show the error and stop. +7. **Verify.** Read each picked tool's block back. An empty one means the fill did not land. + +## Test + +- With no `.md` under `aidd_docs/memory/`, sync creates no context file and stops. +- The script exits `0`. +- Each picked tool's context file exists, its block listing every file in `aidd_docs/memory/`. +- A context file for a tool the user did not pick is unchanged. +- `git diff --cached` is empty: sync stages nothing. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/04-review-memory.md b/plugins/aidd-context/skills/02-project-memory/actions/04-review-memory.md deleted file mode 100644 index ec72b87b..00000000 --- a/plugins/aidd-context/skills/02-project-memory/actions/04-review-memory.md +++ /dev/null @@ -1,22 +0,0 @@ -# 04 - Review memory - -Review every memory file together for cross-file consistency and duplication, fixing what is safe. - -## Input - -The `aidd_docs/memory/` directory with the generated files. - -## Output - -The memory files, corrected in place where safe, and a status report. - -## Process - -1. **Read.** Load every `.md` under `aidd_docs/memory/`, recursively. -2. **Review.** In one pass, check cross-file consistency and accuracy. Fix a safe issue in place, flag one that needs a human. -3. **Deduplicate.** Keep each fact in one file, drop the copies (judge by meaning, not wording). May be handed to an independent checker subagent. - -## Test - -- Every memory file is covered by the report, each flagged file with a reason a human can act on. -- No fact's definition is duplicated across files. diff --git a/plugins/aidd-context/skills/02-project-memory/actions/05-sync-memory.md b/plugins/aidd-context/skills/02-project-memory/actions/05-sync-memory.md deleted file mode 100644 index b7c613c0..00000000 --- a/plugins/aidd-context/skills/02-project-memory/actions/05-sync-memory.md +++ /dev/null @@ -1,20 +0,0 @@ -# 05 - Sync memory - -Fill the `` block in every context file with references to the generated memory files. - -## Input - -The context files with the block, and the populated `aidd_docs/memory/`. - -## Output - -Each `` block lists the generated memory files as references. - -## Process - -1. **Run.** Execute the memory-sync script (`update_memory.js` in the plugin's `hooks/`) to fill each block (the block: `@../references/memory-block.md`). -2. **Guard.** On a non-zero exit, print the error and stop; tell the user to check that `aidd_docs/memory/` holds a `.md` file and that `node` is available. - -## Test - -- Each context file's `` block references every file in `aidd_docs/memory/`. diff --git a/plugins/aidd-context/skills/02-project-memory/assets/report.md b/plugins/aidd-context/skills/02-project-memory/assets/report.md new file mode 100644 index 00000000..41a41b5d --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/assets/report.md @@ -0,0 +1,13 @@ + + +```txt +Memory bank — files under aidd_docs/memory/ + + new | revised + ... + +Flagged + + +Review — independent reviewers | ran without subagents, one fresh pass +``` diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md index 34aebd12..b97c915c 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md @@ -4,23 +4,28 @@ Structured context the AI assistant reads at the start of a session, so it does ## How it loads -- The files at the root of `memory/` are referenced by the `` block in the AI context file and load every session. -- `internal/` and `external/` are listed there too, but load on demand, only when relevant. +```mermaid +flowchart LR + bank["memory/*.md"] -->|every session| ai(["AI context"]) + notes["internal/ · external/"] -.->|on demand| ai +``` + +The root files load every session through the `` block in each AI context file. `internal/` and `external/` load only when relevant. ## Files -The list below is refreshed automatically by the memory hook. Do not edit it by hand. +Refreshed automatically by the memory hook. Do not edit by hand. -## How to maintain it +## Maintaining it + +The AI writes and refreshes these files. When you edit one by hand: - One file per concern (architecture, database, vcs, ...). -- Capture the macro and the non-derivable. Point to the code, do not copy it. -- Keep each file small, well under 200 lines. -- Update a file when the underlying reality changes. -- Current state only. Never personal notes or future TODOs. +- Capture the macro and the non-derivable. Point to the code, never copy it. +- Current state only, kept small. No personal notes, no future TODOs. ## Subdirectories diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/auth/auth.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/auth/auth.md index c12f0dc5..cf67fcdf 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/auth/auth.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/auth/auth.md @@ -6,6 +6,11 @@ How identity and access work: authentication and authorization. - +```mermaid +flowchart LR + TODO[client] -->|credentials| TODO2[provider] -->|token| TODO3[session] +``` + ## Authorization - @@ -16,5 +21,6 @@ How identity and access work: authentication and authorization. diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/database/database.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/database/database.md index 13a6450c..1e80c7e8 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/database/database.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/database/database.md @@ -8,11 +8,11 @@ The data store: its type, the main entities, and the conventions. The macro mode ## Main entities -The core entities and their relationships, high level only. +The aggregate roots and how the main entities group: the design the schema does not show. Point to the schema file for columns and keys. ```mermaid -erDiagram - TODO ||--o{ TODO : "main entities only" +flowchart LR + TODO[aggregate root] --> TODO2[owned entity] ``` ## Conventions @@ -21,6 +21,7 @@ erDiagram - diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/deployment/deployment.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/deployment/deployment.md index f61f0957..ec2a92ea 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/deployment/deployment.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/deployment/deployment.md @@ -7,6 +7,11 @@ Where the project runs and how it ships: CI/CD, environments, and release. - - +```mermaid +flowchart LR + TODO[push] --> TODO2[build] --> TODO3[test] --> TODO4[deploy] +``` + ## Environments - @@ -21,5 +26,6 @@ Where the project runs and how it ships: CI/CD, environments, and release. diff --git a/plugins/aidd-context/skills/02-project-memory/references/capability-signals.md b/plugins/aidd-context/skills/02-project-memory/references/capability-signals.md index bb00ba40..64c5511c 100644 --- a/plugins/aidd-context/skills/02-project-memory/references/capability-signals.md +++ b/plugins/aidd-context/skills/02-project-memory/references/capability-signals.md @@ -1,25 +1,20 @@ # Capability signals -The memory bank is shaped by the concerns the project genuinely has, not by a single project type. The templates live in one folder per capability under `assets/templates/memory/`. The folder is the gate: generate `core/` always, plus the folder of each capability the project has. +A concern scan detects from a concrete fact in the repo, or an equivalent one, never inferred from the domain. -A capability holds when a concrete fact in the repo matches the capability's **definition**. The listed signals are canonical evidence, not a closed set: an equivalent concrete fact (a dedicated module, a set of ports) counts too. What never counts is an inferred dominant domain ("it is a web app, so it probably has auth"). There is no fallback type and no `unknown`. Every fire is shown to the user with its evidence at the Confirm step, so a judged match is never silent. - -## Capability, definition, and folder - -| Folder | Definition (the concern) | Evidence (any concrete one, or an equivalent fact) | Concerns (files) | -| ------------ | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | --------------------------- | -| `core` | always | always | project-brief, architecture, codebase-map, coding-assertions, testing, vcs | -| `ui` | renders a user-facing interface | a web frontend framework in the manifest (not React Native), or a `components/`, `pages/` web UI dir | design, forms, navigation | -| `api` | exposes an HTTP or RPC surface | a server framework in the manifest, or a `routes/`, `controllers/`, `api/` dir | api, integration | -| `database` | persists data in a store | an ORM or driver in the manifest, a `migrations/` dir, or a schema file | database | -| `auth` | authenticates a user or service, or authorizes access | an auth library (passport, next-auth, clerk, auth0, devise), auth middleware, or a dedicated auth module (oauth, token, credential, or session handling) | auth | -| `realtime` | pushes live updates over a persistent connection | a websocket or SSE library (socket.io, ws, pusher, ably) | realtime | -| `messaging` | produces or consumes asynchronous messages | a queue or broker (kafka, rabbitmq, sqs, bullmq) with producers or consumers | messaging | -| `deployment` | is built and shipped to a runtime | a CI config, or a `Dockerfile` | deployment | -| `infra` | provisions infrastructure as code | Terraform, Pulumi, Kubernetes, or Helm files | infra | -| `mobile` | ships a native or cross-platform mobile app | an `ios/` or `android/` dir, a `pubspec.yaml`, a `Podfile`, or React Native or Flutter | mobile | -| `desktop` | ships a native desktop app | Electron or Tauri | desktop | -| `package` | ships a reusable library others import | an importable entry (`main`, `module`, `exports`) that is not the CLI bin target, and publishable (not private) | package | -| `cli` | is run as a command-line tool | a `bin` field, or a CLI-parser dependency (commander, yargs, oclif, clap, click) | cli | -| `data` | processes data or trains models | notebooks, a data-versioning or ML tool, or pipeline and model files | data | -| `monorepo` | hosts several packages in one repo | workspaces, or a monorepo tool (Turborepo, Nx, Lerna) | enriches `core/codebase-map` (the Packages section), no folder | +| Capability | Means | Detected when | +| ------------ | ------------------------------ | ----------------------------------------------------------------------------------------- | +| `core` | always | always | +| `ui` | renders a user interface | a web frontend framework (not React Native), or a `components/` or `pages/` dir | +| `api` | exposes HTTP or RPC | a server framework, or a `routes/`, `controllers/`, or `api/` dir | +| `database` | persists data | an ORM or driver, a `migrations/` dir, or a schema file | +| `auth` | authenticates or authorizes | an auth library (passport, next-auth, clerk, auth0, devise), auth middleware, or an auth module | +| `realtime` | pushes live updates | a websocket or SSE library (socket.io, ws, pusher, ably) | +| `messaging` | async messages | a queue or broker (kafka, rabbitmq, sqs, bullmq) with producers or consumers | +| `deployment` | is built and shipped | a CI config, or a `Dockerfile` | +| `infra` | infrastructure as code | Terraform, Pulumi, Kubernetes, or Helm files | +| `mobile` | ships a mobile app | an `ios/` or `android/` dir, a `pubspec.yaml`, a `Podfile`, or React Native or Flutter | +| `desktop` | ships a desktop app | Electron or Tauri | +| `package` | ships a reusable library | an importable entry (`main`, `module`, `exports`) that is not the CLI bin, and publishable | +| `cli` | runs as a command-line tool | a `bin` field, or a CLI parser (commander, yargs, oclif, clap, click) | +| `data` | processes data or trains models | notebooks, a data-versioning or ML tool, or pipeline and model files | diff --git a/plugins/aidd-context/skills/02-project-memory/references/mapping-ai-context-file.md b/plugins/aidd-context/skills/02-project-memory/references/mapping-ai-context-file.md deleted file mode 100644 index 4a1ae636..00000000 --- a/plugins/aidd-context/skills/02-project-memory/references/mapping-ai-context-file.md +++ /dev/null @@ -1,15 +0,0 @@ -# AI mapping Context file - -## Purpose - -Map the memory file root to the correct AI-specific paths. - -## AI map - -| AI | Paths | -| -------------- | ------------------------------------------------ | -| Claude Code | `CLAUDE.md` | -| Cursor | `AGENTS.md` | -| OpenCode | `AGENTS.md` | -| GitHub Copilot | `.github/copilot-instructions.md` or `AGENTS.md` | -| Codex CLI | `AGENTS.md` | diff --git a/plugins/aidd-context/skills/02-project-memory/references/memory-block.md b/plugins/aidd-context/skills/02-project-memory/references/memory-block.md deleted file mode 100644 index 1c7c7b98..00000000 --- a/plugins/aidd-context/skills/02-project-memory/references/memory-block.md +++ /dev/null @@ -1,12 +0,0 @@ -# Memory block - -The `` block is where a tool's AI context file points to the generated memory files. It sits under `## Memory Management` → `### Project memory` (full template: `@../assets/AGENTS.md`). - -## Upsert - -Apply the first case that matches a tool's context file: - -- **Absent:** copy `@../assets/AGENTS.md`, set the tool's title. -- **No `## Memory Management`:** append that section from the template. -- **Section but no block:** insert an empty `` block after `### Project memory`. -- **Block present:** leave it, report "already ok". diff --git a/plugins/aidd-context/skills/02-project-memory/references/memory-destinations.md b/plugins/aidd-context/skills/02-project-memory/references/memory-destinations.md new file mode 100644 index 00000000..33bbb7fc --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/references/memory-destinations.md @@ -0,0 +1,28 @@ +# Memory destinations + +Where each template lands: flat under `aidd_docs/memory/`, read from this table, never derived. + +| Capability | Template | Write to | +| ---------- | --------------------------- | ---------------------------------------- | +| core | `core/project-brief.md` | `aidd_docs/memory/project-brief.md` | +| core | `core/architecture.md` | `aidd_docs/memory/architecture.md` | +| core | `core/codebase-map.md` | `aidd_docs/memory/codebase-map.md` | +| core | `core/coding-assertions.md` | `aidd_docs/memory/coding-assertions.md` | +| core | `core/testing.md` | `aidd_docs/memory/testing.md` | +| core | `core/vcs.md` | `aidd_docs/memory/vcs.md` | +| api | `api/api.md` | `aidd_docs/memory/api.md` | +| api | `api/integration.md` | `aidd_docs/memory/integration.md` | +| auth | `auth/auth.md` | `aidd_docs/memory/auth.md` | +| cli | `cli/cli.md` | `aidd_docs/memory/cli.md` | +| data | `data/data.md` | `aidd_docs/memory/data.md` | +| database | `database/database.md` | `aidd_docs/memory/database.md` | +| deployment | `deployment/deployment.md` | `aidd_docs/memory/deployment.md` | +| desktop | `desktop/desktop.md` | `aidd_docs/memory/desktop.md` | +| infra | `infra/infra.md` | `aidd_docs/memory/infra.md` | +| messaging | `messaging/messaging.md` | `aidd_docs/memory/messaging.md` | +| mobile | `mobile/mobile.md` | `aidd_docs/memory/mobile.md` | +| package | `package/package.md` | `aidd_docs/memory/package.md` | +| realtime | `realtime/realtime.md` | `aidd_docs/memory/realtime.md` | +| ui | `ui/design.md` | `aidd_docs/memory/design.md` | +| ui | `ui/forms.md` | `aidd_docs/memory/forms.md` | +| ui | `ui/navigation.md` | `aidd_docs/memory/navigation.md` | diff --git a/plugins/aidd-context/skills/02-project-memory/references/memory-rules.md b/plugins/aidd-context/skills/02-project-memory/references/memory-rules.md new file mode 100644 index 00000000..73524d16 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/references/memory-rules.md @@ -0,0 +1,11 @@ +# Memory rules + +A memory file: + +- Captures the macro and the non-derivable: decisions, conventions, gotchas, the why. +- Never restates a schema or a file tree. +- Points to the code over a copy. +- Holds one fact in one home, referenced elsewhere. +- Stays small: short bullets, code in backticks. +- Names a tech without its version (`React`, not `React 19`). +- Reflects the current state only: no unused section, no placeholder. diff --git a/plugins/aidd-context/skills/02-project-memory/references/review-protocol.md b/plugins/aidd-context/skills/02-project-memory/references/review-protocol.md new file mode 100644 index 00000000..261bba90 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/references/review-protocol.md @@ -0,0 +1,13 @@ +# Review protocol + +You review one memory file the AI loads every session. Catch what its writer could not see. + +1. **Read** the file, the code it describes, and the other memory files' names. +2. **Flag** each of these, with a reason and a location: + - A claim the code does not back, or has gone stale. + - A command, path, or file that does not exist or would not run. + - A "why" the code and history do not support. + - A decision, convention, or gotcha the code shows but the file omits. + - A fact that belongs under another file's name, for generate to dedup. + - Any remaining breach of `memory-rules.md`. +3. **Return** the flags. Do not edit the file. diff --git a/plugins/aidd-context/skills/02-project-memory/references/structure.md b/plugins/aidd-context/skills/02-project-memory/references/structure.md new file mode 100644 index 00000000..2d06a2d2 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/references/structure.md @@ -0,0 +1,15 @@ +# Structure + +The tree generate scaffolds. + +```txt +aidd_docs/ +├── README.md from assets/README.md +├── GUIDELINES.md from assets/GUIDELINES.md +├── CONTRIBUTING.md from assets/CONTRIBUTING.md +└── memory/ + ├── README.md from assets/templates/memory/README.md + ├── .md the memory files, flat (see memory-destinations.md) + ├── internal/ a .gitkeep, internal notes read on demand + └── external/ a .gitkeep, external notes read on demand +``` diff --git a/plugins/aidd-context/skills/02-project-memory/references/tools.md b/plugins/aidd-context/skills/02-project-memory/references/tools.md new file mode 100644 index 00000000..c0c470c1 --- /dev/null +++ b/plugins/aidd-context/skills/02-project-memory/references/tools.md @@ -0,0 +1,14 @@ +# Tools + +The AI tools a project can use. + +| Tool | Detected when | Context file | +| -------- | ------------------------------------------------------------------------------------ | --------------------------------- | +| claude | `.claude/` or `CLAUDE.md` | `CLAUDE.md` | +| codex | `.codex/` | `AGENTS.md` | +| cursor | `.cursor/` or `.cursorrules` | `AGENTS.md` | +| opencode | `.opencode/` | `AGENTS.md` | +| copilot | `.github/copilot-instructions.md` or `.github/{instructions,agents,skills,prompts}/` | `.github/copilot-instructions.md` | + +- A shared `AGENTS.md` is a wiring target, never a detection signal. +- Tools sharing a context file wire it once; the block serves them all. diff --git a/scripts/sync-skill-argument-hints.mjs b/scripts/sync-skill-argument-hints.mjs index d4b31bf6..27e35958 100755 --- a/scripts/sync-skill-argument-hints.mjs +++ b/scripts/sync-skill-argument-hints.mjs @@ -92,8 +92,14 @@ function syncArgumentHint(content, hint) { return `---\n${lines.join("\n")}${parts.body}`; } +// Skills whose argument-hint is written by hand, because it names the user's +// cases (set up, refresh, re-wire) rather than one token per action. The hook +// leaves these untouched. This is the base pattern for a case-based router. +const MANUAL_ARGUMENT_HINT = new Set(["02-project-memory"]); + const stale = []; for (const dir of await skillDirs()) { + if (MANUAL_ARGUMENT_HINT.has(path.basename(dir))) continue; const skillPath = path.join(dir, "SKILL.md"); const actionFiles = await collectMarkdownFiles(path.join(dir, "actions")); const names = [...new Set(actionFiles.map(actionName))];