Skip to content

Releases: networkteam/sdd

v0.15.0

Choose a tag to compare

@hlubek hlubek released this 10 Jul 13:32

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 with sdd repo add <clone-url> (and manage connections with sdd repo list, sdd repo remove, sdd repo sync); each dependency is declared as a committed dependencies list in .sdd/config.yaml — the way go.mod declares modules — while the clone URL and homedir cache stay in your user-global config. sdd search and sdd view gain --repo <id> (repeatable) and --all-repos to 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 across sdd show, the show MCP 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 lint flags any cross-repo ref pointing at an undeclared one, and capture auto-fetches on cache miss. The same repo parameters are available through the MCP search, view, and show tools.

  • sdd config and 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 new sdd config command 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 init migrates an existing .sdd/index into the store without clobbering. Concurrent multi-process access is made safe by advisory file locking centralized in one seam. sdd index --repo <id> and sdd index --all-repos build connected indexes eagerly with visible progress, and --force now 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_session with 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 canceled error.
  • Text-only sdd search --repo gives honest first-time clone/pull feedback instead of a mislabeled indexing progress bar.
  • sdd new --summary accepts an explicit summary, bypassing generation for that entry.

Full Changelog: v0.14.1...v0.15.0

v0.14.1

Choose a tag to compare

@hlubek hlubek released this 07 Jul 16:52

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 to sdd wip done. A new removeMarker choice runs a wipRemove engine 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 the sdd binary 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 (over LoadGraph) 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 own MutatesGraph declaration, 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

Choose a tag to compare

@hlubek hlubek released this 06 Jul 21:24

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 new procedure decision 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 mechanical refsInspected gate — 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-engine skill. This is a preview surface: it runs alongside the untouched /sdd skill and you choose per session. /sdd remains 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 boxsdd init now installs and refreshes the project-scope MCP registration and pre-allows the mcp__sdd__* tools per supported agent, so a fresh session can drive procedures with no manual setup or per-tool permission prompts — .mcp.json plus .claude/settings.json for Claude Code, the equivalent .codex/config.toml for 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 lint warnings, and --attach entries 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 --text now regenerate the named entry's summary unconditionally; --all fills only entries with an empty summary, and --all --force regenerates every non-embedded entry. sdd lint drops both hash warnings (stale-hash and summary-without-hash) and keeps the missing-summary warning; sdd show no longer renders summary_hash. Existing files that still carry a summary_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_attachment hands 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

Choose a tag to compare

@hlubek hlubek released this 29 Jun 13:32

Highlights

  • intent — directive lifecycle attribute — Directives now carry a required intent attribute (pending | guiding | settled), supplied at capture via a new --intent flag (and the matching MCP capture arg). NewEntryCmd.Validate enforces 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. settled is 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, and sdd show, and [intent: guiding] on entry lines (pending and unspecified stay quiet). A new intent() view filter composes inside not(), catch-up action lanes now include directives but exclude guiding ones, and /sdd surfaces active guiding directives as a standing-context block. Pre-flight gains a settled-justification rubric 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 view and catch-up.

Full Changelog: v0.12.0...v0.13.0

v0.12.0

Choose a tag to compare

@hlubek hlubek released this 25 Jun 15:18

Highlights

  • sdd status and sdd list retired — overview folds onto sdd info + sdd view — Both standalone overview commands are gone. Session framing lives on sdd info (local participant, language, search modes); the kind-grouped overview and all filtered listing live on the sdd view pipeline, which had already absorbed both surfaces and made the hand-built presenters redundant. sdd status and sdd list now exit nonzero as unknown commands, and bare sdd prints help rather than masking a removed command. The shared EntryLine row format that sdd view and sdd search reuse is preserved; only the dedicated command stacks were removed.

  • Catch-up open-loops lane + coldness rank algorithmsdd view gains a coldness rank 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 view gains participant() and type() filters plus group-by-participantparticipant(name) filters entries by canonical participant (disjoin within a call, intersect across calls; quoted multi-word names supported), and group(by(participant)) buckets entries by author — multi-valued, so co-authored entries bucket under each author. type(d) / type(s) (full names decision / signal also accepted) filters by entry type, mirroring layer(). Answering "what did participant X capture" no longer needs grepping frontmatter.

Other changes

  • sdd view built-in help (viewHelpText) rewritten to enumerate the full implemented vocabulary — the source() section, the participant/untagged/id()/not() filters, name-prefix, the as-counts/as-participants-block/as-wip-list terminators, and the participants/wip macros — so bare sdd view help 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

Choose a tag to compare

@hlubek hlubek released this 18 Jun 19:46

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--agents persistence and symmetric prune on existing trees — On an existing tree, an explicit sdd init --agents now fully replaces and persists supported_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 bare sdd init is unchanged — the recorded value wins, no prune. Adds model.SetYAMLSequence for flow-style sequence upserts in the config.

  • type-system — fact/insight may dissolve a questionvalidateCloses now permits a fact or insight signal to close (dissolve) a question, the sanctioned signal-closes-signal path the framework always intended. The mechanical gate previously blocked it before pre-flight's dissolution check 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 rejected max_tokens with an HTTP 400. The gollm fork's OpenAI request builder now emits max_completion_tokens for gpt-5* models (extending the predicate that already covered o-series and 4o), 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

Choose a tag to compare

@hlubek hlubek released this 14 Jun 09:08

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_agents list in .sdd/config.yaml records which agents a project renders; sdd init offers 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 under metadata:, runtime under compatibility:. Instructions bridge through a canonical AGENTS.md that CLAUDE.md imports via @AGENTS.md; sdd init scaffolds the bridge on a fresh project when a non-Claude agent is selected, never overwriting files you already have. Per-agent deviations (Claude's Skill-tool sub-skills and dynamic injection vs. Codex's instructed $skill invocation and explicit run sdd … steps) are template conditionals from the one source — no duplicated definitions. Skill text generation moved to Go text/template underneath, 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 new surfaced-by ref-kind records, on an entry, that an earlier entry's work raised or produced it — the backward-class inverse of surfaces. This makes the surfaces pair order-independent (the way depends-on/required-by already is) and fills the case where the producing entry is a terminal done signal, where addresses is 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 the surfaced-by-vs-grounded-in boundary so it does not regress.

Known limitations

Codex support is new — treat it as experimental:

  • sdd init --agents doesn't persist on an existing project. Adding an agent to an already-initialized repo requires editing supported_agents in .sdd/config.yaml by hand for now (a fresh sdd init persists 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_tokens parameter SDD sends (they require max_completion_tokens), breaking summary and pre-flight calls; the fix is pending in the networkteam/gollm fork. Use a gpt-4o model, 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

Choose a tag to compare

@hlubek hlubek released this 11 Jun 12:20

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 serve workflow 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

Choose a tag to compare

@hlubek hlubek released this 09 Jun 14:18

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 show restructure — 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, and NO_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 — with 0 turning a direction off (--up 0 --down 0 shows the entry alone). The stored summary is omitted by default; pass --with-summary to include it for drift review.

  • Interactive terminal output for sdd index & sdd search — A new reusable internal/cliout package 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 index shows per-entry progress and a final summary; sdd search keeps 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 and NO_COLOR get 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 ResolvedRef model type exposes the ordered path from origin to head; sdd show and sdd view expand(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 lint flags 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 to sdd show and sdd 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 init now 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

Choose a tag to compare

@hlubek hlubek released this 08 Jun 08:08

Highlights

  • sdd stats — LLM and embedding usage analytics — A new top-level command reads the per-call stats sink at .sdd/stats/llm.jsonl and reports usage rolled up by model/provider and by operation (preflight, summarize, embed-documents, embed-queries) over a selectable --since range (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 --watch monitor 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 /sdd skill'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 /sdd skill now carries a worktree workflow recipe — shipped and refreshed by sdd 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 no sdd command 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, so sdd stats can 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 init no longer fails when OS junk files like .DS_Store are 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