Skip to content

fix(emitters): resolve rule references inside link text, and collapse a dead self-link (0.8.6) - #26

Merged
llima merged 10 commits into
mainfrom
fix/cli-0-8-6
Oct 5, 2026
Merged

llima merged 10 commits into
mainfrom
fix/cli-0-8-6

Conversation

@llima

@llima llima commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR bumps the version to 0.8.6. Merging publishes craftar@0.8.6 to npm once the release is approved in the npm environment.

What changes. 0.8.4 (AGENTS.md) and 0.8.5 (kiro) treated the text of a link they rewrote as opaque. A link whose text repeats its own target, [`.claude/rules/x.md`](.claude/rules/x.md), therefore kept a path the workspace may not have. This PR implements the approved spec rule references inside link text, the contract the user chose ("Token + colapsar"):

  • In both agents-md and kiro, every rule reference inside a matched link's text is resolved like a token, with the same states and wording as the same mode.
  • Collapse. If a link's own state reads "rule not in this workspace" and its text is exactly its own path (backticks kept), the link becomes the token form alone:
    • [`.claude/rules/cc.md`](.claude/rules/cc.md) → `cc (rule not in this workspace)`
  • A link kiro keeps for claude-code (K2). Only the references in its text move. Non-references stay as written (spec Ruling 4).
  • Warnings. A reference in a link's text is reported like a token and comes before the link's own entry.
  • One code path. It is all in resolveRuleRefs (src/emitters/shared.ts): one token pattern and one collapse helper. agents-md.ts and kiro.ts do not change.

Which workspaces see update

The user approved the byte change at the spec's checkpoint, before the commit. They saw the before/after on a scratch Forge holding every example line of the spec, across six target sets.

workspace at the first sync on 0.8.6
every workspace craftar import produced (rules targets: "*", claude-code a target) no byte change in .kiro/, nor in AGENTS.md unless a link's text names one of its hand-written steering files (state B: it becomes .kiro/steering/<x>.md); a kiro link text citing an unknown name adds a kiro: warning entry
AGENTS.md written without claude-code, a link's text holds a .claude/rules/<x>.md reference that text resolves (or the link collapses)
kiro, a link's text cites a rule kiro does not write that text resolves (K2, K3 or D wording), or the link collapses
kiro, a link kept for claude-code whose text cites another name only that reference moves

An affected workspace shows AGENTS.md or the .kiro/ files as update, and craftar sync --check exits 1 until it syncs.

Accepted odd forms

The user accepted these two forms as part of the contract:

  • Repeated annotation. Non-exact link text in a dead link keeps the link's usual wording after its own resolved text: see cc (rule not in this workspace) (cc, rule not in this workspace).
  • Fragment in the text. When the text carries a fragment it does not collapse: cc (rule not in this workspace)#part (cc, rule not in this workspace).

Tests

  • New tests, written literally from the spec's examples. The 7 behaviour tests fail on 0.8.5. The 3 pins pass on both versions:
    • a Forge of the shape import produces keeps its AGENTS.md and kiro bytes;
    • reference-style links stay tokens;
    • links with a title stay tokens.
  • Three kiro tests added during review, two of which fail on 0.8.5:
    • link-text-before-target order;
    • an import-shaped Forge where an unknown name in link text adds one warning entry;
    • an unknown name in a K2 link's text.
  • No existing test changed. The only removed line is a missing final newline.

Known limits (unchanged)

  • Nested brackets ([see [.claude/rules/cc.md](.claude/rules/cc.md)) match the outer [ (spec 15 §4.1). Recorded for the docs.
  • A reference-style definition or a link with a title stays a token (spec 15 §12.6).

Test plan

  • npm run typecheck: exit 0 on 77e395a.
  • npm run build: exit 0.
  • vitest without test/ci.test.ts (Linux): 853 passed / 5 skipped.
  • npx tsx test/helpers/regen-golden.ts: no diff under test/golden/.
  • Oracle: skipped. There is no fixture, and the user declined using a client workspace. Byte evidence:
    • goldens are unchanged;
    • the reviewer fuzzed 360,000 cases against 0.8.5: outputs differ only in bodies with a reference inside link text;
    • the whole-plan comparisons (an imported sandbox, and the spec 14, 15 and 17 Forges) are identical;
    • the approved before/after was re-run after every round, identical each time.
  • Reviews: node-cli-reviewer 2 rounds, the second clean; docs-author 5 rounds on the README; the last finding (a steering name is state B in AGENTS.md) is fixed in 77e395a.
  • CI green on this PR: 8 of 8 (ubuntu and windows × Node 22 and 24, runs 37307562016, 37307567200).

llima added 10 commits October 5, 2026 08:35
… a dead self-link

Spec 20: a reference in a link's text is resolved like a token in agents-md and kiro; a link whose own state reads "rule not in this workspace" and whose text is exactly its path becomes the token form. A K2 link keeps its non-references.
….8.6 changes

Document that references inside link text are resolved like bare tokens in both agents-md and kiro, and that a dead self-link collapses to the token form.
Bump version to 0.8.6 for the link-text-references fix.
…ning entry

Both tests validate spec 20's warning order and the imported-shape no-change
guarantee, pinning behaviour that must not regress.
…lveRuleRefs

Deduplicate the token regex pattern and the collapse logic to reduce code
duplication and make future maintenance easier. Remove the unused warningOffset
field from the Match interface.
Clarify the exact conditions for collapsed links and specify which workspaces
see no byte change in 0.8.6.
Spec 20 §4.1 says a reference inside the text of a K2 link (kept for
claude-code) is resolved. An unknown name inside that text rewrites to
.kiro/steering/ and is reported, covering the only Kiro-specific byte
change 0.8.6 can make in an imported-shape workspace.
An unknown name in a K2 link's text now moves to .kiro/steering/ and is
reported—the only Kiro-specific byte change 0.8.6 makes in an imported-
shape workspace.
…le or not

Clarify that the No byte change condition for AGENTS.md with claude-code
applies when links cite rules claude-code writes OR names that are no rule,
and that without claude-code, updates occur wherever a link text holds
a .claude/rules/<x>.md reference, known rule or not.
…NTS.md

The "No byte change" clause now correctly states that AGENTS.md preserves
bytes unless a link's text names a steering file kiro writes (state B), not
just when it names "no rule" (state C or unknown).
@llima
llima merged commit fd7bffd into main Oct 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant