@nextcommerce/campaigns-os 1.60.0 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +244 -0
- package/README.md +86 -438
- package/agents/claude/CLAUDE.md +20 -0
- package/agents/codex/AGENTS.md +19 -0
- package/agents/copilot/copilot-instructions.md +19 -0
- package/agents/cursor/campaigns-os.mdc +21 -0
- package/campaign-spec/README.md +7 -0
- package/campaign-spec/dist/analytics-vendors.d.ts +40 -0
- package/campaign-spec/dist/analytics-vendors.js +44 -0
- package/campaign-spec/dist/checkout-flow.d.ts +18 -0
- package/campaign-spec/dist/checkout-flow.js +28 -0
- package/campaign-spec/dist/index.d.ts +4 -2
- package/campaign-spec/dist/index.js +5 -1
- package/campaign-spec/dist/rules/analytics-contract-shape.d.ts +8 -0
- package/campaign-spec/dist/rules/analytics-contract-shape.js +39 -0
- package/campaign-spec/dist/rules/campaign-currencies.d.ts +29 -0
- package/campaign-spec/dist/rules/campaign-currencies.js +130 -0
- package/campaign-spec/dist/rules/checkout-path-has-packages.d.ts +31 -0
- package/campaign-spec/dist/rules/checkout-path-has-packages.js +79 -0
- package/campaign-spec/dist/rules/index.d.ts +2 -0
- package/campaign-spec/dist/rules/index.js +6 -0
- package/campaign-spec/dist/types.d.ts +43 -9
- package/compatibility.json +1 -1
- package/contracts/brand-theme-target-tokens.next-core.v0.json +95 -25
- package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
- package/contracts/commerce-surface-catalog.json +68 -61
- package/contracts/effects.v1.json +549 -165
- package/contracts/fixtures/runtime-recipe/accept/current.json +3 -0
- package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -0
- package/contracts/fixtures/runtime-recipe/dist-states.json +1 -1
- package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -0
- package/contracts/release-ledger.json +1767 -0
- package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -0
- package/contracts/supported-surface.json +10 -10
- package/contracts/template-brand-contract.shared-commerce.v0.json +23 -1
- package/docs/access-model.md +20 -0
- package/docs/brand-theme-bridge.md +62 -3
- package/docs/build-packet.md +456 -36
- package/docs/campaign-build-brief.md +16 -0
- package/docs/campaign-standardization-report.md +4 -4
- package/docs/campaigns-os-build-flow.md +112 -2
- package/docs/campaignspec-authoring-examples.md +141 -0
- package/docs/design-source-package.md +64 -8
- package/docs/effects.md +17 -9
- package/docs/entry-points.md +188 -0
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +42 -2
- package/docs/progress-snapshots.md +7 -4
- package/docs/qa-and-test-orders.md +197 -3
- package/docs/quickstart.md +438 -0
- package/docs/readback.md +154 -6
- package/docs/runtime-readiness.md +6 -3
- package/docs/sdk-storage-compatibility.md +4 -2
- package/docs/skills-revision.md +10 -10
- package/docs/source-adapters.md +213 -0
- package/package.json +10 -3
- package/schemas/campaign-design-source-package.v0.schema.json +8 -0
- package/schemas/campaign-runtime-build-context.v0.schema.json +9 -0
- package/schemas/campaign-runtime-build-packet.v0.schema.json +9 -0
- package/schemas/campaign-spec.v4.schema.json +19 -3
- package/schemas/campaign-spec.v5.schema.json +19 -3
- package/schemas/campaigns-os-readback.v2.schema.json +238 -1
- package/schemas/source-html-manifest.v0.schema.json +3 -0
- 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 -4
- package/skills/next-campaigns-os/SKILL.md +7 -4
- package/skills/next-campaigns-os-setup/SKILL.md +5 -3
- package/skills/next-campaigns-polish/SKILL.md +8 -10
- package/skills/next-campaigns-qa/SKILL.md +7 -4
- package/skills/next-campaigns-sdk-bump/SKILL.md +151 -25
- package/skills.json +11 -11
- package/src/brand-theme.mjs +415 -9
- package/src/brief-summary.mjs +6 -2
- package/src/browser-launch.mjs +2 -1
- package/src/build-brief.mjs +13 -3
- package/src/built-site-scope.mjs +2 -2
- package/src/campaign-workspace.mjs +288 -15
- package/src/change-scope.mjs +284 -0
- package/src/cli.mjs +358 -97
- package/src/commercial-journey.mjs +16 -3
- package/src/commercial-parity.mjs +15 -7
- package/src/content-residue.mjs +4 -2
- package/src/design-file-reference.mjs +93 -0
- package/src/design-source-package.mjs +91 -1
- package/src/design-source-publication.mjs +9 -6
- package/src/directory-lock.mjs +73 -19
- package/src/doctor/checks.mjs +87 -81
- package/src/doctor/ci.mjs +177 -0
- package/src/doctor/inspect.mjs +41 -6
- package/src/doctor/next-step.mjs +7 -0
- package/src/doctor/source-provenance.mjs +74 -0
- package/src/doctor-sidecar.mjs +3 -2
- package/src/evidence-debt.mjs +159 -0
- package/src/finding-cause.mjs +12 -11
- package/src/input-refresh.mjs +339 -32
- package/src/invocation.mjs +7 -1
- package/src/live-campaign-refs.mjs +7 -2
- package/src/local-preview-policy.mjs +35 -2
- package/src/page-kit-analytics-vendors.mjs +132 -0
- package/src/parity/compare.mjs +316 -0
- package/src/parity/design-access.mjs +54 -0
- package/src/parity/element-parity-record.mjs +569 -0
- package/src/parity/probe.mjs +205 -0
- package/src/parity/snapshot.mjs +110 -0
- package/src/png-header.mjs +87 -0
- package/src/polish-browser.mjs +189 -10
- package/src/polish-captures-record.mjs +52 -0
- package/src/polish-deadline.mjs +14 -0
- package/src/polish-gate.mjs +25 -6
- package/src/polish-node.mjs +81 -7
- package/src/polish-readability.mjs +221 -9
- package/src/polish-visual-fixtures.mjs +74 -0
- package/src/polish-visual.mjs +613 -0
- package/src/progress-node.mjs +3 -2
- package/src/qa-analytics-correctness.mjs +14 -2
- package/src/qa-analytics-parity.mjs +111 -6
- package/src/qa-browser.mjs +40 -4
- package/src/qa-commercial-parity.mjs +50 -3
- package/src/qa-node.mjs +235 -22
- package/src/qa-publish.mjs +9 -8
- package/src/qa-sidecar.mjs +16 -4
- package/src/qa-vendor-beacons.mjs +232 -0
- package/src/qa-vendor-endpoints.mjs +306 -0
- package/src/qc-accept.mjs +176 -6
- package/src/qc-check-registry.mjs +42 -2
- package/src/qc-results.mjs +477 -42
- package/src/readback.mjs +113 -21
- package/src/route-identity.mjs +10 -0
- package/src/run-record.mjs +18 -10
- package/src/runtime-state-ignore.mjs +6 -2
- package/src/sdk-attribute-index.mjs +11 -11
- package/src/sdk-markup.mjs +77 -2
- package/src/sdk-storage-compatibility.mjs +115 -6
- package/src/source-html-intake.mjs +15 -1
- package/src/source-html-manifest.mjs +7 -0
- package/src/source-html-server.mjs +129 -0
- package/src/spec-derive-campaign.mjs +216 -0
- package/src/spec-derive.mjs +473 -53
- package/src/spec-identity.mjs +14 -0
- package/src/stage-ledger.mjs +40 -1
- package/src/stage-record.mjs +100 -17
- package/src/target-lock.mjs +11 -1
- package/src/theme-gate.mjs +2 -2
- package/src/visual-diff.mjs +296 -0
- package/src/visual-reference.mjs +126 -0
package/AGENTS.md
CHANGED
|
@@ -124,7 +124,8 @@ precede argument refusal: `start`, `prepare-build`, `build`, `run start` and
|
|
|
124
124
|
before argv is refused, which is a declared effect of those commands and is
|
|
125
125
|
suppressed by `--no-write`. Commands implementing `--dry-run` also suppress
|
|
126
126
|
that closeout whenever the flag is present, including a value that will be
|
|
127
|
-
refused (such as `run end --dry-run yes`)
|
|
127
|
+
refused (such as `run end --dry-run yes`), and any `--flag=value` token, which
|
|
128
|
+
every command refuses, skips it too. Every remitting command's effect
|
|
128
129
|
declaration, when published, names its destination as open-world, and the agent onboarding skill
|
|
129
130
|
records an explicit telemetry choice before the first remitting command.
|
|
130
131
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,230 @@
|
|
|
2
2
|
|
|
3
3
|
Notable supported-surface changes are recorded here.
|
|
4
4
|
|
|
5
|
+
## [1.62.0] - 2026-10-30
|
|
6
|
+
|
|
7
|
+
This release makes the path from a Map to a working campaign shorter to start and cheaper to maintain. CampaignSpec validation catches a checkout nothing sells into and malformed currencies, and it carries the starter templates' analytics vendors. One project can hold several funnels. After handoff, `spec derive` keeps the spec in step with the repo's pages and the live campaign. A change to some pages' copy owes QA on those pages only. `qa run --test-order` holds test purchases back from the analytics vendors it can intercept (all of the template vendors except Northbeam), and `qa run --currency` blocks when the currency did not take. To take it, pin `@nextcommerce/campaigns-os@1.62.0` and refresh the installed skills to `1.62.0+skills.1`.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Several funnels in one project (#719).** The first funnel set up in a Page Kit project keeps `campaign-runtime.build.json` and `.campaign-runtime/`. Each later funnel gets `campaign-runtime-<route>.build.json` and keeps its Build Context, Assembly Report, doctor output, theme output, inputs, QA verdict sidecar and Run Records under `.campaign-runtime/funnels/<route>/`, which the packet records as `assembly.runtime_dir`. Every `--packet` command reads and writes that funnel's records.
|
|
12
|
+
- `readback` without `--packet` refuses, naming each packet and its route, when the project holds more than one funnel. `tooling status` then reads no packet pin.
|
|
13
|
+
- `prepare-build` no longer replaces another funnel's Build Packet, including one named with `--out`. `--force` replaces it on purpose: `prepare-build --out campaign-runtime.build.json --force` renames the route of a project's first funnel and keeps its records where they are. When a new route is set up beside an existing funnel, prepare-build prints a `Funnel:` line with the rename steps.
|
|
14
|
+
- Two funnels set up at the same moment no longer collide: the run that waited for the target lock stops and asks to be run again.
|
|
15
|
+
- Existing single-funnel projects read their records where they already are, with no setup rerun. The managed `.gitignore` block gains `.campaign-runtime/funnels/*/run-records/`.
|
|
16
|
+
- **`spec derive` after handoff (#721, #531).** A campaign is handed off once its deploy or its QA has completed. From then on derive adds a page the page tree builds that no spec page binds (id from the file name, type from its page-kit `page_type`; a checkout file with `next_step` is added as a `checkout_step` when it has a `step_number`, as a `checkout` that forwards to the Checkout in a v4 spec, and as a `select` page when it has none), removes a page whose built file is gone (matched by page id), and sets the routing on the edges that name those pages from the page files' `next_url` / `decline_url` / `next_step` frontmatter, rewriting the matching `sdk_hints.meta_tags` routing hint. A page file that is gone while a new file of the same page-kit `page_type` appears is read as a rename: neither change is applied and derive reports `page_renamed`, so the page's authored packages and offers are kept. Page order is reported as not derived, and so are an added page's packages (`page_packages_not_derived`): they are authored, and doctor blocks on `CheckoutPathHasPackages` or `UpsellHasPackages` until they are set.
|
|
17
|
+
- Once the campaign is built, derive makes the same read-only `GET /api/campaign` doctor makes and refreshes the fields the spec mirrors from the Campaigns App: each page package's name, price, recurring price, product, variant and availability, the offer records, and each page's offer copies. Which packages and offers a page carries stays authored, and a price never comes from the repo. `--no-live-refs` sends nothing; `--proxy-base` names the proxy. The effects contract declares the read on both `spec derive` rows and advances its `contract_version` to 1.3.0, because an existing row's declared effect changed.
|
|
18
|
+
- `record spec` binds a move of page routes: it re-projects every page's page-kit target in the packet and the Build Context and rewrites the Design Source Package's page surfaces and references. On a handed-off campaign it also binds a page added or removed, without intake. A respelling that projects to the same targets keeps the build, Polish and QA. A `record spec` that stopped part way is finished by the next one. It refuses a change that moves the route root or slug, leaves a routing hint stale, puts two pages on one target, or would rewrite a Design Source Package that prepare-build did not synthesize or that was edited since.
|
|
19
|
+
- Doctor blocks when a routing hint (`next-success-url`, `next-upsell-accept-url`, `next-upsell-decline-url`) names a route its page no longer has (`spec.routing_hint_stale`). `spec derive` and `record spec` use the same check.
|
|
20
|
+
- **Small changes owe small checks (#720).** After launch, a change that touches only some pages' HTML and leaves checkout pages, commerce markup, routes, scripts and the campaign's Page Kit config entry alone owes QA on those pages only, and Polish is advisory for it. Any other change still owes the full Polish and QA. A page-only change extends only a review that completed and that no brief or spec change has made owed since.
|
|
21
|
+
- `record build` keeps `stages.assembly.commerce_signature` (one hash per page over its commerce-bearing markup, plus the config entry) and `stages.assembly.build_changes`, each rebuild classified `page_only`, `commerce_affecting` or `unknown`.
|
|
22
|
+
- Readback's `evidence_debt` gives each owed stage a `change` object; Polish gains `advisory`, QA gains `scope` and `owed_pages`, and `clean` ignores advisory Polish. `doctor --ci` names the change it found and what each stage owes.
|
|
23
|
+
- New `qa run --packet <packet> --page <page_id>` (repeatable) checks only the named pages and places no test orders. It pays the page-only debt and keeps the purchase proof of the full run it extends. It refuses a commerce-affecting change, an unrecorded rebuild, a changed page left out, a last QA that did not complete, QA that a `qa_policy` or CampaignSpec change owes, and `--test-order` or `--vendor-beacons`.
|
|
24
|
+
- **Analytics vendors in the spec (#689).** The CampaignSpec types and both schemas add `analytics.vendors.<vendor>` for the starter templates' adapters (GA4, AppLovin Axon, Taboola, Triple Whale, TikTok, Northbeam, Snapchat, Pinterest) in the shape Map Builder saves: `enabled`, `id`, `platform`, `identityEnabled`, `allowedEvents`, `blockedEvents`. `AnalyticsContractShape` warns on an unknown vendor, an enabled vendor without an id, and event lists that are not arrays. `spec derive` copies each vendor's `_data/campaigns.json` id key (`ga4_id`, `triplewhale_name` and the rest) into `analytics.vendors.<vendor>.id` with the same empty-value and placeholder rules as GTM and Meta. The new advisory doctor check `page_kit.analytics_vendors` warns when the spec and `campaigns.json` disagree about a vendor or its id.
|
|
25
|
+
- **Test orders stay out of vendor reporting (#689).** `qa run --test-order` answers requests to the known beacon endpoints of GA4, Meta, TikTok, Snap, Pinterest, Taboola, Triple Whale and AppLovin Axon with a local empty response in every browser context it opens. Loader scripts still load, and those contexts block service workers. The new `browser-test-order:vendor-beacons` row records per vendor how many requests the page sent, whether one named a purchase, and the ids and events, and it lists configured vendors that sent nothing, that it cannot observe, or that are not intercepted (Northbeam, whose beacon host is unconfirmed). The row is evidence that the page sent them, never purchase proof, and it never blocks. `--vendor-beacons live` sends them to the vendors; it is refused without `--test-order`. `qa parity` orders are not intercepted.
|
|
26
|
+
- **`qa run --currency` checks the currency took (#713).** Each test order gets a `browser-order-currency:<path>` row that blocks when the order came out in another currency or recorded none. Commercial parity asks for expected totals in the run currency, and a calculate response in another currency is a `commercial-currency:<RUN>:<ANSWERED>` blocker. When the run currency is not the Map's, the fallback prices in the page source are left unresolved instead of compared. Runs without `--currency` are unchanged.
|
|
27
|
+
- **Polish layout conventions (#700).** At the mobile width, Polish warns (`layout.conventions`, acceptable with `checkpoint accept`) when a fixed or sticky CTA bar holds more than its one link or button (`floating_cta`), and when a purchase, accept or submit label is under 16px (`cta_label_size`). The thresholds live in a new `layout_conventions` block in the shared commerce brand contract. Readability records captured before this release show the check as not captured until the next `polish capture`.
|
|
28
|
+
- Skills: `next-campaigns-qa` covers default beacon interception, the `--currency` blockers and page-scoped QA; `next-campaigns-sdk-bump` the beacon default and the currency blockers; `next-campaigns-os` per-funnel records, `spec derive` after handoff and the page-only exception to full Polish and QA; `next-campaigns-os-setup` and `next-campaigns-build` setting up and building a later funnel; `next-campaigns-polish` the layout warnings. The QA and Polish skills read a later funnel's brief and report under its runtime directory. The installed agent context names the page-scoped QA path. Bundled skills advance to `1.62.0+skills.1`.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **A checkout something sells into (#711, #206).** New CampaignSpec rule `CheckoutPathHasPackages`: every path from an entry page to a Checkout must pass a page with a main-cart package entry (one marked neither `is_upsell` nor `is_order_bump`). Bump rows alone, and packages on upsell, downsell or thank-you pages, do not count. Paths follow routing fields, never page order or names. It is an error, or a warning when `build_scope.mode` is `partial`, and doctor reports it as `spec.validation`. The main-cart entry contract is in `docs/template-family-contracts.md`.
|
|
33
|
+
- **Currency codes (#714).** New CampaignSpec rule `CampaignCurrencies`: `campaign.currency` and every `campaign.available_currencies` entry must be a three-letter upper-case ISO 4217 code (an error, with the code to write for a near miss such as `"usd"`). A default currency missing from a non-empty `available_currencies` is a warning. The schemas and authoring guide say the spec owns `available_currencies`, listing every currency including the default; the Campaigns App's `additional_currencies` is not a spec field.
|
|
34
|
+
- The CampaignSpec schemas and authoring guide say that on an upsell or downsell page every package row is that page's offer, never an order bump, whatever `is_upsell` says (#710). Campaigns OS already read it this way, and tests now hold it.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Directory locks (#514): a command that finds the target lock or the progress allocation lock held by a live process of another Campaigns OS release refuses at once and names that process (`ELOCKFORMAT`), instead of racing it. Lock owner records carry `lock_format: 2`, so a holder from an earlier release is refused too; dead holders are still recovered. Two releases that start in the same instant are still not detected, so run one release against a target at a time. The holder also removes `.abandoned-<token>` directories left by an interrupted recovery, and an unreadable directory at the lock path is named as such.
|
|
39
|
+
- Every command refuses a `--flag=value` token, as it refuses any flag up front, and says to write the flag alone (an on/off flag) or `--flag value`; the message names the flag, never the value. Such a command does nothing first: the stale-session closeout that otherwise precedes argument refusal is skipped, as it is for a valued `--dry-run`, because the token's value (a `--packet`, `--target` or `--proxy-base`) is not read. Under `doctor --ci` the refusal is a usage error (`doctor.ci.usage`, exit 2). The shared parser read the token as an unknown key and dropped it, so `qa run --page=upsell1` ran a full QA and `--test-order=common` placed no orders. `standardize`, `page-kit sync` and `spec derive` already refused it as an unknown flag.
|
|
40
|
+
- 1.61.0 residuals (#707): the changed-page list survives `record build`; a reference refused for its location keeps its `location` on a stale-bound row; the readability reader passes an undefined `buildOutput` through unchanged.
|
|
41
|
+
|
|
42
|
+
## [1.61.0+agent.2] - 2026-10-29
|
|
43
|
+
|
|
44
|
+
The `next-campaigns-sdk-bump` skill (1.0.7) takes the findings from its third live run, the first on a static repository. Step 3 now has a table of known changes a bump can cross, and step 6 names the 3-D Secure test card. `sdk storage-check` no longer fails on large repositories, and its inventory error now says why. Refresh installed skills with `install-skills` to get it.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
The `next-campaigns-sdk-bump` skill (1.0.7, bundle `1.61.0+skills.2`) takes the third-run findings on campaigns-os#683:
|
|
49
|
+
|
|
50
|
+
- Step 3 has a table of known changes by version. 0.4.32: the checkout page no longer emits `order:completed` when it creates an order. The skill prefers the SDK's `dl_purchase`, which fires once per order; a capture that stays hand-wired moves to the first page after checkout, reads the order by the order's `?ref_id=`, and sends once per order, and step 6 reloads that page once with beacons blocked to prove it. 0.4.41: the card fields are Spreedly's hosted fields loaded by NEXT's payment script, so a page's own Spreedly `iframe-v1.min.js` tag, calls on the `Spreedly` global and CSS aimed at the v1 frame ids are removed or ported in the same commit as the pin move, after confirming the campaign has a payment key. 0.4.42 points at the `next:initialized` guard and 0.4.43 at the Shop Pay check. A page with a hand-written `modulepreload` list of SDK files rebuilds it from the target tag's `dist/` or removes it.
|
|
51
|
+
- Step 6 names the 3-D Secure test card from `docs/qa-and-test-orders.md`, links the platform's testing page, and asks the developer to confirm the gateway is in test mode before placing the order.
|
|
52
|
+
- Step 4 says that the old storage-check failure below means the pinned Campaigns OS is npm 1.61.0 or earlier, to update the pin, and not to run the check on a copied repository, which can lose tracked files.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- `sdk storage-check` lists only the tracked files under `--scope` (`git ls-files -- <scope>`), so a large repository no longer passes Node's 1 MiB default buffer. Before this, a repository with more than about 25,000 tracked paths stopped with `Cannot inventory tracked Git source files.` (#717)
|
|
57
|
+
- That error now reads `Cannot inventory tracked Git source files: <reason>`, with Git's first stderr line as the reason, or, when Git printed nothing, how it ended (its exit status, the signal that stopped it, or a spawn error code), or a request to narrow a scope whose list passes 256 MiB. `docs/sdk-storage-compatibility.md` says so.
|
|
58
|
+
|
|
59
|
+
## [1.61.0+agent.1] - 2026-10-24
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
The vendored starter catalog is re-synced to campaign-cart-starter-templates `5711e22` (was `b38343e`). That range carries:
|
|
64
|
+
- campaign-cart-starter-templates#246: tiered offers use one shipping method plus a free-shipping card coupon, in place of a separate free-shipping method. The CampaignSpec fixtures follow.
|
|
65
|
+
- campaign-cart-starter-templates#248: the Apollo Template Reference is re-stamped `sdk-0.4.43-shipping-coupon-tiers-2026-10-23`.
|
|
66
|
+
- campaign-cart-starter-templates#250: the MV families' `removeWhenUnsupported` names `variant_slots[].vouchers` for the tier coupon, as the bundle families do, in place of the removed free-shipping row.
|
|
67
|
+
- #247, #249 and #251: recorded SDK 0.4.43 verification evidence.
|
|
68
|
+
|
|
69
|
+
The certified-family fixtures are regenerated at the pin with page-kit 0.3.0, which is what the starter repository now pins. They were last rendered at `3987b18` with page-kit 0.2.0. The payment-chrome `asset_pin` moves to `5711e22`. Its five images have the same bytes there, so no hash changed. Two test files no longer depend on starter data that moved: the live-campaign drift tests give their saved Map its own second shipping method, and the Apollo Template Reference test reads the expected stamp from the catalog. The two payment-chrome tests pass again because the pin moved. The SDK pin and the support policy do not change.
|
|
70
|
+
|
|
71
|
+
## [1.61.0] - 2026-10-23
|
|
72
|
+
|
|
73
|
+
This release gathers the whole 1.60.0 line into one installable version and adds two things of its own. Intake now records a declared design file as the authority for a page, and Polish reports element-level differences between the source render and the built page as warnings an operator can review. To take it, pin `@nextcommerce/campaigns-os@1.61.0`, refresh the installed skills to `1.61.0+skills.1`, and run `polish capture` again before the next completed Polish record. Doctor cannot open design files yet, so a recorded file reads `unexercised` rather than verified.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- Publishes `1.60.0+agent.1`: `qa run --site` requests the campaign's pages under `/<slug>/` instead of joining each route straight onto `--base-url` (campaigns-os#683).
|
|
78
|
+
- Publishes `1.60.0+agent.2`: `analytics-correctness:tag:meta` passes when the declared Meta pixel initialises and tracks in the page even if no `facebook.com/tr` request is seen; a replaced `fbq` reads `unmeasured` (campaigns-os#686).
|
|
79
|
+
- Publishes `1.60.0+agent.3`: doctor's SDK markup check gains the `PAGE_TYPE_ATTRIBUTE` and `UPSELL_PAGE_TYPE_MISSING` advisories, because the SDK reads the page type only from `<meta name="next-page-type">` (campaigns-os#683).
|
|
80
|
+
- Publishes `1.60.0+agent.4`: the `next-campaigns-sdk-bump` skill takes the second-run findings on campaigns-os#683 (per-slug live status, the reload bar, the market pin, vendor beacon disclosure, up-front gate answers), and doctor's SDK attribute index moves to Campaign Cart v0.4.43.
|
|
81
|
+
- Publishes `1.60.0+agent.5`: `qa run`'s test customer and shipping address flags are documented and supported, and a non-USD `--currency` with no `--test-country` warns (campaigns-os#683).
|
|
82
|
+
- Publishes `1.60.0+agent.6`: `sdk storage-check` names an out-of-range `--target-sdk` up front and marks SDK prefix loops in its report (campaigns-os#683).
|
|
83
|
+
- Publishes `1.60.0+agent.7`: installed users receive the quickstart, access, source-adapter and CampaignSpec authoring guides, and the package check verifies documentation links and headings inside the installed package.
|
|
84
|
+
- Publishes `1.60.0+agent.8`: readback reports when a changed build requires Polish or QA again, and `doctor --ci` reports that evidence debt for campaign pull requests. Installed agent context describes revising a live campaign and renewing its evidence (campaigns-os#695, campaigns-os#699).
|
|
85
|
+
- Publishes `1.60.0+agent.9`: completed Polish requires current package captures, with a captured build screenshot for every planned route; source renders are captured beside them for comparison. The review handoff includes visual reference warnings and image differences for operator review; pixel scores do not decide fidelity (campaigns-os#696).
|
|
86
|
+
- Publishes `1.60.0+agent.10`: the brand theme carries the design source's fonts and button radius onto commerce pages. `theme generate` writes `brand-fonts.css` beside `brand-theme.css`, and `record theme` refuses a styled commerce page that doesn't load it (campaigns-os#703).
|
|
87
|
+
- Intake records a manifest `design_file` as the page's authority and its HTML export as derived from that file; a Figma spec `design_source` records that lineage only with figma-sections-export provenance that passes doctor's `source_html.producer_provenance` check without a waiver. This version cannot read design files, so `design.access` reports `unexercised` with `design_access_missing` for a recorded file and explains how to continue or compare the export and file by hand; a changed design file or conflicting declaration is listed for review; an absent declaration reports `design_reference_missing`, with recovery by restoring it or rerunning intake with `--force` to drop the recorded file (campaigns-os#697).
|
|
88
|
+
- Polish probes the source and built renders and reports element-level differences in geometry, typography, colour and copy as warnings an operator can review and accept; they never block Polish or change readiness (campaigns-os#697).
|
|
89
|
+
- The readback schema now describes the optional `evidence_debt` field, its `current`, `owed` and `unknown` stage statuses, reasons and changes against the retained assembly manifest. Any owed Polish or QA stage makes `clean` false; unknown debt still needs review when `clean` is true.
|
|
90
|
+
- Bundled skills advance to `1.61.0+skills.1`.
|
|
91
|
+
|
|
92
|
+
## [1.60.0+agent.10] - 2026-10-23
|
|
93
|
+
|
|
94
|
+
The generated brand theme now carries the design source's fonts and button radius onto the commerce pages, where before it carried only the colours. `theme generate` writes a second file, `brand-fonts.css`, beside `brand-theme.css`. Copy it into the campaign's `assets/css/` and load it on the same pages, because `record theme` refuses a styled commerce page that does not load it. A source that ships no font files of its own gets the same CSS as before.
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
Brand theme carries the design source's type onto commerce pages, not only its colours:
|
|
99
|
+
|
|
100
|
+
- `theme inspect` / `theme generate` read the `@font-face` rules the source ships and the families its headings, body copy and buttons use, plus the button `border-radius`. `var()` references resolve through custom properties on `:root`, `html`, `body` and the class a stylesheet scopes itself under (the importer's `.cc-import`). They map to next-core's `--_text---font-family--heading`, `--_text---font-family--primary` and `--radius-size--buttons` (new `typography` block in `contracts/brand-theme-target-tokens.next-core.v0.json`). Each family is followed directly by the generic the source declared for it. A family is mapped only when the source ships a face for it; one that can't ship is a `theme.typography.face_unavailable` warning and is listed in the report's `typography.unavailable`. The radius takes `0` or one to four lengths or percentages, lists any other button radius in `typography.radius_rejected`, and is mapped only alongside a family, so a source without brand faces generates the same CSS as before.
|
|
101
|
+
- The font-family tokens are emitted in a `:root, body` block, because next-core re-declares them on `body` at its 991, 767 and 479px breakpoints and a `:root`-only value held on desktop alone. `validateGeneratedCss` accepts that block.
|
|
102
|
+
- `theme generate` writes `.campaign-runtime/theme/brand-fonts.css` beside `brand-theme.css`: only `@font-face` rules for the mapped families, always with `font-display: swap`, every format of a face kept, and URLs relative to `assets/css/`. Remote, `data:`, root-relative, missing, or outside-root face files (checked on real paths, so symlinks out are caught) are left out with `theme.typography.face_src_dropped`. The theme report gains `typography`, and `generated.fonts_css_path` names the file.
|
|
103
|
+
- `record theme` refuses a styled commerce page that doesn't load a copy of the generated `brand-fonts.css` (found through the Build Context's `theme.generated.fonts_css_path`) from inside the built site, identical to the generated file, naming the page. The theme gate's generate/apply actions, the build guidance, `docs/brand-theme-bridge.md`, and the build (1.0.50) and polish (1.1.50) skills say to copy and load it. Polish now checks font parity at a mobile width as well as desktop.
|
|
104
|
+
- The skills bundle revision advances to `1.60.0+skills.5`, and every bundled skill moves one patch version.
|
|
105
|
+
|
|
106
|
+
## [1.60.0+agent.9] - 2026-10-23
|
|
107
|
+
|
|
108
|
+
`polish capture` now takes its own screenshots of every mapped page and of its source HTML, at desktop and mobile widths, and compares the pairs section by section as a review aid. A completed Polish record needs those captures, so after upgrading run `polish capture` again before `record polish`; screenshot paths written by hand no longer count. The comparison is a diagnostic only. It never passes, fails or blocks anything, and older Polish records are read as before.
|
|
109
|
+
|
|
110
|
+
### Changed
|
|
111
|
+
|
|
112
|
+
`polish capture` now takes its own full-page captures of each mapped page and of the page's source HTML at desktop and mobile widths, verifies the source screenshots recorded in the Design Source Package, and compares compatible pairs section by section as a review diagnostic with a heatmap. `record polish` now requires these package captures for a completed Polish, including at least one rendered build cell with a captured actual shot for every planned route. Agent-written screenshot paths no longer satisfy the screenshot check for a new record, so run `polish capture` again after upgrading. Polish records written before this version are read as before. The source HTML render runs offline: it reaches only a local read-only server, and requests, WebSocket connections and host-name lookups to anything else are blocked. Source screenshots or pages that are the build's own output are reported as self-referential warnings. Width or pixel-ratio mismatches are reported as unsupported, never resized. The comparison never passes, fails or blocks anything. `pngjs` and `pixelmatch` are new optional dependencies; without them captures are still taken and the comparison is listed as unavailable. Capture images are kept out of the repository by a `.gitignore` inside each capture folder.
|
|
113
|
+
|
|
114
|
+
The Polish skill is 1.1.49, bundle `1.60.0+skills.4`.
|
|
115
|
+
|
|
116
|
+
## [1.60.0+agent.8] - 2026-10-23
|
|
117
|
+
|
|
118
|
+
Readback now tells you whether the Polish and QA records still match the build on disk, in a new `evidence_debt` field: `current`, `owed` or `unknown`. `doctor --ci` reports the same debt as Markdown or JSON for a pull request check, with an example workflow under `docs/examples/`, and exits 3 when a stage is owed. Before revising a live campaign, read readback and renew any owed stage; the installed agent context now describes that procedure.
|
|
119
|
+
|
|
120
|
+
### Added
|
|
121
|
+
|
|
122
|
+
Readback's additive `evidence_debt` field and text section show whether Polish and QA bind to the build on disk: `current`, `owed`, or `unknown`. Changed pages and other changed files are listed against the retained assembly manifest. An empty page list does not clear an owed stage. Missing or unreadable output or a missing assembly fingerprint leaves stage debt unknown. Otherwise a lifecycle-recorded `required` stage is owed (reason `stage_required_by_build`, `stage_required_by_brief`, or `stage_required_by_spec` from `required_by`, and `stage_required` for an absent or unrecognized source), even without a stage fingerprint; other missing stage fingerprints leave debt unknown. A missing or unusable manifest leaves only page changes unknown; matching stage bindings remain current unless required, and differing bindings remain owed. This build comparison is independent of readback's time-based staleness. Either owed stage makes `clean` false (campaigns-os#699).
|
|
123
|
+
|
|
124
|
+
`doctor --ci --packet <packet> --no-live-refs` reports the same evidence debt as Markdown for a PR comment, or under `ci` with `--json`. It exits 0 when both stages are current, 3 when either is owed, 4 when debt cannot be determined, and 2 when the packet is missing or unreadable. Other doctor findings remain visible without changing the CI exit code. The check does not renew evidence or deploy (campaigns-os#695).
|
|
125
|
+
|
|
126
|
+
The workflow example at `docs/examples/campaign-repo-evidence-check.yml` installs locked dependencies, builds the campaign, runs the check and posts or updates one PR comment. Evidence findings are report-only by default; set the repository Actions variable `CAMPAIGNS_OS_EVIDENCE_CHECK` to `fail` to enforce them. Install and build failures still fail normally and replace the comment with a fixed "build failed; evidence not evaluated" message when doctor did not run. A comment-permission failure leaves the report in the job log (campaigns-os#695).
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
|
|
130
|
+
The installed agent context for all four supported harnesses gains a live-campaign revision section: read readback and `next` before editing, follow the Design Source Package, rebuild and record the build before capturing and recording Polish, run QA when owed, and show each changed page's design reference beside its preview in the PR. `install-agent-context --dry-run` previews each destination and its full content without writing files; `--json` carries the same preview (campaigns-os#699).
|
|
131
|
+
|
|
132
|
+
## [1.60.0+agent.7] - 2026-10-22
|
|
133
|
+
|
|
134
|
+
The npm package now ships the quickstart, access model, entry-point, source-adapter and CampaignSpec authoring guides, so links from the Build Packet and the README resolve inside an installed copy instead of pointing at files that are not there. The package check follows those links and their headings, so a guide missing from the package now fails the check. Runtime behaviour is unchanged.
|
|
135
|
+
|
|
136
|
+
### Fixed
|
|
137
|
+
|
|
138
|
+
The installed package now includes the existing quickstart, access model, entry-point, source-adapter and CampaignSpec authoring guides. Links from the Build Packet and README continue inside the package; repository-only evaluation, architecture and case-study references point to GitHub. The authoring guide links the shipped v5 schema and public multi-step examples, which remain repository test data.
|
|
139
|
+
|
|
140
|
+
The package check follows relative documentation links and checks destination headings against the extracted tarball, so a source-only guide or renamed anchor cannot leave installed users at a dead end. It ignores illustrative code and does not fetch external links. Runtime requirements and campaign behavior are unchanged.
|
|
141
|
+
|
|
142
|
+
## [1.60.0+agent.6] - 2026-10-22
|
|
143
|
+
|
|
144
|
+
`sdk storage-check` is clearer about two things. When the `--target-sdk` you ask about is outside the manifest's supported range, the report says so in its first line and the result stays `unknown`, so you know the scan did not speak for that version. Unknown findings inside a loop that scans storage keys by an SDK prefix are marked `[prefix loop: <prefix>]`, with one note explaining why they stay unknown. Exit codes and the commands you run are unchanged.
|
|
145
|
+
|
|
146
|
+
### Changed
|
|
147
|
+
|
|
148
|
+
`sdk storage-check` output, from Sam's findings on campaigns-os#683:
|
|
149
|
+
|
|
150
|
+
- When `--target-sdk` is outside the manifest's supported range, the human report's first line reads `checked against SDK <range>, not the requested target <x.y.z>`, the next line says the report does not speak for that target, and the count line repeats it. The result is still `unknown` and the exit status still 2. `--json` adds `targetCovered`.
|
|
151
|
+
- An unknown `dynamic-key`, `unsupported-storage-method` or `storage-object-escape` line inside a loop that matches the keys it reads from storage by a scoped SDK key's prefix (`k.indexOf('next-cart-state') === 0`, `k.startsWith(...)`) ends in `[prefix loop: <prefix>]`, and `--json` adds `prefixScan` to the finding. A key read from storage is a `k = sessionStorage.key(i)` variable, a for-of over `Object.keys(sessionStorage)` or for-in over `sessionStorage`, or the element parameter (the second for `reduce`) of a callback chained on `Object.keys(sessionStorage)`. Only the line where that key came from, or a line that reads that key by name, is marked; other storage use in the loop, such as passing `sessionStorage` to a function, is not. One note under the findings explains them: the loop survives the scope suffix, but on a shared origin the prefix also matches another campaign's copy, so the lines stay unknown. Where the manifest names a public store for the key, the note names it.
|
|
152
|
+
|
|
153
|
+
## [1.60.0+agent.5] - 2026-10-22
|
|
154
|
+
|
|
155
|
+
`qa run` has always accepted flags for the test customer and shipping address; they are now in `qa help` and the QA docs. Use `--test-country`, `--test-address1`, `--test-city`, `--test-province` and `--test-postal`, plus the name and phone flags, to place test orders against a non-US market; the default is a US address. A non-USD `--currency` with no `--test-country` now warns on stderr but still runs. A checkout with no province select for the chosen country still fails at that field, so those orders are placed by hand.
|
|
156
|
+
|
|
157
|
+
### Changed
|
|
158
|
+
|
|
159
|
+
`qa run`'s test customer and shipping address flags are now documented and supported (campaigns-os#683 review). The order runner has always read them; none was in the usage text or the QA docs. `--test-first-name`, `--test-last-name`, `--test-phone`, `--test-country`, `--test-address1`, `--test-city`, `--test-province` and `--test-postal` are listed in `qa help` with their defaults (a US address in Mountain View, CA), and `docs/qa-and-test-orders.md` gains a "Test customer and shipping address" section with a non-US example. The province select is a required step, so a checkout with no province select for the chosen country fails at that field; those orders are placed by hand.
|
|
160
|
+
|
|
161
|
+
A non-USD `--currency` on a `qa run` that places orders, with no `--test-country`, now prints a warning on stderr naming the address flags. The run is not refused. Only the missing flag is checked, since a currency such as EUR has many markets.
|
|
162
|
+
|
|
163
|
+
`qa run --site` lists `--currency <code>` in its usage line, and a test now proves it: the slug's entry page is fetched with `?currency=<CODE>` and the verdict records `evidence.currency` on that page's `http:` row.
|
|
164
|
+
|
|
165
|
+
The `next-campaigns-sdk-bump` skill (1.0.3, bundle `1.60.0+skills.3`) names the address flags in step 6 as the way to run non-US orders through the runner, with ordering by hand as the fallback.
|
|
166
|
+
|
|
167
|
+
## [1.60.0+agent.4] - 2026-10-22
|
|
168
|
+
|
|
169
|
+
The `next-campaigns-sdk-bump` skill (1.0.2) takes the findings from its second live run. It now reads each slug's live or retired status from the target's `CLAUDE.md` and asks when that is unclear, confirms the market before the first order, names the analytics vendors that will receive real purchase events from test orders, and asks its browser and install questions up front. Refresh installed skills with `install-skills` to get it. Doctor's SDK attribute index moves to Campaign Cart 0.4.43, which has the same `data-next-*` names as 0.4.42, so pages pinned to 0.4.43 pass the placeholder check.
|
|
170
|
+
|
|
171
|
+
### Changed
|
|
172
|
+
|
|
173
|
+
The `next-campaigns-sdk-bump` skill (1.0.2, bundle `1.60.0+skills.2`) takes the second-run findings on campaigns-os#683 and a review of them:
|
|
174
|
+
|
|
175
|
+
- Step 1 reads each slug's live or retired status from the target repository's `CLAUDE.md`, root first. A missing or unclear status is never read as live or retired: the skill lists those slugs and asks. Before any order, it shows the developer the live slugs and the orders planned on each, and orders only on the list they confirm.
|
|
176
|
+
- The reload bar in step 6 is one fresh load and five cached reloads of every SDK page, upsells included, with the counts in the hand-back. The receipt, and any page with a hand-wired purchase push or `order:completed` listener, is left out of the cached reloads, because upsell pages reload the order and can resend a real purchase on each load; purchase events are counted across the run.
|
|
177
|
+
- The first page carries `?currency=<main>&country=<main>`. The SDK picks the market by IP and never reads browser geolocation, so the geolocation step is gone. The skill says `?country=` needs `currencyBehavior: auto`, and that an unsupported value falls back without failing, so the shown market is confirmed before the first order. `qa run` takes `--currency <main>`, which pins only each funnel's entry page.
|
|
178
|
+
- `qa run`'s own test orders use a US shipping address by default, so for a non-US main market the orders are placed by hand, with both parameters on the first page of every new tab.
|
|
179
|
+
- Test orders send real purchase events to every analytics vendor the campaign configures unless beacons are blocked at the network, and `qa run` does not block them yet. The vendors, read from the slug's `_data/campaigns.json` ids and `config.js` on Page Kit or the page's inline config on a static funnel, are named in the test-order question, with a note that GTM-fired tags, hand-wired pixels and server-side conversions may also receive them, and again in the hand-back. `?ignore=true` is ruled out: it turns off the SDK's analytics, `dl_*` included, for the rest of the session.
|
|
180
|
+
- The install-browser, `--browser` and local-only answers are asked up front, so a no-packet bump does not skip the `qa run --browser` pass by default. `doctor --built` runs once per bumped slug and `qa run --site` once per live slug. `--family` must exactly match a template brand contract shipped in the package or a private family in `contracts/private-template-sources.json` (which needs its repository checked out or `PRIVATE_TEMPLATE_SOURCES_ROOT`), and `--slug` a key in `_data/campaigns.json`; otherwise the skill asks.
|
|
181
|
+
- Step 3 lists payment and express methods the range adds (0.4.43 adds Shop Pay), and step 6 starts and cancels each one the campaign offers.
|
|
182
|
+
- The skill asks before the first project-local install, pins a reviewed version whose bundle revision matches the skill, and says to expect and commit the `devDependencies` and `package-lock.json` change. In a static repo it never installs into the publish root. `tooling status` only reads the pin.
|
|
183
|
+
|
|
184
|
+
Doctor's SDK attribute index now names Campaign Cart v0.4.43 (`docs/build-packet.md` says so). Regenerated from the source at that tag, it has the same 149 `data-next-*` names as v0.4.42. The cart placeholder renderers are unchanged too, so pages pinned to 0.4.43 pass the placeholder check instead of reading unexercised.
|
|
185
|
+
|
|
186
|
+
## [1.60.0+agent.3] - 2026-10-21
|
|
187
|
+
|
|
188
|
+
Doctor now warns when a page sets `data-next-page-type` but has no `<meta name="next-page-type">`, and when an upsell page's meta is missing or is not `upsell`. The SDK reads the page type only from the meta tag, so without it an upsell page runs as a product page and records no upsell page view. Both are warnings and block nothing; add the meta tag the message names. `tooling status` also names which harnesses a skills refresh is for.
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
|
|
192
|
+
Doctor's SDK markup check gains two advisories about the page type (campaigns-os#683), on both `doctor --built` and packet doctor:
|
|
193
|
+
|
|
194
|
+
- `PAGE_TYPE_ATTRIBUTE`: a page sets `data-next-page-type` but has no `<meta name="next-page-type">`. The SDK never reads the attribute, so the page runs as the default `product` step, and an upsell page records no upsell page view. The message names the meta value to add, `upsell` on a page with an upsell offer, and never a page type the SDK does not have. Before, the attribute only appeared in the list of `data-next-*` names the SDK does not read.
|
|
195
|
+
- `UPSELL_PAGE_TYPE_MISSING`: a page with a `data-next-upsell` offer whose `next-page-type` meta is missing or is not `upsell`. The SDK records the upsell page view only from `<meta name="next-page-type" content="upsell">` and has no `downsell` page type, so reports showed the purchase with no upsell view before it.
|
|
196
|
+
|
|
197
|
+
Both are warnings; neither blocks. The certified templates raise neither.
|
|
198
|
+
|
|
199
|
+
### Changed
|
|
200
|
+
|
|
201
|
+
When `tooling status` asks for a skills refresh on some installed harnesses only, the action now names them (for example "for Codex and Shared agent skills; not needed in a session that uses another harness"), so a session in another harness does not take it as its own step (campaigns-os#683).
|
|
202
|
+
|
|
203
|
+
## [1.60.0+agent.2] - 2026-10-21
|
|
204
|
+
|
|
205
|
+
`qa run --browser` no longer fails a working Meta pixel. Headless Chromium can run `fbq('init')` and `fbq('track')` without ever sending the `facebook.com/tr` request, so QA now also watches the `fbq` calls in the page and passes the `analytics-correctness:tag:meta` row when the declared pixel initialises and tracks. If page code replaces `window.fbq` so QA cannot see the calls, the row fails as `unmeasured` instead of reporting a clean absence. A Meta Purchase still needs the real pixel request.
|
|
206
|
+
|
|
207
|
+
### Fixed
|
|
208
|
+
|
|
209
|
+
`analytics-correctness:tag:meta` now passes when the declared Meta pixel initialises and tracks in the page, even if the browser never requests `facebook.com/tr` (campaigns-os#686). Headless Chromium can run `fbq('init')` and `fbq('track')` with fbevents.js loaded and still send no pixel request, so `qa run --browser` blocked campaigns whose pixel works in real browsers. QA now also watches `fbq` calls in the page: a pixel id counts once it is initialised and a track call follows on the same page.
|
|
210
|
+
|
|
211
|
+
If page code replaces `window.fbq` so QA can no longer see its calls, and no matching pixel request was seen, the row still fails but now says `unmeasured` and carries `evidence.reason: fbq_observer_disarmed`, instead of reporting a clean absence.
|
|
212
|
+
|
|
213
|
+
These are unchanged:
|
|
214
|
+
- A pixel that initialises but never tracks, or a different pixel id, still fails the row.
|
|
215
|
+
- An in-page `fbq('track', 'Purchase')` is not a Meta Purchase fire and supplies no CAPI dedup key; both still need the pixel request.
|
|
216
|
+
|
|
217
|
+
## [1.60.0+agent.1] - 2026-10-20
|
|
218
|
+
|
|
219
|
+
`qa run --site` now requests a campaign's pages under `/<slug>/`, as the deployed site serves them. Before this fix it joined each route straight onto `--base-url`, so every page returned 404. If a site QA run on 1.60.0 showed nothing but 404s, run it again on this version. The flags are unchanged.
|
|
220
|
+
|
|
221
|
+
### Fixed
|
|
222
|
+
|
|
223
|
+
`qa run --site <repo> --base-url <site origin> --slug <slug>` now requests the campaign's pages under `/<slug>/` (campaigns-os#683). Before, it joined each page route straight onto `--base-url`, so it requested `/checkout/` rather than `/<slug>/checkout/` and every page returned 404. The slug is added the same way packet QA adds it: a base URL that already ends in the slug is used as given, and a slug found from the single campaign under `_site/` is added too.
|
|
224
|
+
|
|
5
225
|
## [1.60.0] - 2026-10-20
|
|
6
226
|
|
|
227
|
+
This release packages the ten `1.59.0+agent` sections below. The largest change for a campaign folder is next-campaign-page-kit 0.3.0: the first build on it can change the build fingerprint with no source change, so run `record build` again and expect Polish, deploy and QA to be owed. `install-skills` now also installs `next-campaigns-sdk-bump`, the procedure for moving a campaign to a later 0.4.x Campaign Cart, and that skill takes the lessons from its first live bump. Pin `@nextcommerce/campaigns-os@1.60.0` and refresh skills to `1.60.0+skills.1`.
|
|
228
|
+
|
|
7
229
|
### Changed
|
|
8
230
|
|
|
9
231
|
- Publishes `1.59.0+agent.4`: the build-flow doc and quickstart describe the Campaigns App's offer-first setup.
|
|
@@ -20,6 +242,8 @@ Notable supported-surface changes are recorded here.
|
|
|
20
242
|
|
|
21
243
|
## [1.59.0+agent.13] - 2026-10-19
|
|
22
244
|
|
|
245
|
+
A CampaignSpec-only change no longer throws away a Polish review of pages it did not touch. When you re-record the build with `record build --deviation-reason` and the output is identical to what Polish reviewed, the completed Polish record is restored instead of staying owed. QA is still owed, because the spec changed. A presentation change or a different build still owes a new Polish.
|
|
246
|
+
|
|
23
247
|
### Fixed
|
|
24
248
|
|
|
25
249
|
A CampaignSpec-only change no longer throws away a Polish review of pages it did not change (campaigns-os#668). Before, `record build --deviation-reason` recorded the build, but Polish stayed owed after the re-intake (or `record spec`). The next `qa run` then stopped on `polish.evidence_missing`, and the agent had to retake the same screenshots and re-record the same findings.
|
|
@@ -36,6 +260,8 @@ These are unchanged:
|
|
|
36
260
|
|
|
37
261
|
## [1.59.0+agent.12] - 2026-10-19
|
|
38
262
|
|
|
263
|
+
`install-skills` now installs a new skill, `next-campaigns-sdk-bump`: the procedure for moving a campaign from one 0.4.x Campaign Cart version to a later one, on page-kit and static repos. It finds every pin, reads the release diff against the campaign's code, runs `sdk storage-check` and doctor, and proves the bump on a preview with approved test orders. It stops at a 0.3.x pin or the legacy Campaigns script, because those are migration work. Run `install-skills` to get it; the bundle is `1.59.0+skills.4`.
|
|
264
|
+
|
|
39
265
|
### Added
|
|
40
266
|
|
|
41
267
|
`install-skills` now installs `next-campaigns-sdk-bump`, so an agent told "bump this campaign to SDK 0.4.x" has a shipped procedure to follow instead of one written into the ticket (campaigns-os#677). It covers a 0.4.x to later 0.4.x Campaign Cart bump on page-kit and static repos, and it stops at a 0.3.x pin or the legacy Campaigns script, because moving those is migration work. The steps:
|
|
@@ -51,18 +277,24 @@ It adds no write, send or order capability. Bundled skills advance to `1.59.0+sk
|
|
|
51
277
|
|
|
52
278
|
## [1.59.0+agent.11] - 2026-10-19
|
|
53
279
|
|
|
280
|
+
Repository CI workflows move to newer versions of three GitHub Actions. This changes nothing in the published package, and there is nothing to do.
|
|
281
|
+
|
|
54
282
|
### Changed
|
|
55
283
|
|
|
56
284
|
Repository workflows move `actions/create-github-app-token` from 3.2.0 to 3.3.0, `actions/upload-artifact` from 7.0.1 to 7.0.2 and `actions/download-artifact` from 8.0.1 to 8.0.2 (campaigns-os#679). This changes repository CI only, and the published package is unchanged.
|
|
57
285
|
|
|
58
286
|
## [1.59.0+agent.10] - 2026-10-19
|
|
59
287
|
|
|
288
|
+
The lockfile moves Playwright to 1.64.1 and acorn to 8.19.0, both inside the ranges `package.json` already declared, so a fresh install resolves the same versions. Playwright drives `qa run --browser` and `polish capture`; acorn parses page scripts for doctor's script-syntax check and now rejects one more malformed async arrow-function shape. There is nothing to do unless doctor newly reports a syntax error in a page script.
|
|
289
|
+
|
|
60
290
|
### Changed
|
|
61
291
|
|
|
62
292
|
The lockfile moves Playwright from 1.63.0 to 1.64.1 and acorn from 8.18.0 to 8.19.0 (campaigns-os#675). Both stay within the ranges `package.json` already declares, so an installed toolkit resolves the same versions on a fresh install. Playwright drives `qa run --browser` and polish capture. acorn parses page scripts for doctor's `built_output.script_syntax` check, and 8.19.0 now rejects additional subscripts before the arrow in async arrow functions.
|
|
63
293
|
|
|
64
294
|
## [1.59.0+agent.9] - 2026-10-19
|
|
65
295
|
|
|
296
|
+
The vendored starter-template catalog moves to campaign-cart-starter-templates `3987b18`. Step and select pages prefetch `next_step` instead of the post-payment URL, and the promo banner is rendered at build time from frontmatter, so the `<promo-banner>` web component and its layout shift are gone. The SDK pin stays 0.4.42 and the CampaignSpec fixtures do not change.
|
|
297
|
+
|
|
66
298
|
### Changed
|
|
67
299
|
|
|
68
300
|
The vendored starter catalog is re-synced to campaign-cart-starter-templates `3987b18` (was `d5ff501`). That range carries:
|
|
@@ -74,6 +306,8 @@ The certified-family fixtures are regenerated at the pin with page-kit 0.2.0, wh
|
|
|
74
306
|
|
|
75
307
|
## [1.59.0+agent.8] - 2026-10-19
|
|
76
308
|
|
|
309
|
+
Campaigns OS now works with next-campaign-page-kit 0.3.0 and keeps 0.2.x targets working. The setup docs pin `next-campaign-page-kit@0.3.0`, and doctor reads 0.3.0's new `assetWarnings`, so an `.html` file under a campaign's `assets/` that page-kit no longer builds is reported instead of 404ing silently on the built site. The first build on 0.3.0 can change the build fingerprint with unchanged source: run `record build` again afterwards and expect Polish, deploy and QA to be owed.
|
|
310
|
+
|
|
77
311
|
### Changed
|
|
78
312
|
|
|
79
313
|
Campaigns OS adopts next-campaign-page-kit 0.3.0 and keeps 0.2.x targets working. The new-folder installs in `docs/local-setup.md`, the quickstart and the README pin `next-campaign-page-kit@0.3.0`; the quickstart and README installed it unpinned, and `docs/local-setup.md` pinned 0.2.0. The example target declares page-kit as a runtime dependency at that pin.
|
|
@@ -88,6 +322,8 @@ The first build on page-kit 0.3.0 can change the build fingerprint with unchange
|
|
|
88
322
|
|
|
89
323
|
## [1.59.0+agent.7] - 2026-10-15
|
|
90
324
|
|
|
325
|
+
`run status` now always points to `next` as the next command, so a finished-looking report no longer sends you to `run end` before `next` has reached done. `next` decides when the campaign is done and names `run end` itself. The output of `next` and doctor is otherwise unchanged.
|
|
326
|
+
|
|
91
327
|
### Fixed
|
|
92
328
|
|
|
93
329
|
`run status` now always names `next` as the next command: `progress.next_command` is `campaigns-os next --packet <packet> --json`. Before, once every stage status the Assembly Report records read completed or skipped, it named `run end` even when `next` had not reached done: after a CampaignSpec edit with no `record spec` (`next` answers build), on a report written before input stamps existed, and after a rebuild with no `record build`. `next` decides whether the campaign is done, and once it is, with a run session active, it names `run end` as a required action. `run status` stays read-only, and `progress.incomplete_stages` still lists the recorded statuses (campaigns-os#673).
|
|
@@ -98,6 +334,8 @@ The first build on page-kit 0.3.0 can change the build fingerprint with unchange
|
|
|
98
334
|
|
|
99
335
|
## [1.59.0+agent.6] - 2026-10-15
|
|
100
336
|
|
|
337
|
+
Two fixes to how the toolkit binds QA and Polish to a build. The progress snapshot now reads the QA record's `qc_build_fingerprint`, so a `qa run` without `--browser` no longer shows `qa.binding: unconfirmed` for a build it did test. The polish gate reads the recorded build only from `stages.assembly.build_fingerprint`, and a report that carries only a legacy fingerprint field now gets a clear `polish.build_fingerprint_missing` from doctor instead of contradictory messages. `npm run smoke:polish-capture` passes again.
|
|
338
|
+
|
|
101
339
|
### Fixed
|
|
102
340
|
|
|
103
341
|
The progress snapshot binds a QA record to its build through the field `next`, the QA gate and the Run Record already read: `stages.qa.evidence.qc_build_fingerprint`, falling back to `source_build_fingerprint`. It used to read only `source_build_fingerprint`, which QA writes only when the placeholder-text gate records an outcome. A `qa run` without `--browser`, or with that gate skipped, therefore showed `qa.binding: "unconfirmed"` and a qa stage row with `build_binding: "unconfirmed"` and no fingerprint, although QA was recorded for the current build. Records that bind no build, or a different one, still read `unconfirmed`.
|
|
@@ -108,18 +346,24 @@ The polish gate reads the recorded build only from `stages.assembly.build_finger
|
|
|
108
346
|
|
|
109
347
|
## [1.59.0+agent.5] - 2026-10-15
|
|
110
348
|
|
|
349
|
+
The hosted preview path is now documented the way `next` has run it since 1.59.0: record the hosted deploy with `record deploy --base-url <route root>` before QA, for both deploy targets. The Polish skill, the Build Packet doc and the README no longer say a hosted preview URL satisfies the deploy stage on its own. A forced `next deploy` or `next qa` on a hosted packet whose preview URL is loopback or production now asks for `qa policy set --preview-url` first. Bundled skills advance to `1.59.0+skills.2`.
|
|
350
|
+
|
|
111
351
|
### Fixed
|
|
112
352
|
|
|
113
353
|
The hosted all-template guidance now matches what `next` has done since 1.59.0, where a hosted preview records its deploy with `record deploy` before QA. The Campaign Polish skill, `docs/build-packet.md` and the README no longer say that the hosted preview URL satisfies the deploy stage or that `record deploy` takes only a loopback route root; they name `record deploy --base-url <route root>` for both deploy targets and leave the order to `next`. A forced `next deploy` or `next qa` on an all-template hosted packet whose preview URL is loopback or the production page now prompts for `qa policy set --preview-url`, as its next actions and doctor already did and as an unset preview URL already did, instead of the generic deploy prompt or a QA command against that URL; the QA prompt then sends the agent to `next`, which records the deploy before QA. The done prompt names `record deploy` for both deploy targets in place of an instruction to record the hosted URL by hand. Bundled skills advance to `1.59.0+skills.2`.
|
|
114
354
|
|
|
115
355
|
## [1.59.0+agent.4] - 2026-10-14
|
|
116
356
|
|
|
357
|
+
The build-flow doc and the quickstart now describe campaign setup in the Campaigns App the way the dashboard does it: create the campaign, then add Offers on its Offers tab. Selecting store products in an Offer creates the campaign's products (packages in the API) at their store price, and the Packages tab is now called Products. Do not create separate `1x`, `2x` and `3x` packages for tier pricing. This is documentation only.
|
|
358
|
+
|
|
117
359
|
### Changed
|
|
118
360
|
|
|
119
361
|
The build-flow doc and the quickstart describe the Campaigns App's offer-first setup: Create Campaign, then Add Offer on the campaign's Offers tab. Selecting store products in an Offer creates one campaign product (a package in the API) per variant at its store price when the Offer is saved, and later Offers reuse it. The dashboard's Packages tab is now Products. The rule against separate `1x` / `2x` / `3x` packages for tier pricing is unchanged, and campaigns set up over the Admin API still create packages before Offers.
|
|
120
362
|
|
|
121
363
|
## [1.59.0] - 2026-10-09
|
|
122
364
|
|
|
365
|
+
This release publishes the 1.58.0 line and adds hosted deploy recording. `record deploy --base-url <https route root>` now works for a hosted preview: it requests every built page, requires HTTP 200, and checks that every script and stylesheet the pages load is byte-identical to the built output. The hosted all-template path no longer skips the deploy stage; `next` hands you `record deploy` and then QA. Pin `@nextcommerce/campaigns-os@1.59.0` and refresh skills to `1.59.0+skills.1`.
|
|
366
|
+
|
|
123
367
|
### Changed
|
|
124
368
|
|
|
125
369
|
- Publishes the untagged `1.58.0` change: multi-step checkout frontmatter follows the starter-template `next_step` contract (campaigns-os#641).
|