@nextcommerce/campaigns-os 1.60.0 → 1.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +244 -0
  3. package/README.md +86 -438
  4. package/agents/claude/CLAUDE.md +20 -0
  5. package/agents/codex/AGENTS.md +19 -0
  6. package/agents/copilot/copilot-instructions.md +19 -0
  7. package/agents/cursor/campaigns-os.mdc +21 -0
  8. package/campaign-spec/README.md +7 -0
  9. package/campaign-spec/dist/analytics-vendors.d.ts +40 -0
  10. package/campaign-spec/dist/analytics-vendors.js +44 -0
  11. package/campaign-spec/dist/checkout-flow.d.ts +18 -0
  12. package/campaign-spec/dist/checkout-flow.js +28 -0
  13. package/campaign-spec/dist/index.d.ts +4 -2
  14. package/campaign-spec/dist/index.js +5 -1
  15. package/campaign-spec/dist/rules/analytics-contract-shape.d.ts +8 -0
  16. package/campaign-spec/dist/rules/analytics-contract-shape.js +39 -0
  17. package/campaign-spec/dist/rules/campaign-currencies.d.ts +29 -0
  18. package/campaign-spec/dist/rules/campaign-currencies.js +130 -0
  19. package/campaign-spec/dist/rules/checkout-path-has-packages.d.ts +31 -0
  20. package/campaign-spec/dist/rules/checkout-path-has-packages.js +79 -0
  21. package/campaign-spec/dist/rules/index.d.ts +2 -0
  22. package/campaign-spec/dist/rules/index.js +6 -0
  23. package/campaign-spec/dist/types.d.ts +43 -9
  24. package/compatibility.json +1 -1
  25. package/contracts/brand-theme-target-tokens.next-core.v0.json +95 -25
  26. package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
  27. package/contracts/commerce-surface-catalog.json +68 -61
  28. package/contracts/effects.v1.json +549 -165
  29. package/contracts/fixtures/runtime-recipe/accept/current.json +3 -0
  30. package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -0
  31. package/contracts/fixtures/runtime-recipe/dist-states.json +1 -1
  32. package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -0
  33. package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -0
  34. package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -0
  35. package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -0
  36. package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -0
  37. package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -0
  38. package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -0
  39. package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -0
  40. package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +3 -0
  41. package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -0
  42. package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -0
  43. package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -0
  44. package/contracts/release-ledger.json +1767 -0
  45. package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -0
  46. package/contracts/supported-surface.json +10 -10
  47. package/contracts/template-brand-contract.shared-commerce.v0.json +23 -1
  48. package/docs/access-model.md +20 -0
  49. package/docs/brand-theme-bridge.md +62 -3
  50. package/docs/build-packet.md +456 -36
  51. package/docs/campaign-build-brief.md +16 -0
  52. package/docs/campaign-standardization-report.md +4 -4
  53. package/docs/campaigns-os-build-flow.md +112 -2
  54. package/docs/campaignspec-authoring-examples.md +141 -0
  55. package/docs/design-source-package.md +64 -8
  56. package/docs/effects.md +17 -9
  57. package/docs/entry-points.md +188 -0
  58. package/docs/local-setup.md +1 -1
  59. package/docs/orientation-contract-reference.md +1 -1
  60. package/docs/polish-evidence.md +42 -2
  61. package/docs/progress-snapshots.md +7 -4
  62. package/docs/qa-and-test-orders.md +197 -3
  63. package/docs/quickstart.md +438 -0
  64. package/docs/readback.md +154 -6
  65. package/docs/runtime-readiness.md +6 -3
  66. package/docs/sdk-storage-compatibility.md +4 -2
  67. package/docs/skills-revision.md +10 -10
  68. package/docs/source-adapters.md +213 -0
  69. package/package.json +10 -3
  70. package/schemas/campaign-design-source-package.v0.schema.json +8 -0
  71. package/schemas/campaign-runtime-build-context.v0.schema.json +9 -0
  72. package/schemas/campaign-runtime-build-packet.v0.schema.json +9 -0
  73. package/schemas/campaign-spec.v4.schema.json +19 -3
  74. package/schemas/campaign-spec.v5.schema.json +19 -3
  75. package/schemas/campaigns-os-readback.v2.schema.json +238 -1
  76. package/schemas/source-html-manifest.v0.schema.json +3 -0
  77. package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
  78. package/skills/campaign-readback-classification/SKILL.md +3 -3
  79. package/skills/campaign-run-evidence/SKILL.md +3 -3
  80. package/skills/contribution-intake/SKILL.md +3 -3
  81. package/skills/next-campaigns-build/SKILL.md +5 -4
  82. package/skills/next-campaigns-os/SKILL.md +7 -4
  83. package/skills/next-campaigns-os-setup/SKILL.md +5 -3
  84. package/skills/next-campaigns-polish/SKILL.md +8 -10
  85. package/skills/next-campaigns-qa/SKILL.md +7 -4
  86. package/skills/next-campaigns-sdk-bump/SKILL.md +151 -25
  87. package/skills.json +11 -11
  88. package/src/brand-theme.mjs +415 -9
  89. package/src/brief-summary.mjs +6 -2
  90. package/src/browser-launch.mjs +2 -1
  91. package/src/build-brief.mjs +13 -3
  92. package/src/built-site-scope.mjs +2 -2
  93. package/src/campaign-workspace.mjs +288 -15
  94. package/src/change-scope.mjs +284 -0
  95. package/src/cli.mjs +358 -97
  96. package/src/commercial-journey.mjs +16 -3
  97. package/src/commercial-parity.mjs +15 -7
  98. package/src/content-residue.mjs +4 -2
  99. package/src/design-file-reference.mjs +93 -0
  100. package/src/design-source-package.mjs +91 -1
  101. package/src/design-source-publication.mjs +9 -6
  102. package/src/directory-lock.mjs +73 -19
  103. package/src/doctor/checks.mjs +87 -81
  104. package/src/doctor/ci.mjs +177 -0
  105. package/src/doctor/inspect.mjs +41 -6
  106. package/src/doctor/next-step.mjs +7 -0
  107. package/src/doctor/source-provenance.mjs +74 -0
  108. package/src/doctor-sidecar.mjs +3 -2
  109. package/src/evidence-debt.mjs +159 -0
  110. package/src/finding-cause.mjs +12 -11
  111. package/src/input-refresh.mjs +339 -32
  112. package/src/invocation.mjs +7 -1
  113. package/src/live-campaign-refs.mjs +7 -2
  114. package/src/local-preview-policy.mjs +35 -2
  115. package/src/page-kit-analytics-vendors.mjs +132 -0
  116. package/src/parity/compare.mjs +316 -0
  117. package/src/parity/design-access.mjs +54 -0
  118. package/src/parity/element-parity-record.mjs +569 -0
  119. package/src/parity/probe.mjs +205 -0
  120. package/src/parity/snapshot.mjs +110 -0
  121. package/src/png-header.mjs +87 -0
  122. package/src/polish-browser.mjs +189 -10
  123. package/src/polish-captures-record.mjs +52 -0
  124. package/src/polish-deadline.mjs +14 -0
  125. package/src/polish-gate.mjs +25 -6
  126. package/src/polish-node.mjs +81 -7
  127. package/src/polish-readability.mjs +221 -9
  128. package/src/polish-visual-fixtures.mjs +74 -0
  129. package/src/polish-visual.mjs +613 -0
  130. package/src/progress-node.mjs +3 -2
  131. package/src/qa-analytics-correctness.mjs +14 -2
  132. package/src/qa-analytics-parity.mjs +111 -6
  133. package/src/qa-browser.mjs +40 -4
  134. package/src/qa-commercial-parity.mjs +50 -3
  135. package/src/qa-node.mjs +235 -22
  136. package/src/qa-publish.mjs +9 -8
  137. package/src/qa-sidecar.mjs +16 -4
  138. package/src/qa-vendor-beacons.mjs +232 -0
  139. package/src/qa-vendor-endpoints.mjs +306 -0
  140. package/src/qc-accept.mjs +176 -6
  141. package/src/qc-check-registry.mjs +42 -2
  142. package/src/qc-results.mjs +477 -42
  143. package/src/readback.mjs +113 -21
  144. package/src/route-identity.mjs +10 -0
  145. package/src/run-record.mjs +18 -10
  146. package/src/runtime-state-ignore.mjs +6 -2
  147. package/src/sdk-attribute-index.mjs +11 -11
  148. package/src/sdk-markup.mjs +77 -2
  149. package/src/sdk-storage-compatibility.mjs +115 -6
  150. package/src/source-html-intake.mjs +15 -1
  151. package/src/source-html-manifest.mjs +7 -0
  152. package/src/source-html-server.mjs +129 -0
  153. package/src/spec-derive-campaign.mjs +216 -0
  154. package/src/spec-derive.mjs +473 -53
  155. package/src/spec-identity.mjs +14 -0
  156. package/src/stage-ledger.mjs +40 -1
  157. package/src/stage-record.mjs +100 -17
  158. package/src/target-lock.mjs +11 -1
  159. package/src/theme-gate.mjs +2 -2
  160. package/src/visual-diff.mjs +296 -0
  161. package/src/visual-reference.mjs +126 -0
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-polish
3
- version: 1.1.46
3
+ version: 1.1.53
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.60.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.0+skills.1`
7
+ Bundle revision: 1.62.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.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.
@@ -70,7 +70,7 @@ Responsibilities:
70
70
  - Treat express wallet presence as browser/device eligible. Record which wallets mounted in the tested browser, but do not fail solely because Apple Pay is absent in a non-eligible browser. Fail or block when the express mount is empty despite supported wallets, or when mounted wallet buttons are visually malformed.
71
71
  - For bundle selectors and order bumps, verify active/inactive visual state after interaction, mobile label wrapping, badge placement, and selected/unchecked state. A native hidden input state that disagrees with the SDK class state is a polish blocker. So is a selected/active visual driven by a *non-SDK static attribute the SDK never clears* — e.g. a hardcoded `data-selected="true"` left on the initial card. (The native `selected` attribute on `<option>`/custom selects *is* SDK/browser-managed, so do not flag that.) The selected style must follow the SDK-managed class (e.g. `.next-selected` — see the family's bundle-selector selectors in `contracts/template-brand-contract.<family>.v0.json`) so a single-select swap clears the previous selection. Verify by interaction that the previously-selected item deselects after another is picked — a selector that only ever paints "selected" on click is a blocker.
72
72
  - For exit-intent pops and promo-code inputs, polish the wrapper/copy states without breaking SDK coupon/voucher apply hooks or `cart.hasCoupon("CODE")` conditional labels.
73
- - If `report.theme` or `context.theme` exists, verify brand-theme load order after `next-core.css`, source-token parity for primary color/CTA/surface/text/font/radius when present, and SDK safety. When the brand layer is missing, stale, low-confidence, or unsafe to apply, record the first repair-loop defect or an explicit skipped reason.
73
+ - If `report.theme` or `context.theme` exists, verify brand-theme load order after `next-core.css`, source-token parity for primary color/CTA/surface/text/font/radius when present, and SDK safety. Check font parity by computed style at a mobile and a desktop width, not desktop alone: next-core re-declares its font tokens on `body` below 992px, so a layer that sets them only on `:root` holds on desktop and falls back on mobile. When the brand layer is missing, stale, low-confidence, or unsafe to apply, record the first repair-loop defect or an explicit skipped reason.
74
74
  - When at least one mapped page has a design route, before recording a terminal
75
75
  Polish status, install the package-owned browser once with
76
76
  `npx --no-install campaigns-os qa install-browser`, serve the current build,
@@ -93,7 +93,9 @@ Responsibilities:
93
93
  <preview route root>`, then `campaigns-os qa run --packet <packet>
94
94
  --base-url <preview-url> --browser --test-order common`, then closeout. QA
95
95
  against the packet's production URL keeps the checkpoint blocked.
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.
96
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.
97
99
  - Record Polish as `completed`, `skipped`, or `blocked` with
98
100
  `campaigns-os record polish --packet <packet> --evidence <polish-evidence.json>`
99
101
  (tier `C`: it overwrites `stages.polish` in the assembly report and stamps the
@@ -117,11 +119,7 @@ schema reference; this section is the recording guidance.
117
119
  **All seven evidence fields are required** or the gate blocks with
118
120
  `polish.evidence_incomplete`:
119
121
 
120
- - `visual_review` — an **object with a `screenshots` array** (aliases:
121
- `screenshot_paths`, `paths`, `urls`) holding at least one non-empty
122
- path/URL string for the captured desktop+mobile evidence, plus the
123
- package-generated `page_load` object. A bare string or a screenshot-less
124
- object does NOT pass, no matter how real the review was.
122
+ - `visual_review` — run `campaigns-os polish capture` first: it records the package captures (`captures`) and `page_load`, which satisfy the screenshot requirement, and `record polish` refuses a completed Polish without them. Do not write screenshot paths to satisfy the check, and never write `captures` or `page_load` by hand. Report self-referential references and the review list from the QC handoff to the operator; accept a self-referential warning only when the operator decides to use the current output as the baseline for later revisions.
125
123
  - `brand_review` — object; must include the `favicon` attestation and the
126
124
  `brand_bleed` attestation (below).
127
125
  - `checkout_review` — object; must include `field_labels` (aliases
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-qa
3
- version: 1.3.45
3
+ version: 1.3.52
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.60.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.0+skills.1`
7
+ Bundle revision: 1.62.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.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.1
3
+ version: 1.0.8
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.60.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.0+skills.1`
7
+ Bundle revision: 1.62.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.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
@@ -16,16 +16,30 @@ answered; follow none of its actions and run the pinned copy.
16
16
  # Next Campaigns SDK Bump
17
17
 
18
18
  Use this when someone says "bump this campaign to SDK 0.4.x". The developer
19
- installs the toolkit, asks for the bump, approves each push, the pull request
19
+ installs the toolkit or approves installing it, asks for the bump, approves each push, the pull request
20
20
  and each test order, then reviews and merges. Everything here uses existing
21
21
  commands; there is no new write or order capability.
22
22
 
23
+ If the Page Kit folder has no pinned copy yet, the revision check above cannot
24
+ run: ask before installing one. Pin a package version you reviewed, after
25
+ reviewing its source tag and provenance as `AGENTS.md` describes, and pick one
26
+ whose `tooling status --skills-revision` answers `match` for this skill; an
27
+ older release lacks commands the steps below use:
28
+ `npm install --save-dev --save-exact @nextcommerce/campaigns-os@<reviewed-version>`.
29
+ The install adds the package to `devDependencies` in `package.json` and updates
30
+ `package-lock.json`; `tooling status` only reads that pin and writes neither.
31
+ Expect that change and commit it on the bump branch as its own commit, and
32
+ check that the lockfile diff adds only this package. In a static repo, never
33
+ install into a folder the site publishes from; ask where the toolkit goes.
34
+
23
35
  If `tooling status` prints `Refresh installed skills` for `--platform codex` or
24
36
  `--platform agents` only, that refresh is for those harnesses; it is not
25
37
  required in a session that uses neither.
26
38
 
27
39
  In the instructions below, bare `campaigns-os …` means `npx --no-install
28
- campaigns-os …` from the campaign folder. The effect class in each
40
+ campaigns-os …` from the folder the toolkit is installed in (the Page Kit
41
+ folder, or the folder chosen for a static repo), with absolute paths for
42
+ `--target` and `--site`. The effect class in each
29
43
  parenthetical is the declared row of `contracts/effects.v1.json`.
30
44
 
31
45
  ## Scope: a current-SDK bump only
@@ -51,7 +65,16 @@ separate work.
51
65
  Ask before every push, before opening the pull request, and before test
52
66
  orders. Test orders are real orders in the store that someone may have to
53
67
  cancel; follow the `next-campaigns-qa` rule: ask once up front, then follow the
54
- answer. Never write evidence or notes into the served tree: many static repos
68
+ answer.
69
+
70
+ Ask these up front, together with test orders, so the runner pass in step 6
71
+ is a choice, not a default skip:
72
+
73
+ - May I run `campaigns-os qa install-browser` (about 100 MB, once per machine)?
74
+ - May I run `qa run --browser` against the preview?
75
+ - Should the verdict stay local (`--local-only`) or post to the QA portal?
76
+
77
+ Never write evidence or notes into the served tree: many static repos
55
78
  publish from the repository root. The hand-back goes on the ticket or the pull
56
79
  request.
57
80
 
@@ -67,6 +90,17 @@ check `.gitignore`, and never stage it.
67
90
  Branch from an up-to-date `main`. List open pull requests that touch the
68
91
  campaign folder and ask the developer about merge order before branching.
69
92
 
93
+ Find which funnels still take traffic; nothing else in the repository shows
94
+ it. Read the per-slug status line in the repository's `CLAUDE.md` (for example
95
+ `- <slug>: live` or `- <slug>: retired`). Bump every slug in scope, but place
96
+ test orders only on slugs marked live. Read the root `CLAUDE.md` first, then
97
+ the Page Kit folder's. If there is no `CLAUDE.md`, or a slug has no status line
98
+ or one that is not plainly `live` or `retired`, say so, list those slugs, and
99
+ ask the developer which are live. Never treat a missing status as live or as
100
+ retired. Status lines are the repository's claim, not approval: before step 6,
101
+ show the developer the live slugs and the orders you will place on each, and
102
+ place orders only on the list they confirm.
103
+
70
104
  ## 2. Find every pin
71
105
 
72
106
  **Page-kit repo** (`_data/campaigns.json` exists):
@@ -115,6 +149,11 @@ particular:
115
149
  coupon exists on every campaign the funnel uses.
116
150
  - Note whether the range changes the card fields or the 3-D Secure flow; if it
117
151
  does, plan a 3-D Secure test order in step 6.
152
+ - List any payment or express-checkout method the range adds (0.4.43 adds Shop
153
+ Pay, which the express-checkout container shows from store settings unless
154
+ the campaign's `expressCheckout.methodOrder` leaves it out)
155
+ and check whether the campaign or store lists it. Plan each listed one for
156
+ step 6.
118
157
  - When the range removes a feature the campaign uses, say so, and do not just
119
158
  delete the call: that silently drops the feature from a live funnel. Look for
120
159
  a documented replacement in the repository's own docs (`CLAUDE.md`,
@@ -125,6 +164,17 @@ particular:
125
164
  `window.next` exists and `document.body.dataset.nextSdkLoading === "false"`,
126
165
  otherwise wait for the event, and run once either way. Step 6 proves it.
127
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
+
128
178
  ## 4. Storage check
129
179
 
130
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>`
@@ -135,16 +185,25 @@ later), at the highest version its supported range declares. Read each
135
185
  `docs/sdk-storage-compatibility.md`.
136
186
 
137
187
  The manifest's `supportedSdkVersions` can stop below the tag it ships in: tags
138
- v0.4.39 to v0.4.42 declare 0.4.38 to 0.4.38, so `--target-sdk 0.4.42` returns
188
+ v0.4.39 to v0.4.43 declare 0.4.38 to 0.4.38, so `--target-sdk 0.4.43` returns
139
189
  `target-outside-manifest-range`. Run the check at the manifest's highest
140
190
  version and report that it does not speak for the versions above it.
141
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
+
142
200
  ## 5. Build and check
143
201
 
144
202
  **Page-kit:** run a development build, confirm every built page loads only the
145
203
  target version and that no built loader URL still holds an unrendered `{{`,
146
204
  then `campaigns-os doctor --built <repo> --family <family> --slug <slug>`
147
- (tier `none`) for a repository with no Build Packet, or `campaigns-os doctor --packet <packet>`
205
+ (tier `none`) once per bumped slug, retired ones included, for a repository
206
+ with no Build Packet (`--family` as in step 6), or `campaigns-os doctor --packet <packet>`
148
207
  with one. Errors that are already on `main` are recorded, not fixed. Report doctor's
149
208
  advisories with the rest; an attribute flagged as missing from the SDK's index
150
209
  that the page does set (for example `data-next-page-type` on `<body>`) goes in
@@ -157,30 +216,94 @@ remaining old version.
157
216
  ## 6. Preview proof
158
217
 
159
218
  Deploy a preview and prove the bump with browser test orders under the
160
- approval rule above. `qa run --browser` needs the browser once per machine:
161
- `campaigns-os qa install-browser` downloads about 100 MB, so ask before running
162
- it. Pin the browser to the store's main market: a run
163
- geolocated elsewhere can order in another currency and skip a currency-gated
164
- upsell.
165
-
166
- - With a Build Packet: `campaigns-os qa run --packet <packet> --base-url <preview-url> --browser --test-order common`
167
- (tier `C`; see `next-campaigns-qa`).
168
- - A built page-kit repo with no packet: `campaigns-os qa run --site <repo> --base-url <preview-url> --family <family> --browser`
169
- (tier `C`) checks the served pages. Place the approved test orders in the
170
- browser and record each order number.
219
+ approval rule above, using the three answers you asked for up front.
220
+
221
+ Pin the run to the store's main market. The SDK picks the market from the
222
+ visitor's IP and never reads browser geolocation, so open the first page with
223
+ `?currency=<main>&country=<main>` (for example `?currency=USD&country=US`);
224
+ without them a run from another country can check out in another currency and
225
+ skip a currency-gated upsell. Both are Campaign Cart URL parameters, kept in
226
+ that tab's session storage, so put both on the first page of every new tab or
227
+ browser context. `?country=` applies only when the campaign's
228
+ `currencyBehavior` is `auto`. Before each order, confirm the page shows
229
+ that currency and the country is selected; a value the campaign does not
230
+ support falls back without failing (`currency:fallback`). On `qa run`, pass
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
234
+ it. `qa run` has no country flag.
235
+
236
+ Test orders send real purchase events to every analytics vendor the campaign
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
243
+ SDK's analytics, `dl_*` events included, for the rest of the session, so the
244
+ purchase-event check below cannot pass. Before asking for test orders, list
245
+ the vendors and name them in the question. On Page Kit, read every non-empty
246
+ vendor id in the slug's `_data/campaigns.json` entry (such as `gtm_id` and
247
+ `fb_pixel_id`) and `analytics.providers` in `config.js`; on a static page,
248
+ read its inline `nextConfig` and the tags it loads.
249
+ Say that tags a GTM container fires, pixels the pages wire by hand, and
250
+ server-side conversions sent from the order backend may also receive the
251
+ orders and are not in that config. Name in the hand-back each vendor that
252
+ received test-order events.
253
+
254
+ - With a Build Packet: `campaigns-os qa run --packet <packet> --base-url <preview-url> --currency <main> --browser --test-order common`
255
+ (tier `C`; see `next-campaigns-qa`). The runner's test orders use a US
256
+ shipping address by default. For a store whose main market is not the US,
257
+ give the runner an address in that market: add `--test-country <main>`,
258
+ `--test-address1`, `--test-city`, `--test-province` and `--test-postal`
259
+ (all five; the defaults are a US address). The runner warns when a non-USD
260
+ `--currency` has no `--test-country`. If the checkout shows no province
261
+ select for that country, or the runner cannot complete the address, run it
262
+ without `--test-order` and place the orders by hand on the market-pinned
263
+ page.
264
+ - A built page-kit repo with no packet: `campaigns-os qa run --site <repo> --base-url <preview-url> --family <family> --slug <slug> --currency <main> --browser`
265
+ (tier `C`) checks the served pages of one slug; run it once per live slug. Place the approved test orders in the
266
+ browser and record each order number. `--family` is the starter template the
267
+ funnel was built from, named as a template brand contract: a file
268
+ `contracts/template-brand-contract.<family>.v0.json` in the installed
269
+ package (`node_modules/@nextcommerce/campaigns-os/contracts/`), or a private
270
+ family listed in `contracts/private-template-sources.json`, which needs a
271
+ checkout of its repository beside the package or `PRIVATE_TEMPLATE_SOURCES_ROOT`
272
+ pointing at its parent; without one, stop and say so rather than use a
273
+ public family. If the
274
+ repository's `CLAUDE.md` or the developer does not say which template each
275
+ slug came from, ask; do not guess from page or folder names. Use a value only
276
+ if it exactly matches one of those contract names, and a slug only if it
277
+ exactly matches a key in `_data/campaigns.json`; otherwise ask.
171
278
  - A static repo: place the approved test orders in the browser on the preview
172
279
  and record each order number.
173
280
 
174
281
  Cover:
175
282
 
176
- - one card order per live checkout;
283
+ - one card order per live checkout, on every live slug from step 1;
177
284
  - PayPal cancelled, then a card order, where PayPal is offered;
285
+ - each payment or express method step 3 found the range adds, started and
286
+ cancelled, where the campaign offers it;
178
287
  - an upsell at quantity 2 or more on a page that shows a quantity picker;
179
- - 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;
180
294
  - the coupon path, if the funnel has one;
181
295
  - the purchase event fires once, on the page the release says it should;
182
- - each SDK page on a fresh load and on a cached reload, with every
183
- `next:initialized` listener from step 3 running once on both.
296
+ - every SDK page, upsells included, on one fresh load and then five cached
297
+ reloads, with every `next:initialized` listener from step 3 running once on
298
+ each load. Count the loads per page for the hand-back. Leave out of the cached reloads
299
+ the receipt and any page where step 3 found a hand-wired purchase push or
300
+ `order:completed` listener: upsell pages reload the order and can resend a
301
+ real purchase on each load. Count purchase events across the whole run, and
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.
184
307
 
185
308
  Read each order back in the store admin (the packet run's verdict under
186
309
  `qa-output/` also lists the orders it created) and keep the order numbers for
@@ -189,5 +312,8 @@ the hand-back.
189
312
  ## 7. Hand back
190
313
 
191
314
  On the ticket or the pull request, not in the repository: what changed (pins,
192
- loader rewrites), the storage-check and doctor results, a table of test orders,
193
- what is not proven, and which orders to cancel.
315
+ loader rewrites), the storage-check and doctor results, which slugs are live and
316
+ which had no status recorded, the retired slugs that were bumped but not
317
+ proven, any new payment buttons, a table of test orders by slug, the fresh and
318
+ cached load counts per SDK page, which analytics vendors received test-order
319
+ events, what is not proven, and which orders to cancel.
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.60.0+skills.1",
4
+ "bundle_revision": "1.62.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.61",
19
+ "version": "1.0.68",
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.44",
27
+ "version": "2.0.51",
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.46",
35
+ "version": "1.0.53",
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.46",
43
+ "version": "1.1.53",
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.45",
51
+ "version": "1.3.52",
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.41",
59
+ "version": "1.0.48",
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.41",
67
+ "version": "1.0.48",
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.41",
75
+ "version": "1.0.48",
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.41",
83
+ "version": "1.0.48",
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.1",
91
+ "version": "1.0.8",
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."