From 72fe17a5d9fe68ae47884ed21281d6064c6e00eb Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 29 Apr 2026 23:40:32 +0100 Subject: [PATCH] Extend paid claim proof boundary --- docs/PULSE_PRO.md | 4 +++- .../canonical_completion_guard_test.py | 5 +++++ .../internal/paid_feature_claims_proof.py | 19 ++++++++++++++++++- .../paid_feature_claims_proof_test.py | 10 ++++++---- .../release_control/subsystem_lookup_test.py | 12 +++++++++--- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/docs/PULSE_PRO.md b/docs/PULSE_PRO.md index b964e381fe..6a995798a3 100644 --- a/docs/PULSE_PRO.md +++ b/docs/PULSE_PRO.md @@ -114,7 +114,9 @@ into first-class product surfaces: ## Paid Feature Proof Map Use this map before adding or changing public Pulse Pro/Relay copy. A feature is safe to sell only -when the claim has a runtime gate, presentation copy, and at least one regression proof. +when the claim has a runtime gate, presentation copy, and at least one regression proof. The +automated proof bundle also checks that ordinary self-hosted sessions stay free-first and do not +surface upgrade prompts unless the user deliberately enters a commercial path. | Claim | Runtime source | Regression proof | |---|---|---| diff --git a/scripts/release_control/canonical_completion_guard_test.py b/scripts/release_control/canonical_completion_guard_test.py index c48de50f3f..ea82bc30ea 100644 --- a/scripts/release_control/canonical_completion_guard_test.py +++ b/scripts/release_control/canonical_completion_guard_test.py @@ -976,6 +976,7 @@ class CanonicalCompletionGuardTest(unittest.TestCase): "exact_files": [ "frontend-modern/src/api/__tests__/agentProfiles.test.ts", "frontend-modern/src/components/Settings/__tests__/AgentProfilesPanel.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/agentProfilesPresentation.test.ts", ], } @@ -1904,6 +1905,7 @@ class CanonicalCompletionGuardTest(unittest.TestCase): "exact_files": [ "frontend-modern/src/api/__tests__/agentProfiles.test.ts", "frontend-modern/src/components/Settings/__tests__/AgentProfilesPanel.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/agentProfilesPresentation.test.ts", ], } @@ -1939,6 +1941,7 @@ class CanonicalCompletionGuardTest(unittest.TestCase): "exact_files": [ "frontend-modern/src/api/__tests__/agentProfiles.test.ts", "frontend-modern/src/components/Settings/__tests__/AgentProfilesPanel.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/agentProfilesPresentation.test.ts", ], } @@ -2510,6 +2513,7 @@ class CanonicalCompletionGuardTest(unittest.TestCase): "frontend-modern/src/components/Settings/__tests__/SecurityPostureSummary.test.tsx", "frontend-modern/src/components/Settings/__tests__/dataHandlingPanelModel.test.ts", "frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/stores/__tests__/systemSettings.test.ts", ], } @@ -2537,6 +2541,7 @@ class CanonicalCompletionGuardTest(unittest.TestCase): "exact_files": [ "frontend-modern/src/components/Settings/__tests__/APITokenManager.test.tsx", "frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", ], } ], diff --git a/scripts/release_control/internal/paid_feature_claims_proof.py b/scripts/release_control/internal/paid_feature_claims_proof.py index 2f907c1958..77f0a06907 100644 --- a/scripts/release_control/internal/paid_feature_claims_proof.py +++ b/scripts/release_control/internal/paid_feature_claims_proof.py @@ -278,6 +278,23 @@ def build_command_specs(args: argparse.Namespace) -> list[CommandSpec]: "src/components/Settings/__tests__/RelaySettingsPanel.runtime.test.tsx", ], ), + CommandSpec( + name="pulse-frontend-free-first-commercial-boundary", + cwd=str(frontend_dir), + command=[ + "npm", + "test", + "--", + "src/stores/__tests__/sessionPresentationPolicy.test.ts", + "src/__tests__/useAppRuntimeState.test.ts", + "src/features/patrol/__tests__/patrolCommercialBoundary.test.ts", + "src/pages/__tests__/AIIntelligence.test.tsx", + "src/components/Alerts/__tests__/InvestigateAlertButton.test.tsx", + "src/components/shared/__tests__/MonitoredSystemLimitWarningBanner.test.tsx", + "src/components/SetupWizard/__tests__/SetupCompletionPanel.guardrails.test.ts", + "src/pages/__tests__/PricingHandoff.test.tsx", + ], + ), CommandSpec( name="pulse-pro-public-pricing-and-checkout-contract", cwd=str(pulse_pro_license_server_dir), @@ -422,7 +439,7 @@ def render_markdown_report(title: str, results: list[CommandResult]) -> str: "", "## Scope", "", - "This proof checks that self-hosted paid claims map to concrete public copy, entitlement, API, UI, Pro admin-extra, license-server, and relay-server behavior.", + "This proof checks that self-hosted paid claims map to concrete public copy, entitlement, API, UI, Pro admin-extra, license-server, and relay-server behavior, while ordinary self-hosted sessions stay free-first and non-promotional.", "", "## Results", "", diff --git a/scripts/release_control/internal/paid_feature_claims_proof_test.py b/scripts/release_control/internal/paid_feature_claims_proof_test.py index c285a6fa2a..ec35471de1 100644 --- a/scripts/release_control/internal/paid_feature_claims_proof_test.py +++ b/scripts/release_control/internal/paid_feature_claims_proof_test.py @@ -164,18 +164,20 @@ class PaidFeatureClaimsProofTest(unittest.TestCase): ) specs = proof.build_command_specs(args) - self.assertEqual(len(specs), 8) + self.assertEqual(len(specs), 9) self.assertEqual(specs[0].cwd, str(pulse_dir.resolve())) self.assertEqual(specs[4].cwd, str(frontend_dir.resolve())) - self.assertEqual(specs[5].cwd, str(pulse_pro_license_server_dir.resolve())) - self.assertEqual(specs[6].cwd, str(pulse_pro_relay_server_dir.resolve())) - self.assertEqual(specs[7].cwd, str(pulse_enterprise_dir.resolve())) + self.assertEqual(specs[5].cwd, str(frontend_dir.resolve())) + self.assertEqual(specs[6].cwd, str(pulse_pro_license_server_dir.resolve())) + self.assertEqual(specs[7].cwd, str(pulse_pro_relay_server_dir.resolve())) + self.assertEqual(specs[8].cwd, str(pulse_enterprise_dir.resolve())) names = {spec.name for spec in specs} self.assertIn("pulse-licensing-paid-feature-contract", names) self.assertIn("pulse-api-history-entitlement-enforcement", names) self.assertIn("pulse-pro-admin-extras-api-contract", names) self.assertIn("pulse-pro-admin-extras-core-packages", names) self.assertIn("pulse-frontend-paid-claim-contract", names) + self.assertIn("pulse-frontend-free-first-commercial-boundary", names) self.assertIn("pulse-pro-public-pricing-and-checkout-contract", names) self.assertIn("pulse-pro-relay-entitlement-runtime", names) self.assertIn("pulse-enterprise-pro-admin-extras-runtime", names) diff --git a/scripts/release_control/subsystem_lookup_test.py b/scripts/release_control/subsystem_lookup_test.py index e6fae2d200..48552cabda 100644 --- a/scripts/release_control/subsystem_lookup_test.py +++ b/scripts/release_control/subsystem_lookup_test.py @@ -1271,6 +1271,7 @@ class SubsystemLookupTest(unittest.TestCase): [ "frontend-modern/src/components/Settings/__tests__/APITokenManager.test.tsx", "frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", ], ) security_match = next( @@ -1629,6 +1630,7 @@ class SubsystemLookupTest(unittest.TestCase): [ "frontend-modern/src/api/__tests__/agentProfiles.test.ts", "frontend-modern/src/components/Settings/__tests__/AgentProfilesPanel.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/agentProfilesPresentation.test.ts", ], ) @@ -1661,6 +1663,7 @@ class SubsystemLookupTest(unittest.TestCase): [ "frontend-modern/src/api/__tests__/agentProfiles.test.ts", "frontend-modern/src/components/Settings/__tests__/AgentProfilesPanel.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/agentProfilesPresentation.test.ts", ], ) @@ -3146,6 +3149,7 @@ class SubsystemLookupTest(unittest.TestCase): "frontend-modern/src/components/Settings/__tests__/OrganizationOverviewPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/OrganizationSharingPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/RBACPaywallPanels.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts", "frontend-modern/src/utils/__tests__/orgUtils.test.ts", "frontend-modern/src/utils/__tests__/organizationRolePresentation.test.ts", @@ -3346,6 +3350,7 @@ class SubsystemLookupTest(unittest.TestCase): "frontend-modern/src/components/Settings/__tests__/OrganizationOverviewPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/OrganizationSharingPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/RBACPaywallPanels.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts", "frontend-modern/src/utils/__tests__/orgUtils.test.ts", "frontend-modern/src/utils/__tests__/organizationRolePresentation.test.ts", @@ -3384,6 +3389,7 @@ class SubsystemLookupTest(unittest.TestCase): "frontend-modern/src/components/Settings/__tests__/OrganizationOverviewPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/OrganizationSharingPanel.test.tsx", "frontend-modern/src/components/Settings/__tests__/RBACPaywallPanels.test.tsx", + "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts", "frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts", "frontend-modern/src/utils/__tests__/orgUtils.test.ts", "frontend-modern/src/utils/__tests__/organizationRolePresentation.test.ts", @@ -3535,7 +3541,7 @@ class SubsystemLookupTest(unittest.TestCase): { "heading": "## Extension Points", "path": "frontend-modern/src/api/orgs.ts", - "line": 74, + "line": 79, "heading_line": 70, }, ], @@ -3572,7 +3578,7 @@ class SubsystemLookupTest(unittest.TestCase): { "heading": "## Shared Boundaries", "path": "internal/api/access_control_handlers.go", - "line": 127, + "line": 131, "heading_line": 88, } ], @@ -3611,7 +3617,7 @@ class SubsystemLookupTest(unittest.TestCase): { "heading": "## Extension Points", "path": "internal/api/access_control_handlers.go", - "line": 76, + "line": 81, "heading_line": 70, }, ],