Preview source-owned dependency edges in the projection dry run (STATE-WP-0094-T05)

diff_against_hub accepts hub_edges/edge_targets and reports edges to create,
remove, retain, unresolved and external, using the same pure planner that
receiving now calls (plan_source_edges + classify_source_edges). The classifier
works on a row list, fixing a collapse where an external duplicate of an owned
edge key could hide the owned row from removal. 7 new pure tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 692292@bnt-lap001
Assistant-Session: 89c7d8e8-e1b3-47eb-9411-a0ab227fca2f
This commit is contained in:
tegwick 2026-10-04 13:19:23 +02:00
parent 216876c0cb
commit c287ed8259
3 changed files with 407 additions and 90 deletions

View file

@ -67,6 +67,24 @@ ownership contract first.
Outcome schema additions (`state-hub.projection-reset.v1`): `created_edges`,
`removed_edges`, `unresolved_edges`, `external_edges` lists and their counts.
## Dry-run preview
`diff_against_hub(..., hub_edges=[...], edge_targets={...})` previews edges
with the same pure planner receiving uses (`plan_source_edges` +
`classify_source_edges`). `hub_edges` are the rows whose from-workplan belongs
to the repository (with `source_owner`); `edge_targets` maps a target record id
to its fleet-wide non-retired candidate ids. A target the hub lacks but this
projection declares resolves to the id the receipt would create. The diff gains
`edges` (`create`, `remove`, `retain`, `unresolved`, `external`) and
`edge_counts`; only `create`/`remove` make it non-clean. Without `hub_edges`
the output is unchanged (no `edges` key).
Duplicate keys: several rows may share one edge key (an owned row plus an
API-authored duplicate). The classifier works on the row list, so an external
duplicate can neither hide an owned row from removal nor turn a satisfied
declaration into an external report (fixed 2026-10-04; the first
implementation keyed rows by edge key and let the last row win).
## Coexistence with C-20
C-20 keys existence on (from task, target, relationship) regardless of owner,
@ -78,7 +96,6 @@ explicit adoption decision.
- Pre-existing C-20/API edges are never adopted, so a removed declaration does
not remove an edge C-20 created earlier; adoption needs its own decision.
- `diff_against_hub` (dry run) does not yet preview edge changes.
- Ambiguity by slug for workplans is mostly prevented by the global slug index;
task `record_id` ambiguity across workplans is the realistic case.
- Not deployed; no evidence of scheduled freshness. T05 stays in progress.