@nextcommerce/campaigns-os 1.59.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +6 -5
  3. package/compatibility.json +1 -1
  4. package/contracts/commerce-surface-catalog.json +18 -18
  5. package/contracts/release-ledger.json +543 -0
  6. package/contracts/supported-surface.json +1 -1
  7. package/contracts/template-brand-contract.shared-commerce.v0.json +1 -1
  8. package/docs/build-packet.md +14 -12
  9. package/docs/campaign-build-brief.md +1 -1
  10. package/docs/campaigns-os-build-flow.md +1 -1
  11. package/docs/local-setup.md +1 -1
  12. package/docs/orientation-contract-reference.md +1 -1
  13. package/docs/polish-evidence.md +1 -1
  14. package/docs/runtime-readiness.md +1 -1
  15. package/docs/skills-revision.md +10 -10
  16. package/package.json +1 -1
  17. package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
  18. package/skills/campaign-readback-classification/SKILL.md +3 -3
  19. package/skills/campaign-run-evidence/SKILL.md +3 -3
  20. package/skills/contribution-intake/SKILL.md +3 -3
  21. package/skills/next-campaigns-build/SKILL.md +4 -4
  22. package/skills/next-campaigns-os/SKILL.md +3 -3
  23. package/skills/next-campaigns-os-setup/SKILL.md +3 -3
  24. package/skills/next-campaigns-polish/SKILL.md +9 -10
  25. package/skills/next-campaigns-qa/SKILL.md +3 -3
  26. package/skills/next-campaigns-sdk-bump/SKILL.md +193 -0
  27. package/skills.json +18 -10
  28. package/src/built-site-scope.mjs +5 -12
  29. package/src/campaign-identity.mjs +6 -4
  30. package/src/cli.mjs +37 -60
  31. package/src/doctor/checks.mjs +6 -3
  32. package/src/doctor/inspect.mjs +2 -8
  33. package/src/doctor/next-step.mjs +6 -3
  34. package/src/orchestration-stage-contract.mjs +6 -3
  35. package/src/page-kit-build-summary.mjs +21 -1
  36. package/src/page-kit-campaign-config.mjs +19 -0
  37. package/src/polish-gate.mjs +1 -5
  38. package/src/progress-node.mjs +2 -1
  39. package/src/spec-derive.mjs +24 -9
  40. package/src/stage-ledger.mjs +27 -1
  41. package/src/stage-record.mjs +18 -2
@@ -8108,6 +8108,549 @@
8108
8108
  }
8109
8109
  ],
8110
8110
  "entry_sha256": "54697c8b2c8e0857687a01f4ac43942202f8e6f9a523fc1151070ac890a0133d"
8111
+ },
8112
+ {
8113
+ "id": "RL-0273",
8114
+ "sequence": 259,
8115
+ "date": "2026-10-14",
8116
+ "kind": "release",
8117
+ "surface_version": null,
8118
+ "changelog_section": "1.59.0+agent.4",
8119
+ "changelog_sha256": "4bfd26f73f0eb599a40cb5fb338653d4fdf511f45ccd0ec291ba67d402c30086",
8120
+ "agent_impact": "When a campaign is set up in the Campaigns App dashboard, expect one package per variant, created by saving an Offer that selects it, and a separate Offer per Buy 1/2/3 tier. The dashboard labels packages Products; pages still reference package IDs. Quickstart and the build-flow commerce section both describe this Create Campaign then Add Offer setup, and that Admin API setups still create packages before Offers.",
8121
+ "compatibility": "compatible",
8122
+ "migration": "none",
8123
+ "changes": [
8124
+ {
8125
+ "class": "named_surface",
8126
+ "path": "docs/campaigns-os-build-flow.md",
8127
+ "surface_entry": "docs/campaigns-os-build-flow.md",
8128
+ "summary": "Describe how the dashboard creates packages from Offers under Commerce Ownership."
8129
+ }
8130
+ ],
8131
+ "entry_sha256": "b0708e5f1d10142d56f4cbc5d346053b89073bc65cb6c69b41afff432908e103"
8132
+ },
8133
+ {
8134
+ "id": "RL-0271",
8135
+ "sequence": 260,
8136
+ "date": "2026-10-15",
8137
+ "kind": "release",
8138
+ "surface_version": null,
8139
+ "changelog_section": "1.59.0+agent.5",
8140
+ "changelog_sha256": "64d75e58cefd497559d4fb0b30817f6d123bfc211ccb461e1c6dbf0b62eb107b",
8141
+ "agent_impact": "On a hosted all-template preview, follow next: record deploy --base-url <preview url>, then qa run, then closeout. The hosted preview URL no longer satisfies the deploy stage on its own (since 1.59.0), and the polish skill, docs and README now say so. A forced next deploy or next qa with an unset, loopback or production-equivalent preview URL prompts for qa policy set --preview-url, matching next actions and doctor. Refresh bundled skills to 1.59.0+skills.2.",
8142
+ "compatibility": "compatible",
8143
+ "migration": "none",
8144
+ "changes": [
8145
+ {
8146
+ "class": "named_surface",
8147
+ "path": "docs/build-packet.md",
8148
+ "surface_entry": "docs/build-packet.md",
8149
+ "summary": "Drop the leftover statement that the hosted all-template preview satisfies the deploy step; QA follows record deploy."
8150
+ },
8151
+ {
8152
+ "class": "named_surface",
8153
+ "path": "docs/skills-revision.md",
8154
+ "surface_entry": "docs/skills-revision.md",
8155
+ "summary": "Show the current 1.59.0+skills.2 bundle identity in preflight examples."
8156
+ },
8157
+ {
8158
+ "class": "skill",
8159
+ "path": "skills.json",
8160
+ "surface_entry": "skills.json",
8161
+ "summary": "Advance the bundle to 1.59.0+skills.2 and each bundled skill by one patch."
8162
+ },
8163
+ {
8164
+ "class": "skill",
8165
+ "path": "skills/next-campaigns-polish/SKILL.md",
8166
+ "surface_entry": null,
8167
+ "summary": "Hand the hosted all-template preview to next: record deploy, then QA, then closeout."
8168
+ },
8169
+ {
8170
+ "class": "skill",
8171
+ "path": "skills/campaign-lifecycle-orientation/SKILL.md",
8172
+ "surface_entry": null,
8173
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8174
+ },
8175
+ {
8176
+ "class": "skill",
8177
+ "path": "skills/campaign-readback-classification/SKILL.md",
8178
+ "surface_entry": null,
8179
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8180
+ },
8181
+ {
8182
+ "class": "skill",
8183
+ "path": "skills/campaign-run-evidence/SKILL.md",
8184
+ "surface_entry": null,
8185
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8186
+ },
8187
+ {
8188
+ "class": "skill",
8189
+ "path": "skills/contribution-intake/SKILL.md",
8190
+ "surface_entry": null,
8191
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8192
+ },
8193
+ {
8194
+ "class": "skill",
8195
+ "path": "skills/next-campaigns-build/SKILL.md",
8196
+ "surface_entry": null,
8197
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8198
+ },
8199
+ {
8200
+ "class": "skill",
8201
+ "path": "skills/next-campaigns-os-setup/SKILL.md",
8202
+ "surface_entry": null,
8203
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8204
+ },
8205
+ {
8206
+ "class": "skill",
8207
+ "path": "skills/next-campaigns-os/SKILL.md",
8208
+ "surface_entry": null,
8209
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8210
+ },
8211
+ {
8212
+ "class": "skill",
8213
+ "path": "skills/next-campaigns-qa/SKILL.md",
8214
+ "surface_entry": null,
8215
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.2."
8216
+ },
8217
+ {
8218
+ "class": "cli_surface",
8219
+ "path": "src/cli.mjs",
8220
+ "surface_entry": null,
8221
+ "summary": "The deploy and QA prompts on an all-template hosted packet use the usable-preview rule next actions and doctor use; the done prompt names record deploy for both deploy targets."
8222
+ }
8223
+ ],
8224
+ "entry_sha256": "2bad692257bfa5a2a5718b1861d1da60ae92c3a4cd23151d659c3867b308c839"
8225
+ },
8226
+ {
8227
+ "id": "RL-0272",
8228
+ "sequence": 261,
8229
+ "date": "2026-10-15",
8230
+ "kind": "release",
8231
+ "surface_version": null,
8232
+ "changelog_section": "1.59.0+agent.7",
8233
+ "changelog_sha256": "766c499fdb0ce69edf48f40f611ffd532a8789665a64208908491b68e0afa70b",
8234
+ "agent_impact": "run status --json now always reports progress.next_command as `campaigns-os next --packet <packet> --json`; it no longer names `run end` when every recorded stage status is terminal, because a stage an input change or a new build owes again still records completed. Follow next, which names `run end` as a required action once the campaign is done and a run session is active. next and doctor output is unchanged.",
8235
+ "compatibility": "compatible",
8236
+ "migration": "none",
8237
+ "changes": [
8238
+ {
8239
+ "class": "cli_surface",
8240
+ "path": "src/cli.mjs",
8241
+ "surface_entry": null,
8242
+ "summary": "run status names next as the next command; next returns the prepare-build recovery answer from one branch and reads the shared readiness ladder."
8243
+ },
8244
+ {
8245
+ "class": "cli_surface",
8246
+ "path": "src/doctor/inspect.mjs",
8247
+ "surface_entry": "doctor",
8248
+ "summary": "Doctor's status reads the shared readiness ladder; its output is unchanged."
8249
+ },
8250
+ {
8251
+ "class": "cli_surface",
8252
+ "path": "src/doctor/next-step.mjs",
8253
+ "surface_entry": "doctor",
8254
+ "summary": "Export the readiness ladder that doctor and next share and drop the stage picker's unused packet parameter; output is unchanged."
8255
+ }
8256
+ ],
8257
+ "entry_sha256": "6182da2e9bf076b2baceb3303518bfed33c3c8cb6ac72cddce70066a490b88c1"
8258
+ },
8259
+ {
8260
+ "id": "RL-0274",
8261
+ "sequence": 262,
8262
+ "date": "2026-10-19",
8263
+ "kind": "release",
8264
+ "surface_version": null,
8265
+ "changelog_section": "1.59.0+agent.8",
8266
+ "changelog_sha256": "a2a97f2d4650f02eecb11398dc05f500f7aaef9a52271825b663009d5cd94ace",
8267
+ "agent_impact": "On a target with next-campaign-page-kit 0.3.0, read doctor's built_output.build_asset_warning: each one names an .html file under assets/ that page-kit neither built nor copied, so a link or iframe to it 404s. Move the file out of assets/ if it is a page, or remove it. On 0.3.0, spec derive and doctor's built-page lookup no longer bind a page to an .html file under the campaign's top-level assets/; 0.2.x targets read as before. New folders install next-campaign-page-kit@0.3.0 from docs/local-setup.md. Refresh bundled skills to 1.59.0+skills.3.",
8268
+ "compatibility": "additive",
8269
+ "migration": "After the first build on page-kit 0.3.0, run record build again: the build fingerprint can change with unchanged source (0.3.0 removes stale _site/<slug>/ output and no longer copies .html under assets/), and polish, deploy and QA are owed again for the new build.",
8270
+ "changes": [
8271
+ {
8272
+ "class": "named_surface",
8273
+ "path": "docs/build-packet.md",
8274
+ "surface_entry": "docs/build-packet.md",
8275
+ "summary": "Say that unpruned _site/ output and an assets/ index.html built as a page are page-kit 0.2.x behaviour, and that 0.3.0 cleans _site/<slug>/ and reports ASSET_IGNORED; the stray_files gate is unchanged."
8276
+ },
8277
+ {
8278
+ "class": "named_surface",
8279
+ "path": "docs/local-setup.md",
8280
+ "surface_entry": "docs/local-setup.md",
8281
+ "summary": "Pin the new-folder page-kit install to next-campaign-page-kit@0.3.0."
8282
+ },
8283
+ {
8284
+ "class": "named_surface",
8285
+ "path": "docs/skills-revision.md",
8286
+ "surface_entry": "docs/skills-revision.md",
8287
+ "summary": "Show the current 1.59.0+skills.3 bundle identity in preflight examples."
8288
+ },
8289
+ {
8290
+ "class": "skill",
8291
+ "path": "skills.json",
8292
+ "surface_entry": "skills.json",
8293
+ "summary": "Advance the bundle to 1.59.0+skills.3 and each bundled skill by one patch."
8294
+ },
8295
+ {
8296
+ "class": "skill",
8297
+ "path": "skills/next-campaigns-build/SKILL.md",
8298
+ "surface_entry": null,
8299
+ "summary": "Name the build summary's assetWarnings and ASSET_IGNORED on page-kit 0.3.0, and what to do with an ignored HTML file under assets/."
8300
+ },
8301
+ {
8302
+ "class": "skill",
8303
+ "path": "skills/campaign-lifecycle-orientation/SKILL.md",
8304
+ "surface_entry": null,
8305
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8306
+ },
8307
+ {
8308
+ "class": "skill",
8309
+ "path": "skills/campaign-readback-classification/SKILL.md",
8310
+ "surface_entry": null,
8311
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8312
+ },
8313
+ {
8314
+ "class": "skill",
8315
+ "path": "skills/campaign-run-evidence/SKILL.md",
8316
+ "surface_entry": null,
8317
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8318
+ },
8319
+ {
8320
+ "class": "skill",
8321
+ "path": "skills/contribution-intake/SKILL.md",
8322
+ "surface_entry": null,
8323
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8324
+ },
8325
+ {
8326
+ "class": "skill",
8327
+ "path": "skills/next-campaigns-os-setup/SKILL.md",
8328
+ "surface_entry": null,
8329
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8330
+ },
8331
+ {
8332
+ "class": "skill",
8333
+ "path": "skills/next-campaigns-os/SKILL.md",
8334
+ "surface_entry": null,
8335
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8336
+ },
8337
+ {
8338
+ "class": "skill",
8339
+ "path": "skills/next-campaigns-polish/SKILL.md",
8340
+ "surface_entry": null,
8341
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8342
+ },
8343
+ {
8344
+ "class": "skill",
8345
+ "path": "skills/next-campaigns-qa/SKILL.md",
8346
+ "surface_entry": null,
8347
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.3."
8348
+ },
8349
+ {
8350
+ "class": "cli_surface",
8351
+ "path": "src/cli.mjs",
8352
+ "surface_entry": null,
8353
+ "summary": "spec derive skips .html under the campaign's top-level assets/ when the target's installed page-kit is 0.3.0 or later; the build prompt names assetWarnings and ASSET_IGNORED."
8354
+ },
8355
+ {
8356
+ "class": "cli_surface",
8357
+ "path": "src/doctor/checks.mjs",
8358
+ "surface_entry": "doctor",
8359
+ "summary": "Doctor reports each build summary assetWarnings entry for the campaign as the non-blocking built_output.build_asset_warning, and on page-kit 0.3.0 or later reads no source permalink from a file under assets/."
8360
+ }
8361
+ ],
8362
+ "entry_sha256": "2127a7133126fd80e7c519f484184463d44b0f1b655350184525b19d76cf979e"
8363
+ },
8364
+ {
8365
+ "id": "RL-0275",
8366
+ "sequence": 263,
8367
+ "date": "2026-10-19",
8368
+ "kind": "release",
8369
+ "surface_version": null,
8370
+ "changelog_section": "1.59.0+agent.10",
8371
+ "changelog_sha256": "a2cc415ae5174c3381b505e8109ce9a30f042593d7e89ac9b25ad2910a0f0092",
8372
+ "agent_impact": "None expected: the lockfile resolves Playwright 1.64.1 and acorn 8.19.0 within the ranges package.json already declares. Browser QA and polish capture run on Playwright 1.64.1; doctor's script syntax check parses with acorn 8.19.0.",
8373
+ "compatibility": "compatible",
8374
+ "migration": "none",
8375
+ "changes": [
8376
+ {
8377
+ "class": "generated_runtime",
8378
+ "path": "package-lock.json",
8379
+ "surface_entry": null,
8380
+ "summary": "Resolve Playwright 1.64.1 and acorn 8.19.0."
8381
+ }
8382
+ ],
8383
+ "entry_sha256": "b0d2fbd5618d4fc635b346ae521085a77e0ac552e67e8f94a9c5ced7049f237b"
8384
+ },
8385
+ {
8386
+ "id": "RL-0276",
8387
+ "sequence": 264,
8388
+ "date": "2026-10-19",
8389
+ "kind": "release",
8390
+ "surface_version": null,
8391
+ "changelog_section": "1.59.0+agent.11",
8392
+ "changelog_sha256": "bbde8ee78d523076a4011ba71cd6674bbc305aa03219c1ba2dd37c6d0fc5ee78",
8393
+ "agent_impact": "None for package consumers: this changes repository CI only (add-to-project and publish workflow action versions).",
8394
+ "compatibility": "compatible",
8395
+ "migration": "none",
8396
+ "changes": [
8397
+ {
8398
+ "class": "workflow",
8399
+ "path": ".github/workflows/add-to-project.yml",
8400
+ "surface_entry": null,
8401
+ "summary": "Move actions/create-github-app-token to 3.3.0."
8402
+ },
8403
+ {
8404
+ "class": "workflow",
8405
+ "path": ".github/workflows/publish.yml",
8406
+ "surface_entry": null,
8407
+ "summary": "Move actions/upload-artifact to 7.0.2 and actions/download-artifact to 8.0.2."
8408
+ }
8409
+ ],
8410
+ "entry_sha256": "dbca912d6c5145cb494f83fe7c334bec6e978bf00f6146c2a7eeb2d706f7cb96"
8411
+ },
8412
+ {
8413
+ "id": "RL-0277",
8414
+ "sequence": 265,
8415
+ "date": "2026-10-19",
8416
+ "kind": "release",
8417
+ "surface_version": null,
8418
+ "changelog_section": "1.59.0+agent.12",
8419
+ "changelog_sha256": "2bd2f6b05e609f8348165e737efc5628af764594fb6cd34b8c0b067a1d08ce6e",
8420
+ "agent_impact": "Refresh bundled skills to 1.59.0+skills.4. For a Campaign Cart 0.4.x to later 0.4.x bump, follow next-campaigns-sdk-bump: it finds hard-coded loader pins as well as sdk_version, scopes sdk repin to the funnel folder, runs sdk storage-check with the target tag's manifest, then doctor and preview test orders under the existing approval rule, and reports what is not proven. It stops at a 0.3.x pin or the legacy Campaigns script.",
8421
+ "compatibility": "additive",
8422
+ "migration": "Run install-skills to install next-campaigns-sdk-bump and the refreshed bundle, then start a fresh agent session.",
8423
+ "changes": [
8424
+ {
8425
+ "class": "named_surface",
8426
+ "path": "docs/skills-revision.md",
8427
+ "surface_entry": "docs/skills-revision.md",
8428
+ "summary": "Show the current 1.59.0+skills.4 bundle identity in preflight examples."
8429
+ },
8430
+ {
8431
+ "class": "skill",
8432
+ "path": "skills.json",
8433
+ "surface_entry": "skills.json",
8434
+ "summary": "Add next-campaigns-sdk-bump 1.0.0, advance the bundle to 1.59.0+skills.4 and each other bundled skill by one patch."
8435
+ },
8436
+ {
8437
+ "class": "skill",
8438
+ "path": "skills/next-campaigns-sdk-bump/SKILL.md",
8439
+ "surface_entry": null,
8440
+ "summary": "New skill: a 0.4.x to later 0.4.x Campaign Cart bump on a page-kit or static repo, from pins through storage check, doctor, preview test orders and hand-back."
8441
+ },
8442
+ {
8443
+ "class": "skill",
8444
+ "path": "skills/campaign-lifecycle-orientation/SKILL.md",
8445
+ "surface_entry": null,
8446
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8447
+ },
8448
+ {
8449
+ "class": "skill",
8450
+ "path": "skills/campaign-readback-classification/SKILL.md",
8451
+ "surface_entry": null,
8452
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8453
+ },
8454
+ {
8455
+ "class": "skill",
8456
+ "path": "skills/campaign-run-evidence/SKILL.md",
8457
+ "surface_entry": null,
8458
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8459
+ },
8460
+ {
8461
+ "class": "skill",
8462
+ "path": "skills/contribution-intake/SKILL.md",
8463
+ "surface_entry": null,
8464
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8465
+ },
8466
+ {
8467
+ "class": "skill",
8468
+ "path": "skills/next-campaigns-build/SKILL.md",
8469
+ "surface_entry": null,
8470
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8471
+ },
8472
+ {
8473
+ "class": "skill",
8474
+ "path": "skills/next-campaigns-os-setup/SKILL.md",
8475
+ "surface_entry": null,
8476
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8477
+ },
8478
+ {
8479
+ "class": "skill",
8480
+ "path": "skills/next-campaigns-os/SKILL.md",
8481
+ "surface_entry": null,
8482
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8483
+ },
8484
+ {
8485
+ "class": "skill",
8486
+ "path": "skills/next-campaigns-polish/SKILL.md",
8487
+ "surface_entry": null,
8488
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8489
+ },
8490
+ {
8491
+ "class": "skill",
8492
+ "path": "skills/next-campaigns-qa/SKILL.md",
8493
+ "surface_entry": null,
8494
+ "summary": "Bump the skill one patch and stamp bundle 1.59.0+skills.4."
8495
+ }
8496
+ ],
8497
+ "entry_sha256": "f258fb6a51dfb20ab1b4eb71dd18fdc224ce6ee553ca3653be5efa581e644655"
8498
+ },
8499
+ {
8500
+ "id": "RL-0278",
8501
+ "sequence": 266,
8502
+ "date": "2026-10-19",
8503
+ "kind": "release",
8504
+ "surface_version": null,
8505
+ "changelog_section": "1.59.0+agent.13",
8506
+ "changelog_sha256": "0e1ce83cf5555290a681ff08d83a03a1e4210aca22b8d349a9af26022513f241",
8507
+ "agent_impact": "After a CampaignSpec-only change, when the operator records build with --deviation-reason over the same output a completed Polish reviewed, Polish reads current again and next moves on toward QA; do not retake Polish captures for that unchanged build. QA is still owed for the changed CampaignSpec. A brief presentation change, a different build, or a build recorded without the deviation reason still owes Polish.",
8508
+ "compatibility": "compatible",
8509
+ "migration": "none",
8510
+ "changes": [
8511
+ {
8512
+ "class": "named_surface",
8513
+ "path": "docs/build-packet.md",
8514
+ "surface_entry": "docs/build-packet.md",
8515
+ "summary": "Name the exception: a deviation-recorded build of the output a completed Polish reviewed restores that Polish after a CampaignSpec-only change."
8516
+ },
8517
+ {
8518
+ "class": "named_surface",
8519
+ "path": "docs/campaign-build-brief.md",
8520
+ "surface_entry": "docs/campaign-build-brief.md",
8521
+ "summary": "Say that a CampaignSpec-only change kept with record build --deviation-reason keeps Polish, and that a presentation change still owes it."
8522
+ }
8523
+ ],
8524
+ "entry_sha256": "8f05d402dfed44c9c94136551ea1aa97aecf3850346484a8f3f3a4d6540052f2"
8525
+ },
8526
+ {
8527
+ "id": "RL-0279",
8528
+ "sequence": 267,
8529
+ "date": "2026-10-20",
8530
+ "kind": "release",
8531
+ "surface_version": "1.60.0",
8532
+ "changelog_section": "1.60.0",
8533
+ "changelog_sha256": "9d37d356a3ffaa2f44c66f14c643bae9dbee69bce507db6076dfa0aa92110106",
8534
+ "agent_impact": "The 1.60.0 package publishes the ten same-surface changes since 1.59.0 (agent.4 to agent.13). Consumers gain the next-campaigns-sdk-bump skill (with the fixes from its first live bump), page-kit 0.3.0 support with asset warnings, the 3987b18 starter catalog, QA build binding and run status fixes, and Polish carry-over after a spec-only change; refresh the bundled skills to 1.60.0+skills.1.",
8535
+ "compatibility": "additive",
8536
+ "migration": "From the published 1.59.0, update the pinned package and run install-skills to get 1.60.0+skills.1, including next-campaigns-sdk-bump. After the first build on page-kit 0.3.0, run record build again: the build fingerprint can change with unchanged source, so Polish, deploy and QA are owed again.",
8537
+ "changes": [
8538
+ {
8539
+ "class": "compatibility_policy",
8540
+ "path": "compatibility.json",
8541
+ "surface_entry": "compatibility.json",
8542
+ "summary": "Name 1.60.0 as the published package version."
8543
+ },
8544
+ {
8545
+ "class": "compatibility_policy",
8546
+ "path": "contracts/supported-surface.json",
8547
+ "surface_entry": "contracts/supported-surface.json",
8548
+ "summary": "Advance surface_version to 1.60.0 for the package release."
8549
+ },
8550
+ {
8551
+ "class": "named_surface",
8552
+ "path": "docs/local-setup.md",
8553
+ "surface_entry": "docs/local-setup.md",
8554
+ "summary": "Pin the documented toolkit install to 1.60.0."
8555
+ },
8556
+ {
8557
+ "class": "documentation",
8558
+ "path": "docs/orientation-contract-reference.md",
8559
+ "surface_entry": "docs/orientation-contract-reference.md",
8560
+ "summary": "Regenerate the orientation reference at surface 1.60.0."
8561
+ },
8562
+ {
8563
+ "class": "named_surface",
8564
+ "path": "docs/runtime-readiness.md",
8565
+ "surface_entry": "docs/runtime-readiness.md",
8566
+ "summary": "Regenerate runtime readiness at surface 1.60.0."
8567
+ },
8568
+ {
8569
+ "class": "named_surface",
8570
+ "path": "docs/skills-revision.md",
8571
+ "surface_entry": "docs/skills-revision.md",
8572
+ "summary": "Show the current 1.60.0+skills.1 bundle identity in preflight examples."
8573
+ },
8574
+ {
8575
+ "class": "generated_runtime",
8576
+ "path": "package-lock.json",
8577
+ "surface_entry": null,
8578
+ "summary": "Advance both package version stamps to 1.60.0."
8579
+ },
8580
+ {
8581
+ "class": "package_export",
8582
+ "path": "package.json",
8583
+ "surface_entry": null,
8584
+ "summary": "Advance the package version to 1.60.0."
8585
+ },
8586
+ {
8587
+ "class": "skill",
8588
+ "path": "skills.json",
8589
+ "surface_entry": "skills.json",
8590
+ "summary": "Advance the bundle to 1.60.0+skills.1 and each bundled skill by one patch."
8591
+ },
8592
+ {
8593
+ "class": "skill",
8594
+ "path": "skills/campaign-lifecycle-orientation/SKILL.md",
8595
+ "surface_entry": null,
8596
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8597
+ },
8598
+ {
8599
+ "class": "skill",
8600
+ "path": "skills/campaign-readback-classification/SKILL.md",
8601
+ "surface_entry": null,
8602
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8603
+ },
8604
+ {
8605
+ "class": "skill",
8606
+ "path": "skills/campaign-run-evidence/SKILL.md",
8607
+ "surface_entry": null,
8608
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8609
+ },
8610
+ {
8611
+ "class": "skill",
8612
+ "path": "skills/contribution-intake/SKILL.md",
8613
+ "surface_entry": null,
8614
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8615
+ },
8616
+ {
8617
+ "class": "skill",
8618
+ "path": "skills/next-campaigns-build/SKILL.md",
8619
+ "surface_entry": null,
8620
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8621
+ },
8622
+ {
8623
+ "class": "skill",
8624
+ "path": "skills/next-campaigns-os-setup/SKILL.md",
8625
+ "surface_entry": null,
8626
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8627
+ },
8628
+ {
8629
+ "class": "skill",
8630
+ "path": "skills/next-campaigns-os/SKILL.md",
8631
+ "surface_entry": null,
8632
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8633
+ },
8634
+ {
8635
+ "class": "skill",
8636
+ "path": "skills/next-campaigns-polish/SKILL.md",
8637
+ "surface_entry": null,
8638
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8639
+ },
8640
+ {
8641
+ "class": "skill",
8642
+ "path": "skills/next-campaigns-qa/SKILL.md",
8643
+ "surface_entry": null,
8644
+ "summary": "Bump the skill one patch and stamp bundle 1.60.0+skills.1."
8645
+ },
8646
+ {
8647
+ "class": "skill",
8648
+ "path": "skills/next-campaigns-sdk-bump/SKILL.md",
8649
+ "surface_entry": null,
8650
+ "summary": "Apply the first live-bump feedback (#683: removed features, next:initialized guard, legacy detection, manifest range, QA portal and qa-output) and stamp bundle 1.60.0+skills.1."
8651
+ }
8652
+ ],
8653
+ "entry_sha256": "25d3db88fb7e0259e9b3a4b91244cf504d0bd99bfc815ab60393b3982927564f"
8111
8654
  }
8112
8655
  ]
8113
8656
  }
@@ -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.59.0",
3
+ "surface_version": "1.60.0",
4
4
  "package_exports": [
5
5
  "./commercial-journey",
6
6
  "./commercial-parity",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "asset_pin": {
57
57
  "repo": "NextCommerceCo/campaign-cart-starter-templates",
58
- "sha": "d5ff501ab57aef160a7108341de8a952006a28a4",
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
  },
@@ -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 (page-kit does not prune
792
- `_site/`) or an HTML file copied into the source, such as a design export's
793
- `index.html` under `assets/`. The repair is to remove the source file if
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`,
@@ -1754,7 +1758,7 @@ own stages) → calls `next` again → repeat until stage="done"
1754
1758
 
1755
1759
  ### Refreshing after a CampaignSpec change
1756
1760
 
1757
- 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.
1758
1762
 
1759
1763
  The CampaignSpec's material content is the whole spec except `spec_identity`,
1760
1764
  `slug`, `map_id` and `saved_at`; a page `label` edit is material. A spec
@@ -1813,13 +1817,11 @@ On a hosted target, record an unset hosted preview URL with
1813
1817
  `campaigns-os qa policy set --packet <p> --preview-url <url>`, then record the
1814
1818
  deploy with `campaigns-os record deploy --packet <p> --base-url <preview url>`. The hosted preview must be a non-loopback
1815
1819
  HTTP(S) URL whose origin or QA-resolved campaign route path differs from `deploy.production_url`;
1816
- query and fragment text does not make the production page a preview. With
1817
- `deploy.preview_url` recorded, run `campaigns-os next qa --packet <p>` and
1818
- `campaigns-os qa run --packet <p> --base-url <preview-url> --browser
1819
- --test-order common`. The recorded hosted preview satisfies the deploy step
1820
- for this all-template shape. After QA records a verdict for the current build,
1821
- `campaigns-os next --packet <p>` reaches closeout without a hosted deploy
1822
- 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.
1823
1825
 
1824
1826
  Each command reads the same packet, Build Context and Assembly Report `next`
1825
1827
  reads (`--context` / `--report` override them the same way), validates what it
@@ -1882,7 +1884,7 @@ Result shape (with `--json`):
1882
1884
  Terminal states:
1883
1885
 
1884
1886
  - **`stage: "doctor-blocked"`** — doctor returned errors. Resolve the blockers and re-run `campaigns-os doctor` to confirm before calling `next` again.
1885
- - **`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, and `qa run` for QA. `record deploy` records the served deploy, a loopback URL for a local-serve target or an https URL for a hosted one. Then call `next` again.
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.
1886
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.
1887
1889
 
1888
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