@nurix/etna 0.20.8 → 0.20.10
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 +2 -2
- package/data/harnesses/code/hooks/awareness.mjs +7 -4
- package/data/harnesses/code/hooks/lib/ownership.mjs +51 -19
- package/data/harnesses/code/skills/brainstorm/references/doctrine.md +27 -0
- package/data/harnesses/code/skills/brainstorm/references/harvest.md +28 -0
- package/data/harnesses/code/skills/documentation/SKILL.md +10 -3
- package/data/harnesses/code/skills/documentation/references/frontmatter.md +21 -7
- package/data/harnesses/code/skills/documentation/templates/Readme.md +3 -1
- package/data/harnesses/code/skills/documentation/templates/package.md +131 -0
- package/data/harnesses/code/skills/documentation/templates/structure.md +9 -3
- package/data/harnesses/code/skills/documentation/templates/system.md +143 -0
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/skills/brainstorm/references/doctrine.md +27 -0
- package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +28 -0
- package/data/harnesses/delivery/skills/documentation/SKILL.md +10 -3
- package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +21 -7
- package/data/harnesses/delivery/skills/documentation/templates/Readme.md +3 -1
- package/data/harnesses/delivery/skills/documentation/templates/package.md +131 -0
- package/data/harnesses/delivery/skills/documentation/templates/structure.md +9 -3
- package/data/harnesses/delivery/skills/documentation/templates/system.md +143 -0
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/brainstorm/references/doctrine.md +27 -0
- package/data/harnesses/etna/skills/brainstorm/references/harvest.md +28 -0
- package/data/harnesses/etna/skills/documentation/SKILL.md +10 -3
- package/data/harnesses/etna/skills/documentation/references/frontmatter.md +21 -7
- package/data/harnesses/etna/skills/documentation/templates/Readme.md +3 -1
- package/data/harnesses/etna/skills/documentation/templates/package.md +131 -0
- package/data/harnesses/etna/skills/documentation/templates/structure.md +9 -3
- package/data/harnesses/etna/skills/documentation/templates/system.md +143 -0
- package/package.json +2 -2
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# System Documentation (docs/architecture/systems/{system}.md)
|
|
2
|
+
|
|
3
|
+
Truth document. Use for: **one machine that spans packages** — exactly how it works, end to end, in one place. One file per machine, named for the machine (`docs/architecture/systems/update-engine.md`). It states the machine's model and its whole path: what enters it, every stage it passes through, what it writes, what re-drives it when it stalls, and what a reader sees at the far end.
|
|
4
|
+
|
|
5
|
+
**A system document's globs win by specificity.** Its `owns:` names the subtrees and exact files the machine is made of — `packages/studio/src/server/execution/**`, `packages/ui/src/shared/harnessVocabulary.ts` — and those are narrower than the package document's `packages/studio/**`, so the system takes them and the package keeps the residue. That is the whole mechanism: **the package document is the residual owner and the system document is the specific one**, and nothing needs to be subtracted by hand. A machine confined to one package still gets a system document if the machine is the thing worth stating; it is the *narrower glob* that makes it a system, not the package count.
|
|
6
|
+
|
|
7
|
+
**Two rules bind the globs.** Neither genre may claim a path another document claims at **equal specificity** — equal-specificity overlap is an ownership conflict to resolve before either document ships. And every glob **matches at least one file on disk** at `status: active`; projected globs are permitted only at `draft` and are confirmed when the document flips. Because a system's `owns:` list is long and hand-assembled, re-glob it whenever the machine's code moves — a stale entry here silently un-owns real code back to the package document, which does not describe it.
|
|
8
|
+
|
|
9
|
+
**How this differs from its neighbours — and the mistake this template exists to prevent.** A **feature** document covers one capability or one page a person names and owns that surface's globs. A **package** document covers one unit of distribution and owns what is left of its tree. A **system** document covers a *machine*: something with an entry, stages, state and an outcome, which a person does not open and cannot point at. **The failure mode is a system document written as a giant feature document** — a tour of screens and what each button does, at ten times a feature doc's length. The test is mechanical: if the subject can be named by an address a person navigates to, it is a feature; if it can be named only as a verb over the product's own nouns — the walk, the egress, the ingest, the settlement — it is a system. A system document says what a surface *renders from* and links to the feature document for what the surface looks like; it never describes the surface.
|
|
10
|
+
|
|
11
|
+
**Required vs optional.** Required in every system document: the **frontmatter**, the **opening statement** (what the machine is, then what this document states end to end), the **boundary paragraph** (what this document does not restate, and which document holds each part), the **machine diagram**, at least one **stage section**, **Files**, and **Related**. Everything else is optional. Do not add a section because it seems owed — a stage the machine does not have is a section that will be filled with something untrue.
|
|
12
|
+
|
|
13
|
+
System documents are long by nature, because the point is that the whole machine is in one place — roughly 300 to 1000 lines. Length is earned by stages, never by restating a neighbour: every paragraph that could have been a link to the document that owns it is the genre's characteristic waste.
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
---
|
|
17
|
+
owns: # required — the machine's subtrees and exact files; narrower than the package glob
|
|
18
|
+
- packages/{pkg}/src/{machine}/**
|
|
19
|
+
- packages/{pkg}/src/routes/{machine}.ts
|
|
20
|
+
- packages/{other}/src/shared/{machine}Vocabulary.ts
|
|
21
|
+
keywords: [machine name, its nouns, its verbs] # required — discovery terms: the machine's own vocabulary, the table and route names
|
|
22
|
+
status: active # required — active | draft | deprecated
|
|
23
|
+
applies: # optional — the decisions and doctrine this machine is BOUND by (obligation, not a bibliography)
|
|
24
|
+
- docs/architecture/decisions/AD-0NN-{slug}.md
|
|
25
|
+
- docs/architecture/common/{doctrine}.md
|
|
26
|
+
type: system # required tooling key — genre stamp; preserve on edits, never narrate
|
|
27
|
+
---
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> A system document carries no `module:` — a machine that spans packages belongs to no single
|
|
31
|
+
> bounded context, and labelling it with one asserts a boundary it crosses by definition.
|
|
32
|
+
> `last-reviewed:` is optional tooling metadata: preserve it, never narrate it.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
# {The machine}
|
|
36
|
+
|
|
37
|
+
{One paragraph that defines the machine in its own first sentence — bold the term being defined —
|
|
38
|
+
then says what this document states, in the order the body states it. The enumeration is the
|
|
39
|
+
contract: a reader who wants one stage finds it by reading this sentence. Where the machine's
|
|
40
|
+
purpose is easier stated as an outcome, lead with `**Goal:**` and one sentence instead.}
|
|
41
|
+
|
|
42
|
+
{One paragraph: the boundary. What this document does **not** restate, and which document holds
|
|
43
|
+
each part — the neighbouring systems, the package documents whose residue this sits inside, the
|
|
44
|
+
feature documents that render from it, the common-plane doctrine it obeys, the decision records
|
|
45
|
+
behind its shape. Name each with a link and the subject it holds. This paragraph is what keeps the
|
|
46
|
+
document from growing into its neighbours.}
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
{The machine diagram. One fenced block, drawn as the thing flows — entry at the top or left,
|
|
50
|
+
each stage a box or a labelled arrow, the durable writes named, the re-drive path shown returning.
|
|
51
|
+
Label the arrows with what crosses them, not with verbs. This is the picture a reader holds while
|
|
52
|
+
reading the rest, so it carries the machine's real names — routes, tables, classes, files — and
|
|
53
|
+
not generic boxes.}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
{Optional, and worth its line whenever the body names paths: "Every path below is relative to
|
|
57
|
+
`packages/{pkg}/src/{dir}/` unless it names another package."}
|
|
58
|
+
|
|
59
|
+
{Optional: a reading order for a long document — "§ X is the data; § Y is the code that reads it;
|
|
60
|
+
§ Z is what re-drives it" — where the section list is not self-evidently a sequence.}
|
|
61
|
+
|
|
62
|
+
## The shape
|
|
63
|
+
|
|
64
|
+
{Optional. Where the machine has parts a reader must hold at once before any stage makes sense,
|
|
65
|
+
name them in one table before the stages begin.}
|
|
66
|
+
|
|
67
|
+
| Part | Where | What it holds |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| {Entry} | `routes/{x}.ts` | {thin, tenancy first} |
|
|
70
|
+
| {Ledger} | `{machine}/ledger.ts` | {the durable row} |
|
|
71
|
+
|
|
72
|
+
## {Stage sections — one per stage, in the order the machine runs them}
|
|
73
|
+
|
|
74
|
+
{The body, and the only genre where the section order is decided for you: the machine's own order.
|
|
75
|
+
Entry, then each stage, then what is written durably, then what re-drives a stalled one, then what
|
|
76
|
+
reads the result. Name each section for its stage in the product's own vocabulary. Within a
|
|
77
|
+
section, state the mechanism and its reason: what the code does, what it refuses, and why it
|
|
78
|
+
refuses that rather than something else. Tables for rosters (routes, columns, frames, states,
|
|
79
|
+
bindings); prose for a rule and the defect it prevents. Never paste an implementation — a
|
|
80
|
+
signature, a state list, a wire shape, a table's columns.}
|
|
81
|
+
|
|
82
|
+
## Tests
|
|
83
|
+
|
|
84
|
+
{Optional. What proves this machine, and what each suite pins — a `Suite | Pins` table. Include it
|
|
85
|
+
where the machine has a suite of its own; omit the heading where the coverage lives in the package
|
|
86
|
+
documents' suites.}
|
|
87
|
+
|
|
88
|
+
## Files
|
|
89
|
+
|
|
90
|
+
| Path | Role |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| `packages/{pkg}/src/{machine}/{file}.ts` | {what it holds, by name — the exports a reader is looking for} |
|
|
93
|
+
|
|
94
|
+
{One row per file this document owns — the roster is the `owns:` list, made readable. Close with
|
|
95
|
+
the inverse: "Read here, owned elsewhere:" naming the paths the body describes but another document
|
|
96
|
+
claims, each with the document that claims it. That closing line is what stops a system document
|
|
97
|
+
from quietly annexing the code it reads.}
|
|
98
|
+
|
|
99
|
+
## Related
|
|
100
|
+
|
|
101
|
+
- [AD-0NN — {the ruling}](../decisions/AD-0NN-{slug}.md) — {the decision behind this shape, the options weighed}
|
|
102
|
+
- [`{neighbour}.md`]({neighbour}.md) — {the machine on the other side of this seam}
|
|
103
|
+
- [`{feature}.md`](../../features/{feature}.md) — {what a person sees of this machine}
|
|
104
|
+
- [`{doctrine}.md`](../common/{doctrine}.md) — {the cross-cutting contract this machine answers to}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### The boundary paragraph is the genre's load-bearing section
|
|
108
|
+
|
|
109
|
+
Systems overlap: they share tables, call each other, and render into the same surfaces. Without a
|
|
110
|
+
paragraph that names the seams, two system documents describe the same stage from two angles and
|
|
111
|
+
drift apart on the first change — and a reader has no way to tell which is authoritative. So the
|
|
112
|
+
boundary paragraph is not a courtesy list of related reading; it is the statement of what this
|
|
113
|
+
document is *not*, written specifically enough that a later editor can tell where to put a fact.
|
|
114
|
+
Write it as a list of subjects with their owners — "the coordinator's tables, alarm and drive claim
|
|
115
|
+
are `harness.md`; a run's ledger row and settlement are `generation-runs.md`" — never as bare
|
|
116
|
+
links.
|
|
117
|
+
|
|
118
|
+
### Marking what is decided and unbuilt
|
|
119
|
+
|
|
120
|
+
Where the machine has a stage that is decided and not built — a predicate that selects but never
|
|
121
|
+
acts, a column that is written and never read, a door with no caller — wrap the prose in a marker
|
|
122
|
+
so the gap is machine-findable and its evidence travels with it:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
<!-- UNBUILT:START — {what is decided, where it is decided (an AD § or an owner ruling), and the
|
|
126
|
+
source evidence that it is not built: the function with no caller, the route that is not mounted,
|
|
127
|
+
the value written and never read} -->
|
|
128
|
+
{the prose describing the unbuilt stage, and what runs in its place}
|
|
129
|
+
<!-- UNBUILT:END -->
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**State what runs instead.** A machine with a hole in it still works somehow, and the workaround is
|
|
133
|
+
the fact a reader needs. **A design decided *against* carries no marker** — a marker means the work
|
|
134
|
+
is owed and absent, so using one for a rejected design turns the register of debt into a register
|
|
135
|
+
of opinions.
|
|
136
|
+
|
|
137
|
+
### `status: draft` on a system
|
|
138
|
+
|
|
139
|
+
A system document is `draft` when the **machine as a whole** does not run — the code is on disk and
|
|
140
|
+
nothing reaches it. Say so in the first section, in plain words, with the evidence: which halves
|
|
141
|
+
exist, which do not, and what a reader who invokes it actually observes. A scoped gap in a working
|
|
142
|
+
machine is not a draft: the document stays `active` and takes an UNBUILT marker at the stage that
|
|
143
|
+
has the hole.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.10",
|
|
4
4
|
"description": "Bootstrap a project with a Nurix harness — copies the harness's CLAUDE.md, skills, agents, rules, and hooks directly into the project from a bundled payload (no marketplace fetch, no network).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"agent",
|
|
43
43
|
"plugin"
|
|
44
44
|
],
|
|
45
|
-
"etnaFingerprint": "
|
|
45
|
+
"etnaFingerprint": "0fa183cce9ee"
|
|
46
46
|
}
|