@nextcommerce/campaigns-os 1.41.2 → 1.43.2

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 (83) hide show
  1. package/AGENTS.md +4 -2
  2. package/CHANGELOG.md +629 -0
  3. package/README.md +8 -6
  4. package/agents/claude/CLAUDE.md +5 -1
  5. package/campaign-spec/dist/types.d.ts +2 -0
  6. package/contracts/agent-relevant-change-policy.v1.json +5 -0
  7. package/contracts/effects.v1.json +118 -25
  8. package/contracts/migration-sidecar-bundle.v0.json +9 -0
  9. package/contracts/release-ledger.json +1424 -0
  10. package/contracts/supported-surface.json +12 -11
  11. package/docs/build-packet.md +120 -8
  12. package/docs/campaigns-os-build-flow.md +3 -2
  13. package/docs/design-source-package.md +89 -15
  14. package/docs/effects.md +83 -2
  15. package/docs/local-setup.md +51 -0
  16. package/docs/migration-sidecar-bundle.md +6 -1
  17. package/docs/orientation-contract-reference.md +1 -1
  18. package/docs/progress-snapshots.md +16 -6
  19. package/docs/qa-and-test-orders.md +157 -17
  20. package/docs/release-ledger-authoring-guide.md +6 -4
  21. package/docs/runtime-readiness.md +1 -1
  22. package/docs/skills-revision.md +10 -10
  23. package/package.json +3 -2
  24. package/schemas/campaign-runtime-assembly-report.v0.schema.json +6 -1
  25. package/schemas/campaign-runtime-build-packet.v0.schema.json +6 -1
  26. package/schemas/campaign-spec.v4.schema.json +4 -0
  27. package/schemas/campaigns-os-progress-snapshot.v0.schema.json +1 -0
  28. package/schemas/campaigns-os-qa-verdict-sidecar.v0.schema.json +1 -0
  29. package/schemas/campaigns-os-qa-verdict.v0.schema.json +1 -0
  30. package/schemas/campaigns-os-run-record.v0.schema.json +1 -0
  31. package/skills/campaign-lifecycle-orientation/SKILL.md +13 -8
  32. package/skills/campaign-readback-classification/SKILL.md +3 -3
  33. package/skills/campaign-run-evidence/SKILL.md +8 -6
  34. package/skills/contribution-intake/SKILL.md +3 -3
  35. package/skills/next-campaigns-build/SKILL.md +4 -4
  36. package/skills/next-campaigns-os/SKILL.md +17 -4
  37. package/skills/next-campaigns-os/references/session-intake.md +4 -4
  38. package/skills/next-campaigns-os-setup/SKILL.md +3 -3
  39. package/skills/next-campaigns-polish/SKILL.md +3 -3
  40. package/skills/next-campaigns-qa/SKILL.md +10 -9
  41. package/skills.json +11 -11
  42. package/src/build-brief.mjs +6 -4
  43. package/src/built-script-syntax.mjs +480 -0
  44. package/src/campaigns-api-key.mjs +99 -0
  45. package/src/cli-helpers.mjs +118 -0
  46. package/src/cli.mjs +796 -6963
  47. package/src/design-source-package.mjs +1 -1
  48. package/src/design-source-publication.mjs +898 -0
  49. package/src/diagnostic.mjs +2 -1
  50. package/src/directory-lock.mjs +270 -0
  51. package/src/doctor/checks.mjs +4415 -0
  52. package/src/doctor/inspect.mjs +636 -0
  53. package/src/doctor/next-step.mjs +731 -0
  54. package/src/finding-cause.mjs +14 -10
  55. package/src/install-invocation.mjs +29 -0
  56. package/src/invocation.mjs +179 -0
  57. package/src/lifecycle.mjs +5 -4
  58. package/src/polish-node.mjs +5 -2
  59. package/src/private-template-source.mjs +1 -1
  60. package/src/progress-node.mjs +9 -37
  61. package/src/progress.mjs +5 -3
  62. package/src/proof-policy.mjs +1 -1
  63. package/src/qa-analytics-correctness.mjs +3 -0
  64. package/src/qa-binding-evidence.mjs +76 -11
  65. package/src/qa-browser.mjs +778 -77
  66. package/src/qa-build-scope.mjs +47 -0
  67. package/src/qa-node.mjs +276 -39
  68. package/src/qa-publish.mjs +4 -0
  69. package/src/qa-sidecar.mjs +2 -0
  70. package/src/qa-verdict-discovery.mjs +11 -0
  71. package/src/qa-verdict-publish.mjs +1 -0
  72. package/src/qa-verdict.mjs +8 -1
  73. package/src/readback.mjs +2 -1
  74. package/src/run-record-closeout.mjs +3 -4
  75. package/src/run-record.mjs +4 -0
  76. package/src/sidecar-bundle.mjs +21 -0
  77. package/src/source-html-intake.mjs +1 -1
  78. package/src/source-html-manifest.mjs +9 -2
  79. package/src/spec-source-identity.mjs +44 -0
  80. package/src/stage-ledger.mjs +32 -1
  81. package/src/target-lock.mjs +54 -0
  82. package/src/template-brand-contract.mjs +17 -1
  83. package/src/tooling-setup.mjs +160 -0
package/AGENTS.md CHANGED
@@ -117,8 +117,10 @@ appends no lifecycle entry and creates no file of its own. One effect does
117
117
  precede argument refusal: `start`, `prepare-build`, `build`, `run start` and
118
118
  `run end` close out a stale run session at the root they are about to act on
119
119
  before argv is refused, which is a declared effect of those commands and is
120
- suppressed by `--no-write`. Every remitting command's effect declaration, when
121
- published, names its destination as open-world, and the agent onboarding skill
120
+ suppressed by `--no-write`. Commands implementing `--dry-run` also suppress
121
+ that closeout whenever the flag is present, including a value that will be
122
+ refused (such as `run end --dry-run yes`). Every remitting command's effect
123
+ declaration, when published, names its destination as open-world, and the agent onboarding skill
122
124
  records an explicit telemetry choice before the first remitting command.
123
125
 
124
126
  1.37.0 adds `demo --target <new-directory>`, an offline visual sample
package/CHANGELOG.md CHANGED
@@ -2,6 +2,635 @@
2
2
 
3
3
  Notable supported-surface changes are recorded here.
4
4
 
5
+ ## [1.43.2] - 2026-09-28
6
+
7
+ ### Changed
8
+
9
+ - Stabilization release. Package and supported-surface version advance to
10
+ 1.43.2 and ship every same-surface change recorded since 1.43.1
11
+ (`1.43.1+agent.1` through `1.43.1+agent.23`). No command, message, or exit
12
+ code changes in this release itself.
13
+ - `contracts/effects.v1.json` notes for the eight `--dry-run` invocations now
14
+ say the command is declared `dryRun` in `src/invocation.mjs` instead of
15
+ naming the removed `DRY_RUN_COMMANDS` set. The declared effects are
16
+ unchanged.
17
+ - The local setup install command pins the 1.43.2 package. Bundled skills
18
+ carry revision `1.43.2+skills.1`, with each skill version advanced one patch.
19
+
20
+ ## [1.43.1+agent.23] - 2026-09-28
21
+
22
+ ### Changed
23
+
24
+ - No command behaves differently. The comment in the doctor's `route_root`
25
+ declaration check now uses a neutral placeholder for its near-miss route
26
+ examples and states the canonical form (`"/"` or `"/<public_route_slug>/"`)
27
+ outright. Comment-only; every message and every exit code is unchanged.
28
+
29
+ ## [1.43.1+agent.22] - 2026-09-28
30
+
31
+ ### Changed
32
+
33
+ - No command behaves differently. Follow-ups the 1.43.1+agent.21 review
34
+ recorded: the filesystem path-identity helper the doctor's next-step picker
35
+ and the Design Source Package publication share moved from `src/doctor/`
36
+ to the shared helper module (one definition; the doctor module now imports
37
+ it), stale comments in the publication module that still named
38
+ `prepare-build` as the target-lock holder now name the publication entry
39
+ that holds it, the Campaign Build Brief's private JSON clone (which maps a
40
+ nullish brief to an empty object, unlike the shared clone) is renamed so it
41
+ no longer shadows the shared helper, and the CLI drops three imports
42
+ nothing used. Every message and every exit code is unchanged.
43
+
44
+ ## [1.43.1+agent.21] - 2026-09-27
45
+
46
+ ### Changed
47
+
48
+ - No command behaves differently. Design Source Package publication for
49
+ `prepare-build`, `start` and `build` now has one owner instead of being
50
+ restated inside `prepare-build`: the pending provenance record, the target
51
+ lock's critical section, the output collision checks, the stage-evidence
52
+ re-checks and the staged publication order. The on-disk names, the
53
+ publication order, every message and every exit code are unchanged.
54
+
55
+ ## [1.43.1+agent.20] - 2026-09-27
56
+
57
+ ### Changed
58
+
59
+ - No command behaves differently. The doctor checks, the Build Packet and
60
+ built-output inspection, and the next-step picker that `doctor` and `next`
61
+ share now live under `src/doctor/` instead of inside the CLI module. Every
62
+ check, its order, its messages and its exit codes are unchanged.
63
+ - `contracts/agent-relevant-change-policy.v1.json` classifies a change under
64
+ `src/doctor/` as a CLI-surface change, so a later change there owes a
65
+ release-ledger entry. The shared helper modules `src/install-invocation.mjs`,
66
+ `src/cli-helpers.mjs` and `src/campaigns-api-key.mjs` are classified as
67
+ implementation, so a change confined to them owes a CHANGELOG section but no
68
+ release-ledger entry, even where a doctor message reads through them.
69
+ - The general helpers the CLI and the doctor share (the install-aware command
70
+ spelling, small value and JSON-file helpers, and Campaigns API key
71
+ resolution) moved to their own modules under `src/`. They are internal
72
+ implementation, not package exports.
73
+ - The repository's tests and performance worker import the moved functions from
74
+ their new modules.
75
+
76
+ ## [1.43.1+agent.19] - 2026-09-27
77
+
78
+ ### Changed
79
+
80
+ - No command behaves differently. The CLI's invocation policy now has one
81
+ owner instead of being restated at each step: which commands run outside
82
+ session recovery and lifecycle capture, where the stale run-session
83
+ closeout runs before `start`, `prepare-build`, `build`, `run start` and
84
+ `run end` and what suppresses it (`--no-write`, `--no-run-session`, and
85
+ `--dry-run` on a command that implements it), which invocations append no
86
+ lifecycle entry, which commands implement `--dry-run`, and when `qa run`
87
+ ends its run session. Every declared effect, every argument refusal and its
88
+ order, and the valued `--dry-run` and bare `run` behaviours are unchanged.
89
+ - The command list behind the did-you-mean suggestion for an unknown command
90
+ now comes from that same declaration instead of being read out of the
91
+ dispatch code's text. The list, its order and the suggestions are
92
+ unchanged.
93
+
94
+ ## [1.43.1+agent.18] - 2026-09-27
95
+
96
+ ### Fixed
97
+
98
+ - `prepare-build` no longer loses track of a Design Source Package it
99
+ synthesized when the run fails or is killed after publishing the package
100
+ but before writing the Assembly Report that records it. Before the package
101
+ goes out, the run writes a pending provenance record beside it
102
+ (`.campaign-runtime/input/.design-source-package.json.pending-provenance.json`)
103
+ with the sha256 of the bytes it is publishing, and removes it once the
104
+ report is written. A retry that finds the record treats a package that
105
+ still hashes to it as `origin: "synthesized"`, so a later `--force` after a
106
+ manifest edit regenerates the package instead of refusing it as someone
107
+ else's. A `--force` regeneration keeps the replaced package's hash in the
108
+ record until the replacement is recorded, so a regeneration that fails or
109
+ dies part way leaves the package on disk provable, and a run that adopts
110
+ another writer's package instead of publishing drops its own candidate from
111
+ the record. Just before the report is published the record is narrowed to
112
+ the package the report records. Bytes changed since the failure, and a
113
+ malformed record, are not vouched for. The record's path is reserved: no
114
+ configurable output may point at it.
115
+ - The `manifest_sha256` the Design Source Package records is now the hash of
116
+ the exact source-html manifest bytes source intake parsed. The file was
117
+ read twice, once to parse and once to hash, so an edit between the two
118
+ recorded a hash that did not describe the parsed manifest.
119
+ - With `--map-id`, `start`, `prepare-build` and `build` still fetch the Map
120
+ first, but write the fetched spec to the shared
121
+ `.campaign-runtime/fetched-specs/<map-id>.json` cache file only once they
122
+ hold the per-target prepare-build lock. A run waiting for the lock could
123
+ previously overwrite the cache with a newer revision while the lock holder
124
+ was still recording it, so the holder recorded mappings from one revision
125
+ beside hashes of the other. Argv-only intake refusals still happen before
126
+ any spec read, fetch or cache write, and a failed fetch still writes
127
+ nothing.
128
+ ## [1.43.1+agent.17] - 2026-09-27
129
+
130
+ ### Fixed
131
+
132
+ - The per-target lock that `prepare-build` holds, and the progress allocation
133
+ lock, can no longer be held by two processes at once. A process suspended
134
+ after creating the lock directory but before recording its owner used to
135
+ lose the lock to a waiter after ten seconds, and then both ran. The lock
136
+ directory and its owner record are now published together by one rename,
137
+ each holder confirms its own token before entering, and release only ever
138
+ removes a lock that still carries the holder's token. A lock directory with
139
+ no owner record, which only an older release leaves, is never taken over:
140
+ the command refuses it after about a second with a message naming the lock
141
+ directory (for progress capture, the warning now names the affected
142
+ `.allocation-lock`); remove it by hand once no campaigns-os process is
143
+ working on the target. A waiter that loses the publishing rename to a
144
+ holder that has already released now retries instead of failing. Do not run
145
+ an older release against the same target at the same time.
146
+ - Commands that edit the Assembly Report (`doctor`, `qa run`, waivers, the
147
+ polish merge and the other stage producers) now take the same per-target
148
+ lock as `prepare-build` for their read-modify-write, so stage evidence can
149
+ no longer land between `prepare-build`'s final stage-evidence check and its
150
+ publication. A producer reached from inside `prepare-build`'s own run enters
151
+ without waiting on itself. A waiver `--dry-run` preview writes nothing and
152
+ takes no lock.
153
+ - `prepare-build` refuses a `--out`, `--context-out`, `--report-out`,
154
+ `--doctor-out` or `--brief-out` path inside the lock directory
155
+ (`.campaign-runtime/input/.design-source-package.json.lock`) or the
156
+ staging and tomb directories the lock creates beside it (`.lock.staging-*`,
157
+ `.lock.recovery-staging-*`, `.lock.released-*`, `.lock.abandoned-*`),
158
+ including through a symlinked directory or a case-only alias. Such an output was written and then deleted with the lock, leaving
159
+ the packet and context pointing at a missing file.
160
+ ## [1.43.1+agent.16] - 2026-09-27
161
+
162
+ ### Fixed
163
+
164
+ - QA's optional analytics comparison against a legacy funnel
165
+ (`--analytics-baseline`) now measures a partial build's first built page
166
+ when the campaign root is not part of the build or does not answer, the same
167
+ way the analytics correctness check has since #493. It used to measure the
168
+ campaign root only, which a partial build does not have. The comparison
169
+ records which page it measured. When no built page answers, it is skipped
170
+ if there was nothing to try, and blocks if every page it tried failed; in
171
+ both cases the legacy funnel is not loaded. An explicit
172
+ `--analytics-candidate` URL is still measured as given.
173
+ - A funnel entry whose URL differs from the campaign root only by its query
174
+ string (for example `/campaign/?step=checkout`) is no longer treated as the
175
+ root. On a partial build, the root counted as built and the entry was
176
+ dropped as a duplicate, so the root's generic page was measured instead of
177
+ that entry. The entry is now measured itself and marked `query_routed`.
178
+ Step routing stays path-based in every certified family.
179
+ - `docs/qa-and-test-orders.md` now describes which page the analytics checks
180
+ measure on a partial build, the `no_in_scope_page_captured` and
181
+ `no_capture_page_answered` outcomes, how query strings affect page identity,
182
+ and when a local-serve run turns a silent pixel into `manual_review`: a
183
+ recorded development render and a page measured on localhost, with
184
+ `data-layer-purchase` still blocking.
185
+ ## [1.43.1+agent.15] - 2026-09-27
186
+
187
+ ### Fixed
188
+
189
+ - The doctor `built_output.script_syntax` gate and the QA `script-parse`
190
+ check now resolve each `<script src>` against the base in effect when the
191
+ parser prepares that script at its end tag: the first HTML `<base href>` in
192
+ tree order among those already parsed, or else the page. A `<base>` parsed
193
+ after a script no longer moves it, whether it is async, deferred or a
194
+ module, and parse order decides even when table foster parenting reorders
195
+ the tree. An SVG `base` no longer counts, and the href is no longer trimmed
196
+ of non-ASCII whitespace the URL parser keeps. Only HTML-namespace
197
+ `<script>` elements are page scripts: an SVG `<script src>` is no longer
198
+ read or parsed by doctor, and QA leaves a page with an SVG script dynamic
199
+ instead of fetching it. Only an empty `src` is skipped, as the browser
200
+ skips it; a `src` of other whitespace is resolved and read. QA recognises
201
+ the Campaign Cart SDK by its URL as the parser reads it, so a tab or
202
+ newline inside the attribute no longer makes the SDK look like an
203
+ unavailable config script. A base
204
+ the browser refuses (a `data:` or `javascript:` URL, or one that does not
205
+ parse) now falls back to the page, as the HTML "set the frozen base URL"
206
+ steps require, so the local script is read and a parse failure in it blocks
207
+ instead of the script being listed as unresolved (#502).
208
+
209
+ ### Changed
210
+
211
+ - A local script a built page loads that is not in the built output is now a
212
+ doctor warning, `built_output.script_syntax.missing_script`, one per src
213
+ naming the pages that load it. It was information on the gate only. It does
214
+ not block. While a parse failure blocks the gate, the missing scripts stay
215
+ on the gate's `warned[]` (#502).
216
+ - `fixtures/certified-families/` now carries every local script the rendered
217
+ pages load (each family's `js/*.js` beside `config.js`), refreshed from the
218
+ same templates commit. `scripts/refresh-certified-family-fixtures.mjs`
219
+ copies them, resolved the way the gate resolves them, and fails when a
220
+ referenced script is not in the render, or a copied file is a symlink or
221
+ resolves outside the family's render. The reachability test reads the
222
+ expected scripts from the HTML independently of the gate and requires the
223
+ gate to read exactly that set on every certified family (#502).
224
+ ## [1.43.1+agent.14] - 2026-09-27
225
+
226
+ ### Fixed
227
+
228
+ - An accepted upsell whose mutation body loads late is now matched to the
229
+ request its own click made, not to any response on the order-upsells URL.
230
+ Every upsell step in a path posts to the same `/orders/<ref>/upsells/` URL,
231
+ whether the steps share a page or sit on separate pages, so an earlier
232
+ step's slow body could land while a later step waited for its own and be
233
+ judged as the later step's evidence: failing it when that body lacked its
234
+ line, or passing it on the earlier step's line. The runner keeps the
235
+ Playwright request of each captured response and of each step's mutation
236
+ and accepts a late body only when the two are the same request. A step
237
+ whose own body never arrived and that no later read-back settled is
238
+ unverified even when the stale lines on hand would have matched. The
239
+ step's mutation watch also ignores any order-upsells response whose
240
+ request started before the watch was armed at the click, so an earlier
241
+ step's response that arrives late, after its own watch expired, is no
242
+ longer taken as this step's.
243
+ - A test-order path whose only open question is an unverified accepted upsell
244
+ is no longer `ok` on its result. The result carries `upsell_unverified`
245
+ instead, the order's `verification.verified` is `false` (so the purchase
246
+ proof summary no longer counts it in `orders_verified`; it still counts in
247
+ `orders_created`), and the path is neither re-run (a second order) nor
248
+ passed through read-only recovery (which cannot re-check an upsell). The
249
+ `browser-test-order` assertion still reports it as `manual_review`. A path
250
+ with an unverified upsell and another failure is recovered as before, but
251
+ a recovery that clears the other failure leaves the upsell unverified: the
252
+ result goes to `manual_review`, not `pass`, and the order stays unverified.
253
+ ## [1.43.1+agent.13] - 2026-09-27
254
+
255
+ ### Changed
256
+
257
+ - The lifecycle effects tests now prove that `start`, `prepare-build` and
258
+ `build` refuse a bare, empty or whitespace `--template-family`,
259
+ `--allow-uncertified-template`, `--theme-policy` or `--brief`, and an
260
+ unsupported `--theme-policy`, before the CampaignSpec is looked at. The
261
+ earlier refusal tests seeded a valid spec, so a check that ran after the
262
+ spec was read would still have passed them. The new cases make the local
263
+ `--spec` file and the `--cached-spec` cache file missing, a directory, or
264
+ malformed JSON, and require the flag refusal with no journal entry, no fetch
265
+ and an unchanged tree. The tree snapshot these tests compare now lists
266
+ directories as well as files, so a refusal that only creates an empty
267
+ directory is caught too. Tests only; CLI behavior is unchanged (#504).
268
+
269
+ ## [1.43.1+agent.12] - 2026-09-26
270
+
271
+ ### Fixed
272
+
273
+ - QA no longer blocks every local proof run on analytics. Under
274
+ `deploy.target: local-serve` the build renders the development environment,
275
+ which leaves out the vendor loaders on purpose, so a declared pixel could
276
+ never fire on localhost. When the run is served from localhost and the build
277
+ recorded `stages.assembly.evidence.build_environment: development`, the tag,
278
+ out-of-band vendor and receipt Purchase (`purchase-fires`) checks that did
279
+ not fire on a page measured on localhost are now `manual_review` with the
280
+ reason `local_serve_development_render` instead of blockers. Each one says
281
+ to re-run QA against the PR preview with `--base-url <preview-url>`, which
282
+ is a production render and still gates them, and cites the recorded
283
+ `page-kit parity` result when there is one. A production build, or a build
284
+ with no recorded environment, keeps its blockers on localhost. The exception
285
+ covers only pages measured on localhost: the tracking capture now records
286
+ the page URL it settled on after redirects (`final_url`), and a capture that
287
+ landed on another host, such as a built entry page whose URL is a production
288
+ preview or a localhost root that redirects to production, keeps its
289
+ blockers. So does a receipt Purchase check whose receipt page is not on
290
+ localhost, judged both by the order's final URL and by the page URL read
291
+ after the receipt's analytics settled (`receipt_document_url`), so a
292
+ localhost receipt that redirects to a hosted page while analytics settle
293
+ keeps its blocker, as does any check whose measured page was not recorded.
294
+ So does a capture that failed: a `purchase-fires` failure that lists
295
+ unmeasured receipts in `capture_error_plan_ids` still blocks, and a tracking
296
+ capture whose page could not be read (for example, a page that reloaded
297
+ while the capture read it) now fails as the analytics runner blocker instead
298
+ of reading as a page where nothing fired. The data-layer Purchase
299
+ check (`data-layer-purchase`) still blocks too: the SDK pushes `dl_purchase`
300
+ in the development render as well.
301
+
302
+ ## [1.43.1+agent.11] - 2026-09-26
303
+
304
+ ### Fixed
305
+
306
+ - `start`, `prepare-build` and `build` now refuse a bare, empty or
307
+ whitespace-only `--template-family`, `--allow-uncertified-template`,
308
+ `--theme-policy` or `--brief`, and a `--theme-policy` other than
309
+ `inspect_only`, `auto` or `off`, before reading the spec, fetching the Map or
310
+ writing the spec cache. Before, these four were read only after the spec was
311
+ resolved: a blank value was quietly ignored (or, for `--theme-policy`, fell
312
+ back to `inspect_only`), and an unknown theme policy failed partway through
313
+ intake and was journaled as a handler failure. A refused invocation writes
314
+ no journal entry. Whether a named family is certified, and whether a named
315
+ brief can be read, still depend on file content, so those failures are still
316
+ journaled.
317
+ ## [1.43.1+agent.10] - 2026-09-26
318
+
319
+ ### Fixed
320
+
321
+ - Browser QA no longer hangs on an upsell accept when the page moves on before
322
+ the upsell response body has loaded. The runner read that body with no time
323
+ limit, and a page that redirected as soon as the response headers arrived
324
+ could leave the read waiting forever. The read now gives up after a few
325
+ seconds: the step still reports the response and its status, with no order
326
+ body, and records that the read timed out. Checkout event capture keeps its
327
+ unbounded read, since nothing waits on it: an order body that loads late
328
+ still counts as order evidence.
329
+ - A slow but successful upsell accept is no longer failed as "no new upsell
330
+ line". When the upsell body read times out on a successful response, the
331
+ step waits up to 15 seconds, inside its own time budget, for the late body
332
+ or an order read-back that shows the accepted line. If neither arrives, the
333
+ upsell is reported as unverified and the test order goes to manual review,
334
+ not to a blocker. A late body, or an order read-back captured after the
335
+ click, that lacks the line still fails.
336
+ ## [1.43.1+agent.9] - 2026-09-26
337
+
338
+ ### Fixed
339
+
340
+ - Doctor no longer reports a build ready when a campaign script has a syntax
341
+ error. Every doctor run that sees built output, `doctor --built` and the
342
+ packet path alike, now parses each campaign-owned `.js` file a built page
343
+ loads by a local `<script src>`, and blocks under
344
+ `built_output.script_syntax.parse_failure` when one does not parse. The error
345
+ names the file, line and column, for example a hand-edited checkout script
346
+ left with one closing `});` too many. Remote scripts such as CDN URLs are not
347
+ read, `type="module"` scripts are parsed as modules, and classic `nomodule`
348
+ scripts are skipped. Script types are read as the browser reads them, trimmed
349
+ of surrounding whitespace and case-insensitive, and a module script is parsed
350
+ even when it carries `nomodule`, since the browser still runs it. Script paths resolve against the page's `<base href>` and are
351
+ percent-decoded, as the browser loads them. The gate is not waivable and
352
+ passes on every certified starter family.
353
+ - QA no longer reads a page script that does not parse as "dynamic". The
354
+ credential binding treats its declarations as unavailable, and QA adds a
355
+ `script-parse:<page_id>` blocker naming the script, line and column. Both
356
+ report a fixed diagnostic category, never text from the script. QA
357
+ classifies script types the same way doctor does.
358
+ ## [1.43.1+agent.8] - 2026-09-26
359
+
360
+ ### Fixed
361
+
362
+ - `prepare-build --force` (and `start --force` and `build --force`) now
363
+ regenerates a stale Design Source Package that an earlier `prepare-build`
364
+ synthesized, instead of refusing it. Previously, editing the source manifest
365
+ after a first run left `.campaign-runtime/input/design-source-package.json`
366
+ stale, and every rerun failed until the file was deleted by hand, with nothing
367
+ in the output saying so. The Assembly Report now records the package's
368
+ `origin` (`synthesized` or `adopted`), and a package counts as the producer's
369
+ own only when that report says `synthesized` and the bytes on disk still match
370
+ its hash. A package placed by an operator, edited by hand, or recorded by an
371
+ older report is still refused, `--force` or not. Every refusal now names the
372
+ file and the recovery: rerun with `--force` for the producer's own package,
373
+ otherwise reconcile it or delete it and rerun.
374
+ - The manifest docs now say up front that a source-html manifest `pages[]`
375
+ entry with both `path` and `skip_reason` is invalid.
376
+ ## [1.43.1+agent.7] - 2026-09-26
377
+
378
+ ### Fixed
379
+
380
+ - QA's analytics tracking check works on partial builds. It used to capture the
381
+ campaign root (`/<slug>/`) even when the build starts deeper, such as at
382
+ `checkout/`, so it read an empty page and failed every declared pixel as
383
+ absent. On a partial build the root now counts as in scope only when a
384
+ built, in-scope page is served there, so a host's directory index or
385
+ generic fallback at the root is never measured. When the root is out of
386
+ scope, answers with a non-2xx status, or fails to load (a navigation timeout
387
+ or network error), the check captures the first built in-scope page, the same entry partial-scope QA starts from, and records the
388
+ page it used and why on the `analytics-correctness:capture` evidence. If the
389
+ build has no capturable page at all, the check is skipped with the reason
390
+ `no_in_scope_page_captured`. If pages existed but none answered 2xx or
391
+ loaded at all, the check fails as a blocker with the reason `no_capture_page_answered` and
392
+ lists each attempt, because the declared vendors went unmeasured.
393
+
394
+ ## [1.43.1+agent.6] - 2026-09-26
395
+
396
+ ### Fixed
397
+
398
+ - Browser QA no longer misses the upsell accept on a control that pulses
399
+ forever, such as a stock `pb-animate="pulse-upsell"` button. The runner used
400
+ to wait about 30 seconds for the control to settle before scrolling to it and
401
+ another 10 before forcing the click, so the upsell POST landed after its
402
+ 20-second watch had expired. That reported `api_response_seen: false` for an
403
+ accept that had worked, and could time out deep accept paths. Controls are now
404
+ scrolled into view without a settle wait, a control that animates forever is
405
+ clicked straight away, and the watch starts at the click. Cart-entry,
406
+ package-card, checkout-submit and text-matched clicks use the same bounded
407
+ scroll.
408
+
409
+ ## [1.43.1+agent.5] - 2026-09-26
410
+
411
+ ### Fixed
412
+
413
+ - Payment-logo residue checks ignore starter `payment-logos.html` logos that
414
+ are still `hidden`. The template hides each method's logo until the campaign
415
+ offers it, so doctor and browser QA no longer flag PayPal or Klarna on pages
416
+ built from the new templates. A logo left visible is still checked; when a
417
+ page forces one on, doctor's warning points at the `payment_flags.show_<method>`
418
+ frontmatter flag.
419
+
420
+ ## [1.43.1+agent.4] - 2026-09-26
421
+
422
+ ### Fixed
423
+
424
+ - Partial-build QA skips recorded, unbuilt out-of-scope pages with explicit
425
+ `out_of_build_scope` evidence and starts at the first in-scope page. Built
426
+ stock pages rejoin QA; missing in-scope pages still fail. Commercial checks
427
+ share the same scope as HTTP and browser checks.
428
+ - Build handoffs keep skipped routes unbuilt by default. Materializing a stock
429
+ stand-in requires explicit per-page operator opt-in, so upstream pages on
430
+ another host are not replaced with placeholder copy.
431
+ ## [1.43.1+agent.3] - 2026-09-26
432
+
433
+ ### Fixed
434
+
435
+ - Legacy direct-API QA rejects missing or unusable carts and unknown test-order
436
+ modes before resolving campaign inputs, without appending a lifecycle entry.
437
+ Browser QA precedence and legacy API credential checks are unchanged.
438
+
439
+ ## [1.43.1+agent.2] - 2026-09-26
440
+
441
+ ### Fixed
442
+
443
+ - `run end --dry-run yes` now refuses the valued flag without closing a stale
444
+ session first. No Run Record, lifecycle entry, remit, or session deletion
445
+ occurs. Bare `--dry-run` and ordinary run closeout keep their existing behavior.
446
+
447
+ ## [1.43.1+agent.1] - 2026-09-25
448
+
449
+ ### Fixed
450
+
451
+ - Doctor recognizes numeric package, shipping and offer references exported by
452
+ the Map, so declared commerce IDs no longer trigger false undeclared-package
453
+ blockers or starter-demo warnings. Reference fallback fields now use the same
454
+ string-or-finite-number rule; other types are ignored instead of stringified.
455
+
456
+ ## [1.43.1] - 2026-09-24
457
+
458
+ ### Fixed
459
+
460
+ - Restamp the local setup install command to the 1.43.1 package and check its
461
+ documented toolkit pin against `package.json` during CI.
462
+ - In 1.42.1, `run end` journaled several inherited flag refusals that 1.41.x
463
+ refused without a journal entry, including unknown `--surfaces` and valued
464
+ `--dry-run`. `run end` and `run-record` now refuse bare, empty, or
465
+ whitespace-only values for every value-taking inherited run-record flag
466
+ before packet work. The agent token and elapsed-time flags keep their integer
467
+ diagnostics; unknown `--surfaces` and valued `--dry-run` are refused. `run end`
468
+ also refuses `--new-run` and `--run-id`, since the saved session fixes its run
469
+ ID. `run-record` also refuses bare, empty, or whitespace-only `--run-id` and
470
+ valued `--new-run`. These argv-only refusals append no lifecycle entry.
471
+ - `start`, `prepare-build`, and `build` refuse bare, empty, or whitespace-only
472
+ values of `--spec`, `--map-id`, `--source`, `--target`, `--source-kind`,
473
+ `--proxy-base`, `--wrapper-policy`, `--design-manifest`, and
474
+ `--order-path-depth` before local spec reads, Map fetches, or cache writes on
475
+ the `--spec`, `--map-id`, and `--map-id --cached-spec` paths.
476
+ - Internal stale-session and QA closeouts retain their prior handling of
477
+ inherited flags. A bare, empty, or whitespace-only `--proxy-base` on a
478
+ sweeping command still writes the stale session's Run Record. Terminal QA
479
+ still auto-ends with a whitespace-only inherited `--context`, `--report`, or
480
+ `--proxy-base`; a whitespace-only `--context` resolves as a literal relative
481
+ path, so the default context file is not read. Bare or empty `--context` or
482
+ `--report` still makes QA auto-end fail and leaves the session open. A bare
483
+ or empty `--qa-verdict` still fails a Run Record closeout when inherited;
484
+ QA auto-end supplies its own verdict path.
485
+ - Correct the 1.42.1 note: QA with a named packet yielding no Map ID after
486
+ checkpoint preflight changed from a refusal to a journaled handler failure
487
+ in that release; it did not *remain* journaled. A named packet now satisfies
488
+ QA identity with a Map ID or a valid local-spec identity. If preflight yields
489
+ neither or finds conflicting local and Map identities, QA journals a handler
490
+ failure.
491
+
492
+ ### Changed
493
+
494
+ - Package and supported-surface version advance to 1.43.1. Bundled skills
495
+ carry revision `1.43.1+skills.1`, with each skill version advanced one patch.
496
+
497
+ ## [1.43.0+agent.4] - 2026-09-24
498
+
499
+ ### Fixed
500
+
501
+ - Run Record validation and its schema treat a null `local_spec_id` as absent,
502
+ preserving saved-Map records and best-effort capture with partial identity.
503
+ Non-null malformed or conflicting local IDs still fail before persistence.
504
+
505
+ ## [1.43.0+agent.3] - 2026-09-24
506
+
507
+ ### Fixed
508
+
509
+ - Invalid campaign identities cannot select prior doctor history, including
510
+ when a malformed local ID would otherwise leave a Map-only or unfiltered
511
+ lookup. Such findings retain unknown cause instead of borrowing evidence.
512
+ - Integrate the 1.42.1 argument-refusal fixes: local-spec packet QA remains
513
+ supported, while identity failures discovered from packet content remain
514
+ journaled handler failures. Advance bundled skill versions beyond 1.42.1.
515
+
516
+ ## [1.43.0+agent.2] - 2026-09-24
517
+
518
+ ### Fixed
519
+
520
+ - Evidence identity projection and Run Record writes reject malformed or
521
+ conflicting local IDs instead of propagating them. Doctor keeps malformed
522
+ input diagnosable with `spec.local_identity`; saved-Map errors retain their
523
+ existing code and normalization. Local IDs remain exact canonical tokens.
524
+ - Declare the optional local progress identity inline without mutating the
525
+ portable schema after construction.
526
+
527
+ ## [1.43.0+agent.1] - 2026-09-24
528
+
529
+ ### Fixed
530
+
531
+ - Entry-point and QA instructions distinguish saved-Map builds from local-spec
532
+ builds, including local verdict storage, evidence identity and publication
533
+ suppression. Bundled QA and evidence skills follow the same distinction.
534
+ - Page Kit sync and spec derivation retain the saved-Map mismatch diagnostic
535
+ while refusing mismatched local identities before writes.
536
+
537
+ ## [1.43.0] - 2026-09-24
538
+
539
+ ### Added
540
+
541
+ - Agent-authored CampaignSpecs can use a stable `spec_identity.local_spec_id`
542
+ instead of a saved Map. Preparation preserves that identity in packets and
543
+ reports; doctor, polish, QA, progress, readback and run closeout distinguish it
544
+ from both the public route and saved Map identity. Material hashes continue
545
+ to bind each spec revision, including across fresh checkouts.
546
+ - Packet-based local QA writes full verdicts and committed sidecars with the
547
+ local ID, refuses foreign or stale local reports, and never publishes them to
548
+ the Map portal. `qa publish` refuses local-spec packets. Existing saved-Map
549
+ workflows retain their identity and publication behavior.
550
+ - Local setup and intake instructions let the coding agent author the spec
551
+ from prepared HTML, a brief and verified configured commerce. Existing
552
+ certification, source, runtime, polish and checkout proof gates still apply.
553
+
554
+ ## [1.42.1] - 2026-09-24
555
+
556
+ ### Fixed
557
+
558
+ - `start`, `prepare-build`, and `build` now refuse missing or invalid argument
559
+ values for source, target, source kind, wrapper policy, design-manifest value,
560
+ and order-path depth before spec resolution or preparation. `run-record`
561
+ refuses conflicting `--new-run`/`--run-id` and invalid agent token counts
562
+ before reading its packet or journal. These argv-only refusals append no
563
+ lifecycle entry.
564
+ - `qa run` and `qa resolve` refuse empty campaign selectors and selector flags
565
+ without values before checkpoint or site reads. Built-site QA also refuses
566
+ missing `--base-url` or `--family` before scanning the site. An unknown
567
+ `next` stage refuses before the handler reads the packet or runs doctor,
568
+ names the accepted stages (`setup`, `build`, `polish`, `deploy`, `qa`), and
569
+ appends no lifecycle entry. The `next` help line now shows those stages.
570
+ - Three state-dependent decisions remain journaled handler failures: `polish
571
+ capture` when `packet.assembly.target_repo` does not resolve to a local target
572
+ repo; `run end` with no packet in argv or the saved session; and `qa run` or
573
+ `qa resolve` with a named packet that yields no Map ID after checkpoint
574
+ preflight. The polish check currently cannot fire through the CLI because
575
+ the workspace resolver supplies a local path. Separately, a named design
576
+ manifest that is missing, not a file, or invalid is a journaled handler
577
+ failure. A nested run-record refusal during `run end` or QA auto-closeout
578
+ stays within the closeout attempt, so it does not turn the invoking command's
579
+ journal verdict into a refusal. The ambient run-session lookup may still
580
+ read a named `--packet` before the handler runs.
581
+
582
+ ### Changed
583
+
584
+ - Package and supported-surface version advance to 1.42.1. The bundled skills
585
+ carry revision `1.42.1+skills.1`, with each skill version advanced one patch
586
+ so an agent can detect instructions loaded from an older release.
587
+
588
+ ## [1.42.0+agent.2] - 2026-09-24
589
+
590
+ ### Fixed
591
+
592
+ - The effects guide names both `qa install-browser` and `tooling setup` as
593
+ browser downloaders, matching the declared effects contract.
594
+
595
+ ## [1.42.0+agent.1] - 2026-09-24
596
+
597
+ ### Fixed
598
+
599
+ - Setup recovery preserves an existing project's dependency choices instead
600
+ of recommending a fixed page-kit version. New projects use the install
601
+ instructions bundled with the release.
602
+ - Setup explicitly confines managed destinations to the selected project;
603
+ regression coverage proves files and dangling symlinks cannot stand in for
604
+ context directories.
605
+ - Receipt-analytics deadline tests advance a controlled clock after entering
606
+ the phase under test, avoiding a CI scheduling race between settle and capture.
607
+
608
+ ## [1.42.0] - 2026-09-23
609
+
610
+ ### Added
611
+
612
+ - `tooling setup --target <campaign-directory> --platform claude` composes the
613
+ existing skill, project context and QA-browser installers after checking the
614
+ selected project's exact toolkit pin and installed page-kit dependency.
615
+ npm installs the dependencies first; setup runs from the project copy through
616
+ `npx --no-install campaigns-os`. It preserves campaign pages and existing
617
+ project instructions, appends the Claude context import once, and refuses
618
+ conflicting pins, edited context and symlink destinations before writes.
619
+ `--dry-run` writes nothing and downloads no browser. Browser-install failure
620
+ reports an incomplete setup that can be rerun. Setup bypasses campaign-session
621
+ recovery, gateway credential reads, lifecycle capture and telemetry.
622
+ - Bundled local-setup guide documents the initial npm install, context import,
623
+ browser step and required agent restart. Setup reports `restart_required`;
624
+ installation is not proof that an agent loaded the matching skill revision.
625
+
626
+ ### Changed
627
+
628
+ - Skills bundle revision `1.42.0+skills.1`; each bundled skill version advances
629
+ one patch so a session holding previous instructions must restart.
630
+ - Declared effects include setup and its read-only dry run. Offline effects
631
+ tests cover every campaign-session/consent condition; browser archive download
632
+ remains preflight-proved, alongside focused preservation and recovery tests.
633
+
5
634
  ## [1.41.2] - 2026-09-23
6
635
 
7
636
  ### Fixed