@piercebarney/whs-eleventy 2026.10.21 → 2026.10.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piercebarney/whs-eleventy",
3
- "version": "2026.10.21",
3
+ "version": "2026.10.23",
4
4
  "description": "The web house style's Eleventy + Netlify tooling — the compliance sweep, the infra doctor, the link/CSP integrity check, and the a11y scan, shared by every project on the stack.",
5
5
  "bin": {
6
6
  "whs": "cli.js"
@@ -31,7 +31,7 @@
31
31
  "node": ">=22"
32
32
  },
33
33
  "dependencies": {
34
- "@piercebarney/whs-core": ">=2026.10.21",
34
+ "@piercebarney/whs-core": ">=2026.10.23",
35
35
  "node-html-parser": "^9.0.2"
36
36
  },
37
37
  "devDependencies": {
@@ -23,6 +23,266 @@ enforced, new *opt-in* chapters/capabilities, tooling-only changes — is
23
23
 
24
24
  ---
25
25
 
26
+ ## 2026-10-23 [non-breaking]
27
+
28
+ Release 2b's first slice of SvelteKit stack parity
29
+ (`BACKLOG.md#sveltekit-tooling-parity`): a status-only `@piercebarney/whs-sveltekit`
30
+ package, `/whs:upgrade` for this stack, and the `SessionStart` drift hook —
31
+ the same shape Eleventy's own drift tooling has, minus the compliance sweep
32
+ (still to come). No behaviour change for Eleventy or Phoenix.
33
+
34
+ **Action for SvelteKit projects (one-time bootstrap):** a project scaffolded
35
+ before this release predates `/whs:upgrade`. Copy
36
+ `templates/sveltekit-netlify/.claude/commands/whs/upgrade.md` and
37
+ `templates/sveltekit-netlify/.claude/hooks/standard-drift.sh` into the
38
+ project verbatim, add the `SessionStart` hook entry from
39
+ `templates/sveltekit-netlify/.claude/settings.json` to the project's own
40
+ `.claude/settings.json` (merged in without disturbing any other hook already
41
+ configured there), add `"@piercebarney/whs-sveltekit": ">=2026.10.23"` to
42
+ `devDependencies` and `"status": "whs status"` to `scripts` in
43
+ `package.json`, then `npm install`. After this one-time step, `/whs:upgrade`
44
+ handles every later release on its own.
45
+
46
+ ### packages/whs-sveltekit (new)
47
+
48
+ A new, thin per-stack npm package (`@piercebarney/whs-sveltekit`,
49
+ `>=2026.10.23` on `@piercebarney/whs-core`) — status only. `cli.js` supports
50
+ `status` and `--version` (an unknown subcommand prints usage, matching
51
+ `whs-eleventy`'s). `lib/status.js` wires `@piercebarney/whs-core`'s
52
+ stack-agnostic `runStatus` with `instructionsFile: "AGENTS.md"`,
53
+ `toolingName: "@piercebarney/whs-sveltekit"`, `bindingMarkers` for
54
+ `### stacks/sveltekit-netlify.md`, `### stacks/sveltekit-netlify`, the
55
+ legacy `### stacks/sveltekit.md`, `### templates/sveltekit-netlify`,
56
+ `### packages/whs-sveltekit`, and `### packages/whs-core`, no dashboard
57
+ (`null` loader), and an `upgradeHint` that names the bootstrap copy steps
58
+ above when `.claude/commands/whs/upgrade.md` is absent from the project. No
59
+ `compliance`, `doctor`, `a11y`, or link-check command exists yet — see
60
+ `stacks/sveltekit-netlify.md#compliance` and the remaining scope on
61
+ `BACKLOG.md#sveltekit-tooling-parity`. Tests cover: the pin read from
62
+ `AGENTS.md`, SvelteKit sections surfacing while Eleventy-only sections
63
+ don't, hook silence when current, and the `--version` string.
64
+
65
+ ### templates/sveltekit-netlify
66
+
67
+ - `package.json` — `devDependencies` gains
68
+ `"@piercebarney/whs-sveltekit": "file:../../packages/whs-sveltekit"` and
69
+ `scripts` gains `"status": "whs status"`.
70
+ - `.claude/hooks/standard-drift.sh` (new) — the same best-effort,
71
+ never-blocking `SessionStart` drift check Eleventy's own hook runs, via
72
+ `node_modules/.bin/whs status --hook`.
73
+ - `.claude/settings.json` — a `SessionStart` entry running the new hook,
74
+ keeping every hook already configured there.
75
+ - `.claude/commands/whs/upgrade.md` (new) — adapted from Eleventy's: reads
76
+ the `### core:`, `### stacks/sveltekit-netlify(.md)`,
77
+ `### templates/sveltekit-netlify`, `### packages/whs-sveltekit`,
78
+ `### packages/whs-core`, and `### module: <name>` CHANGELOG headings in
79
+ scope; step 3 builds its backlog from `npm run status`'s re-check rows
80
+ plus each in-scope entry's own "action for projects" prose, since no
81
+ `npm run compliance` exists yet (says so plainly, points at
82
+ `BACKLOG.md#sveltekit-tooling-parity`); the rest of the flow (agents,
83
+ block-or-proceed, verify, re-pin, never deploys) is unchanged from
84
+ Eleventy's.
85
+ - `bin/init` — a new `pinTooling()` rewrites the `file:` dev dependency on
86
+ `@piercebarney/whs-sveltekit` to a `>=<dotted pin>` range matching
87
+ `AGENTS.md`'s `standard-version` and drops the lockfile before
88
+ `npm install`, same fix as Eleventy's `bin/init`.
89
+ - `AGENTS.md` / `TEMPLATE.md` — mention `/whs:upgrade` and `npm run status`.
90
+
91
+ ### stacks/sveltekit-netlify.md
92
+
93
+ Closes the "no drift tooling / no `/whs:upgrade`" banners in `#adopting` and
94
+ partly in `#compliance`. `status` stays `draft` in `index.json` — compliance
95
+ still isn't there.
96
+
97
+ ### .github/workflows/publish.yml, .claude/agents/sveltekit.md, .claude/hooks/agent-only.js, CLAUDE.md, templates/commands/whs/adopt.md
98
+
99
+ - `.github/workflows/publish.yml` — a new `sveltekit` job (`needs: core`),
100
+ mirroring the `eleventy` job: root `npm ci`, check, tag↔version agreement,
101
+ `npm view` skip, `npm publish` from `packages/whs-sveltekit`. No-ops
102
+ cleanly if the package directory is absent, like `core`'s own job.
103
+ - `.claude/agents/sveltekit.md` — territory gains `packages/whs-sveltekit/**`
104
+ (the thin per-stack package, mirroring how `eleventy` owns
105
+ `packages/whs-eleventy/`); `packages/whs-core/` stays the `tooling`
106
+ agent's territory, named explicitly so it's clear this agent doesn't touch
107
+ it.
108
+ - Root `CLAUDE.md` and `.claude/hooks/agent-only.js`'s `DELEGATE_HINT`
109
+ (above the hand-copied marker only) — routing updated to name
110
+ `packages/whs-sveltekit` under `sveltekit` and to name both
111
+ `packages/whs-eleventy` and `packages/whs-sveltekit` as the packages
112
+ `packages/whs-core`'s stack-agnostic logic serves.
113
+ - `templates/commands/whs/adopt.md` — the SvelteKit tier now also wires in
114
+ the `@piercebarney/whs-sveltekit` devDependency (`>=` the published
115
+ version), the `status` script, `.claude/hooks/standard-drift.sh` plus its
116
+ `SessionStart` settings entry, and `.claude/commands/whs/upgrade.md` —
117
+ the same status-only slice this release ships for a freshly-scaffolded
118
+ project.
119
+
120
+ ### BACKLOG.md
121
+
122
+ - `sveltekit-tooling-parity` — notes `status` / `/whs:upgrade` / the drift
123
+ hook shipped in this release; remaining scope is the compliance sweep,
124
+ `/audit/` tabs, deploy preflight, `deploy.yml`, `.env.example`, and the
125
+ reduced-motion check-scope fix.
126
+ - New `ready` entry `eleventy-status-package-markers` (source: request,
127
+ owner, filed 2026-09-29 — no `feedback/` note; found directly while
128
+ reviewing whs-sveltekit's status markers): `packages/whs-eleventy/lib/status.js`
129
+ has no `bindingMarkers` for `### packages/whs-eleventy` /
130
+ `### packages/whs-core`, so a package-only CHANGELOG date block yields
131
+ zero `whs status` rows for Eleventy (verified against the 2026-10-21
132
+ block) — fix is the same markers plus tests, and the "`status` is a
133
+ helper, not the ground truth" step-3 wording this release added to
134
+ SvelteKit's `upgrade.md`, ported to
135
+ `templates/eleventy-netlify/.claude/commands/whs/upgrade.md`.
136
+
137
+ Nothing closes here — `sveltekit-tooling-parity` stays open for its
138
+ remaining scope.
139
+
140
+ ## 2026-10-22 [breaking]
141
+
142
+ Inbox triage release: fixes a SvelteKit `build.ts` bug that made the
143
+ `#noindex` "Layer 1, verified working" claim false for the client bundle —
144
+ "corrects a documented mechanism that didn't actually work," per this file's
145
+ own breaking definition. Also lands the two-way `requests/` drawer +
146
+ placeholder rule (`core.md#content-model`) across every stack, a new
147
+ SvelteKit `pages` binding, and the CI/verify plumbing to actually run a
148
+ SvelteKit add-on's tests.
149
+
150
+ **Action for SvelteKit projects:** replace `src/lib/build.ts` with the
151
+ version below and add the `envPrefix: ['VITE_', 'DEPLOY_TARGET']` line to
152
+ `vite.config.ts`, as documented in `stacks/sveltekit-netlify.md#noindex` /
153
+ `#config-idiom`. A project with `content-ops: reserved` should also adopt
154
+ the two-way `requests/` wording (`requests/README.md`, `CONTENT.md`,
155
+ `.claude/agents/content.md`).
156
+
157
+ ### core: content-model
158
+
159
+ The escalation channel (`requests/`) is now explicitly **two-way**: content
160
+ → build (a structural change the content arm can't make) and build →
161
+ content (the build needs content it isn't allowed to author — e.g. a schema
162
+ gains a required field with no real copy behind it yet). A new
163
+ **build → content placeholder rule** is the sole exception to the reserved
164
+ set's read-only rule: the build writes only a clearly-marked `[COPY
165
+ PENDING]` placeholder (never authored prose) into each newly-required
166
+ field, flags the entry as a draft wherever the schema allows so it can't
167
+ publish, and files the `requests/` note listing each field; the content arm
168
+ replaces the placeholders and clears the draft flag. Verify line added: a
169
+ production build contains no `[COPY PENDING]` text.
170
+
171
+ ### templates/sveltekit-netlify
172
+
173
+ - **`src/lib/build.ts` / `vite.config.ts`** — `isProduction` now reads
174
+ `import.meta.env.DEPLOY_TARGET` instead of `process.env.DEPLOY_TARGET`,
175
+ with `envPrefix: ['VITE_', 'DEPLOY_TARGET']` added to `vite.config.ts` so
176
+ the existing `DEPLOY_TARGET` env var (unchanged — `bin/deploy`/CI keep
177
+ setting it the same way) is populated identically in the server bundle, a
178
+ real production client bundle, and the plain dev server. `process.env`
179
+ reads don't survive Vite's classic unbundled `vite dev` for client code at
180
+ all (crashes with `process is not defined`) and silently evaluate to `{}`
181
+ in a bundled client build (always `false`, regardless of the real
182
+ `DEPLOY_TARGET`) — so a production page kept re-adding the noindex meta
183
+ and showing draft links after hydration. `$env/static/public` was weighed
184
+ and rejected: it would need either renaming the var to
185
+ `PUBLIC_DEPLOY_TARGET` or widening `kit.env.publicPrefix`, a single string
186
+ that can't also keep matching `PUBLIC_`. `envPrefix` matches by
187
+ `startsWith`, not exact name, so this array exposes exactly
188
+ `DEPLOY_TARGET` to the client bundle — a future client-exposed var is
189
+ added by its own full name, never by widening either entry to a broad
190
+ prefix like `'DEPLOY_'`, which would inline every matching var, secret or
191
+ not.
192
+ - **`.claude/agents/brand.md` / `stacks/sveltekit-netlify.md#styling`** —
193
+ the `tailwind-shadcn` recipe now documents `shadcn-svelte@1.7.0`'s real
194
+ `init` flow: a two-step preset menu (curated-list vs. one-by-one, then the
195
+ eight named presets with Vega pre-highlighted), followed by an unrelated
196
+ `layout.css` overwrite confirmation — not the single default-highlighted
197
+ prompt previously described. States plainly that the CLI is **not
198
+ pipe-scriptable** (clack's TUI needs a real pty; a plain pipe or `yes`
199
+ just hangs with no error) and gives an `expect` recipe that sizes the pty
200
+ with `stty rows/columns` before sending input and waits on rendered
201
+ anchor text per screen.
202
+ - **Two-way `requests/`** — `requests/README.md`, `CONTENT.md`,
203
+ `.claude/agents/content.md` all now document both directions and the
204
+ placeholder rule, matching the `core.md#content-model` update above.
205
+ - **`add-ons/pages/` (new)** — the `pages` marketing-blocks module's
206
+ SvelteKit binding (see `### module: pages` below): zod block schemas
207
+ (`hero`, `feature-list`, `cta`) plus a prose section and `include` marker,
208
+ a `Body.svelte` renderer and one Svelte component per block type
209
+ (structure-only, CSP-safe, no inline styles/scripts), the module's shared
210
+ `pages.schema.blocks.json` vendored byte-identical, a `CONTENT.pages.md`
211
+ addendum for reserved projects, and vitest tests against the module's
212
+ shared fixtures (`pages.blocks.test.ts`, 14 tests).
213
+
214
+ ### stacks/sveltekit-netlify.md
215
+
216
+ `#noindex` Layer 1 and `#config-idiom` updated to match the `build.ts` fix
217
+ above; the "verified working" claim now says it's checked after hydration
218
+ in a real browser, not just a diff of two builds' prerendered `index.html`.
219
+ `#content-model` mirrors the two-way `requests/` + placeholder rule.
220
+ `#styling`'s `tailwind-shadcn` recipe corrected per the `shadcn-svelte`
221
+ entry above.
222
+
223
+ ### module: pages
224
+
225
+ New binding: `templates/sveltekit-netlify/add-ons/pages/`, following
226
+ `modules/pages/MODULE.md` and mirroring the shape of
227
+ `templates/eleventy-netlify/add-ons/pages/`. `modules/README.md`'s index
228
+ now lists `sveltekit-netlify` for `pages`.
229
+
230
+ ### templates/eleventy-netlify / stacks/eleventy-netlify.md
231
+
232
+ Wording-only recheck of the `#content-model` mirror for the two-way
233
+ `requests/` + placeholder rule — no mechanism change.
234
+ `templates/eleventy-netlify/requests/README.md`, `CONTENT.md`, and
235
+ `.claude/agents/content.md` updated to match. Also corrects the **Drafts**
236
+ bullet in `stacks/eleventy-netlify.md`: draft state is a `draft` boolean
237
+ field on the content-model entry itself (`src/content/schema.js`), not
238
+ frontmatter — each domain's directory-data file computes
239
+ `isSuppressedDraft` and suppresses production/collection inclusion
240
+ accordingly.
241
+
242
+ ### bin/check
243
+
244
+ Sterility allowlist gains `shadcn-svelte\.com` alongside the existing
245
+ CSS-tooling domains (`daisyui.com`, `tailwindcss.com`, `heroicons.com`) —
246
+ it's the real CLI's own prompt text, quoted verbatim in
247
+ `stacks/sveltekit-netlify.md`.
248
+
249
+ ### templates/verify.sh, .github/workflows/standard.yml
250
+
251
+ Both now run a SvelteKit template's own `add-ons/*/*.test.*` files when
252
+ present, matching the eleventy branch's `node --test
253
+ add-ons/*/test/*.test.js` intent for this stack's runner (vitest). Neither
254
+ `npm run check` nor the project's own `vite.config.ts` (its `test.projects`
255
+ workspace scopes `include` to `src/**/*`) reaches add-on sources before
256
+ they're copied into the project, so each now writes a throwaway vitest
257
+ config (outside the template's own workspace-projects setup, so its
258
+ `src/`-only `include` doesn't shadow it) scoped to `add-ons/**/*.{test,spec}.{js,ts}`
259
+ and runs it with `npx vitest run --config <tmp file>` — no file under
260
+ `templates/sveltekit-netlify/` changed. Verified against
261
+ `add-ons/pages/pages.blocks.test.ts`: 14 tests pass.
262
+
263
+ ### BACKLOG.md
264
+
265
+ - New `ready` entry `commit-early-often` (source: request, owner,
266
+ 2026-09-28): a commit-cadence rule (distinct from `core.md`'s existing
267
+ commit-granularity rule), with the filed note's open questions carried
268
+ over verbatim.
269
+ - `sveltekit-tooling-parity` gains `covenant-in-color` to `requested-by:`,
270
+ `reduced-motion-check-scope` to `aliases:`, and a line on the fix: `whs
271
+ compliance`'s `#a11y` reduced-motion check only scans `src/`, `static/`,
272
+ `scripts/` for CSS `transition`/`animation`, missing a root-level authored
273
+ stylesheet/script and JS-driven smooth scroll (`scrollIntoView({ behavior:
274
+ "smooth" })`) — folds into `whs-core`'s shared a11y check (CSS
275
+ `scroll-behavior`, a crude JS smooth-scroll match, and root-level
276
+ authored `*.css`/`*.js`) during Release 2b, not a per-stack fix.
277
+
278
+ The `feedback/2026-09-27-reduced-motion-check-scope.md` and
279
+ `needs/2026-09-28-commit-early-often.md` notes are folded/backlogged, not
280
+ closed — no slug for either below.
281
+
282
+ **Closes:** build-ts-process-env-in-client, shadcn-init-not-scriptable-by-pipe,
283
+ requests-drawer-one-directional, sveltekit-pages-binding,
284
+ sveltekit-envprefix-too-broad
285
+
26
286
  ## 2026-10-21 [non-breaking]
27
287
 
28
288
  Release 2a of SvelteKit stack parity (`BACKLOG.md#sveltekit-tooling-parity`):
package/standard/core.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Web project house style — CORE (stack-agnostic)
2
2
 
3
- **Version:** 2026-10-21 · **Status:** active
3
+ **Version:** 2026-10-23 · **Status:** active
4
4
 
5
5
  This is the stack-agnostic contract every web project follows, regardless of
6
6
  framework, host, or CSS system. It says **what** must be true, with concrete
@@ -127,18 +127,31 @@ a build-time schema gate hard-fails the build on invalid content.
127
127
  and one file at the repo root (`CONTENT.md`) names the reserving party and
128
128
  the exact set it owns, and is authoritative for every party. The builder
129
129
  treats the reserved set as read-only and routes any change it needs there
130
- through the project's escalation channel, never a direct edit. The reserved
131
- set is enumerated at whatever granularity the project needs — all content,
132
- or named collections/paths.
130
+ through the project's escalation channel, never a direct edit — the sole
131
+ exception is the placeholder rule below. The reserved set is enumerated at
132
+ whatever granularity the project needs — all content, or named
133
+ collections/paths.
133
134
  - An **LLM agent** editing reserved content follows a documented per-project
134
135
  content-ops protocol: it changes only the reserved set; a pre-commit content
135
136
  check (the content-relevant slice of the gate) **errors** on any staged change
136
- outside that set; a `content:` commit convention; and an escalation channel for
137
- anything structural, so a blocked request is recorded, not lost. The agent does
138
- not deploy: it commits a finished change to the default branch and hands it to
139
- the human deploy cadence (`#ci-cd`) — a session-closing report that names what
137
+ outside that set; a `content:` commit convention; and a **two-way escalation
138
+ channel** for anything structural, so a blocked request is recorded, not
139
+ lost — content → build when the content arm needs a structural change it
140
+ isn't allowed to make itself; build → content when the build needs content
141
+ it isn't allowed to author (a schema gains a required field whose real copy
142
+ must come from the reserved content operation). The agent does not deploy:
143
+ it commits a finished change to the default branch and hands it to the
144
+ human deploy cadence (`#ci-cd`) — a session-closing report that names what
140
145
  landed and whether it is time-sensitive, with any deadline also carried in the
141
146
  commit subject. See your stack's impl doc.
147
+ - **Build → content placeholder rule** is the sole exception to the reserved
148
+ set's read-only rule above. Filing a build → content request does not block
149
+ the build on an answer: it files a build → content escalation note listing
150
+ every affected field, writes only a clearly-marked `[COPY PENDING]`
151
+ placeholder — never authored prose — into exactly those fields, and flags
152
+ the entry as a draft wherever the schema allows so it can't publish. The
153
+ content arm supplies the real copy, replaces each placeholder, and clears
154
+ the draft flag.
142
155
  - **Drafts** are a data flag. A draft renders in local and preview builds
143
156
  (reviewable) but is excluded from the production build and the sitemap.
144
157
  Publishing is removing the flag.
@@ -165,7 +178,7 @@ reserved set is what lets a builder and a separate content operation work the
165
178
  same repo without overwriting each other or leaving a request unanswered.
166
179
 
167
180
  **Verify.** The gate fails the build on invalid content. The audit page shows
168
- validation status.
181
+ validation status. A production build contains no `[COPY PENDING]` text.
169
182
 
170
183
  **Implementation.** See your stack's impl doc, same slug.
171
184
 
@@ -1541,7 +1554,7 @@ governs it and follow that chapter — the slugs are the index (a `<script>` →
1541
1554
  - content-type: tool # tool | article (article => feeds)
1542
1555
  - add-ons: none # or: comma list of modules/ packs no field above implies (calculator, glossary, pages) — see modules/README.md
1543
1556
  - publishing-rate: ~5 pages/week
1544
- - standard-version: 2026-10-21 # recommended — enables standard-version drift tracking (#compliance)
1557
+ - standard-version: 2026-10-23 # recommended — enables standard-version drift tracking (#compliance)
1545
1558
 
1546
1559
  <!-- optional, present only while a filed need is unresolved -->
1547
1560
  ### Waiting on the standard