Skip to content

anchored-docs 2.0.1: spec-compliant frontmatter and audit fixes - #5

Merged
Pmac627 merged 9 commits into
mainfrom
fix/skill-metadata-version
Oct 8, 2026
Merged

Pmac627 merged 9 commits into
mainfrom
fix/skill-metadata-version

Conversation

@Pmac627

@Pmac627 Pmac627 commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

anchored-docs 2.0.1: spec-compliant frontmatter and every remaining 2.0.0 audit item. Merge, then tag v2.0.1 on main.

Changes, one commit each

  • metadata.version (fix:): the skill version moves from a top-level version key (which skills-ref validate rejects) to metadata.version. build-skill.mjs reads it and refuses non-spec top-level keys. INSTALL.md:3 corrected.
  • B7, B9 (fix:): no ** match under a missing --repo root; ste_check expands ~\ in STE_AGENT_PACK.
  • EPIPE (fix:): | head no longer prints a stack trace or turns the exit code into 1.
  • PATH regex (perf:): linear scan replaces a quadratic regex (80,000 dots: about 4 s to 0.17 s). Same output, checked against the regex on 50,000 random strings and on real prose.
  • B13 (fix:): control characters (ESC, OSC 8, bidi overrides) in reports are shown as \x1b / ‮; SKILL.md tells agents to treat docs, code, and tool output as data.
  • B17 (fix:): map --check names a broken _map.json (exit 2) and gives the _map.yaml notice; glossary.md and SKILL.md describe error positions and streams accurately.
  • Mutation survivors (test:): 12 survivors now killed by unit tests; one dead clause removed; the stale >/>= mutant is untestable without a fake clock (documented).
  • Parser quirks (fix:): quotes, key:value, nested lists, reported skipped lines (frontmatter line N not understood), and glossary entries with no term (B16). okf output unchanged on 20 local docs bundles.
  • Baseline (test:): tests/golden/2.0.1 recorded; CI compares against it. Rename rules apply to golden/1.2.0 only. Coverage 77/77 on both.

Verified

  • 71 unit tests, 41/41 parity, 77/77 coverage; CI green on ubuntu, windows, macos.
  • build --tag v2.0.1 succeeds; skills-ref validate passes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2

Pmac627 and others added 9 commits October 7, 2026 16:20
The Agent Skills specification allows only name, description, license,
compatibility, metadata, and allowed-tools at the top level. skills-ref
validate rejected 2.0.0 for its top-level version key. build-skill.mjs now
reads metadata.version and refuses any other top-level key. INSTALL.md
lists the real keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
globExists yielded the root for "**" even when it did not exist, so
okf --repo nope accepted sources: "**" (1.2.0 reported "matches no file").
ste_check had its own expandUser that handled only ~/; it now uses the one
in _fm.mjs, which also handles ~\ as STE_ORG_GLOSSARY does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
docs_check | head and ste_check | head printed an unhandled EPIPE stack
trace and exited 1, the findings code. writeReport in _compat.mjs ignores
EPIPE on stdout, so the exit code stays the one the checks gave.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
The PATH regex in ste_check restarted at every "." and "-" of a run and read
to the end of the run each time: 80,000 dots took about 4 s. replacePaths in
_compat.mjs scans once and gives the same result; a unit test compares it
with the regex on fixed edge cases and 50,000 random strings. ste_check
output is unchanged on the references, SKILL.md, README, the fixtures, and
the ste-generator-kit docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
…put as data

The reports repeat text from docs, glossaries, and arguments. An ESC or OSC 8
sequence there reached the terminal raw (B13), as in 1.x. writeReport and the
stderr paths now pass text through escapeControls, which shows C0/C1
controls, DEL, and bidi overrides as \xNN or \uNNNN. SKILL.md Rule 1 tells
the agent to treat docs, code, and tool output as data, not instructions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
B17 from the 2.0.0 audit:
- map --check treated an invalid _map.json as "out of date" (exit 1). It now
  stops with exit 2 and names the file, as affected does.
- The _map.yaml notice appeared only in affected; map --check gives it too.
  links does not read the map, so it has no notice.
- glossary.md promised the position of every JSON error. V8 gives none for
  "Unexpected token" errors (a leftover YAML file) or an empty file; the doc
  now says so.
- SKILL.md says which stream carries the exit-2 cause: stderr for ste_check,
  stdout for docs_check (unchanged from 1.x).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
The audit left 15 surviving mutants. Re-run with a fresh harness, 13 of the
14 that still applied now fail a unit test: path-depth order, each skipped
vendor folder, --repo removal, image links, process: actors, the Unicode
word boundary, let's, ste-ok: all, blockquotes, and lettered lists.

- The "**"-to-"*" retry in affected could never change the result
  (fnmatchTranslate already collapses "**"), so it is removed.
- The stale ">" vs ">=" mutant differs only at the exact millisecond; it
  stays, as noted in tests/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
2.0.0 kept five 1.x parser quirks to prove the port. 2.0.1 fixes them:
- A quote opens a quoted value only where a value starts, so the
  apostrophe in "Don't # note" no longer hides the comment.
- A key needs whitespace or end of line after the colon: "key:value" and
  "http://x.y" are no longer keys.
- A list under a key in a list item or block map is that key's value,
  indented under the key or at its column.
- okf reports each frontmatter line outside the subset as "frontmatter line
  N not understood" instead of dropping it silently.
- A glossary entry with no term text is a GlossaryError naming the entry
  (B16), instead of losing its synonyms silently.

fm.test.mjs records the four 1.2.0 cases that change (INTENDED). okf output
is unchanged on 20 local docs bundles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
tests/golden/2.0.1 is the run-cases output of 2.0.1, recorded after it
matched tests/golden/1.2.0 on all 41 cases. CI now compares with it, so a
later intended output change records a new baseline instead of adding
rename rules. intended-differences.json applies to golden/1.2.0 only (a
legacy-file notice in a newer baseline must keep the 1.x name), and
coverage applies the same rules, with patterns now in 2.0 names: 77 of 77 on
both baselines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGrZof6i8VqejqmYTqEfg2
@Pmac627
Pmac627 marked this pull request as ready for review October 8, 2026 12:05
@Pmac627
Pmac627 merged commit 23593a7 into main Oct 8, 2026
3 checks passed
@Pmac627
Pmac627 deleted the fix/skill-metadata-version branch October 8, 2026 12:25
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