@open-agent-toolkit/cli 0.3.23 → 0.3.24

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 (28) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/docs-tooling/workflows.md +39 -5
  3. package/assets/docs/reference/cli-reference.md +1 -1
  4. package/assets/docs/reference/configuration.md +4 -2
  5. package/assets/public-package-versions.json +4 -4
  6. package/assets/skills/authoring-docs/SKILL.md +18 -8
  7. package/assets/skills/authoring-docs/references/guidance-sources.md +95 -0
  8. package/assets/skills/authoring-docs/references/information-architecture.md +121 -86
  9. package/assets/skills/authoring-docs/references/page-types.md +35 -7
  10. package/assets/skills/authoring-docs/references/review-rubric.md +12 -12
  11. package/assets/skills/authoring-docs/references/templates.md +54 -0
  12. package/assets/skills/authoring-docs/references/workflow.md +6 -1
  13. package/assets/skills/authoring-docs/references/writing-style.md +1 -1
  14. package/assets/skills/authoring-docs/scripts/resolve-guidance.mjs +53 -0
  15. package/assets/skills/oat-docs-analyze/SKILL.md +37 -4
  16. package/assets/skills/oat-docs-analyze/references/analysis-artifact-template.md +12 -0
  17. package/assets/skills/oat-docs-apply/SKILL.md +19 -1
  18. package/assets/skills/oat-docs-apply/references/apply-plan-template.md +9 -0
  19. package/assets/skills/oat-docs-authoring/SKILL.md +20 -8
  20. package/assets/skills/oat-docs-bootstrap/SKILL.md +54 -13
  21. package/dist/commands/config/index.d.ts.map +1 -1
  22. package/dist/commands/config/index.js +78 -1
  23. package/dist/config/oat-config.d.ts +5 -0
  24. package/dist/config/oat-config.d.ts.map +1 -1
  25. package/dist/config/oat-config.js +38 -4
  26. package/dist/config/resolve.d.ts.map +1 -1
  27. package/dist/config/resolve.js +1 -0
  28. package/package.json +2 -2
@@ -547,3 +547,57 @@ docs/
547
547
 
548
548
  - <Explicitly out-of-scope docs>
549
549
  ```
550
+
551
+ ## IA Proposal
552
+
553
+ Use for bootstrap or an existing-tree `--ia` analysis. This proposes structure;
554
+ it neither persists an IA decision nor materializes a preset. Feature and QA
555
+ validation page templates are not included; use the page-type guidance to
556
+ plan their content.
557
+
558
+ ````markdown
559
+ # IA Proposal: {surface}
560
+
561
+ ## Evidence and guidance
562
+
563
+ - Resolved sources, in order: {path/URL, provenance: explicit/conversation/shared/user/builtin}
564
+ - Local authority: {AGENTS/contributing paths and relevant rules}
565
+ - Repo signals: {manifests, navigators, bin, routers, IaC, e2e, docs, units}
566
+ - Readers and work contexts: {who must succeed at what}
567
+ - Entry key per track: {task/domain/capability/unit/command/page type}
568
+ - Page purposes: {one primary job per representative page}
569
+ - Verification overlay: {triad/agent-only/none and evidence}
570
+ - Size gate: {page count and amount of structure justified}
571
+ - Canonical facts elsewhere and links to preserve: {paths/URLs}
572
+ - Unresolved conflicts: {ask_user finding with source citations, or none}
573
+
574
+ ## Candidate A: {reader-facing name}
575
+
576
+ Nearest preset: {approved label}. Choose when: {signals and tradeoffs}.
577
+
578
+ ```text
579
+ {track-or-section}/
580
+ {page.md} — {page's one job}
581
+ {page.md} — {page's one job}
582
+ {track-or-section}/
583
+ {page.md} — {page's one job}
584
+ {page.md} — {page's one job}
585
+ {page.md} — {page's one job}
586
+ ```
587
+
588
+ Use a two-level tree and 5–8 representative page placements. For Flat Small,
589
+ first-level labels are grouped headings in one index, not new directories.
590
+
591
+ ## Candidate B: {alternative reader-facing name}
592
+
593
+ Nearest preset: {approved label}. Choose when: {different plausible signals}.
594
+
595
+ {Second two-level tree with 5–8 representative page placements and page jobs.}
596
+
597
+ ## Recommendation and open decisions
598
+
599
+ {Preferred candidate, evidence and tradeoffs. Ask only decision-changing
600
+ questions. Record an explicit choice before replacement or a second app.
601
+ Existing docs default to analyze → apply of approved recommendations.
602
+ No private exemplar text, copied external contents or unapproved moves.}
603
+ ````
@@ -80,7 +80,12 @@ Most docs serve one or more of these readers:
80
80
  - support engineer
81
81
  - AI agent making future changes
82
82
 
83
- Write pages for actual tasks, not org-chart abstractions.
83
+ Map personas to tracks by work context: consumers and CLI/API users usually
84
+ enter through tasks or contracts; maintainers through domains and operations;
85
+ product stakeholders through behavior; independent QA through validation;
86
+ agents through exact task inputs and checks. One person may use several tracks.
87
+ Use the five axes in [Information Architecture](information-architecture.md)
88
+ before naming a preset. Write pages for actual tasks, not org-chart abstractions.
84
89
 
85
90
  ## 5. Decide the Minimum Useful Set
86
91
 
@@ -93,7 +93,7 @@ Use notes for useful context, not ordinary tips.
93
93
  - Use one `#` heading per page.
94
94
  - Do not skip heading levels.
95
95
  - Use fenced code blocks with language identifiers.
96
- - Use `sh` for shell commands.
96
+ - Use `bash` for shell commands unless the example is POSIX-only (`sh`) or local repository conventions require another fence.
97
97
  - Use `txt` for command output.
98
98
  - Do not include shell prompts unless the prompt itself matters.
99
99
  - Use angle brackets for placeholders, such as `<environment>`.
@@ -0,0 +1,53 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { parseArgs } from 'node:util';
3
+
4
+ // Select inputs only. The consuming skill reads Markdown and checks Contents,
5
+ // local authority and conflicts; this helper never fetches or writes a source.
6
+ const { values } = parseArgs({
7
+ options: {
8
+ builtin: { type: 'string' },
9
+ 'ia-guidance': { type: 'string', multiple: true },
10
+ 'conversation-guidance': { type: 'string', multiple: true },
11
+ },
12
+ });
13
+ const explicit = values['ia-guidance'];
14
+ const conversation = values['conversation-guidance'];
15
+ if (explicit && conversation) {
16
+ throw new Error(
17
+ 'Use one explicit source list; reconcile argument/conversation disagreement with the user first.',
18
+ );
19
+ }
20
+ const input = JSON.parse(readFileSync(0, 'utf8'));
21
+ if (input.status !== 'ok' || input.key !== 'documentation.guidance') {
22
+ throw new Error(
23
+ 'Expected successful oat config get documentation.guidance --json output.',
24
+ );
25
+ }
26
+ let locations;
27
+ let source;
28
+ if (explicit || conversation) {
29
+ locations = explicit ?? conversation;
30
+ source = explicit ? 'explicit' : 'conversation';
31
+ } else if (input.value !== null && input.value !== undefined) {
32
+ if (!['shared', 'user'].includes(input.source)) {
33
+ throw new Error(
34
+ `Unsupported documentation.guidance config source: ${input.source}`,
35
+ );
36
+ }
37
+ locations = Array.isArray(input.value) ? input.value : [input.value];
38
+ source = input.source;
39
+ } else {
40
+ locations = [values.builtin];
41
+ source = 'builtin';
42
+ }
43
+ if (
44
+ !locations.length ||
45
+ locations.some((location) => typeof location !== 'string' || !location.trim())
46
+ ) {
47
+ throw new Error(
48
+ 'Guidance requires non-empty path/URL strings (or --builtin for fallback).',
49
+ );
50
+ }
51
+ process.stdout.write(
52
+ `${JSON.stringify({ sources: locations.map((location) => ({ location: location.trim(), source })) }, null, 2)}\n`,
53
+ );
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  name: oat-docs-analyze
3
3
  description: Run when you need to evaluate documentation structure, navigation, and coverage against the OAT documentation contract. Produces a severity-rated analysis artifact for oat-docs-apply.
4
+ argument-hint: '[target] [--ia] [--ia-guidance <path|url>]'
4
5
  disable-model-invocation: true
5
6
  user-invocable: true
6
- allowed-tools: Read, Write, Bash(git:*), Bash(oat config:*), Bash(oat docs nav sync --check:*), Bash(pnpm:*), Bash(bash:*), Bash(jq:*), Bash(mkdir:*), Bash(date:*), Bash(echo:*), Bash(cd:*), Bash(pwd:*), Glob, Grep, AskUserQuestion, Task
7
+ allowed-tools: Read, Write, Bash(git:*), Bash(oat config:*), Bash(oat docs nav sync --check:*), Bash(pnpm:*), Bash(bash:*), Bash(jq:*), Bash(node:*), Bash(mkdir:*), Bash(date:*), Bash(echo:*), Bash(cd:*), Bash(pwd:*), Glob, Grep, AskUserQuestion, Task
7
8
  metadata:
8
- version: '1.6.3'
9
+ version: '1.7.0'
9
10
  ---
10
11
 
11
12
  # Docs Analysis
@@ -85,6 +86,38 @@ When executing this skill, provide lightweight progress feedback so the user can
85
86
 
86
87
  ## Process
87
88
 
89
+ ### Shared authoring method and optional IA proposal
90
+
91
+ Independently probe each exact `authoring-docs/SKILL.md` in order:
92
+ `${SKILL_DIR}/..` from the loaded skill (`SKILL_DIR` is the absolute directory
93
+ containing that loaded `SKILL.md`), `${HOME}/.agents/skills`, then
94
+ `<repo-root>/.agents/skills`. Bind the first matching `authoring-docs` directory
95
+ once as `AUTHORING_DOCS_ROOT`; load `${AUTHORING_DOCS_ROOT}/SKILL.md` and use
96
+ that same root for every authoring-docs reference and script, never ambient
97
+ discovery. If none is found, name `authoring-docs`, stop this handoff, and give
98
+ the intended-scope recovery command: `oat tools install docs --scope <user|project>`
99
+ or `oat tools update --pack docs --scope <user|project>`.
100
+
101
+ Always use its landing-page contract, section entries and one-purpose-per-page
102
+ rule for the quality pass even without `--ia`. For IA work, read
103
+ `${AUTHORING_DOCS_ROOT}/references/guidance-sources.md` and use the source-aware config-get
104
+ interface/helper: explicit `--ia-guidance` or conversation → repo → user →
105
+ built-in. Preserve selected source order and cite locators/provenance in the
106
+ analysis artifact. External Markdown packs require `index.md` and `## Contents`;
107
+ non-repo inputs stay read-only and private contents never enter the artifact.
108
+
109
+ `--ia` is a skill argument, not a CLI docs command. It adds the shared IA Proposal
110
+ to the **same analysis artifact and existing artifact-review loop**. Read manifests,
111
+ UI navigators/journeys, CLI `bin`, routers, IaC, `e2e/`/`.maestro/`, existing docs
112
+ and independent monorepo units. Ask only decision-changing questions about reader
113
+ work contexts, independent verification, canonical facts and link survival.
114
+ Use the five axes before presets and show two plausible two-level trees with
115
+ 5–8 representative page placements each, page jobs, nearest approved presets
116
+ and tradeoffs. A UI alone does not justify Product/Engineering/QA; size chooses
117
+ depth, not audience. For an existing tree respect AGENTS/contributing authority;
118
+ conflicts are `ask_user`, with both source citations. Propose only: no IA
119
+ persistence, restructure action or scaffold materialization in this stage.
120
+
88
121
  ### Step 0: Resolve Docs Target and Analysis Mode
89
122
 
90
123
  Determine the documentation root using explicit docs-app evidence before generic
@@ -267,8 +300,8 @@ For each evaluated page or directory:
267
300
  syntax intentionally shown inside inline code, fenced examples, or template
268
301
  snippets.
269
302
  4. Check Markdown hygiene: opening code fences need language identifiers; shell
270
- examples should follow local fence conventions, defaulting to `sh` unless
271
- local guidance uses `bash` or the block needs Bash-only syntax.
303
+ examples should follow local fence conventions, defaulting to `bash` unless
304
+ the example is POSIX-only (`sh`) or local guidance requires another fence.
272
305
  5. Flag empty headings, multiple document-level H1s outside intentional imported
273
306
  README contexts, overlong frontmatter descriptions when local guidance
274
307
  defines a limit, ellipsis-truncated descriptions, and README-copy metadata
@@ -15,6 +15,18 @@ oat_analysis_commit: { commitHash }
15
15
  **Surface Type:** {mkdocs-app|oat-fumadocs-app|docs-tree|root-markdown}
16
16
  **Commit:** {short-hash}
17
17
 
18
+ ## IA guidance and proposal
19
+
20
+ - Selected sources in order: {locator + explicit/conversation/shared/user/builtin provenance}
21
+ - Resolved index entries: {entry paths/URLs; external Markdown has index.md + Contents}
22
+ - Local authority: {AGENTS/contributing source citations}
23
+ - Conflicts/unreadable sources: {ask_user with both citations, or none}
24
+ - IA proposal: {when --ia, embed the shared authoring-docs IA Proposal template:
25
+ two two-level trees, 5–8 placements each, page jobs, nearest approved presets,
26
+ evidence and tradeoffs; otherwise not requested}
27
+
28
+ Do not copy private guidance contents or persist an IA decision from this report.
29
+
18
30
  ## Summary
19
31
 
20
32
  - **Files evaluated:** {N}
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  user-invocable: true
6
6
  allowed-tools: Read, Write, Edit, Bash(git:*), Bash(gh:*), Bash(oat:*), Bash(pnpm:*), Bash(bash:*), Bash(jq:*), Bash(mkdir:*), Bash(date:*), Bash(echo:*), Bash(cd:*), Bash(pwd:*), Glob, Grep, AskUserQuestion
7
7
  metadata:
8
- version: '1.4.4'
8
+ version: '1.4.5'
9
9
  ---
10
10
 
11
11
  # Docs Apply
@@ -200,6 +200,24 @@ If branch creation fails because of unrelated local changes, ask the user to res
200
200
 
201
201
  ### Step 4: Apply Approved Changes
202
202
 
203
+ Independently probe each exact `authoring-docs/SKILL.md` in order:
204
+ `${SKILL_DIR}/..` from the loaded skill (`SKILL_DIR` is the absolute directory
205
+ containing that loaded `SKILL.md`), `${HOME}/.agents/skills`, then
206
+ `<repo-root>/.agents/skills`. Bind the first matching `authoring-docs` directory
207
+ once as `AUTHORING_DOCS_ROOT`; load `${AUTHORING_DOCS_ROOT}/SKILL.md` and use
208
+ that same root for every authoring-docs reference and script, never ambient
209
+ discovery. If none is found, name `authoring-docs`, stop this handoff, and give
210
+ the intended-scope recovery command: `oat tools install docs --scope <user|project>`
211
+ or `oat tools update --pack docs --scope <user|project>`.
212
+
213
+ Before content actions, use its page-purpose, landing, placement and five-axis IA
214
+ method within the approved recommendation scope. Carry the analysis artifact's ordered guidance
215
+ locators/provenance into the apply plan; do not silently re-resolve different
216
+ sources. Verify cited inputs still exist and remain read-only outside the repo.
217
+ Local AGENTS/contributing rules stay authoritative; a conflict is `ask_user`
218
+ and blocks that recommendation pending a fresh analysis/user decision. Cite
219
+ sources without copying private contents. This hook adds no restructure action.
220
+
203
221
  Before the first approved write, initialize `OWNED_OUTPUT_FILES=()`. Append
204
222
  each exact successfully created, modified or removed path at that write,
205
223
  including both names of a rename and any generated navigation/index file this
@@ -12,6 +12,15 @@ oat_docs_target: { docs-target-path }
12
12
  **Source Analysis:** `{analysis-artifact-path}`
13
13
  **Docs Target:** `{docs-target-path}`
14
14
 
15
+ ## Guidance provenance
16
+
17
+ - Analysis-selected IA sources, in order: {locators + provenance}
18
+ - Local authority: {AGENTS/contributing citations}
19
+ - Read-only sources verified: {resolved entries or blocked recommendation IDs}
20
+ - Conflicts: {ask_user disposition or none}
21
+
22
+ Keep the analysis selection; do not copy private contents or invent missing evidence.
23
+
15
24
  ## Instructions
16
25
 
17
26
  Review the full recommendation set first, then choose a review mode:
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: oat-docs-authoring
3
3
  description: Use when authoring or restructuring targeted content inside an existing OAT Markdown surface or OAT/Fumadocs docs app. Preserves OAT docs navigation, generated indexes, and validation boundaries.
4
- argument-hint: '[docs task or target path]'
4
+ argument-hint: '[docs task or target path] [--ia-guidance <path|url>]'
5
5
  disable-model-invocation: false
6
6
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
7
7
  user-invocable: true
8
8
  metadata:
9
- version: '1.1.3'
9
+ version: '1.2.0'
10
10
  ---
11
11
 
12
12
  # OAT Docs Authoring
@@ -14,9 +14,8 @@ metadata:
14
14
  Use this skill for targeted documentation authoring and small structural edits
15
15
  inside an existing OAT Markdown surface or OAT/Fumadocs docs app.
16
16
 
17
- This is a thin wrapper over `authoring-docs`. Load `authoring-docs` for
18
- universal evidence gathering, page-type selection, writing style, templates,
19
- and review standards. Keep this wrapper focused on OAT Markdown/Fumadocs placement,
17
+ This is a thin wrapper over `authoring-docs` for universal evidence gathering,
18
+ page-type selection, writing style, templates, and review standards. Keep this wrapper focused on OAT Markdown/Fumadocs placement,
20
19
  navigation, generated artifacts, validation, and lifecycle boundaries.
21
20
 
22
21
  ## Prerequisites
@@ -111,9 +110,22 @@ Use `references/docs-root-resolution.md` before assuming any path. OAT docs apps
111
110
  commonly live outside `apps/oat-docs`, and `.oat/config.json` may describe the
112
111
  generated root index separately from the authored docs root.
113
112
 
114
- If the request needs universal documentation standards, load `authoring-docs`
115
- and use its reference map for evidence gathering, page type, writing style,
116
- templates, and review rubric.
113
+ Independently probe each exact `authoring-docs/SKILL.md` in order:
114
+ `${SKILL_DIR}/..` from the loaded skill (`SKILL_DIR` is the absolute directory
115
+ containing that loaded `SKILL.md`), `${HOME}/.agents/skills`, then
116
+ `<repo-root>/.agents/skills`. Bind the first matching `authoring-docs` directory
117
+ once as `AUTHORING_DOCS_ROOT`; load `${AUTHORING_DOCS_ROOT}/SKILL.md` and use
118
+ that same root for every authoring-docs reference and script, never ambient
119
+ discovery. If none is found, name `authoring-docs`, stop this handoff, and give
120
+ the intended-scope recovery command: `oat tools install docs --scope <user|project>`
121
+ or `oat tools update --pack docs --scope <user|project>`.
122
+
123
+ Use the bound skill's reference map for evidence gathering, page type, writing
124
+ style, templates and review rubric. For IA work use its five-axis method and
125
+ `${AUTHORING_DOCS_ROOT}/references/guidance-sources.md`: explicit `--ia-guidance` or
126
+ conversation → repo config → user config → built-in. Cite ordered source
127
+ locators/provenance in the handoff; respect AGENTS/contributing authority,
128
+ keep non-repo sources read-only and report conflicts as `ask_user`.
117
129
 
118
130
  ### Step 2: Inspect Evidence and Local Maps
119
131
 
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: oat-docs-bootstrap
3
3
  description: Use when bootstrapping or adopting an OAT documentation surface in a repo. Guides the user through preflight detection, richer input gathering than the raw CLI, `oat docs init` invocation with gated post-patches for open CLI gaps, build verification, post-scaffold config inspection, and an educational walkthrough. Supports plain Markdown (file-level path), Fumadocs (full path), and MkDocs (lean path with defined minimum contract).
4
- argument-hint: '<optional-target-dir>'
4
+ argument-hint: '<optional-target-dir> [--ia-guidance <path|url>]'
5
5
  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.3.3'
9
+ version: '1.4.0'
10
10
  ---
11
11
 
12
12
  # Docs Bootstrap
@@ -114,13 +114,15 @@ OAT ▸ DOCS BOOTSTRAP
114
114
 
115
115
  The detailed framework procedures below apply to Fumadocs/MkDocs. When the selected tooling is `markdown`, use this path for Steps 2–7 instead; never run framework post-patches, the FP-15 AGENTS bridge, dependency discovery/install, package/Turbo patches, or a site build. Step 1 remains the shared read-only detector.
116
116
 
117
- 1. **Preflight and routing:** Read `documentation.tooling` as a non-empty string. A non-string value (including a legacy object with a `framework` field) is invalid/undeclared tooling in the CLI; surface it for a user decision before proceeding, without silently clearing or retagging it. Declared tooling is authoritative: configured Markdown uses `documentation.root` literally, including when it contains a child named `docs`; declared frameworks or unknown stacks are not plain-doc adoption candidates. With no declared tooling, check framework evidence first (`mkdocs.yml`, Fumadocs/Next config and docs-app package scripts/dependencies), then inspect the chosen dedicated content directory for authored `.md`/`.mdx` pages. A repository-root README alone is insufficient; an empty selected directory is fresh setup. For a populated plain tree, lead with **adopt and audit**, **audit only**, or **abort**. Audit only delegates read-only to `oat-docs-analyze` and exits. Adoption requires the explicit user choice and CLI `--adopt`; `--yes` alone never authorizes it. An incompatible declared root/index/tooling requires a user decision, with no silent clearing or retagging. Keep the existing explicitly authorized framework replacement path when a framework is selected.
117
+ 1. **Preflight and routing:** Read `documentation.tooling` as a non-empty string. A non-string value (including a legacy object with a `framework` field) is invalid/undeclared tooling in the CLI; surface it for a user decision before proceeding, without silently clearing or retagging it. Declared tooling is authoritative: configured Markdown uses `documentation.root` literally, including when it contains a child named `docs`; declared frameworks or unknown stacks are not plain-doc adoption candidates. With no declared tooling, check framework evidence first (`mkdocs.yml`, Fumadocs/Next config and docs-app package scripts/dependencies), then inspect the chosen dedicated content directory for authored `.md`/`.mdx` pages. A repository-root README alone is insufficient; an empty selected directory is fresh setup. For a populated plain tree, default to `oat-docs-analyze` then `oat-docs-apply` for approved repairs and exit without scaffolding. Offer **adopt and audit**, **audit only**, or **abort** when adoption is explicitly requested. Audit only delegates read-only to `oat-docs-analyze` and exits. Adoption requires the explicit user choice and CLI `--adopt`; `--yes` alone never authorizes it. An incompatible declared root/index/tooling requires a user decision, with no silent clearing or retagging. Keep the existing explicitly authorized framework replacement path when a framework is selected.
118
118
  2. **Gather inputs:** Offer “Markdown (plain files), Fumadocs, or MkDocs?” Collect documentation title (`--site-name`), dedicated relative target directory (default `docs` in every repo shape), and optional description. Reuse an existing compatible configured Markdown root. Ask no app/package name, package-manager, site-runtime, or dependency questions. Lint and format default to `none`; describe selected existing repository tools only, without installing them. Validate a nonempty title and a dedicated in-repository target, excluding the repository root and escaping symlinks. Confirm fresh setup or additive adoption, title, root, and audit handoff. `appName` is absent and `conflictResolution` is `adopt`, `audit`, `abort`, or null for this path.
119
+ Before Markdown CLI invocation, run **Step 2.5** for fresh setup and explicitly selected adoption; it is not bypassed by this condensed path.
120
+
119
121
  3. **Invoke CLI:** Probe `$CLI_CMD docs init --help` and require advertised Markdown/`--adopt` support before invocation; if missing, report the needed CLI update rather than fabricating scaffold files. Run `$CLI_CMD docs init --framework markdown --target-dir <root> --site-name <title> --description <description> --lint none --format none --yes`, adding `--adopt` only for explicit adoption. Pass the selected lint/format values when using existing tools. Never pass app-only flags. An optional `--dry-run` previews file/config/guidance changes without writes; it does not count as a completed bootstrap. Capture terminal/JSON results, exact exit, created/preserved files, config changes, guidance action, and audit advice. `partial`/exit 1 with manual-required or blocked guidance means unresolved guidance; real runs may have created files, whereas dry-runs have only planned files. Report actual state and stop before claiming completion. Other refusals also stop without post-patches. For success, read config back to resolve the actual content root and authored index.
120
122
  4. **Verify files:** Print `[4/7] Verifying files…`. Check config root/index, baseline file existence, nonempty `title`/`description`, useful audience/scope context and populated `## Contents` links resolving to actual sibling pages or child `index.md`s. Honor excludes and asset-only exceptions; preserve local AGENTS instructions. Fresh setup creates only authored `index.md` and `contributing.md` in the target; verify no docs-root AGENTS, app package, framework config, dependencies, or root build changes. Run already documented lint/link/format checks when applicable; otherwise inspect files/links directly. Adoption preserves existing bytes and may leave missing child indexes, metadata, context, or links: record these as audit gaps for analyze/apply rather than repairing them or calling the tree fully conformant. Distinguish successful setup verification from content-conformance findings.
121
123
  5. **Inspect config:** `documentation.tooling` is the string `markdown`; `root` is the literal content directory; `index` is its authored entrypoint, normally `<root>/index.md`. Markdown introduces no `documentation.config`. Preserve unrelated config/excludes/completion settings. Verify deterministic managed root Documentation guidance names that root, Markdown tooling, authored index, and `<root>/contributing.md`; preserve manual/local guidance and surface unresolved disposition. The Step 5e completion opt-in remains available using the docs root rather than an app name, without silently changing an existing value. No nested app-config reconciliation or framework patch inspection applies.
122
124
  6. **Walkthrough:** In short chunks, show actual config and `<root>/index.md`: useful context plus the Contents map, title/description metadata, sibling `page.md` and child `section/index.md` links, exclusions and asset-only exceptions. Explain adding a page/section and updating the nearest authored map without overwriting existing context. Root AGENTS Documentation guidance and `<root>/contributing.md` establish agent/human conventions; a preexisting local AGENTS file remains authoritative, but bootstrap creates none. Authored indexes are edited directly. Optional generated inventories require explicit external output, e.g. `$CLI_CMD docs generate-index --docs-dir <root> --output .oat/docs-manifest.md`; output must stay outside the full configured content root and cannot overwrite the configured authored index even with a narrowed `--docs-dir`. Generation does not repoint `documentation.index`. Markdown bootstrap never generates a manifest automatically. Skip framework deep dives and preview-server/build commands.
123
- 7. **Audit handoff and summary:** Offer `oat-docs-analyze` against the literal configured root, followed by `oat-docs-apply` only for approved repairs. An adopted incomplete tree needs that audit; config/guidance alone prove no full conformance. Explain `oat-project-document` for source-backed project deltas. Summarize tooling, actual root/authored index, created/preserved files, guidance/config disposition, file-check outcomes, unresolved audit gaps, optional manifest ownership, and exact skill handoff. For dry-run/partial/refusal, label the outcome accordingly rather than printing BOOTSTRAP COMPLETE. No app, install, build, patch, or dev-command fields apply.
125
+ 7. **Audit handoff and summary:** Offer `oat-docs-analyze` against the literal configured root, followed by `oat-docs-apply` only for approved repairs. An adopted incomplete tree needs that audit; config/guidance alone prove no full conformance. Explain `oat-project-document` for source-backed project deltas. Summarize tooling, actual root/authored index, created/preserved files, guidance/config disposition, ordered IA guidance locators/provenance and proposal recommendation/conflicts, file-check outcomes, unresolved audit gaps, optional manifest ownership, and exact skill handoff. For dry-run/partial/refusal, label the outcome accordingly rather than printing BOOTSTRAP COMPLETE. No app, install, build, patch, or dev-command fields apply.
124
126
 
125
127
  ### Step 1: Preflight Detector
126
128
 
@@ -155,7 +157,7 @@ Read (do not modify):
155
157
 
156
158
  Build `conflicts: []` by adding an entry for each finding:
157
159
 
158
- - If `configDocumentation` is non-null → `{ kind: 'existing-config', detail: <summary of what's there> }`
160
+ - If `configDocumentation` declares a docs surface (`root`, `tooling`, `index` or `config`) → `{ kind: 'existing-config', detail: <summary of what's there> }`. A guidance-only section is an IA input, not evidence of an existing docs surface; retain it and continue fresh setup.
159
161
  - If `docsAppPath` exists on disk → `{ kind: 'existing-app-dir', detail: <path + whether it has uncommitted changes> }`
160
162
  - If `agentsMdSection` is true → `{ kind: 'existing-agents-section', detail: <what the section says> }`
161
163
 
@@ -208,7 +210,7 @@ Print `[2/7] Gathering inputs…` at the start of this step.
208
210
 
209
211
  **2a. Resolve Preflight conflicts (if any).**
210
212
 
211
- If `conflicts[]` from Preflight is non-empty, present them together and collect a `conflictResolution`. See the **Conflict Resolution Contract** sub-procedure below for the exact semantics of each option. Do not proceed to input questions until the user has chosen a resolution.
213
+ If `conflicts[]` from Preflight is non-empty, present them together and default to `repair`: run `oat-docs-analyze` (with `--ia` when structure is requested), review its artifact, then `oat-docs-apply` for approved repairs and exit. Use replacement or a second app only after an explicit user choice; a generic request to bootstrap is insufficient. See the **Conflict Resolution Contract** below. Do not scaffold until that contract is satisfied.
212
214
 
213
215
  If `conflicts[]` is empty, skip conflict handling and go to 2b.
214
216
 
@@ -271,14 +273,14 @@ Input Result:
271
273
 
272
274
  #### Conflict Resolution Contract (sub-procedure)
273
275
 
274
- When Preflight (Step 1) records non-empty `conflicts[]`, present them to the user together and collect exactly one resolution. Each resolution below has a precise definition in terms of **allowed mutations**, **preserved state**, and **stop conditions**. The Scaffold Runner (Step 3) reads the chosen resolution and adjusts its behavior; it never reinvents these semantics.
276
+ When Preflight (Step 1) records non-empty `conflicts[]`, present them together and default to `repair` unless the user explicitly selects another resolution. Record exactly one resolution. Each resolution below has a precise definition in terms of **allowed mutations**, **preserved state**, and **stop conditions**. The Scaffold Runner (Step 3) reads the chosen resolution and adjusts its behavior; it never reinvents these semantics.
275
277
 
276
278
  Resolution options:
277
279
 
278
280
  - **`replace`** — Treat the existing docs setup as disposable and scaffold fresh.
279
281
  - **Allowed mutations (executed by this sub-procedure before Scaffold Runner begins):**
280
282
  - Remove the existing docs app directory (`existingDocs.docsAppPath`), if present on disk.
281
- - Remove the `documentation` section from `$REPO_ROOT/.oat/config.json`, if present. The CLI will rewrite it during init.
283
+ - Clear the replaced surface fields in `documentation` in `$REPO_ROOT/.oat/config.json`, preserving `documentation.guidance` if present. The CLI will rewrite surface ownership during init; advisory guidance is unrelated to the discarded scaffold.
282
284
  - Remove the `## Documentation` section from `$REPO_ROOT/AGENTS.md`, if present. The CLI upserts its own.
283
285
  - **Preserved state:** Everything outside the three touchpoints above. Git history is preserved — deletions are tracked normally and remain recoverable via `git revert` / `git checkout`.
284
286
  - **Stop conditions:**
@@ -336,10 +338,10 @@ Preflight detected existing docs setup:
336
338
  - existing-agents-section: AGENTS.md has a ## Documentation section
337
339
 
338
340
  How should I proceed?
339
- 1. replace — remove the existing docs app and scaffold fresh at the same path
340
- 2. second-app — (deferred) add a new docs app alongside; not available in current CLI
341
- 3. abort — exit without changes
342
- 4. repair — run `oat-docs-analyze` / `oat-docs-apply` on the existing setup
341
+ 1. repair — default: run `oat-docs-analyze` / `oat-docs-apply` on the existing setup
342
+ 2. replace — explicit choice required: remove the existing docs app and scaffold fresh
343
+ 3. second-app — explicit choice required; deferred because current CLI cannot support it
344
+ 4. abort — exit without changes
343
345
 
344
346
  Choose:
345
347
  ```
@@ -351,10 +353,47 @@ Record the user's choice as `conflictResolution` in the Input Result. If the use
351
353
  No matter which resolution the user picks, the Scaffold Runner (Step 3) **never** invokes `oat docs init` until:
352
354
 
353
355
  1. The chosen resolution's "Allowed mutations" have **completed successfully**, and
354
- 2. The working-tree state **matches what the CLI expects** for that resolution (e.g., for `replace`: the target directory is empty or absent, the `documentation` config section is cleared, the root `AGENTS.md` `## Documentation` section is cleared; for `abort` / `repair`: the skill has already exited).
356
+ 2. The working-tree state **matches what the CLI expects** for that resolution (e.g., for `replace`: the target directory is empty or absent, the `documentation` surface fields are cleared (any `guidance` input is preserved), the root `AGENTS.md` `## Documentation` section is cleared; for `abort` / `repair`: the skill has already exited).
355
357
 
356
358
  If any mutation fails or any invariant check fails, **stop the flow before scaffold** and surface the error. A partial resolution followed by a scaffold produces a worse end state than either doing nothing or completing the resolution cleanly.
357
359
 
360
+ ### Step 2.5: IA Discovery and Proposal
361
+
362
+ Run for fresh Markdown, Fumadocs and MkDocs setup, and explicit adoption, before
363
+ any scaffold invocation. An existing surface routed to repair takes this stage
364
+ through `oat-docs-analyze --ia`; it does not return to scaffold afterward.
365
+
366
+ 1. Independently probe each exact `authoring-docs/SKILL.md` in order:
367
+ `${SKILL_DIR}/..` from the loaded skill (`SKILL_DIR` is the absolute directory
368
+ containing that loaded `SKILL.md`), `${HOME}/.agents/skills`, then
369
+ `<repo-root>/.agents/skills`. Bind the first matching `authoring-docs` directory
370
+ once as `AUTHORING_DOCS_ROOT`; load `${AUTHORING_DOCS_ROOT}/SKILL.md` and use
371
+ that same root for every authoring-docs reference and script, never ambient
372
+ discovery. If none is found, name `authoring-docs`, stop this handoff, and give
373
+ the intended-scope recovery command: `oat tools install docs --scope <user|project>`
374
+ or `oat tools update --pack docs --scope <user|project>`.
375
+ Read `${AUTHORING_DOCS_ROOT}/references/guidance-sources.md` and
376
+ `${AUTHORING_DOCS_ROOT}/references/information-architecture.md`.
377
+ Resolve explicit `--ia-guidance`/conversation → repo → user → built-in and
378
+ retain ordered locators/provenance. These are skill inputs, not new CLI flags.
379
+ 2. Read repo signals: manifests, UI navigators and journeys, CLI `bin`, routers,
380
+ IaC, `e2e/` or `.maestro/`, existing docs, independently consumed monorepo units.
381
+ Read AGENTS/contributing authority first. Do not infer triad needs from UI alone.
382
+ 3. Ask only decision-changing questions about readers/work contexts, independent
383
+ verification, canonical facts elsewhere and links that must survive.
384
+ 4. Use the shared five axes and IA Proposal template to present **two plausible
385
+ candidate structures**, each a **two-level tree with 5–8 representative page
386
+ placements**, one page job per placement and the **nearest approved preset**.
387
+ Size controls materialized depth; it does not select audience. For Flat Small,
388
+ use grouped index headings rather than new directories.
389
+ 5. Recommend one with evidence and tradeoffs; retain unresolved conflicts as
390
+ `ask_user` with local/external source citations. Non-repo guidance stays read-only
391
+ and private exemplars are never copied. Cite ordered sources in the proposal
392
+ and final summary, including the built-in path when it wins.
393
+ 6. Carry the proposal to analyze/apply content kickoff. This stage proposes only:
394
+ it does not persist an accepted IA, restructure pages or scaffold preset trees.
395
+ CLI scaffold output remains the existing starter; those capabilities ship later.
396
+
358
397
  ### Step 3: Scaffold Runner
359
398
 
360
399
  Invoke `oat docs init` with the collected inputs and then apply gated post-patches for any CLI gaps the Capability Detection sub-procedure reports as still-open. The Scaffold Runner probes CLI capabilities, invokes the CLI, and applies the AGENTS.md bridge if still needed. Template content is CLI-owned; report old-scaffold shapes through `oat-docs-analyze`.
@@ -826,6 +865,8 @@ OAT ▸ DOCS BOOTSTRAP COMPLETE
826
865
  App: {appName}
827
866
  Location: {appRoot}
828
867
  Framework: {framework}
868
+ IA guidance: {ordered selected locators + explicit/conversation/shared/user/builtin provenance}
869
+ IA proposal: {candidate recommendation, nearest preset, conflicts or none}
829
870
  Config: {configPath} (documentation section)
830
871
 
831
872
  Created:
@@ -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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"}
@@ -12,7 +12,7 @@ import { normalizeDispatchMatrix, validateDispatchRouteTarget, walkDispatchMatri
12
12
  import { formatDispatchNotices, terminalReviewerNoticesForMatrix, } from '../../config/dispatch-notices.js';
13
13
  import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
14
14
  import { parseJsonConfig } from '../../config/json.js';
15
- import { DEFAULT_INSTRUCTION_SYNC_STRATEGY, INSTRUCTION_SYNC_STRATEGIES, VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, isValidProjectLogDigestBound, normalizeWorkflowPostImplementSequence, readOatConfig, readOatConfigForDefaultScopeRepair, readOatConfigForDocumentationExcludesRepair, readOatConfigForInstructionPointerExcludesRepair, readOatConfigForInstructionSyncStrategyRepair, readOatConfigWithWarnings, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, VALID_POST_IMPLEMENT_LEGACY_SEQUENCES, } from '../../config/oat-config.js';
15
+ import { DEFAULT_INSTRUCTION_SYNC_STRATEGY, INSTRUCTION_SYNC_STRATEGIES, VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, isValidProjectLogDigestBound, normalizeWorkflowPostImplementSequence, normalizeDocumentationGuidance, readOatConfig, readOatConfigForDefaultScopeRepair, readOatConfigForDocumentationExcludesRepair, readOatConfigForInstructionPointerExcludesRepair, readOatConfigForInstructionSyncStrategyRepair, readOatConfigWithWarnings, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, VALID_POST_IMPLEMENT_LEGACY_SEQUENCES, } from '../../config/oat-config.js';
16
16
  import { getOwnKey, setOwnKey } from '../../config/own-keys.js';
17
17
  import { resolveEffectiveConfig, resolveEnvOverride, } from '../../config/resolve.js';
18
18
  import { resolveAssetsRoot } from '../../fs/assets.js';
@@ -67,6 +67,7 @@ const KEY_ORDER = [
67
67
  'archive.awsRegion',
68
68
  'autoReviewAtCheckpoints',
69
69
  'lastPausedProject',
70
+ 'documentation.guidance',
70
71
  'documentation.root',
71
72
  'documentation.tooling',
72
73
  'documentation.config',
@@ -238,6 +239,17 @@ const CONFIG_CATALOG = [
238
239
  description: 'Deprecated compatibility alias for workflow.autoReviewAtHillCheckpoints. Prefer `oat config set workflow.autoReviewAtHillCheckpoints <true|false>`.',
239
240
  deprecated: { supersededBy: 'workflow.autoReviewAtHillCheckpoints' },
240
241
  },
242
+ {
243
+ key: 'documentation.guidance',
244
+ group: 'Documentation Guidance (shared > user)',
245
+ scope: 'shared | user',
246
+ file: '.oat/config.json | ~/.oat/config.json',
247
+ type: 'string | string[]',
248
+ defaultValue: 'null (skills use built-in IA reference)',
249
+ mutability: 'read-write',
250
+ owningCommand: 'oat config set documentation.guidance <path|JSON-array> [--user]',
251
+ description: 'Ordered advisory Markdown IA sources. Explicit skill input wins, then repo, then user, then built-in. Only path/URL strings are stored.',
252
+ },
241
253
  {
242
254
  key: 'documentation.root',
243
255
  group: 'Shared Repo (.oat/config.json)',
@@ -1153,6 +1165,12 @@ function validateSurfaceForKey(key, surface) {
1153
1165
  if (surface === 'auto') {
1154
1166
  return;
1155
1167
  }
1168
+ if (key === 'documentation.guidance') {
1169
+ if (surface !== 'shared' && surface !== 'user') {
1170
+ throw new Error('documentation.guidance supports shared or user scope only.');
1171
+ }
1172
+ return;
1173
+ }
1156
1174
  if (key === 'updateNotifications') {
1157
1175
  if (surface !== 'user') {
1158
1176
  throw new Error(`Cannot set 'updateNotifications' at '${surface}' scope. updateNotifications can only be set at user scope (~/.oat/config.json).`);
@@ -1766,6 +1784,55 @@ async function listConfigKeys(repoRoot, userConfigDir, dependencies) {
1766
1784
  async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, dependencies, warn) {
1767
1785
  validateSurfaceForKey(key, surface);
1768
1786
  const effectiveSurface = surface === 'auto' ? defaultSurfaceForKey(key) : surface;
1787
+ if (key === 'documentation.guidance') {
1788
+ const configPath = effectiveSurface === 'user'
1789
+ ? join(userConfigDir, 'config.json')
1790
+ : join(repoRoot, '.oat', 'config.json');
1791
+ const trimmed = rawValue.trim();
1792
+ let guidance;
1793
+ try {
1794
+ guidance = normalizeDocumentationGuidance(trimmed.startsWith('[') ? JSON.parse(trimmed) : trimmed, configPath, effectiveSurface === 'user' ? 'user' : 'shared');
1795
+ }
1796
+ catch {
1797
+ throw new Error('Invalid documentation.guidance value: expected a non-empty path/URL string or ordered non-empty string array.');
1798
+ }
1799
+ let raw = { version: 1 };
1800
+ try {
1801
+ const parsed = parseJsonConfig(await dependencies.readFile(configPath), configPath);
1802
+ if (typeof parsed !== 'object' ||
1803
+ parsed === null ||
1804
+ Array.isArray(parsed)) {
1805
+ throw new Error(`Expected a config object in ${configPath}`);
1806
+ }
1807
+ raw = parsed;
1808
+ }
1809
+ catch (error) {
1810
+ if (error.code !== 'ENOENT')
1811
+ throw error;
1812
+ }
1813
+ const documentation = raw.documentation;
1814
+ if (documentation !== undefined &&
1815
+ (typeof documentation !== 'object' ||
1816
+ documentation === null ||
1817
+ Array.isArray(documentation))) {
1818
+ throw new Error(`Expected a documentation object in ${configPath}`);
1819
+ }
1820
+ // Patch only the declared input; do not normalize away unrelated or future fields.
1821
+ if (!isDeepStrictEqual(documentation?.guidance, guidance)) {
1822
+ await dependencies.atomicWriteJson(configPath, {
1823
+ ...raw,
1824
+ documentation: {
1825
+ ...documentation,
1826
+ guidance,
1827
+ },
1828
+ });
1829
+ }
1830
+ return {
1831
+ key,
1832
+ value: guidance ?? null,
1833
+ source: effectiveSurface,
1834
+ };
1835
+ }
1769
1836
  if (isPjmRemoteConfigKey(key)) {
1770
1837
  const config = await dependencies.readOatConfig(repoRoot);
1771
1838
  const remote = applyPjmRemoteSharedValue(config.pjm?.remote, key, rawValue);
@@ -2326,6 +2393,16 @@ async function unsetConfigValue(repoRoot, userConfigDir, key, surface, dependenc
2326
2393
  * runs only when the normalized pass found nothing to remove.
2327
2394
  */
2328
2395
  async function removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface, path, dependencies) {
2396
+ if (key === 'documentation.guidance') {
2397
+ const configPath = effectiveSurface === 'user'
2398
+ ? join(userConfigDir, 'config.json')
2399
+ : join(repoRoot, '.oat', 'config.json');
2400
+ const repaired = await removeConfigPathOnDisk(configPath, path);
2401
+ if (!repaired)
2402
+ return false;
2403
+ await dependencies.atomicWriteJson(configPath, repaired);
2404
+ return true;
2405
+ }
2329
2406
  if (effectiveSurface === 'user') {
2330
2407
  const configPath = join(userConfigDir, 'config.json');
2331
2408
  const userConfig = await dependencies.readUserConfig(userConfigDir);