@nurix/etna 0.20.24 → 0.20.25
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/CLAUDE.md +1 -1
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/hooks/hooks.json +4 -4
- package/data/harnesses/code/skills/design/components/index.md +1 -1
- package/data/harnesses/code/skills/documentation/SKILL.md +1 -1
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/hooks/hooks.json +1 -1
- package/data/harnesses/delivery/skills/documentation/SKILL.md +1 -1
- package/data/harnesses/discussion/harness.json +2 -2
- package/data/harnesses/discussion/hooks/hooks.json +1 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/hooks/hooks.json +1 -1
- package/data/harnesses/etna/skills/documentation/SKILL.md +1 -1
- package/lib/install/materialize.mjs +14 -2
- package/package.json +2 -2
package/data/harness-index.json
CHANGED
|
@@ -157,7 +157,7 @@ Defaults — ❌ prohibitions hold unless the user explicitly asks otherwise;
|
|
|
157
157
|
- ✅ **Verification** — batched at the gate, never continuous, and the gate is the build's last step, never a separate ask; the regimes and the gate are `.claude/rules/testing.md`, the procedure the `testing` skill (gate mode).
|
|
158
158
|
- ❌ **Dependencies** – Never upgrade pinned packages without asking; security patches and test-tooling installs at `latest` (`testing.md`) are exempt.
|
|
159
159
|
- ❌ **Compatibility** – Never maintain backward compatibility unless specified.
|
|
160
|
-
- ❌ **Branches & Worktrees [override]** –
|
|
160
|
+
- ❌ **Branches & Worktrees [override]** – `dev` and `production` are merge-only. Work on a short-lived branch cut from `dev` (`feat/<slug>`, `fix/<slug>`, `docs/<slug>`; `hotfix/<slug>` off `production`), commit there, and open a pull request into `dev` (or `production` for a hotfix) — never commit to either long-lived branch, and never create a worktree. The branch is created when the first commit is due, not at session start. This replaces any built-in "branch first on the default branch" default: the branch is required, and it is never `main`.
|
|
161
161
|
- ❌ **Protected Files** – Once per session, if `docs/operations/protected-files.md` exists, read it and never modify any path it lists; never modify `AGENTS.md` (harness-regenerated) or `protected-files.md` itself.
|
|
162
162
|
- ✅ **Browser Automation** – If the runtime provides browser automation, use it freely; no need to ask first. If it doesn't — or the executing agent can't hold the browser connection (see Runtime Notes) — return a browser-verification checklist (URLs, actions, expected outcomes) for the orchestrating session or the user to run.
|
|
163
163
|
- ✅ **Bookkeeping [override]** — dispatching outranks a runtime default that reserves sub-agents for explicit requests (§ Delegation), and `hooks/compliance.mjs` enforces it: Stop is blocked on unresolved rows unless the transcript carries a real `subagent_type: bookkeeper` record. Hooks append doc-debt rows to `docs/operations/bookkeeping.md`; three walls read it at three widths (Stop = your session's rows · commit = rows implicating staged files · CI = all), each re-verifying conditions at gate time. Dispatch the `bookkeeper` for your rows — **never drain `auto:`/`note:` rows in your own loop**, whichever agent you are: the drain is dispatched work at every nesting level (a sub-agent dispatches its own `bookkeeper` — § Delegation), and only `needs-session:` rows are yours to resolve directly. A drained row is **deleted**. The full grammar arrives in the deny message when a wall fires.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "code",
|
|
3
3
|
"name": "code",
|
|
4
|
-
"version": "3.19.
|
|
4
|
+
"version": "3.19.3",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
}
|
|
26
26
|
],
|
|
27
27
|
"docsRoot": "docs",
|
|
28
|
-
"digest": "
|
|
28
|
+
"digest": "5181bf532ddd"
|
|
29
29
|
}
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
},
|
|
9
9
|
"hooks": {
|
|
10
10
|
"SessionStart": [
|
|
11
|
-
{ "matcher": "", "hooks": [ { "type": "command", "command": "
|
|
11
|
+
{ "matcher": "", "hooks": [ { "type": "command", "command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/awareness.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"", "timeout": 10 } ] }
|
|
12
12
|
],
|
|
13
13
|
"PostToolUse": [
|
|
14
|
-
{ "matcher": "Edit|Write|MultiEdit|Bash", "hooks": [ { "type": "command", "command": "
|
|
14
|
+
{ "matcher": "Edit|Write|MultiEdit|Bash", "hooks": [ { "type": "command", "command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/awareness.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"", "timeout": 10 }, { "type": "command", "command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/build-graph.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"", "timeout": 10 } ] }
|
|
15
15
|
],
|
|
16
16
|
"PreToolUse": [
|
|
17
|
-
{ "matcher": "Edit|Write|MultiEdit|Bash", "hooks": [ { "type": "command", "command": "
|
|
17
|
+
{ "matcher": "Edit|Write|MultiEdit|Bash", "hooks": [ { "type": "command", "command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/compliance.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"", "timeout": 10 } ] }
|
|
18
18
|
],
|
|
19
19
|
"Stop": [
|
|
20
|
-
{ "matcher": "", "hooks": [ { "type": "command", "command": "
|
|
20
|
+
{ "matcher": "", "hooks": [ { "type": "command", "command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/compliance.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"", "timeout": 15 } ] }
|
|
21
21
|
]
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component catalog — the fused index
|
|
2
2
|
|
|
3
|
-
> **Generated folder — never hand-edit.** Everything under `skills/design/components/` is emitted by the components-repo regen instruction set (`docs/
|
|
3
|
+
> **Generated folder — never hand-edit.** Everything under `skills/design/components/` is emitted by the components-repo regen instruction set (`docs/skills/design/components-regen-spec.md`, run against the `@nurix/components` library checkout). Regeneration may reshape any file beneath this one; the design skill's only seam with this folder is this index.
|
|
4
4
|
|
|
5
5
|
**Load contract.** This index loads in **both** positions of the project's `primitives` switch (`design.md`, `primitives: nurix | native`) — it is how the skill knows what chrome *exists* to compose with. The per-category deep references beside it ([inputs](inputs.md), [overlays](overlays.md), [collections](collections.md), [navigation](navigation.md), [layout](layout.md), [feedback](feedback.md), [charts](charts.md), [typography](typography.md), [media](media.md), [motion](motion.md), [hooks](hooks.md), [utils](utils.md), plus [setup](setup.md) for install/Tailwind wiring) load **only under `primitives: nurix`**, and only when that category is touched.
|
|
6
6
|
|
|
@@ -113,7 +113,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
113
113
|
| Derive/update an owning doc's `owns:` (feature, package, system) | [`references/frontmatter.md`](references/frontmatter.md) |
|
|
114
114
|
| Update existing doc | § Editing an existing doc (below) |
|
|
115
115
|
| Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | [`references/instruction-style.md`](references/instruction-style.md) — not these templates; every-load prose stays lean, and the present-tense rule still applies |
|
|
116
|
-
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`
|
|
116
|
+
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`13`. **No etna checkout available ⇒ ask the user for access to the etna repo, or proceed from first principles** with [`references/instruction-style.md`](references/instruction-style.md) governing the prose. This row is the only place the playbook is referenced |
|
|
117
117
|
| **No template matches** | [`references/untemplated.md`](references/untemplated.md) — shape decisions + the co-authoring workflow |
|
|
118
118
|
|
|
119
119
|
---
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "delivery",
|
|
3
3
|
"name": "delivery",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.36",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -10,5 +10,5 @@
|
|
|
10
10
|
"seeds": [],
|
|
11
11
|
"tools": [],
|
|
12
12
|
"docsRoot": "docs",
|
|
13
|
-
"digest": "
|
|
13
|
+
"digest": "c2d4fb33502b"
|
|
14
14
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/generate-ownership-index.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"",
|
|
10
10
|
"timeout": 10
|
|
11
11
|
}
|
|
12
12
|
]
|
|
@@ -113,7 +113,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
113
113
|
| Derive/update an owning doc's `owns:` (feature, package, system) | [`references/frontmatter.md`](references/frontmatter.md) |
|
|
114
114
|
| Update existing doc | § Editing an existing doc (below) |
|
|
115
115
|
| Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | [`references/instruction-style.md`](references/instruction-style.md) — not these templates; every-load prose stays lean, and the present-tense rule still applies |
|
|
116
|
-
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`
|
|
116
|
+
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`13`. **No etna checkout available ⇒ ask the user for access to the etna repo, or proceed from first principles** with [`references/instruction-style.md`](references/instruction-style.md) governing the prose. This row is the only place the playbook is referenced |
|
|
117
117
|
| **No template matches** | [`references/untemplated.md`](references/untemplated.md) — shape decisions + the co-authoring workflow |
|
|
118
118
|
|
|
119
119
|
---
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "discussion",
|
|
3
3
|
"name": "discussion",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -10,5 +10,5 @@
|
|
|
10
10
|
"seeds": [],
|
|
11
11
|
"tools": [],
|
|
12
12
|
"docsRoot": "docs",
|
|
13
|
-
"digest": "
|
|
13
|
+
"digest": "ed9548ee592a"
|
|
14
14
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "
|
|
8
|
+
"command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/update-topics.sh\"; [ -f \"$f\" ] || exit 0; bash \"$f\"",
|
|
9
9
|
"timeout": 15,
|
|
10
10
|
"statusMessage": "Syncing workspace metadata"
|
|
11
11
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "etna",
|
|
3
3
|
"name": "etna",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.26",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -10,5 +10,5 @@
|
|
|
10
10
|
"seeds": [],
|
|
11
11
|
"tools": [],
|
|
12
12
|
"docsRoot": "docs",
|
|
13
|
-
"digest": "
|
|
13
|
+
"digest": "6448aac5edb5"
|
|
14
14
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "f=\"$CLAUDE_PROJECT_DIR/.claude/hooks/generate-ownership-index.mjs\"; [ -f \"$f\" ] || exit 0; node \"$f\"",
|
|
10
10
|
"timeout": 10
|
|
11
11
|
}
|
|
12
12
|
]
|
|
@@ -113,7 +113,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
113
113
|
| Derive/update an owning doc's `owns:` (feature, package, system) | [`references/frontmatter.md`](references/frontmatter.md) |
|
|
114
114
|
| Update existing doc | § Editing an existing doc (below) |
|
|
115
115
|
| Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | [`references/instruction-style.md`](references/instruction-style.md) — not these templates; every-load prose stays lean, and the present-tense rule still applies |
|
|
116
|
-
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`
|
|
116
|
+
| Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`13`. **No etna checkout available ⇒ ask the user for access to the etna repo, or proceed from first principles** with [`references/instruction-style.md`](references/instruction-style.md) governing the prose. This row is the only place the playbook is referenced |
|
|
117
117
|
| **No template matches** | [`references/untemplated.md`](references/untemplated.md) — shape decisions + the co-authoring workflow |
|
|
118
118
|
|
|
119
119
|
---
|
|
@@ -227,10 +227,19 @@ function groupHasCommand(group, command) {
|
|
|
227
227
|
return (group.hooks || []).some((h) => h.command === command);
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
// The harness script a hook command runs, by its `.claude/hooks/<name>` path — the identity
|
|
231
|
+
// that survives a change to the command's shape. Null for a command that runs no such script.
|
|
232
|
+
function hookScript(command) {
|
|
233
|
+
const found = /\.claude\/hooks\/([\w.-]+)/.exec(command || '');
|
|
234
|
+
return found ? found[1] : null;
|
|
235
|
+
}
|
|
236
|
+
|
|
230
237
|
// Deep-merge the bundle's hooks.json object into <project>/.claude/settings.json under
|
|
231
238
|
// "hooks", preserving every existing key. Idempotent: for each event, an incoming entry
|
|
232
239
|
// merges into the matcher-group of the same matcher, skipping any hook whose command
|
|
233
|
-
// already exists there; a
|
|
240
|
+
// already exists there; a hook already registered for the same script under an older command
|
|
241
|
+
// shape is replaced in place, never doubled; a new matcher creates a new group. Returns the
|
|
242
|
+
// count of hooks added or replaced.
|
|
234
243
|
function mergeHooks(targetDir, bundledHooksJson) {
|
|
235
244
|
if (!existsSync(bundledHooksJson)) return 0;
|
|
236
245
|
const bundled = readJson(bundledHooksJson);
|
|
@@ -261,7 +270,10 @@ function mergeHooks(targetDir, bundledHooksJson) {
|
|
|
261
270
|
match.hooks = match.hooks || [];
|
|
262
271
|
for (const hook of group.hooks || []) {
|
|
263
272
|
if (groupHasCommand(match, hook.command)) continue;
|
|
264
|
-
|
|
273
|
+
const script = hookScript(hook.command);
|
|
274
|
+
const staleIndex = script ? match.hooks.findIndex((h) => hookScript(h.command) === script) : -1;
|
|
275
|
+
if (staleIndex === -1) match.hooks.push(hook);
|
|
276
|
+
else match.hooks[staleIndex] = hook;
|
|
265
277
|
added += 1;
|
|
266
278
|
}
|
|
267
279
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.25",
|
|
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": "c24bc6f1af10"
|
|
46
46
|
}
|