@nextcommerce/campaigns-os 1.52.0 → 1.54.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.
- package/CHANGELOG.md +109 -0
- package/README.md +1 -0
- package/agents/claude/CLAUDE.md +2 -0
- package/agents/codex/AGENTS.md +2 -0
- package/agents/copilot/copilot-instructions.md +2 -0
- package/agents/cursor/campaigns-os.mdc +2 -0
- package/compatibility.json +1 -1
- package/contracts/campaign-cart-checkout-field-contract.v0.json +10 -0
- package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
- package/contracts/commerce-surface-catalog.json +27 -27
- package/contracts/effects.v1.json +295 -47
- package/contracts/release-ledger.json +660 -0
- package/contracts/supported-surface.json +3 -3
- package/contracts/template-brand-contract.shared-commerce.v0.json +1 -1
- package/docs/brand-theme-bridge.md +2 -0
- package/docs/build-packet.md +67 -19
- package/docs/campaign-build-brief.md +48 -17
- package/docs/campaign-standardization-report.md +32 -0
- package/docs/design-source-package.md +7 -3
- package/docs/effects.md +10 -1
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +2 -0
- package/docs/progress-snapshots.md +5 -5
- package/docs/qa-and-test-orders.md +30 -3
- package/docs/readback.md +19 -2
- package/docs/runtime-readiness.md +1 -1
- package/docs/sdk-storage-compatibility.md +15 -0
- package/docs/skills-revision.md +10 -10
- package/docs/supported-surface.md +1 -0
- package/package.json +1 -1
- package/schemas/campaign-runtime-assembly-report.v0.schema.json +5 -1
- package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +3 -3
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +5 -3
- package/skills/next-campaigns-os/SKILL.md +10 -19
- package/skills/next-campaigns-os/references/session-intake.md +10 -6
- package/skills/next-campaigns-os-setup/SKILL.md +4 -3
- package/skills/next-campaigns-polish/SKILL.md +7 -5
- package/skills/next-campaigns-qa/SKILL.md +5 -3
- package/skills.json +10 -10
- package/src/brand-theme.mjs +21 -20
- package/src/brief-summary.mjs +275 -0
- package/src/build-brief.mjs +167 -15
- package/src/campaign-ecosystem.mjs +153 -31
- package/src/cli.mjs +182 -115
- package/src/contrast.mjs +649 -0
- package/src/design-source-publication.mjs +110 -3
- package/src/directory-lock.mjs +79 -7
- package/src/doctor/checks.mjs +141 -16
- package/src/doctor/inspect.mjs +13 -0
- package/src/doctor/next-step.mjs +15 -6
- package/src/input-currency.mjs +394 -0
- package/src/input-refresh.mjs +708 -0
- package/src/invocation.mjs +6 -2
- package/src/polish-browser.mjs +503 -201
- package/src/polish-deadline.mjs +7 -0
- package/src/polish-node.mjs +326 -46
- package/src/polish-readability.mjs +828 -0
- package/src/progress-node.mjs +18 -5
- package/src/qa-browser.mjs +211 -93
- package/src/qa-node.mjs +47 -7
- package/src/qc-accept.mjs +44 -8
- package/src/qc-check-registry.mjs +15 -7
- package/src/qc-results.mjs +326 -34
- package/src/readback.mjs +58 -10
- package/src/sdk-attribute-index.mjs +111 -23
- package/src/sdk-markup.mjs +49 -10
- package/src/sdk-repin.mjs +282 -0
- package/src/stage-ledger.mjs +235 -44
- package/src/stage-record.mjs +154 -30
- package/src/standardization-report.mjs +26 -1
- package/src/target-lock.mjs +9 -1
- package/src/tooling-setup.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,115 @@
|
|
|
2
2
|
|
|
3
3
|
Notable supported-surface changes are recorded here.
|
|
4
4
|
|
|
5
|
+
## [1.54.0] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
Ships the same-surface changes 1.53.0+agent.1 through +agent.11 (+agent.6 and +agent.8 were never used), including the `qa run --test-order` fix for Campaign Cart SDK 0.4.41 card fields (+agent.5) and the starter catalog, SDK attribute index and support policy at 0.4.41 (+agent.10, +agent.11).
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
`campaigns-os sdk repin --target <repo> [--target-sdk <x.y.z>] [--apply] [--json]` updates the Campaign Cart SDK pins written into a static campaign repo's HTML, the `loader.js` and `campaign-cart.css` URLs that `standardize` already lists with path and line. It rewrites only a semver pin (`@vX.Y.Z` or `@X.Y.Z`) below the target version, and only the version part of the URL. `@latest`, `@main`, commit and prerelease refs, and pins already at or above the target, are listed and left alone. Without `--target-sdk` the target is the SDK support policy's `preferred_minimum`. By default it only previews, printing each path and line with the old and new URL. `--apply` writes the files and a change record at `.campaign-runtime/sdk-repin.json` with the files touched, the reference count and the from and to versions, which a Run Record can cite. A second run finds nothing to change and writes nothing. A repo with `_data/campaigns.json` is refused with exit 2, because page-kit owns that pin; use `page-kit sync` there. This replaces the hand-run `sed` step in the SDK bump for static repos.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
`qa run` no longer publishes a verdict to the QA portal by default when the base URL is a local address (`localhost` or any `*.localhost` name, any `127.x.x.x` address, `0.0.0.0`, `[::1]` or an IPv4-mapped loopback), whether the spec came from a saved Map or a local file. The verdict stays local, and the output names the destination plus `qa publish` and `--post-verdict`. Pass `--post-verdict` to publish a local-address run. `publish_decision.reason` reads `loopback_base_url` when this default applied. Runs against a remote base URL publish exactly as before. The `--post-verdict` help line now names the IPv4-mapped loopback too.
|
|
16
|
+
|
|
17
|
+
`record deploy` now stamps `stages.deploy.source_build_fingerprint` with the recorded build it probed. When a later `record build` records different output, a deploy stamped with the old build becomes `required` (`required_by` build, `required_for` qa), its old probe (`outputs` and `evidence`) leaves the live stage and the prior record is kept in `stages.deploy.history`, and `next` routes back to `record deploy` before QA. A rebuild with byte-identical output keeps the deploy current. A deploy recorded before this change carries no stamp and is kept as recorded. The Assembly Report schema describes the field.
|
|
18
|
+
|
|
19
|
+
The effects contract declares the `sdk repin` and `sdk repin --apply` rows, and its `record deploy` and `record build` rows say a deploy is stamped with the build it probed and owed again after a build of other output. On the eight `qa run` rows, the verdict send to `{proxy-base}/api/qa/verdicts` now names the local-address default in its condition, and the offline fixture no longer observes it because it serves the campaign from 127.0.0.1; `qa publish` proves that send.
|
|
20
|
+
|
|
21
|
+
## [1.53.0+agent.11] - 2026-10-07
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
The bundled Campaign Cart SDK support policy records 0.4.41 as the latest known release (`provenance.latest_known_release`, was 0.4.38). With the starter catalog verified against 0.4.41 (1.53.0+agent.10), template freshness already took 0.4.41 as the current SDK, so no family's freshness changes; the policy now agrees with the catalog instead of naming a release three behind it, and "current SDK" is reported from the policy. `minimum_supported` (0.4.20) and `preferred_minimum` (0.4.30) are unchanged.
|
|
26
|
+
|
|
27
|
+
## [1.53.0+agent.10] - 2026-10-07
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- The vendored starter-template catalog is re-synced to campaign-cart-starter-templates `7833290` (was `2c61894`). Every certified family now records Campaign Cart SDK 0.4.41 verification evidence (`sdk-0.4.41-2026-10-06.5`, a `lint-sdk` pass), and the eight agent CampaignSpec fixtures pin `sdk_version` 0.4.41. Doctor's missing-SDK-pin message therefore names 0.4.41 as the version a family was verified against. The certified-family render fixtures are regenerated at the new pin: the loader moves to 0.4.41, and the checkout and receipt pages pick up the starters' SDK address blocks (`data-next-address`) and the savings badge drawn from the summary token. The payment-chrome `asset_pin` moves to the same commit; the five hashed assets are byte-identical there.
|
|
32
|
+
- The SDK attribute index (`src/sdk-attribute-index.mjs`) moves from v0.4.38 to v0.4.41. v0.4.41 removed the generated `docs/attribute-index.md` the old recipe read, and the SDK's hand-written attribute docs leave out names its source still reads. The list is now regenerated from the SDK source at the tag (every `data-next-*` string and `dataset.next*` property in non-test TypeScript), and that recipe is in the file. It keeps all 135 names of the v0.4.38 list and adds 14: the address block (`data-next-address`, `-lang`, `-api`, `-field`, `-row`, `-state`), `data-next-i18n`, `data-next-phone-e164`, `data-next-phone-country`, `data-next-bump-section`, `data-next-button-text`, and the variant option state (`data-next-variant-name`, `-value`, `data-next-unavailable`). `built_output.sdk_markup` no longer reports these as unknown, and its findings now name `sdk_attribute_index_version` 0.4.41. The checkout field names are unchanged at v0.4.41.
|
|
33
|
+
- The raw cart placeholder check (`built_output.cart_placeholders`) accepts pages pinned to 0.4.41: all ten renderer files it was generated from have the same git blob ids at v0.4.38 and v0.4.41. Before, every 0.4.41 page reported `unexercised` (`sdk_pin_unverified`).
|
|
34
|
+
|
|
35
|
+
## [1.53.0+agent.9] - 2026-10-06
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
The per-target lock now tells an ownerless lock apart from something at the lock path that is not a lock. When the wait ends on an ordinary file, a symbolic link, or a directory with no owner record that holds other entries, the refusal names what is there and says it is never removed automatically; before, it read as a busy or ownerless lock. An empty ownerless lock directory is still refused as before. The holder of a lock also clears the staging, recovery-staging and released directories that a crashed process or a failed release left beside the lock, but only those whose recorded owner process no longer exists; a sibling with a live or unreadable owner is left alone.
|
|
40
|
+
|
|
41
|
+
## [1.53.0+agent.7] - 2026-10-06
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
`doctor --built --base-url <url>` now says that it checked the local built files only. The URL is not fetched: it fills `deploy.preview_url` in the minimal Build Packet. The output names `qa run --site <repo> --base-url <url> --family <family> --browser` as the command that loads the served pages, and `--json` carries `derived.base_url` with `fetched: false`. The checks themselves are unchanged.
|
|
46
|
+
|
|
47
|
+
## [1.53.0+agent.5] - 2026-10-06
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- `qa run --test-order` types the test card on pages running Campaign Cart SDK 0.4.41. That release draws the card number and CVV with the fields NEXT's `payments.29next.com` script mounts, whose iframes are named `spreedly-hosted-number-…` and `spreedly-hosted-cvv-…`; the runner looked only for the `spreedly-number-frame-…` and `spreedly-cvv-frame-…` iframes of 0.4.40 and earlier, so on a 0.4.41 checkout it timed out before submitting. It now finds either, and nothing changes on pages pinned to 0.4.40 or earlier. A checkout carrying both kinds of card iframe, or two of either, fails at `card_fields_filled` with the iframe ids it found instead of typing into whichever comes first, and the step's evidence records which iframes it typed into.
|
|
52
|
+
- `qa run --test-order` no longer loses card digits typed before the card fields are ready. On SDK 0.4.41 the hosted number input appears before its script has loaded, and digits typed in that window are dropped. The SDK then refuses the shortened number without tokenizing, so the run timed out at `order_submitted` 45 seconds later with no order created. This happened about once in 33 live runs, usually when the card fields loaded slowly. The runner now waits up to 15 seconds for the checkout form to drop its `next-loading-spreedly` class (SDK 0.4.38 to 0.4.41 set it until the card fields are ready); if it is still there, `card_fields_filled` fails and says the card script never finished loading. It then reads the card number and CVV back, and retypes up to three attempts in all. If the fields still don't hold the card, `card_fields_filled` fails and names what the fields held, instead of the run timing out at submit.
|
|
53
|
+
|
|
54
|
+
## [1.53.0+agent.4] - 2026-10-06
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- The checkout field-name checks now read the SDK version of the page they judge. `first_name` and `last_name` pass on Campaign Cart SDK 0.4.39 and later, and `phone_number` passes on 0.4.41 and later; `fname`, `lname` and `phone` still pass on every version. Earlier releases blocked `first_name` and `last_name` (`built_output.sdk_markup` `WRONG_FIELD_NAME`, and `checkout.unsupported_field_binding` in `standardize`) and flagged `phone_number` on every SDK, so a page written to the 0.4.41 field names failed doctor although the SDK maps them. Doctor reads the page's own exact loader pin, then the campaign's `sdk_version` in `_data/campaigns.json`. `standardize` reads the file's own loader pin, then the lowest exact pin the campaign declares (for a bundled `campaign-cart` dependency, an exact pin or the floor of a `^`, `~` or `>=` range). When neither gives an exact released version, the checks keep their earlier behaviour, because `fname`, `lname` and `phone` work on every version. Below a name's version the result is also unchanged, and the message names the version the name needs. Findings and bindings now record the SDK version they were judged against.
|
|
59
|
+
|
|
60
|
+
## [1.53.0+agent.3] - 2026-10-06
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- `standardize` now judges a bundled `campaign-cart` dependency against the SDK support policy by the lowest version its `package.json` spec allows. Earlier releases took the version written in the spec, so `<0.4.39` was evaluated as 0.4.39 and `0.4.41 || 0.4.10` as 0.4.41, and both could pass the minimum although npm may install an older SDK. An exact pin or one `^`, `~` or `>=` range on a released version is evaluated by that version, as before. Any other spec gets no policy evaluation and raises the new warning `version.sdk_dependency_floor_unknown`. The lowest version is recorded as `sdk_loader.bundled_dependency.floor_version`.
|
|
65
|
+
|
|
66
|
+
## [1.53.0+agent.2] - 2026-10-05
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
`next` now prints a short campaign intent summary, generated from the normalized Campaign Build Brief, in every result (`intent_summary` in JSON) and at the top of the setup, build, Polish and QA prompts. Each value is marked as set in the saved brief file, taken from the source, a generated default, or not stated; a value whose origin was not recorded, or that changed since it was recorded, says so. These marks are tamper evidence, not proof of who wrote a value. Values are shown as quoted data. The summary never shows a purpose or palette source that Campaigns OS inferred from page types or page names: unless the brief file states them, they read "not stated". The summary is output only: nothing reads it, and it cannot change prices or commerce behaviour. Bundled skills and the agent context files now tell agents to read the brief and the recorded assembly decisions.
|
|
71
|
+
|
|
72
|
+
The build stage prompt that `next` returns now tells the agent to save a changed Campaign Build Brief with `record brief` or a changed CampaignSpec with `record spec` before building on the change.
|
|
73
|
+
|
|
74
|
+
Bundled skills are at revision `1.53.0+skills.2`. The lifecycle skill saves brief answers with `record brief` and returns the single compact brief defined in `references/session-intake.md`, whose work-type field is now `Work:` beside a new `Campaign:` field. The build skill passes `--deviation-reason` to `record build` only on the operator's explicit decision, the Polish skill records a skipped Polish only on the operator's decision, and the Polish and QA skills say how to report a readability warning and offer repairs inside the brand palette.
|
|
75
|
+
|
|
76
|
+
### Migration
|
|
77
|
+
|
|
78
|
+
**Migration.** The agent context files changed, so `tooling setup` refuses until each existing campaign refreshes its installed copy. From the campaign folder:
|
|
79
|
+
|
|
80
|
+
1. `npm install --save-dev --save-exact @nextcommerce/campaigns-os@1.53.0`
|
|
81
|
+
2. `npx --no-install campaigns-os install-agent-context --target .` (overwrites all four files under `.campaign-runtime/agent-context/`; local edits there are lost)
|
|
82
|
+
3. Review and commit `git diff .campaign-runtime/agent-context/`
|
|
83
|
+
4. `npx --no-install campaigns-os tooling setup --target . --platform claude`
|
|
84
|
+
5. Restart the agent session so it loads the new skills and context.
|
|
85
|
+
|
|
86
|
+
Codex, Cursor and Copilot users run step 2 and reinstall skills with `install-skills --platform codex` (or `agents`).
|
|
87
|
+
|
|
88
|
+
## [1.53.0+agent.1] - 2026-10-05
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- Polish now measures text readability on every built page at desktop and mobile widths and reports warnings, review and coverage results in the QC handoff. QA's primary-CTA check and the theme generator use the same unrounded WCAG 2.x measurement. Results change on some campaigns: ratios in [4.495, 4.5), translucent text or backgrounds, and child text now warn; large bold text at 3:1 and Tailwind v4 `oklch()` colours are measured correctly; gradients, unreadable colours, and opacity, filters, blend modes or masks on surrounding elements become manual review instead of a contrast result. QA's primary-CTA check no longer skips pages by page type: every page with an expected next route is checked, every route-matching CTA is measured (not only the most readable one), each piece of text inside a CTA is compared with the requirement for its own size, and a CTA measured before its text, the SDK, stylesheets or fonts are ready is reported for manual review, never as a pass. The primary-CTA check also reports manual review, not a failure or a pass, when the page inspection itself errors (earlier releases reported a failure), when every route-matching CTA is disabled, and when a CTA's text includes text generated by CSS `::before` or `::after` (earlier releases reported a contrast pass or failure for both). `polish capture` on a campaign with no mapped pages now measures readability and exits successfully, printing the page-load message as a warning. Polish media weight and readability results now read as stale when the built output changed without a new `record build`.
|
|
93
|
+
|
|
94
|
+
## [1.53.0] - 2026-10-05
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- Adds `record brief`, which saves Campaign Build Brief answers without re-running intake. A brief file is guided unless it sets `"brief_mode": "prepared"` (a campaign whose report already records a prepared brief stays prepared). An unchanged or reformatted save keeps all stage evidence and statuses. A material change marks build, Polish and QA (or QA alone for `qa_policy`) as owed again and keeps the last five superseded records per stage as history. `next` routes to the owed stage. Re-recording an unchanged build after an input change keeps the build owed unless the operator records a reason, including when a CampaignSpec change was never saved with `record spec`; an edit to the brief file is read only once it is saved with `record brief`. Intake now also refuses, without `--force`, to discard recorded waivers, warning accepts, stage history, an applied theme, or a recorded deploy target, preview URL, production URL, order-path depth or allowed-domains confirmation; with `--force`, it keeps stage history and archives the records it clears.
|
|
99
|
+
- Adds `record spec`, a non-destructive refresh after a CampaignSpec change. Superseded build, Polish and QA records move to stage history, and `next`, progress, readback and the Assembly Report status now report the owed stage instead of recommending QA. Spec material changes are detected for saved-Map and gateway packets too (against the fetched copy; remote currency is reported as unconfirmed). `spec derive` no longer rebinds report identity on its own; run `record spec` after it. Re-recording an unchanged build or replaying a Polish record after an input change no longer makes them current, whether or not the change was saved with `record spec`.
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- `spec derive --json` no longer carries the `rebound` field, because `spec derive` no longer rebinds report identity.
|
|
104
|
+
- A stage status outside the recognized list (`pending`, `blocked`, `required`, `completed`, `completed_with_warnings`, `completed_partial`, `skipped`) now reads as unknown and stops `next`, where earlier releases accepted any status beginning `completed` or `skipped`.
|
|
105
|
+
- The effects contract declares the `record brief` and `record spec` rows (tier C) and their `--dry-run` rows (tier none, with no lifecycle entry). It corrects the intake rows: `start`, `prepare-build` and `build` are refused without `--force` when the report carries stage evidence, stage history or operator decisions, and their `--force` forms archive completed build, Polish and QA records into stage history, which is kept. It also states that `record build` writes `input_change` and makes Polish and QA owed when it detects a brief or CampaignSpec change, and that `record polish`, `record theme` and `record deploy` are refused while an earlier stage is owed again.
|
|
106
|
+
|
|
107
|
+
### Migration
|
|
108
|
+
|
|
109
|
+
**Migration.** Build, Polish and QA records made before this release do not record which brief and CampaignSpec content they used, so they read as unconfirmed. After upgrading, `next` routes each in-flight campaign back to build once: re-record build and Polish, and run QA again for a new verdict. Hand-written brief files without `brief_mode` are now guided for new campaigns; add `"brief_mode": "prepared"` if you want open questions to block.
|
|
110
|
+
|
|
111
|
+
- Re-running `start`, `prepare-build` or `build` over a campaign with recorded waivers, warning accepts, stage history, an applied theme, or a recorded deploy target, preview URL, production URL, order-path depth or allowed-domains confirmation is now refused without `--force`. Save brief answers with `record brief` and a CampaignSpec change with `record spec` instead; pass `--force` only to clear that state on purpose.
|
|
112
|
+
- Scripts that read `rebound` from `spec derive --json` must stop: run `record spec` after `spec derive` to bind the new CampaignSpec content.
|
|
113
|
+
|
|
5
114
|
## [1.52.0+agent.1] - 2026-10-05
|
|
6
115
|
|
|
7
116
|
### Added
|
package/README.md
CHANGED
|
@@ -290,6 +290,7 @@ npm run campaigns-os -- doctor --packet <page-kit-repo>/campaign-runtime.build.j
|
|
|
290
290
|
npm run campaigns-os -- page-kit sync --packet <page-kit-repo>/campaign-runtime.build.json --dry-run
|
|
291
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
292
|
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
|
|
293
|
+
npm run campaigns-os -- sdk repin --target <static-campaign-repo> --target-sdk 0.4.38
|
|
293
294
|
npm run campaigns-os -- standardize --target <page-kit-repo-or-cpk-repo> --json
|
|
294
295
|
npm run campaigns-os -- theme inspect --packet <page-kit-repo>/campaign-runtime.build.json --json
|
|
295
296
|
npm run campaigns-os -- theme generate --packet <page-kit-repo>/campaign-runtime.build.json --json
|
package/agents/claude/CLAUDE.md
CHANGED
|
@@ -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 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
|
+
|
|
11
13
|
Core rules:
|
|
12
14
|
|
|
13
15
|
- Treat CampaignSpec as campaign intent and the Campaigns API as live commerce truth.
|
package/agents/codex/AGENTS.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Use this context when working in a target campaign repo with Campaigns OS artifacts.
|
|
4
4
|
|
|
5
|
+
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.
|
|
6
|
+
|
|
5
7
|
- Read `campaign-runtime.build.json` first.
|
|
6
8
|
- 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/`.
|
|
7
9
|
- If `.campaign-runtime/build-context.json` or `.campaign-runtime/assembly-report.json` exists, read them before editing campaign files.
|
|
@@ -8,6 +8,8 @@ When this repository contains Campaigns OS artifacts, use them as the build hand
|
|
|
8
8
|
- 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/`.
|
|
9
9
|
- `.campaign-runtime/theme/theme-report.json`, when present, is optional brand-theme evidence. Generated `brand-theme.css` must load after `next-core.css`; missing or low-confidence theme is a warning/skipped reason, not permission to edit SDK-owned runtime surfaces.
|
|
10
10
|
|
|
11
|
+
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
|
+
|
|
11
13
|
CampaignSpec validation is owned by the public `@nextcommerce/campaigns-os/campaign-spec` rules surfaced through doctor `spec.validation` findings; use structured rule/path detail when available.
|
|
12
14
|
|
|
13
15
|
Preserve Campaign Cart SDK-owned commerce surfaces. Replace starter demo refs from CampaignSpec/API. Prepared AI/exported HTML must be converted into page-kit-ready source first: keep page-owned body markup, strip document wrappers, add YAML frontmatter, move shared CSS/assets into the campaign structure, and use Liquid helpers only for page-kit links/assets/includes. Landing/presell pages can preserve source design; checkout/upsell/downsell/receipt should use starter-template commerce surfaces as SDK contract references while campaign/source owns visual chrome. Reproduce the source design's own proof and urgency elements as designed (reviews, ratings, stock counters, countdowns, guarantees). They are the merchant's content; Campaigns OS does not review them, so do not remove, soften or flag them. Copy starter template families atomically with dependent pages, `_includes/`, `_layouts/`, `assets/css/`, and `assets/js/`; do not copy only checkout/receipt pages. Do not claim launch readiness until build, polish, deploy, and QA evidence are recorded.
|
|
@@ -8,6 +8,8 @@ alwaysApply: false
|
|
|
8
8
|
|
|
9
9
|
Read Campaigns OS artifacts before editing campaign pages. 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/`. Treat CampaignSpec/API values as live commerce truth, starter-template contracts as SDK surface truth, and designed HTML/assets as visual/content intent. Treat CampaignSpec validation as owned by the public `@nextcommerce/campaigns-os/campaign-spec` rules surfaced through doctor `spec.validation` findings; use structured rule/path detail when available. If `context.theme` or `.campaign-runtime/theme/theme-report.json` exists, use it as optional brand-theme evidence; generated `brand-theme.css` must load after `next-core.css`, and missing/low-confidence theme is a warning or skipped reason, not permission to edit SDK-owned runtime surfaces.
|
|
10
10
|
|
|
11
|
+
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
|
+
|
|
11
13
|
Do not carry over demo package, shipping, voucher, payment, tracking, footer, or SEO values. Prepared AI/exported HTML must be converted into page-kit-ready source first: keep page-owned body markup, strip document wrappers, add YAML frontmatter, move shared CSS/assets into the campaign structure, and use Liquid helpers only for page-kit links/assets/includes. Preserve prepared landing/presell source HTML when it is a real standalone design. For checkout/upsell/downsell/receipt, use starter-template commerce surfaces as SDK contract references while campaign/source owns visual chrome. Reproduce the source design's own proof and urgency elements as designed (reviews, ratings, stock counters, countdowns, guarantees). They are the merchant's content; Campaigns OS does not review them, so do not remove, soften or flag them. Copy starter template families atomically with dependent pages, `_includes/`, `_layouts/`, `assets/css/`, and `assets/js/`; do not copy only checkout/receipt pages. Emit SDK routing meta tags as campaign-root paths such as `/campaign-slug/upsell/`. Preserve SDK-owned checkout/cart/upsell/receipt surfaces. For `shop-three-step`, shipping is dynamic via `window.next.getShippingMethods()`.
|
|
12
14
|
|
|
13
15
|
Before Polish becomes terminal or hands off to deploy/QA, install the package-owned Playwright browser with `npm run qa:install-browser`, serve the current build, and run `npx --no-install campaigns-os polish capture --packet campaign-runtime.build.json --base-url <served-current-build-url>`. After that checkpoint clears, QA uses the Campaigns OS Node/npm runner: `npx --no-install campaigns-os qa resolve`, then `npx --no-install campaigns-os qa run --browser --test-order common` against the tested URL. Test-order proof uses `npx --no-install campaigns-os qa run --test-order <common|checkout|decline|accept|both|full|explicit-path>` through the tested checkout and rendered upsell controls. `qa run` has no permission flag: coverage is its only control. Test orders still land in the store as real orders (global test cards: no charge, no transaction) that someone may have to cancel. Unless the operator has already said test orders are fine for this campaign, ask once, up front in your first turn with your other setup questions, so the answer covers the whole build and QA and neither stops for it later. `common` runs every actual terminal path when they fit under the flood cap (`--max-test-orders`, 6 by default); above the cap it runs the checkout baseline, first-offer accept and decline, and a deduplicated shortest real receipt path, then adds one decline path per offer or downsell page not yet declined, up to the cap, and names any page left out. A page counts as covered only when an order clicks its decline; the `browser-test-order:upsell-action-coverage` verdict row warns naming each page whose decline no order clicked. `full` walks every actual terminal path in the selected checkout topology; cycles, missing routes, and reachable nonterminals block exhaustive proof before browser launch. The accidental-flood cap remains `6`, and an overflow names the exact explicit `--max-test-orders` raise. Analytics correctness is two-phase: the campaign-root visit inventories declared providers/tags only, and the same canonical typed-card run proves Purchase only from the topology-recognized final receipt document after `--analytics-settle`. Missing/unrecognized receipts are manual-review warnings; recognized receipt no-signal and capture/settle errors block. Only the genuine recognized-receipt/no-signal failure is waivable; capture/settle errors are not. Checkout/upsell signals remain whole-journey parity evidence and cannot satisfy a silent receipt. Do not use `next.getCartData().cartLines` as cart-populated proof; use typed-card order read-back, `cart:updated` payload `items` / `summary.lines`, and rendered bundle DOM evidence. Localhost on any port is a Campaigns App Development domain for SDK QA with analytics suppressed; non-localhost preview/production origins still need SDK origin allowlist confirmation. External browser skills, SDK test-mode events, and direct backend orders are not launch proof. 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.
|
package/compatibility.json
CHANGED
|
@@ -31,6 +31,16 @@
|
|
|
31
31
|
"cc-year": "exp-year"
|
|
32
32
|
},
|
|
33
33
|
"prefixes": ["billing-"],
|
|
34
|
+
"version_gated_aliases": {
|
|
35
|
+
"first_name": { "canonical": "fname", "since": "0.4.39" },
|
|
36
|
+
"last_name": { "canonical": "lname", "since": "0.4.39" },
|
|
37
|
+
"phone_number": { "canonical": "phone", "since": "0.4.41" }
|
|
38
|
+
},
|
|
39
|
+
"version_gated_provenance": {
|
|
40
|
+
"source": "NextCommerceCo/campaign-cart src/utils/checkout-field-names.ts at v0.4.39 (first_name, last_name; v0.4.40 is the same SDK) and v0.4.41 (phone_number), and v0.4.41 docs/guides/reference/data-attributes.md (Field names)",
|
|
41
|
+
"rule": "A version-gated alias is supported when the binding's SDK version is an exact release at or after since. Below since, or when the version is unknown, the alias is judged as on an earlier SDK: a name also listed in stale_aliases is a stale alias, any other is unknown. The canonical name is supported on every version.",
|
|
42
|
+
"captured_at": "2026-10-06"
|
|
43
|
+
},
|
|
34
44
|
"stale_aliases": {
|
|
35
45
|
"state": "province",
|
|
36
46
|
"region": "province",
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"schema_version": "campaign-cart-sdk-support-policy/v0",
|
|
3
3
|
"provenance": {
|
|
4
4
|
"source": "NextCommerceCo/campaign-cart release tags",
|
|
5
|
-
"latest_known_release": "0.4.
|
|
6
|
-
"captured_at": "2026-
|
|
5
|
+
"latest_known_release": "0.4.41",
|
|
6
|
+
"captured_at": "2026-10-07"
|
|
7
7
|
},
|
|
8
8
|
"source": "contracts/campaign-cart-sdk-support-policy.v0.json",
|
|
9
9
|
"minimum_supported": "0.4.20",
|
|
@@ -848,9 +848,9 @@
|
|
|
848
848
|
}
|
|
849
849
|
},
|
|
850
850
|
"verification": {
|
|
851
|
-
"sdk_version": "0.4.
|
|
852
|
-
"verified_at": "2026-10-
|
|
853
|
-
"evidence": "sdk-0.4.
|
|
851
|
+
"sdk_version": "0.4.41",
|
|
852
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
853
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
854
854
|
"status": "certified",
|
|
855
855
|
"source": "template-verification.json"
|
|
856
856
|
}
|
|
@@ -861,7 +861,7 @@
|
|
|
861
861
|
"id": "template-reference-apollo",
|
|
862
862
|
"family": "apollo",
|
|
863
863
|
"version": "sdk-0.4.38-composable-upsells-2026-09-25",
|
|
864
|
-
"source_commit": "
|
|
864
|
+
"source_commit": "1a3bf7218e7f10ef5733ceba84d2856eeca2cfbd",
|
|
865
865
|
"provenance_url": "https://raw.githubusercontent.com/NextCommerceCo/campaign-cart-starter-templates/main/docs/template-references/apollo/README.md",
|
|
866
866
|
"contract_path": "contracts/commerce-surface-catalog.json",
|
|
867
867
|
"standard_viewport_refs": [
|
|
@@ -1272,9 +1272,9 @@
|
|
|
1272
1272
|
}
|
|
1273
1273
|
},
|
|
1274
1274
|
"verification": {
|
|
1275
|
-
"sdk_version": "0.4.
|
|
1276
|
-
"verified_at": "2026-10-
|
|
1277
|
-
"evidence": "sdk-0.4.
|
|
1275
|
+
"sdk_version": "0.4.41",
|
|
1276
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
1277
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
1278
1278
|
"status": "certified",
|
|
1279
1279
|
"source": "template-verification.json"
|
|
1280
1280
|
}
|
|
@@ -1583,9 +1583,9 @@
|
|
|
1583
1583
|
}
|
|
1584
1584
|
},
|
|
1585
1585
|
"verification": {
|
|
1586
|
-
"sdk_version": "0.4.
|
|
1587
|
-
"verified_at": "2026-10-
|
|
1588
|
-
"evidence": "sdk-0.4.
|
|
1586
|
+
"sdk_version": "0.4.41",
|
|
1587
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
1588
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
1589
1589
|
"status": "certified",
|
|
1590
1590
|
"source": "template-verification.json"
|
|
1591
1591
|
}
|
|
@@ -1886,9 +1886,9 @@
|
|
|
1886
1886
|
}
|
|
1887
1887
|
},
|
|
1888
1888
|
"verification": {
|
|
1889
|
-
"sdk_version": "0.4.
|
|
1890
|
-
"verified_at": "2026-10-
|
|
1891
|
-
"evidence": "sdk-0.4.
|
|
1889
|
+
"sdk_version": "0.4.41",
|
|
1890
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
1891
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
1892
1892
|
"status": "certified",
|
|
1893
1893
|
"source": "template-verification.json"
|
|
1894
1894
|
}
|
|
@@ -2227,9 +2227,9 @@
|
|
|
2227
2227
|
}
|
|
2228
2228
|
},
|
|
2229
2229
|
"verification": {
|
|
2230
|
-
"sdk_version": "0.4.
|
|
2231
|
-
"verified_at": "2026-10-
|
|
2232
|
-
"evidence": "sdk-0.4.
|
|
2230
|
+
"sdk_version": "0.4.41",
|
|
2231
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
2232
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
2233
2233
|
"status": "certified",
|
|
2234
2234
|
"source": "template-verification.json"
|
|
2235
2235
|
}
|
|
@@ -2666,9 +2666,9 @@
|
|
|
2666
2666
|
}
|
|
2667
2667
|
},
|
|
2668
2668
|
"verification": {
|
|
2669
|
-
"sdk_version": "0.4.
|
|
2670
|
-
"verified_at": "2026-10-
|
|
2671
|
-
"evidence": "sdk-0.4.
|
|
2669
|
+
"sdk_version": "0.4.41",
|
|
2670
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
2671
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
2672
2672
|
"status": "certified",
|
|
2673
2673
|
"source": "template-verification.json"
|
|
2674
2674
|
}
|
|
@@ -3023,9 +3023,9 @@
|
|
|
3023
3023
|
}
|
|
3024
3024
|
},
|
|
3025
3025
|
"verification": {
|
|
3026
|
-
"sdk_version": "0.4.
|
|
3027
|
-
"verified_at": "2026-10-
|
|
3028
|
-
"evidence": "sdk-0.4.
|
|
3026
|
+
"sdk_version": "0.4.41",
|
|
3027
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
3028
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
3029
3029
|
"status": "certified",
|
|
3030
3030
|
"source": "template-verification.json"
|
|
3031
3031
|
}
|
|
@@ -3313,9 +3313,9 @@
|
|
|
3313
3313
|
}
|
|
3314
3314
|
},
|
|
3315
3315
|
"verification": {
|
|
3316
|
-
"sdk_version": "0.4.
|
|
3317
|
-
"verified_at": "2026-10-
|
|
3318
|
-
"evidence": "sdk-0.4.
|
|
3316
|
+
"sdk_version": "0.4.41",
|
|
3317
|
+
"verified_at": "2026-10-06T23:03:41Z",
|
|
3318
|
+
"evidence": "sdk-0.4.41-2026-10-06.5",
|
|
3319
3319
|
"status": "certified",
|
|
3320
3320
|
"source": "template-verification.json"
|
|
3321
3321
|
}
|
|
@@ -3504,6 +3504,6 @@
|
|
|
3504
3504
|
}
|
|
3505
3505
|
},
|
|
3506
3506
|
"_synced_from_repo": "NextCommerceCo/campaign-cart-starter-templates",
|
|
3507
|
-
"_synced_from_ref": "
|
|
3508
|
-
"_synced_from_sha": "
|
|
3507
|
+
"_synced_from_ref": "783329017c6994a94d11e46580c33bd052aabdb0",
|
|
3508
|
+
"_synced_from_sha": "783329017c6994a94d11e46580c33bd052aabdb0"
|
|
3509
3509
|
}
|