export

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package export renders []storage.Entry into the machine-readable output formats used by `brag list --format ...` and `brag export --format ...`. The JSON shape is locked by DEC-011; the TSV shape mirrors the JSON field order with a header row.

Index

Constants

View Source
const TSVHeader = "id\ttitle\tdescription\ttags\tproject\ttype\timpact\tcreated_at\tupdated_at"

TSVHeader is the first line of `brag list --format tsv` output: 9 column names in the same order as DEC-011, separated by 8 tabs. No trailing newline — the caller writes it with one.

Variables

This section is empty.

Functions

func RenderEntry

func RenderEntry(w io.Writer, e storage.Entry, headingLevel int)

RenderEntry writes e as a markdown block to w. The title appears at headingLevel (e.g., 1 → "# ", 3 → "### "). The "Description" sub-heading appears one level below (headingLevel + 1).

Optional metadata rows (tags, project, type, impact) are suppressed when empty; an entry with no description omits the description heading entirely. Lifted from internal/cli/show.go in SPEC-015 — pre-lift behavior for `brag show` is preserved exactly at headingLevel == 1.

func ToCoverageJSON added in v0.4.0

func ToCoverageJSON(entries []storage.Entry, opts CoverageOptions) ([]byte, error)

ToCoverageJSON renders the DEC-014 envelope with DEC-033's payload keys. Every key is always emitted; on an empty window numbers are 0, filters {}, and by_month is still the full zero-filled month series so the trend slot is present even when empty. JSON never contains glyphs — the sparkline is a markdown-only rendering (DEC-031 choice f).

func ToCoverageMarkdown added in v0.4.0

func ToCoverageMarkdown(entries []storage.Entry, opts CoverageOptions) ([]byte, error)

ToCoverageMarkdown renders the in-window entries as the coverage digest per DEC-014/DEC-033: header + provenance block, then ## Provenance share (agent vs human counts + %), ## Monthly trend (the agent-share sparkline + per-month lines), and ## Self-reference. Returns bytes with the trailing "\n" stripped (matches every other renderer). On an empty window only the header + provenance block (through "Entries: 0") is emitted; the body sections are omitted (DEC-014 part 4).

func ToImpactJSON added in v0.4.0

func ToImpactJSON(entries []storage.Entry, opts ImpactOptions) ([]byte, error)

ToImpactJSON renders the DEC-014 envelope with DEC-028's per-spec payload keys: generated_at, scope, filters, entries_in_window, entries_with_impact, counts_by_project (map over the with-impact subset), impact_by_project (array of grouped 4-key projections). 2-space indent. Empty-state per DEC-014 choice (4): counts {}, impact_by_project [], filters {}, never null.

func ToImpactMarkdown added in v0.4.0

func ToImpactMarkdown(entries []storage.Entry, opts ImpactOptions) ([]byte, error)

ToImpactMarkdown renders the in-window entries as an impact-first digest per DEC-014/DEC-028. The renderer receives the already-in- window slice; it selects the with-impact subset (aggregate.WithImpact), groups it by project (aggregate.GroupEntriesByProject), and renders each shown entry's impact text in full. Returns bytes with the trailing "\n" stripped (matches ToSummaryMarkdown). On zero with- impact entries, only the header + provenance block is emitted; the ## Impact body is omitted.

func ToJSON

func ToJSON(entries []storage.Entry) ([]byte, error)

ToJSON marshals entries per DEC-011: naked array, 9 keys in SQL- column order, tags comma-joined string, timestamps RFC3339, empty fields as "", pretty-printed with 2-space indent. Empty/nil input returns exactly "[]" (never "null").

func ToMarkdown

func ToMarkdown(entries []storage.Entry, opts MarkdownOptions) ([]byte, error)

ToMarkdown renders entries as a review-ready markdown document per DEC-013. Returns bytes with the trailing "\n" stripped; the CLI layer appends one newline via fmt.Fprintln, matching ToJSON's byte contract. Empty entries slice returns header + provenance block only (no summary, no groups).

func ToMemoryJSON added in v0.6.0

func ToMemoryJSON(result memory.Result, opts MemoryOptions) ([]byte, error)

ToMemoryJSON renders the DEC-014 envelope with SPEC-073's payload keys. Every key is always emitted; on an empty candidate pool numbers are 0, filters {}, and slice [] (non-nil). score is rounded to 6 decimal places (DEC-043 sub-decision 6) so the goldens stay readable and the constants stay observable.

func ToMemoryMarkdown added in v0.6.0

func ToMemoryMarkdown(result memory.Result, opts MemoryOptions) ([]byte, error)

ToMemoryMarkdown renders a memory.Result as the DEC-014/DEC-043/DEC-044 memory-slice digest: header + provenance block, then ## Slice (the ranked, budget-trimmed entry lines) and ## Budget (the accounting). Entries: N is the CANDIDATE-POOL size, not the included count — the ## Budget section decomposes it. On an empty candidate pool only the header block (through "Entries: 0") is emitted — no ## Slice, no ## Budget (DEC-014 part 4). A non-empty pool that includes zero entries still renders both sections. Returns bytes with the trailing "\n" stripped (matches every other renderer).

func ToProjectJSON added in v0.2.0

func ToProjectJSON(p storage.Project) ([]byte, error)

ToProjectJSON renders a single project as a JSON object (not an array) for `brag project show --format json`. 2-space indent; an empty Locations renders "[]", never "null".

func ToProjectStatusesJSON added in v0.2.0

func ToProjectStatusesJSON(statuses []storage.ProjectStatus) ([]byte, error)

ToProjectStatusesJSON renders dashboard rows as a naked JSON array (DEC-011 shape; 2-space indent). Empty/nil input renders "[]", never "null".

func ToProjectsJSON added in v0.2.0

func ToProjectsJSON(projects []storage.Project) ([]byte, error)

ToProjectsJSON renders projects as a naked JSON array (DEC-011 shape; 2-space indent). Empty/nil input renders "[]", never "null".

func ToProjectsMarkdown added in v0.6.0

func ToProjectsMarkdown(statuses []storage.ProjectStatus) ([]byte, error)

ToProjectsMarkdown renders statuses as the `brag://projects` resource body (SPEC-074 LD10): every non-archived project, most-recently-updated first, with its status and brag count. Locations and state_note are deliberately excluded (DEC-045 sub-decision 3) — this is a name-selection lookup for the `brag://memory/project/{name}` template, not a dashboard. Returns bytes with the trailing "\n" stripped (matches every other renderer).

func ToReviewJSON

func ToReviewJSON(entries []storage.Entry, opts ReviewOptions) ([]byte, error)

ToReviewJSON renders the DEC-014 envelope for brag review. Per-entry shape inside entries_grouped[].entries is the DEC-011 9-key shape (via the toEntryRecord helper).

func ToReviewMarkdown

func ToReviewMarkdown(entries []storage.Entry, opts ReviewOptions) ([]byte, error)

ToReviewMarkdown renders the DEC-014 markdown digest for brag review. Returns bytes with trailing "\n" stripped (matches the byte contract of the other renderers). The Reflection questions block ALWAYS renders, even on empty entries — the questions are the point of the command.

func ToSparkJSON added in v0.5.0

func ToSparkJSON(entries []storage.Entry, opts SparkOptions) ([]byte, error)

ToSparkJSON renders the DEC-014 envelope with SPEC-059's payload keys. Every key is always emitted; on an empty window total is the full zero-filled series, by_project is [] (non-nil), and filters is {}. JSON never contains glyphs — each row carries a raw series int array (DEC-031 choice f).

func ToSparkMarkdown added in v0.5.0

func ToSparkMarkdown(entries []storage.Entry, opts SparkOptions) ([]byte, error)

ToSparkMarkdown renders the in-window entries as the sparkline pulse per DEC-014/DEC-037: header + provenance block, then ## Pulse with a Total row and the by-project rows. Each row is "<label> (<count>): <glyphs>" (or raw space-joined counts when opts.Spark is false). On an empty window only the header block (through "Entries: 0") is emitted; the ## Pulse body is omitted (DEC-014 part 4). Trailing newline stripped (matches every other renderer).

func ToStatsJSON

func ToStatsJSON(entries []storage.Entry, opts StatsOptions) ([]byte, error)

ToStatsJSON renders the JSON envelope per DEC-014 with the SPEC-020 per-spec payload keys at top level.

func ToStatsMarkdown

func ToStatsMarkdown(entries []storage.Entry, opts StatsOptions) ([]byte, error)

ToStatsMarkdown renders stats as the DEC-014 markdown digest. Returns bytes with trailing "\n" stripped (matches the byte contract of the other renderers). Empty entries → header + provenance only (no ## Stats wrapper, no metric body) per DEC-014 part (4).

func ToSummaryJSON

func ToSummaryJSON(entries []storage.Entry, opts SummaryOptions) ([]byte, error)

ToSummaryJSON renders the JSON envelope per DEC-014: single object, flat top-level keys (generated_at, scope, filters, counts_by_type, counts_by_project, highlights), pretty-printed with 2-space indent. Empty-state values per DEC-014 choice (4): counts maps render as {} and highlights as [], never null.

func ToSummaryMarkdown

func ToSummaryMarkdown(entries []storage.Entry, opts SummaryOptions) ([]byte, error)

ToSummaryMarkdown renders entries as a rule-based digest per DEC-014. Returns bytes with the trailing "\n" stripped (matches ToJSON / ToMarkdown). On empty input, only the header + provenance block is emitted; the Summary and Highlights sections are omitted.

func ToTSVRow

func ToTSVRow(e storage.Entry) string

ToTSVRow renders one storage.Entry as a tab-separated data row. Field order matches TSVHeader and DEC-011. Embedded tabs in user text are NOT escaped — same accepted MVP trade-off as `brag list` plain mode.

func ToTagsJSON added in v0.2.0

func ToTagsJSON(tags []storage.TagCount) ([]byte, error)

ToTagsJSON renders the tag taxonomy as a naked JSON array of {tag, count} objects (DEC-011 shape; DEC-016 choice 1). Empty input renders "[]", never "null".

func ToWrappedJSON added in v0.4.0

func ToWrappedJSON(entries []storage.Entry, opts WrappedOptions) ([]byte, error)

ToWrappedJSON renders the DEC-014 envelope with DEC-030's per-spec payload keys. Every key is always emitted; on an empty period arrays are [], objects {}, busiest_month/date fields null, numbers 0 (DEC-014 part 4) — but cadence.series is still the full zero-filled month series so the sparkline slot is present even when empty.

func ToWrappedMarkdown added in v0.4.0

func ToWrappedMarkdown(entries []storage.Entry, opts WrappedOptions) ([]byte, error)

ToWrappedMarkdown renders the in-period entries as the celebratory wrapped digest per DEC-014/DEC-030: provenance, then the section arc Cadence → Top initiatives → Impact moments → Rhythm → Span. Returns bytes with the trailing "\n" stripped (matches every other renderer). On an empty period only the header + provenance block (through "Entries: 0") is emitted; the body sections are omitted (DEC-014 part 4).

Types

type CoverageOptions added in v0.4.0

type CoverageOptions struct {
	Scope       string
	Filters     string
	FiltersJSON map[string]string
	ScopeMonths []string
	Now         time.Time
	Spark       bool
}

CoverageOptions controls the rule-based coverage digest (SPEC-045), the sixth DEC-014 consumer. Scope echoes the DEC-028/DEC-032 window token ("year", "quarter:previous", "since:<raw>"). Filters is the pre-formatted markdown line ("(none)" or echoed flags); FiltersJSON is the object the JSON envelope renders (nil → {}). ScopeMonths is the ordered set of "YYYY-MM" labels in scope — the CLI derives it from the window so the monthly series is always fully present (zero-filled), even on an empty window. Now is injected for a deterministic Generated: line.

The renderer receives the ALREADY-in-window slice (the CLI does the bounded-window filtering) plus ScopeMonths, exactly like wrapped. Spark, when true and rendering markdown, prints the agent-share sparkline line inside ## Monthly trend (DEC-031); JSON ignores it — a sparkline is a lossy visual of by_month[].share, not data (DEC-031 choice f).

type ImpactOptions added in v0.4.0

type ImpactOptions struct {
	Scope           string
	Filters         string
	FiltersJSON     map[string]string
	EntriesInWindow int
	Now             time.Time
}

ImpactOptions controls the rule-based impact digest (SPEC-048), the fourth DEC-014 consumer. Scope echoes the window token ("quarter"|"month"|"year"|"since:<raw>"). Filters is the pre-formatted markdown line ("(none)" or echoed flags); FiltersJSON is the object the JSON envelope renders (nil → {}). EntriesInWindow is the raw in-window count (the CLI does the windowing and passes it so the renderer can print the <shown>/<in-window> tally without re-deriving it). Now is injected for deterministic goldens. DEC-014 locks the envelope; DEC-028 locks the per-spec payload.

type MarkdownOptions

type MarkdownOptions struct {
	Flat    bool
	Filters string
	Now     time.Time
}

MarkdownOptions controls ToMarkdown's output. Flat switches from grouped-by-project to a single chronological section. Filters is the pre-formatted value the CLI layer assembled from its flag state (e.g. "(none)" or "--project platform --since 7d"). Now is the timestamp rendered into the "Exported:" provenance line — injected (not time.Now()-called internally) so tests produce deterministic goldens.

type MemoryOptions added in v0.6.0

type MemoryOptions struct {
	Filters     string
	FiltersJSON map[string]string
	Now         time.Time
}

MemoryOptions controls the rule-based memory-slice digest (SPEC-073), the eighth DEC-014 consumer. Scope is always "lifetime" (memory ranks the whole corpus, like stats) and is hard-coded rather than a field. Filters is the pre-formatted markdown line ("(none)" or "--query X --project Y" in declared order); FiltersJSON is the object the JSON envelope renders (Go's map encoder sorts keys alphabetically — the documented DEC-014 markdown/JSON ordering asymmetry). Now is injected for a deterministic Generated: line.

type ReviewOptions

type ReviewOptions struct {
	Scope string
	Now   time.Time
}

ReviewOptions controls ToReviewMarkdown / ToReviewJSON. Scope is "week" or "month" (echoed into provenance + envelope). Now is injected for deterministic Generated: lines (mirrors MarkdownOptions.Now + SummaryOptions.Now). No Filters field — review does not accept filter flags; "(none)" is hard-coded in the markdown provenance line and {} is hard-coded in the JSON envelope.

type SparkOptions added in v0.5.0

type SparkOptions struct {
	Scope   string
	Now     time.Time
	Width   time.Duration
	Buckets int
	Project string
	Spark   bool
}

SparkOptions controls the rule-based sparkline "pulse" digest (SPEC-059), the seventh DEC-014 consumer. Scope echoes the rolling-window token ("week"/"month"/"quarter"). Now is the injected wall clock (the axis end); Width and Buckets define the rolling axis passed to aggregate.RollingBuckets. Project, when non-empty, is a ROW SELECTOR (DEC-037 choice 3): the by-project rows collapse to that one project (rendered even at zero count), while the Total row still spans the whole in-window corpus. Empty Project → the top-8 by-project auto-selection. Spark, when true and rendering markdown, prints the glyph rows; when false it falls back to raw per-bucket counts. JSON never carries glyphs — each row carries a raw series int array (DEC-031 choice f).

type StatsOptions

type StatsOptions struct {
	Now time.Time
}

StatsOptions controls the rule-based stats digest. Now is injected for deterministic Generated: lines AND for the streak today-reference (single source — the renderer passes opts.Now straight through to aggregate.Streak). NO Scope field — stats always renders "Scope: lifetime". NO Filters / FiltersJSON fields — stats accepts no filter flags; "Filters: (none)" / "filters": {} are hard-coded. SPEC-020.

type SummaryOptions

type SummaryOptions struct {
	Scope       string
	Filters     string
	FiltersJSON map[string]string
	Now         time.Time
}

SummaryOptions controls the rule-based summary digest. Filters is the pre-formatted markdown line ("(none)" or an echoed flag string); FiltersJSON is the object the JSON envelope renders (empty map → "{}", populated → an object with alphabetically-sorted keys per Go's encoding/json map handling). Now is injected for deterministic goldens — mirrors MarkdownOptions.Now. DEC-014 locks the shape.

type WrappedOptions added in v0.4.0

type WrappedOptions struct {
	Scope       string
	Filters     string
	FiltersJSON map[string]string
	ScopeMonths []string
	Now         time.Time
	// Spark, when true and rendering markdown, prints the cadence
	// sparkline line inside ## Cadence (SPEC-052). JSON ignores it — a
	// sparkline is a lossy visual of cadence.series[].count, not data.
	Spark bool
}

WrappedOptions controls the rule-based wrapped digest (SPEC-051), the fifth DEC-014 consumer. Scope echoes the named-period token ("2026" or "2026-Q3"). Filters is the pre-formatted markdown line ("(none)" or echoed flags); FiltersJSON is the object the JSON envelope renders (nil → {}). ScopeMonths is the ordered set of "YYYY-MM" labels in scope (12 for a year, 3 for a quarter) — the CLI derives it from the period so the cadence series is always fully present, even on an empty period. Now is injected for a deterministic Generated: line.

The renderer receives the ALREADY-in-period slice (the CLI does the bounded-window filtering, DEC-030 choice 3) plus ScopeMonths. Now here only feeds the Generated: line: wrapped surfaces LONGEST streak, which is period-scoped and independent of now (DEC-022 / DEC-030 note), so the streak number never couples to the clock seam.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL