@nextcommerce/campaigns-os 1.57.0 → 1.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +176 -0
- package/README.md +6 -5
- package/campaign-spec/dist/checkout-flow.d.ts +7 -0
- package/campaign-spec/dist/checkout-flow.js +17 -1
- package/compatibility.json +1 -1
- package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
- package/contracts/commerce-surface-catalog.json +27 -28
- package/contracts/effects.v1.json +5 -5
- package/contracts/release-ledger.json +975 -0
- package/contracts/supported-surface.json +4 -4
- package/contracts/template-brand-contract.shared-commerce.v0.json +1 -1
- package/docs/build-packet.md +35 -19
- package/docs/campaign-build-brief.md +1 -1
- package/docs/campaigns-os-build-flow.md +1 -1
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +1 -1
- package/docs/qa-and-test-orders.md +54 -12
- package/docs/runtime-readiness.md +1 -1
- package/docs/skills-revision.md +10 -10
- package/package.json +1 -1
- package/schemas/campaign-runtime-build-context.v0.schema.json +2 -1
- package/schemas/campaign-runtime-build-packet.v0.schema.json +2 -1
- package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +3 -3
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +7 -7
- package/skills/next-campaigns-os/SKILL.md +3 -3
- package/skills/next-campaigns-os-setup/SKILL.md +3 -3
- package/skills/next-campaigns-polish/SKILL.md +9 -10
- package/skills/next-campaigns-qa/SKILL.md +3 -3
- package/skills/next-campaigns-sdk-bump/SKILL.md +193 -0
- package/skills.json +18 -10
- package/src/built-site-scope.mjs +96 -12
- package/src/campaign-identity.mjs +6 -4
- package/src/cli.mjs +50 -81
- package/src/doctor/checks.mjs +79 -6
- package/src/doctor/inspect.mjs +2 -8
- package/src/doctor/next-step.mjs +9 -17
- package/src/orchestration-stage-contract.mjs +6 -3
- package/src/page-kit-build-summary.mjs +21 -1
- package/src/page-kit-campaign-config.mjs +19 -0
- package/src/polish-gate.mjs +1 -5
- package/src/polish-node.mjs +5 -4
- package/src/progress-node.mjs +2 -1
- package/src/qa-browser.mjs +137 -2
- package/src/qa-cart-entry.mjs +105 -0
- package/src/qa-node.mjs +3 -1
- package/src/qa-verdict.mjs +24 -1
- package/src/sdk-attribute-index.mjs +8 -7
- package/src/source-html-intake.mjs +27 -18
- package/src/spec-derive.mjs +24 -9
- package/src/stage-ledger.mjs +27 -1
- package/src/stage-record.mjs +218 -35
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "The downstream contract manifest. Everything listed here is SUPPORTED SURFACE: consumers (campaigns-agent, campaign-builder, the private ops repo, page-kit campaign repos) may depend on it, and changing it is a deliberate act — hashed entries require a surface_version bump in the same change (check-supported-surface.mjs --base, mirroring the skills.json bump gate), named entries must keep existing at their path, cli_commands must keep resolving in the CLI dispatch, package_exports must stay exported, and every entry must ship in the npm pack (files[] coverage). Anything NOT listed here — src/** internals, scripts/** checkers, examples/**, prompts/**, contracts/** other than this file and the entries named[] below (the orientation contract, the release ledger, and the consumer-facing orientation fixtures) — is implementation: consumers may read it for context but must not build on it, and it can change without notice. Rationale and the compatibility promise: docs/supported-surface.md.",
|
|
3
|
-
"surface_version": "1.
|
|
3
|
+
"surface_version": "1.60.0",
|
|
4
4
|
"package_exports": [
|
|
5
5
|
"./commercial-journey",
|
|
6
6
|
"./commercial-parity",
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"sha256": "625a6f2ed6bee726f9cddad750e64a54a7e03744c777f5a70afe4a39afdd9848"
|
|
65
65
|
},
|
|
66
66
|
"schemas/campaign-runtime-build-context.v0.schema.json": {
|
|
67
|
-
"sha256": "
|
|
67
|
+
"sha256": "2aa8f652f6bb602cdbadada34b5793da1bb8842223fcae2fd24700aac14f4de6"
|
|
68
68
|
},
|
|
69
69
|
"schemas/campaign-runtime-build-packet.v0.schema.json": {
|
|
70
|
-
"sha256": "
|
|
70
|
+
"sha256": "e57d31f190a7ddfbf63afb39bc67762a09dff25707c841e84a4e1c6ee9afd9ed"
|
|
71
71
|
},
|
|
72
72
|
"schemas/campaign-spec.v4.schema.json": {
|
|
73
73
|
"sha256": "af56c3de638d3c4e1fd5df8c2d733754d9ad16caa23b5bec92ce3a6f71bd0271"
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"sha256": "dfc9abed38d456969e47a21f606d308a03bdf036f3466f7d6e47a602747dacf4"
|
|
125
125
|
},
|
|
126
126
|
"contracts/effects.v1.json": {
|
|
127
|
-
"sha256": "
|
|
127
|
+
"sha256": "9c1d69e44eab7403ca3ff80f850214d89b0a02fdc51544beef37dbd0a653eeaa"
|
|
128
128
|
},
|
|
129
129
|
"schemas/campaigns-os-effects.v1.schema.json": {
|
|
130
130
|
"sha256": "3eadd22169ab98bc7c2f682af2751267605170581182158d96be035b0cfe44dc"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"asset_pin": {
|
|
57
57
|
"repo": "NextCommerceCo/campaign-cart-starter-templates",
|
|
58
|
-
"sha": "
|
|
58
|
+
"sha": "3987b18a356cb961b06c94b2035622bafe938316",
|
|
59
59
|
"path": "src/<family>/assets/<asset>",
|
|
60
60
|
"note": "asset_sha256 is the sha256 of each shipped starter asset at this commit (the commerce-surface-catalog _synced_from_sha pin; the bytes are identical across every family). A served asset whose bytes hash to the shipped value is the untouched starter asset and counts as residue even though its markup names no method; different bytes mean it was edited in place. check-template-doctrine verifies these hashes against the pinned checkout."
|
|
61
61
|
},
|
package/docs/build-packet.md
CHANGED
|
@@ -788,9 +788,13 @@ One error per finding; each names the two files and the two values, so the
|
|
|
788
788
|
repair is a one-line edit. Every built HTML file under `_site/<slug>/` is
|
|
789
789
|
scanned, because every one is served. When doctor has the CampaignSpec, a
|
|
790
790
|
finding that names a file no active spec page builds to says so and lists it
|
|
791
|
-
under `stray_files`. Such a file is leftover output
|
|
792
|
-
|
|
793
|
-
`index.html` under `assets/`.
|
|
791
|
+
under `stray_files`. Such a file is leftover output or an HTML file copied
|
|
792
|
+
into the source. On page-kit 0.2.x both happen: it does not prune `_site/`,
|
|
793
|
+
and it builds and copies a design export's `index.html` under `assets/`. From
|
|
794
|
+
0.3.0 page-kit removes `_site/<slug>/` before each build and neither builds
|
|
795
|
+
nor copies `.html` under `assets/` (the build summary lists each one as
|
|
796
|
+
`ASSET_IGNORED`), so a stray there is a source page no spec page claims or
|
|
797
|
+
output written outside a build. The repair is to remove the source file if
|
|
794
798
|
there is one, delete the built file, and rebuild and record the build again,
|
|
795
799
|
not to retag it. Pages whose route contains a `-backup-` or `-old-`
|
|
796
800
|
segment are parked copies: skipped and listed on the gate as `pages_skipped`,
|
|
@@ -828,7 +832,7 @@ Blockers (not waivable — the markup provably does not do what it says):
|
|
|
828
832
|
- `CHECKOUT_NOT_FORM` — `data-next-checkout` on an element that is not `<form>`.
|
|
829
833
|
- `WRONG_FIELD_NAME` — `data-next-checkout-field` with a value the SDK does not
|
|
830
834
|
map. The set is vendored from the SDK at a named tag
|
|
831
|
-
(`src/sdk-attribute-index.mjs`, currently v0.4.
|
|
835
|
+
(`src/sdk-attribute-index.mjs`, currently v0.4.42: `email`, `fname`, `lname`,
|
|
832
836
|
`phone`, `address1`, `address2`, `city`, `province`, `postal`, `country`,
|
|
833
837
|
`payment-method`, `accepts_marketing`, `cc-number`, `cc-month`, `cc-year`,
|
|
834
838
|
`exp-month`, `exp-year`, `cvv`, the legacy `card-*` spellings, and any
|
|
@@ -1207,6 +1211,20 @@ recorded build). `polish capture` refuses by name when the built route root is
|
|
|
1207
1211
|
missing, unreadable, or drifted; symbolic links are never build output and are
|
|
1208
1212
|
skipped by the walk.
|
|
1209
1213
|
|
|
1214
|
+
`record build` also keeps the manifest itself on `stages.assembly.build_manifest`,
|
|
1215
|
+
a sorted list of `{ "path", "sha256" }` entries that hashes to `build_fingerprint`.
|
|
1216
|
+
When the output drifts, `built_output.fingerprint_stale` and the `polish capture`
|
|
1217
|
+
refusal name the paths that are extra, missing, or changed against it, at most 20
|
|
1218
|
+
per list followed by `(+N more)`; doctor's issue `detail.drift` carries the counts
|
|
1219
|
+
and the same capped lists. An extra path shaped like a macOS or iCloud sync
|
|
1220
|
+
conflict copy (`<name> 2.<ext>`, `<name> 3.<ext>`, ...) whose unsuffixed original
|
|
1221
|
+
also exists is marked `[sync conflict copy]` with a hint to remove those copies and
|
|
1222
|
+
rebuild; a trailing number alone (`chapter 12.html`) is not flagged. A record
|
|
1223
|
+
made before build kept a manifest, or a manifest that does not hash to the recorded
|
|
1224
|
+
fingerprint, refuses as before and says the manifest is unavailable; run
|
|
1225
|
+
`record build` again to record one. Cleaning `_site/` before a build is Page Kit's
|
|
1226
|
+
job, not this check's.
|
|
1227
|
+
|
|
1210
1228
|
A stale or missing Assembly Source Package Fingerprint is waivable only as an
|
|
1211
1229
|
exceptional Source Freshness Waiver. The waiver must be structured in
|
|
1212
1230
|
`waivers[]`, with `scope: "assembly_source_package_freshness"` or an
|
|
@@ -1477,7 +1495,7 @@ Fresh `prepare-build` output also writes `source_html.pages[].page_kit` for mapp
|
|
|
1477
1495
|
- `output_path` is the same target file relative to `assembly.target_repo`.
|
|
1478
1496
|
- `public_route` is the rendered campaign-rooted route Page Kit should produce.
|
|
1479
1497
|
- `page_type` is the CPK runtime/analytics vocabulary (`product`, `checkout`, `upsell`, `receipt`), not the richer CampaignSpec or producer page type. CampaignSpec `select` and `checkout_step` pages project as CPK `checkout` because they render the SDK checkout surface ahead of the page that takes payment.
|
|
1480
|
-
- `frontmatter` names the Page Kit frontmatter fields the build should write or preserve. Beside `page_type`, `permalink`, `next_url` and `decline_url`,
|
|
1498
|
+
- `frontmatter` names the Page Kit frontmatter fields the build should write or preserve. Beside `page_type`, `permalink`, `next_url` and `decline_url`, multi-step checkout paths follow the starter-template contract. On a `select` or `checkout_step` page on a path to a Checkout, `next_url` is that Checkout's post-payment destination, the meaning `next_url` has on every checkout page, and feeds the page's `next-success-url` meta tag, which the SDK reads for express orders; `next_step` is the page's forward link, rendered as the step form's `data-next-checkout-step` or the select page's checkout link; `step_number`, on a `checkout_step` only, is its position on its path from 1, for the step form's `data-next-step-number`. A landing page keeps `next_url` as its call-to-action target, so an express landing page takes its `next-success-url` from the Checkout's `next_url`. `success_url` is no longer emitted; the schema still accepts it so packets written by 1.56.0 and 1.57.0 validate.
|
|
1481
1499
|
- `permalink_required` is true when Page Kit's filename-derived route would not match `public_route`.
|
|
1482
1500
|
|
|
1483
1501
|
An entry page (`is_entry: true`) declares the campaign root when `page_url` is
|
|
@@ -1740,7 +1758,7 @@ own stages) → calls `next` again → repeat until stage="done"
|
|
|
1740
1758
|
|
|
1741
1759
|
### Refreshing after a CampaignSpec change
|
|
1742
1760
|
|
|
1743
|
-
When the CampaignSpec's material content changes, every build, Polish and QA record made against the earlier content stops counting as current, in local-spec, saved-Map and gateway packets alike. For a saved Map or gateway packet, Campaigns OS compares the copy intake fetched; it does not check whether that copy is the latest remote revision, and reports the remote as unconfirmed. Doctor warns `spec.material_stale`, and `next`, progress, readback, the Assembly Report's own status and the QA gate show the stages that are owed again; `next` routes to the first one. Run `campaigns-os record spec --packet <packet>` to bind the new content: it updates the build context and report identity, re-reads the brief file last saved (by intake or `record brief`), keeps waivers, warning accepts, the applied theme and deploy settings, and moves each superseded stage record into that stage's `history`, which is never used as current proof. `spec derive` no longer rebinds identity; run `record spec` after it. A change to the set, order or routes of active pages still needs intake. Re-recording an unchanged build after a spec change keeps the build owed, because the change has not reached the pages, unless the operator records a reason with `--deviation-reason`; this holds even when `record spec` was not run, and that `record build` also marks Polish and QA owed again. Polish stays owed until a new `polish capture`, and QA must produce a new verdict against the current content. Polish measurements of byte-identical output keep their values, but the Polish stage is owed again. These checks are tamper evidence, not proof: a hand-written record that copies the current values, or a packet pointed at an older copy of the spec, is not detected.
|
|
1761
|
+
When the CampaignSpec's material content changes, every build, Polish and QA record made against the earlier content stops counting as current, in local-spec, saved-Map and gateway packets alike. For a saved Map or gateway packet, Campaigns OS compares the copy intake fetched; it does not check whether that copy is the latest remote revision, and reports the remote as unconfirmed. Doctor warns `spec.material_stale`, and `next`, progress, readback, the Assembly Report's own status and the QA gate show the stages that are owed again; `next` routes to the first one. Run `campaigns-os record spec --packet <packet>` to bind the new content: it updates the build context and report identity, re-reads the brief file last saved (by intake or `record brief`), keeps waivers, warning accepts, the applied theme and deploy settings, and moves each superseded stage record into that stage's `history`, which is never used as current proof. `spec derive` no longer rebinds identity; run `record spec` after it. A change to the set, order or routes of active pages still needs intake. Re-recording an unchanged build after a spec change keeps the build owed, because the change has not reached the pages, unless the operator records a reason with `--deviation-reason`; this holds even when `record spec` was not run, and that `record build` also marks Polish and QA owed again. Polish stays owed until a new `polish capture`, with one exception: when `record build --deviation-reason` records the very output a completed Polish reviewed (same build fingerprint and source package) and only the CampaignSpec changed, not the brief's presentation, that `record build` restores the Polish record the change moved to history, stamped with the current inputs. It is the same review of the same pages. QA must produce a new verdict against the current content. Polish measurements of byte-identical output keep their values, but the Polish stage is owed again. These checks are tamper evidence, not proof: a hand-written record that copies the current values, or a packet pointed at an older copy of the spec, is not detected.
|
|
1744
1762
|
|
|
1745
1763
|
The CampaignSpec's material content is the whole spec except `spec_identity`,
|
|
1746
1764
|
`slug`, `map_id` and `saved_at`; a page `label` edit is material. A spec
|
|
@@ -1786,7 +1804,7 @@ hand-editing `.campaign-runtime/` JSON:
|
|
|
1786
1804
|
| `campaigns-os record build --packet <p> [--build-environment <development\|production>] [--adapter-decision <key>=<value>[,<key>=<value>...]]` | `stages.assembly` completed with `build_fingerprint` = doctor's `derived.build_output_fingerprint.value`, `source_package_material_fingerprint` = the report's Design Source Package material fingerprint when present, `evidence.build_environment` = the `--build-environment` value when given (kept from the last record otherwise), and the specified scalar `report.adapter_decisions`; all recordable decisions go in one comma-separated flag (a repeated flag keeps only the last list); `wrapper_policy` stays an intake choice. `stages.polish` resets to `required` (`required_by` build, `required_for` qa) unless its evidence is bound to this exact output; a completed `stages.deploy` whose `source_build_fingerprint` names other output resets to `required` the same way, without the old probe's `outputs` and `evidence`, and its prior record is kept in `stages.deploy.history` (a deploy with no `source_build_fingerprint`, recorded before deploy stamped it, is kept) | doctor cannot compute the fingerprint (no `_site/<public_route_slug>/`), setup is still required, `stages.setup` is not terminal, or an adapter decision key/value is invalid |
|
|
1787
1805
|
| `campaigns-os record polish --packet <p> --evidence <file>` | `stages.polish` from the file (`docs/polish-evidence.md` §7: completed, blocked or skipped), bound to doctor's current fingerprint; `report.theme.repair_loop_defect` when the file sets it | build is not recorded for the current output, the file has a shape error (named by field), or, for a completed status, the polish gate doctor evaluates would not pass on the result |
|
|
1788
1806
|
| `campaigns-os record theme --packet <p>` | `report.theme`: status `applied`, `load_order` `after-next-core`, `css_path`, `commerce_pages` and per-page evidence read from each built commerce page's stylesheet links; any earlier theme waiver is cleared | build is not recorded for the current output, the campaign ships no commerce pages, a built commerce page that loads `next-core.css` does not load `brand-theme.css` (or `checkout-brand.css`) after it or links one missing from the built output, or no built commerce page loads `next-core.css` |
|
|
1789
|
-
| `campaigns-os record deploy --packet <p> --base-url <url>` | the packet's `deploy.preview_url` and `stages.deploy` completed with the URL in `outputs`, one evidence line per built page that answered (each page is requested under the URL first), and `source_build_fingerprint` = the recorded `stages.assembly.build_fingerprint` it probed, so a later `record build` of different output makes deploy owed again and `next` routes back to `record deploy` before QA; a byte-identical rebuild keeps it current | the
|
|
1807
|
+
| `campaigns-os record deploy --packet <p> --base-url <url>` | the packet's `deploy.preview_url` and `stages.deploy` completed with the URL in `outputs`, one evidence line per built page that answered (each page is requested under the URL first) and, on a hosted target, one per script or stylesheet served as built, and `source_build_fingerprint` = the recorded `stages.assembly.build_fingerprint` it probed, so a later `record build` of different output makes deploy owed again and `next` routes back to `record deploy` before QA; a byte-identical rebuild keeps it current | the URL does not name the campaign's route root; on a `local-serve` packet, the URL is not a loopback origin or a built page does not answer 2xx; on any other deploy target, the URL is not https (plain http only on a loopback host), a built page does not answer 200, or a script or stylesheet the built pages load from that origin is missing or served with other bytes (sha256) than the built output (each one named; HTML is not compared, since hosts inject markup); polish is not recorded, the built output changed since build was recorded, or the theme gate is blocked |
|
|
1790
1808
|
|
|
1791
1809
|
Each command also refuses a stage `next` has not reached: while doctor's
|
|
1792
1810
|
prepare-build gate is set (`next` answers prepare-build) or while an earlier
|
|
@@ -1795,17 +1813,15 @@ makes: on the local preview, a polish doctor carries forward (never recorded
|
|
|
1795
1813
|
for this build) does not hold `record deploy` back, as it does not hold `next`;
|
|
1796
1814
|
polish stays owed and QA reports it. If every mapped page is template stock on
|
|
1797
1815
|
a hosted preview, doctor carries the same missing-evidence shape forward.
|
|
1798
|
-
|
|
1799
|
-
`campaigns-os qa policy set --packet <p> --preview-url <url>`, then
|
|
1800
|
-
`campaigns-os
|
|
1816
|
+
On a hosted target, record an unset hosted preview URL with
|
|
1817
|
+
`campaigns-os qa policy set --packet <p> --preview-url <url>`, then record the
|
|
1818
|
+
deploy with `campaigns-os record deploy --packet <p> --base-url <preview url>`. The hosted preview must be a non-loopback
|
|
1801
1819
|
HTTP(S) URL whose origin or QA-resolved campaign route path differs from `deploy.production_url`;
|
|
1802
|
-
query and fragment text does not make the production page a preview. With
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
`campaigns-os next --packet <p>` reaches closeout without a hosted deploy
|
|
1808
|
-
record. QA against the packet's production URL retains the strict gate.
|
|
1820
|
+
query and fragment text does not make the production page a preview. With the
|
|
1821
|
+
deploy recorded, run `campaigns-os qa run --packet <p> --base-url <preview-url>
|
|
1822
|
+
--browser --test-order common`; after QA records a verdict for the current
|
|
1823
|
+
build, `campaigns-os next --packet <p>` reaches closeout. QA against the
|
|
1824
|
+
packet's production URL retains the strict gate.
|
|
1809
1825
|
|
|
1810
1826
|
Each command reads the same packet, Build Context and Assembly Report `next`
|
|
1811
1827
|
reads (`--context` / `--report` override them the same way), validates what it
|
|
@@ -1835,7 +1851,7 @@ build` after every page-kit build; a rebuild that changes the output needs
|
|
|
1835
1851
|
rebuilt output, `next` asks for QA again if the last QA record names the
|
|
1836
1852
|
previous build fingerprint, even while its stage status still says completed.
|
|
1837
1853
|
|
|
1838
|
-
Stage order: `setup → build → polish → deploy → qa`. The picker walks this list and returns the first stage whose recorded status isn't terminal (`completed`, `completed_with_warnings`, `skipped`)
|
|
1854
|
+
Stage order: `setup → build → polish → deploy → qa`. The picker walks this list and returns the first stage whose recorded status isn't terminal (`completed`, `completed_with_warnings`, `skipped`). During Polish, when a design route exists, install the package-owned browser first, then run `campaigns-os polish capture` against the served current build before recording a terminal `stages.polish.status` or proceeding to deploy/QA; the producer attaches package-owned `visual_review.page_load` evidence and never marks the stage complete itself. Template-stock campaigns with no design route have no capture to run and follow the preview policy above.
|
|
1839
1855
|
|
|
1840
1856
|
| Stage | Report key | Owner |
|
|
1841
1857
|
|---|---|---|
|
|
@@ -1868,7 +1884,7 @@ Result shape (with `--json`):
|
|
|
1868
1884
|
Terminal states:
|
|
1869
1885
|
|
|
1870
1886
|
- **`stage: "doctor-blocked"`** — doctor returned errors. Resolve the blockers and re-run `campaigns-os doctor` to confirm before calling `next` again.
|
|
1871
|
-
- **`stage: "done"`** — every stage is terminal
|
|
1887
|
+
- **`stage: "done"`** — every stage is terminal. Pipeline is complete. To repeat build work, do the work and use `record build`; it makes downstream stages owed as needed. Use `record setup` or `record polish` after repeating those stages. `record deploy` records the served deploy, a loopback URL for a local-serve target or an https URL for a hosted one. Use `qa run` for QA. Then call `next` again.
|
|
1872
1888
|
- **`stage_blocked: true`** — the picker returned a stage whose recorded status is `blocked`. Don't run the prompt as-is; clear the blocker first.
|
|
1873
1889
|
|
|
1874
1890
|
The legacy form `campaigns-os next <stage>` (e.g. `next build`) still works and is the way to force a specific stage when you want to override the picker.
|
|
@@ -64,7 +64,7 @@ A brief is prepared, where every open question blocks, only when the file sets `
|
|
|
64
64
|
|
|
65
65
|
Saving a brief whose content is unchanged keeps all stage evidence and statuses. Reformatting, reordering keys, writing a default value explicitly, or changing only `_meta` also keeps all stage evidence and statuses; the save may rewrite the brief files. When the presentation sections change (`campaign_intent`, `design_authority`, `brand`, `media`, `offer_presentation`, `promo_urgency`, `commerce_surfaces`, `canonical_display`, `template_residue_policy`, or any section you add), build, Polish and QA are owed again. When only `qa_policy` changes, QA alone is owed again. Setup and deploy records are kept. Each affected stage records when its inputs changed. Each replaced record is kept under the stage's `history`; the last five superseded records per stage are kept, and older ones are dropped. History is display only and is never used as current proof.
|
|
66
66
|
|
|
67
|
-
Recording build again over output that has not changed since the brief or CampaignSpec changed does not make the build current: `next` keeps asking for a build, because the change has not reached the pages. If the operator decides the change needs no change to the built pages, record build with `--deviation-reason "<the operator's reason>"`; the build is then recorded with a warning, and the reason is shown in `next` and the QC handoff. `--deviation-reason` is a general flag any caller can pass: Campaigns OS records the reason, but cannot tell whether the operator chose it. A CampaignSpec change that was never saved with `record spec` is recorded by the next `record build`, `record polish` or QA run, with the same effect; `record build` then also marks Polish and QA owed again. An edit to the brief file is not read until it is saved with `record brief`: until then the build reads the saved brief, and doctor warns `build_brief.input_unsaved`. The same applies after `prepare-build --force`, which now keeps stage history, archives the build, Polish and QA records it clears, and keeps the record that the inputs changed. Recording Polish again does not make it current until a new `polish capture` runs after the change. Recording Polish as skipped, with a skip reason, while it is owed is the operator's decision to skip it: the input change no longer makes Polish owed. The Polish gate still passes only a completed Polish, so `next` stays at Polish until one is recorded (see `docs/polish-evidence.md`).
|
|
67
|
+
Recording build again over output that has not changed since the brief or CampaignSpec changed does not make the build current: `next` keeps asking for a build, because the change has not reached the pages. If the operator decides the change needs no change to the built pages, record build with `--deviation-reason "<the operator's reason>"`; the build is then recorded with a warning, and the reason is shown in `next` and the QC handoff. `--deviation-reason` is a general flag any caller can pass: Campaigns OS records the reason, but cannot tell whether the operator chose it. A CampaignSpec change that was never saved with `record spec` is recorded by the next `record build`, `record polish` or QA run, with the same effect; `record build` then also marks Polish and QA owed again. An edit to the brief file is not read until it is saved with `record brief`: until then the build reads the saved brief, and doctor warns `build_brief.input_unsaved`. The same applies after `prepare-build --force`, which now keeps stage history, archives the build, Polish and QA records it clears, and keeps the record that the inputs changed. Recording Polish again does not make it current until a new `polish capture` runs after the change. The exception is a CampaignSpec-only change recorded with `record build --deviation-reason` over the exact output a completed Polish reviewed: that `record build` restores the Polish record, since it reviewed the same pages. A brief presentation change still owes a new Polish. Recording Polish as skipped, with a skip reason, while it is owed is the operator's decision to skip it: the input change no longer makes Polish owed. The Polish gate still passes only a completed Polish, so `next` stays at Polish until one is recorded (see `docs/polish-evidence.md`).
|
|
68
68
|
|
|
69
69
|
A build, Polish or QA record that does not say which brief and CampaignSpec content it was made against counts as unconfirmed, not current. Records made by earlier releases are unconfirmed, so after upgrading, `next` routes back to build once; record build and Polish again and run QA again. These checks are tamper evidence, not proof: a record written by hand that copies the current values or removes the record of an input change, or a packet pointed at an older copy of the spec or brief, is not detected.
|
|
70
70
|
|
|
@@ -41,7 +41,7 @@ URL.
|
|
|
41
41
|
- Starter template contracts own the SDK attribute contract and protected runtime surfaces: checkout/cart/upsell/receipt/payment/address/totals/submit controls and their required data attributes.
|
|
42
42
|
- Designed source owns visual composition, content hierarchy, imagery, and page-level copy.
|
|
43
43
|
|
|
44
|
-
Packages identify sellable products or variants, and Offers own campaign price changes. Package Retail Price/Quantity fields
|
|
44
|
+
Packages identify sellable products or variants, and Offers own campaign price changes. The Campaigns App dashboard calls packages **Products** and creates one per variant when an Offer that selects it is saved, so a campaign set up there has one package per variant and a separate Offer for each Buy 1/2/3 tier. Package Retail Price/Quantity fields and multi-unit packages exist on older campaigns that have the legacy **Enable Package Retail Price & Quantity** setting on (see the "Older Campaigns" section of [Campaign Products](https://docs.nextcommerce.com/docs/apps/campaigns-app/build-campaign-packages)), but assembly should not introduce them for new tier pricing.
|
|
45
45
|
|
|
46
46
|
## Offer Application Surfaces
|
|
47
47
|
|
package/docs/local-setup.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
For a new campaign, create an empty working folder and run this from it:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npm init -y && npm install --save-exact next-campaign-page-kit@0.
|
|
6
|
+
npm init -y && npm install --save-exact next-campaign-page-kit@0.3.0 && npm install --save-dev --save-exact @nextcommerce/campaigns-os@1.60.0 && npx --no-install campaigns-os tooling setup --target . --platform claude
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
`npm init -y` gives the folder its own `package.json`. Without one, npm
|
|
@@ -26,7 +26,7 @@ Ledger schema id: `campaigns-os-release-ledger/v1`
|
|
|
26
26
|
Change policy version: `1.0.0`
|
|
27
27
|
Reason-code vocabulary version: `1.0.0`
|
|
28
28
|
Limits version: `1.0.0`
|
|
29
|
-
Supported surface at generation time: `1.
|
|
29
|
+
Supported surface at generation time: `1.60.0`
|
|
30
30
|
|
|
31
31
|
## Forward compatibility
|
|
32
32
|
|
package/docs/polish-evidence.md
CHANGED
|
@@ -37,7 +37,7 @@ The gate only applies once assembly is complete
|
|
|
37
37
|
| `status` | `stages.polish.status` | Must start with `completed`. `blocked` → `polish.blocked`; anything else → `polish.evidence_missing`. |
|
|
38
38
|
| `performed_by` | `stages.polish.performed_by`, `stages.polish.command_identity`, `evidence.performed_by` | Must be exactly `next-campaigns-polish`. Anything else (including missing) → `polish.self_certified`. |
|
|
39
39
|
| `commands` | `stages.polish.commands` and/or `evidence.commands` | Must NOT mention a build command anywhere — a polish record that ran build is self-certification → `polish.self_certified`. The matcher is exactly the strings `next-campaigns-build` and `campaigns-os next build` (case-insensitive); other build tooling (e.g. page-kit's `campaign-build`) is not matched. |
|
|
40
|
-
| `source_build_fingerprint` | `stages.polish.source_build_fingerprint` or `evidence.source_build_fingerprint` | Required, and must equal the current build fingerprint (`stages.assembly.build_fingerprint
|
|
40
|
+
| `source_build_fingerprint` | `stages.polish.source_build_fingerprint` or `evidence.source_build_fingerprint` | Required, and must equal the current build fingerprint (`stages.assembly.build_fingerprint`). Missing → `polish.source_build_fingerprint_missing`; different → `polish.stale`. Doctor, QA, and `polish capture` also recompute the fingerprint from the built output under `_site/<slug>/` (algorithm in `docs/build-packet.md`); when the output no longer matches the recorded value the gate is `polish.output_drift` with `current_output_fingerprint` and a `rerun_build` action, whatever the recorded string says. |
|
|
41
41
|
| `source_package_material_fingerprint` | `stages.polish.source_package_material_fingerprint` or `evidence.source_package_material_fingerprint` | Only enforced when the report carries a current Design Source Package material fingerprint (`design_source_package.material_fingerprint` or equivalents). Missing → `polish.source_package_material_fingerprint_missing`; different → `polish.source_package_stale`. |
|
|
42
42
|
| `completed_at` | `stages.polish.completed_at` or `evidence.completed_at` | Required non-empty timestamp string → else `polish.completed_at_missing`. |
|
|
43
43
|
|
|
@@ -119,15 +119,14 @@ checks are carried forward:
|
|
|
119
119
|
|
|
120
120
|
A carried-forward gate has status `carried_forward`. Doctor reports it as a
|
|
121
121
|
warning starting "Carried forward on the local preview" or "Carried forward on the hosted preview"; `next` moves past
|
|
122
|
-
polish to deploy and QA
|
|
122
|
+
polish to deploy and QA; QA records it as a `warn` row, so the verdict is at
|
|
123
123
|
best `ready_with_exceptions`. The evidence is reported as missing, never as
|
|
124
124
|
passed. On a hosted all-template preview, first record an unset preview URL
|
|
125
125
|
with `campaigns-os qa policy set --packet <packet> --preview-url <url>`, then
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
carried forward. The hosted exception
|
|
126
|
+
record the deploy with `campaigns-os record deploy --packet <packet> --base-url <preview-url>`
|
|
127
|
+
(on a hosted target it takes an https URL, requires every built page to answer
|
|
128
|
+
200, and compares the served scripts and stylesheets with the build by sha256),
|
|
129
|
+
then run `campaigns-os qa run --packet <packet> --base-url <preview-url> --browser --test-order common`. After QA records the current-build verdict, run `campaigns-os next --packet <packet>` for closeout. The hosted exception
|
|
131
130
|
requires a distinct packet `deploy.preview_url`; a query or fragment on the production page does not count as distinct. QA with `--base-url` equal to
|
|
132
131
|
the packet's `deploy.production_url` stays blocked. A `local-serve` packet
|
|
133
132
|
served from any other host also gets strict gates. `record polish` and the
|
|
@@ -1345,6 +1344,7 @@ Assembly Report's `stages.qa`:
|
|
|
1345
1344
|
"declared_order_path_depth": "common",
|
|
1346
1345
|
"declared_typed_card_depth": "common",
|
|
1347
1346
|
"order_paths_executed": 3,
|
|
1347
|
+
"test_order_attempts": 3,
|
|
1348
1348
|
"orders_created": 3,
|
|
1349
1349
|
"orders_verified": 3,
|
|
1350
1350
|
"all_orders_test_mode": true
|
|
@@ -1357,7 +1357,9 @@ readback bundle, where the verdict's own order arrays are deliberately emptied
|
|
|
1357
1357
|
(see the committed verdict sidecar above) — so the signal that a purchase
|
|
1358
1358
|
happened has to be numbers, not the orders themselves. `all_orders_test_mode` is
|
|
1359
1359
|
`null`, not `false`, when nothing ran: "no order left test mode" and "no order
|
|
1360
|
-
ran" are different facts.
|
|
1360
|
+
ran" are different facts. `order_paths_executed` counts planned paths and
|
|
1361
|
+
`test_order_attempts` counts every attempt, so a re-run adds an attempt and not a
|
|
1362
|
+
path.
|
|
1361
1363
|
|
|
1362
1364
|
Beside it, `stages.qa.evidence` carries the build the verdict judged and the
|
|
1363
1365
|
outcome of the gates doctor's static scan can only approximate:
|
|
@@ -1554,16 +1556,49 @@ Evidence: `landing_url`, `landing_page_id`, `landing_page_type`,
|
|
|
1554
1556
|
`landing_resolution` (`routes_into_checkout`, `entry_page_fallback`,
|
|
1555
1557
|
`first_page_fallback`), `control_text`, `control_kind` (`add_to_cart`,
|
|
1556
1558
|
`checkout_link`, or `checkout_button`), `package_id`, `bundle_card_selection`
|
|
1557
|
-
when `--select-package` clicked a bundle card, `
|
|
1559
|
+
when `--select-package` clicked a bundle card, `variant_selections` when the
|
|
1560
|
+
runner chose slot variants (below), `sdk_ready`, `arrived_url`, the
|
|
1558
1561
|
`checkout_selection_surface` probe result, `selection_surface_probe`
|
|
1559
1562
|
(`loaded`, `reused`, or `failed`), and `selection_surface_probe_error` when it
|
|
1560
1563
|
failed. The failure codes are
|
|
1561
1564
|
`cart_entry_unresolved` (no selection surface on checkout and no entry page
|
|
1562
1565
|
resolves from the topology), `cart_entry_control_missing` (the entry page
|
|
1563
1566
|
renders no control, or none carrying the requested ref), and
|
|
1564
|
-
`cart_entry_no_navigation` (the click did not reach the checkout URL)
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
+
`cart_entry_no_navigation` (the click did not reach the checkout URL), and
|
|
1568
|
+
`cart_entry_variant_unfilled` (a bundle slot's variant control has no in-stock
|
|
1569
|
+
option or row, or its row could not be clicked, named by slot). Each fails the path inside the step budget with the
|
|
1570
|
+
code as the first word of the error, never as a step timeout.
|
|
1571
|
+
|
|
1572
|
+
On a select page whose bundle slots each need a variant (size, colour) before
|
|
1573
|
+
Next, the runner chooses one per slot after any bundle card click and before
|
|
1574
|
+
the checkout control, one field at a time. It looks at every visible, enabled
|
|
1575
|
+
slot variant select (`[data-next-variant-selectors] select` or
|
|
1576
|
+
`.next-slot-variant-field select`, the native select the SDK renders, counted
|
|
1577
|
+
visible when its field is):
|
|
1578
|
+
|
|
1579
|
+
- When the field shows a dropdown UI (an `os-dropdown` with a
|
|
1580
|
+
`.os-card__variant-dropdown-toggle` and `os-dropdown-item` rows, as the
|
|
1581
|
+
olympus-mv-two-step starter renders), the runner clicks the toggle and then a
|
|
1582
|
+
row, like a shopper, even when the select is already filled. A page may count
|
|
1583
|
+
a field as chosen only when a row was clicked. It clicks the row matching the
|
|
1584
|
+
select's current value when that row is in stock, so the cart stays what the
|
|
1585
|
+
SDK chose, and otherwise the first in-stock row. After the toggle click it
|
|
1586
|
+
finds the field again by slot identity and the row again by its value, and
|
|
1587
|
+
waits up to 2 s for that row to show, so a menu that opens late or re-renders
|
|
1588
|
+
its rows is handled.
|
|
1589
|
+
- With no dropdown UI, an empty select gets its first in-stock option, with
|
|
1590
|
+
`input` and `change` dispatched. A filled native select is left alone.
|
|
1591
|
+
|
|
1592
|
+
In stock means enabled, not hidden, and with a non-empty value. For a row it
|
|
1593
|
+
also means not `[disabled]`, `aria-disabled`, `.next-oos`,
|
|
1594
|
+
`.next-variant-unavailable` or `data-available="false"`, and that the row's
|
|
1595
|
+
native option is not disabled. Each choice is recorded in
|
|
1596
|
+
`variant_selections` as `{ bundle_id, slot, variant_code, value, via }`, where
|
|
1597
|
+
`via` is `dropdown` or `select`, so the ordered variants can be checked against
|
|
1598
|
+
the cart lines. A field with nothing to choose, or a row that does not show
|
|
1599
|
+
or cannot be clicked, fails the path with `cart_entry_variant_unfilled` before Next is
|
|
1600
|
+
clicked. A page whose filled selects have no dropdown UI is left untouched and
|
|
1601
|
+
`variant_selections` is omitted.
|
|
1567
1602
|
|
|
1568
1603
|
Which page a funnel enters the cart from is still inferred from topology and
|
|
1569
1604
|
the rendered checkout. Recording it authoritatively on the spec is the open
|
|
@@ -1840,7 +1875,7 @@ deciding what to do next, it classifies what the attempt did to the store:
|
|
|
1840
1875
|
|
|
1841
1876
|
| Classification | What it means | What the runner does |
|
|
1842
1877
|
|---|---|---|
|
|
1843
|
-
| `not_created` | The path failed before the checkout was submitted (including the runner's own named refusals: `cart_entry_unresolved`, `cart_entry_control_missing`, `cart_entry_no_navigation`, `cart_empty_before_submit`), or the platform rejected every order create it saw. Nothing reached the store. | Re-runs the path once, if the creation budget has a slot no still-unrun planned path needs. This is the bounded retry for a transient miss; the re-run decides the assertion. |
|
|
1878
|
+
| `not_created` | The path failed before the checkout was submitted (including the runner's own named refusals: `cart_entry_unresolved`, `cart_entry_control_missing`, `cart_entry_no_navigation`, `cart_entry_variant_unfilled`, `cart_empty_before_submit`), or the platform rejected every order create it saw. Nothing reached the store. | Re-runs the path once, if the creation budget has a slot no still-unrun planned path needs. This is the bounded retry for a transient miss; the re-run decides the assertion. |
|
|
1844
1879
|
| `created` | An order exists and was read back — the failure happened after the purchase (most often a receipt that did not render its line items). | Runs a **read-only recovery pass**: reloads the receipt the order already produced, re-reads the persisted order, and re-checks the buyer-visible receipt surface and the voucher read-back. It clicks nothing, applies nothing, and submits nothing. |
|
|
1845
1880
|
| `ambiguous` | The submit may have created an order this runner cannot see: a ref id with an unusable read-back, a lost create response, a network-failed create, or a 4xx that follows an earlier 2xx on the same endpoint. | Stops. It never resubmits, and the assertion names the check an operator should run — look for an existing order against the run's QA email or the observed ref id. |
|
|
1846
1881
|
|
|
@@ -1865,6 +1900,13 @@ is not re-run and its assertion records why under
|
|
|
1865
1900
|
re-runs for those paths. A re-run that stops on the budget never becomes the
|
|
1866
1901
|
deciding result: it proved nothing, so the first attempt's real failure stands.
|
|
1867
1902
|
|
|
1903
|
+
Every attempt is its own `test_orders[]` entry, because a re-run can place its
|
|
1904
|
+
own real order. Each entry carries `plan_id`, the planned path it belongs to,
|
|
1905
|
+
and `attempt`, 1 for the first try and 2 for the re-run, so a run with five
|
|
1906
|
+
planned paths that each re-ran once holds ten entries for five paths. The
|
|
1907
|
+
`qa run` summary prints the three counts apart, for example
|
|
1908
|
+
`Test orders: 5 paths, 10 attempts, 0 orders created`.
|
|
1909
|
+
|
|
1868
1910
|
Recovery may only clear a failure on evidence it actually re-read. If the
|
|
1869
1911
|
receipt reload's persisted-order read-back fails or never happens, the pass stops
|
|
1870
1912
|
honestly: the read-back failure is itself a remaining failure, and the receipt
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
How a checkout of this repository at one commit becomes a usable installed runtime, and how a consumer decides whether a prepared one is still trustworthy. Everything below is generated from `contracts/runtime-recipe.campaigns-os-node-v1.json`, which is the only authority for these values.
|
|
10
10
|
|
|
11
|
-
Recipe kind `campaigns-os-node-v1`, revision `1.0.3`, validated by `schemas/campaigns-os-runtime-recipe.v1.schema.json` (`Campaigns OS Runtime Recipe v1`). Supported surface at generation time: `1.
|
|
11
|
+
Recipe kind `campaigns-os-node-v1`, revision `1.0.3`, validated by `schemas/campaigns-os-runtime-recipe.v1.schema.json` (`Campaigns OS Runtime Recipe v1`). Supported surface at generation time: `1.60.0`.
|
|
12
12
|
|
|
13
13
|
## What this is
|
|
14
14
|
|
package/docs/skills-revision.md
CHANGED
|
@@ -16,7 +16,7 @@ that the copy on disk moved.
|
|
|
16
16
|
`skills.json` carries one top-level field:
|
|
17
17
|
|
|
18
18
|
```json
|
|
19
|
-
"bundle_revision": "1.
|
|
19
|
+
"bundle_revision": "1.60.0+skills.1"
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
The spelling is `<package version>+skills.<n>`:
|
|
@@ -25,7 +25,7 @@ The spelling is `<package version>+skills.<n>`:
|
|
|
25
25
|
skills ship with (`check-skill-versions.mjs` fails if the two disagree);
|
|
26
26
|
- `<n>` is a plain counter, not a semver component. It says "this is the *n*th
|
|
27
27
|
skill-text revision published against that package version" and it **resets
|
|
28
|
-
with the prefix**. `1.
|
|
28
|
+
with the prefix**. `1.60.0+skills.1` is therefore ahead of `1.40.0+skills.7`.
|
|
29
29
|
|
|
30
30
|
It is one identity for the bundle as a whole, on purpose. Per-skill versions
|
|
31
31
|
still exist and still gate per-skill changes, but an agent that loaded one skill
|
|
@@ -37,7 +37,7 @@ The first body line of every bundled `SKILL.md`, immediately after the
|
|
|
37
37
|
frontmatter, is exactly:
|
|
38
38
|
|
|
39
39
|
```
|
|
40
|
-
Bundle revision: 1.
|
|
40
|
+
Bundle revision: 1.60.0+skills.1
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
followed by a short paragraph telling the agent to run the check below at the
|
|
@@ -48,7 +48,7 @@ text the agent is actually reading, not from a file it would have to go and open
|
|
|
48
48
|
## The check
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
51
|
+
npx --no-install campaigns-os tooling status --skills-revision 1.60.0+skills.1
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
The value is compared against the bundle revision of the **CLI the command runs
|
|
@@ -90,20 +90,20 @@ reports the choice as `skills.scope` (`requested`, `installed_platforms`, or
|
|
|
90
90
|
"revision_check": "match",
|
|
91
91
|
"skills_revision": {
|
|
92
92
|
"status": "match",
|
|
93
|
-
"requested": "1.
|
|
93
|
+
"requested": "1.60.0+skills.1",
|
|
94
94
|
"spelling": "bundle",
|
|
95
|
-
"on_disk": "1.
|
|
95
|
+
"on_disk": "1.60.0+skills.1",
|
|
96
96
|
"on_disk_skill": null,
|
|
97
|
-
"message": "match (1.
|
|
97
|
+
"message": "match (1.60.0+skills.1)"
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
The text view prints one named line, as a header above the rest of the status:
|
|
102
102
|
|
|
103
103
|
```
|
|
104
|
-
Skills revision: match (1.
|
|
105
|
-
Skills revision: mismatch: loaded 1.39.0+skills.1, on disk 1.
|
|
106
|
-
Skills revision: unchecked (on disk 1.
|
|
104
|
+
Skills revision: match (1.60.0+skills.1)
|
|
105
|
+
Skills revision: mismatch: loaded 1.39.0+skills.1, on disk 1.60.0+skills.1 — start a fresh session
|
|
106
|
+
Skills revision: unchecked (on disk 1.60.0+skills.1)
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
`unchecked` is the state when the flag is absent. It is not an error — an
|
package/package.json
CHANGED
|
@@ -192,7 +192,8 @@
|
|
|
192
192
|
"permalink": { "type": "string", "minLength": 1 },
|
|
193
193
|
"next_url": { "type": "string", "minLength": 1 },
|
|
194
194
|
"decline_url": { "type": "string", "minLength": 1 },
|
|
195
|
-
"
|
|
195
|
+
"next_step": { "type": "string", "minLength": 1, "description": "On a select or checkout_step page on a path to a Checkout: this page's forward link, for the step form's data-next-checkout-step or the select page's checkout link. next_url on such a page is the Checkout's post-payment destination, for the next-success-url meta tag the SDK reads for express orders (campaign-cart-starter-templates#223)." },
|
|
196
|
+
"success_url": { "type": "string", "minLength": 1, "description": "No longer emitted: the starter templates read the post-payment destination from next_url and the forward link from next_step. Accepted so packets written by 1.56.0 and 1.57.0 still validate." },
|
|
196
197
|
"step_number": { "type": "integer", "minimum": 1, "description": "On a checkout_step page: its position among its path's steps, from 1, for the step form's data-next-step-number." }
|
|
197
198
|
}
|
|
198
199
|
}
|
|
@@ -194,7 +194,8 @@
|
|
|
194
194
|
"permalink": { "type": "string", "minLength": 1 },
|
|
195
195
|
"next_url": { "type": "string", "minLength": 1 },
|
|
196
196
|
"decline_url": { "type": "string", "minLength": 1 },
|
|
197
|
-
"
|
|
197
|
+
"next_step": { "type": "string", "minLength": 1, "description": "On a select or checkout_step page on a path to a Checkout: this page's forward link, for the step form's data-next-checkout-step or the select page's checkout link. next_url on such a page is the Checkout's post-payment destination, for the next-success-url meta tag the SDK reads for express orders (campaign-cart-starter-templates#223)." },
|
|
198
|
+
"success_url": { "type": "string", "minLength": 1, "description": "No longer emitted: the starter templates read the post-payment destination from next_url and the forward link from next_step. Accepted so packets written by 1.56.0 and 1.57.0 still validate." },
|
|
198
199
|
"step_number": { "type": "integer", "minimum": 1, "description": "On a checkout_step page: its position among its path's steps, from 1, for the step form's data-next-step-number." }
|
|
199
200
|
}
|
|
200
201
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: campaign-lifecycle-orientation
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.41
|
|
4
4
|
description: Orient a reader to the Campaigns OS lifecycle artifacts a run has already emitted, without advancing any stage or changing any state.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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: campaign-readback-classification
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.41
|
|
4
4
|
description: Classify a selected campaign from the readback projection's v2 fields and write a read-only handoff without turning diagnosis into permission.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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: campaign-run-evidence
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.41
|
|
4
4
|
description: Interpret existing Campaigns OS doctor, QA and proof-depth evidence without claiming more proof than the artifacts contain.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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: contribution-intake
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.41
|
|
4
4
|
description: Turn a suggestion about the agent surface into a classified, evidence-checked proposal and, only with attended approval, one issue on this repository's tracker.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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-build
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.46
|
|
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.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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
|
|
@@ -100,9 +100,9 @@ Build rules:
|
|
|
100
100
|
- If setup/build needs starter-template files, copy the template family atomically with its dependent pages, `_includes/`, `_layouts/`, `assets/css/`, and `assets/js/`; copying only checkout/receipt pages is incomplete.
|
|
101
101
|
- Resolve SDK routing meta tags to deployed campaign-root paths, not spec literals. For example, `next-success-url: upsell/` in the spec should become `/<public_route_slug>/upsell/` in built HTML.
|
|
102
102
|
- If an order bump package comes from `packages.prepurchase_*` and is not one of the main `bundles[]`, default `package_sync=false` and `show_line_total_price=false` unless the CampaignSpec explicitly says the add-on quantity must sync with the main bundle.
|
|
103
|
-
- Multi-step checkout paths run `select` → `checkout_step`… → `checkout`; only the `checkout` page takes payment. On a `select` page the swap-mode bundle selector (`data-next-bundle-selector` with `data-next-selection-mode="swap"`) writes the cart and the SDK persists it between pages; a checkout button or link (`href` from the page's `
|
|
104
|
-
- Each `checkout_step` page's checkout form (`<form data-next-checkout="form">`) carries `data-next-checkout-step="<its
|
|
105
|
-
- On
|
|
103
|
+
- Multi-step checkout paths run `select` → `checkout_step`… → `checkout`; only the `checkout` page takes payment. On a `select` page the swap-mode bundle selector (`data-next-bundle-selector` with `data-next-selection-mode="swap"`) writes the cart and the SDK persists it between pages; a checkout button or link (`href` from the page's `next_step`) goes to the next page. Use `forcePackageId` only on a page with no selector, such as a landing call-to-action into a checkout that renders none.
|
|
104
|
+
- Each `checkout_step` page's checkout form (`<form data-next-checkout="form">`) carries `data-next-checkout-step="<its next_step>"` and `data-next-step-number="<step_number>"` (frontmatter `next_step` and `step_number`, 1 for the first step on its path). The `checkout` page's form carries neither.
|
|
105
|
+
- On `select` and `checkout_step` pages, frontmatter `next_url` is the Checkout's post-payment destination, the same meaning it has on the `checkout` page, and the layout renders it as the `next-success-url` meta tag: the SDK reads that tag for express orders placed on the page. `next_step` is the page's forward link. A landing page keeps `next_url` as its call-to-action target; if it has express checkout buttons, set its `next-success-url` to the Checkout's own `next_url` from the Build Context `page_map`, never to the landing page's `next_url`. Forward navigation uses the step form attribute or a plain link, never that meta tag. Page Kit frontmatter has no `success_url` key; `success_url` stays a CampaignSpec field on `checkout` pages.
|
|
106
106
|
- Record intentional drops from source HTML in the assembly report, especially payment/provider changes such as "PayPal removed because CampaignSpec available_payment_methods excludes it." Polish must inherit these decisions.
|
|
107
107
|
- Preserve any existing Build Context `theme` inspection state and Assembly Report `theme` application state. If build applies, skips, or invalidates generated theme CSS, update `report.theme` rather than leaving stale evidence.
|
|
108
108
|
- After page-kit build, inspect rendered `_site` output: body exists, Campaign Cart runtime markers exist, `sdk_hints.meta_tags` rendered, route meta points at the campaign root, and copied funnel attribution/runtime baggage is gone.
|
|
@@ -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.
|
|
3
|
+
version: 1.0.61
|
|
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.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.60.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.60.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
|