@nextcommerce/campaigns-os 1.60.0 → 1.62.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 (161) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +244 -0
  3. package/README.md +86 -438
  4. package/agents/claude/CLAUDE.md +20 -0
  5. package/agents/codex/AGENTS.md +19 -0
  6. package/agents/copilot/copilot-instructions.md +19 -0
  7. package/agents/cursor/campaigns-os.mdc +21 -0
  8. package/campaign-spec/README.md +7 -0
  9. package/campaign-spec/dist/analytics-vendors.d.ts +40 -0
  10. package/campaign-spec/dist/analytics-vendors.js +44 -0
  11. package/campaign-spec/dist/checkout-flow.d.ts +18 -0
  12. package/campaign-spec/dist/checkout-flow.js +28 -0
  13. package/campaign-spec/dist/index.d.ts +4 -2
  14. package/campaign-spec/dist/index.js +5 -1
  15. package/campaign-spec/dist/rules/analytics-contract-shape.d.ts +8 -0
  16. package/campaign-spec/dist/rules/analytics-contract-shape.js +39 -0
  17. package/campaign-spec/dist/rules/campaign-currencies.d.ts +29 -0
  18. package/campaign-spec/dist/rules/campaign-currencies.js +130 -0
  19. package/campaign-spec/dist/rules/checkout-path-has-packages.d.ts +31 -0
  20. package/campaign-spec/dist/rules/checkout-path-has-packages.js +79 -0
  21. package/campaign-spec/dist/rules/index.d.ts +2 -0
  22. package/campaign-spec/dist/rules/index.js +6 -0
  23. package/campaign-spec/dist/types.d.ts +43 -9
  24. package/compatibility.json +1 -1
  25. package/contracts/brand-theme-target-tokens.next-core.v0.json +95 -25
  26. package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
  27. package/contracts/commerce-surface-catalog.json +68 -61
  28. package/contracts/effects.v1.json +549 -165
  29. package/contracts/fixtures/runtime-recipe/accept/current.json +3 -0
  30. package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -0
  31. package/contracts/fixtures/runtime-recipe/dist-states.json +1 -1
  32. package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -0
  33. package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -0
  34. package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -0
  35. package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -0
  36. package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -0
  37. package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -0
  38. package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -0
  39. package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -0
  40. package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +3 -0
  41. package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -0
  42. package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -0
  43. package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -0
  44. package/contracts/release-ledger.json +1767 -0
  45. package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -0
  46. package/contracts/supported-surface.json +10 -10
  47. package/contracts/template-brand-contract.shared-commerce.v0.json +23 -1
  48. package/docs/access-model.md +20 -0
  49. package/docs/brand-theme-bridge.md +62 -3
  50. package/docs/build-packet.md +456 -36
  51. package/docs/campaign-build-brief.md +16 -0
  52. package/docs/campaign-standardization-report.md +4 -4
  53. package/docs/campaigns-os-build-flow.md +112 -2
  54. package/docs/campaignspec-authoring-examples.md +141 -0
  55. package/docs/design-source-package.md +64 -8
  56. package/docs/effects.md +17 -9
  57. package/docs/entry-points.md +188 -0
  58. package/docs/local-setup.md +1 -1
  59. package/docs/orientation-contract-reference.md +1 -1
  60. package/docs/polish-evidence.md +42 -2
  61. package/docs/progress-snapshots.md +7 -4
  62. package/docs/qa-and-test-orders.md +197 -3
  63. package/docs/quickstart.md +438 -0
  64. package/docs/readback.md +154 -6
  65. package/docs/runtime-readiness.md +6 -3
  66. package/docs/sdk-storage-compatibility.md +4 -2
  67. package/docs/skills-revision.md +10 -10
  68. package/docs/source-adapters.md +213 -0
  69. package/package.json +10 -3
  70. package/schemas/campaign-design-source-package.v0.schema.json +8 -0
  71. package/schemas/campaign-runtime-build-context.v0.schema.json +9 -0
  72. package/schemas/campaign-runtime-build-packet.v0.schema.json +9 -0
  73. package/schemas/campaign-spec.v4.schema.json +19 -3
  74. package/schemas/campaign-spec.v5.schema.json +19 -3
  75. package/schemas/campaigns-os-readback.v2.schema.json +238 -1
  76. package/schemas/source-html-manifest.v0.schema.json +3 -0
  77. package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
  78. package/skills/campaign-readback-classification/SKILL.md +3 -3
  79. package/skills/campaign-run-evidence/SKILL.md +3 -3
  80. package/skills/contribution-intake/SKILL.md +3 -3
  81. package/skills/next-campaigns-build/SKILL.md +5 -4
  82. package/skills/next-campaigns-os/SKILL.md +7 -4
  83. package/skills/next-campaigns-os-setup/SKILL.md +5 -3
  84. package/skills/next-campaigns-polish/SKILL.md +8 -10
  85. package/skills/next-campaigns-qa/SKILL.md +7 -4
  86. package/skills/next-campaigns-sdk-bump/SKILL.md +151 -25
  87. package/skills.json +11 -11
  88. package/src/brand-theme.mjs +415 -9
  89. package/src/brief-summary.mjs +6 -2
  90. package/src/browser-launch.mjs +2 -1
  91. package/src/build-brief.mjs +13 -3
  92. package/src/built-site-scope.mjs +2 -2
  93. package/src/campaign-workspace.mjs +288 -15
  94. package/src/change-scope.mjs +284 -0
  95. package/src/cli.mjs +358 -97
  96. package/src/commercial-journey.mjs +16 -3
  97. package/src/commercial-parity.mjs +15 -7
  98. package/src/content-residue.mjs +4 -2
  99. package/src/design-file-reference.mjs +93 -0
  100. package/src/design-source-package.mjs +91 -1
  101. package/src/design-source-publication.mjs +9 -6
  102. package/src/directory-lock.mjs +73 -19
  103. package/src/doctor/checks.mjs +87 -81
  104. package/src/doctor/ci.mjs +177 -0
  105. package/src/doctor/inspect.mjs +41 -6
  106. package/src/doctor/next-step.mjs +7 -0
  107. package/src/doctor/source-provenance.mjs +74 -0
  108. package/src/doctor-sidecar.mjs +3 -2
  109. package/src/evidence-debt.mjs +159 -0
  110. package/src/finding-cause.mjs +12 -11
  111. package/src/input-refresh.mjs +339 -32
  112. package/src/invocation.mjs +7 -1
  113. package/src/live-campaign-refs.mjs +7 -2
  114. package/src/local-preview-policy.mjs +35 -2
  115. package/src/page-kit-analytics-vendors.mjs +132 -0
  116. package/src/parity/compare.mjs +316 -0
  117. package/src/parity/design-access.mjs +54 -0
  118. package/src/parity/element-parity-record.mjs +569 -0
  119. package/src/parity/probe.mjs +205 -0
  120. package/src/parity/snapshot.mjs +110 -0
  121. package/src/png-header.mjs +87 -0
  122. package/src/polish-browser.mjs +189 -10
  123. package/src/polish-captures-record.mjs +52 -0
  124. package/src/polish-deadline.mjs +14 -0
  125. package/src/polish-gate.mjs +25 -6
  126. package/src/polish-node.mjs +81 -7
  127. package/src/polish-readability.mjs +221 -9
  128. package/src/polish-visual-fixtures.mjs +74 -0
  129. package/src/polish-visual.mjs +613 -0
  130. package/src/progress-node.mjs +3 -2
  131. package/src/qa-analytics-correctness.mjs +14 -2
  132. package/src/qa-analytics-parity.mjs +111 -6
  133. package/src/qa-browser.mjs +40 -4
  134. package/src/qa-commercial-parity.mjs +50 -3
  135. package/src/qa-node.mjs +235 -22
  136. package/src/qa-publish.mjs +9 -8
  137. package/src/qa-sidecar.mjs +16 -4
  138. package/src/qa-vendor-beacons.mjs +232 -0
  139. package/src/qa-vendor-endpoints.mjs +306 -0
  140. package/src/qc-accept.mjs +176 -6
  141. package/src/qc-check-registry.mjs +42 -2
  142. package/src/qc-results.mjs +477 -42
  143. package/src/readback.mjs +113 -21
  144. package/src/route-identity.mjs +10 -0
  145. package/src/run-record.mjs +18 -10
  146. package/src/runtime-state-ignore.mjs +6 -2
  147. package/src/sdk-attribute-index.mjs +11 -11
  148. package/src/sdk-markup.mjs +77 -2
  149. package/src/sdk-storage-compatibility.mjs +115 -6
  150. package/src/source-html-intake.mjs +15 -1
  151. package/src/source-html-manifest.mjs +7 -0
  152. package/src/source-html-server.mjs +129 -0
  153. package/src/spec-derive-campaign.mjs +216 -0
  154. package/src/spec-derive.mjs +473 -53
  155. package/src/spec-identity.mjs +14 -0
  156. package/src/stage-ledger.mjs +40 -1
  157. package/src/stage-record.mjs +100 -17
  158. package/src/target-lock.mjs +11 -1
  159. package/src/theme-gate.mjs +2 -2
  160. package/src/visual-diff.mjs +296 -0
  161. package/src/visual-reference.mjs +126 -0
package/README.md CHANGED
@@ -1,471 +1,119 @@
1
1
  # Campaigns OS
2
2
 
3
- Campaigns OS is the developer toolkit for agent-assisted campaign builds on [Next Commerce](https://nextcommerce.com), a full-stack ecommerce platform for direct-response brands. A *campaign* is a short, conversion-focused funnel — landing page, checkout, optional upsells/downsells, receipt — wired to live products, price tiers, shipping, and payments.
4
-
5
- This toolkit gives campaign developers and AI coding tools a clear path for assembling one from prepared page files:
6
-
7
- 1. Configure the campaign in the Next Commerce dashboard (Campaigns App).
8
- 2. Use the current saved Map in [Campaign Map Builder](https://campaign-map.nextcommerce.com), or have the coding agent author a [local CampaignSpec](docs/build-packet.md#local-spec-entry) from the brief and verified campaign values.
9
- 3. Keep the CampaignSpec JSON with its saved Map ID or stable `local_spec_id`, plus its public route slug.
10
- 4. Bring prepared HTML/CSS/assets for the campaign pages.
11
- 5. Provide or generate a [Campaign Build Brief](./docs/campaign-build-brief.md) for merchandising/design presentation decisions.
12
- 6. Create and doctor a Build Packet.
13
- 7. Hand off to `next-campaigns-build`.
14
- 8. Run build/lint and record the build with `campaigns-os record build`, then install the Campaigns OS Playwright browser once with `campaigns-os qa install-browser`.
15
- 9. Run `next-campaigns-polish`, serve the current build, run the mandatory `campaigns-os polish capture` producer, then record Polish with `campaigns-os record polish --evidence <file>`.
16
- 10. Deploy a preview and record it with `campaigns-os record deploy --base-url <route root>`: for a local preview (`--deploy-target local-serve`), serve the current build and pass its loopback route root; for a hosted preview, deploy through your host and pass the https route root. A later `record build` of different output makes the deploy owed again.
17
- 11. Run `next-campaigns-qa` against the tested URL.
18
- 12. Record launch blockers and follow-up work.
19
-
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
-
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
-
25
- ## Quick Start
26
-
27
- You do not need to clone this repository to use it. The toolkit is pinned as a
28
- devDependency of the campaign folder (a page-kit project) and runs through
29
- `npx --no-install campaigns-os …` from that folder — the pin is committed in
30
- `package.json` and the lockfile, so CI and the deploy host install the same
31
- package bytes. Keep `--no-install`: `campaigns-os` is only the bin name of
32
- `@nextcommerce/campaigns-os`, so in a folder without the pinned copy a plain
33
- `npx campaigns-os` looks that name up on the registry and, with no terminal to
34
- ask, installs what it finds; with the flag, npx stops with an error instead.
35
- Requirements: Node `>=20.19.0` and npm 10 or 11 (Node 22 ships npm 10). Three
36
- steps, in this order:
37
-
38
- 1. **Orient before you run anything.** Read
39
- [`AGENTS.md`](AGENTS.md), `contracts/supported-surface.json`,
40
- `contracts/release-ledger.json` and `CHANGELOG.md` on GitHub at one commit,
41
- using the canonical reading order in `AGENTS.md`, and keep that commit's sha. Orientation is a read of declarative data; it
42
- never executes toolkit code.
43
- 2. **Pin the reviewed release and install its agent skills.** Check the release tag/provenance against the reviewed source commit.
44
- 3. **Start a real campaign build** from that installation.
3
+ Campaigns OS is the toolkit for building campaigns on [Next Commerce](https://nextcommerce.com) with an AI coding agent. A campaign is a short direct-response funnel (landing page, checkout, optional upsells and downsells, receipt) that sells live products at live prices with real shipping and payment methods. The toolkit takes the campaign's configuration, the prepared page files and a starter template, and walks the agent from intake to a QA'd preview, recording evidence at every stage so a reviewer can see what was built and how it was proved.
4
+
5
+ It is published to npm as `@nextcommerce/campaigns-os` and installed as an exact dev dependency of the campaign folder, which is a Campaign Page Kit project. Nothing is cloned, and every command runs as `npx --no-install campaigns-os …` from that folder.
6
+
7
+ ## What a build looks like
8
+
9
+ 1. **Configure the campaign** in the Campaigns App in the Next Commerce dashboard: create the campaign, add an Offer for each price tier (the products an Offer selects become the campaign's packages), set shipping and payment methods, and note the campaign's API key.
10
+ 2. **Describe it as a CampaignSpec.** Export the saved Map from [Campaign Map Builder](https://campaign-map.nextcommerce.com), or have the agent author a [local CampaignSpec](docs/build-packet.md#local-spec-entry) from the brief and the verified campaign values. The spec carries the Map ID or a stable `local_spec_id`, plus the public route slug.
11
+ 3. **Bring the page files.** Prepared HTML, CSS and assets for the pages you are building go in a `source/` folder with a source manifest and desktop and mobile screenshot proof for each designed page (the [Design Source Package](docs/design-source-package.md)). Pages that use the starter template's own design are declared as template stock rather than left out. A [Campaign Build Brief](docs/campaign-build-brief.md) records the merchandising and presentation decisions.
12
+ 4. **Run `start`.** It writes the Build Packet and the run artifacts into the campaign folder and finishes with doctor. Doctor's first verdict on a fresh folder is normally `BLOCKED` with a list of what to supply. That list is the intake checklist, not a failed install.
13
+ 5. **Follow `next`.** After `start` and after every stage, run `next`. It names the stage, who owns it (a skill, or you for deploy) and the exact commands: setup, then build, then Polish (with `polish capture` against the served build), then deploy (`record deploy --base-url <route root>`), then QA (`qa run --browser --test-order common`). Each `record` command validates what it would write and refuses a stage `next` has not reached.
14
+ 6. **Read the evidence.** Doctor output, the Assembly Report, the QA verdict and the Polish captures stay in the campaign folder under `.campaign-runtime/`. `readback` summarises them and reports whether Polish and QA still match the build on disk.
15
+
16
+ Where it can, the toolkit holds the agent to contracts rather than judgment. Each starter template family ships a contract saying which parts are reusable page structure, which are live commerce wiring, and which demo values must be replaced, and doctor checks the assembled pages against it. That is what stops an agent from carrying sample package IDs into a real checkout or editing SDK-owned checkout markup as plain HTML.
17
+
18
+ ## Install
19
+
20
+ Requirements: Node 20.19 or later and npm 10 or 11. In a new campaign folder:
45
21
 
46
22
  ```bash
47
23
  mkdir "<route>" && cd "<route>"
48
24
  npm init -y && npm i --save-exact next-campaign-page-kit@0.3.0
49
25
  npx campaign-init --non-interactive --template <family> --slug "<route>" --name "<campaign name>"
50
26
  npm install --save-dev --save-exact @nextcommerce/campaigns-os@<version>
51
- npx --no-install campaigns-os tooling status --platform claude
52
- npx --no-install campaigns-os install-skills --platform claude
53
- mkdir -p source
54
27
  ```
55
28
 
56
- With Claude Code, [local setup](docs/local-setup.md) replaces the last two
57
- lines with one: `npx --no-install campaigns-os tooling setup --target .
58
- --platform claude` installs the QA browser, the skills and the project
59
- context, and keeps existing pages and instructions. It does not scaffold
60
- pages; the agent chooses the template at intake. Codex, Cursor and other
61
- agents keep the separate steps: `install-skills --platform codex` (or
62
- `--platform agents`), `install-agent-context --target .` and
63
- `qa install-browser`.
29
+ For an existing Page Kit campaign, skip the first three lines and run the last one in its folder. `<version>` is the exact release you reviewed. `npm view @nextcommerce/campaigns-os version` prints the newest, and [`CHANGELOG.md`](CHANGELOG.md) opens each release with a short summary of what changed and what to do. Pin the exact version and commit `package.json` and `package-lock.json`, so CI and the deploy host install the same bytes.
64
30
 
65
- The toolkit is also published to npm as `@nextcommerce/campaigns-os`, so the
66
- CLI can be installed once, globally, instead of pinned per campaign:
31
+ Then connect your coding agent. With Claude Code, one command installs the QA browser, the bundled skills and the project context, and keeps any existing pages and instructions:
67
32
 
68
33
  ```bash
69
- npm install -g @nextcommerce/campaigns-os@<version>
70
- campaigns-os tooling status --platform claude
71
- campaigns-os install-skills --platform claude
34
+ npx --no-install campaigns-os tooling setup --target . --platform claude
72
35
  ```
73
36
 
74
- A global install ships without a browser. Polish capture and QA need the
75
- Playwright Chromium: run `campaigns-os qa install-browser` once. Playwright
76
- itself is an optional dependency, installed by default; an install that
77
- omitted it (`--omit=optional`) is told exactly that by the commands that need
78
- it, and every other command runs without it.
79
- Releases are cut by pushing a `v<version>` tag that matches `package.json`
80
- and `surface_version` on a commit on `main`; `.github/workflows/publish.yml`
81
- runs the full check in an unprivileged job and publishes the verified tarball
82
- with provenance from a second, environment-gated job.
83
-
84
- For an existing page-kit campaign, skip the first three lines and `cd` into it
85
- (its `package.json` already declares `next-campaign-page-kit`). `<version>` is
86
- the exact release you reviewed. The newest published release is npm's `latest`
87
- (`npm view @nextcommerce/campaigns-os version`), and
88
- `contracts/release-ledger.json` and `CHANGELOG.md` list every release. Pin the
89
- exact version, never a floating dist-tag, for a reproducible build. Commit `package.json` and `package-lock.json`.
90
- `tooling diagnose` requires 1.35.0 or later and `demo` requires 1.37.0 or later.
91
- A Git source pin remains supported when using an unreleased reviewed commit:
92
- `npm install --save-dev --save-exact "github:NextCommerceCo/campaigns-os#<full-sha>"`.
93
-
94
- For a visual sample, run
95
- `npx --no-install campaigns-os demo --target ./apollo-sample` (1.37.0 or later).
96
- It copies four inert Apollo pages; open the printed
97
- `landing/index.html` directly. It downloads nothing and creates no campaign
98
- evidence. Keep sample edits and start a real campaign in a separate new Page Kit
99
- folder. See [offline sample preview](docs/demo-preview.md).
100
- The lockfile records the resolved source and integrity; `tooling status` reports
101
- install mode, package version, and a source commit when derivable. It does not
102
- check registry currency or establish trust. On a fresh profile, preflight exits
103
- 2 with `ATTENTION_REQUIRED` until that profile's skills are installed. Run
104
- `tooling status --platform claude` again after `install-skills` for `READY`;
105
- use `--platform codex` for a Codex-only profile. Without `--platform`, status
106
- checks every supported agent profile.
107
- `install-skills` writes `~/.claude/skills` (`--platform codex` writes
108
- `~/.codex/skills`), replacing same-name folders, and lists each `SKILL.md` it
109
- wrote under `Read now`. A running agent does not load skills installed after it
110
- started, so read those files now in the same session; a new session loads them
111
- on its own.
112
- Run commands from the campaign folder: `npx` selects its local installation
113
- even when another global copy is on PATH. A global-only installation prints
114
- bare commands when its binary matches PATH, or an explicit `node` invocation
115
- when another install shadows it.
116
- Prepared page HTML goes in `./source`, which must exist even when every page is
117
- template stock. To update, review the new release source and install its exact version again.
118
-
119
- > **Heads up — `start` turns on run telemetry, and remit is ON by default.**
120
- > The first `start` opens a run session in the target folder and, unless you
121
- > opt out, the session's Run Record is remitted to the Campaigns telemetry
122
- > endpoint with the packet's Campaigns API key. Opt out with
123
- > `npx --no-install campaigns-os telemetry off`, `CAMPAIGNS_OS_TELEMETRY=off`, or
124
- > `--no-remit` on the remitting command; capture stays local either way. The
125
- > full note — endpoint, payload, what `off` changes, and `--no-run-session` —
126
- > is in [docs/quickstart.md](docs/quickstart.md) above the first `start`; the
127
- > contract is [Run Telemetry](docs/workflow-findings-sidecar.md).
37
+ Codex, Cursor and other agents take the separate steps, with `--platform codex`, `--platform agents` or `--platform all` for the profile your agent reads:
128
38
 
129
39
  ```bash
130
- npx --no-install campaigns-os start --map-id <map-id> --target . --source ./source --template-family <family>
131
- npx --no-install campaigns-os next --packet ./campaign-runtime.build.json --json
40
+ npx --no-install campaigns-os install-skills --platform codex
41
+ npx --no-install campaigns-os install-agent-context --target .
42
+ npx --no-install campaigns-os qa install-browser
132
43
  ```
133
44
 
134
- `--map-id <id>` starts from a map saved in Campaign Map Builder (add
135
- `--proxy-base <origin>` when the map was saved on a non-production map store);
136
- `--spec <campaignspec.json>` starts from a local export or an agent-authored
137
- [local spec](docs/build-packet.md#local-spec-entry) instead. Local-spec identity
138
- requires a reviewed 1.43.0-or-later release. To prove the campaign on
139
- localhost before a preview deploy, add `--deploy-target local-serve` (and
140
- `--preview-url http://localhost:<port>/`); `qa policy set --deploy-target <target>`
141
- changes it later. `--source` is
142
- always required: the folder of prepared HTML/CSS/assets for the pages you are
143
- building, with a source manifest that carries desktop and mobile screenshot
144
- proof for each designed page
145
- ([Design Source Package](docs/design-source-package.md)). Pages that use the
146
- starter family's own design are declared, not omitted — see the template-stock
147
- note below.
148
-
149
- `start` ends by running doctor, and doctor's first verdict on a fresh target is
150
- normally `BLOCKED` with a list of what to supply — missing screenshot proof,
151
- demo values to replace, a scaffold to run. That list is the intake checklist,
152
- not a failed install. The demo values are the store profile and SDK pin
153
- `campaign-init` seeded into `_data/campaigns.json`; doctor prints the one
154
- command that replaces them from the CampaignSpec, `npx --no-install
155
- campaigns-os page-kit sync --packet campaign-runtime.build.json`, and after it
156
- both page-kit gates pass. The reverse write exists for a configured campaign:
157
- `npx --no-install campaigns-os spec derive --packet
158
- campaign-runtime.build.json` copies what the repo already
159
- states (the SDK pin, page routes, analytics ids) into the local CampaignSpec,
160
- and with `--write-map` records the pin in the saved Map's Build hints too, so
161
- a bump in the repo is one edit followed by a derive rather than a hand edit
162
- in two tools; with `--from-store <subdomain>` and the store's Admin API read
163
- token in the environment it derives the store profile from the store as well.
164
- Map write-back stays explicit and pin-only.
165
-
166
- For changes after handoff, follow the
167
- [spec review procedure](docs/build-packet.md#changing-a-campaign-after-handoff):
168
- apply the PM's authored changes to the current repository spec, preserve derived
169
- fields, and resolve competing edits before the next build.
170
-
171
- Everything after `start` is agent-driven: after `start`
172
- and after every stage, run `next` and do what it prints — it names the skill
173
- and the exact commands for the next stage, already spelled `npx --no-install
174
- campaigns-os …` for this install, which is why `install-skills` comes first.
175
- Releases before 1.41.2 print the same commands without `--no-install`; add it
176
- when you copy one. The browser for polish capture and QA is a one-time
177
- `npx --no-install campaigns-os qa install-browser`, which installs the browser
178
- for the Playwright this toolkit bundles. A pin older than that command shows
179
- `npx playwright install chromium` instead; that is equivalent only when `npx playwright` resolves to the toolkit's Playwright
180
- (a campaign that depends on its own Playwright version gets that one's
181
- browser instead), so prefer `qa install-browser` on pins that have it.
182
-
183
- ### Other ways to run it
184
-
185
- The pinned devDependency above is the primary path. To change the toolkit, use
186
- a checkout ([docs/quickstart.md](docs/quickstart.md)): every `npm run
187
- campaigns-os -- <command> …` example in this repository is that checkout form,
188
- and from a campaign folder the same command is
189
- `npx --no-install campaigns-os <command> …` with identical arguments (`npm run
190
- qa:install-browser` is the checkout's `qa install-browser`).
191
-
192
- From a checkout, the same first run uses the bundled example inputs:
45
+ Restart the agent afterwards, because a running session does not load skills installed after it started. `tooling status --platform claude` reports the install mode, the pinned version and whether the installed skills are current; on a fresh profile it exits 2 until the skills are installed, and prints the command that installs them.
46
+
47
+ Keep `--no-install` in every command. `campaigns-os` is only the bin name of `@nextcommerce/campaigns-os`, so in a folder without the pinned copy a plain `npx campaigns-os` would fetch whatever the registry returns; with the flag, npx stops with an error instead.
48
+
49
+ Before you install, orient. Read [`AGENTS.md`](AGENTS.md), `contracts/supported-surface.json`, `contracts/release-ledger.json` and `CHANGELOG.md` on GitHub at one commit, and check the release tag and npm provenance against that commit. Orientation is a read of declarative data and never runs toolkit code.
50
+
51
+ To see a built campaign before you have one, `npx --no-install campaigns-os demo --target ./apollo-sample` writes four inert sample pages; open the printed `landing/index.html`. It downloads nothing and creates no campaign evidence. See [offline sample preview](docs/demo-preview.md).
52
+
53
+ ## Start a build
54
+
55
+ > **`start` turns on run telemetry, and remit is on by default.** The first `start` opens a run session in the campaign folder, and unless you opt out the session's Run Record is sent to the Campaigns telemetry endpoint with the packet's Campaigns API key. Opt out with `npx --no-install campaigns-os telemetry off`, `CAMPAIGNS_OS_TELEMETRY=off`, or `--no-remit` on the remitting command; capture stays local either way. The full note is in [docs/quickstart.md](docs/quickstart.md) above the first `start`, and the contract is [Run Telemetry](docs/workflow-findings-sidecar.md).
193
56
 
194
57
  ```bash
195
- npm install
196
- npm run campaigns-os -- tooling status
197
- npm run campaigns-os -- start \
198
- --spec examples/campaignspec.v42.basic.json \
199
- --source examples/source-html \
200
- --target examples/target-page-kit \
201
- --template-family olympus
58
+ mkdir -p source
59
+ npx --no-install campaigns-os start --map-id <map-id> --target . --source ./source --template-family <family>
60
+ npx --no-install campaigns-os next --packet ./campaign-runtime.build.json --json
202
61
  ```
203
62
 
204
- If that first run stops at intake with `DESIGN_SOURCE_PACKAGE_NOT_READY`, the
205
- source material arrived without desktop/mobile screenshot proof. Supply it
206
- through `pages[].screenshots[]` in
207
- `<source-root>/.campaigns-os/source-html-manifest.json` — or in a manifest
208
- outside the source root named with `--design-manifest <path>`, when the source
209
- tree is not yours to write — and follow
210
- [Clearing `DESIGN_SOURCE_PACKAGE_NOT_READY`](docs/design-source-package.md#clearing-design_source_package_not_ready),
211
- which also gives the recovery sequence for the package a blocked run left behind.
212
-
213
- That path assumes the pages carry a standalone design of the merchant's. If they
214
- are template stock instead — no bespoke design, the starter family *is* the
215
- design — there is no screenshot to honestly supply. Declare those pages out of
216
- source scope (a manifest `skip_reason` entry, or CampaignSpec
217
- `build_scope.mode: "partial"`): intake records them as template stock, demands
218
- no design source for them, and leaves them unbuilt unless the operator opts in
219
- per page to materializing the locked family's stock. A family that publishes Template Reference proof
220
- (today `apollo`) covers them with `template_baseline`; every other family
221
- records an accepted Source Gap and intake lands at `ready_with_gaps`. See
222
- [Template-stock pages: the family decides](docs/design-source-package.md#template-stock-pages-the-family-decides).
223
-
224
- The command writes these target-repo artifacts:
225
-
226
- - `campaign-runtime.build.json`
227
- - `.campaign-runtime/build-context.json`
228
- - `.campaign-runtime/assembly-report.json`
229
- - `.campaign-runtime/doctor-output.json`
230
- - `.campaign-runtime/qa-verdict.json` (after QA)
63
+ `--map-id <id>` starts from a Map saved in Campaign Map Builder; `--spec <campaignspec.json>` starts from a local export or an agent-authored spec instead. `--source` is required even when every page is template stock. `--template-family` names a certified starter family from `contracts/commerce-surface-catalog.json`, such as `olympus`, `apollo` or `demeter`. To prove the campaign on localhost before a hosted preview, add `--deploy-target local-serve`.
64
+
65
+ Then do what `next` prints. From here the build is agent-driven: the setup, build, Polish and QA stages each name their skill (`next-campaigns-os-setup`, `next-campaigns-build`, `next-campaigns-polish`, `next-campaigns-qa`) and their commands, already spelled for this install. The deploy stage is yours to run; `next` prints the `record deploy --base-url <route root>` command for it, a loopback URL for a local-serve target or an https URL for a hosted one. Two things doctor asks for on a fresh folder are worth knowing in advance. `page-kit sync --packet campaign-runtime.build.json` replaces the store profile and SDK pin that `campaign-init` seeded into `_data/campaigns.json` with the CampaignSpec's values. And every designed page needs its screenshot proof in the source manifest at `source/.campaigns-os/source-html-manifest.json`, or in a manifest named with `--design-manifest <path>`; [Clearing `DESIGN_SOURCE_PACKAGE_NOT_READY`](docs/design-source-package.md#clearing-design_source_package_not_ready) walks through it.
66
+
67
+ `start` writes these files into the campaign folder, among others that [declared command effects](docs/effects.md) lists in full:
68
+
69
+ - `campaign-runtime.build.json`, the Build Packet
70
+ - `.campaign-runtime/build-context.json`, `.campaign-runtime/assembly-report.json` and `.campaign-runtime/doctor-output.json`
71
+ - `.campaign-runtime/run-session.json`, the run session the telemetry note above describes
72
+ - `.campaign-runtime/input/*`, the normalised brief and Design Source Package
73
+ - `.campaign-runtime/qa-verdict.json`, after QA
231
74
  - `.campaign-runtime/agent-context/*`
232
75
 
233
- Validate the standardized CI/readback set with:
76
+ A folder can hold several funnels. The first one set up uses the paths above; each later funnel gets its own `campaign-runtime-<route>.build.json` and keeps its records under `.campaign-runtime/funnels/<route>/`, so one funnel's setup never overwrites another's. Pass that funnel's packet with `--packet`. See [several funnels in one project](docs/build-packet.md#several-funnels-in-one-project).
234
77
 
235
- ```bash
236
- npm run campaigns-os -- bundle check --packet <page-kit-repo>/campaign-runtime.build.json --json
237
- ```
78
+ ## Proof, test orders and launch
79
+
80
+ Build output is not launch readiness. A complete run has build and lint evidence, a Polish record backed by `polish capture` against the served build, a recorded deploy, a browser QA verdict, and typed-card test-order proof from `--test-order common`. Global test cards bypass the gateway and create no transactions, but each test order leaves a real store order record. Unless the operator has already said test orders are fine for this campaign, ask once, up front, before placing test orders; then proceed. There is no permission flag. Localhost on any port is a Campaigns App development domain, so the SDK runs and analytics are suppressed there; a hosted preview or production origin must be on the campaign API key's allowed domains.
81
+
82
+ Before real shoppers see a campaign, confirm the production storefront URL, live payment methods, shipping markets, legal and support URLs, analytics expectations and the merchant-side configuration. Those sit outside the toolkit's proof.
238
83
 
239
- Use `--require-qa` when the campaign claims QA is complete. `status: conformant`
240
- means the sidecars agree with each other and the contract; it says nothing about
241
- whether doctor or QA passed. Read the warnings for that (a blocked doctor run
242
- emits `bundle.doctor_output.blocked`, a blocked QA verdict
243
- `bundle.qa_verdict.blocked`). See
244
- [Migration sidecar bundle v0](docs/migration-sidecar-bundle.md).
245
-
246
- Then ask your AI tool to continue from the emitted handoff. Fresh target repos usually start with `next-campaigns-os-setup`; existing campaign directories can move directly to `next-campaigns-build`.
247
-
248
- ## Source Files
249
-
250
- The current source adapter is `html_funnel`: bring prepared HTML/CSS/assets for the campaign pages, plus a CampaignSpec exported from Campaign Map Builder or authored by the coding agent through the [local-spec entry](docs/build-packet.md#local-spec-entry).
251
-
252
- Standalone HTML mockups: keep them whole and set
253
- `wrapper_policy: preserve_document_wrappers` in the source-html manifest at
254
- `<source>/.campaigns-os/source-html-manifest.json` (or pass
255
- `--wrapper-policy preserve_document_wrappers` to `start`). Source screenshot
256
- proof must be of the standalone document, so a page kept whole needs no
257
- conversion; doctor reports its document wrappers as a warning that names the
258
- decision. For pages without a Figma `design_source`, no exporter is required:
259
- a hand-written manifest is enough (when any active page's `design_source` is
260
- Figma, the manifest must pass the Figma provenance gate, which needs the
261
- exporter's handoff manifest), for example
262
- `{"schema_version": "source-html-manifest/v0", "wrapper_policy": "preserve_document_wrappers", "pages": [{"page_id": "landing", "path": "landing.html"}]}`
263
- (schema: `schemas/source-html-manifest.v0.schema.json`; see
264
- [Selecting the wrapper policy at intake](docs/source-adapters.md#selecting-the-wrapper-policy-at-intake)).
265
-
266
- Otherwise, for raw AI-generated or exported static HTML, "prepared" means
267
- page-kit-ready source, not a browser document dropped in unchanged and not a
268
- wholesale Liquid rewrite. Page Kit source is HTML with YAML frontmatter and
269
- optional Liquid helpers. Convert standalone HTML into the target page format
270
- first: remove outer
271
- `<html>`, `<head>`, and `<body>` wrappers, add page frontmatter, move shared
272
- CSS/assets into the campaign asset tree when useful, root links/assets with
273
- `campaign_link` and `campaign_asset` when needed, and keep landing/presell
274
- design markup separate from SDK-owned commerce controls.
275
-
276
- ## Important Commands
277
-
278
- 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.
84
+ After launch, keep a standing pull-request check. `doctor --packet <packet> --ci --no-live-refs` reports whether Polish and QA still bind to the build on disk, and the [workflow example](https://github.com/NextCommerceCo/campaigns-os/blob/main/docs/examples/campaign-repo-evidence-check.yml) posts that report as a PR comment. See [live-campaign changes](docs/campaigns-os-build-flow.md#live-campaign-changes).
85
+
86
+ ## Other ways to run it
87
+
88
+ A global install works too: `npm install -g @nextcommerce/campaigns-os@<version>`, then bare `campaigns-os …`. It ships without a browser, so run `campaigns-os qa install-browser` once. From a checkout of this repository, `npm install` and then `npm run campaigns-os -- <command> …`; every example in these docs that reads `npm run campaigns-os -- …` is the checkout form of `npx --no-install campaigns-os …` with the same arguments. The bundled example inputs let a checkout run a first intake:
279
89
 
280
90
  ```bash
281
- npm run campaigns-os -- tooling status
282
- npm run campaigns-os -- tooling setup --target <page-kit-repo> --platform claude --dry-run --json
283
- npm run campaigns-os -- install-skills --dry-run
284
- npm run campaigns-os -- install-skills --platform codex --dry-run
285
- npm run campaigns-os -- install-agent-context --target <page-kit-repo> --dry-run
286
- npm run campaigns-os -- qa install-browser
287
- npm run skills -- status
288
- npm run campaigns-os -- prepare-build --spec <spec.json> --source <html-dir> --target <page-kit-repo> --template-family <family> --brief <campaign-build-brief.yaml>
289
- npm run campaigns-os -- doctor --packet <page-kit-repo>/campaign-runtime.build.json
290
- npm run campaigns-os -- page-kit sync --packet <page-kit-repo>/campaign-runtime.build.json --dry-run
291
- npm run campaigns-os -- checkpoint waive --packet <packet.json> --gate source_html.producer_provenance --page <page_id> --reason "<why>" --waived-by "<named human>" --review-condition "<trigger>" --dry-run
292
- npm run campaigns-os -- sdk storage-check --target <campaign-git-root> --target-sdk <x.y.z> --manifest <sdk-storage-manifest.json> --scope <campaign,shared> --json
293
- npm run campaigns-os -- sdk repin --target <static-campaign-repo> --target-sdk <x.y.z>
294
- npm run campaigns-os -- standardize --target <page-kit-repo-or-cpk-repo> --json
295
- npm run campaigns-os -- theme inspect --packet <page-kit-repo>/campaign-runtime.build.json --json
296
- npm run campaigns-os -- theme generate --packet <page-kit-repo>/campaign-runtime.build.json --json
297
- npm run campaigns-os -- next setup --packet <page-kit-repo>/campaign-runtime.build.json
298
- npm run campaigns-os -- next build --packet <page-kit-repo>/campaign-runtime.build.json
299
- npm run campaigns-os -- record setup --packet <page-kit-repo>/campaign-runtime.build.json
300
- npm run campaigns-os -- record build --packet <page-kit-repo>/campaign-runtime.build.json
301
- npm run qa:install-browser
302
- npm run campaigns-os -- next polish --packet <packet.json> --report <assembly-report.json>
303
- npm run campaigns-os -- polish capture --packet <packet.json> --base-url <served-current-build-url>
304
- npm run campaigns-os -- record polish --packet <packet.json> --evidence <polish-evidence.json>
305
- npm run campaigns-os -- record theme --packet <packet.json>
306
- npm run campaigns-os -- record deploy --packet <packet.json> --base-url <route-root>
307
- npm run campaigns-os -- record brief --packet <packet.json> --brief <campaign-build-brief.yaml>
308
- npm run campaigns-os -- record spec --packet <packet.json>
309
- npm run campaigns-os -- next qa --packet <packet.json> --report <assembly-report.json>
310
- npm run campaigns-os -- qa resolve --packet <packet.json>
311
- npm run campaigns-os -- qa run --packet <packet.json> --base-url <preview-url> --browser --test-order common
312
- npm run smoke:polish-capture
313
- npm run campaigns-os -- findings add --stage overall --kind positive_signal --summary "..."
314
- npm run campaigns-os -- findings harvest --packet <packet.json>
315
- npm run campaigns-os -- findings export --summary
91
+ npm install
92
+ npm run campaigns-os -- start \
93
+ --spec examples/campaignspec.v42.basic.json \
94
+ --source examples/source-html \
95
+ --target examples/target-page-kit \
96
+ --template-family olympus
316
97
  ```
317
98
 
318
- Doctor inspects without changing the retained Assembly Report or doctor sidecar.
319
- A stale local `_site` still fails the current inspection; it does not rewrite
320
- the proof of an earlier delivered build. Use `doctor --packet <packet> --write`
321
- only when deliberately recording a new doctor stage. `--no-write` overrides
322
- `--write`. A custom `--doctor-out <path>` also requires `--write`; naming an
323
- output path alone does not create or refresh the file. Build/QA producer
324
- commands continue to record their own stages.
325
-
326
- Record a stage's completion with `record setup`, `record build` (after every
327
- rebuild), `record polish --evidence <file>`, `record theme` (once the brand layer
328
- is linked) and `record deploy --base-url <route root>` (a loopback URL for a
329
- local preview, https for a hosted one), rather than hand-editing
330
- `.campaign-runtime/build-context.json` or
331
- `.campaign-runtime/assembly-report.json`. A recorded deploy is bound to the
332
- build it probed, so a later `record build` of different output makes it owed
333
- again. When the brief or the CampaignSpec changes after stages are recorded, save
334
- it with `record brief` or `record spec`: an unchanged or reformatted save keeps
335
- every stage, a material change moves the superseded build, Polish and QA records
336
- to stage history instead of discarding them, and `next` names the stage that is
337
- owed again. Re-running
338
- `start` or `prepare-build` over recorded stages is refused without `--force`.
339
- Each `record` command validates what it would write, refuses a stage `next` has
340
- not reached, and writes nothing on failure; `--dry-run` runs the checks without
341
- writing. See
342
- [Build Packet](docs/build-packet.md) and [Polish evidence](docs/polish-evidence.md).
343
-
344
- Do not use `prepare-build --force` merely to refresh a catalog path: doctor
345
- already resolves the running toolkit's catalog, and `--force` resets the recorded stages (completed build, Polish and QA records move to stage history).
346
-
347
-
348
- `qa run` automatically checks contract-governed authored price, recurring
349
- cadence, and voucher claims against fresh `/api/price-preview` results for
350
- commercial pages. It needs no private repo import or extra catalog flag; proven
351
- mismatches are warn-severity pricing assertions in the normal verdict.
352
-
353
- Run `tooling status` before a build session. It names the install mode — a
354
- pinned package (`npx`, or a consumer's `node_modules`) or a git checkout — and
355
- checks that the package metadata, CLI entrypoint, and installed Campaigns OS
356
- skills agree. For a checkout it also reports branch, upstream, and ahead/behind;
357
- for a package install the pinned version is the freshness answer, and the
358
- status does not compare it with npm's `latest` dist-tag. Neither mode makes agent skills current on
359
- its own: when skills are stale, run the refresh command the status output
360
- prints (it names each stale platform, through the same prefix you ran
361
- `tooling status` with), then read the `SKILL.md` files it lists under `Read now`
362
- in the running session (new sessions load them on their own). Without `--platform`,
363
- status checks only the platforms where Campaigns OS skills are installed.
364
-
365
- Run `campaigns-os qa install-browser` (`npm run qa:install-browser` from a
366
- checkout) once after install/update and before mandatory `polish capture` or
367
- any QA command that uses `--browser` or `--test-order`. It installs the Chromium
368
- binary used by the package-owned Playwright flow;
369
- Campaigns OS proof should not depend on external browser skills. `polish
370
- capture` must run against the served current build before Polish becomes
371
- terminal, deploy begins, or QA starts.
372
-
373
- `npm run smoke:polish-capture` is an optional real-Chromium package smoke. It
374
- requires the installed browser and permission to open a loopback HTTP listener;
375
- it is intentionally excluded from `npm run check` and CI.
376
-
377
- ## Template Contracts
378
-
379
- The starter-template catalog snapshot lives in `contracts/commerce-surface-catalog.json`.
380
-
381
- For each selected family, the agent must read:
382
-
383
- - `families[family].agentContract`
384
- - `sharedFrontmatterVocabulary`
385
- - `frontmatter.demoOnlyValues`
386
- - `frontmatter.replaceFromSpecOrApi`
387
- - `frontmatter.removeWhenUnsupported`
388
-
389
- Shipping is family-specific. Families whose contracts include `shipping_methods`
390
- or `shipping_method` must source those refs from CampaignSpec/API. Families that
391
- do not own explicit shipping frontmatter, including `shop-single-step`, should
392
- not receive copied Olympus-style `shipping_methods` blocks. Special case:
393
- `shop-three-step` uses dynamic shipping through `window.next.getShippingMethods()`.
394
-
395
- When bootstrapping a family such as `demeter`, copy the family as an atomic
396
- page-kit slice. Checkout/receipt pages depend on matching `_includes/`,
397
- `_layouts/`, `assets/css/`, and `assets/js/`; copying only individual page files
398
- is not a valid minimum file set.
399
-
400
- ## Spec Validation
401
-
402
- `campaign-spec/` is the single, public source of truth for CampaignSpec
403
- validation: a `normalize` phase, a composable rule registry, and a fixture
404
- corpus. The `doctor` runs these rules during spec validation (emitted under the
405
- `spec.validation` code, complementary to its packet/build-aware spec checks), and
406
- any campaign authoring UI (such as a Map Builder bundle) can import the same
407
- registry — so a spec rule is authored once and reaches internal teams and
408
- third-party agencies alike. The rules are authored in TypeScript with no heavy
409
- dependencies and compiled to plain ESM (`npm run build:spec`, on `prepare`) and a
410
- stable subpath export `@nextcommerce/campaigns-os/campaign-spec`, so consumers run
411
- them on `engines.node` (>=20.19.0) with no type-stripping or build step of their own.
412
- See [`campaign-spec/README.md`](campaign-spec/README.md).
413
-
414
99
  ## Docs
415
100
 
416
- - [Quickstart](docs/quickstart.md)
417
- - [Access Model](docs/access-model.md)
418
- - [Build Packet](docs/build-packet.md)
419
- - [Supported Surface](docs/supported-surface.md) — what downstream consumers may depend on, and the gate that enforces it
420
- - [Brand Theme Bridge](docs/brand-theme-bridge.md)
421
- - [CampaignSpec Authoring Examples](docs/campaignspec-authoring-examples.md)
422
- - [Campaigns OS Build Flow](docs/campaigns-os-build-flow.md)
423
- - [Campaign Standardization Report](docs/campaign-standardization-report.md)
424
- - [Entry Points](docs/entry-points.md) — five intake shapes (template-stock, Figma-driven, AI-generated, hand-authored, mixed) and which producer / manifest each one ships with
425
- - [Source Adapters](docs/source-adapters.md)
426
- - [Setup Profile Parity](docs/setup-profile-parity.md)
427
- - [Developer Evaluation](docs/developer-evaluation.md)
428
- - [QA And Test Orders](docs/qa-and-test-orders.md)
429
- - [Run-Artifact Readback](docs/readback.md) — `campaigns-os readback`: a read-only projection of one run's emitted artifacts, with per-artifact freshness against the checkout and a versioned JSON contract to gate on
430
- - [Declared Command Effects](docs/effects.md) — what every supported invocation writes and sends, one row per command and effect-changing flag, each row proved by a test that runs the real CLI in a disposable target
431
- - [Legacy Migration Contract](docs/legacy-migration.md) — pure inventory, preview-plan, receipt, Offer request/readback, and token-free evidence helpers for bounded SDK 0.3.x shadow migrations
432
- - [Template Family vs Figma-extraction vs Hybrid](docs/template-vs-extraction-decision.md) — when to mint a template family, when to extract a bespoke design, and when to do both
433
- - [Small PR Review Path](docs/small-pr-review-path.md)
434
- - [Run Telemetry](docs/workflow-findings-sidecar.md) — per-run Run Record (system signal + workflow findings) tagged by improvement surface; captured locally always, remitted to Next Commerce only with up-front opt-out consent
435
- - [Versioning](docs/versioning.md)
436
- - [ADR 0002: One shipping path](docs/adr/0002-one-shipping-path-campaigns-agent-fold.md) — decides that the agent surface (skills, charter, declared effects, readback) lives in this repository; Campaigns Agent folds in
437
-
438
- ## Status
439
-
440
- Developer preview. Build output still needs the normal proof gates: build/lint evidence, polish plus package-owned page-load capture against the served current build, preview deploy or local dev URL, Playwright browser QA, and typed-card test-order proof via `--test-order common`. Global test cards bypass the gateway and create no transactions, but each test order leaves a real store order record. Unless the operator has already said test orders are fine for this campaign, ask once, up front, before placing test orders; then proceed. There is no permission flag. Localhost on any port is a Campaigns App Development domain, so SDK calls are allowed and analytics are suppressed there; non-localhost preview/production origins still need SDK origin allowlist confirmation.
441
-
442
- Launch readiness is separate from Campaigns OS proof. Before real shoppers see a campaign, confirm the production storefront URL, live payment methods, shipping markets, legal/support URLs, analytics expectations, and merchant-side configuration.
443
-
444
- ## Review standards
445
-
446
- Two rules reviewers apply to every patch, beyond the gates in
447
- `npm run check`:
448
-
449
- - **A guard test includes the failing case.** A test that passes against the
450
- unfixed code guards nothing, so assert the behaviour that was broken and check
451
- that it fails without the fix. Prefer assertions against the parsed module or
452
- its output — call the function, read the value — over matching substrings of
453
- source text, which passes on a comment and breaks on a rename.
454
- - **A `catch` branches on the condition it claims to handle.** Test
455
- `error.code` (or whatever specific condition the comment justifies), handle
456
- that case, and journal or rethrow everything else. A bare `catch` that
457
- swallows every error turns a typo, a permission failure, and an expected
458
- absence into the same silent success.
459
-
460
- ## Issue tracking
461
-
462
- Work in this repo is tracked with GitHub Issues and coordinated on the
463
- org-level **[Operations](https://github.com/orgs/NextCommerceCo/projects/10)**
464
- Kanban board (Todo / In Progress / Done). New issues are added to the board
465
- automatically by the `add-to-project` workflow.
466
-
467
- Before starting work on an issue: check it is not assigned to someone else,
468
- assign yourself (`gh issue edit <n> --add-assignee @me`), and move the card to
469
- In Progress. Open PRs with `Closes #<n>`; when the issue closes on merge, the board's built-in "Item closed" automation moves the card to Done.
470
- Contributors have a `/next-board` skill that wraps these board operations
471
- (status, claim, move, create).
101
+ - [Quickstart](docs/quickstart.md) and [local setup with Claude Code](docs/local-setup.md)
102
+ - [Activation, access and evidence](docs/activation-and-evidence.md): what an install, a saved Map, a preview and a QA verdict each prove
103
+ - [Build flow](docs/campaigns-os-build-flow.md) and [Build Packet](docs/build-packet.md)
104
+ - [Entry points](docs/entry-points.md): template-stock, Figma-driven, AI-generated, hand-authored and mixed sources
105
+ - [Design Source Package](docs/design-source-package.md) and [source adapters](docs/source-adapters.md): preparing page HTML and its manifest
106
+ - [Campaign Build Brief](docs/campaign-build-brief.md) and [CampaignSpec authoring examples](docs/campaignspec-authoring-examples.md)
107
+ - [Brand theme bridge](docs/brand-theme-bridge.md): carrying the design's palette and fonts onto the commerce pages
108
+ - [Polish evidence](docs/polish-evidence.md), [QA and test orders](docs/qa-and-test-orders.md) and [readback](docs/readback.md)
109
+ - [Declared command effects](docs/effects.md): what every command writes and sends
110
+ - [SDK storage compatibility](docs/sdk-storage-compatibility.md) and [legacy migration](docs/legacy-migration.md), for moving an existing campaign to a newer Campaign Cart
111
+ - [Supported surface](docs/supported-surface.md), [versioning](docs/versioning.md) and the [release ledger guide](docs/release-ledger-authoring-guide.md): what you may depend on and how changes are recorded
112
+ - [Run Telemetry](docs/workflow-findings-sidecar.md)
113
+ - Repository-only: [developer evaluation](https://github.com/NextCommerceCo/campaigns-os/blob/main/docs/developer-evaluation.md), [template family versus Figma extraction](https://github.com/NextCommerceCo/campaigns-os/blob/main/docs/template-vs-extraction-decision.md), [small PR review path](https://github.com/NextCommerceCo/campaigns-os/blob/main/docs/small-pr-review-path.md) and [setup profile parity](https://github.com/NextCommerceCo/campaigns-os/blob/main/docs/setup-profile-parity.md)
114
+
115
+ `campaign-spec/` is the CampaignSpec validator: a normalize phase, a rule registry and a fixture corpus, compiled to plain ESM and exported as `@nextcommerce/campaigns-os/campaign-spec`, so other tools can run the same rules doctor runs. See [`campaign-spec/README.md`](campaign-spec/README.md).
116
+
117
+ ## Contributing
118
+
119
+ Work is tracked in GitHub Issues and on the org's [Operations](https://github.com/orgs/NextCommerceCo/projects/10) board. Assign yourself before starting an issue, and open pull requests with `Closes #<n>`. `npm run check` runs every gate, and `npm run check:fast` runs the ones CI's types and contracts lanes run. Reviewers apply two rules beyond the gates: a guard test includes the failing case (assert the behaviour that was broken, and check that it fails without the fix), and a `catch` branches on the condition it claims to handle rather than swallowing every error. Releases are cut by pushing a `v<version>` tag that matches `package.json` on a commit on `main`; the publish workflow runs the full check and publishes the verified tarball with provenance.
@@ -8,6 +8,8 @@ project copy. Do not use private runtime source as the campaign's starting point
8
8
 
9
9
  To pick up an existing campaign, run `npx --no-install campaigns-os readback .` and `npx --no-install campaigns-os next --packet campaign-runtime.build.json` before reading artifacts by hand; `next` blocks polish and QA again whenever the built output changes. The committed `.campaign-runtime/qa-verdict.json` keeps no order records or URLs: its `browser-test-order:<path>` assertions are the typed-card proof, and the full verdict is under `qa-output/`.
10
10
 
11
+ A project that holds several funnels has one Build Packet per funnel: `campaign-runtime.build.json` for the first funnel set up, whose records are directly under `.campaign-runtime/`, and `campaign-runtime-<route>.build.json` for each other funnel, whose records are under `.campaign-runtime/funnels/<route>/` (its `assembly.runtime_dir`). Pass that funnel's packet with `--packet` to every command, `readback . --packet` included; without one, readback refuses and names the packets.
12
+
11
13
  A NEXT campaign is one connected commerce journey: the pages the CampaignSpec declares, in its order, through product choice, checkout, post-purchase offers and receipt. Creative intent — audience, purpose, layout, imagery, approved copy, visual style — belongs to the operator, the Campaign Build Brief and the accepted design source. Commerce behaviour — products, package IDs, prices, offers, shipping, routes, cart, checkout, payment and post-purchase — belongs to CampaignSpec/API values and the SDK. Before changing a campaign, read the normalized brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions: `adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet. The setup, build, Polish and QA prompts begin with a campaign intent summary, and every `next` result carries it (`intent_summary` in JSON); treat it as orientation, never as a source of prices or behaviour. When a revision is narrow, keep the recorded intent and ask only about missing choices that affect that revision. Ask the operator before saving brief answers.
12
14
 
13
15
  Core rules:
@@ -39,3 +41,21 @@ Core rules:
39
41
  - Campaigns OS proof is not merchant launch readiness. Before launch, confirm production storefront URL, live payment methods, shipping markets, legal/support URLs, analytics expectations, and merchant-side configuration.
40
42
 
41
43
  Current source adapter: prepared HTML/assets (`html_funnel`).
44
+
45
+ ## Revising a live campaign
46
+
47
+ 1. Before editing, run `npx --no-install campaigns-os readback .` and
48
+ `npx --no-install campaigns-os next --packet campaign-runtime.build.json`.
49
+ Readback's `evidence_debt` compares the build on disk with the builds Polish and QA were recorded for.
50
+ Changed pages are listed against the recorded assembly build manifest; an owed stage with an empty page list still means evidence is owed.
51
+ 2. For pages built from a provided design, the Design Source Package is the authority, not the punch list's wording.
52
+ 3. Before opening the pull request, after the final edit, rebuild, then run `npx --no-install campaigns-os record build --packet campaign-runtime.build.json`.
53
+ When `next` or the pull-request check says the change is page-only, run
54
+ `npx --no-install campaigns-os qa run --packet campaign-runtime.build.json --page <page_id>` against that build,
55
+ with one `--page` for each changed page it names; Polish is optional for it.
56
+ Otherwise run `npx --no-install campaigns-os polish capture --packet campaign-runtime.build.json --base-url <served-current-build-url>` for the whole route
57
+ and `npx --no-install campaigns-os record polish --packet campaign-runtime.build.json --evidence <polish-evidence.json>`, in that order,
58
+ and when QA is owed, run `npx --no-install campaigns-os qa run --packet campaign-runtime.build.json` against that build.
59
+ 4. In the pull request body, put the design reference and the preview of each changed page side by side.
60
+
61
+ The standing pull-request check is `npx --no-install campaigns-os doctor --ci --packet campaign-runtime.build.json --no-live-refs`, report-only unless the repo opts in.