@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.
- package/README.md +1 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/CHANGELOG.md +184 -0
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/.claude-plugin/plugin.json +1 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-adoption-and-configuration/SKILL.md +4 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-agent-authoring/SKILL.md +4 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-audit/SKILL.md +4 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-enterprise-org/SKILL.md +3 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-knowledge-resources/SKILL.md +43 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-rag/SKILL.md +4 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-authoring/SKILL.md +27 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-distribution/SKILL.md +5 -2
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-review/SKILL.md +4 -1
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vibe-agent-toolkit/SKILL.md +5 -1
- package/dist/generated/resources/skills/SKILL.js +3 -3
- package/dist/generated/resources/skills/markdown-rewriting.d.ts +28 -0
- package/dist/generated/resources/skills/markdown-rewriting.js +48 -0
- package/dist/generated/resources/skills/vat-knowledge-resources.d.ts +1 -0
- package/dist/generated/resources/skills/vat-knowledge-resources.js +6 -1
- package/dist/generated/resources/skills/vat-skill-authoring.d.ts +1 -0
- package/dist/generated/resources/skills/vat-skill-authoring.js +6 -1
- package/dist/skills/vat-adoption-and-configuration/SKILL.md +4 -1
- package/dist/skills/vat-agent-authoring/SKILL.md +4 -1
- package/dist/skills/vat-audit/SKILL.md +4 -1
- package/dist/skills/vat-enterprise-org/SKILL.md +3 -1
- package/dist/skills/vat-knowledge-resources/SKILL.md +43 -1
- package/dist/skills/vat-rag/SKILL.md +4 -1
- package/dist/skills/vat-skill-authoring/SKILL.md +27 -1
- package/dist/skills/vat-skill-distribution/SKILL.md +5 -2
- package/dist/skills/vat-skill-review/SKILL.md +4 -1
- package/dist/skills/vibe-agent-toolkit/SKILL.md +5 -1
- package/package.json +4 -4
- package/dist/.claude/plugins/marketplaces/vat-skills/plugins/vibe-agent-toolkit/skills/vat-skill-distribution/resources/marketplace-distribution.md +0 -427
- 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-
|
|
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.
|
|
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,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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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](
|
|
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
|
|
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.
|
|
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
|
|