@markstanden/opencode-docs-plugin 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CONVENTION.md CHANGED
@@ -4,13 +4,42 @@ This plugin owns this convention: it is what the `docs` tool's `add` writes,
4
4
  what `check` validates, and what the registered `docs` skill teaches. A
5
5
  repository that adopts the plugin takes the convention with it.
6
6
 
7
+ ## Classes and scope
8
+
9
+ Every doc belongs to exactly one class. The class is fixed by the lake it lives
10
+ in, so a doc cannot mix scopes.
11
+
12
+ | Class | Where | Reader | Writes |
13
+ | ------------------ | ----------------------------------- | ---------------------------- | ------------------------------------- |
14
+ | **Instructions** | nested `README.md` files | code-local how-to | never by the tool |
15
+ | **RepoContext** | `<repo>/docs` by default | this repo | yes |
16
+ | **MachineContext** | a personal lake such as `~/doclake` | this person, across machines | yes |
17
+ | **GlobalContext** | an organisation lake | every team, every repo | yes, lock down with `writable: false` |
18
+ | **Wiki** | a human-readable wiki checkout | humans first, agents second | no |
19
+
20
+ Place at the **narrowest scope where the whole claim is true**:
21
+
22
+ 1. Command or step to build, run, test, deploy → Instructions.
23
+ 2. True only for this repo → RepoContext.
24
+ 3. True for you across machines → MachineContext.
25
+ 4. True for the org across repos → GlobalContext.
26
+ 5. Human-facing narrative → Wiki.
27
+
28
+ Two answers mean two focused docs, one per class. A doc that needs a placement
29
+ debate is not focused enough.
30
+
7
31
  ## Where knowledge lives
8
32
 
9
- Durable knowledge is one Markdown file per topic under the docs root, grouped by
10
- area: `<area>/<name>.md` (the root is the plugin's `root` option; default
11
- `<location>/docs`). The excluded areas — never scanned, never validated —
12
- are `plans/` (scratch, gitignored, deleted when the work lands),
13
- `requirements/` and `wiki/` (vendored mirrors).
33
+ Durable knowledge is one Markdown file per topic under a lake root, grouped by
34
+ area: `<area>/<name>.md`. The default repo lake is `<location>/docs`; its docs
35
+ are RepoContext. A repo adds other local roots in
36
+ `.opencode/docs-lakes.json`; a personal or managed base file lists the
37
+ machine, global and wiki lakes.
38
+
39
+ The excluded areas — never scanned, never validated in a knowledge lake — are
40
+ `plans/` (scratch, gitignored, deleted when the work lands), `requirements/`
41
+ and `wiki/` (vendored mirrors). The wiki profile has no such exclusions; only
42
+ dot-directories and `node_modules` are skipped there.
14
43
 
15
44
  Search also covers `README.md` files nested in the project tree, so an agent
16
45
  finds the map beside the code. They are indexed as they stand (H1 title,
@@ -21,27 +50,38 @@ are skipped by name.
21
50
 
22
51
  ## Front-matter
23
52
 
24
- Every doc opens with a `---` front-matter block. The fields, in canonical order:
53
+ Every knowledge doc opens with a `---` front-matter block. The fields, in
54
+ canonical order:
25
55
 
26
- | Field | Required | Meaning |
27
- | ------------ | -------- | ----------------------------------------------------------------------- |
28
- | `Area` | yes | One top-level path segment; the doc's group. |
29
- | `Keywords` | yes | Comma-separated search terms; the second half of the doc's identity. |
30
- | `Summary` | yes | One self-contained sentence: enough to decide whether to open the file. |
31
- | `Status` | no | `active` (the default) or `superseded`. |
32
- | `Supersedes` | no | The doc this one replaces. |
56
+ | Field | Required | Meaning |
57
+ | ---------- | -------- | ----------------------------------------------------------------------- |
58
+ | `Area` | yes | One top-level path segment; the doc's group. |
59
+ | `Keywords` | yes | Comma-separated search terms; the second half of the doc's identity. |
60
+ | `Summary` | yes | One self-contained sentence: enough to decide whether to open the file. |
33
61
 
34
62
  `Date` is **derived, never written**: the file's last git commit date, falling
35
63
  back to mtime. A hand-maintained `Date` is a finding, not a field.
36
64
 
65
+ There is no lifecycle field. `Status` and `Supersedes` are **obsolete**; `check`
66
+ reports them as notes so an existing lake can be cleaned once. A doc is current
67
+ or deleted: git is the archive.
68
+
37
69
  The tool serialises the front-matter — never copy it by hand.
38
70
 
71
+ Wiki pages carry no front-matter. ADO renders YAML as raw text, and a human wiki
72
+ should read cleanly. The wiki profile derives the title from the H1, the area
73
+ from the folder, the summary from the first prose paragraph, and the date from
74
+ git. Optional invisible metadata may be added later; it is not required.
75
+
39
76
  ## Body
40
77
 
41
78
  - An `H1` title: the first half of the doc's identity.
42
79
  - At least one claim section as an `H2`/`H3` heading — `Facts`, `Inferred`,
43
- `Tested`, `Open questions` — so a reader knows how much to rely on each claim.
44
- Group claims by section rather than mixing them.
80
+ `Tested`, `Failed approaches`, `Open questions` — so a reader knows how much
81
+ to rely on each claim. Group claims by section rather than mixing them.
82
+ - A failed attempt is a valid current doc or section: state what was tried, why
83
+ it failed, what is true now, and what not to retry. Do not keep a doc whose
84
+ claims are no longer true.
45
85
 
46
86
  ## Identity and duplicates
47
87
 
@@ -52,16 +92,44 @@ The tool serialises the front-matter — never copy it by hand.
52
92
  `add` refuses a near-twin write and returns the candidates to reconcile
53
93
  against — edit before add, merge near-twins, split a bloated doc into
54
94
  per-topic files.
95
+ - Near-twins are per lake. The same topic at repo and global scope is
96
+ legitimate; the narrower doc states its delta and links up.
97
+
98
+ ## Focus, ownership and promotion
99
+
100
+ - One question per doc. One topic per doc.
101
+ - More than one H2 aimed at different topics or audiences means split.
102
+ - Never write an omnibus notes doc to avoid choosing a class.
103
+ - The narrowest true scope owns the claim. A broader class owns the general
104
+ rule; the narrower doc states only its delta and links up.
105
+ - Do not copy between knowledge classes. Move or link.
106
+ - Instructions own commands. Knowledge docs own reasons and link to the
107
+ command. Knowledge docs link to the wiki page for human narrative.
108
+ - Wiki duplication is expected, not a defect. If a wiki page drifts from a
109
+ knowledge doc, report it and name both pages; do not edit the wiki.
110
+ - Promotion is a move: the general claim goes up, the local delta stays. Delete
111
+ the emptied doc and repoint every in-repo link. No superseded stubs. An
112
+ unrepointable external link is reported for a human to fix.
113
+ - A soft note appears when a body exceeds `maxDocLines` (default 200,
114
+ configurable). A note, not a refusal. Reference tables are judged by review.
115
+
116
+ ## Safety
117
+
118
+ - No secrets, credentials, tokens, or customer data. Name the vault or variable,
119
+ never the value.
120
+ - No personal data in GlobalContext or Wiki.
121
+ - The wiki profile is read-only to the tool. Its own owners review changes.
55
122
 
56
123
  ## Lifecycle
57
124
 
58
- `Status` and `Supersedes` are load-bearing, not decoration. A doc marked
59
- `Status: superseded` is flagged `(superseded)` in search results and ranks below
60
- an active doc on a tie; `check` flags a `Supersedes` that names no doc in the
61
- tree.
125
+ A doc is current or deleted. Correct a wrong doc by replacing it in place with
126
+ `add` and an explicit `path`. Delete an obsolete doc through the shell with
127
+ explicit approval; there is no `delete` verb. A failed attempt is still valid
128
+ knowledge when it records the outcome and the current truth.
62
129
 
63
130
  ## Adopting it
64
131
 
65
132
  Run `check` to audit an existing tree, and the gate's `defined comply` before
66
- proposing a commit. A missing docs root is not an error: the plugin scans
67
- what is there and reports per-doc findings for what is not.
133
+ proposing a commit. A missing lake root is a note, not an error: the plugin
134
+ scans what is there and reports per-doc findings for what is not. Wiki lakes
135
+ are read-only and are reported as not validated, never silently skipped.
package/README.md CHANGED
@@ -1,24 +1,49 @@
1
1
  # opencode-docs-plugin
2
2
 
3
- An [OpenCode](https://opencode.ai) V2 plugin that gives an agent a knowledge
4
- tree it can actually use: a `docs` tool and a `/docs` command over the
5
- configured docs root's `*.md` files (the `root` plugin option; default
6
- `<location>/docs`), plus nested `README.md` files in the project tree, and the
3
+ An [OpenCode](https://opencode.ai) V2 plugin that gives an agent a set of
4
+ knowledge **lakes** it can actually use: a `docs` tool and a `/docs` command
5
+ over configured Markdown trees, nested `README.md` files in the project, and the
7
6
  writing convention those docs follow.
8
7
 
9
- - `docs` (tool) — blank search lists the 10 most recently changed docs
10
- (`path — Area — date — Summary`); a search ranks docs over their
11
- front-matter, path and body identifiers, falling back to the closest
12
- matches rather than a dead end; `add` writes knowledge through a typed DTO;
13
- `check` validates the tree against the convention. Nested project
14
- `README.md` files are indexed too — `.gitignore` rules decide what is
15
- skipped — but only for search: `add` and `check` never touch them.
8
+ Docs are grouped by **class**:
9
+
10
+ | Class | Where | Use it for | Writes |
11
+ | ------------------ | ------------------------------- | --------------------------------------- | ------------- |
12
+ | **Instructions** | nested `README.md` | build, run, test, deploy this code | never |
13
+ | **RepoContext** | `<repo>/docs` by default | this repo's traps, decisions, landmines | yes |
14
+ | **MachineContext** | personal lake, e.g. `~/doclake` | tooling and traps across your machines | yes |
15
+ | **GlobalContext** | organisation lake | standards and integrations across repos | yes, reviewed |
16
+ | **Wiki** | human-readable wiki checkout | narrative for humans | read-only |
17
+
18
+ Place knowledge at the narrowest scope where the whole claim is true. A doc that
19
+ spans scopes is split into focused docs, one per class. The full rulebook is
20
+ [CONVENTION.md](CONVENTION.md); the registered `docs` skill carries the working
21
+ version.
22
+
23
+ ## The tool and command
24
+
25
+ - `docs` (tool) — blank search lists the most recently changed docs
26
+ (`path — Area — date — Summary`); a search ranks docs over their front-matter,
27
+ path and body identifiers (plus wiki prose), falling back to the closest
28
+ matches rather than a dead end; `read` returns a doc verbatim and accepts a
29
+ `lake` or `lake:path`; `add` writes knowledge through a typed DTO; `check`
30
+ validates the knowledge lakes. Nested project `README.md` files are indexed
31
+ too — `.gitignore` rules decide what is skipped — but only for search: `add`
32
+ and `check` never touch them, and their results are prefixed `instructions:`
33
+ and read with the built-in `read` tool. A Code Mode twin, `docs_search`,
34
+ registers alongside it, so `execute` reaches the same lakes as
35
+ `tools.docs.docs_search(…)`.
16
36
  - `/docs` (command) — the same core, driven from the prompt:
17
37
  `search <text>` (bare text searches too), `add <text>`, `check`, `help`.
18
38
  - The plugin also registers the `docs` skill, so the convention travels with
19
39
  the tool rather than living in always-loaded prose.
20
40
 
21
- Reading a matched doc stays OpenCode's built-in `read`.
41
+ Reading a matched project file stays OpenCode's built-in `read`. The tool's own
42
+ `read` serves lake docs and wiki pages.
43
+
44
+ Every source reserves a few results (default 3 per source) before the rest of
45
+ the cap fills by score, so a broad wiki cannot bury a focused repo doc. The
46
+ cap is 10 results; the cut is counted.
22
47
 
23
48
  ## Installation
24
49
 
@@ -38,17 +63,19 @@ or as a `plugins` entry in `opencode.json(c)` (global, project or `.opencode/`):
38
63
  ```
39
64
 
40
65
  Unpinned entries update on the next server start or `opencode plugin update`;
41
- an exact version (e.g. `@0.2.0`) stays pinned.
66
+ an exact version (e.g. `@0.5.0`) stays pinned.
42
67
 
43
68
  ## Configuration
44
69
 
45
- The docs root defaults to `<location>/docs`. Set the `root` option with the
46
- object form — `~` expands against the home directory, so a global config can
47
- point every project at one shared tree:
70
+ One docs plugin entry, in the global or managed config. **Do not repeat the
71
+ entry at project level**: the same package loads twice and both copies receive
72
+ the project options, losing the base lakes. Add per-repo lakes through the repo
73
+ file instead.
74
+
75
+ The simplest setup uses `root` — one repo lake:
48
76
 
49
77
  ```jsonc
50
78
  {
51
- "$schema": "https://opencode.ai/config.json",
52
79
  "plugins": [
53
80
  {
54
81
  "package": "@markstanden/opencode-docs-plugin",
@@ -60,12 +87,103 @@ point every project at one shared tree:
60
87
  }
61
88
  ```
62
89
 
63
- Relative paths resolve against the location's directory; absolute paths pass
64
- through. A blank `root` value counts as unset and uses the default; a
65
- non-string value fails at startup. The root directory itself need not exist in
66
- advance — it is created on the first `add`, and a search or `check` over a
67
- still-empty tree simply reports nothing. Restart OpenCode after editing the
68
- config — it isn't hot-reloaded.
90
+ `root` expands `~`, resolves a relative path against the location, and defaults
91
+ to `<location>/docs`. A blank value counts as unset. `root` declares a **repo**
92
+ lake; for a personal or global lake, use `lakes` with the class instead.
93
+
94
+ For several lakes, list them inline, in a base file, or both. The base file is
95
+ usually a personal or managed file; the repo file adds local lakes:
96
+
97
+ ```jsonc
98
+ {
99
+ "plugins": [
100
+ {
101
+ "package": "@markstanden/opencode-docs-plugin",
102
+ "options": {
103
+ "lakesFile": "~/.config/opencode/docs-lakes.json",
104
+ "lakes": [{ "class": "repo", "root": "./docs" }],
105
+ "maxDocLines": 200,
106
+ "perLakeQuota": 3,
107
+ },
108
+ },
109
+ ],
110
+ }
111
+ ```
112
+
113
+ `~/.config/opencode/docs-lakes.json`:
114
+
115
+ ```jsonc
116
+ {
117
+ "lakes": [
118
+ { "class": "machine", "root": "~/doclake", "name": "doclake" },
119
+ { "class": "global", "root": "~/org-docs", "name": "global" },
120
+ { "class": "wiki", "root": "~/org-wiki", "name": "wiki" },
121
+ ],
122
+ }
123
+ ```
124
+
125
+ A repo adds its own lakes in `.opencode/docs-lakes.json`, checked into the repo:
126
+
127
+ ```jsonc
128
+ {
129
+ "lakes": [
130
+ { "root": "documentation", "name": "docs" },
131
+ { "root": "reference", "name": "reference", "writable": false },
132
+ ],
133
+ }
134
+ ```
135
+
136
+ Repo-file rules:
137
+
138
+ - only `repo` lakes;
139
+ - roots must resolve inside the location;
140
+ - an absent file is ignored; a malformed file fails at startup.
141
+
142
+ A sibling repository's docs belong in the base `lakesFile`, not the repo file.
143
+
144
+ Merge order: base `lakesFile`, repo file, inline `lakes`, then `root`. Duplicate
145
+ lake names fail at startup. If no repo lake is configured, one implicit repo
146
+ lake at `<location>/docs` is added — so a repo needs no lake file unless its
147
+ docs live elsewhere.
148
+
149
+ Lake entries:
150
+
151
+ | Field | Meaning |
152
+ | ---------- | ------------------------------------------------------------------------------------------------ |
153
+ | `class` | `repo`, `machine`, `global` or `wiki`; default `repo`. |
154
+ | `root` | The lake root. Required for `machine`/`global`/`wiki`; defaults to `<location>/docs` for `repo`. |
155
+ | `name` | Lower-case dashes; defaults to the root folder name. `instructions` is reserved. |
156
+ | `writable` | Defaults true for knowledge classes, fixed false for `wiki`. |
157
+
158
+ Lake paths never follow symlinks: a symlinked doc is skipped by search and
159
+ `check`, refused by `read`, and refused by `add`. The configured `root` itself
160
+ may be a symlink; the content beneath it must be real.
161
+
162
+ `maxDocLines` (default 200, `0` disables) is a **soft** note on a long doc, not a
163
+ refusal. `perLakeQuota` (default 3, `0` disables) is the per-source result
164
+ reservation.
165
+
166
+ ## Wiki lakes
167
+
168
+ Wiki pages are read-only reference. They carry no required front-matter: the
169
+ title comes from the H1, the area from the folder, the summary from the first
170
+ prose paragraph, and the date from git. Prose and tables are indexed so a page
171
+ that names an Azure region only in a table is still searchable. Wiki lakes are
172
+ never validated. If a wiki page drifts from a knowledge doc, report it; the
173
+ wiki's owners decide.
174
+
175
+ ## Check
176
+
177
+ `check` validates the knowledge lakes: required front-matter, an H1, at least
178
+ one claim section (`Facts`, `Inferred`, `Tested`, `Failed approaches`,
179
+ `Open questions`), no hand-maintained `Date`, a distinctive H1+Keywords
180
+ identity, same-area near-twins, and broken relative `.md` links. Obsolete
181
+ `Status`/`Supersedes` fields, long docs, and unversioned or missing roots are
182
+ **notes**, not findings. An empty findings list means compliant.
183
+
184
+ There is no lifecycle field. A doc is current or deleted; git is the archive.
185
+ Correct a wrong doc by replacing it in place. A failed attempt is valid
186
+ knowledge when it records the outcome and what is true now.
69
187
 
70
188
  ## Status
71
189
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@markstanden/opencode-docs-plugin",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
- "description": "OpenCode V2 plugin: a `docs` tool and `/docs` command over a repository's knowledge tree and the project's nested README.md files (search only), with the writing convention it owns",
5
+ "description": "OpenCode V2 plugin: a `docs` tool and `/docs` command over configurable knowledge lakes (repo, machine, global and read-only wiki), nested README.md search, and the writing convention they share",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/markstanden/opencode-docs-plugin.git"
package/src/SKILL.md CHANGED
@@ -1,13 +1,26 @@
1
1
  # Docs
2
2
 
3
- Durable knowledge lives under the configured docs root (the plugin's `root`
4
- option; default `<location>/docs`). This skill covers both
5
- halves of the loop: **find** (discover with the `docs` tool, read the match) and
6
- **record** (write or update a doc for the current task).
3
+ Durable knowledge lives in **lakes**. The plugin reads every configured lake
4
+ and the project's nested `README.md` files. This skill covers both halves of the
5
+ loop: **find** (search, then read) and **record** (write or update a focused
6
+ doc at the narrowest true scope).
7
7
 
8
- Call the `docs` tool directly at top level. It is a plugin-registered tool and
9
- is **not** reachable from the `execute` (Code Mode) catalog — do not try to
10
- batch it inside `execute`, and do not be misled by the unknown-tool suggestion.
8
+ Call the `docs` tool at top level. Inside `execute` (Code Mode) the same tool
9
+ is reachable as the twin `tools.docs.docs_search(…)` — same verbs, same lakes —
10
+ so batch it with the rest of the catalog there.
11
+
12
+ ## Classes
13
+
14
+ | Class | Where | Use it for | Writes |
15
+ | ------------------ | --------------------------- | --------------------------------------- | ------------- |
16
+ | **Instructions** | nested `README.md` | build, run, test, deploy this code | never |
17
+ | **RepoContext** | `<repo>/docs` | this repo's traps, decisions, landmines | yes |
18
+ | **MachineContext** | personal lake (`~/doclake`) | tooling and traps across your machines | yes |
19
+ | **GlobalContext** | organisation lake | standards and integrations across repos | yes, reviewed |
20
+ | **Wiki** | human-readable wiki | narrative for humans | read-only |
21
+
22
+ Record at the **narrowest scope where the whole claim is true**. Two scopes
23
+ means two focused docs. Never one omnibus doc that is out of place.
11
24
 
12
25
  ## Find it
13
26
 
@@ -15,78 +28,88 @@ Call the `docs` tool:
15
28
 
16
29
  - **blank `search`** — the most recently changed docs, one line per doc
17
30
  (`path — Area — date — Summary`).
18
- - **a `search`** — those docs ranked over title, path, keywords, body headings
19
- and code spans, area and summary. When no doc contains every term it returns
20
- the closest matches under a `Closest matches` header rather than a dead end.
21
- A term must appear as a **substring** to match — a typo returns nothing, by
22
- design. Terms shorter than `MIN_TERM_LENGTH` (3) are ignored unless they are
23
- the whole query, so filler words cannot drag in the catalogue.
24
- - **every call** caps at `MAX_RESULTS` (10), preferring the best matches and
25
- then the most recent edits, and ends with `… and N more not shown.` when
26
- anything was cut.
27
- - **exactly `help`** — plain text explaining the weights, the hit qualities and
28
- the outcomes, instead of a search.
29
-
30
- Then open the match with the built-in `read` tool. The tool only discovers; it
31
- never returns a doc's body. `/docs [search]` runs the same search into the
32
- session (`/docs search <text>` is the explicit form).
33
-
34
- Every `*.md` under the root is covered except the excluded areas — scratch (`plans/`)
35
- and vendored mirrors (`requirements/`, `wiki/`). `Area` comes from the path,
36
- `date` from git. A doc marked `Status: superseded` carries a `(superseded)`
37
- marker in results and ranks below an active doc on a tie.
38
-
39
- Search also covers nested `README.md` files in the project tree — the map lives
40
- beside the code. They are indexed as they stand (H1 title, headings, code
41
- spans) and are **search-only**: `add` and `check` never touch them.
42
- `.gitignore` decides which directories are skipped; outside git, dependency and
43
- build directories are skipped by name. The lake root is skipped when it sits
44
- inside the project, since those READMEs are already knowledge docs.
31
+ - **a `search`** — docs ranked over title, path, keywords, body headings and
32
+ code spans, area, summary and wiki prose. When no doc contains every term it
33
+ returns the closest matches under a `Closest matches` header rather than a
34
+ dead end. A term must appear as a **substring** to match — a typo returns
35
+ nothing, by design. Terms shorter than `MIN_TERM_LENGTH` (3) are ignored
36
+ unless they are the whole query.
37
+ - **every call** reserves up to `perLakeQuota` results per source (default 3),
38
+ caps at `MAX_RESULTS` (10), and ends with `… and N more not shown.` when
39
+ anything was cut. The reservation keeps a broad wiki from burying a focused
40
+ repo doc.
41
+ - **exactly `help`** — the configured lakes, their classes and writability,
42
+ then the ranking rules.
43
+
44
+ Then open the match with the tool's `read` verb — pass the root-relative path,
45
+ or `lake:path` when several lakes are configured. A project README result is
46
+ prefixed `instructions:`; read it with the built-in `read` tool instead.
47
+ `/docs [search]` runs the same search into the session (`/docs search <text>` is
48
+ the explicit form).
49
+
50
+ Every `*.md` under a knowledge lake is covered except the excluded areas —
51
+ scratch (`plans/`) and vendored mirrors (`requirements/`, `wiki/`). `Area` comes
52
+ from the path, `date` from git. Wiki lakes are read-only; their pages are
53
+ indexed as prose and tables, and their summaries are derived from the first
54
+ paragraph. A README is search-only, rendered as `instructions:path`, and is
55
+ never validated.
45
56
 
46
57
  ## Read it
47
58
 
48
59
  - Consult matching docs before a broad grep: they are the curated knowledge.
60
+ - Class precedence on a tie is repo, instructions, global, machine, wiki. A
61
+ non-primary lake is prefixed (`global:platform/regions.md`,
62
+ `wiki:Integrations/Billing.md`).
49
63
  - A `Summary` is a self-contained sentence — enough to decide whether to open
50
64
  the file.
51
65
 
52
66
  ## Record it
53
67
 
54
68
  Write durable findings and task documentation to `<area>/<title>.md` under the
55
- root so the
56
- next human or agent skips the rediscovery. The convention is this plugin's
57
- `CONVENTION.md`, restated here.
69
+ right lake so the next human or agent skips the rediscovery. The convention is
70
+ this plugin's `CONVENTION.md`, restated here.
58
71
 
59
72
  Before writing:
60
73
 
61
- 1. **Read first, never duplicate.** List the tree with the `docs` tool and read
62
- the docs relevant to the task: the same `<area>/` neighbourhood, keyword
63
- hits on the task's entities (service names, file paths, error strings, class
64
- names), or links from touched docs.
65
- 2. **Reconcile, then add.** Edit before add; merge near-twins; split a bloated
74
+ 1. **Read first, never duplicate.** Search the tree and read the docs relevant
75
+ to the task: the same `<area>/` neighbourhood, keyword hits on the task's
76
+ entities (service names, file paths, error strings, class names), or links
77
+ from touched docs.
78
+ 2. **Choose one class.** Repo-specific goes to RepoContext. Personal setup goes
79
+ to MachineContext. Cross-repo org knowledge goes to GlobalContext. How-to
80
+ commands stay in the README. Human narrative goes to the wiki, read-only.
81
+ 3. **Reconcile, then add.** Edit before add; merge near-twins; split a bloated
66
82
  doc into per-topic files; after any split, merge or move, grep for inbound
67
- references and repoint them, leaving a stub if needed.
83
+ references and repoint them. Delete the emptied doc — no superseded stubs.
84
+
85
+ One artifact per topic, one class per artifact: a session's findings land as
86
+ several focused docs, never one session dump — a compaction nudge hands you
87
+ `Record with docs add:` blocks already shaped for this.
68
88
 
69
89
  Then record through the `docs` tool's typed `add`: metadata (`Area`, `Keywords`
70
- as a list, `Summary`; optionally `Status`/`Supersedes`) plus a body carrying an
71
- `H1` and the claim sections (`Facts`, `Inferred`, `Tested`, `Open questions`).
72
- The tool serialises the front-matter — never copy it — and derives
73
- the target (`<Area>/<slug>.md`) when `path` is omitted; pass `path` to
74
- update an existing doc, replacing its body wholesale. Its guardrails refuse
75
- blank metadata, path traversal, a body without an `H1`, and a same-area
76
- near-twin (returning the candidates to reconcile against). A plan for an
77
- in-flight effort is scratch, not a doc — a `plans/` area, excluded from the
78
- index and deleted when the work lands. `/docs add <text>` runs this record
79
- loop for a fact supplied inline.
90
+ as a list, `Summary`) plus a body carrying an `H1` and a claim section (`Facts`,
91
+ `Inferred`, `Tested`, `Failed approaches`, `Open questions`). The tool
92
+ serialises the front-matter — never copy it — and derives the target
93
+ (`<Area>/<slug>.md`) when `path` is omitted; pass `path` to update an existing
94
+ doc, replacing its body wholesale. Its guardrails refuse blank metadata, path
95
+ traversal, a body without an `H1`, a read-only wiki lake, and a same-area
96
+ near-twin (returning the candidates to reconcile against).
97
+
98
+ A doc is current or deleted. There is no `Status` or `Supersedes` field. A
99
+ failed attempt is valid knowledge when it records what was tried, why it failed,
100
+ what is true now, and what not to retry. `check` reports the old fields as
101
+ obsolete notes so a lake can be cleaned once.
80
102
 
81
103
  ## Check it
82
104
 
83
- To audit the tree instead of writing it, call the tool's `check` (`/docs check`
84
- runs it into the session): it validates every doc against the convention —
85
- required front-matter, an `H1`, at least one claim section, no hand-maintained
86
- `Date`, an `H1`+`Keywords` identity with a term of `MIN_TERM_LENGTH` (3) or
87
- longer, a `Supersedes` naming a doc in the tree, and same-area near-twins — and
88
- reports findings per doc. An empty report means compliant. `add` enforces the
89
- same rules at the trust boundary.
105
+ To audit the knowledge lakes instead of writing them, call the tool's `check`
106
+ (`/docs check` runs it into the session): it validates required front-matter, an
107
+ `H1`, at least one claim section, no hand-maintained `Date`, an `H1`+`Keywords`
108
+ identity with a term of `MIN_TERM_LENGTH` (3) or longer, same-area near-twins,
109
+ and broken relative `.md` links. Obsolete fields, long docs and unversioned or
110
+ missing roots are **notes**, not findings. Wiki lakes are read-only and are
111
+ reported as not validated. `add` enforces the same structural rules at the
112
+ trust boundary.
90
113
 
91
114
  Finally, run the repo's gate (`defined comply` where `.defined.json` exists,
92
115
  else what its README documents) before proposing a commit. Fix failures; never