Implement cross repo references#2
Merged
Merged
Conversation
…cceptance <repo-id>:<entry-id> refs now store verbatim and validate syntactically at every parse/resolve site: excluded from local reverse indexes and dangling checks, pass-through in short-ID resolution, accepted by --refs and the engine typed store, with lifecycle edges (closes/supersedes) rejected at the boundary. Dangling detection honors the forward-class exemption (surfaces, required-by) per d-cpt-uh0. Config gains the committed repo_id identity field. Part of d-tac-i6f (cross-repo references, foundation layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A cross-repo ref renders as an upstream leaf carrying the verbatim <repo-id>:<entry-id> plus [unresolved: repo X] in the qualifier slot — in sdd show trees (plain and styled), view expand(refs) sub-lines, and the show envelope (verbatim refs). ShowTreeItem gains CrossRepoID and NodeID() so a later resolved remote node reuses the same shape; the RefExpansion row carries UnresolvedRepo the same way. MCP show/view inherit through the shared finders and presenters. Part of d-tac-i6f (cross-repo references, foundation layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A backward-class cross-repo ref now produces a high-severity cross-repo-ref-unresolved finding unless it resolves in the target repo's cached graph; forward-class kinds (surfaces, required-by) are exempt per d-cpt-uh0. The check takes a resolver seam — nil (no connected-repos machinery) reports every repo unavailable; the discovery layer wires the cache-backed, fetch-on-miss implementation. Local ref resolution stays where it was: dangling local refs hard-block at write-time validation before pre-flight runs. Part of d-tac-i6f (cross-repo references, foundation layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The user-global config at $XDG_CONFIG_HOME/sdd/config.yaml (default
~/.config/sdd/config.yaml) holds connected repos {repo_id, clone_url}
plus the single global embedding config defining the shared vector
space. Caches are managed read-only clones at $XDG_CACHE_HOME/sdd/
<repo-id>/ with lazy clone, cooldown-gated pull (marker in .git/,
attempts not successes), forced pull, and declared-repo-id
verification for repo add. model.DeriveRepoID normalizes ssh/https
remote forms to the canonical host/path identity. Plain functions
throughout — handlers orchestrate and invalidate the GraphSource.
Part of d-tac-i6f (cross-repo references, discovery layer).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…graphs model.MultiGraph is the cross-graph read model: local graph plus member graphs keyed by repo-id, loaded lazily through a loader closure wired only inside the finder-owned GraphSource — CLI commands, MCP reads, engine serves, and capture-time resolution all inherit the one seam. Member graphs come from connected-repos caches as pure reads; a not-connected repo resolves to the unresolved state while a corrupt cache propagates its error. Show trees now hop graphs at cross-repo edges: the walk continues in the owning member graph with every node repo-qualified, dedup runs on the (repo-id, entry-id) colon key, embedded entries dedup by bare ID so exactly one copy surfaces, and supersede head-walks stay within the owning graph with trails qualified for display. sdd show accepts a <repo-id>:<entry-id> primary through the same path. Ref expansion, the ref-kind applicability check, and the LLM ref-meta context all resolve remote targets through the assembly. Part of d-tac-i6f (cross-repo references, discovery layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h-on-miss sdd repo add clones the target's cache, verifies the repo declares the identity its URL derives, and registers the connection; list/remove manage entries and sync force-pulls (all or named). sdd init derives repo_id from the origin remote — recorded on fresh init, upserted into configs that predate the field, never overwriting a recorded value and never user-choosable. Capture now reads the live caches: referenced repos are refreshed (lazy clone + cooldown pull) before the graph loads, and a backward-class cross-repo target still missing from a connected cache triggers one forced fetch and reload before pre-flight judges — so a just-pushed remote entry doesn't false-block, while a genuinely absent target still blocks. sdd show freshens the caches of any repos named by colon-form IDs before reading. Part of d-tac-i6f (cross-repo references, discovery layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…x exclusion sdd search gains --repo (repeatable, additive to local) and --all-repos; finders.MultiSearch resolves member sources from the query graph's cross-graph assembly and merges every hit into one list by comparable score, remote hits repo-prefixed with status derived in the owning graph. The side-effect half lives in Handler.PrepareCrossRepoSearch — cache freshen plus per-repo index lazy-fill under the shared embedder (user-global config wins for cross-repo queries), mirroring how local lazy-fill precedes the search finder. Member indexes build at <cache>/.index excluding embedded entries; member hits on embedded entries are dropped so exactly one copy surfaces. A drifted member index re-embeds on the next cross-graph search rather than being excluded, and sdd lint reports the pending drift per repo. sdd view gains the same flags, rendering the layout over each selected repo's graph under a repo heading; the MCP search and view tools accept equivalent repos/all_repos parameters, and MCP show freshens the caches of colon-ID arguments — all served by the same finders as the CLI. Part of d-tac-i6f (cross-repo references, discovery layer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mary Two fixes from live end-to-end verification. RepoAdd now clones into a staging dir first and establishes the identity from the repo_id the target declares — canonical by design — moving the clone into its cache location afterwards; a clone URL that derives an identity (ssh/https) still must match the declared value, while local paths and offline mirrors work without the cross-check. And sdd new gains --summary: a caller-supplied summary stores verbatim and skips LLM generation entirely, for callers that already hold a faithful summary or run without a reachable LLM. Part of d-tac-i6f (cross-repo references). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A caller-supplied Summary stores verbatim in the written entry's frontmatter and the LLM runner is provably never consulted — the stub runner fails the test on any call. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
hlubek
commented
Jul 7, 2026
The character-identical collectors crossRepoIDsIn (CLI) and crossRepoIDsOf (MCP server) collapse onto one pure function beside SplitCrossRepoID — push-down and single-path per the PR #2 review (d-tac-fyd, finding 1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every git subprocess sdd runs now lives in internal/git behind the consumer-defined interfaces (handlers.Committer/Brancher/Mover/Puller, finders.GitSyncer): git.CLI implements them all, with the staged-deletion commit variant on git.RemovalCommitter since it shares the Commit method name. The loose helpers (repo root, user.name, remote get-url) move as package functions, and the pathspec-scoping regression tests move with the code. cmd/sdd keeps wiring only — a future (possibly partial) go-git swap touches nothing but this package (d-tac-fyd, finding 3). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
internal/repos stops reading XDG env vars as hidden globals: Locations carries the config path and cache root, resolved once by repos.DefaultLocations() at the composition roots (CLI helpers, sdd serve). On top sit two abstractions following the read/write seam — a pure Registry (connections, cache layout; injected into finders.Options and the search finder) and a side-effectful Manager (clone, pull, config writes; wraps the Registry plus a narrow Git interface implemented by internal/git; injected into handlers.Options). Finder purity is now type-enforced: the read side's dependency has no clone or pull. Config reads stay lazy per call so a long-lived MCP server sees new connections without restart. Tests build Locations over temp dirs — the XDG t.Setenv workarounds are gone except in the test of DefaultLocations itself (d-tac-fyd, finding 2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
populateIndexLint/populateRepoIndexLint were finder-shaped code in the CLI layer: config → manifest → fingerprint drift counts. They now live beside Finder.Lint as Finder.IndexLint, taking an IndexLintQuery (resolved embedding config + index dir — flag merging stays the shell's only job); the cross-repo section reads through the injected Registry with no CLI-side wiring. The deliberate degrade-silently posture (lint never blocks on absent index machinery) moves with the code (d-tac-fyd, finding 4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
Review round 1 addressed in four commits (recorded in the graph as directive d-tac-fyd, surfaced by evaluation s-tac-vyq):
Verified: full test suite, go vet, gofmt, golangci-lint clean; live two-repo fixture re-run against the rebuilt binary (repo add/list/sync/remove, capture with resolvable cross-repo ref, resolve-or-block on an absent target, cross-repo show, merged 🤖 Generated with Claude Code |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
No description provided.