@nurix/etna 0.19.48 → 0.19.49

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/bin/etna.js CHANGED
@@ -318,7 +318,7 @@ function mergeHooks(targetDir, bundledHooksJson) {
318
318
  const settings = readJson(settingsPath);
319
319
  settings.hooks = settings.hooks || {};
320
320
  let added = 0;
321
- // Harness-shipped permission defaults (e.g. Edit/Write on docs/** flow without prompts —
321
+ // Harness-shipped permission defaults (e.g. Edit on docs/** flows without prompts —
322
322
  // the deny hooks still hard-block frozen/protected paths underneath). Additive, idempotent.
323
323
  for (const rule of bundled.permissions?.allow || []) {
324
324
  settings.permissions = settings.permissions || {};
@@ -1,5 +1,5 @@
1
1
  {
2
- "fingerprint": "6af99ea8c41f",
2
+ "fingerprint": "889424d916fc",
3
3
  "harnesses": {
4
4
  "apollo": {
5
5
  "plugin": "apollo",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "harness": "apollo",
3
3
  "name": "apollo",
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
@@ -14,5 +14,5 @@
14
14
  "docs/history/backlog.md",
15
15
  "docs/memory/main.md"
16
16
  ],
17
- "digest": "5d04f43486c8"
17
+ "digest": "113c398c1e31"
18
18
  }
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Edit(docs/**)",
5
- "Write(docs/**)"
4
+ "Edit(docs/**)"
6
5
  ]
7
6
  },
8
7
  "hooks": {
@@ -50,6 +50,28 @@ Derive the stack first, then place tests: a placement argument that starts "this
50
50
 
51
51
  Why this is the cheap strategy at the horizon: layering makes cost **additive** — a new API behavior costs one layer-2 test and maybe a layer-3 edge, zero frontend tests; a new UI state costs one layer-7 test, zero backend tests. A flat suite pays N×M, because every top-layer path implicitly re-verifies every behavior beneath it.
52
52
 
53
+ ## The tree
54
+
55
+ The directory layout follows the strata, so a test's home states its layer and the runner split is mechanical, not per-file judgment:
56
+
57
+ ```
58
+ tests/
59
+ schema/ L1 — infrastructure-bound runner (real engine)
60
+ domain/ L2 — infrastructure-bound runner (real storage, modeled ports)
61
+ routes/ L3 — infrastructure-bound runner (in-process app)
62
+ contract/ L4 — no runner; typed fixtures + interception handlers
63
+ client/ L5 — plain unit runner
64
+ view/ L6 — plain unit runner
65
+ component/ L7 — unit runner + DOM environment (per-file opt-in)
66
+ helpers/ shared seeds, fakes, and builders — owned by no stratum
67
+ e2e/ L8 — its own config, never mixed into the unit runner's glob
68
+ ```
69
+
70
+ - **A stratum the app lacks gets no directory** — an empty `component/` in a backend service is a lie about the app's shape.
71
+ - **One shared glob list, imported by both runner configs** — the infrastructure-bound runner *includes* `schema|domain|routes`, the unit runner *excludes* them. Two hand-maintained lists drift; one imported constant cannot.
72
+ - **Which concrete runner, framework, and DOM environment fill these slots is `testing.md`'s per-stack table** — this skill names the slot, never the brand, so the two files cannot disagree.
73
+ - **Contract modules the provider binds** (the layer-4 source types) live in the app's shared source zone — importable by both provider and consumer builds — not in the test tree; `tests/contract/` holds only the fixtures and fakes compiled from them.
74
+
53
75
  ## Bridge to the obligation ledger
54
76
 
55
77
  The `test-plan` skill's ledger assigns each obligation a runner altitude — `unit` / `component` / `integration` / `e2e`. Those are coarse names for where a test *runs*; the strata here say what it may *assert*. The mapping:
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "harness": "code",
3
3
  "name": "code",
4
- "version": "3.6.0",
4
+ "version": "3.6.1",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
10
  "seeds": [],
11
- "digest": "d1663c2f882b"
11
+ "digest": "0efadb49b336"
12
12
  }
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Edit(docs/**)",
5
- "Write(docs/**)"
4
+ "Edit(docs/**)"
6
5
  ]
7
6
  },
8
7
  "hooks": {
@@ -50,6 +50,28 @@ Derive the stack first, then place tests: a placement argument that starts "this
50
50
 
51
51
  Why this is the cheap strategy at the horizon: layering makes cost **additive** — a new API behavior costs one layer-2 test and maybe a layer-3 edge, zero frontend tests; a new UI state costs one layer-7 test, zero backend tests. A flat suite pays N×M, because every top-layer path implicitly re-verifies every behavior beneath it.
52
52
 
53
+ ## The tree
54
+
55
+ The directory layout follows the strata, so a test's home states its layer and the runner split is mechanical, not per-file judgment:
56
+
57
+ ```
58
+ tests/
59
+ schema/ L1 — infrastructure-bound runner (real engine)
60
+ domain/ L2 — infrastructure-bound runner (real storage, modeled ports)
61
+ routes/ L3 — infrastructure-bound runner (in-process app)
62
+ contract/ L4 — no runner; typed fixtures + interception handlers
63
+ client/ L5 — plain unit runner
64
+ view/ L6 — plain unit runner
65
+ component/ L7 — unit runner + DOM environment (per-file opt-in)
66
+ helpers/ shared seeds, fakes, and builders — owned by no stratum
67
+ e2e/ L8 — its own config, never mixed into the unit runner's glob
68
+ ```
69
+
70
+ - **A stratum the app lacks gets no directory** — an empty `component/` in a backend service is a lie about the app's shape.
71
+ - **One shared glob list, imported by both runner configs** — the infrastructure-bound runner *includes* `schema|domain|routes`, the unit runner *excludes* them. Two hand-maintained lists drift; one imported constant cannot.
72
+ - **Which concrete runner, framework, and DOM environment fill these slots is `testing.md`'s per-stack table** — this skill names the slot, never the brand, so the two files cannot disagree.
73
+ - **Contract modules the provider binds** (the layer-4 source types) live in the app's shared source zone — importable by both provider and consumer builds — not in the test tree; `tests/contract/` holds only the fixtures and fakes compiled from them.
74
+
53
75
  ## Bridge to the obligation ledger
54
76
 
55
77
  The `test-plan` skill's ledger assigns each obligation a runner altitude — `unit` / `component` / `integration` / `e2e`. Those are coarse names for where a test *runs*; the strata here say what it may *assert*. The mapping:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nurix/etna",
3
- "version": "0.19.48",
3
+ "version": "0.19.49",
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": "6af99ea8c41f"
45
+ "etnaFingerprint": "889424d916fc"
46
46
  }