@nextcommerce/campaigns-os 1.43.1 → 1.46.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 +9 -2
- package/CHANGELOG.md +1099 -5103
- package/README.md +34 -13
- package/agents/claude/CLAUDE.md +1 -1
- package/agents/codex/AGENTS.md +1 -1
- package/agents/copilot/copilot-instructions.md +1 -1
- package/agents/cursor/campaigns-os.mdc +1 -1
- package/campaign-spec/dist/rules/analytics-contract-shape.d.ts +2 -2
- package/campaign-spec/dist/rules/analytics-contract-shape.js +2 -2
- package/campaign-spec/dist/rules/store-profile-shape.d.ts +5 -1
- package/campaign-spec/dist/rules/store-profile-shape.js +8 -10
- package/campaign-spec/dist/types.d.ts +2 -2
- package/contracts/agent-relevant-change-policy.v1.json +5 -0
- package/contracts/archive/CHANGELOG.2026-09-30.md +5111 -0
- package/contracts/archive/release-ledger.2026-09-30.json +5068 -0
- package/contracts/effects.v1.json +1184 -121
- package/contracts/orientation-reason-codes.v1.json +7 -0
- package/contracts/release-ledger.json +2190 -5260
- package/contracts/supported-surface.json +7 -4
- package/contracts/template-slot-manifest.shared-content-core.v0.json +403 -0
- package/docs/brand-theme-bridge.md +81 -0
- package/docs/build-packet.md +222 -23
- package/docs/campaigns-os-build-flow.md +4 -3
- package/docs/design-source-package.md +162 -15
- package/docs/effects.md +66 -12
- package/docs/gateway-login.md +3 -0
- package/docs/local-setup.md +1 -1
- package/docs/orientation-contract-reference.md +42 -2
- package/docs/polish-evidence.md +74 -0
- package/docs/progress-snapshots.md +10 -6
- package/docs/qa-and-test-orders.md +230 -20
- package/docs/release-ledger-authoring-guide.md +70 -8
- package/docs/runtime-readiness.md +1 -1
- package/docs/sdk-storage-compatibility.md +1 -1
- package/docs/skills-revision.md +10 -10
- package/docs/supported-surface.md +2 -2
- package/docs/versioning.md +4 -1
- package/package.json +1 -1
- package/schemas/campaigns-os-release-ledger.v1.schema.json +32 -2
- package/schemas/campaigns-os-tooling-orientation.v1.schema.json +1 -0
- package/skills/campaign-lifecycle-orientation/SKILL.md +16 -5
- package/skills/campaign-readback-classification/SKILL.md +3 -3
- package/skills/campaign-run-evidence/SKILL.md +7 -6
- package/skills/contribution-intake/SKILL.md +3 -3
- package/skills/next-campaigns-build/SKILL.md +7 -6
- package/skills/next-campaigns-os/SKILL.md +7 -7
- package/skills/next-campaigns-os/references/session-intake.md +9 -3
- package/skills/next-campaigns-os-setup/SKILL.md +5 -5
- package/skills/next-campaigns-polish/SKILL.md +28 -9
- package/skills/next-campaigns-qa/SKILL.md +7 -4
- package/skills.json +10 -10
- package/src/brand-theme.mjs +320 -20
- package/src/build-brief.mjs +6 -4
- package/src/built-script-syntax.mjs +480 -0
- package/src/built-site-scope.mjs +16 -4
- package/src/campaigns-api-key.mjs +99 -0
- package/src/cli-helpers.mjs +118 -0
- package/src/cli.mjs +1530 -7580
- package/src/commercial-parity.mjs +48 -2
- package/src/design-source-package.mjs +1 -1
- package/src/design-source-publication.mjs +898 -0
- package/src/deviation.mjs +13 -1
- package/src/diagnostic.mjs +6 -2
- package/src/directory-lock.mjs +270 -0
- package/src/doctor/checks.mjs +4654 -0
- package/src/doctor/inspect.mjs +678 -0
- package/src/doctor/next-step.mjs +731 -0
- package/src/doctor/source-provenance.mjs +184 -0
- package/src/install-invocation.mjs +29 -0
- package/src/invocation.mjs +183 -0
- package/src/live-campaign-refs.mjs +466 -0
- package/src/login.mjs +2 -2
- package/src/page-kit-store-profile.mjs +69 -12
- package/src/page-kit-sync.mjs +31 -12
- package/src/private-template-source.mjs +1 -1
- package/src/progress-node.mjs +9 -36
- package/src/proof-policy.mjs +1 -1
- package/src/qa-analytics-correctness.mjs +3 -0
- package/src/qa-binding-evidence.mjs +76 -11
- package/src/qa-browser.mjs +1316 -105
- package/src/qa-build-scope.mjs +47 -0
- package/src/qa-commercial-parity.mjs +48 -5
- package/src/qa-node.mjs +339 -19
- package/src/qa-test-order-topology.mjs +148 -0
- package/src/sdk-markup.mjs +72 -8
- package/src/source-html-intake.mjs +117 -1
- package/src/source-html-manifest.mjs +9 -2
- package/src/stage-ledger.mjs +28 -0
- package/src/stage-record.mjs +551 -0
- package/src/target-lock.mjs +54 -0
- package/src/template-brand-contract.mjs +17 -1
- package/src/upsell-selector-scope.mjs +112 -2
|
@@ -652,8 +652,8 @@ function recurrenceEquivalent(claim, truth) {
|
|
|
652
652
|
if (moneyToCents(claim.amount) !== moneyToCents(truth.amount)) return false;
|
|
653
653
|
if (claim.interval_count === truth.interval_count && claim.interval === truth.interval) return true;
|
|
654
654
|
|
|
655
|
-
//
|
|
656
|
-
// its API cadence is expressed as 30 days. Do not generalize rate math.
|
|
655
|
+
// One merchant's accepted monthly disclosure is the one narrow proven
|
|
656
|
+
// equivalence: its API cadence is expressed as 30 days. Do not generalize rate math.
|
|
657
657
|
return (claim.interval_count === 1 && claim.interval === "month"
|
|
658
658
|
&& truth.interval_count === 30 && truth.interval === "day")
|
|
659
659
|
|| (truth.interval_count === 1 && truth.interval === "month"
|
|
@@ -872,6 +872,52 @@ export function serializeCommercialFindings(findingsValue, options = {}) {
|
|
|
872
872
|
return { assertions, omittedFindingCount };
|
|
873
873
|
}
|
|
874
874
|
|
|
875
|
+
export const RECURRING_CLAIM_ABSENT_CODE = "commercial_parity.recurring_claim_absent";
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* A subscription package a page renders with no recurring claim extracted for
|
|
879
|
+
* it (#533). The diff above is silent when there is nothing to compare, which
|
|
880
|
+
* is exactly how a page whose rebill copy could not be read used to pass. This
|
|
881
|
+
* is incomplete evidence, not a mismatch: it names the package, never a price.
|
|
882
|
+
* `subscriptionRefsByPage` maps a page id to the refs the spec says recur;
|
|
883
|
+
* a capture carries the package refs its page renders as
|
|
884
|
+
* `rendered_package_refs`. A capture that failed extraction is skipped — that
|
|
885
|
+
* failure is already its own issue — and so is one with no page id: there is
|
|
886
|
+
* no page to hold its subscriptions against, and it is never keyed as "null".
|
|
887
|
+
*/
|
|
888
|
+
export function recurringClaimAbsences(capturesValue, subscriptionRefsByPage) {
|
|
889
|
+
const absences = [];
|
|
890
|
+
const seen = new Set();
|
|
891
|
+
partitionCaptures(capturesValue).valid.forEach((capture) => {
|
|
892
|
+
if (!present(capture.page_id)) return;
|
|
893
|
+
const pageId = String(capture.page_id);
|
|
894
|
+
const subscriptions = subscriptionRefsByPage?.get?.(pageId);
|
|
895
|
+
if (!subscriptions?.size) return;
|
|
896
|
+
const claimed = new Set(capture.recurrence_claims.map((claim) => String(claim.package_id)));
|
|
897
|
+
array(capture.rendered_package_refs).map(String).forEach((ref) => {
|
|
898
|
+
const key = `${pageId}\u0000${ref}`;
|
|
899
|
+
if (!subscriptions.has(ref) || claimed.has(ref) || seen.has(key)) return;
|
|
900
|
+
seen.add(key);
|
|
901
|
+
absences.push({ type: "recurring-claim-absent", page_id: pageId, ...(present(capture.url) ? { url: String(capture.url) } : {}), package_id: ref });
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
return absences;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
export function recurringClaimAbsentAssertions(absences, { maxAssertions = Number.POSITIVE_INFINITY } = {}) {
|
|
908
|
+
return array(absences).slice(0, Math.max(0, maxAssertions)).map((absence) => ({
|
|
909
|
+
id: `${RECURRING_CLAIM_ABSENT_CODE}:${component(absence.page_id)}:package-${component(absence.package_id)}`,
|
|
910
|
+
family: "pricing",
|
|
911
|
+
page: absence.page_id || "campaign",
|
|
912
|
+
...(absence.url ? { url: absence.url } : {}),
|
|
913
|
+
status: "warn",
|
|
914
|
+
severity: "warn",
|
|
915
|
+
expected: `a readable recurring (rebill) claim for subscription package ${absence.package_id}`,
|
|
916
|
+
actual: `no recurring claim extracted for package ${absence.package_id}`,
|
|
917
|
+
evidence: { type: absence.type, code: RECURRING_CLAIM_ABSENT_CODE, package_id: absence.package_id },
|
|
918
|
+
}));
|
|
919
|
+
}
|
|
920
|
+
|
|
875
921
|
/**
|
|
876
922
|
* Build the runner-facing commercial evidence section and flat QA assertions.
|
|
877
923
|
* `countsOnly` retains matched array lengths without walking claim elements.
|
|
@@ -612,7 +612,7 @@ export function synthesizeHtmlFunnelDesignSourcePackage({
|
|
|
612
612
|
kind: "coverage_absence",
|
|
613
613
|
scope: "primary_design_coverage",
|
|
614
614
|
applies_to: [surface.id],
|
|
615
|
-
reason: `Page surface "${surface.id}" is template stock from the ${template.family} family: it has no design source of its own
|
|
615
|
+
reason: `Page surface "${surface.id}" is template stock from the ${template.family} family: it has no design source of its own; keep it unbuilt unless the operator opts in to materialising that family's stock page.`,
|
|
616
616
|
status: "accepted",
|
|
617
617
|
attributed_by: "prepare-build",
|
|
618
618
|
attributed_at: null,
|