Problem
The `defineContract` invariants defined in all four contract files are pure declarative objects — they are not imported or called by any runtime route handler or service layer. This means:
- `AgendaItemContract.invariants` (e.g. `resolved_has_timestamp`) — not enforced at write time
- `CCTaskContract.invariants` (e.g. `proposed_task_needs_approval`, `completed_has_timestamp`) — not enforced at write time
- `GoalContract.invariants` (e.g. `completed_has_timestamp`) — not enforced at write time
- `MemoryEntryContract.invariants` (e.g. `refuted_entry_not_canonical`, `high_confidence_for_canonical`) — not enforced at write time
Contracts currently serve as governance/specification artifacts only. Tests exist to verify the invariant `check()` functions themselves (added in OTDD sweep on `auto/feature/issue-72`), but production operations can violate them without any error.
Note: `executor-router.contract.ts` invariants (I1–I6) are structural validators called explicitly by tests — they are in a better state, but still not called automatically at route dispatch time.
Proposed solution
Add a thin service-layer guard that runs all applicable invariant `check()` functions before committing D1 writes. Options:
Option A — Inline at each route handler: Call `Contract.invariants.filter(i => i.appliesTo.includes(op)).forEach(i => { const r = i.check(entity); if (r !== true) throw new Error(r); })` before each D1 mutation.
Option B — Generic `enforceInvariants(contract, operation, entity)` helper: A single reusable function that accepts a contract, the operation name, and the entity object; iterates `appliesTo` filtering; throws a structured error on violation. Route handlers call this once per mutation.
Option C — Middleware/hook layer: If routes consistently go through a service object, enforce at that boundary rather than in individual route handlers.
Option B is recommended — minimal abstraction, easy to test, applies uniformly across all `defineContract` domains.
Acceptance criteria
Context
Discovered during OTDD sweep (aegis-oss branch `auto/feature/issue-72`). The `resolveAgendaItem` terminal-state guard was already fixed in that branch as a direct implementation bug. This issue tracks the broader systematic gap.
Problem
The `defineContract` invariants defined in all four contract files are pure declarative objects — they are not imported or called by any runtime route handler or service layer. This means:
Contracts currently serve as governance/specification artifacts only. Tests exist to verify the invariant `check()` functions themselves (added in OTDD sweep on `auto/feature/issue-72`), but production operations can violate them without any error.
Note: `executor-router.contract.ts` invariants (I1–I6) are structural validators called explicitly by tests — they are in a better state, but still not called automatically at route dispatch time.
Proposed solution
Add a thin service-layer guard that runs all applicable invariant `check()` functions before committing D1 writes. Options:
Option A — Inline at each route handler: Call `Contract.invariants.filter(i => i.appliesTo.includes(op)).forEach(i => { const r = i.check(entity); if (r !== true) throw new Error(r); })` before each D1 mutation.
Option B — Generic `enforceInvariants(contract, operation, entity)` helper: A single reusable function that accepts a contract, the operation name, and the entity object; iterates `appliesTo` filtering; throws a structured error on violation. Route handlers call this once per mutation.
Option C — Middleware/hook layer: If routes consistently go through a service object, enforce at that boundary rather than in individual route handlers.
Option B is recommended — minimal abstraction, easy to test, applies uniformly across all `defineContract` domains.
Acceptance criteria
Context
Discovered during OTDD sweep (aegis-oss branch `auto/feature/issue-72`). The `resolveAgendaItem` terminal-state guard was already fixed in that branch as a direct implementation bug. This issue tracks the broader systematic gap.