Repository navigation
links: typed-edge view on CorpusStore + GraphStore protocol (#46) - #53
Merged
Merged
Conversation
The semantic link graph — capability 1's substrate (ADR discussion #43, report 12): - CorpusStore gains a 6th optional `links` view (the calibration-view pattern): get_links/set_links/delete_links/link_items; adjacency artifact_id -> {edge_type: [target]}, target a bare aid or [source, aid] pair. Derived state, outside build identity; absent view = no edges. - ir/graph.py: GraphStore runtime_checkable Protocol (__getitem__ + neighbors — minimal so a traversal operator binds to any conforming store); CorpusGraph adapter (node = artifact_id, payload = the artifact's records, neighbors from the links view); edge vocabulary NEXT/PREV/PARENT/CHILD/REF (NEXT/PREV derivable from the ledger, not materialized). Naming guard: semantic link graph (cyclic, query-time) != ef.artifact_graph (acyclic build-time DAG). - EdgeExtractor seam + default_edge_extractor (Package deps -> REF with PEP 508 names stripped to the bare distribution; Skill parent -> PARENT). build(source, *, edge_extractor=) ingests eagerly — edges (re)written for every in-scope artifact (decompose-only, no embedding) so the graph never goes partially stale; pruned artifacts' edges deleted under full refresh. Embedding stays incremental. 25 new tests; 319 total pass.
…nonicalization (#46) Adversarial-review findings on the links-graph diff: - _dep_name now splits on '@' too, so a PEP 508 direct-reference dep ("dol@git+https://...") yields the bare name "dol" instead of the whole URL as a garbage REF target. - default_edge_extractor drops self-edges case-insensitively (_dep_name lower-cases; an "AA" package depending on "aa" is now recognized). - canonical_node_id(target, *, source) — resolves a neighbor target (bare aid in this graph's source, or a [source, aid] pair) to the canonical (source, artifact_id) a traversal's visited-set needs (#47). neighbors() docstring tightened: bare targets are implicitly this graph's source, a cross-corpus pair fed back in is out of contract. - GraphStore docstring notes runtime_checkable validates attribute names only; build() docstring notes an extractor-less rebuild leaves edges untouched (only prune clears them). - 11 new tests: URL/spaced deps, case-insensitive self-edge, dep dedup, canonical_node_id, file-backed neighbors round-trip, cross-corpus edge_type=None dedup, name@parent skill-collision parent edges.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #46. The semantic link graph — capability 1's substrate (ADR discussion #43, report 12), on the design decisions recorded in the issue comment. First of two PRs (this, then #47's
traverse).What
linksview onCorpusStore(6th view, the calibration-view pattern): a defaulted constructor arg +local()file store;get_links/set_links/delete_links/link_items. Adjacencyartifact_id → {edge_type: [target]}, a target a bareartifact_idor a[source, artifact_id]pair. Regenerable derived state — not in build identity; absent view ⇒ no edges, never hard-fails.ir/graph.py(new): theGraphStoreruntime_checkableprotocol (__getitem__+neighbors— minimal sotraversebinds to any conforming store); theCorpusGraphadapter (node =artifact_id, payload = the artifact's records, neighbors from the links view); the edge vocabularyNEXT/PREV/PARENT/CHILD/REF(NEXT/PREV derivable from the ledger, not materialized);canonical_node_id(resolves a neighbor target to the(source, artifact_id)a traversal's visited-set keys on). Naming guard: the semantic link graph (cyclic, query-time) ≠ef.artifact_graph(acyclic build-time DAG).EdgeExtractorseam +default_edge_extractor(Packagedeps→REFwith PEP 508 names stripped to the bare distribution incl. URLname@…deps; Skillparent→PARENT, self-edges dropped case-insensitively).build(source, *, edge_extractor=)ingests eagerly — edges (re)written for every in-scope artifact (decompose-only, no embedding) so the graph never goes partially stale; pruned artifacts' edges deleted underfull. Embedding stays incremental.Acceptance (from #46)
linksview round-trips (memory + file-backed; JSON-clean, incl.[source, aid]pair targets).neighbors(aid, edge_type="REF")returns Package deps on a packages corpus built with edge ingest.GraphStoresatisfied byCorpusGraph(runtime_checkabletest, withisinstance(object(), GraphStore)False for teeth).edge_extractor, and that only the ingested build has edges.36 tests in
tests/test_graph.py; 330 total pass. An adversarial multi-agent review ran before this PR; its confirmed findings (PEP 508 URL deps, case-insensitive self-edge, node-id canonicalization for #47, doc overpromises) are fixed in the second commit. A test also caught a real footgun — an emptyCorpusStoreis falsy (__len__is 0), sostore or defaultdiscards a passed store;build()uses the correctis Nonecheck.