@nurix/etna 0.19.7 → 0.19.9
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/data/harness-index.json +1 -1
- package/data/harnesses/code/harness.json +1 -1
- package/data/harnesses/code/rules/pnpm.md +54 -0
- package/data/harnesses/code/rules/typescript.md +2 -21
- package/data/harnesses/kb-agi/CLAUDE.md +33 -29
- package/data/harnesses/kb-agi/agents/kb-apply.md +34 -0
- package/data/harnesses/kb-agi/agents/kb-audit.md +49 -0
- package/data/harnesses/kb-agi/agents/kb-init.md +316 -0
- package/data/harnesses/kb-agi/harness.json +2 -2
- package/data/harnesses/kb-agi/scripts/kb-export.mjs +167 -0
- package/package.json +1 -1
- package/data/harnesses/code/rules/nustack.md +0 -150
- package/data/harnesses/kb-agi/agents/kb-agi-init.md +0 -285
- package/data/harnesses/kb-agi/agents/kb-catch-stale.md +0 -22
- package/data/harnesses/kb-agi/agents/kb-find-gaps.md +0 -27
- package/data/harnesses/kb-agi/agents/kb-fix-links.md +0 -22
- package/data/harnesses/kb-agi/agents/kb-refresh-frontdoor.md +0 -22
- package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +0 -22
- package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +0 -25
- package/data/harnesses/kb-agi/rules/kb.md +0 -13
package/data/harness-index.json
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# pnpm — `@nurix/*` Workspaces: naming, boundaries, and consuming
|
|
2
|
+
|
|
3
|
+
How a `@nurix/*` multi-package repo is **named**, **structured**, and how its published packages are **consumed**. Publishing one — the pipeline, tokens, and the publish workflow — lives in the `nustack-publish` skill, not here. TypeScript language conventions are [`typescript.md`](typescript.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Package naming
|
|
8
|
+
|
|
9
|
+
Every workspace package is scoped to **`@nurix/`**. The segment after the scope encodes **intent** — the dot vs. hyphen is semantic, not cosmetic:
|
|
10
|
+
|
|
11
|
+
| Form | Meaning | Examples |
|
|
12
|
+
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
+
| `@nurix/workflows-sdk` (hyphen, single segment) | The **published, externally-destined** surface. A clean `@nurix/*` name is a published _contract_ — changing an export or peer dep is a breaking change for consumers outside this repo. | `@nurix/workflows-sdk` |
|
|
14
|
+
| `@nurix/workflows.<name>` (dot separator) | **Internal** to the workflows product — `private: true`, refactor freely, no external consumers. | `@nurix/workflows.agent-core`, `.worker`, `.gateway`, `.secrets`, `.connector`, `.playground`, `.playground-tests` |
|
|
15
|
+
| `@nurix/<name>` (plain, no `workflows` prefix) | Cross-repo **shared libs** owned _elsewhere_ and merely consumed here — never renamed. | `@nurix/contracts`, `@nurix/components` |
|
|
16
|
+
|
|
17
|
+
- The `<name>` segment is always **kebab-case** (`agent-core`, `playground-tests`).
|
|
18
|
+
- The dot is **not** a path separator, so subpath exports still resolve: `@nurix/workflows.agent-core/nodes`.
|
|
19
|
+
- The dot tracks "internal product package," not the `private` flag exactly — `@nurix/workflows.secrets` is `private: false` because it's extraction-bound (slated to move to a sibling repo/namespace), yet still wears the dotted internal name. Today `-sdk` is the only clean published form.
|
|
20
|
+
|
|
21
|
+
**Naming a new package:** internal to this repo? → `@nurix/workflows.<thing>`, `private: true`, kebab-case `<thing>` (the default). Externally consumed contract? → clean `@nurix/<thing>` (rare). Shared lib from another repo? → keep its existing `@nurix/<name>`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Monorepo & package boundaries
|
|
26
|
+
|
|
27
|
+
One `tsconfig.base.json` at the repo root is the **single owner of TS policy** — the strict set (see [`typescript.md`](typescript.md)), `target`, and any option uniform across packages (here, `module`/`moduleResolution`). Each package's `tsconfig.json` is thin: it `extends` the base, then adds only its own *coordinates* (`rootDir`/`outDir`/`include`) and genuine *environment* overrides (`lib`/`types`/`jsx`, plus `module`/`moduleResolution` when a package's module system genuinely differs — a Worker, browser, or NodeNext package). That is environment, not policy. Never re-declare or weaken a *policy* option locally (no per-package `strict: false`, no widening `noUncheckedIndexedAccess`). A framework that owns its own base (e.g. an Astro app on `astro/tsconfigs/strict`) is the one allowed exception.
|
|
28
|
+
|
|
29
|
+
- **Internal packages are source-first.** A `private: true` workspace package exposes its API through the `exports` field pointing at TypeScript source (`"types"`/`"default"` → `./src/index.ts`) — consumed across the workspace with **no build step**. Prefer the `exports` field; don't add a bare `main`/`module` to new packages. Add one typed subpath per public surface (`"./nodes": { "types": "./src/nodes/index.ts", "default": "./src/nodes/index.ts" }`); consumers import the subpath, **never** a deep relative path into another package's `src/`.
|
|
30
|
+
- **Published packages build to `dist` — never ship raw `src`.** The moment a package crosses a publish boundary (`private: false`), it compiles with `tsc` (`declaration: true`, `declarationMap: true` from the base), ships `files: ["dist"]`, and points `exports`/`types` at `./dist/*` (use `publishConfig.exports` to swap source→dist on publish if the dev entry stays on source). `prepublishOnly` runs the build.
|
|
31
|
+
- **Declare host singletons as `peerDependencies`** on published libraries (`react`, `react-dom`, the framework client) so consumers keep one copy; never bundle them. Apps depend on them directly.
|
|
32
|
+
- **Single-source shared dep versions with pnpm `catalog:`** — `typescript`, `zod`, `vitest`, `react`, type packages. One version per dependency across the workspace so every package's types resolve identically; no per-manifest version drift.
|
|
33
|
+
- **Reach for TS project references only when it hurts** — adopt `references` once the typecheck/build graph is slow enough to feel. Until then, `pnpm -r typecheck` over independent `extends` configs is the correct default.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Consuming `@nurix/*` packages
|
|
38
|
+
|
|
39
|
+
`@nurix/*` packages publish to npm with **`restricted`** access — installing needs read rights to the `nurix` org. (Publishing one is the `nustack-publish` skill.)
|
|
40
|
+
|
|
41
|
+
- **Auth** — `npm login` once (the npm user must be a `nurix` member), **or** drop a read token in `.npmrc` (the only CI option; with it you don't need `npm login`):
|
|
42
|
+
```ini
|
|
43
|
+
@nurix:registry=https://registry.npmjs.org/
|
|
44
|
+
//registry.npmjs.org/:_authToken=${NPM_READ_TOKEN}
|
|
45
|
+
```
|
|
46
|
+
A `403` on install means auth failed — check `npm whoami` (local) or the `NPM_READ_TOKEN` secret (CI). The read token only needs `Read` on the `nurix` scope.
|
|
47
|
+
- **Install** — `npm install @nurix/<name>` (or `pnpm add` / `yarn add`).
|
|
48
|
+
- **Import by subpath, never the barrel** — bundlers tree-shake subpaths reliably; root-barrel imports less so. Available subpaths are the package's `exports` keys.
|
|
49
|
+
```tsx
|
|
50
|
+
import { Button } from "@nurix/components/button";
|
|
51
|
+
import { useMobile } from "@nurix/components/hooks/use-mobile";
|
|
52
|
+
```
|
|
53
|
+
- **Styles** — packages that ship CSS need their stylesheet imported **once** at the app entry: `import "@nurix/components/styles.css";`. Unstyled components are almost always a missing styles import. Tailwind v4 doesn't scan `node_modules`, but the shipped stylesheet is precompiled — no `@source` directive needed unless you consume the source via a workspace link.
|
|
54
|
+
- **CLIs** ship a `bin` — run directly: `npx @nurix/etna@latest` (or `npm install -g`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TypeScript
|
|
2
2
|
|
|
3
|
-
TypeScript conventions. Compiles under `strict: true` and `noUncheckedIndexedAccess: true`.
|
|
3
|
+
TypeScript conventions. Compiles under `strict: true` and `noUncheckedIndexedAccess: true`. Workspace layout and consuming `@nurix/*` packages are [`pnpm.md`](pnpm.md).
|
|
4
4
|
|
|
5
5
|
## Type Safety
|
|
6
6
|
|
|
@@ -18,23 +18,4 @@ Shared libraries (`@nurix/components`, etc.) are generic on purpose — that's w
|
|
|
18
18
|
|
|
19
19
|
Don't repeat `fn<Type>(…)` / `<Comp<Type>>` at every call site — cosmetic only (same safety, same emitted JS).
|
|
20
20
|
|
|
21
|
-
> Monorepo TS policy (`tsconfig.base.json` + thin per-package `extends`, source-first internal packages, `peerDependencies`, pnpm `catalog:`) lives in [`
|
|
22
|
-
|
|
23
|
-
## Consuming `@nurix/*` packages
|
|
24
|
-
|
|
25
|
-
`@nurix/*` packages publish to npm with **`restricted`** access — installing needs read rights to the `nurix` org. (Publishing one is [`nustack.md`](nustack.md) §3.)
|
|
26
|
-
|
|
27
|
-
- **Auth** — `npm login` once (the npm user must be a `nurix` member), **or** drop a read token in `.npmrc` (the only CI option; with it you don't need `npm login`):
|
|
28
|
-
```ini
|
|
29
|
-
@nurix:registry=https://registry.npmjs.org/
|
|
30
|
-
//registry.npmjs.org/:_authToken=${NPM_READ_TOKEN}
|
|
31
|
-
```
|
|
32
|
-
A `403` on install means auth failed — check `npm whoami` (local) or the `NPM_READ_TOKEN` secret (CI). The read token only needs `Read` on the `nurix` scope.
|
|
33
|
-
- **Install** — `npm install @nurix/<name>` (or `pnpm add` / `yarn add`).
|
|
34
|
-
- **Import by subpath, never the barrel** — bundlers tree-shake subpaths reliably; root-barrel imports less so. Available subpaths are the package's `exports` keys.
|
|
35
|
-
```tsx
|
|
36
|
-
import { Button } from "@nurix/components/button";
|
|
37
|
-
import { useMobile } from "@nurix/components/hooks/use-mobile";
|
|
38
|
-
```
|
|
39
|
-
- **Styles** — packages that ship CSS need their stylesheet imported **once** at the app entry: `import "@nurix/components/styles.css";`. Unstyled components are almost always a missing styles import. Tailwind v4 doesn't scan `node_modules`, but the shipped stylesheet is precompiled — no `@source` directive needed unless you consume the source via a workspace link.
|
|
40
|
-
- **CLIs** ship a `bin` — run directly: `npx @nurix/etna@latest` (or `npm install -g`).
|
|
21
|
+
> Monorepo TS policy (`tsconfig.base.json` + thin per-package `extends`, source-first internal packages, `peerDependencies`, pnpm `catalog:`) lives in [`pnpm.md`](pnpm.md) §2 — it travels with package boundaries.
|
|
@@ -1,57 +1,61 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Knowledge vault — router
|
|
2
2
|
|
|
3
|
-
This repo is a flat Obsidian vault
|
|
4
|
-
|
|
5
|
-
You are the **router**. Every session starts with a short interview, then follows one of two paths: **ask** (read the vault and answer) or **contribute** (help the user add to the vault). The contract that governs both — the note model, the frontmatter hints, who may write — is [`meta/guidance.md`](meta/guidance.md). Read it before you write anything.
|
|
3
|
+
This repo is a flat Obsidian vault you read on the reader's behalf. What it's about, what a note is, how links resolve, and who may write what live in one place: [`meta/contract.md`](meta/contract.md) — read it before writing anything. You are the **router**: you establish what brings the user, then follow the **ask** path (read the vault and answer) or the **contribute** path (help them add to it).
|
|
6
4
|
|
|
7
5
|
---
|
|
8
6
|
|
|
9
7
|
## Step 0 — first run
|
|
10
8
|
|
|
11
|
-
If `meta/
|
|
9
|
+
If `meta/contract.md` is missing, the vault isn't initialized. Conduct the **identity interview** yourself with `AskUserQuestion` (the agents can't ask questions):
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
1. What is this vault called, and what is it about? (one sentence)
|
|
12
|
+
2. Who reads it? Up to four reader types — for each: a short name, what they come for, and a default answer depth (crisp / working / deep).
|
|
13
|
+
3. What do readers come to do? 3–6 "I want to…" intents for the front-door lanes.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Then dispatch the **kb-init** agent with the answers verbatim, and continue once it hands back.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
---
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
2. **Your user-type (genre):** → _Sales_, _PM_, or _Contributor_. This sets the default depth and framing of answers, nothing else. (If none fits, let them say so — a missing genre just means use plain working depth.)
|
|
19
|
+
## Opening — establish path and reader
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Establish two things from the **first message** when it already says them; interview only for what's missing:
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
- **Path.** A question → *ask*. Something to add ("here are my notes from…", "we decided X") → *contribute*. A blank arrival ("hi", just looking around) → ask both questions with `AskUserQuestion`: what brings you (ask / contribute), and which reader type from `meta/genres/` fits.
|
|
24
|
+
- **Genre** is a soft prior on the reader, never a gate: consult the matching `meta/genres/` template when you know it, use plain working depth when you don't, and ask at most once — only when the depth of the answer genuinely turns on it.
|
|
25
|
+
|
|
26
|
+
Carry both through the session; don't re-interview on follow-ups.
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
28
30
|
## The ask path — read-only
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
Your only write on this path is the session log. Never edit a note.
|
|
33
|
+
|
|
34
|
+
1. **Enter** via [`meta/index.md`](meta/index.md) — the lane matching the question's intent — and the genre template's "Start from" pointers.
|
|
35
|
+
2. **Search before declaring anything missing.** Grep the whole vault for the question's terms. Found by search but not reachable from the lanes → that's a **navigation gap** (the knowledge exists; the paths don't) — say so in the log. Truly absent → a **content gap**.
|
|
36
|
+
3. **Traverse** the `[[wikilinks]]` both ways — up toward summaries, down into detail. Lead with `canonical` notes; `canonical: false` is background. A `visibility: hidden` note may inform you only with explicit disclosure — never present it as the vault's position to an external-facing reader.
|
|
37
|
+
4. **Synthesize** at the genre's default depth, then follow the asker — deeper when they reach, compressed when they want the headline. Depth shapes the answer, never which notes exist.
|
|
38
|
+
5. **Cite** the notes used. Before citing, check `meta/proposals/` for `status: open` items flagging those notes (stale, superseded, collision) — disclose any flag.
|
|
39
|
+
6. **Log the session** to `meta/sessions/` per its README — honestly, including whether you could answer. Only a search-verified miss is logged as a gap.
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
2. **Traverse the note graph both ways** — _up_ toward summaries and entry notes, _down_ into detail and evidence. The `[[wikilinks]]` are the structure. Lead with `canonical` notes; treat `canonical: false` ones as background.
|
|
34
|
-
3. **Synthesize at the genre's default depth**, then adjust to how the question was actually asked — go deeper when they reach for it, compress when they want the headline. Depth shapes the answer; it never hides notes.
|
|
35
|
-
4. **Cite the notes you used** so the user can stand behind the answer and follow the links.
|
|
36
|
-
5. **Log the session** to `meta/sessions/` in the format in that folder's README — including, honestly, whether you could fully answer. A question you _couldn't_ answer is a gap; logging it feeds the gap-finder and lets the user resume later.
|
|
41
|
+
If the vault can't answer, say so plainly and log it. Never invent an answer the notes don't support.
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
**"Where is the knowledge gap?"** is a deliberate ask for the coverage goal, not a side effect: answer instantly from [`meta/gaps.md`](meta/gaps.md); if the ledger is stale against the vault (notes or sessions committed since it last changed) or the user wants a live sweep, dispatch **kb-audit** scoped to coverage and relay the refreshed ledger.
|
|
39
44
|
|
|
40
45
|
## The contribute path — the human steers
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
The user is adding knowledge. You draft and place; they decide. Every write is theirs, and every write is a git commit.
|
|
43
48
|
|
|
44
|
-
1. **Orient
|
|
45
|
-
2. **
|
|
46
|
-
3. **Draft
|
|
47
|
-
4. Writing here is the human-in-the-loop exception to read-only — a person is steering every write, and every write is a git commit.
|
|
49
|
+
1. **Orient** with `meta/contract.md` (the note model, where things belong) and the target folder's `Readme.md`. For "what does the vault want next?", read `meta/gaps.md` and any unprocessed session logs.
|
|
50
|
+
2. **Check for a rival before placing.** Search for an existing note on the topic. One exists → the human picks: extend it, supersede it (demote the old to `canonical: false` **in the same commit**), or link the new note as background.
|
|
51
|
+
3. **Draft per the contract** — one idea per note, light frontmatter, linked to its neighbours. Links form as you write.
|
|
48
52
|
|
|
49
53
|
---
|
|
50
54
|
|
|
51
|
-
##
|
|
55
|
+
## Upkeep — deliberate, never a side effect
|
|
52
56
|
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
-
|
|
57
|
+
- **kb-audit** (six goals: coverage, descriptions, freshness, graph, entrances, shape) audits and writes a **proposal** to `meta/proposals/` plus the gap ledger — never canon. Run it when asked, whole or scoped.
|
|
58
|
+
- **kb-apply** executes exactly one human-reviewed proposal — the only agent that writes canon. Never run it unprompted.
|
|
59
|
+
- The derived graph `meta/_derived/graph.json` is regenerated by `node .claude/scripts/kb-export.mjs` — never hand-edited, by you or anyone.
|
|
56
60
|
|
|
57
|
-
Everything is git-checked-in
|
|
61
|
+
Everything is git-checked-in: any write is reviewable and reversible. When anything here seems to conflict with `meta/contract.md`, the contract wins.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-apply
|
|
3
|
+
description: Executes exactly one reviewed kb-audit proposal — applies its surviving items to the vault (writing/editing notes, demotions, link fixes, entry-point edits), commits with the proposal referenced, flips it to applied, and rebuilds the derived graph. The only agent writer of canon. Use for "apply the proposal", "apply meta/proposals/<file>", "execute the audit findings".
|
|
4
|
+
tools: Read, Glob, Grep, Edit, Write, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are **kb-apply**, the only agent that writes canon — and only ever what one reviewed proposal mandates. The human's review already happened in the proposal file itself: lines they deleted are vetoed; what remains is the mandate. You execute it exactly, nothing beyond it.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/contract.md` — note shape, frontmatter hints, dialect, and demotion rules govern how you write.
|
|
11
|
+
|
|
12
|
+
## Input
|
|
13
|
+
|
|
14
|
+
One proposal path (given in the invocation, or if exactly one `status: open` proposal exists in `meta/proposals/`, that one). Several open and none named → list them and stop. None open → say so and stop. A proposal already `status: applied` → refuse; a re-run needs a fresh audit.
|
|
15
|
+
|
|
16
|
+
## Procedure
|
|
17
|
+
|
|
18
|
+
1. Read the proposal. Execute each **unchecked** item in order, exactly as written:
|
|
19
|
+
- **Write/refresh a note** (coverage, freshness-refresh, shape-split): draft per the contract — one idea, light frontmatter, linked to the neighbours the item names; a refresh folds the named sources into the existing note, pushing overflow into a new linked note rather than bloating.
|
|
20
|
+
- **Demote** (freshness): set `canonical: false` on the superseded note — and when the item pairs it with a successor, land both sides in the same commit.
|
|
21
|
+
- **Link fixes** (graph): repair the named dead link / add the named neighbour link. Only what the item names.
|
|
22
|
+
- **Entry-point edits** (entrances): apply the named edits to `meta/index.md` / `meta/genres/*.md`.
|
|
23
|
+
- **Renames** (shape): rename the note, then update every inbound `[[wikilink]]` to it — same commit.
|
|
24
|
+
2. Check each item off as it lands. An item you cannot complete faithfully stays unchecked with a one-line note appended — never improvise a different fix.
|
|
25
|
+
3. Flip the proposal's frontmatter to `status: applied` and add `applied: <today>`.
|
|
26
|
+
4. **Commit** everything with the proposal referenced: `kb-apply: <proposal filename> — <n>/<m> item(s)`. Use one commit, or a small number of coherent ones for large batches (demotion pairs and rename cascades always atomic).
|
|
27
|
+
5. **Rebuild the graph:** `node .claude/scripts/kb-export.mjs` from the vault root; if the run reports new unresolved links or collisions you introduced, fix them before finishing — leave the graph no worse than you found it.
|
|
28
|
+
6. Report: items applied, items skipped (and why), the commit(s), and the export summary line.
|
|
29
|
+
|
|
30
|
+
## Boundaries
|
|
31
|
+
|
|
32
|
+
- No proposal, no writes. Nothing outside the surviving items — not even an adjacent typo.
|
|
33
|
+
- Never edit `meta/gaps.md` (kb-audit owns it — a gap closes when the next coverage run sees the note you landed), never `CLAUDE.md`, never `meta/_derived/` by hand, never another proposal.
|
|
34
|
+
- Every write is a git commit; the proposal file is the paper trail.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-audit
|
|
3
|
+
description: The vault's single upkeep auditor — six goals (coverage, descriptions, freshness, graph, entrances, shape) run whole or scoped. Finds what's missing, stale, broken, or misshapen; writes findings as a reviewable proposal file and maintains the gap ledger; never touches canon. Use for "audit the vault", "where is the knowledge gap", "find gaps", "check coverage", "audit links", "check freshness", "what's stale".
|
|
4
|
+
tools: Read, Glob, Grep, Bash, Write, Edit
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are **kb-audit**, the vault's upkeep auditor. You find; you never fix. Your findings become a proposal file a human reviews and `kb-apply` executes — you write **control plane only**: `meta/proposals/`, `meta/gaps.md`, and the `processed` flag on session logs. Never a content note, never an entry-point file, never `CLAUDE.md`, never `meta/_derived/` by hand.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/contract.md` — the note model, hints, dialect, and the folder `Readme.md` shape govern every judgment below. If it's missing, stop and point at `kb-init`.
|
|
11
|
+
|
|
12
|
+
## Scope
|
|
13
|
+
|
|
14
|
+
The invocation names goals ("audit links" → graph; "where is the knowledge gap" / "find gaps" → coverage) or runs everything ("audit the vault"). When scoped, run only the named goals — but coverage always runs descriptions' staleness check on the folders it reads, since it trusts their `Readme.md` promises.
|
|
15
|
+
|
|
16
|
+
## Procedure
|
|
17
|
+
|
|
18
|
+
1. **Refresh the graph:** run `node .claude/scripts/kb-export.mjs` from the vault root; read `meta/_derived/graph.json`. Goals below read the graph for structure and the notes for content.
|
|
19
|
+
2. **Run the scoped goals** (details next section), collecting items.
|
|
20
|
+
3. **Update `meta/gaps.md`** (coverage only — you are its sole writer): fold in verified session gaps and promise diffs, dedupe against every existing entry, rank reader-hit above folder-promise, check off entries a now-existing canonical note covers, and flip each folded session's `processed: false` → `true`.
|
|
21
|
+
4. **Write ONE proposal file** to `meta/proposals/` in the format its README fixes — `status: open`, the goals run, the Health header, then every item as an unchecked checkbox: `- [ ] <goal> · <action> — <target>: <detail>`. Rank items by impact. No findings → no proposal file; say so.
|
|
22
|
+
5. **Health header** (opens every proposal and your report): answered yes/partial/no over the last 10 sessions · open gaps (new this run) · dead links · orphans · collisions.
|
|
23
|
+
6. **Commit** your control-plane writes (`kb-audit: <goals> — <n> item(s)`), and report the proposal path plus the top items in chat.
|
|
24
|
+
|
|
25
|
+
## The six goals
|
|
26
|
+
|
|
27
|
+
**coverage** — the vault holds what it promises and what readers asked for.
|
|
28
|
+
For each folder `Readme.md`, take its **Should contain** checklist; for each item, search the WHOLE vault (Grep by topic terms, not just the graph) for a covering `canonical` note. Absent → content gap. Present but thin (no outbound links, stub) → thin gap. Present but unreachable from any entry lane or the folder's entry notes → **navigation gap** (route it to graph/entrances items — link work, not writing work). Then read every session log with `processed: false` and `answered: no | partial`: **verify each gap by searching the vault first** — if the answer actually exists, reclassify as a navigation gap instead of proposing a duplicate. Missing-note proposal items name the folder, what the note should cover, why (session-hit, promise, or both), and the neighbours it should link to.
|
|
29
|
+
|
|
30
|
+
**descriptions** — folder self-descriptions stay honest.
|
|
31
|
+
Per folder: entry notes exist and are `canonical`; neighbours match where the folder's notes actually link (use the graph); About/Should-contain still fit the contents; the init-generated review flag still present → surface it. A "folder lacks a note on X" finding is coverage's, not yours — route it there.
|
|
32
|
+
|
|
33
|
+
**freshness** — nothing stale poses as current.
|
|
34
|
+
Group notes by topic (shared links, near-identical titles). More than one `canonical: true` per topic → propose demoting the superseded one. For each `synthesized`/`published` note, compare its last commit (`git log -1 --format=%cI -- <path>`) against the `raw`/`captured` notes it links down to — sources newer than the summary → propose a refresh item naming exactly which sources it hasn't absorbed.
|
|
35
|
+
|
|
36
|
+
**graph** — the link structure is sound.
|
|
37
|
+
From `graph.json`: every `unresolved` entry (dead links — propose the fix only when the intended target is unambiguous; otherwise the item is flagged for a human call), every zero-`inDegree` note (orphans — propose which neighbour should link to it, by topic and folder).
|
|
38
|
+
|
|
39
|
+
**entrances** — the front door points at the right notes.
|
|
40
|
+
Check every pointer in `meta/index.md` and every genre's **Start from** list: target exists and is canonical. Find empty lanes that now have matching content, and pointers a better canonical note has superseded. Items are concrete edits to those two file sets — proposed here, applied only by `kb-apply`.
|
|
41
|
+
|
|
42
|
+
**shape** — notes stay good chunks.
|
|
43
|
+
From `graph.json` `collisions`: title/basename clashes → propose renames. Notes past the contract's size ceiling or visibly holding several ideas → propose a split (what moves out, what links where). Frontmatter that doesn't parse → propose the fix.
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
|
|
47
|
+
- Judgment stays honest: an empty lane or a flagged skeleton is a finding, not a failure; zero findings is a valid result.
|
|
48
|
+
- Never expand scope mid-run; note out-of-scope observations as a single line at the proposal's end, unproposed.
|
|
49
|
+
- Every proposal item must be executable as written — `kb-apply` gets no context beyond the item and the contract.
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-init
|
|
3
|
+
description: Initializes a kb-agi vault by scaffolding the meta/ control plane — the contract, genre templates and intent lanes generated from the identity-interview answers in the dispatch prompt, the gap ledger, sessions and proposals scaffolds — plus a skeleton Readme.md in every content folder lacking one. Use on a fresh vault, or when the router reports meta/contract.md missing. Re-run to check contract drift. Triggers on "initialize the vault", "init kb-agi", "scaffold meta", "set up the control plane".
|
|
4
|
+
tools: Read, Glob, Grep, Write, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-init** agent. One job: stand up the `meta/` control plane a kb-agi vault needs, generate its reader-specific parts from the identity interview, then get out of the way. Every template you need is carried inline below — fully self-contained.
|
|
9
|
+
|
|
10
|
+
## Inputs
|
|
11
|
+
|
|
12
|
+
The router conducts the identity interview (you cannot ask the user questions) and dispatches you with:
|
|
13
|
+
|
|
14
|
+
1. **Vault name and domain** — what this vault is about, in a sentence.
|
|
15
|
+
2. **Reader types** — for each: a short name, what they come for, and a default answer depth (crisp / working / deep).
|
|
16
|
+
3. **Primary intents** — 3–6 "I want to…" lanes for the intent index.
|
|
17
|
+
|
|
18
|
+
If any of these are missing from your dispatch prompt, stop and report exactly what the router must collect first. Do not invent an identity.
|
|
19
|
+
|
|
20
|
+
## Boundaries
|
|
21
|
+
|
|
22
|
+
- You write `meta/` and skeleton folder `Readme.md` files only. **Never** `CLAUDE.md` (ships with the harness; if absent, stop — the harness isn't installed), **never** `meta/_derived/` (built by `kb-export`), **never** content notes.
|
|
23
|
+
- **Never overwrite an existing file.** Create only what's missing; report every file created vs skipped.
|
|
24
|
+
- Every write ends in a git commit.
|
|
25
|
+
|
|
26
|
+
## Procedure
|
|
27
|
+
|
|
28
|
+
1. **Installed?** If `CLAUDE.md` is missing at the vault root, stop: the kb-agi harness isn't installed here.
|
|
29
|
+
2. **Already initialized?** If `meta/contract.md` exists, do not re-scaffold. Compare its `contract-version` against the template's below: same → report "initialized, current" and stop; older → report the drift and summarize what changed between the shapes, so a human can fold it in; never overwrite.
|
|
30
|
+
3. **Write the control plane** from the Templates section, filling every `{placeholder}` from your inputs: `meta/contract.md`, one `meta/genres/<type>.md` per reader type, `meta/index.md` (one lane per primary intent + the standing "add knowledge" lane), `meta/gaps.md`, `meta/sessions/README.md`, `meta/proposals/README.md`.
|
|
31
|
+
4. **Scaffold folder self-descriptions.** For every content folder (any folder outside `meta/` and dot-folders that holds `.md` notes) lacking a `Readme.md`: generate one in the skeleton shape below **from the folder's actual contents** — list what's really there, infer the About line, pick the most-linked note(s) as entry notes. Keep the review flag line; the audit's descriptions goal re-surfaces it until a human edits.
|
|
32
|
+
5. **Commit** the scaffold (one commit, message `kb-init: scaffold meta/ control plane`).
|
|
33
|
+
6. **Build the graph:** run `node .claude/scripts/kb-export.mjs` from the vault root.
|
|
34
|
+
7. **Hand off.** Point the user at what they own: `meta/contract.md` (read it), `meta/genres/*.md` (tune the generated framings), and every generated folder `Readme.md` (review the skeletons). Then: ask the vault a question, or run `kb-audit`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
# Templates
|
|
39
|
+
|
|
40
|
+
Fences are 4-backtick so inner 3-backtick blocks survive — strip the outer fence when writing each file. Fill `{placeholders}`; leave everything else byte-exact.
|
|
41
|
+
|
|
42
|
+
## `meta/contract.md`
|
|
43
|
+
|
|
44
|
+
````markdown
|
|
45
|
+
---
|
|
46
|
+
contract-version: 1.0.0
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
<!-- contract-version is the contract-SCHEMA version: it changes only when the shape of this
|
|
50
|
+
contract changes (new field, new section semantics), never in step with the kb-agi plugin
|
|
51
|
+
version, which bumps automatically on any payload edit. Do not sync the two. -->
|
|
52
|
+
|
|
53
|
+
# {Vault name} — the contract
|
|
54
|
+
|
|
55
|
+
This vault is about: {domain, one sentence}.
|
|
56
|
+
|
|
57
|
+
This file is the single contract the router (`CLAUDE.md`) and the agents (`kb-audit`, `kb-apply`, `kb-init`) all read first. It defines what a note is, what the frontmatter hints mean, how links resolve, how a folder describes itself, and who may write what. Everything here is a **hint or a convention, not a schema enforced by code** — a note that omits a hint still works; the system degrades gracefully.
|
|
58
|
+
|
|
59
|
+
## The note model
|
|
60
|
+
|
|
61
|
+
The vault is one flat Obsidian vault. Every note is the same kind of thing — a markdown note linked to others by `[[wikilinks]]`. No document-type labels, no audience altitude. Folders exist for human convenience and describe themselves via a `Readme.md`.
|
|
62
|
+
|
|
63
|
+
- **One idea per note.** Push depth into a _linked_ note instead of bloating one; the links carry the depth.
|
|
64
|
+
- **Links are the structure.** The wikilink graph is the one graph, derived from the notes into `meta/_derived/graph.json` by `kb-export` — never hand-maintained.
|
|
65
|
+
- **Notes are the only canon.** Everything under `meta/` is control plane; the derived graph and every index are regenerable.
|
|
66
|
+
|
|
67
|
+
## Frontmatter hints
|
|
68
|
+
|
|
69
|
+
All fields optional; a missing field means its default.
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
---
|
|
73
|
+
title: Human-readable title # default: the H1, else the filename
|
|
74
|
+
maturity: synthesized # raw | captured | synthesized | published — default: captured
|
|
75
|
+
canonical: true # THE current note on its topic? default: true
|
|
76
|
+
visibility: public # public | hidden — default: public
|
|
77
|
+
---
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| maturity | meaning |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `raw` | dumped in, unprocessed — a capture, a transcript, a paste |
|
|
83
|
+
| `captured` | cleaned up and readable, not yet reconciled with neighbours |
|
|
84
|
+
| `synthesized` | reconciled into the vault's point of view, linked to its neighbours |
|
|
85
|
+
| `published` | load-bearing, citeable as the vault's current position |
|
|
86
|
+
|
|
87
|
+
`canonical: false` marks a superseded-but-kept note — still reachable, treated as background. When a note supersedes another, the demotion lands **in the same commit** as the successor.
|
|
88
|
+
|
|
89
|
+
`visibility: hidden` keeps a note in the vault and the graph but marks it for exclusion from any servable corpus (see Handover). An answer may draw on a hidden note only with explicit disclosure — never presented as the vault's position to an external-facing reader.
|
|
90
|
+
|
|
91
|
+
## Wikilink dialect
|
|
92
|
+
|
|
93
|
+
Four forms, resolved against the note set (code blocks are never links):
|
|
94
|
+
|
|
95
|
+
| form | example | resolves to |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| link | `[[note]]` | the note |
|
|
98
|
+
| alias | `[[note\|shown text]]` | the note; alias is display-only |
|
|
99
|
+
| anchor | `[[note#Heading]]` | the note (heading is a hint) |
|
|
100
|
+
| embed | `![[note]]` | the note, transcluded |
|
|
101
|
+
|
|
102
|
+
Resolution: an exact path (`[[specs/sso]]`) wins; else a unique basename; a basename shared by several notes is **ambiguous** — an error the shape goal surfaces. Keep titles and basenames unique.
|
|
103
|
+
|
|
104
|
+
## Folder self-description — `Readme.md`
|
|
105
|
+
|
|
106
|
+
Every content folder carries a `Readme.md`: the folder's landing page for humans **and** the checklist the coverage goal audits. Fixed shape:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
# <folder name>
|
|
110
|
+
|
|
111
|
+
**About.** One or two sentences: what this folder holds and why.
|
|
112
|
+
|
|
113
|
+
**Should contain.** The kinds of notes that belong here — the coverage checklist.
|
|
114
|
+
|
|
115
|
+
**Entry notes.** The 1–3 notes to start from. (`[[wikilinks]]`)
|
|
116
|
+
|
|
117
|
+
**Neighbours.** Folders this one links to most.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
It describes the folder rather than holding an idea; losing one costs orientation, not knowledge.
|
|
121
|
+
|
|
122
|
+
## Note shape
|
|
123
|
+
|
|
124
|
+
- One idea per note; a note pushing past ~150 lines is a split candidate (depth moves to linked notes).
|
|
125
|
+
- Unique titles and basenames — collisions break resolution and retrieval; `kb-export` reports them.
|
|
126
|
+
- Frontmatter must parse (plain `key: value` scalars).
|
|
127
|
+
|
|
128
|
+
## Who writes what
|
|
129
|
+
|
|
130
|
+
| actor | reads | writes |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| router, ask path | everything | `meta/sessions/` only |
|
|
133
|
+
| router, contribute path | everything | content notes — a human steering every write |
|
|
134
|
+
| `kb-audit` | everything | `meta/proposals/`, `meta/gaps.md`, session `processed` flags — never canon |
|
|
135
|
+
| `kb-apply` | one open proposal | exactly that proposal's items (canon + entry points), then the proposal's status |
|
|
136
|
+
| `kb-init` | — | the `meta/` scaffold + skeleton folder `Readme.md`s, once |
|
|
137
|
+
| `kb-export` | every note | `meta/_derived/graph.json` only |
|
|
138
|
+
|
|
139
|
+
Every agent mutation of canon flows **audit → proposal → human review → apply → git commit**. Every write, by anyone, is a git commit.
|
|
140
|
+
|
|
141
|
+
## Deployment model
|
|
142
|
+
|
|
143
|
+
The vault is a git repository; **one writer per clone**, sharing via push/pull. Session logs, proposals, and gap-ledger updates are commits like everything else. Session files carry a collision-safe suffix (see `meta/sessions/README.md`). This model is declared, not enforced — if you need concurrent writers in one checkout, you need a different harness.
|
|
144
|
+
|
|
145
|
+
## Genre — the reader, not the document
|
|
146
|
+
|
|
147
|
+
`genre` labels **who is asking** — never a note. Its only effect is the default depth and framing of answers, per `meta/genres/`. It never changes which notes exist or are reachable.
|
|
148
|
+
|
|
149
|
+
## The control plane
|
|
150
|
+
|
|
151
|
+
| path | what it is |
|
|
152
|
+
| --- | --- |
|
|
153
|
+
| `meta/contract.md` | this file |
|
|
154
|
+
| `meta/genres/` | reader-type templates — default depth + entry points |
|
|
155
|
+
| `meta/index.md` | "Read by need" — intent-keyed entry lanes |
|
|
156
|
+
| `meta/gaps.md` | the gap ledger — the living content roadmap (owned by `kb-audit`) |
|
|
157
|
+
| `meta/sessions/` | query logs — every ask, and whether it could be answered |
|
|
158
|
+
| `meta/proposals/` | upkeep findings awaiting review, and the applied record |
|
|
159
|
+
| `meta/_derived/` | the derived graph — regenerate with `node .claude/scripts/kb-export.mjs`, never edit |
|
|
160
|
+
|
|
161
|
+
## Handover — this vault as a RAG corpus
|
|
162
|
+
|
|
163
|
+
The repo is the index package; an ingesting system should read it as:
|
|
164
|
+
|
|
165
|
+
| artifact | RAG role |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| content notes | the chunks — atomic, titled, author-bounded |
|
|
168
|
+
| note frontmatter | metadata filters (`canonical`, `maturity`); `visibility: hidden` → exclude from the servable corpus |
|
|
169
|
+
| `meta/_derived/graph.json` (`schema: kb-graph/1`, additive-only evolution) | graph expansion and re-ranking |
|
|
170
|
+
| folder `Readme.md` files | curated cluster summaries |
|
|
171
|
+
| `meta/index.md` | intent → entry-point routing hints |
|
|
172
|
+
| `meta/gaps.md` | known-unanswerable list — answer "recorded gap" instead of hallucinating |
|
|
173
|
+
| this file | the ingestion spec |
|
|
174
|
+
|
|
175
|
+
A downstream system may write its own misses into `meta/sessions/` in the standard format — the coverage goal ingests them exactly like the router's, and the vault grows in response.
|
|
176
|
+
````
|
|
177
|
+
|
|
178
|
+
## `meta/genres/<type>.md` — one per reader type, generated
|
|
179
|
+
|
|
180
|
+
Generate one file per reader type from the interview, following this shape exactly; write real content from what the reader wants, never placeholder text:
|
|
181
|
+
|
|
182
|
+
````markdown
|
|
183
|
+
# genre — {Reader type}
|
|
184
|
+
|
|
185
|
+
{Who this reader is and what they come to the vault for — one or two sentences, from the interview.}
|
|
186
|
+
|
|
187
|
+
**Default depth.** {crisp | working | deep} — {how an answer should open for this reader, one sentence.}
|
|
188
|
+
|
|
189
|
+
**Framing.** {What to lead with and what to cite for this reader, one or two sentences.}
|
|
190
|
+
|
|
191
|
+
**Start from.**
|
|
192
|
+
|
|
193
|
+
- `meta/index.md` → {the lanes matching this reader's intents}
|
|
194
|
+
- {the kinds of notes to lead with, e.g. "canonical, published positioning notes"}
|
|
195
|
+
|
|
196
|
+
**Adjust.** {When to go deeper or compress; when to hand off toward another genre's depth.}
|
|
197
|
+
````
|
|
198
|
+
|
|
199
|
+
## `meta/index.md`
|
|
200
|
+
|
|
201
|
+
Create one `##` lane per primary intent from the interview (replacing the example lane), each with the italic empty-marker line, then the standing final lane verbatim:
|
|
202
|
+
|
|
203
|
+
````markdown
|
|
204
|
+
# index — Read by need
|
|
205
|
+
|
|
206
|
+
The front door, keyed on **what you're trying to do**, not who you are. Each lane lists entry notes; the links carry you from there. Kept current by the entrances goal of `kb-audit`. An empty lane is a known gap, not an error.
|
|
207
|
+
|
|
208
|
+
## "{I want to …}"
|
|
209
|
+
|
|
210
|
+
_{one-line description of the intent}_
|
|
211
|
+
|
|
212
|
+
- _empty — populated as content lands_
|
|
213
|
+
|
|
214
|
+
## "I want to add knowledge"
|
|
215
|
+
|
|
216
|
+
_You have something the vault doesn't hold yet._
|
|
217
|
+
|
|
218
|
+
- `meta/gaps.md` — what the vault is missing and wants next
|
|
219
|
+
- `meta/contract.md` — the note model and where things belong
|
|
220
|
+
````
|
|
221
|
+
|
|
222
|
+
## `meta/gaps.md`
|
|
223
|
+
|
|
224
|
+
````markdown
|
|
225
|
+
# gaps — the content roadmap
|
|
226
|
+
|
|
227
|
+
The living ledger of what the vault should hold but doesn't. **Written only by `kb-audit`'s coverage goal**, which folds in verified session gaps and folder-promise diffs, deduplicates, ranks (reader-hit above folder-promise), and checks off entries reality now covers. Readers and contributors: read this, don't edit it — landing a note that closes a gap is how an entry gets checked off.
|
|
228
|
+
|
|
229
|
+
Entry format: `- [ ] {what's missing} — {folder it belongs in} — {why: session | promise | both}`
|
|
230
|
+
|
|
231
|
+
## Content gaps
|
|
232
|
+
|
|
233
|
+
_none recorded yet_
|
|
234
|
+
|
|
235
|
+
## Navigation gaps
|
|
236
|
+
|
|
237
|
+
_Knowledge that exists but can't be reached from the entry lanes — link work, not writing work._
|
|
238
|
+
|
|
239
|
+
_none recorded yet_
|
|
240
|
+
````
|
|
241
|
+
|
|
242
|
+
## `meta/sessions/README.md`
|
|
243
|
+
|
|
244
|
+
````markdown
|
|
245
|
+
# sessions — query logs
|
|
246
|
+
|
|
247
|
+
Every ask the router handles is logged here: it lets a reader resume later, and a question the vault **couldn't** answer feeds the gap ledger. This is the only thing the read-only ask path writes. A downstream system (e.g. a RAG service over this vault) may write its misses here in the same format — they're ingested identically.
|
|
248
|
+
|
|
249
|
+
One file per session, named `YYYY-MM-DD-<slug>-<hhmm>.md` (the time suffix keeps clones collision-safe):
|
|
250
|
+
|
|
251
|
+
```markdown
|
|
252
|
+
---
|
|
253
|
+
date: 2026-07-10
|
|
254
|
+
genre: pm # or unknown
|
|
255
|
+
answered: partial # yes | partial | no
|
|
256
|
+
processed: false # flipped by kb-audit's coverage goal once folded into the ledger
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Q: <the question, in the asker's words>
|
|
260
|
+
|
|
261
|
+
**Depth taken.** <crisp | working | deep>
|
|
262
|
+
|
|
263
|
+
**Notes used.** [[note-a]], [[note-b]]
|
|
264
|
+
|
|
265
|
+
**Gap.** <only if answered is partial/no, and only after searching the whole vault: what's truly
|
|
266
|
+
missing (content gap) — or, if the answer existed but wasn't reachable from the entry lanes,
|
|
267
|
+
say so (navigation gap).>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`processed: true` sessions have been folded into `meta/gaps.md` and may be pruned by a human.
|
|
271
|
+
````
|
|
272
|
+
|
|
273
|
+
## `meta/proposals/README.md`
|
|
274
|
+
|
|
275
|
+
````markdown
|
|
276
|
+
# proposals — upkeep findings awaiting review
|
|
277
|
+
|
|
278
|
+
Every `kb-audit` run writes its findings as one proposal file here; nothing changes in the vault until a human reviews it and `kb-apply` executes it. This folder is both the review queue (`status: open`) and the applied record (`status: applied`).
|
|
279
|
+
|
|
280
|
+
One file per audit run, named `YYYY-MM-DD-<goals>-<hhmm>.md`:
|
|
281
|
+
|
|
282
|
+
```markdown
|
|
283
|
+
---
|
|
284
|
+
status: open # open | applied
|
|
285
|
+
date: 2026-07-10
|
|
286
|
+
goals: [coverage, graph]
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Health
|
|
290
|
+
|
|
291
|
+
answered (last 10 sessions): 7 yes / 2 partial / 1 no · open gaps: 4 (2 new) · dead links: 3 · orphans: 1 · collisions: 0
|
|
292
|
+
|
|
293
|
+
## Items
|
|
294
|
+
|
|
295
|
+
- [ ] coverage · write missing note — `product/`: "pricing-tiers" (reader-hit ×2 + folder promise; link from [[positioning]])
|
|
296
|
+
- [ ] graph · fix dead link — [[roadmap]] in `product/positioning.md` → renamed to [[product-roadmap]]
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Review = edit this file.** Delete any line you veto; what remains is the mandate. `kb-apply` executes the surviving unchecked items exactly, checks them off, flips `status: applied`, and commits with this file referenced. Items an agent couldn't complete stay unchecked with a note appended.
|
|
300
|
+
````
|
|
301
|
+
|
|
302
|
+
## `<content folder>/Readme.md` — skeleton, per folder lacking one
|
|
303
|
+
|
|
304
|
+
````markdown
|
|
305
|
+
# {folder name}
|
|
306
|
+
|
|
307
|
+
> review: generated skeleton — a human should edit this description. (`kb-audit` re-surfaces this flag until edited.)
|
|
308
|
+
|
|
309
|
+
**About.** {inferred from the notes actually present}
|
|
310
|
+
|
|
311
|
+
**Should contain.** {the kinds of notes observed here — this is the coverage checklist; extend it with what SHOULD be here}
|
|
312
|
+
|
|
313
|
+
**Entry notes.** {the 1–3 most-linked or most central notes, as [[wikilinks]]}
|
|
314
|
+
|
|
315
|
+
**Neighbours.** {folders these notes link to most}
|
|
316
|
+
````
|