@nurix/etna 0.19.74 → 0.19.76
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/rules/changelog.md +0 -2
- package/data/harnesses/code/rules/cloudflare.md +28 -19
- package/data/harnesses/code/rules/frontend.md +3 -3
- package/data/harnesses/code/rules/general.md +3 -3
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/rules/changelog.md +0 -2
- package/data/harnesses/etna/CLAUDE.md +10 -2
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/rules/changelog.md +0 -2
- package/data/harnesses/etna/rules/general.md +3 -3
- package/package.json +2 -2
package/data/harness-index.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "code",
|
|
3
3
|
"name": "code",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.10.2",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
"docs/memory/main.md",
|
|
16
16
|
".mcp.json"
|
|
17
17
|
],
|
|
18
|
-
"digest": "
|
|
18
|
+
"digest": "7eff5a4d7de8"
|
|
19
19
|
}
|
|
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
|
|
|
10
10
|
| The user asks for a changelog | The entry for the work in hand. No commit required |
|
|
11
11
|
| A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
|
|
12
12
|
|
|
13
|
-
An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
|
|
14
|
-
|
|
15
13
|
Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
|
|
16
14
|
|
|
17
15
|
## Lifecycle
|
|
@@ -6,29 +6,37 @@ Conventions for Cloudflare Workers — `wrangler.jsonc` setup, vars and secrets,
|
|
|
6
6
|
|
|
7
7
|
### 1.1 Wrangler version
|
|
8
8
|
|
|
9
|
-
- Use Wrangler **v4
|
|
10
|
-
- **No `package.json`** (dep-free worker): use `npx wrangler@4` in every command and doc
|
|
9
|
+
- Use Wrangler **v4**. If an editor flags valid config as invalid, check the wrangler version first.
|
|
10
|
+
- **No `package.json`** (dep-free worker): use `npx wrangler@4` in every command and doc. Never create a `package.json` just to record the version.
|
|
11
11
|
- **`package.json` exists**: pin wrangler to the exact version tested against (not `^4.0.0`), reinstall, and verify with `wrangler deploy --dry-run` before pushing.
|
|
12
12
|
|
|
13
13
|
### 1.2 Config format
|
|
14
14
|
|
|
15
15
|
- Use `wrangler.jsonc` (not `wrangler.toml`).
|
|
16
|
-
- Include `"$schema": "node_modules/wrangler/config-schema.json"
|
|
16
|
+
- Include `"$schema": "node_modules/wrangler/config-schema.json"`.
|
|
17
17
|
|
|
18
18
|
### 1.3 Comments in jsonc
|
|
19
19
|
|
|
20
20
|
None by default. Keep a comment only when it captures a non-obvious **WHY** — a hidden constraint, workaround, or account-specific quirk. Never narrate what a key already says.
|
|
21
21
|
|
|
22
|
-
### 1.4 workers.dev URLs
|
|
22
|
+
### 1.4 Public entry points — workers.dev & preview URLs
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
24
|
+
- **Don't expose on `workers.dev` by default** — it is public and guessable (`<worker>.<account>.workers.dev`). Default to `"workers_dev": false`; when a deploy is requested and no custom domain or route exists yet, warn the user that enabling it makes the Worker public and enable it only on confirmation.
|
|
25
|
+
- **`preview_urls` is a second public door** (`<version>-<worker>.<account>.workers.dev`) — `workers_dev` alone is not the whole switch. Set `"preview_urls": false` with it.
|
|
26
|
+
- Pair a custom domain with a `routes` entry using `custom_domain: true`. **The zone must be in the same account as the Worker** — a route pointing at a zone the account doesn't hold fails at deploy, so check the zone before writing the route.
|
|
27
|
+
- **Declare both keys explicitly, in the same edit that adds the route** — never leave them to the implicit default, and never delete them as redundant once a route exists.
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
> **Adding a route cuts over atomically — you cannot stage it.** The moment a `routes` entry lands, an absent `workers_dev` key disables `workers.dev` on that same deploy; "add the route now, turn it off once the custom domain answers" is not a sequence wrangler will execute. Where the certificate is slow to provision, that gap is downtime — confirm the outage window with the user before cutting over.
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
Deleting a route is likewise a cutover: `workers.dev` does not return until `"workers_dev": true` is set explicitly, and a torn-down hostname `404`s rather than redirecting — callers holding the old URL get no forwarding.
|
|
32
|
+
|
|
33
|
+
### 1.5 Default config
|
|
34
|
+
|
|
35
|
+
Every Worker carries these keys. Deviate only where a rule below says to.
|
|
30
36
|
|
|
31
37
|
```jsonc
|
|
38
|
+
"workers_dev": false,
|
|
39
|
+
"preview_urls": false,
|
|
32
40
|
"observability": {
|
|
33
41
|
"logs": {
|
|
34
42
|
"enabled": false,
|
|
@@ -37,14 +45,15 @@ Default block for every Worker:
|
|
|
37
45
|
}
|
|
38
46
|
```
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
- `workers_dev` / `preview_urls` — entry-point policy and cutover mechanics: §1.4.
|
|
49
|
+
- **Bootstrap override:** a new Worker (especially cron-only) runs `logs.enabled: true` until a few real runs look clean, then flips back — with logs off, `console.log` is live-only via `npx wrangler tail` and nothing persists after a failed run.
|
|
41
50
|
|
|
42
51
|
### 1.6 Project structure & dependencies
|
|
43
52
|
|
|
44
53
|
- Main entry file: `index.ts`. Reusable helpers: `helper.ts`.
|
|
45
|
-
- TypeScript under `strict: true` —
|
|
54
|
+
- TypeScript under `strict: true` — no build step, and a minimal `tsconfig.json` ships even in dep-free Workers.
|
|
46
55
|
- Don't run `npm run build` or `npm run deploy` in examples.
|
|
47
|
-
- **`package.json` / `package-lock.json` are opt-in
|
|
56
|
+
- **`package.json` / `package-lock.json` are opt-in.** Create them only when code under `src/` imports an npm package at runtime; add both the moment the first real dep lands. Run wrangler, linters, and one-offs via `npx <tool>`. `node_modules/` stays in `.gitignore` either way.
|
|
48
57
|
|
|
49
58
|
### 1.7 Environment & configuration
|
|
50
59
|
|
|
@@ -67,15 +76,15 @@ Access in code: `await env.CLICKUP_KEY.get()`.
|
|
|
67
76
|
|
|
68
77
|
- Repo/dir: `cf-<name>` (e.g. `cf-extract-design`).
|
|
69
78
|
- Worker name: `<name>` — repo name minus the `cf-` prefix.
|
|
70
|
-
- R2 bucket, D1 database, and KV namespace names: equal to the worker name.
|
|
79
|
+
- R2 bucket, D1 database, and KV namespace names: equal to the worker name.
|
|
71
80
|
|
|
72
81
|
### 1.10 Vars & secrets
|
|
73
82
|
|
|
74
|
-
**Non-secret vars live in the `vars` block in `wrangler.jsonc
|
|
83
|
+
**Non-secret vars live in the `vars` block in `wrangler.jsonc`**, checked in. Never move them to the dashboard. A single-tenant application Worker declares them at the top level; a multi-tenant Worker declares per-tenant vars under each `env.<tenant>` block (§11).
|
|
75
84
|
|
|
76
85
|
**Secrets never touch git.** Local dev: a gitignored `.dev.vars` (`KEY=VALUE` dotenv, auto-loaded by `wrangler dev`) with a committed `.dev.vars.example` listing the keys and placeholder values. Production: `wrangler secret put <NAME>`, a gitignored `.secrets` file pushed with `wrangler secret bulk .secrets` (or shipped with a deploy via `wrangler deploy --secrets-file .secrets`), or the Secrets Store (§1.8). Never log or echo a secret value.
|
|
77
86
|
|
|
78
|
-
**No `keep_vars
|
|
87
|
+
**No `keep_vars`** — leave it unset. It guards only plaintext vars set out-of-band in the dashboard and never touches secrets; `wrangler secret put` secrets survive every deploy regardless, so never add it to protect them. Only the multi-tenant pattern sets `keep_vars: true` (§11).
|
|
79
88
|
|
|
80
89
|
**Never name a deployed-value file `.env` or `.env.<anything>`** — `wrangler dev` auto-loads a root `.env` as local dev vars, so a prod-valued `.env` silently becomes the local environment on a fresh clone or in CI. Committed `*.example` files carry keys with placeholder values only.
|
|
81
90
|
|
|
@@ -83,11 +92,11 @@ Access in code: `await env.CLICKUP_KEY.get()`.
|
|
|
83
92
|
|
|
84
93
|
### 1.11 Deploys
|
|
85
94
|
|
|
86
|
-
**Never auto-deploy.** `wrangler deploy` (any variant — `--env`, `versions upload
|
|
95
|
+
**Never auto-deploy.** `wrangler deploy` (any variant — `--env`, `versions upload`) runs only when the user explicitly asks. Building, dry-running (`wrangler deploy --dry-run`), and `wrangler dev` are fine unprompted. Finish the change, then tell the user it's ready to deploy.
|
|
87
96
|
|
|
88
97
|
## 2. Code & Helpers
|
|
89
98
|
|
|
90
|
-
- Use `generateUuidV7()` in `helper.ts` for IDs
|
|
99
|
+
- Use `generateUuidV7()` in `helper.ts` for IDs.
|
|
91
100
|
- Only `await` what's needed (e.g. `request.json()`, `do.fetch(...)`).
|
|
92
101
|
|
|
93
102
|
## 3. fetch() Structure
|
|
@@ -159,13 +168,13 @@ Follows the shared database naming and column-type vocabulary; what earns a tabl
|
|
|
159
168
|
|
|
160
169
|
## 11. Multi-tenant Workers (native environments)
|
|
161
170
|
|
|
162
|
-
Rare — only when **one Worker codebase ships as several independent tenants
|
|
171
|
+
Rare — only when **one Worker codebase ships as several independent tenants**: separate Workers, domains, and data stores from a single `src/`. Use **native wrangler environments**, never one Worker that switches tenant at runtime. For a single-tenant application Worker, §1.10 applies and this section does not.
|
|
163
172
|
|
|
164
173
|
- **One config, `env.<tenant>` blocks.** The top-level block is **local dev** (`wrangler dev`): a `*-dev` name and placeholder D1/KV ids, simulated locally. Each `env.<tenant>` block is **one production tenant**; deploy it with `wrangler deploy --env <tenant>`.
|
|
165
174
|
- **Named environments never inherit** `vars` / `d1_databases` / `kv_namespaces` / `routes` / `secrets_store_secrets` / `assets` from the top level — **each `env.<tenant>` declares them in full**. Dropping a binding from an env block disables that capability for that one tenant.
|
|
166
|
-
- **Per-tenant non-secret vars live in `env.<tenant>.vars
|
|
175
|
+
- **Per-tenant non-secret vars live in `env.<tenant>.vars`**, checked in.
|
|
167
176
|
- **Local-dev vars** come from a gitignored `.vars.local`, injected as `--var` by the dev script (the top-level block carries no in-config `vars`).
|
|
168
177
|
- **Per-tenant secrets, never in git** — `wrangler secret put <NAME> --env <tenant>`, or a gitignored per-tenant `.secrets` (e.g. `worker/tenants/<tenant>/.secrets`) pushed with `wrangler secret bulk --env <tenant>`, plus a committed `.secrets.example`. Secrets Store bindings are declared inside each env block.
|
|
169
178
|
- **`keep_vars: true`** (top level) keeps a per-tenant deploy **additive**: tenants inject their non-secret vars via `--var` (or the dashboard), and without it a deploy would wipe them. On secrets it changes nothing (§1.10).
|
|
170
179
|
|
|
171
|
-
`.gitignore`: `.vars.local
|
|
180
|
+
`.gitignore`: §1.10's list, with `.vars.local` in place of `.dev.vars`.
|
|
@@ -25,6 +25,6 @@ Every package compiles under `strict: true` and `noUncheckedIndexedAccess: true`
|
|
|
25
25
|
|
|
26
26
|
Shared libraries (`@nurix/components`, etc.) are generic on purpose — that's what types `cell(row)`, checks `slug` against `keyof TData`, and ties `data`/`columns` together; **never** widen to `any` to dodge it. State the row type **once per file** and let inference carry it — repeating `fn<Type>(…)` / `<Comp<Type>>` per call site is cosmetic (same safety, same emitted JS):
|
|
27
27
|
|
|
28
|
-
- **Bind a repeated factory once** (preferred): `const col = defineColumn<
|
|
29
|
-
- **Infer JSX type args from props:** `<Table data={rows} columns={columns} />`, not `<Table<
|
|
30
|
-
- **Anchor with a collection annotation** when nothing else can: `const columns: ColumnDefinition<
|
|
28
|
+
- **Bind a repeated factory once** (preferred): `const col = defineColumn<Row>;` → `col({...})`.
|
|
29
|
+
- **Infer JSX type args from props:** `<Table data={rows} columns={columns} />`, not `<Table<Row> …>`.
|
|
30
|
+
- **Anchor with a collection annotation** when nothing else can: `const columns: ColumnDefinition<Row>[] = [...]`.
|
|
@@ -4,13 +4,13 @@ Runtime versions, package policy, the API response envelope, and GitHub Actions
|
|
|
4
4
|
|
|
5
5
|
## Runtime Versions
|
|
6
6
|
|
|
7
|
-
- **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` —
|
|
7
|
+
- **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — never a hardcoded number anywhere.
|
|
8
8
|
- **Package manager:** detect from the lockfile — **never** hardcode one.
|
|
9
9
|
- **PostgreSQL:** 17 · **Redis:** 7.x (latest)
|
|
10
10
|
|
|
11
11
|
## Packages
|
|
12
12
|
|
|
13
|
-
**Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
|
|
13
|
+
**Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
|
|
14
14
|
|
|
15
15
|
## API Response Envelope
|
|
16
16
|
|
|
@@ -37,4 +37,4 @@ Pin the major, and check it against the action's releases — a major behind sti
|
|
|
37
37
|
| `actions/checkout` | v7 | Repo checkout |
|
|
38
38
|
| `actions/setup-node` | v7 | Node toolchain + npm cache |
|
|
39
39
|
|
|
40
|
-
Set `node-version` via `node-version-file: .nvmrc`, **never**
|
|
40
|
+
Set `node-version` via `node-version-file: .nvmrc`, **never** the runner's default.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "delivery",
|
|
3
3
|
"name": "delivery",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.14",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
8
8
|
".vscode/settings.json"
|
|
9
9
|
],
|
|
10
10
|
"seeds": [],
|
|
11
|
-
"digest": "
|
|
11
|
+
"digest": "3ef9954da94f"
|
|
12
12
|
}
|
|
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
|
|
|
10
10
|
| The user asks for a changelog | The entry for the work in hand. No commit required |
|
|
11
11
|
| A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
|
|
12
12
|
|
|
13
|
-
An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
|
|
14
|
-
|
|
15
13
|
Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
|
|
16
14
|
|
|
17
15
|
## Lifecycle
|
|
@@ -178,9 +178,17 @@ The single policy for sub-agent dispatch — when to fan out, at what tier, and
|
|
|
178
178
|
|
|
179
179
|
## Authoring Conventions
|
|
180
180
|
|
|
181
|
-
Most artifacts are markdown — skills, agents, rules, docs. Follow the
|
|
181
|
+
Most artifacts are markdown — skills, agents, rules, docs. Follow the `kb` / `nomenclature` rules; markdown has no file-path-comment rule. Keep the `.claude/rules/*` reference docs frontmatter-free.
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
**Each artifact class has an authoring guide — read the one you are editing, before you edit it.** The forge is the only repo that authors these, so the guides live here and ship nowhere:
|
|
184
|
+
|
|
185
|
+
| Editing | Guide |
|
|
186
|
+
| --- | --- |
|
|
187
|
+
| A **rule** (`rules/*.md`) | [`docs/architecture/rules.md`](docs/architecture/rules.md) — the catalog, the conventions, and the whole-file audit |
|
|
188
|
+
| A **skill** (`skills/*/`) | [`docs/architecture/skills/playbook/`](docs/architecture/skills/playbook/Readme.md) — fit and scope through shipping and maintenance |
|
|
189
|
+
| An **agent** (`agents/*.md`) | [`docs/architecture/harness/authoring-agents.md`](docs/architecture/harness/authoring-agents.md) |
|
|
190
|
+
|
|
191
|
+
Authoring or updating an **agent** keeps both runtimes in sync: the `.md` is the single source, and its Codex `.codex.toml` twin is derived from it by the guide above, then checked with `node packages/cli/lib/codex/validate-codex-agents.mjs`.
|
|
184
192
|
|
|
185
193
|
For real code (the CLI under `packages/`, hook scripts):
|
|
186
194
|
|
|
@@ -10,8 +10,6 @@ Every unit of work leaves one record — `docs/history/changelog/YYYY-MM-DD-{thr
|
|
|
10
10
|
| The user asks for a changelog | The entry for the work in hand. No commit required |
|
|
11
11
|
| A commit is made | Every non-exempt commit is covered by an entry — the `commit` skill writes or completes it (no `commit` skill in the runtime ⇒ write the entry from the `documentation` skill's `templates/changelog-entry.md` and stage it with the commit) |
|
|
12
12
|
|
|
13
|
-
An entry is owed only by work that changes promised behavior or takes a design decision; mechanical and cosmetic commits — a typo, a copy tweak, a config value, a log line — take only their `docs/history/CHANGELOG.md` row, no entry file. The failure fields (`Ask:`, `Skills:`, `Pin:`) are required only when non-none.
|
|
14
|
-
|
|
15
13
|
Route the lesson by who pays for losing it: product context — what changed and why — belongs in the entry; anything the **next session would re-pay** — a library's API drifted from what the model expects, a validator's quirk, a tooling workaround — goes to `docs/memory/main.md` as well, because a changelog is read by people tracing history and memory is read by every session before it repeats the mistake.
|
|
16
14
|
|
|
17
15
|
## Lifecycle
|
|
@@ -4,13 +4,13 @@ Runtime versions, package policy, the API response envelope, and GitHub Actions
|
|
|
4
4
|
|
|
5
5
|
## Runtime Versions
|
|
6
6
|
|
|
7
|
-
- **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` —
|
|
7
|
+
- **Node.js:** the version pinned in `.nvmrc` / `package.json` `engines` — never a hardcoded number anywhere.
|
|
8
8
|
- **Package manager:** detect from the lockfile — **never** hardcode one.
|
|
9
9
|
- **PostgreSQL:** 17 · **Redis:** 7.x (latest)
|
|
10
10
|
|
|
11
11
|
## Packages
|
|
12
12
|
|
|
13
|
-
**Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
|
|
13
|
+
**Only packages in the approved table** — `.claude/hooks/approved-packages.md`, enforced by the PreToolUse install gate, which names the file on a block. The table changes only by explicit user decision.
|
|
14
14
|
|
|
15
15
|
## API Response Envelope
|
|
16
16
|
|
|
@@ -37,4 +37,4 @@ Pin the major, and check it against the action's releases — a major behind sti
|
|
|
37
37
|
| `actions/checkout` | v7 | Repo checkout |
|
|
38
38
|
| `actions/setup-node` | v7 | Node toolchain + npm cache |
|
|
39
39
|
|
|
40
|
-
Set `node-version` via `node-version-file: .nvmrc`, **never**
|
|
40
|
+
Set `node-version` via `node-version-file: .nvmrc`, **never** the runner's default.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.76",
|
|
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": "ae6ba8fb523a"
|
|
46
46
|
}
|