@nextcommerce/campaigns-os 1.47.0 → 1.50.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 (53) hide show
  1. package/CHANGELOG.md +307 -0
  2. package/README.md +30 -3
  3. package/agents/claude/CLAUDE.md +6 -3
  4. package/agents/codex/AGENTS.md +6 -4
  5. package/agents/copilot/copilot-instructions.md +3 -2
  6. package/agents/cursor/campaigns-os.mdc +3 -3
  7. package/compatibility.json +1 -1
  8. package/contracts/commerce-surface-catalog.json +17 -17
  9. package/contracts/effects.v1.json +173 -0
  10. package/contracts/release-ledger.json +798 -0
  11. package/contracts/supported-surface.json +4 -4
  12. package/contracts/template-brand-contract.shared-commerce.v0.json +1 -1
  13. package/docs/brand-theme-bridge.md +12 -6
  14. package/docs/build-packet.md +9 -4
  15. package/docs/campaign-build-brief.md +25 -28
  16. package/docs/local-setup.md +7 -2
  17. package/docs/orientation-contract-reference.md +1 -1
  18. package/docs/qa-and-test-orders.md +70 -9
  19. package/docs/runtime-readiness.md +1 -1
  20. package/docs/skills-revision.md +10 -10
  21. package/package.json +1 -1
  22. package/schemas/campaign-runtime-build-packet.v0.schema.json +4 -0
  23. package/schemas/campaigns-os-qa-verdict.v0.schema.json +8 -3
  24. package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
  25. package/skills/campaign-readback-classification/SKILL.md +3 -3
  26. package/skills/campaign-run-evidence/SKILL.md +9 -4
  27. package/skills/contribution-intake/SKILL.md +3 -3
  28. package/skills/next-campaigns-build/SKILL.md +5 -4
  29. package/skills/next-campaigns-os/SKILL.md +3 -3
  30. package/skills/next-campaigns-os-setup/SKILL.md +3 -3
  31. package/skills/next-campaigns-polish/SKILL.md +6 -5
  32. package/skills/next-campaigns-qa/SKILL.md +3 -3
  33. package/skills.json +10 -10
  34. package/src/brand-theme.mjs +13 -2
  35. package/src/cli.mjs +17 -12
  36. package/src/content-residue.mjs +18 -90
  37. package/src/doctor/checks.mjs +21 -29
  38. package/src/doctor/inspect.mjs +13 -3
  39. package/src/doctor/next-step.mjs +4 -0
  40. package/src/gate-actions.mjs +8 -0
  41. package/src/install-mode.mjs +0 -8
  42. package/src/invocation.mjs +3 -1
  43. package/src/local-preview-policy.mjs +92 -0
  44. package/src/page-kit-sdk-version.mjs +8 -1
  45. package/src/polish-node.mjs +26 -2
  46. package/src/progress-node.mjs +5 -1
  47. package/src/qa-binding-evidence.mjs +22 -1
  48. package/src/qa-browser.mjs +92 -14
  49. package/src/qa-node.mjs +43 -6
  50. package/src/readback.mjs +19 -10
  51. package/src/source-prep.mjs +1 -1
  52. package/src/stage-record.mjs +303 -22
  53. package/src/theme-gate.mjs +3 -3
@@ -849,8 +849,8 @@
849
849
  },
850
850
  "verification": {
851
851
  "sdk_version": "0.4.40",
852
- "verified_at": "2026-10-01T04:56:01Z",
853
- "evidence": "sdk-0.4.40-2026-10-01",
852
+ "verified_at": "2026-10-01T16:01:10Z",
853
+ "evidence": "sdk-0.4.40-2026-10-01.2",
854
854
  "status": "certified",
855
855
  "source": "template-verification.json"
856
856
  }
@@ -1273,8 +1273,8 @@
1273
1273
  },
1274
1274
  "verification": {
1275
1275
  "sdk_version": "0.4.40",
1276
- "verified_at": "2026-10-01T04:56:01Z",
1277
- "evidence": "sdk-0.4.40-2026-10-01",
1276
+ "verified_at": "2026-10-01T16:01:10Z",
1277
+ "evidence": "sdk-0.4.40-2026-10-01.2",
1278
1278
  "status": "certified",
1279
1279
  "source": "template-verification.json"
1280
1280
  }
@@ -1584,8 +1584,8 @@
1584
1584
  },
1585
1585
  "verification": {
1586
1586
  "sdk_version": "0.4.40",
1587
- "verified_at": "2026-10-01T04:56:01Z",
1588
- "evidence": "sdk-0.4.40-2026-10-01",
1587
+ "verified_at": "2026-10-01T16:01:10Z",
1588
+ "evidence": "sdk-0.4.40-2026-10-01.2",
1589
1589
  "status": "certified",
1590
1590
  "source": "template-verification.json"
1591
1591
  }
@@ -1887,8 +1887,8 @@
1887
1887
  },
1888
1888
  "verification": {
1889
1889
  "sdk_version": "0.4.40",
1890
- "verified_at": "2026-10-01T04:56:01Z",
1891
- "evidence": "sdk-0.4.40-2026-10-01",
1890
+ "verified_at": "2026-10-01T16:01:10Z",
1891
+ "evidence": "sdk-0.4.40-2026-10-01.2",
1892
1892
  "status": "certified",
1893
1893
  "source": "template-verification.json"
1894
1894
  }
@@ -2228,8 +2228,8 @@
2228
2228
  },
2229
2229
  "verification": {
2230
2230
  "sdk_version": "0.4.40",
2231
- "verified_at": "2026-10-01T04:56:01Z",
2232
- "evidence": "sdk-0.4.40-2026-10-01",
2231
+ "verified_at": "2026-10-01T16:01:10Z",
2232
+ "evidence": "sdk-0.4.40-2026-10-01.2",
2233
2233
  "status": "certified",
2234
2234
  "source": "template-verification.json"
2235
2235
  }
@@ -2667,8 +2667,8 @@
2667
2667
  },
2668
2668
  "verification": {
2669
2669
  "sdk_version": "0.4.40",
2670
- "verified_at": "2026-10-01T04:56:01Z",
2671
- "evidence": "sdk-0.4.40-2026-10-01",
2670
+ "verified_at": "2026-10-01T16:01:10Z",
2671
+ "evidence": "sdk-0.4.40-2026-10-01.2",
2672
2672
  "status": "certified",
2673
2673
  "source": "template-verification.json"
2674
2674
  }
@@ -3024,8 +3024,8 @@
3024
3024
  },
3025
3025
  "verification": {
3026
3026
  "sdk_version": "0.4.40",
3027
- "verified_at": "2026-10-01T04:56:01Z",
3028
- "evidence": "sdk-0.4.40-2026-10-01",
3027
+ "verified_at": "2026-10-01T16:01:10Z",
3028
+ "evidence": "sdk-0.4.40-2026-10-01.2",
3029
3029
  "status": "certified",
3030
3030
  "source": "template-verification.json"
3031
3031
  }
@@ -3314,8 +3314,8 @@
3314
3314
  },
3315
3315
  "verification": {
3316
3316
  "sdk_version": "0.4.40",
3317
- "verified_at": "2026-10-01T04:56:01Z",
3318
- "evidence": "sdk-0.4.40-2026-10-01",
3317
+ "verified_at": "2026-10-01T16:01:10Z",
3318
+ "evidence": "sdk-0.4.40-2026-10-01.2",
3319
3319
  "status": "certified",
3320
3320
  "source": "template-verification.json"
3321
3321
  }
@@ -3525,5 +3525,5 @@
3525
3525
  },
3526
3526
  "_synced_from_repo": "NextCommerceCo/campaign-cart-starter-templates",
3527
3527
  "_synced_from_ref": "main",
3528
- "_synced_from_sha": "3793b1de3b77cc31dffe9176f47e8e99ea6134aa"
3528
+ "_synced_from_sha": "37a8d945db4c360739ded98348814cfd632da94f"
3529
3529
  }
@@ -5816,6 +5816,179 @@
5816
5816
  "test_scope": "full",
5817
5817
  "notes": "record polish --dry-run runs every check the real invocation runs and prints what it would write; it writes nothing under the target, appends no lifecycle entry (the command is declared `dryRun` in src/invocation.mjs) and runs no stale-session closeout."
5818
5818
  },
5819
+ {
5820
+ "command": "record",
5821
+ "subcommand": "theme",
5822
+ "flags": [],
5823
+ "annotations": {
5824
+ "readOnlyHint": false,
5825
+ "destructiveHint": true,
5826
+ "openWorldHint": false,
5827
+ "idempotentHint": false
5828
+ },
5829
+ "tier": "C",
5830
+ "writes": [
5831
+ {
5832
+ "path": "{target}/.campaign-runtime/assembly-report.json",
5833
+ "when": "the record passes every check — theme.status becomes applied with load_order after-next-core, css_path, commerce_pages and per-page evidence read from the built pages; any earlier theme waiver is cleared",
5834
+ "observed_in": [
5835
+ "no_session",
5836
+ "ambient_session",
5837
+ "stale_session",
5838
+ "lifecycle_log",
5839
+ "persisted_consent"
5840
+ ]
5841
+ },
5842
+ {
5843
+ "path": "{target}/.campaign-runtime/doctor-output.json",
5844
+ "when": "a retained doctor sidecar exists — the record postdates the doctor snapshot, so it is stamped stale",
5845
+ "observed_in": [
5846
+ "no_session",
5847
+ "ambient_session",
5848
+ "stale_session",
5849
+ "lifecycle_log",
5850
+ "persisted_consent"
5851
+ ]
5852
+ },
5853
+ {
5854
+ "path": "{lifecycle-journal}",
5855
+ "when": "a lifecycle journal is selected for the invocation — an active run session, --lifecycle-journal, or CAMPAIGNS_OS_LIFECYCLE_LOG",
5856
+ "observed_in": [
5857
+ "ambient_session",
5858
+ "lifecycle_log"
5859
+ ]
5860
+ }
5861
+ ],
5862
+ "sends": [],
5863
+ "effect_test": "effects: record theme",
5864
+ "test_scope": "full",
5865
+ "notes": "Destructive: it replaces report.theme's status, css_path, load_order, commerce_pages, evidence and waiver. Refused, writing nothing, when build is not recorded for the current output, when the campaign ships no commerce pages, when a built commerce page that loads next-core.css does not load brand-theme.css (or checkout-brand.css) after it, or links one that is not in the built output, or when no built commerce page loads next-core.css. The Build Context is read, not written."
5866
+ },
5867
+ {
5868
+ "command": "record",
5869
+ "subcommand": "theme",
5870
+ "flags": [
5871
+ "--dry-run"
5872
+ ],
5873
+ "annotations": {
5874
+ "readOnlyHint": true,
5875
+ "destructiveHint": false,
5876
+ "openWorldHint": false,
5877
+ "idempotentHint": true
5878
+ },
5879
+ "tier": "none",
5880
+ "writes": [],
5881
+ "sends": [],
5882
+ "effect_test": "effects: record theme --dry-run",
5883
+ "test_scope": "full",
5884
+ "notes": "record theme --dry-run runs every check the real invocation runs and prints what it would write; it writes nothing under the target, appends no lifecycle entry (the command is declared `dryRun` in src/invocation.mjs) and runs no stale-session closeout."
5885
+ },
5886
+ {
5887
+ "command": "record",
5888
+ "subcommand": "deploy",
5889
+ "flags": [],
5890
+ "annotations": {
5891
+ "readOnlyHint": false,
5892
+ "destructiveHint": true,
5893
+ "openWorldHint": true,
5894
+ "idempotentHint": false
5895
+ },
5896
+ "tier": "C",
5897
+ "writes": [
5898
+ {
5899
+ "path": "{packet}",
5900
+ "when": "the record passes every check — deploy.preview_url becomes the served URL",
5901
+ "observed_in": [
5902
+ "no_session",
5903
+ "ambient_session",
5904
+ "stale_session",
5905
+ "lifecycle_log",
5906
+ "persisted_consent"
5907
+ ]
5908
+ },
5909
+ {
5910
+ "path": "{target}/.campaign-runtime/assembly-report.json",
5911
+ "when": "the record passes every check — stages.deploy becomes completed with the served URL in outputs and one evidence line per page that answered",
5912
+ "observed_in": [
5913
+ "no_session",
5914
+ "ambient_session",
5915
+ "stale_session",
5916
+ "lifecycle_log",
5917
+ "persisted_consent"
5918
+ ]
5919
+ },
5920
+ {
5921
+ "path": "{target}/.campaign-runtime/doctor-output.json",
5922
+ "when": "a retained doctor sidecar exists — the record postdates the doctor snapshot, so it is stamped stale",
5923
+ "observed_in": [
5924
+ "no_session",
5925
+ "ambient_session",
5926
+ "stale_session",
5927
+ "lifecycle_log",
5928
+ "persisted_consent"
5929
+ ]
5930
+ },
5931
+ {
5932
+ "path": "{lifecycle-journal}",
5933
+ "when": "a lifecycle journal is selected for the invocation — an active run session, --lifecycle-journal, or CAMPAIGNS_OS_LIFECYCLE_LOG",
5934
+ "observed_in": [
5935
+ "ambient_session",
5936
+ "lifecycle_log"
5937
+ ]
5938
+ }
5939
+ ],
5940
+ "sends": [
5941
+ {
5942
+ "destination": "{base-url}",
5943
+ "what": "a GET for each built page under the served URL, to prove the local preview answers before it is recorded",
5944
+ "when": "the packet's deploy target is local-serve and --base-url is a loopback origin naming the campaign's route root",
5945
+ "requires_consent": false,
5946
+ "observed_in": [
5947
+ "no_session",
5948
+ "ambient_session",
5949
+ "stale_session",
5950
+ "lifecycle_log",
5951
+ "persisted_consent"
5952
+ ]
5953
+ }
5954
+ ],
5955
+ "effect_test": "effects: record deploy",
5956
+ "test_scope": "full",
5957
+ "notes": "Destructive: it replaces stages.deploy and the packet's deploy.preview_url. The requests stay on this machine: --base-url must be a loopback origin. Refused, writing nothing, when the packet is not local-serve, the URL is not loopback or not the campaign's route root, a built page does not answer 2xx, polish is not recorded, the built output changed since build was recorded, or the theme gate is blocked. The Build Context is read, not written."
5958
+ },
5959
+ {
5960
+ "command": "record",
5961
+ "subcommand": "deploy",
5962
+ "flags": [
5963
+ "--dry-run"
5964
+ ],
5965
+ "annotations": {
5966
+ "readOnlyHint": false,
5967
+ "destructiveHint": false,
5968
+ "openWorldHint": true,
5969
+ "idempotentHint": true
5970
+ },
5971
+ "tier": "A",
5972
+ "writes": [],
5973
+ "sends": [
5974
+ {
5975
+ "destination": "{base-url}",
5976
+ "what": "a GET for each built page under the served URL, to prove the local preview answers before it is recorded",
5977
+ "when": "the packet's deploy target is local-serve and --base-url is a loopback origin naming the campaign's route root",
5978
+ "requires_consent": false,
5979
+ "observed_in": [
5980
+ "no_session",
5981
+ "ambient_session",
5982
+ "stale_session",
5983
+ "lifecycle_log",
5984
+ "persisted_consent"
5985
+ ]
5986
+ }
5987
+ ],
5988
+ "effect_test": "effects: record deploy --dry-run",
5989
+ "test_scope": "full",
5990
+ "notes": "record deploy --dry-run runs every check the real invocation runs, the page requests included, and prints what it would write; it writes nothing under the target, appends no lifecycle entry (the command is declared `dryRun` in src/invocation.mjs) and runs no stale-session closeout."
5991
+ },
5819
5992
  {
5820
5993
  "command": "login",
5821
5994
  "subcommand": null,