@nextcommerce/campaigns-os 1.48.0 → 1.52.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 +539 -0
- package/agents/claude/CLAUDE.md +6 -5
- package/agents/codex/AGENTS.md +6 -5
- package/agents/copilot/copilot-instructions.md +3 -3
- package/agents/cursor/campaigns-os.mdc +3 -3
- package/campaign-spec/dist/rules/campaign-metadata.d.ts +5 -1
- package/campaign-spec/dist/rules/campaign-metadata.js +9 -2
- package/campaign-spec/dist/rules/design-source-shape.js +13 -3
- package/campaign-spec/dist/rules/sdk-version.js +2 -1
- package/compatibility.json +1 -1
- package/contracts/commerce-surface-catalog.json +26 -46
- package/contracts/effects.v1.json +254 -2
- package/contracts/release-ledger.json +1239 -0
- package/contracts/supported-surface.json +4 -4
- package/contracts/template-brand-contract.shared-commerce.v0.json +2 -2
- package/contracts/template-slot-manifest.shared-content-core.v0.json +24 -0
- package/docs/brand-theme-bridge.md +12 -6
- package/docs/build-packet.md +101 -12
- package/docs/campaign-build-brief.md +25 -1
- package/docs/effects.md +6 -0
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +10 -0
- package/docs/qa-and-test-orders.md +66 -11
- package/docs/runtime-readiness.md +1 -1
- package/docs/sdk-storage-compatibility.md +1 -1
- package/docs/skills-revision.md +10 -10
- package/package.json +1 -1
- package/schemas/campaign-runtime-build-packet.v0.schema.json +4 -0
- package/schemas/campaigns-os-qa-verdict.v0.schema.json +8 -3
- 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 +4 -4
- package/skills/next-campaigns-os/SKILL.md +4 -4
- package/skills/next-campaigns-os/references/session-intake.md +7 -3
- package/skills/next-campaigns-os-setup/SKILL.md +3 -3
- package/skills/next-campaigns-polish/SKILL.md +5 -4
- package/skills/next-campaigns-qa/SKILL.md +6 -5
- package/skills.json +10 -10
- package/src/adapter-decision-contract.mjs +1 -1
- package/src/brand-theme.mjs +25 -2
- package/src/build-brief.mjs +68 -21
- package/src/built-site-scope.mjs +39 -6
- package/src/built-smoke-qc.mjs +1117 -0
- package/src/campaign-identity.mjs +36 -2
- package/src/cart-placeholders.mjs +730 -0
- package/src/cli.mjs +320 -42
- package/src/commercial-journey.mjs +65 -4
- package/src/commercial-parity.mjs +6 -1
- package/src/doctor/checks.mjs +291 -24
- package/src/doctor/inspect.mjs +53 -2
- package/src/doctor/next-step.mjs +1 -1
- package/src/install-mode.mjs +0 -8
- package/src/invocation.mjs +5 -2
- package/src/local-preview-policy.mjs +1 -1
- package/src/local-proof.mjs +4 -1
- package/src/polish-browser.mjs +218 -1
- package/src/polish-capture.mjs +1 -1
- package/src/polish-media-weight.mjs +492 -0
- package/src/polish-node.mjs +96 -4
- package/src/progress-node.mjs +5 -1
- package/src/qa-binding-evidence.mjs +21 -0
- package/src/qa-browser.mjs +338 -97
- package/src/qa-content-params.mjs +889 -0
- package/src/qa-node.mjs +114 -14
- package/src/qa-order-bump.mjs +22 -1
- package/src/qa-policy-links.mjs +1019 -0
- package/src/qa-tracking-params.mjs +1389 -0
- package/src/qa-url-privacy.mjs +168 -0
- package/src/qc-accept.mjs +446 -0
- package/src/qc-check-registry.mjs +83 -0
- package/src/qc-results.mjs +1049 -0
- package/src/sdk-attribute-index.mjs +71 -0
- package/src/sdk-markup.mjs +2 -2
- package/src/sdk-storage-compatibility.mjs +63 -3
- package/src/source-prep.mjs +37 -7
- package/src/stage-record.mjs +356 -36
- package/src/theme-gate.mjs +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,545 @@
|
|
|
2
2
|
|
|
3
3
|
Notable supported-surface changes are recorded here.
|
|
4
4
|
|
|
5
|
+
## [1.52.0+agent.1] - 2026-10-05
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Doctor now reports built-page smoke warnings: missing in-page anchor targets, missing favicon and Open Graph tags, unresolved `og:image`, the Tailwind CDN script in production builds, `cdn.29next.store` asset references, and loopback URLs.
|
|
10
|
+
|
|
11
|
+
## [1.52.0] - 2026-10-05
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- QA now checks that configured store policy links are rendered and reachable, recording link presence and availability separately. QA now sends bounded header-only requests to the configured policy URLs; the effects contract declares them.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- The effects contract now states that `qa run --browser` sends the header-only GET requests to the configured store policy URLs, rather than declaring them ahead of the check that sends them.
|
|
20
|
+
|
|
21
|
+
## [1.51.0+agent.4] - 2026-10-05
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- QA now checks at runtime that declared content parameters hide their content, comparing fresh contexts with and without `?<name>=n`.
|
|
26
|
+
|
|
27
|
+
## [1.51.0+agent.3] - 2026-10-05
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- QA browser test orders now report URL preservation and order attribution for synthetic tracking parameters as separate results. QA order evidence no longer stores query strings in `checkout_url`, `final_url` or request URLs.
|
|
32
|
+
|
|
33
|
+
## [1.51.0+agent.2] - 2026-10-05
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Polish capture now records image geometry and redirect chains, and reports origin and weight warnings for video and large images served from the page's own origin, plus oversized images.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- `polish capture` now records media weight beside page load evidence in the Assembly Report, so `next` reads the image weight and oversize results of a fresh capture.
|
|
42
|
+
|
|
43
|
+
## [1.51.0+agent.1] - 2026-10-04
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Doctor now warns on SDK cart placeholders printed in live built HTML (`built_output.cart_placeholders`), ported from the public starter-template lint.
|
|
48
|
+
|
|
49
|
+
## [1.51.0] - 2026-10-04
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- Adds `checkpoint accept`, which records an operator's accept of a measured warning next to the unchanged measurement, and a QC handoff section in `next` that lists open, review, lapsed, unexercised and excluded results. Accepts never change readiness, and `checkpoint waive` still refuses gates that are not blocked.
|
|
54
|
+
- The effects contract now declares bounded header-only GET requests to the store policy URLs a CampaignSpec configures, for `qa run --browser`, ahead of the check that sends them; QA does not send them yet.
|
|
55
|
+
|
|
56
|
+
## [1.50.0+agent.20] - 2026-10-04
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- `scripts/refresh-certified-family-fixtures.mjs` now sets `og_image` to
|
|
61
|
+
`https://example.com/og-image.png` on each certified family's
|
|
62
|
+
`_data/campaigns.json` entry before it renders, and records that in the
|
|
63
|
+
fixture manifest as `render_inputs`. The starters leave `og:image` out until
|
|
64
|
+
a campaign sets one, so without it every certified page would report a
|
|
65
|
+
missing `og:image` to the coming built-output smoke checks. The value is on a
|
|
66
|
+
reserved domain, so it is plainly synthetic, and doctor `--built` neither
|
|
67
|
+
maps nor fetches it. The committed fixture tree is unchanged until the next
|
|
68
|
+
regeneration.
|
|
69
|
+
|
|
70
|
+
## [1.50.0+agent.19] - 2026-10-03
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
|
|
74
|
+
- A campaign-identity finding (`funnel_drift`, `funnel_missing`,
|
|
75
|
+
`api_key_drift`, `attribution_drift`) that names a built file no active
|
|
76
|
+
CampaignSpec page builds to now says so, and lists the file on the finding as
|
|
77
|
+
`stray_files`. The message says to remove the source file if there is one,
|
|
78
|
+
delete the built file, and rebuild and record the build again. Before, a
|
|
79
|
+
design `index.html` copied under `assets/` built as its own page and blocked
|
|
80
|
+
as funnel drift, with the message telling the agent to retag a page it never
|
|
81
|
+
meant to ship. The gate still blocks, because the file is still served.
|
|
82
|
+
|
|
83
|
+
## [1.50.0+agent.18] - 2026-10-03
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- Commercial parity no longer warns `price-claim-mismatch` on a page that shows
|
|
88
|
+
a voucher the normalized plan cannot price. An upsell priced by a live
|
|
89
|
+
voucher showed the voucher price, and QA compared it with the list-price
|
|
90
|
+
total. Those price claims now count as unresolved, as the page's voucher
|
|
91
|
+
claims already did, so coverage reads incomplete instead.
|
|
92
|
+
- `browser-order-bump-state` reads a `✓` glyph marker as checked only when its
|
|
93
|
+
text is painted. A tick that stays in the marker and is hidden with
|
|
94
|
+
`color: transparent` read checked before, so a declined bump failed as
|
|
95
|
+
misaligned.
|
|
96
|
+
|
|
97
|
+
## [1.50.0+agent.17] - 2026-10-03
|
|
98
|
+
|
|
99
|
+
### Fixed
|
|
100
|
+
|
|
101
|
+
- Three CampaignSpec validation messages that doctor and `start` print now say
|
|
102
|
+
which field to change:
|
|
103
|
+
- The missing-`payment_env_key` warning keeps "No campaign loaded — campaign
|
|
104
|
+
key required for spec export." and adds that `campaign.payment_env_key` is
|
|
105
|
+
empty, where its value comes from, and that a Campaigns API key in the spec
|
|
106
|
+
does not fill it. Before, it printed next to doctor's "Campaigns API key
|
|
107
|
+
available via the packet-local CampaignSpec" line and read as if the key
|
|
108
|
+
were missing.
|
|
109
|
+
- The missing SDK version error keeps "SDK version is required for spec
|
|
110
|
+
export." and names `global_config.sdk_version` and the form it takes.
|
|
111
|
+
- The missing `design_source.file_url` warning, for a page whose
|
|
112
|
+
`design_source.type` is not `figma` or `ai-generated`, and doctor's
|
|
113
|
+
matching no-source-mapping error, say that hand-written or template HTML
|
|
114
|
+
leaves `design_source` off the page. Before, a plain HTML page with a
|
|
115
|
+
`design_source` block was told only to add a design-tool URL.
|
|
116
|
+
|
|
117
|
+
## [1.50.0+agent.16] - 2026-10-03
|
|
118
|
+
|
|
119
|
+
### Fixed
|
|
120
|
+
|
|
121
|
+
- `prepare-build` (and `start`) no longer write an Assembly Report that fails
|
|
122
|
+
its own schema. When the brand-theme write failed, each error was copied
|
|
123
|
+
onto `theme.warnings[]` as `{ code, message, detail: error.detail || null }`.
|
|
124
|
+
The schema's `themeIssue.detail` is an object, so an error with no detail
|
|
125
|
+
(`theme.generate.not_ready`, `theme.generate.empty`) left `detail: null`.
|
|
126
|
+
`record setup` and `record build` then refused the report with
|
|
127
|
+
"Assembly Report theme.warnings.0.detail must be object". `detail` is now
|
|
128
|
+
written only when the error carries an object. The schema is unchanged.
|
|
129
|
+
|
|
130
|
+
## [1.50.0+agent.15] - 2026-10-03
|
|
131
|
+
|
|
132
|
+
### Fixed
|
|
133
|
+
|
|
134
|
+
- `record setup|build|polish|theme|deploy` accept `--deviation-reason`, as
|
|
135
|
+
every other command does. The deviation notice tells an agent that departs
|
|
136
|
+
from `next` to "Declare intent with --deviation-reason". `record` checks its
|
|
137
|
+
flags against a strict allowlist, which held only its own flags and the global
|
|
138
|
+
`--run-id` and `--lifecycle-journal`, so it refused the flag as unknown on
|
|
139
|
+
every stage. It is now a global flag there too. A bare `--deviation-reason`
|
|
140
|
+
with no value is refused as before.
|
|
141
|
+
|
|
142
|
+
## [1.50.0+agent.14] - 2026-10-03
|
|
143
|
+
|
|
144
|
+
### Fixed
|
|
145
|
+
|
|
146
|
+
- QA's placeholder text-residue gate (`template-residue:<page>:placeholder-text`,
|
|
147
|
+
and doctor's built-output warning) now also matches the starter templates'
|
|
148
|
+
own icon-grid placeholders, `Benefit one`, `Benefit two`, `Benefit three` and
|
|
149
|
+
`Benefit four`. The olympus checkouts ship them, and a campaign that kept
|
|
150
|
+
them passed QA with no failures, because the shared-commerce term list held
|
|
151
|
+
only `Lorem`, `lorem ipsum`, `Placeholder`, `TODO` and `Product Name`.
|
|
152
|
+
- The terms live in `contracts/template-brand-contract.shared-commerce.v0.json`,
|
|
153
|
+
so every family inherits them.
|
|
154
|
+
- Matching is word-bounded, so "Benefit once" does not fire.
|
|
155
|
+
- Doctor's next-step hint and `docs/template-family-contracts.md` list them.
|
|
156
|
+
|
|
157
|
+
## [1.50.0+agent.13] - 2026-10-03
|
|
158
|
+
|
|
159
|
+
### Fixed
|
|
160
|
+
|
|
161
|
+
- The source preparation check `source_html.prep.document_wrapper` reads a
|
|
162
|
+
page's converted page-kit file once it exists at `page_kit.output_path`, not
|
|
163
|
+
the design it was converted from. Wrappers are stripped during conversion,
|
|
164
|
+
and the converted page is what page-kit builds. The check only ever read the
|
|
165
|
+
mapped design, so a correctly stripped build still failed. To clear it,
|
|
166
|
+
agents copied built pages over the design source (breaking the Design Source
|
|
167
|
+
Package hashes) or recorded `preserve_document_wrappers` for pages they had
|
|
168
|
+
stripped. A converted page that still carries wrappers is reported under its
|
|
169
|
+
own path. Before conversion the design is checked as before. The frontmatter
|
|
170
|
+
and source-link checks are unchanged. `docs/source-adapters.md` says so.
|
|
171
|
+
|
|
172
|
+
## [1.50.0+agent.12] - 2026-10-03
|
|
173
|
+
|
|
174
|
+
### Fixed
|
|
175
|
+
|
|
176
|
+
- `record deploy` follows `next` past a polish carried forward on the local
|
|
177
|
+
preview. On a `local-serve` packet with a loopback preview, `next`'s stage
|
|
178
|
+
picker skips a polish that was never recorded for this build (the
|
|
179
|
+
local-preview policy carries it forward as a warning), so after
|
|
180
|
+
`record build` it answers deploy. `record deploy` checked every earlier
|
|
181
|
+
stage strictly and refused with "stages.polish.status is "required", so next
|
|
182
|
+
answers polish", which contradicted `next`. Sessions hand-wrote a polish skip
|
|
183
|
+
record to get past it. Both now read the same rule, from doctor's
|
|
184
|
+
`polish_gate`. Polish stays owed on the report and QA still reports it.
|
|
185
|
+
`record polish` and the waiver commands keep the strict gates.
|
|
186
|
+
`docs/build-packet.md` names the exception.
|
|
187
|
+
|
|
188
|
+
## [1.50.0+agent.11] - 2026-10-03
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
|
|
192
|
+
- Doctor warns `spec.material_stale` when a local-spec campaign's CampaignSpec
|
|
193
|
+
no longer has the material hash prepare-build bound on the Assembly Report
|
|
194
|
+
(`identity.spec_material_hash`). `next` prints the warning with the rest of
|
|
195
|
+
doctor's. QA already refused such a run ("Re-run prepare-build after a
|
|
196
|
+
material revision"). Until now it was the only command that checked, so a
|
|
197
|
+
spec edited after `start` was accepted by doctor, `next` and every `record`
|
|
198
|
+
command, and the problem surfaced only after the build, polish and deploy
|
|
199
|
+
stages had been recorded against the old spec. The warning names both hashes
|
|
200
|
+
and says to re-run prepare-build from the edited spec.
|
|
201
|
+
`docs/build-packet.md` says so.
|
|
202
|
+
|
|
203
|
+
## [1.50.0+agent.10] - 2026-10-03
|
|
204
|
+
|
|
205
|
+
### Fixed
|
|
206
|
+
|
|
207
|
+
- A checkout row marked `is_order_bump: true` is now read as an order bump.
|
|
208
|
+
The CampaignSpec schema and the authoring guide mark a checkout add-on with
|
|
209
|
+
that flag, and the certified fixtures use it alone, but the one bump
|
|
210
|
+
predicate the toolkit shares read only `is_upsell`. Such a row was treated
|
|
211
|
+
as a main package:
|
|
212
|
+
- the QA tier planner made it a selector tier of its own;
|
|
213
|
+
- `next` named no bump-cart QA command (`qa_run_bump`);
|
|
214
|
+
- commercial-journey priced the bump into the representative checkout and
|
|
215
|
+
planned no with/without-bump scenarios.
|
|
216
|
+
|
|
217
|
+
Either flag now marks a bump, and a row carrying `is_upsell: true` behaves as
|
|
218
|
+
before. On the certified fixtures, the five checkouts that declare a bump now
|
|
219
|
+
plan only their real tiers, and their bumps get the bump-cart command.
|
|
220
|
+
- Messages that named a bump `(is_upsell)` now say
|
|
221
|
+
`(is_order_bump or is_upsell)`: the tier planner's warning and refusal, the
|
|
222
|
+
`next` bump-command description, the `qa run --help` text and the QA
|
|
223
|
+
test-order notes. `docs/qa-and-test-orders.md` says the same.
|
|
224
|
+
|
|
225
|
+
## [1.50.0+agent.9] - 2026-10-03
|
|
226
|
+
|
|
227
|
+
### Added
|
|
228
|
+
|
|
229
|
+
- `record build --build-environment <development|production>` records the
|
|
230
|
+
page-kit environment the built output was rendered in, on
|
|
231
|
+
`stages.assembly.evidence.build_environment`. A later `record build` without
|
|
232
|
+
the flag keeps the recorded value. Before this, local proof mode
|
|
233
|
+
(`deploy.target: local-serve`) asked the agent to record the field, but no
|
|
234
|
+
command wrote it, so it was hand-edited into the Assembly Report.
|
|
235
|
+
- Under local-serve, `next` now names
|
|
236
|
+
`record build --packet <packet> --build-environment development` in the
|
|
237
|
+
build action and the build prompt.
|
|
238
|
+
- Doctor's `local_proof.build_environment` warning, the parity messages and
|
|
239
|
+
the local-proof rebuild hint name the same command.
|
|
240
|
+
- `docs/build-packet.md` and `docs/qa-and-test-orders.md` describe it.
|
|
241
|
+
|
|
242
|
+
### Fixed
|
|
243
|
+
|
|
244
|
+
- A `record` refused for a value outside a schema enum now lists the values the
|
|
245
|
+
schema allows and the value it got. For example,
|
|
246
|
+
`adapter_decisions.wrapper_policy must be equal to one of the allowed values:
|
|
247
|
+
"strip_document_wrappers", "preserve_document_wrappers", "not_required",
|
|
248
|
+
"unknown" (got "strip")`; before, it stopped at "allowed values".
|
|
249
|
+
- Doctor's adapter-decision warning for an unknown value lists the allowed
|
|
250
|
+
values too.
|
|
251
|
+
|
|
252
|
+
## [1.50.0+agent.8] - 2026-10-03
|
|
253
|
+
|
|
254
|
+
### Changed
|
|
255
|
+
|
|
256
|
+
- The vendored commerce-surface catalog is re-synced to
|
|
257
|
+
campaign-cart-starter-templates `02ffc61`, from `37a8d94`. That brings in
|
|
258
|
+
three starter changes:
|
|
259
|
+
- the single-offer upsell keeps a hidden in-offer skip, so its closing-card
|
|
260
|
+
decline works in every family (#205);
|
|
261
|
+
- `payment-methods.html` takes `method_order` and `default_method` (#202);
|
|
262
|
+
- fresh SDK 0.4.40 verification evidence (#203).
|
|
263
|
+
|
|
264
|
+
The upstream order-bump notes were consolidated, and the vendored copy
|
|
265
|
+
follows them.
|
|
266
|
+
- `fixtures/certified-families/` is regenerated at the new pin. Every
|
|
267
|
+
`upsell-single` fixture now carries the in-offer skip, so QA's static
|
|
268
|
+
`route-link:<page>:decline` check, which fails a proxy decline with no
|
|
269
|
+
target, passes on all eight families instead of failing on each.
|
|
270
|
+
- The shared commerce payment-chrome `asset_pin` moves to the new pin. The
|
|
271
|
+
asset bytes are unchanged.
|
|
272
|
+
|
|
273
|
+
## [1.50.0+agent.7] - 2026-10-03
|
|
274
|
+
|
|
275
|
+
### Fixed
|
|
276
|
+
|
|
277
|
+
- `sdk storage-check` resolves Page Kit's `campaign_asset` script srcs. A
|
|
278
|
+
page under `src/<slug>/` that loads `{{ 'js/checkout.js' | campaign_asset }}`
|
|
279
|
+
is read as `src/<slug>/assets/js/checkout.js`, where Page Kit serves it from,
|
|
280
|
+
and a page's frontmatter `scripts:` entries resolve the same way, since a
|
|
281
|
+
layout's `{% for script in scripts %}` loop loads them through that filter.
|
|
282
|
+
Until now every such tag read as a relative path that was never in scope and
|
|
283
|
+
reported `shared-script-outside-scope`, so every Page Kit campaign came back
|
|
284
|
+
`unknown` even when nothing was incompatible (#582). A resolved script left
|
|
285
|
+
out of `--scope`, or excluded, is still reported, under its real path; a
|
|
286
|
+
`campaign_asset` value the scan cannot resolve stays unknown.
|
|
287
|
+
`docs/sdk-storage-compatibility.md` says so.
|
|
288
|
+
|
|
289
|
+
## [1.50.0+agent.6] - 2026-10-03
|
|
290
|
+
|
|
291
|
+
### Fixed
|
|
292
|
+
|
|
293
|
+
- QA no longer passes an upsell decline or accept that does nothing. Some
|
|
294
|
+
upsell pages show a `data-upsell-proxy="skip"` (or `"add"`) button that
|
|
295
|
+
forwards its click to the SDK's `data-next-upsell-action` inside the offer.
|
|
296
|
+
When the offer has no such action, the static `route-link:<page>:decline`
|
|
297
|
+
(or `:accept`) check used to pass on the decline URL in the page's meta tag,
|
|
298
|
+
and only browser QA, after placing the order, found the control missing. The
|
|
299
|
+
static check now fails as a blocker and says the proxy has nothing to
|
|
300
|
+
forward to. The starter templates' single-offer upsell shipped this way in
|
|
301
|
+
every family until the templates kept a hidden in-offer skip.
|
|
302
|
+
- Browser QA declines (and accepts) through the control a shopper sees. When
|
|
303
|
+
the page's `data-next-upsell-action` is hidden and a visible
|
|
304
|
+
`data-upsell-proxy` button forwards to it, QA clicks the proxy instead of
|
|
305
|
+
failing with `Element is not visible` on the hidden action. A proxy with no
|
|
306
|
+
in-offer action is still reported as a missing upsell control.
|
|
307
|
+
|
|
308
|
+
## [1.50.0+agent.5] - 2026-10-03
|
|
309
|
+
|
|
310
|
+
### Changed
|
|
311
|
+
|
|
312
|
+
- The agent context the toolkit installs (`agents/claude/CLAUDE.md`,
|
|
313
|
+
`agents/codex/AGENTS.md`, `agents/cursor/campaigns-os.mdc`,
|
|
314
|
+
`agents/copilot/copilot-instructions.md`) and the `next-campaigns-os` and
|
|
315
|
+
`next-campaigns-qa` skills no longer say test orders need no permission or
|
|
316
|
+
approval, or are safe to fire any time. They say `qa run` has no permission
|
|
317
|
+
flag and coverage is its only control, and that test orders still land in
|
|
318
|
+
the store as real orders (global test cards: no charge, no transaction) that
|
|
319
|
+
someone may have to cancel. Unless the operator has already said test orders
|
|
320
|
+
are fine for the campaign, the agent asks once, up front in its first turn
|
|
321
|
+
with its other setup questions, so the answer covers the whole build and QA
|
|
322
|
+
and neither stops for it later. The skill's session-intake reference says
|
|
323
|
+
the same in its test-order proof policy.
|
|
324
|
+
- The QA skill follows an answer the operator already gave and does not pause
|
|
325
|
+
QA to ask again. When nobody asked earlier, it asks once before the first
|
|
326
|
+
test order.
|
|
327
|
+
- `qa run` is unchanged: it has no permission flag and none is added. Its
|
|
328
|
+
help text and the docs are unchanged.
|
|
329
|
+
- Bundled skills carry revision `1.50.0+skills.2`, with each skill version
|
|
330
|
+
advanced one patch.
|
|
331
|
+
|
|
332
|
+
## [1.50.0+agent.4] - 2026-10-02
|
|
333
|
+
|
|
334
|
+
### Changed
|
|
335
|
+
|
|
336
|
+
- At the QA stage, `next` lists a second QA command when the CampaignSpec's
|
|
337
|
+
checkout declares an order bump (`is_upsell: true` rows). `qa_run_bump`,
|
|
338
|
+
beside `qa_run`, is the same `qa run --browser --test-order common` with
|
|
339
|
+
`--cart <base>:1,<bump>:1`, so its test orders carry the add-on and prove
|
|
340
|
+
its charge. Until now `next` named only the default run. Its test orders
|
|
341
|
+
never toggle a bump, because the tier planner skips bump rows by design and
|
|
342
|
+
bump coverage comes from `--cart`, so a verdict could read ready with the
|
|
343
|
+
add-on never ordered. The base is the first selector tier the checkout
|
|
344
|
+
declares; a checkout that declares no tier gets the bump alone, and several
|
|
345
|
+
declared bumps share one cart. The QA stage prompt and the human `next`
|
|
346
|
+
output name the same command, and `docs/qa-and-test-orders.md` says so
|
|
347
|
+
under its launch-grade proof list. The bump is read from the one checkout
|
|
348
|
+
QA's test orders run on, the first enabled checkout across funnels, so a
|
|
349
|
+
bump declared only on a later funnel's checkout gets no command. When the
|
|
350
|
+
CampaignSpec does not parse, `next` warns
|
|
351
|
+
(`next.order_bump_spec_unreadable`) instead of silently naming no bump
|
|
352
|
+
command.
|
|
353
|
+
- A progress snapshot records `qa_run_bump` as `qa_run`. The snapshot's
|
|
354
|
+
action vocabulary is unchanged, and a ready QA continuation does not read
|
|
355
|
+
as blocked.
|
|
356
|
+
- The QA tier planner reads its bump and tier helpers from the
|
|
357
|
+
commercial-journey module, where `next` reads them too. Tier planning is
|
|
358
|
+
unchanged.
|
|
359
|
+
|
|
360
|
+
## [1.50.0+agent.3] - 2026-10-02
|
|
361
|
+
|
|
362
|
+
### Changed
|
|
363
|
+
|
|
364
|
+
- The Campaign Build Brief question `promo_urgency_copy` now asks only about
|
|
365
|
+
the starter template's own promo placeholders: demo countdown timers, promo
|
|
366
|
+
banners, placeholder voucher codes and exit-pop offers. It asks whether to
|
|
367
|
+
fill them from the campaign's promo codes and offers or remove them. It no
|
|
368
|
+
longer asks which promo, savings and urgency language is approved, which
|
|
369
|
+
read as a request to approve the source design's own copy; that copy is the
|
|
370
|
+
merchant's content and is built as designed.
|
|
371
|
+
- The question is asked only when the CampaignSpec maps a surface that fills
|
|
372
|
+
those placeholders: a `funnels[].promo_codes` roster, or a checkout page's
|
|
373
|
+
enabled `exit_intent` or `promo_code_input`. It used to be asked for any CampaignSpec
|
|
374
|
+
key naming an offer, discount, timer or urgency, so the offer catalog,
|
|
375
|
+
before-discount prices and design slot names all raised it. Without such a
|
|
376
|
+
surface the guided draft sets `promo_urgency.header_claim_source` and
|
|
377
|
+
`promo_urgency.timer_label` to `"none"` (the template's promo placeholders
|
|
378
|
+
are removed). The draft used to set `timer_label` to "Limited-time offer".
|
|
379
|
+
- Doctor's `build_brief.guided_questions` warning names the brief fields that
|
|
380
|
+
close each open question and says how to record the answers: copy the
|
|
381
|
+
normalized draft to `campaign-build-brief.json` in the target repo, set the
|
|
382
|
+
fields, and re-run `start` or `prepare-build`. It also says the re-run needs
|
|
383
|
+
`--force`, which clears stage evidence, once a stage has recorded evidence.
|
|
384
|
+
`build_brief.questions_unanswered` names the fields too. An answer given
|
|
385
|
+
only in conversation was never recorded, so a later session asked again.
|
|
386
|
+
- `next`'s QA prompt compares the template's own promo placeholders and trust
|
|
387
|
+
badges with the brief and says not to flag the source design's own proof,
|
|
388
|
+
urgency or guarantee elements. It used to ask for promo/urgency copy and
|
|
389
|
+
trust/guarantee claims to be compared. The build prompt names the template's
|
|
390
|
+
promo placeholders where it named promo/urgency language.
|
|
391
|
+
- `docs/campaign-build-brief.md` rewords question 5 and adds "Answering The
|
|
392
|
+
Questions", with the fields that close each question.
|
|
393
|
+
|
|
394
|
+
## [1.50.0+agent.2] - 2026-10-02
|
|
395
|
+
|
|
396
|
+
### Changed
|
|
397
|
+
|
|
398
|
+
- `docs/build-packet.md` says how to read a campaign's package, offer and
|
|
399
|
+
shipping refs for a local CampaignSpec. Its new "Reading package, offer and
|
|
400
|
+
shipping refs" section, under "Local-spec entry", gives the read doctor and
|
|
401
|
+
QA already make against the live campaign: one GET of NEXT's proxy,
|
|
402
|
+
`https://campaign-map.nextcommerce.com/api/campaign`, with the public
|
|
403
|
+
Campaigns API key in the `X-Campaign-Key` header. It shows a `node` and a
|
|
404
|
+
`curl` form, describes the envelope, and maps the campaign retrieve body's
|
|
405
|
+
`id`, `packages[]`, `offers[]` and `shipping_methods[]` to
|
|
406
|
+
`campaign.ref_id`, `funnels[].pages[].packages[]`, root `offers[]` and root
|
|
407
|
+
`shipping_methods[]`. It also notes that the proxy refuses some default user
|
|
408
|
+
agents, Python `urllib`'s and Perl `libwww-perl`'s among them. No command
|
|
409
|
+
writes these refs, as before.
|
|
410
|
+
- With no saved gateway login, `tooling status` no longer only says to run
|
|
411
|
+
`login`. Its warning says login is optional and only lets `spec derive
|
|
412
|
+
--from-store` fill the Store Profile fields, and a second warning says
|
|
413
|
+
package, offer and shipping refs never come from the gateway login and
|
|
414
|
+
where the public-key read is documented. Both lines are under `warnings`,
|
|
415
|
+
and the exit code is unchanged.
|
|
416
|
+
|
|
417
|
+
## [1.50.0+agent.1] - 2026-10-02
|
|
418
|
+
|
|
419
|
+
### Changed
|
|
420
|
+
|
|
421
|
+
- No command behaves differently. A comment in the QA browser module that
|
|
422
|
+
explains how repeated package declarations become purchase multipliers
|
|
423
|
+
named an internal store as its example; it now gives a neutral one (a 1x
|
|
424
|
+
and a 2x package). Two QA test files swap the same name in a fixture SKU
|
|
425
|
+
and a hosted-checkout URL for neutral placeholders, and the same fixture's
|
|
426
|
+
product title becomes "Demo Bag". Comment and test fixtures only; every
|
|
427
|
+
message and every exit code is unchanged.
|
|
428
|
+
- The private-string check adds that store name to its hashed list, so it
|
|
429
|
+
cannot return.
|
|
430
|
+
|
|
431
|
+
## [1.50.0] - 2026-10-02
|
|
432
|
+
|
|
433
|
+
### Changed
|
|
434
|
+
|
|
435
|
+
- With `qa run --browser`, each page's `page-binding:<page_id>` row comes
|
|
436
|
+
from the key the Campaign Cart SDK actually sent. The SDK sends the page's
|
|
437
|
+
key as `Authorization` on every Campaigns API request. The browser pass
|
|
438
|
+
reads that header on each page it loads, compares it with the expected key
|
|
439
|
+
in memory and keeps only the outcome: `match` (pass) when every request
|
|
440
|
+
carried the expected key, `mismatch` (blocker) when any carried another.
|
|
441
|
+
The key itself is never recorded. The static read of a page's declarations
|
|
442
|
+
could not resolve most real pages: the starter templates' `config.js` opens
|
|
443
|
+
with `window.dataLayer = window.dataLayer || []` and
|
|
444
|
+
`window.nextReady = window.nextReady || []`, which the static grammar treats
|
|
445
|
+
as dynamic, so every starter page was left for manual review, and inline
|
|
446
|
+
scripts, `async` scripts and scripts from other origins left other pages
|
|
447
|
+
the same way. A page that sends no Campaigns API request, a run with no
|
|
448
|
+
single expected key, and `qa run` without `--browser` keep the static read.
|
|
449
|
+
- The QA verdict schema's page-binding evidence accepts
|
|
450
|
+
`observation: "sdk_request"` and the `sdk_request` source kind for that row.
|
|
451
|
+
Nothing is removed, so every verdict that validated before still does.
|
|
452
|
+
`docs/qa-and-test-orders.md` describes both observations.
|
|
453
|
+
- Ships the same-surface changes recorded since 1.49.0, each described in
|
|
454
|
+
its own section below: the agent context spells every command
|
|
455
|
+
`npx --no-install campaigns-os …` and carries the build skill's proof rule
|
|
456
|
+
(`+agent.1`); and the install-mode module drops a stale comment, with no
|
|
457
|
+
behavior change (`+agent.2`).
|
|
458
|
+
- Package and supported-surface version advance to 1.50.0 for the QA verdict
|
|
459
|
+
schema hash. The local setup install command pins 1.50.0. Bundled skills
|
|
460
|
+
carry revision `1.50.0+skills.1`, with each skill version advanced one
|
|
461
|
+
patch. The skill text is unchanged.
|
|
462
|
+
|
|
463
|
+
## [1.49.0+agent.2] - 2026-10-02
|
|
464
|
+
|
|
465
|
+
### Changed
|
|
466
|
+
|
|
467
|
+
- No command behaves differently. The install-mode module drops a trailing
|
|
468
|
+
comment that described `applyInvocationPrefix`, a function removed when
|
|
469
|
+
commands began to be spelled with their prefix at the source (`cmd()` and
|
|
470
|
+
`asInvocation` in the install-invocation module). Comment-only; every
|
|
471
|
+
message and every exit code is unchanged.
|
|
472
|
+
|
|
473
|
+
## [1.49.0+agent.1] - 2026-10-02
|
|
474
|
+
|
|
475
|
+
### Changed
|
|
476
|
+
|
|
477
|
+
- The agent context that `install-agent-context` and `tooling setup` write
|
|
478
|
+
(`agents/claude/CLAUDE.md`, `agents/codex/AGENTS.md`,
|
|
479
|
+
`agents/copilot/copilot-instructions.md`, `agents/cursor/campaigns-os.mdc`)
|
|
480
|
+
spells every command `npx --no-install campaigns-os …`, as the skills and
|
|
481
|
+
`AGENTS.md` do. It said `campaigns-os readback .`, `campaigns-os qa run …`
|
|
482
|
+
and so on, and fresh sessions ran them as written: "command not found"
|
|
483
|
+
where nothing is installed globally, and an older global copy instead of
|
|
484
|
+
the campaign's pinned one where something is. A test keeps bare commands
|
|
485
|
+
out of the agent context.
|
|
486
|
+
- The agent context carries the build skill's proof rule: reproduce the
|
|
487
|
+
source design's own proof and urgency elements as designed, and do not
|
|
488
|
+
remove, soften or flag them. The rule was only in the build and polish
|
|
489
|
+
skills, and sessions were still questioning or removing the merchant's
|
|
490
|
+
proof.
|
|
491
|
+
- An installed copy keeps the old text until `install-agent-context`
|
|
492
|
+
refreshes it.
|
|
493
|
+
|
|
494
|
+
## [1.49.0] - 2026-10-02
|
|
495
|
+
|
|
496
|
+
### Added
|
|
497
|
+
|
|
498
|
+
- `campaigns-os record theme --packet <p>` records an applied brand layer on
|
|
499
|
+
the Assembly Report, where the theme gate previously sent the operator to
|
|
500
|
+
edit `report.theme` by hand. It reads each built commerce page's stylesheet
|
|
501
|
+
links in document order. A page that loads `next-core.css` must load
|
|
502
|
+
`brand-theme.css` (or `checkout-brand.css`) after it, and that file must be
|
|
503
|
+
in the built output. A page that loads neither renders the design's own
|
|
504
|
+
markup and is left out, noted in the evidence. When every page passes and at
|
|
505
|
+
least one loads the brand layer, it writes `report.theme`: status `applied`,
|
|
506
|
+
`load_order` `after-next-core`, `css_path`, `commerce_pages` and one evidence
|
|
507
|
+
line per page, and clears any earlier theme waiver. Otherwise it is refused,
|
|
508
|
+
naming each page, and writes nothing. Build must be recorded for the current
|
|
509
|
+
output first. `--dry-run` runs every check and writes nothing.
|
|
510
|
+
- `campaigns-os record deploy --packet <p> --base-url <url>` records a local
|
|
511
|
+
preview (`deploy.target: local-serve`), where `next` previously sent the
|
|
512
|
+
operator to edit the packet and `stages.deploy` by hand. The URL must be a
|
|
513
|
+
loopback origin naming the campaign's route root. Every built page is
|
|
514
|
+
requested under it and must answer 2xx. It then writes the packet's
|
|
515
|
+
`deploy.preview_url` and `stages.deploy` completed, with the URL in
|
|
516
|
+
`outputs` and one evidence line per page. It is refused, writing nothing,
|
|
517
|
+
when any check fails, when polish is not recorded, when the built output
|
|
518
|
+
changed since build was recorded, or while the theme gate is blocked. The
|
|
519
|
+
requests stay on this machine. `--dry-run` runs every check, the requests
|
|
520
|
+
included, and writes nothing.
|
|
521
|
+
|
|
522
|
+
### Changed
|
|
523
|
+
|
|
524
|
+
- The theme gate's apply and load-order actions, the starter-palette notice,
|
|
525
|
+
the build prompt, the build and polish skills, `docs/brand-theme-bridge.md`
|
|
526
|
+
and `docs/build-packet.md` name `record theme` where they described a hand
|
|
527
|
+
edit of `report.theme`.
|
|
528
|
+
- `next`'s local-serve deploy action and deploy prompt,
|
|
529
|
+
`docs/build-packet.md` and `docs/qa-and-test-orders.md` name `record deploy`
|
|
530
|
+
where they described a hand edit of `deploy.preview_url` and
|
|
531
|
+
`stages.deploy`.
|
|
532
|
+
- `contracts/effects.v1.json` declares `record theme`, `record deploy` and
|
|
533
|
+
their `--dry-run` forms.
|
|
534
|
+
- The Build Packet schema's `assembly.template_family` accepts every family
|
|
535
|
+
the commerce surface catalog and the private template sources name:
|
|
536
|
+
`apollo`, `apollo-mv-single-step`, `arjuna` and `karna` join the enum, which
|
|
537
|
+
had fallen behind both. Nothing is removed, so every packet that validated
|
|
538
|
+
before still does.
|
|
539
|
+
- Package and supported-surface version advance to 1.49.0 for the effects
|
|
540
|
+
contract and Build Packet schema hashes. The local setup install command pins 1.49.0. Bundled skills
|
|
541
|
+
carry revision `1.49.0+skills.1`, with each skill version advanced one patch;
|
|
542
|
+
the build and polish skills also name `record theme`.
|
|
543
|
+
|
|
5
544
|
## [1.48.0] - 2026-10-02
|
|
6
545
|
|
|
7
546
|
### Changed
|
package/agents/claude/CLAUDE.md
CHANGED
|
@@ -6,7 +6,7 @@ Packet exists, read it and follow `next`. Check the loaded skill's bundle
|
|
|
6
6
|
revision and restart the session if it differs from the
|
|
7
7
|
project copy. Do not use private runtime source as the campaign's starting point.
|
|
8
8
|
|
|
9
|
-
To pick up an existing campaign, run `campaigns-os readback .` and `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
|
+
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
11
|
Core rules:
|
|
12
12
|
|
|
@@ -19,20 +19,21 @@ Core rules:
|
|
|
19
19
|
- 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.
|
|
20
20
|
- Preserve prepared source HTML for landing/presell pages when it is a real standalone design.
|
|
21
21
|
- For checkout/upsell/downsell/receipt, use starter-template commerce surfaces as SDK contract references: preserve required `data-next-*` controls and runtime wiring, but let the campaign/source own visual chrome, copy hierarchy, imagery, and brand layer.
|
|
22
|
+
- 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.
|
|
22
23
|
- If `.campaign-runtime/build-context.json` has `theme` or `.campaign-runtime/theme/theme-report.json` exists, use it as optional brand-theme evidence. A 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.
|
|
23
24
|
- Copy a starter template family atomically with dependent pages, `_includes/`, `_layouts/`, `assets/css/`, and `assets/js/`; do not copy only checkout/receipt pages.
|
|
24
25
|
- Resolve SDK routing meta tags to campaign-root paths such as `/campaign-slug/upsell/`; do not emit source filenames or unrooted `upsell/` values into built checkout/upsell pages.
|
|
25
26
|
- Default one-time `packages.prepurchase_*` order bumps to fixed quantity rather than syncing with the main bundle unless the spec explicitly requires sync.
|
|
26
27
|
- Record spec-driven removals, such as unavailable payment methods, so polish does not reintroduce them.
|
|
27
28
|
- Do not copy Olympus-style `shipping_methods` frontmatter into `shop-three-step`; it uses dynamic shipping through `window.next.getShippingMethods()`.
|
|
28
|
-
- Run build/lint checks and record evidence in the assembly report, then hand off to polish. 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 `campaigns-os polish capture --packet campaign-runtime.build.json --base-url <served-current-build-url>`.
|
|
29
|
-
- After that checkpoint clears, QA uses the Campaigns OS Node/npm runner: run `campaigns-os qa resolve --packet campaign-runtime.build.json`, then run `campaigns-os qa run --packet campaign-runtime.build.json --base-url <url> --browser --test-order common`.
|
|
30
|
-
- Typed-card test-order proof uses `campaigns-os qa run --test-order <common|checkout|decline|accept|both|full|explicit-path>` through the deployed checkout and rendered upsell controls. `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.
|
|
29
|
+
- Run build/lint checks and record evidence in the assembly report, then hand off to polish. 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>`.
|
|
30
|
+
- After that checkpoint clears, QA uses the Campaigns OS Node/npm runner: run `npx --no-install campaigns-os qa resolve --packet campaign-runtime.build.json`, then run `npx --no-install campaigns-os qa run --packet campaign-runtime.build.json --base-url <url> --browser --test-order common`.
|
|
31
|
+
- Typed-card test-order proof uses `npx --no-install campaigns-os qa run --test-order <common|checkout|decline|accept|both|full|explicit-path>` through the deployed checkout and rendered upsell controls. `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. `qa run` has no permission flag: coverage is its only control.
|
|
31
32
|
- 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.
|
|
32
33
|
- Test-order proof must use the canonical Playwright typed-card path through the tested checkout: select the rendered cart, fill customer/shipping fields, type the sandbox card into active hosted payment iframes, click the real submit button, then click rendered SDK upsell accept/decline controls and verify receipt/order evidence.
|
|
33
34
|
- 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.
|
|
34
35
|
- Do not use external browser skills, the SDK test-mode event, or hand-built backend API orders as launch proof. Those are diagnostic fallbacks only when explicitly requested.
|
|
35
|
-
- Test orders
|
|
36
|
+
- Test orders still land in the store as real orders that someone may have to cancel (global test cards bypass the gateway: no charge, no transaction, no merchant-specific routing to confirm). 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. Localhost on any port is a Campaigns App Development domain for SDK QA with analytics suppressed; non-localhost preview/production origins must be allowlisted for the campaign API key so the SDK loads — that is about SDK initialization, not test-order permission.
|
|
36
37
|
- 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.
|
|
37
38
|
|
|
38
39
|
Current source adapter: prepared HTML/assets (`html_funnel`).
|
package/agents/codex/AGENTS.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Use this context when working in a target campaign repo with Campaigns OS artifacts.
|
|
4
4
|
|
|
5
5
|
- Read `campaign-runtime.build.json` first.
|
|
6
|
-
- To pick up an existing campaign, run `campaigns-os readback .` and `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/`.
|
|
6
|
+
- 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
7
|
- If `.campaign-runtime/build-context.json` or `.campaign-runtime/assembly-report.json` exists, read them before editing campaign files.
|
|
8
|
-
- Run `campaigns-os doctor --packet campaign-runtime.build.json` before build work.
|
|
8
|
+
- Run `npx --no-install campaigns-os doctor --packet campaign-runtime.build.json` before build work.
|
|
9
9
|
- 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.
|
|
10
10
|
- Respect the selected template family's `agentContract`.
|
|
11
11
|
- Replace demo refs from CampaignSpec/API; do not preserve starter sample IDs.
|
|
@@ -13,15 +13,16 @@ Use this context when working in a target campaign repo with Campaigns OS artifa
|
|
|
13
13
|
- 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.
|
|
14
14
|
- Preserve prepared source HTML for landing/presell pages when it is a real standalone design.
|
|
15
15
|
- For checkout/upsell/downsell/receipt, use starter-template commerce surfaces as SDK contract references: preserve required `data-next-*` controls and runtime wiring, but let the campaign/source own visual chrome, copy hierarchy, imagery, and brand layer.
|
|
16
|
+
- 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.
|
|
16
17
|
- If `.campaign-runtime/build-context.json` has `theme` or `.campaign-runtime/theme/theme-report.json` exists, use it as optional brand-theme evidence. A 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.
|
|
17
18
|
- Copy a starter template family atomically with dependent pages, `_includes/`, `_layouts/`, `assets/css/`, and `assets/js/`; do not copy only checkout/receipt pages.
|
|
18
19
|
- Emit SDK routing meta tags as campaign-root paths such as `/campaign-slug/upsell/`.
|
|
19
20
|
- Default one-time `packages.prepurchase_*` bumps to fixed quantity unless the CampaignSpec explicitly requires package sync.
|
|
20
21
|
- Record spec-driven drops so polish does not reintroduce unsupported source elements.
|
|
21
22
|
- For `shop-three-step`, keep dynamic shipping via `window.next.getShippingMethods()` and do not add Olympus-style static `shipping_methods` frontmatter.
|
|
22
|
-
- Build hands off to polish. 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 `campaigns-os polish capture --packet campaign-runtime.build.json --base-url <served-current-build-url>`.
|
|
23
|
-
- After that checkpoint clears, QA uses the Campaigns OS Node/npm runner: run `campaigns-os qa resolve`, then `campaigns-os qa run --browser --test-order common` against the tested URL.
|
|
24
|
-
- Typed-card test-order proof uses `campaigns-os qa run --test-order <common|checkout|decline|accept|both|full|explicit-path>` through the tested checkout and rendered upsell controls.
|
|
23
|
+
- Build hands off to polish. 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>`.
|
|
24
|
+
- After that checkpoint clears, QA uses the Campaigns OS Node/npm runner: run `npx --no-install campaigns-os qa resolve`, then `npx --no-install campaigns-os qa run --browser --test-order common` against the tested URL.
|
|
25
|
+
- Typed-card 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. 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. Do not use external browser skills, the SDK test-mode event, or hand-built backend API orders as launch proof.
|
|
25
26
|
- 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.
|
|
26
27
|
- 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.
|
|
27
28
|
- 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.
|