Conversation
`sdd export --format json` writes the local graph plus selected connected repos with engine-derived status, heat, effective topics and first-parent git arrival times, for prototyping a hosted graph viewer. Not a stable read contract: built on the internal model, not pkg/application. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The experimental export now follows the repo's declared dependencies transitively instead of the machine's connected repos: --dependencies none|referenced|all, with --hops bounding the upstream expansion from cited entries. Base entries are emitted once at the top level, and --out writes the document atomically. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| if err = tmp.Close(); err != nil { | ||
| return err | ||
| } | ||
| if err = os.Chmod(tmp.Name(), 0o644); err != nil { |
There was a problem hiding this comment.
Private exports become readable
If other local users can access the output directory, --out lets them read the exported entry bodies and text attachments. os.Chmod forces 0644, ignoring a restrictive umask and replacing any existing 0600 file with a readable one. Keep the temporary file private, or preserve the destination's permissions.
How this was verified: The output writer applies 0644 before renaming a document that includes entry bodies and attachment contents.
Prompt To Fix With AI
This is a comment left during a code review.
Path: internal/cliapp/export.go
Line: 144
Comment:
**Private exports become readable**
If other local users can access the output directory, `--out` lets them read the exported entry bodies and text attachments. `os.Chmod` forces `0644`, ignoring a restrictive umask and replacing any existing `0600` file with a readable one. Keep the temporary file private, or preserve the destination's permissions.
**How this was verified:** The output writer applies `0644` before renaming a document that includes entry bodies and attachment contents.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if x.arrivals, err = h.FileArrivals(ctx, dir); err != nil { | ||
| return query.ExportRepo{}, err | ||
| } |
There was a problem hiding this comment.
In an initialized Git repository with no commits, HeadRevision returns an empty revision without an error. But exportRepo still calls FileArrivals, whose git log fails because there is no commit. The command stops without exporting the uncommitted graph. Skip the history lookup when the revision is empty and leave landed_at unset.
Prompt To Fix With AI
This is a comment left during a code review.
Path: internal/finders/export.go
Line: 133-135
Comment:
**New graphs cannot export**
In an initialized Git repository with no commits, `HeadRevision` returns an empty revision without an error. But `exportRepo` still calls `FileArrivals`, whose `git log` fails because there is no commit. The command stops without exporting the uncommitted graph. Skip the history lookup when the revision is empty and leave `landed_at` unset.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| for _, e := range gf.graph.Entries { | ||
| if e.Embedded { | ||
| result.Embedded = append(result.Embedded, x.entry(gf.graph, e, nil)) | ||
| } |
There was a problem hiding this comment.
Dependency references lose base entries
When the local repository overrides a base entry's ID, that original entry disappears from the top-level embedded list. A dependency can still reference the original because each graph loads its own base entries. But dependency exports skip those entries too, so the reference has no exported target. Build embedded from the complete base set, while keeping each repository's overrides in its own entries list.
Prompt To Fix With AI
This is a comment left during a code review.
Path: internal/finders/export.go
Line: 65-68
Comment:
**Dependency references lose base entries**
When the local repository overrides a base entry's ID, that original entry disappears from the top-level `embedded` list. A dependency can still reference the original because each graph loads its own base entries. But dependency exports skip those entries too, so the reference has no exported target. Build `embedded` from the complete base set, while keeping each repository's overrides in its own `entries` list.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| // committer time of the first-parent commit that added it. Log order is | ||
| // newest first, so a path added more than once keeps its latest addition — | ||
| // the one that brought the current file. | ||
| func ParseFileArrivals(gitLogOutput string) (map[string]time.Time, error) { |
| // returns every reached repo ID once, in first-reached order, never root | ||
| // itself. declared returns a reached repo's own declarations; a repo it cannot | ||
| // resolve returns none, so it stays listed but nothing behind it is reached. | ||
| func DependencyClosure(root string, direct []string, declared func(repoID string) ([]string, error)) ([]string, error) { |
There was a problem hiding this comment.
Add unit tests for this model logic
There was a problem hiding this comment.
Also: is that the best place for this code? Why not a method on a type that owns the dependencies? I dislike passing these areound as arguments.
| // bare ID within that entry's repo, a cross-repo ID into the repo it names. | ||
| // Only repos in scope are entered, and embedded entries are never selected | ||
| // (no repo owns them). The result maps repo ID to the selected entry IDs. | ||
| func CitedAcross(local *Graph, scope []string, hops int) (map[string]map[string]bool, error) { |
There was a problem hiding this comment.
I don't like the []string type. We should have a proper custom type (based on string) for repository identifiers.
Adds
sdd export, an experimental command that writes the graph as one JSON document, for prototyping UIs that need entries and references as data. It is built on the internal model and finders, not onpkg/application, and its shape is explicitly unstable; the structured read the application is to return (20260928-080143-d-cpt-kv4) stays the real target..sdd/config.yaml).referenced(default) exports only the dependency entries the local graph cites, plus--hopsupstream steps inside the dependency (default 1);allexports whole dependency graphs;noneonly the local graph. Each dependency records itsselection {mode, hops, total_entries}.status/status_by/closed_by/superseded_by, refs with kind and desc,heat(exp-14d) andin_degree, summary, body, attachments (Markdown and plain text inlined, cut under 16 KB), andlanded_at: the committer time of the first-parent commit that brought the entry onto the branch, read in onegit logpass.embeddedlist; any repo's ref to such an ID resolves there unless the repo has its own entry with that ID.--outwrites atomically via temp file and rename; stdout otherwise.Known limits, noted for the structured read: capture time carries no zone; ref kinds are normalized at parse time; heat, in-degree and closure stop at the repo boundary; the dependency walk mirrors serve's semantics because
inDependencyClosureis private topkg/application.Tests:
TestCLIExportJSON(a real git repo with a--no-ffmerge forlanded_at, status, refs, heat, attachments, WIP, revision) andTestCLIExportDependencySelection(local → dep → deep closure acrossnone,--hops 0/1/2,all,--out, refused flag combinations).go vet ./...clean, full test suite passing.🤖 Generated with Claude Code
Fix the output permissions, first-commit failure, and missing base targets before merging.
Findings
Fix with agent prompt
Summary
Adds experimental
sdd exportJSON output with dependency selection, derived entry fields, attachment text, Git arrival times, and atomic file replacement.Acknowledged limits:
hlubekexplicitly described the shape as unstable, capture times as zone-free, ref kinds as normalized, derived scores and closure as repository-local, and the dependency walk as matching serve's semantics. These intentional limits are not findings.Reviews (1) · Last reviewed commit: "feat(cli): select export dependencies fr..."