@vibe-agent-toolkit/vat-development-agents 0.1.37 → 0.1.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/dist/.claude/plugins/marketplaces/vat-skills/.claude-plugin/marketplace.json +1 -1
  3. package/dist/.claude/plugins/marketplaces/vat-skills/CHANGELOG.md +184 -0
  4. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/.claude-plugin/plugin.json +1 -1
  5. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-adoption-and-configuration/SKILL.md +4 -1
  6. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-agent-authoring/SKILL.md +4 -1
  7. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-audit/SKILL.md +4 -1
  8. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-enterprise-org/SKILL.md +3 -1
  9. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-knowledge-resources/SKILL.md +43 -1
  10. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-rag/SKILL.md +4 -1
  11. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-authoring/SKILL.md +27 -1
  12. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-distribution/SKILL.md +5 -2
  13. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-review/SKILL.md +4 -1
  14. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vibe-agent-toolkit/SKILL.md +5 -1
  15. package/dist/generated/resources/skills/SKILL.js +3 -3
  16. package/dist/generated/resources/skills/markdown-rewriting.d.ts +28 -0
  17. package/dist/generated/resources/skills/markdown-rewriting.js +48 -0
  18. package/dist/generated/resources/skills/vat-knowledge-resources.d.ts +1 -0
  19. package/dist/generated/resources/skills/vat-knowledge-resources.js +6 -1
  20. package/dist/generated/resources/skills/vat-skill-authoring.d.ts +1 -0
  21. package/dist/generated/resources/skills/vat-skill-authoring.js +6 -1
  22. package/dist/skills/vat-adoption-and-configuration/SKILL.md +4 -1
  23. package/dist/skills/vat-agent-authoring/SKILL.md +4 -1
  24. package/dist/skills/vat-audit/SKILL.md +4 -1
  25. package/dist/skills/vat-enterprise-org/SKILL.md +3 -1
  26. package/dist/skills/vat-knowledge-resources/SKILL.md +43 -1
  27. package/dist/skills/vat-rag/SKILL.md +4 -1
  28. package/dist/skills/vat-skill-authoring/SKILL.md +27 -1
  29. package/dist/skills/vat-skill-distribution/SKILL.md +5 -2
  30. package/dist/skills/vat-skill-review/SKILL.md +4 -1
  31. package/dist/skills/vibe-agent-toolkit/SKILL.md +5 -1
  32. package/package.json +4 -4
  33. package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-distribution/resources/marketplace-distribution.md +0 -427
  34. package/dist/skills/vat-skill-distribution/resources/marketplace-distribution.md +0 -427
package/README.md CHANGED
@@ -71,7 +71,7 @@ vat skills install ./packages/vat-development-agents
71
71
  vat skills list --installed
72
72
  ```
73
73
 
74
- The `vibe-agent-toolkit` skill will be installed to `~/.claude/plugins/vibe-agent-toolkit/` and will appear in Claude Code after restarting or running `/reload-skills`.
74
+ The `vibe-agent-toolkit` skill will be installed to `~/.claude/plugins/vibe-agent-toolkit/` and will appear in Claude Code after restarting or running `/reload-plugins`.
75
75
 
76
76
  **What the skill includes:**
77
77
  - VAT overview and use cases
@@ -9,7 +9,7 @@
9
9
  "name": "vibe-agent-toolkit",
10
10
  "description": "Development agents and skills for building with vibe-agent-toolkit",
11
11
  "source": "./plugins/vibe-agent-toolkit",
12
- "version": "0.1.37",
12
+ "version": "0.1.38",
13
13
  "author": {
14
14
  "name": "vibe-agent-toolkit contributors"
15
15
  }
@@ -7,6 +7,190 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.38] - 2026-05-18
11
+
12
+ ### Changed (breaking, pre-1.0)
13
+
14
+ - **`findProjectRoot` from `@vibe-agent-toolkit/utils` has new semantics.** It
15
+ now walks `vibe-agent-toolkit.config.yaml` → `.git/` and returns
16
+ `string | null` with no fallback to `cwd`. The previous workspace-anchored
17
+ behavior (workspace `package.json` → git → `cwd`, returning `string`) moved
18
+ to a new function: `findNodeWorkspaceRoot`, scoped to workspace `package.json`
19
+ lookup only and also returning `string | null`. Migration: use
20
+ `findNodeWorkspaceRoot` if you wanted Node-monorepo binary discovery; use
21
+ `findProjectRoot` if you wanted the VAT authoring boundary. Either way,
22
+ handle the `null` return — there is no more silent `cwd` fallback.
23
+
24
+ - **`resolveLocalHref` returns a discriminated union.** From
25
+ `{ resolvedPath; anchor } | null` to one of `anchor_only | resolved |
26
+ absolute_no_root | absolute_escapes_root`. The function exported from
27
+ `@vibe-agent-toolkit/resources` now also accepts an optional `projectRoot`
28
+ parameter. Leading-`/` markdown links and frontmatter URI-references now
29
+ resolve against `projectRoot` per RFC 3986 §4.2 absolute-path-reference
30
+ semantics — matching GitHub, MkDocs, Sphinx, Docusaurus, VuePress, Jekyll,
31
+ Astro Starlight, Nextra, and MDN. Previously `safePath.resolve(sourceDir,
32
+ '/docs/foo.md')` resolved to filesystem-absolute `/docs/foo.md`. The two
33
+ new union kinds (`absolute_no_root`, `absolute_escapes_root`) surface to
34
+ consumers as the existing `broken_file` issue with distinct messages — no
35
+ new validation-code names. External callers destructuring the old return
36
+ shape must update to switch on `kind`.
37
+
38
+ - **`ValidateLinkOptions.projectRoot` semantic narrowing.** In monorepos, the
39
+ effective root for link validation is now the nearest
40
+ `vibe-agent-toolkit.config.yaml` ancestor (or `.git/` ancestor), not the
41
+ workspace root. Cross-package relative links (`../sibling-pkg/foo.md`) are
42
+ still validated for file existence, case mismatches, and anchor resolution
43
+ — path-based logic is unaffected. **The gitignore-safety gate, however,
44
+ scopes to the sub-package's `projectRoot` only.** Adopters who own per-package
45
+ `vibe-agent-toolkit.config.yaml` files in a monorepo and rely on
46
+ workspace-wide gitignore checking for cross-package doc links must either
47
+ move the config up to the workspace root or accept the narrower scope. In
48
+ practice, the file-existence + anchor checks are what catch broken links;
49
+ the narrower gitignore gate matches how VAT already treats links to
50
+ truly-external files.
51
+
52
+ - **Some adopter configs may need `validation.allow.LINK_OUTSIDE_PROJECT`.**
53
+ Because the effective `projectRoot` narrows in monorepos with per-package
54
+ configs, cross-package links that previously passed under workspace-wide
55
+ scope may now emit `LINK_OUTSIDE_PROJECT`. Add a `validation.allow` entry
56
+ for the affected paths or `validation.severity` override at the config that
57
+ governs the linking skill.
58
+
59
+ - **`Logger.warn` added to the CLI `Logger` interface.** The interface widened
60
+ with a `warn(message: string): void` method that writes to stderr. If you
61
+ implement the `Logger` interface directly (custom embedders, test doubles),
62
+ add the method.
63
+
64
+ - **`excludeReferencesFromBundle` no longer masks cross-package links flagged
65
+ as outside-project.** Under the new `projectRoot` model, `outside-project`
66
+ fires before bundle-exclusion pattern match. If you used
67
+ `excludeReferencesFromBundle` to hide cross-package links from audit, those
68
+ links will now surface — switch to `validation.severity` or `validation.allow`
69
+ on `LINK_OUTSIDE_PROJECT` for the relevant skill.
70
+
71
+ - **Skill packager rewrites frontmatter URI-references during packaging.**
72
+ When a markdown file's collection has a `frontmatterSchema` configured, the
73
+ packager now walks every schema-annotated URI-reference field (`format:
74
+ uri-reference`, `uri`, `iri-reference`, `iri`) and rewrites the value with
75
+ the same target-path lookup that drives body-link rewriting. Body and
76
+ frontmatter URI-refs now agree on packaged paths, and inline comments on
77
+ rewritten fields survive. Previously, packaged artifacts could ship with
78
+ rewritten body links but stale source-path frontmatter pointers — a silent
79
+ half-correct rewrite.
80
+
81
+ - **`@vibe-agent-toolkit/resource-compiler` now depends on
82
+ `@vibe-agent-toolkit/resources`.** The markdown parser there goes through
83
+ `openFrontmatter` so frontmatter comments survive into compiled output.
84
+ Pure transitive consumers see no API change; embedders who installed
85
+ `resource-compiler` standalone now pull `resources` too.
86
+
87
+ ### Added
88
+
89
+ - **Canonical comment-preserving primitive for frontmatter edits:
90
+ `openFrontmatter` from `@vibe-agent-toolkit/resources`.** Wraps `yaml`
91
+ (eemeli) in a round-trip-safe editor with `get` / `set` / `setArrayItem` /
92
+ `appendArrayItem` / `delete` / `toString` and a settable `body`. Comments,
93
+ blank lines, key order, quoting style, anchors, and EOL survive on
94
+ mutation. `openFrontmatter(x).toString()` is byte-identical to `x` until
95
+ you mutate. Malformed YAML throws `FrontmatterParseError` with the
96
+ underlying error on `.cause`. Use this instead of `gray-matter`,
97
+ `front-matter`, or raw `yaml.parse` for any write path — those drop
98
+ comments silently.
99
+
100
+ - **`createAjvWithUriFormats(options?)` from `@vibe-agent-toolkit/resources`** —
101
+ Ajv factory pre-registered with the URI-family formats (`uri`,
102
+ `uri-reference`, `iri`, `iri-reference`) plus the rest of the
103
+ `ajv-formats` standard vocabulary. Use this anywhere downstream code
104
+ compiles a schema that may reference those formats: vanilla
105
+ `new Ajv({ allErrors: true })` throws `unknown format "uri-reference"
106
+ ignored` under default strict mode, and adopters had to invent the
107
+ workaround themselves. `iri` / `iri-reference` are registered as no-op
108
+ validators (semantic validation is the caller's job — VAT uses
109
+ `resolveLocalHref` for that). Ajv options pass through unchanged so
110
+ callers control `allErrors`, `strict`, `verbose`, etc.
111
+
112
+ - **Three rewriter helpers sharing one `(href: string) => string` callback
113
+ shape**, exported from `@vibe-agent-toolkit/resources`:
114
+ - `rewriteBodyLinks(body, rewriteHref)` — inline links + reference
115
+ definitions in the markdown body.
116
+ - `rewriteFrontmatterFieldsAtPaths(editor, paths, rewriteHref)` — when you
117
+ know the field paths by convention (`'meta.parent'`, `'adrs-cited[]'`).
118
+ - `rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref)`
119
+ — when you have a JSON Schema and want every `format: uri-reference`
120
+ field walked automatically. Compose with `rewriteBodyLinks` for the
121
+ common file/folder-rename case.
122
+
123
+ - **New `markdown-rewriting` skill in the `vibe-agent-toolkit` Claude Code
124
+ plugin** — steers any session about to programmatically edit markdown or
125
+ frontmatter toward the comment-preserving primitives above. Includes the
126
+ canonical file-move recipe (body + frontmatter together) and the
127
+ schema-driven variant. Triggers on prompts like "rewrite references
128
+ across these docs", "rename `/docs/specs/` to `/docs/architecture/`",
129
+ "batch-update parent_spec".
130
+
131
+ - **URI-references in frontmatter are now a documented affordance.** Updates
132
+ to two existing skills:
133
+ - `vat-knowledge-resources` — explains the leading-`/` resolution
134
+ + comment-preservation story for schema-annotated URI-ref fields.
135
+ - `vat-skill-authoring` — recommends leading-`/` URI-refs for cross-document
136
+ references in SKILL.md frontmatter and cross-links `markdown-rewriting`
137
+ for programmatic edits.
138
+
139
+ - **Per-command `projectRoot` and config policies, documented and enforced.**
140
+ Every `vat` command now declares its `projectRoot` policy (`required` /
141
+ `tolerate null` / `loud-cwd` / `N/A`) and config policy (`required file` /
142
+ `required fields` / `accept defaults` / `not used`) in `--help` output and
143
+ in its CLI reference doc under `packages/cli/docs/` or `docs/cli/`. The
144
+ canonical source is the new [Roots and Config — Canonical
145
+ Concepts](docs/concepts/roots-and-config.md) doc. Run `vat <cmd> --help` to
146
+ see the `Requirements:` block for any command.
147
+
148
+ - **Loud-cwd fallback for `vat resources scan` and `vat resources validate`.**
149
+ When invoked without an explicit path and no `vibe-agent-toolkit.config.yaml`
150
+ or `.git/` ancestor is found, these commands now fall back to `cwd` and emit
151
+ a single stderr warning (`warn: no vibe-agent-toolkit.config.yaml or .git/
152
+ ancestor; using <cwd> as projectRoot`) instead of failing silently or
153
+ surprising the user. With an explicit path argument the path is used and no
154
+ warning fires.
155
+
156
+ - **`docs/concepts/roots-and-config.md`** — single source of truth for the
157
+ three-root model (`projectRoot` / `gitRoot` / `nodeWorkspaceRoot`), the
158
+ config-then-git discovery ladder, the CLI-boundary discovery rule, the
159
+ per-command policy matrix, and the loud-cwd fallback contract. Every
160
+ command's `Requirements:` help block links to this doc.
161
+
162
+ ### Removed
163
+
164
+ - `findConfigPath`, `findConfigFile` (from `packages/resources/src/config-parser.ts`),
165
+ `findGoverningConfig`, `resetGoverningConfigCache`. Use `findConfigFile`
166
+ from `@vibe-agent-toolkit/utils` for config discovery, and `findProjectRoot`
167
+ + `loadConfigCached` for root + config loading at CLI boundaries. Cache
168
+ resets: `resetGoverningConfigCache()` → `resetProjectRootCaches() +
169
+ resetLoadedConfigCache()`.
170
+
171
+ ### Performance
172
+
173
+ - **`vat audit` is faster on large scan targets.** Per-skill `projectRoot`
174
+ lookup now hits a module-level cache pre-warmed during the scan descent, so
175
+ large multi-skill audits no longer repeat filesystem walk-ups per skill.
176
+
177
+ ### Fixed
178
+
179
+ - **Markdown links to directories now surface as `broken_file`.** Previously, links resolving to an existing directory (e.g., `/docs/`, `../`, or any href whose resolved path is a directory rather than a file) silently passed validation. They now emit `broken_file` with `Link target is a directory: <path>` and a suggestion to link to a file inside the directory.
180
+
181
+ - **Leading-`/` links no longer false-flag as path-traversal escapes when the project root traverses a symlink.** `isWithinProject` now canonicalizes both sides of the within-check symmetrically (via `realpathSync`). Previously, when `projectRoot` was a symlinked path — common on macOS (`/tmp` → `/private/tmp`), bind mounts, and CI containers — a legitimate `/foo.md` resolution to `projectRoot/foo.md` was incorrectly reported as `absolute_escapes_root` because only the file side was realpath'd. The same fix also corrects the latent identical bug in the pre-existing gitignore-safety gate of `validateLocalFile`.
182
+
183
+ - **`vat claude plugin install` post-install hints now point to the correct Claude Code slash command.** Both the standard and `--dev` install paths previously suggested `/reload-skills`, which is not a registered Claude Code CLI command — the real one is `/reload-plugins`. Docs (`packages/cli/docs/skills.md`, `docs/guides/distributing-vat-skills.md`, plugin READMEs, `vat-example-cat-agents` distribution doc) updated to match.
184
+
185
+ - **`vat resources validate` no longer floods stderr with `unknown format
186
+ "uri-reference" ignored` warnings.** Ajv's default vocabulary doesn't
187
+ include URI-family formats; with `format: uri-reference` first-class in
188
+ frontmatter, the validator used to log one warning per occurrence (often 20+
189
+ per validate run). The validator now registers `ajv-formats` against its
190
+ Ajv instance, which silences the warnings without changing semantics — VAT's
191
+ own walker validates URI-ref hrefs against `resolveLocalHref`, not Ajv's
192
+ format definitions. Adopter-surfaced cleanup.
193
+
10
194
  ## [0.1.37] - 2026-05-16
11
195
 
12
196
  ### Fixed
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "license": "MIT",
3
3
  "name": "vibe-agent-toolkit",
4
- "version": "0.1.37",
4
+ "version": "0.1.38",
5
5
  "author": {
6
6
  "name": "vibe-agent-toolkit contributors"
7
7
  },
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-adoption-and-configuration
3
- description: Use when starting a new VAT project, adding VAT to an existing repo, or orienting to `vibe-agent-toolkit.config.yaml`. Covers project setup, repo structure, package.json wiring, vibe-validate integration, and the npm postinstall hook.
3
+ description: Use when starting a new VAT project, adding VAT to an existing
4
+ repo, or orienting to `vibe-agent-toolkit.config.yaml`. Covers project setup,
5
+ repo structure, package.json wiring, vibe-validate integration, and the npm
6
+ postinstall hook.
4
7
  ---
5
8
 
6
9
  # VAT Adoption and Configuration
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-agent-authoring
3
- description: Use when authoring TypeScript portable agents — agent archetypes, agent.yaml, result envelopes, orchestration patterns, and runtime adapters (Vercel/LangChain/OpenAI/Claude Agent SDK). Paired with vat-skill-authoring for the SKILL.md side.
3
+ description: Use when authoring TypeScript portable agents — agent archetypes,
4
+ agent.yaml, result envelopes, orchestration patterns, and runtime adapters
5
+ (Vercel/LangChain/OpenAI/Claude Agent SDK). Paired with vat-skill-authoring
6
+ for the SKILL.md side.
4
7
  ---
5
8
 
6
9
  # VAT Agent Authoring: Archetypes, Envelopes, Orchestration
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-audit
3
- description: Use when running vat audit to validate Claude plugins, agent skills, or marketplaces. Covers the audit command, --compat flag for surface compatibility analysis, --exclude for noise filtering, and interpreting audit output.
3
+ description: Use when running vat audit to validate Claude plugins, agent
4
+ skills, or marketplaces. Covers the audit command, --compat flag for surface
5
+ compatibility analysis, --exclude for noise filtering, and interpreting audit
6
+ output.
4
7
  ---
5
8
 
6
9
  # VAT Audit: Validating Plugins, Skills & Marketplaces
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: vat-enterprise-org
3
- description: Use for Anthropic Enterprise/Team org administration via the Admin API — user management, API-key auditing, cost/usage reporting, workspace admin, and enterprise skill distribution. Requires ANTHROPIC_ADMIN_API_KEY.
3
+ description: Use for Anthropic Enterprise/Team org administration via the Admin
4
+ API — user management, API-key auditing, cost/usage reporting, workspace
5
+ admin, and enterprise skill distribution. Requires ANTHROPIC_ADMIN_API_KEY.
4
6
  ---
5
7
 
6
8
  # Claude Org Administration
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: vat-knowledge-resources
3
- description: Use when working with VAT resource collections, per-directory frontmatter schema validation, link validation, or the vat resources command. Covers collection configuration, schema mapping, and validation modes.
3
+ description: Use when working with VAT resource collections, per-directory
4
+ frontmatter schema validation, link validation, or the vat resources command.
5
+ Covers collection configuration, schema mapping, and validation modes.
4
6
  ---
5
7
 
6
8
  # VAT Resources: Collections & Frontmatter Validation
@@ -111,6 +113,46 @@ const PrdFrontmatter = z.object({
111
113
 
112
114
  **Tip:** `format` is advisory in JSON Schema; pair it with a `pattern` regex when you also need parse-time rejection of invalid inputs.
113
115
 
116
+ ## URI-references in frontmatter
117
+
118
+ VAT validates frontmatter fields whose schema position has `format: uri-reference`
119
+ (or `uri`, `iri-reference`, `iri`) against the same rules as body links:
120
+
121
+ - Leading-`/` is RFC 3986 §4.2 absolute-path reference — resolved against
122
+ the project root. Same semantics as body links.
123
+ - Anchor fragments and external URLs are accepted; broken local refs error.
124
+ - Inline comments on URI-ref fields are **preserved** when any tool rewrites
125
+ the file via `openFrontmatter` (VAT packager, hand-rolled adopter scripts).
126
+
127
+ Example:
128
+
129
+ ```yaml
130
+ ---
131
+ parent_spec: /docs/specs/foo.md # the spec this one supersedes
132
+ adrs-cited:
133
+ - /docs/adrs/0007-storage.md # primary reference
134
+ - /docs/adrs/0011-snapshot.md # impacted by storage choice
135
+ ---
136
+ ```
137
+
138
+ Schema:
139
+
140
+ ```json
141
+ {
142
+ "type": "object",
143
+ "properties": {
144
+ "parent_spec": { "type": "string", "format": "uri-reference" },
145
+ "adrs-cited": {
146
+ "type": "array",
147
+ "items": { "type": "string", "format": "uri-reference" }
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ For tools that **modify** frontmatter (not just validate it), see
154
+ [[markdown-rewriting]].
155
+
114
156
  ## Validation Output
115
157
 
116
158
  ```yaml
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-rag
3
- description: Use when running `vat rag index` / `vat rag query` or configuring RAG for agent context — covers the CLI commands, native embedding providers and vector store support, chunking, custom metadata, and extension points for adding new backends.
3
+ description: Use when running `vat rag index` / `vat rag query` or configuring
4
+ RAG for agent context — covers the CLI commands, native embedding providers
5
+ and vector store support, chunking, custom metadata, and extension points for
6
+ adding new backends.
4
7
  ---
5
8
 
6
9
  # VAT RAG: Indexing and Querying Markdown with Native Providers
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-skill-authoring
3
- description: Use when authoring or revising a SKILL.md file — frontmatter, body structure, references, packagingOptions (linkFollowDepth, excludeReferencesFromBundle), and validation overrides. Paired with vat-skill-review for pre-publication checks.
3
+ description: Use when authoring or revising a SKILL.md file — frontmatter, body
4
+ structure, references, packagingOptions (linkFollowDepth,
5
+ excludeReferencesFromBundle), and validation overrides. Paired with
6
+ vat-skill-review for pre-publication checks.
4
7
  ---
5
8
 
6
9
  # VAT Skill Authoring: SKILL.md Structure and Packaging
@@ -34,6 +37,29 @@ Best practices for `description`:
34
37
  - Write in third person. First-person ("I can...") and conversational second-person ("You can use...") fire `SKILL_DESCRIPTION_WRONG_PERSON`.
35
38
  - Keep under 250 characters so the Claude Code `/skills` listing doesn't truncate the tail (target ≤200 for safety, ≤130 if shipping a large skill collection). The hard schema limit is 1024.
36
39
 
40
+ ## Cross-document references in SKILL.md frontmatter
41
+
42
+ When SKILL.md frontmatter references other documents (parent specs, ADRs,
43
+ related skills), use **leading-`/`** URI-references:
44
+
45
+ ```yaml
46
+ ---
47
+ parent_spec: /docs/specs/foo.md
48
+ related-skills:
49
+ - /packages/foo/resources/skills/bar/SKILL.md
50
+ ---
51
+ ```
52
+
53
+ These resolve against the project root per RFC 3986 §4.2 (same rule VAT
54
+ applies to body links). Source-relative paths (`../../docs/foo.md`) also
55
+ work but are fragile when skills move.
56
+
57
+ If a tool needs to programmatically rewrite these references — e.g., when
58
+ moving a file — load [[markdown-rewriting]] for the canonical pattern.
59
+ Never use `gray-matter`, `front-matter`, or `js-yaml` directly for SKILL.md
60
+ edits; they silently drop frontmatter comments. ESLint enforces this for
61
+ VAT-internal code.
62
+
37
63
  ## Body Structure
38
64
 
39
65
  - Lead with a short orientation paragraph: what the skill owns and when to reach for it.
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-skill-distribution
3
- description: Use when setting up `vat build`, configuring plugin distribution (marketplace, plugins, managed settings), npm publishing with postinstall hooks, or `vat verify` — the full pipeline from skill source to installed plugin.
3
+ description: Use when setting up `vat build`, configuring plugin distribution
4
+ (marketplace, plugins, managed settings), npm publishing with postinstall
5
+ hooks, or `vat verify` — the full pipeline from skill source to installed
6
+ plugin.
4
7
  ---
5
8
 
6
9
  # VAT Distribution: Build, Publish & Install
@@ -468,4 +471,4 @@ everything (minus `skills/` and `.claude-plugin/`), merges author `plugin.json`
468
471
  VAT-owned identity fields, and applies any `files[]` mappings for artifacts built
469
472
  outside the plugin dir.
470
473
 
471
- See [docs/guides/marketplace-distribution.md](resources/marketplace-distribution.md) section "Full-plugin authoring".
474
+ See [docs/guides/marketplace-distribution.md]() section "Full-plugin authoring".
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vat-skill-review
3
- description: Use when reviewing a skill before publication or running `vat skill review`. Pre-publication quality checklist grouped into general (all skills) and CLI-backed items, tied to VAT validation codes and Anthropic's skill-authoring best practices.
3
+ description: Use when reviewing a skill before publication or running `vat skill
4
+ review`. Pre-publication quality checklist grouped into general (all skills)
5
+ and CLI-backed items, tied to VAT validation codes and Anthropic's
6
+ skill-authoring best practices.
4
7
  ---
5
8
 
6
9
  # Skill Quality Checklist (vat skill review)
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  name: vibe-agent-toolkit
3
- description: Use when starting VAT work or deciding which VAT sub-skill applies. Router that points at sub-skills for adoption, skill/agent authoring, audit, distribution, RAG, knowledge resources, skill review, and enterprise org admin.
3
+ description: Use when starting VAT work or deciding which VAT sub-skill applies.
4
+ Router that points at sub-skills for adoption, skill/agent authoring, audit,
5
+ distribution, RAG, knowledge resources, skill review, and enterprise org
6
+ admin.
4
7
  ---
5
8
 
6
9
  # Vibe Agent Toolkit
@@ -38,6 +41,7 @@ Poor fits:
38
41
  | `vat rag index` / `vat rag query`, embedding providers, vector stores, chunking | `vibe-agent-toolkit:vat-rag` |
39
42
  | Pre-publication quality review, `vat skill review`, validation-code triage | `vibe-agent-toolkit:vat-skill-review` |
40
43
  | Anthropic Admin API: org users, cost/usage, workspace skills, `ANTHROPIC_ADMIN_API_KEY` | `vibe-agent-toolkit:vat-enterprise-org` |
44
+ | Programmatic markdown/frontmatter edits — moving files, updating references, schema-evolution migrations; comment-preserving FrontmatterEditor + rewriteBodyLinks | `vibe-agent-toolkit:markdown-rewriting` |
41
45
 
42
46
  ## CLI Surface at a Glance
43
47
 
@@ -7,7 +7,7 @@ export const meta = {
7
7
  description: "Use when starting VAT work or deciding which VAT sub-skill applies. Router that points at sub-skills for adoption, skill/agent authoring, audit, distribution, RAG, knowledge resources, skill review, and enterprise org admin."
8
8
  };
9
9
 
10
- export const text = "\n# Vibe Agent Toolkit\n\n**Vibe Agent Toolkit (VAT)** is a modular toolkit for building, packaging, and distributing portable AI agents and skills that work across multiple Claude surfaces and adjacent frameworks. Write skill or agent content once; VAT handles validation, packaging, plugin/marketplace layout, and npm publishing.\n\nThis is a router skill. Load the sibling sub-skill that matches the work you\'re doing — each sub-skill owns one slice of VAT\'s surface and is designed to be pulled in on demand.\n\n## When to Use VAT\n\nGood fits:\n\n- Publishing a Claude skill or plugin to npm with a proper marketplace layout\n- Multi-runtime agent projects (Vercel AI SDK, LangChain, OpenAI, Claude Agent SDK)\n- Validating plugins / skills / marketplaces with \`vat audit\` before shipping\n- Enforcing frontmatter schemas across large markdown corpora\n- Wiring RAG indexing into an agent project\n\nPoor fits:\n\n- Simple one-off scripts where the framework is already decided\n- Non-TypeScript/JavaScript projects\n- Cases where you need deep framework-specific features with no reuse goal\n\n## Picking a Sub-skill\n\n| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |\n\n## CLI Surface at a Glance\n\n\`\`\`bash\nvat --help # top-level help\nvat build # build all artifacts (skills → claude plugins)\nvat verify # validate all artifacts\nvat skills validate # validate skill quality\nvat resources validate # validate markdown collections\nvat audit # audit plugins/skills/marketplaces/settings\nvat rag index docs/ # index markdown for RAG\nvat skill review <path> # pre-publication review\nvat claude org --help # enterprise admin surface\n\`\`\`\n\nEach sub-skill covers its slice of the CLI in depth — don\'t memorize this table, load the sub-skill when you need detail.\n\n## Getting Help\n\n- \`vat --help\` and \`vat <group> --help --verbose\` for CLI depth\n- Repo docs: the VAT repository\'s \`docs/\` directory carries the full setup guide, architecture notes, and design references (not bundled with this plugin)\n- Contributor reference docs (debugging VAT, install architecture) live under \`docs/contributing/\` in the VAT repo\n";
10
+ export const text = "\n# Vibe Agent Toolkit\n\n**Vibe Agent Toolkit (VAT)** is a modular toolkit for building, packaging, and distributing portable AI agents and skills that work across multiple Claude surfaces and adjacent frameworks. Write skill or agent content once; VAT handles validation, packaging, plugin/marketplace layout, and npm publishing.\n\nThis is a router skill. Load the sibling sub-skill that matches the work you\'re doing — each sub-skill owns one slice of VAT\'s surface and is designed to be pulled in on demand.\n\n## When to Use VAT\n\nGood fits:\n\n- Publishing a Claude skill or plugin to npm with a proper marketplace layout\n- Multi-runtime agent projects (Vercel AI SDK, LangChain, OpenAI, Claude Agent SDK)\n- Validating plugins / skills / marketplaces with \`vat audit\` before shipping\n- Enforcing frontmatter schemas across large markdown corpora\n- Wiring RAG indexing into an agent project\n\nPoor fits:\n\n- Simple one-off scripts where the framework is already decided\n- Non-TypeScript/JavaScript projects\n- Cases where you need deep framework-specific features with no reuse goal\n\n## Picking a Sub-skill\n\n| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |\n| Programmatic markdown/frontmatter edits — moving files, updating references, schema-evolution migrations; comment-preserving FrontmatterEditor + rewriteBodyLinks | \`vibe-agent-toolkit:markdown-rewriting\` |\n\n## CLI Surface at a Glance\n\n\`\`\`bash\nvat --help # top-level help\nvat build # build all artifacts (skills → claude plugins)\nvat verify # validate all artifacts\nvat skills validate # validate skill quality\nvat resources validate # validate markdown collections\nvat audit # audit plugins/skills/marketplaces/settings\nvat rag index docs/ # index markdown for RAG\nvat skill review <path> # pre-publication review\nvat claude org --help # enterprise admin surface\n\`\`\`\n\nEach sub-skill covers its slice of the CLI in depth — don\'t memorize this table, load the sub-skill when you need detail.\n\n## Getting Help\n\n- \`vat --help\` and \`vat <group> --help --verbose\` for CLI depth\n- Repo docs: the VAT repository\'s \`docs/\` directory carries the full setup guide, architecture notes, and design references (not bundled with this plugin)\n- Contributor reference docs (debugging VAT, install architecture) live under \`docs/contributing/\` in the VAT repo\n";
11
11
 
12
12
  export const fragments = {
13
13
  whenToUseVat: {
@@ -17,8 +17,8 @@ export const fragments = {
17
17
  },
18
18
  pickingASubSkill: {
19
19
  header: "## Picking a Sub-skill",
20
- body: "| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |",
21
- text: "## Picking a Sub-skill\n\n| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |"
20
+ body: "| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |\n| Programmatic markdown/frontmatter edits — moving files, updating references, schema-evolution migrations; comment-preserving FrontmatterEditor + rewriteBodyLinks | \`vibe-agent-toolkit:markdown-rewriting\` |",
21
+ text: "## Picking a Sub-skill\n\n| If you\'re working on... | Load |\n|---|---|\n| New project setup, \`vibe-agent-toolkit.config.yaml\` orientation, repo structure, vibe-validate integration, npm postinstall | \`vibe-agent-toolkit:vat-adoption-and-configuration\` |\n| Writing or revising a SKILL.md — frontmatter, body, references, packagingOptions, validation overrides | \`vibe-agent-toolkit:vat-skill-authoring\` |\n| TypeScript agent archetypes, \`agent.yaml\`, result envelopes, orchestration, runtime adapters | \`vibe-agent-toolkit:vat-agent-authoring\` |\n| \`vat audit\` on plugins, marketplaces, skills, or settings — including \`--compat\`, \`--exclude\`, \`--user\`, CI use | \`vibe-agent-toolkit:vat-audit\` |\n| Markdown collections, \`resources:\` config, frontmatter schema validation, \`vat resources validate\` | \`vibe-agent-toolkit:vat-knowledge-resources\` |\n| \`vat build\`, \`vat verify\`, plugin/marketplace layout, npm publishing, postinstall | \`vibe-agent-toolkit:vat-skill-distribution\` |\n| \`vat rag index\` / \`vat rag query\`, embedding providers, vector stores, chunking | \`vibe-agent-toolkit:vat-rag\` |\n| Pre-publication quality review, \`vat skill review\`, validation-code triage | \`vibe-agent-toolkit:vat-skill-review\` |\n| Anthropic Admin API: org users, cost/usage, workspace skills, \`ANTHROPIC_ADMIN_API_KEY\` | \`vibe-agent-toolkit:vat-enterprise-org\` |\n| Programmatic markdown/frontmatter edits — moving files, updating references, schema-evolution migrations; comment-preserving FrontmatterEditor + rewriteBodyLinks | \`vibe-agent-toolkit:markdown-rewriting\` |"
22
22
  },
23
23
  cliSurfaceAtAGlance: {
24
24
  header: "## CLI Surface at a Glance",
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Generated TypeScript declarations - DO NOT EDIT
3
+ */
4
+
5
+ export interface Fragment {
6
+ readonly header: string;
7
+ readonly body: string;
8
+ readonly text: string;
9
+ }
10
+
11
+ export const meta: {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ };
15
+
16
+ export const text: string;
17
+
18
+ export const fragments: {
19
+ readonly theRule: Fragment;
20
+ readonly antiPatterns-DoNotUseThese: Fragment;
21
+ readonly canonicalRecipeMoveAFileAndUpdateReferences: Fragment;
22
+ readonly whenYouHaveAJsonSchemaForTheFrontmatter: Fragment;
23
+ readonly bulkMigrationManyFilesAtOnce: Fragment;
24
+ readonly whatsPreservedWhatIsnt: Fragment;
25
+ readonly crossLinks: Fragment;
26
+ };
27
+
28
+ export type FragmentName = keyof typeof fragments;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Generated from markdown file - DO NOT EDIT
3
+ */
4
+
5
+ export const meta = {
6
+ name: "markdown-rewriting",
7
+ description: "Use when programmatically editing markdown or frontmatter — moving files, updating references, batch-renaming, schema-evolution migrations. Steers to comment-preserving FrontmatterEditor + rewriteBodyLinks; away from gray-matter/js-yaml/regex."
8
+ };
9
+
10
+ export const text = "\n# Editing markdown safely\n\nWhen you write code that opens a markdown file, mutates the frontmatter or\nbody, and writes it back, you have ONE job that\'s easy to get wrong: keep\nthe file\'s content stable except for the intentional change. Lose comments,\nblank lines, anchors, or quoting style, and every iteration degrades the\ndocs.\n\nVAT ships canonical primitives for this. Use them.\n\n## The rule\n\nFor **any** programmatic markdown edit, use \`@vibe-agent-toolkit/resources\`:\n\n- \`openFrontmatter(markdown)\` — round-trip-safe editor. Comments,\n blank lines, EOL, YAML style all survive read → mutate → write. Exposes\n \`.body\` (settable), \`.get(path)\`, \`.set(path, value)\`, \`.setArrayItem\`,\n \`.appendArrayItem\`, \`.delete(path)\`, \`.isDirty()\`, and \`.toString()\`.\n The underlying \`yaml.Document\` is intentionally not exposed.\n- \`rewriteBodyLinks(body, rewriteHref)\` — walk inline + reference-style\n body links with a per-href callback.\n- \`rewriteFrontmatterFieldsAtPaths(editor, paths, rewriteHref)\` — rewrite\n specific frontmatter fields you know by name. Path syntax: \`\'name\'\`\n (top-level), \`\'name[]\'\` (array of strings — rewrite each item),\n \`\'meta.parent\'\` (nested), \`\'meta.refs[]\'\` (nested array).\n- \`rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref)\` —\n walk every schema-annotated URI-reference field automatically.\n\n**The \`rewriteHref\` callback contract.** Return the new href, or return the\ninput string unchanged to skip that link. Anchor-only hrefs (\`#section\`),\nexternal URLs, and refs that don\'t match your rule should all return as-is.\nThe callback receives only the href string — there is no field-path\ncontext. When rules differ per field (e.g. \`parent_spec\` strict; \`related[]\`\npermissive), use \`rewriteFrontmatterFieldsAtPaths\` with one call per path\ngroup rather than the schema-driven helper.\n\n**The primitives are pure (no I/O).** Read and write with whatever FS API\nfits — \`fs/promises\`, \`fs-extra\`, streams, anything. The recipes below\nuse \`readFileSync\` / \`writeFileSync\` for clarity; production code is\nfree to use async equivalents.\n\n## Anti-patterns — do NOT use these\n\n- ❌ \`gray-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`front-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`js-yaml\` — drops comments AND has YAML 1.1 quirks (ISO date\n promotion). Already banned by ESLint.\n- ❌ Raw \`yaml.parse(text) → mutate → yaml.stringify(obj)\` — drops comments\n even with eemeli \`yaml\`. Use \`openFrontmatter\` for the round-trip case.\n- ❌ Regex on \`---\` fences to extract or replace frontmatter — fragile,\n loses style.\n- ❌ Naive \`body.replaceAll(\'/docs/old/\', \'/docs/new/\')\` — matches inside\n code blocks, inline code spans, attribute values, etc. Use\n \`rewriteBodyLinks\` so only actual markdown links are rewritten.\n\n## Canonical recipe: move a file and update references\n\n\`\`\`typescript\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterFieldsAtPaths,\n} from \'@vibe-agent-toolkit/resources\';\nimport { readFileSync, writeFileSync } from \'node:fs\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/old/\', \'/docs/new/\');\n\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterFieldsAtPaths(\n editor,\n [\'parent_spec\', \'adrs-cited[]\', \'related-specs[]\'],\n rewriteHref,\n);\nwriteFileSync(filePath, editor.toString());\n\`\`\`\n\n## When you have a JSON Schema for the frontmatter\n\nIf the file\'s frontmatter is governed by a schema (collection-validated, or\njust a hand-written schema you trust), use the schema-driven helper\ninstead of listing field paths by hand. **Compose it with \`rewriteBodyLinks\`\nto cover the body too** — most rewrites (file moves, folder renames) want\nboth sides updated:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\n\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\nwriteFileSync(filePath, editor.toString());\n\`\`\`\n\nThe schema-driven call walks every field whose schema position has\n\`format: uri-reference\` (or \`uri\`, \`iri-reference\`, \`iri\`) and rewrites\nthe value via your callback. Fields outside the URI-family are not\ntouched. **Templated-URI formats are intentionally excluded** —\n\`uri-template\` (RFC 6570 templates with \`{var}\` placeholders) and\nJSON-Pointer-derived formats aren\'t file references and don\'t fit the\nrewrite shape.\n\n**Frontmatter-only**: drop the \`rewriteBodyLinks\` line — the rest\nis identical.\n\nAfter running, diff the file (\`git diff <path>\`) to confirm the rewrite\ntouched only the fields and links you expected.\n\n## Bulk migration: many files at once\n\nWhen the rewrite spans dozens or thousands of files (folder rename,\nschema-evolution migration, citation cleanup), the natural shape is\nglob + iterate + dry-run + \`isDirty()\` gate. Pattern:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport { globSync } from \'glob\'; // or \`node:fs\`\'s glob, or fast-glob\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst DRY_RUN = process.env[\'DRY_RUN\'] !== \'false\';\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst files = globSync(\'docs/**/*.md\');\n\nlet changed = 0;\nlet unchanged = 0;\nfor (const filePath of files) {\n const original = readFileSync(filePath, \'utf8\');\n const editor = openFrontmatter(original);\n\n editor.body = rewriteBodyLinks(editor.body, rewriteHref);\n rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\n // Skip files where nothing material changed. Avoids the no-op churn\n // described in §\"What\'s preserved, what isn\'t\".\n const next = editor.toString();\n if (!editor.isDirty() || next === original) {\n unchanged++;\n continue;\n }\n\n if (DRY_RUN) {\n console.log(\`would update ${filePath}\`);\n } else {\n writeFileSync(filePath, next);\n }\n changed++;\n}\n\nconsole.log(\`${DRY_RUN ? \'DRY RUN: \' : \'\'}${changed} changed, ${unchanged} unchanged\`);\n\`\`\`\n\n**Recommended workflow for bulk runs:**\n\n1. **Sentinel-first.** Run on a single representative file first\n (\`globSync\` pattern that matches exactly one path). Eyeball the diff.\n2. **Dry-run the full set.** \`DRY_RUN=true\` lists every file the script\n would touch. Spot-check at least 3 entries before going wet.\n3. **Iterate.** Adjust the callback or schema until the dry-run plan\n matches your intent.\n4. **Run wet.** \`DRY_RUN=false\`. Then run your project\'s link validator\n (\`vat resources validate\`, link-check CI, etc.) on the corpus before\n committing — the rewrite is reversible via \`git checkout\` if any\n targets are wrong.\n\n**Delegating to a subagent.** Bulk rewrites are good subagent work, but\nbrief them with the same three guardrails: provide the exact callback\nrule, mandate dry-run first, and ask for a structured report (counts\nof files changed/unchanged, a sample of 3 before/after diffs). Without\nthose guardrails, a subagent can silently produce a thousand-file diff\nthat\'s wrong in a subtle way and only catchable on careful review.\n\n## What\'s preserved, what isn\'t\n\n\`openFrontmatter\` inherits its preservation guarantees from \`yaml.Document\`\n(eemeli). Read-only round-trip (no mutations) is byte-identical. Once you\nmutate, the frontmatter section is re-emitted by \`yaml.Document\` and a few\nthings normalize:\n\n| Behavior | Preserved on mutation? |\n|---|---|\n| Inline comment **text** (\`# comment\`) | ✅ |\n| Inline comment **leading whitespace** (\` #\` vs \` #\`) | ❌ collapsed to one space |\n| Leading comments on keys | ✅ (best-effort; comment-attachment is yaml.Document\'s call) |\n| Comments on individual array items | ✅ |\n| Block scalar style (\`|\`, \`>\`, \`|-\`, \`>+\`) | ✅ |\n| Quoting style (plain / single / double) | ✅ |\n| Blank lines between blocks | ✅ |\n| Key ordering | ✅ |\n| EOL (LF or CRLF) | ✅ (detected from first line break) |\n| Anchors and aliases | ✅ on round-trip; mutating them follows \`yaml.Document\` semantics, not ours |\n\n**Consequence:** even a \"no-op\" rewrite (callback returns the input\nunchanged) re-emits frontmatter and can collapse \` #\` → \` #\` on every\nline that has an inline comment. The change is harmless but shows up in\n\`git diff\`. Two ways to skip the write in this case:\n\n- **\`editor.isDirty()\`** — returns \`true\` if any mutator was called or\n \`body\` was reassigned to a different string. Cheap, no string compare,\n but flips on any mutator call even when the value didn\'t change\n (e.g. \`set(\'foo\', sameValue)\`). Fine for most workflows.\n- **Byte-level dirty check** — \`editor.toString() !== originalText\`. Catches\n the no-op-rewrite case exactly; one extra serialize per file. Use this\n when you must produce zero diff on no-op runs.\n\nThe bulk-migration recipe above combines both: \`isDirty()\` as the cheap\nshort-circuit, then a byte compare to filter out comment-whitespace-only\ndeltas.\n\n## Cross-links\n\n- \`vat-knowledge-resources\` — how to validate URI-references in\n frontmatter against a collection schema.\n- \`vat-skill-authoring\` — when to use leading-\`/\` (project-root-relative)\n URI-refs in SKILL.md frontmatter.\n";
11
+
12
+ export const fragments = {
13
+ theRule: {
14
+ header: "## The rule",
15
+ body: "For **any** programmatic markdown edit, use \`@vibe-agent-toolkit/resources\`:\n\n- \`openFrontmatter(markdown)\` — round-trip-safe editor. Comments,\n blank lines, EOL, YAML style all survive read → mutate → write. Exposes\n \`.body\` (settable), \`.get(path)\`, \`.set(path, value)\`, \`.setArrayItem\`,\n \`.appendArrayItem\`, \`.delete(path)\`, \`.isDirty()\`, and \`.toString()\`.\n The underlying \`yaml.Document\` is intentionally not exposed.\n- \`rewriteBodyLinks(body, rewriteHref)\` — walk inline + reference-style\n body links with a per-href callback.\n- \`rewriteFrontmatterFieldsAtPaths(editor, paths, rewriteHref)\` — rewrite\n specific frontmatter fields you know by name. Path syntax: \`\'name\'\`\n (top-level), \`\'name[]\'\` (array of strings — rewrite each item),\n \`\'meta.parent\'\` (nested), \`\'meta.refs[]\'\` (nested array).\n- \`rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref)\` —\n walk every schema-annotated URI-reference field automatically.\n\n**The \`rewriteHref\` callback contract.** Return the new href, or return the\ninput string unchanged to skip that link. Anchor-only hrefs (\`#section\`),\nexternal URLs, and refs that don\'t match your rule should all return as-is.\nThe callback receives only the href string — there is no field-path\ncontext. When rules differ per field (e.g. \`parent_spec\` strict; \`related[]\`\npermissive), use \`rewriteFrontmatterFieldsAtPaths\` with one call per path\ngroup rather than the schema-driven helper.\n\n**The primitives are pure (no I/O).** Read and write with whatever FS API\nfits — \`fs/promises\`, \`fs-extra\`, streams, anything. The recipes below\nuse \`readFileSync\` / \`writeFileSync\` for clarity; production code is\nfree to use async equivalents.",
16
+ text: "## The rule\n\nFor **any** programmatic markdown edit, use \`@vibe-agent-toolkit/resources\`:\n\n- \`openFrontmatter(markdown)\` — round-trip-safe editor. Comments,\n blank lines, EOL, YAML style all survive read → mutate → write. Exposes\n \`.body\` (settable), \`.get(path)\`, \`.set(path, value)\`, \`.setArrayItem\`,\n \`.appendArrayItem\`, \`.delete(path)\`, \`.isDirty()\`, and \`.toString()\`.\n The underlying \`yaml.Document\` is intentionally not exposed.\n- \`rewriteBodyLinks(body, rewriteHref)\` — walk inline + reference-style\n body links with a per-href callback.\n- \`rewriteFrontmatterFieldsAtPaths(editor, paths, rewriteHref)\` — rewrite\n specific frontmatter fields you know by name. Path syntax: \`\'name\'\`\n (top-level), \`\'name[]\'\` (array of strings — rewrite each item),\n \`\'meta.parent\'\` (nested), \`\'meta.refs[]\'\` (nested array).\n- \`rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref)\` —\n walk every schema-annotated URI-reference field automatically.\n\n**The \`rewriteHref\` callback contract.** Return the new href, or return the\ninput string unchanged to skip that link. Anchor-only hrefs (\`#section\`),\nexternal URLs, and refs that don\'t match your rule should all return as-is.\nThe callback receives only the href string — there is no field-path\ncontext. When rules differ per field (e.g. \`parent_spec\` strict; \`related[]\`\npermissive), use \`rewriteFrontmatterFieldsAtPaths\` with one call per path\ngroup rather than the schema-driven helper.\n\n**The primitives are pure (no I/O).** Read and write with whatever FS API\nfits — \`fs/promises\`, \`fs-extra\`, streams, anything. The recipes below\nuse \`readFileSync\` / \`writeFileSync\` for clarity; production code is\nfree to use async equivalents."
17
+ },
18
+ antiPatterns-DoNotUseThese: {
19
+ header: "## Anti-patterns — do NOT use these",
20
+ body: "- ❌ \`gray-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`front-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`js-yaml\` — drops comments AND has YAML 1.1 quirks (ISO date\n promotion). Already banned by ESLint.\n- ❌ Raw \`yaml.parse(text) → mutate → yaml.stringify(obj)\` — drops comments\n even with eemeli \`yaml\`. Use \`openFrontmatter\` for the round-trip case.\n- ❌ Regex on \`---\` fences to extract or replace frontmatter — fragile,\n loses style.\n- ❌ Naive \`body.replaceAll(\'/docs/old/\', \'/docs/new/\')\` — matches inside\n code blocks, inline code spans, attribute values, etc. Use\n \`rewriteBodyLinks\` so only actual markdown links are rewritten.",
21
+ text: "## Anti-patterns — do NOT use these\n\n- ❌ \`gray-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`front-matter\` — drops comments. Already banned by ESLint.\n- ❌ \`js-yaml\` — drops comments AND has YAML 1.1 quirks (ISO date\n promotion). Already banned by ESLint.\n- ❌ Raw \`yaml.parse(text) → mutate → yaml.stringify(obj)\` — drops comments\n even with eemeli \`yaml\`. Use \`openFrontmatter\` for the round-trip case.\n- ❌ Regex on \`---\` fences to extract or replace frontmatter — fragile,\n loses style.\n- ❌ Naive \`body.replaceAll(\'/docs/old/\', \'/docs/new/\')\` — matches inside\n code blocks, inline code spans, attribute values, etc. Use\n \`rewriteBodyLinks\` so only actual markdown links are rewritten."
22
+ },
23
+ canonicalRecipeMoveAFileAndUpdateReferences: {
24
+ header: "## Canonical recipe: move a file and update references",
25
+ body: "\`\`\`typescript\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterFieldsAtPaths,\n} from \'@vibe-agent-toolkit/resources\';\nimport { readFileSync, writeFileSync } from \'node:fs\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/old/\', \'/docs/new/\');\n\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterFieldsAtPaths(\n editor,\n [\'parent_spec\', \'adrs-cited[]\', \'related-specs[]\'],\n rewriteHref,\n);\nwriteFileSync(filePath, editor.toString());\n\`\`\`",
26
+ text: "## Canonical recipe: move a file and update references\n\n\`\`\`typescript\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterFieldsAtPaths,\n} from \'@vibe-agent-toolkit/resources\';\nimport { readFileSync, writeFileSync } from \'node:fs\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/old/\', \'/docs/new/\');\n\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterFieldsAtPaths(\n editor,\n [\'parent_spec\', \'adrs-cited[]\', \'related-specs[]\'],\n rewriteHref,\n);\nwriteFileSync(filePath, editor.toString());\n\`\`\`"
27
+ },
28
+ whenYouHaveAJsonSchemaForTheFrontmatter: {
29
+ header: "## When you have a JSON Schema for the frontmatter",
30
+ body: "If the file\'s frontmatter is governed by a schema (collection-validated, or\njust a hand-written schema you trust), use the schema-driven helper\ninstead of listing field paths by hand. **Compose it with \`rewriteBodyLinks\`\nto cover the body too** — most rewrites (file moves, folder renames) want\nboth sides updated:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\n\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\nwriteFileSync(filePath, editor.toString());\n\`\`\`\n\nThe schema-driven call walks every field whose schema position has\n\`format: uri-reference\` (or \`uri\`, \`iri-reference\`, \`iri\`) and rewrites\nthe value via your callback. Fields outside the URI-family are not\ntouched. **Templated-URI formats are intentionally excluded** —\n\`uri-template\` (RFC 6570 templates with \`{var}\` placeholders) and\nJSON-Pointer-derived formats aren\'t file references and don\'t fit the\nrewrite shape.\n\n**Frontmatter-only**: drop the \`rewriteBodyLinks\` line — the rest\nis identical.\n\nAfter running, diff the file (\`git diff <path>\`) to confirm the rewrite\ntouched only the fields and links you expected.",
31
+ text: "## When you have a JSON Schema for the frontmatter\n\nIf the file\'s frontmatter is governed by a schema (collection-validated, or\njust a hand-written schema you trust), use the schema-driven helper\ninstead of listing field paths by hand. **Compose it with \`rewriteBodyLinks\`\nto cover the body too** — most rewrites (file moves, folder renames) want\nboth sides updated:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst filePath = \'docs/specs/foo.md\';\nconst editor = openFrontmatter(readFileSync(filePath, \'utf8\'));\n\neditor.body = rewriteBodyLinks(editor.body, rewriteHref);\nrewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\nwriteFileSync(filePath, editor.toString());\n\`\`\`\n\nThe schema-driven call walks every field whose schema position has\n\`format: uri-reference\` (or \`uri\`, \`iri-reference\`, \`iri\`) and rewrites\nthe value via your callback. Fields outside the URI-family are not\ntouched. **Templated-URI formats are intentionally excluded** —\n\`uri-template\` (RFC 6570 templates with \`{var}\` placeholders) and\nJSON-Pointer-derived formats aren\'t file references and don\'t fit the\nrewrite shape.\n\n**Frontmatter-only**: drop the \`rewriteBodyLinks\` line — the rest\nis identical.\n\nAfter running, diff the file (\`git diff <path>\`) to confirm the rewrite\ntouched only the fields and links you expected."
32
+ },
33
+ bulkMigrationManyFilesAtOnce: {
34
+ header: "## Bulk migration: many files at once",
35
+ body: "When the rewrite spans dozens or thousands of files (folder rename,\nschema-evolution migration, citation cleanup), the natural shape is\nglob + iterate + dry-run + \`isDirty()\` gate. Pattern:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport { globSync } from \'glob\'; // or \`node:fs\`\'s glob, or fast-glob\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst DRY_RUN = process.env[\'DRY_RUN\'] !== \'false\';\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst files = globSync(\'docs/**/*.md\');\n\nlet changed = 0;\nlet unchanged = 0;\nfor (const filePath of files) {\n const original = readFileSync(filePath, \'utf8\');\n const editor = openFrontmatter(original);\n\n editor.body = rewriteBodyLinks(editor.body, rewriteHref);\n rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\n // Skip files where nothing material changed. Avoids the no-op churn\n // described in §\"What\'s preserved, what isn\'t\".\n const next = editor.toString();\n if (!editor.isDirty() || next === original) {\n unchanged++;\n continue;\n }\n\n if (DRY_RUN) {\n console.log(\`would update ${filePath}\`);\n } else {\n writeFileSync(filePath, next);\n }\n changed++;\n}\n\nconsole.log(\`${DRY_RUN ? \'DRY RUN: \' : \'\'}${changed} changed, ${unchanged} unchanged\`);\n\`\`\`\n\n**Recommended workflow for bulk runs:**\n\n1. **Sentinel-first.** Run on a single representative file first\n (\`globSync\` pattern that matches exactly one path). Eyeball the diff.\n2. **Dry-run the full set.** \`DRY_RUN=true\` lists every file the script\n would touch. Spot-check at least 3 entries before going wet.\n3. **Iterate.** Adjust the callback or schema until the dry-run plan\n matches your intent.\n4. **Run wet.** \`DRY_RUN=false\`. Then run your project\'s link validator\n (\`vat resources validate\`, link-check CI, etc.) on the corpus before\n committing — the rewrite is reversible via \`git checkout\` if any\n targets are wrong.\n\n**Delegating to a subagent.** Bulk rewrites are good subagent work, but\nbrief them with the same three guardrails: provide the exact callback\nrule, mandate dry-run first, and ask for a structured report (counts\nof files changed/unchanged, a sample of 3 before/after diffs). Without\nthose guardrails, a subagent can silently produce a thousand-file diff\nthat\'s wrong in a subtle way and only catchable on careful review.",
36
+ text: "## Bulk migration: many files at once\n\nWhen the rewrite spans dozens or thousands of files (folder rename,\nschema-evolution migration, citation cleanup), the natural shape is\nglob + iterate + dry-run + \`isDirty()\` gate. Pattern:\n\n\`\`\`typescript\nimport { readFileSync, writeFileSync } from \'node:fs\';\nimport { globSync } from \'glob\'; // or \`node:fs\`\'s glob, or fast-glob\nimport {\n openFrontmatter,\n rewriteBodyLinks,\n rewriteFrontmatterUriReferencesFromSchema,\n} from \'@vibe-agent-toolkit/resources\';\n\nconst DRY_RUN = process.env[\'DRY_RUN\'] !== \'false\';\nconst rewriteHref = (href: string): string =>\n href.replace(\'/docs/specs/\', \'/docs/architecture/\');\n\nconst schema = JSON.parse(readFileSync(\'schemas/spec.schema.json\', \'utf8\'));\nconst files = globSync(\'docs/**/*.md\');\n\nlet changed = 0;\nlet unchanged = 0;\nfor (const filePath of files) {\n const original = readFileSync(filePath, \'utf8\');\n const editor = openFrontmatter(original);\n\n editor.body = rewriteBodyLinks(editor.body, rewriteHref);\n rewriteFrontmatterUriReferencesFromSchema(editor, schema, rewriteHref);\n\n // Skip files where nothing material changed. Avoids the no-op churn\n // described in §\"What\'s preserved, what isn\'t\".\n const next = editor.toString();\n if (!editor.isDirty() || next === original) {\n unchanged++;\n continue;\n }\n\n if (DRY_RUN) {\n console.log(\`would update ${filePath}\`);\n } else {\n writeFileSync(filePath, next);\n }\n changed++;\n}\n\nconsole.log(\`${DRY_RUN ? \'DRY RUN: \' : \'\'}${changed} changed, ${unchanged} unchanged\`);\n\`\`\`\n\n**Recommended workflow for bulk runs:**\n\n1. **Sentinel-first.** Run on a single representative file first\n (\`globSync\` pattern that matches exactly one path). Eyeball the diff.\n2. **Dry-run the full set.** \`DRY_RUN=true\` lists every file the script\n would touch. Spot-check at least 3 entries before going wet.\n3. **Iterate.** Adjust the callback or schema until the dry-run plan\n matches your intent.\n4. **Run wet.** \`DRY_RUN=false\`. Then run your project\'s link validator\n (\`vat resources validate\`, link-check CI, etc.) on the corpus before\n committing — the rewrite is reversible via \`git checkout\` if any\n targets are wrong.\n\n**Delegating to a subagent.** Bulk rewrites are good subagent work, but\nbrief them with the same three guardrails: provide the exact callback\nrule, mandate dry-run first, and ask for a structured report (counts\nof files changed/unchanged, a sample of 3 before/after diffs). Without\nthose guardrails, a subagent can silently produce a thousand-file diff\nthat\'s wrong in a subtle way and only catchable on careful review."
37
+ },
38
+ whatsPreservedWhatIsnt: {
39
+ header: "## What\'s preserved, what isn\'t",
40
+ body: "\`openFrontmatter\` inherits its preservation guarantees from \`yaml.Document\`\n(eemeli). Read-only round-trip (no mutations) is byte-identical. Once you\nmutate, the frontmatter section is re-emitted by \`yaml.Document\` and a few\nthings normalize:\n\n| Behavior | Preserved on mutation? |\n|---|---|\n| Inline comment **text** (\`# comment\`) | ✅ |\n| Inline comment **leading whitespace** (\` #\` vs \` #\`) | ❌ collapsed to one space |\n| Leading comments on keys | ✅ (best-effort; comment-attachment is yaml.Document\'s call) |\n| Comments on individual array items | ✅ |\n| Block scalar style (\`|\`, \`>\`, \`|-\`, \`>+\`) | ✅ |\n| Quoting style (plain / single / double) | ✅ |\n| Blank lines between blocks | ✅ |\n| Key ordering | ✅ |\n| EOL (LF or CRLF) | ✅ (detected from first line break) |\n| Anchors and aliases | ✅ on round-trip; mutating them follows \`yaml.Document\` semantics, not ours |\n\n**Consequence:** even a \"no-op\" rewrite (callback returns the input\nunchanged) re-emits frontmatter and can collapse \` #\` → \` #\` on every\nline that has an inline comment. The change is harmless but shows up in\n\`git diff\`. Two ways to skip the write in this case:\n\n- **\`editor.isDirty()\`** — returns \`true\` if any mutator was called or\n \`body\` was reassigned to a different string. Cheap, no string compare,\n but flips on any mutator call even when the value didn\'t change\n (e.g. \`set(\'foo\', sameValue)\`). Fine for most workflows.\n- **Byte-level dirty check** — \`editor.toString() !== originalText\`. Catches\n the no-op-rewrite case exactly; one extra serialize per file. Use this\n when you must produce zero diff on no-op runs.\n\nThe bulk-migration recipe above combines both: \`isDirty()\` as the cheap\nshort-circuit, then a byte compare to filter out comment-whitespace-only\ndeltas.",
41
+ text: "## What\'s preserved, what isn\'t\n\n\`openFrontmatter\` inherits its preservation guarantees from \`yaml.Document\`\n(eemeli). Read-only round-trip (no mutations) is byte-identical. Once you\nmutate, the frontmatter section is re-emitted by \`yaml.Document\` and a few\nthings normalize:\n\n| Behavior | Preserved on mutation? |\n|---|---|\n| Inline comment **text** (\`# comment\`) | ✅ |\n| Inline comment **leading whitespace** (\` #\` vs \` #\`) | ❌ collapsed to one space |\n| Leading comments on keys | ✅ (best-effort; comment-attachment is yaml.Document\'s call) |\n| Comments on individual array items | ✅ |\n| Block scalar style (\`|\`, \`>\`, \`|-\`, \`>+\`) | ✅ |\n| Quoting style (plain / single / double) | ✅ |\n| Blank lines between blocks | ✅ |\n| Key ordering | ✅ |\n| EOL (LF or CRLF) | ✅ (detected from first line break) |\n| Anchors and aliases | ✅ on round-trip; mutating them follows \`yaml.Document\` semantics, not ours |\n\n**Consequence:** even a \"no-op\" rewrite (callback returns the input\nunchanged) re-emits frontmatter and can collapse \` #\` → \` #\` on every\nline that has an inline comment. The change is harmless but shows up in\n\`git diff\`. Two ways to skip the write in this case:\n\n- **\`editor.isDirty()\`** — returns \`true\` if any mutator was called or\n \`body\` was reassigned to a different string. Cheap, no string compare,\n but flips on any mutator call even when the value didn\'t change\n (e.g. \`set(\'foo\', sameValue)\`). Fine for most workflows.\n- **Byte-level dirty check** — \`editor.toString() !== originalText\`. Catches\n the no-op-rewrite case exactly; one extra serialize per file. Use this\n when you must produce zero diff on no-op runs.\n\nThe bulk-migration recipe above combines both: \`isDirty()\` as the cheap\nshort-circuit, then a byte compare to filter out comment-whitespace-only\ndeltas."
42
+ },
43
+ crossLinks: {
44
+ header: "## Cross-links",
45
+ body: "- \`vat-knowledge-resources\` — how to validate URI-references in\n frontmatter against a collection schema.\n- \`vat-skill-authoring\` — when to use leading-\`/\` (project-root-relative)\n URI-refs in SKILL.md frontmatter.",
46
+ text: "## Cross-links\n\n- \`vat-knowledge-resources\` — how to validate URI-references in\n frontmatter against a collection schema.\n- \`vat-skill-authoring\` — when to use leading-\`/\` (project-root-relative)\n URI-refs in SKILL.md frontmatter."
47
+ }
48
+ };
@@ -25,6 +25,7 @@ export const fragments: {
25
25
  readonly addingANewDocType: Fragment;
26
26
  readonly recommendFormatUriReferenceForPathShapedFrontmatterFields: Fragment;
27
27
  readonly annotatingFrontmatterSchemasWithZod4: Fragment;
28
+ readonly uriReferencesInFrontmatter: Fragment;
28
29
  readonly validationOutput: Fragment;
29
30
  };
30
31