@open-agent-toolkit/cli 0.3.31 → 0.3.33

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 (58) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/docs-tooling/check.md +54 -30
  3. package/assets/docs/docs-tooling/commands.md +21 -2
  4. package/assets/docs/docs-tooling/workflows.md +14 -6
  5. package/assets/docs/reference/cli-reference.md +2 -2
  6. package/assets/docs/reference/config-and-local-state.md +1 -1
  7. package/assets/docs/reference/configuration.md +2 -2
  8. package/assets/docs/reference/docs-index-contract.md +3 -2
  9. package/assets/docs/reference/oat-directory-structure.md +1 -1
  10. package/assets/public-package-versions.json +4 -4
  11. package/assets/skills/oat-agent-instructions-analyze/SKILL.md +2 -2
  12. package/assets/skills/oat-docs-analyze/SKILL.md +63 -25
  13. package/assets/skills/oat-docs-analyze/references/analysis-artifact-template.md +9 -6
  14. package/assets/skills/oat-docs-analyze/references/quality-checklist.md +2 -2
  15. package/assets/skills/oat-docs-analyze/scripts/package-drift.mjs +358 -40
  16. package/assets/skills/oat-docs-apply/SKILL.md +22 -12
  17. package/assets/skills/oat-docs-apply/references/apply-plan-template.md +3 -2
  18. package/dist/commands/config/index.d.ts.map +1 -1
  19. package/dist/commands/config/index.js +47 -9
  20. package/dist/commands/docs/check/check.d.ts.map +1 -1
  21. package/dist/commands/docs/check/check.js +1 -0
  22. package/dist/commands/docs/check/checker.d.ts +2 -0
  23. package/dist/commands/docs/check/checker.d.ts.map +1 -1
  24. package/dist/commands/docs/check/checker.js +2 -0
  25. package/dist/commands/docs/check/commands.d.ts.map +1 -1
  26. package/dist/commands/docs/check/commands.js +74 -30
  27. package/dist/commands/docs/check/files.d.ts +2 -0
  28. package/dist/commands/docs/check/files.d.ts.map +1 -1
  29. package/dist/commands/docs/check/files.js +16 -0
  30. package/dist/commands/docs/check/navigation.d.ts +7 -1
  31. package/dist/commands/docs/check/navigation.d.ts.map +1 -1
  32. package/dist/commands/docs/check/navigation.js +19 -68
  33. package/dist/commands/docs/check/reader-rules.d.ts.map +1 -1
  34. package/dist/commands/docs/check/reader-rules.js +8 -3
  35. package/dist/commands/docs/index-generate/generator.d.ts +9 -1
  36. package/dist/commands/docs/index-generate/generator.d.ts.map +1 -1
  37. package/dist/commands/docs/index-generate/generator.js +17 -6
  38. package/dist/commands/docs/index-generate/index.d.ts +1 -1
  39. package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
  40. package/dist/commands/docs/index-generate/index.js +24 -12
  41. package/dist/commands/docs/init/content.d.ts +2 -3
  42. package/dist/commands/docs/init/content.d.ts.map +1 -1
  43. package/dist/commands/docs/init/content.js +3 -10
  44. package/dist/commands/docs/nav/fumadocs.d.ts +29 -0
  45. package/dist/commands/docs/nav/fumadocs.d.ts.map +1 -1
  46. package/dist/commands/docs/nav/fumadocs.js +8 -5
  47. package/dist/commands/docs/nav/membership.d.ts +37 -0
  48. package/dist/commands/docs/nav/membership.d.ts.map +1 -0
  49. package/dist/commands/docs/nav/membership.js +475 -0
  50. package/dist/commands/docs/nav/sync.d.ts +26 -2
  51. package/dist/commands/docs/nav/sync.d.ts.map +1 -1
  52. package/dist/commands/docs/nav/sync.js +160 -43
  53. package/dist/config/documentation-ia.d.ts +19 -0
  54. package/dist/config/documentation-ia.d.ts.map +1 -0
  55. package/dist/config/documentation-ia.js +42 -0
  56. package/dist/config/oat-config.d.ts.map +1 -1
  57. package/dist/config/oat-config.js +5 -1
  58. package/package.json +3 -3
@@ -1,18 +1,17 @@
1
1
  #!/usr/bin/env node
2
- // Read-only, offline comparison used by oat-docs-analyze. No package resolution or install.
3
- import { readFile, realpath } from 'node:fs/promises';
4
- import { dirname, join, resolve } from 'node:path';
2
+ // Read-only, offline comparison used by oat-docs-analyze. It reads installed
3
+ // package manifests the way Node resolves packages (the app's node_modules,
4
+ // then each ancestor's) and never installs, fetches or executes anything.
5
+ import { access, open, readFile, realpath } from 'node:fs/promises';
6
+ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
5
7
  import { parseArgs } from 'node:util';
6
8
 
7
9
  const shellQuote = (value) =>
8
10
  `'${value.replaceAll("'", String.fromCharCode(39, 92, 39, 39))}'`;
9
11
 
10
- async function versionsForCli(executable) {
11
- if (!executable)
12
- throw new Error(
13
- 'Provide --cli with the installed oat executable or --versions with its bundled public-package-versions.json.',
14
- );
15
- let directory = dirname(await realpath(executable));
12
+ // Walk up from a real file to the installed CLI package root.
13
+ async function cliPackageFor(file) {
14
+ let directory = dirname(file);
16
15
  for (;;) {
17
16
  try {
18
17
  const pkg = JSON.parse(
@@ -24,14 +23,302 @@ async function versionsForCli(executable) {
24
23
  if (error.code !== 'ENOENT') throw error;
25
24
  }
26
25
  const parent = dirname(directory);
27
- if (parent === directory)
28
- throw new Error(
29
- 'Cannot locate the running CLI bundle through this wrapper; supply --versions from that installed CLI.',
30
- );
26
+ if (parent === directory) return null;
31
27
  directory = parent;
32
28
  }
33
29
  }
34
30
 
31
+ // Package-manager shims (pnpm, cmd-shim) are POSIX shell scripts. Parse them as
32
+ // text and never execute them: the `# cmd-shim-target=` comment names the
33
+ // absolute entry; `exec` lines name it relative to the shim's real directory.
34
+ async function shimTargets(file) {
35
+ const handle = await open(file, 'r');
36
+ let text;
37
+ try {
38
+ const { size } = await handle.stat();
39
+ if (size > 65536) return [];
40
+ text = await handle.readFile('utf8');
41
+ } finally {
42
+ await handle.close();
43
+ }
44
+ const [shebang = ''] = text.split(/\r?\n/, 1);
45
+ if (!/^#!.*\b(?:sh|bash|dash|ksh|zsh)\b/.test(shebang)) return [];
46
+ const base = dirname(file);
47
+ const targets = [];
48
+ for (const match of text.matchAll(/^#\s*cmd-shim-target=(.+?)\s*$/gm))
49
+ targets.push(isAbsolute(match[1]) ? match[1] : resolve(base, match[1]));
50
+ for (const match of text.matchAll(/"\$basedir\/([^"$`\\]+\.(?:c|m)?js)"/g))
51
+ targets.push(resolve(base, match[1]));
52
+ return [...new Set(targets)];
53
+ }
54
+
55
+ async function versionsForCli(executable) {
56
+ if (!executable)
57
+ throw new Error(
58
+ 'Provide --cli with the installed oat executable or --versions with its bundled public-package-versions.json.',
59
+ );
60
+ const file = await realpath(executable);
61
+ const targets = await shimTargets(file);
62
+ // Direct installs resolve to the bundle entry itself; shims are never walked
63
+ // from their own location, which can sit above an unrelated package.
64
+ for (const target of targets.length > 0 ? targets : [file]) {
65
+ let entry;
66
+ try {
67
+ entry = await realpath(target);
68
+ } catch (error) {
69
+ if (error.code === 'ENOENT' || error.code === 'ENOTDIR') continue;
70
+ throw error;
71
+ }
72
+ const found = await cliPackageFor(entry);
73
+ if (found) return found;
74
+ }
75
+ throw new Error(
76
+ 'Cannot locate the running CLI bundle through this wrapper; supply --versions from that installed CLI.',
77
+ );
78
+ }
79
+
80
+ async function exists(path) {
81
+ try {
82
+ await access(path);
83
+ return true;
84
+ } catch (error) {
85
+ if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return false;
86
+ throw error;
87
+ }
88
+ }
89
+
90
+ async function readJson(path) {
91
+ try {
92
+ return JSON.parse(await readFile(path, 'utf8'));
93
+ } catch (error) {
94
+ if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return null;
95
+ throw error;
96
+ }
97
+ }
98
+
99
+ function ancestors(directory) {
100
+ const list = [];
101
+ for (let current = directory; ; current = dirname(current)) {
102
+ list.push(current);
103
+ if (dirname(current) === current) return list;
104
+ }
105
+ }
106
+
107
+ // Node package lookup: <dir>/node_modules/<name> from the app upward, so
108
+ // hoisted installs (pnpm node-linker=hoisted, npm/yarn workspaces) resolve.
109
+ async function installedManifest(appPath, name) {
110
+ for (const directory of ancestors(appPath)) {
111
+ const path = join(directory, 'node_modules', name, 'package.json');
112
+ const manifest = await readJson(path);
113
+ if (manifest !== null) return { path, manifest };
114
+ }
115
+ return null;
116
+ }
117
+
118
+ // The app's own packageManager wins, then the nearest ancestor's.
119
+ async function packageManagerFor(appPath) {
120
+ for (const directory of ancestors(appPath)) {
121
+ const manifest = await readJson(join(directory, 'package.json'));
122
+ if (typeof manifest?.packageManager === 'string')
123
+ return manifest.packageManager.trim();
124
+ }
125
+ return null;
126
+ }
127
+
128
+ // Remove a YAML comment: `#` at line start or after whitespace, outside quotes.
129
+ function stripYamlComment(line) {
130
+ let quote = null;
131
+ for (let index = 0; index < line.length; index += 1) {
132
+ const char = line[index];
133
+ if (quote) {
134
+ if (char === quote) quote = null;
135
+ } else if (char === '"' || char === "'") quote = char;
136
+ else if (char === '#' && (index === 0 || /\s/.test(line[index - 1])))
137
+ return line.slice(0, index);
138
+ }
139
+ return line;
140
+ }
141
+
142
+ function unquoteYaml(value) {
143
+ const text = value.trim();
144
+ if (text.length >= 2 && text.startsWith("'") && text.endsWith("'"))
145
+ return text.slice(1, -1).replaceAll("''", "'");
146
+ if (text.length >= 2 && text.startsWith('"') && text.endsWith('"')) {
147
+ try {
148
+ return JSON.parse(text);
149
+ } catch {
150
+ return text.slice(1, -1);
151
+ }
152
+ }
153
+ return text;
154
+ }
155
+
156
+ // Split a flow sequence body on commas outside quotes and braces.
157
+ function splitFlowItems(body) {
158
+ const items = [];
159
+ let quote = null;
160
+ let depth = 0;
161
+ let current = '';
162
+ for (const char of body) {
163
+ if (quote) {
164
+ if (char === quote) quote = null;
165
+ } else if (char === '"' || char === "'") quote = char;
166
+ else if (char === '{') depth += 1;
167
+ else if (char === '}') depth -= 1;
168
+ else if (char === ',' && depth === 0) {
169
+ items.push(current);
170
+ current = '';
171
+ continue;
172
+ }
173
+ current += char;
174
+ }
175
+ items.push(current);
176
+ return items;
177
+ }
178
+
179
+ // The `packages` list of a pnpm-workspace.yaml: an indented or unindented
180
+ // block sequence or a flow sequence, with quotes and comments. A file
181
+ // without `packages` (settings only) declares no member packages.
182
+ function workspacePatterns(text) {
183
+ const lines = text.split(/\r?\n/).map(stripYamlComment);
184
+ const start = lines.findIndex((line) => /^packages\s*:/.test(line));
185
+ if (start < 0) return [];
186
+ const inline = lines[start].replace(/^packages\s*:/, '').trim();
187
+ if (inline.startsWith('[')) {
188
+ let flow = inline;
189
+ for (
190
+ let index = start + 1;
191
+ !flow.includes(']') && index < lines.length;
192
+ index += 1
193
+ )
194
+ flow += ` ${lines[index].trim()}`;
195
+ return splitFlowItems(flow.slice(1, flow.lastIndexOf(']')))
196
+ .map(unquoteYaml)
197
+ .filter((entry) => entry.length > 0);
198
+ }
199
+ const patterns = [];
200
+ for (const line of lines.slice(start + 1)) {
201
+ if (line.trim() === '') continue;
202
+ const item = line.match(/^\s*-\s*(.*)$/);
203
+ if (!item) break;
204
+ patterns.push(unquoteYaml(item[1]));
205
+ }
206
+ return patterns.filter((entry) => entry.length > 0);
207
+ }
208
+
209
+ // Expand `{a,b}` alternatives, innermost first.
210
+ function expandBraces(pattern) {
211
+ const match = pattern.match(/\{([^{}]*)\}/);
212
+ if (!match) return [pattern];
213
+ return match[1]
214
+ .split(',')
215
+ .flatMap((alternative) =>
216
+ expandBraces(
217
+ pattern.slice(0, match.index) +
218
+ alternative +
219
+ pattern.slice(match.index + match[0].length),
220
+ ),
221
+ );
222
+ }
223
+
224
+ // Glob syntax evaluated here: `*`, `**`, `?`, braces (expanded first) and
225
+ // positive character classes. Extglobs, negated classes, escapes and
226
+ // unbalanced brackets are not, and never count as a non-match.
227
+ function unsupportedGlob(pattern) {
228
+ return (
229
+ /[+@!?*]\(/.test(pattern) ||
230
+ /\[[!^]/.test(pattern) ||
231
+ pattern.includes('\\') ||
232
+ /\[(?![^\]]*\])/.test(pattern) ||
233
+ /\[\]/.test(pattern)
234
+ );
235
+ }
236
+
237
+ function globToRegExp(pattern) {
238
+ const source = pattern
239
+ .split(/(\*\*\/|\*\*|\*|\?|\[[^\]]+\])/)
240
+ .map((part) =>
241
+ part === '**/'
242
+ ? '(?:.*/)?'
243
+ : part === '**'
244
+ ? '.*'
245
+ : part === '*'
246
+ ? '[^/]*'
247
+ : part === '?'
248
+ ? '[^/]'
249
+ : part.startsWith('[') && part.endsWith(']')
250
+ ? `(?!/)[${part.slice(1, -1).replace(/[\\\]]/g, '\\$&')}]`
251
+ : part.replace(/[.+^${}()|[\]\\]/g, '\\$&'),
252
+ )
253
+ .join('');
254
+ return new RegExp(`^${source}$`);
255
+ }
256
+
257
+ // pnpm finds members by globbing `<pattern>/package.json`, so a trailing
258
+ // globstar also matches the directory itself; negations exclude. Returns
259
+ // true or false, or `{ unsupported: pattern }` when a pattern whose result
260
+ // matters cannot be evaluated.
261
+ function workspaceIncludes(patterns, rel) {
262
+ const target = `${rel}/package.json`;
263
+ const evaluate = (pattern) => {
264
+ const expanded = expandBraces(
265
+ pattern.replace(/^\.\//, '').replace(/\/+$/, ''),
266
+ );
267
+ if (expanded.some(unsupportedGlob)) return { unsupported: pattern };
268
+ return expanded.some((glob) =>
269
+ globToRegExp(`${glob}/package.json`).test(target),
270
+ );
271
+ };
272
+ const any = (list) => {
273
+ let unknown = null;
274
+ for (const pattern of list) {
275
+ const result = evaluate(pattern);
276
+ if (result === true) return true;
277
+ if (result !== false && unknown === null) unknown = result;
278
+ }
279
+ return unknown ?? false;
280
+ };
281
+ const included = any(patterns.filter((pattern) => !pattern.startsWith('!')));
282
+ if (included !== true) return included;
283
+ const excluded = any(
284
+ patterns
285
+ .filter((pattern) => pattern.startsWith('!'))
286
+ .map((pattern) => pattern.slice(1)),
287
+ );
288
+ return excluded === true ? false : excluded === false ? true : excluded;
289
+ }
290
+
291
+ // The app's relation to the nearest pnpm workspace: its own root, a member of
292
+ // an ancestor workspace, standalone (the ancestor's `packages` globs exclude
293
+ // it, so installs need --ignore-workspace), or undetermined when a pattern
294
+ // cannot be evaluated. Lockfile presence is not evidence: a member can keep
295
+ // its own lockfile with shared-workspace-lockfile=false.
296
+ async function workspaceMembership(appPath) {
297
+ if (await exists(join(appPath, 'pnpm-workspace.yaml')))
298
+ return { root: appPath, membership: 'root', reason: null };
299
+ for (const directory of ancestors(dirname(appPath))) {
300
+ const file = join(directory, 'pnpm-workspace.yaml');
301
+ if (!(await exists(file))) continue;
302
+ const rel = relative(directory, appPath).split(sep).join('/');
303
+ const included = workspaceIncludes(
304
+ workspacePatterns(await readFile(file, 'utf8')),
305
+ rel,
306
+ );
307
+ if (typeof included === 'boolean')
308
+ return {
309
+ root: directory,
310
+ membership: included ? 'member' : 'standalone',
311
+ reason: null,
312
+ };
313
+ return {
314
+ root: directory,
315
+ membership: 'undetermined',
316
+ reason: `pnpm-workspace.yaml pattern "${included.unsupported}" uses glob syntax this helper does not evaluate; workspace membership is unknown, so the command omits --ignore-workspace. Confirm membership with pnpm -r ls before running it.`,
317
+ };
318
+ }
319
+ return { root: null, membership: null, reason: null };
320
+ }
321
+
35
322
  try {
36
323
  const { values } = parseArgs({
37
324
  options: {
@@ -41,14 +328,46 @@ try {
41
328
  },
42
329
  });
43
330
  if (!values.app) throw new Error('Required: --app <docs-app-directory>.');
331
+ const appPath = resolve(values.app);
332
+ const manifest = await readJson(join(appPath, 'package.json'));
333
+ if (manifest === null) {
334
+ process.stdout.write(
335
+ `${JSON.stringify(
336
+ {
337
+ versionsPath: null,
338
+ appPath,
339
+ applicable: false,
340
+ reason:
341
+ 'No package.json in the docs directory: Markdown docs have no app-package drift check.',
342
+ packages: [],
343
+ },
344
+ null,
345
+ 2,
346
+ )}\n`,
347
+ );
348
+ process.exit(0);
349
+ }
44
350
  const versionsPath = resolve(
45
351
  values.versions ?? (await versionsForCli(values.cli)),
46
352
  );
47
353
  const versions = JSON.parse(await readFile(versionsPath, 'utf8'));
48
- const appPath = resolve(values.app);
49
- const manifest = JSON.parse(
50
- await readFile(join(appPath, 'package.json'), 'utf8'),
354
+ const packageManager = await packageManagerFor(appPath);
355
+ const pinned = packageManager?.match(
356
+ /^pnpm@(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)(?:\+.*)?$/,
51
357
  );
358
+ // Run the repository's pinned pnpm rather than whatever global pnpm is on
359
+ // PATH: a different major can rewrite workspace settings or reject the store.
360
+ // npx ships with npm on every Node line; Corepack is absent from Node 25+.
361
+ const pnpm = pinned ? `npx --yes pnpm@${pinned[1]}` : 'pnpm';
362
+ const otherManager =
363
+ packageManager && !packageManager.startsWith('pnpm@')
364
+ ? packageManager
365
+ : null;
366
+ // A nested app the ancestor workspace does not include must be installed
367
+ // with --ignore-workspace; an undetermined result never adds the flag.
368
+ const workspace = await workspaceMembership(appPath);
369
+ const ignoreWorkspace =
370
+ workspace.membership === 'standalone' ? ' --ignore-workspace' : '';
52
371
  const packages = [];
53
372
  for (const section of [
54
373
  'dependencies',
@@ -58,6 +377,8 @@ try {
58
377
  for (const [name, declared] of Object.entries(manifest[section] ?? {})) {
59
378
  if (
60
379
  ![
380
+ // The app-local CLI runs generate-index in predev/prebuild.
381
+ '@open-agent-toolkit/cli',
61
382
  '@open-agent-toolkit/docs-config',
62
383
  '@open-agent-toolkit/docs-theme',
63
384
  '@open-agent-toolkit/docs-transforms',
@@ -71,29 +392,22 @@ try {
71
392
  )
72
393
  throw new Error(`Missing/invalid bundled version for ${name}.`);
73
394
  // Report installed package bytes when available, not just a declared range.
74
- let installed = null;
75
- try {
76
- const installedManifest = JSON.parse(
77
- await readFile(
78
- join(appPath, 'node_modules', name, 'package.json'),
79
- 'utf8',
80
- ),
81
- );
82
- if (typeof installedManifest.version !== 'string')
83
- throw new Error(`Invalid installed version for ${name}.`);
84
- installed = installedManifest.version;
85
- } catch (error) {
86
- if (error.code !== 'ENOENT') throw error;
87
- }
395
+ const found = await installedManifest(appPath, name);
396
+ if (found !== null && typeof found.manifest.version !== 'string')
397
+ throw new Error(`Invalid installed version for ${name}.`);
398
+ const installed = found?.manifest.version ?? null;
88
399
  // Only stable numeric releases are orderable here; prereleases and other
89
400
  // package-manager version forms need manual verification, never an upgrade.
90
401
  const stable = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
91
402
  let status = 'unverified';
92
- if (
93
- installed !== null &&
94
- stable.test(installed) &&
95
- stable.test(bundled)
96
- ) {
403
+ let reason = null;
404
+ if (installed === null)
405
+ reason = `not installed: no node_modules/${name} found from the app or its ancestors; run the app install first`;
406
+ else if (!stable.test(installed))
407
+ reason = `installed version ${installed} is not a stable release; verify it manually`;
408
+ else if (!stable.test(bundled))
409
+ reason = `bundled version ${bundled} is a prerelease; verify it manually`;
410
+ else {
97
411
  const left = installed.split('.').map(BigInt);
98
412
  const right = bundled.split('.').map(BigInt);
99
413
  const differing = left.findIndex(
@@ -106,22 +420,26 @@ try {
106
420
  ? 'drift'
107
421
  : 'ahead';
108
422
  }
423
+ let upgradeCommand = null;
424
+ if (status === 'drift' && otherManager)
425
+ reason = `packageManager is ${otherManager}; translate the upgrade to its add command, preserving the dependency section and exact version`;
426
+ else if (status === 'drift')
427
+ upgradeCommand = `${pnpm} --dir ${shellQuote(appPath)} add${ignoreWorkspace}${section === 'devDependencies' ? ' --save-dev' : section === 'optionalDependencies' ? ' --save-optional' : ''} ${name}@${bundled}`;
109
428
  packages.push({
110
429
  name,
111
430
  section,
112
431
  declared,
113
432
  installed,
433
+ installedPath: found?.path ?? null,
114
434
  bundled,
115
435
  status,
116
- upgradeCommand:
117
- status === 'drift' || status === 'current'
118
- ? `pnpm --dir ${shellQuote(appPath)} add${section === 'devDependencies' ? ' --save-dev' : section === 'optionalDependencies' ? ' --save-optional' : ''} ${name}@${bundled}`
119
- : null,
436
+ reason,
437
+ upgradeCommand,
120
438
  });
121
439
  }
122
440
  }
123
441
  process.stdout.write(
124
- `${JSON.stringify({ versionsPath, appPath, packages }, null, 2)}\n`,
442
+ `${JSON.stringify({ versionsPath, appPath, applicable: true, packageManager, workspace, packages }, null, 2)}\n`,
125
443
  );
126
444
  } catch (error) {
127
445
  process.stderr.write(`${error.message}\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.6'
8
+ version: '1.4.8'
9
9
  ---
10
10
 
11
11
  # Docs Apply
@@ -276,6 +276,9 @@ a conflict with config becomes `ask_user`, never a config-driven rewrite.
276
276
  Mirror the accepted record using shared repo config only:
277
277
  `oat config set documentation.ia '<JSON>'`, with exactly `{preset, decision,
278
278
  tracks?: [{path, principle}], verification?: 'triad'|'agent-only'|'none'}`.
279
+ Write `preset` as the canonical ID (`product-engineering-qa`,
280
+ `consumer-maintainer`, `domain-engineering`, `task-type`, `toolkit-cli` or
281
+ `flat-small`) of the approved label.
279
282
  `decision` is repo-relative; preserve guidance and unrelated config. For a
280
283
  framework surface, separately record the operator's approved sidebar owner via
281
284
  `oat config set documentation.navOwner nav-sync` or `hand-authored`. Missing
@@ -315,21 +318,28 @@ after each block, preserving residual findings instead of claiming a clean run.
315
318
  #### Individually approved tooling update
316
319
 
317
320
  A `tooling-update` recommendation has `approval: explicit`. Even with individual
318
- approval, its out-of-Markdown allowance is only these three operations:
319
-
320
- 1. Bump the docs app's existing `@open-agent-toolkit/docs-*` dependencies to the
321
- bundled versions using the artifact's exact upgrade command (preserve dependency
322
- section and package manager; include its resulting lockfile only). Never downgrade
323
- an installed version: `ahead` or `unverified` requires CLI selection/update or
324
- manual verification before re-analysis, not a docs-package tooling update.
325
- 2. Run `oat docs migrate --docs-dir <authored-root> --apply` only for its currently
321
+ approval, its out-of-Markdown allowance is only these four operations:
322
+
323
+ 1. Bump the docs app's existing `@open-agent-toolkit/docs-*` dependencies, and the
324
+ app's own `@open-agent-toolkit/cli` dependency when the app declares it, to the
325
+ bundled versions using the artifact's exact upgrade commands (preserve each
326
+ dependency section and the package manager; include the resulting lockfile only).
327
+ Run the pinned package-manager form the command gives; a global pnpm of another
328
+ major can rewrite workspace settings and break the store link.
329
+ Never downgrade an installed version: `ahead` or `unverified` requires CLI
330
+ selection/update or manual verification before re-analysis, not a tooling update.
331
+ 2. After a CLI bump, regenerate the app's generated manifest (`index.md`) with that
332
+ upgraded app-local CLI, using the `oat docs generate-index` invocation from the
333
+ app's existing `predev`/`prebuild` scripts; inspect the diff.
334
+ 3. Run `oat docs migrate --docs-dir <authored-root> --apply` only for its currently
326
335
  supported admonition conversions and injected frontmatter; inspect the diff.
327
- 3. Run the docs build verifier from the app's existing scripts.
336
+ 4. Run the docs build verifier from the app's existing scripts.
328
337
 
329
338
  Scaffold changes the CLI cannot make (app config, routes, package scripts) are
330
339
  `manual`: report the required change and ID without editing those files. This
331
- allowance does not permit application dependencies, host settings, arbitrary
332
- migrations or an app-shell rebuild. Other out-of-scope prohibitions remain.
340
+ allowance does not permit other application dependencies, framework upgrades,
341
+ host settings, arbitrary migrations or an app-shell rebuild. Other out-of-scope
342
+ prohibitions remain.
333
343
 
334
344
  When approved actions involve docs app creation or nav updates:
335
345
 
@@ -85,8 +85,9 @@ blocked pending a fresh analysis rather than guessed.
85
85
 
86
86
  - Record IA: {adoption.state from target pjm doctor; decision command/path;
87
87
  framework AGENTS or Markdown contributing section; shared mirror JSON}
88
- - Tooling update: {individually approved ID; exact docs-app docs-\* upgrade
89
- command; supported migrate conversions; existing build verifier}
88
+ - Tooling update: {individually approved ID; exact docs-app docs-\* and declared
89
+ app-local cli upgrade commands; manifest regeneration with that cli; supported
90
+ migrate conversions; existing build verifier}
90
91
  - Unsupported app config/routes/scripts: {manual required changes; no edits}
91
92
 
92
93
  ## Summary of Actions
@@ -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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"}