You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
§FS-check.checks.config-version-1, §FS-config.5.3, §DF-config-version-1-caution: A config file on version 1 is cautioned. A clean grund check, grund config validate or grund config show on a grund.toml that writes grund_config_version = 1, or no version, printed success and now prints warning: grund.toml is version 1; migrate it with grund config migrate --to 2 on stderr instead, one line per version 1 config in a workspace, naming the member's directory; under --format json it is a stderr finding with code config-version-1. What does not move: every exit code, every other finding, a version 2 config and a project with no config file, which earn no line, and version 1's meaning, which the caution never retires. Who this breaks: a script that compares stdout to success or expects a clean JSON run to be silent on stderr on a version 1 config; pass --ignore config-version-1, or run grund config migrate --to 2 --write.
§FS-declarations.checks.conflict-marker, §FS-fmt.7.4.3, §DF-conflicted-declaration, §REQ-backwards-compatibility.5, §REQ-no-wrong-citation.1: a declaration that still holds an
unresolved merge conflict fails check, and fmt writes nothing while one exists. A
column-0 conflict block in a Markdown file that declares an ID, fences included, or in a source
declaration's body is the new error conflict-marker, at the block's first line and naming
every declaration it overlaps. Who this breaks: the verdict moves from pass to fail for grund check on such a tree (exit 0 becomes 1), and every fmt run that needs the whole
declaration set refuses it and rewrites nothing, so fmt --write exits 2 where it exited 0
and fmt --check exits 2 where it exited 0 or 1; Python raises OperationError and Node
rejects with kind operation, both with code conflict-marker, and Rust returns the new FmtConflictAbort. A spec that shows a marker line literally indents it by one space, and a
seven-level blockquote is written > > > > > > >. A run refused for an unreadable path no
longer rewrites files before refusing. Every finding that replaces the old verdict names its
location and the action to take: resolve the conflict by hand. Closes issue #837.
The managed block now teaches coordinate globs in place of the jq pipe, so both current block versions move: v23/v24 becomes v27/v28 and v25/v26 becomes v29/v30, grund check and grund init --check report every earlier block outdated, and one grund init re-renders it, keeping unmanaged content. A marked citation whose brace group opens before the section separator, such as <§>FS-login{.1,.2}, is no longer recorded as a citation of FS-login: check reports the pattern as the glob-citation error, which fails the run, so a declaration cited only through one may now be reported unused, and a unit grounded or satisfying a citation rule only through one may now fail that rule. Cite each exact point, or escape the illustration with the configured marker wrapped in angle brackets. This verdict change is the correction recorded in §DF-coordinate-globs.4, under §REQ-backwards-compatibility.5, for the prior violation of §REQ-no-wrong-citation.1. Every finding names its location and an action the maintainer can take.
§DF-docs-flag-removed-in-0-19, §FS-init.1.7, §REQ-backwards-compatibility.2: grund init --docs is removed; spell it --scaffold. What grund 0.18.0 announced lands: --docs is now an unknown flag, so grund init --docs prints error: unknown flag `--docs` , writes nothing and exits 2, and grund init --help no longer mentions it. --scaffold lays the same starter files --docs did. Who this affects: a script or CI step that still runs grund init --docs, which saw the deprecation warning in 0.18.0: change it to grund init --scaffold. The Rust, Python and Node docs option keeps its name and is unaffected. Closes issue #881.
The managed agent block now teaches grund fmt --write after authored declaration
renames or file moves. Its versions advance from v31/v32 to v35/v36 and from
v33/v34 to v37/v38. Existing blocks are reported outdated by grund check and grund init --check; run grund init to refresh them, preserving unmanaged text.
Formatter link, lock, and preview/write behavior is unchanged.
§DF-fmt-preserves-authored-link-labels, §FS-citations.wrap.enclosing, §FS-check.3.18.5, §REQ-backwards-compatibility.5, §REQ-no-data-loss.2, §REQ-no-wrong-citation.2: grund fmt --cross-refs no longer writes a link inside a link you wrote, and grund check takes your link as the index entry. A citation in the text of a Markdown link, as in See [the <§>ADR-x record](decisions/functional/adr/x.md). or the index row - [<§>ADR-x: Use Postgres](decisions/functional/x.md), was wrapped in a second link, which broke yours, and check reported the index row as index entry … is not a link until it was. Both lines are now left as written, and the row is the entry. Who this affects: a repository with a citation inside link text. The verdict moves from fail to pass: fmt --check stops listing those lines and check stops reporting those rows. Every finding that replaces the old verdict names its location and the action to take: an index row whose link has an empty destination, [<§>ADR-x: Use Postgres](), is reported as a missing entry instead, at the declaration's heading, naming the index file and the form an entry takes. Lines an older grund already nested are left as they are; to find them, search for [[§, which catches a nested index row, and for the pattern \[[^]\n]*\[§, which catches a citation linked inside longer link text, and unwrap them by hand.
§DF-fmt-preserves-authored-markup, §FS-citations.wrap.enclosing.scope, §FS-citations.zones.authored-markup, §FS-citations.checks.image-index-entry, §REQ-backwards-compatibility.5, §REQ-no-data-loss.2, §REQ-no-wrong-citation.2: grund fmt no longer writes into a reference link, a definition, an autolink, an HTML anchor, link text that spans lines, or a citation-only image's destination.See [the <§>ADR-x rationale][x]., [the <§>ADR-x record]: x.md, <https://example.com/<§>ADR-x>, <a href="x.md">the <§>ADR-x record</a> and  are left as written, and a collapsed or shortcut reference's text keeps every byte with its definition's label. Who this affects: a repository with a citation in one of those forms. The verdict moves from fail to pass: fmt --check stops listing those lines, and in a kind's index a reference to a matching definition and a multi-line link are entries. Every finding that replaces the old verdict names its location and the action to take: an unresolved reference, a definition's label, an autolink, an HTML anchor, or a label a lone backtick leaves unclosed is reported as a missing entry instead, at the declaration's heading, naming the index and the form an entry takes. A citation-only image that is an ID's only index entry warns image-index-entry in grund 0.19.0, naming the link to write beside it, and stops counting in grund 0.20.0. Lines an older grund already nested are left; to find them, search for [[§, for the pattern \[[^]\n]*\[§, and for ]( inside <…> or <a …>…</a>, and unwrap them by hand.
§DF-fs-home-lands-in-0-19, §FS-config.3.4.4, §FS-init.2.4.10, §REQ-backwards-compatibility.2: the built-in FS home is now docs/functional-spec/, and the fs-home-moves warning is gone. What grund 0.18.0 announced lands: a project with no grund.toml and a grund.toml that omits [[kinds]] both home FS in docs/functional-spec/, and a fresh grund init --template software-development --scaffold declares FS there with folders = ["docs/functional-spec"], writes docs/functional-spec/README.md, and no longer writes requirements.md. Who this affects: only a project with no grund.toml whose FS declarations live in requirements.md, the project 0.18.0 warned with fs-home-moves: those declarations are no longer in the FS home. To keep them there, run grund init and set its FS row to files = ["requirements.md"], since the row it writes is folders = ["docs/functional-spec"]; or move the declarations into docs/functional-spec/. Every config grund init has written names its FS home and is unaffected. --only fs-home-moves and --ignore fs-home-moves are now refused as an unknown code, so drop them from scripts. Closes issue #723.
§DF-glob-citation-lands-in-0-19, §FS-check.checks.glob-citation, §FS-errors.5.5, §REQ-backwards-compatibility.2: a glob citation is now an error. What grund 0.18.0 announced lands: a marked citation written as a pattern, such as <§>FS-login.*, <§>FS-log*in.requirements or <§>FS-[a,b], and from this release the brace form <§>FS-x{.1,.2} too, is reported as <path>:<line>: error: glob citation … and fails grund check with exit 1. Its message now ends this became an error in grund 0.19.0, and JSON carries "severity":"error"; the code, the location and the rest of the message do not change. Who this affects: a repository whose grund check showed a glob-citation warning in 0.18.0, and one that writes the brace form before a section separator: cite the exact point, or escape the illustration with the configured marker wrapped in angle brackets. Closes issue #881.
§FS-scan.scope.ignore-files.global, §REQ-deterministic-output.2, §REQ-backwards-compatibility.5, §DF-global-excludes-anchor-at-the-repository-top: a pattern in git's global core.excludesFile now anchors at the top of its path's repository, as git anchors it, wherever grund runs from and on every platform. grund rooted that matcher at the working directory, so an anchored pattern such as notes/gen/ ignored nothing when grund ran from a subdirectory of the repository, from outside it, or under a grund.toml above the repository top, and on Windows it ignored nothing from anywhere; an unanchored pattern such as gen/ was unaffected. Inside a repository nested in the one the run starts at, such as a submodule, the pattern was matched against the outer top and is now matched against the nested one. grund counts a jj workspace as a top, as the ignore crate does, so in a jj workspace inside a git repository it anchors at the workspace, whereas git anchors at the outer top. Who this affects: a project with files such a pattern ignores, run from one of those places or holding a nested repository. Those files are no longer read, so the verdict moves there: a citation that resolved only to a declaration in one now dangles and check exits 1, a declaration only one of them cited may go uncited, a citation rule only one of them satisfied may fail, and a finding inside one is no longer reported. The move also runs the other way: a pattern that matched only as spelled from the working directory or the outer top, such as fs/gen/ run from docs/, or notes/sub/x/ for a nested notes/sub, no longer ignores those files, so they are now read and a finding inside one is reported. From the repository top on Linux and macOS nothing changes for that repository's own paths. A stub to such a target is refused from every directory, the broken-stub refusal of 0.19.0. Every finding that replaces the old verdict names its location and the action to take: move the file out of what the global excludes file ignores, or re-include it with a ! line in the repository's .gitignore, and to keep a file now read ignored, spell the pattern from the top of its own repository. Closes issue #785.
§FS-scan.scope.ignore-files.pathname, §REQ-deterministic-output.2, §REQ-backwards-compatibility.5, §DF-global-excludes-literal-tilde: grund now loads a readable global core.excludesFile whose pathname contains a literal tilde, including Windows short names such as RUNNER~1. Previously the loader substituted the home directory for interior tildes and usually loaded nothing. Files Git ignores through the intended file now leave the scan: findings inside them disappear, while citations to their declarations may dangle, declarations only they cited may become uncited or ungrounded, and citation rules they satisfied may fail. If the wrongly substituted file existed, correcting which patterns load can also bring files and their findings back into the scan. The verdict changes where these patterns alter the scan; every finding names its location and the action to fix it: move needed declarations or citations out of ignored paths, re-include needed paths with ! rules in the repository's .gitignore, or deliberately ignore newly read files there. Ignored stub targets receive the existing 0.19.0 refusal naming the stub, excludes file, pattern and remedy. Valid leading ~/ expansion, including a literal tilde in the home pathname, remains supported. This does not introduce general diagnostics for missing or unreadable global files. Closes issue #788.
§DF-guide-command, §FS-init.5: grund agent-setup-instructions is now grund guide, and the guide is in sections. Bare grund guide prints the three commands a fresh repository runs, then every section with its size and what it holds. grund guide setup prints the adoption workflow, at most 16,000 bytes, and grund guide <section> any of ten reference sections (config, citations, languages, members, scoped-guidance, schema, queries, editor, integrations, rules). grund guide --full prints the whole guide in one response, in a new order. Who this affects:grund agent-setup-instructions keeps working until grund 0.20.0, printing what grund guide setup prints with a warning on stderr, so a caller that read the whole guide from it passes grund guide --full instead. The Python and Node agent_setup_instructions() and agentSetupInstructions() keep their names and still return the whole guide. No verdict moves.
§FS-errors.3.8, §FS-errors.3.8.1, §FS-list.1.1, §DF-homeless-code-declares-no-ids: code, in a project that declares no homeless kind, is refused as declaring no IDs, without unknown kind. The window 0.18.0 announced closes for code: grund list --kind code printed error: unknown kind `code` — kind `code` declares no IDs; this wording changes in grund 0.19.0 and now prints error: kind `code` declares no IDs; list --selector 'Each code', check --rule 'Each code must have exactly one terms chapter.' and check --rule 'Each FS must cite at least one code.' printed error: unknown kind "code" — kind "code" declares no IDs; this wording changes in grund 0.19.0 and now print error: kind "code" declares no IDs; and list --selector code printed error: literal subject "code" does not match the configured ID grammar — kind "code" declares no IDs; this wording changes in grund 0.19.0 and now prints error: kind "code" declares no IDs. What does not move: each is still followed by its known kinds: line and exits 2, the invalid-rule code and its severity, and unknown kind "POLICY" for a kind no project configures. Who this breaks: a script that matches the legacy prefix of one of the five refusals above. Closes issue #680.
§DF-lisp-doc-grounding-lands-in-0-19, §FS-check.3.6.2.2, §REQ-backwards-compatibility.2: an ungrounded Lisp doc-comment is now an error. What grund 0.18.0 announced lands: under grounding_level 2 or higher a Lisp doc-comment that cites and declares nothing printed src/router.lisp:3: warning: ungrounded doc-comment: no § citation to a declared ID; this warning becomes an error in grund 0.19.0 and now prints src/router.lisp:3: error: ungrounded doc-comment: no § citation to a declared ID, as every other ungrounded doc-comment does, and fails grund check with exit 1 wherever those do. Who this affects: a repository with Lisp sources and grounding_level 2 or higher whose grund check showed that warning in 0.18.0: cite the spec the documented item realizes in its doc-comment, or declare an ID there. Closes issue #881.
The managed block's heading now reads ## Grounding with grund (block vN), so its number reads as the revision of the block's text rather than a grund release; grund -V is where the release is read. Both current block versions move: v27/v28 becomes v31/v32 and v29/v30 becomes v33/v34. v23 to v30 never shipped, so a 0.18 repository goes from v19–v22 straight to v31–v34 with the one grund init it already owes: grund check and grund init --check report the earlier block outdated, and grund init re-renders it in place, keeping unmanaged content. This breaks two readers. Anything that matches ## Grounding with grund (vN) must also accept (block vN). An older grund reports the new block as malformed, so upgrade grund before running grund init.
§FS-citations.checks.mixed-path, §FS-rules.7.12, §FS-section-lock.checks.unrecorded-section-citation: Mixed citation warnings
become ordinary errors in 0.19.0 after the 0.18.0 warning release. Repositories
relying on unresolved citations of a name under a number, or required rule and
configured citation findings only those sites cause, now fail check and CI.
Codes and sites stay the same; messages lose the mixed warning suffix, JSON
severity becomes error, and such errors cause exit 1. Fix the target or
citation, adjust an intended constraint, or explicitly filter its code.
Independent warning windows, explicit warning strengths and opt-in suggestions
keep their behavior. An unrecorded mixed address still errors until grund fmt --write records it, with no historical version suffix. The shared
release floor prevents a 0.18.x publication from this tree; patches require a
branch made before this transition. Closes #710.
§FS-check.1.4.1, §FS-check.2.2.1.4, §DF-narrowed-check-judged-nothing, §REQ-backwards-compatibility.5: a narrowed check says when what it selected judged nothing.--only <code> of a check the run leaves off prints warning: --only <code> judged nothing — …, naming the switch that turns it on, in place of success, with the new code selected-check-off. A must or should rule, declared or --rule, whose subject kind holds files but no unit prints warning: <rule> applies to nothing — … under empty-citation-obligation, and a run narrowed to a code rules produce now keeps every empty-citation-obligation row. Who this breaks: a script that greps a narrowed run for success or treats a stderr line as failure, and a CI step that used --only <code> as a no-op; with --format json stderr gains a warning object. One exit moves:empty-citation-obligation joins the rule-produced codes, so --only empty-citation-obligation keeps every invalid-rule row, and over a tree holding an invalid rule it exits 1 with the error the unnarrowed grund check already prints, where it printed success. The opt-outs:--ignore selected-check-off, --ignore empty-citation-obligation, and --ignore invalid-rule. The verdict moves by the correction route of §REQ-backwards-compatibility.5, because the old success broke §REQ-no-missed-citation.1 and §REQ-no-missed-citation.2; every finding that replaces it is about the run rather than a file location, or is the invalid-rule row the unnarrowed run already prints, and names the fix: the switch to set, the code to select, the folder that holds no unit, or the rule to repair. Closes issue #829.
§DF-nested-alias-targets-land-in-0-19, §FS-rules.7.9, §REQ-backwards-compatibility.2: a finding a rule target pinned at its own nested alias path alone produces is now an error. What grund 0.18.0 announced lands: in a member nested inside another, such as group/api, a rule that pins the member's own alias path, such as Each API must not cite any group/api/AR., printed group/api/docs/api/API-a.md:3: warning: API must not cite group/api/AR (RULE-y) — re-point the citation or downgrade it to a plain Markdown link; a target pinned at the rule's own nested alias path now matches, and this warning becomes an error in grund 0.19.0 and now prints group/api/docs/api/API-a.md:3: error: API must not cite group/api/AR (RULE-y) — re-point the citation or downgrade it to a plain Markdown link, failing grund check with exit 1. The same holds for an at most N or exactly N count the pin pushes out of bounds, outbound or inbound, and for a per-target cite each finding on a declaration the pin brings in. Who this affects: a workspace whose grund check showed that warning in 0.18.0: remove the citation, add the missing one, loosen the rule's count, or pass --ignore on the finding's code. Closes issue #881.
§DF-one-grammar-lands-in-0-19, §FS-errors.3.8.1, §FS-config.3.9.5.2, §REQ-backwards-compatibility.2: a non-citable kind and a wildcard subject are refused with their reason alone, and a [citations] target the run cannot accept is an error. What grund 0.18.0 announced lands. check --rule 'Each e2e must have exactly one terms chapter.', where e2e is a configured non-citable kind homed at tests/e2e/, printed error: unknown kind "e2e" — kind "e2e" declares no IDs — tests/e2e/ is not a citable home; this wording changes in grund 0.19.0 and now prints error: kind "e2e" declares no IDs — tests/e2e/ is not a citable home, on a rule's subject and object, a configured rule and list --selector alike; list --selector e2e.terms no longer opens with literal subject "e2e.terms" does not match the configured ID grammar; and check --rule 'FS-x.* must cite at least one FS and must not cite any FS.' printed the conjunction refusal first and now prints error: section-component wildcards are not accepted in phase 1. A pinned or */ target the run cannot accept, such as [citations.FS] must-not = ["api/FS"] where member api configures no FS, printed a warning ending ; this becomes an error in grund 0.19.0 and loaded; it now prints the same line as an error: ending ; this became an error in grund 0.19.0, and every command exits 2. Who this affects: a script that matches the legacy prefix of one of those refusals, which should match the reason after the — it printed in 0.18.0; and a config that saw the [citations] warning in 0.18.0, which now fails to load until the target names a kind its project configures as citable, or, for a run with no workspace, until the config declares the [workspace] the alias names. Closes issue #881.
§DF-one-parse-lands-in-0-19, §REQ-one-answer.differences.sections, §FS-declarations.section.relative.where, §FS-init.2.3.7.1, §REQ-backwards-compatibility.2: every command now reads one parse of each file, the parse-moves warning is gone, and relative and mixed doc-comment headings are sections. What grund 0.18.0 announced lands: show --full and list --size end a Markdown body at the next same-or-higher heading, plain or declaring, and leave out a // note next to a /// block; a deeper declaration no longer ends its parent's body; show ends a section at a plain heading of its level or above; --toc stops listing /// # 1. Sub and drops a heading's closing hashes from its title; a /** … */ line without * that reads ## 1. Sub is section .1; and refs, cover --lines, the chapter rules and the editor end a doc-comment section where show does. In a doc-comment declaration body, /// ### .1: Username under /// ## format: Formatting is section format.1, and /// ### 1.goals: Goals or /// ### .goals: Goals under /// ## 1. Overview is 1.goals, as in Markdown. Who this affects: a repository that saw parse-moves in 0.18.0 sees the verdict it named; one that did not sees changed output only. --only parse-moves and --ignore parse-moves are now refused as an unknown code, so drop them from scripts. The managed block teaches the doc-comment forms, so a v19, v20, v21 or v22 block is reported agents-init as outdated until one grund init re-renders it at v23, v24, v25 or v26. Closes issue #639.
§DF-path-narrows-the-report-in-0-19, §FS-scan.path.show, §FS-scan.path.list, §FS-scan.path.id, §FS-scan.projects.narrowed: a path narrows what show, list and id report, not what they resolve, and in a workspace check <dir> resolves every project a run from <dir> sees.grund <ID> <path> finds an ID the project declares outside the path, and reports one declared both inside and outside it as ambiguous. list <path> counts and selects its entries by every citation in the project and notes a duplicate home outside the path. id <KIND> <title> <path> numbers from the whole project. Below a workspace root and outside every member, check <dir> prints the root run's findings within <dir>, so a qualified citation the root resolves is no longer unknown project alias and the run can exit 0; a member directory is a member run as before. The 0.18.0 warnings that announced this are gone. Who this breaks: a script that relied on show <path> missing an ID declared outside the path, on id <path> numbering from the path alone, or on check <dir> exiting 1 for an alias the workspace root resolves. Closes issue #621.
§DF-per-target-once-ceiling: Per-target citation rules now spell a ceiling of
one as at most once. Replace cite each AR at most 1 times. with cite each AR at most once. (and likewise for other target kinds) in RULE
titles and check --rule sentences. Who this breaks: a formerly passing
check using numeric upper-one can now fail, and init refuses to write until
the title is corrected; the refusal offers the accepted replacement. After
editing rendered rules, rerun grund init. Other count families and the
finding text requires at most 1 are unchanged.
Qualified citations in supported source comments after prose apostrophes, Rust
lifetimes and Haskell identifier primes are now recognized. Repositories may fail
existing checks for previously hidden unknown aliases, missing targets or sections,
or citation-policy violations. Follow the located finding to correct/configure the
alias, correct/declare the target or section, satisfy the policy, or escape an
illustration with the marker in angle brackets. Formatter and bare-token behavior
are unchanged. This verdict change follows §DF-qualified-comment-quotes.2
under §REQ-backwards-compatibility.5
for the prior violation of §REQ-no-missed-citation.2.
Every finding names its location and an action the maintainer can take; the existing
remedies apply to recovered citations.
From grund 0.19.0, a stub whose target is excluded or ignored by an enabled
ignore rule is an error coded broken-stub, instead of the excluded-stub-target warning shipped in 0.18.0. Check exits 1 and show refuses.
Rejected targets no longer lend bodies, sections, chapters or citation edges.
Move the target or change the refusing rule named in the error.
An old --ignore excluded-stub-target no longer suppresses this finding;
select or ignore broken-stub instead. --only excluded-stub-target still
parses but selects no findings (§FS-declarations.checks.excluded-stub-target).
Targets outside include alone and explicit scan-root precedence keep their behavior.
The shared 0.19.0 release floor (§FS-distribution.release-floor) independently prevents publishing
this activation in a 0.18.x patch even without diagnostic text; delivery relies
on that shared floor. The guard also enforces the diagnostic's landed-message bound.