@nextcommerce/campaigns-os 1.33.0 → 1.37.1

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 (136) hide show
  1. package/AGENTS.md +42 -13
  2. package/CHANGELOG.md +129 -0
  3. package/README.md +42 -20
  4. package/compatibility.json +1 -1
  5. package/contracts/agent-relevant-change-policy.v1.json +1 -0
  6. package/contracts/fixtures/progress/observation.v0.json +89 -0
  7. package/contracts/fixtures/runtime-recipe/accept/current.json +3 -5
  8. package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -5
  9. package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -5
  10. package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -5
  11. package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -5
  12. package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -5
  13. package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -5
  14. package/contracts/fixtures/runtime-recipe/reject/missing-required-field.json +3 -5
  15. package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -5
  16. package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -5
  17. package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -5
  18. package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +2 -4
  19. package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -5
  20. package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -5
  21. package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -5
  22. package/contracts/release-ledger.json +614 -0
  23. package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -5
  24. package/contracts/supported-surface.json +23 -6
  25. package/demo/apollo-v0/NOTICE.txt +51 -0
  26. package/demo/apollo-v0/assets/css/demo.css +2 -0
  27. package/demo/apollo-v0/assets/css/landing/tokens.css +35 -0
  28. package/demo/apollo-v0/assets/css/next-core.css +16124 -0
  29. package/demo/apollo-v0/assets/images/1x1_1.svg +19 -0
  30. package/demo/apollo-v0/assets/images/1x1_2.svg +19 -0
  31. package/demo/apollo-v0/assets/images/affirm-logo.svg +24 -0
  32. package/demo/apollo-v0/assets/images/apple-pay-logo.svg +4 -0
  33. package/demo/apollo-v0/assets/images/bancontact-logo.svg +1 -0
  34. package/demo/apollo-v0/assets/images/cc-visa.svg +28 -0
  35. package/demo/apollo-v0/assets/images/cc_amex.svg +20 -0
  36. package/demo/apollo-v0/assets/images/cc_discover.svg +21 -0
  37. package/demo/apollo-v0/assets/images/cc_master.svg +22 -0
  38. package/demo/apollo-v0/assets/images/credit-card-flags.svg +38 -0
  39. package/demo/apollo-v0/assets/images/demo-inline-40788e52a7c75b78.svg +1 -0
  40. package/demo/apollo-v0/assets/images/demo-inline-686e73c8840a0f0a.svg +1 -0
  41. package/demo/apollo-v0/assets/images/google-pay-logo.svg +7 -0
  42. package/demo/apollo-v0/assets/images/guarantee-badge.png +0 -0
  43. package/demo/apollo-v0/assets/images/icon-dollar.svg +5 -0
  44. package/demo/apollo-v0/assets/images/icon-guarantee.svg +5 -0
  45. package/demo/apollo-v0/assets/images/icon-shipping.svg +5 -0
  46. package/demo/apollo-v0/assets/images/icons8-lock-24_1icons8-lock-24.png +0 -0
  47. package/demo/apollo-v0/assets/images/ideal-logo.svg +30 -0
  48. package/demo/apollo-v0/assets/images/klarna-logo.svg +9 -0
  49. package/demo/apollo-v0/assets/images/landing/_shared/16x9.svg +19 -0
  50. package/demo/apollo-v0/assets/images/landing/_shared/1x1_1.svg +19 -0
  51. package/demo/apollo-v0/assets/images/landing/_shared/4x3.svg +19 -0
  52. package/demo/apollo-v0/assets/images/landing/_shared/arrow-right.svg +6 -0
  53. package/demo/apollo-v0/assets/images/landing/_shared/cta-guarantee-icon.png +0 -0
  54. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-1.svg +8 -0
  55. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-2.svg +10 -0
  56. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-3.svg +13 -0
  57. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-4.svg +11 -0
  58. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-quote.svg +6 -0
  59. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-verified.svg +10 -0
  60. package/demo/apollo-v0/assets/images/landing/bottomcta-1/check-bullet.svg +5 -0
  61. package/demo/apollo-v0/assets/images/landing/faq-1/faq-chevron.svg +6 -0
  62. package/demo/apollo-v0/assets/images/landing/footer-1/footer-logo.png +0 -0
  63. package/demo/apollo-v0/assets/images/landing/guarantee-1/guarantee-1-badge.svg +8 -0
  64. package/demo/apollo-v0/assets/images/landing/hero-1/icon-check.svg +5 -0
  65. package/demo/apollo-v0/assets/images/landing/hero-1/icon-star.svg +6 -0
  66. package/demo/apollo-v0/assets/images/landing/hero-1/icon-verified.svg +6 -0
  67. package/demo/apollo-v0/assets/images/landing/icons-5/icon-batteries.svg +7 -0
  68. package/demo/apollo-v0/assets/images/landing/icons-5/icon-cuff-checking.svg +6 -0
  69. package/demo/apollo-v0/assets/images/landing/icons-5/icon-dual-user.svg +5 -0
  70. package/demo/apollo-v0/assets/images/landing/icons-5/icon-fda-cleared.svg +5 -0
  71. package/demo/apollo-v0/assets/images/landing/icons-5/icon-heartbeat.svg +17 -0
  72. package/demo/apollo-v0/assets/images/landing/icons-5/icon-lcd-display.svg +10 -0
  73. package/demo/apollo-v0/assets/images/landing/icons-5/icon-movement-error.svg +7 -0
  74. package/demo/apollo-v0/assets/images/landing/icons-5/icon-portable.png +0 -0
  75. package/demo/apollo-v0/assets/images/landing/icons-5/icon-reading-memory.svg +6 -0
  76. package/demo/apollo-v0/assets/images/landing/icons-5/icon-wrist-comfort.svg +5 -0
  77. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-1.jpg +0 -0
  78. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-2.jpg +0 -0
  79. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-3.jpg +0 -0
  80. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-4.jpg +0 -0
  81. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-1.png +0 -0
  82. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-2.png +0 -0
  83. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-3.png +0 -0
  84. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-4.png +0 -0
  85. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-5.png +0 -0
  86. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-6.png +0 -0
  87. package/demo/apollo-v0/assets/images/landing/nav-1/flag-us.png +0 -0
  88. package/demo/apollo-v0/assets/images/landing/reviews-3/star-card.svg +3 -0
  89. package/demo/apollo-v0/assets/images/landing/reviews-3/star-lg.svg +3 -0
  90. package/demo/apollo-v0/assets/images/landing/reviews-3/star-sm.svg +3 -0
  91. package/demo/apollo-v0/assets/images/landing/reviews-3/verified.svg +10 -0
  92. package/demo/apollo-v0/assets/images/landing/testimonials-2/testimonials-2-reactions.svg +9 -0
  93. package/demo/apollo-v0/assets/images/landing/testimonials-2/testimonials-2-stars.svg +6 -0
  94. package/demo/apollo-v0/assets/images/link-logo.svg +1 -0
  95. package/demo/apollo-v0/assets/images/next-dark.svg +8 -0
  96. package/demo/apollo-v0/assets/images/paypal-logo.svg +5 -0
  97. package/demo/apollo-v0/assets/images/paypal-txt.svg +8 -0
  98. package/demo/apollo-v0/assets/images/paypal.svg +22 -0
  99. package/demo/apollo-v0/assets/images/sepa-logo.svg +275 -0
  100. package/demo/apollo-v0/assets/images/twint-logo.svg +1 -0
  101. package/demo/apollo-v0/assets/images/united-states-flag-icon.webp +0 -0
  102. package/demo/apollo-v0/assets/images/upsell-payment-logos.svg +38 -0
  103. package/demo/apollo-v0/assets/images/usps.png +0 -0
  104. package/demo/apollo-v0/checkout/index.html +1370 -0
  105. package/demo/apollo-v0/landing/index.html +1836 -0
  106. package/demo/apollo-v0/provenance.json +342 -0
  107. package/demo/apollo-v0/receipt/index.html +292 -0
  108. package/demo/apollo-v0/upsell-bundle-stepper/index.html +401 -0
  109. package/docs/activation-and-evidence.md +37 -0
  110. package/docs/demo-preview.md +63 -0
  111. package/docs/diagnostics.md +55 -0
  112. package/docs/orientation-contract-reference.md +3 -1
  113. package/docs/progress-snapshots.md +142 -0
  114. package/docs/qa-and-test-orders.md +26 -0
  115. package/docs/runtime-readiness.md +3 -3
  116. package/docs/sdk-storage-compatibility.md +19 -0
  117. package/docs/supported-surface.md +14 -1
  118. package/docs/versioning.md +1 -1
  119. package/package.json +22 -8
  120. package/schemas/campaign-runtime-build-context.v0.schema.json +42 -0
  121. package/schemas/campaigns-os-progress-snapshot.v0.schema.json +370 -0
  122. package/skills/next-campaigns-build/SKILL.md +17 -1
  123. package/skills/next-campaigns-os/SKILL.md +19 -3
  124. package/skills/next-campaigns-os-setup/SKILL.md +17 -1
  125. package/skills/next-campaigns-polish/SKILL.md +18 -2
  126. package/skills/next-campaigns-qa/SKILL.md +24 -8
  127. package/skills.json +5 -5
  128. package/src/cli.mjs +96 -6
  129. package/src/consent.mjs +2 -2
  130. package/src/demo-artifact.mjs +97 -0
  131. package/src/demo.mjs +85 -0
  132. package/src/diagnostic.mjs +101 -0
  133. package/src/install-mode.mjs +13 -1
  134. package/src/progress-node.mjs +177 -0
  135. package/src/progress.mjs +133 -0
  136. package/src/sdk-storage-compatibility.mjs +359 -0
package/AGENTS.md CHANGED
@@ -61,19 +61,48 @@ is a refusal, not a value to interpret. And a prepared runtime can build and
61
61
  type-check but **cannot run browser QA** — preparation suppresses lifecycle
62
62
  scripts, which is also what suppresses the browser download.
63
63
 
64
- The recipe describes preparing a runtime from a **checkout**. The supported
65
- way to *run* the toolkit without a checkout is as a **pinned devDependency of
66
- the campaign folder** (a page-kit project): `npm i -D
67
- "github:NextCommerceCo/campaigns-os#<sha>"` there, then `npx campaigns-os …`
68
- from that folder. The same pin discipline applies — the sha is the one you
69
- oriented on — and npm records the resolved commit in that folder's
70
- `package.json` and `package-lock.json`, so CI and the deploy host install the
71
- same commit and `tooling status` reads the pin back (`Install mode: package
72
- install …`). It runs the package's own lifecycle script at install time, so it
73
- is not a recipe execution and makes no claim under the recipe's output
74
- checks. Every command the toolkit prints for you to copy is spelled for the
75
- install it came from (`npx campaigns-os …` there). A recipe kind for package
76
- installs is not published yet.
64
+ The recipe describes preparing a runtime from a **checkout**. The primary
65
+ way to *run* the toolkit is an **exact project-local devDependency** in the
66
+ campaign's Page Kit folder: `npm install --save-dev --save-exact
67
+ @nextcommerce/campaigns-os@<reviewed-version>`, then `npx campaigns-os …` from
68
+ that folder. Review the release's source tag and provenance against the commit
69
+ you oriented on; installation cannot supply its own trust decision. Commit
70
+ `package.json` and `package-lock.json` so other hosts install the same bytes.
71
+ For an unreleased reviewed commit use `npm install --save-dev --save-exact
72
+ "github:NextCommerceCo/campaigns-os#<full-sha>"` instead. Both run package
73
+ lifecycle scripts and are separate from this checkout-only recipe.
74
+
75
+ An exact global registry install is also supported:
76
+ `npm install -g @nextcommerce/campaigns-os@<reviewed-version>`. `tooling status`
77
+ reports whether the installation is local, global, or a checkout, its version,
78
+ and a source commit when derivable. It does not check registry currency. Use
79
+ its printed invocation to avoid another installation on PATH; a project-local
80
+ installation prints `npx campaigns-os`, while a shadowed global copy prints an
81
+ explicit invocation of that copy. Use `--platform claude` or `--platform codex`
82
+ consistently for profile-only setup and preflight, and install bundled skills
83
+ before following the stage recommendations. Browser proof uses the package's
84
+ `qa install-browser`; optional Playwright absence does not block other commands.
85
+
86
+ [Activation, access, and evidence](docs/activation-and-evidence.md) describes
87
+ public milestones without introducing another lifecycle. For support,
88
+ `tooling diagnose [--packet <packet>] [--platform <profile>] [--json]` reads
89
+ status and the read-only doctor's existing `next` recommendation and exports a
90
+ strict allowlist summary. It neither establishes orientation trust nor changes
91
+ campaign evidence or run sessions. See [diagnostics](docs/diagnostics.md).
92
+
93
+ Candidate 1.36.0 also records minimal progress observations after canonical
94
+ `next` and committed QA. Run `next` after agent-owned stages to observe their
95
+ reports. `--no-write` disables capture and send; `--no-remit` keeps it local.
96
+ The portable `./progress` contract preserves separate saved Map, semantic spec
97
+ and output identities, and grants no orientation or deployment trust. See
98
+ [progress snapshots](docs/progress-snapshots.md).
99
+
100
+ Candidate 1.37.0 adds `demo --target <new-directory>`, an offline visual sample
101
+ that copies a pinned inert Apollo bundle and prints its landing/index.html path.
102
+ It bypasses session recovery and creates no campaign evidence or telemetry.
103
+ Unsupported flags, including no-write and dry-run, are rejected before writes.
104
+ Start real work in a separate new Page Kit folder and preserve sample edits.
105
+ See [offline demo preview](docs/demo-preview.md).
77
106
 
78
107
  ## Supported versus internal
79
108
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,135 @@
2
2
 
3
3
  Notable supported-surface changes are recorded here.
4
4
 
5
+ ## [1.37.1] - 2026-09-18
6
+
7
+ ### Fixed
8
+
9
+ - Demo copies that detect a changed destination explain how to preserve its
10
+ files and retry with a different new directory. Ownership checks and cleanup
11
+ remain unchanged; a replacement-directory regression proves copying stops
12
+ after the first write and preserves files authored in the replacement.
13
+ - Clarify that demo raw arguments are validated in the CLI entry point before
14
+ the private dispatcher rechecks the parsed shape and extracts the target.
15
+
16
+ ## [1.37.0] - 2026-09-18
17
+
18
+ ### Added
19
+
20
+ - `demo --target <new-directory>` copies four pinned inert Apollo sample pages
21
+ for direct local-file exploration, with active sample navigation, disabled
22
+ commerce controls, local assets and restrictive CSP. It downloads nothing,
23
+ bypasses session recovery, and emits no campaign evidence or telemetry.
24
+ - Exclusive target creation refuses existing files, directories and symlinks.
25
+ Failed copies clean only owned entries; unsupported flags fail before writes.
26
+ A hashed provenance manifest and retained notices document the static projection,
27
+ pinned published Page Kit toolchain, build-time CSS and system font fallback.
28
+ Real campaigns begin separately, preserving sample edits.
29
+
30
+ ## [1.36.0+agent.1] - 2026-09-18
31
+
32
+ ### Fixed
33
+
34
+ - Progress treats a missing Build Context packet pointer as unconfirmed binding
35
+ and refuses its source endpoint. Sequence allocation recovers dead owners while
36
+ preserving live writers; interrupted recovery has an explicit offline procedure.
37
+ - Integration coverage now observes the actual next picker and committed QA with
38
+ complete local spec/build identity, then independently changes each binding.
39
+
40
+ ## [1.36.0] - 2026-09-18
41
+
42
+ ### Added
43
+
44
+ - Minimal progress snapshots observe canonical next-stage recommendations and
45
+ committed QA without replacing lifecycle rules or altering closeout. Separate
46
+ saved Map, semantic spec and output identities prevent completion claims from
47
+ crossing builds. A strict portable progress export, v0 schema and example
48
+ fixture support receiver validation and grouped histories without readiness
49
+ inference.
50
+ - Immutable local capture precedes consent-scoped delivery to the planned
51
+ progress receiver. Bounded retry preserves exact bytes and requires a matching
52
+ digest acknowledgment; failures leave the lifecycle result unchanged.
53
+ No-write disables capture/send and no-remit keeps observations local.
54
+
55
+ ### Changed
56
+
57
+ - Telemetry disclosure includes minimal stage observations intended for Workspace.
58
+ Noncanonical progress sharing requires explicit scoped opt-in; unscoped
59
+ environment ON does not bypass that protection. Fetched Map provenance retains
60
+ its original saved hash and local baseline separately from raw spec bytes.
61
+
62
+ ## [1.35.0] - 2026-09-18
63
+
64
+ ### Added
65
+
66
+ - A public activation/access/evidence contract separates installed tooling,
67
+ demo previews, saved Maps, resolved campaigns, observed previews, and recorded
68
+ QA while preserving the existing lifecycle and independent trust/freshness
69
+ and revision checks.
70
+ - `tooling diagnose [--packet <packet>] [--platform <profile>] [--json]`
71
+ projects installation status and the read-only doctor's next recommendation
72
+ into a compact support export. A fixed allowlist excludes paths, URLs,
73
+ credentials, identities, order values, content, argv, and environment.
74
+ Unknown producer values receive fixed markers and no repair authority.
75
+ Diagnosis never sweeps sessions, writes evidence, runs orders, or publishes.
76
+
77
+ ### Changed
78
+
79
+ - Exact npm project-local devDependency installation is the primary public
80
+ path; exact global releases and reviewed full-SHA sources remain supported.
81
+ Installed skills use the package-owned browser command and explain invocation
82
+ translation for local, global, and contributor installations.
83
+
84
+ ### Fixed
85
+
86
+ - Global npm installations are distinguished from campaign-local dependencies.
87
+ Global recovery commands address the inspected copy even when another
88
+ installation shadows it; project-local commands continue to resolve via npx.
89
+ Publication recovery continues to use `qa publish` on retained evidence,
90
+ without repeating checkout or placing another order.
91
+
92
+ ## [1.34.1+agent.1] - 2026-09-18
93
+
94
+ ### Changed
95
+
96
+ - Upgrade HTML parsing to parse5 8.0.1 and entities 8.1.0. Existing ESM
97
+ imports and the Node 20.19 minimum remain compatible; no consumer migration
98
+ or supported API change is required.
99
+
100
+ ## [1.34.1] - 2026-09-18
101
+
102
+ ### Fixed
103
+
104
+ - Playwright 1.63.0 and YAML 2.9.1 are validated with runtime recipe 1.0.2,
105
+ whose install-script expectation reflects removal of fsevents. The v1
106
+ contract retains exact agreement for additions and removals.
107
+ - CI runs independent TypeScript, unit, contract and required Chromium checks
108
+ behind the existing `check` status. Missing Chromium fails browser proof.
109
+ Installed-package checks exercise shared, conflicting and latest consumer
110
+ Playwright versions using the package-owned browser installer and launcher.
111
+ - Unit tests are discovered automatically as the codebase grows. Dependabot
112
+ groups minor/patch updates and leaves major API upgrades separate.
113
+
114
+ ## [1.34.0] - 2026-09-17
115
+
116
+ ### Added
117
+
118
+ - `campaigns-os sdk storage-check --target <git-root> --target-sdk <x.y.z>
119
+ --manifest <SDK-manifest.json> --scope <dir,file> [--exclude <dir,file>]
120
+ [--json]` checks Git-tracked campaign HTML and JavaScript before an SDK
121
+ upgrade. The SDK-owned migration manifest supplies storage keys, verified
122
+ release boundaries, and public replacements; the scanner carries no second
123
+ registry. Explicit source scope and exclusions are recorded with file hashes.
124
+ Inline scripts and local shared scripts are checked, with findings at their
125
+ original source locations. Known incompatible accesses fail the check;
126
+ unresolved code, unreadable sources, and unsupported target versions cannot
127
+ produce a clean result. No merchant source, SDK pin, or lifecycle journal is
128
+ written. The report identifies manifest bytes and available Git provenance.
129
+ - The new `sdk` CLI command and its reference are supported surface. This is
130
+ source compatibility evidence only: order, browser, and analytics behavior
131
+ still need their own proof. Supply the SDK manifest explicitly; the pending
132
+ SDK contract change does not imply an existing released tag contains it.
133
+
5
134
  ## [1.33.0+agent.5] - 2026-09-17
6
135
 
7
136
  ### Changed
package/README.md CHANGED
@@ -19,28 +19,31 @@ This toolkit gives campaign developers and AI coding tools a clear path for asse
19
19
 
20
20
  The toolkit is contract-backed: starter templates describe which parts are reusable page structure, which parts are live commerce wiring, and which demo values must be replaced for a real campaign. That helps AI tools avoid common mistakes like carrying over sample package IDs, copying shipping options from the wrong template shape, or editing SDK-owned checkout surfaces as plain HTML.
21
21
 
22
+ See [activation, access, and evidence](docs/activation-and-evidence.md) for what
23
+ installation, a saved Map, preview observation, and recorded QA each establish.
24
+
22
25
  ## Quick Start
23
26
 
24
27
  You do not need to clone this repository to use it. The toolkit is pinned as a
25
28
  devDependency of the campaign folder (a page-kit project) and runs through
26
- `npx campaigns-os …` from that folder — the pin is committed in `package.json`,
27
- so CI and the deploy host install the same commit. Requirements: Node
29
+ `npx campaigns-os …` from that folder — the pin is committed in `package.json`
30
+ and the lockfile, so CI and the deploy host install the same package bytes. Requirements: Node
28
31
  `>=20.19.0` and npm 10 or 11 (Node 22 ships npm 10). Three steps, in this
29
32
  order:
30
33
 
31
34
  1. **Orient before you run anything.** Read
32
35
  [`AGENTS.md`](AGENTS.md), `contracts/supported-surface.json`,
33
36
  `contracts/release-ledger.json` and `CHANGELOG.md` on GitHub at one commit,
34
- and keep that commit's sha. Orientation is a read of declarative data; it
37
+ using the canonical reading order in `AGENTS.md`, and keep that commit's sha. Orientation is a read of declarative data; it
35
38
  never executes toolkit code.
36
- 2. **Pin the toolkit and install its agent skills** from that same commit.
37
- 3. **Start a build** from that same commit.
39
+ 2. **Pin the reviewed release and install its agent skills.** Check the release tag/provenance against the reviewed source commit.
40
+ 3. **Start a real campaign build** from that installation.
38
41
 
39
42
  ```bash
40
43
  mkdir "<route>" && cd "<route>"
41
44
  npm init -y && npm i next-campaign-page-kit
42
45
  npx campaign-init --non-interactive --template <family> --slug "<route>" --name "<campaign name>"
43
- npm i -D "github:NextCommerceCo/campaigns-os#<sha>"
46
+ npm install --save-dev --save-exact @nextcommerce/campaigns-os@1.34.1
44
47
  npx campaigns-os tooling status --platform claude
45
48
  npx campaigns-os install-skills --platform claude
46
49
  mkdir -p source
@@ -50,8 +53,9 @@ The toolkit is also published to npm as `@nextcommerce/campaigns-os`, so the
50
53
  CLI can be installed once, globally, instead of pinned per campaign:
51
54
 
52
55
  ```bash
53
- npm install -g @nextcommerce/campaigns-os
56
+ npm install -g @nextcommerce/campaigns-os@1.34.1
54
57
  campaigns-os tooling status --platform claude
58
+ campaigns-os install-skills --platform claude
55
59
  ```
56
60
 
57
61
  A global install ships without a browser. Polish capture and QA need the
@@ -65,22 +69,37 @@ runs the full check in an unprivileged job and publishes the verified tarball
65
69
  with provenance from a second, environment-gated job.
66
70
 
67
71
  For an existing page-kit campaign, skip the first three lines and `cd` into it
68
- (its `package.json` already declares `next-campaign-page-kit`). `#<sha>` is
69
- the commit you oriented on, so the code that runs is the code whose contracts
70
- you read; npm records the resolved commit in the folder's `package.json` and
71
- `package-lock.json`, which is how `tooling status` can print `Install mode:
72
- package install (node_modules), pinned at <version> @ <sha>`. The install runs
73
- the package's own build step (about 7 s). On a fresh profile that first
74
- `tooling status --platform claude` exits 2 with `ATTENTION_REQUIRED` and one
75
- action, the `install-skills` line — it is telling you the skills are not
76
- installed yet, not that the install failed; run it again after
77
- `install-skills` for `READY`. Without `--platform`, status checks every agent
78
- profile (Claude, Codex, shared) and stays at exit 2 until each is installed.
72
+ (its `package.json` already declares `next-campaign-page-kit`). `1.34.1` is
73
+ an exact published example; choose the release you reviewed, never a floating
74
+ dist-tag for a reproducible build. Commit `package.json` and `package-lock.json`.
75
+ The new `tooling diagnose` command requires 1.35.0 or later. When that release
76
+ is not published yet, use the reviewed full-SHA source pin below; the 1.34.1
77
+ example does not include diagnostics or the global invocation rendering fix.
78
+ A Git source pin remains supported when using an unreleased reviewed commit:
79
+ `npm install --save-dev --save-exact "github:NextCommerceCo/campaigns-os#<full-sha>"`.
80
+
81
+ For a visual sample, candidate 1.37.0 adds
82
+ `npx campaigns-os demo --target ./apollo-sample`. Open the printed
83
+ `landing/index.html` directly to explore four inert Apollo pages. This command
84
+ requires a reviewed candidate or a published release at least 1.37.0; the 1.34.1
85
+ example above does not include it. It downloads nothing and creates no campaign
86
+ evidence. Keep sample edits and start a real campaign in a separate new Page Kit
87
+ folder. See [offline sample preview](docs/demo-preview.md).
88
+ The lockfile records the resolved source and integrity; `tooling status` reports
89
+ install mode, package version, and a source commit when derivable. It does not
90
+ check registry currency or establish trust. On a fresh profile, preflight exits
91
+ 2 with `ATTENTION_REQUIRED` until that profile's skills are installed. Run
92
+ `tooling status --platform claude` again after `install-skills` for `READY`;
93
+ use `--platform codex` for a Codex-only profile. Without `--platform`, status
94
+ checks every supported agent profile.
79
95
  `install-skills` writes `~/.claude/skills` (`--platform codex` writes
80
96
  `~/.codex/skills`), replacing same-name folders; restart the agent after.
97
+ Run commands from the campaign folder: `npx` selects its local installation
98
+ even when another global copy is on PATH. A global-only installation prints
99
+ bare commands when its binary matches PATH, or an explicit `node` invocation
100
+ when another install shadows it.
81
101
  Prepared page HTML goes in `./source`, which must exist even when every page is
82
- template stock. To move to a newer commit, re-orient on it and run `npm i -D
83
- "github:NextCommerceCo/campaigns-os#<new-sha>"` again.
102
+ template stock. To update, review the new release source and install its exact version again.
84
103
 
85
104
  > **Heads up — `start` turns on run telemetry, and remit is ON by default.**
86
105
  > The first `start` opens a run session in the target folder and, unless you
@@ -211,6 +230,8 @@ design markup separate from SDK-owned commerce controls.
211
230
 
212
231
  ## Important Commands
213
232
 
233
+ Before an SDK bump, scan explicitly scoped tracked merchant HTML/JS with [SDK storage compatibility](docs/sdk-storage-compatibility.md). The SDK-generated manifest is supplied separately; a clean result covers static source compatibility only.
234
+
214
235
  ```bash
215
236
  npm run campaigns-os -- tooling status
216
237
  npm run campaigns-os -- install-skills --dry-run
@@ -219,6 +240,7 @@ npm run campaigns-os -- qa install-browser
219
240
  npm run skills -- status
220
241
  npm run campaigns-os -- prepare-build --spec <spec.json> --source <html-dir> --target <page-kit-repo> --template-family <family> --brief <campaign-build-brief.yaml>
221
242
  npm run campaigns-os -- doctor --packet <page-kit-repo>/campaign-runtime.build.json
243
+ npm run campaigns-os -- sdk storage-check --target <campaign-git-root> --target-sdk 0.4.38 --manifest <sdk-storage-manifest.json> --scope <campaign,shared> --json
222
244
  npm run campaigns-os -- standardize --target <page-kit-repo-or-cpk-repo> --json
223
245
  npm run campaigns-os -- theme inspect --packet <page-kit-repo>/campaign-runtime.build.json --json
224
246
  npm run campaigns-os -- theme generate --packet <page-kit-repo>/campaign-runtime.build.json --json
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@nextcommerce/campaigns-os",
3
- "version": "1.33.0",
3
+ "version": "1.34.0",
4
4
  "status": "developer-preview",
5
5
  "contracts": {
6
6
  "campaign_spec": "4.2-4.3",
@@ -87,6 +87,7 @@
87
87
  { "match": { "kind": "prefix", "value": "contracts/fixtures/" }, "reason": "Test fixtures. Consumer-facing fixtures reach the supported surface through contracts/supported-surface.json named[], which the derived pass classifies first." },
88
88
  { "match": { "kind": "prefix", "value": "fixtures/" }, "reason": "Test fixtures." },
89
89
  { "match": { "kind": "prefix", "value": "scripts/" }, "reason": "Repository checkers. Explicitly unsupported implementation (docs/supported-surface.md)." },
90
+ { "match": { "kind": "prefix", "value": "demo/" }, "reason": "Static projection implementation copied by the supported demo command; the declared provenance manifest pins all output digests. Named and hashed entries are classified by the derived supported-surface pass first." },
90
91
  { "match": { "kind": "prefix", "value": "src/" }, "reason": "Implementation. Explicitly unsupported except through declared package exports, which package.json changes classify." },
91
92
  { "match": { "kind": "prefix", "value": "campaign-spec/" }, "reason": "Tests, fixtures, and packaging metadata for the generated runtime. The runtime sources a consumer must rebuild are classified by the generated_runtime rule first; only that rule's exclusions reach here." },
92
93
  { "match": { "kind": "prefix", "value": "examples/" }, "reason": "Illustrative, regenerated at will (docs/supported-surface.md)." },
@@ -0,0 +1,89 @@
1
+ {
2
+ "schema_version": "campaigns-os-progress-snapshot/v0",
3
+ "stream_id": "progress_11111111111111111111111111111111",
4
+ "sequence": 1,
5
+ "previous_snapshot_id": null,
6
+ "observed_at": "2026-09-18T00:00:00.000Z",
7
+ "package_version": "1.36.0",
8
+ "producer": "next",
9
+ "identity": {
10
+ "map_id": "example-map",
11
+ "map_revision_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
12
+ "map_revision_algorithm": "map-store-v1",
13
+ "saved_revision_alignment": "aligned",
14
+ "local_spec_material_hash": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
15
+ "local_spec_material_algorithm": "campaign-spec-material-v1",
16
+ "build_fingerprint": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
17
+ "build_fingerprint_algorithm": "sha256-manifest/v1"
18
+ },
19
+ "stages": [
20
+ {
21
+ "stage": "prepare_build",
22
+ "status": "completed",
23
+ "build_binding": "unconfirmed",
24
+ "source_build_fingerprint": null
25
+ },
26
+ {
27
+ "stage": "setup",
28
+ "status": "completed",
29
+ "build_binding": "unconfirmed",
30
+ "source_build_fingerprint": null
31
+ },
32
+ {
33
+ "stage": "assembly",
34
+ "status": "completed",
35
+ "build_binding": "matching",
36
+ "source_build_fingerprint": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
37
+ },
38
+ {
39
+ "stage": "polish",
40
+ "status": "pending",
41
+ "build_binding": "unconfirmed",
42
+ "source_build_fingerprint": null
43
+ },
44
+ {
45
+ "stage": "deploy",
46
+ "status": "pending",
47
+ "build_binding": "unconfirmed",
48
+ "source_build_fingerprint": null
49
+ },
50
+ {
51
+ "stage": "qa",
52
+ "status": "pending",
53
+ "build_binding": "unconfirmed",
54
+ "source_build_fingerprint": null
55
+ }
56
+ ],
57
+ "preview": {
58
+ "present": false,
59
+ "url_hash": null
60
+ },
61
+ "continuation": {
62
+ "stage": "polish",
63
+ "blocked": false,
64
+ "divergent": false,
65
+ "action_ids": [
66
+ "polish_skill"
67
+ ],
68
+ "gates": [
69
+ {
70
+ "id": "doctor",
71
+ "state": "pass"
72
+ },
73
+ {
74
+ "id": "prepare_build",
75
+ "state": "pass"
76
+ },
77
+ {
78
+ "id": "theme_gate",
79
+ "state": "waived"
80
+ },
81
+ {
82
+ "id": "polish_gate",
83
+ "state": "not_applicable"
84
+ }
85
+ ]
86
+ },
87
+ "qa": null,
88
+ "snapshot_id": "sha256:f52f2418c30e6696471fbcc86dcc3fc28caa7e17df9151b58d150747dd3f48fb"
89
+ }
@@ -3,7 +3,7 @@
3
3
  "_growth_note": "When a bound below is genuinely reached, the answer is to find out why before raising it. A dependency install that exceeds its bound on a warm machine is a supply-chain change, not a slow morning; an output inventory that exceeds its file or byte bound is a build that went wrong, not a package that grew 50x overnight. Raising a bound is the fallback, it advances recipe_revision, and it owes a release-ledger entry. Widening the accepted npm range follows the same path, and its trigger is external and checkable: widen when a Node release line ships that npm major by default, not when a particular machine happens to have it installed.",
4
4
  "schema": "campaigns-os-runtime-recipe/v1",
5
5
  "recipe_kind": "campaigns-os-node-v1",
6
- "recipe_revision": "1.0.1",
6
+ "recipe_revision": "1.0.2",
7
7
  "refusal_reason_code": "runtime_recipe_refused",
8
8
  "fail_closed": true,
9
9
  "unperformable_check_disposition": "failed",
@@ -84,7 +84,7 @@
84
84
  "stdin": "closed",
85
85
  "lifecycle_scripts": "disabled",
86
86
  "timeout_bound": "install_seconds",
87
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
87
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
88
88
  },
89
89
  {
90
90
  "id": "build",
@@ -286,9 +286,7 @@
286
286
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
287
287
  "prepare": "npm run build:spec"
288
288
  },
289
- "install_script_dependencies": [
290
- "fsevents"
291
- ]
289
+ "install_script_dependencies": []
292
290
  },
293
291
  "capabilities": {
294
292
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": "campaigns-os-runtime-recipe/v1",
3
3
  "recipe_kind": "campaigns-os-node-v1",
4
- "recipe_revision": "1.0.1",
4
+ "recipe_revision": "1.0.2",
5
5
  "refusal_reason_code": "runtime_recipe_refused",
6
6
  "fail_closed": true,
7
7
  "unperformable_check_disposition": "failed",
@@ -79,7 +79,7 @@
79
79
  "stdin": "closed",
80
80
  "lifecycle_scripts": "disabled",
81
81
  "timeout_bound": "install_seconds",
82
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
82
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
83
83
  },
84
84
  {
85
85
  "id": "build",
@@ -281,9 +281,7 @@
281
281
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
282
282
  "prepare": "npm run build:spec"
283
283
  },
284
- "install_script_dependencies": [
285
- "fsevents"
286
- ]
284
+ "install_script_dependencies": []
287
285
  },
288
286
  "capabilities": {
289
287
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",
@@ -3,7 +3,7 @@
3
3
  "_growth_note": "When a bound below is genuinely reached, the answer is to find out why before raising it. A dependency install that exceeds its bound on a warm machine is a supply-chain change, not a slow morning; an output inventory that exceeds its file or byte bound is a build that went wrong, not a package that grew 50x overnight. Raising a bound is the fallback, it advances recipe_revision, and it owes a release-ledger entry. Widening the accepted npm range follows the same path, and its trigger is external and checkable: widen when a Node release line ships that npm major by default, not when a particular machine happens to have it installed.",
4
4
  "schema": "campaigns-os-runtime-recipe/v1",
5
5
  "recipe_kind": "campaigns-os-node-v1",
6
- "recipe_revision": "1.0.1",
6
+ "recipe_revision": "1.0.2",
7
7
  "refusal_reason_code": "runtime_recipe_refused",
8
8
  "fail_closed": false,
9
9
  "unperformable_check_disposition": "failed",
@@ -84,7 +84,7 @@
84
84
  "stdin": "closed",
85
85
  "lifecycle_scripts": "disabled",
86
86
  "timeout_bound": "install_seconds",
87
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
87
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
88
88
  },
89
89
  {
90
90
  "id": "build",
@@ -286,9 +286,7 @@
286
286
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
287
287
  "prepare": "npm run build:spec"
288
288
  },
289
- "install_script_dependencies": [
290
- "fsevents"
291
- ]
289
+ "install_script_dependencies": []
292
290
  },
293
291
  "capabilities": {
294
292
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",
@@ -3,7 +3,7 @@
3
3
  "_growth_note": "When a bound below is genuinely reached, the answer is to find out why before raising it. A dependency install that exceeds its bound on a warm machine is a supply-chain change, not a slow morning; an output inventory that exceeds its file or byte bound is a build that went wrong, not a package that grew 50x overnight. Raising a bound is the fallback, it advances recipe_revision, and it owes a release-ledger entry. Widening the accepted npm range follows the same path, and its trigger is external and checkable: widen when a Node release line ships that npm major by default, not when a particular machine happens to have it installed.",
4
4
  "schema": "campaigns-os-runtime-recipe/v1",
5
5
  "recipe_kind": "campaigns-os-node-v1",
6
- "recipe_revision": "1.0.1",
6
+ "recipe_revision": "1.0.2",
7
7
  "refusal_reason_code": "runtime_recipe_refused",
8
8
  "fail_closed": true,
9
9
  "unperformable_check_disposition": "failed",
@@ -82,7 +82,7 @@
82
82
  "stdin": "closed",
83
83
  "lifecycle_scripts": "disabled",
84
84
  "timeout_bound": "install_seconds",
85
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
85
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
86
86
  },
87
87
  {
88
88
  "id": "build",
@@ -284,9 +284,7 @@
284
284
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
285
285
  "prepare": "npm run build:spec"
286
286
  },
287
- "install_script_dependencies": [
288
- "fsevents"
289
- ]
287
+ "install_script_dependencies": []
290
288
  },
291
289
  "capabilities": {
292
290
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",
@@ -3,7 +3,7 @@
3
3
  "_growth_note": "When a bound below is genuinely reached, the answer is to find out why before raising it. A dependency install that exceeds its bound on a warm machine is a supply-chain change, not a slow morning; an output inventory that exceeds its file or byte bound is a build that went wrong, not a package that grew 50x overnight. Raising a bound is the fallback, it advances recipe_revision, and it owes a release-ledger entry. Widening the accepted npm range follows the same path, and its trigger is external and checkable: widen when a Node release line ships that npm major by default, not when a particular machine happens to have it installed.",
4
4
  "schema": "campaigns-os-runtime-recipe/v1",
5
5
  "recipe_kind": "campaigns-os-node-v1",
6
- "recipe_revision": "1.0.1",
6
+ "recipe_revision": "1.0.2",
7
7
  "refusal_reason_code": "runtime_recipe_refused",
8
8
  "fail_closed": true,
9
9
  "unperformable_check_disposition": "failed",
@@ -84,7 +84,7 @@
84
84
  "stdin": "closed",
85
85
  "lifecycle_scripts": "disabled",
86
86
  "timeout_bound": "install_seconds",
87
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
87
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
88
88
  },
89
89
  {
90
90
  "id": "build",
@@ -286,9 +286,7 @@
286
286
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
287
287
  "prepare": "npm run build:spec"
288
288
  },
289
- "install_script_dependencies": [
290
- "fsevents"
291
- ]
289
+ "install_script_dependencies": []
292
290
  },
293
291
  "capabilities": {
294
292
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",
@@ -3,7 +3,7 @@
3
3
  "_growth_note": "When a bound below is genuinely reached, the answer is to find out why before raising it. A dependency install that exceeds its bound on a warm machine is a supply-chain change, not a slow morning; an output inventory that exceeds its file or byte bound is a build that went wrong, not a package that grew 50x overnight. Raising a bound is the fallback, it advances recipe_revision, and it owes a release-ledger entry. Widening the accepted npm range follows the same path, and its trigger is external and checkable: widen when a Node release line ships that npm major by default, not when a particular machine happens to have it installed.",
4
4
  "schema": "campaigns-os-runtime-recipe/v1",
5
5
  "recipe_kind": "campaigns-os-node-v1",
6
- "recipe_revision": "1.0.1",
6
+ "recipe_revision": "1.0.2",
7
7
  "refusal_reason_code": "runtime_recipe_refused",
8
8
  "fail_closed": true,
9
9
  "unperformable_check_disposition": "failed",
@@ -84,7 +84,7 @@
84
84
  "stdin": "closed",
85
85
  "lifecycle_scripts": "disabled",
86
86
  "timeout_bound": "install_seconds",
87
- "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
87
+ "rationale": "ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime."
88
88
  },
89
89
  {
90
90
  "id": "build",
@@ -286,9 +286,7 @@
286
286
  "build:spec": "tsc -p campaign-spec/tsconfig.build.json",
287
287
  "prepare": "npm run build:spec"
288
288
  },
289
- "install_script_dependencies": [
290
- "fsevents"
291
- ]
289
+ "install_script_dependencies": []
292
290
  },
293
291
  "capabilities": {
294
292
  "_note": "What a generation prepared by this recipe can and cannot do. Stated explicitly because 'runtime ready' invites the wrong reading: the same flag that makes the install safe also means the prepared generation has no browser to drive. Preparing a runtime and being able to run browser QA are different readiness questions, and this recipe answers only the first.",