Documentation
¶
Overview ¶
Package entity parses and represents SpecScore entity artifacts (`*.entity.md` files under `spec/features/**`).
The package is a leaf parser: it provides Discover, Parse, and Walk over entity files plus a typed Doc representation. Lint rules and CLI verbs that consume entities import this package; parsing here never imports `pkg/lint` or `internal/cli`.
Parse is intentionally resilient — it returns a partial Doc for malformed input so lint can report every issue rather than bailing on the first. See `spec/features/cli/entity/README.md` for the validation contract.
Index ¶
- Constants
- func ResolveInherits(specRoot, entityPath, inherits string) (string, bool, error)
- func ResolveRef(specRoot, entityPath, ref string) (string, bool, error)
- func ValidateSlug(slug string) error
- func Walk(specRoot string, fn func(*Doc) error) error
- type Discovered
- type Doc
- type Frontmatter
- type PropertyItem
- type Section
Constants ¶
const EntitySuffix = ".entity.md"
EntitySuffix is the canonical filename suffix for entity files.
Variables ¶
This section is empty.
Functions ¶
func ResolveInherits ¶
ResolveInherits takes a frontmatter `inherits:` value and returns the absolute path of the referenced .entity.md file. Mirrors ResolveRef's URL handling so cross-repo inheritance and cross-repo property references share the same surface.
func ResolveRef ¶
ResolveRef takes a property item's `ref:` value (relative path or URL) and returns the absolute path of the referenced .property.md file, plus a boolean indicating whether the path resolved within specRoot.
URLs return ("", false, nil) — the caller decides whether to flag the URL form as a broken reference. Today the URL form is permitted (per [entity#req:ref-target-exists] which allows the URL form "when cross-repo imports land"); lint MUST NOT treat it as a violation.
func ValidateSlug ¶
ValidateSlug returns nil if slug matches `[a-z0-9]+(-[a-z0-9]+)*` per [entity#req:slug-format].
func Walk ¶
Walk is a convenience wrapper: Discover + Parse, invoking fn for each discovered entity. Returns the first non-nil error from fn; nil otherwise. I/O errors during discovery are returned as-is. Parse errors are propagated only when Parse itself returns one (I/O failure); malformed-but-readable files are still passed to fn with a partial Doc, matching Parse's resilience contract.
Types ¶
type Discovered ¶
type Discovered struct {
Slug string // filename stem without ".entity.md"
Path string // absolute path to the .entity.md file
}
Discovered is a summary of an entity file found during a Discover walk.
func Discover ¶
func Discover(specRoot string) ([]Discovered, error)
Discover walks `<specRoot>/features/**/*.entity.md` and returns every discovered entity. Hidden directories (path segment starting with ".") and reserved underscore-prefixed directories (e.g., "_tests") are skipped — same convention used by walkMatchingFiles in pkg/lint/adherence_footer.go and required by [cli/entity#req:discovery-scope].
Returns ([], nil) when `<specRoot>/features` does not exist. Returns absolute paths and is deterministic across invocations (results are sorted by path).
type Doc ¶
type Doc struct {
Path string
Slug string
RawLines []string // body lines for managed-section rewriting
Title string // full `# Entity: ...` title line, "" if absent
TitleName string // the `<singular>` portion after "Entity: "
TitleOK bool // true if Title matches "# Entity: <Name>"
TitleLine int // 1-based line number of the title
HasTitle bool
Frontmatter *Frontmatter // nil when frontmatter is absent or unparseable
FmRaw *yaml.Node // round-trippable node for --fix mutations
Sections []Section
SectionByTitle map[string]*Section
Properties []PropertyItem // mirrors Frontmatter.Properties for convenience
}
Doc is a parsed entity file. The struct is intentionally permissive — Parse returns a partial Doc even when the file is malformed, so lint rules can report every issue they find rather than bailing on the first.
func Parse ¶
Parse reads the file at `path` and returns a Doc. Parse is resilient: the returned Doc is partial when frontmatter is missing or malformed. The caller (lint) decides which issues are violations.
Parse returns a non-nil error only for I/O failures (file not found, permission denied). YAML parse errors and structural issues do NOT surface as Go errors — they manifest as nil Frontmatter or empty fields on the returned Doc.
type Frontmatter ¶
type Frontmatter struct {
Kind string // MUST equal "entity"
ID string // MUST equal Doc.Slug
Singular string
Plural string
Description string
Inherits string // optional path or URL; "" when absent
Properties []PropertyItem
// Extras carries any frontmatter keys not listed above so that
// forward-compatibility (per [entity#req:frontmatter-required-fields]
// "Additional keys MUST NOT be a lint error in MVP") is preserved.
Extras map[string]any
}
Frontmatter mirrors the typed fields from [entity#req:frontmatter-required-fields].
type PropertyItem ¶
type PropertyItem struct {
Name string // required
DataType string // inline form
Ref string // reference form (path or URL)
Description string
Checks map[string]any // free-form per [property#req:checks-shape]
}
PropertyItem is a single entry in the entity's frontmatter `properties` list. Exactly one of (DataType, Ref) is non-empty in a valid item; Parse leaves both empty when neither is present (lint flags this).