@nextcommerce/campaigns-os 1.61.0 → 1.63.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 +127 -0
- package/README.md +86 -438
- package/agents/claude/CLAUDE.md +9 -4
- package/agents/codex/AGENTS.md +8 -4
- package/agents/copilot/copilot-instructions.md +8 -4
- package/agents/cursor/campaigns-os.mdc +10 -4
- 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 +30 -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 +3 -0
- package/campaign-spec/dist/rules/index.js +9 -0
- package/campaign-spec/dist/rules/package-currency-prices.d.ts +29 -0
- package/campaign-spec/dist/rules/package-currency-prices.js +137 -0
- package/campaign-spec/dist/types.d.ts +59 -9
- package/compatibility.json +1 -1
- package/contracts/commerce-surface-catalog.json +59 -53
- package/contracts/effects.v1.json +549 -165
- package/contracts/fixtures/runtime-recipe/accept/current.json +4 -0
- package/contracts/fixtures/runtime-recipe/accept/minimal.json +4 -0
- package/contracts/fixtures/runtime-recipe/dist-states.json +1 -1
- package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +4 -0
- package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +4 -0
- package/contracts/release-ledger.json +1260 -0
- package/contracts/runtime-recipe.campaigns-os-node-v1.json +4 -0
- package/contracts/supported-surface.json +8 -8
- package/contracts/template-brand-contract.shared-commerce.v0.json +23 -1
- package/docs/build-packet.md +430 -37
- package/docs/campaign-standardization-report.md +4 -4
- package/docs/campaigns-os-build-flow.md +54 -3
- package/docs/campaignspec-authoring-examples.md +59 -4
- package/docs/design-source-package.md +18 -6
- package/docs/effects.md +17 -9
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +2 -0
- package/docs/progress-snapshots.md +7 -4
- package/docs/qa-and-test-orders.md +147 -1
- package/docs/readback.md +40 -5
- package/docs/runtime-readiness.md +7 -3
- 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-context.v0.schema.json +9 -0
- package/schemas/campaign-runtime-build-packet.v0.schema.json +9 -0
- package/schemas/campaign-spec.v4.schema.json +34 -3
- package/schemas/campaign-spec.v5.schema.json +34 -3
- package/schemas/campaigns-os-readback.v2.schema.json +62 -1
- package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +3 -3
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +4 -3
- package/skills/next-campaigns-os/SKILL.md +6 -4
- package/skills/next-campaigns-os-setup/SKILL.md +5 -3
- package/skills/next-campaigns-polish/SKILL.md +5 -4
- package/skills/next-campaigns-qa/SKILL.md +7 -4
- package/skills/next-campaigns-sdk-bump/SKILL.md +42 -9
- package/skills.json +11 -11
- package/src/brand-theme.mjs +2 -1
- package/src/build-brief.mjs +4 -1
- package/src/campaign-workspace.mjs +288 -15
- package/src/change-scope.mjs +284 -0
- package/src/cli.mjs +308 -86
- package/src/commercial-journey.mjs +16 -3
- package/src/commercial-parity.mjs +15 -7
- package/src/content-residue.mjs +4 -2
- package/src/design-source-package.mjs +36 -0
- package/src/design-source-publication.mjs +9 -6
- package/src/directory-lock.mjs +73 -19
- package/src/doctor/checks.mjs +79 -7
- package/src/doctor/ci.mjs +75 -10
- package/src/doctor/inspect.mjs +23 -6
- package/src/doctor/next-step.mjs +7 -0
- package/src/doctor-sidecar.mjs +3 -2
- package/src/evidence-debt.mjs +47 -7
- 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/polish-browser.mjs +3 -1
- package/src/polish-readability.mjs +221 -9
- package/src/polish-visual.mjs +9 -2
- package/src/progress-node.mjs +3 -2
- package/src/qa-analytics-parity.mjs +17 -1
- package/src/qa-browser.mjs +40 -4
- package/src/qa-commercial-parity.mjs +50 -3
- package/src/qa-node.mjs +196 -16
- 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 +29 -1
- package/src/qc-check-registry.mjs +5 -1
- package/src/qc-results.mjs +73 -26
- package/src/readback.mjs +58 -10
- 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-storage-compatibility.mjs +21 -2
- package/src/source-html-intake.mjs +15 -1
- 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 +58 -13
- package/src/target-lock.mjs +11 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-polish
|
|
3
|
-
version: 1.1.
|
|
3
|
+
version: 1.1.54
|
|
4
4
|
description: Run the visual/runtime polish pass after build and before QA for a Campaigns OS campaign.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.63.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.63.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -59,7 +59,7 @@ Responsibilities:
|
|
|
59
59
|
- Scan **visible** rendered text inside the family's content/commerce surfaces (the selectors enumerated in `contracts/template-brand-contract.<family>.v0.json`) for placeholder/residue copy the build should have replaced — the *literal starter defaults*: lorem-ipsum, the unmodified starter headings (`Product Name` / `Package Title` / `Your headline`), `[VERIFY …]` author notes, `TODO` markers. Match the literal starter strings, not any authored copy that merely contains those words, and skip `<script>` / `<style>` / JSON-LD / `data-*` attributes. Treat a surviving literal starter default on a content/commerce surface as a polish blocker — replace it from the prepared source / CampaignSpec; do not draft substitute copy (if the design's authored copy is genuinely missing, flag it rather than invent it). This is *copy* residue, complementary to the computed-style / asset residue gated by `next-campaigns-qa` + the brand contract — not a duplicate of it.
|
|
60
60
|
- Flag template *defaults* left where they disagree with the prepared design — e.g. the same benefit icon repeated across a grid *when the design uses distinct icons*, or a guarantee badge/term that disagrees with the design — as polish defects, not just logos. Judge against the prepared source, not taste: copy or imagery the source/CampaignSpec does not supply (e.g. a placeholder testimonial name/quote/role) is residue; "looks generic" on its own is not. Copy the source does supply, including its proof and urgency elements (reviews, "Verified Purchase" labels, recent-purchase popups, stock counters, countdowns, guarantees), is the merchant's content: keep it as designed and do not record it as an issue or an unconfirmed claim.
|
|
61
61
|
- **Brand-bleed (cloned-source de-brand) pass.** When a campaign is cloned from a proven sibling, the sibling's brand defaults ride along. Inspect the built pages and assets for residual cross-brand bleed and clear it before recording: (1) a residual promo/sale banner or coupon code/copy from the source campaign (including a baked-in *fake* code); (2) a prior-campaign / sibling favicon left in place; (3) scaffold or non-design fonts the design did not specify (e.g. starter `Plus Jakarta`); (4) hardcoded non-token colors — any brand color literal that should be a token, such as next-core's `#C670FE` "Most Popular" pill. Clear each from the prepared source / CampaignSpec and brand theme (tokens, not literals); flag — do not invent — anything the design genuinely doesn't supply. Treat surviving bleed as a polish blocker. This complements the favicon/logo and copy-residue checks above; it is the cross-brand contamination angle, not a duplicate.
|
|
62
|
-
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour.
|
|
62
|
+
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour. For a later funnel in a multi-funnel project, read the same files under its own `assembly.runtime_dir` (`.campaign-runtime/funnels/<route>/`); the paths `next` prints are already the right ones.
|
|
63
63
|
- Read the assembly report decisions before polishing. Do not reintroduce source-HTML elements that build intentionally dropped because CampaignSpec/API did not support them, such as unavailable payment methods.
|
|
64
64
|
- **Remove or rename a contract-listed payment-chrome asset; never edit one in place.** The assets named in `contracts/template-brand-contract.<family>.v0.json` under `default_residue.payment_chrome.assets` are keyed by QA on the *referenced basename*, not on their contents. Stripping the unsupported marks from inside a shared file such as `upsell-payment-logos.svg` leaves the reference in place, so QA reports residue for an asset that no longer carries any — and on 2026-09-06 the repair loop's remedy for that report deleted a cards-only trust strip that was correct. Delete the asset, or write a new one under a new name and repoint the reference. QA downgrades an edited-in-place asset to `manual_review` rather than a blocker, but that is a safety net for a mistake, not the supported way to do this.
|
|
65
65
|
- Preserve existing `report.theme` data. If polish changes generated theme CSS, load order, commerce-page coverage, theme warnings, or the first repair-loop defect, update the Assembly Report `theme` block rather than leaving stale evidence.
|
|
@@ -95,6 +95,7 @@ Responsibilities:
|
|
|
95
95
|
against the packet's production URL keeps the checkpoint blocked.
|
|
96
96
|
- In the handoff, `parity.element` rows are element differences to review or accept. `design.access` unexercised means the file was not read: compare by hand. A `design.access` review row means a changed, missing or conflicting design file: fix the declaration or rerun intake with `--force`. These rows never block Polish.
|
|
97
97
|
- When a readability warning appears, report it with its colours, ratio, requirement and pages. Offer the operator options inside the brand palette (a darker or lighter shade of the same hue, the palette's text colour, or a larger, bold label where the design allows). Do not recolour the merchant's design until the operator chooses. Accept a warning only with the refs, reason and name the operator gives you at the QC handoff.
|
|
98
|
+
- A `layout.conventions` warning is a mobile layout convention: `floating_cta` means a fixed or sticky CTA bar holds more than its one control (the row names the bar and the other text), and `cta_label_size` means a CTA label is under 16px (the row gives the measured size). Report it with the page and element, offer the fix (move the extra text out of the bar, or raise the label size where the design allows), and leave the merchant's copy alone. Accept it only with the refs, reason and name the operator gives you. These rows never block Polish.
|
|
98
99
|
- Record Polish as `completed`, `skipped`, or `blocked` with
|
|
99
100
|
`campaigns-os record polish --packet <packet> --evidence <polish-evidence.json>`
|
|
100
101
|
(tier `C`: it overwrites `stages.polish` in the assembly report and stamps the
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-qa
|
|
3
|
-
version: 1.3.
|
|
3
|
+
version: 1.3.53
|
|
4
4
|
description: Run spec-aware QA from a saved Map or local-spec Build Packet and tested campaign URL after build, polish, and deploy/local evidence exist, including Playwright typed-card test-order proof.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.63.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.63.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -70,7 +70,7 @@ Inputs:
|
|
|
70
70
|
- tested base URL (localhost dev URL, preview URL, or production URL)
|
|
71
71
|
- assembly report
|
|
72
72
|
- Test-order coverage choice (`common` default vs explicit paths vs topology-complete `full`) and SDK origin state (localhost is a Development domain; non-localhost origins need allowlist confirmation so the SDK loads)
|
|
73
|
-
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour.
|
|
73
|
+
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour. For a later funnel in a multi-funnel project, read the same files under its own `assembly.runtime_dir` (`.campaign-runtime/funnels/<route>/`); the paths `next` prints are already the right ones.
|
|
74
74
|
|
|
75
75
|
Rules:
|
|
76
76
|
|
|
@@ -95,6 +95,7 @@ Rules:
|
|
|
95
95
|
- Saved-Map QA publishes to the QA portal under the existing consent and flag controls; report the portal link only when publication succeeds. Pass `--no-post-verdict` (or `--local-only`) to keep that verdict local. This stays tier `C`: served-page probes, requested orders, Run Telemetry and progress retain their own controls. See `docs/qa-and-test-orders.md` for the saved-Map publication policy.
|
|
96
96
|
- Local-spec QA always keeps verdicts and progress local. `qa run` suppresses portal publication even with `--post-verdict`; `qa publish` refuses local-spec packets with `local_spec`. Report the local verdict/sidecar as evidence, never a dashboard link. A matching route cannot replace a matching `local_spec_id`, and QA refuses a foreign or stale local Assembly Report. Run Telemetry still follows its consent controls.
|
|
97
97
|
- Browser QA must include checkout commerce geometry evidence, not just mount counts: express-wallet buttons rendered in the current browser, card/CVV hosted iframe host dimensions, iframe text-path height, and center alignment. Apple Pay is browser/device eligible, so record mounted wallet kinds instead of requiring Apple Pay in Chrome-only QA.
|
|
98
|
+
- After launch, when `next` or `doctor --ci` reports a page-only change (only some pages' HTML changed, and no checkout page, commerce markup, route, script or Page Kit config entry), QA is owed on those pages only and Polish is advisory: after `record build`, run `qa run --packet <packet> --page <page_id>` with one `--page` per changed page it names. A page-scoped run places no test orders and keeps the purchase proof of the full run it extends; it refuses a commerce-affecting change, a last QA that did not complete, or a brief `qa_policy` or CampaignSpec change, each of which owes a full `qa run`. See `docs/campaigns-os-build-flow.md#what-a-change-owes`.
|
|
98
99
|
- `qa resolve` accepts either the deploy host or the campaign-root URL; when a Build Packet carries `campaign.public_route_slug`, the runner resolves page URLs under that slug.
|
|
99
100
|
- Routing meta tags must be checked in runtime form. `next-success-url`, `next-upsell-accept-url`, and `next-upsell-decline-url` should point at campaign-root paths such as `/campaign-slug/upsell/`, not source filenames or unrooted spec literals.
|
|
100
101
|
- Upsell accept/decline routes may be SDK-bound controls rather than static `<a href>` links. Treat rendered `data-next-upsell-action="add"` and `data-next-upsell-action="skip"` controls as valid route evidence, then prove the path in the browser walkthrough.
|
|
@@ -102,6 +103,7 @@ Rules:
|
|
|
102
103
|
- When CampaignSpec declares checkout `promo_code_input.enabled`, browser QA should enter the mapped `offer_code` and verify active-code state, repricing, discount row rendering, and conditional presentation. Missing promo-code input is a blocker when CampaignSpec, source design, or user instructions declared it.
|
|
103
104
|
- A declared offer surface that the build never shipped is a blocker, not a silent pass. Every `--browser` run emits `browser-exit-intent-surface:<page>` and `browser-promo-code-surface:<page>` for each checkout page whose CampaignSpec declares the surface with `enabled: true`. Absent markup is `FAIL`/`BLOCKER`; a surface that renders but cannot be tied to the declared `offer_code` (or sits behind an unopened disclosure) is `MANUAL_REVIEW`/`WARN`. Exit-intent markup is looked for inside `<template>` content as well as the live document, because a correctly built pop lives nowhere else before it fires. A browser collector that threw mid-read `SKIP`s with the cause instead of blocking — it did not find nothing, it could not look.
|
|
104
105
|
- Typed-card runs reconcile the persisted order against what the checkout displayed at submit, and report both halves separately from whether the order was created: `browser-order-display-parity:<plan>` fails as a blocker naming any `is_upsell: false` line whose package the checkout never rendered as selected (and any displayed package that was never charged), and `browser-order-total-parity:<plan>` fails as a blocker when the order's pre-upsell total disagrees with the displayed summary total. Both `SKIP` with a stated reason when the page gives them nothing to compare — a summary whose rows carry no `data-package-id`, or a checkout with no `[data-next-display="cart.total"]` surface. Read a skip as missing coverage, never as a pass.
|
|
106
|
+
- A `qa run --currency <CODE>` run checks the currency took: each created test order gets `browser-order-currency:<plan>`, which fails as a blocker when the order came out in any other currency (Campaign Cart falls back to the default one when the requested one is unavailable), and automatic commercial parity requests expected totals in `<CODE>`, with a `commercial-currency:<CODE>:<ANSWERED>` blocker when the calculate endpoint prices in another currency. Without `--currency` neither row is written.
|
|
105
107
|
- Test orders must exercise the tested campaign through the Campaign Cart SDK, not a hand-built backend API request.
|
|
106
108
|
- Use the canonical Playwright typed-card path: fill customer/shipping fields, type sandbox card data into the active hosted payment iframes, and click the real checkout submit button.
|
|
107
109
|
- Use a shared safe inbox for typed-card test-order customer email when the operator provides one. Reusing one safe inbox keeps customer/user lists clean while still allowing notification delivery.
|
|
@@ -119,6 +121,7 @@ Rules:
|
|
|
119
121
|
- Keep multi-funnel and `tiers:common` / `tiers:full` plans isolated to each selected checkout's own funnel graph, tiers, and recognized terminals; never borrow an unrelated funnel's receipt page.
|
|
120
122
|
- Accepted-upsell proof is valid only when the browser observes the order upsell API mutation and the final order evidence contains the selected upsell package. A checkout bump line marked `is_upsell` is not accepted-upsell proof.
|
|
121
123
|
- Test orders are real orders in the store, but global test cards bypass the gateway: no charge, no transaction, and no merchant-specific sandbox routing to confirm. Localhost on any port is globally available as a Campaigns App Development domain and suppresses Campaigns analytics; 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.
|
|
124
|
+
- `qa run --test-order` answers the analytics vendors' beacons itself by default (GA4, Meta, TikTok, Snap, Pinterest, Taboola, Triple Whale, AppLovin Axon), so test orders do not reach those vendors; their scripts still load. The `browser-test-order:vendor-beacons` row records, per vendor, the requests the page sent and whether one named a purchase. It is evidence that the page sent them, never purchase proof, and it never blocks; it also lists configured vendors that are not intercepted (Northbeam, GTM-loaded tags outside the list). Pass `--vendor-beacons live` only when the operator wants the vendors to receive the test purchases; `qa parity` orders are not intercepted.
|
|
122
125
|
- Launch readiness is separate from Campaigns OS proof. If QA passes on local/preview, still surface production storefront URL, live payment methods, shipping markets, legal/support URLs, analytics expectations, and merchant-side configuration as real-shopper readiness items before launch.
|
|
123
126
|
- For multi-market campaigns, verify at least one non-default currency/country path: currency display, shipping method names/prices, available payment methods, and market-specific copy.
|
|
124
127
|
- Treat missing deploy URL, missing polish status, or unresolved doctor blockers as launch blockers.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-sdk-bump
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.9
|
|
4
4
|
description: Bump a live campaign's Campaign Cart SDK from one 0.4.x release to a later 0.4.x on a page-kit or static repo. Use for any request to bump, upgrade or move a campaign to SDK 0.4.x, including when the repository has its own BUMP.md. Find every pin, check the release diff and storage against the campaign's own code, prove on a preview with approved test orders, and report what is not proven.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.63.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.63.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -164,6 +164,17 @@ particular:
|
|
|
164
164
|
`window.next` exists and `document.body.dataset.nextSdkLoading === "false"`,
|
|
165
165
|
otherwise wait for the event, and run once either way. Step 6 proves it.
|
|
166
166
|
|
|
167
|
+
Known changes a bump can cross. Check each row the range covers, as well as the
|
|
168
|
+
release notes:
|
|
169
|
+
|
|
170
|
+
| Version | What changed | What to check |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| 0.4.32 | The checkout page no longer emits `order:completed` when it creates an order. The event fires on the first page opened with the order's `?ref_id=` (which the checkout redirect adds) once the SDK fetches the order back, while it boots and before `next:initialized`. | A hand-wired purchase capture on the checkout stops firing. Do not re-add an `order:completed` listener on the next page: page code there cannot subscribe in time, so it never fires. Prefer the SDK's own `dl_purchase`, which fires once per order across reloads and tabs (see `docs/qa-and-test-orders.md`, "Purchase data layer"). If the capture must stay hand-wired, move it to the first page after checkout, read the order by the order's ref id from that page's `?ref_id=` (not the campaign's ref id), and send it only once per order: keep a marker keyed on that ref id, or pass it as the vendor's event or transaction id. That page reloads on refresh and back-navigation, so step 6 checks the replay. |
|
|
173
|
+
| 0.4.41 | The card fields are set up by NEXT's payment script (`payments.29next.com`), which loads Spreedly itself, with the campaign's `payment_env_key`. A `next-spreedly-key` meta tag is no longer read; it does no harm if it stays. | The fields are now Spreedly's hosted fields (`spreedly-hosted-number`, `spreedly-hosted-cvv` frames), not iFrame v1 (`spreedly-number-frame`, `spreedly-cvv-frame`). Confirm the campaign has a payment key. Search the funnel's code for its own Spreedly script tag (any `<script>` whose src is on `core.spreedly.com`; SDK 0.4.40 loaded `core.spreedly.com/iframe/iframe-v1.min.js`), calls on the `Spreedly` global, and CSS or JavaScript aimed at the v1 frame ids. Remove or port each one in the same commit that moves that page's pin to 0.4.41 or later, never before, since a page still below 0.4.41 needs them. Add both hosts to any Content-Security-Policy. Plan a 3-D Secure order and check the card fields' styling in step 6. |
|
|
174
|
+
| 0.4.42 | `next:initialized` fires once and is not replayed. | Guard every listener, as above. |
|
|
175
|
+
| 0.4.43 | Shop Pay in the express-checkout container. | Check whether the campaign's `expressCheckout.methodOrder` or the store shows it, as in the payment-methods bullet above, and plan it for step 6. |
|
|
176
|
+
| Any, if a page has a hand-written `<link rel="modulepreload">` list of SDK files | The SDK's chunk file names change between versions. | Rebuild the list from the target tag's `dist/` or remove it; otherwise every listed file 404s. |
|
|
177
|
+
|
|
167
178
|
## 4. Storage check
|
|
168
179
|
|
|
169
180
|
Run `campaigns-os sdk storage-check --target <git-root> --target-sdk <x.y.z> --manifest <storage-migrations.v1.json> --scope <funnel folder,shared js>`
|
|
@@ -178,6 +189,14 @@ v0.4.39 to v0.4.43 declare 0.4.38 to 0.4.38, so `--target-sdk 0.4.43` returns
|
|
|
178
189
|
`target-outside-manifest-range`. Run the check at the manifest's highest
|
|
179
190
|
version and report that it does not speak for the versions above it.
|
|
180
191
|
|
|
192
|
+
If the check stops with exactly `Cannot inventory tracked Git source files.`
|
|
193
|
+
(with nothing after the period), the pinned Campaigns OS is npm 1.61.0 or
|
|
194
|
+
earlier, which lists the whole repository and fails once that list passes
|
|
195
|
+
1 MiB. Update the pin to a release whose bundle revision matches this skill, as
|
|
196
|
+
the check at the top of this skill requires, and run the check again. Do not
|
|
197
|
+
work around it in a copied repository: a copy can lose tracked files and report
|
|
198
|
+
a false `source-compatible`.
|
|
199
|
+
|
|
181
200
|
## 5. Build and check
|
|
182
201
|
|
|
183
202
|
**Page-kit:** run a development build, confirm every built page loads only the
|
|
@@ -209,13 +228,18 @@ browser context. `?country=` applies only when the campaign's
|
|
|
209
228
|
`currencyBehavior` is `auto`. Before each order, confirm the page shows
|
|
210
229
|
that currency and the country is selected; a value the campaign does not
|
|
211
230
|
support falls back without failing (`currency:fallback`). On `qa run`, pass
|
|
212
|
-
`--currency <main>`: it tags each funnel's entry page
|
|
213
|
-
|
|
231
|
+
`--currency <main>`: it tags each funnel's entry page, records the currency in
|
|
232
|
+
the verdict, and blocks the run when an order or the calculate endpoint comes
|
|
233
|
+
back in another currency, but the runner's separate page checks open new tabs without
|
|
214
234
|
it. `qa run` has no country flag.
|
|
215
235
|
|
|
216
236
|
Test orders send real purchase events to every analytics vendor the campaign
|
|
217
|
-
configures unless the vendor beacons are blocked at the network. `qa run
|
|
218
|
-
|
|
237
|
+
configures unless the vendor beacons are blocked at the network. `qa run
|
|
238
|
+
--test-order` answers the listed vendors' beacons locally by default, and its
|
|
239
|
+
`browser-test-order:vendor-beacons` verdict row names the vendors it does not
|
|
240
|
+
intercept (`--vendor-beacons live` sends them all; see
|
|
241
|
+
`docs/qa-and-test-orders.md`, "Analytics vendor beacons"). Orders placed by
|
|
242
|
+
hand are not held back. Do not add `?ignore=true` to stop them: it turns off the
|
|
219
243
|
SDK's analytics, `dl_*` events included, for the rest of the session, so the
|
|
220
244
|
purchase-event check below cannot pass. Before asking for test orders, list
|
|
221
245
|
the vendors and name them in the question. On Page Kit, read every non-empty
|
|
@@ -261,7 +285,12 @@ Cover:
|
|
|
261
285
|
- each payment or express method step 3 found the range adds, started and
|
|
262
286
|
cancelled, where the campaign offers it;
|
|
263
287
|
- an upsell at quantity 2 or more on a page that shows a quantity picker;
|
|
264
|
-
- a 3-D Secure card when step 3 found card-field or 3-D Secure changes, and whether it challenged
|
|
288
|
+
- a 3-D Secure card when step 3 found card-field or 3-D Secure changes, and whether it challenged.
|
|
289
|
+
Use the 3-D Secure test card in `docs/qa-and-test-orders.md` (`6011 0009 9013 9424`;
|
|
290
|
+
the platform's [testing page](https://developers.nextcommerce.com/docs/testing)
|
|
291
|
+
lists it as the "3DS payment flow" card). You cannot see whether the store's
|
|
292
|
+
gateway is in test mode, so ask the developer to confirm it before placing
|
|
293
|
+
the order;
|
|
265
294
|
- the coupon path, if the funnel has one;
|
|
266
295
|
- the purchase event fires once, on the page the release says it should;
|
|
267
296
|
- every SDK page, upsells included, on one fresh load and then five cached
|
|
@@ -270,7 +299,11 @@ Cover:
|
|
|
270
299
|
the receipt and any page where step 3 found a hand-wired purchase push or
|
|
271
300
|
`order:completed` listener: upsell pages reload the order and can resend a
|
|
272
301
|
real purchase on each load. Count purchase events across the whole run, and
|
|
273
|
-
list those pages' listeners as not proven on cached reloads
|
|
302
|
+
list those pages' listeners as not proven on cached reloads;
|
|
303
|
+
- where a purchase capture is hand-wired, one reload of the page it runs on,
|
|
304
|
+
with the vendor beacons blocked at the network (`qa run --test-order` blocks
|
|
305
|
+
the listed vendors by default; a reload by hand does not), and the purchase
|
|
306
|
+
sent only once for that order.
|
|
274
307
|
|
|
275
308
|
Read each order back in the store admin (the packet run's verdict under
|
|
276
309
|
`qa-output/` also lists the orders it created) and keep the order numbers for
|
package/skills.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "campaigns-os-skills",
|
|
3
3
|
"description": "Skills bundled with Campaigns OS. `skills.sh` installs these into the shared agent skill directories (~/.claude/skills, ~/.codex/skills), so each one is a versioned package: bump the version whenever a package changes. `bundle_revision` identifies the bundle as a whole — `<package version>+skills.<n>`, where the prefix is this package's version and `<n>` counts the skill-text revisions published against it. It advances whenever ANY bundled skill changes, every SKILL.md states it on its first body line, and `campaigns-os tooling status --skills-revision <value>` compares the value an agent read from a skill against the bundle on disk. See docs/skills-revision.md.",
|
|
4
|
-
"bundle_revision": "1.
|
|
4
|
+
"bundle_revision": "1.63.0+skills.1",
|
|
5
5
|
"homepage": "https://github.com/NextCommerceCo/campaigns-os",
|
|
6
6
|
"retired_skills": [
|
|
7
7
|
{
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"id": "next-campaigns-os",
|
|
18
18
|
"name": "Campaigns OS Lifecycle",
|
|
19
|
-
"version": "1.0.
|
|
19
|
+
"version": "1.0.69",
|
|
20
20
|
"path": "skills/next-campaigns-os/SKILL.md",
|
|
21
21
|
"domain": "campaigns",
|
|
22
22
|
"description": "Coordinate Campaigns OS lifecycle workflows from CampaignSpec, Build Packet, starter-template contracts, stage reports, deploy evidence, and QA proof depth."
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
{
|
|
25
25
|
"id": "next-campaigns-os-setup",
|
|
26
26
|
"name": "Campaigns OS Setup",
|
|
27
|
-
"version": "2.0.
|
|
27
|
+
"version": "2.0.52",
|
|
28
28
|
"path": "skills/next-campaigns-os-setup/SKILL.md",
|
|
29
29
|
"domain": "campaigns",
|
|
30
30
|
"description": "Bootstrap or prepare a target page-kit campaign repo from a doctor-cleared Campaigns OS Build Packet before full build wiring. Formerly next-campaigns-setup; renamed to release that name to the published NextCommerceCo/skills scaffolder."
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
{
|
|
33
33
|
"id": "next-campaigns-build",
|
|
34
34
|
"name": "Campaign Build",
|
|
35
|
-
"version": "1.0.
|
|
35
|
+
"version": "1.0.54",
|
|
36
36
|
"path": "skills/next-campaigns-build/SKILL.md",
|
|
37
37
|
"domain": "campaigns",
|
|
38
38
|
"description": "Assemble a NEXT campaign from a doctor-cleared Build Packet, CampaignSpec/API values, prepared HTML/assets, page-kit, and starter-template contracts."
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
{
|
|
41
41
|
"id": "next-campaigns-polish",
|
|
42
42
|
"name": "Campaign Polish",
|
|
43
|
-
"version": "1.1.
|
|
43
|
+
"version": "1.1.54",
|
|
44
44
|
"path": "skills/next-campaigns-polish/SKILL.md",
|
|
45
45
|
"domain": "campaigns",
|
|
46
46
|
"description": "Run the visual/runtime polish pass after build and before QA for a Campaigns OS campaign."
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
{
|
|
49
49
|
"id": "next-campaigns-qa",
|
|
50
50
|
"name": "Campaign QA",
|
|
51
|
-
"version": "1.3.
|
|
51
|
+
"version": "1.3.53",
|
|
52
52
|
"path": "skills/next-campaigns-qa/SKILL.md",
|
|
53
53
|
"domain": "campaigns",
|
|
54
54
|
"description": "Run spec-aware QA from a saved Map or local-spec Build Packet and tested campaign URL after build, polish, and deploy/local evidence exist, including Playwright typed-card test-order proof."
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
{
|
|
57
57
|
"id": "campaign-lifecycle-orientation",
|
|
58
58
|
"name": "Campaign Lifecycle Orientation",
|
|
59
|
-
"version": "1.0.
|
|
59
|
+
"version": "1.0.49",
|
|
60
60
|
"path": "skills/campaign-lifecycle-orientation/SKILL.md",
|
|
61
61
|
"domain": "campaigns",
|
|
62
62
|
"description": "Orient a reader to the Campaigns OS lifecycle artifacts a run has already emitted, without advancing their state: the shared vocabulary, doctor as a gate, the stage record, and the store-theme/Page Kit two-worlds trap."
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
{
|
|
65
65
|
"id": "campaign-run-evidence",
|
|
66
66
|
"name": "Campaign Run Evidence",
|
|
67
|
-
"version": "1.0.
|
|
67
|
+
"version": "1.0.49",
|
|
68
68
|
"path": "skills/campaign-run-evidence/SKILL.md",
|
|
69
69
|
"domain": "campaigns",
|
|
70
70
|
"description": "Interpret existing doctor, QA verdict and proof-depth evidence without claiming more proof than the artifacts contain, and keep funnel proof apart from merchant launch readiness."
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
{
|
|
73
73
|
"id": "campaign-readback-classification",
|
|
74
74
|
"name": "Campaign Readback Classification",
|
|
75
|
-
"version": "1.0.
|
|
75
|
+
"version": "1.0.49",
|
|
76
76
|
"path": "skills/campaign-readback-classification/SKILL.md",
|
|
77
77
|
"domain": "campaigns",
|
|
78
78
|
"description": "Classify a selected campaign from the campaigns-os-readback/v2 fields (artifacts, staleness.stale_keys, clean, doctor, divergences, skip_cascades) and write a read-only handoff without turning diagnosis into permission."
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
{
|
|
81
81
|
"id": "contribution-intake",
|
|
82
82
|
"name": "Contribution Intake",
|
|
83
|
-
"version": "1.0.
|
|
83
|
+
"version": "1.0.49",
|
|
84
84
|
"path": "skills/contribution-intake/SKILL.md",
|
|
85
85
|
"domain": "campaigns",
|
|
86
86
|
"description": "Turn a suggestion about the agent surface into a classified, evidence-checked and redacted proposal, filed on this repository tracker only with attended approval."
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
{
|
|
89
89
|
"id": "next-campaigns-sdk-bump",
|
|
90
90
|
"name": "Campaign SDK Bump",
|
|
91
|
-
"version": "1.0.
|
|
91
|
+
"version": "1.0.9",
|
|
92
92
|
"path": "skills/next-campaigns-sdk-bump/SKILL.md",
|
|
93
93
|
"domain": "campaigns",
|
|
94
94
|
"description": "Bump a live campaign from one Campaign Cart 0.4.x release to a later 0.4.x on a page-kit or static repo: find every pin, check the release diff and storage against the campaign code, prove on a preview with approved test orders, and report what is not proven."
|
package/src/brand-theme.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from "node:fs";
|
|
16
16
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
|
+
import { packetRuntimeRelPath } from "./campaign-workspace.mjs";
|
|
18
19
|
|
|
19
20
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
21
|
const SOURCE_DEFAULTS_PATH = "contracts/brand-theme-source-defaults.figma-sections-export.v0.json";
|
|
@@ -1557,7 +1558,7 @@ export function inspectBrandTheme({ packet, packetPath, context = null, policy =
|
|
|
1557
1558
|
const contracts = loadContracts(repoRoot);
|
|
1558
1559
|
const sourceRoot = resolveFromFile(packetPath, packet.source_html?.root);
|
|
1559
1560
|
const targetRepo = resolveFromFile(packetPath, packet.assembly?.target_repo) || dirname(resolve(packetPath));
|
|
1560
|
-
const themeOutDir = outDir ? resolve(outDir) : resolve(targetRepo, "
|
|
1561
|
+
const themeOutDir = outDir ? resolve(outDir) : resolve(targetRepo, packetRuntimeRelPath(packet), "theme");
|
|
1561
1562
|
const cssPath = resolve(themeOutDir, "brand-theme.css");
|
|
1562
1563
|
const fontsCssPath = resolve(themeOutDir, BRAND_FONTS_FILENAME);
|
|
1563
1564
|
const reportPath = resolve(themeOutDir, "theme-report.json");
|
package/src/build-brief.mjs
CHANGED
|
@@ -632,8 +632,11 @@ function evaluateCampaignBuildBrief(brief, { spec, activePages, pageMappings, so
|
|
|
632
632
|
const variantSignals = collectVariantSignals(spec, sourceAssetCrawl);
|
|
633
633
|
const regulated = hasRegulatedSignals(spec);
|
|
634
634
|
const pageIds = [...new Set((activePages || []).map((page) => page.id).filter(Boolean))];
|
|
635
|
+
// A page added from the repo's page tree after handoff (#721) has the repo
|
|
636
|
+
// page itself as its authority; the brief is not asked to name one.
|
|
637
|
+
const repoPages = new Set((pageMappings || []).filter((page) => page?.origin === "repo").map((page) => page.page_id));
|
|
635
638
|
|
|
636
|
-
const missingDesignAuthority = pageIds.filter((pageId) => !isObject(brief.design_authority?.[pageId]) || !isNonEmptyString(brief.design_authority?.[pageId]?.source));
|
|
639
|
+
const missingDesignAuthority = pageIds.filter((pageId) => !repoPages.has(pageId) && (!isObject(brief.design_authority?.[pageId]) || !isNonEmptyString(brief.design_authority?.[pageId]?.source)));
|
|
637
640
|
if (missingDesignAuthority.length) {
|
|
638
641
|
addQuestion(questions, "page_design_authority", {
|
|
639
642
|
detail: `Missing page authority for: ${missingDesignAuthority.join(", ")}.`,
|