grounds

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package grounds is the recorded-grounds vocabulary as DATA: the closed set of three values, the `<token>: <text>` grammar, the parser, the renderer, and the substance floor that refuses a degenerate text.

It is a leaf for the same reason core/issueschema and core/changelog are: two record families record grounds — the intent record (core/intent) and the issue ledger (core/capture) — and the CLI parses a caller's operand before either of them is reached. A vocabulary spelled three times is a vocabulary the three can disagree about, which is how a value one surface writes becomes a value another refuses. The committed-record gate (core/lint) is deliberately NOT among them: it blocks a frontmatter `grounds:` key without judging its value, so it needs no reading of the grammar and imports nothing from here. It imports core/mdrecord — the record-body machinery the `## Grounds` section is read and written through — and core/frontmatter, for the one rule about where a record's frontmatter stops and its body begins; otherwise only the standard library: no filesystem, no transport, no record store.

The grounds name the CONJECTURE being acted on, not the route taken. "Planned it because it is next" restates the decision; "planned it because we expect a stamped identity to survive rewording, which nothing else does" is a conjecture somebody can later find wrong. That distinction is a review property and no machine reads a sentence and knows which it is, so what lives here is a FLOOR — it refuses the degenerate cases and claims nothing more. The substantive requirement is carried by the interview prompts on the plugin surface.

Index

Constants

View Source
const Heading = "Grounds"

Heading is the section a record carries its grounds under. It is spelled once for the two that have to agree: the writer that creates the section and the reader that locates it, across both record families. Record-lint names the section in a remedy as literal prose, because core/lint does not import this package and one message is not a reason to (iss-2608301836222858).

View Source
const MinTextLetters = 20

MinTextLetters is the substance floor in LETTERS. It refuses the degenerate texts — a single word, a shrug, a restated flag name — without pretending to judge whether what clears it names a conjecture. It is deliberately low: a floor that refused real but terse reasoning would push the caller into padding, which records less than a short honest sentence does.

Letters rather than runes, because a rune count is answered by whatever occupies a rune and the padding is exactly what says nothing: three one-letter words and seventeen dots carry twenty runes and three letters of reasoning, and a text of letters that render as nothing carries no reasoning at all (iss-2608301455387735). isTextLetter is which runes count.

View Source
const MinTextWords = 3

MinTextWords is the same floor measured in LEXICAL UNITS, and it is the half that does the work. A rune count alone is answerable with nothing at all: twenty zero-width spaces, twenty dots or twenty digits each occupy twenty runes and carry no letters, and a refusal a caller can satisfy with characters that render as emptiness is not a floor (iss-2608301206034359). Three is the lowest count that can carry a subject, a verb and an object — the shape of a claim somebody could later find wrong — and the corpus's shortest real entry runs to thirty-two words, so nothing honest is anywhere near it.

What a unit IS depends on the script, and that is the whole of the fix for iss-2608301301044588: a letter-run is a word only where the script separates words, and counting runs made a Chinese or Japanese text of any length exactly one word. See textUnits for the counting and scriptioContinua for the scripts.

Variables

View Source
var Vocabulary = []Token{Pursued, Deferred, Declined}

Vocabulary is the closed set, in the order a surface should offer it. The two refusals that reject a TOKEN -- Parse's grammar refusal and ParseToken's -- render it (vocabularyList), so a caller told their token is wrong is told which tokens are right. The package's other eleven refusals render nothing of the kind -- and that is all this comment claims about them. Two earlier spellings each replaced an overclaim with a smaller one: first that every refusal rendered the list, then that the other eleven all speak about the text, which is false of the three in record.go that speak about the record's structure and one of which ends "the grounds text is not the fault" (iss-2608301908284034, iss-2608301918362294).

Every rendering of the set for a reader goes through this package: the two refusals above through vocabularyList, and the help text and usage refusals a caller reads through UsageSpelling and ProseList. Prose documentation is the stated exception and spells the values by hand, which is what prose does.

Earlier spellings of this comment enumerated the places the values were copied. Each correction of that list introduced a fresh error, because a prose enumeration cannot fail and so cannot be maintained (iss-2608301836222858). There is no list here because there is nothing left to list.

Functions

func AppendToRecord

func AppendToRecord(content string, g Grounds) (string, error)

AppendToRecord appends one grounds entry to a record FILE, creating the `## Grounds` section when it is absent, and returns the file to write.

The append and its read-back run over the record BODY, and the result is spliced back onto the frontmatter unchanged. That is what makes the guard a property of the section the reader will actually consult rather than of the whole file: judged over the whole file, the writer matched a frontmatter `# Grounds` comment as its heading, wrote the bullet there, read it back happily, and reported success about a value the body reader could not see (iss-2608301805069999).

It refuses a write that would leave the record LESS readable than it was (iss-2608300927577980) rather than performing it. A grounds text is operator prose, and prose can carry an unclosed `<!--`. The comment mask then runs to end of file: the entry disappears, every line after it disappears with it, and the result still reports success, so nothing anywhere says the record was blinded. The check is two questions asked of the bytes about to be written, before they are written, rather than a pattern ban on the text: a text that leaves a comment open, and a write whose entry does not actually arrive.

The count question subsumes more than the comment one: a bullet swallowed by a fence, by a mask this reader does not yet model, or by anything else, fails to raise the count and is refused for the same reason. The comment question is still asked separately because it is the one whose remedy the caller can act on — "close the comment, or drop the marker" — and a refusal that can name the cause is worth more than one that can only say the entry did not arrive.

The refusal names no record family; the caller wraps it with its own.

func Body

func Body(content string) string

Body returns the part of a record FILE the `## Grounds` section lives in — everything after the leading frontmatter block. It is the ONE answer the writer and every reader ask, so the bytes a write is judged over are the bytes a reader will consult.

Handed the whole file instead, a reader looks for its heading in the frontmatter too, where `# Grounds` is a legal YAML comment the block parser skips and an ATX heading pattern matches. Writer and reader could then agree an entry had landed while disagreeing about where (iss-2608301805069999).

A text that carries no frontmatter is already a body and comes back unchanged, which is what lets a caller holding either shape ask.

func Fold

func Fold(text string) string

Fold collapses every run of whitespace to a single space and trims the ends — the normalisation both writers need, held here so neither invents its own.

func ProseList

func ProseList() string

ProseList renders the closed set for running prose — at today's set, `pursued | deferred | declined` — spaced, for a sentence naming the vocabulary where a bracketed placeholder would read as shell syntax.

func UsageSpelling

func UsageSpelling() string

UsageSpelling renders the closed set as the operand placeholder a surface prints in help text and in a usage refusal: at today's set, `<pursued|deferred|declined>` — the alternation a caller types exactly one of, followed by `: <the conjecture being acted on>`.

It exists so that no surface types that string. The accepted cost is that the usage text stops being greppable from the surface that prints it: a search for the literal alternation lands here and in the test that pins this function's output — both of them beside the set the string is rendered from — and otherwise only in the prose documentation.

func ValidateText

func ValidateText(text string) error

ValidateText is the substance floor over an already-folded text. It refuses the empty text, the text carrying a control character the frontmatter serialiser refuses (below U+0020, the class yamlScalar will not write — NOT every character a record cannot hold, because the store holds DEL, C1, the line separator and the bidi overrides quite happily; the wording is narrowed to the check rather than the check widened to the wording, because widening would put this floor out of step with the serialiser it exists to mirror, iss-2608301646042379), the text below either half of the floor — the UNIT count and the LETTER count, neither of which a text of zero-width spaces can satisfy — and the text made only of the vocabulary's own words or the asking verb's name. Everything else passes: what this cannot do is tell a conjecture from a restatement of the decision, and it does not claim to.

A unit is a word where the script separates words and a letter where it does not (textUnits, scriptioContinua), so the floor is a property of the TEXT rather than of the writing system. The UNIT count is asked FIRST. Every unit of a text the scriptio-continua refusal speaks for is a single letter, so such a text has as many letters as units: asking the letter count first would refuse each of them for its letters and that refusal would never be reached.

Both halves of the feature inherit the floor from here — the writing verbs through New, and the intent record reader through ParseSectionAboveFloor — which is why it belongs at this one place: a floor the writer and the reader disagree about is a gate reporting no recorded grounds about a record that visibly carries one.

Types

type Grounds

type Grounds struct {
	Token Token  `json:"token"`
	Text  string `json:"text"`
}

Grounds is one recorded ground: the disposition plus the free-text conjecture. It is comparable, so a round trip through String and Parse can be asserted whole.

func New

func New(tok Token, text string) (Grounds, error)

New builds a validated Grounds from a token and a free text, PUTTING THE TEXT TO THE SUBSTANCE FLOOR. It is the writing verb's gate over what a caller supplies; Parse is the reader's gate over what is already written. The text is folded to one line first — both carriers hold a single line — so a text that is only line breaks is refused as the empty text it is.

func Parse

func Parse(s string) (Grounds, error)

Parse reads the `<token>: <text>` grammar — the one spelling written to a `grounds:` frontmatter scalar and to a `- <token>: <text>` bullet alike. It splits on the FIRST colon, because the text is prose and may carry colons of its own.

It checks the GRAMMAR and the VOCABULARY, and deliberately not the substance floor. Parse is what the readers and the committed-record gate use, and those judge values already written: a wontfix stamps its grounds from a reason whose own contract is merely non-empty, so a floor here would make a reader skip records the ledger has always accepted. The floor is an input gate, applied by New at the writing verb over what a caller supplies.

func ParseSection

func ParseSection(content string) []Grounds

ParseSection reads a record's recorded grounds, in the order they were written. It is the single reader every consumer asks, so no two of them can disagree about what an entry is.

A bullet that does not parse is not an entry: it is prose under the heading, and reporting it as a malformed ground would put a gate verdict on a sentence somebody wrote for a human.

It checks the GRAMMAR and stops there, which is what lets the ledger use it. A wontfix stamps its grounds from a reason whose own contract is merely non-empty, so a floor here would make the reader skip entries the ledger has always accepted and a gate then report no recorded grounds about a record that visibly carries one. A consumer that claims the floor asks for ParseSectionAboveFloor instead.

func ParseSectionAboveFloor

func ParseSectionAboveFloor(content string) []Grounds

ParseSectionAboveFloor is ParseSection keeping only the entries that also clear the SUBSTANCE FLOOR, so a consumer that CLAIMS the floor holds a hand-typed bullet to exactly what New holds a supplied one to. Reading the grammar alone let `- pursued: yes` satisfy the intent readiness check, which claims the floor and would then have been enforcing only a colon (iss-2608300930057882).

It is expressed on top of ParseSection rather than beside it: what an ENTRY is stays one definition, and this adds a filter over it rather than a second reading of the section.

func (Grounds) Bullet

func (g Grounds) Bullet() string

Bullet renders the record form: one top-level Markdown bullet under the record's `## Grounds` heading, so the entry reads as prose to a human and as data to the gate with no second parser.

func (Grounds) String

func (g Grounds) String() string

String renders the canonical `<token>: <text>` value — what a frontmatter scalar carries and what Parse reads back.

type Token

type Token string

Token is one of the three recorded dispositions a ground may carry. The set is closed: a fourth value would be a fourth meaning nothing downstream reads.

const (
	// Pursued records the reasoning behind work that went FORWARD — the half of
	// the record that had no home before and evaporated at the gate.
	Pursued Token = "pursued"
	// Deferred records a conjecture considered and left for later.
	Deferred Token = "deferred"
	// Declined records deliberate non-action: the wontfix's own type.
	Declined Token = "declined"
)

The vocabulary (the 2026-08-28 decision-log entry): grounds extend the ADR family's decision-granularity reasoning rather than duplicating it, at the finer conjecture granularity, in these three values.

func ParseToken

func ParseToken(s string) (Token, error)

ParseToken validates one vocabulary value. Surrounding whitespace and case are forgiven — the value is stored canonically either way, and refusing `Pursued:` would spend a refusal on nothing.

Jump to

Keyboard shortcuts

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