@open-agent-toolkit/cli 0.3.28 → 0.3.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/docs-tooling/add-docs-to-a-repo.md +2 -0
- package/assets/docs/docs-tooling/commands.md +111 -3
- package/assets/docs/docs-tooling/workflows.md +16 -0
- package/assets/docs/reference/cli-reference.md +2 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/authoring-docs/SKILL.md +2 -2
- package/assets/skills/authoring-docs/references/information-architecture.md +5 -2
- package/assets/skills/authoring-docs/references/page-templates/alert-runbook.md +63 -0
- package/assets/skills/authoring-docs/references/page-templates/command-reference.md +55 -0
- package/assets/skills/authoring-docs/references/page-templates/decisions-pointer.md +44 -0
- package/assets/skills/authoring-docs/references/page-templates/engineering-feature.md +53 -0
- package/assets/skills/authoring-docs/references/page-templates/per-area-agents.md +42 -0
- package/assets/skills/authoring-docs/references/page-templates/product-feature.md +49 -0
- package/assets/skills/authoring-docs/references/page-templates/qa-validation.md +59 -0
- package/assets/skills/authoring-docs/references/page-templates/screen-spec.md +51 -0
- package/assets/skills/authoring-docs/references/page-templates/skill-command-guide.md +44 -0
- package/assets/skills/authoring-docs/references/page-templates/solution-record.md +43 -0
- package/assets/skills/authoring-docs/references/templates.md +22 -2
- package/assets/skills/oat-docs-analyze/SKILL.md +89 -3
- package/assets/skills/oat-docs-analyze/references/analysis-artifact-template.md +23 -0
- package/assets/skills/oat-docs-analyze/references/quality-checklist.md +18 -0
- package/assets/skills/oat-docs-bootstrap/SKILL.md +11 -5
- package/dist/commands/docs/index.d.ts.map +1 -1
- package/dist/commands/docs/index.js +2 -0
- package/dist/commands/docs/init/content.d.ts +23 -0
- package/dist/commands/docs/init/content.d.ts.map +1 -0
- package/dist/commands/docs/init/content.js +361 -0
- package/dist/commands/docs/init/index.d.ts.map +1 -1
- package/dist/commands/docs/init/index.js +32 -1
- package/dist/commands/docs/init/markdown.d.ts.map +1 -1
- package/dist/commands/docs/init/markdown.js +21 -2
- package/dist/commands/docs/init/resolve-options.d.ts +4 -1
- package/dist/commands/docs/init/resolve-options.d.ts.map +1 -1
- package/dist/commands/docs/init/resolve-options.js +4 -0
- package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
- package/dist/commands/docs/init/scaffold.js +20 -1
- package/dist/commands/docs/literals/evidence.d.ts +39 -0
- package/dist/commands/docs/literals/evidence.d.ts.map +1 -0
- package/dist/commands/docs/literals/evidence.js +205 -0
- package/dist/commands/docs/literals/literals.d.ts +3 -0
- package/dist/commands/docs/literals/literals.d.ts.map +1 -0
- package/dist/commands/docs/literals/literals.js +50 -0
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +10 -0
- package/package.json +3 -3
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const IA_PRESETS = [
|
|
4
|
+
'product-engineering-qa',
|
|
5
|
+
'consumer-maintainer',
|
|
6
|
+
'domain-engineering',
|
|
7
|
+
'task-type',
|
|
8
|
+
'toolkit-cli',
|
|
9
|
+
'flat-small',
|
|
10
|
+
];
|
|
11
|
+
/** Validate the opt-in pair before planning or writing any scaffold files. */
|
|
12
|
+
export function resolvePresetSelection(preset, count) {
|
|
13
|
+
if (preset === undefined && count === undefined)
|
|
14
|
+
return {};
|
|
15
|
+
if (preset === undefined || count === undefined)
|
|
16
|
+
throw new Error('--ia-preset and --planned-pages are required together.');
|
|
17
|
+
if (!IA_PRESETS.includes(preset))
|
|
18
|
+
throw new Error(`Unknown IA preset "${preset}". Choose: ${IA_PRESETS.join(', ')}.`);
|
|
19
|
+
if (!/^\d+$/.test(String(count)) ||
|
|
20
|
+
!Number.isSafeInteger(Number(count)) ||
|
|
21
|
+
Number(count) < 1)
|
|
22
|
+
throw new Error('--planned-pages must be an integer of at least 1 (anticipated reader pages only).');
|
|
23
|
+
return { iaPreset: preset, plannedPages: Number(count) };
|
|
24
|
+
}
|
|
25
|
+
const engineering = {
|
|
26
|
+
path: 'engineering',
|
|
27
|
+
title: 'Engineering',
|
|
28
|
+
principle: 'Domain and implementation contracts alongside paired feature pages',
|
|
29
|
+
purpose: 'Engineering is hybrid: enter by domain or implementation contract when changing shared behavior, and by feature when following its paired Product and QA pages.',
|
|
30
|
+
sections: [
|
|
31
|
+
[
|
|
32
|
+
'Domain contracts',
|
|
33
|
+
'Place shared domain rules, interface boundaries and invariants here; link the features that depend on them.',
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
'Feature implementation',
|
|
37
|
+
'Link implementation details for each feature to its Product intent, shared domain contracts and QA validation.',
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
'Operations and failure modes',
|
|
41
|
+
'Place diagnosis, recovery and operational limits here; link runbooks and incident solution records.',
|
|
42
|
+
],
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
const TRACKS = {
|
|
46
|
+
'product-engineering-qa': [
|
|
47
|
+
{
|
|
48
|
+
path: 'product',
|
|
49
|
+
title: 'Product',
|
|
50
|
+
principle: 'Feature or journey',
|
|
51
|
+
purpose: 'Product readers enter by feature or journey to understand availability, intended behavior and user-visible boundaries.',
|
|
52
|
+
sections: [
|
|
53
|
+
[
|
|
54
|
+
'Availability',
|
|
55
|
+
'Describe who can use each feature, supported environments and known availability limits; link its feature page.',
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
'Journeys and behavior',
|
|
59
|
+
'Place feature goals and ordered user journeys here, with their expected user-visible outcomes.',
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
'States and boundaries',
|
|
63
|
+
'Document visible states, transitions, empty and error behavior, and what each feature excludes.',
|
|
64
|
+
],
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
engineering,
|
|
68
|
+
{
|
|
69
|
+
path: 'qa',
|
|
70
|
+
title: 'QA',
|
|
71
|
+
principle: 'Feature or journey with reproducible verification',
|
|
72
|
+
purpose: 'QA readers enter by feature or journey to reproduce behavior with named seeds, ready signals, exact expectations and cleanup.',
|
|
73
|
+
sections: [
|
|
74
|
+
[
|
|
75
|
+
'Seeds and configuration',
|
|
76
|
+
'Place reproducible test data, configuration and ready signals here; identify safe setup and cleanup.',
|
|
77
|
+
],
|
|
78
|
+
[
|
|
79
|
+
'Scenarios',
|
|
80
|
+
'Organize validation by feature or journey, with actions, exact expectations and links to the supported contract.',
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
'Execution evidence',
|
|
84
|
+
'Keep dated runs, observed results and discrepancies here, separate from planned automation and implemented assertions.',
|
|
85
|
+
],
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
'consumer-maintainer': [
|
|
90
|
+
{
|
|
91
|
+
path: 'consumer',
|
|
92
|
+
title: 'Consumer',
|
|
93
|
+
principle: 'Reader task and supported contract',
|
|
94
|
+
purpose: 'Consumers enter by the task they need to complete and the supported contract they can rely on.',
|
|
95
|
+
sections: [
|
|
96
|
+
[
|
|
97
|
+
'Start here',
|
|
98
|
+
'Link the shortest supported first task, including prerequisites and a result the reader can verify.',
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
'Tasks',
|
|
102
|
+
'Place bounded procedures for consumer goals here; link required inputs and verification steps.',
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
'Supported reference',
|
|
106
|
+
'Collect supported interfaces, inputs, outputs and compatibility limits for consumer lookup.',
|
|
107
|
+
],
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
path: 'maintainer',
|
|
112
|
+
title: 'Maintainer',
|
|
113
|
+
principle: 'Change, operation and maintenance responsibility',
|
|
114
|
+
purpose: 'Maintainers enter by the responsibility they own: implementation, delivery, operations or support of the shared contract.',
|
|
115
|
+
sections: [
|
|
116
|
+
[
|
|
117
|
+
'Implementation contracts',
|
|
118
|
+
'Place internal interfaces, invariants and ownership boundaries here for maintainers changing behavior.',
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
'Delivery',
|
|
122
|
+
'Document release preparation, compatibility checks, rollout and rollback responsibilities here.',
|
|
123
|
+
],
|
|
124
|
+
[
|
|
125
|
+
'Operations',
|
|
126
|
+
'Link routine maintenance, diagnostic procedures and recovery runbooks, with their authority and safety boundaries.',
|
|
127
|
+
],
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
'domain-engineering': [engineering],
|
|
132
|
+
'task-type': [
|
|
133
|
+
{
|
|
134
|
+
path: 'tutorials',
|
|
135
|
+
title: 'Tutorials',
|
|
136
|
+
principle: 'Learning by a complete safe exercise',
|
|
137
|
+
purpose: 'Learners enter through a guided exercise with a clear starting state and an independently verifiable result.',
|
|
138
|
+
sections: [
|
|
139
|
+
[
|
|
140
|
+
'Prerequisites',
|
|
141
|
+
'State the required knowledge, access, environment and safe starting data before the reader begins.',
|
|
142
|
+
],
|
|
143
|
+
[
|
|
144
|
+
'Guided exercise',
|
|
145
|
+
'Walk through one complete learning exercise in order, explaining what each step demonstrates.',
|
|
146
|
+
],
|
|
147
|
+
[
|
|
148
|
+
'Expected result',
|
|
149
|
+
'Show how to recognize a successful exercise and compare the observed result with the learning goal.',
|
|
150
|
+
],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
path: 'how-to',
|
|
155
|
+
title: 'How-to',
|
|
156
|
+
principle: 'One concrete reader task',
|
|
157
|
+
purpose: 'Readers who know their goal enter by task, confirm prerequisites and follow a bounded procedure.',
|
|
158
|
+
sections: [
|
|
159
|
+
[
|
|
160
|
+
'Prerequisites',
|
|
161
|
+
'State the required knowledge, access, environment and safe starting data before the reader begins.',
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
'Procedure',
|
|
165
|
+
'Give the ordered actions for one concrete task, including decision points and supported alternatives.',
|
|
166
|
+
],
|
|
167
|
+
[
|
|
168
|
+
'Verification and cleanup',
|
|
169
|
+
'Explain how to check the task result, remove temporary resources and recover from an incomplete attempt.',
|
|
170
|
+
],
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
path: 'reference',
|
|
175
|
+
title: 'Reference',
|
|
176
|
+
principle: 'Lookup by supported interface or contract',
|
|
177
|
+
purpose: 'Readers enter by a named interface or contract to find exact inputs, outputs, defaults and supported limits.',
|
|
178
|
+
sections: [
|
|
179
|
+
[
|
|
180
|
+
'Interfaces',
|
|
181
|
+
'Describe supported commands, APIs or configuration fields with their accepted inputs and observable outputs.',
|
|
182
|
+
],
|
|
183
|
+
[
|
|
184
|
+
'Defaults and limits',
|
|
185
|
+
'Record source-verified defaults, supported ranges and compatibility constraints for precise lookup.',
|
|
186
|
+
],
|
|
187
|
+
[
|
|
188
|
+
'Failure behavior',
|
|
189
|
+
'Describe errors, partial outcomes and recovery expectations for each supported interface.',
|
|
190
|
+
],
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
path: 'explanation',
|
|
195
|
+
title: 'Explanation',
|
|
196
|
+
principle: 'Understanding concepts and tradeoffs',
|
|
197
|
+
purpose: 'Readers enter by a concept or design question to understand relationships, constraints and tradeoffs.',
|
|
198
|
+
sections: [
|
|
199
|
+
[
|
|
200
|
+
'Concepts',
|
|
201
|
+
'Explain the vocabulary and mental models readers need before following task or reference pages.',
|
|
202
|
+
],
|
|
203
|
+
[
|
|
204
|
+
'Relationships',
|
|
205
|
+
'Show how the concepts and components depend on one another, linking their canonical contracts.',
|
|
206
|
+
],
|
|
207
|
+
[
|
|
208
|
+
'Tradeoffs',
|
|
209
|
+
'Explain design choices, alternatives and constraints, linking the decisions that establish them.',
|
|
210
|
+
],
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
'toolkit-cli': [
|
|
215
|
+
{
|
|
216
|
+
path: 'tools',
|
|
217
|
+
title: 'Tools',
|
|
218
|
+
principle: 'Tool, skill or command invocation',
|
|
219
|
+
purpose: 'Tool users enter by command or skill, confirm prerequisites and mutation scope, then inspect the expected output.',
|
|
220
|
+
sections: [
|
|
221
|
+
[
|
|
222
|
+
'Invocation',
|
|
223
|
+
'Document how to invoke each command or skill, including prerequisites and supported examples.',
|
|
224
|
+
],
|
|
225
|
+
[
|
|
226
|
+
'Inputs and side effects',
|
|
227
|
+
'Describe accepted arguments and configuration, mutation scope, required approval and external effects.',
|
|
228
|
+
],
|
|
229
|
+
[
|
|
230
|
+
'Outputs',
|
|
231
|
+
'Document result fields, generated artifacts, exit behavior and the next action each outcome supports.',
|
|
232
|
+
],
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
path: 'workflows',
|
|
237
|
+
title: 'Workflows',
|
|
238
|
+
principle: 'Reader goal across a sequence of tools',
|
|
239
|
+
purpose: 'Workflow users enter by their goal and follow an ordered sequence of tools with explicit authority and handoffs.',
|
|
240
|
+
sections: [
|
|
241
|
+
[
|
|
242
|
+
'Starting state',
|
|
243
|
+
'State the reader goal, required inputs, authority and ready signals before a workflow begins.',
|
|
244
|
+
],
|
|
245
|
+
[
|
|
246
|
+
'Sequence and handoffs',
|
|
247
|
+
'Order the tools and decisions, naming what each step passes to the next responsible actor.',
|
|
248
|
+
],
|
|
249
|
+
[
|
|
250
|
+
'Completion evidence',
|
|
251
|
+
'Define the observable result that closes the workflow and where to retain its execution evidence.',
|
|
252
|
+
],
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
'flat-small': [
|
|
257
|
+
{
|
|
258
|
+
path: 'start-here',
|
|
259
|
+
title: 'Start here',
|
|
260
|
+
principle: 'Reader goal in a flat grouped index',
|
|
261
|
+
purpose: 'Readers enter by their immediate goal, using one grouped index instead of navigating a hierarchy before choosing a task.',
|
|
262
|
+
sections: [
|
|
263
|
+
[
|
|
264
|
+
'Reader tasks',
|
|
265
|
+
'Group links by the immediate goals readers need to accomplish, keeping each procedure focused.',
|
|
266
|
+
],
|
|
267
|
+
[
|
|
268
|
+
'Reference',
|
|
269
|
+
'Link canonical interface and configuration facts for lookup without repeating them in task pages.',
|
|
270
|
+
],
|
|
271
|
+
[
|
|
272
|
+
'Operations',
|
|
273
|
+
'Link routine maintenance, diagnostic procedures and recovery runbooks, with their authority and safety boundaries.',
|
|
274
|
+
],
|
|
275
|
+
],
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
};
|
|
279
|
+
const SUPPORT_TEMPLATES = [
|
|
280
|
+
'alert-runbook',
|
|
281
|
+
'solution-record',
|
|
282
|
+
'command-reference',
|
|
283
|
+
'skill-command-guide',
|
|
284
|
+
'decisions-pointer',
|
|
285
|
+
'per-area-agents',
|
|
286
|
+
];
|
|
287
|
+
const TRIAD_TEMPLATES = [
|
|
288
|
+
'product-feature',
|
|
289
|
+
'engineering-feature',
|
|
290
|
+
'qa-validation',
|
|
291
|
+
'screen-spec',
|
|
292
|
+
...SUPPORT_TEMPLATES,
|
|
293
|
+
];
|
|
294
|
+
export function mergeTemplateExclusion(paths = []) {
|
|
295
|
+
return [...new Set([...paths, 'contributing/templates/**'])];
|
|
296
|
+
}
|
|
297
|
+
function page(title, description, body) {
|
|
298
|
+
return `---\ntitle: ${JSON.stringify(title)}\ndescription: ${JSON.stringify(description)}\n---\n\n# ${title}\n\n${body}\n`;
|
|
299
|
+
}
|
|
300
|
+
function link(title, path, description) {
|
|
301
|
+
return `- [${title}](${path}) - ${description}`;
|
|
302
|
+
}
|
|
303
|
+
/** Shared narrow content plan; bodies are loaded from the bundled canonical skill. */
|
|
304
|
+
export async function planPresetContent(options) {
|
|
305
|
+
const selection = resolvePresetSelection(options.iaPreset, options.plannedPages);
|
|
306
|
+
if (!selection.iaPreset)
|
|
307
|
+
return null;
|
|
308
|
+
const preset = selection.iaPreset;
|
|
309
|
+
const tracks = TRACKS[preset];
|
|
310
|
+
const flat = selection.plannedPages < 15 || preset === 'flat-small';
|
|
311
|
+
const files = [];
|
|
312
|
+
const rootLinks = [];
|
|
313
|
+
for (const track of tracks) {
|
|
314
|
+
const guideName = flat ? `${track.path}.md` : `${track.path}/start-here.md`;
|
|
315
|
+
const indexName = `${track.path}/index.md`;
|
|
316
|
+
const guideTitle = `${track.title}: choose a safe first task`;
|
|
317
|
+
const guide = `${track.purpose}\n\n## Choose the right contract\n\nIdentify your goal and supported environment before acting. Check availability, permissions and prerequisites in the repository's current source and reviewed guidance. A missing fact is a review gap, not permission to guess.\n\n## Establish a safe starting state\n\nPrefer an isolated example or read-only inspection. Record relevant configuration and inputs, avoid real personal data, and identify the owner of any external dependency. For changes, confirm approval and a cleanup or rollback route before proceeding.\n\n## Verify the result\n\nCompare the observable result with the supported contract. Keep concepts in prose; use backticks only for literals verified in source. Separate proposed automation, implemented test assertions and dated execution evidence. Escalate a discrepancy with the input, expected result and observed evidence.\n\n## Continue\n\nReturn to the [${flat ? 'documentation map' : `${track.title} map`}](index.md) to choose the next reader goal.\n`;
|
|
318
|
+
files.push({
|
|
319
|
+
name: guideName,
|
|
320
|
+
content: page(guideTitle, `Select prerequisites, boundaries and a verifiable first result for ${track.title.toLowerCase()} work.`, guide),
|
|
321
|
+
});
|
|
322
|
+
if (flat) {
|
|
323
|
+
rootLinks.push(`### ${track.title}\n\n${track.purpose}\n\n${link(guideTitle, guideName, 'Choose a safe starting state and verify the result.')}\n`);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
const sections = track.sections
|
|
327
|
+
.map(([title, guidance]) => `## ${title}\n\n${guidance}`)
|
|
328
|
+
.join('\n\n');
|
|
329
|
+
files.push({
|
|
330
|
+
name: indexName,
|
|
331
|
+
content: page(track.title, track.purpose, `${track.purpose}\n\nEntry principle: ${track.principle}. This track owns its canonical facts; route to shared contracts and paired pages rather than copying their claims.\n\n## Contents\n\n${link(guideTitle, 'start-here.md', 'Choose a safe starting state and verify the result.')}\n\n${sections}`),
|
|
332
|
+
});
|
|
333
|
+
rootLinks.push(link(track.title, indexName, track.purpose));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const contributor = options.markdown
|
|
337
|
+
? 'contributing.md'
|
|
338
|
+
: 'contributing/index.md';
|
|
339
|
+
rootLinks.push(`${flat ? '### Contributing\n\n' : ''}${link('Contributing', contributor, 'Authoring conventions and template selection.')}\n`);
|
|
340
|
+
files.unshift({
|
|
341
|
+
name: 'index.md',
|
|
342
|
+
content: page(options.siteName, options.siteDescription?.trim() ||
|
|
343
|
+
`Reader entry points for the ${preset} model.`, `Choose the entry matching your work context. This documentation uses the ${preset} reader model; its entry principles guide placement, while page count controls materialized depth. Confirm repository-specific behavior against source before acting.\n\n## Contents\n\n${rootLinks.join('\n')}`),
|
|
344
|
+
});
|
|
345
|
+
const templates = preset === 'product-engineering-qa'
|
|
346
|
+
? TRIAD_TEMPLATES
|
|
347
|
+
: preset === 'domain-engineering'
|
|
348
|
+
? ['engineering-feature', ...SUPPORT_TEMPLATES]
|
|
349
|
+
: SUPPORT_TEMPLATES;
|
|
350
|
+
for (const name of templates) {
|
|
351
|
+
files.push({
|
|
352
|
+
name: `contributing/templates/${name}.md`,
|
|
353
|
+
content: await readFile(join(options.assetsRoot, 'skills', 'authoring-docs', 'references', 'page-templates', `${name}.md`), 'utf8'),
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
const table = tracks
|
|
357
|
+
.map((track) => `| ${flat ? `index.md (group: ${track.title})` : `${track.path}/`} | ${track.title} | ${track.principle} |`)
|
|
358
|
+
.join('\n');
|
|
359
|
+
const guidance = `## Preset selection\n\nAccepted selection supplied to init: ${preset}; anticipated reader pages: ${selection.plannedPages}. ${flat ? 'Reader structure is collapsed into grouped root headings.' : 'Reader directories are materialized at 15 or more anticipated pages.'} Contributor, template and toolchain pages are outside this reader-page estimate.\n\n| Location | Reader track | Entry principle |\n| --- | --- | --- |\n${table}\n\n${tracks.map((t) => t.purpose).join('\n\n')}\n\nUse contributing/templates/ as non-reader drafting assets. Screen specs are conditional on several journeys sharing a screen; no screen page or per-track AGENTS file is created automatically. Preserve canonical facts and paired links. This selection is not a persisted IA decision: complete the existing explicit approval/adoption and record-ia flow before claiming an authored IA record or config mirror. It does not initialize project management. Existing surfaces route to analyze and individually approved apply; init never restructures them.\n`;
|
|
360
|
+
return { files, guidance };
|
|
361
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,mBAAmB,EAGxB,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import { readOatConfig, writeOatConfig, } from '../../../config/oat-config.js';
|
|
|
9
9
|
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
10
10
|
import { atomicWriteJson, fileExists } from '../../../fs/io.js';
|
|
11
11
|
import { Command, Option } from 'commander';
|
|
12
|
+
import { mergeTemplateExclusion } from './content.js';
|
|
12
13
|
import { buildDocsCommands } from './docs-commands.js';
|
|
13
14
|
import { applyMarkdownDocsPlan, MarkdownDocsWriteError, planMarkdownDocs, validateMarkdownConfig, validateMarkdownTarget, } from './markdown.js';
|
|
14
15
|
import { DEFAULT_DOCS_REPO_SHAPE_DEPENDENCIES, detectDocsRepoShape, getDefaultDocsAppName, resolveDocsInitOptions, } from './resolve-options.js';
|
|
@@ -107,8 +108,27 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
107
108
|
root: plan.targetDir,
|
|
108
109
|
tooling: 'markdown',
|
|
109
110
|
index: `${plan.targetDir}/index.md`,
|
|
111
|
+
...(options.iaPreset
|
|
112
|
+
? {
|
|
113
|
+
nonReaderPaths: mergeTemplateExclusion(latest.documentation?.nonReaderPaths),
|
|
114
|
+
}
|
|
115
|
+
: {}),
|
|
110
116
|
};
|
|
111
|
-
|
|
117
|
+
if (options.iaPreset) {
|
|
118
|
+
const configPath = join(context.cwd, '.oat/config.json');
|
|
119
|
+
const raw = (await fileExists(configPath))
|
|
120
|
+
? JSON.parse(await readFile(configPath, 'utf8'))
|
|
121
|
+
: latest;
|
|
122
|
+
await atomicWriteJson(configPath, {
|
|
123
|
+
...raw,
|
|
124
|
+
documentation: {
|
|
125
|
+
...raw.documentation,
|
|
126
|
+
...latest.documentation,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else
|
|
131
|
+
await writeOatConfig(context.cwd, latest);
|
|
112
132
|
report.configStatus = 'updated';
|
|
113
133
|
}
|
|
114
134
|
catch (error) {
|
|
@@ -145,6 +165,8 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
145
165
|
enabled: options.rootPatch,
|
|
146
166
|
});
|
|
147
167
|
const config = await readOatConfig(context.cwd);
|
|
168
|
+
if (options.iaPreset)
|
|
169
|
+
result.documentationConfig.nonReaderPaths = mergeTemplateExclusion(config.documentation?.nonReaderPaths);
|
|
148
170
|
config.documentation = {
|
|
149
171
|
...config.documentation,
|
|
150
172
|
...result.documentationConfig,
|
|
@@ -250,6 +272,8 @@ async function runDocsInitCommand(context, options, dependencies) {
|
|
|
250
272
|
interactive: context.interactive,
|
|
251
273
|
acceptDefaults: options.yes ?? false,
|
|
252
274
|
providedFramework: options.framework,
|
|
275
|
+
providedIaPreset: options.iaPreset,
|
|
276
|
+
providedPlannedPages: options.plannedPages,
|
|
253
277
|
providedAdopt: options.adopt,
|
|
254
278
|
providedAppName: options.appName,
|
|
255
279
|
providedSiteName: options.siteName,
|
|
@@ -276,6 +300,11 @@ async function runDocsInitCommand(context, options, dependencies) {
|
|
|
276
300
|
}
|
|
277
301
|
const inapplicableOptions = [];
|
|
278
302
|
const existingConfig = await dependencies.readOatConfig(context.cwd);
|
|
303
|
+
if (resolved.iaPreset &&
|
|
304
|
+
(existingConfig.documentation?.root ||
|
|
305
|
+
existingConfig.documentation?.ia ||
|
|
306
|
+
existingConfig.documentation?.navOwner))
|
|
307
|
+
throw new Error('Preset init cannot replace an existing docs surface or navigation ownership. Use oat-docs-analyze and individually approved oat-docs-apply.');
|
|
279
308
|
if (resolved.framework === 'markdown') {
|
|
280
309
|
resolved.targetDir = await validateMarkdownTarget(context.cwd, resolved.targetDir);
|
|
281
310
|
validateMarkdownConfig(context.cwd, resolved.targetDir, existingConfig.documentation);
|
|
@@ -464,6 +493,8 @@ export function createDocsInitCommand(overrides = {}) {
|
|
|
464
493
|
.addOption(new Option('--app-name <name>', 'Docs app name (inapplicable to Markdown)'))
|
|
465
494
|
.addOption(new Option('--site-name <name>', 'Site display title or Markdown documentation title'))
|
|
466
495
|
.addOption(new Option('--target-dir <path>', 'Docs directory (Markdown defaults to docs; requires a dedicated directory)'))
|
|
496
|
+
.option('--ia-preset <preset>', 'Approved IA preset (requires --planned-pages; fresh empty target only)')
|
|
497
|
+
.option('--planned-pages <count>', 'Anticipated reader pages: integer >=1; collapse below 15 (requires --ia-preset)')
|
|
467
498
|
.addOption(new Option('--description <text>', 'Documentation description'))
|
|
468
499
|
.addOption(new Option('--lint <mode>', 'Markdown lint mode').choices([
|
|
469
500
|
'none',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/markdown.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/markdown.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAMjE,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,mBAAmB,CAAC;AAE3B,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAsBD,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,sBAAsB,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mBAAmB,EAAE,sBAAsB,CAAC;IAC5C,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mBAAmB,EAAE,sBAAsB,CAAC;CAC7C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAG7C,QAAQ,CAAC,MAAM,EAAE,kBAAkB;IAFrC,YACE,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,kBAAkB,EACnC,KAAK,EAAE,OAAO,EAGf;CACF;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,sBAAsB,GAChC,IAAI,CAeN;AA6JD,kEAAkE;AAClE,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAuG3B;AAED,kFAAkF;AAClF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,kBAAkB,CAAC,CA+E7B"}
|
|
@@ -4,6 +4,7 @@ import { createExclusionMatcher } from '../../docs/index-generate/generator.js';
|
|
|
4
4
|
import { dirExists, ensureDir } from '../../../fs/io.js';
|
|
5
5
|
import { normalizeToPosixPath, validatePathWithinScope } from '../../../fs/paths.js';
|
|
6
6
|
import { parse as parseYaml } from 'yaml';
|
|
7
|
+
import { mergeTemplateExclusion, planPresetContent } from './content.js';
|
|
7
8
|
import { humanizeAppName, } from './resolve-options.js';
|
|
8
9
|
/** Validate a dedicated Markdown root, including existing symlink ancestors. */
|
|
9
10
|
export async function validateMarkdownTarget(repoRoot, targetDir) {
|
|
@@ -192,15 +193,27 @@ export async function planMarkdownDocs(options) {
|
|
|
192
193
|
(await readdir(appRoot)).length > 0) {
|
|
193
194
|
throw new Error(`Markdown docs target is not empty: ${targetDir}. Use --adopt to preserve existing docs, then run oat-docs-analyze for content gaps.`);
|
|
194
195
|
}
|
|
196
|
+
if (options.iaPreset &&
|
|
197
|
+
(await dirExists(appRoot)) &&
|
|
198
|
+
(await readdir(appRoot)).length > 0)
|
|
199
|
+
throw new Error('Preset init requires an empty docs target. Preserve existing docs and use oat-docs-analyze with individually approved oat-docs-apply.');
|
|
200
|
+
const contentPlan = await planPresetContent({ ...options, markdown: true });
|
|
195
201
|
const documentationConfig = {
|
|
196
202
|
...options.documentation,
|
|
197
203
|
root: targetDir,
|
|
198
204
|
tooling: 'markdown',
|
|
199
205
|
index: `${targetDir}/index.md`,
|
|
206
|
+
...(contentPlan
|
|
207
|
+
? {
|
|
208
|
+
nonReaderPaths: mergeTemplateExclusion(options.documentation?.nonReaderPaths),
|
|
209
|
+
}
|
|
210
|
+
: {}),
|
|
200
211
|
};
|
|
201
212
|
const configChanged = options.documentation?.root !== targetDir ||
|
|
202
213
|
options.documentation?.tooling !== 'markdown' ||
|
|
203
|
-
options.documentation?.index !== `${targetDir}/index.md
|
|
214
|
+
options.documentation?.index !== `${targetDir}/index.md` ||
|
|
215
|
+
(contentPlan !== null &&
|
|
216
|
+
!options.documentation?.nonReaderPaths?.includes('contributing/templates/**'));
|
|
204
217
|
const existing = new Map();
|
|
205
218
|
for (const name of ['index.md', 'contributing.md'])
|
|
206
219
|
existing.set(name, await readBaseline(options.repoRoot, join(appRoot, name)));
|
|
@@ -223,9 +236,14 @@ export async function planMarkdownDocs(options) {
|
|
|
223
236
|
const template = await readFile(join(options.assetsRoot, 'templates', 'docs-markdown', name), 'utf8');
|
|
224
237
|
files.push({
|
|
225
238
|
name,
|
|
226
|
-
content:
|
|
239
|
+
content: (contentPlan?.files.find((file) => file.name === name)?.content ??
|
|
240
|
+
renderMarkdownTemplate(template, options, contents)) +
|
|
241
|
+
(contentPlan && name === 'contributing.md'
|
|
242
|
+
? `\n${contentPlan.guidance}`
|
|
243
|
+
: ''),
|
|
227
244
|
});
|
|
228
245
|
}
|
|
246
|
+
files.push(...(contentPlan?.files.filter((file) => file.name !== 'index.md') ?? []));
|
|
229
247
|
return {
|
|
230
248
|
repoRoot: options.repoRoot,
|
|
231
249
|
targetDir,
|
|
@@ -254,6 +272,7 @@ export async function applyMarkdownDocsPlan(plan) {
|
|
|
254
272
|
for (const { name, content } of plan.files) {
|
|
255
273
|
await validateMarkdownTarget(plan.repoRoot, plan.targetDir);
|
|
256
274
|
const path = join(plan.appRoot, name);
|
|
275
|
+
await ensureDir(dirname(path));
|
|
257
276
|
let handle;
|
|
258
277
|
try {
|
|
259
278
|
handle = await open(path, 'wx');
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { PromptContext, SelectChoice } from '../../shared/shared.prompts.js';
|
|
2
|
+
import { type PresetSelection } from './content.js';
|
|
2
3
|
export type DocsRepoShape = 'monorepo' | 'single-package' | 'nested-standalone';
|
|
3
4
|
export type DocsDetectedRepoShape = Exclude<DocsRepoShape, 'nested-standalone'>;
|
|
4
5
|
export type DocsFramework = 'fumadocs' | 'mkdocs' | 'markdown';
|
|
5
6
|
export type DocsLintMode = 'none' | 'markdownlint-cli2';
|
|
6
7
|
export type DocsFormatMode = 'oxfmt' | 'none';
|
|
7
|
-
export interface DocsInitResolvedOptions {
|
|
8
|
+
export interface DocsInitResolvedOptions extends PresetSelection {
|
|
8
9
|
repoRoot: string;
|
|
9
10
|
repoShape: DocsRepoShape;
|
|
10
11
|
framework: DocsFramework;
|
|
@@ -23,6 +24,8 @@ export interface ResolveDocsInitOptionsInput {
|
|
|
23
24
|
interactive: boolean;
|
|
24
25
|
acceptDefaults: boolean;
|
|
25
26
|
providedFramework?: DocsFramework;
|
|
27
|
+
providedIaPreset?: string;
|
|
28
|
+
providedPlannedPages?: string;
|
|
26
29
|
providedAdopt?: boolean;
|
|
27
30
|
providedAppName?: string;
|
|
28
31
|
providedSiteName?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-options.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/resolve-options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACb,MAAM,iCAAiC,CAAC;AAGzC,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;AAChF,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;AAChF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9C,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"resolve-options.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/resolve-options.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { basename, isAbsolute, join, relative, resolve } from 'node:path';
|
|
2
2
|
import { dirExists, fileExists } from '../../../fs/io.js';
|
|
3
|
+
import { resolvePresetSelection } from './content.js';
|
|
3
4
|
const FRAMEWORK_CHOICES = [
|
|
4
5
|
{ label: 'Fumadocs (Next.js + MDX, static export)', value: 'fumadocs' },
|
|
5
6
|
{ label: 'MkDocs (Python, Material theme)', value: 'mkdocs' },
|
|
@@ -83,6 +84,7 @@ export function resolveEffectiveDocsShape(repoShape, framework, repoRoot, target
|
|
|
83
84
|
return isRepoSubdirectory ? 'nested-standalone' : repoShape;
|
|
84
85
|
}
|
|
85
86
|
export async function resolveDocsInitOptions(input) {
|
|
87
|
+
const selection = resolvePresetSelection(input.providedIaPreset, input.providedPlannedPages);
|
|
86
88
|
const ctx = { interactive: input.interactive };
|
|
87
89
|
const framework = input.providedFramework ||
|
|
88
90
|
(input.interactive && !input.acceptDefaults
|
|
@@ -109,6 +111,7 @@ export async function resolveDocsInitOptions(input) {
|
|
|
109
111
|
if (!targetDir)
|
|
110
112
|
return null;
|
|
111
113
|
return {
|
|
114
|
+
...selection,
|
|
112
115
|
repoRoot: input.repoRoot,
|
|
113
116
|
repoShape: input.repoShape,
|
|
114
117
|
framework,
|
|
@@ -168,6 +171,7 @@ export async function resolveDocsInitOptions(input) {
|
|
|
168
171
|
}
|
|
169
172
|
const repoShape = resolveEffectiveDocsShape(input.repoShape, framework, input.repoRoot, targetDir);
|
|
170
173
|
return {
|
|
174
|
+
...selection,
|
|
171
175
|
repoRoot: input.repoRoot,
|
|
172
176
|
repoShape,
|
|
173
177
|
framework,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAOjE,OAAO,KAAK,EAEV,aAAa,EACb,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAqG3B,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACrE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,sBAAsB,CAAC;IAC5C,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,EAAE,MAAM,YAAY,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACjE,0BAA0B,EAAE,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,KACZ,YAAY,CAAC,OAAO,CAAC,CAAC;CAC5B;AAUD,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAgDD,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAaxB;AAmOD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,MAAM,GAChB,sBAAsB,CAwBxB;AAyDD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAAC,qBAAqB,CAAC,CA0GhC"}
|
|
@@ -2,6 +2,7 @@ import { readdir, readFile, realpath, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import { basename, dirname, isAbsolute, join, relative, resolve, } from 'node:path';
|
|
3
3
|
import { dirExists, ensureDir, fileExists } from '../../../fs/io.js';
|
|
4
4
|
import { OAT_VERSION } from '../../../shared/oat-version.js';
|
|
5
|
+
import { planPresetContent } from './content.js';
|
|
5
6
|
import { buildDocsCommands, shellQuote } from './docs-commands.js';
|
|
6
7
|
import { applyMarkdownDocsPlan, planMarkdownDocs } from './markdown.js';
|
|
7
8
|
import { getTemplateDir } from './resolve-options.js';
|
|
@@ -387,6 +388,7 @@ export async function scaffoldDocsApp(options, overrides = {}) {
|
|
|
387
388
|
throw new Error(`Docs app templates not found under ${templateRoot}`);
|
|
388
389
|
}
|
|
389
390
|
await ensureTargetWritable(appRoot);
|
|
391
|
+
const contentPlan = await planPresetContent({ ...options, markdown: false });
|
|
390
392
|
await ensureDir(appRoot);
|
|
391
393
|
const packageManagerField = await buildPackageManagerField(options, appRoot, dependencies);
|
|
392
394
|
const nodeRequirement = await detectNodeRequirement(options.repoRoot);
|
|
@@ -396,14 +398,31 @@ export async function scaffoldDocsApp(options, overrides = {}) {
|
|
|
396
398
|
if (templateFile.destination === 'pnpm-workspace.yaml' &&
|
|
397
399
|
!independentPnpmRoot)
|
|
398
400
|
continue;
|
|
401
|
+
if (contentPlan &&
|
|
402
|
+
[join('docs', 'index.md'), join('docs', 'getting-started.md')].includes(templateFile.destination))
|
|
403
|
+
continue;
|
|
399
404
|
const source = join(templateRoot, templateFile.source);
|
|
400
405
|
const destination = join(appRoot, templateFile.destination);
|
|
401
406
|
const template = await readFile(source, 'utf8');
|
|
402
|
-
|
|
407
|
+
let rendered = renderTemplate(template, options, depContext, packageManagerField, nodeRequirement, templateFile.destination === 'package.json');
|
|
408
|
+
if (contentPlan && templateFile.destination === 'AGENTS.md') {
|
|
409
|
+
rendered = rendered.replace('This starter separates reader Getting Started from contributor setup.', 'This starter uses the selected reader tracks and entry principles listed below.');
|
|
410
|
+
rendered += `\n${contentPlan.guidance}`;
|
|
411
|
+
}
|
|
412
|
+
if (contentPlan &&
|
|
413
|
+
templateFile.destination ===
|
|
414
|
+
join('docs', 'contributing', 'docs-toolchain.md'))
|
|
415
|
+
rendered = rendered.replaceAll('[Getting Started](../getting-started.md)', '[the documentation home](../index.md)');
|
|
403
416
|
await ensureDir(dirname(destination));
|
|
404
417
|
await writeFile(destination, rendered, 'utf8');
|
|
405
418
|
createdFiles.push(templateFile.destination);
|
|
406
419
|
}
|
|
420
|
+
for (const file of contentPlan?.files ?? []) {
|
|
421
|
+
const destination = join(appRoot, 'docs', file.name);
|
|
422
|
+
await ensureDir(dirname(destination));
|
|
423
|
+
await writeFile(destination, file.content, 'utf8');
|
|
424
|
+
createdFiles.push(join('docs', file.name));
|
|
425
|
+
}
|
|
407
426
|
return {
|
|
408
427
|
appRoot,
|
|
409
428
|
createdFiles,
|