67%

§01 edge class contract honest envelopes

Goal

Every later section lands on rails: a machine-readable edge-class contract (identity/producer/replacement-scope/prune/freshness per class), the provenance-derived confidence ADR, honest query envelopes (unresolved sections, status partial, missing-facet reporting), and per-facet staleness generations.

Implementation Sketch

  • Contract registry: one JSON/py registry in intel_repo/neo4j/ validated at import; every subsequent section adds its row BEFORE first ingestion (codex F8 shape).
  • Confidence ADR: provenance tag + match tier -> confidence class via ONE mapping fn (glm F1; 133,615 edges already provenance-tagged); shared predicate exported to seam_scan/cypher_query.py and gds_enrich.py; numeric-field alternative rejected (LEAK:scattered-knowledge).
  • Honest envelopes: unresolved-callee section in cmd_callers/cmd_callees (target_identifier + call_shape + counts); schema-absent (silent-empty correct) vs resolution-absent (must surface) distinction per glm F5.
  • Staleness: mirror rc_remarks_stale per new facet; absent timestamp = None (unknown), never fresh.

Spec References

  • intel_repo/neo4j/import_code_graph.py (provenance tags, MERGE-only prune debt); intel_repo/neo4j/staleness.py (facet pattern); .claude/rules/impl-hygiene.md SSOT-04 (shadow home), COVER-09 (canonical registration)

Work Items

  • Author the edge-class contract registry (machine-readable, intel_repo): every node/edge class declares stable identity key, producer, replacement scope, prune semantics, freshness facet, confidence derivation, resolution-accounting policy, and supported forward/reverse query surfaces; document the registry in intel_repo/CLAUDE.md and validate completeness at import time before a producer may ingest that class
  • Record the provenance-derived confidence ADR (decisions/): define ONE shared mapping from each registered edge class’s provenance evidence to a confidence class, including existing CALLS provenance tag + match tier, with no parallel numeric field; require every edge-class registry row to select a supported derivation and ship the shared consumer predicate used by query_graph.py and seam_scan/cypher_query.py
  • Implement registry-driven per-facet staleness generations: facet-run stamps on :Repo per the rc_remarks_stale pattern; require a staleness.py block and status projection for every registered produced facet across both estates, including call resolution, ownership, field-use, comments-wide, platform, artifact-fabric, sibling divergence, co-change, and test topology; treat an absent timestamp as None (unknown), never fresh, and surface every facet through intel-query.sh status
  • Honest envelopes: cmd_callers/cmd_callees emit an unresolved section (UnresolvedSymbol target_identifier list + counts, call_shape breakdown) distinguishing schema-absent from resolution-absent; add status partial + missing/stale facet fields to the query envelope
  • Tests: contract-registry validation, envelope shape pins, staleness facet unknown-vs-fresh-vs-stale matrix
  • Tests: contract-registry schema and import-time completeness rejection for identity, lifecycle, confidence, resolution accounting, forward/reverse query surfaces, and freshness; shared confidence-derivation coverage for every registered edge class; registry-to-staleness facet completeness; envelope shape pins including schema-absent versus resolution-absent, unresolved call-shape counts, and partial propagation for missing/stale facets; staleness facet unknown-vs-fresh-vs-stale matrix

Fresh intel (regenerated)

This section is correctly placed as the contract foundation, but the live graph proves that its deliverable is broader than adding a registry file and a few response fields. Three current representations erase the evidence the proposed honest envelope needs:

  1. UnresolvedSymbol carries only (repo, target_identifier). Its incoming CALLS edge carries only provenance; neither endpoint stores call_shape, match tier, source line, or an occurrence identity.
  2. cmd_callers and cmd_callees match only :Symbol targets. A real production function, rewrite_phis, has 23 outgoing unresolved CALLS and zero resolved CALLS, yet intel-query.sh callees rewrite_phis prints No callees found.
  3. status is not a whole-graph freshness verdict. The code graph is fresh, but the graph-resident intel-graph-deepening plan still says not-started, including its completed walking skeleton. Separately, :Repo.last_rc_remarks_at is populated while rc_remarks_stale is null because compute_staleness does not copy last_rc_remarks into its per-repo input map.

The live CALLS substrate makes the scale and semantics concrete: Ori has 33,956 resolved Symbol-to-Symbol tree-sitter edges and 76,420 Symbol-to-UnresolvedSymbol tree-sitter edges. Those are edge counts, while the unresolved target set is 2,558 nodes. Any envelope field named merely count is ambiguous unless it states whether it counts call sites, unique source-target pairs, or unique targets.

[JOIN] The graph-invariant verifier passes all 24 verification tests while mission fitness reports 1 pass, 5 failures, and 1 unavailable probe. Structural validity and truthful completeness are different contracts. Section 01 must make that distinction machine-readable rather than inferable from prose.

Decisions this package forces before implementation:

  1. Define CALLS identity before adding unresolved metadata. The existing tree-sitter two-endpoint MERGE and SCIP source-line-keyed MERGE do not represent the same unit.
  2. Preserve call_shape and a nonnumeric match_tier at ingestion. A confidence function cannot derive a class from information the graph discarded.
  3. Make every envelope count dimension explicit: resolved_edges, unresolved_edges, unresolved_targets, and call-shape buckets. Do not overload count.
  4. Derive freshness fields from the contract registry or one canonical facet registry. Do not add five copied staleness blocks and five copied status projections.
  5. Repair and pin the existing RC-remarks freshness path before using it as the template for new facets.
  6. Include plan-corpus freshness or explicit omission in the status contract. stale:false must not imply every graph estate is current.

VERDICT: The architecturally sound deliverable is one validated contract registry that drives ingestion identity/lifecycle, confidence selection, and facet-status enumeration, plus lossless unresolved CALLS records consumed by honest query envelopes. A registry that only documents today’s lossy graph would encode the defect instead of fixing it. This direction is required by SSOT-01, SSOT-04, SSOT-05, and SSOT-15; it must avoid LEAK:scattered-knowledge and LEAK:lossy-fallback.

DIG DEEPER

scripts/intel-query.sh status --human
scripts/intel-query.sh fitness --human
scripts/intel-query.sh verify-graph-invariants --rebuild-mode --human
scripts/intel-query.sh cypher "MATCH (:Symbol {repo:'ori'})-[r:CALLS]->(t) RETURN labels(t)[0] AS target_kind, r.provenance AS provenance, count(*) AS edges, count(DISTINCT t) AS targets ORDER BY target_kind, provenance" --human

(full dossier: edge-class-contract-honest-envelopes—s-75d59dc3.intel.md)