Documentation
¶
Overview ¶
specscore:feature/cli/spec/lint
Implements the `index-entries` rule and its --fix support. The bidirectional check (phantom links + orphan children) satisfies REQ:index-entries-bidirectional. The fixer satisfies REQ:index-entries-fix-deletes-phantom-rows (Phase 1) and REQ:index-entries-fix-inserts-orphan-rows (Phase 2). All three REQs and their ACs live under the "Features index synchronization" subsection of the cli/spec/lint feature README.
Index ¶
- Constants
- func AllRuleNames() map[string]bool
- func CheckRegistryParity() error
- func FixTargetNames() []string
- func Migrate(specRoot string) ([]string, error)
- func RegisterChecker(c Checker)
- func RenderCatalog() string
- func RenderStudioToolbar(name, urlStr, host, org, repo, artifactPath string) string
- func ResetCustomCheckers()
- func ValidateFixTargets(targets []string) error
- func ValidateRuleNames(names []string) error
- func WriteCatalog(repoRoot string) error
- type Checker
- type Options
- type Result
- type Rule
- type Violation
Constants ¶
const ( FixTargetAll = "all" FixTargetNoSource = "no-source" )
Fix target sentinels. FixTargetAll is the implicit target of a bare `--fix` (run every standard fixer). FixTargetNoSource is the opt-in plan fix that rewrites a sourceless plan to `**Source:** none` — never enabled by the unscoped pass; only when explicitly named.
const CatalogPath = "docs/lint-rules.md"
CatalogPath is the canonical location of the rendered lint-rule catalog, relative to the repository root (cli/rules#req:catalog-canonical-path).
Variables ¶
This section is empty.
Functions ¶
func AllRuleNames ¶
AllRuleNames returns the canonical set of known rule names, derived from the structured rule registry (the single source of truth).
func CheckRegistryParity ¶ added in v0.6.0
func CheckRegistryParity() error
CheckRegistryParity verifies that the rule registry and the set of rule IDs a checker can emit are in full parity. It compares the registry ID set (keys of the canonical registry, as returned by AllRuleNames) against the emittable ID set (the rule names a freshly built default linter registers checkers under).
A default linter (newLinter(Options{})) registers no custom checkers, so the emittable set is the built-in surface only.
It returns a non-nil error naming the offending IDs when either an orphan registry entry (an ID no checker can emit) or an unregistered emission (an ID a checker can emit that is absent from the registry) exists. On full parity it returns nil.
func FixTargetNames ¶ added in v0.10.0
func FixTargetNames() []string
FixTargetNames returns the sorted set of valid `--fix=<target>` action names: every fixer-backed rule name (both fixer-interface and check-time fixers) plus the opt-in "no-source" action. It excludes the "all" sentinel, which is always valid. Used by the CLI to validate `--fix=<targets>` and to render help.
func Migrate ¶ added in v0.7.0
Migrate performs the one-shot artifact-frontmatter-convention backfill (cli/spec/migrate): for every artifact the convention rules walk, it ensures a leading frontmatter block carrying the type's canonical `format:` URL and, for status-bearing types, a `status:` mirroring the body `**Status:**`; it then aligns the adherence-footer URL to `format:`. It is deterministic, offline, and idempotent (a conformant artifact is left byte-unchanged).
Returns the spec-root-relative, slash-separated paths of the files it changed, sorted.
func RegisterChecker ¶
func RegisterChecker(c Checker)
RegisterChecker registers a custom checker that will run alongside built-in checkers during Lint(). Must be called before any concurrent use of Lint (typically during init or program startup).
func RenderCatalog ¶ added in v0.6.0
func RenderCatalog() string
RenderCatalog builds the full markdown lint-rule catalog from the registry.
The output is deterministic: it derives entirely from AllRules() (itself an ID-sorted copy of the registry) and carries no timestamps, host, path, or other environment-dependent content. Families are emitted in sorted order, and rules within each family are listed in ID order, so re-rendering an unchanged registry yields byte-identical output (cli/rules#req:catalog-deterministic). The document is grouped by family, each rule showing its id and description (cli/rules#req:catalog-canonical-path).
func RenderStudioToolbar ¶
RenderStudioToolbar returns the canonical toolbar line per studio-toolbar#req:toolbar-line-shape. The returned string includes the trailing LF. Callers (lint, --fix) compare or replace line 3 with this exact byte sequence.
Inputs:
- name: studio.name (with or without dots; bold-wrap rules apply per brand-attribution-rendering / brand-attribution-no-dot / brand-attribution-multi-dot).
- url: studio.url; MUST end in exactly one "/" — the validation is enforced upstream in projectdef.Validate(). The renderer strips the trailing "/" per url-grammar-trailing-slash before joining with the path grammar.
- host, org, repo: resolved from specscore.yaml project.host/.org/.repo, falling back to git origin parsing.
- artifactPath: the feature directory path from repo root, e.g. "spec/features/repo-config". MUST NOT include "/README.md".
func ResetCustomCheckers ¶
func ResetCustomCheckers()
ResetCustomCheckers clears all registered custom checkers (for testing).
func ValidateFixTargets ¶ added in v0.10.0
ValidateFixTargets rejects any target that is neither the "all" sentinel nor a known fix-target name. Empty input is valid (no targets).
func ValidateRuleNames ¶
ValidateRuleNames checks that all names are known rules. The legacy `view-link` rule was removed by the studio-toolbar Feature; flagging it surfaces a migration message naming `studio-toolbar` as the replacement (studio-toolbar#req:studio-toolbar-lint-removes-view-link).
func WriteCatalog ¶ added in v0.6.0
WriteCatalog renders the catalog and writes it to CatalogPath under repoRoot, creating the parent directory if needed. It is a reusable helper for the commands that own the `--write`/`--check` behavior; it does not itself wire to any flag.
Types ¶
type Checker ¶
type Checker interface {
Name() string
Severity() string
Check(specRoot string) ([]Violation, error)
}
Checker is the public interface for custom rule implementations. External tools can implement this to add custom rules to the linter.
type Options ¶
type Options struct {
SpecRoot string
Rules []string // enabled rules; nil = all
Ignore []string // disabled rules
Severity string // minimum severity: error, warning, info
Fix bool // when true, auto-fixable violations are repaired on disk by checkers that support it
// FixTargets names opt-in fixes to enable on top of the standard fix pass
// (only consulted when Fix is true). These are fixes that are deliberately
// off by default because they mask a likely authoring mistake — e.g.
// "no-source" rewrites a plan with no source line to `**Source:** none`.
FixTargets []string
// CLIVersion is the running CLI's own version as a semver string (e.g.
// "0.3.0", with optional leading "v"). Used by the dogfood-version-bump
// rule to detect stale pins in .github/workflows/*.yml. Empty, "dev",
// or any non-semver value disables the comparison silently.
CLIVersion string
}
Options holds linting options.
type Result ¶ added in v0.6.0
Result is the full outcome of a lint pass. Fixed is populated only when opts.Fix is true and lists the specRoot-relative paths of files whose bytes changed during the fix pass (de-duplicated, sorted). It matches how Violation.File paths are rendered (relative to opts.SpecRoot).
func LintWithResult ¶ added in v0.6.0
LintWithResult runs all enabled lint rules against the spec tree and returns both the violations and, when opts.Fix is true, the set of files the fix pass modified.
type Rule ¶ added in v0.6.0
type Rule struct {
ID string `json:"id" yaml:"id"`
Description string `json:"description" yaml:"description"`
Family string `json:"family" yaml:"family"`
Severity string `json:"severity" yaml:"severity"`
}
Rule is a structured registry entry describing a single lint rule. The registry of Rule values is the single source of truth for the set of known rule names, their human-readable descriptions, the family they belong to, and the severity at which their checker reports.
Tags mirror the Violation struct style so downstream commands can emit registry entries as JSON/YAML directly.
type Violation ¶
type Violation struct {
File string `json:"file" yaml:"file"`
Line int `json:"line" yaml:"line"`
Severity string `json:"severity" yaml:"severity"`
Rule string `json:"rule" yaml:"rule"`
Message string `json:"message" yaml:"message"`
// FixTarget, when non-empty, names the `--fix=<target>` action that repairs
// this specific violation (e.g. "no-source"). Only set on violations a fixer
// can actually resolve; drives the "How to fix" hint in text output.
FixTarget string `json:"fix_target,omitempty" yaml:"fix_target,omitempty"`
}
Violation represents a single linting violation.
func CheckIdeas ¶
CheckIdeas runs all idea lint rules. If fix is true, auto-fixable violations are repaired on disk and omitted from the returned slice.
func FilterBySeverity ¶
FilterBySeverity filters violations to those at or above the minimum severity.
Source Files
¶
- adherence_footer.go
- capability.go
- catalog.go
- config_scope.go
- decision_immutability.go
- decision_rules.go
- decisions_index_rules.go
- dogfood_version.go
- entity.go
- feature_index.go
- feature_readme_walk.go
- feature_rules.go
- footer_format_mirror.go
- format_field.go
- frontmatter.go
- grade.go
- idea.go
- idea_index.go
- implementation_matrix.go
- implements_reference.go
- index_entries.go
- issue_rules.go
- legacy_status_fix.go
- lint.go
- linter.go
- migrate.go
- oq_section.go
- other_platforms.go
- parity.go
- plan_hierarchy.go
- plan_roi.go
- plan_rules.go
- property.go
- readme_exists.go
- registry.go
- rules_registry.go
- sidekick_seed.go
- status_mirror.go
- studio_toolbar.go
- test_seams_decision.go
- test_seams_entity_property.go