Version. 0.2 Date. 2026-07-27 Change from v0.1. CR number corrected from provisional CR-2026-146 to CR-2026-154, assigned from the record sequence (highest present: CR-2026-153). No other change. Status. Filing note. Two new candidates for the queued-directions-and-deferred-work document, to be absorbed at its next version bump (add-new-file discipline; this note does not amend the document in place). Source: graph-hygiene step-0 inspection report (2026-07-27) and drafting handoff §6 / D-5. Note on scope. The drafting handoff §6 commissioned the first candidate only. The second is carried because the inspection report explicitly requires it be "filed as a separate finding" (report B.10); the Operator may strike it.
What. add_relationship / _record_relationship (engagement/assertions.py:610–701) and add_relationship_route (api/routers/relations.py:49–71) perform no validation of any kind: no existence check on source or target, no engagement check, no state check. Any two MemoryRefs are accepted and written.
Evidence (dev database, 2026-07-27). 5 relationships whose target does not resolve within their own engagement's projection; 4 relationships targeting retracted assertions; 8 relationships between two held assertions (the last is intended behaviour, listed for completeness).
Why queued, not fixed now. Broader than the graph-hygiene change request (drafting handoff D-5). And CR-2026-154 deliberately relies on the permissiveness: the redirect edge targets a retracted assertion in another engagement. Any future validation must carve out cross-engagement and retracted targets for the redirect edge write (engagement/redirect.py) and the redirect backfill (engagement/redirect_edge_backfill.py) — CR-2026-154 §3 CD-11 names both sites.
Shape of the eventual work. Decide, per check: existence (probably yes, with the redirect carve-out for cross-engagement resolution), engagement (design question — cross-engagement references are load-bearing for redirect), state (design question — held→held and →retracted both have legitimate uses today).
current_memory_objects rows behind
What. hard_delete.py discovers dependent tables by walking foreign keys that reference engagements.id (hard_delete.py:16–33). current_memory_objects has no such foreign key, so hard delete never cleans it.
Evidence (dev database, 2026-07-27). 85 orphaned projection rows across 20 deleted engagements; 106 projection rows with no matching object_id in memory_events at all (896 projection rows vs 1156 event rows).
Why queued. Out of scope for graph hygiene per scoping note §6 ("a finding to report, not absorb"). It already bound on one design decision: the redirect backfill is driven from memory_events joined to engagements, never from the projection alone, because a naive sweep would raise EngagementNotFound against orphaned rows.
Shape of the eventual work. Two halves: (a) one-time cleanup of the 85 orphaned rows; (b) prevention — either an FK from current_memory_objects.engagement_id to engagements.id, or an explicit table entry in hard-delete's sweep. The FK is the structural fix but changes the projector's failure modes; a scoping pass decides.
DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — Queued-Directions Candidates — Relate-Path Validation and Hard-Delete Projection Cleanup — v0.2 — 2026-07-27