@nextcommerce/campaigns-os 1.33.0 → 1.37.1

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 (136) hide show
  1. package/AGENTS.md +42 -13
  2. package/CHANGELOG.md +129 -0
  3. package/README.md +42 -20
  4. package/compatibility.json +1 -1
  5. package/contracts/agent-relevant-change-policy.v1.json +1 -0
  6. package/contracts/fixtures/progress/observation.v0.json +89 -0
  7. package/contracts/fixtures/runtime-recipe/accept/current.json +3 -5
  8. package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -5
  9. package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -5
  10. package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -5
  11. package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -5
  12. package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -5
  13. package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -5
  14. package/contracts/fixtures/runtime-recipe/reject/missing-required-field.json +3 -5
  15. package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -5
  16. package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -5
  17. package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -5
  18. package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +2 -4
  19. package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -5
  20. package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -5
  21. package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -5
  22. package/contracts/release-ledger.json +614 -0
  23. package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -5
  24. package/contracts/supported-surface.json +23 -6
  25. package/demo/apollo-v0/NOTICE.txt +51 -0
  26. package/demo/apollo-v0/assets/css/demo.css +2 -0
  27. package/demo/apollo-v0/assets/css/landing/tokens.css +35 -0
  28. package/demo/apollo-v0/assets/css/next-core.css +16124 -0
  29. package/demo/apollo-v0/assets/images/1x1_1.svg +19 -0
  30. package/demo/apollo-v0/assets/images/1x1_2.svg +19 -0
  31. package/demo/apollo-v0/assets/images/affirm-logo.svg +24 -0
  32. package/demo/apollo-v0/assets/images/apple-pay-logo.svg +4 -0
  33. package/demo/apollo-v0/assets/images/bancontact-logo.svg +1 -0
  34. package/demo/apollo-v0/assets/images/cc-visa.svg +28 -0
  35. package/demo/apollo-v0/assets/images/cc_amex.svg +20 -0
  36. package/demo/apollo-v0/assets/images/cc_discover.svg +21 -0
  37. package/demo/apollo-v0/assets/images/cc_master.svg +22 -0
  38. package/demo/apollo-v0/assets/images/credit-card-flags.svg +38 -0
  39. package/demo/apollo-v0/assets/images/demo-inline-40788e52a7c75b78.svg +1 -0
  40. package/demo/apollo-v0/assets/images/demo-inline-686e73c8840a0f0a.svg +1 -0
  41. package/demo/apollo-v0/assets/images/google-pay-logo.svg +7 -0
  42. package/demo/apollo-v0/assets/images/guarantee-badge.png +0 -0
  43. package/demo/apollo-v0/assets/images/icon-dollar.svg +5 -0
  44. package/demo/apollo-v0/assets/images/icon-guarantee.svg +5 -0
  45. package/demo/apollo-v0/assets/images/icon-shipping.svg +5 -0
  46. package/demo/apollo-v0/assets/images/icons8-lock-24_1icons8-lock-24.png +0 -0
  47. package/demo/apollo-v0/assets/images/ideal-logo.svg +30 -0
  48. package/demo/apollo-v0/assets/images/klarna-logo.svg +9 -0
  49. package/demo/apollo-v0/assets/images/landing/_shared/16x9.svg +19 -0
  50. package/demo/apollo-v0/assets/images/landing/_shared/1x1_1.svg +19 -0
  51. package/demo/apollo-v0/assets/images/landing/_shared/4x3.svg +19 -0
  52. package/demo/apollo-v0/assets/images/landing/_shared/arrow-right.svg +6 -0
  53. package/demo/apollo-v0/assets/images/landing/_shared/cta-guarantee-icon.png +0 -0
  54. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-1.svg +8 -0
  55. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-2.svg +10 -0
  56. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-3.svg +13 -0
  57. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-icon-4.svg +11 -0
  58. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-quote.svg +6 -0
  59. package/demo/apollo-v0/assets/images/landing/benefits-2/benefits-2-verified.svg +10 -0
  60. package/demo/apollo-v0/assets/images/landing/bottomcta-1/check-bullet.svg +5 -0
  61. package/demo/apollo-v0/assets/images/landing/faq-1/faq-chevron.svg +6 -0
  62. package/demo/apollo-v0/assets/images/landing/footer-1/footer-logo.png +0 -0
  63. package/demo/apollo-v0/assets/images/landing/guarantee-1/guarantee-1-badge.svg +8 -0
  64. package/demo/apollo-v0/assets/images/landing/hero-1/icon-check.svg +5 -0
  65. package/demo/apollo-v0/assets/images/landing/hero-1/icon-star.svg +6 -0
  66. package/demo/apollo-v0/assets/images/landing/hero-1/icon-verified.svg +6 -0
  67. package/demo/apollo-v0/assets/images/landing/icons-5/icon-batteries.svg +7 -0
  68. package/demo/apollo-v0/assets/images/landing/icons-5/icon-cuff-checking.svg +6 -0
  69. package/demo/apollo-v0/assets/images/landing/icons-5/icon-dual-user.svg +5 -0
  70. package/demo/apollo-v0/assets/images/landing/icons-5/icon-fda-cleared.svg +5 -0
  71. package/demo/apollo-v0/assets/images/landing/icons-5/icon-heartbeat.svg +17 -0
  72. package/demo/apollo-v0/assets/images/landing/icons-5/icon-lcd-display.svg +10 -0
  73. package/demo/apollo-v0/assets/images/landing/icons-5/icon-movement-error.svg +7 -0
  74. package/demo/apollo-v0/assets/images/landing/icons-5/icon-portable.png +0 -0
  75. package/demo/apollo-v0/assets/images/landing/icons-5/icon-reading-memory.svg +6 -0
  76. package/demo/apollo-v0/assets/images/landing/icons-5/icon-wrist-comfort.svg +5 -0
  77. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-1.jpg +0 -0
  78. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-2.jpg +0 -0
  79. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-3.jpg +0 -0
  80. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-card-4.jpg +0 -0
  81. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-1.png +0 -0
  82. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-2.png +0 -0
  83. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-3.png +0 -0
  84. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-4.png +0 -0
  85. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-5.png +0 -0
  86. package/demo/apollo-v0/assets/images/landing/ingredients-3/ingredients-3-promise-6.png +0 -0
  87. package/demo/apollo-v0/assets/images/landing/nav-1/flag-us.png +0 -0
  88. package/demo/apollo-v0/assets/images/landing/reviews-3/star-card.svg +3 -0
  89. package/demo/apollo-v0/assets/images/landing/reviews-3/star-lg.svg +3 -0
  90. package/demo/apollo-v0/assets/images/landing/reviews-3/star-sm.svg +3 -0
  91. package/demo/apollo-v0/assets/images/landing/reviews-3/verified.svg +10 -0
  92. package/demo/apollo-v0/assets/images/landing/testimonials-2/testimonials-2-reactions.svg +9 -0
  93. package/demo/apollo-v0/assets/images/landing/testimonials-2/testimonials-2-stars.svg +6 -0
  94. package/demo/apollo-v0/assets/images/link-logo.svg +1 -0
  95. package/demo/apollo-v0/assets/images/next-dark.svg +8 -0
  96. package/demo/apollo-v0/assets/images/paypal-logo.svg +5 -0
  97. package/demo/apollo-v0/assets/images/paypal-txt.svg +8 -0
  98. package/demo/apollo-v0/assets/images/paypal.svg +22 -0
  99. package/demo/apollo-v0/assets/images/sepa-logo.svg +275 -0
  100. package/demo/apollo-v0/assets/images/twint-logo.svg +1 -0
  101. package/demo/apollo-v0/assets/images/united-states-flag-icon.webp +0 -0
  102. package/demo/apollo-v0/assets/images/upsell-payment-logos.svg +38 -0
  103. package/demo/apollo-v0/assets/images/usps.png +0 -0
  104. package/demo/apollo-v0/checkout/index.html +1370 -0
  105. package/demo/apollo-v0/landing/index.html +1836 -0
  106. package/demo/apollo-v0/provenance.json +342 -0
  107. package/demo/apollo-v0/receipt/index.html +292 -0
  108. package/demo/apollo-v0/upsell-bundle-stepper/index.html +401 -0
  109. package/docs/activation-and-evidence.md +37 -0
  110. package/docs/demo-preview.md +63 -0
  111. package/docs/diagnostics.md +55 -0
  112. package/docs/orientation-contract-reference.md +3 -1
  113. package/docs/progress-snapshots.md +142 -0
  114. package/docs/qa-and-test-orders.md +26 -0
  115. package/docs/runtime-readiness.md +3 -3
  116. package/docs/sdk-storage-compatibility.md +19 -0
  117. package/docs/supported-surface.md +14 -1
  118. package/docs/versioning.md +1 -1
  119. package/package.json +22 -8
  120. package/schemas/campaign-runtime-build-context.v0.schema.json +42 -0
  121. package/schemas/campaigns-os-progress-snapshot.v0.schema.json +370 -0
  122. package/skills/next-campaigns-build/SKILL.md +17 -1
  123. package/skills/next-campaigns-os/SKILL.md +19 -3
  124. package/skills/next-campaigns-os-setup/SKILL.md +17 -1
  125. package/skills/next-campaigns-polish/SKILL.md +18 -2
  126. package/skills/next-campaigns-qa/SKILL.md +24 -8
  127. package/skills.json +5 -5
  128. package/src/cli.mjs +96 -6
  129. package/src/consent.mjs +2 -2
  130. package/src/demo-artifact.mjs +97 -0
  131. package/src/demo.mjs +85 -0
  132. package/src/diagnostic.mjs +101 -0
  133. package/src/install-mode.mjs +13 -1
  134. package/src/progress-node.mjs +177 -0
  135. package/src/progress.mjs +133 -0
  136. package/src/sdk-storage-compatibility.mjs +359 -0
@@ -0,0 +1,142 @@
1
+ # Minimal progress observations
2
+
3
+ Candidate release **1.36.0** adds the portable `@nextcommerce/campaigns-os/progress`
4
+ export and `schemas/campaigns-os-progress-snapshot.v0.schema.json`. The currently
5
+ published install example does not include this feature. Progress is a compact
6
+ observation of the existing lifecycle, not a second workflow or proof of readiness.
7
+
8
+ `next --packet <packet>` records the canonical picker result after the same doctor
9
+ checks that supply its continuation and gates. Agents run `next` after setup,
10
+ assembly, polish and preview deployment so those committed stage reports become
11
+ visible. The CLI `build` command prepares inputs and runs doctor; it does not build
12
+ or deploy the campaign. Preview's existing stage is `deploy`. Arbitrary edits are
13
+ not tracked. `qa run --packet <packet>` observes its successfully committed or
14
+ unchanged QA report before the existing closeout: ready QA closes its run once,
15
+ blocked QA keeps it open. A progress delivery cannot close a run.
16
+
17
+ ## What is shared
18
+
19
+ The strict v0 object carries its schema, package version, observation timestamp,
20
+ producer (`next` or `qa`), opaque progress stream and sequence, prior snapshot ID,
21
+ content digest, Map ID and separate revision/spec/build hashes. Six independent
22
+ stage records retain observed status and explicit build binding. Continuation
23
+ retains the canonical stage, blocked/divergent flags, fixed action IDs and gate
24
+ states. Preview carries only presence and a hash of the URL. An optional QA block
25
+ retains the exact verdict ID, disposition (including `ready_with_exceptions`),
26
+ binding and publication state. Publication failure does not invalidate a locally
27
+ retained verdict; recovery uses `qa publish`, without repeating an order.
28
+
29
+ No commands, prompts, free text, content, local paths, URLs, query strings,
30
+ credentials, order values or customer payloads enter the wire. Unknown vocabulary
31
+ becomes a fixed `unknown` marker and cannot imply a passing continuation. A
32
+ stage's observed `completed` status is a ledger claim, not independent verification.
33
+ Only matching fingerprints carry `matching`; absent or unverifiable binding is
34
+ `unconfirmed`. A current local output hash never proves a deployment is current.
35
+
36
+ The identity algorithms are deliberately different:
37
+
38
+ - `map-store-v1` retains the original saved Map hash. A fresh Map fetch records
39
+ that hash and the fetched local semantic baseline in Build Context intake.
40
+ Saved revision alignment is `aligned` only while the local spec still matches
41
+ that baseline and the context names this packet and Map. Existing contexts,
42
+ offline caches and local exports without that provenance remain `unconfirmed`.
43
+ The saved hash may still be retained as identity; it alone proves no alignment.
44
+ - `campaign-spec-material-v1` hashes recursively key-sorted JSON after removing
45
+ top-level `spec_identity`, `slug`, `map_id` and `saved_at`, as existing
46
+ `specMaterialHash` does. It includes lifecycle and parent Map fields that the
47
+ saved Map producer excludes. It must never be compared as a Map-store hash.
48
+ Assembly Report `identity.spec_hash` is a raw-byte hash and is not this value.
49
+ - `sha256-manifest/v1` is the existing doctor's output fingerprint: SHA-256 of
50
+ the sorted relative-path and file-SHA-256 manifest under the built route.
51
+ Reported assembly/QA binding uses the doctor's actual observed output and its
52
+ recorded-fingerprint comparison. Missing output remains nullable/unconfirmed.
53
+
54
+ Different Map revisions, local specs, builds, packet/context/report bindings and
55
+ endpoint scopes have independent streams. Completed stages cannot be combined
56
+ across them. A progress stream is independent of a run-session ID.
57
+
58
+ ## Capture and delivery
59
+
60
+ Sanitized immutable snapshots are written under the target repository's
61
+ `.campaign-runtime/progress/` before any request. Allocation uses an exclusive
62
+ local lock with a process owner. Dead owners are recovered through an exclusive
63
+ recovery claim and an atomic rename; a live process is never evicted. An ownerless
64
+ crash gap is recoverable after ten seconds. If recovery itself is interrupted,
65
+ capture fails closed: stop all Campaigns OS writers for that target, then remove
66
+ the abandoned `.allocation-lock` directory in the affected progress scope before
67
+ retrying `next`. Do not remove a lock while a writer is active.
68
+
69
+ An unchanged projection reuses its ID, timestamp and sequence. Identity
70
+ changes start a new stream. Each local scope retains at most 32 snapshots and
71
+ separate remit metadata; retention can leave an incomplete history. There is no
72
+ daemon. A later observation retries its current pending delivery; old pending
73
+ snapshots remain in the bounded local history, without background sends.
74
+
75
+ `--no-write` disables both capture and delivery. `--no-remit` keeps capture local.
76
+ `--no-run-session` does not start a session. A missing/invalid Map ID keeps the
77
+ observation local with `map_id_missing`; a missing campaign key similarly yields
78
+ `campaign_key_missing`. Capture or delivery failures never alter the lifecycle
79
+ result or exit status.
80
+ Capture may wait up to 1.5 seconds for allocation. Delivery is awaited within
81
+ its separate two-second network budget. Unchanged lifecycle results mean the
82
+ command's output and status remain unchanged; these bounded waits can add latency.
83
+
84
+ The planned ops receiver is `POST /api/progress`. Destination precedence is an
85
+ explicit `--proxy-base`, then the bound Build Context's `intake.proxy_base`, then
86
+ the canonical NEXT endpoint only when there is no source binding. An invalid or
87
+ foreign source binding fails closed, including a context without a nonempty
88
+ matching packet pointer. An explicit endpoint override remains independent of
89
+ that context, and cannot confirm its saved revision.
90
+
91
+ HTTPS and plain HTTP loopback are accepted;
92
+ userinfo, query, fragment and other protocols are refused. Redirects are refused.
93
+ The existing campaign-key resolver supplies `X-Campaign-Key`; keys never enter
94
+ snapshots or metadata.
95
+
96
+ The same telemetry on/off choice governs sharing. Canonical delivery defaults on;
97
+ explicit off, malformed environment/configuration and scope mismatch keep delivery
98
+ off. Consent off still permits the sanitized local capture and sends no request.
99
+ Noncanonical progress delivery requires an explicit matching scoped file
100
+ opt-in (`telemetry on --proxy-base <endpoint>`). Unlike existing Run Record remit,
101
+ unscoped environment ON cannot bypass scope for progress; it yields
102
+ `scoped_consent_required`. Minimal stage observations are intended to be visible
103
+ in Workspace. This producer does not implement the receiver or Workspace UI.
104
+
105
+ Delivery uses a total two-second budget, at most one initial request and one retry
106
+ for transport errors, 429 or 5xx. Both requests use identical canonical JSON bytes,
107
+ ID and timestamp. A response body is bounded to 4 KiB. A 2xx or 409 succeeds only
108
+ with `{ "ok": true, "snapshot_id": "<id>", "digest": "<same-id>" }`. Other
109
+ 400/401/403/409 answers and nonmatching acknowledgments remain failed; a conflict
110
+ never silently counts as stored. Response error text is never copied to metadata.
111
+
112
+ ## Portable consumption
113
+
114
+ ```js
115
+ import {
116
+ verifyProgressSnapshot, groupProgressHistories, progressStorageKey,
117
+ } from '@nextcommerce/campaigns-os/progress';
118
+
119
+ const checked = await verifyProgressSnapshot(snapshot);
120
+ const histories = await groupProgressHistories(snapshots);
121
+ const key = progressStorageKey(snapshot, scopeHash);
122
+ ```
123
+
124
+ The export uses standard Web Crypto and TextEncoder; it has no Node, filesystem
125
+ or network dependency. `validateProgressSnapshot` checks bounded strict shape and
126
+ binding invariants; `verifyProgressSnapshot` also verifies the content digest.
127
+ `snapshot_id` hashes recursively key-sorted JSON of every field except itself.
128
+ Canonical transport JSON includes the ID, with no whitespace or newline.
129
+ The exported schema and supported example fixture agree byte-for-byte in tests.
130
+
131
+ `groupProgressHistories` accepts at most 256 snapshots, groups whole observations
132
+ by complete identity plus stream, removes exact duplicate IDs and sorts sequences.
133
+ Groups are `conflicted`, `incomplete`, `unconfirmed` or `observed`. It neither
134
+ chooses a lifecycle stage nor merges completion claims. `observed` confers no
135
+ receiver trust or readiness. Invalid members are rejected with fixed reason codes.
136
+
137
+ The planned immutable receiver key is
138
+ `progress:v0:<scope-hex>:<map-id>:<revision-hex>:<stream>:<sequence>:<digest-hex>`.
139
+ `progressStorageKey` returns null without a valid shape, scope hash, Map or saved
140
+ revision. A key match identifies scope; it is not authentication or trust. The
141
+ receiver must verify the digest and authorized Map scope and stamp its own trust.
142
+ Unknown, incomplete or conflicted histories must never yield a ready workspace.
@@ -1689,3 +1689,29 @@ meta assertions to avoid duplicating their values into the verdict.
1689
1689
  Older verdicts lacking this assertion were not checked. Consumers must retain
1690
1690
  run/time/spec-hash context and segregate server-stamped untrusted submissions;
1691
1691
  a trusted submission attests the runner, not execution or resource identity.
1692
+
1693
+ ### Playwright updates and consumer installs
1694
+
1695
+ After installing or updating Campaigns OS, run `npx campaigns-os qa install-browser`
1696
+ from the campaign project (or `campaigns-os qa install-browser` for a global
1697
+ installation). This resolves the same Playwright package as QA and polish capture.
1698
+ A project's own `npx playwright install` can resolve a different version and install
1699
+ a different Chromium build. Campaigns OS is an optional-dependency owner, not a
1700
+ Playwright peer dependency: npm may share a compatible copy or install a nested one.
1701
+ The consumer project's lockfile determines its installed version; this repository's
1702
+ lockfile only controls checkout builds.
1703
+
1704
+ CI reports independent types, unit, contracts, and browser lanes under the existing
1705
+ required `check` status. `npm run check:browser` requires working Chromium and fails
1706
+ on launch errors. `npm run check:consumer` installs the packed package into fresh
1707
+ projects with a shared Playwright, an older conflicting version, and `latest`, then
1708
+ installs and launches Campaigns OS's Chromium. These checks use local fixture pages;
1709
+ they do not place merchant orders. `npm run check` remains the browser-free contributor
1710
+ check; run the browser commands separately after installing Chromium.
1711
+
1712
+ Dependency PRs must include any required release-ledger entries. If the set of
1713
+ install-script dependencies changes, update the runtime recipe's exact expectation,
1714
+ advance its revision and the supported-surface/package patch version, and regenerate
1715
+ the runtime-readiness guide and fixtures. The v1 recipe still uses exact agreement:
1716
+ removing a dependency does not authorize silently reinterpreting that field as an
1717
+ allowlist. Dependabot groups minor/patch updates; major API upgrades remain separate.
@@ -8,7 +8,7 @@
8
8
 
9
9
  How a checkout of this repository at one commit becomes a usable installed runtime, and how a consumer decides whether a prepared one is still trustworthy. Everything below is generated from `contracts/runtime-recipe.campaigns-os-node-v1.json`, which is the only authority for these values.
10
10
 
11
- Recipe kind `campaigns-os-node-v1`, revision `1.0.1`, validated by `schemas/campaigns-os-runtime-recipe.v1.schema.json` (`Campaigns OS Runtime Recipe v1`). Supported surface at generation time: `1.33.0`.
11
+ Recipe kind `campaigns-os-node-v1`, revision `1.0.2`, validated by `schemas/campaigns-os-runtime-recipe.v1.schema.json` (`Campaigns OS Runtime Recipe v1`). Supported surface at generation time: `1.37.1`.
12
12
 
13
13
  ## What this is
14
14
 
@@ -65,7 +65,7 @@ npm ci --ignore-scripts --no-audit --fund=false
65
65
 
66
66
  Working directory `target_root`, stdin `closed`, lifecycle scripts `disabled`, bounded by `install_seconds`.
67
67
 
68
- ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. Exactly one dependency in the resolved tree declares an install script, and it ships a prebuilt binary in its published tarball, so nothing in the tree needs its scripts to function. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime.
68
+ ci rather than install, so the lockfile is authoritative and the tree is reproducible. --ignore-scripts is the load-bearing flag: it suppresses every dependency lifecycle script and the target's own prepare. No dependency in the resolved tree declares an install script. The exact list in target_expectations remains a reviewed expectation: additions and removals require a recipe revision, so existing v1 consumers retain the same agreement semantics. --no-audit and --fund=false remove two network- and output-side effects that are not part of preparing a runtime.
69
69
 
70
70
  ### build
71
71
 
@@ -170,7 +170,7 @@ What this revision assumes about the target, stated as values a checker can comp
170
170
  | Lockfile | `package-lock.json`, version `3`, integrity pinned `true` |
171
171
  | Script `build:spec` | `tsc -p campaign-spec/tsconfig.build.json` |
172
172
  | Script `prepare` | `npm run build:spec` |
173
- | Dependencies declaring an install script | `fsevents` |
173
+ | Dependencies declaring an install script | none |
174
174
 
175
175
  ## Bounds
176
176
 
@@ -0,0 +1,19 @@
1
+ # SDK storage compatibility before a bump
2
+
3
+ Run the read-only source scanner from a campaign repository before changing its SDK pin:
4
+
5
+ ```sh
6
+ npx campaigns-os sdk storage-check --target . --target-sdk 0.4.38 --manifest /path/to/campaign-cart/docs/compatibility/storage-migrations.v1.json --scope campaigns/spring,shared --json
7
+ ```
8
+
9
+ Omit `--json` for the concise human report. Exit 0 means source-compatible; exit 2 means incompatible or unknown; invalid arguments or manifests exit 1. No merchant files or pins are rewritten. This is independent of doctor's built HTML markup check.
10
+
11
+ The manifest is generated and owned by Campaign Cart, from its storage registry. The scanner has no independent SDK key list and fetches no remote code. Supply the generated `storage-migrations.v1.json` from the SDK contract change (campaign-cart #102); until that change is published, this command does **not** imply a released SDK tag contains that file. The report records the full file SHA-256, SDK version, supported target range, registry/extractor/input digest, and Git provenance. When the supplied bytes equal their repository HEAD blob, provenance is `verified-git-blob` with commit and repository path. Proposed, modified, or copied manifests are labeled `unverified-local-file`; the label never certifies a release. Review/pin SDK provenance separately before acting on findings. Targets outside the manifest's supported SDK range report unknown.
12
+
13
+ `--target` must name the Git root. `--scope` is mandatory: comma-separated literal repository-relative directory/file paths; use `.` only when the complete repository is intended. Add shared JavaScript directories explicitly. `--exclude` uses the same syntax and records explicit exclusions. Archives receive no implicit exemption. Only Git-tracked `.html`, `.htm`, `.js`, `.mjs`, and `.cjs` files in the selected scope are scanned, using current working-tree bytes and per-file digests; untracked files and built dependencies are outside this evidence. A selected HTML page's local script outside the selected files reports unknown. Relative scripts affected by an HTML `<base href>` also report unknown; review their actual dependency paths. Remote SDK and third-party scripts are not fetched or analyzed.
14
+
15
+ Acorn parses JavaScript ASTs; parse5 identifies executable inline HTML scripts and source offsets. Findings inventory storage area, operation, key, file/line/column, reason, and SDK-owned public replacement when supplied. The scanner recognizes direct `localStorage`/`sessionStorage`, `window`/`globalThis`/`self` properties, simple constant browser-global/storage aliases and storage destructuring, literal `getItem`/`setItem`/`removeItem` calls (including bracket method notation), property access/assignment/deletion, and lexical constant string indirection. Comments, ordinary strings, JSON script blocks and public store calls do not become storage reads. A literal legacy SDK key at or after its manifest migration boundary is incompatible. Guessed prefixes cannot establish compatibility.
16
+
17
+ Dynamic storage keys, unresolved storage methods, shadowed storage names, missing migration release evidence, unsupported target versions, and JavaScript parse failures report unknown. This bounded analysis does not execute merchant code or prove computed keys correct. It does not follow arbitrary data flow, dynamic imports, event-handler attributes, generated code or runtime-loaded script graphs. Inspect unresolved findings and include all campaign sources in scope; a clean result is only static tracked source compatibility evidence. Browser behavior, order creation, tracking and analytics still require their own proof, especially where multiple campaigns share an origin. Use the SDK public store API where the manifest recommends it; do not invent a prefix-first merchant repair.
18
+
19
+ Storage `length` property reads are unaffected metadata (`storage-metadata-read`). Storage `key()` enumeration, extracted method references, and mutations of reserved members remain unknown; enumeration cannot prove an SDK key lookup safe. Git discovery failures return one bounded CLI error. Local script diagnostics retain repository-relative spellings from HTML source, including `../` paths; excluded/outside sources are not read. The Git root and operator target are compared by filesystem device/inode identity, so supported case aliases and symlinks can name the same root. Source containment uses realpaths below the Git root without case folding. Extra positional CLI arguments are rejected so an accidental scope or version value cannot silently disappear.
@@ -14,7 +14,8 @@ implementation detail, however stable it looks.
14
14
  | Surface | Contract | Change discipline |
15
15
  |---|---|---|
16
16
  | `schemas/*.schema.json` (all of them) | The portable contract catalog: CampaignSpec, Design Source Package, Build Packet, Build Context, Assembly Report, Doctor Output, sidecar-bundle conformance, Run Record, Workflow Finding, Build Brief, Source-HTML Manifest, Tooling Orientation, Release Ledger, QA Verdict, the QA Verdict sidecar projection, Runtime Recipe, and the legacy-migration inventory/plan/receipt trio. | Hashed. Any content change requires updating the recorded hash **and** bumping `surface_version` in the same PR. A shape change that alters meaning gets a new schema-version const — one version identifier must never cover two shapes (the 2026-08 assembly-report drift is the incident this rule encodes). Additions to an open `v0` schema are expected and consumers must tolerate unknown fields; the security-sensitive legacy-migration schemas are closed, so additions there require a new lineage. 1.28.0 (RL entry `surface_version: 1.28.0`, breaking) removed the two required Build Packet booleans `qa.test_orders_allowed` and `qa.sandbox_test_card_confirmed` (nothing read them; test orders run from `--test-order <mode>` alone), added `local-serve` to the `deploy.target` enum, and added the optional `remit_result` / `remit_base_kind` fields to the Run Record. 1.30.0 (additive) added the optional `data_layer` record to the QA Verdict's `test_orders[]` entries — the order's `dl_purchase` reading (#325). 1.33.0 (additive) added the optional `qa_verdict_publish` block to the Run Record — which verdict was posted to the QA portal, by `qa run` or `qa publish`, and what the portal answered, in the `remit_result` vocabulary (#328). |
17
- | CLI commands: `start`, `prepare-build`, `build`, `polish`, `checkpoint`, `page-kit`, `spec`, `doctor`, `bundle`, `next`, `theme`, `tooling`, `install-skills`, `install-agent-context`, `validate-assembly-report`, `telemetry`, `standardize`, `qa`, `findings`, `run-record`, `run` | Scriptable entry points. The founding list (1.0.0) was the argv surface Campaigns Agent's remit fixture pins; 1.25.0 adds the partner entry path the public guides instruct — `install-skills` (skill install), `tooling status` (preflight), `next --packet` (the runtime cursor) — plus `theme`, `install-agent-context`, `validate-assembly-report`, and `telemetry`, since consent is part of the partner contract. `validate-build-packet`, formerly an undocumented and unsupported alias of `doctor`, was removed in 1.25.0+agent.7 (RL-0036) and now gets the unknown-command error; use `doctor`. `standardization-report`, a supported but redundant second spelling of `standardize` — same flags, same output, same exit codes — was removed in 1.27.0 and now gets the same unknown-command error; use `standardize`. Removing a supported command is a breaking change and is why that release moved the minor. `bundle check` validates the canonical JSON readback set and makes QA required only under `--require-qa`. `polish capture` owns page-load evidence production. `checkpoint waive` currently accepts four registered gates: `page_kit.store_profile`, `page_kit.sdk_version`, `polish.hidden_eager_media`, and `built_output.upsell_selector_scope`. `page-kit sync` (added in 1.29.0) writes the CampaignSpec's Store Profile fields and SDK pin into the target's `_data/campaigns.json` entry — the repair the first two gates name — and is the only `page-kit` subcommand. `spec derive` (added in 1.31.0) is the reverse write for the repo-derived field class (#432): the target's SDK pin, page routes and analytics ids into the packet's local CampaignSpec; it is the only `spec` subcommand, and the `page_kit.sdk_version.repo_newer` advisory names it; its `--write-map` flag (1.33.0+agent.2) also records the derived pin in the saved Map's Build hints field through the proxy Worker, never moving a Map pin backwards. `qa publish` (added in 1.33.0) posts an already-stored verdict to the QA portal without a re-run or an order, refusing a stale `spec_hash` or a verdict its Run Record already records as published (#328). Within Polish, only the broader Source Freshness waiver remains on its existing report lane; theme and QA decisions also retain their existing lanes. | Any change to this list — adding, renaming, or removing a command — bumps `surface_version` in the same PR, and since 1.25.0 `check-supported-surface.mjs --base` enforces that (before, only hashed and named entries owed a bump, so `checkpoint` landed unbumped). Subcommands, registered gates, and flags may grow freely beneath a listed command. Removing a listed command from dispatch fails the gate outright. Do not infer support for an unregistered checkpoint from the top-level command. |
17
+ | CLI commands: `start`, `prepare-build`, `build`, `polish`, `checkpoint`, `page-kit`, `spec`, `doctor`, `bundle`, `next`, `theme`, `tooling`, `install-skills`, `install-agent-context`, `validate-assembly-report`, `telemetry`, `standardize`, `qa`, `findings`, `run-record`, `run`, `sdk`, `demo` | Scriptable entry points. The founding list (1.0.0) was the argv surface Campaigns Agent's remit fixture pins; 1.25.0 adds the partner entry path the public guides instruct — `install-skills` (skill install), `tooling status` (preflight), `next --packet` (the runtime cursor) — plus `theme`, `install-agent-context`, `validate-assembly-report`, and `telemetry`, since consent is part of the partner contract. `validate-build-packet`, formerly an undocumented and unsupported alias of `doctor`, was removed in 1.25.0+agent.7 (RL-0036) and now gets the unknown-command error; use `doctor`. `standardization-report`, a supported but redundant second spelling of `standardize` — same flags, same output, same exit codes — was removed in 1.27.0 and now gets the same unknown-command error; use `standardize`. Removing a supported command is a breaking change and is why that release moved the minor. `bundle check` validates the canonical JSON readback set and makes QA required only under `--require-qa`. `polish capture` owns page-load evidence production. `checkpoint waive` currently accepts four registered gates: `page_kit.store_profile`, `page_kit.sdk_version`, `polish.hidden_eager_media`, and `built_output.upsell_selector_scope`. `page-kit sync` (added in 1.29.0) writes the CampaignSpec's Store Profile fields and SDK pin into the target's `_data/campaigns.json` entry — the repair the first two gates name — and is the only `page-kit` subcommand. `spec derive` (added in 1.31.0) is the reverse write for the repo-derived field class (#432): the target's SDK pin, page routes and analytics ids into the packet's local CampaignSpec; it is the only `spec` subcommand, and the `page_kit.sdk_version.repo_newer` advisory names it; its `--write-map` flag (1.33.0+agent.2) also records the derived pin in the saved Map's Build hints field through the proxy Worker, never moving a Map pin backwards. `qa publish` (added in 1.33.0) posts an already-stored verdict to the QA portal without a re-run or an order, refusing a stale `spec_hash` or a verdict its Run Record already records as published (#328). Within Polish, only the broader Source Freshness waiver remains on its existing report lane; theme and QA decisions also retain their existing lanes. | Any change to this list — adding, renaming, or removing a command — bumps `surface_version` in the same PR, and since 1.25.0 `check-supported-surface.mjs --base` enforces that (before, only hashed and named entries owed a bump, so `checkpoint` landed unbumped). Subcommands, registered gates, and flags may grow freely beneath a listed command. Removing a listed command from dispatch fails the gate outright. Do not infer support for an unregistered checkpoint from the top-level command. |
18
+ | `sdk storage-check` and `docs/sdk-storage-compatibility.md` | Read-only AST compatibility report for explicitly scoped tracked campaign HTML/JS before an SDK bump; consumes the supplied SDK-owned manifest and records its SHA-256 and verified or unverified local Git provenance. Incompatible and unknown findings exit 2; a clean scan is static source evidence only. | Additive supported CLI and named documentation; no automatic merchant integration repair. |
18
19
  | `bin/campaigns-os.mjs` (`campaigns-os`) | The CLI entry itself. | Declared in `package.json` `bin`; the gate fails if it disappears. |
19
20
  | Package export `./campaign-spec` | The versioned campaign-spec rule registry, consumed as `@nextcommerce/campaigns-os` (pinned by consumers' lockfiles; lockstep policy — ADR-003 in the ops repo). | Behavior-guarded from the consumer side by their contract tests; the export path itself is gated here. |
20
21
  | Package exports `./commercial-journey` and `./commercial-parity` | Portable scenario planning, response normalization, contract-governed source extraction, Exact-only parity comparison, and deterministic QA assertion serialization. These modules own no network transport and do not calculate prices locally. | Consumers execute descriptors through a supported calculate transport, then pass captured envelopes into the pure normalizer. Existing export paths are gated and may not be renamed or removed without a breaking surface change. |
@@ -81,3 +82,15 @@ the package a consumer installs."
81
82
  the PR body — downstream pins (Campaigns Agent context spine, ops-repo
82
83
  `public-contracts.manifest.json`) update on their own cadence against a
83
84
  version they can see move.
85
+
86
+ Candidate 1.36.0 adds the portable `./progress` export, its strict v0 JSON schema,
87
+ [progress observation reference](progress-snapshots.md), and supported example
88
+ fixture. Observations preserve canonical continuation and separate Map/spec/build
89
+ identities; consumers must not treat history presence or scope-key matching as
90
+ readiness or trust.
91
+
92
+ Candidate 1.37.0 adds the `demo` CLI command, [offline sample reference](demo-preview.md),
93
+ a hashed `demo/apollo-v0/provenance.json` and named attribution notice. The command
94
+ exclusively creates a new target with validated inert pages. Its internal static
95
+ files are covered by the provenance output hashes; they are not independent
96
+ consumer interfaces. No campaign proof or session authority is granted.
@@ -2,7 +2,7 @@
2
2
 
3
3
  This repo uses independent compatibility versions:
4
4
 
5
- - package version: `1.33.0` — equals `surface_version` in
5
+ - package version: `1.34.0` — equals `surface_version` in
6
6
  `contracts/supported-surface.json` (`check:supported-surface` enforces it)
7
7
  and is the version published to the npm registry; `+agent.N` changelog
8
8
  sections are same-surface changes and are not published on their own
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextcommerce/campaigns-os",
3
- "version": "1.33.0",
3
+ "version": "1.37.1",
4
4
  "description": "Toolkit for agent-assisted NEXT campaign builds.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -47,7 +47,12 @@
47
47
  "./schemas/campaigns-os-legacy-migration-inventory.v0.schema.json": "./schemas/campaigns-os-legacy-migration-inventory.v0.schema.json",
48
48
  "./schemas/campaigns-os-legacy-provisioning-plan.v0.schema.json": "./schemas/campaigns-os-legacy-provisioning-plan.v0.schema.json",
49
49
  "./schemas/campaigns-os-legacy-provisioning-receipt.v0.schema.json": "./schemas/campaigns-os-legacy-provisioning-receipt.v0.schema.json",
50
- "./package.json": "./package.json"
50
+ "./package.json": "./package.json",
51
+ "./progress": {
52
+ "import": "./src/progress.mjs",
53
+ "default": "./src/progress.mjs"
54
+ },
55
+ "./schemas/campaigns-os-progress-snapshot.v0.schema.json": "./schemas/campaigns-os-progress-snapshot.v0.schema.json"
51
56
  },
52
57
  "scripts": {
53
58
  "campaigns-os": "node ./bin/campaigns-os.mjs",
@@ -60,7 +65,7 @@
60
65
  "prepare": "npm run build:spec",
61
66
  "check:spec": "node --test \"campaign-spec/test/**/*.test.ts\"",
62
67
  "check": "npm run check:provenance && npm run check:workflows && npm run check:changelog-structure && npm run build:spec && npm run check:tests && npm run check:spec && npm run check:fixtures && npm run check:legacy-migration && npm run check:spec-conformance && npm run check:private-strings && npm run check:template-doctrine && npm run check:slot-manifest && npm run check:skill-versions && npm run check:cart-readiness && npm run check:sidecar-bundle && npm run check:supported-surface && npm run check:release-ledger && npm run check:runtime-recipe && npm run check:orientation-docs && npm run check:runtime-docs && npm run check:pack -- --skip-prepare",
63
- "check:tests": "node --test ./src/*.test.mjs ./scripts/refresh-starter-template-catalog.test.mjs ./scripts/check-catalog-provenance.test.mjs ./scripts/check-workflow-contracts.test.mjs ./scripts/check-changelog-structure.test.mjs ./scripts/check-slot-manifest.test.mjs ./scripts/check-skill-versions.test.mjs ./scripts/check-supported-surface.test.mjs ./scripts/check-campaign-spec-conformance.test.mjs ./scripts/check-release-ledger.test.mjs ./scripts/generate-orientation-reference.test.mjs ./scripts/check-runtime-recipe.test.mjs ./scripts/check-fixtures.test.mjs ./scripts/starter-templates-path.test.mjs ./scripts/check-template-doctrine.test.mjs",
68
+ "check:tests": "node ./scripts/check-tests.mjs",
64
69
  "check:legacy-migration": "node ./scripts/check-legacy-migration.mjs",
65
70
  "check:fixtures": "node ./scripts/check-fixtures.mjs",
66
71
  "check:spec-conformance": "node ./scripts/check-campaign-spec-conformance.mjs",
@@ -80,7 +85,10 @@
80
85
  "check:runtime-recipe": "node ./scripts/check-runtime-recipe.mjs",
81
86
  "check:runtime-docs": "node ./scripts/generate-runtime-readiness.mjs --check",
82
87
  "generate:runtime-docs": "node ./scripts/generate-runtime-readiness.mjs --write",
83
- "check:sidecar-bundle": "node ./bin/campaigns-os.mjs bundle check --packet contracts/fixtures/sidecar-bundle/production-shaped/campaign-runtime.build.json --require-qa --json"
88
+ "check:sidecar-bundle": "node ./bin/campaigns-os.mjs bundle check --packet contracts/fixtures/sidecar-bundle/production-shaped/campaign-runtime.build.json --require-qa --json",
89
+ "check:browser": "node ./scripts/check-tests.mjs --browser",
90
+ "check:consumer": "node ./scripts/check-playwright-consumer.mjs",
91
+ "check:contracts": "npm run check:provenance && npm run check:workflows && npm run check:changelog-structure && npm run check:fixtures && npm run check:legacy-migration && npm run check:spec-conformance && npm run check:private-strings && npm run check:template-doctrine && npm run check:slot-manifest && npm run check:skill-versions && npm run check:cart-readiness && npm run check:sidecar-bundle && npm run check:supported-surface && npm run check:release-ledger && npm run check:runtime-recipe && npm run check:orientation-docs && npm run check:runtime-docs"
84
92
  },
85
93
  "engines": {
86
94
  "node": ">=20.19.0"
@@ -88,11 +96,11 @@
88
96
  "dependencies": {
89
97
  "acorn": "^8.18.0",
90
98
  "ajv": "^8.20.0",
91
- "parse5": "^7.3.0",
92
- "yaml": "^2.9.0"
99
+ "parse5": "^8.0.1",
100
+ "yaml": "^2.9.1"
93
101
  },
94
102
  "optionalDependencies": {
95
- "playwright": "^1.62.1"
103
+ "playwright": "^1.63.0"
96
104
  },
97
105
  "devDependencies": {
98
106
  "typescript": "^5.9.3"
@@ -130,6 +138,12 @@
130
138
  "CONTEXT.md",
131
139
  "compatibility.json",
132
140
  "AGENTS.md",
133
- "CHANGELOG.md"
141
+ "CHANGELOG.md",
142
+ "docs/sdk-storage-compatibility.md",
143
+ "docs/activation-and-evidence.md",
144
+ "docs/diagnostics.md",
145
+ "docs/progress-snapshots.md",
146
+ "demo",
147
+ "docs/demo-preview.md"
134
148
  ]
135
149
  }
@@ -24,6 +24,48 @@
24
24
  },
25
25
  "description": "Context-relative reference to the normalized Design Source Package. sha256 hashes the exact artifact bytes; material_fingerprint drives freshness gates."
26
26
  },
27
+ "intake": {
28
+ "type": "object",
29
+ "additionalProperties": true,
30
+ "properties": {
31
+ "saved_map_revision": {
32
+ "anyOf": [
33
+ {
34
+ "type": "null"
35
+ },
36
+ {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "required": [
40
+ "map_id",
41
+ "hash",
42
+ "algorithm",
43
+ "local_spec_material_hash"
44
+ ],
45
+ "properties": {
46
+ "map_id": {
47
+ "type": "string",
48
+ "minLength": 1
49
+ },
50
+ "hash": {
51
+ "type": [
52
+ "string",
53
+ "null"
54
+ ]
55
+ },
56
+ "algorithm": {
57
+ "const": "map-store-v1"
58
+ },
59
+ "local_spec_material_hash": {
60
+ "type": "string",
61
+ "pattern": "^sha256:[0-9a-f]{64}$"
62
+ }
63
+ }
64
+ }
65
+ ]
66
+ }
67
+ }
68
+ },
27
69
  "spec": {
28
70
  "type": "object",
29
71
  "required": ["path", "hash", "active_pages"],