Documentation
¶
Overview ¶
Package presenters renders structured query results as text for CLI output. Presenters take pure data from finders plus an io.Writer and formatting parameters; they have no IO of their own beyond the writer.
The package isolates the view layer from finders (data) and from CLI command plumbing — separating concerns so each can be tested in isolation.
Index ¶
- func EntryLine(w io.Writer, e *model.Entry, g *model.Graph)
- func EntryLineWithScore(w io.Writer, e *model.Entry, g *model.Graph, score float64)
- func FormatConfidence(c string) string
- func FormatScore(score float64) string
- func FormatSearchCapability(vectorAvailable bool) string
- func FormatStatus(s model.Status) string
- func FormatStatusTrail(s model.Status, supersedePath []string) string
- func FormatTopics(paths []model.TopicPath) string
- func GroupByLayer(entries []*model.Entry) map[model.Layer][]*model.Entry
- func LayerOrder() []model.Layer
- func RenderInfo(w io.Writer, result *query.InfoResult)
- func RenderInitPrune(w io.Writer, result command.AgentPruneResult)
- func RenderInitSkills(w io.Writer, installDir string, result command.SkillInstallResult)
- func RenderLint(w io.Writer, result *query.LintResult, g *model.Graph)
- func RenderList(w io.Writer, result *query.ListResult)
- func RenderResultLine(dst io.Writer, headline, detail string)
- func RenderSchemaError(w io.Writer, compat model.CompatibilityResult)
- func RenderSearch(w io.Writer, result *query.SearchResult, g *model.Graph)
- func RenderShow(w io.Writer, result *query.ShowResult, opts ShowOptions)
- func RenderShowStyled(dst io.Writer, result *query.ShowResult, opts ShowOptions)
- func RenderStatsJSON(w io.Writer, r *query.StatsResult) error
- func RenderStatsTable(dst io.Writer, r *query.StatsResult)
- func RenderStatus(w io.Writer, result *query.StatusResult)
- func RenderView(w io.Writer, result *query.ViewResult)
- func RenderWIPList(w io.Writer, result *query.WIPListResult)
- type ShowOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EntryLine ¶
EntryLine writes a single entry summary line — used by status, list, and other surfaces that show entries in a flat list.
Format: `<id> <layer> <kind>? <type> [confidence: <conf>]? (<participants>) {status: <status>}? {score: <score>}? <topics>? <summary>` Kind renders as a qualifier alongside layer/type — it's identity, not an attribute (d-cpt-omm's two-type redesign makes every entry carry a kind). Square brackets denote stored attributes (today: confidence); curly braces denote derived attributes computed from graph relationships (d-tac-3yi); angle brackets denote topic membership (also derived — inline topics merged with annotation declarations). Participants are always present — empty is rendered as `()`. Status is present for signals and decisions; omitted for done signals (terminal). Topics are omitted entirely when the effective set is empty. Score is per-rendering, computed by a rank algorithm; emitted only via EntryLineWithScore (slice 3 — d-tac-uww).
func EntryLineWithScore ¶ added in v0.5.0
EntryLineWithScore is EntryLine plus a `{score: X.XXX}` segment after status. Used by the as-list renderer when the section was ranked.
func FormatConfidence ¶
FormatConfidence renders a stored confidence attribute in square-bracket notation.
func FormatScore ¶ added in v0.5.0
FormatScore renders a per-rendering rank score in curly-brace notation alongside the other derived-attribute segments. Three decimal places balance precision with line length — heat scores are typically small floats (a few units) and three places preserves enough resolution to distinguish similar entries.
func FormatSearchCapability ¶ added in v0.4.0
FormatSearchCapability renders the capability suffix shown in `sdd status`'s header: `text` when only text mode is available; `vector,text` when a vector embedder is configured. Used by callers that want to surface the search surface alongside other status fields.
func FormatStatus ¶
FormatStatus renders a derived status in curly-brace notation. Returns the empty string for StatusNone so callers can omit the attribute. Compound states use a space separator in the value (`closed-by <id>`) to avoid ambiguity with the outer `{key: value}` delimiter.
func FormatStatusTrail ¶ added in v0.9.0
FormatStatusTrail renders the status segment for a ref sub-line, expanding a superseded target into its full supersede trail through to the live head: `{status: superseded-by <hop1> → … → <head>}`. supersedePath is the resolved origin→head path (model.ResolveRef(...).Path()); its first element is the origin (the sub-line's own entry) and is dropped, so the rendered hops are the superseders ending at the head. When the target is not superseded (path length ≤ 1) this is identical to FormatStatus — only ref sub-lines, where a reader is traversing a reference, surface the intermediate hops; flat surfaces keep the head-only form.
func FormatTopics ¶ added in v0.5.0
FormatTopics renders an entry's effective topic set in angle-bracket notation (`<label1, label2>`). Returns the empty string when the set is empty so callers can omit the segment entirely.
func GroupByLayer ¶
GroupByLayer groups entries by layer for display. Returns a map from layer to entries; iterate with LayerOrder to render in canonical order.
func LayerOrder ¶
LayerOrder returns the display order for layers (strategic → process).
func RenderInfo ¶ added in v0.5.2
func RenderInfo(w io.Writer, result *query.InfoResult)
RenderInfo writes the session-framing header — participant, language (when configured), and search capability. The same lines prefix `sdd status` (via writeInfoHeader), so the two surfaces stay in lockstep.
func RenderInitPrune ¶ added in v0.11.1
func RenderInitPrune(w io.Writer, result command.AgentPruneResult)
RenderInitPrune summarises the skill files removed for an agent dropped from supported_agents, and lists any user-modified files left untouched.
func RenderInitSkills ¶ added in v0.2.0
func RenderInitSkills(w io.Writer, installDir string, result command.SkillInstallResult)
RenderInitSkills summarises a skill install pass for the user. Counts are always printed; individual paths appear only for categories that warrant per-path attention (overwritten, skipped-modified).
func RenderLint ¶
RenderLint writes a human-readable lint report to w. Returns nothing — the caller decides what to do about a non-zero issue count (typically returning a non-zero exit code from the CLI).
func RenderList ¶
func RenderList(w io.Writer, result *query.ListResult)
RenderList writes one EntryLine per matched entry.
func RenderResultLine ¶ added in v0.9.0
RenderResultLine writes a completed-operation summary in the CLI palette: a prominent headline (bold white, the qualifier style) followed by faint detail. On a non-TTY destination or with NO_COLOR the colorprofile writer downsamples to plain text, so agents and pipes get a clean line. detail may be empty.
This is the styled-feedback surface the terminal-experience directive (d-cpt-mvb) calls for, sharing the palette established by d-cpt-n0f so the summary reads as one piece with sdd show and sdd stats.
func RenderSchemaError ¶ added in v0.2.0
func RenderSchemaError(w io.Writer, compat model.CompatibilityResult)
RenderSchemaError writes a user-facing explanation of a compatibility failure to w. The CompatibilityResult.Reason is already human-readable; this presenter frames it with a fixed prefix and exit hint so output reads the same across every write command.
func RenderSearch ¶ added in v0.4.0
RenderSearch writes one section per ranked entry: a header line that matches `sdd list` shape, then one citation line per entry-citation (capped by SearchQuery.MaxCitationsPerEntry on the finder side).
Render format (single-citation case):
<id> <layer> <kind>? <type> [confidence: ?]? (<participants>) {status: ?}? <summary>
↳ 100% · Breadcrumb > Chain · <snippet>
Render format (multi-citation case):
<id> ... ↳ 100% · Summary · <snippet> ↳ 91% · Approach > Storage · <snippet> ↳ 87% · ... [attachment: ...] · <snippet>
The percentage is each citation's score normalized against the strongest score in the result set — the top citation everywhere renders 100%, others scale relative. This is honest about the cross- entry ranking without making any claims about absolute "confidence" (cosine values aren't calibrated across embedders, and text-mode match counts and hybrid RRF scores live on different scales than cosine — but ALL citations within a single result set share whatever scale the active mode uses).
func RenderShow ¶
func RenderShow(w io.Writer, result *query.ShowResult, opts ShowOptions)
RenderShow writes the plain-markdown show output for a ShowResult. Each group renders as a YAML frontmatter envelope + raw markdown body for the primary, followed by compact markdown trees for the upstream and downstream neighborhoods (each present to the depth the query set; an empty direction is omitted). Groups are separated by a blank line — each is a self-contained frontmatter+body markdown document.
This is the agent / pipe / `--format text` renderer; the styled terminal renderer shares the same data model (see the styled renderer / slice 3).
func RenderShowStyled ¶ added in v0.9.0
func RenderShowStyled(dst io.Writer, result *query.ShowResult, opts ShowOptions)
RenderShowStyled writes the styled, human-facing show output for an interactive terminal: a dimmed YAML envelope, the markdown body rendered with glamour, and a lipgloss-styled neighborhood tree (relation-kind color, dimmed status, dim indent guides). It shares the read-side data model with the plain renderer (RenderShow) — only presentation differs.
The colorprofile writer downsamples ANSI to the destination's capability and strips it for a non-terminal writer (d-cpt-mvb), so a plain io.Writer — a test buffer or a pipe — receives clean, color-free structured text.
func RenderStatsJSON ¶ added in v0.9.0
func RenderStatsJSON(w io.Writer, r *query.StatsResult) error
RenderStatsJSON writes the same aggregates as structured JSON on the agent / non-TTY path — no styling, no chrome. An empty sink yields valid JSON with zeroed totals and empty arrays (a clean result, exit 0), not an error.
func RenderStatsTable ¶ added in v0.9.0
func RenderStatsTable(dst io.Writer, r *query.StatsResult)
RenderStatsTable writes the styled, human-facing usage report: a header and source line, an overall totals block, then per-model and per-op tables. Used on the interactive TTY path. The empty cases (no sink yet, or nothing in the selected range) render a single explanatory line instead of blank tables.
lipgloss styles always emit ANSI at Render() time; the colorprofile writer downsamples to the destination's actual capability and strips color when NO_COLOR is set or the writer is not a terminal — so a plain io.Writer (a test buffer, a pipe) gets clean text and a real TTY keeps color (d-cpt-mvb).
func RenderStatus ¶
func RenderStatus(w io.Writer, result *query.StatusResult)
RenderStatus writes the status view: top-line counts, then one section per decision kind (Aspirations, Contracts, Plans, Activities, Directives), followed by the signal sections (Gaps and Questions, Recent Insights, Recent Done Signals). Decision-kind sections are grouped by layer; signal sections are flat activity streams. Empty sections are suppressed — the section header implies membership, so "open" / "active" prefixes are not needed on the headers.
func RenderView ¶ added in v0.5.0
func RenderView(w io.Writer, result *query.ViewResult)
RenderView writes one section per SectionResult, dispatching to the per-render helper based on the section's Render name. Sections are separated by a blank line so visual clusters are obvious. A non-empty Section.Name renders as a `## <name>` header before the section body; empty Name omits the header (the as-list / as-grouped default).
Render names are matched against the slice's known set; unknown names silently produce no output for that section. The finder validates the pipeline shape before reaching here, so an unknown name implies a programmer-side mistake (a layout produced by some path other than the parser+executor) rather than a user-facing error.
func RenderWIPList ¶
func RenderWIPList(w io.Writer, result *query.WIPListResult)
RenderWIPList writes the active WIP markers in a fixed-width layout.
Types ¶
type ShowOptions ¶ added in v0.9.0
type ShowOptions struct {
// WithSummary includes the primary's stored summary in the envelope.
// Off by default — the body renders right after the envelope, and the
// summary is only needed for human drift-review.
WithSummary bool
// Width is the target wrap width for the styled renderer's glamour body
// (terminal columns). Zero falls back to a sensible default. Ignored by
// the plain renderer, which never reflows the body.
Width int
}
ShowOptions controls optional segments of the show rendering.