@nurix/etna 0.19.16 → 0.19.17
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
CHANGED
|
@@ -64,24 +64,27 @@ The `nurixlabs` marketplace entry in `~/.claude/settings.json` is harmless to le
|
|
|
64
64
|
|
|
65
65
|
Listed by `npx --yes @nurix/etna` (no args) using the bundled `data/harness-index.json`.
|
|
66
66
|
|
|
67
|
-
|
|
|
67
|
+
| Harness | Source in etna | What it ships |
|
|
68
68
|
| --- | --- | --- |
|
|
69
69
|
| `code` | [`harness/code/`](../../harness/code/) | Governance + session agents, baseline workflow skills, the ownership-index hook (merged single-folder layout) |
|
|
70
|
-
| `kb-agi` | [`
|
|
70
|
+
| `kb-agi` | [`harness/kb-agi/`](../../harness/kb-agi/) | Knowledge-vault scaffolding |
|
|
71
71
|
|
|
72
72
|
## How it works
|
|
73
73
|
|
|
74
|
-
Each harness
|
|
74
|
+
Each harness lives in a single folder in the etna repo — `harness/<name>/`:
|
|
75
75
|
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
76
|
+
- `readme.md` — the **manifest**: identity (name, description, version, keywords) plus the shared `skills:`/`rules:`/`agents:` lists it pulls in from the top-level catalogs. Its body becomes the harness's published README.
|
|
77
|
+
- `CLAUDE.md` — the **policy**: pure policy, no frontmatter, installed as a verbatim copy at the consumer repo's root.
|
|
78
|
+
- Any owned `agents/`, `rules/`, `hooks/`, `scripts/` — purpose-built components that belong to this harness alone.
|
|
79
|
+
|
|
80
|
+
Shared root config common to every harness (`.prettierrc.json`, `.prettierignore`, `.vscode/settings.json`) lives once, in `harness/common/`, instead of duplicated per harness.
|
|
78
81
|
|
|
79
82
|
Two kinds of membership:
|
|
80
83
|
|
|
81
|
-
- **Shared, listed** — skills, rules, and agents live in the flat top-level `skills/`/`rules/`/`agents/` catalogs, reusable across
|
|
84
|
+
- **Shared, listed** — skills, rules, and agents live in the flat top-level `skills/`/`rules/`/`agents/` catalogs, reusable across harnesses. The manifest names the ones it pulls in:
|
|
82
85
|
|
|
83
86
|
```yaml
|
|
84
|
-
#
|
|
87
|
+
# harness/code/readme.md
|
|
85
88
|
---
|
|
86
89
|
name: code
|
|
87
90
|
skills: [boundary, brainstorm, documentation, workflow-mapper, design]
|
|
@@ -90,9 +93,9 @@ agents: [brainstorm, change-review, lld-mode, maintenance, performance-review]
|
|
|
90
93
|
---
|
|
91
94
|
```
|
|
92
95
|
|
|
93
|
-
- **Owned, by location** — hooks (and any unlisted, harness-specific agents) live inside the
|
|
96
|
+
- **Owned, by location** — hooks, scripts (and any unlisted, harness-specific agents) live inside the harness folder (`harness/<name>/{agents,hooks,scripts}/`). No list — membership is presence in the folder, exactly how a Claude Code plugin ships them. Shared governance agents are listed instead (above) and resolved from the `agents/` catalog, local-first; a harness can still drop its own copy beside it to override one by name.
|
|
94
97
|
|
|
95
|
-
`scripts/build-data.js` (run by `prepack`) resolves the listed skills/rules/agents from the catalogs (local-first), copies any unlisted
|
|
98
|
+
`scripts/build-data.js` (run by `prepack`) resolves the listed skills/rules/agents from the catalogs (local-first), copies any unlisted harness-owned agents plus the harness's `hooks/` and `scripts/` wholesale into `data/harnesses/<folder>/`; a listed skill/rule/agent that doesn't exist is a hard error. The marketplace channel (`.github/scripts/publish.mjs`) reads the same harness folder, so both channels resolve identical membership — and both ship the harness's hooks and scripts. The installer (`bin/etna.js`) reads from the bundle at install time; no GitHub fetch at runtime.
|
|
96
99
|
|
|
97
100
|
## Building / contributing
|
|
98
101
|
|
package/data/harness-index.json
CHANGED
|
@@ -27,7 +27,7 @@ etna authors the components it also runs and ships, so **three copies of every c
|
|
|
27
27
|
|
|
28
28
|
| Copy | Where | Role |
|
|
29
29
|
| --- | --- | --- |
|
|
30
|
-
| **Source** (canonical) | the shared catalogs — `skills/`, `agents/`, `rules/`, plus `
|
|
30
|
+
| **Source** (canonical) | the shared catalogs — `skills/`, `agents/`, `rules/`, plus `harness/*/` (each harness — its `readme.md` manifest, `CLAUDE.md` policy, and owned trees in one folder) | Edit here. Etna is the source of truth. |
|
|
31
31
|
| **Dogfood** | `.claude/skills/`, `.claude/agents/`, `.claude/rules/`, `.claude/hooks/` (git-tracked) | The subset the `etna` harness installs on itself — the copy this repo actually runs this session. |
|
|
32
32
|
| **Shipped bundle** | `packages/cli/data/harnesses/*/` (git-tracked build artifact, regenerated by `packages/cli/scripts/build-data.js`) | Generated — never hand-edit. |
|
|
33
33
|
|
|
@@ -38,7 +38,7 @@ etna authors the components it also runs and ships, so **three copies of every c
|
|
|
38
38
|
|
|
39
39
|
## Workflows
|
|
40
40
|
|
|
41
|
-
Three peer modes plus a Completion step — enter wherever the user's thinking already is. Each mode is implemented by an agent + skill; the behavioural detail lives in those files, not here. "Code" below means **authoring artifacts** — a feature LLD owns `skills/**`, `
|
|
41
|
+
Three peer modes plus a Completion step — enter wherever the user's thinking already is. Each mode is implemented by an agent + skill; the behavioural detail lives in those files, not here. "Code" below means **authoring artifacts** — a feature LLD owns `skills/**`, `harness/**`, `packages/cli/**`, not `src/`.
|
|
42
42
|
|
|
43
43
|
| Mode | Enter when | Implemented by | Exits to |
|
|
44
44
|
| --- | --- | --- | --- |
|
|
@@ -64,7 +64,7 @@ These three mechanisms keep the repo self-updating: **ownership** routes you to
|
|
|
64
64
|
|
|
65
65
|
### Ownership — route before you edit
|
|
66
66
|
|
|
67
|
-
Which doc is canonical for which paths is the **feature doc's own frontmatter**. A feature doc (flat in `docs/features/`) carries `owns:` (path globs — the only ownership key, pointing at `skills/**`, `
|
|
67
|
+
Which doc is canonical for which paths is the **feature doc's own frontmatter**. A feature doc (flat in `docs/features/`) carries `owns:` (path globs — the only ownership key, pointing at `skills/**`, `harness/**`, `packages/cli/**`, …), an optional `module:` label, `keywords:`, and `status:`. Path → doc ownership is the union of every feature doc's `owns:` globs, surfaced as the generated ownership index at session start. Architecture docs describe cross-cutting patterns and own nothing; operations docs describe procedures.
|
|
68
68
|
|
|
69
69
|
Before modifying a component in an unfamiliar area:
|
|
70
70
|
|
|
@@ -77,7 +77,7 @@ The `lld-mode` agent checks for ownership conflicts during LLD research — feat
|
|
|
77
77
|
|
|
78
78
|
etna has no db schema, wire envelope, or auth of its own — the `boundary` skill's stack mechanisms describe the contracts of the **rules etna ships**, checked in the consumer's repo, not here. etna's **own** live contracts are authoring and distribution ones, each with no static link between the two sides:
|
|
79
79
|
|
|
80
|
-
- a
|
|
80
|
+
- a harness `readme.md` manifest's `skills:` / `rules:` / `agents:` list ↔ the shared catalogs it resolves from (local-first);
|
|
81
81
|
- a component's **source ↔ `.claude/` dogfood ↔ shipped bundle** (three-way parity, per Authoring & Distribution);
|
|
82
82
|
- a hook script ↔ its `hooks.json` registration;
|
|
83
83
|
- the CLI's managed-block edits ↔ a consumer's `settings.json` / `.env`.
|
package/lib/codex/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Owning doc: [`docs/features/codex-support.md`](../../../../docs/features/codex-s
|
|
|
25
25
|
```bash
|
|
26
26
|
node packages/cli/lib/codex/gen-agents.mjs # shared catalog (agents/*.md), stale/missing only
|
|
27
27
|
node packages/cli/lib/codex/gen-agents.mjs --force # regenerate all shared agents
|
|
28
|
-
node packages/cli/lib/codex/gen-agents.mjs --include-
|
|
28
|
+
node packages/cli/lib/codex/gen-agents.mjs --include-harness # + harness/*/agents/*.md
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
`gen-agents.mjs` runs `codex exec` per agent and writes a committed `agents/<name>.codex.toml` sibling. It runs **only on a laptop with `codex` installed + authenticated — never in CI**. `build-data.js` and `publish.mjs` then ship those committed TOML; the installer copies them, so **consumers need no Codex CLI**. Regenerate an agent's TOML in the same change that edits its `.md` (source↔generated parity).
|
package/lib/codex/gen-agents.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// packages/cli/lib/codex/gen-agents.mjs
|
|
2
2
|
// AUTHORING-TIME generator — runs ON A LAPTOP with the Codex CLI installed and
|
|
3
3
|
// authenticated, NEVER in CI. For each Claude subagent (agents/<name>.md in the
|
|
4
|
-
// shared catalog, plus
|
|
4
|
+
// shared catalog, plus harness/*/agents/*.md with --include-harness) it runs
|
|
5
5
|
// `codex exec` to translate the markdown into an OpenAI Codex subagent TOML and
|
|
6
6
|
// writes a committed sibling agents/<name>.codex.toml. The shippers (build-data.js,
|
|
7
7
|
// publish.mjs) then carry those committed files; the installer copies them into a
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// Usage:
|
|
11
11
|
// node packages/cli/lib/codex/gen-agents.mjs # shared catalog, only stale/missing
|
|
12
12
|
// node packages/cli/lib/codex/gen-agents.mjs --force # regenerate all shared agents
|
|
13
|
-
// node packages/cli/lib/codex/gen-agents.mjs --include-
|
|
13
|
+
// node packages/cli/lib/codex/gen-agents.mjs --include-harness # + harness/*/agents/*.md
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
16
|
existsSync,
|
|
@@ -45,7 +45,7 @@ const CONVERSION_PROMPT = [
|
|
|
45
45
|
|
|
46
46
|
const args = process.argv.slice(2);
|
|
47
47
|
const force = args.includes('--force');
|
|
48
|
-
const
|
|
48
|
+
const includeHarness = args.includes('--include-harness');
|
|
49
49
|
|
|
50
50
|
function die(msg) {
|
|
51
51
|
console.error(`gen-codex-agents: ${msg}`);
|
|
@@ -60,7 +60,7 @@ function assertCodexReady() {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Every agents/<name>.md to convert: the shared catalog, plus
|
|
63
|
+
// Every agents/<name>.md to convert: the shared catalog, plus harness-owned agents on request.
|
|
64
64
|
function collectAgentFiles() {
|
|
65
65
|
const files = [];
|
|
66
66
|
const shared = join(repoRoot, 'agents');
|
|
@@ -69,11 +69,12 @@ function collectAgentFiles() {
|
|
|
69
69
|
if (f.endsWith('.md')) files.push(join(shared, f));
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
if (
|
|
73
|
-
const
|
|
74
|
-
if (existsSync(
|
|
75
|
-
for (const
|
|
76
|
-
|
|
72
|
+
if (includeHarness) {
|
|
73
|
+
const harnessDir = join(repoRoot, 'harness');
|
|
74
|
+
if (existsSync(harnessDir)) {
|
|
75
|
+
for (const harness of readdirSync(harnessDir)) {
|
|
76
|
+
if (harness === 'common') continue; // not a harness — the shared root-files folder
|
|
77
|
+
const agentsDir = join(harnessDir, harness, 'agents');
|
|
77
78
|
if (!existsSync(agentsDir)) continue;
|
|
78
79
|
for (const f of readdirSync(agentsDir)) {
|
|
79
80
|
if (f.endsWith('.md')) files.push(join(agentsDir, f));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.17",
|
|
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": {
|