@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.
- package/AGENTS.md +4 -2
- package/CHANGELOG.md +629 -0
- package/README.md +8 -6
- package/agents/claude/CLAUDE.md +5 -1
- package/campaign-spec/dist/types.d.ts +2 -0
- package/contracts/agent-relevant-change-policy.v1.json +5 -0
- package/contracts/effects.v1.json +118 -25
- package/contracts/migration-sidecar-bundle.v0.json +9 -0
- package/contracts/release-ledger.json +1424 -0
- package/contracts/supported-surface.json +12 -11
- package/docs/build-packet.md +120 -8
- package/docs/campaigns-os-build-flow.md +3 -2
- package/docs/design-source-package.md +89 -15
- package/docs/effects.md +83 -2
- package/docs/local-setup.md +51 -0
- package/docs/migration-sidecar-bundle.md +6 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/progress-snapshots.md +16 -6
- package/docs/qa-and-test-orders.md +157 -17
- package/docs/release-ledger-authoring-guide.md +6 -4
- package/docs/runtime-readiness.md +1 -1
- package/docs/skills-revision.md +10 -10
- package/package.json +3 -2
- package/schemas/campaign-runtime-assembly-report.v0.schema.json +6 -1
- package/schemas/campaign-runtime-build-packet.v0.schema.json +6 -1
- package/schemas/campaign-spec.v4.schema.json +4 -0
- package/schemas/campaigns-os-progress-snapshot.v0.schema.json +1 -0
- package/schemas/campaigns-os-qa-verdict-sidecar.v0.schema.json +1 -0
- package/schemas/campaigns-os-qa-verdict.v0.schema.json +1 -0
- package/schemas/campaigns-os-run-record.v0.schema.json +1 -0
- package/skills/campaign-lifecycle-orientation/SKILL.md +13 -8
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +8 -6
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +4 -4
- package/skills/next-campaigns-os/SKILL.md +17 -4
- package/skills/next-campaigns-os/references/session-intake.md +4 -4
- package/skills/next-campaigns-os-setup/SKILL.md +3 -3
- package/skills/next-campaigns-polish/SKILL.md +3 -3
- package/skills/next-campaigns-qa/SKILL.md +10 -9
- package/skills.json +11 -11
- package/src/build-brief.mjs +6 -4
- package/src/built-script-syntax.mjs +480 -0
- package/src/campaigns-api-key.mjs +99 -0
- package/src/cli-helpers.mjs +118 -0
- package/src/cli.mjs +796 -6963
- package/src/design-source-package.mjs +1 -1
- package/src/design-source-publication.mjs +898 -0
- package/src/diagnostic.mjs +2 -1
- package/src/directory-lock.mjs +270 -0
- package/src/doctor/checks.mjs +4415 -0
- package/src/doctor/inspect.mjs +636 -0
- package/src/doctor/next-step.mjs +731 -0
- package/src/finding-cause.mjs +14 -10
- package/src/install-invocation.mjs +29 -0
- package/src/invocation.mjs +179 -0
- package/src/lifecycle.mjs +5 -4
- package/src/polish-node.mjs +5 -2
- package/src/private-template-source.mjs +1 -1
- package/src/progress-node.mjs +9 -37
- package/src/progress.mjs +5 -3
- package/src/proof-policy.mjs +1 -1
- package/src/qa-analytics-correctness.mjs +3 -0
- package/src/qa-binding-evidence.mjs +76 -11
- package/src/qa-browser.mjs +778 -77
- package/src/qa-build-scope.mjs +47 -0
- package/src/qa-node.mjs +276 -39
- package/src/qa-publish.mjs +4 -0
- package/src/qa-sidecar.mjs +2 -0
- package/src/qa-verdict-discovery.mjs +11 -0
- package/src/qa-verdict-publish.mjs +1 -0
- package/src/qa-verdict.mjs +8 -1
- package/src/readback.mjs +2 -1
- package/src/run-record-closeout.mjs +3 -4
- package/src/run-record.mjs +4 -0
- package/src/sidecar-bundle.mjs +21 -0
- package/src/source-html-intake.mjs +1 -1
- package/src/source-html-manifest.mjs +9 -2
- package/src/spec-source-identity.mjs +44 -0
- package/src/stage-ledger.mjs +32 -1
- package/src/target-lock.mjs +54 -0
- package/src/template-brand-contract.mjs +17 -1
- 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`.
|
|
121
|
-
|
|
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
|