Releases: networkteam/sdd
Release list
v0.15.0
Highlights
-
Cross-repo references — reference the reasoning in another SDD graph — An entry can now cite an entry in a different repo's graph as
<repo-id>:<entry-id>, and the reference resolves, renders, and traverses like a local one. Connect a repo withsdd repo add <clone-url>(and manage connections withsdd repo list,sdd repo remove,sdd repo sync); each dependency is declared as a committeddependencieslist in.sdd/config.yaml— the waygo.moddeclares modules — while the clone URL and homedir cache stay in your user-global config.sdd searchandsdd viewgain--repo <id>(repeatable) and--all-reposto search across connected graphs, with remote hits merged by cosine score and prefixed by repo-id;sdd show <repo-id>:<entry-id>resolves through a read-only cache and walks cross-repo chains. Bare IDs (short or unprefixed-full) resolve local-first, then across declared dependencies, uniformly acrosssdd show, theshowMCP tool, and written refs. Directedness is structural: capture blocks a cross-repo ref at high severity unless its target repo is a declared dependency,sdd lintflags any cross-repo ref pointing at an undeclared one, and capture auto-fetches on cache miss. The same repo parameters are available through the MCPsearch,view, andshowtools. -
sdd configand a unified config overlay — Configuration now resolves through one global-first overlay: user-global~/.config/sdd/config.yaml→ committed.sdd/config.yaml→ machine-local.sdd/config.local.yaml→ CLI flags. Shared user/machine settings (participant, llm, embedding, sync) live in the user-global layer and take effect in every repo, while repository facts (repo_id, dependencies, graph_dir, supported_agents) stay committed per-repo. The newsdd configcommand creates the global file, gets and sets keys in the global or machine-local layers, and prints the effective merged config with per-value provenance so you can see where each value comes from. Unknown or misplaced keys now fail loud with an error naming the file and the key, rather than being silently dropped. -
Machine-global vector index — The vector index moved out of the working tree into one machine-global, content-addressed store keyed by
(repo-id, embedder-fingerprint). A checkout, its worktrees, and any connected-repo cache now share a single index, ending the double-embedding of a repo that is both developed and connected and removing the in-tree.sdd/index(and its worktree copy recipe) entirely.sdd initmigrates an existing.sdd/indexinto the store without clobbering. Concurrent multi-process access is made safe by advisory file locking centralized in one seam.sdd index --repo <id>andsdd index --all-reposbuild connected indexes eagerly with visible progress, and--forcenow rebuilds connected member indexes, not only the local one. -
Post-compaction reorientation for engine sessions — An MCP-connected agent that has lost its context — no session or instance handle, or a summarized transcript — can now call
resume_sessionwith no arguments to re-serve the live position of the session its connection is already bound to: the framing plus every running move at its current step, each with the schema needed to continue it. Every serve that carries open moves also foregrounds a short reorientation breadcrumb naming the open work and how to continue or reorient, so a compacted agent is routed home by whatever call it makes next.
Other changes
- Cross-repo clone and connected-index builds render transient progress through the output coordinator on a TTY and clean structured logs off-TTY.
- Ctrl-C during an embedding run now exits cleanly with the SIGINT code instead of surfacing a raw
context cancelederror. - Text-only
sdd search --repogives honest first-time clone/pull feedback instead of a mislabeledindexingprogress bar. sdd new --summaryaccepts an explicit summary, bypassing generation for that entry.
Full Changelog: v0.14.1...v0.15.0
v0.14.1
Highlights
engine— host-neutral groom marker cleanup — Clearing an orphaned WIP marker during an engine-mode groom no longer tells the agent to shell out tosdd wip done. A newremoveMarkerchoice runs awipRemoveengine transition that clears the marker through the same removal path (FinishWIP), reading the marker ID the sweep collected. This was the last groom step that directed the agent to the host CLI, so groom's stale-marker cleanup now works against a remote or hosted graph where thesddbinary isn't on the agent's path — realizing the host-neutral-procedures directive for the marker path.
Other changes
- Finder-owned
GraphSource— Graph reads now route through a single memoizing read-through seam (overLoadGraph) with invalidate-on-write, replacing the engine's mutable graph field and the four hand-maintained refresh sites scattered across the shell. Post-write freshness is driven by each write command's ownMutatesGraphdeclaration, so the fidelity-review read always sees the just-written entry. This deletes the latent "forgot to refresh" bug class where an engine session could silently serve a stale snapshot after a write. No CLI or engine behavior change; foundational groundwork for cross-repo graphs.
Full Changelog: v0.14.0...v0.14.1
v0.14.0
Highlights
-
sdd serve— v1 workflow engine (preview) — SDD now ships a workflow engine that drives a full session as served procedure steps over an MCP surface, as an alternative to the skill-prose flow. Playbook moves become first-class graph entries under a newproceduredecision kind: their frontmatter carries a state machine over a typed variable store, their body carries per-step instruction units, and the engine executes them in-process against a closed Go registry of named predicates, queries, and commands composed by name in YAML. Sessions persist as append-only JSONL event logs and survive restart by replay. A session opens through one door — a start tool that auto-starts a base "shell" procedure and returns tiered knowledge (the compressed process core, conduct and register rules, and the live procedure enumeration pulled from the graph); every move nests under that base and lands back on it, so the agent is never goalless before, between, or after moves. The loop tools (start_procedure,next,park,abandon,resume_session,list_sessions,stage_attachment,read_attachment) reject without a started session and point back at the door, while free reads (search,view,show,info,registry) stay ungated. Graph writes exist only as procedure transitions, and capture enforces a mechanicalrefsInspectedgate — every ref you cite must have been read at full depth in the session read log. Eight procedures ship: capture, engage, explore, catch-up, groom, evaluate, implementation, and interview. Drive it through the new/sdd-engineskill. This is a preview surface: it runs alongside the untouched/sddskill and you choose per session./sddremains the default for now, but will be marked legacy and phased out in a future release as the engine reaches parity. -
sdd init— engine works out of the box —sdd initnow installs and refreshes the project-scope MCP registration and pre-allows themcp__sdd__*tools per supported agent, so a fresh session can drive procedures with no manual setup or per-tool permission prompts —.mcp.jsonplus.claude/settings.jsonfor Claude Code, the equivalent.codex/config.tomlfor Codex. It follows the standing per-agent render pattern (agent-specific config as a cheap layer over neutral intent) and is drift-respecting: it refreshes stamped entries but leaves registrations or permission entries the user has modified in place. -
Summaries — hash machinery removed, derived on demand — The per-entry summary skip-hash is gone. Because the hash was computed over a prompt that embeds neighbor summary prose and a read-order-dependent attachment list, it drifted on its own and produced a treadmill of false-staleness
sdd lintwarnings, and--attachentries were born stale. Under entry immutability an entry's meaning is fixed at creation, so staleness tracking guarded against a change that cannot happen.sdd summarize <id>and--textnow regenerate the named entry's summary unconditionally;--allfills only entries with an empty summary, and--all --forceregenerates every non-embedded entry.sdd lintdrops both hash warnings (stale-hash and summary-without-hash) and keeps the missing-summary warning;sdd showno longer renderssummary_hash. Existing files that still carry asummary_hash:key load without error — the now-unknown key is ignored and drops the next time that entry's summary is written. No migration. -
Auto-commit — fail-fast, fail-loud — SDD's background Git auto-commit no longer hangs indefinitely or degrades a failure into a swallowed stderr warning. It detaches the controlling TTY, applies a timeout, and propagates errors: a failed or timed-out commit returns an error — the entry file stays on disk for durability, but the failure surfaces instead of letting execution continue as if nothing broke. This also unwedges the Codex capture path that previously stalled on SSH commit signing.
Other changes
- Evaluation reshaped into verification/validation lenses — the evaluate surface now frames its two lenses as generic postures (verification = built right; validation = the right thing) rather than domain-specific checks.
read_attachmenthands local (stdio) MCP clients the absolute path to the staged file.sdd index/ search lazy-fill progress bar tracks by chunks and advances honestly on completion.
Full Changelog: v0.13.0...v0.14.0
v0.13.0
Highlights
-
intent— directive lifecycle attribute — Directives now carry a requiredintentattribute (pending | guiding | settled), supplied at capture via a new--intentflag (and the matching MCP capture arg).NewEntryCmd.Validateenforces it as directive-only, from the closed value set, and required on every directive write path, while the model stays permissive so directives captured before the attribute read unchanged.settledis a new born-terminal status — it needs no closing edge, supersession beats it, and closing a settled directive is rejected. Rendering reflects all of this:{status: settled}across view, chains, andsdd show, and[intent: guiding]on entry lines (pending and unspecified stay quiet). A newintent()view filter composes insidenot(), catch-up action lanes now include directives but exclude guiding ones, and/sddsurfaces active guiding directives as a standing-context block. Pre-flight gains asettled-justificationrubric that flags a settled directive whose body doesn't justify its terminality. Skill capture guidance, bootstrap examples, view help text, and the German vocabulary gloss are all refreshed. -
Summary prompt — lead with substance, demote supersession — The summary-generation prompt now leads with what an entry actually commits to instead of the bookkeeping of what it supersedes. The first sentence of a superseding entry's summary states its own commitment; "supersedes X" is named only when the supersession is itself substantive — a reversal or material change — and omitted or de-emphasized for re-statements and attribute-stamps. Refs and closes stay primary relational sentences; only supersedes is demoted. This fixes the bookkeeping-crowds-the-lede problem in generated summaries that readers consume in
sdd viewand catch-up.
Full Changelog: v0.12.0...v0.13.0
v0.12.0
Highlights
-
sdd statusandsdd listretired — overview folds ontosdd info+sdd view— Both standalone overview commands are gone. Session framing lives onsdd info(local participant, language, search modes); the kind-grouped overview and all filtered listing live on thesdd viewpipeline, which had already absorbed both surfaces and made the hand-built presenters redundant.sdd statusandsdd listnow exit nonzero as unknown commands, and baresddprints help rather than masking a removed command. The sharedEntryLinerow format thatsdd viewandsdd searchreuse is preserved; only the dedicated command stacks were removed. -
Catch-up open-loops lane +
coldnessrank algorithm —sdd viewgains acoldnessrank algorithm —coldness(e) = decay(entry-age) / (1 + in-degree), the inverse of heat — so fresh, un-referenced entries rank highest. This catches the just-captured commitment that heat scores near zero because nothing refs it yet. The catch-up briefing gained an "Open loops" lane built on it (rank(coldness(exp-30d))), surfacing fresh directives and un-acted-on commitments that the heat-based lanes were blind to. Default half-life is exp-30d (slower than heat's exp-14d), sanity-checked against the live graph. -
sdd viewgainsparticipant()andtype()filters plus group-by-participant —participant(name)filters entries by canonical participant (disjoin within a call, intersect across calls; quoted multi-word names supported), andgroup(by(participant))buckets entries by author — multi-valued, so co-authored entries bucket under each author.type(d)/type(s)(full namesdecision/signalalso accepted) filters by entry type, mirroringlayer(). Answering "what did participant X capture" no longer needs grepping frontmatter.
Other changes
sdd viewbuilt-in help (viewHelpText) rewritten to enumerate the full implemented vocabulary — thesource()section, theparticipant/untagged/id()/not()filters,name-prefix, theas-counts/as-participants-block/as-wip-listterminators, and theparticipants/wipmacros — so baresdd viewhelp agrees with the binary again.- Bundled worktree recipe in the agent skills now re-anchors after entering a worktree (re-Read each file at its worktree path, flag the base-checkout path habit), fixing silent worktree-isolation failures.
Full Changelog: v0.11.1...v0.12.0
v0.11.1
Highlights
-
pre-flight— generalized artifact-durability rubric — A done signal no longer has to point at a commit to clear the durability check. Pre-flight now accepts any of several durable artifacts — a commit, an attachment on the entry or a referenced upstream entry, a URL to external work (PR/CI/deploy), or, for an act that changed nothing, a human participant's attestation — with "most specific artifact" as author guidance. The one hard requirement is scoped to changes to the repository's code or source: those must cite the commit that landed them. A done whose deliverable is an attached research, synthesis, or evaluation document is now durable via that attachment and is no longer false-blocked. Validated by the live pre-flight eval (10/10 on the durability subset). -
sdd init—--agentspersistence and symmetric prune on existing trees — On an existing tree, an explicitsdd init --agentsnow fully replaces and persistssupported_agents. When the selection drops a previously-recorded agent, its rendered skills are pruned using the same content-hash classification that drives overwrite protection: pristine files are removed, user-modified files are preserved and reported (removed only under--force), and emptied skill directories are cleaned up. A baresdd initis unchanged — the recorded value wins, no prune. Addsmodel.SetYAMLSequencefor flow-style sequence upserts in the config. -
type-system— fact/insight may dissolve a question —validateClosesnow permits afactorinsightsignal to close (dissolve) aquestion, the sanctioned signal-closes-signal path the framework always intended. The mechanical gate previously blocked it before pre-flight'sdissolutioncheck could run, forcing semantically false directive or done-signal workarounds when a finding simply answered an open question. Other non-done signal closures stay blocked. -
llm— OpenAI gpt-5 compatibility fix — gpt-5-class models rejectedmax_tokenswith an HTTP 400. The gollm fork's OpenAI request builder now emitsmax_completion_tokensforgpt-5*models (extending the predicate that already covered o-series and4o), so summary and pre-flight calls work against gpt-5. The Anthropic path was never affected.
Full Changelog: v0.11.0...v0.11.1
v0.11.0
Highlights
-
Multi-agent skill rendering — Codex support — SDD now renders its skills and instructions from a single agent-neutral template source to multiple agent harnesses, with Claude Code becoming one render target among several and OpenAI Codex the first non-Claude target. A committed
supported_agentslist in.sdd/config.yamlrecords which agents a project renders;sdd initoffers a multi-select on a fresh project, re-renders every listed agent idempotently on each run, and writes per-agent skill dirs (.claude/skills/,.agents/skills/). Codex skills conform to the open Agent Skills standard — SDD stamps undermetadata:, runtime undercompatibility:. Instructions bridge through a canonicalAGENTS.mdthatCLAUDE.mdimports via@AGENTS.md;sdd initscaffolds the bridge on a fresh project when a non-Claude agent is selected, never overwriting files you already have. Per-agent deviations (Claude'sSkill-tool sub-skills and dynamic injection vs. Codex's instructed$skillinvocation and explicitrun sdd …steps) are template conditionals from the one source — no duplicated definitions. Skill text generation moved to Gotext/templateunderneath, and the Claude render is verified byte-equivalent to the previous bundle, so nothing changes for current Claude Code users. -
surfaced-by— ninth ref-kind — A newsurfaced-byref-kind records, on an entry, that an earlier entry's work raised or produced it — the backward-class inverse ofsurfaces. This makes thesurfacespair order-independent (the waydepends-on/required-byalready is) and fills the case where the producing entry is a terminaldonesignal, whereaddressesis mechanically blocked and authors previously had to re-anchor onto a convenient live decision. The closed ref-kind set is now nine; CLI help, the MCP tool schema, the pre-flight rubric, and the skill/CLI references all enumerate it, and an eval case pins thesurfaced-by-vs-grounded-inboundary so it does not regress.
Known limitations
Codex support is new — treat it as experimental:
sdd init --agentsdoesn't persist on an existing project. Adding an agent to an already-initialized repo requires editingsupported_agentsin.sdd/config.yamlby hand for now (a freshsdd initpersists the selection correctly).- Codex sandbox approvals. Codex prompts for approval on the network- and LLM-backed commands SDD runs (search, capture) the first time it hits them — approve them so the first capture completes.
- OpenAI gpt-5-class models aren't usable as the LLM provider yet. They reject the
max_tokensparameter SDD sends (they requiremax_completion_tokens), breaking summary and pre-flight calls; the fix is pending in thenetworkteam/gollmfork. Use agpt-4omodel, or another provider, for now. - Behavioral parity is early. A first smoke run with gpt-5.5 held the full discipline loop through the thin port, but coverage is still limited.
Full Changelog: v0.10.0...v0.11.0
v0.10.0
Highlights
- Pre-flight ref-kind reliability rework — Ref-kind applicability decisions moved out of the LLM into a Go-declared matrix with deterministic mechanical enforcement, and the finding schema now emits its reasoning before the severity verdict — removing the severity-before-reasoning mechanism that drove cross-run oscillation (the same finding flipping high / absent / medium on identical input). The calibration eval gained six pinned leak cases with N-run pass-rate assertions and now stands at 29/29 clean. The rework also establishes an evidence-gated medium calibration as a standing directive: a ref-kind sharpness finding only rises above informational when the body itself supplies the contradicting evidence.
Other changes
-
Default LLM model for fresh and unconfigured installs changed from Haiku to
claude-sonnet-4-6, so pre-flight runs on the same model class the calibration eval measures. Configured graphs are unaffected. -
Experimental: new
sdd serveworkflow MCP server, exposing a session-based dialogue loop over stdio and HTTP. Early preview — the tool surface will change and is not yet stable.
Full Changelog: v0.9.0...v0.10.0
v0.9.0
Highlights
-
sdd stats— LLM & embedding usage analytics — A net-new command reading the per-call stats sink at.sdd/stats/llm.jsonl. It rolls up usage by model/provider over a selectable range (all-time / 30d / 7d) — call count, tokens in/out, cache read/create, total duration — plus per-op throughput for preflight, summarize, and embedding ops (tokens/s, ms/call, items/s). A styled lipgloss table renders for terminals; non-TTY consumers and agents get the same aggregates as structured JSON on stdout. An absent or empty sink yields a clean "no stats yet" result rather than an error. -
sdd showrestructure — The bespoke padded-label / arrow block is gone. Each entry now renders as a YAML frontmatter envelope (metadata, refs, closes, supersedes, attachments, derived status/topics) followed by its raw markdown body, with the upstream/downstream neighborhood as a compact markdown tree — one line per node (<ref-kind> <full-id> (<kind>, <status>) — <first-sentence>), indentation encoding depth, and a↳sub-line for ref descriptions. Two renderers share one data model: a lipgloss/glamour-styled view for terminals and plain markdown for agents and pipes, selected by TTY detection,--format text, andNO_COLOR. Depth is now controlled by independent--up N(grounding, default 2) and--down N(consumers, default 1, shown by default) flags — replacing--max-depth/--downstream— with0turning a direction off (--up 0 --down 0shows the entry alone). The stored summary is omitted by default; pass--with-summaryto include it for drift review. -
Interactive terminal output for
sdd index&sdd search— A new reusableinternal/clioutpackage drives a transient inline progress region — spinner, a determinate bar where a total is known, and an absolute count — that redraws in place at the bottom of normal terminal flow and clears on completion, with leveled log lines scrolling above it.sdd indexshows per-entry progress and a final summary;sdd searchkeeps lazy-fill indexing transient so only the ranked results remain. Producers stay oblivious: handlers and finders log only through the context logger, and the CLI layer alone decides whether that drives the TUI or a plain leveled stderr handler. Non-TTY consumers andNO_COLORget clean structured stderr logs and stdout results with no TUI — agents never see progress animation. -
Supersede-chain resolution — Refs and derived status now walk the supersede chain transitively to the live head instead of stopping at a superseded intermediate. A new
ResolvedRefmodel type exposes the ordered path from origin to head;sdd showandsdd viewexpand(refs)render the path to the head for stale targets only; pre-flight resolves each ref target to its live head before reasoning about it; and status reporting selects an active closer/superseder rather than a superseded one.sdd lintflags a fork — an entry with more than one currently-active head — as an anomaly. -
CLI color scheme — Styled TTY output is committed to a single concept-keyed palette so every command reads consistently: entry ids in gold, kinds and live-status words white-bold, ref kinds purple, YAML keys cyan, with prominence carried by weight rather than extra hues and closed/superseded nodes receding wholesale. Color lives only on the styled path — lipgloss renders through a colorprofile writer that downsamples to the terminal and strips color entirely for non-TTY writers or
NO_COLOR. Applied tosdd showandsdd stats.
Other changes
- Capture-time check blocks superseding a non-head entry, emitting a high-severity pre-flight finding that directs authors to the live head; settled branches stay exempt.
- The supersede-fork lint is narrowed to live forks only — a settled fork, where every branch has since closed or been superseded, stays quiet.
sdd initnow adds.sdd/stats/to the gitignore set it writes, so the machine-local stats sink is excluded on upgraded projects.
Full Changelog: v0.8.0...v0.9.0
v0.8.0
Highlights
-
sdd stats— LLM and embedding usage analytics — A new top-level command reads the per-call stats sink at.sdd/stats/llm.jsonland reports usage rolled up by model/provider and by operation (preflight, summarize, embed-documents, embed-queries) over a selectable--sincerange (all-time default, durations, or an ISO date). Each rollup shows call count, tokens in/out, cache read/create, total duration, and per-op throughput — tokens/s, ms/call, and items/s for embedding ops. Interactive terminals get a styled table; non-TTY and agent invocations get the same aggregates as structured JSON on stdout. A live--watchmonitor and graph-derived activity stats are scoped as follow-ups. -
sdd sync --pull— merge-only pull that never rewrites shared history — A new pull command that merges on a clean working tree (git pull --no-rebase) and refuses on a dirty one, so background sync can never rewrite the shared graph's history. The background sync-check status lines now speak in merge terms rather than rebase, and the/sddskill's conflict guidance was rewritten to a single-resolution merge flow — resolve once, one commit — in place of the old rebase-continue loop. -
Worktree workflow for concurrent agent sessions — The bundled
/sddskill now carries a worktree workflow recipe — shipped and refreshed bysdd init— for running an implementation session in an isolated git worktree and concluding it back to the branch. The recipe drives the agent harness's worktree entry/exit plus plain git plumbing (git worktree add, merge, branch delete), with a two-gate conclude: one confirmation to start, one to merge. By design nosddcommand owns the worktree lifecycle — a CLI subprocess can't relocate its caller's working directory, so the seamless part belongs to the harness and the rest is ordinary git. -
Pre-flight prompt caching restructure — The pre-flight system prompt is now a byte-stable, type-independent preamble with per-type rubrics, and proposed entries moved to the user prompt. The open-signal completeness scan was dropped from the decision-refs check in favor of skill-side coverage. Together this makes the cacheable prefix reusable across captures, cutting redundant token cost and reducing attention dilution as the graph grows.
Other changes
- Embedding calls now record per-batch timing and token data to
.sdd/stats/llm.jsonl, sosdd statscan report embedding throughput (verified live against Ollama). - Upgraded the charm TUI stack to v2 (bubbletea 2.0.7, bubbles 2.1.0, lipgloss 2.0.3);
sdd init's interactive prompts migrated to the new API. sdd initno longer fails when OS junk files like.DS_Storeare present — the skill embed now excludes dotfiles at the source rather than carrying them into the bundle.
Full Changelog: v0.7.1...v0.8.0