@nextcommerce/campaigns-os 1.60.0 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +244 -0
- package/README.md +86 -438
- package/agents/claude/CLAUDE.md +20 -0
- package/agents/codex/AGENTS.md +19 -0
- package/agents/copilot/copilot-instructions.md +19 -0
- package/agents/cursor/campaigns-os.mdc +21 -0
- package/campaign-spec/README.md +7 -0
- package/campaign-spec/dist/analytics-vendors.d.ts +40 -0
- package/campaign-spec/dist/analytics-vendors.js +44 -0
- package/campaign-spec/dist/checkout-flow.d.ts +18 -0
- package/campaign-spec/dist/checkout-flow.js +28 -0
- package/campaign-spec/dist/index.d.ts +4 -2
- package/campaign-spec/dist/index.js +5 -1
- package/campaign-spec/dist/rules/analytics-contract-shape.d.ts +8 -0
- package/campaign-spec/dist/rules/analytics-contract-shape.js +39 -0
- package/campaign-spec/dist/rules/campaign-currencies.d.ts +29 -0
- package/campaign-spec/dist/rules/campaign-currencies.js +130 -0
- package/campaign-spec/dist/rules/checkout-path-has-packages.d.ts +31 -0
- package/campaign-spec/dist/rules/checkout-path-has-packages.js +79 -0
- package/campaign-spec/dist/rules/index.d.ts +2 -0
- package/campaign-spec/dist/rules/index.js +6 -0
- package/campaign-spec/dist/types.d.ts +43 -9
- package/compatibility.json +1 -1
- package/contracts/brand-theme-target-tokens.next-core.v0.json +95 -25
- package/contracts/campaign-cart-sdk-support-policy.v0.json +2 -2
- package/contracts/commerce-surface-catalog.json +68 -61
- package/contracts/effects.v1.json +549 -165
- package/contracts/fixtures/runtime-recipe/accept/current.json +3 -0
- package/contracts/fixtures/runtime-recipe/accept/minimal.json +3 -0
- package/contracts/fixtures/runtime-recipe/dist-states.json +1 -1
- package/contracts/fixtures/runtime-recipe/reject/advisory-enforcement.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/allowlist-without-hosts.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/committed-output-claim.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/engines-disagreement-warns.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/lifecycle-scripts-enabled.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-kind.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-network-policy.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-output-check.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-revision.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unknown-step-id.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unperformable-check-skipped.json +3 -0
- package/contracts/fixtures/runtime-recipe/reject/unpinned-lockfile.json +3 -0
- package/contracts/release-ledger.json +1767 -0
- package/contracts/runtime-recipe.campaigns-os-node-v1.json +3 -0
- package/contracts/supported-surface.json +10 -10
- package/contracts/template-brand-contract.shared-commerce.v0.json +23 -1
- package/docs/access-model.md +20 -0
- package/docs/brand-theme-bridge.md +62 -3
- package/docs/build-packet.md +456 -36
- package/docs/campaign-build-brief.md +16 -0
- package/docs/campaign-standardization-report.md +4 -4
- package/docs/campaigns-os-build-flow.md +112 -2
- package/docs/campaignspec-authoring-examples.md +141 -0
- package/docs/design-source-package.md +64 -8
- package/docs/effects.md +17 -9
- package/docs/entry-points.md +188 -0
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +42 -2
- package/docs/progress-snapshots.md +7 -4
- package/docs/qa-and-test-orders.md +197 -3
- package/docs/quickstart.md +438 -0
- package/docs/readback.md +154 -6
- package/docs/runtime-readiness.md +6 -3
- package/docs/sdk-storage-compatibility.md +4 -2
- package/docs/skills-revision.md +10 -10
- package/docs/source-adapters.md +213 -0
- package/package.json +10 -3
- package/schemas/campaign-design-source-package.v0.schema.json +8 -0
- package/schemas/campaign-runtime-build-context.v0.schema.json +9 -0
- package/schemas/campaign-runtime-build-packet.v0.schema.json +9 -0
- package/schemas/campaign-spec.v4.schema.json +19 -3
- package/schemas/campaign-spec.v5.schema.json +19 -3
- package/schemas/campaigns-os-readback.v2.schema.json +238 -1
- package/schemas/source-html-manifest.v0.schema.json +3 -0
- package/skills/campaign-lifecycle-orientation/SKILL.md +3 -3
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +3 -3
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +5 -4
- package/skills/next-campaigns-os/SKILL.md +7 -4
- package/skills/next-campaigns-os-setup/SKILL.md +5 -3
- package/skills/next-campaigns-polish/SKILL.md +8 -10
- package/skills/next-campaigns-qa/SKILL.md +7 -4
- package/skills/next-campaigns-sdk-bump/SKILL.md +151 -25
- package/skills.json +11 -11
- package/src/brand-theme.mjs +415 -9
- package/src/brief-summary.mjs +6 -2
- package/src/browser-launch.mjs +2 -1
- package/src/build-brief.mjs +13 -3
- package/src/built-site-scope.mjs +2 -2
- package/src/campaign-workspace.mjs +288 -15
- package/src/change-scope.mjs +284 -0
- package/src/cli.mjs +358 -97
- package/src/commercial-journey.mjs +16 -3
- package/src/commercial-parity.mjs +15 -7
- package/src/content-residue.mjs +4 -2
- package/src/design-file-reference.mjs +93 -0
- package/src/design-source-package.mjs +91 -1
- package/src/design-source-publication.mjs +9 -6
- package/src/directory-lock.mjs +73 -19
- package/src/doctor/checks.mjs +87 -81
- package/src/doctor/ci.mjs +177 -0
- package/src/doctor/inspect.mjs +41 -6
- package/src/doctor/next-step.mjs +7 -0
- package/src/doctor/source-provenance.mjs +74 -0
- package/src/doctor-sidecar.mjs +3 -2
- package/src/evidence-debt.mjs +159 -0
- package/src/finding-cause.mjs +12 -11
- package/src/input-refresh.mjs +339 -32
- package/src/invocation.mjs +7 -1
- package/src/live-campaign-refs.mjs +7 -2
- package/src/local-preview-policy.mjs +35 -2
- package/src/page-kit-analytics-vendors.mjs +132 -0
- package/src/parity/compare.mjs +316 -0
- package/src/parity/design-access.mjs +54 -0
- package/src/parity/element-parity-record.mjs +569 -0
- package/src/parity/probe.mjs +205 -0
- package/src/parity/snapshot.mjs +110 -0
- package/src/png-header.mjs +87 -0
- package/src/polish-browser.mjs +189 -10
- package/src/polish-captures-record.mjs +52 -0
- package/src/polish-deadline.mjs +14 -0
- package/src/polish-gate.mjs +25 -6
- package/src/polish-node.mjs +81 -7
- package/src/polish-readability.mjs +221 -9
- package/src/polish-visual-fixtures.mjs +74 -0
- package/src/polish-visual.mjs +613 -0
- package/src/progress-node.mjs +3 -2
- package/src/qa-analytics-correctness.mjs +14 -2
- package/src/qa-analytics-parity.mjs +111 -6
- package/src/qa-browser.mjs +40 -4
- package/src/qa-commercial-parity.mjs +50 -3
- package/src/qa-node.mjs +235 -22
- package/src/qa-publish.mjs +9 -8
- package/src/qa-sidecar.mjs +16 -4
- package/src/qa-vendor-beacons.mjs +232 -0
- package/src/qa-vendor-endpoints.mjs +306 -0
- package/src/qc-accept.mjs +176 -6
- package/src/qc-check-registry.mjs +42 -2
- package/src/qc-results.mjs +477 -42
- package/src/readback.mjs +113 -21
- package/src/route-identity.mjs +10 -0
- package/src/run-record.mjs +18 -10
- package/src/runtime-state-ignore.mjs +6 -2
- package/src/sdk-attribute-index.mjs +11 -11
- package/src/sdk-markup.mjs +77 -2
- package/src/sdk-storage-compatibility.mjs +115 -6
- package/src/source-html-intake.mjs +15 -1
- package/src/source-html-manifest.mjs +7 -0
- package/src/source-html-server.mjs +129 -0
- package/src/spec-derive-campaign.mjs +216 -0
- package/src/spec-derive.mjs +473 -53
- package/src/spec-identity.mjs +14 -0
- package/src/stage-ledger.mjs +40 -1
- package/src/stage-record.mjs +100 -17
- package/src/target-lock.mjs +11 -1
- package/src/theme-gate.mjs +2 -2
- package/src/visual-diff.mjs +296 -0
- package/src/visual-reference.mjs +126 -0
|
@@ -77,6 +77,11 @@
|
|
|
77
77
|
"pattern": "^sha256:[0-9a-f]{64}$",
|
|
78
78
|
"description": "Canonical semantic identity used to correlate QA with the authored spec. hash remains exact raw-byte integrity."
|
|
79
79
|
},
|
|
80
|
+
"route_masked_material_hash": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"pattern": "^sha256:[0-9a-f]{64}$",
|
|
83
|
+
"description": "The spec material with every page's page_url left out. record spec compares it to tell a change of routes alone from one that also changed anything else the build reads (#531)."
|
|
84
|
+
},
|
|
80
85
|
"active_pages": {
|
|
81
86
|
"type": "array",
|
|
82
87
|
"items": {
|
|
@@ -164,6 +169,10 @@
|
|
|
164
169
|
"type": ["string", "null"],
|
|
165
170
|
"description": "Page Kit target file path relative to the target repo. This mirrors page_kit.output_path; source_path remains producer provenance."
|
|
166
171
|
},
|
|
172
|
+
"origin": {
|
|
173
|
+
"enum": ["repo"],
|
|
174
|
+
"description": "Set on a page added from the repo's page tree after handoff (#721): its source is the target page file (page_kit.output_path), not a design source file, so source_path and skip_reason are null."
|
|
175
|
+
},
|
|
167
176
|
"page_kit": {
|
|
168
177
|
"type": ["object", "null"],
|
|
169
178
|
"properties": {
|
|
@@ -149,6 +149,10 @@
|
|
|
149
149
|
"pattern": "^[0-9a-f]{64}$",
|
|
150
150
|
"description": "Optional sha256 of the source HTML file at the time the manifest was written. Doctor compares this to the on-disk file's actual hash and warns on mismatch (Slice 6 drift detection)."
|
|
151
151
|
},
|
|
152
|
+
"origin": {
|
|
153
|
+
"enum": ["repo"],
|
|
154
|
+
"description": "Set by record spec on a page added from the repo's page tree after handoff (#721): the page's source is its target page file (page_kit.output_path) in the target repo, not a file under source_html.root, so it carries no path. Doctor counts it as mapped, and as built once that file exists."
|
|
155
|
+
},
|
|
152
156
|
"page_kit": {
|
|
153
157
|
"type": "object",
|
|
154
158
|
"additionalProperties": false,
|
|
@@ -332,6 +336,11 @@
|
|
|
332
336
|
"type": "string",
|
|
333
337
|
"minLength": 1
|
|
334
338
|
},
|
|
339
|
+
"runtime_dir": {
|
|
340
|
+
"type": "string",
|
|
341
|
+
"pattern": "^\\.campaign-runtime(?:/funnels/[A-Za-z0-9_-][A-Za-z0-9._-]*)?$",
|
|
342
|
+
"description": "Where this funnel's records live, relative to target_repo (and, for the QA verdict sidecar and Run Records, to this packet's directory). prepare-build writes \".campaign-runtime/funnels/<public_route_slug>\" when the project already holds another funnel's records, so one Page Kit project can hold several funnels without one overwriting another's Build Context, Assembly Report, doctor output, theme output, inputs, QA verdict sidecar or Run Records. Absent (every packet before per-funnel records, and a project's first funnel) means the project-level \".campaign-runtime\". Any value other than those two for this packet's public_route_slug is refused."
|
|
343
|
+
},
|
|
335
344
|
"output_dir": {
|
|
336
345
|
"type": "string",
|
|
337
346
|
"minLength": 1
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"id": { "type": "string", "description": "Campaign slug-style identifier (28/33 real specs)." },
|
|
74
74
|
"name": { "type": "string" },
|
|
75
75
|
"slug": { "type": "string" },
|
|
76
|
-
"currency": { "type": "string" },
|
|
76
|
+
"currency": { "type": "string", "description": "The campaign's default currency: a three-letter upper-case ISO 4217 code such as \"USD\". The CampaignCurrencies rule reports any other value as an error; a lower-case code can make Campaign Cart fall back to a cached USD campaign." },
|
|
77
77
|
"language": { "type": "string" },
|
|
78
78
|
"payment_env_key": { "type": "string" },
|
|
79
79
|
"campaigns_api_key": { "type": ["string", "null"], "description": "Public-by-design, domain-allowlisted Campaigns API key (32/33 real specs)." },
|
|
80
80
|
"available_payment_methods": { "type": "array" },
|
|
81
81
|
"available_express_payment_methods": { "type": "array" },
|
|
82
|
-
"available_currencies": { "type": "array", "items": { "type": "string" } },
|
|
82
|
+
"available_currencies": { "type": "array", "items": { "type": "string" }, "description": "Every currency the campaign sells in, the default currency included, as three-letter upper-case ISO 4217 code strings. The Campaigns API returns { code, label } objects here; write the code strings. This is the CampaignSpec field: the Campaigns App API's additional_currencies is the same list without the default and is not part of the spec. The CampaignCurrencies rule reports a malformed entry as an error, and a default currency missing from a non-empty list as a warning." },
|
|
83
83
|
"available_shipping_countries": {
|
|
84
84
|
"description": "Arrives in THREE incompatible shapes in real exports: bare string \"all\" (5 specs), an array of country-code strings incl. [] (22+), and an array of { code, label } objects (5). All three are accepted here; normalization to one canonical shape is deliberately deferred to a later change.",
|
|
85
85
|
"anyOf": [
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
"product_purchase_availability": { "type": ["string", "null"] },
|
|
261
261
|
"product_inventory_availability": { "type": ["string", "null"] },
|
|
262
262
|
"image": { "type": ["string", "null"] },
|
|
263
|
-
"is_upsell": { "type": "boolean", "description": "Boolean role flag. There is no 'role' field in real exports — role is expressed by the is_upsell/is_order_bump/default_selected boolean trio." },
|
|
263
|
+
"is_upsell": { "type": "boolean", "description": "Boolean role flag. There is no 'role' field in real exports — role is expressed by the is_upsell/is_order_bump/default_selected boolean trio. What the flag means depends on the page type. On an upsell or downsell page every package row is that page's post-purchase offer and never an order bump, whatever is_upsell says, so a plain { ref_id, qty } row and one with is_upsell: true are both the page's offer. On any other page (checkout or select), is_upsell: true or is_order_bump: true marks the row as an add-on (an order bump) offered beside the main package; a row with neither flag is a main package." },
|
|
264
264
|
"is_order_bump": { "type": "boolean" },
|
|
265
265
|
"default_selected": { "type": "boolean" },
|
|
266
266
|
"configurable": { "type": "boolean", "description": "Fixture/authoring extension marking quantity-configurable package rows." },
|
|
@@ -426,6 +426,22 @@
|
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
|
+
"vendors": {
|
|
430
|
+
"type": "object",
|
|
431
|
+
"description": "Starter-template vendor adapters, keyed by vendor key (ga4, axon, taboola, triplewhale, tiktok, northbeam, snap, pinterest), as the Map Builder emits them. Each is switched on by a flat key in the campaign's _data/campaigns.json entry; see AnalyticsVendor in campaign-spec/types.ts.",
|
|
432
|
+
"additionalProperties": {
|
|
433
|
+
"type": "object",
|
|
434
|
+
"additionalProperties": true,
|
|
435
|
+
"properties": {
|
|
436
|
+
"enabled": { "type": "boolean" },
|
|
437
|
+
"id": { "type": "string" },
|
|
438
|
+
"platform": { "type": "string" },
|
|
439
|
+
"identityEnabled": { "type": "boolean" },
|
|
440
|
+
"allowedEvents": { "type": "array", "items": { "type": "string" } },
|
|
441
|
+
"blockedEvents": { "type": "array", "items": { "type": "string" } }
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
429
445
|
"out_of_band_pixels": {
|
|
430
446
|
"type": "array",
|
|
431
447
|
"items": {
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"id": { "type": "string", "description": "Campaign slug-style identifier (28/33 real specs)." },
|
|
74
74
|
"name": { "type": "string" },
|
|
75
75
|
"slug": { "type": "string" },
|
|
76
|
-
"currency": { "type": "string" },
|
|
76
|
+
"currency": { "type": "string", "description": "The campaign's default currency: a three-letter upper-case ISO 4217 code such as \"USD\". The CampaignCurrencies rule reports any other value as an error; a lower-case code can make Campaign Cart fall back to a cached USD campaign." },
|
|
77
77
|
"language": { "type": "string" },
|
|
78
78
|
"payment_env_key": { "type": "string" },
|
|
79
79
|
"campaigns_api_key": { "type": ["string", "null"], "description": "Public-by-design, domain-allowlisted Campaigns API key (32/33 real specs)." },
|
|
80
80
|
"available_payment_methods": { "type": "array" },
|
|
81
81
|
"available_express_payment_methods": { "type": "array" },
|
|
82
|
-
"available_currencies": { "type": "array", "items": { "type": "string" } },
|
|
82
|
+
"available_currencies": { "type": "array", "items": { "type": "string" }, "description": "Every currency the campaign sells in, the default currency included, as three-letter upper-case ISO 4217 code strings. The Campaigns API returns { code, label } objects here; write the code strings. This is the CampaignSpec field: the Campaigns App API's additional_currencies is the same list without the default and is not part of the spec. The CampaignCurrencies rule reports a malformed entry as an error, and a default currency missing from a non-empty list as a warning." },
|
|
83
83
|
"available_shipping_countries": {
|
|
84
84
|
"description": "Arrives in THREE incompatible shapes in real exports: bare string \"all\" (5 specs), an array of country-code strings incl. [] (22+), and an array of { code, label } objects (5). All three are accepted here; normalization to one canonical shape is deliberately deferred to a later change.",
|
|
85
85
|
"anyOf": [
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
"product_purchase_availability": { "type": ["string", "null"] },
|
|
261
261
|
"product_inventory_availability": { "type": ["string", "null"] },
|
|
262
262
|
"image": { "type": ["string", "null"] },
|
|
263
|
-
"is_upsell": { "type": "boolean", "description": "Boolean role flag. There is no 'role' field in real exports — role is expressed by the is_upsell/is_order_bump/default_selected boolean trio." },
|
|
263
|
+
"is_upsell": { "type": "boolean", "description": "Boolean role flag. There is no 'role' field in real exports — role is expressed by the is_upsell/is_order_bump/default_selected boolean trio. What the flag means depends on the page type. On an upsell or downsell page every package row is that page's post-purchase offer and never an order bump, whatever is_upsell says, so a plain { ref_id, qty } row and one with is_upsell: true are both the page's offer. On any other page (checkout, checkout_step, select), is_upsell: true or is_order_bump: true marks the row as an add-on (an order bump) offered beside the main package; a row with neither flag is a main package." },
|
|
264
264
|
"is_order_bump": { "type": "boolean" },
|
|
265
265
|
"default_selected": { "type": "boolean" },
|
|
266
266
|
"configurable": { "type": "boolean", "description": "Fixture/authoring extension marking quantity-configurable package rows." },
|
|
@@ -426,6 +426,22 @@
|
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
|
+
"vendors": {
|
|
430
|
+
"type": "object",
|
|
431
|
+
"description": "Starter-template vendor adapters, keyed by vendor key (ga4, axon, taboola, triplewhale, tiktok, northbeam, snap, pinterest), as the Map Builder emits them. Each is switched on by a flat key in the campaign's _data/campaigns.json entry; see AnalyticsVendor in campaign-spec/types.ts.",
|
|
432
|
+
"additionalProperties": {
|
|
433
|
+
"type": "object",
|
|
434
|
+
"additionalProperties": true,
|
|
435
|
+
"properties": {
|
|
436
|
+
"enabled": { "type": "boolean" },
|
|
437
|
+
"id": { "type": "string" },
|
|
438
|
+
"platform": { "type": "string" },
|
|
439
|
+
"identityEnabled": { "type": "boolean" },
|
|
440
|
+
"allowedEvents": { "type": "array", "items": { "type": "string" } },
|
|
441
|
+
"blockedEvents": { "type": "array", "items": { "type": "string" } }
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
429
445
|
"out_of_band_pixels": {
|
|
430
446
|
"type": "array",
|
|
431
447
|
"items": {
|
|
@@ -44,12 +44,249 @@
|
|
|
44
44
|
"description": "Where two artifacts record different states for one stage: the assembly report calls a stage completed while the QA verdict fails an assertion whose id is namespaced to that stage. One record per stage, in the order the failures were seen. The readback reports the disagreement and does not adjudicate it. This too is the readback's own layer.",
|
|
45
45
|
"items": { "$ref": "#/$defs/divergence" }
|
|
46
46
|
},
|
|
47
|
+
"evidence_debt": {
|
|
48
|
+
"description": "Optional additive build-binding assessment emitted by current readback in JSON and text. Reads built bytes without timestamps, processes, writes or network. It does not rerun stages or reinterpret verdicts; unknown never establishes no debt.",
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": true,
|
|
51
|
+
"required": [
|
|
52
|
+
"polish",
|
|
53
|
+
"qa",
|
|
54
|
+
"changes"
|
|
55
|
+
],
|
|
56
|
+
"properties": {
|
|
57
|
+
"polish": {
|
|
58
|
+
"$ref": "#/$defs/evidence_debt_stage"
|
|
59
|
+
},
|
|
60
|
+
"qa": {
|
|
61
|
+
"$ref": "#/$defs/evidence_debt_stage"
|
|
62
|
+
},
|
|
63
|
+
"changes": {
|
|
64
|
+
"$ref": "#/$defs/evidence_debt_changes"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
47
68
|
"clean": {
|
|
48
69
|
"type": "boolean",
|
|
49
|
-
"description": "True only when every artifact the readback found is loaded or absent (never unreadable or unrecognized), staleness is computable and NO loaded artifact is stale, staleness.unparseable_keys is empty (no loaded artifact recorded an age the readback could not read), divergences is empty,
|
|
70
|
+
"description": "True only when every artifact the readback found is loaded or absent (never unreadable or unrecognized), staleness is computable and NO loaded artifact is stale, staleness.unparseable_keys is empty (no loaded artifact recorded an age the readback could not read), divergences is empty, doctor.error_count is zero, and neither evidence_debt stage is owed (any owed Polish or QA stage makes clean false, except Polish marked advisory for a page-only change). Unknown debt alone does not make clean false; consumers must inspect evidence_debt even when clean is true. A readback-integrity flag, not a verdict: a blocked QA verdict whose artifacts all read cleanly is still clean, because the readback saw exactly what Campaigns OS recorded. docs/readback.md states the rule and its limits."
|
|
50
71
|
}
|
|
51
72
|
},
|
|
52
73
|
"$defs": {
|
|
74
|
+
"build_fingerprint": {
|
|
75
|
+
"type": [
|
|
76
|
+
"string",
|
|
77
|
+
"null"
|
|
78
|
+
],
|
|
79
|
+
"minLength": 1
|
|
80
|
+
},
|
|
81
|
+
"evidence_debt_stage": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"additionalProperties": true,
|
|
84
|
+
"required": [
|
|
85
|
+
"status",
|
|
86
|
+
"matches_current_build",
|
|
87
|
+
"recorded_build_fingerprint",
|
|
88
|
+
"current_build_fingerprint",
|
|
89
|
+
"reason"
|
|
90
|
+
],
|
|
91
|
+
"properties": {
|
|
92
|
+
"status": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"enum": [
|
|
95
|
+
"current",
|
|
96
|
+
"owed",
|
|
97
|
+
"unknown"
|
|
98
|
+
],
|
|
99
|
+
"description": "current: the stage binding matches current built bytes, the assembly fingerprint is available, and the stage is not required. owed: the binding differs or the lifecycle requires the stage again. unknown: the packet, the built output or the assembly fingerprint is unavailable, which takes precedence over owed even for a required stage, or the stage fingerprint is missing on a stage that is not required; unknown never means no debt."
|
|
100
|
+
},
|
|
101
|
+
"matches_current_build": {
|
|
102
|
+
"type": [
|
|
103
|
+
"boolean",
|
|
104
|
+
"null"
|
|
105
|
+
],
|
|
106
|
+
"description": "Fingerprint equality, or null when either fingerprint is absent. A true value does not cancel lifecycle debt."
|
|
107
|
+
},
|
|
108
|
+
"recorded_build_fingerprint": {
|
|
109
|
+
"$ref": "#/$defs/build_fingerprint",
|
|
110
|
+
"description": "The stage binding: Polish source_build_fingerprint (top-level before evidence); QA evidence.qc_build_fingerprint before source_build_fingerprint."
|
|
111
|
+
},
|
|
112
|
+
"current_build_fingerprint": {
|
|
113
|
+
"$ref": "#/$defs/build_fingerprint"
|
|
114
|
+
},
|
|
115
|
+
"reason": {
|
|
116
|
+
"enum": [
|
|
117
|
+
null,
|
|
118
|
+
"build_fingerprint_changed",
|
|
119
|
+
"stage_required_by_build",
|
|
120
|
+
"stage_required_by_brief",
|
|
121
|
+
"stage_required_by_spec",
|
|
122
|
+
"stage_required",
|
|
123
|
+
"packet_unavailable",
|
|
124
|
+
"build_output_location_unknown",
|
|
125
|
+
"build_output_missing",
|
|
126
|
+
"build_output_unreadable",
|
|
127
|
+
"assembly_build_fingerprint_missing",
|
|
128
|
+
"stage_build_fingerprint_missing"
|
|
129
|
+
],
|
|
130
|
+
"description": "Null for current. Owed names a changed binding or the recorded required_by cause (build, brief, spec, or unspecified). Unknown names the unavailable input or fingerprint."
|
|
131
|
+
},
|
|
132
|
+
"change": {
|
|
133
|
+
"description": "On an owed stage, what changed since the build that stage reviewed: the rebuilds `record build` kept in stages.assembly.build_changes plus the drift on disk. Null when the stage is not owed.",
|
|
134
|
+
"oneOf": [{ "$ref": "#/$defs/evidence_debt_change" }, { "type": "null" }]
|
|
135
|
+
},
|
|
136
|
+
"advisory": {
|
|
137
|
+
"type": "boolean",
|
|
138
|
+
"description": "Polish only. True when Polish is owed but the change since it last reviewed the campaign is page-only and no brief or spec change requires it: Polish is reported and not required by next, doctor --ci or the QA gate."
|
|
139
|
+
},
|
|
140
|
+
"scope": {
|
|
141
|
+
"enum": [null, "pages", "full"],
|
|
142
|
+
"description": "QA only. pages: the change since the build QA reviewed is page-only, so QA is owed on owed_pages and qa run --page pays it. full: the change touches commerce, cannot be classified, or an input change requires QA. Null when QA is not owed."
|
|
143
|
+
},
|
|
144
|
+
"owed_pages": {
|
|
145
|
+
"type": "array",
|
|
146
|
+
"description": "QA only. The changed pages a page-scoped run must cover when scope is pages; empty otherwise.",
|
|
147
|
+
"items": { "$ref": "#/$defs/evidence_debt_page" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"evidence_debt_page": {
|
|
152
|
+
"type": "object",
|
|
153
|
+
"additionalProperties": true,
|
|
154
|
+
"required": ["page_id", "built_path"],
|
|
155
|
+
"properties": {
|
|
156
|
+
"page_id": { "type": "string", "minLength": 1 },
|
|
157
|
+
"built_path": { "type": "string", "minLength": 1 }
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"evidence_debt_change_kind": {
|
|
161
|
+
"enum": ["none", "page_only", "commerce_affecting", "unknown"],
|
|
162
|
+
"description": "page_only: only pages changed, and none of them is a checkout page or changed its package, offer, shipping, upsell, route or script markup, and the campaign's Page Kit config entry is unchanged. commerce_affecting: anything else that could be read. unknown: the change could not be read (no usable manifest, no commerce signature on an older record, or a rebuild history that does not reach the reviewed build)."
|
|
163
|
+
},
|
|
164
|
+
"evidence_debt_reason": {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"additionalProperties": true,
|
|
167
|
+
"required": ["code"],
|
|
168
|
+
"properties": {
|
|
169
|
+
"code": {
|
|
170
|
+
"enum": ["unmapped_file", "page_added", "page_removed", "checkout_page", "commerce_markup_changed", "commerce_signature_unavailable", "campaign_config_changed", "campaign_config_unavailable", "change_history_unavailable"]
|
|
171
|
+
},
|
|
172
|
+
"path": { "type": "string", "minLength": 1 }
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"evidence_debt_change": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"additionalProperties": true,
|
|
178
|
+
"required": ["kind", "since_build_fingerprint", "changed_pages", "unmapped_files", "reasons"],
|
|
179
|
+
"properties": {
|
|
180
|
+
"kind": { "$ref": "#/$defs/evidence_debt_change_kind" },
|
|
181
|
+
"since_build_fingerprint": { "$ref": "#/$defs/build_fingerprint" },
|
|
182
|
+
"changed_pages": { "type": "array", "items": { "$ref": "#/$defs/evidence_debt_page" } },
|
|
183
|
+
"unmapped_files": { "type": "array", "items": { "type": "string" }, "description": "At most 20 paths." },
|
|
184
|
+
"reasons": { "type": "array", "items": { "$ref": "#/$defs/evidence_debt_reason" }, "description": "Why the change counts as commerce-affecting or unknown; at most 20." }
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"evidence_debt_changes": {
|
|
188
|
+
"type": "object",
|
|
189
|
+
"additionalProperties": true,
|
|
190
|
+
"description": "Current built output compared with the retained assembly manifest, which need not be the build an older stage reviewed. Empty lists under unknown do not establish that no files changed; older stage manifests are not reconstructed.",
|
|
191
|
+
"required": [
|
|
192
|
+
"status",
|
|
193
|
+
"reason",
|
|
194
|
+
"recorded_build_fingerprint",
|
|
195
|
+
"current_build_fingerprint",
|
|
196
|
+
"changed_pages",
|
|
197
|
+
"unmapped_files",
|
|
198
|
+
"extra",
|
|
199
|
+
"missing",
|
|
200
|
+
"changed"
|
|
201
|
+
],
|
|
202
|
+
"properties": {
|
|
203
|
+
"status": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"enum": [
|
|
206
|
+
"known",
|
|
207
|
+
"unknown"
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
"reason": {
|
|
211
|
+
"enum": [
|
|
212
|
+
null,
|
|
213
|
+
"packet_unavailable",
|
|
214
|
+
"build_output_location_unknown",
|
|
215
|
+
"build_output_missing",
|
|
216
|
+
"build_output_unreadable",
|
|
217
|
+
"assembly_build_fingerprint_missing",
|
|
218
|
+
"build_output_pages_unresolved",
|
|
219
|
+
"build_manifest_unavailable"
|
|
220
|
+
],
|
|
221
|
+
"description": "Null when known. Missing or unusable manifest and unresolved page map make changes unknown independently of stage binding status."
|
|
222
|
+
},
|
|
223
|
+
"recorded_build_fingerprint": {
|
|
224
|
+
"$ref": "#/$defs/build_fingerprint",
|
|
225
|
+
"description": "The retained assembly baseline fingerprint."
|
|
226
|
+
},
|
|
227
|
+
"current_build_fingerprint": {
|
|
228
|
+
"$ref": "#/$defs/build_fingerprint"
|
|
229
|
+
},
|
|
230
|
+
"changed_pages": {
|
|
231
|
+
"type": "array",
|
|
232
|
+
"description": "Added, removed or modified HTML pages in sorted built-path order, using route-derived page identities. Removed HTML uses the same route projection. Paths are relative to _site/<public_route_slug>/.",
|
|
233
|
+
"items": {
|
|
234
|
+
"type": "object",
|
|
235
|
+
"additionalProperties": true,
|
|
236
|
+
"required": [
|
|
237
|
+
"page_id",
|
|
238
|
+
"built_path"
|
|
239
|
+
],
|
|
240
|
+
"properties": {
|
|
241
|
+
"page_id": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"minLength": 1
|
|
244
|
+
},
|
|
245
|
+
"built_path": {
|
|
246
|
+
"type": "string",
|
|
247
|
+
"minLength": 1
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"unmapped_files": {
|
|
253
|
+
"type": "array",
|
|
254
|
+
"items": {
|
|
255
|
+
"type": "string"
|
|
256
|
+
},
|
|
257
|
+
"description": "Sorted differing paths outside the built page map, including shared CSS, scripts and assets."
|
|
258
|
+
},
|
|
259
|
+
"extra": {
|
|
260
|
+
"type": "array",
|
|
261
|
+
"items": {
|
|
262
|
+
"type": "string"
|
|
263
|
+
},
|
|
264
|
+
"description": "Complete sorted paths added since the retained manifest, relative to the built output root."
|
|
265
|
+
},
|
|
266
|
+
"missing": {
|
|
267
|
+
"type": "array",
|
|
268
|
+
"items": {
|
|
269
|
+
"type": "string"
|
|
270
|
+
},
|
|
271
|
+
"description": "Complete sorted paths removed since the retained manifest, relative to the built output root."
|
|
272
|
+
},
|
|
273
|
+
"changed": {
|
|
274
|
+
"type": "array",
|
|
275
|
+
"items": {
|
|
276
|
+
"type": "string"
|
|
277
|
+
},
|
|
278
|
+
"description": "Complete sorted paths modified since the retained manifest, relative to the built output root."
|
|
279
|
+
},
|
|
280
|
+
"kind": {
|
|
281
|
+
"$ref": "#/$defs/evidence_debt_change_kind",
|
|
282
|
+
"description": "This drift from the retained assembly manifest, classified."
|
|
283
|
+
},
|
|
284
|
+
"reasons": {
|
|
285
|
+
"type": "array",
|
|
286
|
+
"items": { "$ref": "#/$defs/evidence_debt_reason" }
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
53
290
|
"artifact_key": {
|
|
54
291
|
"type": "string",
|
|
55
292
|
"enum": ["packet", "doctor", "context", "report", "qa_verdict", "findings"]
|
|
@@ -139,6 +139,9 @@
|
|
|
139
139
|
"minLength": 1,
|
|
140
140
|
"description": "Active CampaignSpec page id. This is the primary join key."
|
|
141
141
|
},
|
|
142
|
+
"design_file": {
|
|
143
|
+
"description": "Optional design-file authority behind this page's HTML export, normally {type?, file_url, breakpoints?: {desktop?, tablet?, mobile?}}. Deliberately unconstrained: the runtime accepts every JSON value here, warns on unusable declarations or frame links and ignores them without rejecting the manifest. Usable file_url values parse as absolute HTTPS URLs (scheme case-insensitive)."
|
|
144
|
+
},
|
|
142
145
|
"path": {
|
|
143
146
|
"type": "string",
|
|
144
147
|
"minLength": 1,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: campaign-lifecycle-orientation
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.48
|
|
4
4
|
description: Orient a reader to the Campaigns OS lifecycle artifacts a run has already emitted, without advancing any stage or changing any state.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: campaign-readback-classification
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.48
|
|
4
4
|
description: Classify a selected campaign from the readback projection's v2 fields and write a read-only handoff without turning diagnosis into permission.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: campaign-run-evidence
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.48
|
|
4
4
|
description: Interpret existing Campaigns OS doctor, QA and proof-depth evidence without claiming more proof than the artifacts contain.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: contribution-intake
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.48
|
|
4
4
|
description: Turn a suggestion about the agent surface into a classified, evidence-checked proposal and, only with attended approval, one issue on this repository's tracker.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-build
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.53
|
|
4
4
|
description: Assemble a NEXT campaign from a doctor-cleared Build Packet, CampaignSpec/API values, prepared HTML/assets, page-kit, and starter-template contracts.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -76,6 +76,7 @@ Inputs:
|
|
|
76
76
|
- target page-kit repo
|
|
77
77
|
- starter-template commerce catalog
|
|
78
78
|
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour.
|
|
79
|
+
- A Page Kit project can hold several funnels. The first one set up uses `campaign-runtime.build.json` and the `.campaign-runtime/` paths named here; each later funnel has `campaign-runtime-<route>.build.json` and keeps the same files under `.campaign-runtime/funnels/<route>/` (the packet's `assembly.runtime_dir`). Read and pass the funnel's own packet and paths; the paths `next` prints are already the right ones.
|
|
79
80
|
|
|
80
81
|
Build rules:
|
|
81
82
|
|
|
@@ -90,7 +91,7 @@ Build rules:
|
|
|
90
91
|
- Reproduce the source design's own proof and urgency elements as designed: reviews and testimonials, ratings, "Verified Purchase" labels, recent-purchase popups, stock counters, countdowns and guarantees. They are the merchant's content and the merchant's responsibility; Campaigns OS does not review them, so do not remove, soften or flag them. The starter templates shipping without some of these elements is not a reason to drop the source's.
|
|
91
92
|
- Prepared source HTML means page-kit-ready markup, not a wholesale Liquid rewrite. Standalone HTML mockups that are meant to stay whole (their `source_screenshot` proof is of the full document) keep their document wrappers: the source-html manifest records `wrapper_policy: preserve_document_wrappers` (or `--wrapper-policy preserve_document_wrappers` on `start` / `prepare-build`), and doctor reports the wrappers as a warning. Otherwise, standalone AI/exported HTML should keep page-owned body markup, remove document wrappers, add YAML frontmatter, move shared CSS/assets into the campaign structure, and use Liquid helpers only where page-kit needs campaign-rooted links/assets/includes.
|
|
92
93
|
- For `checkout`, `upsell`, `downsell`, and `receipt` pages, treat the selected starter-template commerce surface as the SDK contract reference: preserve required `data-next-*` controls, hidden fields, payment/address/totals/submit wiring, and `next_dont_touch` regions. The surrounding HTML wrapper, page composition, imagery, copy hierarchy, and brand layer are campaign/source-owned. Do not carry starter visual chrome forward when prepared source design should own that surface. QA checks what the checkout does, not family class names: do not add family shell classes (`.checkout-wrapper`, `.checkout-layout__left/right`) to the campaign's own grid or swap source-owned field markup for family includes to satisfy QA. Keep the checkout working instead: a `<form data-next-checkout="form">`, the contact and shipping fields bound with `data-next-checkout-field` inside it, and a visible cart total. A required field bound only on a `type="hidden"` input, a disabled control, a read-only input or read-only textarea, or a control with `aria-disabled="true"` does not count as bound: QA reports it in `fields_bound.missing`.
|
|
93
|
-
- Read `context.theme` and `.campaign-runtime/theme/theme-report.json` when present. If a fresh `brand-theme.css` artifact exists, copy it into the campaign asset tree and load it after `next-core.css` on checkout, upsell, downsell, and receipt pages. If policy is `inspect_only`, either run `campaigns-os theme generate` (tier `B`: writes the theme artifacts and doctor output under the target; `--force` is tier `C`) or record an explicit skipped reason before applying a new brand layer.
|
|
94
|
+
- Read `context.theme` and `.campaign-runtime/theme/theme-report.json` when present. If a fresh `brand-theme.css` artifact exists, copy it into the campaign asset tree and load it after `next-core.css` on checkout, upsell, downsell, and receipt pages. When theme generate also wrote `brand-fonts.css` (the design's own `@font-face` rules for its heading and body families), copy it into the same `assets/css/` folder and load it on the same pages: without it the font tokens in `brand-theme.css` name faces the page can't load, and commerce pages fall back to the system font. `record theme` refuses a styled page that skips it. If policy is `inspect_only`, either run `campaigns-os theme generate` (tier `B`: writes the theme artifacts and doctor output under the target; `--force` is tier `C`) or record an explicit skipped reason before applying a new brand layer.
|
|
94
95
|
- Generated brand-theme v0 is root-variable-only. It may skin commerce pages through next-core custom properties, but it is not permission to edit SDK-owned selectors, package controls, payment fields, totals, submit controls, receipt templates, route meta tags, or SDK JavaScript.
|
|
95
96
|
- Payment, express checkout, bundle selectors, and order bumps must start from the selected family's canonical component DOM/classes, not from raw custom/source HTML with `data-next-*` added afterward. For payment specifically, preserve the family payment-method wrapper, hosted field classes, and iframe geometry assumptions (for example `input-flds spreedly-field` in shop-style templates). Skin these components with campaign tokens; do not rebuild Spreedly/card fields as arbitrary divs.
|
|
96
97
|
- When a checkout page declares `exit_intent.enabled`, wire the popup as an offer application surface: use `offer_ref_id`/`offer_code` from CampaignSpec, apply the code through the SDK/API coupon/voucher path, and render applied-state copy with SDK conditionals such as `cart.hasCoupon("FREESHIP")`.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-os
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.68
|
|
4
4
|
description: Coordinate Campaigns OS lifecycle workflows from CampaignSpec, Build Packet, starter-template contracts, stage reports, deploy evidence, and QA proof depth.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -74,13 +74,14 @@ to author a spec or fabricate a Map ID. Verify store/campaign binding and real
|
|
|
74
74
|
package/offer references. Store contact and policy details can come from the
|
|
75
75
|
brief; gateway access is optional. Current authoring is v4.3+ while preserving
|
|
76
76
|
the v4.2 `funnels[]` topology as the compatibility shape.
|
|
77
|
+
When the HTML was exported from a design file, name it as `design_file: {file_url, type?, breakpoints?}` on the source-html manifest page; see `docs/design-source-package.md` for the shape and the Figma-only spec `design_source` provenance rule.
|
|
77
78
|
2. Run `campaigns-os start` or `campaigns-os prepare-build` (tier `A`: they write the
|
|
78
79
|
Build Packet, Build Context, assembly report, run session and `.gitignore` under
|
|
79
80
|
the target plus a Run Record under the working directory, and they contact the
|
|
80
81
|
Map and run endpoints) with a local CampaignSpec, prepared HTML/assets source, target page-kit repo, and explicit template family. The family must be certified (commerce catalog + brand contract; the CLI lists them on rejection) — an uncertified/custom family requires `--allow-uncertified-template "<reason>"` and forfeits deterministic assembly, residue QA, and pricing contracts. The entry point auto-opens the run session in the target repo; do not skip `campaigns-os run end` (tier `C`: it clears the active run session — a write that discards prior state — while assembling and remitting the Run Record) at the finish. If intake blocks with `DESIGN_SOURCE_PACKAGE_NOT_READY`, the source material carries no desktop/mobile screenshot proof: supply it through `pages[].screenshots[]` in `<source-root>/.campaigns-os/source-html-manifest.json` and follow "Clearing `DESIGN_SOURCE_PACKAGE_NOT_READY`" in `docs/design-source-package.md`, which also gives the recovery for the package a blocked run left behind.
|
|
81
82
|
3. Brand-theme discovery runs in inspect-only mode by default and records `context.theme`. When it proves a brand theme is generatable and the campaign ships commerce pages, the theme gate BLOCKS polish/deploy/QA until the brand layer is applied after `next-core.css` or explicitly waived (`campaigns-os theme waive --packet <p> --reason "<why>" --waived-by "<named human>"` — tier `C`: it overwrites the assembly report and doctor output, the same named-human rule as `checkpoint waive`). Run `campaigns-os theme generate` (tier `B`: writes the theme artifacts and doctor output under the target; `--force` is tier `C` because it overwrites an existing theme) and apply it during build; do not defer the decision.
|
|
82
83
|
4. Run `campaigns-os doctor --packet <packet>` (tier `A`: inspection that writes nothing and is exempt from lifecycle capture, plus one read-only live campaign request once the site is built and a public campaign key resolves; `--write` is tier `A` (the same read, plus it writes doctor output); `--built` and `--built --emit-packet` are tier `B` and write doctor output or the emitted packet under the target).
|
|
83
|
-
5. Resolve the registered **Page Kit** checkpoints before runtime work. The CampaignSpec is the authority for the target's `_data/campaigns.json` entry, and the reconcile is a command, not a hand edit: `campaigns-os page-kit sync --packet <p>` (tier `B`: writes the target's `_data/campaigns.json` entry and doctor output, nothing off the machine; add `--dry-run`, tier `none` and read-only, to see the field-by-field diff first) writes the spec's `campaign.store_*` fields into the entry for the packet's route and seeds the released SDK pin (`global_config.sdk_version` is canonical, `runtime.sdk_version` an accepted alias) while the entry is still in scaffold state or behind the spec; it never moves a configured campaign's pin backwards (on an existing campaign the repo pin moves first and the Map is stale: run `campaigns-os spec derive --packet <p>` (tier `
|
|
84
|
+
5. Resolve the registered **Page Kit** checkpoints before runtime work. The CampaignSpec is the authority for the target's `_data/campaigns.json` entry, and the reconcile is a command, not a hand edit: `campaigns-os page-kit sync --packet <p>` (tier `B`: writes the target's `_data/campaigns.json` entry and doctor output, nothing off the machine; add `--dry-run`, tier `none` and read-only, to see the field-by-field diff first) writes the spec's `campaign.store_*` fields into the entry for the packet's route and seeds the released SDK pin (`global_config.sdk_version` is canonical, `runtime.sdk_version` an accepted alias) while the entry is still in scaffold state or behind the spec; it never moves a configured campaign's pin backwards (on an existing campaign the repo pin moves first and the Map is stale: run `campaigns-os spec derive --packet <p>` (tier `A`: writes the local CampaignSpec and doctor output, and once the campaign is built makes the one read-only live campaign read doctor makes; `--no-live-refs` keeps it tier `B`), which writes the repo pin — and the page routes and analytics ids the repo carries, after handoff the pages the page tree adds or removes, and the offer and package fields the spec mirrors from the Campaigns App — into the local CampaignSpec with a field-by-field diff (bind it with `campaigns-os record spec --packet <p>`), and add `--write-map` (tier `A`: the same local writes plus a read and a write against the Map endpoints) to record the pin in the saved Map's Build hints too (it reads the Map back and moves only the pin, forward or not at all; a Map pin ahead of the repo is refused as a warning), or re-save the Map by hand; a hand edit of the spec is never the answer for a derived field; the `campaign.store_*` fields are derived from the store itself with `spec derive --packet <p> --from-store <subdomain>` (tier `A`: it contacts the store's Admin API through the login gateway), using gateway credentials saved by `campaigns-os login --store <subdomain>` (tier `A`: it contacts the gateway and writes the credential file under your home directory) by default within the admitted owned-store private pilot; existing direct Admin callers must explicitly add `--store-token-source env:<VAR>` naming their existing environment variable (this warned break-glass path bypasses gateway custody; there is no implicit environment lookup or fallback after gateway failure; see `docs/gateway-login.md`), and a field the store cannot state is reported and left as it is, never emptied), and touches nothing else; doctor and `next` print it as the gate's `repair_target` action, and after it `page_kit.store_profile` and `page_kit.sdk_version` pass without a waiver. Starter demo residue (a demo storefront URL or phone) in that entry is never waivable and must be replaced this way. A `PARTIAL` status means a field could not be made spec-authoritative (a spec value of the wrong type or shape, the demo value itself in the spec, demo residue in a field the spec does not carry, a conflicting or non-released pin, or a gate under an active waiver); the warnings name the spec field to fix, then sync again. Missing/malformed Store Profile or SDK evidence, invalid types or semantic versions, and conflicting dual SDK declarations are not waivable. An exact valid mismatch may be accepted with named-human attribution and a bound: `campaigns-os checkpoint waive` (tier `C`: a waiver overwrites the assembly report and doctor output) `--packet <p> --gate <page_kit.store_profile|page_kit.sdk_version> --reason "<why>" --waived-by "<named human>" --review-condition "<trigger>"` (or `--expires-at <future ISO timestamp>`). The package-owned hidden eager-media checkpoint is produced and resolved during Polish in step 9.
|
|
84
85
|
6. On any doctor run that sees built output, resolve `built_output.upsell_selector_scope`. A `data-next-bundle-selector` on a page whose funnel role is `upsell` or `downsell` writes to the shopper's LIVE CART unless it carries `data-next-upsell-context`; loading the page then adds that package with no click, and it is charged at the next checkout without appearing in that checkout's rendered order summary. Being hidden does not help — the write happens at init. Fix it by adding `data-next-upsell-context` to the named selector, or by deleting a selector that exists only to display a price. This gate runs on EVERY doctor invocation, not only after assembly, because the defect it was written for was introduced by a later review round. If a cart-scoped selector on a post-purchase page is genuinely intended, record it: `campaigns-os checkpoint waive --packet <p> --gate built_output.upsell_selector_scope --reason "<why>" --waived-by "<named human>" --review-condition "<trigger>"`. On the same runs, resolve `built_output.campaign_identity`: every page must name the same campaign — one API key (`next-api-key` meta or the `config.js` / `window.nextConfig` `apiKey`), one `next-funnel`, and any `setAttribution({ funnel })` call agreeing with the tag of the page that makes it. A page copied from another funnel that still carries the other campaign's key, tag, or call binds and renders without complaint and puts the order on the wrong campaign. Each error names the two files and the two values; make the one-line edit it describes. Not waivable — there is no `checkpoint waive` lane for it. Parked `-backup-` / `-old-` copies are skipped and listed, not scanned. Also resolve `built_output.sdk_markup`: its blockers (`SWAP_WITH_ADD_TO_CART`, `CHECKOUT_NOT_FORM`, `WRONG_FIELD_NAME`, `MISSING_SELECTOR_ID_MATCH`) are markup the SDK binds and then silently no-ops or double-writes on — fix the markup the message names (it gives the SDK spelling for a wrong field name); its warnings (`DOUBLE_SELECTED`, `TEMPLATE_DOUBLE_BRACE`) are advisory. Neither is waivable. A `data-next-*` name the SDK does not read shows up as one advisory line naming the attribute index version, not a warning.
|
|
85
86
|
7. If doctor's `next` block says `doctor-blocked` or `prepare-build` (it names the same stage `campaigns-os next` would), stop and resolve the named blockers.
|
|
86
87
|
8. If doctor returns `build`, hand off with `campaigns-os next build --packet <packet>` (tier `A`, like every `next` form: additive writes under `.campaign-runtime/` plus a stage-progress POST once Run Telemetry consent is persisted; `--no-write` and `--no-remit` are each tier `B` and keep the invocation local) and follow `next-campaigns-build`'s recommended **build → independent review → repair → verification** loop. Stage completion is recorded by command, never by hand-editing `.campaign-runtime/` JSON: `campaigns-os record setup`, `record build` (after every page-kit build) and `record polish --evidence <file>` (tier `C` each: they overwrite the stage record they name and stamp the doctor output stale; `--dry-run` is tier `none`).
|
|
@@ -95,6 +96,7 @@ Map and run endpoints) with a local CampaignSpec, prepared HTML/assets source, t
|
|
|
95
96
|
retains each attributed exception as `ready_with_exceptions`, and one
|
|
96
97
|
exception never suppresses another blocker.
|
|
97
98
|
10. Run the package-owned proof path in sequence: ensure `npx --no-install campaigns-os qa install-browser` has completed, run `campaigns-os qa resolve --packet <packet>` (tier `A`: it fetches `--base-url`; `--no-probe` is tier `B` and local), then `campaigns-os qa run --packet <packet> --base-url <url> --browser --test-order common` (tier `C`: it overwrites the stored verdict and assembly report, places real typed-card test orders against the campaign, and posts the verdict and progress; `--no-post-verdict` drops the verdict POST and `--no-remit` the Run Record remit, but both stay tier `C`).
|
|
99
|
+
After launch, a rebuild that touches only some pages' HTML is the exception to steps 9 and 10: readback's `evidence_debt` marks Polish advisory and QA scoped to the changed pages, and `campaigns-os next` names `qa run --packet <packet> --page <page_id>`, which places no test orders. Follow `next`.
|
|
98
100
|
11. Treat typed-card proof coverage as the control: `qa run` has no permission flag. Test orders still land in the store as real orders (global test cards: no charge, no transaction) that someone may have to cancel. Unless the operator has already said test orders are fine for this campaign, ask once, up front in your first turn with your other setup questions, so the answer covers the whole build and QA and neither stops for it later. `common` runs every actual terminal path when they fit under the flood cap (`--max-test-orders`, 6 by default); above the cap it runs checkout, first-offer accept and decline, and a deduplicated shortest real receipt path, then adds one decline path per offer or downsell page not yet declined, up to the cap, and names any page left out. A page counts as covered only when an order clicks its decline; the `browser-test-order:upsell-action-coverage` verdict row warns naming each page whose decline no order clicked. `full` walks every actual terminal path in the selected checkout topology; cycles, missing routes, and reachable nonterminals block exhaustive proof before browser launch. The accidental-flood cap remains `6`, and an overflow names the exact explicit `--max-test-orders` raise. Localhost on any port is a Campaigns App Development domain for SDK QA with analytics suppressed; non-localhost preview/production origins still need SDK origin allowlist confirmation.
|
|
99
101
|
12. Discuss launch only from recorded build, polish, deploy, browser QA, and test-order evidence, or from explicit blockers.
|
|
100
102
|
|
|
@@ -132,6 +134,7 @@ Rules:
|
|
|
132
134
|
- Designed source owns visual composition and page-level content.
|
|
133
135
|
- Brand-theme evidence is workflow-order neutral. Do not assume a Figma export came first; consume `context.theme` and `.campaign-runtime/theme/theme-report.json` when present. A truly missing/ungeneratable theme stays a warning, but a generatable-and-unapplied theme on a commerce-page campaign is a gate: apply it or waive it explicitly before polish/deploy/QA.
|
|
134
136
|
- Follow `campaigns-os next` literally. Every `next` response carries its applicable Store Profile, SDK, hidden eager-media, theme, and broad Polish gates plus `next_actions` with exact commands — execute those instead of improvising. With an active run session, pipeline-advancing commands that don't match the last `next` recommendation are recorded to `.campaign-runtime/agent-deviations.jsonl`; declare a detour with `--deviation-reason "<the operator's reason>"` only when the operator has decided on that detour in this conversation, and quote their reason; never pass the flag on your own judgement. On `record build` after a brief or CampaignSpec change the flag records that the change needs no change to the built pages, so pass it there only on the operator's explicit decision, as `next-campaigns-build` says.
|
|
137
|
+
- A Page Kit project can hold several funnels. The first one set up uses `campaign-runtime.build.json` and the `.campaign-runtime/` paths named here; each later funnel has `campaign-runtime-<route>.build.json` and keeps the same files under `.campaign-runtime/funnels/<route>/` (the packet's `assembly.runtime_dir`). Read and pass the funnel's own packet and paths; the paths `next` prints are already the right ones.
|
|
135
138
|
- Close the loop: when `next` reports `done` (or QA has published its verdict and the PR is up), finish with `campaigns-os run end` (tier `C`; `--no-write` still clears the session file) so the Run Record is assembled and the run session clears. `campaigns-os run status` (tier `none`: read-only) shows incomplete stages and the exact next command at any point.
|
|
136
139
|
- Do not copy demo refs or unsupported optional surfaces into the target campaign.
|
|
137
140
|
- Use SDK conditionals such as `cart.hasCoupon("CODE")` for code-specific presentation; do not mutate visible prices from campaign-specific JavaScript.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: next-campaigns-os-setup
|
|
3
|
-
version: 2.0.
|
|
3
|
+
version: 2.0.51
|
|
4
4
|
description: Bootstrap or prepare a target page-kit campaign repo from a doctor-cleared Campaigns OS Build Packet before full build wiring. Formerly installed as next-campaigns-setup; renamed 2026-08 to stop colliding with the published NextCommerceCo/skills scaffolder of that name.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Bundle revision: 1.
|
|
8
|
-
Run `npx --no-install campaigns-os tooling status --skills-revision 1.
|
|
7
|
+
Bundle revision: 1.62.0+skills.1
|
|
8
|
+
Run `npx --no-install campaigns-os tooling status --skills-revision 1.62.0+skills.1`
|
|
9
9
|
from the campaign's Page Kit folder, where it runs the project's pinned copy and
|
|
10
10
|
never installs one, at the start of each task. Start a fresh session if it
|
|
11
11
|
reports `mismatch`: this text is already in your context and is never re-read
|
|
@@ -53,6 +53,8 @@ Responsibilities:
|
|
|
53
53
|
- Public families resolve from the default `public` starter-templates source. A **private** family (one whose source lives in an access-controlled repo, e.g. a certified family not present in the public picker) is scaffolded via page-kit's template-source mechanism (`next-campaign-page-kit` >= 0.2.0): add a named source to the target repo's `_data/template-sources.json` (a `git` source with the SSH `url` + optional `ref`, or a `local` source `path`), then `campaign-init --source <name> --template <slug>`. The source repo must expose a root `templates.json` catalog + `src/<slug>/` tree. page-kit holds no family→repo mapping; the source config lives in the (private) consuming repo, and this skill (plus the family's certified contract) is where that source is known.
|
|
54
54
|
- Install or reference `.campaign-runtime/agent-context` without overwriting existing root agent files.
|
|
55
55
|
- Read the normalized Campaign Build Brief at `.campaign-runtime/input/campaign-build-brief.normalized.json` and the recorded decisions (`adapter_decisions`, `decisions` and `theme` in `.campaign-runtime/assembly-report.json`, and `assembly.template_decision_notes` in the Build Packet) before working on the campaign. The campaign intent summary at the top of the setup, build, Polish and QA prompts and in every `next` result is orientation, never a source of prices or commerce behaviour.
|
|
56
|
+
- A Page Kit project can hold several funnels. The first one set up uses `campaign-runtime.build.json` and the `.campaign-runtime/` paths named here; each later funnel has `campaign-runtime-<route>.build.json` and keeps the same files under `.campaign-runtime/funnels/<route>/` (the packet's `assembly.runtime_dir`). Read and pass the funnel's own packet and paths; the paths `next` prints are already the right ones.
|
|
57
|
+
- When prepare-build prints a `Funnel:` line, it set up a new route as another funnel beside the default packet. If the operator meant to rename the existing funnel's route, follow the steps that line prints (delete the new packet and its directory, then re-run with `--out campaign-runtime.build.json --force`); ask before running it, because `--force` clears that funnel's recorded stage evidence.
|
|
56
58
|
- Record setup with `campaigns-os record setup --packet <packet>` once the campaign output directory exists (tier `C`: it overwrites `stages.setup` in `.campaign-runtime/assembly-report.json` and the `scaffold` block of `.campaign-runtime/build-context.json`, and stamps the doctor output stale; `--dry-run` is tier `none`). It sets `scaffold.required` to false and `stages.setup` to completed, validates both files against their schemas, and writes nothing when a check fails. Do not hand-edit either file.
|
|
57
59
|
- Preserve existing Build Context `theme` inspection data and Assembly Report `theme` application data when setup is rerun against an existing campaign directory.
|
|
58
60
|
- Hand off to `next-campaigns-build`.
|