Skip to content

Slim SKILL.md, split the READMEs, and fix the export and audit scripts (0.2.0) - #2

Merged
88lin merged 6 commits into
masterfrom
refactor/slim-skill-and-split-docs
Aug 3, 2026
Merged

Slim SKILL.md, split the READMEs, and fix the export and audit scripts (0.2.0)#2
88lin merged 6 commits into
masterfrom
refactor/slim-skill-and-split-docs

Conversation

@88lin

@88lin 88lin commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Why

An audit of this repository found that its own tooling flagged its own front page. scripts/audit_docs.py rated README.md the single highest-risk document in the tree (score 6) — 558 lines doing tutorial, how-to, reference and explanation work at once. SKILL.md had four sections describing the same workflow and three describing the same per-form writing rules. Three of the shipped scripts had functional bugs, and CI carried an 11 KB inline copy of one of them that had already drifted.

This PR fixes those and ships 0.2.0. Four commits, one theme each.

Breaking changes

Change Why What to do
The {"skills": {"paths": [...]}} install option is removed OpenCode has no such config key. Anyone following "Option 2" installed a skill that never loaded. Clone into a directory named diataxis-docs under your skills directory.
Cursor export is now .cursor/rules/diataxis.mdc Cursor's rule system ignores plain .md files in .cursor/rules. The previous export has never been read by Cursor. Delete any stale .cursor/rules/diataxis.md and re-run the exporter.
SKILL.md frontmatter version moved to metadata.version version is not in the skill spec; OpenCode ignores unknown top-level keys. Nothing, unless you parse the frontmatter yourself.
audit_docs.py JSON signal key tables renamed to table_rows It counts rows, not tables. Update any consumer of the JSON output.

Functional bugs fixed

  1. The Cursor export never worked. Cursor requires .mdc with frontmatter for files under .cursor/rules; the exporter wrote .md. Now writes .mdc with description and alwaysApply: false, i.e. agent-requested rather than always-on.
  2. Windsurf output silently exceeded the platform limit. Workspace rules cap at 12,000 characters per file, and the full SKILL.md body is about 20,900. Added a modern .windsurf/rules/diataxis.md target with trigger: model_decision, kept legacy .windsurfrules, and the exporter now warns when a target's limit is exceeded.
  3. Resident-context cost was undocumented. Ten of the thirteen targets load into every request — roughly 5,200 tokens per request for a full export. --compact exports five decision-critical sections instead, at roughly 2,300. Documented in the IDE integration page.
  4. audit_docs.py miscounted tables. Any line with two or more | characters counted as a table row, so shell pipelines inside code blocks inflated the reference signal. Tables now require a header row followed by a separator row; code fences and frontmatter are excluded from prose signals.
  5. export_rules.py truncated its own output. strip_frontmatter() used content.split("---", 2), so the body was cut at the first thematic break. Now anchored to line boundaries.
  6. export_rules.py exited 0 on failure. Write errors and unknown --only keys now exit 1.
  7. check_local.py reported a false positive. diataxis-docs-skill/scripts was read as a skills/scripts install path. The pattern now requires a word boundary before skills/.
  8. check_local.py required a non-existent field. Command frontmatter name is not part of the OpenCode command spec — the command name comes from the filename. It is now optional, and validated only when present.

Documentation

README.md goes from 558 lines to 128, README.zh-CN.md from 566 to 122. Everything else moves into ten task-scoped pages under docs/ and docs/zh-CN/, kept in sync by a new parity check:

Page For
installation.md Getting it loaded in OpenCode or Claude Code
commands.md What each slash command takes and returns
ide-integration.md Exporting to 11 other assistants, and what it costs
development.md Running the checks, adding evals and commands
faq.md Scope, design, and what the skill does not do

The install docs now warn that the clone target directory must be named diataxis-docs: OpenCode matches it against the frontmatter name and fails silently on a mismatch, so git clone with the default repository name produces a skill that is never loaded.

SKILL.md drops from 463 to 413 lines with no guidance removed — the deleted sections restated content that already lived elsewhere, and the artifact-to-compass-cell table moved to references/template-map.md, which loads on demand rather than on every invocation.

Tests and CI

tests/test_check_local.py is new (23 cases); tests/test_audit_docs.py was rewritten around the table and code-fence fixes (13 cases). CI is now a single matrix job over Python 3.11 and 3.12 with a read-only token, ref-scoped concurrency and manual dispatch, calling the scripts instead of re-implementing them.

Verification

python scripts/check_local.py                                      exit 0, 1 warning
python -m unittest discover -s tests -p 'test_*.py'                36 tests, OK
python scripts/audit_docs.py . --exclude CHANGELOG.md --fail-on high   exit 0, high risk: 0
python scripts/export_rules.py --list                              13 targets, 11 assistants
python scripts/export_rules.py --target TMP --dry-run --compact    writes nothing, exit 0

README.md drops from high risk (score 6) to medium (score 2); no page in the repository is high risk. Installing into a directory named diataxis-docs was simulated and the frontmatter name matches.

Known limitations

  • The one remaining check_local.py warning is that SKILL.md is 405 body lines, past the 400-line soft budget and under the 500-line hard limit. Getting it materially smaller means restructuring around progressive disclosure — moving the anti-pattern lists and workflow philosophy into references/ — which is a behavioural change to the skill, not a cleanup, and belongs in its own PR.
  • Unknown frontmatter keys warn rather than fail. Both OpenCode and Claude Code ignore unrecognised keys, so a hard failure would break anyone carrying custom metadata. The tests assert the warning is emitted.
  • --compact output is about 9,400 characters, still over the 6,000-character legacy .windsurfrules limit. The exporter warns; the docs point Windsurf users at the modern target.

PR-Codex overview

This PR focuses on updating documentation for the Diataxis Docs Skill, including changes to commands, installation instructions, and metadata. It enhances clarity and structure while introducing new guidelines for command usage.

Detailed summary

  • Updated command descriptions in .opencode/commands/.
  • Added new entries to .gitignore.
  • Revised frontmatter requirements in CONTRIBUTING.md.
  • Changed versioning format in SKILL.md.
  • Enhanced documentation clarity in various files, including faq.md and development.md.

The following files were skipped due to too many changes: SKILL.md, .github/workflows/ci.yml, scripts/audit_docs.py, tests/test_check_local.py, README.zh-CN.md, scripts/export_rules.py, evals/evals.json, CHANGELOG.md, scripts/check_local.py, README.md

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

88lin and others added 6 commits July 30, 2026 17:00
The file had four sections describing the same workflow and three
describing the same per-form writing rules. `compass` appeared 30 times
in 463 lines.

- Merge `Core idea` into the compass section opener.
- Fold `Template selection heuristic` into the decision tree as
  `Request phrasing shortcuts`.
- Distribute `Writing patterns` into the matching `Classification guide`
  bullets, where the same guidance already lived.
- Merge `Practical output pattern` diagnosis steps into
  `Typical delivery pattern`.
- Move the artifact-to-compass-cell table to references/template-map.md,
  which is loaded on demand instead of on every skill invocation.
- Fix the intent check pointing at a "Diataxis decision tree" section
  that does not exist.

Frontmatter: `version` is not a field OpenCode recognises, and unknown
keys are silently ignored, so the value moves under `metadata.version`.

463 -> 413 lines, no guidance removed.
The repository's own audit script rated README.md the single highest
risk page in the tree (score 6): 558 lines doing tutorial, how-to,
reference and explanation work at once. A skill about not mixing
document forms should not ship that as its front door.

- README.md: 558 -> 128 lines. Keeps what a first-time reader needs to
  decide whether to install, and links out for everything else.
- README.zh-CN.md: mirrors the same structure.
- docs/ and docs/zh-CN/: five task-scoped pages per language covering
  installation, slash commands, IDE integration, development and FAQ.

Two documentation bugs fixed along the way:

- The `{"skills": {"paths": [...]}}` install option does not exist.
  OpenCode has no such config key, so anyone following "Option 2" ended
  up with a skill that never loaded. Removed, with a FAQ entry saying
  so explicitly.
- The clone target directory must be named `diataxis-docs`. OpenCode
  matches the directory name against the frontmatter `name` and fails
  silently on a mismatch, so `git clone` with the default repository
  name produces a skill that is never loaded. Both READMEs and both
  installation pages now call this out.
CI carried ~11 KB of inline Python that re-implemented check_local.py.
The two copies had already drifted. CI now calls the script.

check_local.py
- Validate skill and command frontmatter against the fields OpenCode
  actually recognises. Unknown keys warn rather than fail: both OpenCode
  and Claude Code ignore them, so failing would break custom metadata.
- Command frontmatter no longer requires `name`; OpenCode derives the
  command from the filename. When present it must match the stem.
- Fix a false positive where `diataxis-docs-skill/scripts` was read as
  a `skills/scripts` install path.
- Fix frontmatter parsing stripping a `#` inside a quoted value.
- Add eval structure validation, HTML <img src> link checking, and
  bilingual translation parity.

audit_docs.py
- Any line with two pipes counted as a table row, so shell pipelines in
  code blocks inflated the reference signal. Tables now need a header
  row plus a separator row, and code blocks and frontmatter are excluded
  from prose signals.
- Rename the `tables` signal key to `table_rows`.
- Add --fail-on {none,medium,high} and repeatable --exclude GLOB.

export_rules.py
- Cursor ignores plain .md files in .cursor/rules, so the Cursor export
  has never loaded. Write .cursor/rules/diataxis.mdc with `description`
  and `alwaysApply: false`.
- Add a modern Windsurf target with `trigger: model_decision`. Warn when
  output exceeds a target's limit (12k modern, 6k legacy .windsurfrules).
- strip_frontmatter() used content.split("---", 2) and truncated the
  body at the first thematic break. Now anchored to line boundaries.
- Add --list, --dry-run, --force, --only, --target, --compact. Ten of
  the thirteen targets are always-on, roughly 5.2k tokens per request
  for a full export against 2.3k for --compact.
- Exit 1 on write failure and on an unknown --only key.

tests/
- test_check_local.py is new: 23 cases over frontmatter parsing, name
  and description limits, install-path scanning and anchors.
- test_audit_docs.py rewritten around the table and code-fence fixes.

.gitignore is new: build artefacts plus every rule file the exporter
can write, so exporting inside this repository no longer dirties it.
Twelve unreleased subsections had accumulated since 0.1.0. Archive them
into a single [0.2.0] entry grouped Removed / Added / Changed / Fixed,
one line per change, with the breaking items marked:

- The `skills.paths` install option is gone; it never existed.
- SKILL.md frontmatter `version` moved to `metadata.version`.
- The Cursor export target changed from .md to .mdc.
- The audit signal key `tables` is now `table_rows`.

evals.json: version 0.2.0 and a top-level `categories` array listing the
11 categories the 32 evals cover, so coverage gaps are visible without
walking the eval list.
@88lin
88lin merged commit 8089f75 into master Aug 3, 2026
4 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