@penpair/web 0.2.0 → 0.3.0

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.
Files changed (60) hide show
  1. package/README.md +12 -2
  2. package/docs/adapters.md +83 -0
  3. package/docs/build-kit.md +4 -2
  4. package/docs/conventions/README.md +63 -0
  5. package/docs/conventions/completion-2026-10-22.md +73 -0
  6. package/docs/conventions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  7. package/docs/conventions/plugin-code.md +23 -0
  8. package/docs/conventions/structure.md +48 -0
  9. package/docs/conventions/templates/adapter-command.ts +28 -0
  10. package/docs/conventions/templates/conventions.test.ts +81 -0
  11. package/docs/conventions/templates/frame-inspection.ts +27 -0
  12. package/docs/conventions/templates/frame-label.ts +15 -0
  13. package/docs/conventions/tsconfig.json +13 -0
  14. package/docs/conventions/typescript.md +59 -0
  15. package/docs/conventions/vitest.config.ts +11 -0
  16. package/docs/design-workflow.md +3 -1
  17. package/docs/fixtures/browser-capture-2026-10-22.json +217 -0
  18. package/docs/fixtures/feedback-reproductions.md +12 -0
  19. package/docs/fixtures/feedback-scratch.template.json +9 -0
  20. package/docs/formats.md +2 -0
  21. package/docs/getting-started.md +2 -0
  22. package/docs/guide.md +2 -2
  23. package/docs/handoff.md +2 -0
  24. package/docs/marwes-tokens.md +13 -0
  25. package/docs/marwes.md +2 -0
  26. package/docs/plans/registry-polling-fix.md +101 -0
  27. package/docs/plans/tradient-feedback-0.2.0.md +209 -0
  28. package/docs/plans/tradient-feedback-review.md +83 -0
  29. package/docs/recovery.md +8 -0
  30. package/docs/releasing.md +34 -4
  31. package/docs/snapshots.md +1 -1
  32. package/docs/theme-previews.md +18 -0
  33. package/examples/component-pilot/renderer.mjs +100 -0
  34. package/examples/coverage-matrix.json +126 -0
  35. package/examples/hello-card/README.md +18 -0
  36. package/examples/hello-card/build.js +24 -0
  37. package/examples/hello-card/helpers.js +27 -0
  38. package/examples/hello-card/inspect.js +4 -0
  39. package/examples/hello-card/readback.js +3 -0
  40. package/examples/reflection-browser/README.md +49 -0
  41. package/examples/reflection-browser/capture.mjs +311 -0
  42. package/examples/reflection-browser/fixture/Abel-Regular.ttf +0 -0
  43. package/examples/reflection-browser/fixture/OFL.txt +93 -0
  44. package/examples/reflection-browser/fixture/index.html +11 -0
  45. package/examples/reflection-browser/fixture-hooks.mjs +24 -0
  46. package/examples/reflection-browser/provider.mjs +90 -0
  47. package/examples/reflection-browser/serve.mjs +37 -0
  48. package/examples/theme-preview/README.md +21 -0
  49. package/examples/theme-preview/apply.js +8 -0
  50. package/examples/theme-preview/helpers.js +12 -0
  51. package/examples/theme-preview/inspect.js +3 -0
  52. package/examples/theme-preview/readback.js +7 -0
  53. package/examples/trials/hold-inspect.js +5 -0
  54. package/examples/trials/hold-readback.js +8 -0
  55. package/examples/trials/hold-writer.js +16 -0
  56. package/examples/trials/recovery-build.js +23 -0
  57. package/examples/trials/recovery-inspect.js +10 -0
  58. package/examples/trials/recovery-readback.js +7 -0
  59. package/examples/trials/wrong-file-read.js +3 -0
  60. package/package.json +3 -2
@@ -0,0 +1,217 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "date": "2026-10-22",
4
+ "browser": "148.0.7778.96",
5
+ "kind": "local-browser-plumbing-trial",
6
+ "approvedDesignTrial": false,
7
+ "cases": [
8
+ {
9
+ "id": "1280-light-loaded",
10
+ "complete": true,
11
+ "diffPixelRatio": 0,
12
+ "clip": {
13
+ "x": 0,
14
+ "y": 64,
15
+ "width": 1280,
16
+ "height": 720
17
+ },
18
+ "fonts": [
19
+ {
20
+ "family": "Fixture",
21
+ "weight": "400",
22
+ "style": "normal",
23
+ "status": "loaded"
24
+ }
25
+ ],
26
+ "hoveredControls": 0,
27
+ "occlusion": {
28
+ "samples": 5,
29
+ "blocked": 0
30
+ }
31
+ },
32
+ {
33
+ "id": "1280-light-empty",
34
+ "complete": true,
35
+ "diffPixelRatio": 0,
36
+ "clip": {
37
+ "x": 0,
38
+ "y": 64,
39
+ "width": 1280,
40
+ "height": 720
41
+ },
42
+ "fonts": [
43
+ {
44
+ "family": "Fixture",
45
+ "weight": "400",
46
+ "style": "normal",
47
+ "status": "loaded"
48
+ }
49
+ ],
50
+ "hoveredControls": 0,
51
+ "occlusion": {
52
+ "samples": 5,
53
+ "blocked": 0
54
+ }
55
+ },
56
+ {
57
+ "id": "1280-dark-loaded",
58
+ "complete": true,
59
+ "diffPixelRatio": 0,
60
+ "clip": {
61
+ "x": 0,
62
+ "y": 64,
63
+ "width": 1280,
64
+ "height": 720
65
+ },
66
+ "fonts": [
67
+ {
68
+ "family": "Fixture",
69
+ "weight": "400",
70
+ "style": "normal",
71
+ "status": "loaded"
72
+ }
73
+ ],
74
+ "hoveredControls": 0,
75
+ "occlusion": {
76
+ "samples": 5,
77
+ "blocked": 0
78
+ }
79
+ },
80
+ {
81
+ "id": "1280-dark-empty",
82
+ "complete": true,
83
+ "diffPixelRatio": 0,
84
+ "clip": {
85
+ "x": 0,
86
+ "y": 64,
87
+ "width": 1280,
88
+ "height": 720
89
+ },
90
+ "fonts": [
91
+ {
92
+ "family": "Fixture",
93
+ "weight": "400",
94
+ "style": "normal",
95
+ "status": "loaded"
96
+ }
97
+ ],
98
+ "hoveredControls": 0,
99
+ "occlusion": {
100
+ "samples": 5,
101
+ "blocked": 0
102
+ }
103
+ },
104
+ {
105
+ "id": "390-light-loaded",
106
+ "complete": true,
107
+ "diffPixelRatio": 0,
108
+ "clip": {
109
+ "x": 0,
110
+ "y": 64,
111
+ "width": 390,
112
+ "height": 844
113
+ },
114
+ "fonts": [
115
+ {
116
+ "family": "Fixture",
117
+ "weight": "400",
118
+ "style": "normal",
119
+ "status": "loaded"
120
+ }
121
+ ],
122
+ "hoveredControls": 0,
123
+ "occlusion": {
124
+ "samples": 5,
125
+ "blocked": 0
126
+ }
127
+ },
128
+ {
129
+ "id": "390-light-empty",
130
+ "complete": true,
131
+ "diffPixelRatio": 0,
132
+ "clip": {
133
+ "x": 0,
134
+ "y": 64,
135
+ "width": 390,
136
+ "height": 844
137
+ },
138
+ "fonts": [
139
+ {
140
+ "family": "Fixture",
141
+ "weight": "400",
142
+ "style": "normal",
143
+ "status": "loaded"
144
+ }
145
+ ],
146
+ "hoveredControls": 0,
147
+ "occlusion": {
148
+ "samples": 5,
149
+ "blocked": 0
150
+ }
151
+ },
152
+ {
153
+ "id": "390-dark-loaded",
154
+ "complete": true,
155
+ "diffPixelRatio": 0,
156
+ "clip": {
157
+ "x": 0,
158
+ "y": 64,
159
+ "width": 390,
160
+ "height": 844
161
+ },
162
+ "fonts": [
163
+ {
164
+ "family": "Fixture",
165
+ "weight": "400",
166
+ "style": "normal",
167
+ "status": "loaded"
168
+ }
169
+ ],
170
+ "hoveredControls": 0,
171
+ "occlusion": {
172
+ "samples": 5,
173
+ "blocked": 0
174
+ }
175
+ },
176
+ {
177
+ "id": "390-dark-empty",
178
+ "complete": true,
179
+ "diffPixelRatio": 0,
180
+ "clip": {
181
+ "x": 0,
182
+ "y": 64,
183
+ "width": 390,
184
+ "height": 844
185
+ },
186
+ "fonts": [
187
+ {
188
+ "family": "Fixture",
189
+ "weight": "400",
190
+ "style": "normal",
191
+ "status": "loaded"
192
+ }
193
+ ],
194
+ "hoveredControls": 0,
195
+ "occlusion": {
196
+ "samples": 5,
197
+ "blocked": 0
198
+ }
199
+ }
200
+ ],
201
+ "negativeCases": [
202
+ "wrong theme",
203
+ "missing face",
204
+ "missing weight",
205
+ "scale mismatch",
206
+ "hover contamination",
207
+ "sticky shell occlusion"
208
+ ],
209
+ "delayedFontCase": "passed",
210
+ "baselineBytesPreserved": true,
211
+ "verdict": "owner-review-required",
212
+ "limitations": [
213
+ "Synthetic unapproved browser references; no Penpot target authorized",
214
+ "Occlusion is sampled; visual inspection remains necessary",
215
+ "MCP could not import local modules; tested provider using bundled Playwright and cached Chromium"
216
+ ]
217
+ }
@@ -0,0 +1,12 @@
1
+ # Adoption feedback baseline
2
+
3
+ Source: owner-supplied `feedback-0.2.0-2026-10-22.md`, consumer trial dated 2026-10-22. Installed Penpair 0.1.3 → 0.2.0; hosted plugin API 2.18.4. Repository baseline: `57f9782`, pnpm 10.12.1, TypeScript 5.6.3, Vitest 3.2.4. The consumer used Codex; its exact model/build and browser version were not recorded here and remain unknown.
4
+
5
+ Portable reproductions execute real plugin bodies against minimal objects, with no copied consumer runners, logs, endpoints or private journals:
6
+
7
+ - `packages/core/test/feedback-repro.test.ts`: idle native wait failure despite stable geometry; deferred revision during inspection (lease save and external edit both refuse); delayed page navigation. Initially expected failures identify the fixes still required.
8
+ - `packages/marwes-ui/test/migration.test.ts`: identical values with legacy metadata/hash still produce an unexplained stale snapshot.
9
+
10
+ Confirmed: native failure blocks fallback, metadata staleness lacks an explanation, a single page-switch delay is insufficient in the synthetic delayed editor. Unproven: the hosted lease/save race and the root cause of the consumer's multi-page failure. Synthetic reproduction is not live causal evidence.
11
+
12
+ Copy `feedback-scratch.template.json` only after an owner confirms a disposable file. Fill public IDs from inspection; `null` values are deliberately not executable. Keep the personal MCP key outside this manifest. Before any write, inspect, pin a snapshot, apply once, independently read back and look at two exports. Repeat and change one heading; compare IDs, bindings and preservation fields.
@@ -0,0 +1,9 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "authorized": false,
4
+ "fileId": null,
5
+ "pages": [{ "role": "build", "id": null }, { "role": "preservation", "id": null }],
6
+ "build": { "ownedPrefix": "penpair-feedback/", "flex": true, "text": true, "tokenBindings": ["typography", "fill", "rowGap"] },
7
+ "preserve": ["unrelated shape IDs and values", "token definitions and order", "global theme selections", "original visible page"],
8
+ "cases": ["desktop/light/loaded", "desktop/light/empty", "desktop/dark/loaded", "desktop/dark/empty", "mobile/light/loaded", "mobile/light/empty", "mobile/dark/loaded", "mobile/dark/empty"]
9
+ }
package/docs/formats.md CHANGED
@@ -18,3 +18,5 @@ This is a deliberately limited, validated subset of [DTCG Format 2025.10](https:
18
18
  The version-1 portable artifact retains typed values, paths, group metadata and explicit losses. Supported conversions are lossless and report an empty losses list. Unsupported input is rejected before output; it is never silently omitted. Bounds are 8 MiB input, 10,000 tokens, 32 group levels and 64 alias levels. This is offline exchange, not a Penpot token-set importer or an implementation of the complete DTCG resolver specification.
19
19
 
20
20
  Outside this subset: JSON Pointer/property references, group extensions/inheritance, deprecated metadata, root tokens, other composite types, named weights, nonnumeric color components, additional color spaces and native Penpot arithmetic expressions. Formula evaluation and px/rem conversion are intentionally absent: the tool preserves units rather than choosing a root font size. Native token snapshots retain their own richer values and formulas; using this exchange subset does not claim full standards conformance.
21
+
22
+ `projected-theme-preview` v1 records deterministic offline values, source/theme/set identity and explicit unknowns; `nativeBindings:false` distinguishes it from live binding evidence. See [theme previews](theme-previews.md).
@@ -69,6 +69,8 @@ npx @penpair/web skills install
69
69
  This copies the rules the assistant follows (how to work safely in Penpot, and how to judge a screen) into `.skills/` and makes them visible to Codex and Claude Code. It prints a line for each to add to your `AGENTS.md`. Then fill in `.skills/penpair-design/references/project-facts.md` (your file, never replaced): the Penpot file, the token sets, the names you use, who approves.
70
70
 
71
71
  ### Every day
72
+ Before moving into frontend implementation, choose the [companion adapters](adapters.md): use the library adapter for library-aware tokens/recipes and the recommended Reflection Check adapter for comparing the running frontend with approved designs. Installation and registration are the first steps; browser setup/provider evidence is a separate readiness stage.
73
+
72
74
  Open the file in Penpot, choose **File, MCP Server, Connect**, keep the tab visible, and start working with the assistant.
73
75
 
74
76
  ### Your safety net
package/docs/guide.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Guide
2
2
 
3
- For this unreleased improvement branch, start with the [review guide](branch-review.md). Choose a tested workflow below, then use the extension and command references for the selected work. Live checks are identified separately.
3
+ Choose a workflow below, starting with [companion adapters](adapters.md) when connecting a component library or verifying frontend code. Use the [review guide](branch-review.md) for the original improvement delivery; live checks are identified separately.
4
4
 
5
5
  ## Documentation map
6
6
 
@@ -9,7 +9,7 @@ For this unreleased improvement branch, start with the [review guide](branch-rev
9
9
  | First run / shared file | [Getting started](getting-started.md), [team](team.md), [trial runbook](trials.md) |
10
10
  | Build / handoff | [Cookbook](cookbook.md), [workflow](design-workflow.md), [kit](build-kit.md), [file scripts](run-file.md), [handoff](handoff.md) |
11
11
  | Evidence | [Inspection](inspection.md), [advisory audits](audits.md), [snapshots](snapshots.md), [approvals](approvals.md), [coverage](coverage.md), [artifacts](artifacts.md) |
12
- | Integration | [MCP](mcp.md), [formats](formats.md), [extension trust](extensions-trust.md), [credentials](credentials.md), [token adapter](marwes.md), [upstream draft](upstream/marwes-requests.md) |
12
+ | Integration | [Companion adapters](adapters.md), [MCP](mcp.md), [formats](formats.md), [extension trust](extensions-trust.md), [credentials](credentials.md), [token adapter](marwes.md), [upstream draft](upstream/marwes-requests.md) |
13
13
  | Repair / operations | [Status/open](status.md), [troubleshooting](troubleshooting.md), [recovery](recovery.md), [backup](backup.md), [compatibility](compatibility.md), [releasing](releasing.md) |
14
14
 
15
15
  ## Extension points
package/docs/handoff.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Derived design handoff
2
2
 
3
+ For frontend implementation, pair this handoff with the recommended [Reflection Check companion](adapters.md#check-the-frontend-against-the-design). The handoff carries observed design facts; the companion connects approved cases to actual browser comparison evidence. Install/register the adapter and configure the project's real provider before claiming that comparison is ready.
4
+
3
5
  ```sh
4
6
  penpair spec --page Dashboard --frame FRAME_ID --out design/specs/dashboard.md
5
7
  penpair spec --from design/inspections/dashboard.json --map design/component-map.json --out design/specs/dashboard.md
@@ -161,3 +161,16 @@ Each apply still checks file/source identity, original journal inputs and struct
161
161
  After `--include @kit`, opt into `--include @marwes-kit` for card, segmented, progress, icon-tile and stat-tile recipes. Project radius constants and progress sizing height remain explicit inputs; these recipes do not claim measured native-component parity. See [the build kit](build-kit.md).
162
162
 
163
163
  Component anatomy is a separate [measured three-component pilot](marwes-components.md); token sync does not establish component parity.
164
+
165
+ ## Metadata-only upgrades
166
+
167
+ `tokens check --json` includes `reasons` with stable codes: `missing-snapshot`, `schema-migration`, `missing-ownership`, `content-drift`, `metadata-mismatch` and `package-mismatch`. `current:false` always explains why, even if `diff.identical:true`. Exit 2 is stale data; invalid/unreadable input is still an error.
168
+
169
+ For a legacy snapshot, explicitly map **every** set name to `"adapter"` or `"project"` in `ownership.json`. Preview without connecting to Penpot:
170
+
171
+ ```sh
172
+ penpair marwes tokens migrate --from design/legacy-tokens.json --ownership ownership.json
173
+ penpair marwes tokens migrate --from design/legacy-tokens.json --ownership ownership.json --out design/migrated-tokens.json
174
+ ```
175
+
176
+ Review values, themes and original provenance before adopting the migrated file. Do not infer ownership from name prefixes or regenerate away the source evidence.
package/docs/marwes.md CHANGED
@@ -5,3 +5,5 @@
5
5
  The adapter consumes the adopting project's installed library/theme, and keeps project knowledge outside the neutral core. Project extras remain declared inputs. Computed component values are measurements in a theme/state/viewport; token matches are candidates, not inferred semantic bindings. Native library generation and human adoption acceptance remain pending until observed proof exists.
6
6
 
7
7
  `penpair marwes theme lint` compares declared project colors with installed defaults in light/dark mode. When primary changes, unchanged brand-family siblings with a distant hue become advisory warnings. Configure `marwes.themeLint.hueThresholdDegrees` (default 30) and exact `suppressions: [{theme:"light",token:"mw-color-border-brand",reason:"Intentional blue navigation"}]`. Suppressions remain visible. Transparent, non-literal and achromatic colors remain unknown; hue is neither a brand rule nor an accessibility score. Warnings return success and never rewrite themes or Penpot.
8
+
9
+ [Projected theme previews](theme-previews.md) resolve declared light/dark values offline without changing active selections or claiming native per-frame theme bindings.
@@ -0,0 +1,101 @@
1
+ # Registry visibility polling — 2026-10-22
2
+
3
+ Branch: `codex/release-registry-polling`. Base: reviewed 0.3.0 release on main,
4
+ `4ea9975`. Repository package versions remain 0.3.0.
5
+
6
+ ## Failure and evidence
7
+
8
+ The [publish job](https://github.com/niklas-westman/penpair/actions/runs/39801876697/job/119904592523)
9
+ accepted `@penpair/core@0.3.0` at 15:17:02 UTC with signed provenance. npm explicitly
10
+ reported that processing could take a few minutes. The script exhausted twelve
11
+ five-second visibility checks and stopped at 15:18:05 UTC. No subsequent package
12
+ was published by that run.
13
+
14
+ An independent registry check then found core 0.3.0 visible, with Docker, the token
15
+ adapter, the comparison adapter and web still absent. This establishes a
16
+ processing-delay failure after an accepted upload; increasing a publish timeout
17
+ or retrying the upload is unnecessary.
18
+
19
+ ## Completed checklist
20
+
21
+ - [x] Extract a focused post-publish visibility helper. It checks immediately and
22
+ then at minute intervals within a ten-minute deadline for each uploaded package.
23
+ - [x] Count registry query time toward the deadline and report elapsed time and
24
+ the next check/deadline in workflow logs.
25
+ - [x] Bound each npm metadata process and HTTP request to 30 seconds or the
26
+ remaining deadline, with hidden npm retries disabled.
27
+ - [x] Retain errors for failed lookups, explicit interrupted-release continuation,
28
+ dependency-order publishing and the configured short-name exception. The
29
+ visibility helper never uploads a package.
30
+ - [x] Add virtual-clock tests for immediate/delayed visibility, exact minute
31
+ cadence, query duration, ten-minute expiry, remaining query budget, late
32
+ observations and registry errors. Query-boundary tests cover 404, authentication,
33
+ network errors and killed processes without touching npm.
34
+ - [x] Document recovery and the order of operations before merging a tooling fix.
35
+
36
+ ## Validation
37
+
38
+ - `pnpm check`: **658 tests** pass, including 15 new polling/query tests, along
39
+ with builds, typechecks, style/path checks and the six-package version guard.
40
+ - `pnpm smoke:package`: all six tarballs install and run.
41
+ - Final polling/logging tests pass independently using virtual time. No real
42
+ ten-minute sleeps or npm publication were used for testing.
43
+ - `git diff --check` passes. The empty Changeset records repository tooling work
44
+ and does not propose a package version bump.
45
+
46
+ ## Current release recovery and remaining risk
47
+
48
+ - [ ] On current `main`, dispatch **Publish reviewed Penpair release** with
49
+ `version=0.3.0` and `continue_release=true`, then approve `npm-release`.
50
+ - [ ] Verify all five required scoped versions and provenance. The `penpair`
51
+ wrapper remains explicitly excluded.
52
+ - [x] Polling fix merged as PR #5 before recovery completed; the early-merge recovery below supersedes the original merge order.
53
+
54
+ The current main workflow still has its original one-minute visibility wait. If
55
+ another accepted upload exceeds it, inspect the registry and explicitly continue
56
+ the same version again. Rerunning the failed push workflow does not select
57
+ continuation automatically.
58
+
59
+ Finish recovery before merging this branch: its pending Changeset would block the
60
+ manual release gate on main. This preserves the existing guard rather than
61
+ changing it to accommodate an interrupted release. Ten minutes is a bounded
62
+ window, not a guarantee that npm finishes processing; a failed lookup or an
63
+ expired deadline still stops for inspection.
64
+
65
+ ## Early merge recovery
66
+
67
+ PR #5 was merged on 2026-10-22 as `d339a19` while the 0.3.0 release remained
68
+ interrupted. The new minute polling is now on main. The remaining pending note
69
+ `bounded-registry-polling` has an empty release list and requests no version bump.
70
+ The version-PR workflow therefore created no release PR. Manual continuation is
71
+ blocked until that metadata has been consumed.
72
+
73
+ The post-merge push workflow separately hit a GitHub API HTTP 500 while reading
74
+ associated PRs; its publish job was skipped. That API error is distinct from the
75
+ pending-note check. Manual dispatch uses the explicit-version path.
76
+
77
+ - [x] Reproduce Changesets' consumption in an isolated workspace: only the empty
78
+ note is removed and every package stays at 0.3.0.
79
+ - [x] Use the same Changesets CLI operation on the cleanup branch. Confirm no
80
+ package manifest, source version, lockfile, script or workflow changes.
81
+ - [x] Run the unchanged `checkReleaseCommit` and manual workflow gate against the
82
+ resulting tree: both accept 0.3.0 with no pending notes. No publish command runs.
83
+ - [x] Pass style/path checks and 47 existing Changesets, release-guard, polling,
84
+ registry-query and documentation tests. The cleanup changes only metadata/docs;
85
+ the previous 658-test run and six-package smoke cover the retained polling code.
86
+ - [ ] Review/merge the metadata-only cleanup PR and pass its CI.
87
+ - [ ] On the resulting main, dispatch **Publish reviewed Penpair release** with
88
+ `version=0.3.0`, `continue_release=true`, and approve `npm-release`.
89
+ - [ ] Verify all five scoped packages and their provenance before marking the
90
+ release complete; the short-name exception remains enabled.
91
+
92
+ The consumed tooling note is preserved here:
93
+
94
+ > Allow npm processing time after successful uploads: check visibility immediately
95
+ > and then once per minute within a ten-minute deadline per package. Bound metadata
96
+ > queries and retain explicit recovery for interrupted releases. This changes
97
+ > repository release tooling only.
98
+
99
+ This cleanup completes an empty metadata item through Changesets. Package release
100
+ notes and release guards remain intact; the interrupted version remains 0.3.0,
101
+ with core skipped by explicit continuation once independently observed on npm.