Context
test/playwright/unit/ai/services/memory-core/SourceRegistryService.spec.mjs:152 asserts the tenant audit trail's action order as ['REGISTERED', 'PROVISIONED']. In CI this raced red twice within one job, then passed on a manual rerun of the same head (receipt: unit job 29872221667, attempt-1 88774761941 red with PROVISIONED before REGISTERED on both attempts; attempt 2 88777168494 green on the same PR head).
Amended 2026-07-22 per Euclid's intake (issuecomment-5040162854): needs-narrowing + needs-contract-alignment. His receipt + source read proves this is a production operator-audit ordering defect, not a test-only flake: #recordAudit() writes recorded_at = Date.now() plus a random UUID audit_id; listAuditForTenant() orders by (recorded_at, audit_id); registration and provisioning can land in the same millisecond, so the random UUID becomes the semantic tie-breaker; and communitySourceOperator.mjs --action audit returns that list directly — the order is an operator-facing audit contract. Making the assertion order-insensitive would hide the defect. The original body's order-insensitive option is removed.
The Problem
Audit append order has no durable monotonic sequence independent of wall-clock collisions and random ids. Two events in the same millisecond order by UUID chance, and the operator's audit JSON inherits it.
The Fix (intake-recommended shape)
Add an explicit durable sequence: audit_sequence INTEGER PRIMARY KEY AUTOINCREMENT on mc_source_registration_audit, retaining audit_id as UNIQUE NOT NULL. Migrate existing rows in the current (recorded_at, audit_id) order, then query by audit_sequence. An implicit rowid is insufficient: Memory Core maintenance can run SQLite VACUUM.
Contract Ledger
| Surface |
Required contract |
Edge / migration |
Docs |
Evidence |
mc_source_registration_audit |
append order has a durable monotonic audit_sequence independent of wall-clock collisions and random ids |
existing rows backfilled in prior (recorded_at, audit_id) order; historical same-ms causality cannot be reconstructed — preserve that prior order during migration |
schema migration note |
forced same-clock/reverse-id witness |
listAuditForTenant() |
returns lifecycle events in stored causal sequence |
never uses UUID or implicit SQLite rowid as durable authority (VACUUM can renumber rowids) |
method JSDoc |
REGISTERED → PROVISIONED |
operator --action audit JSON |
inherits the same sequence without client sorting |
no output-shape drift beyond corrected ordering |
existing operator docs |
focused operator spec or service seam |
Acceptance Criteria
Out of Scope
- Re-deriving historical same-ms causality (unrecoverable; migration preserves prior deterministic order)
- Audit content/payload changes beyond ordering
Related
ai/services/memory-core/SourceRegistryService.mjs (audit write path)
- PR #15661 (the PR whose CI it reddened — comment-only delta, proving the race)
- ADR 0036 (accepted via PR #15473; deterministic audited lifecycle preserves §2.3 — aligned-with, no amendment)
Origin Session ID: d8a51237-4fcc-4171-8071-a391da0be361
Retrieval Hint: "SourceRegistryService audit trail order flake REGISTERED PROVISIONED audit_sequence migration VACUUM"
Context
test/playwright/unit/ai/services/memory-core/SourceRegistryService.spec.mjs:152asserts the tenant audit trail's action order as['REGISTERED', 'PROVISIONED']. In CI this raced red twice within one job, then passed on a manual rerun of the same head (receipt: unit job29872221667, attempt-188774761941red withPROVISIONEDbeforeREGISTEREDon both attempts; attempt 288777168494green on the same PR head).Amended 2026-07-22 per Euclid's intake (issuecomment-5040162854): needs-narrowing + needs-contract-alignment. His receipt + source read proves this is a production operator-audit ordering defect, not a test-only flake:
#recordAudit()writesrecorded_at = Date.now()plus a random UUIDaudit_id;listAuditForTenant()orders by(recorded_at, audit_id); registration and provisioning can land in the same millisecond, so the random UUID becomes the semantic tie-breaker; andcommunitySourceOperator.mjs --action auditreturns that list directly — the order is an operator-facing audit contract. Making the assertion order-insensitive would hide the defect. The original body's order-insensitive option is removed.The Problem
Audit append order has no durable monotonic sequence independent of wall-clock collisions and random ids. Two events in the same millisecond order by UUID chance, and the operator's audit JSON inherits it.
The Fix (intake-recommended shape)
Add an explicit durable sequence:
audit_sequence INTEGER PRIMARY KEY AUTOINCREMENTonmc_source_registration_audit, retainingaudit_idasUNIQUE NOT NULL. Migrate existing rows in the current(recorded_at, audit_id)order, then query byaudit_sequence. An implicitrowidis insufficient: Memory Core maintenance can run SQLiteVACUUM.Contract Ledger
mc_source_registration_auditaudit_sequenceindependent of wall-clock collisions and random ids(recorded_at, audit_id)order; historical same-ms causality cannot be reconstructed — preserve that prior order during migrationlistAuditForTenant()rowidas durable authority (VACUUM can renumber rowids)REGISTERED → PROVISIONED--action auditJSONAcceptance Criteria
audit_sequence INTEGER PRIMARY KEY AUTOINCREMENTadded;audit_idremainsUNIQUE NOT NULL; existing rows migrated in prior(recorded_at, audit_id)orderDate.now()and forces reverse-sorting UUIDs so pre-fix code is deterministically red, then asserts both action order and increasing stored sequencelistAuditForTenant()and the operator--action auditJSON return the stored causal sequence with no client-side sortingOut of Scope
Related
ai/services/memory-core/SourceRegistryService.mjs(audit write path)Origin Session ID: d8a51237-4fcc-4171-8071-a391da0be361
Retrieval Hint: "SourceRegistryService audit trail order flake REGISTERED PROVISIONED audit_sequence migration VACUUM"