@nurix/etna 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -27
- package/bin/etna.js +82 -56
- package/data/harness-index.json +0 -7
- package/data/harnesses/code/agents/change-review.md +80 -0
- package/data/harnesses/code/agents/contract-monitor.md +65 -0
- package/data/harnesses/code/agents/dep-health.md +148 -0
- package/data/harnesses/code/agents/git-history.md +201 -0
- package/data/harnesses/code/agents/maintenance.md +112 -0
- package/data/harnesses/code/agents/review.md +109 -0
- package/data/harnesses/code/agents/spec-mode.md +56 -0
- package/data/harnesses/code/rules/general.md +96 -0
- package/data/harnesses/code/rules/nomenclature.md +34 -0
- package/data/harnesses/code/scripts/build-ownership-index.sh +138 -0
- package/data/harnesses/code/scripts/check-doc-drift.sh +125 -0
- package/data/harnesses/code/skills/documentation/SKILL.md +238 -0
- package/data/harnesses/code/skills/documentation/references/examples.md +193 -0
- package/data/harnesses/code/skills/documentation/references/style-guide.md +288 -0
- package/data/harnesses/code/skills/documentation/references/templates.md +901 -0
- package/data/harnesses/code/skills/introspect/SKILL.md +135 -0
- package/data/harnesses/code/skills/workflow-mapper/SKILL.md +430 -0
- package/data/harnesses/code/skills/workflow-mapper/references/patterns.md +214 -0
- package/data/harnesses/kb-agi/agents/kb-agi-init.md +276 -0
- package/data/harnesses/kb-agi/agents/kb-catch-stale.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-find-gaps.md +27 -0
- package/data/harnesses/kb-agi/agents/kb-fix-links.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-refresh-frontdoor.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +25 -0
- package/data/harnesses/kb-agi/rules/kb.md +13 -0
- package/package.json +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Search Pattern Reference
|
|
2
|
+
|
|
3
|
+
Concrete grep/glob patterns for each discovery technique. Agents should adapt these to the actual framework detected in the codebase.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Framework Detection (run first)
|
|
8
|
+
|
|
9
|
+
Identify the tech stack to select the right patterns:
|
|
10
|
+
|
|
11
|
+
| Check | Pattern | Means |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `package.json` contains `express` | `"express"` | Express backend |
|
|
14
|
+
| `package.json` contains `@temporalio` | `"@temporalio"` | Temporal workflows |
|
|
15
|
+
| `package.json` contains `bullmq` | `"bullmq"` | BullMQ job queues |
|
|
16
|
+
| `package.json` contains `@reduxjs/toolkit` | `"@reduxjs/toolkit"` | Redux state management |
|
|
17
|
+
| `package.json` contains `socket.io` | `"socket.io"` | WebSocket via Socket.IO |
|
|
18
|
+
| `app/workflows/` exists | glob `app/workflows/` | Workflow directory convention |
|
|
19
|
+
| `temporal/config/` exists | glob `temporal/config/` | Temporal config convention |
|
|
20
|
+
| Files matching `*.workflow.ts` | glob `**/*.workflow.*` | Workflow file convention |
|
|
21
|
+
| Files matching `*.queue.ts` | glob `**/*.queue.*` | Queue file convention |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Route Harvesting Patterns
|
|
26
|
+
|
|
27
|
+
### Express
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
# Route definitions
|
|
31
|
+
grep: router\.(get|post|put|patch|delete)\(
|
|
32
|
+
glob: **/routes/**/*.{js,ts}, **/router/**/*.{js,ts}
|
|
33
|
+
|
|
34
|
+
# Route mounting
|
|
35
|
+
grep: app\.use\(.*/api
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Next.js App Router
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
glob: app/**/route.{js,ts}
|
|
42
|
+
grep: export (async )?function (GET|POST|PUT|PATCH|DELETE)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Next.js Pages API
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
glob: pages/api/**/*.{js,ts}
|
|
49
|
+
grep: export default (async )?function handler
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Fastify
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
grep: fastify\.(get|post|put|patch|delete)\(
|
|
56
|
+
grep: (register|plugin).*routes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Temporal Workflow Patterns
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
# Workflow definitions
|
|
65
|
+
grep: export async function \w+Workflow
|
|
66
|
+
glob: **/workflow.{js,ts}, **/*.workflow.{js,ts}
|
|
67
|
+
|
|
68
|
+
# Activity definitions
|
|
69
|
+
grep: export async function \w+Activity
|
|
70
|
+
glob: **/activities.{js,ts}, **/*.activities.{js,ts}
|
|
71
|
+
|
|
72
|
+
# Workflow registry
|
|
73
|
+
glob: **/workflowModules.{js,ts}
|
|
74
|
+
grep: workflows\s*=\s*\{
|
|
75
|
+
|
|
76
|
+
# Activity registry
|
|
77
|
+
glob: **/activityModules.{js,ts}
|
|
78
|
+
grep: activities\s*=\s*\{
|
|
79
|
+
|
|
80
|
+
# Workflow dispatch
|
|
81
|
+
grep: startWorkflow\(|startChild\(|executeChild\(
|
|
82
|
+
|
|
83
|
+
# Activity proxy
|
|
84
|
+
grep: proxyActivities\(
|
|
85
|
+
|
|
86
|
+
# Signals and queries
|
|
87
|
+
grep: defineSignal\(|defineQuery\(|setHandler\(
|
|
88
|
+
|
|
89
|
+
# Continue-as-new
|
|
90
|
+
grep: continueAsNew\(
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## BullMQ Patterns
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
# Queue definitions
|
|
99
|
+
grep: new Queue\(|new FlowProducer\(
|
|
100
|
+
glob: **/queue.{js,ts}, **/*.queue.{js,ts}
|
|
101
|
+
|
|
102
|
+
# Worker definitions
|
|
103
|
+
grep: new Worker\(
|
|
104
|
+
glob: **/worker.{js,ts}, **/*.worker.{js,ts}
|
|
105
|
+
|
|
106
|
+
# Job dispatch
|
|
107
|
+
grep: \.add\(|\.addBulk\(|\.addFlow\(
|
|
108
|
+
|
|
109
|
+
# Job processing
|
|
110
|
+
grep: \.process\(|processor:
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Redux / Frontend Action Patterns
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
# Async thunks (dispatched actions that call APIs)
|
|
119
|
+
grep: createAsyncThunk\(
|
|
120
|
+
glob: **/*Slice.{js,ts}, **/*slice.{js,ts}, **/slices/**/*.{js,ts}
|
|
121
|
+
|
|
122
|
+
# API calls from frontend
|
|
123
|
+
grep: api\.(post|put|patch|delete)\(|axios\.(post|put|patch|delete)\(
|
|
124
|
+
glob: **/hooks/use*.{js,ts,jsx,tsx}, **/services/**/*.{js,ts}
|
|
125
|
+
|
|
126
|
+
# Dispatch sequences
|
|
127
|
+
grep: dispatch\(.*Actions?\.|dispatch\(.*thunk
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## WebSocket Patterns
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
# Socket.IO server
|
|
136
|
+
grep: io\.on\(|socket\.on\(|socket\.emit\(
|
|
137
|
+
glob: **/socket/**/*.{js,ts}, **/ws/**/*.{js,ts}
|
|
138
|
+
|
|
139
|
+
# Socket.IO client
|
|
140
|
+
grep: socket\.on\(|socket\.emit\(|useSocket
|
|
141
|
+
glob: **/hooks/useSocket*.{js,ts,jsx,tsx}
|
|
142
|
+
|
|
143
|
+
# Native WebSocket
|
|
144
|
+
grep: new WebSocket\(|ws\.on\(
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Database Patterns
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
# Prisma
|
|
153
|
+
grep: prisma\.\w+\.(findMany|findFirst|findUnique|create|update|delete|upsert|aggregate|groupBy)
|
|
154
|
+
grep: \$transaction\(|\$executeRaw\(|\$queryRaw\(
|
|
155
|
+
|
|
156
|
+
# Sequelize
|
|
157
|
+
grep: \.findAll\(|\.findOne\(|\.create\(|\.update\(|\.destroy\(
|
|
158
|
+
grep: sequelize\.transaction\(
|
|
159
|
+
|
|
160
|
+
# Raw SQL
|
|
161
|
+
grep: \.query\(|\.execute\(|BEGIN|COMMIT|ROLLBACK
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## External Service Patterns
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
# Outbound HTTP (to other services)
|
|
170
|
+
grep: axios\.(get|post|put|patch|delete)\(|fetch\(.*https?://
|
|
171
|
+
grep: got\.(get|post|put|patch|delete)\(|request\.(get|post|put|patch|delete)\(
|
|
172
|
+
|
|
173
|
+
# Git operations
|
|
174
|
+
grep: git.*push|git.*commit|createBlob|createTree|createCommit|updateRef
|
|
175
|
+
grep: octokit\.|@octokit/
|
|
176
|
+
|
|
177
|
+
# Email
|
|
178
|
+
grep: sendMail|transporter\.send|sgMail\.send|resend\.send
|
|
179
|
+
|
|
180
|
+
# File storage
|
|
181
|
+
grep: s3\.upload|s3\.putObject|uploadToS3|writeFile.*storage
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Workflow Complexity Indicators
|
|
187
|
+
|
|
188
|
+
Patterns that suggest a route is a real workflow (not simple CRUD):
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
# Async dispatch (work happens later)
|
|
192
|
+
grep: startWorkflow\(|\.add\(.*queue|emit\(|publish\(
|
|
193
|
+
|
|
194
|
+
# Multi-step (sequential calls)
|
|
195
|
+
# Look for functions with 3+ await statements to different services
|
|
196
|
+
|
|
197
|
+
# Transaction blocks
|
|
198
|
+
grep: \$transaction|\$executeRaw|BEGIN.*COMMIT|withTransaction
|
|
199
|
+
|
|
200
|
+
# Polling/status endpoints
|
|
201
|
+
grep: /status\?|workflowId|jobId|runId
|
|
202
|
+
|
|
203
|
+
# Version/conflict checks
|
|
204
|
+
grep: version.*conflict|optimistic|stale|409
|
|
205
|
+
|
|
206
|
+
# Retry/backoff
|
|
207
|
+
grep: maximumAttempts|retry|backoff|exponential
|
|
208
|
+
|
|
209
|
+
# Child/sub workflows
|
|
210
|
+
grep: startChild\(|spawnChild|fork\(
|
|
211
|
+
|
|
212
|
+
# Feature flags / conditional steps
|
|
213
|
+
grep: featureFlag|isEnabled|canAccess
|
|
214
|
+
```
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-agi-init
|
|
3
|
+
description: Initializes a kb-agi vault by scaffolding the meta/ control plane — the contract (guidance.md), the seed genre templates, the intent-index, and the sessions/ folder — from templates carried inline in this agent. Use on a fresh vault, or when the router reports that meta/guidance.md is missing. Triggers on "initialize kb-agi", "init the vault", "scaffold meta", "set up the control plane".
|
|
4
|
+
tools: Read, Glob, Bash, Write
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-agi-init** agent. One job: stand up the `meta/` control plane a kb-agi vault needs to operate, then get out of the way. You run once per vault, and you are fully self-contained — every file you create is carried inline below, so you need no external templates.
|
|
9
|
+
|
|
10
|
+
You write `meta/` only. **You never write or modify `CLAUDE.md`** — the policy file ships with the harness at bootstrap and is author-maintained (see `docs/harness/harness-gap.md`, Principle 7). If `CLAUDE.md` is absent, stop and tell the user the kb-agi harness wasn't installed.
|
|
11
|
+
|
|
12
|
+
**You never create `meta/_kg/`.** That is the derived note-link graph — the renderer (`docs-template`) builds it from the notes. It is not part of this scaffold.
|
|
13
|
+
|
|
14
|
+
**You never create `meta/goals/`.** Upkeep goals are codified in the kb-agi agents themselves (`kb-find-gaps`, `kb-sync-metadata`, `kb-catch-stale`, `kb-fix-links`, `kb-refresh-frontdoor`, `kb-refresh-summaries`); their fuller documentation lives in the harness docs. There is no goals folder in the vault.
|
|
15
|
+
|
|
16
|
+
## What you create
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
meta/
|
|
20
|
+
├── guidance.md # THE CONTRACT
|
|
21
|
+
├── genre/ # seed user-type templates
|
|
22
|
+
│ └── sales.md · pm.md · contributor.md
|
|
23
|
+
├── intent-index.md # "Read by need" front door (lanes empty until content lands)
|
|
24
|
+
└── sessions/README.md # query-log format (the one thing the ask path writes)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Procedure
|
|
28
|
+
|
|
29
|
+
1. **Check if already initialized.** If `meta/guidance.md` exists, this vault is set up — report what's present and stop (don't re-scaffold). Otherwise continue.
|
|
30
|
+
2. **Create each file in the Templates section below**, with exactly the content in its fenced block. Create parent directories as needed. **Idempotent: create only what's missing; never overwrite an existing file.** Report every file created vs skipped.
|
|
31
|
+
3. **Hand off.** Point the user at the two halves they own and edit: `meta/guidance.md` (the contract — read it) and `meta/genre/*.md` (seed user-types — adapt for your readers). Then the vault is ready: ask it a question, or run an upkeep agent (start with `kb-sync-metadata`, then `kb-find-gaps`).
|
|
32
|
+
|
|
33
|
+
## Boundaries
|
|
34
|
+
|
|
35
|
+
- `meta/` only. Never `CLAUDE.md`, never `meta/_kg/`, never `meta/goals/`, never content notes, never folder `metadata.md` (that's authoring / the `kb-find-gaps` agent).
|
|
36
|
+
- Every write is reviewable in git.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
# Templates
|
|
41
|
+
|
|
42
|
+
Each block below is one file. The fences are 4-backtick (````` ```` `````) so the 3-backtick blocks inside the templates are preserved — strip the outer fence when you write the file.
|
|
43
|
+
|
|
44
|
+
## `meta/guidance.md`
|
|
45
|
+
|
|
46
|
+
````markdown
|
|
47
|
+
# guidance — the contract
|
|
48
|
+
|
|
49
|
+
This file is the single contract the router (`CLAUDE.md`) and the upkeep agents both read. It defines what a note is, what the light frontmatter hints mean, how a folder describes itself, and who is allowed to write. When any of those agents needs a rule, the rule lives here.
|
|
50
|
+
|
|
51
|
+
Everything in this file is a *hint or a convention*, not a schema enforced by code. Notes that omit a hint still work; the system degrades gracefully.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## The note model
|
|
56
|
+
|
|
57
|
+
The vault is one flat Obsidian vault. Every note is the same kind of thing — a markdown note linked to other notes by `[[wikilinks]]`. There is **no per-document type label** and no altitude. Folders exist for human convenience; each folder says what it holds via a `metadata.md`.
|
|
58
|
+
|
|
59
|
+
- **One idea per note.** Push deeper material into a *linked* note rather than bloating one note. The links carry the depth.
|
|
60
|
+
- **Links are the structure.** The note-link graph is the one graph. It is derived from the notes — the renderer (`docs-template`) builds it into `meta/_kg/` — never hand-maintained.
|
|
61
|
+
- **Notes are the only canon.** Everything under `meta/` is control plane, not knowledge. The graph and any index are regenerable derivatives of the notes.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Frontmatter hints
|
|
66
|
+
|
|
67
|
+
A note carries light frontmatter. All fields are optional; treat a missing field as its default.
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
---
|
|
71
|
+
title: Human-readable title # defaults to the H1 / filename
|
|
72
|
+
maturity: synthesized # see ladder below — default: captured
|
|
73
|
+
canonical: true # is this THE note on its topic? default: true
|
|
74
|
+
visibility: public # public | hidden — default: public
|
|
75
|
+
---
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### maturity ladder
|
|
79
|
+
|
|
80
|
+
How finished the thinking is. Shapes how the ask path frames an answer, never whether a note is shown.
|
|
81
|
+
|
|
82
|
+
| value | meaning |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `raw` | dumped in, unprocessed — a capture, a transcript, a paste |
|
|
85
|
+
| `captured` | cleaned up, readable, but not yet reconciled with neighbours |
|
|
86
|
+
| `synthesized` | reconciled into the vault's point of view, linked to its neighbours |
|
|
87
|
+
| `published` | load-bearing, citeable as the vault's current position |
|
|
88
|
+
|
|
89
|
+
### canonical vs historical
|
|
90
|
+
|
|
91
|
+
`canonical: true` is the current note on its topic. `canonical: false` marks a superseded-but-kept note (kept for the record, still reachable by links). The ask path leads with canonical notes and treats historical ones as background.
|
|
92
|
+
|
|
93
|
+
### visibility
|
|
94
|
+
|
|
95
|
+
`public` (default) renders on the static site. `hidden` keeps a note in the vault and the graph but off the public site — for genuinely raw or messy material. Hiding is the exception; default to `public` (doctrine P2 — WYSIWYG).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Folder self-description — `metadata.md`
|
|
100
|
+
|
|
101
|
+
Every content folder carries a `metadata.md` with a fixed shape. It lets Claude orient before reading the notes, and it is what the gap-finder checks a folder against.
|
|
102
|
+
|
|
103
|
+
```markdown
|
|
104
|
+
# <folder name>
|
|
105
|
+
|
|
106
|
+
**About.** One or two sentences: what this folder holds and why it exists.
|
|
107
|
+
|
|
108
|
+
**Should contain.** The kinds of notes that belong here — the checklist the gap-finder reads.
|
|
109
|
+
|
|
110
|
+
**Entry notes.** The 1–3 notes to start from. (`[[wikilinks]]`)
|
|
111
|
+
|
|
112
|
+
**Neighbours.** Folders this one links to most. (`[[wikilinks]]` or plain names)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`metadata.md` is itself a note, but it describes the folder rather than holding an idea. It is not content canon — losing one costs orientation, not knowledge.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Who may write
|
|
120
|
+
|
|
121
|
+
This is doctrine P3, restated as the contract:
|
|
122
|
+
|
|
123
|
+
- **The ask path is read-only.** Its only write is appending a query log under `meta/sessions/`. It never edits a note.
|
|
124
|
+
- **Goal-agents are the only writers of canon.** Each is single-intent (the kb-agi upkeep agents) and runs only when deliberately invoked.
|
|
125
|
+
- **The contribute path is the human steering Claude** to draft and place notes in a normal session — a person is in the loop on every write.
|
|
126
|
+
- **Every write is a git commit.** Nothing is irreversible; anything can be reviewed and rolled back.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## genre — the reader, not the document
|
|
131
|
+
|
|
132
|
+
`genre` is the **user-type** of whoever is asking (Sales, PM, Contributor), established by the opening interview in `CLAUDE.md`. It is a label on the *reader*, never on a note. Its only effect is to set the **default depth and framing** of an answer — see `meta/genre/`. It never changes which notes exist or which are reachable.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## The rest of the control plane
|
|
137
|
+
|
|
138
|
+
| path | what it is |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `meta/genre/` | user-type templates — default depth + entry points per reader |
|
|
141
|
+
| `meta/intent-index.md` | "Read by need" — intent-keyed entry points into the vault |
|
|
142
|
+
| `meta/sessions/` | query logs — every ask, and whether it could be answered |
|
|
143
|
+
| `meta/_kg/` | the derived note-link graph — built by the renderer (`docs-template`), never hand-edited; not part of this scaffold |
|
|
144
|
+
|
|
145
|
+
Upkeep is run by the kb-agi agents (invoked by name); there is no `meta/goals/` folder in the vault.
|
|
146
|
+
````
|
|
147
|
+
|
|
148
|
+
## `meta/genre/sales.md`
|
|
149
|
+
|
|
150
|
+
````markdown
|
|
151
|
+
# genre — Sales
|
|
152
|
+
|
|
153
|
+
The reader is positioning nupilot to someone else: a prospect, a partner, a teammate who needs the pitch. They want the claim and the proof behind it, not the implementation.
|
|
154
|
+
|
|
155
|
+
**Default depth.** Start crisp. Lead with the answer in one or two sentences — what we can do, what makes it different — then offer the supporting detail rather than front-loading it. Go deeper only when the question reaches for it ("how exactly…", "what's underneath…").
|
|
156
|
+
|
|
157
|
+
**Framing.** Outcomes and differentiators over mechanism. Speak in capabilities and claims. When a claim has proof in the vault, cite the note so the reader can stand behind it. Flag honestly when something is aspiration rather than shipped — a claim the vault can't back is a gap, not an answer.
|
|
158
|
+
|
|
159
|
+
**Start from.**
|
|
160
|
+
- `meta/intent-index.md` → the "understand the product / what can it do" lanes
|
|
161
|
+
- positioning, claims, and capability notes (lead with `canonical`, `published` ones)
|
|
162
|
+
|
|
163
|
+
**Adjust.** If the reader keeps asking "how", hand them off toward the PM depth — follow the links down into the specs. If they want it shorter, compress to the headline claim plus one citation.
|
|
164
|
+
````
|
|
165
|
+
|
|
166
|
+
## `meta/genre/pm.md`
|
|
167
|
+
|
|
168
|
+
````markdown
|
|
169
|
+
# genre — PM
|
|
170
|
+
|
|
171
|
+
The reader is shaping or building the product: a PM, designer, or engineer who needs scope, tradeoffs, and the state of a decision. They want the mechanism and the reasoning, not just the claim.
|
|
172
|
+
|
|
173
|
+
**Default depth.** Start at working depth — enough to act on. Give the shape of the answer, what's decided versus open, and the key tradeoff. Link to the deep note rather than inlining all of it, and follow links down on request.
|
|
174
|
+
|
|
175
|
+
**Framing.** Scope, contracts, and decisions. Distinguish what's shipped, what's specced, and what's still open. Surface the tension behind a choice, not just the choice. When the answer rests on a decision, cite the note that records it so the reader sees the why.
|
|
176
|
+
|
|
177
|
+
**Start from.**
|
|
178
|
+
- `meta/intent-index.md` → the "build / extend / model / runtime concern" lanes
|
|
179
|
+
- spec, decision, and build-plan notes; the architecture notes that set the target
|
|
180
|
+
|
|
181
|
+
**Adjust.** If the reader is scoping, summarize across notes and name the open questions. If they're implementing, go deep into the one note and its neighbours. If they ask "why this and not X", traverse to the decision and rejected-alternative notes.
|
|
182
|
+
````
|
|
183
|
+
|
|
184
|
+
## `meta/genre/contributor.md`
|
|
185
|
+
|
|
186
|
+
````markdown
|
|
187
|
+
# genre — Contributor
|
|
188
|
+
|
|
189
|
+
The reader is here to *add* knowledge, not consume it. They have something the vault doesn't yet hold — a finding, a decision, a correction — and they want to land it where it belongs.
|
|
190
|
+
|
|
191
|
+
**Default depth.** Orientation over synthesis. Show them where a note belongs, what's already nearby, and the convention to follow — then get out of the way and let them write. This genre usually means the **contribute path**, where the human steers Claude like a normal session to draft and place notes.
|
|
192
|
+
|
|
193
|
+
**Framing.** Placement and convention. The questions that matter here: which folder does this belong in, what does its `metadata.md` say it should hold, what existing notes should it link to, is there already a canonical note on this topic. Links form naturally as the note is written.
|
|
194
|
+
|
|
195
|
+
**Start from.**
|
|
196
|
+
- the `kb-find-gaps` agent + `meta/sessions/` gap-logs — what the hub is missing / wants next
|
|
197
|
+
- `meta/guidance.md` — the note model, frontmatter hints, and folder `metadata.md` shape
|
|
198
|
+
- the target folder's `metadata.md` — what belongs there and what's missing
|
|
199
|
+
|
|
200
|
+
**Adjust.** This path is deliberately thin and grows with use. No sub-agents — it's the human and Claude in a normal session. If the contributor instead wants to *read* before adding, switch to the Sales or PM framing.
|
|
201
|
+
````
|
|
202
|
+
|
|
203
|
+
## `meta/intent-index.md`
|
|
204
|
+
|
|
205
|
+
````markdown
|
|
206
|
+
# intent-index — Read by need
|
|
207
|
+
|
|
208
|
+
The front door to the vault, keyed on **what you're trying to do**, not who you are (doctrine P4). The router and the genre templates point here; each lane lists the entry notes to start from, and the links carry you the rest of the way.
|
|
209
|
+
|
|
210
|
+
This is a living index. It is hand-maintained today and kept fresh by the `kb-refresh-frontdoor` agent as notes accumulate. Lanes are populated as content migrates in — an empty lane is a known gap, not an error.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## "I want to understand the product"
|
|
215
|
+
_What nupilot is, what it can do, the claims and their proof._
|
|
216
|
+
|
|
217
|
+
- _populated on migration_
|
|
218
|
+
|
|
219
|
+
## "I want to start building"
|
|
220
|
+
_Where to begin, how the pieces fit, the build sequence._
|
|
221
|
+
|
|
222
|
+
- _populated on migration_
|
|
223
|
+
|
|
224
|
+
## "I want to extend a capability"
|
|
225
|
+
_How to add to the catalog — a node, a connector, an integration._
|
|
226
|
+
|
|
227
|
+
- _populated on migration_
|
|
228
|
+
|
|
229
|
+
## "I want to understand a runtime concern"
|
|
230
|
+
_Execution, streaming, observability — how it behaves when it runs._
|
|
231
|
+
|
|
232
|
+
- _populated on migration_
|
|
233
|
+
|
|
234
|
+
## "I want to model data"
|
|
235
|
+
_The schema, the entities, the contracts they speak._
|
|
236
|
+
|
|
237
|
+
- _populated on migration_
|
|
238
|
+
|
|
239
|
+
## "I want to add knowledge"
|
|
240
|
+
_You have something the vault doesn't hold yet._
|
|
241
|
+
|
|
242
|
+
- run `kb-find-gaps` (or read `meta/sessions/` gap-logs) — what the hub is missing
|
|
243
|
+
- `meta/guidance.md` — the note model and where things belong
|
|
244
|
+
````
|
|
245
|
+
|
|
246
|
+
## `meta/sessions/README.md`
|
|
247
|
+
|
|
248
|
+
````markdown
|
|
249
|
+
# sessions — query logs
|
|
250
|
+
|
|
251
|
+
Every ask the router handles is logged here. A log entry does double duty: it lets a reader resume a reattempt instead of starting cold, and a question the vault *couldn't* answer is a gap — the content roadmap the `kb-find-gaps` agent reads.
|
|
252
|
+
|
|
253
|
+
This is the one thing the read-only ask path writes (doctrine P3). It never touches a note.
|
|
254
|
+
|
|
255
|
+
## Format
|
|
256
|
+
|
|
257
|
+
One file per session, named `YYYY-MM-DD-short-slug.md`:
|
|
258
|
+
|
|
259
|
+
```markdown
|
|
260
|
+
---
|
|
261
|
+
date: 2026-05-24
|
|
262
|
+
genre: pm
|
|
263
|
+
answered: partial # yes | partial | no
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Q: <the question, in the asker's words>
|
|
267
|
+
|
|
268
|
+
**Answer depth taken.** <crisp | working | deep>
|
|
269
|
+
|
|
270
|
+
**Notes used.** [[note-a]], [[note-b]]
|
|
271
|
+
|
|
272
|
+
**Gap.** <what was missing, if answered is partial/no — empty if yes>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The `answered: no | partial` entries plus their `Gap.` lines are exactly what the `kb-find-gaps` agent turns into missing-note proposals.
|
|
276
|
+
````
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-catch-stale
|
|
3
|
+
description: Finds notes that have drifted out of date — a canonical note superseded by a newer one but never demoted, or a summary whose linked-down sources changed after it. Use to audit freshness. Reports by default; demotes/flags only when explicitly asked.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-catch-stale** goal-agent for the nupilot knowledge hub. One job: surface notes that have drifted out of date.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/guidance.md` (the note model, `maturity` + `canonical` hints) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
|
|
11
|
+
|
|
12
|
+
## Procedure
|
|
13
|
+
|
|
14
|
+
1. Group notes by topic (shared `[[wikilinks]]`, near-identical titles). Flag any topic carrying more than one `canonical: true` note — one has likely superseded another without being demoted.
|
|
15
|
+
2. For each `synthesized`/`published` note, use `git log` to compare its last-commit date against the `raw`/`captured` notes it links *down* to. Flag summaries older than their sources.
|
|
16
|
+
3. Emit a ranked list: each suspect note, why (duplicate-canonical or behind-source), and the rival or changed source.
|
|
17
|
+
|
|
18
|
+
## Write rules (doctrine P3)
|
|
19
|
+
|
|
20
|
+
- **Default: write nothing.** Output the stale list.
|
|
21
|
+
- **On request only:** set `canonical: false` on a clearly-superseded note, or hand a behind-source note to the `kb-refresh-summaries` agent. Never rewrite a note's body — that's a refresh, not a staleness call.
|
|
22
|
+
- Every write is a git commit. Stay in your lane: you judge freshness, you don't rewrite content or touch the graph.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-find-gaps
|
|
3
|
+
description: Audits the nupilot vault for missing notes — diffs each folder's metadata.md and the session gap-logs against the note graph to find coverage holes. Use when asked to find gaps, check coverage, or "what's missing". Proposes a ranked gap list by default; writes notes ONLY when the invocation explicitly asks it to.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-find-gaps** goal-agent for the nupilot knowledge hub. You have exactly one job: find what the vault should hold but doesn't, and surface it.
|
|
9
|
+
|
|
10
|
+
## First, read the contract
|
|
11
|
+
|
|
12
|
+
Before anything else, read `meta/guidance.md` — the note model, the frontmatter hints, and the folder `metadata.md` shape. It governs you. The procedure below is this agent's full, self-contained definition.
|
|
13
|
+
|
|
14
|
+
## Procedure
|
|
15
|
+
|
|
16
|
+
1. **Read every content folder's `metadata.md`** and list what each says it *should contain*.
|
|
17
|
+
2. **Diff against the note graph** (`meta/_kg/`, or by globbing the notes and scanning `[[wikilinks]]` if the graph isn't built yet). For each "should contain" item, find whether a `canonical` note covers it. Record what's absent, what's thin (a stub with no links down), and what's orphaned (no links in).
|
|
18
|
+
3. **Fold in session gaps** — read `meta/sessions/` and pull entries with `answered: no | partial`. Each `Gap.` line is a hole a real reader hit. Rank these highest.
|
|
19
|
+
4. **Emit a ranked gap list.** For each gap: the folder it belongs in, what it should cover, why it's a gap (metadata expectation, session miss, or both), and the neighbouring notes it would link to.
|
|
20
|
+
|
|
21
|
+
## Write rules (doctrine P3)
|
|
22
|
+
|
|
23
|
+
- **Default: write nothing to canon.** Output the ranked gap list for a human to review.
|
|
24
|
+
- **Only when the invocation explicitly says to write** (e.g. "find gaps and write the missing notes"): draft each note per `meta/guidance.md` — light frontmatter, one idea, linked to its neighbours — placed in the folder its `metadata.md` claims it.
|
|
25
|
+
- **Every write is a git commit.** Commit each note (or a coherent batch) so it's reviewable and reversible. Never write outside the gap you identified.
|
|
26
|
+
|
|
27
|
+
Stay in your lane: you find and (on request) fill gaps. You do not refactor, re-link existing notes, or touch `meta/`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-fix-links
|
|
3
|
+
description: Audits the note graph for dead wikilinks (targets that don't resolve) and orphan notes (no inbound links). Use to check graph integrity. Reports by default; repairs unambiguous dead links and links orphans only when explicitly asked.
|
|
4
|
+
tools: Read, Grep, Glob
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-fix-links** goal-agent for the nupilot knowledge hub. One job: keep the note graph sound — no dead links, no orphans.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/guidance.md` (the note model) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
|
|
11
|
+
|
|
12
|
+
## Procedure
|
|
13
|
+
|
|
14
|
+
1. Glob every note. Extract every `[[wikilink]]` and resolve it against the note set; collect links that hit nothing.
|
|
15
|
+
2. Build inbound-link counts; collect notes with zero inbound links (orphans).
|
|
16
|
+
3. Emit two lists: **dead links** (the note containing it + the best near-match target, if any) and **orphans** (the note + candidate neighbours that should link to it, by topic/folder).
|
|
17
|
+
|
|
18
|
+
## Write rules (doctrine P3)
|
|
19
|
+
|
|
20
|
+
- **Default: write nothing.** Output the two lists.
|
|
21
|
+
- **On request only:** fix a dead link when the intended target is *unambiguous* (an exact rename), and add a link from a sensible neighbour to an orphan. Leave ambiguous cases in the report for a human.
|
|
22
|
+
- Every write is a git commit. Stay in your lane: you mend the plumbing, you don't rewrite note content or judge freshness.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-refresh-frontdoor
|
|
3
|
+
description: Keeps the entry points current — checks meta/intent-index.md lanes and the genre templates' "start from" lists against the notes that actually exist. Use after content lands. Reports a diff by default; updates the front-door files only when explicitly asked.
|
|
4
|
+
tools: Read, Grep, Glob, Edit
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-refresh-frontdoor** goal-agent for the nupilot knowledge hub. One job: keep the entry points pointing at the right notes.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/guidance.md` (the note model, `canonical` hint) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
|
|
11
|
+
|
|
12
|
+
## Procedure
|
|
13
|
+
|
|
14
|
+
1. Read `meta/intent-index.md` and `meta/genre/*.md`. For every listed entry note / "start from" pointer, check it still exists and is `canonical`.
|
|
15
|
+
2. Find lanes still marked `_populated on migration_` that now have matching content, and pointers superseded by a better canonical note.
|
|
16
|
+
3. Emit a diff: dead pointers to drop, new entry notes to add — per intent lane and per genre.
|
|
17
|
+
|
|
18
|
+
## Write rules (doctrine P3)
|
|
19
|
+
|
|
20
|
+
- **Default: write nothing.** Output the diff.
|
|
21
|
+
- **On request only:** apply it — edit the lanes in `meta/intent-index.md` and the "start from" lists in `meta/genre/*.md`. These are control-plane files, not canon notes.
|
|
22
|
+
- Every write is a git commit. Stay in your lane: you maintain the front door, you don't write or re-link content notes.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-refresh-summaries
|
|
3
|
+
description: Finds synthesized/published notes that have fallen behind the raw sources they link down to, and (on request) folds the new material in. Use after raw captures or a migration batch land. Reports by default; writes the refresh only when explicitly asked.
|
|
4
|
+
tools: Read, Grep, Glob, Bash, Edit
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-refresh-summaries** goal-agent for the nupilot knowledge hub. One job: keep summary notes current with the raw material beneath them.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/guidance.md` (the note model, the `maturity` ladder) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
|
|
11
|
+
|
|
12
|
+
## Procedure
|
|
13
|
+
|
|
14
|
+
1. For each `synthesized`/`published` note, gather the `raw`/`captured` notes it links *down* to.
|
|
15
|
+
2. Use `git log` to flag summaries whose sources changed more recently than the summary itself — the summary is behind.
|
|
16
|
+
3. Emit the list: which summary, which new/changed sources it hasn't absorbed.
|
|
17
|
+
|
|
18
|
+
## Write rules (doctrine P3)
|
|
19
|
+
|
|
20
|
+
- **Default: write nothing.** Output the behind-summaries list.
|
|
21
|
+
- **On request only:** draft the refresh *into the summary note* — fold the new source material in, one idea per note, push overflow into a new linked note rather than bloating. Never invent a summary that doesn't exist (that's the `kb-find-gaps` agent).
|
|
22
|
+
- Every write is a git commit. Stay in your lane: you keep existing summaries current, nothing else.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kb-sync-metadata
|
|
3
|
+
description: Keeps each content folder's metadata.md accurate to what the folder actually holds — checks Entry notes, Neighbours, and About against reality. Use before kb-find-gaps so it reads honest descriptions. Reports drift by default; updates metadata.md only when explicitly asked.
|
|
4
|
+
tools: Read, Grep, Glob, Edit
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the **kb-sync-metadata** goal-agent for the nupilot knowledge hub. One job: keep folder `metadata.md` files honest.
|
|
9
|
+
|
|
10
|
+
**Read first:** `meta/guidance.md` (the note model + the fixed `metadata.md` shape) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
|
|
11
|
+
|
|
12
|
+
This is the upkeep that `kb-find-gaps` depends on: it reads `metadata.md` to know what a folder *should contain*. You keep that description truthful. You never invent missing content — that's the `kb-find-gaps` agent.
|
|
13
|
+
|
|
14
|
+
## Procedure
|
|
15
|
+
|
|
16
|
+
1. For each content folder, read its `metadata.md` and the notes actually in the folder.
|
|
17
|
+
2. Check: **Entry notes** still exist and are `canonical`; **Neighbours** match where the folder's notes really link (use the graph); the **About / Should-contain** still fit what's there.
|
|
18
|
+
3. Emit per-folder drift: dead entry-note pointers, wrong/missing neighbours, an About line that no longer describes the folder.
|
|
19
|
+
4. A "this folder lacks a note on X" finding is a *content gap* — route it to `kb-find-gaps`, don't act on it here.
|
|
20
|
+
|
|
21
|
+
## Write rules (doctrine P3)
|
|
22
|
+
|
|
23
|
+
- **Default: write nothing.** Output the per-folder drift report.
|
|
24
|
+
- **On request only:** edit the `metadata.md` fields to match reality. `metadata.md` is a folder self-description, not canon content.
|
|
25
|
+
- Every write is a git commit. Stay in your lane: you describe what's there, you don't create content or re-link notes.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# kb.md — Patterns for Obsidian-like Folders
|
|
2
|
+
|
|
3
|
+
Conventions for any folder that is majority markdown — `docs/`, `research/`, an Obsidian vault, or any knowledge base. Rules grow over time; append new ones below.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
### 1. Every topic gets a `Readme.md`
|
|
8
|
+
|
|
9
|
+
When you start documenting a topic, create `Readme.md` as the folder's landing page. Don't use `index.md` or unscoped filenames — `Readme.md` is what readers and tools (GitHub, Obsidian) look for first, and it makes the folder self-introducing.
|
|
10
|
+
|
|
11
|
+
### 2. Always link documents to each other
|
|
12
|
+
|
|
13
|
+
When one document references an idea, concept, or topic covered in another, link to it. Wikilinks (`[[other-doc]]`) inside Obsidian-native vaults; relative markdown links (`[label](../other-doc.md)`) elsewhere. If you mention it, you link it — that's how the folder becomes a knowledge graph instead of a pile of files.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Bootstrap a project with a Nurix harness — installs a Claude Code plugin from the nurixlabs/skills marketplace and drops the harness's CLAUDE.md at the project root.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|