topic

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package topic parses and validates current-state topic inputs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreatedDocument added in v0.30.0

func CreatedDocument(files []ScaffoldFile) (presentation.Document, error)

CreatedDocument maps successfully created topic files into one path per line.

func ParseMetadata

func ParseMetadata(metadataRoot, path string, data []byte) (TopicID, Metadata, error)

func ParseSelector

func ParseSelector(selector string) (topicID, claimID string, err error)

func RenderIndex

func RenderIndex(tid string, template []byte, model IndexRenderModel) (string, error)

RenderIndex renders one domain's topic index from caller-supplied template identity and content, on the same contract as RenderTopic.

func RenderTopic

func RenderTopic(tid string, template []byte, model TopicRenderModel) (string, error)

RenderTopic renders one topic doc. Template identity and content are the caller's: the render pipeline already holds both (it hashes the same bytes into the drift signal), so this package never re-reads the embedded tree and template identity keeps its single derivation there.

func StaticReferenceDetail added in v0.30.0

func StaticReferenceDetail() presentation.Detail

StaticReferenceDetail maps the unadopted-project topic reference into the same presentation tree as ordinary topic output.

func SubstituteProvenance added in v0.30.0

func SubstituteProvenance(root string, renames map[string]string) error

SubstituteProvenance rewrites the authored claim parts under root so every `ADR-<slug>` provenance entry whose slug is a key of renames takes that record's assigned `ADR-NNNN` form, and every touched `Revised-by:` list is rewritten to the duplicate-free ascending order ADR-0191 requires.

This is the substitution half of numbering (ADR-0202 item 9), and it lives here because the `Origin:`/`Revised-by:` line grammar is this package's. Two scoping rules keep the effect exhaustive: it is anchored on those two metadata lines, so a slug named in claim prose is never rewritten, and it walks only .awf/topics/parts, so no generated topic doc, no domain part, no ADR body, and no plan is reachable from here. Generated outputs follow from the caller's re-render.

Types

type ADRHistory

type ADRHistory struct {
	Number string `json:"number"`
	Title  string `json:"title"`
	Status string `json:"status"`
}

type Backing

type Backing string
const (
	NoBacking         Backing = ""
	ExplicitNoBacking Backing = "none"
	TestBacking       Backing = "test"
	Unbacked          Backing = "unbacked"
)

type Claim

type Claim struct {
	ID, Slug              string
	Type                  ClaimType
	Prose                 string
	Summary               string
	Origin                string
	RevisedBy, References []string
	Backing               Backing
	Verify                string
}

type ClaimHistory

type ClaimHistory struct {
	ClaimID        string       `json:"claimId"`
	Origin         *ADRHistory  `json:"origin,omitempty"`
	LegacyBaseline bool         `json:"legacyBaseline,omitempty"`
	RevisedBy      []ADRHistory `json:"revisedBy"`
	RemovedBy      *ADRHistory  `json:"removedBy,omitempty"`
}

type ClaimReferences

type ClaimReferences struct {
	ClaimID  string   `json:"claimId"`
	Incoming []string `json:"incoming"`
	Outgoing []string `json:"outgoing"`
}

type ClaimType

type ClaimType string
const (
	Rule      ClaimType = "rule"
	Invariant ClaimType = "invariant"
)

type Corpus

type Corpus struct {
	DomainPaths map[string][]string
	Markers     MarkerIndex
	// contains filtered or unexported fields
}

func LoadAuthorityCorpusFromFiles added in v0.30.0

func LoadAuthorityCorpusFromFiles(files []snapshot.File, cfg *config.Config, adrs adr.Corpus) (Corpus, error)

LoadAuthorityCorpusFromFiles parses the reduced topic authority from the supplied snapshot files. Historical selections use this exact byte-fed core without materializing a complete Tree.

func LoadCorpus

func LoadCorpus(root string, cfg *config.Config, adrs adr.Corpus) (Corpus, error)

LoadCorpus parses the on-disk .awf/topics tree into a Corpus, reading domain ownership from cfg and scanning marker sources under root. It reads every input into memory and delegates the identity, provenance, reference, and marker assembly to assembleCorpus, the byte-fed core the snapshot loader shares.

func LoadCorpusFromTree added in v0.22.0

func LoadCorpusFromTree(tree *snapshot.Tree, cfg *config.Config, adrs adr.Corpus) (Corpus, error)

LoadCorpusFromTree parses the complete current-state topic corpus from an immutable snapshot. It retains domain ownership and marker validation for callers that need the complete repository projection.

func (Corpus) All

func (c Corpus) All() []Topic

func (Corpus) ByClaimID

func (c Corpus) ByClaimID(id string) (Claim, bool)

func (Corpus) ByTopicID

func (c Corpus) ByTopicID(id string) (Topic, bool)

func (Corpus) ForDomain

func (c Corpus) ForDomain(domain string) []Topic

func (Corpus) Incoming

func (c Corpus) Incoming(id string) []string

func (Corpus) Outgoing

func (c Corpus) Outgoing(id string) []string

type CoverageFinding added in v0.22.0

type CoverageFinding struct {
	Path            string       `json:"path"`
	Domain          string       `json:"domain,omitempty"`
	Kind            CoverageKind `json:"kind"`
	CandidateTopics []string     `json:"candidateTopics,omitempty"`
	// The rank is not part of this struct's wire form. Stated rather than left
	// implicit: an untagged exported field still marshals, as a bare 0 or 1.
	Severity severity.Rank `json:"-"`
	Topics   int           `json:"topics,omitempty"`
}

CoverageFinding is one deterministic coverage result. Domain names the owning domain of an Uncovered finding and is empty for a Fanout finding, which is emitted once per path across owners; Topics carries a Fanout finding's matching count. CandidateTopics names claim-bearing global topics in the uncovered domain whose ownership selector can be extended as one recovery.

func EvaluateCoverage added in v0.22.0

func EvaluateCoverage(c Corpus, paths []string, policy CoveragePolicy) []CoverageFinding

EvaluateCoverage returns the sorted coverage and fan-out findings for the eligible paths (ADR-0134 item 11). Every domain owning a path is evaluated independently: a domain with no claim-bearing topic owning the path yields one Uncovered finding at error, so a topic from one owner never satisfies another owner's gap. A global topic owns only its declared paths bounded by its parent domain. Across all owners the distinct owning topics matching a path are counted once; exceeding the budget yields a single Fanout finding at warn. The caller selects which checks run through the policy, and no value suppresses a requested check. Unowned paths are the context ownership concern and produce no finding here.

func (CoverageFinding) Message added in v0.34.0

func (c CoverageFinding) Message() string

Message renders the finding's semantic diagnostic. The model owner retains both the finding vocabulary and its actionable recovery mapping.

type CoverageKind added in v0.22.0

type CoverageKind string

CoverageKind distinguishes a missing topic-owner finding from a fan-out one.

const (
	// Uncovered marks a domain-owned path with no claim-bearing topic owner.
	Uncovered CoverageKind = "uncovered"
	// Fanout marks a path owned by more topics than the budget.
	Fanout CoverageKind = "fanout"
)

type CoveragePolicy added in v0.22.0

type CoveragePolicy struct {
	Coverage, Fanout bool
}

CoveragePolicy carries which coverage checks a caller wants evaluated. A caller that does not want a finding class does not request it; no value suppresses a requested check (ADR-0183 items 2 and 8).

type IndexRenderModel

type IndexRenderModel struct {
	Domain string
	Topics []TopicListItem
}

func BuildIndexModel

func BuildIndexModel(domain string, topics []Topic) IndexRenderModel

type MarkerIndex

type MarkerIndex struct {
	// contains filtered or unexported fields
}

func BuildMarkerIndex

func BuildMarkerIndex(root string, corpus Corpus, cfg *config.CurrentStateConfig) (MarkerIndex, error)

func (MarkerIndex) All

func (m MarkerIndex) All() []MarkerSite

func (MarkerIndex) ForClaim

func (m MarkerIndex) ForClaim(id string) []MarkerSite

type MarkerKind

type MarkerKind string
const (
	StateMarker   MarkerKind = "state"
	ProofMarker   MarkerKind = "invariant"
	TouchesMarker MarkerKind = "touches-state"
)

type MarkerSite

type MarkerSite struct {
	Path    string     `json:"path"`
	Line    int        `json:"line"`
	Kind    MarkerKind `json:"kind"`
	ClaimID string     `json:"claimId"`
	Note    string     `json:"note,omitempty"`
}

type Metadata

type Metadata struct {
	Title, Summary string
	Paths          []string
	Applies        string
}
type NavigationModel struct {
	IndexLink string
	Topics    []TopicListItem
}

func BuildNavigationModel

func BuildNavigationModel(domain string, topics []Topic) NavigationModel

type QueryClaim

type QueryClaim struct {
	ID      string    `json:"id"`
	Type    ClaimType `json:"type"`
	Prose   string    `json:"prose"`
	Backing Backing   `json:"backing"`
	Verify  string    `json:"verify,omitempty"`
}

type QueryCoverage

type QueryCoverage struct {
	Applicability TopicApplicability `json:"applicability"`
}

type QueryOptions

type QueryOptions struct {
	History, References, Coverage bool
}

QueryOptions selects independent detail projections for a current-state query.

type QueryResult

type QueryResult struct {
	Kind           string            `json:"kind"`
	ID             string            `json:"id"`
	Title          string            `json:"title,omitempty"`
	Summary        string            `json:"summary,omitempty"`
	Claims         []QueryClaim      `json:"claims"`
	History        []ClaimHistory    `json:"history,omitempty"`
	References     []ClaimReferences `json:"references,omitempty"`
	Coverage       *QueryCoverage    `json:"coverage,omitempty"`
	HistoricalOnly bool              `json:"historicalOnly,omitempty"`
}

QueryResult is the single deterministic semantic model used by human and JSON presentation. Optional detail blocks are nil unless their corresponding flag was requested.

func Query

func Query(c Corpus, adrs adr.Corpus, selector string, opts QueryOptions, currentPaths []string) (QueryResult, error)

Query resolves one active topic or claim and assembles only the requested direct detail. A qualified removed claim resolves only when History is set; it never traverses references or constructs tombstone state.

func (QueryResult) Detail added in v0.30.0

func (result QueryResult) Detail() presentation.Detail

Detail maps every selected topic query result field into the shared presentation tree. Topic owns this semantic mapping; presentation owns validation and text rendering.

type ScaffoldFile

type ScaffoldFile struct {
	Path    string
	Content []byte
}

ScaffoldFile is one repository-relative authored input produced for a topic.

func ScaffoldFiles

func ScaffoldFiles(root string, cfg *config.Config, domain, title string) ([]ScaffoldFile, error)

ScaffoldFiles validates and allocates the paired authored inputs for a topic. It inspects both trees but performs no writes.

type Topic

type Topic struct {
	ID                     TopicID
	Metadata               Metadata
	Intro, Part            string
	Claims                 []Claim
	MetadataPath, PartPath string
}

func ParsePart

func ParsePart(id TopicID, path string, data []byte) (Topic, error)

func TopicsForPath added in v0.22.0

func TopicsForPath(c Corpus, path string) []Topic

TopicsForPath returns the topics applicable to a repo-relative path: every global topic plus every path-scoped topic whose effective scope (its owning domain's paths intersected with the topic's own selectors) covers the path. Scoped topics are domain-bounded; global topics remain applicable outside their bounded ownership. Results are sorted by topic ID, so a caller's per-file selection is deterministic.

type TopicApplicability added in v0.22.0

type TopicApplicability struct {
	DeclaredGlobal  bool         `json:"declaredGlobal"`
	DomainPaths     []string     `json:"domainPaths"`
	TopicPaths      []string     `json:"topicPaths"`
	ApplicablePaths []string     `json:"applicablePaths"`
	OwnedPaths      []string     `json:"ownedPaths"`
	MarkerSites     []MarkerSite `json:"markerSites"`
}

TopicApplicability preserves separate witnesses for repository-wide authority and domain-bounded path ownership. ApplicablePaths and OwnedPaths are from the caller's selected universe, not symbolic glob-intersection proofs.

func ApplicabilityForTopic added in v0.22.0

func ApplicabilityForTopic(t Topic, domainPaths []string, markers MarkerIndex, currentPaths []string) TopicApplicability

type TopicID

type TopicID struct{ Domain, Slug string }

func (TopicID) String

func (id TopicID) String() string

type TopicListItem

type TopicListItem struct{ Slug, Title, Summary, Link string }

type TopicRenderModel

type TopicRenderModel struct{ Title, Summary, Applicability, Part string }

func BuildTopicModel

func BuildTopicModel(t Topic, domainPaths []string, markers MarkerIndex, currentPaths []string) TopicRenderModel

Jump to

Keyboard shortcuts

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