@open-agent-toolkit/cli 0.3.25 → 0.3.26

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 (42) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/docs-tooling/add-docs-to-a-repo.md +14 -6
  3. package/assets/docs/docs-tooling/commands.md +12 -9
  4. package/assets/docs/reference/cli-reference.md +1 -1
  5. package/assets/docs/reference/configuration.md +2 -1
  6. package/assets/docs/reference/docs-index-contract.md +19 -6
  7. package/assets/docs/reference/oat-directory-structure.md +13 -0
  8. package/assets/public-package-versions.json +4 -4
  9. package/assets/skills/oat-docs-bootstrap/SKILL.md +11 -4
  10. package/assets/templates/docs-app-fuma/package.json.template +1 -1
  11. package/assets/templates/docs-app-fuma/source.config.ts +6 -1
  12. package/assets/templates/docs-app-mkdocs/package.json.template +2 -2
  13. package/dist/commands/config/index.d.ts.map +1 -1
  14. package/dist/commands/config/index.js +21 -3
  15. package/dist/commands/docs/index-generate/generator.d.ts +4 -34
  16. package/dist/commands/docs/index-generate/generator.d.ts.map +1 -1
  17. package/dist/commands/docs/index-generate/generator.js +51 -157
  18. package/dist/commands/docs/index-generate/index.d.ts +1 -1
  19. package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
  20. package/dist/commands/docs/index-generate/index.js +26 -8
  21. package/dist/commands/docs/init/index.d.ts.map +1 -1
  22. package/dist/commands/docs/init/index.js +21 -1
  23. package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
  24. package/dist/commands/docs/init/scaffold.js +20 -13
  25. package/dist/commands/docs/nav/contents.d.ts +13 -3
  26. package/dist/commands/docs/nav/contents.d.ts.map +1 -1
  27. package/dist/commands/docs/nav/contents.js +85 -24
  28. package/dist/commands/docs/nav/fumadocs.d.ts +1 -0
  29. package/dist/commands/docs/nav/fumadocs.d.ts.map +1 -1
  30. package/dist/commands/docs/nav/fumadocs.js +26 -9
  31. package/dist/commands/docs/nav/sync.d.ts +2 -0
  32. package/dist/commands/docs/nav/sync.d.ts.map +1 -1
  33. package/dist/commands/docs/nav/sync.js +21 -1
  34. package/dist/commands/docs/shared/exclusions.d.ts +37 -0
  35. package/dist/commands/docs/shared/exclusions.d.ts.map +1 -0
  36. package/dist/commands/docs/shared/exclusions.js +161 -0
  37. package/dist/config/oat-config.d.ts +2 -0
  38. package/dist/config/oat-config.d.ts.map +1 -1
  39. package/dist/config/oat-config.js +6 -3
  40. package/dist/config/resolve.d.ts.map +1 -1
  41. package/dist/config/resolve.js +1 -0
  42. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "oatVersion": "0.3.25"
3
+ "oatVersion": "0.3.26"
4
4
  }
@@ -212,10 +212,18 @@ oat docs nav sync --target-dir apps/my-docs
212
212
 
213
213
  Generated Fumadocs `meta.json` is strict: a page no `## Contents` map lists
214
214
  stays out of the sidebar. The `prebuild` script that `oat docs init` scaffolds
215
- for Fumadocs does not run the read-only check. To make builds fail on stale
216
- navigation or an unlisted page, as `apps/oat-docs` does, append
217
- `&& oat docs nav sync --check` to it; the script runs from the app directory,
218
- which `--target-dir` defaults to.
215
+ for Fumadocs runs the read-only check before generation/build; fresh MkDocs
216
+ `docs:build` does too. Init explicitly seeds `documentation.navOwner: nav-sync`
217
+ and generates navigation after successful scaffold/config. External scripts select
218
+ `--target-dir .` from the app directory; source-workspace scripts select the
219
+ repo-relative app and quote paths with spaces. Existing apps are not rewritten:
220
+ bootstrap sends undeclared/hand-authored ownership through analyze/apply.
221
+
222
+ Use shared `documentation.nonReaderPaths` for drafts/page templates with the
223
+ [bounded glob grammar](commands.md#exclusion-patterns). Nav, nav checks and
224
+ manifests omit matches even when Contents links them; `documentation.excludes`
225
+ stays manifest-only. OAT's Fumadocs collections also omit their rendering. Pinned
226
+ MkDocs 1.4.2 still renders those routes; nav exclusion does not make content private.
219
227
 
220
228
  **Fumadocs** apps also have an app-root docs index manifest, generated from
221
229
  the Markdown file tree automatically via `predev`/`prebuild` hooks. You can
@@ -305,8 +313,8 @@ need.
305
313
  - If a Node/pnpm team wants a hosted site, choose Fumadocs. Its build hooks
306
314
  regenerate the app-root `index.md` inventory but not the sidebar files, so run
307
315
  `oat docs nav sync` after adding, moving, or renaming pages, commit the
308
- `meta.json` files it writes, and add `oat docs nav sync --check` to your build
309
- or CI yourself, because the scaffold does not.
316
+ `meta.json` files it writes. Fresh scaffold builds already run the read-only
317
+ check; older apps can add it explicitly after choosing nav-sync ownership.
310
318
  - If your team uses Python and MkDocs Material, choose MkDocs. Run
311
319
  `oat docs nav sync --check` to see what would change before letting nav sync
312
320
  rewrite `nav:`.
@@ -31,7 +31,7 @@ or **MkDocs Material**.
31
31
  Use the framework-specific generated-artifact command:
32
32
 
33
33
  - Fumadocs apps run `fumadocs-mdx` and `oat docs generate-index`. In this repo, `predev` and `prebuild` regenerate `apps/oat-docs/index.md` from `apps/oat-docs/docs`. Run `oat docs nav sync` yourself after structural changes to rewrite the committed `meta.json` sidebar files from authored directory `index.md` `## Contents` sections; the hooks never write them. `prebuild` runs `oat docs nav sync --check`, so a build fails when those files are stale or a page is unlisted.
34
- - MkDocs apps use `oat docs nav sync` to regenerate the `nav:` block in `mkdocs.yml` from authored directory `index.md` `## Contents` sections.
34
+ - MkDocs apps use `oat docs nav sync` to regenerate the `nav:` block in `mkdocs.yml` from authored directory `index.md` `## Contents` sections. Fresh scaffolds run its read-only `--check` in `docs:build`.
35
35
 
36
36
  Markdown needs no generation command or site build; optional inventories require
37
37
  explicit external output and retain the authored config index. Both frameworks keep authored `## Contents` sections as the source of local discovery. The generated artifact differs by framework.
@@ -50,6 +50,8 @@ Key behavior:
50
50
  to `apps/<app-name>` for monorepos
51
51
  - framework apps default to `<app-name>/` at repo root for single-package repos
52
52
  - sets `documentation.tooling`, `documentation.root`, and `documentation.index` in `.oat/config.json`
53
+ - fresh Fumadocs/MkDocs creation explicitly seeds `documentation.navOwner: nav-sync` and generates navigation after successful scaffold/config, including an explicitly selected new app in a repo with prior docs config; the old app is not rewritten
54
+ - existing app directories are refused rather than regenerated; bootstrap routes existing framework surfaces through analyze/apply, and Markdown/dry runs never sync navigation
53
55
  - for framework apps, when the repo root exposes a compatible Turbo `scripts.build`, patches it to exclude the new docs app from the default root build and adds a root-level `build:docs` script
54
56
  - prints a unified diff before writing the root `package.json` change and returns a manual snippet when the patch is skipped because the build script is missing, non-Turbo, or ambiguous
55
57
 
@@ -90,12 +92,12 @@ Fumadocs scaffold:
90
92
 
91
93
  - thin Next.js app importing from `@open-agent-toolkit/docs-config`, `@open-agent-toolkit/docs-theme`, `@open-agent-toolkit/docs-transforms`
92
94
  - static export (`output: 'export'`) with FlexSearch, Mermaid diagrams, dark/light mode
93
- - `predev`/`prebuild` hooks run `oat docs generate-index` automatically
95
+ - `predev`/`prebuild` hooks run `oat docs generate-index` automatically; `prebuild` first runs `oat docs nav sync --target-dir . --check` (source-workspace scripts explicitly select the repo-relative app)
94
96
  - starter docs: `docs/index.md`, `docs/getting-started.md`, `docs/contributing.md`
95
97
 
96
98
  MkDocs scaffold:
97
99
 
98
- - MkDocs Material with OAT contributor contract (unchanged from previous behavior)
100
+ - MkDocs Material with OAT contributor contract; `docs:build` first runs `oat docs nav sync --target-dir . --check` (source workspaces select the app explicitly)
99
101
  - includes `docs/index.md`, `docs/contributing.md`, and the local tooling needed to run the app
100
102
 
101
103
  Supported flags:
@@ -174,10 +176,10 @@ Key behavior:
174
176
  - writes configuration only for the Fumadocs manifest transition — recording the manifest it just wrote inside `documentation.root` in `documentation.index`, when `documentation.tooling` is `fumadocs` or the config declares neither `tooling` nor `config`. Markdown and MkDocs configurations are never written, and `documentation.root` and `documentation.config` are never modified
175
177
  - prepends an `AUTOGENERATED` warning comment to the output and rewrites the file on every run; do not hand-edit the generated `index.md`
176
178
  - should be freshness-checked against authored `docs/**/index.md` `## Contents` maps before treating it as navigation evidence
177
- - sorting: `index.md` first, then directories before files, then lexical
178
- - reports the derived docs directory in human output and as `docsDir` / `docsDirSource` under `--json`, alongside `excludes` — the effective exclusion list, `documentation.excludes` merged with the `--exclude` flags exactly as it was handed to the generator
179
+ - ordering: authored local Contents orders surviving direct entries in the hierarchical inventory; cross-directory links order the containing entry without duplicates. Child directory titles use index frontmatter, then H1, then slug. Remaining entries use index/directories/files/lexical fallback and are flagged `[unlisted in Contents]` when Contents exists. Missing Contents keeps fallback; malformed present Contents is an error
180
+ - reports the derived docs directory in human output and as `docsDir` / `docsDirSource` under `--json`, alongside `excludes` — the effective exclusion list, `documentation.excludes`, applicable `documentation.nonReaderPaths`, then the `--exclude` flags, exactly as handed to the generator
179
181
  - says where to look when a manifest is empty rather than reporting a bare `0 entries`: which exclusion patterns were active, or that the docs directory held no indexable pages. The wording is observational — the command reports indexed entries, not pattern matches, so it names the exclusions without asserting they are the cause. An empty manifest is a report, not a failure — the file is still written, so a stale index is never left behind, and the command still exits `0`
180
- - omits pages matching the exclusion list. Nothing is excluded by default; once listed, non-page Markdown such as `CLAUDE.md` or `AGENTS.md` stops reaching the manifest. Patterns come from `documentation.excludes` in `.oat/config.json` and from repeated `--exclude` flags, and the flags **extend** the configured list rather than replacing it. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all
182
+ - omits pages matching the exclusion list. Nothing is excluded by default; once listed, non-page Markdown such as `CLAUDE.md` or `AGENTS.md` stops reaching the manifest. Manifest-only patterns come from `documentation.excludes` in `.oat/config.json` and from repeated `--exclude` flags; matching-root `documentation.nonReaderPaths` also applies, and the flags **extend** the configured list rather than replacing it. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all
181
183
 
182
184
  Supported flags:
183
185
 
@@ -227,7 +229,7 @@ script hooks.
227
229
  Use nav sync after adding, removing, renaming, or reordering docs pages.
228
230
 
229
231
  The command reads only the reserved `## Contents` section from each directory
230
- `index.md`. It detects the framework from the app directory:
232
+ `index.md`. Starting in 0.3.26, the shared parser reports malformed Contents in both nav sync and manifest generation. Dash links preserve authored order; `### <Label>` groups become Fumadocs separators or MkDocs nested lists. Empty authored groups and `*`/`+` link bullets report file/line errors: add a dash link/remove the heading, or change the bullet to `-`. See the [shared grammar](../reference/docs-index-contract.md#-contents-format). It detects the framework from the app directory:
231
233
 
232
234
  Plain Markdown needs file/link checks and authored Contents maintenance, without
233
235
  site nav generation. Framework apps generate navigation as follows:
@@ -245,8 +247,9 @@ site nav generation. Framework apps generate navigation as follows:
245
247
  Use `--check` in builds and CI. It computes the same navigation, writes
246
248
  nothing, and exits 1 when any generated file would change or, for Fumadocs,
247
249
  any page or folder is unlisted, naming each one (`stale` and `unlisted` in
248
- `--json`). This repository's `apps/oat-docs` `prebuild` runs it, so
249
- `pnpm build:docs` fails on stale navigation.
250
+ `--json`). Fresh Fumadocs `prebuild` and MkDocs `docs:build` scripts run it with explicit app selection, preserving external `oat` versus source-workspace CLI commands and quoting paths with spaces. This repository's `apps/oat-docs` `prebuild` also runs it, so `pnpm build:docs` fails on stale navigation.
251
+
252
+ Shared `documentation.nonReaderPaths` uses the exclusion grammar above, relative to the configured content root. Navigation inventory, explicit Contents links, `--check` and manifests omit matches; excluded metadata is never cleaned or rewritten. An unrelated explicit target does not inherit the setting. `documentation.excludes` stays manifest-only. OAT Fumadocs source collections omit non-readers from rendering too; pinned MkDocs 1.4.2 omits them from nav/manifest but still renders their routes (no rendering-exclusion support).
250
253
 
251
254
  Fumadocs apps also regenerate the root markdown manifest with
252
255
  `oat docs generate-index`; the two commands write different artifacts.
@@ -233,7 +233,7 @@ Notable commands introduced in the current CLI surface:
233
233
  - `--local` — write to or remove from `.oat/config.local.json` (per-developer repo state, gitignored)
234
234
  - `--user` — write to or remove from `~/.oat/config.json` (user-level fallback, applies across all repos)
235
235
 
236
- When no flag is passed, the CLI picks a sensible default per key type: structural keys (`projects.root`, `documentation.*`, etc.) go to shared, state keys (`activeProject`, etc.) go to local, workflow preferences (`workflow.*`) go to local. Pass at most one flag — the command rejects multiple surface flags. `documentation.guidance` is shared by default and also accepts `--user`; use a path/URL string or a JSON string array, not a comma-separated list. `documentation.ia` accepts the [recorded IA JSON shape](configuration.md#shared-repo-config-you-will-touch-most-often) and `documentation.navOwner` accepts `nav-sync` or `hand-authored`; both are shared-only. Unset owner means undeclared, and Markdown ignores it. IA is an atomic value in get/dump, not a set of separately configurable child keys.
236
+ When no flag is passed, the CLI picks a sensible default per key type: structural keys (`projects.root`, `documentation.*`, etc.) go to shared, state keys (`activeProject`, etc.) go to local, workflow preferences (`workflow.*`) go to local. Pass at most one flag — the command rejects multiple surface flags. `documentation.guidance` is shared by default and also accepts `--user`; use a path/URL string or a JSON string array, not a comma-separated list. `documentation.ia` accepts the [recorded IA JSON shape](configuration.md#shared-repo-config-you-will-touch-most-often) and `documentation.navOwner` accepts `nav-sync` or `hand-authored`; both are shared-only. Unset owner means undeclared, and Markdown ignores it. IA is an atomic value in get/dump, not a set of separately configurable child keys. `documentation.nonReaderPaths` is also shared-only and uses a comma-separated glob list on `set`, stored as an array; empty clears it. It omits matching reader paths from nav/check/manifest and supported Fumadocs collections, while `documentation.excludes` remains manifest-only. See [non-reader configuration](configuration.md#shared-repo-config-you-will-touch-most-often).
237
237
 
238
238
  Per-key restrictions apply identically to `set` and `unset`: structural keys can only be written at shared scope, most state keys can only be written at local scope (`activeIdea` is the exception — it accepts both local and user), and workflow preference keys accept any non-auto surface. Legacy `autoReviewAtCheckpoints` remains shared-only; prefer `workflow.autoReviewAtHillCheckpoints`.
239
239
 
@@ -95,8 +95,9 @@ Common keys in `.oat/config.json`:
95
95
  - `git.defaultBranch` — base branch fallback for PR workflows
96
96
  - `documentation.root`, `documentation.tooling`, `documentation.config` — docs-surface ownership. With tooling `markdown`, root is the literal content directory (including nested `docs`) and `documentation.index` is authored `<root>/index.md`; Markdown adds no framework config. Framework roots retain app/source semantics. Use `oat docs init --framework markdown` or explicit `--adopt` for setup; optional manifests need external output and never change the authored index. See [Documentation path resolution](oat-directory-structure.md#documentation-path-resolution)
97
97
  - `documentation.ia` — shared repository-only mirror of the accepted authored IA. Set JSON with required `preset` and repo-relative `decision`, optional `tracks: [{path, principle}]`, and optional `verification: "triad" | "agent-only" | "none"`. The decision record plus Information architecture section in framework docs-app `AGENTS.md` or Markdown contributing page remain authoritative. Use `oat config set documentation.ia '{"preset":"Flat Small","decision":".oat/repo/reference/decisions/DR-example.md","verification":"none"}'`; unset removes the mirror only. Invalid shapes/paths are rejected; neither `--user` nor `--local` is supported.
98
- - `documentation.navOwner` — shared `nav-sync | hand-authored`, independent of recorded IA, for Fumadocs/MkDocs only. Set with `oat config set documentation.navOwner hand-authored`. Absent is undeclared (`get --json` reports null/default), never implied nav-sync; analyze asks the operator and no automatic regeneration is authorized. Markdown ignores this field. This config support does not change CLI scaffold defaults or explicit nav-sync command behavior.
98
+ - `documentation.navOwner` — shared `nav-sync | hand-authored`, independent of recorded IA, for Fumadocs/MkDocs only. Set with `oat config set documentation.navOwner hand-authored`. Absent is undeclared (`get --json` reports null/default), never implied nav-sync; analyze asks the operator and no automatic regeneration is authorized. Markdown ignores this field. Fresh Fumadocs/MkDocs init explicitly seeds nav-sync and generates navigation after scaffold/config succeeds. Existing apps are not regenerated through bootstrap; explicit nav-sync commands retain their behavior.
99
99
  - `documentation.guidance` — advisory Markdown IA source paths/URLs, as a string or ordered non-empty string array. Repo config overrides user config; explicit skill input overrides both. Absent values use the installed `authoring-docs` IA reference. Use `oat config set documentation.guidance ./docs/ia/index.md` or `oat config set documentation.guidance '["~/guidance/index.md","https://example.com/docs/index.md"]' --user`. Arrays retain order; commas in paths are literal. `--local` is unsupported. `get --json` reports `shared`, `user`, or `default` provenance; `unset` reveals the next tier. Only locators are stored, with unrelated config fields preserved. Sources stay read-only, external packs have `index.md` and `## Contents`, and local AGENTS/contributing rules remain authoritative. Conflicts become `ask_user`. See [IA selection](../docs-tooling/workflows.md#ia-selection-and-guidance).
100
+ - `documentation.nonReaderPaths` — shared repository-only array of content-root-relative globs for drafts/templates. Set with `oat config set documentation.nonReaderPaths 'templates/,drafts/**'`; empty value clears and `unset` removes it. Entries are trimmed/de-duplicated; non-arrays, empty or non-string entries are rejected. Local/user writes are refused. The [bounded grammar](../docs-tooling/commands.md#exclusion-patterns) matches nav inventory, explicit Contents targets, nav checks and manifests only for the configured app/content root; excluded metadata is not rewritten. Fumadocs source collections also exclude rendering when wired through OAT source config. Pinned MkDocs 1.4.2 still renders excluded pages as routes; only nav/manifest exclusion is supported.
100
101
  - `documentation.excludes` — a JSON array of globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. `oat config set` takes the list as one comma-separated value (`"a/**,b.md"`) and stores it as an array; repeated `--exclude` flags extend it, and an empty value clears the key
101
102
  - `documentation.requireForProjectCompletion` — whether docs sync is a completion gate
102
103
  - `instructions.claude.shims` — how `oat instructions sync` keeps a `CLAUDE.md` beside each `AGENTS.md`: `none` (the default: no shims; sync removes the ones OAT created and warns about any other `CLAUDE.md`, all or nothing: it removes none while any `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md` has content of its own; see [All or nothing](../provider-sync/instruction-sync.md#all-or-nothing)), `pointer`, `symlink`, or `copy`. The `--strategy` flag overrides it for one run. Set it with `oat config set instructions.claude.shims pointer` when contributors need `CLAUDE.md` (see [Claude Code and AGENTS.md](../provider-sync/instruction-sync.md#claude-code-and-agentsmd)); `oat config unset` returns to `none`. Any other value is rejected with exit code `2` rather than read as unset, and `oat config set` can still replace it
@@ -15,23 +15,28 @@ OAT docs navigation starts from authored `docs/**/index.md` files. Each `## Cont
15
15
  - The `## Contents` section is the machine-readable local map for sibling pages and child directories.
16
16
  - Every `## Contents` link should use a `.md`-suffixed relative target, including child directory links such as `subdir/index.md`.
17
17
  - Do not hand-edit generated navigation or generated root-index artifacts.
18
- - For Fumadocs, refresh or freshness-check the generated app-root manifest after adding, removing, or renaming Markdown files. Compare that manifest against authored `## Contents` maps for drift; reordering `## Contents` does not reorder the generated manifest's file-tree sort.
18
+ - For Fumadocs, refresh or freshness-check the generated app-root manifest after adding, removing, or renaming Markdown files. Compare that manifest against authored `## Contents` maps for drift; the manifest follows each local Contents order, with deterministic unlisted fallback entries.
19
19
  - Run `oat docs nav sync` after adding, removing, renaming, or reordering pages. It regenerates the framework's navigation from authored `## Contents` maps and preserves the order declared in each local map: the `nav:` block in `mkdocs.yml` for MkDocs, and one `meta.json` per docs directory for Fumadocs.
20
20
 
21
21
  ## `## Contents` format
22
22
 
23
- Use Markdown bullet links for sibling pages and child directories:
23
+ Use dash-prefixed Markdown links for sibling pages and child directories. Optional third-level headings start ordered groups:
24
24
 
25
25
  ```md
26
26
  ## Contents
27
27
 
28
28
  - [Getting Started](getting-started.md) - Setup and local workflow.
29
+
30
+ ### Reference
31
+
29
32
  - [Reference](reference/index.md) - Reference pages for the subsystem.
30
33
  ```
31
34
 
32
35
  Notes:
33
36
 
34
37
  - Links after `## Contents` can include short human-readable descriptions.
38
+ - Groups start at `### <Label>` and end at the next group or the next second-level heading. Links before the first group remain ungrouped. Fumadocs emits `---Label---` before the first retained entry; MkDocs emits a labeled nested list. Filtering a self-index or non-reader link never leaves an empty separator.
39
+ - A group with no authored entries is an error with its file and line; add a dash link or remove the empty heading. A `*` or `+` link bullet is also an error with file and line; replace it with `-`.
35
40
  - Child directories should link to their `index.md`.
36
41
  - Leaf pages should link to their `.md` filename.
37
42
  - Prose outside `## Contents` is ignored by nav generation and remains freeform; it can explain scope, reader paths, or migration status.
@@ -65,8 +70,8 @@ pnpm -w run cli:source -- docs generate-index --docs-dir apps/oat-docs/docs --ou
65
70
 
66
71
  Fumadocs generated behavior:
67
72
 
68
- - Generated entries are ordered by the file-tree generator: `index.md` first, directories before files, then lexical order.
69
- - Reordering a `## Contents` block does not reorder the generated manifest's file-tree sort.
73
+ - The inventory stays hierarchical. Each local Contents orders its surviving direct entries; a cross-directory link orders its containing direct entry without duplicating the page. Child directory titles come from their index frontmatter title, then H1, then slug, independently of nav labels.
74
+ - Remaining entries use deterministic index/directories/files/lexical fallback and carry `[unlisted in Contents]` when a Contents map exists. With no Contents map the inventory keeps its fallback order; malformed present Contents reports the shared grammar errors.
70
75
  - Generated manifests should carry an autogen warning and are rewritten by `predev` / `prebuild`.
71
76
 
72
77
  ## Fumadocs Nav Sync
@@ -75,7 +80,7 @@ In a Fumadocs app (detected by its `source.config.ts`), `oat docs nav sync --tar
75
80
 
76
81
  Fumadocs generated behavior:
77
82
 
78
- - `pages` follows the order of the directory's `## Contents` links. The root list starts with `index`; a child directory appears by its folder name, and its own `index.md` becomes that folder's landing page. A folder whose `meta.json` keeps `root: true` also lists `index` first, because Fumadocs gives a root folder no implicit landing page.
83
+ - `pages` follows the order of the directory's `## Contents` links. The root list starts with `index`; a child directory appears by its folder name, and its own `index.md` becomes that folder's landing page. A folder whose `meta.json` keeps `root: true` or a nonempty trimmed string also lists `index` first, because Fumadocs gives a root folder no implicit landing page. OAT source config narrowly adapts the pinned metadata schema to accept these named roots.
79
84
  - Navigation is strict: there is no `"..."` rest entry. A page or folder that no `## Contents` map lists stays out of the sidebar, and the command reports it by path in its human output and in `--json` (`unlisted`). Add the page to its directory's `## Contents` map to show it.
80
85
  - A `## Contents` link to a page in another directory is written as a Fumadocs link entry such as `[Writing Skills](/contributing/skills)`, so each page belongs to exactly one folder.
81
86
  - A page or folder whose name Fumadocs would read as a `pages` directive, such as `!hidden`, `z...a`, `...name`, or `---`, is written in the local-path form `./!hidden` so it stays a page entry.
@@ -94,9 +99,17 @@ MkDocs generated behavior:
94
99
 
95
100
  - Root `docs/index.md` becomes `Home`.
96
101
  - Child directory `index.md` files become section landing pages.
97
- - Nested entries are emitted in the order they appear under each local `## Contents` block.
102
+ - Nested entries are emitted in the order they appear under each local `## Contents` block, including labeled groups.
98
103
  - `mkdocs.yml` may contain other configuration, but its `nav:` block is derived from authored `## Contents`.
99
104
 
105
+ ## Non-reader paths and ownership
106
+
107
+ Shared `documentation.nonReaderPaths` declares drafts/templates outside the reader tree using the [bounded exclusion grammar](../docs-tooling/commands.md#exclusion-patterns), relative to the content root. It applies only to the configured app/content root. Navigation inventory, explicit Contents links, read-only nav checks and manifests skip matches; an explicit link does not override an exclusion. Excluded subtrees are not read, rewritten or cleaned by nav sync. A missing reader entry remains an error in Fumadocs `--check`. Existing `documentation.excludes` affects manifests only.
108
+
109
+ Fumadocs collections also omit matching pages and metadata when `defineDocs` uses OAT's `docs` and `meta` source options with an explicit repository config path. The pinned MkDocs 1.4.2 has no configurable rendering exclusion: these pages leave navigation and manifests but still render as routes. This setting is not a way to keep private content out of a MkDocs site.
110
+
111
+ Fresh Fumadocs/MkDocs init explicitly writes `documentation.navOwner: nav-sync` and generates navigation after scaffold/config succeeds. Their generated `prebuild` / `docs:build` scripts run `nav sync --check`. Existing hand-authored or undeclared surfaces are preserved through bootstrap and use analyze/apply to choose ownership; absence never implies permission to regenerate. Markdown has no sidebar or nav sync.
112
+
100
113
  ## Generated-file boundaries
101
114
 
102
115
  - Edit authored files under the resolved content root (`docs/` inside framework apps, or the literal configured Markdown root), especially the nearest `index.md` and `## Contents`.
@@ -124,6 +124,7 @@ Current schema keys:
124
124
  | `documentation.tooling` | `string` | - | Documentation tooling identifier (`markdown`, `mkdocs`, or `fumadocs`); parsing remains permissive |
125
125
  | `documentation.config` | `string` | - | Path to the documentation framework config file (e.g., `mkdocs.yml`, `next.config.js`) |
126
126
  | `documentation.index` | `string` | - | Path to the docs surface entry point: authored `<root>/index.md` for Markdown, the generated app-root manifest `<root>/index.md` for Fumadocs, `mkdocs.yml` for MkDocs. Set by `oat docs init`. `oat docs generate-index` writes it only for the Fumadocs manifest transition and never for Markdown or MkDocs. |
127
+ | `documentation.nonReaderPaths` | `string[]` | - | Shared-only content-root-relative bounded globs omitted from nav inventory/Contents/check/manifest and, with OAT source config, Fumadocs rendering. MkDocs 1.4.2 still renders routes. See [Non-reader paths](#non-reader-paths). |
127
128
  | `documentation.excludes` | `string[]` | - | Globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. See [Excluding pages from the generated index](#excluding-pages-from-the-generated-index). |
128
129
  | `documentation.requireForProjectCompletion` | `boolean` | `false` | When `true`, OAT project completion gates require documentation to be updated |
129
130
  | `git.defaultBranch` | `string` | `"main"` | Default branch for PR creation. Auto-detected during `oat init` via `gh repo view` or `origin/HEAD`. Used by `oat-project-pr-final` and `oat-project-pr-progress`. |
@@ -195,6 +196,18 @@ A legacy source root with no `docs` child resolves `--docs-dir` and `--output` t
195
196
 
196
197
  **Configuration writes.** The only configuration write generation performs is the Fumadocs manifest transition: when the written manifest lies inside `documentation.root` and `documentation.tooling` is `fumadocs`, the repo-relative output path is recorded in `documentation.index`. A config that declares neither `documentation.tooling` nor `documentation.config` is treated as the same Fumadocs-shaped case. Any other declared tooling — `markdown` and `mkdocs` included — is never written, and neither are `documentation.root` and `documentation.config`. The value is always repo-relative: when `documentation.root` points outside the repository, the manifest is still generated but the key is left untouched rather than recording a machine-specific path.
197
198
 
199
+ ### Non-reader paths
200
+
201
+ `documentation.nonReaderPaths` declares drafts/templates outside the reader tree. It uses the bounded grammar below, relative to the configured content root (literal Markdown root or framework app's `docs/`). Nav inventory, explicit Contents targets, read-only nav checks and generated manifests skip matches; excluded subtrees and their metadata are never rewritten or cleaned. The setting applies only to the matching configured app/content root, not an unrelated explicit target. Fumadocs rendering uses the same exclusions through OAT source config's collection options. Pinned MkDocs 1.4.2 cannot exclude rendering: nav/manifest omission leaves routes in the build.
202
+
203
+ ```bash
204
+ oat config set documentation.nonReaderPaths 'templates/,drafts/**'
205
+ oat config set documentation.nonReaderPaths ''
206
+ oat config unset documentation.nonReaderPaths
207
+ ```
208
+
209
+ This is shared repository config only; `--local` and `--user` are rejected. Entries are trimmed and de-duplicated, with malformed values rejected and repairable through `set`. `documentation.excludes` remains manifest-only.
210
+
198
211
  ### Excluding pages from the generated index
199
212
 
200
213
  `documentation.excludes` and the repeatable `--exclude <glob>` flag feed one matcher. Flags **extend** the configured list rather than replacing it, so a one-off exclusion cannot silently republish pages the repository deliberately excluded. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all.
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.3.25",
3
- "docs-config": "0.3.25",
4
- "docs-theme": "0.3.25",
5
- "docs-transforms": "0.3.25"
2
+ "cli": "0.3.26",
3
+ "docs-config": "0.3.26",
4
+ "docs-theme": "0.3.26",
5
+ "docs-transforms": "0.3.26"
6
6
  }
@@ -6,7 +6,7 @@ disable-model-invocation: true
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
8
8
  metadata:
9
- version: '1.4.1'
9
+ version: '1.4.2'
10
10
  ---
11
11
 
12
12
  # Docs Bootstrap
@@ -399,7 +399,7 @@ through `oat-docs-analyze --ia`; it does not return to scaffold afterward.
399
399
  it unrecorded. Do not silently initialize PJM. For an existing surface, hand
400
400
  off an analysis artifact plus approved recommendation IDs to apply, with
401
401
  individual approval for explicit record/restructure/tooling items.
402
- This stage does not materialize preset trees or change scaffold/nav defaults.
402
+ This IA selection stage does not materialize preset trees or change ownership for an existing app.
403
403
  Sidebar ownership is separately chosen for existing framework apps; absent
404
404
  remains undeclared, Markdown ignores it, and no automatic nav generation is
405
405
  authorized by IA approval alone.
@@ -412,6 +412,10 @@ Print `[3/7] Scaffolding…` at the start of this step.
412
412
 
413
413
  **Precondition:** The Conflict Resolution Contract's "Allowed mutations" have completed and the working-tree state matches what the CLI expects (Step 2's pre-scaffold invariant). If any resolution-triggered mutation is still pending, **do not invoke the CLI** — stop the flow and surface the missing state.
414
414
 
415
+ For an explicitly fresh Fumadocs/MkDocs app, current CLI init writes `documentation.navOwner: nav-sync` and generates navigation after successful scaffold/config. An explicitly selected new app in a repository with prior docs config is fresh creation; preserve the old app's authored files. This does not authorize regeneration of an existing app: keep undeclared/hand-authored ownership untouched and use the existing analyze/apply handoff. IA approval alone never authorizes navigation writes. Markdown and dry runs run no nav sync.
416
+
417
+ Inspect the generated package scripts rather than adding a duplicate patch: Fumadocs `prebuild` and MkDocs `docs:build` run `nav sync --check`, using external `oat` from the app directory with `--target-dir .`, or source-workspace CLI with the explicit quoted repo-relative app. A stale navigation check requires fixing authored Contents and explicitly syncing owned navigation before retrying, not deleting the check or silently regenerating an undeclared owner.
418
+
415
419
  **3a. Assemble CLI flags.**
416
420
 
417
421
  Build the flag list deterministically from the Input Result (Step 2e) and the Capability Detection result (Step 3b). Non-interactive mode is mandatory — the skill owns the interactive flow; the CLI runs headless.
@@ -712,6 +716,8 @@ Narrate each field actually present in their config (skip fields that are absent
712
716
  - **Fumadocs:** this should be the generated app-root manifest, usually `<appRoot>/index.md`, after the successful build ran `oat docs generate-index`. Explain that this machine-shaped file is how tools inspect the full Markdown file tree, and that the authored source map the user edits is a separate file at `<appRoot>/docs/index.md` with its own `## Contents`.
713
717
  - **Fumadocs stale path warning:** if the inspected path still points inside `<appRoot>/docs/` after build verification, do not teach that as normal. Surface it as a warning that `oat docs generate-index` did not update `documentation.index` as expected, then point the user to Section B for the generated/authored split.
714
718
  - **MkDocs:** this should point at the configured MkDocs nav/config surface, usually `<appRoot>/mkdocs.yml` and matching `documentation.config`. Explain that the YAML file contains the generated/derived `nav:` block when `oat docs nav sync` is used, while authored `docs/index.md` and nested `## Contents` sections remain the source maps the user edits.
719
+ - **`documentation.navOwner`** — fresh framework init explicitly sets `nav-sync`; existing absent means undeclared and `hand-authored` stays authored. Never infer write permission from missing ownership. Markdown ignores it.
720
+ - **`documentation.nonReaderPaths`** — if present, content-root-relative bounded globs omit drafts/templates from nav inventory, explicit Contents links, nav checks and manifests; excluded metadata is not rewritten. OAT Fumadocs collections also omit rendering when wired through source config. Pinned MkDocs 1.4.2 still renders these routes; explain the limitation and do not add a plugin or upgrade as a bootstrap repair. `documentation.excludes` stays manifest-only. Do not add exclusions or mutate this setting without an approved content/config change through the existing workflow.
715
721
  - **`documentation.config`** — optional path to the framework configuration, such as `mkdocs.yml` or `next.config.js`. Inspect whichever path is actually configured.
716
722
  - **`documentation.requireForProjectCompletion`** — the opt-in collected in Step 5e. If `true`, `oat-project-complete` will block project completion until the project records `oat_docs_updated: complete` or an explicit `skipped` after the `oat-project-document` prompt. Explain whichever value is set on this project.
717
723
 
@@ -744,11 +750,12 @@ This section explains why tooling works at all — the contract every OAT docs t
744
750
 
745
751
  Narrate:
746
752
 
747
- - **Every directory under `docs/` has an `index.md`.** No exceptions, no `overview.md`, no README-as-index. Missing `index.md`s are the first thing `oat-docs-analyze` flags.
753
+ - **Every non-excluded Markdown-bearing directory under `docs/` has an `index.md`.** Asset-only and non-reader trees are exempt; use no `overview.md` or README-as-index. Missing reader indexes are an analyze finding.
748
754
  - **Every `index.md` has a `## Contents` section.** The section is a plain Markdown bulleted list of links to the direct children of that directory — both subdirectory `index.md`s and leaf pages.
749
755
  - **Link targets use `.md` extensions.** Leaf pages link as `[Title](page.md)`; subdirectories link as `[Section](subdir/index.md)`. The `@open-agent-toolkit/docs-transforms` remark-links plugin normalizes these at build time for Fumadocs routing (`.md` stripped; `dir/index.md` collapsed to `dir`). `.md`-suffixed authored links render correctly **and** let agents follow each link to the target file without path inference — the best of both worlds.
750
756
  - **The `## Contents` section is the machine-readable local map.** For Fumadocs, `oat docs nav sync` reads it to write the committed `meta.json` sidebar files, and agents compare it against the generated app-root manifest. For MkDocs, `oat docs nav sync` reads it to update `mkdocs.yml` `nav:`. `oat-docs-analyze` reads the same authored source to find orphaned pages and stale generated artifacts.
751
- - **Anything not listed in `## Contents` is invisible to the tooling.** Adding a Markdown file is not enough — it must also appear under the parent `index.md`'s `## Contents`.
757
+ - **Contents uses dash links and optional `### <Label>` groups.** Groups become Fumadocs separators or MkDocs nested nav. Empty authored groups and `*`/`+` link bullets are file/line errors; add a dash link/remove the empty heading, or replace the bullet with `-`.
758
+ - **Reader pages must appear in the local Contents map for navigation.** The manifest retains deterministic unlisted fallback entries and flags them; adding a file alone does not put it in the sidebar. Non-reader exclusions take precedence over explicit Contents links.
752
759
 
753
760
  Show the user their own `docs/index.md` `## Contents` as a concrete example (read the file and paste the relevant 5–15 lines). Then note: "That's the pattern. Every directory you create from now on follows the same shape — `.md`-suffixed links, bulleted list, dash-separated summary per entry."
754
761
 
@@ -7,7 +7,7 @@
7
7
  "scripts": {
8
8
  "predev": "fumadocs-mdx && {{GENERATE_INDEX_CMD}}",
9
9
  "dev": "next dev",
10
- "prebuild": "fumadocs-mdx && {{GENERATE_INDEX_CMD}}",
10
+ "prebuild": "{{NAV_SYNC_CHECK_CMD}} && fumadocs-mdx && {{GENERATE_INDEX_CMD}}",
11
11
  "build": "next build",
12
12
  "start": "next start",
13
13
  "docs:lint": "{{DOCS_LINT_SCRIPT}}",
@@ -1,10 +1,15 @@
1
1
  import { createSourceConfig } from '@open-agent-toolkit/docs-config';
2
2
  import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
3
3
 
4
- const sourceConfig = createSourceConfig();
4
+ const sourceConfig = createSourceConfig({
5
+ oatConfigFile: '{{OAT_CONFIG_RELATIVE_PATH}}',
6
+ appRoot: '.',
7
+ });
5
8
 
6
9
  export const docs = defineDocs({
7
10
  dir: sourceConfig.contentDir,
11
+ docs: sourceConfig.docs,
12
+ meta: sourceConfig.meta,
8
13
  });
9
14
 
10
15
  export default defineConfig({
@@ -6,7 +6,7 @@
6
6
  "description": "MkDocs Material documentation for {{SITE_NAME}}.",
7
7
  "scripts": {
8
8
  "docs:dev": "mkdocs serve",
9
- "docs:build": "mkdocs build",
9
+ "docs:build": "{{NAV_SYNC_CHECK_CMD}} && mkdocs build",
10
10
  "docs:setup": "sh ./setup-docs.sh",
11
11
  "docs:lint": "{{DOCS_LINT_SCRIPT}}",
12
12
  "docs:format": "{{DOCS_FORMAT_SCRIPT}}",
@@ -14,6 +14,6 @@
14
14
  "test": "echo 'Documentation tests complete'"
15
15
  },
16
16
  "devDependencies": {
17
- {{DEV_DEPENDENCIES}}
17
+ "@open-agent-toolkit/cli": "{{OAT_CLI_DEP}}"{{DEV_DEPENDENCIES}}
18
18
  }
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"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"}
@@ -68,6 +68,7 @@ const KEY_ORDER = [
68
68
  'autoReviewAtCheckpoints',
69
69
  'lastPausedProject',
70
70
  'documentation.ia',
71
+ 'documentation.nonReaderPaths',
71
72
  'documentation.navOwner',
72
73
  'documentation.guidance',
73
74
  'documentation.root',
@@ -307,6 +308,17 @@ const CONFIG_CATALOG = [
307
308
  owningCommand: 'oat config set documentation.config <value>',
308
309
  description: 'Repository-relative path to the primary documentation tool config file.',
309
310
  },
311
+ {
312
+ key: 'documentation.nonReaderPaths',
313
+ group: 'Shared Repo (.oat/config.json)',
314
+ file: '.oat/config.json',
315
+ scope: 'shared repo',
316
+ type: 'string[]',
317
+ defaultValue: 'unset',
318
+ mutability: 'read/write',
319
+ owningCommand: 'oat config set documentation.nonReaderPaths <glob[,glob...]>',
320
+ description: 'Content-root-relative globs excluded from reader navigation, manifest and supported framework rendering. Empty clears the key.',
321
+ },
310
322
  {
311
323
  key: 'documentation.excludes',
312
324
  group: 'Shared Repo (.oat/config.json)',
@@ -1808,7 +1820,8 @@ async function listConfigKeys(repoRoot, userConfigDir, dependencies) {
1808
1820
  async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, dependencies, warn) {
1809
1821
  validateSurfaceForKey(key, surface);
1810
1822
  const effectiveSurface = surface === 'auto' ? defaultSurfaceForKey(key) : surface;
1811
- if (key === 'documentation.guidance' ||
1823
+ if (key === 'documentation.nonReaderPaths' ||
1824
+ key === 'documentation.guidance' ||
1812
1825
  key === 'documentation.ia' ||
1813
1826
  key === 'documentation.navOwner') {
1814
1827
  const configPath = effectiveSurface === 'user'
@@ -1818,7 +1831,11 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
1818
1831
  const trimmed = rawValue.trim();
1819
1832
  let value;
1820
1833
  try {
1821
- if (key === 'documentation.ia') {
1834
+ if (key === 'documentation.nonReaderPaths') {
1835
+ const paths = parseDocumentationExcludes(rawValue);
1836
+ value = paths.length > 0 ? paths : undefined;
1837
+ }
1838
+ else if (key === 'documentation.ia') {
1822
1839
  const parsed = JSON.parse(trimmed);
1823
1840
  if (parsed === null)
1824
1841
  throw new Error('Expected an IA JSON object.');
@@ -2431,7 +2448,8 @@ async function unsetConfigValue(repoRoot, userConfigDir, key, surface, dependenc
2431
2448
  * runs only when the normalized pass found nothing to remove.
2432
2449
  */
2433
2450
  async function removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface, path, dependencies) {
2434
- if (key === 'documentation.guidance' ||
2451
+ if (key === 'documentation.nonReaderPaths' ||
2452
+ key === 'documentation.guidance' ||
2435
2453
  key === 'documentation.ia' ||
2436
2454
  key === 'documentation.navOwner') {
2437
2455
  const configPath = effectiveSurface === 'user'
@@ -1,8 +1,12 @@
1
+ export { createExclusionMatcher } from '../../docs/shared/exclusions.js';
2
+ export type { ExclusionMatcher } from '../../docs/shared/exclusions.js';
1
3
  export interface IndexEntry {
2
4
  title: string;
3
5
  description?: string;
4
6
  path: string;
5
7
  children?: IndexEntry[];
8
+ /** Present Contents did not list this direct reader entry. */
9
+ unlisted?: boolean;
6
10
  }
7
11
  export interface GenerateIndexOptions {
8
12
  /**
@@ -12,40 +16,6 @@ export interface GenerateIndexOptions {
12
16
  */
13
17
  excludes?: string[];
14
18
  }
15
- /**
16
- * A compiled exclusion list.
17
- *
18
- * Files and directories are asked separately so a trailing-slash pattern can
19
- * mean "directories only" while every other pattern applies to both.
20
- */
21
- export interface ExclusionMatcher {
22
- excludesFile: (relativePath: string) => boolean;
23
- excludesDirectory: (relativePath: string) => boolean;
24
- }
25
- /**
26
- * Compile exclusion globs matched against **docs-root-relative POSIX paths**
27
- * (`api/auth.md`, `api/nested`), never against absolute or CWD-relative ones.
28
- *
29
- * Grammar, defined once and documented in
30
- * `apps/oat-docs/docs/reference/oat-directory-structure.md`:
31
- *
32
- * - `*` matches any run of characters inside a single path segment.
33
- * - `**` spans `/` only as a whole segment, where it covers zero or more
34
- * segments: `**\/CLAUDE.md` matches `CLAUDE.md` and `api/CLAUDE.md`. Inside a
35
- * segment (`a**b`) it is an ordinary single-segment wildcard.
36
- * - Patterns are anchored at both ends against the whole relative path, so a
37
- * bare `CLAUDE.md` matches only the root-level file. Use `**\/CLAUDE.md` for
38
- * every depth.
39
- * - A trailing `/` restricts a pattern to directories: `drafts/` prunes the
40
- * `drafts` directory and everything beneath it, and never matches a file.
41
- * Without it, a pattern that matches a directory path prunes it too.
42
- * - Matching is case-sensitive, `/` is the separator on every platform, and
43
- * `*` is the only metacharacter — `.`, `+`, and friends are literal.
44
- *
45
- * Entries are trimmed; a leading `./` or `/` is stripped so both spellings
46
- * anchor at the docs root. Blank entries are ignored.
47
- */
48
- export declare function createExclusionMatcher(patterns: readonly string[]): ExclusionMatcher;
49
19
  export declare function generateIndex(docsDir: string, options?: GenerateIndexOptions): Promise<IndexEntry[]>;
50
20
  export declare function renderIndex(entries: IndexEntry[]): string;
51
21
  //# sourceMappingURL=generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/index-generate/generator.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,iBAAiB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CACtD;AAmHD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,gBAAgB,CAwClB;AAqID,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,UAAU,EAAE,CAAC,CAMvB;AAmBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAMzD"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/index-generate/generator.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,YAAY,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAgLD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,UAAU,EAAE,CAAC,CAMvB;AAuBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAMzD"}