@nextcommerce/campaigns-os 1.52.0 → 1.53.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/CHANGELOG.md +48 -0
- package/agents/claude/CLAUDE.md +2 -0
- package/agents/codex/AGENTS.md +2 -0
- package/agents/copilot/copilot-instructions.md +2 -0
- package/agents/cursor/campaigns-os.mdc +2 -0
- package/compatibility.json +1 -1
- package/contracts/effects.v1.json +201 -12
- package/contracts/release-ledger.json +327 -0
- package/contracts/supported-surface.json +2 -2
- package/docs/brand-theme-bridge.md +2 -0
- package/docs/build-packet.md +56 -15
- package/docs/campaign-build-brief.md +48 -17
- package/docs/effects.md +8 -0
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +1 -1
- package/docs/polish-evidence.md +2 -0
- package/docs/progress-snapshots.md +2 -4
- package/docs/qa-and-test-orders.md +2 -0
- package/docs/readback.md +19 -2
- package/docs/runtime-readiness.md +1 -1
- package/docs/skills-revision.md +10 -10
- package/package.json +1 -1
- 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 -3
- package/skills/next-campaigns-os/SKILL.md +10 -19
- package/skills/next-campaigns-os/references/session-intake.md +10 -6
- package/skills/next-campaigns-os-setup/SKILL.md +4 -3
- package/skills/next-campaigns-polish/SKILL.md +7 -5
- package/skills/next-campaigns-qa/SKILL.md +5 -3
- package/skills.json +10 -10
- package/src/brand-theme.mjs +21 -20
- package/src/brief-summary.mjs +275 -0
- package/src/build-brief.mjs +167 -15
- package/src/cli.mjs +160 -112
- package/src/contrast.mjs +649 -0
- package/src/design-source-publication.mjs +110 -3
- package/src/doctor/checks.mjs +129 -14
- package/src/doctor/next-step.mjs +15 -6
- package/src/input-currency.mjs +394 -0
- package/src/input-refresh.mjs +708 -0
- package/src/invocation.mjs +3 -1
- package/src/polish-browser.mjs +503 -201
- package/src/polish-deadline.mjs +7 -0
- package/src/polish-node.mjs +326 -46
- package/src/polish-readability.mjs +828 -0
- package/src/progress-node.mjs +15 -3
- package/src/qa-browser.mjs +131 -84
- package/src/qa-node.mjs +14 -3
- package/src/qc-accept.mjs +44 -8
- package/src/qc-check-registry.mjs +15 -7
- package/src/qc-results.mjs +326 -34
- package/src/readback.mjs +58 -10
- package/src/stage-ledger.mjs +235 -44
- package/src/stage-record.mjs +119 -26
- package/src/tooling-setup.mjs +1 -1
|
@@ -5870,6 +5870,333 @@
|
|
|
5870
5870
|
}
|
|
5871
5871
|
],
|
|
5872
5872
|
"entry_sha256": "e9063da2788630cb0017eedc0b2e77b717b290bae0e7cb5d6bcdbbb6e6b7368e"
|
|
5873
|
+
},
|
|
5874
|
+
{
|
|
5875
|
+
"id": "RL-0233",
|
|
5876
|
+
"sequence": 225,
|
|
5877
|
+
"date": "2026-10-05",
|
|
5878
|
+
"kind": "release",
|
|
5879
|
+
"surface_version": "1.53.0",
|
|
5880
|
+
"changelog_section": "1.53.0",
|
|
5881
|
+
"changelog_sha256": "b5e6bbfd3ab22a16b715fbd574128715ab5a9a70d76c1e09f8f91c1d25ce72f6",
|
|
5882
|
+
"agent_impact": "Surface 1.53.0. Adds record brief, which saves Campaign Build Brief answers without re-running intake, and record spec, which binds a CampaignSpec change without discarding operator state; their --dry-run forms write nothing and append no lifecycle entry. A brief file is guided unless it sets \"brief_mode\": \"prepared\" (a campaign whose report already records a prepared brief stays prepared). An unchanged or reformatted save keeps every stage's evidence and status. A material brief or CampaignSpec change makes build, Polish and QA owed again (QA alone for a qa_policy change), keeps the last five superseded records per stage as history that is never current proof, and next, doctor, progress, readback and the Assembly Report status report the owed stage; next offers refresh_inputs (record brief or record spec) when a recorded stage was made against earlier content. Build, Polish and QA records now stamp the brief and CampaignSpec content they were made against; records without stamps read unconfirmed. Re-recording an unchanged build after an input change keeps the build owed unless the operator's --deviation-reason records that the change needs no output change; Polish stays owed until a new capture postdates the change. Intake refuses, without --force, to discard recorded waivers, warning accepts, stage history, an applied theme, or a recorded deploy target, preview URL, production URL, order-path depth or allowed-domains confirmation; --force archives the build, Polish and QA records it clears and keeps stage history. spec derive no longer rebinds report identity and its --json result no longer carries rebound; run record spec after it. Bundled skills carry revision 1.53.0+skills.1: an agent that loaded an earlier revision should start a fresh session. Install the 1.53.0 package with the documented local setup command.",
|
|
5883
|
+
"compatibility": "breaking",
|
|
5884
|
+
"migration": "After upgrading, next routes each in-flight campaign back to build once, because build, Polish and QA records made before 1.53.0 do not record which brief and CampaignSpec content they used: re-record build and Polish, and run QA again for a new verdict. Add \"brief_mode\": \"prepared\" to a hand-written brief file whose open questions should block. Save brief answers with record brief and CampaignSpec changes with record spec instead of re-running start, prepare-build or build, which now refuse without --force to discard recorded waivers, warning accepts, stage history, an applied theme, or a recorded deploy target, preview URL, production URL, order-path depth or allowed-domains confirmation. Run record spec after spec derive, and stop reading rebound from spec derive --json.",
|
|
5885
|
+
"changes": [
|
|
5886
|
+
{
|
|
5887
|
+
"class": "compatibility_policy",
|
|
5888
|
+
"path": "compatibility.json",
|
|
5889
|
+
"surface_entry": null,
|
|
5890
|
+
"summary": "Advance the declared version to 1.53.0."
|
|
5891
|
+
},
|
|
5892
|
+
{
|
|
5893
|
+
"class": "compatibility_policy",
|
|
5894
|
+
"path": "contracts/effects.v1.json",
|
|
5895
|
+
"surface_entry": "contracts/effects.v1.json",
|
|
5896
|
+
"summary": "Declare the record brief and record spec rows (tier C) and their --dry-run rows (tier none); correct the start, prepare-build and build notes (refused without --force when the report carries stage evidence, stage history or operator decisions) and their --force notes (completed build, Polish and QA records are archived into stage history, which is kept); state that record build writes input_change and makes Polish and QA owed when it detects a brief or CampaignSpec change; and state that record polish, record theme and record deploy are refused while an earlier stage is owed again."
|
|
5897
|
+
},
|
|
5898
|
+
{
|
|
5899
|
+
"class": "compatibility_policy",
|
|
5900
|
+
"path": "contracts/supported-surface.json",
|
|
5901
|
+
"surface_entry": "contracts/supported-surface.json",
|
|
5902
|
+
"summary": "Advance surface_version to 1.53.0 and record the effects contract hash."
|
|
5903
|
+
},
|
|
5904
|
+
{
|
|
5905
|
+
"class": "named_surface",
|
|
5906
|
+
"path": "docs/build-packet.md",
|
|
5907
|
+
"surface_entry": "docs/build-packet.md",
|
|
5908
|
+
"summary": "Describe CampaignSpec material changes for local-spec, saved-Map and gateway packets, record spec, spec derive no longer rebinding identity, and the brief and CampaignSpec dependency map."
|
|
5909
|
+
},
|
|
5910
|
+
{
|
|
5911
|
+
"class": "named_surface",
|
|
5912
|
+
"path": "docs/campaign-build-brief.md",
|
|
5913
|
+
"surface_entry": "docs/campaign-build-brief.md",
|
|
5914
|
+
"summary": "Replace Answering The Questions with saving answers through record brief, the brief_mode rule, which changes make which stages owed again, stage history, --deviation-reason, and the one-time re-proof of records made before 1.53.0."
|
|
5915
|
+
},
|
|
5916
|
+
{
|
|
5917
|
+
"class": "named_surface",
|
|
5918
|
+
"path": "docs/effects.md",
|
|
5919
|
+
"surface_entry": "docs/effects.md",
|
|
5920
|
+
"summary": "Describe what record brief and record spec write and refuse, their dry runs, and the intake refusal and --force archive."
|
|
5921
|
+
},
|
|
5922
|
+
{
|
|
5923
|
+
"class": "named_surface",
|
|
5924
|
+
"path": "docs/local-setup.md",
|
|
5925
|
+
"surface_entry": "docs/local-setup.md",
|
|
5926
|
+
"summary": "Pin the 1.53.0 package in the local setup install command."
|
|
5927
|
+
},
|
|
5928
|
+
{
|
|
5929
|
+
"class": "documentation",
|
|
5930
|
+
"path": "docs/orientation-contract-reference.md",
|
|
5931
|
+
"surface_entry": "docs/orientation-contract-reference.md",
|
|
5932
|
+
"summary": "Regenerate at surface 1.53.0."
|
|
5933
|
+
},
|
|
5934
|
+
{
|
|
5935
|
+
"class": "named_surface",
|
|
5936
|
+
"path": "docs/progress-snapshots.md",
|
|
5937
|
+
"surface_entry": "docs/progress-snapshots.md",
|
|
5938
|
+
"summary": "Stage records carry each stage's effective status: a stage owed again by a brief or CampaignSpec change reads required, and one whose inputs cannot be confirmed reads unknown."
|
|
5939
|
+
},
|
|
5940
|
+
{
|
|
5941
|
+
"class": "named_surface",
|
|
5942
|
+
"path": "docs/readback.md",
|
|
5943
|
+
"surface_entry": "docs/readback.md",
|
|
5944
|
+
"summary": "The STAGES header prints the recorded and the effective report status, and a stage line whose effective status differs adds the recorded status and the reason."
|
|
5945
|
+
},
|
|
5946
|
+
{
|
|
5947
|
+
"class": "named_surface",
|
|
5948
|
+
"path": "docs/runtime-readiness.md",
|
|
5949
|
+
"surface_entry": "docs/runtime-readiness.md",
|
|
5950
|
+
"summary": "Regenerate at surface 1.53.0."
|
|
5951
|
+
},
|
|
5952
|
+
{
|
|
5953
|
+
"class": "named_surface",
|
|
5954
|
+
"path": "docs/skills-revision.md",
|
|
5955
|
+
"surface_entry": "docs/skills-revision.md",
|
|
5956
|
+
"summary": "Use the current 1.53.0+skills.1 bundle in executable examples."
|
|
5957
|
+
},
|
|
5958
|
+
{
|
|
5959
|
+
"class": "generated_runtime",
|
|
5960
|
+
"path": "package-lock.json",
|
|
5961
|
+
"surface_entry": null,
|
|
5962
|
+
"summary": "Advance the package version to 1.53.0."
|
|
5963
|
+
},
|
|
5964
|
+
{
|
|
5965
|
+
"class": "package_export",
|
|
5966
|
+
"path": "package.json",
|
|
5967
|
+
"surface_entry": null,
|
|
5968
|
+
"summary": "Advance the package version to 1.53.0."
|
|
5969
|
+
},
|
|
5970
|
+
{
|
|
5971
|
+
"class": "skill",
|
|
5972
|
+
"path": "skills.json",
|
|
5973
|
+
"surface_entry": "skills.json",
|
|
5974
|
+
"summary": "Advance the bundled skill revision to 1.53.0+skills.1 and each skill version one patch."
|
|
5975
|
+
},
|
|
5976
|
+
{
|
|
5977
|
+
"class": "skill",
|
|
5978
|
+
"path": "skills/campaign-lifecycle-orientation/SKILL.md",
|
|
5979
|
+
"surface_entry": null,
|
|
5980
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
5981
|
+
},
|
|
5982
|
+
{
|
|
5983
|
+
"class": "skill",
|
|
5984
|
+
"path": "skills/campaign-readback-classification/SKILL.md",
|
|
5985
|
+
"surface_entry": null,
|
|
5986
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
5987
|
+
},
|
|
5988
|
+
{
|
|
5989
|
+
"class": "skill",
|
|
5990
|
+
"path": "skills/campaign-run-evidence/SKILL.md",
|
|
5991
|
+
"surface_entry": null,
|
|
5992
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
5993
|
+
},
|
|
5994
|
+
{
|
|
5995
|
+
"class": "skill",
|
|
5996
|
+
"path": "skills/contribution-intake/SKILL.md",
|
|
5997
|
+
"surface_entry": null,
|
|
5998
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
5999
|
+
},
|
|
6000
|
+
{
|
|
6001
|
+
"class": "skill",
|
|
6002
|
+
"path": "skills/next-campaigns-build/SKILL.md",
|
|
6003
|
+
"surface_entry": null,
|
|
6004
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
6005
|
+
},
|
|
6006
|
+
{
|
|
6007
|
+
"class": "skill",
|
|
6008
|
+
"path": "skills/next-campaigns-os-setup/SKILL.md",
|
|
6009
|
+
"surface_entry": null,
|
|
6010
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
6011
|
+
},
|
|
6012
|
+
{
|
|
6013
|
+
"class": "skill",
|
|
6014
|
+
"path": "skills/next-campaigns-os/SKILL.md",
|
|
6015
|
+
"surface_entry": null,
|
|
6016
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
6017
|
+
},
|
|
6018
|
+
{
|
|
6019
|
+
"class": "skill",
|
|
6020
|
+
"path": "skills/next-campaigns-polish/SKILL.md",
|
|
6021
|
+
"surface_entry": null,
|
|
6022
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
6023
|
+
},
|
|
6024
|
+
{
|
|
6025
|
+
"class": "skill",
|
|
6026
|
+
"path": "skills/next-campaigns-qa/SKILL.md",
|
|
6027
|
+
"surface_entry": null,
|
|
6028
|
+
"summary": "Publish the 1.53.0+skills.1 bundle revision."
|
|
6029
|
+
},
|
|
6030
|
+
{
|
|
6031
|
+
"class": "cli_surface",
|
|
6032
|
+
"path": "src/cli.mjs",
|
|
6033
|
+
"surface_entry": "record",
|
|
6034
|
+
"summary": "Add record brief and record spec to the usage text; intake binds the brief material and refuses to discard operator state without --force; QA records stamp their inputs; next carries input_currency, offers refresh_inputs and notes an operator's unchanged-output decision in the QC handoff; spec derive no longer rebinds report identity, drops the rebound result field and names record spec."
|
|
6035
|
+
},
|
|
6036
|
+
{
|
|
6037
|
+
"class": "cli_surface",
|
|
6038
|
+
"path": "src/doctor/checks.mjs",
|
|
6039
|
+
"surface_entry": "doctor",
|
|
6040
|
+
"summary": "Doctor reports input currency in derived.input_currency and warns spec.material_stale, spec.binding_unknown, build_brief.material_changed, build_brief.binding_unknown, build_brief.input_unsaved, assembly.output_unchanged_after_input_change and assembly.output_unchanged_by_operator_decision; a normalized brief that is not valid JSON, or not a JSON object, is the build_brief.normalized_path error, not a crash."
|
|
6041
|
+
},
|
|
6042
|
+
{
|
|
6043
|
+
"class": "cli_surface",
|
|
6044
|
+
"path": "src/doctor/next-step.mjs",
|
|
6045
|
+
"surface_entry": "next",
|
|
6046
|
+
"summary": "The stage picker reads each stage's effective status, so a stage owed again by a brief or CampaignSpec change, or one whose inputs cannot be confirmed, is the stage next recommends."
|
|
6047
|
+
}
|
|
6048
|
+
],
|
|
6049
|
+
"entry_sha256": "85e37bd6392dcfa8415a654897eb8dbe8ab417fc9c92ec21732d2fff5a5f5f5b"
|
|
6050
|
+
},
|
|
6051
|
+
{
|
|
6052
|
+
"id": "RL-0234",
|
|
6053
|
+
"sequence": 226,
|
|
6054
|
+
"date": "2026-10-05",
|
|
6055
|
+
"kind": "release",
|
|
6056
|
+
"surface_version": null,
|
|
6057
|
+
"changelog_section": "1.53.0+agent.1",
|
|
6058
|
+
"changelog_sha256": "b865a430b924ff48016930621ba3905deb7861516d9dfdabfd797ed5aaebf6db",
|
|
6059
|
+
"agent_impact": "polish capture now measures text readability on every built page at desktop and mobile widths and attaches it as stages.polish.evidence.visual_review.readability; next lists readability.contrast warnings, review and coverage results in its QC handoff, grouping each warning colour pair across pages and widths for one checkpoint accept. On a campaign whose every mapped page is template stock, polish capture measures readability, prints the page-load no_capturable_routes message as a warning, and exits 0 with status captured_with_warnings; record polish still refuses a completed Polish record there. Polish media weight and readability results read as stale when doctor reports the built output changed since record build. Readability results never block Polish or change readiness. QA's browser-primary-cta check now runs on every page with an expected_next_url, whatever its page type, and measures every visible route-matching CTA (not only the most readable one) and each piece of text inside it, unrounded, with the same measurement Polish uses, against the requirement for its own size; its evidence lists each candidate's elements[] with contrast_ratio_exact and required_ratio. A CTA observed incompletely (the SDK, stylesheets, fonts or its text not ready, a review trigger, text generated by ::before or ::after, or disabled controls) reads manual_review at severity warn, never pass, and so does a page whose inspection script errors (inspection_error, earlier a fail). So browser-primary-cta results on existing campaigns can change in either direction: pages that were skipped are now checked, a second CTA or child text can now fail, large bold text at 3:1 can now pass, and incomplete observations read manual_review instead of pass or fail. The brand theme generator compares contrast unrounded, so a declared colour in [4.495, 4.5) now adds theme.foreground.low_contrast; generated CSS and colour choices are unchanged.",
|
|
6060
|
+
"compatibility": "additive",
|
|
6061
|
+
"migration": "none",
|
|
6062
|
+
"changes": [
|
|
6063
|
+
{
|
|
6064
|
+
"class": "cli_surface",
|
|
6065
|
+
"path": "src/cli.mjs",
|
|
6066
|
+
"surface_entry": "polish",
|
|
6067
|
+
"summary": "polish capture attaches the readability record beside page_load (which now carries captured_at), and on a campaign with no mapped pages measures readability only, reports the held page-load message as a warning and exits 0."
|
|
6068
|
+
},
|
|
6069
|
+
{
|
|
6070
|
+
"class": "named_surface",
|
|
6071
|
+
"path": "docs/qa-and-test-orders.md",
|
|
6072
|
+
"surface_entry": "docs/qa-and-test-orders.md",
|
|
6073
|
+
"summary": "Describe accepting a readability warning: one colour pair and size class per page and width, what orphans or lapses the accept, and that it never hides review, unexercised or excluded results."
|
|
6074
|
+
},
|
|
6075
|
+
{
|
|
6076
|
+
"class": "named_surface",
|
|
6077
|
+
"path": "docs/brand-theme-bridge.md",
|
|
6078
|
+
"surface_entry": "docs/brand-theme-bridge.md",
|
|
6079
|
+
"summary": "State that theme contrast uses the same unrounded measurement as Polish and QA, so a declared colour at 4.495:1 now warns, and that the generator's colour choices are unchanged."
|
|
6080
|
+
}
|
|
6081
|
+
],
|
|
6082
|
+
"entry_sha256": "b75e489a53ea7b60a3a9b3037f6f17c96b13c2960a1cbd34eb7a3cc69b54f617"
|
|
6083
|
+
},
|
|
6084
|
+
{
|
|
6085
|
+
"id": "RL-0235",
|
|
6086
|
+
"sequence": 227,
|
|
6087
|
+
"date": "2026-10-05",
|
|
6088
|
+
"kind": "release",
|
|
6089
|
+
"surface_version": null,
|
|
6090
|
+
"changelog_section": "1.53.0+agent.2",
|
|
6091
|
+
"changelog_sha256": "a7fc7d90ee83e6ad44d310d77942e00de56656259e9c754eec14cd5bd8d124d4",
|
|
6092
|
+
"agent_impact": "next prints a campaign intent summary, generated from the normalized Campaign Build Brief, on every result (intent_summary in JSON, a Campaign intent section in text) and at the top of the setup, build, Polish and QA prompts. Each value carries its origin (stated, from the source, default, not stated, or source not recorded); values are quoted data, purpose and palette source inferred from page types or names read not stated, and nothing reads the summary, so it never sets prices or commerce behaviour. The four agent context files and the setup, build, Polish and QA skills tell agents to read .campaign-runtime/input/campaign-build-brief.normalized.json and the recorded assembly decisions. Bundled skills carry revision 1.53.0+skills.2: an agent that loaded an earlier revision should start a fresh session. The lifecycle skill returns the single compact brief in references/session-intake.md (Intent: is now Work:, with a new Campaign: field and Proof policy:) and saves brief answers with record brief after asking the operator; the build skill passes --deviation-reason only on the operator's explicit decision, the Polish skill records a skipped Polish only on the operator's decision, and the Polish and QA skills report readability warnings and offer repairs inside the brand palette. tooling setup refuses an installed agent context from an earlier release and names install-agent-context --target . in its refusal.",
|
|
6093
|
+
"compatibility": "breaking",
|
|
6094
|
+
"migration": "From each existing campaign folder: install the exact 1.53.0 package, run npx --no-install campaigns-os install-agent-context --target . (it overwrites all four files under .campaign-runtime/agent-context/; local edits there are lost), review and commit the diff, rerun npx --no-install campaigns-os tooling setup --target . --platform claude, and restart the agent session. Codex, Cursor and Copilot users run install-agent-context and reinstall skills with install-skills --platform codex (or agents).",
|
|
6095
|
+
"changes": [
|
|
6096
|
+
{
|
|
6097
|
+
"class": "documentation",
|
|
6098
|
+
"path": "agents/claude/CLAUDE.md",
|
|
6099
|
+
"surface_entry": "agents/claude/CLAUDE.md",
|
|
6100
|
+
"summary": "Add the generic campaign paragraph: what a NEXT campaign is, who owns creative intent and commerce behaviour, read the normalized brief and the recorded decisions before changing a campaign, treat the intent summary as orientation only, and ask the operator before saving brief answers."
|
|
6101
|
+
},
|
|
6102
|
+
{
|
|
6103
|
+
"class": "documentation",
|
|
6104
|
+
"path": "agents/codex/AGENTS.md",
|
|
6105
|
+
"surface_entry": "agents/codex/AGENTS.md",
|
|
6106
|
+
"summary": "Add the generic campaign paragraph: what a NEXT campaign is, who owns creative intent and commerce behaviour, read the normalized brief and the recorded decisions before changing a campaign, treat the intent summary as orientation only, and ask the operator before saving brief answers."
|
|
6107
|
+
},
|
|
6108
|
+
{
|
|
6109
|
+
"class": "documentation",
|
|
6110
|
+
"path": "agents/copilot/copilot-instructions.md",
|
|
6111
|
+
"surface_entry": "agents/copilot/copilot-instructions.md",
|
|
6112
|
+
"summary": "Add the generic campaign paragraph: what a NEXT campaign is, who owns creative intent and commerce behaviour, read the normalized brief and the recorded decisions before changing a campaign, treat the intent summary as orientation only, and ask the operator before saving brief answers."
|
|
6113
|
+
},
|
|
6114
|
+
{
|
|
6115
|
+
"class": "documentation",
|
|
6116
|
+
"path": "agents/cursor/campaigns-os.mdc",
|
|
6117
|
+
"surface_entry": "agents/cursor/campaigns-os.mdc",
|
|
6118
|
+
"summary": "Add the generic campaign paragraph: what a NEXT campaign is, who owns creative intent and commerce behaviour, read the normalized brief and the recorded decisions before changing a campaign, treat the intent summary as orientation only, and ask the operator before saving brief answers."
|
|
6119
|
+
},
|
|
6120
|
+
{
|
|
6121
|
+
"class": "named_surface",
|
|
6122
|
+
"path": "docs/skills-revision.md",
|
|
6123
|
+
"surface_entry": "docs/skills-revision.md",
|
|
6124
|
+
"summary": "Use the current 1.53.0+skills.2 bundle in executable examples."
|
|
6125
|
+
},
|
|
6126
|
+
{
|
|
6127
|
+
"class": "skill",
|
|
6128
|
+
"path": "skills.json",
|
|
6129
|
+
"surface_entry": "skills.json",
|
|
6130
|
+
"summary": "Advance the bundled skill revision to 1.53.0+skills.2 and each skill version one patch."
|
|
6131
|
+
},
|
|
6132
|
+
{
|
|
6133
|
+
"class": "skill",
|
|
6134
|
+
"path": "skills/campaign-lifecycle-orientation/SKILL.md",
|
|
6135
|
+
"surface_entry": null,
|
|
6136
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision."
|
|
6137
|
+
},
|
|
6138
|
+
{
|
|
6139
|
+
"class": "skill",
|
|
6140
|
+
"path": "skills/campaign-readback-classification/SKILL.md",
|
|
6141
|
+
"surface_entry": null,
|
|
6142
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision."
|
|
6143
|
+
},
|
|
6144
|
+
{
|
|
6145
|
+
"class": "skill",
|
|
6146
|
+
"path": "skills/campaign-run-evidence/SKILL.md",
|
|
6147
|
+
"surface_entry": null,
|
|
6148
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision."
|
|
6149
|
+
},
|
|
6150
|
+
{
|
|
6151
|
+
"class": "skill",
|
|
6152
|
+
"path": "skills/contribution-intake/SKILL.md",
|
|
6153
|
+
"surface_entry": null,
|
|
6154
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision."
|
|
6155
|
+
},
|
|
6156
|
+
{
|
|
6157
|
+
"class": "skill",
|
|
6158
|
+
"path": "skills/next-campaigns-build/SKILL.md",
|
|
6159
|
+
"surface_entry": null,
|
|
6160
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision; read the normalized brief and the recorded decisions; rebuild after an input change and pass --deviation-reason to record build only on the operator's explicit decision, quoting their reason."
|
|
6161
|
+
},
|
|
6162
|
+
{
|
|
6163
|
+
"class": "skill",
|
|
6164
|
+
"path": "skills/next-campaigns-os-setup/SKILL.md",
|
|
6165
|
+
"surface_entry": null,
|
|
6166
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision; read the normalized brief and the recorded decisions."
|
|
6167
|
+
},
|
|
6168
|
+
{
|
|
6169
|
+
"class": "skill",
|
|
6170
|
+
"path": "skills/next-campaigns-os/SKILL.md",
|
|
6171
|
+
"surface_entry": null,
|
|
6172
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision; return the compact brief defined in references/session-intake.md instead of a second copy, rename the Intent and Proof depth fields to Work and Proof policy, save brief answers with record brief after asking the operator, and declare a detour with --deviation-reason only when the operator has decided on it in the conversation, quoting their reason, including on record build after an input change."
|
|
6173
|
+
},
|
|
6174
|
+
{
|
|
6175
|
+
"class": "skill",
|
|
6176
|
+
"path": "skills/next-campaigns-os/references/session-intake.md",
|
|
6177
|
+
"surface_entry": null,
|
|
6178
|
+
"summary": "The single compact brief: Intent becomes Work, a Campaign field takes the Campaign intent lines from next, Missing inputs covers only choices that affect this revision, and brief answers are saved with record brief after asking the operator."
|
|
6179
|
+
},
|
|
6180
|
+
{
|
|
6181
|
+
"class": "skill",
|
|
6182
|
+
"path": "skills/next-campaigns-polish/SKILL.md",
|
|
6183
|
+
"surface_entry": null,
|
|
6184
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision; read the normalized brief and the recorded decisions; record a skipped Polish only on the operator's decision, quoting their reason as skip_reason; report readability warnings and offer repairs inside the brand palette, accepting one only with the operator's refs, reason and name."
|
|
6185
|
+
},
|
|
6186
|
+
{
|
|
6187
|
+
"class": "skill",
|
|
6188
|
+
"path": "skills/next-campaigns-qa/SKILL.md",
|
|
6189
|
+
"surface_entry": null,
|
|
6190
|
+
"summary": "Publish the 1.53.0+skills.2 bundle revision; read the normalized brief and the recorded decisions; report readability warnings and offer repairs inside the brand palette, accepting one only with the operator's refs, reason and name."
|
|
6191
|
+
},
|
|
6192
|
+
{
|
|
6193
|
+
"class": "cli_surface",
|
|
6194
|
+
"path": "src/cli.mjs",
|
|
6195
|
+
"surface_entry": "next",
|
|
6196
|
+
"summary": "next carries intent_summary on every result and prints a Campaign intent section under the status; the setup, build, Polish and QA prompts start with the summary and the absolute normalized brief path, and the build prompt names record brief and record spec for refreshing a changed brief or CampaignSpec."
|
|
6197
|
+
}
|
|
6198
|
+
],
|
|
6199
|
+
"entry_sha256": "197929e76610b701b015cac7ee37f1f8a75b18e350a8268b679b8ca51a9b7f14"
|
|
5873
6200
|
}
|
|
5874
6201
|
]
|
|
5875
6202
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "The downstream contract manifest. Everything listed here is SUPPORTED SURFACE: consumers (campaigns-agent, campaign-builder, the private ops repo, page-kit campaign repos) may depend on it, and changing it is a deliberate act — hashed entries require a surface_version bump in the same change (check-supported-surface.mjs --base, mirroring the skills.json bump gate), named entries must keep existing at their path, cli_commands must keep resolving in the CLI dispatch, package_exports must stay exported, and every entry must ship in the npm pack (files[] coverage). Anything NOT listed here — src/** internals, scripts/** checkers, examples/**, prompts/**, contracts/** other than this file and the entries named[] below (the orientation contract, the release ledger, and the consumer-facing orientation fixtures) — is implementation: consumers may read it for context but must not build on it, and it can change without notice. Rationale and the compatibility promise: docs/supported-surface.md.",
|
|
3
|
-
"surface_version": "1.
|
|
3
|
+
"surface_version": "1.53.0",
|
|
4
4
|
"package_exports": [
|
|
5
5
|
"./commercial-journey",
|
|
6
6
|
"./commercial-parity",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"sha256": "dfc9abed38d456969e47a21f606d308a03bdf036f3466f7d6e47a602747dacf4"
|
|
121
121
|
},
|
|
122
122
|
"contracts/effects.v1.json": {
|
|
123
|
-
"sha256": "
|
|
123
|
+
"sha256": "8282f7ffe91aaf12c4b79e4431b5ddc35cce82e42f1746d4a0ea44f54bd7fb8e"
|
|
124
124
|
},
|
|
125
125
|
"schemas/campaigns-os-effects.v1.schema.json": {
|
|
126
126
|
"sha256": "3eadd22169ab98bc7c2f682af2751267605170581182158d96be035b0cfe44dc"
|
|
@@ -94,6 +94,8 @@ used and reported with `theme.foreground.low_contrast`. With no declared CTA
|
|
|
94
94
|
foreground, the output is unchanged. Declarations inside CSS comments are not
|
|
95
95
|
read, so a commented-out token or rule never supplies a CTA or body text colour.
|
|
96
96
|
|
|
97
|
+
Contrast is computed with the same unrounded measurement Polish and QA use, so a declared colour at 4.495:1 now warns. The generator's colour choices are unchanged. Polish measures the rendered text at its real size and weight: a qualifying large label at 3:1 passes there, and smaller text produces a warning the operator can accept.
|
|
98
|
+
|
|
97
99
|
### Body text prefers the darkest declared text token
|
|
98
100
|
|
|
99
101
|
A declared text token is a `:root` custom property in the selected source whose
|
package/docs/build-packet.md
CHANGED
|
@@ -48,8 +48,10 @@ report writes, polish capture, progress, run closeout and QA compare that local
|
|
|
48
48
|
identity. Material spec hashes still bind the current revision; a changed ID or
|
|
49
49
|
content cannot reuse earlier proof. After a material revision, doctor and
|
|
50
50
|
`next` warn `spec.material_stale` (the spec no longer has the material hash
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
the Assembly Report binds, which QA refuses), and `next` routes to the build
|
|
52
|
+
and names the refresh: run `campaigns-os record spec --packet <packet>` to bind
|
|
53
|
+
the new content and keep stage history (see
|
|
54
|
+
[Refreshing after a CampaignSpec change](#refreshing-after-a-campaignspec-change)). Keep the spec, source, dependency
|
|
53
55
|
pins and canonical sidecars in Git. Use `readback` and `next` after a fresh
|
|
54
56
|
checkout; identity survives the move, but proof freshness is assessed again.
|
|
55
57
|
|
|
@@ -523,16 +525,13 @@ writing it would declare an analytics contract QA then blocks on. A derived
|
|
|
523
525
|
field the entry does not carry at all is listed under `not_in_target[]` and
|
|
524
526
|
left as it is.
|
|
525
527
|
|
|
526
|
-
|
|
528
|
+
`spec derive` writes the spec alone and no longer rebinds identity: the
|
|
527
529
|
Build Context's `spec.hash` / `spec.material_hash` and the Assembly Report's
|
|
528
|
-
`identity.spec_hash` / `identity.spec_material_hash`
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
is what keeps a derive-then-QA run conformant. A sidecar already carrying
|
|
534
|
-
another identity is left alone with a `spec.derive.identity_not_rebound`
|
|
535
|
-
warning naming `prepare-build`. A derived route change also warns
|
|
530
|
+
`identity.spec_hash` / `identity.spec_material_hash` keep the spec they were
|
|
531
|
+
bound to, so every build, Polish and QA record made against the earlier
|
|
532
|
+
content reads owed again. Run `record spec` after it (the result's `next`
|
|
533
|
+
names it) to bind the derived spec; QA's verdict and `bundle check` correlate
|
|
534
|
+
against the bound material hash. A derived route change also warns
|
|
536
535
|
`spec.derive.projection_stale`: the packet's page-kit projection
|
|
537
536
|
(`source_html.pages[].page_kit`) and the Build Context page map were prepared
|
|
538
537
|
from the old routes, and `prepare-build` (or `start`) regenerates them. A
|
|
@@ -552,8 +551,8 @@ the spec resolves to, which must lie inside the spec's own directory or the
|
|
|
552
551
|
target repo (`spec.derive.spec_escapes_boundary` otherwise, so a symlinked
|
|
553
552
|
`spec.local_path` cannot redirect the write); the retained doctor sidecar is
|
|
554
553
|
marked stale after a write, and a terminal build gets a
|
|
555
|
-
`spec.derive.build_stale` warning naming
|
|
556
|
-
|
|
554
|
+
`spec.derive.build_stale` warning naming `record spec`, after which `next`
|
|
555
|
+
routes back to the build. `--dry-run` prints the
|
|
557
556
|
same diff and writes nothing; unknown flags and a valued `--dry-run` are
|
|
558
557
|
rejected. Exit 2 with `spec.derive.*` error codes and nothing written when the
|
|
559
558
|
packet cannot be read, `spec.local_path` is absent or not a file, the spec is
|
|
@@ -1058,8 +1057,13 @@ full.
|
|
|
1058
1057
|
and auto-discover `campaign-build-brief.yaml`, `.yml`, or `.json` from the
|
|
1059
1058
|
source root or target repo. When none is present, Campaigns OS creates a guided
|
|
1060
1059
|
draft at `.campaign-runtime/input/campaign-build-brief.normalized.json`.
|
|
1061
|
-
|
|
1062
|
-
prepared
|
|
1060
|
+
A brief file is guided unless it sets `"brief_mode": "prepared"` (a campaign
|
|
1061
|
+
whose Assembly Report already records a prepared brief stays prepared). Save
|
|
1062
|
+
answers later with `record brief`, which keeps stage evidence unless the brief's
|
|
1063
|
+
material content changes; a presentation change makes build, Polish and QA
|
|
1064
|
+
owed again, and a `qa_policy` change makes QA alone owed again. See
|
|
1065
|
+
[Campaign Build Brief](./campaign-build-brief.md) for the schema, the mode
|
|
1066
|
+
rule and the stage map.
|
|
1063
1067
|
|
|
1064
1068
|
`start` / `prepare-build` also prepares the normalized Design Source Package at
|
|
1065
1069
|
`.campaign-runtime/input/design-source-package.json`. When that path is absent,
|
|
@@ -1681,6 +1685,43 @@ records it (`campaigns-os record setup|build|polish`; deploy and QA record their
|
|
|
1681
1685
|
own stages) → calls `next` again → repeat until stage="done"
|
|
1682
1686
|
```
|
|
1683
1687
|
|
|
1688
|
+
### Refreshing after a CampaignSpec change
|
|
1689
|
+
|
|
1690
|
+
When the CampaignSpec's material content changes, every build, Polish and QA record made against the earlier content stops counting as current, in local-spec, saved-Map and gateway packets alike. For a saved Map or gateway packet, Campaigns OS compares the copy intake fetched; it does not check whether that copy is the latest remote revision, and reports the remote as unconfirmed. Doctor warns `spec.material_stale`, and `next`, progress, readback, the Assembly Report's own status and the QA gate show the stages that are owed again; `next` routes to the first one. Run `campaigns-os record spec --packet <packet>` to bind the new content: it updates the build context and report identity, re-reads the brief file last saved (by intake or `record brief`), keeps waivers, warning accepts, the applied theme and deploy settings, and moves each superseded stage record into that stage's `history`, which is never used as current proof. `spec derive` no longer rebinds identity; run `record spec` after it. A change to the set, order or routes of active pages still needs intake. Re-recording an unchanged build after a spec change keeps the build owed, because the change has not reached the pages, unless the operator records a reason with `--deviation-reason`; this holds even when `record spec` was not run, and that `record build` also marks Polish and QA owed again. Polish stays owed until a new `polish capture`, and QA must produce a new verdict against the current content. Polish measurements of byte-identical output keep their values, but the Polish stage is owed again. These checks are tamper evidence, not proof: a hand-written record that copies the current values, or a packet pointed at an older copy of the spec, is not detected.
|
|
1691
|
+
|
|
1692
|
+
The CampaignSpec's material content is the whole spec except `spec_identity`,
|
|
1693
|
+
`slug`, `map_id` and `saved_at`; a page `label` edit is material. A spec
|
|
1694
|
+
change affects the stages as follows:
|
|
1695
|
+
|
|
1696
|
+
| Stage | After a spec material change |
|
|
1697
|
+
|---|---|
|
|
1698
|
+
| `prepare_build` | unchanged (`record spec` refuses a page-scope change, which needs intake) |
|
|
1699
|
+
| `doctor` | recomputed on every read |
|
|
1700
|
+
| `setup` | kept |
|
|
1701
|
+
| `assembly` | owed: `required`, `required_by: "spec"`, `required_for: ["polish", "qa"]` |
|
|
1702
|
+
| `polish` | owed: `required`, `required_by: "spec"`, `required_for: ["qa"]` |
|
|
1703
|
+
| `deploy` | kept |
|
|
1704
|
+
| `qa` | owed: `required`, `required_by: "spec"`, `required_for: []` |
|
|
1705
|
+
|
|
1706
|
+
`record spec` refuses, writing nothing, in this order: `spec_unreadable` (the
|
|
1707
|
+
spec does not parse), `spec_identity_changed` (its map id or local spec id
|
|
1708
|
+
names another campaign than the packet or the report), `page_scope_changed`,
|
|
1709
|
+
then, for the brief file last saved (by intake or `record brief`), `brief_too_large`,
|
|
1710
|
+
`brief_source_is_package_artifact` and `brief_file_missing` (the recorded
|
|
1711
|
+
path is missing or is not a readable regular file: a directory, a pipe or
|
|
1712
|
+
socket, a symlink to nothing, or a file without read permission). When it must
|
|
1713
|
+
re-derive the brief, it also refuses `brief_inputs_unavailable` (the Build
|
|
1714
|
+
Context lacks an intake product re-deriving the brief needs). It reads
|
|
1715
|
+
`unchanged` and writes nothing when the bound material equals the spec and no
|
|
1716
|
+
stage's spec or brief stamp differs from the current content; a stage that
|
|
1717
|
+
does not record which content it was made against is named in a
|
|
1718
|
+
`binding_unknown` notice instead. Otherwise it refreshes, re-deriving the
|
|
1719
|
+
normalized brief from the brief file last saved, so an edit made to the
|
|
1720
|
+
normalized brief itself is replaced by what its source gives. A stage whose spec
|
|
1721
|
+
stamp already equals the new content (a build recorded after the edit) is not
|
|
1722
|
+
demoted. `record spec` does not write the Build Packet. `--dry-run` runs every
|
|
1723
|
+
check and writes nothing.
|
|
1724
|
+
|
|
1684
1725
|
### Recording stage completion
|
|
1685
1726
|
|
|
1686
1727
|
Setup, build and polish completion is recorded with one command each, never by
|
|
@@ -35,7 +35,7 @@ The Build Packet, Build Context, and Assembly Report all reference that normaliz
|
|
|
35
35
|
|
|
36
36
|
## Modes
|
|
37
37
|
|
|
38
|
-
Prepared mode is for veteran users. A complete brief should let the build proceed without business questions. If a
|
|
38
|
+
Prepared mode is for veteran users, and a brief file selects it with `"brief_mode": "prepared"` (see [Brief mode](#brief-mode)). A complete brief should let the build proceed without business questions. If a prepared brief is incomplete or contradictory, doctor blocks with `build_brief.*` errors.
|
|
39
39
|
|
|
40
40
|
Guided mode is for new or partial inputs. Campaigns OS drafts a brief from CampaignSpec, page mappings, template family, source assets, and available runtime hints. It records only high-impact unresolved questions as warnings so existing builds still run while the business uncertainty is visible.
|
|
41
41
|
|
|
@@ -56,27 +56,58 @@ The CLI avoids SDK/page-kit jargon in questions. The implementation can resolve
|
|
|
56
56
|
|
|
57
57
|
Question 5 is asked only when the CampaignSpec maps a surface that fills the template's promo placeholders: a `funnels[].promo_codes` roster, or a checkout page's enabled `exit_intent` or `promo_code_input`. It never asks for approval of the source design's own promo, proof or urgency copy, which is built as designed (see below). Without such a surface the guided draft sets `header_claim_source` and `timer_label` to `"none"`: the template's promo placeholders are removed.
|
|
58
58
|
|
|
59
|
-
##
|
|
59
|
+
## Saving Answers
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Save brief answers with `campaigns-os record brief --packet <packet>`. Copy the normalized draft to `campaign-build-brief.json` in the target repository, set the fields named in the open questions, and run `record brief`. You do not need to re-run `start` or `prepare-build`, and no stage evidence is cleared unless the saved answers change the brief's material content. `record brief` refuses a path that points at one of the files Campaigns OS writes itself, such as the normalized brief.
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
2. Set the fields that close each open question:
|
|
63
|
+
A brief is prepared, where every open question blocks, only when the file sets `"brief_mode": "prepared"`. A brief file without `brief_mode` is guided: questions you leave open remain warnings. One exception keeps existing campaigns as they were built: when the campaign's Assembly Report already records a prepared brief, a file without `brief_mode` stays prepared. Set `"brief_mode": "guided"` to make it guided.
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
|---|---|
|
|
68
|
-
| `page_design_authority` | `design_authority.<page_id>.source` for each page named in the question |
|
|
69
|
-
| `brand_palette_cta` | `brand.commerce_palette_source`, `brand.cta_style` |
|
|
70
|
-
| `variant_media_rules` | `media.sold_variants`, `media.allow_other_variant_colors` |
|
|
71
|
-
| `bundle_pricing_presentation` | `offer_presentation.bundle_cards.primary_price` |
|
|
72
|
-
| `promo_urgency_copy` | `promo_urgency.header_claim_source` (`campaign_offers` or `none`), `promo_urgency.timer_label` (the template timer's label, or `none`) |
|
|
73
|
-
| `payment_methods_trust` | `commerce_surfaces.payment_methods_allowed` |
|
|
74
|
-
| `canonical_display_names` | `canonical_display.product_name_source` |
|
|
75
|
-
| `regulated_claims` | one of `campaign_intent.compliance.approved_benefit_language`, `.forbidden_claims`, `.approved_claims`, `.copy_rules` |
|
|
65
|
+
Saving a brief whose content is unchanged keeps all stage evidence and statuses. Reformatting, reordering keys, writing a default value explicitly, or changing only `_meta` also keeps all stage evidence and statuses; the save may rewrite the brief files. When the presentation sections change (`campaign_intent`, `design_authority`, `brand`, `media`, `offer_presentation`, `promo_urgency`, `commerce_surfaces`, `canonical_display`, `template_residue_policy`, or any section you add), build, Polish and QA are owed again. When only `qa_policy` changes, QA alone is owed again. Setup and deploy records are kept. Each affected stage records when its inputs changed. Each replaced record is kept under the stage's `history`; the last five superseded records per stage are kept, and older ones are dropped. History is display only and is never used as current proof.
|
|
76
66
|
|
|
77
|
-
|
|
67
|
+
Recording build again over output that has not changed since the brief or CampaignSpec changed does not make the build current: `next` keeps asking for a build, because the change has not reached the pages. If the operator decides the change needs no change to the built pages, record build with `--deviation-reason "<the operator's reason>"`; the build is then recorded with a warning, and the reason is shown in `next` and the QC handoff. `--deviation-reason` is a general flag any caller can pass: Campaigns OS records the reason, but cannot tell whether the operator chose it. A CampaignSpec change that was never saved with `record spec` is recorded by the next `record build`, `record polish` or QA run, with the same effect; `record build` then also marks Polish and QA owed again. An edit to the brief file is not read until it is saved with `record brief`: until then the build reads the saved brief, and doctor warns `build_brief.input_unsaved`. The same applies after `prepare-build --force`, which now keeps stage history, archives the build, Polish and QA records it clears, and keeps the record that the inputs changed. Recording Polish again does not make it current until a new `polish capture` runs after the change. Recording Polish as skipped, with a skip reason, while it is owed is the operator's decision to skip it: the input change no longer makes Polish owed. The Polish gate still passes only a completed Polish, so `next` stays at Polish until one is recorded (see `docs/polish-evidence.md`).
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
A build, Polish or QA record that does not say which brief and CampaignSpec content it was made against counts as unconfirmed, not current. Records made by earlier releases are unconfirmed, so after upgrading, `next` routes back to build once; record build and Polish again and run QA again. These checks are tamper evidence, not proof: a record written by hand that copies the current values or removes the record of an input change, or a packet pointed at an older copy of the spec or brief, is not detected.
|
|
70
|
+
|
|
71
|
+
The fields that close each open question (doctor's `build_brief.guided_questions` warning names the open questions and their fields):
|
|
72
|
+
|
|
73
|
+
| Question | Fields |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `page_design_authority` | `design_authority.<page_id>.source` for each page named in the question |
|
|
76
|
+
| `brand_palette_cta` | `brand.commerce_palette_source`, `brand.cta_style` |
|
|
77
|
+
| `variant_media_rules` | `media.sold_variants`, `media.allow_other_variant_colors` |
|
|
78
|
+
| `bundle_pricing_presentation` | `offer_presentation.bundle_cards.primary_price` |
|
|
79
|
+
| `promo_urgency_copy` | `promo_urgency.header_claim_source` (`campaign_offers` or `none`), `promo_urgency.timer_label` (the template timer's label, or `none`) |
|
|
80
|
+
| `payment_methods_trust` | `commerce_surfaces.payment_methods_allowed` |
|
|
81
|
+
| `canonical_display_names` | `canonical_display.product_name_source` |
|
|
82
|
+
| `regulated_claims` | one of `campaign_intent.compliance.approved_benefit_language`, `.forbidden_claims`, `.approved_claims`, `.copy_rules` |
|
|
83
|
+
|
|
84
|
+
### Brief mode
|
|
85
|
+
|
|
86
|
+
The mode is decided in this order:
|
|
87
|
+
|
|
88
|
+
1. `"brief_mode": "prepared"` in the file: prepared.
|
|
89
|
+
2. `"brief_mode": "guided"` in the file: guided.
|
|
90
|
+
3. No `brief_mode`, and the campaign's Assembly Report on disk records a prepared brief: prepared.
|
|
91
|
+
4. No `brief_mode` otherwise, including the generated draft and every new hand-written file: guided.
|
|
92
|
+
5. Any other `brief_mode` value is the error `build_brief.brief_mode`, and the brief reads `invalid`.
|
|
93
|
+
|
|
94
|
+
The file's own `_meta` (including a copied draft's `_meta.mode`) is never read for the mode; the normalized brief records how the mode was decided in `_meta.mode_source` (`field`, `legacy_report` or `generated`). Input errors block in both modes. In guided mode, open questions and evaluation gates stay warnings.
|
|
95
|
+
|
|
96
|
+
### What a brief change makes owed
|
|
97
|
+
|
|
98
|
+
The brief's material content is the normalized brief without `_meta`, `status`, `questions`, `gates`, `confidence`, `schema_version`, `brief_mode` and `qa_policy.enforcement`, in two parts: `qa_policy`, and every other section (presentation).
|
|
99
|
+
|
|
100
|
+
| Stage | Presentation changed | `qa_policy` changed |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| `prepare_build` | brief blockers re-derived; other blockers kept | re-derived |
|
|
103
|
+
| `doctor` | recomputed on every read | recomputed on every read |
|
|
104
|
+
| `setup` | kept | kept |
|
|
105
|
+
| `assembly` | owed (`required`, `required_by: "brief"`) | kept |
|
|
106
|
+
| `polish` | owed (`required`, `required_by: "brief"`) | kept |
|
|
107
|
+
| `deploy` | kept | kept |
|
|
108
|
+
| `qa` | owed (`required`, `required_by: "brief"`) | owed |
|
|
109
|
+
|
|
110
|
+
Only completed records are made owed. A skipped stage stays skipped.
|
|
80
111
|
|
|
81
112
|
## Risky Defaults
|
|
82
113
|
|
package/docs/effects.md
CHANGED
|
@@ -127,6 +127,14 @@ itself carries QA's own read).
|
|
|
127
127
|
|
|
128
128
|
**Accepting a warning.** `campaigns-os checkpoint accept` records an operator's decision about a warning that a Campaigns OS check measured. It does not change readiness, does not remove the warning, does not change the status `next` reports, and cannot be used on review, unexercised, or excluded results. The warning must already be on record (in the doctor snapshot `next` writes, the Polish capture, or the full QA verdict) before it can be accepted. The accept is bound to the exact measured state and lapses when that state changes, or when its evidence is stale or cannot be reproduced. An optional expiry or review condition adds a second bound. Run it only with the operator's explicit decision, made after the warning was shown to them. A plausible name is not authorization. The command refuses placeholder and automation identities. Results are re-derived from the package's raw captures on every read, and a result whose capture is missing or does not match is listed as unexercised. These checks are tamper evidence, not proof of authorship: a hand-written record that copies every value and recomputes the checksum, or a hand-written result written together with a matching capture, is not detected.
|
|
129
129
|
|
|
130
|
+
### `record brief` and `record spec`
|
|
131
|
+
|
|
132
|
+
**Saving brief answers.** `campaigns-os record brief --packet <packet>` saves Campaign Build Brief answers without re-running `start` or `prepare-build`. It writes the normalized brief under `{target}/.campaign-runtime/input/`, the Build Packet, the build context, the Assembly Report and the doctor-sidecar stale stamp, and sends nothing. It refuses a path that points at one of the files Campaigns OS writes itself, such as the normalized brief. Saving a brief whose content is unchanged keeps all stage evidence and statuses. Reformatting, reordering keys, writing a default value explicitly, or changing only `_meta` also keeps all stage evidence and statuses; the save may rewrite the brief files. When the presentation sections change, build, Polish and QA are owed again. When only `qa_policy` changes, QA alone is owed again. Setup and deploy records are kept. Each replaced record is kept under the stage's `history`; the last five superseded records per stage are kept, and history is never used as current proof.
|
|
133
|
+
|
|
134
|
+
**Binding a CampaignSpec change.** `campaigns-os record spec --packet <packet>` binds the new CampaignSpec content: it updates the build context and report identity, re-reads the brief file last saved (by intake or `record brief`), keeps waivers, warning accepts, the applied theme and deploy settings, and moves each superseded stage record into that stage's `history`. It writes the build context, the Assembly Report, the normalized brief and the doctor-sidecar stale stamp; it does not write the Build Packet, and it sends nothing. `spec derive` no longer rebinds identity; run `record spec` after it. A change to the set, order or routes of active pages still needs intake.
|
|
135
|
+
|
|
136
|
+
Both rows are tier C, because a change makes recorded stages owed again, and each `--dry-run` form is tier none: it writes nothing and appends no lifecycle entry. A CampaignSpec change that was never saved with `record spec` is recorded by the next `record build`, `record polish` or QA run, with the same effect; `record build` then also marks Polish and QA owed again. An edit to the brief file is not read until it is saved with `record brief`: until then the build reads the saved brief, and doctor warns `build_brief.input_unsaved`. Intake now also refuses, without `--force`, to discard recorded waivers, warning accepts, stage history, an applied theme, or a recorded deploy target, preview URL, production URL, order-path depth or allowed-domains confirmation; with `--force`, it keeps stage history, archives the build, Polish and QA records it clears, and keeps the record that the inputs changed.
|
|
137
|
+
|
|
130
138
|
## How to read a row
|
|
131
139
|
|
|
132
140
|
```jsonc
|
package/docs/local-setup.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
For a new campaign, create an empty working folder and run this from it:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npm init -y && npm install --save-exact next-campaign-page-kit@0.2.0 && npm install --save-dev --save-exact @nextcommerce/campaigns-os@1.
|
|
6
|
+
npm init -y && npm install --save-exact next-campaign-page-kit@0.2.0 && npm install --save-dev --save-exact @nextcommerce/campaigns-os@1.53.0 && npx --no-install campaigns-os tooling setup --target . --platform claude
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
`npm init -y` gives the folder its own `package.json`. Without one, npm
|
|
@@ -26,7 +26,7 @@ Ledger schema id: `campaigns-os-release-ledger/v1`
|
|
|
26
26
|
Change policy version: `1.0.0`
|
|
27
27
|
Reason-code vocabulary version: `1.0.0`
|
|
28
28
|
Limits version: `1.0.0`
|
|
29
|
-
Supported surface at generation time: `1.
|
|
29
|
+
Supported surface at generation time: `1.53.0`
|
|
30
30
|
|
|
31
31
|
## Forward compatibility
|
|
32
32
|
|