mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
1064 lines
27 KiB
Python
1064 lines
27 KiB
Python
import unittest
|
|
|
|
from contract_audit import audit_contract_payload, parse_args
|
|
|
|
|
|
class ContractAuditTest(unittest.TestCase):
|
|
def test_parse_args_accepts_staged_flag(self) -> None:
|
|
args = parse_args(["--check", "--staged"])
|
|
self.assertTrue(args.check)
|
|
self.assertTrue(args.staged)
|
|
|
|
def test_audit_contract_payload_accepts_valid_contracts(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {
|
|
"lanes": [
|
|
{"id": "L6"},
|
|
]
|
|
}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "alerts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/alerts/specs/types.go`
|
|
2. `go.mod`
|
|
3. `go.sum`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertEqual(report["errors"], [])
|
|
self.assertEqual(report["summary"]["contract_count"], 1)
|
|
self.assertEqual(report["contracts"][0]["subsystem_id"], "alerts")
|
|
|
|
def test_audit_contract_payload_rejects_metadata_mismatch(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {
|
|
"lanes": [
|
|
{"id": "L6"},
|
|
]
|
|
}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "monitoring",
|
|
"lane": "L3",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/monitoring.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/alerts/specs/types.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
joined = "\n".join(report["errors"])
|
|
self.assertIn("contract metadata subsystem_id = 'monitoring', want 'alerts'", joined)
|
|
self.assertIn("contract metadata lane = 'L3', want 'L6'", joined)
|
|
self.assertIn(
|
|
"contract metadata contract_file = 'docs/release-control/v6/internal/subsystems/monitoring.md', want 'docs/release-control/v6/internal/subsystems/alerts.md'",
|
|
joined,
|
|
)
|
|
|
|
def test_audit_contract_payload_rejects_empty_required_list_section(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {
|
|
"lanes": [
|
|
{"id": "L6"},
|
|
]
|
|
}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "alerts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
No list here.
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/alerts.md section '## Canonical Files' must contain a numbered list",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_rejects_missing_canonical_file_reference(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "alerts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/alerts/specs/missing.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/alerts.md ## Canonical Files references missing path 'internal/alerts/specs/missing.go'",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_accepts_cross_repo_contract_paths(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "relay-runtime",
|
|
"lane": "L7",
|
|
"contract": "docs/release-control/v6/internal/subsystems/relay-runtime.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {
|
|
"scope": {
|
|
"active_repos": ["pulse", "pulse-mobile"],
|
|
},
|
|
"lanes": [{"id": "L7"}],
|
|
}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/relay-runtime.md": """# Relay Runtime Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "relay-runtime",
|
|
"lane": "L7",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/relay-runtime.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own relay runtime truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `pulse-mobile:src/relay/client.ts`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add mobile relay reconnect behavior through `pulse-mobile:src/relay/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. Ad hoc mobile relay reconnect state.
|
|
|
|
## Completion Obligations
|
|
|
|
1. Keep mobile relay runtime changes tied to tests.
|
|
|
|
## Current State
|
|
|
|
Cross-repo relay ownership is explicit.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertEqual(report["errors"], [])
|
|
|
|
def test_audit_contract_payload_rejects_missing_extension_point_reference(self) -> None:
|
|
registry_payload = {
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
}
|
|
]
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "alerts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/alerts/specs/types.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/missing/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/alerts.md ## Extension Points references missing path 'internal/alerts/specs/missing/'",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_requires_declared_cross_subsystem_dependencies(self) -> None:
|
|
registry_payload = {
|
|
"shared_ownerships": [],
|
|
"subsystems": [
|
|
{
|
|
"id": "monitoring",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/monitoring.md",
|
|
"owned_prefixes": ["internal/monitoring/"],
|
|
"owned_files": [],
|
|
},
|
|
{
|
|
"id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"owned_prefixes": ["internal/unifiedresources/"],
|
|
"owned_files": [],
|
|
},
|
|
]
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/monitoring.md": """# Monitoring Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "monitoring",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/monitoring.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own monitoring truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/monitoring/monitor.go`
|
|
2. `internal/unifiedresources/views.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add typed read access through `internal/unifiedresources/views.go`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc snapshot truth
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical monitoring still depends on unified read-state truth.
|
|
""",
|
|
"docs/release-control/v6/internal/subsystems/unified-resources.md": """# Unified Resources Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own unified resource truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/unifiedresources/views.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add view adapters through `internal/unifiedresources/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New parallel runtime registries
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical read state owns the live view layer.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/monitoring.md contract metadata dependency_subsystem_ids = [], want ['unified-resources']",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_rejects_stale_declared_dependencies(self) -> None:
|
|
registry_payload = {
|
|
"shared_ownerships": [],
|
|
"subsystems": [
|
|
{
|
|
"id": "alerts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"owned_prefixes": ["internal/alerts/"],
|
|
"owned_files": [],
|
|
},
|
|
{
|
|
"id": "monitoring",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/monitoring.md",
|
|
"owned_prefixes": ["internal/monitoring/"],
|
|
"owned_files": [],
|
|
},
|
|
]
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/alerts.md": """# Alerts Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "alerts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/alerts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": ["monitoring"]
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own alert truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/alerts/specs/types.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add new alert rule kinds in `internal/alerts/specs/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New ad hoc evaluator logic
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical alert identity is live runtime truth.
|
|
""",
|
|
"docs/release-control/v6/internal/subsystems/monitoring.md": """# Monitoring Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "monitoring",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/monitoring.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own monitoring truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/monitoring/monitor.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add pollers in `internal/monitoring/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New snapshot-only paths
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical monitoring truth is still being consolidated.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/alerts.md contract metadata dependency_subsystem_ids = ['monitoring'], want []",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_requires_shared_boundary_entries_from_registry(self) -> None:
|
|
registry_payload = {
|
|
"shared_ownerships": [
|
|
{
|
|
"path": "internal/api/resources.go",
|
|
"rationale": "shared api resource boundary",
|
|
"subsystems": ["api-contracts", "unified-resources"],
|
|
}
|
|
],
|
|
"subsystems": [
|
|
{
|
|
"id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"owned_prefixes": ["internal/api/"],
|
|
"owned_files": [],
|
|
},
|
|
{
|
|
"id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"owned_prefixes": ["internal/unifiedresources/"],
|
|
"owned_files": ["internal/api/resources.go"],
|
|
},
|
|
],
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md": """# API Contracts
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own API truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/api/resources.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. None.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource payload fields in `internal/api/resources.go`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New handler-local payload drift
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical API resource payloads are live.
|
|
""",
|
|
"docs/release-control/v6/internal/subsystems/unified-resources.md": """# Unified Resources Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own unified resource truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/unifiedresources/views.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. `internal/api/resources.go` shared with `api-contracts`: shared api resource boundary.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource adapters in `internal/unifiedresources/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New parallel runtime registries
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical read state owns the live view layer.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md section '## Shared Boundaries' paths = [], want ['internal/api/resources.go']",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_rejects_shared_boundary_without_partner_marker(self) -> None:
|
|
registry_payload = {
|
|
"shared_ownerships": [
|
|
{
|
|
"path": "internal/api/resources.go",
|
|
"rationale": "shared api resource boundary",
|
|
"subsystems": ["api-contracts", "unified-resources"],
|
|
}
|
|
],
|
|
"subsystems": [
|
|
{
|
|
"id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"owned_prefixes": ["internal/api/"],
|
|
"owned_files": [],
|
|
},
|
|
{
|
|
"id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"owned_prefixes": ["internal/unifiedresources/"],
|
|
"owned_files": ["internal/api/resources.go"],
|
|
},
|
|
],
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md": """# API Contracts
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own API truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/api/resources.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. `internal/api/resources.go` shared with unified-resources: shared api resource boundary.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource payload fields in `internal/api/resources.go`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New handler-local payload drift
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical API resource payloads are live.
|
|
""",
|
|
"docs/release-control/v6/internal/subsystems/unified-resources.md": """# Unified Resources Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own unified resource truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/unifiedresources/views.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. `internal/api/resources.go` shared with `api-contracts`: shared api resource boundary.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource adapters in `internal/unifiedresources/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New parallel runtime registries
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical read state owns the live view layer.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md shared boundary 'internal/api/resources.go' must mention partner subsystem 'unified-resources' in backticks",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
def test_audit_contract_payload_rejects_noncanonical_shared_boundary_text(self) -> None:
|
|
registry_payload = {
|
|
"shared_ownerships": [
|
|
{
|
|
"path": "internal/api/resources.go",
|
|
"rationale": "shared api resource boundary",
|
|
"subsystems": ["api-contracts", "unified-resources"],
|
|
}
|
|
],
|
|
"subsystems": [
|
|
{
|
|
"id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"owned_prefixes": ["internal/api/"],
|
|
"owned_files": [],
|
|
},
|
|
{
|
|
"id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"owned_prefixes": ["internal/unifiedresources/"],
|
|
"owned_files": ["internal/api/resources.go"],
|
|
},
|
|
],
|
|
}
|
|
status_payload = {"lanes": [{"id": "L6"}]}
|
|
contract_texts = {
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md": """# API Contracts
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "api-contracts",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/api-contracts.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own API truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/api/resources.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. `internal/api/resources.go` shared with `unified-resources`: shared API resource boundary.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource payload fields in `internal/api/resources.go`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New handler-local payload drift
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical API resource payloads are live.
|
|
""",
|
|
"docs/release-control/v6/internal/subsystems/unified-resources.md": """# Unified Resources Contract
|
|
|
|
## Contract Metadata
|
|
|
|
```json
|
|
{
|
|
"subsystem_id": "unified-resources",
|
|
"lane": "L6",
|
|
"contract_file": "docs/release-control/v6/internal/subsystems/unified-resources.md",
|
|
"status_file": "docs/release-control/v6/internal/status.json",
|
|
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
|
|
"dependency_subsystem_ids": []
|
|
}
|
|
```
|
|
|
|
## Purpose
|
|
|
|
Own unified resource truth.
|
|
|
|
## Canonical Files
|
|
|
|
1. `internal/unifiedresources/views.go`
|
|
|
|
## Shared Boundaries
|
|
|
|
1. `internal/api/resources.go` shared with `api-contracts`: shared api resource boundary.
|
|
|
|
## Extension Points
|
|
|
|
1. Add resource adapters in `internal/unifiedresources/`
|
|
|
|
## Forbidden Paths
|
|
|
|
1. New parallel runtime registries
|
|
|
|
## Completion Obligations
|
|
|
|
1. Update contract and tests together
|
|
|
|
## Current State
|
|
|
|
Canonical read state owns the live view layer.
|
|
""",
|
|
}
|
|
|
|
report = audit_contract_payload(
|
|
registry_payload=registry_payload,
|
|
status_payload=status_payload,
|
|
contract_texts=contract_texts,
|
|
)
|
|
|
|
self.assertIn(
|
|
"docs/release-control/v6/internal/subsystems/api-contracts.md section '## Shared Boundaries' items = ['`internal/api/resources.go` shared with `unified-resources`: shared API resource boundary.'], want ['`internal/api/resources.go` shared with `unified-resources`: shared api resource boundary.']",
|
|
"\n".join(report["errors"]),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|