@nextcommerce/campaigns-os 1.59.0 → 1.61.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 (96) hide show
  1. package/CHANGELOG.md +242 -0
  2. package/README.md +11 -10
  3. package/agents/claude/CLAUDE.md +15 -0
  4. package/agents/codex/AGENTS.md +15 -0
  5. package/agents/copilot/copilot-instructions.md +15 -0
  6. package/agents/cursor/campaigns-os.mdc +15 -0
  7. package/compatibility.json +1 -1
  8. package/contracts/brand-theme-target-tokens.next-core.v0.json +95 -25
  9. package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
  10. package/contracts/commerce-surface-catalog.json +27 -26
  11. package/contracts/release-ledger.json +1311 -0
  12. package/contracts/supported-surface.json +4 -4
  13. package/contracts/template-brand-contract.shared-commerce.v0.json +1 -1
  14. package/docs/access-model.md +20 -0
  15. package/docs/brand-theme-bridge.md +62 -3
  16. package/docs/build-packet.md +42 -13
  17. package/docs/campaign-build-brief.md +17 -1
  18. package/docs/campaigns-os-build-flow.md +62 -3
  19. package/docs/campaignspec-authoring-examples.md +116 -0
  20. package/docs/design-source-package.md +46 -2
  21. package/docs/entry-points.md +188 -0
  22. package/docs/local-setup.md +1 -1
  23. package/docs/orientation-contract-reference.md +1 -1
  24. package/docs/polish-evidence.md +41 -3
  25. package/docs/qa-and-test-orders.md +50 -2
  26. package/docs/quickstart.md +438 -0
  27. package/docs/readback.md +119 -6
  28. package/docs/runtime-readiness.md +1 -1
  29. package/docs/sdk-storage-compatibility.md +3 -1
  30. package/docs/skills-revision.md +10 -10
  31. package/docs/source-adapters.md +213 -0
  32. package/package.json +10 -3
  33. package/schemas/campaign-design-source-package.v0.schema.json +8 -0
  34. package/schemas/campaigns-os-readback.v2.schema.json +177 -1
  35. package/schemas/source-html-manifest.v0.schema.json +3 -0
  36. package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
  37. package/skills/campaign-readback-classification/SKILL.md +3 -3
  38. package/skills/campaign-run-evidence/SKILL.md +3 -3
  39. package/skills/contribution-intake/SKILL.md +3 -3
  40. package/skills/next-campaigns-build/SKILL.md +5 -5
  41. package/skills/next-campaigns-os/SKILL.md +4 -3
  42. package/skills/next-campaigns-os-setup/SKILL.md +3 -3
  43. package/skills/next-campaigns-polish/SKILL.md +12 -16
  44. package/skills/next-campaigns-qa/SKILL.md +3 -3
  45. package/skills/next-campaigns-sdk-bump/SKILL.md +286 -0
  46. package/skills.json +18 -10
  47. package/src/brand-theme.mjs +413 -8
  48. package/src/brief-summary.mjs +6 -2
  49. package/src/browser-launch.mjs +2 -1
  50. package/src/build-brief.mjs +9 -2
  51. package/src/built-site-scope.mjs +7 -14
  52. package/src/campaign-identity.mjs +6 -4
  53. package/src/cli.mjs +89 -73
  54. package/src/design-file-reference.mjs +93 -0
  55. package/src/design-source-package.mjs +55 -1
  56. package/src/doctor/checks.mjs +14 -77
  57. package/src/doctor/ci.mjs +112 -0
  58. package/src/doctor/inspect.mjs +20 -8
  59. package/src/doctor/next-step.mjs +6 -3
  60. package/src/doctor/source-provenance.mjs +74 -0
  61. package/src/evidence-debt.mjs +119 -0
  62. package/src/orchestration-stage-contract.mjs +6 -3
  63. package/src/page-kit-build-summary.mjs +21 -1
  64. package/src/page-kit-campaign-config.mjs +19 -0
  65. package/src/parity/compare.mjs +316 -0
  66. package/src/parity/design-access.mjs +54 -0
  67. package/src/parity/element-parity-record.mjs +569 -0
  68. package/src/parity/probe.mjs +205 -0
  69. package/src/parity/snapshot.mjs +110 -0
  70. package/src/png-header.mjs +87 -0
  71. package/src/polish-browser.mjs +186 -9
  72. package/src/polish-captures-record.mjs +52 -0
  73. package/src/polish-deadline.mjs +14 -0
  74. package/src/polish-gate.mjs +26 -11
  75. package/src/polish-node.mjs +81 -7
  76. package/src/polish-visual-fixtures.mjs +74 -0
  77. package/src/polish-visual.mjs +606 -0
  78. package/src/progress-node.mjs +2 -1
  79. package/src/qa-analytics-correctness.mjs +14 -2
  80. package/src/qa-analytics-parity.mjs +94 -5
  81. package/src/qa-node.mjs +39 -6
  82. package/src/qc-accept.mjs +148 -6
  83. package/src/qc-check-registry.mjs +37 -1
  84. package/src/qc-results.mjs +404 -16
  85. package/src/readback.mjs +57 -13
  86. package/src/sdk-attribute-index.mjs +11 -11
  87. package/src/sdk-markup.mjs +77 -2
  88. package/src/sdk-storage-compatibility.mjs +94 -4
  89. package/src/source-html-manifest.mjs +7 -0
  90. package/src/source-html-server.mjs +129 -0
  91. package/src/spec-derive.mjs +24 -9
  92. package/src/stage-ledger.mjs +27 -1
  93. package/src/stage-record.mjs +63 -9
  94. package/src/theme-gate.mjs +2 -2
  95. package/src/visual-diff.mjs +296 -0
  96. package/src/visual-reference.mjs +126 -0
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-build
3
- version: 1.0.42
3
+ version: 1.0.51
4
4
  description: Assemble a NEXT campaign from a doctor-cleared Build Packet, CampaignSpec/API values, prepared HTML/assets, page-kit, and starter-template contracts.
5
5
  ---
6
6
 
7
- Bundle revision: 1.59.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.59.0+skills.1`
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.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
@@ -90,7 +90,7 @@ Build rules:
90
90
  - Reproduce the source design's own proof and urgency elements as designed: reviews and testimonials, ratings, "Verified Purchase" labels, recent-purchase popups, stock counters, countdowns and guarantees. They are the merchant's content and the merchant's responsibility; Campaigns OS does not review them, so do not remove, soften or flag them. The starter templates shipping without some of these elements is not a reason to drop the source's.
91
91
  - Prepared source HTML means page-kit-ready markup, not a wholesale Liquid rewrite. Standalone HTML mockups that are meant to stay whole (their `source_screenshot` proof is of the full document) keep their document wrappers: the source-html manifest records `wrapper_policy: preserve_document_wrappers` (or `--wrapper-policy preserve_document_wrappers` on `start` / `prepare-build`), and doctor reports the wrappers as a warning. Otherwise, standalone AI/exported HTML should keep page-owned body markup, remove document wrappers, add YAML frontmatter, move shared CSS/assets into the campaign structure, and use Liquid helpers only where page-kit needs campaign-rooted links/assets/includes.
92
92
  - For `checkout`, `upsell`, `downsell`, and `receipt` pages, treat the selected starter-template commerce surface as the SDK contract reference: preserve required `data-next-*` controls, hidden fields, payment/address/totals/submit wiring, and `next_dont_touch` regions. The surrounding HTML wrapper, page composition, imagery, copy hierarchy, and brand layer are campaign/source-owned. Do not carry starter visual chrome forward when prepared source design should own that surface. QA checks what the checkout does, not family class names: do not add family shell classes (`.checkout-wrapper`, `.checkout-layout__left/right`) to the campaign's own grid or swap source-owned field markup for family includes to satisfy QA. Keep the checkout working instead: a `<form data-next-checkout="form">`, the contact and shipping fields bound with `data-next-checkout-field` inside it, and a visible cart total. A required field bound only on a `type="hidden"` input, a disabled control, a read-only input or read-only textarea, or a control with `aria-disabled="true"` does not count as bound: QA reports it in `fields_bound.missing`.
93
- - Read `context.theme` and `.campaign-runtime/theme/theme-report.json` when present. If a fresh `brand-theme.css` artifact exists, copy it into the campaign asset tree and load it after `next-core.css` on checkout, upsell, downsell, and receipt pages. If policy is `inspect_only`, either run `campaigns-os theme generate` (tier `B`: writes the theme artifacts and doctor output under the target; `--force` is tier `C`) or record an explicit skipped reason before applying a new brand layer.
93
+ - Read `context.theme` and `.campaign-runtime/theme/theme-report.json` when present. If a fresh `brand-theme.css` artifact exists, copy it into the campaign asset tree and load it after `next-core.css` on checkout, upsell, downsell, and receipt pages. When theme generate also wrote `brand-fonts.css` (the design's own `@font-face` rules for its heading and body families), copy it into the same `assets/css/` folder and load it on the same pages: without it the font tokens in `brand-theme.css` name faces the page can't load, and commerce pages fall back to the system font. `record theme` refuses a styled page that skips it. If policy is `inspect_only`, either run `campaigns-os theme generate` (tier `B`: writes the theme artifacts and doctor output under the target; `--force` is tier `C`) or record an explicit skipped reason before applying a new brand layer.
94
94
  - Generated brand-theme v0 is root-variable-only. It may skin commerce pages through next-core custom properties, but it is not permission to edit SDK-owned selectors, package controls, payment fields, totals, submit controls, receipt templates, route meta tags, or SDK JavaScript.
95
95
  - Payment, express checkout, bundle selectors, and order bumps must start from the selected family's canonical component DOM/classes, not from raw custom/source HTML with `data-next-*` added afterward. For payment specifically, preserve the family payment-method wrapper, hosted field classes, and iframe geometry assumptions (for example `input-flds spreedly-field` in shop-style templates). Skin these components with campaign tokens; do not rebuild Spreedly/card fields as arbitrary divs.
96
96
  - When a checkout page declares `exit_intent.enabled`, wire the popup as an offer application surface: use `offer_ref_id`/`offer_code` from CampaignSpec, apply the code through the SDK/API coupon/voucher path, and render applied-state copy with SDK conditionals such as `cart.hasCoupon("FREESHIP")`.
@@ -110,7 +110,7 @@ Build rules:
110
110
  - Run page-kit build and SDK/template lint available in the target repo.
111
111
  - Record build with `campaigns-os record build --packet <packet>` after every page-kit build (tier `C`: it overwrites `stages.assembly` and, when the output changed, resets `stages.polish` to `required` in the assembly report, and stamps the doctor output stale; `--dry-run` is tier `none`). It stamps `stages.assembly.build_fingerprint` with the fingerprint doctor computes from `_site/<slug>/` and the Design Source Package material fingerprint when the report has one. Never type or copy these fields by hand.
112
112
  - If `next` reports that the build output is unchanged after a brief or CampaignSpec change, rebuild so the change reaches the pages. Pass `--deviation-reason` to `record build` only when the operator explicitly decides in this conversation that the change needs no change to the built pages, and quote their reason.
113
- - Capture the machine-readable build summary as an artifact: `npx campaign-build --json > .campaign-runtime/page-kit-build-summary.json` (requires `next-campaign-page-kit` >= 0.1.4). Doctor's `built_output.build_summary` check verifies per-page build status and Page Kit shape warnings (`NESTED_NO_PERMALINK`, `DUPLICATE_OUTPUT`, `MISSING_FRONTMATTER`, `LAYOUT_NOT_FOUND`, `NO_CAMPAIGN`) from this artifact. If the installed page-kit predates `--json`, record that in the assembly report instead of skipping silently.
113
+ - Capture the machine-readable build summary as an artifact: `npx campaign-build --json > .campaign-runtime/page-kit-build-summary.json` (requires `next-campaign-page-kit` >= 0.1.4). Doctor's `built_output.build_summary` check verifies per-page build status and Page Kit shape warnings (`NESTED_NO_PERMALINK`, `DUPLICATE_OUTPUT`, `MISSING_FRONTMATTER`, `LAYOUT_NOT_FOUND`, `NO_CAMPAIGN`) from this artifact. On `next-campaign-page-kit` >= 0.3.0 it also reads the summary's top-level `assetWarnings`: each `ASSET_IGNORED` entry names an `.html` file under `assets/` that page-kit neither builds nor copies, so a link or iframe to it 404s. Move such a file out of `assets/` if it is a page, or remove it. If the installed page-kit predates `--json`, record that in the assembly report instead of skipping silently.
114
114
  - Update the assembly report with commands, evidence, warnings, blockers, and next owner. If a brand theme was applied, run `campaigns-os record theme --packet <p>` (tier `C`) after `record build`: it reads each built commerce page's stylesheet links and records `report.theme` (status applied, `load_order=after-next-core`, `css_path`, `commerce_pages`, evidence). It refuses, writing nothing, when a page that loads `next-core.css` does not load the brand layer after it. Don't hand-edit `report.theme`; a first repair-loop defect goes through `record polish`.
115
115
 
116
116
  Build does not replace polish or QA. Hand off to `next-campaigns-polish` when the campaign is runnable.
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-os
3
- version: 1.0.57
3
+ version: 1.0.66
4
4
  description: Coordinate Campaigns OS lifecycle workflows from CampaignSpec, Build Packet, starter-template contracts, stage reports, deploy evidence, and QA proof depth.
5
5
  ---
6
6
 
7
- Bundle revision: 1.59.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.59.0+skills.1`
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.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
@@ -74,6 +74,7 @@ to author a spec or fabricate a Map ID. Verify store/campaign binding and real
74
74
  package/offer references. Store contact and policy details can come from the
75
75
  brief; gateway access is optional. Current authoring is v4.3+ while preserving
76
76
  the v4.2 `funnels[]` topology as the compatibility shape.
77
+ When the HTML was exported from a design file, name it as `design_file: {file_url, type?, breakpoints?}` on the source-html manifest page; see `docs/design-source-package.md` for the shape and the Figma-only spec `design_source` provenance rule.
77
78
  2. Run `campaigns-os start` or `campaigns-os prepare-build` (tier `A`: they write the
78
79
  Build Packet, Build Context, assembly report, run session and `.gitignore` under
79
80
  the target plus a Run Record under the working directory, and they contact the
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-os-setup
3
- version: 2.0.40
3
+ version: 2.0.49
4
4
  description: Bootstrap or prepare a target page-kit campaign repo from a doctor-cleared Campaigns OS Build Packet before full build wiring. Formerly installed as next-campaigns-setup; renamed 2026-08 to stop colliding with the published NextCommerceCo/skills scaffolder of that name.
5
5
  ---
6
6
 
7
- Bundle revision: 1.59.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.59.0+skills.1`
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.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
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-polish
3
- version: 1.1.42
3
+ version: 1.1.51
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.59.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.59.0+skills.1`
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.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 @@ 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,
@@ -87,13 +87,13 @@ Responsibilities:
87
87
  evidence forward as a warning. Query or fragment text on the production
88
88
  page does not make it a distinct preview. If the hosted preview URL is not
89
89
  yet recorded, run
90
- `campaigns-os qa policy set --packet <packet> --preview-url <url>` first,
91
- then `campaigns-os next --packet <packet>`. Run
92
- `campaigns-os next qa --packet <packet>`, then
93
- `campaigns-os qa run --packet <packet> --base-url <preview-url> --browser
94
- --test-order common`. The hosted preview URL satisfies the deploy handoff;
95
- after QA records its verdict, run `campaigns-os next --packet <packet>` for
96
- closeout. QA against the packet's production URL keeps the checkpoint blocked.
90
+ `campaigns-os qa policy set --packet <packet> --preview-url <url>` first.
91
+ Then follow `campaigns-os next --packet <packet>`: it hands off
92
+ `campaigns-os record deploy --packet <packet> --base-url
93
+ <preview route root>`, then `campaigns-os qa run --packet <packet>
94
+ --base-url <preview-url> --browser --test-order common`, then closeout. QA
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.
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
98
  - Record Polish as `completed`, `skipped`, or `blocked` with
99
99
  `campaigns-os record polish --packet <packet> --evidence <polish-evidence.json>`
@@ -118,11 +118,7 @@ schema reference; this section is the recording guidance.
118
118
  **All seven evidence fields are required** or the gate blocks with
119
119
  `polish.evidence_incomplete`:
120
120
 
121
- - `visual_review` — an **object with a `screenshots` array** (aliases:
122
- `screenshot_paths`, `paths`, `urls`) holding at least one non-empty
123
- path/URL string for the captured desktop+mobile evidence, plus the
124
- package-generated `page_load` object. A bare string or a screenshot-less
125
- object does NOT pass, no matter how real the review was.
121
+ - `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.
126
122
  - `brand_review` — object; must include the `favicon` attestation and the
127
123
  `brand_bleed` attestation (below).
128
124
  - `checkout_review` — object; must include `field_labels` (aliases
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: next-campaigns-qa
3
- version: 1.3.41
3
+ version: 1.3.50
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.59.0+skills.1
8
- Run `npx --no-install campaigns-os tooling status --skills-revision 1.59.0+skills.1`
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.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
@@ -0,0 +1,286 @@
1
+ ---
2
+ name: next-campaigns-sdk-bump
3
+ version: 1.0.6
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
+ ---
6
+
7
+ Bundle revision: 1.61.0+skills.1
8
+ Run `npx --no-install campaigns-os tooling status --skills-revision 1.61.0+skills.1`
9
+ from the campaign's Page Kit folder, where it runs the project's pinned copy and
10
+ never installs one, at the start of each task. Start a fresh session if it
11
+ reports `mismatch`: this text is already in your context and is never re-read
12
+ while the CLI on disk can move under it. If the output has no `Skills revision:`
13
+ line (no `revision_check` under `--json`), a campaigns-os older than this check
14
+ answered; follow none of its actions and run the pinned copy.
15
+
16
+ # Next Campaigns SDK Bump
17
+
18
+ Use this when someone says "bump this campaign to SDK 0.4.x". The developer
19
+ installs the toolkit or approves installing it, asks for the bump, approves each push, the pull request
20
+ and each test order, then reviews and merges. Everything here uses existing
21
+ commands; there is no new write or order capability.
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
+
35
+ If `tooling status` prints `Refresh installed skills` for `--platform codex` or
36
+ `--platform agents` only, that refresh is for those harnesses; it is not
37
+ required in a session that uses neither.
38
+
39
+ In the instructions below, bare `campaigns-os …` means `npx --no-install
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
43
+ parenthetical is the declared row of `contracts/effects.v1.json`.
44
+
45
+ ## Scope: a current-SDK bump only
46
+
47
+ A bump moves a funnel from one Campaign Cart 0.4.x release to a later 0.4.x.
48
+ Before anything else, confirm every page in scope loads a 0.4.x loader. Stop
49
+ and say so if you find a 0.3.x pin or a legacy page: one whose own code calls
50
+ the Campaigns JS or the Campaigns API directly for cart and checkout. Moving
51
+ those changes bundle selection, cart calculation and more, and is migration
52
+ work, not a bump.
53
+
54
+ Judge a legacy page by what drives its cart and checkout, not by a script URL.
55
+ The 0.4.x SDK loads the Campaigns analytics script (`/js/v1/campaign/`) itself
56
+ for analytics, and some layouts also load it by hand; on a page the 0.4.x SDK
57
+ drives, that script alone is not a reason to stop.
58
+
59
+ A bump does not adopt new SDK components. Hand-written address or phone fields
60
+ stay hand-written; adopting `data-next-address` or another new component is
61
+ separate work.
62
+
63
+ ## Approval gates
64
+
65
+ Ask before every push, before opening the pull request, and before test
66
+ orders. Test orders are real orders in the store that someone may have to
67
+ cancel; follow the `next-campaigns-qa` rule: ask once up front, then follow the
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
78
+ publish from the repository root. The hand-back goes on the ticket or the pull
79
+ request.
80
+
81
+ `qa run` against a preview that is not a local address posts its verdict to the
82
+ QA portal on campaign-map.nextcommerce.com and prints the link. Say so when you
83
+ ask about test orders, and pass `--local-only` unless the developer wants the
84
+ verdict there. `qa run` writes its local verdict under `qa-output/` in the
85
+ current folder (or `--output-dir <path>`). Keep `qa-output/` out of commits:
86
+ check `.gitignore`, and never stage it.
87
+
88
+ ## 1. Branch
89
+
90
+ Branch from an up-to-date `main`. List open pull requests that touch the
91
+ campaign folder and ask the developer about merge order before branching.
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
+
104
+ ## 2. Find every pin
105
+
106
+ **Page-kit repo** (`_data/campaigns.json` exists):
107
+
108
+ - `sdk_version` on each slug's entry in `_data/campaigns.json`.
109
+ - Pages that type the version into their own loader. Search with
110
+ `grep -rn "campaign-cart@v" src`. Switch each one to
111
+ `campaign-cart@v{{ campaign.sdk_version }}` so the data file is the only pin.
112
+ A data-file-only bump leaves those pages on the old SDK. The starter
113
+ templates render with Liquid and expose the entry as `campaign`; on a page
114
+ that does not, keep a literal version instead and say so. Step 5 checks the
115
+ built pages for an unrendered `{{`.
116
+ - With a Build Packet, `campaigns-os page-kit sync --packet <packet>` (tier `B`)
117
+ writes the CampaignSpec's pin into the entry; without one, edit the entry.
118
+
119
+ **Static repo** (no `_data/campaigns.json` anywhere in the repository, root
120
+ included):
121
+
122
+ - Preview with `campaigns-os sdk repin --target <funnel folder> --target-sdk <x.y.z>`
123
+ (tier `none` without `--apply`). It lists every loader and CSS pin with path
124
+ and line.
125
+ - Scope it to the funnel folder, not the repository root. Repin rewrites every
126
+ semver pin below `--target`, so in a repository where funnels sit side by
127
+ side, a root-level `--apply` moves pages outside the bump. Check every listed
128
+ file belongs to the funnel, then run the same command with `--apply` (tier
129
+ `B`). It writes `.campaign-runtime/sdk-repin.json` under the target; that file
130
+ is served if the publish root includes it, so say so or keep it out of the
131
+ deploy.
132
+ - `sdk repin` refuses a target with `_data/campaigns.json` at or below it,
133
+ but it does not look above `--target`. A funnel folder inside a page-kit
134
+ repository is not refused, so never point `sdk repin` at one; use the
135
+ page-kit steps above.
136
+
137
+ ## 3. Read the release diff against the campaign
138
+
139
+ Read the release notes and the source diff between the two Campaign Cart tags.
140
+ For each change, search the campaign's own JavaScript, includes and markup, and
141
+ report file and line where the campaign depends on the changed behaviour. In
142
+ particular:
143
+
144
+ - Trace where the funnel's purchase event comes from before the bump. Static
145
+ funnels often hand-wire `order:completed` listeners and their own `dataLayer`
146
+ pushes; check that event's page and timing against the release you are
147
+ moving to.
148
+ - If a page shows a discount before the SDK confirms a coupon, check that the
149
+ coupon exists on every campaign the funnel uses.
150
+ - Note whether the range changes the card fields or the 3-D Secure flow; if it
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.
157
+ - When the range removes a feature the campaign uses, say so, and do not just
158
+ delete the call: that silently drops the feature from a live funnel. Look for
159
+ a documented replacement in the repository's own docs (`CLAUDE.md`,
160
+ `BUMP.md`) and the release notes. If none is documented, stop and ask.
161
+ - Classify every `next:initialized` listener. From 0.4.42 the SDK fires that
162
+ event once and does not replay it, so a deferred script that only listens for
163
+ it can miss it on a cached reload. Guard each one in the bump: run now if
164
+ `window.next` exists and `document.body.dataset.nextSdkLoading === "false"`,
165
+ otherwise wait for the event, and run once either way. Step 6 proves it.
166
+
167
+ ## 4. Storage check
168
+
169
+ Run `campaigns-os sdk storage-check --target <git-root> --target-sdk <x.y.z> --manifest <storage-migrations.v1.json> --scope <funnel folder,shared js>`
170
+ (tier `none`). Take the manifest from an unmodified checkout of the target
171
+ Campaign Cart tag (`docs/compatibility/storage-migrations.v1.json`, v0.4.40 or
172
+ later), at the highest version its supported range declares. Read each
173
+ `incompatible` and `unknown` line and say whose key it is. See
174
+ `docs/sdk-storage-compatibility.md`.
175
+
176
+ The manifest's `supportedSdkVersions` can stop below the tag it ships in: tags
177
+ v0.4.39 to v0.4.43 declare 0.4.38 to 0.4.38, so `--target-sdk 0.4.43` returns
178
+ `target-outside-manifest-range`. Run the check at the manifest's highest
179
+ version and report that it does not speak for the versions above it.
180
+
181
+ ## 5. Build and check
182
+
183
+ **Page-kit:** run a development build, confirm every built page loads only the
184
+ target version and that no built loader URL still holds an unrendered `{{`,
185
+ then `campaigns-os doctor --built <repo> --family <family> --slug <slug>`
186
+ (tier `none`) once per bumped slug, retired ones included, for a repository
187
+ with no Build Packet (`--family` as in step 6), or `campaigns-os doctor --packet <packet>`
188
+ with one. Errors that are already on `main` are recorded, not fixed. Report doctor's
189
+ advisories with the rest; an attribute flagged as missing from the SDK's index
190
+ that the page does set (for example `data-next-page-type` on `<body>`) goes in
191
+ the hand-back as unchecked, not fixed by guesswork.
192
+
193
+ **Static:** there is no build and no doctor. Re-run the repin preview (it
194
+ should list nothing below the target) and search the served pages for any
195
+ remaining old version.
196
+
197
+ ## 6. Preview proof
198
+
199
+ Deploy a preview and prove the bump with browser test orders under the
200
+ approval rule above, using the three answers you asked for up front.
201
+
202
+ Pin the run to the store's main market. The SDK picks the market from the
203
+ visitor's IP and never reads browser geolocation, so open the first page with
204
+ `?currency=<main>&country=<main>` (for example `?currency=USD&country=US`);
205
+ without them a run from another country can check out in another currency and
206
+ skip a currency-gated upsell. Both are Campaign Cart URL parameters, kept in
207
+ that tab's session storage, so put both on the first page of every new tab or
208
+ browser context. `?country=` applies only when the campaign's
209
+ `currencyBehavior` is `auto`. Before each order, confirm the page shows
210
+ that currency and the country is selected; a value the campaign does not
211
+ support falls back without failing (`currency:fallback`). On `qa run`, pass
212
+ `--currency <main>`: it tags each funnel's entry page and records the currency
213
+ in the verdict, but the runner's separate page checks open new tabs without
214
+ it. `qa run` has no country flag.
215
+
216
+ 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` does
218
+ not block them yet. Do not add `?ignore=true` to stop them: it turns off the
219
+ SDK's analytics, `dl_*` events included, for the rest of the session, so the
220
+ purchase-event check below cannot pass. Before asking for test orders, list
221
+ the vendors and name them in the question. On Page Kit, read every non-empty
222
+ vendor id in the slug's `_data/campaigns.json` entry (such as `gtm_id` and
223
+ `fb_pixel_id`) and `analytics.providers` in `config.js`; on a static page,
224
+ read its inline `nextConfig` and the tags it loads.
225
+ Say that tags a GTM container fires, pixels the pages wire by hand, and
226
+ server-side conversions sent from the order backend may also receive the
227
+ orders and are not in that config. Name in the hand-back each vendor that
228
+ received test-order events.
229
+
230
+ - With a Build Packet: `campaigns-os qa run --packet <packet> --base-url <preview-url> --currency <main> --browser --test-order common`
231
+ (tier `C`; see `next-campaigns-qa`). The runner's test orders use a US
232
+ shipping address by default. For a store whose main market is not the US,
233
+ give the runner an address in that market: add `--test-country <main>`,
234
+ `--test-address1`, `--test-city`, `--test-province` and `--test-postal`
235
+ (all five; the defaults are a US address). The runner warns when a non-USD
236
+ `--currency` has no `--test-country`. If the checkout shows no province
237
+ select for that country, or the runner cannot complete the address, run it
238
+ without `--test-order` and place the orders by hand on the market-pinned
239
+ page.
240
+ - 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`
241
+ (tier `C`) checks the served pages of one slug; run it once per live slug. Place the approved test orders in the
242
+ browser and record each order number. `--family` is the starter template the
243
+ funnel was built from, named as a template brand contract: a file
244
+ `contracts/template-brand-contract.<family>.v0.json` in the installed
245
+ package (`node_modules/@nextcommerce/campaigns-os/contracts/`), or a private
246
+ family listed in `contracts/private-template-sources.json`, which needs a
247
+ checkout of its repository beside the package or `PRIVATE_TEMPLATE_SOURCES_ROOT`
248
+ pointing at its parent; without one, stop and say so rather than use a
249
+ public family. If the
250
+ repository's `CLAUDE.md` or the developer does not say which template each
251
+ slug came from, ask; do not guess from page or folder names. Use a value only
252
+ if it exactly matches one of those contract names, and a slug only if it
253
+ exactly matches a key in `_data/campaigns.json`; otherwise ask.
254
+ - A static repo: place the approved test orders in the browser on the preview
255
+ and record each order number.
256
+
257
+ Cover:
258
+
259
+ - one card order per live checkout, on every live slug from step 1;
260
+ - PayPal cancelled, then a card order, where PayPal is offered;
261
+ - each payment or express method step 3 found the range adds, started and
262
+ cancelled, where the campaign offers it;
263
+ - 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;
265
+ - the coupon path, if the funnel has one;
266
+ - the purchase event fires once, on the page the release says it should;
267
+ - every SDK page, upsells included, on one fresh load and then five cached
268
+ reloads, with every `next:initialized` listener from step 3 running once on
269
+ each load. Count the loads per page for the hand-back. Leave out of the cached reloads
270
+ the receipt and any page where step 3 found a hand-wired purchase push or
271
+ `order:completed` listener: upsell pages reload the order and can resend a
272
+ real purchase on each load. Count purchase events across the whole run, and
273
+ list those pages' listeners as not proven on cached reloads.
274
+
275
+ Read each order back in the store admin (the packet run's verdict under
276
+ `qa-output/` also lists the orders it created) and keep the order numbers for
277
+ the hand-back.
278
+
279
+ ## 7. Hand back
280
+
281
+ On the ticket or the pull request, not in the repository: what changed (pins,
282
+ loader rewrites), the storage-check and doctor results, which slugs are live and
283
+ which had no status recorded, the retired slugs that were bumped but not
284
+ proven, any new payment buttons, a table of test orders by slug, the fresh and
285
+ cached load counts per SDK page, which analytics vendors received test-order
286
+ 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.59.0+skills.1",
4
+ "bundle_revision": "1.61.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.57",
19
+ "version": "1.0.66",
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.40",
27
+ "version": "2.0.49",
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.42",
35
+ "version": "1.0.51",
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.42",
43
+ "version": "1.1.51",
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.41",
51
+ "version": "1.3.50",
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.37",
59
+ "version": "1.0.46",
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.37",
67
+ "version": "1.0.46",
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.37",
75
+ "version": "1.0.46",
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,10 +80,18 @@
80
80
  {
81
81
  "id": "contribution-intake",
82
82
  "name": "Contribution Intake",
83
- "version": "1.0.37",
83
+ "version": "1.0.46",
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."
87
+ },
88
+ {
89
+ "id": "next-campaigns-sdk-bump",
90
+ "name": "Campaign SDK Bump",
91
+ "version": "1.0.6",
92
+ "path": "skills/next-campaigns-sdk-bump/SKILL.md",
93
+ "domain": "campaigns",
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."
87
95
  }
88
96
  ]
89
97
  }