@freetesh/zeno 0.10.0 → 0.12.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.
@@ -8,7 +8,7 @@ file with its own `agent-contract.md` in a configured standards folder.
8
8
  - Read the repo's `CLAUDE.md` / `AGENTS.md`: stack, layout, the rules that are
9
9
  the repo's own.
10
10
  - Read `.context/tasks.md`. It is the ordered queue — the top item of `## Now`
11
- is the next action. After finishing, tick the task and append a Session Note.
11
+ is the next action. After finishing, delete the task.
12
12
  - For a non-trivial request, run the weigh gate first (`/zeno:weigh`).
13
13
 
14
14
  ## Repository rules
@@ -40,7 +40,8 @@ function's own name.
40
40
 
41
41
  ## Before calling work done
42
42
 
43
- 1. Reflect changed behaviour in `CLAUDE.md` and any affected `.context/` page.
43
+ 1. Update any `.context/` page the change made wrong. Add a page only if an
44
+ agent would get something wrong without it.
44
45
  2. Run the repo's own lint, typecheck and tests.
45
46
  3. Run `zeno check`. Every checker the repo declares under `commands:` runs
46
47
  with it.
@@ -52,10 +52,10 @@ folder.
52
52
 
53
53
  ## Naming and frontmatter
54
54
 
55
- - Append-only, time-ordered files → ISO date: `YYYY-MM-DD-slug.md`.
56
- - Files referenced by a stable ID → zero-padded number: `NNNN-slug.md`.
57
- - Frontmatter follows the wiki schema: `id`, `type`, `status`, `last-verified`,
58
- `supersedes`, `superseded-by`. Kebab-case keys.
55
+ - Dated sources (`raw/`) → ISO date: `YYYY-MM-DD-slug.md`.
56
+ - Features → zero-padded number: `NNNN-slug.md`.
57
+ - Everything else is named by topic and edited in place.
58
+ - Frontmatter: `last-verified`, kebab-case keys. See the wiki schema.
59
59
 
60
60
  ## Where each kind of document lives
61
61
 
@@ -64,8 +64,8 @@ separate folder per name.
64
64
 
65
65
  | Document | Home |
66
66
  |---|---|
67
- | ADR | `wiki/decisions/`, `status: canonical` |
68
- | RFC | `wiki/decisions/`, `status: draft` — the same page becomes the ADR when accepted |
67
+ | ADR | `wiki/decisions/<topic>.md`, overwritten when the choice changes |
68
+ | RFC | `features/`; once accepted, the choice goes in `wiki/decisions/` |
69
69
  | PRD | `features/`, `type: feature` |
70
70
  | Experiment | `features/`, `type: experiment`; the result is a decision page |
71
71
  | Initiative | `wiki/synthesis/`, linking its features and decisions |
@@ -99,16 +99,11 @@ An experiment adds `## Hypothesis`, `## Metric` (a name from
99
99
  `metrics/definitions.yml`) and `## Result` once it has run.
100
100
 
101
101
  The wiki describes what *is*; `features/` describes what is *next*. A shipped
102
- feature goes `status: shipped` and is never deleted.
102
+ feature goes `status: shipped`.
103
103
 
104
- ## `tasks.md` — the ordered queue
104
+ ## `tasks.md` — open work only
105
105
 
106
106
  ```markdown
107
- ---
108
- updated: 2026-09-29
109
- horizon: 2026-10-13 # this file is stale after this date
110
- ---
111
-
112
107
  # Tasks
113
108
 
114
109
  ## Now <!-- position is the dependency; do in order -->
@@ -116,7 +111,7 @@ horizon: 2026-10-13 # this file is stale after this date
116
111
  2. [ ] T002 Write the capture flows needs:T001 ~3h
117
112
 
118
113
  ## Parallel <!-- independent, safe to batch -->
119
- - [ ] T004 [P] Move the SKU IDs into the wiki ~1h
114
+ - [ ] T004 Move the SKU IDs into the wiki ~1h
120
115
 
121
116
  ## Blocked
122
117
  - [ ] T005 Submit the iOS build
@@ -125,14 +120,9 @@ horizon: 2026-10-13 # this file is stale after this date
125
120
 
126
121
  ## Waiting <!-- deferred by time, not by a task -->
127
122
  - [ ] T006 Second-language listing wait:2026-11-01
128
-
129
- ## Done
130
- - [x] T000 Set up .context done:2026-09-29
131
-
132
- ## Session Notes
133
- ### 2026-09-29
134
- - Done: T000. Learned: … Next: T001.
135
123
  ```
136
124
 
137
- A blocker with no named unblocking action and no check date is a silent leak.
138
- A task that needs more than a line and a continuation is a `features/` page.
125
+ Delete a task when it is done — the commit records it. No `## Done`, no session
126
+ notes. Cap: 100 lines. A blocker with no unblocking action and no check date is a
127
+ silent leak. A task that needs more than a line and a continuation is a
128
+ `features/` page.
@@ -1,299 +1,71 @@
1
- # Wiki — schema and rules
1
+ # Wiki — rules
2
2
 
3
- This folder is a **Claude-maintained knowledge base** for the product. The model is the LLM-Wiki pattern: `.context/raw/` holds immutable sources, `.context/wiki/` holds synthesised pages with `[[wikilinks]]`, this file defines the schema.
3
+ `.context/wiki/` holds what an agent would get wrong without being told. `.context/raw/` holds
4
+ sources, never edited. Answer from the wiki, not from raw.
4
5
 
5
- **Read this file before creating or editing any page under `.context/wiki/`.**
6
+ ## The test
6
7
 
7
- ---
8
-
9
- ## Three layers
10
-
11
- | Layer | Path | Mutability | Who writes |
12
- |---|---|---|---|
13
- | Raw | `.context/raw/`, `.context/designs/` | **Immutable** — never edit | Humans (or external systems) |
14
- | Wiki | `.context/wiki/` | Mutable, schema-bound | Claude (via `/zeno:ingest`, `/zeno:ask`, `/zeno:wiki-lint`) |
15
- | Index | `.context/wiki/index.md` | Auto-maintained | `/zeno:ingest` and `/zeno:wiki-lint` |
16
-
17
- The wiki is the **only** layer Claude reads for `/zeno:ask`. Never answer from `.context/raw/` directly — the synthesis must be written down or it doesn't exist.
18
-
19
- ---
8
+ Keep a line only if an agent would make a mistake without it. Never write what the
9
+ code, an HTML design, or `git log` already says. Describe what is true **now**:
10
+ history is git's job.
20
11
 
21
- ## Page types
22
-
23
- Every page in `.context/wiki/` belongs to exactly one type. The folder name is the type.
24
-
25
- | Type | Folder | What it owns | Example |
26
- |---|---|---|---|
27
- | `concept` | `concepts/` | An idea, principle, or invariant. Prose-shaped. | `offline-first`, `money-in-minor-units` |
28
- | `entity` | `entities/` | A thing with canonical values (price, name, enum). Table-shaped. | `plan-pro`, `plan-free` |
29
- | `surface` | `surfaces/` | One screen / route / email / callable. Links to a raw wireframe. | `onboarding-welcome` |
30
- | `flow` | `flows/` | A user journey. Ordered list of `[[surface]]` steps. | `new-user-to-first-save` |
31
- | `decision` | `decisions/` | One ADR. Filename = `YYYY-MM-DD-slug.md`. Append-only. | `2026-06-24-annual-plan-only` |
32
- | `synthesis` | `synthesis/` | Cross-cutting page built from many entities/concepts. Refreshable. | `pricing`, `launch-checklist` |
33
-
34
- A page cannot be two types. If it feels like it is, it's two pages — split it.
35
-
36
- A product adds a type in `.claude/zeno.yaml`, with the reason and the `## `
37
- sections every page of it must have:
38
-
39
- ```yaml
40
- wiki:
41
- types:
42
- - { type: postmortem, folder: postmortems, reason: …, sections: [Summary, Timeline, Root cause, Fix, Sources] }
43
- ```
12
+ ## Folders
44
13
 
45
- `zeno check` fails a page of that type that misses a section. Its ID is
46
- `<TYPE>.<SLUG>` (`POSTMORTEM.MIDNIGHT-RESET`). The six built-in types and their
47
- folders cannot be redefined. Try the six first — an added type is a shape every
48
- reader and every product must learn.
49
-
50
- ### Data sources
51
-
52
- Each tool that holds product data (Datadog, Sentry, Snowflake, an analytics
53
- console) is one `entity` page, `id: SOURCE.<NAME>`, in `entities/`:
54
-
55
- ```markdown
56
- ## Summary
57
- What this source holds, in one sentence.
58
-
59
- ## Canonical values
60
- | Key | Value | Last changed |
14
+ | Folder | Holds | Example |
61
15
  |---|---|---|
62
- | SOURCE.SENTRY.PROJECT | streaks-mobile | 2026-10-23 |
63
- | SOURCE.SENTRY.ACCESS | mcp: sentry | 2026-10-23 |
16
+ | `concepts/` | a rule or invariant | `money-in-minor-units` |
17
+ | `entities/` | canonical values (prices, SKUs, limits) — the one home for each | `plan-pro` |
18
+ | `decisions/` | one file per topic: the current choice | `pricing` |
19
+ | `surfaces/` | a screen's notes: what its HTML can't show (only screens that have some) | `paywall` |
20
+ | `synthesis/` | research and cross-cutting analysis | `tax-table-verification-ay-2026-27` |
64
21
 
65
- ## How to query
66
- The claims this source can answer, and one example query for each.
67
- ```
22
+ There is no page per screen: the HTML design is the screen spec. A screen gets a
23
+ `surfaces/<slug>.md` only when it has a constraint or decision invisible in its pixels;
24
+ the design set's notes button shows it, and `routes.js` sets `notes: null` for every
25
+ other screen. A user journey worth keeping is a concept.
26
+ A product may add a folder in `.claude/zeno.yaml` under `wiki.types`, with a reason.
68
27
 
69
- zeno has no connector of its own. The repo picks what does the reading, and
70
- `ACCESS` names it: `mcp: <server>`, `skill: <name>`, `cli: <command>`, or
71
- `manual: <where>` for a dashboard with no API, which a person reads and pastes
72
- into `raw/`. A `cli:` must also be in `doctor.tools` in `.claude/zeno.yaml`, so `zeno doctor`
73
- reports when it is missing. `zeno check` fails a source page that breaks either
74
- rule or has no `## How to query`. Never put a key or token on the page.
28
+ ## Pages
75
29
 
76
- The weigh gate reads sources to check a claim (C-14). Every query follows these
77
- rules:
30
+ - Frontmatter: `last-verified: YYYY-MM-DD` is the only required field. `id` is kept
31
+ where code references it (`SOURCE.*`, entity keys).
32
+ - Write only the sections you have something to say in. No `TBD`, no `none yet`.
33
+ - One file per topic, edited in place. No dated names, no `v2`, no supersede chains.
34
+ - Caps: page 60 lines, decision 30. Synthesis is exempt.
35
+ - Link with `[[slug]]` (the file name without `.md`). `index.md` is one line per page.
78
36
 
79
- - **Read only.** Never create, change or delete anything in the source.
80
- - **Small.** One or two queries per claim, with a row limit. Some sources bill
81
- per query.
82
- - **No user data in git.** Save counts, totals and rates, never rows that name
83
- a person, an email or a device. Results that back a decision go to
84
- `raw/YYYY-MM-DD-<source>-<slug>.md`: the query, the date and the numbers.
37
+ ## Decisions
85
38
 
86
- ---
87
-
88
- ## Frontmatter (mandatory)
89
-
90
- Every page begins with YAML frontmatter:
91
-
92
- ```yaml
93
- ---
94
- id: PLAN.PRO # Stable, uppercase, dot-separated. Never changes. Referenced from code.
95
- type: entity # concept | entity | surface | flow | decision | synthesis
96
- status: canonical # canonical | draft | superseded
97
- last-verified: 2026-06-24 # ISO date. /zeno:wiki-lint flags pages > 90 days.
98
- supersedes: [] # IDs this page replaces (decisions only)
99
- superseded-by: null # If non-null, this page is no longer canonical
100
- ---
101
- ```
102
-
103
- ### ID conventions
104
-
105
- | Type | ID shape | Example |
106
- |---|---|---|
107
- | concept | `CONCEPT.<SLUG>` | `CONCEPT.OFFLINE-FIRST` |
108
- | entity | `<DOMAIN>.<NAME>` | `PLAN.PRO`, `PLAN.FREE` |
109
- | surface | `SURFACE.<APP>.<PATH>` | `SURFACE.MOBILE.ONBOARDING.WELCOME` |
110
- | flow | `FLOW.<SLUG>` | `FLOW.NEW-USER-TO-FIRST-SAVE` |
111
- | decision | `DECISION.<YYYY-MM-DD>.<SLUG>` | `DECISION.2026-06-24.ANNUAL-PLAN-ONLY` |
112
- | synthesis | `SYNTHESIS.<SLUG>` | `SYNTHESIS.PRICING` |
113
-
114
- Once assigned, an ID never changes. If a page is renamed, the ID stays. If the thing it describes is killed, mark `status: superseded` and set `superseded-by`; do not delete.
115
-
116
- ---
117
-
118
- ## Page body — required sections
119
-
120
- Each type has a required section list. `/zeno:wiki-lint` fails the page if any are missing.
121
-
122
- ### `concept`
123
39
  ```markdown
124
- ## Summary
125
- One sentence — what the concept is.
126
-
127
- ## Why it matters
128
- Why this is a load-bearing idea. Tie it to a constraint, an incident, or a principle.
129
-
130
- ## Implications
131
- Bulleted: what this forces / forbids in practice.
132
-
133
- ## Related
134
- - [[other-concept]] — relationship
135
- - [[entity-x]] — where this applies
136
-
137
- ## Sources
138
- - .context/raw/<source> or .context/designs/<surface>/<flow>/<screen>.html
139
- ```
140
-
141
- ### `entity`
142
- ```markdown
143
- ## Summary
144
- One sentence — what this entity is.
145
-
146
- ## Canonical values
147
- | Key | Value | Last changed |
148
- |---|---|---|
149
- | PRICE.PRO.YEARLY | $49 | 2026-04-12 |
150
- | STORAGE.PRO | 5 GB | 2026-04-12 |
151
-
152
- ## Related
153
- - [[concept-x]] — concept this entity instantiates
154
- - [[entity-y]] — sibling / upgrade-from
155
-
156
- ## Sources
157
- - .context/raw/<source>
158
- ```
159
-
160
- The `Canonical values` table is the single source of truth. Any value here that disagrees with the codebase is a bug — fix the code or update this page.
161
-
162
- ### `surface`
163
- ```markdown
164
- ## Summary
165
- One sentence — what this screen does.
166
-
167
- ## Raw wireframe
168
- - .context/designs/<surface>/<flow>/<screen>.html
169
-
170
- ## Copy
171
- Verbatim user-visible strings. Each must pass the [[copy-voice]] rules.
172
-
173
- ## Flows that touch this surface
174
- - [[new-user-to-first-save]] — step 4
175
-
176
- ## Entities referenced
177
- - [[plan-free]]
178
- - [[privacy-consent]]
179
-
180
- ## Sources
181
- - .context/raw/<source>
182
- ```
183
-
184
- ### `flow`
185
- ```markdown
186
- ## Summary
187
- One sentence — what journey this is.
188
-
189
- ## Audience
190
- end-user | admin
191
-
192
- ## Entry
193
- Where the user arrives from.
194
-
195
- ## Steps
196
- | # | Step | Surface | Notes |
197
- |---|---|---|---|
198
- | 1 | Welcome | [[welcome]] | First launch |
199
- | 2 | Sign up | [[sign-up]] | Email |
200
- | ... |
201
-
202
- ## Exit
203
- The success state.
204
-
205
- ## Escapes
206
- Back-button, skips, abandonment outcomes.
207
-
208
- ## Sources
209
- - .context/raw/<source>
210
- ```
211
-
212
- ### `decision`
213
- ```markdown
214
- ## Decision
215
- One-line statement.
216
-
217
- ## Why
218
- The motivation. Cite the trigger — incident, user feedback, regulator, scope cut.
219
-
220
- ## Impact
221
- What changes downstream. Which [[entities]] / [[surfaces]] / [[concepts]] update.
222
-
223
- ## Status
224
- Active | Superseded by [[decision-id]]
225
-
226
- ## Sources
227
- - .context/raw/<source>
228
- ```
229
-
230
- Decisions are append-only. To reverse a decision, write a new one with `supersedes: [DECISION.<old>]` and mark the old one's `superseded-by`.
231
-
232
- ### `synthesis`
233
- ```markdown
234
- ## Summary
235
- What this synthesis combines.
236
-
237
- ## Built from
238
- - [[entity-x]]
239
- - [[entity-y]]
240
- - [[concept-z]]
241
-
242
- ## Body
243
- The cross-cutting answer. Every claim links back to a source page.
244
-
245
- ## Last refresh
246
- 2026-06-24 — refresh when any "Built from" page changes.
247
-
248
- ## Sources
249
- - (synthesis pages cite wiki pages, not raw files)
250
- ```
251
-
252
- Synthesis pages are **derived**. If a source page changes, `/zeno:wiki-lint` marks the synthesis stale.
253
-
254
40
  ---
255
-
256
- ## Linking
257
-
258
- - Use `[[page-slug]]` — the filename without `.md`. Match the file exactly (case-sensitive on case-sensitive filesystems).
259
- - Cross-folder links use the slug, not the path: `[[tier-self]]`, not `[[entities/tier-self]]`.
260
- - An `[[unknown-link]]` is a TODO marker — `/zeno:wiki-lint` reports it. Never silently delete a broken link; either create the target page or rename the link.
261
- - The `Related` section is what makes the graph navigable. Every page must have at least two outbound links (or be flagged as orphan-source).
262
-
41
+ last-verified: 2026-10-27
263
42
  ---
43
+ # Pricing
44
+ **Choice:** annual plan only, ₹249 ([[plan-pro]]).
45
+ **Why:** monthly churn was 3× annual in the 2026-06 test.
46
+ **Rejected:** monthly plan (churn) · lifetime deal (no recurring revenue).
47
+ ```
264
48
 
265
- ## Lint rules (what `/zeno:wiki-lint` enforces)
266
-
267
- | Rule | Failure |
268
- |---|---|
269
- | Missing required section | Block — must be fixed |
270
- | `[[wikilink]]` to a non-existent page | Block — create target or rename link |
271
- | Orphan page (zero inbound links) | Warn |
272
- | Two entities claim the same `id` | Block |
273
- | Two entities have contradictory canonical values for the same key | Block |
274
- | `last-verified` > 90 days | Warn |
275
- | `status: superseded` without `superseded-by` | Block |
276
- | Source file in `.context/raw/` not referenced by any wiki page | Warn |
277
- | Synthesis page where a `Built from` page changed after `Last refresh` | Warn |
278
- | Filename does not match the `id`'s slug portion | Block |
49
+ When the choice changes, overwrite the file. `Rejected:` is what stops the same idea
50
+ being proposed again; keep it. Fix lists and audit results go in commit messages or
51
+ `CHANGELOG.md`, not here.
279
52
 
280
- `/zeno:wiki-lint --fix` auto-fixes: filename ↔ id mismatches, missing `last-verified` (sets to today if the page is touched), index regeneration.
53
+ ## Data sources
281
54
 
282
- ---
55
+ Each tool that holds product data is one entity page, `id: SOURCE.<NAME>`, with a
56
+ `## How to query` section and a `SOURCE.<NAME>.ACCESS` row: `mcp: <server>`,
57
+ `skill: <name>`, `cli: <command>` (also listed in `doctor.tools`) or `manual: <where>`.
58
+ Queries are read-only, one or two per claim, with a row limit. Save counts and
59
+ rates to `raw/YYYY-MM-DD-<source>-<slug>.md`, never rows that name a person. Never
60
+ put a key or token on the page.
283
61
 
284
- ## What the wiki is NOT for
62
+ ## Not for
285
63
 
286
- - **Not for code documentation.** Docstrings stay in code. The wiki is product-shaped, not API-shaped.
287
- - **Not for transient task tracking.** Use `TaskCreate` / PR descriptions / commit messages for ephemeral work.
288
- - **Not for chat logs.** If a chat produces a decision, write a `decision` page; throw the chat away.
289
- - **Not for drafts of code.** If it would be a comment, it's a comment.
290
-
291
- ---
64
+ Code docs (they go next to the code) · tasks (`tasks.md`) · plans (`features/`) ·
65
+ chat logs · session notes · changelogs.
292
66
 
293
- ## Source of truth
67
+ ## Checked by `zeno check`
294
68
 
295
- `.context/wiki/` is the canonical knowledge base, and every page in it follows
296
- the schema above — there are no plan-shaped exceptions. What is *next* lives in
297
- `.context/features/`, and the ordered queue lives in `.context/tasks.md`; the
298
- wiki describes what is, not what is planned. The repo root holds no
299
- product-knowledge `.md` files.
69
+ `wiki-frontmatter` (last-verified, placeholders, stale > 90 days) · `context-size`
70
+ (caps, dated decision names, no `flows/`) · `canonical-values` (a
71
+ price in a decision or screen note is held by an entity) · `sources`.