@open-agent-toolkit/cli 0.3.29 → 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 +2 -0
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/docs-tooling/commands.md +64 -1
- 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/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/dist/commands/docs/index.d.ts.map +1 -1
- package/dist/commands/docs/index.js +2 -0
- 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/package.json +3 -3
package/README.md
CHANGED
|
@@ -51,6 +51,8 @@ Fumadocs static exports include `llms.txt`, `llms-full.txt` and `llms/<page-slug
|
|
|
51
51
|
|
|
52
52
|
`oat docs check [--target-dir <dir>] [--rule <id>...] [--json]` performs read-only reader, navigation, contributor-command and Mermaid/SVG checks without a site build. Errors exit 1; warnings exit 0. Configure validated severities, numeric thresholds and reason-bearing exceptions under `documentation.check`. Mermaid syntax parsing lazily uses a real DOM with strict sanitization and no script/resource execution; Node 22.17 remains the minimum. See [checker rules and configuration](../../apps/oat-docs/docs/docs-tooling/check.md).
|
|
53
53
|
|
|
54
|
+
`oat docs literals [--target-dir <dir>] --page <content-relative-reader.md> --source-root <repo-relative-dir> [--source-exclude <pattern>] --json` supplies read-only inline-code occurrence candidates for a matching triad IA mirror. Repeat each single-value selection flag as needed. Sources stay within narrow explicit implementation roots; searched/skipped evidence and first source physical lines are reported. Once-only strict HTML entity decoding and case-sensitive line-local substring matching do not establish runtime validity; analyze judges canonical relevance and authored IA acceptance. Completed not-found/not-applicable exits 0, input/config errors 1, unexpected failures 2. See [literal helper scope and limits](../../apps/oat-docs/docs/docs-tooling/commands.md#oat-docs-literals).
|
|
55
|
+
|
|
54
56
|
Fumadocs starters constrain `mdast-util-to-markdown` to 2.1.2 for the current upstream handler compatibility defect. New independent install roots get `pnpm-workspace.yaml`; workspace members get manual setup advice for the existing root YAML, with approval/conflict preservation in bootstrap. No member-local boundary or root dependency-policy merge is performed; `--no-root-patch` still controls build scripts only. Keep the effective policy and lockfile and verify actual resolution before building.
|
|
55
57
|
|
|
56
58
|
Framework starters expose `docs:check` and run it before build; MkDocs `test` is a real check. Bootstrap proposes approved PR CI edits with explicit generated-manifest freshness. Markdown needs neither an app build nor a default manifest.
|
|
@@ -13,7 +13,7 @@ or **MkDocs Material**.
|
|
|
13
13
|
|
|
14
14
|
- What it does: documents the docs-specific CLI surface for scaffolding apps, migrating markdown, generating Fumadocs app-root index manifests, and syncing MkDocs or Fumadocs navigation.
|
|
15
15
|
- When to use it: when you already know you are working on a docs surface and need the exact command-level behavior.
|
|
16
|
-
- Primary commands: `oat docs init`, `oat docs migrate`, `oat docs generate-index`, `oat docs nav sync`, `oat docs check`
|
|
16
|
+
- Primary commands: `oat docs init`, `oat docs migrate`, `oat docs generate-index`, `oat docs nav sync`, `oat docs check`, `oat docs literals`
|
|
17
17
|
|
|
18
18
|
## Command surface
|
|
19
19
|
|
|
@@ -24,6 +24,7 @@ or **MkDocs Material**.
|
|
|
24
24
|
| `oat docs generate-index` | Generate a manifest from Markdown files, outside authored content. |
|
|
25
25
|
| `oat docs nav sync` | Regenerate `mkdocs.yml` nav or Fumadocs `meta.json` from `index.md` maps. |
|
|
26
26
|
| `oat docs check` | Read-only reader, navigation, command and diagram checks; errors fail, warnings pass. |
|
|
27
|
+
| `oat docs literals` | Read-only occurrence candidates for explicitly selected Product/QA pages in a triad. |
|
|
27
28
|
| `oat docs analyze` | CLI entrypoint that points users to the `oat-docs-analyze` skill. |
|
|
28
29
|
| `oat docs apply` | CLI entrypoint that points users to the `oat-docs-apply` skill. |
|
|
29
30
|
|
|
@@ -315,6 +316,68 @@ Related reference:
|
|
|
315
316
|
|
|
316
317
|
- [`../reference/docs-index-contract.md`](../reference/docs-index-contract.md)
|
|
317
318
|
|
|
319
|
+
## `oat docs literals`
|
|
320
|
+
|
|
321
|
+
After `oat-docs-analyze` confirms the authored accepted IA and config mirror
|
|
322
|
+
agree on `verification: triad`, select Product/QA reader pages and narrow
|
|
323
|
+
canonical implementation directories:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
oat docs literals --target-dir manual \
|
|
327
|
+
--page experience/save.md --page verify/save.md \
|
|
328
|
+
--source-root src/ui --source-exclude src/ui/generated/ --json
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
`--target-dir` is optional and uses the same configured-root/app/content
|
|
332
|
+
resolution as check. `--page` and `--source-root` are required, repeatable
|
|
333
|
+
single-value flags. Pages are content-relative Markdown (`.md` or `.mdx`,
|
|
334
|
+
without evaluating JSX); roots are repo-relative directories, never the repo
|
|
335
|
+
root. Source roots must also use their canonical on-disk spelling (including case).
|
|
336
|
+
Pages must use their canonical on-disk spelling (including case) and be
|
|
337
|
+
readable readers within the real content tree, outside `nonReaderPaths`,
|
|
338
|
+
with no symlink components below the resolved content root
|
|
339
|
+
(including page files and directory aliases). Sources must remain within the
|
|
340
|
+
repository; nested symlinks are skipped, never traversed. Invalid/escaping selections, unreadable traversal
|
|
341
|
+
and an empty effective text inventory fail visibly. Select implementation
|
|
342
|
+
roots and explicit exclusions to omit docs, fixtures, generated output and
|
|
343
|
+
vendor code as evidence. The helper does not automatically exclude documentation
|
|
344
|
+
from selected source roots. A match to documentation itself is not canonical
|
|
345
|
+
implementation support; inspect the citation and judge its relevance.
|
|
346
|
+
|
|
347
|
+
`--source-exclude` is optional/repeatable, using the existing bounded POSIX
|
|
348
|
+
exclusion grammar in **repository** coordinates: segment `*`, whole-segment
|
|
349
|
+
`**`, trailing `/` for directories; other metacharacters are literal. Parent
|
|
350
|
+
segments, absolute patterns and backslashes are invalid. `documentation.excludes`
|
|
351
|
+
remains manifest-only; `nonReaderPaths` remains content-relative.
|
|
352
|
+
|
|
353
|
+
Only a matching mirror declaring triad enables extraction. Other overlays,
|
|
354
|
+
absent IA or an unrelated explicit target return `not-applicable` with reason
|
|
355
|
+
and empty candidates before selected pages/sources are read. This gate does
|
|
356
|
+
not establish authored acceptance; the skill judges that separately.
|
|
357
|
+
|
|
358
|
+
JSON completion has `status: ok`, `scope: {contentRoot, pages, sourceRoots,
|
|
359
|
+
sourceExcludes}`, `searched` source paths, `skipped: [{path, reason}]`, and
|
|
360
|
+
`literals: [{path, line, literal, normalized, status, source?}]`. Candidate
|
|
361
|
+
status is `found` or `not-found`; source is `{path, line}`. Docs locations are
|
|
362
|
+
content-relative; contentRoot/source scope is repo-relative POSIX. Duplicate
|
|
363
|
+
pages/overlapping inventories are deduplicated. Page order and source file
|
|
364
|
+
order are lexical, then physical line order; the first source occurrence is
|
|
365
|
+
reported. Skipped reasons include symlink, binary, non-UTF8 and non-regular.
|
|
366
|
+
No source snippets, severity or runtime verdict are emitted.
|
|
367
|
+
|
|
368
|
+
Extraction uses Markdown AST inline code and ignores fenced blocks. Matching
|
|
369
|
+
applies one strict HTML entity decode to each value and each physical source
|
|
370
|
+
line, then a case-sensitive substring search. CommonMark may normalize multiline
|
|
371
|
+
spans; source matching stays per physical line. There is no whitespace/Unicode
|
|
372
|
+
folding, JS escape decoding, interpolation, i18n loading or runtime evaluation.
|
|
373
|
+
A comment, dead code or longer text can match. Inspect canonical relevance;
|
|
374
|
+
`not-found` starts as unverified, and explained concepts require judgment.
|
|
375
|
+
|
|
376
|
+
Exit 0 means completed evidence, including not-found/not-applicable; exit 1 is
|
|
377
|
+
an actionable input/config error; exit 2 is an unexpected runtime failure.
|
|
378
|
+
Global `--json`/`--cwd` work as usual. This helper is separate from check's G5
|
|
379
|
+
rules, and `oat docs analyze` remains a guidance entrypoint.
|
|
380
|
+
|
|
318
381
|
## `oat docs analyze` and `oat docs apply`
|
|
319
382
|
|
|
320
383
|
These CLI commands intentionally reserve the docs workflow surface without
|
|
@@ -508,6 +508,22 @@ consumer and agent coverage. A top-level misroute is High when it blocks normal
|
|
|
508
508
|
first success/verification, Medium when it causes material detours; cosmetic
|
|
509
509
|
organization stays Low. Missing IA/owner raises `ask_user`.
|
|
510
510
|
|
|
511
|
+
When the authored accepted IA and its mirror agree on triad verification,
|
|
512
|
+
analyze also checks six source-related concerns: mapped feature slug parity,
|
|
513
|
+
real peer links/anchors (including QA Scope pairing), quoted literals versus
|
|
514
|
+
explained concepts, exact membership in the repository's own test-ID registry,
|
|
515
|
+
scoped duplicate/contradictory scenarios, and raw Contents links to templates
|
|
516
|
+
even when nav excludes them. Roles come from the decision/local guidance,
|
|
517
|
+
including renamed tracks and hybrid Engineering; flat layouts may be not
|
|
518
|
+
applicable. Missing mapping/registry stays unverified / `ask_user`. Other
|
|
519
|
+
overlays continue ordinary analysis unchanged.
|
|
520
|
+
|
|
521
|
+
The [literal occurrence helper](commands.md#oat-docs-literals) supplies bounded
|
|
522
|
+
text candidates for selected Product/QA pages. A found substring requires
|
|
523
|
+
canonical-source judgment; not-found is initially unverified. It cannot prove
|
|
524
|
+
runtime behavior, registry membership or scenario correctness. Accepted IA,
|
|
525
|
+
source citations and existing recommendation approval classes still govern.
|
|
526
|
+
|
|
511
527
|
For framework apps, offline drift compares installed `@open-agent-toolkit/docs-*` packages to the
|
|
512
528
|
running CLI's bundled `public-package-versions.json`, never registry latest.
|
|
513
529
|
Missing installations are unverified. The recommendation includes the exact
|
|
@@ -80,6 +80,8 @@ Lifecycle](../workflows/backlog-and-planning/backlog-lifecycle.md).
|
|
|
80
80
|
|
|
81
81
|
`oat docs check [--target-dir <dir>] [--rule <id>...] [--json]` validates reader structure, links, navigation, contributor commands and diagrams without a site build. Errors exit 1; warning-only exits 0. See [Check Documentation](../docs-tooling/check.md) for rules/config and JSON.
|
|
82
82
|
|
|
83
|
+
`oat docs literals --page <reader.md> --source-root <implementation-dir> [--target-dir <dir>] [--source-exclude <pattern>] --json` reports bounded inline-code occurrence candidates for triad IA mirrors. Pages and roots are repeatable single-value flags in content/repository coordinates respectively. Found candidates require canonical-source judgment. See [literal helper scope, JSON and limits](../docs-tooling/commands.md#oat-docs-literals).
|
|
84
|
+
|
|
83
85
|
## Command Groups
|
|
84
86
|
|
|
85
87
|
| Command group | What it covers | Go deeper |
|
|
@@ -4,9 +4,9 @@ description: Run when you need to evaluate documentation structure, navigation,
|
|
|
4
4
|
argument-hint: '[target] [--ia] [--ia-guidance <path|url>]'
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
user-invocable: true
|
|
7
|
-
allowed-tools: Read, Write, Bash(git:*), Bash(oat config:*), Bash(oat docs nav sync --check:*), Bash(oat docs check:*), Bash(pnpm:*), Bash(bash:*), Bash(jq:*), Bash(node:*), 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(oat docs check:*), Bash(oat docs literals:*), Bash(pnpm:*), Bash(bash:*), Bash(jq:*), Bash(node:*), Bash(mkdir:*), Bash(date:*), Bash(echo:*), Bash(cd:*), Bash(pwd:*), Glob, Grep, AskUserQuestion, Task
|
|
8
8
|
metadata:
|
|
9
|
-
version: '1.7.
|
|
9
|
+
version: '1.7.4'
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Docs Analysis
|
|
@@ -336,7 +336,8 @@ app's docs avoid merely mirroring implementation directories. Review coverage
|
|
|
336
336
|
only for declared readers: Product features/journeys/screens/states; QA scenario
|
|
337
337
|
tables with seeds and automation references; consumer first-success/task guides;
|
|
338
338
|
agent entrypoints, canonical sources and verification commands. Do not demand
|
|
339
|
-
these tracks from every repository
|
|
339
|
+
these tracks from every repository. For an accepted triad, also perform the
|
|
340
|
+
conditional source assessments below.
|
|
340
341
|
|
|
341
342
|
Top-level IA misroutes a declared audience: `High` when the reader cannot find
|
|
342
343
|
a normal first-success or required verification path; `Medium` when that path
|
|
@@ -389,6 +390,91 @@ Evidence standard for this step:
|
|
|
389
390
|
- If multiple repo files are needed to verify a claim, cite all relevant sources.
|
|
390
391
|
- If the canonical source is ambiguous, mark the claim `unverified` rather than guessing.
|
|
391
392
|
|
|
393
|
+
### Conditional triad source assessments (P24)
|
|
394
|
+
|
|
395
|
+
Run these six assessments only after the authored **accepted** IA decision and
|
|
396
|
+
local Information architecture section agree with the mirror's
|
|
397
|
+
`verification: triad`. Cite that agreement first. A mirror alone does not prove
|
|
398
|
+
acceptance. For absent, `agent-only`, or `none` overlays, record not applicable
|
|
399
|
+
and continue ordinary analysis unchanged. Missing/broken authored acceptance or
|
|
400
|
+
a conflicting mirror blocks these assessments with `unverified` / `ask_user`;
|
|
401
|
+
it does not block ordinary analysis or justify choosing an IA.
|
|
402
|
+
|
|
403
|
+
Map Product, QA and Engineering feature subsets from the accepted decision,
|
|
404
|
+
tracks/principles and local guidance, citing each mapping. Do not infer roles
|
|
405
|
+
from fixed folder names or tracks array order. Engineering may mix domain
|
|
406
|
+
contracts with feature pages: compare only its mapped feature subset. A grouped
|
|
407
|
+
flat IA may have no per-feature triad; explain not applicable rather than invent
|
|
408
|
+
folders. An unresolved mapping stays `unverified` / `ask_user` without new config.
|
|
409
|
+
|
|
410
|
+
1. **Slug parity.** Compare relative feature/journey keys in the mapped subsets.
|
|
411
|
+
Exclude indexes, support pages, templates and Engineering domain contracts.
|
|
412
|
+
Cite missing/extra peers and the declared mapping before recommending repair.
|
|
413
|
+
2. **Paired documentation.** Inspect each member's actual peer links, resolving
|
|
414
|
+
relative paths and anchors within the repository. Accept case-insensitive
|
|
415
|
+
Paired Documentation headings and QA's canonical Scope links when they point
|
|
416
|
+
to the appropriate Product/Engineering peers. A heading alone or an unrelated
|
|
417
|
+
resolving link is insufficient. Cite both link and target/anchor; unresolved
|
|
418
|
+
or wrong-peer links become evidence-backed findings.
|
|
419
|
+
3. **Quoted literals and concepts.** Select Product/QA reader Markdown and narrow
|
|
420
|
+
canonical implementation directories from cited source references/local
|
|
421
|
+
guidance, then invoke the read-only helper (repeat one value per flag):
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
oat docs literals --target-dir <resolved-target> \
|
|
425
|
+
--page <product-page> --page <qa-page> \
|
|
426
|
+
--source-root <implementation-dir> \
|
|
427
|
+
--source-exclude <generated-or-fixture-pattern> --json
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Pages are content-relative; roots and exclusions are repository-relative.
|
|
431
|
+
Never scan the repository root, dependencies, home or external sources.
|
|
432
|
+
Select implementation roots and exclusions that omit docs, templates,
|
|
433
|
+
generated/vendor output and example/test fixtures as evidence. The helper
|
|
434
|
+
does not automatically exclude documentation from selected source roots;
|
|
435
|
+
a match to documentation itself is not canonical implementation support.
|
|
436
|
+
Inspect the returned scope, searched files and skipped symlink/binary/non-UTF8
|
|
437
|
+
inputs; incomplete traversal or invalid selections fail visibly. Missing
|
|
438
|
+
canonical sources remain unverified; do not broaden scanning to manufacture
|
|
439
|
+
matches.
|
|
440
|
+
|
|
441
|
+
The helper extracts AST inline code, ignores fences, and performs exactly
|
|
442
|
+
one strict HTML entity decode per value and physical source line, followed
|
|
443
|
+
by case-sensitive substring matching. It reports the first lexical source
|
|
444
|
+
file/physical line, without snippets or a runtime verdict. CommonMark can
|
|
445
|
+
normalize multiline spans; source matching stays per physical line. It does
|
|
446
|
+
not fold whitespace/Unicode, decode JS escapes, evaluate interpolation or
|
|
447
|
+
load i18n/runtime values. A found substring can be in a comment, dead code,
|
|
448
|
+
fixture or longer text: read the citation and judge canonical relevance.
|
|
449
|
+
`not-found` is initially **unverified**, never automatic contradiction.
|
|
450
|
+
Require a differing canonical value before judging contradicted. Distinguish
|
|
451
|
+
intentionally explained concepts from UI literals; prose concepts need no
|
|
452
|
+
occurrence, while ambiguous backticked concepts require clarification or a
|
|
453
|
+
cited conceptual explanation. Exit 0 means completed candidates (including
|
|
454
|
+
not-found/not-applicable), not verified documentation.
|
|
455
|
+
|
|
456
|
+
4. **Test-ID registry membership.** Locate the repository's actual canonical
|
|
457
|
+
test-ID registry and read its real format. Check exact member equality,
|
|
458
|
+
never substring occurrence in arbitrary source. Cite registry and docs.
|
|
459
|
+
Missing/ambiguous registry stays `unverified` / `ask_user`; do not invent a
|
|
460
|
+
registry path/schema or treat helper matches as membership proof.
|
|
461
|
+
5. **Scoped scenario candidates.** Inspect QA tables for duplicate IDs and the
|
|
462
|
+
same scoped Given + When with different Then outcomes. Compare feature,
|
|
463
|
+
seed, platform and configuration preconditions before judging contradiction;
|
|
464
|
+
meaningful differences can explain the result. Cite both rows and scope.
|
|
465
|
+
Ambiguous scope stays unverified. This is judgment, not a scenario engine.
|
|
466
|
+
6. **Templates in authored Contents.** Read raw authored `## Contents` links
|
|
467
|
+
before applying reader/nav exclusions. Flag links that expose drafting
|
|
468
|
+
templates as reader destinations even when `nonReaderPaths` makes nav/check
|
|
469
|
+
skip them; cite the map entry and template purpose/local declaration. Do not
|
|
470
|
+
infer safety from a clean generated nav or checker result.
|
|
471
|
+
|
|
472
|
+
Record applicability, mappings, docs/source citations, candidates and judgments
|
|
473
|
+
in the existing artifact's Accuracy Verification section. Use the existing
|
|
474
|
+
severity and recommendation `approval: explicit | default` classes; missing
|
|
475
|
+
mapping/registry evidence is not permission to add a schema or implementation.
|
|
476
|
+
No P24 `oat docs check` rule is added, and its G5 JSON/rule IDs are unchanged.
|
|
477
|
+
|
|
392
478
|
### Step 5: Analyze Content Coverage Opportunities
|
|
393
479
|
|
|
394
480
|
Add a coverage-gap pass after accuracy verification.
|
|
@@ -247,6 +247,29 @@ runtime-only behavior here.
|
|
|
247
247
|
|
|
248
248
|
{Or: "No repo-checkable substantive claims required accuracy verification."}
|
|
249
249
|
|
|
250
|
+
### Conditional triad source assessments (P24)
|
|
251
|
+
|
|
252
|
+
- Gate: {accepted authored IA + local section citations and mirror agreement;
|
|
253
|
+
non-triad: not applicable; missing/conflict: unverified / ask_user}
|
|
254
|
+
- Role/subset mapping: {Product, QA, Engineering feature roots and citations;
|
|
255
|
+
hybrid domain exclusions; flat applicability; never folder names/array order}
|
|
256
|
+
- Literal helper: {exact invocation; scope, searched files and skipped reasons;
|
|
257
|
+
occurrence candidates only, not a runtime verdict}
|
|
258
|
+
|
|
259
|
+
| Assessment | Docs / canonical evidence | Candidate and judgment |
|
|
260
|
+
| -------------------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
261
|
+
| Slug parity | {mapped feature keys and missing/extra peers} | {verdict or unverified / not applicable} |
|
|
262
|
+
| Paired documentation | {peer links + resolved target anchors; QA Scope accepted} | {correct peers, not just any resolving link} |
|
|
263
|
+
| Quoted literals / concepts | {helper path:line + canonical source / conceptual explanation} | {found requires relevance judgment; not-found initially unverified} |
|
|
264
|
+
| Test-ID registry | {actual registry path:line + exact member} | {membership; absent registry unverified / ask_user} |
|
|
265
|
+
| Scoped scenarios | {both rows + feature/seed/platform/config scope} | {duplicate ID / same Given+When with differing Then candidate; explained or unresolved} |
|
|
266
|
+
| Raw authored Contents | {map entry + template purpose / nonReaderPaths} | {flag reader links to templates even when nav excludes them} |
|
|
267
|
+
|
|
268
|
+
Keep one strict HTML entity decode per side and physical-source-line matching
|
|
269
|
+
limits visible. No JS/i18n evaluation, runtime claim, invented mapping/registry,
|
|
270
|
+
or automatic contradiction from absence. Recommendations retain existing
|
|
271
|
+
approval classes and docs/source citations.
|
|
272
|
+
|
|
250
273
|
## Coverage Review by Surface
|
|
251
274
|
|
|
252
275
|
Summarize which documentable surfaces were proven by repo evidence and how well
|
|
@@ -55,6 +55,24 @@ Use this checklist when evaluating a docs surface.
|
|
|
55
55
|
- Referenced paths exist.
|
|
56
56
|
- Tooling/setup instructions are current.
|
|
57
57
|
|
|
58
|
+
## Conditional triad source assessments (P24)
|
|
59
|
+
|
|
60
|
+
- Authored accepted IA and local section agree with the mirror's triad overlay;
|
|
61
|
+
other overlays are not applicable, missing/conflicting evidence unverified / ask_user.
|
|
62
|
+
- Roles and feature subsets come from cited decisions/local guidance, including
|
|
63
|
+
renamed tracks, hybrid Engineering and flat applicability; no folder/order inference.
|
|
64
|
+
- Slug parity compares only mapped feature keys, excluding support/domain pages.
|
|
65
|
+
- Peer links resolve to the correct member and anchor; QA Scope links count.
|
|
66
|
+
- Product/QA literals use `oat docs literals` with explicit pages, narrow source
|
|
67
|
+
roots and source exclusions. Scope, searched files and skipped reasons are reviewed.
|
|
68
|
+
- Once-decoded, case-sensitive physical-line occurrences receive canonical-source
|
|
69
|
+
judgment; not-found remains unverified and explained concepts are distinguished.
|
|
70
|
+
- Test IDs use exact membership in the actual registry; absent registry stays unverified.
|
|
71
|
+
- Duplicate IDs and same scoped Given+When/different Then candidates are judged
|
|
72
|
+
with seed/platform/configuration evidence, never automatically contradicted.
|
|
73
|
+
- Raw authored Contents links to templates are flagged despite reader/nav exclusions.
|
|
74
|
+
- Existing severity, citations and recommendation approval classes are preserved.
|
|
75
|
+
|
|
58
76
|
## Discoverability
|
|
59
77
|
|
|
60
78
|
- Important pages are reachable from a parent `index.md` or site nav.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/docs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/docs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,iBAAiB,IAAI,OAAO,CAW3C"}
|
|
@@ -4,12 +4,14 @@ import { createDocsApplyCommand } from './apply.js';
|
|
|
4
4
|
import { createDocsCheckCommand } from './check/check.js';
|
|
5
5
|
import { createDocsGenerateIndexCommand } from './index-generate/index.js';
|
|
6
6
|
import { createDocsInitCommand } from './init/index.js';
|
|
7
|
+
import { createDocsLiteralsCommand } from './literals/literals.js';
|
|
7
8
|
import { createDocsMigrateCommand } from './migrate/index.js';
|
|
8
9
|
import { createDocsNavCommand } from './nav/index.js';
|
|
9
10
|
export function createDocsCommand() {
|
|
10
11
|
return new Command('docs')
|
|
11
12
|
.description('OAT documentation bootstrap and maintenance commands')
|
|
12
13
|
.addCommand(createDocsCheckCommand())
|
|
14
|
+
.addCommand(createDocsLiteralsCommand())
|
|
13
15
|
.addCommand(createDocsAnalyzeCommand())
|
|
14
16
|
.addCommand(createDocsApplyCommand())
|
|
15
17
|
.addCommand(createDocsGenerateIndexCommand())
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare class LiteralInputError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export interface LiteralOptions {
|
|
4
|
+
cwd: string;
|
|
5
|
+
targetDir?: string;
|
|
6
|
+
page: string[];
|
|
7
|
+
sourceRoot: string[];
|
|
8
|
+
sourceExclude: string[];
|
|
9
|
+
}
|
|
10
|
+
interface Candidate {
|
|
11
|
+
path: string;
|
|
12
|
+
line: number;
|
|
13
|
+
literal: string;
|
|
14
|
+
normalized: string;
|
|
15
|
+
status: 'found' | 'not-found';
|
|
16
|
+
source?: {
|
|
17
|
+
path: string;
|
|
18
|
+
line: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface LiteralResult {
|
|
22
|
+
status: 'ok' | 'not-applicable';
|
|
23
|
+
reason?: string;
|
|
24
|
+
scope: {
|
|
25
|
+
contentRoot: string;
|
|
26
|
+
pages: string[];
|
|
27
|
+
sourceRoots: string[];
|
|
28
|
+
sourceExcludes: string[];
|
|
29
|
+
};
|
|
30
|
+
searched: string[];
|
|
31
|
+
skipped: {
|
|
32
|
+
path: string;
|
|
33
|
+
reason: 'symlink' | 'binary' | 'non-utf8' | 'non-regular';
|
|
34
|
+
}[];
|
|
35
|
+
literals: Candidate[];
|
|
36
|
+
}
|
|
37
|
+
export declare function collectLiteralEvidence(options: LiteralOptions): Promise<LiteralResult>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/literals/evidence.ts"],"names":[],"mappings":"AAgBA,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AACD,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,WAAW,CAAC;IAC9B,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AACD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,GAAG,gBAAgB,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;KAC3D,EAAE,CAAC;IACJ,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAkDD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA6MxB"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { lstat, readFile, readdir, realpath, stat } from 'node:fs/promises';
|
|
2
|
+
import { join, relative, resolve } from 'node:path';
|
|
3
|
+
import { containedFile, inside, posix, resolveCheckTarget, } from '../../docs/check/files.js';
|
|
4
|
+
import { parsePage } from '../../docs/check/markdown.js';
|
|
5
|
+
import { createExclusionMatcher, isExcludedPath, } from '../../docs/shared/exclusions.js';
|
|
6
|
+
import { decodeHTMLStrict } from 'entities';
|
|
7
|
+
export class LiteralInputError extends Error {
|
|
8
|
+
}
|
|
9
|
+
function inputPath(value, label, pattern = false) {
|
|
10
|
+
const path = value.trim().replace(/^\.\//, '');
|
|
11
|
+
const parts = path.replace(/\/$/, '').split('/');
|
|
12
|
+
if (!path ||
|
|
13
|
+
path.startsWith('/') ||
|
|
14
|
+
/^[A-Za-z]:/.test(path) ||
|
|
15
|
+
path.includes('\\') ||
|
|
16
|
+
[...path].some((c) => c.charCodeAt(0) < 32) ||
|
|
17
|
+
parts.some((p) => !p || p === '.' || p === '..') ||
|
|
18
|
+
(!pattern && path.includes('*')))
|
|
19
|
+
throw new LiteralInputError(`${label} must be a non-empty relative POSIX ${pattern ? 'pattern' : 'path'} without parent segments.`);
|
|
20
|
+
return pattern ? path : path.replace(/\/$/, '');
|
|
21
|
+
}
|
|
22
|
+
const unique = (values) => [...new Set(values)].sort();
|
|
23
|
+
async function selected(label, operation) {
|
|
24
|
+
try {
|
|
25
|
+
return await operation();
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (['ENOENT', 'ENOTDIR', 'EACCES', 'EPERM', 'ELOOP', 'EISDIR'].includes(error.code ?? ''))
|
|
29
|
+
throw new LiteralInputError(`Cannot read ${label}; check that it exists and is readable.`);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function text(bytes) {
|
|
34
|
+
if (bytes.includes(0))
|
|
35
|
+
return { reason: 'binary' };
|
|
36
|
+
try {
|
|
37
|
+
return { value: new TextDecoder('utf-8', { fatal: true }).decode(bytes) };
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { reason: 'non-utf8' };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function collectLiteralEvidence(options) {
|
|
44
|
+
const target = await selected('documentation target/config', async () => {
|
|
45
|
+
try {
|
|
46
|
+
return await resolveCheckTarget(options.cwd, options.targetDir);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (!error.code)
|
|
50
|
+
throw new LiteralInputError('Cannot resolve documentation target/config; check .oat/config.json, documentation.root, documentation.ia and --target-dir.');
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const result = {
|
|
55
|
+
status: 'not-applicable',
|
|
56
|
+
scope: {
|
|
57
|
+
contentRoot: posix(relative(target.repoRoot, target.contentRoot)) || '.',
|
|
58
|
+
pages: [],
|
|
59
|
+
sourceRoots: [],
|
|
60
|
+
sourceExcludes: [],
|
|
61
|
+
},
|
|
62
|
+
searched: [],
|
|
63
|
+
skipped: [],
|
|
64
|
+
literals: [],
|
|
65
|
+
};
|
|
66
|
+
// Config is only the extraction gate. The skill separately reconciles authored acceptance.
|
|
67
|
+
if (target.documentation.ia?.verification !== 'triad') {
|
|
68
|
+
result.reason =
|
|
69
|
+
'The matching documentation IA mirror does not declare verification: triad.';
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
if (!inside(target.repoRoot, target.contentRoot))
|
|
73
|
+
throw new LiteralInputError('Docs content root must be inside the repository.');
|
|
74
|
+
if (!options.page.length || !options.sourceRoot.length)
|
|
75
|
+
throw new LiteralInputError('Provide at least one --page and one narrow --source-root.');
|
|
76
|
+
const pages = unique(options.page.map((p) => inputPath(p, '--page')));
|
|
77
|
+
const roots = unique(options.sourceRoot.map((p) => inputPath(p, '--source-root')));
|
|
78
|
+
const excludes = unique(options.sourceExclude.map((p) => inputPath(p, '--source-exclude', true)));
|
|
79
|
+
result.scope = {
|
|
80
|
+
contentRoot: result.scope.contentRoot,
|
|
81
|
+
pages,
|
|
82
|
+
sourceRoots: roots,
|
|
83
|
+
sourceExcludes: excludes,
|
|
84
|
+
};
|
|
85
|
+
const matcher = createExclusionMatcher(excludes);
|
|
86
|
+
const sources = new Set();
|
|
87
|
+
const skipped = new Map();
|
|
88
|
+
// Inspect each component so an explicitly selected nested alias cannot bypass traversal policy.
|
|
89
|
+
const symlinkComponent = async (root, path) => {
|
|
90
|
+
const parts = path.split('/');
|
|
91
|
+
for (let i = 1; i <= parts.length; i++) {
|
|
92
|
+
if ((await lstat(join(root, ...parts.slice(0, i)))).isSymbolicLink())
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
97
|
+
const walk = async (path) => {
|
|
98
|
+
const absolute = join(target.repoRoot, path);
|
|
99
|
+
const info = await selected(`source ${path}`, () => lstat(absolute));
|
|
100
|
+
if (info.isSymbolicLink()) {
|
|
101
|
+
skipped.set(path, 'symlink');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (isExcludedPath(matcher, path, info.isDirectory()))
|
|
105
|
+
return;
|
|
106
|
+
if (info.isDirectory()) {
|
|
107
|
+
const entries = await selected(`source directory ${path}`, () => readdir(absolute));
|
|
108
|
+
for (const name of entries.sort())
|
|
109
|
+
await walk(`${path}/${name}`);
|
|
110
|
+
}
|
|
111
|
+
else if (info.isFile())
|
|
112
|
+
sources.add(path);
|
|
113
|
+
else
|
|
114
|
+
skipped.set(path, 'non-regular');
|
|
115
|
+
};
|
|
116
|
+
for (const path of roots) {
|
|
117
|
+
await selected(`source root ${path}`, async () => {
|
|
118
|
+
const absolute = resolve(target.repoRoot, path);
|
|
119
|
+
if (!inside(target.repoRoot, absolute) || absolute === target.repoRoot)
|
|
120
|
+
throw new LiteralInputError('Source roots must be narrow directories inside the repository, never the repository root.');
|
|
121
|
+
if (await symlinkComponent(target.repoRoot, path)) {
|
|
122
|
+
// An external alias is invalid input, even though it will never be read.
|
|
123
|
+
if (!inside(target.repoRoot, await realpath(absolute)))
|
|
124
|
+
throw new LiteralInputError(`Source root ${path} resolves outside the repository.`);
|
|
125
|
+
skipped.set(path, 'symlink');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!inside(target.repoRoot, await realpath(absolute)) ||
|
|
129
|
+
!(await stat(absolute)).isDirectory())
|
|
130
|
+
throw new LiteralInputError(`Source root ${path} must be a contained directory.`);
|
|
131
|
+
const canonical = posix(relative(await realpath(target.repoRoot), await realpath(absolute)));
|
|
132
|
+
if (canonical !== path)
|
|
133
|
+
throw new LiteralInputError(`Source root ${path} must use its canonical repo-relative spelling: ${canonical}.`);
|
|
134
|
+
await walk(path);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const sourceLines = [];
|
|
138
|
+
for (const path of [...sources].sort()) {
|
|
139
|
+
if (!(await containedFile(target.repoRoot, join(target.repoRoot, path))))
|
|
140
|
+
throw new LiteralInputError(`Source ${path} is no longer a contained file; rerun with stable inputs.`);
|
|
141
|
+
const decoded = text(await selected(`source ${path}`, () => readFile(join(target.repoRoot, path))));
|
|
142
|
+
if ('reason' in decoded)
|
|
143
|
+
skipped.set(path, decoded.reason);
|
|
144
|
+
else {
|
|
145
|
+
result.searched.push(path);
|
|
146
|
+
sourceLines.push({
|
|
147
|
+
path,
|
|
148
|
+
lines: decoded.value
|
|
149
|
+
.split(/\r\n|\n|\r/)
|
|
150
|
+
.map((line) => decodeHTMLStrict(line)),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!sourceLines.length)
|
|
155
|
+
throw new LiteralInputError(`No readable UTF-8 source files remain after exclusions; correct --source-root/--source-exclude. Skipped: ${[...skipped]
|
|
156
|
+
.sort()
|
|
157
|
+
.map(([path, reason]) => `${path} (${reason})`)
|
|
158
|
+
.join(', ') || 'none'}.`);
|
|
159
|
+
for (const path of pages) {
|
|
160
|
+
await selected(`page ${path}`, async () => {
|
|
161
|
+
const absolute = resolve(target.contentRoot, path);
|
|
162
|
+
if (!/\.mdx?$/.test(path) ||
|
|
163
|
+
isExcludedPath(target.matcher, path) ||
|
|
164
|
+
(await symlinkComponent(target.contentRoot, path)) ||
|
|
165
|
+
!(await containedFile(target.contentRoot, absolute)))
|
|
166
|
+
throw new LiteralInputError(`Page ${path} must be readable reader Markdown inside the content root, outside nonReaderPaths, with no symlink components below the content root.`);
|
|
167
|
+
const canonical = posix(relative(await realpath(target.contentRoot), await realpath(absolute)));
|
|
168
|
+
if (canonical !== path)
|
|
169
|
+
throw new LiteralInputError(`Page ${path} must use its canonical content-relative spelling: ${canonical}.`);
|
|
170
|
+
const decoded = text(await readFile(absolute));
|
|
171
|
+
if ('reason' in decoded)
|
|
172
|
+
throw new LiteralInputError(`Page ${path} must be UTF-8 Markdown text.`);
|
|
173
|
+
const page = parsePage(path, decoded.value);
|
|
174
|
+
if (page.frontmatterError)
|
|
175
|
+
throw new LiteralInputError(`Page ${path} has invalid YAML frontmatter.`);
|
|
176
|
+
for (const node of page.nodes) {
|
|
177
|
+
if (node.type !== 'inlineCode')
|
|
178
|
+
continue;
|
|
179
|
+
const literal = node.value ?? '';
|
|
180
|
+
const normalized = decodeHTMLStrict(literal);
|
|
181
|
+
const candidate = {
|
|
182
|
+
path,
|
|
183
|
+
line: node.position?.start.line ?? 1,
|
|
184
|
+
literal,
|
|
185
|
+
normalized,
|
|
186
|
+
status: 'not-found',
|
|
187
|
+
};
|
|
188
|
+
for (const source of sourceLines) {
|
|
189
|
+
const index = source.lines.findIndex((line) => line.includes(normalized));
|
|
190
|
+
if (index >= 0) {
|
|
191
|
+
candidate.status = 'found';
|
|
192
|
+
candidate.source = { path: source.path, line: index + 1 };
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
result.literals.push(candidate);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
result.status = 'ok';
|
|
201
|
+
result.skipped = [...skipped]
|
|
202
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
203
|
+
.map(([path, reason]) => ({ path, reason }));
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literals.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/literals/literals.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,yBAAyB,IAAI,OAAO,CAmEnD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { buildCommandContext } from '../../../app/command-context.js';
|
|
2
|
+
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { collectLiteralEvidence, LiteralInputError, } from './evidence.js';
|
|
5
|
+
export function createDocsLiteralsCommand() {
|
|
6
|
+
const append = (value, previous = []) => previous.concat(value);
|
|
7
|
+
return new Command('literals')
|
|
8
|
+
.allowExcessArguments(false)
|
|
9
|
+
.description('Read-only triad inline-code occurrence candidates; found does not prove runtime behavior')
|
|
10
|
+
.option('--target-dir <dir>', 'Docs app root or literal Markdown content root')
|
|
11
|
+
.requiredOption('--page <path>', 'Content-relative Product/QA reader Markdown (repeat one value per flag)', append)
|
|
12
|
+
.requiredOption('--source-root <dir>', 'Narrow repo-relative implementation directory, never repo root (repeatable)', append)
|
|
13
|
+
.option('--source-exclude <pattern>', 'Repo-relative bounded POSIX exclusion: segment *, whole-segment **, trailing / directories (repeatable)', append, [])
|
|
14
|
+
.addHelpText('after', '\nMatching: one strict HTML entity decode per inline-code value and physical source line; case-sensitive substring. CommonMark may normalize multiline code spans. No whitespace/Unicode folding, JS escapes, interpolation or runtime evaluation. Sources are searched only within explicit roots; inspect searched/skipped evidence. Exit 0: completed (including not-found/not-applicable); 1: input/config; 2: runtime failure.')
|
|
15
|
+
.action(async (options, command) => {
|
|
16
|
+
const context = buildCommandContext(readGlobalOptions(command));
|
|
17
|
+
try {
|
|
18
|
+
const result = await collectLiteralEvidence({
|
|
19
|
+
...options,
|
|
20
|
+
cwd: context.cwd,
|
|
21
|
+
});
|
|
22
|
+
process.exitCode = 0;
|
|
23
|
+
if (context.json)
|
|
24
|
+
context.logger.json(result);
|
|
25
|
+
else {
|
|
26
|
+
context.logger.info(result.status === 'not-applicable'
|
|
27
|
+
? `Not applicable: ${result.reason}`
|
|
28
|
+
: `Literal occurrence candidates: ${result.literals.filter((c) => c.status === 'found').length} found, ${result.literals.filter((c) => c.status === 'not-found').length} not-found. These require canonical-source judgment.`);
|
|
29
|
+
context.logger.info(JSON.stringify({
|
|
30
|
+
scope: result.scope,
|
|
31
|
+
searched: result.searched,
|
|
32
|
+
skipped: result.skipped,
|
|
33
|
+
literals: result.literals,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const input = error instanceof LiteralInputError;
|
|
39
|
+
process.exitCode = input ? 1 : 2;
|
|
40
|
+
// Resolver/config diagnostics can carry local absolute paths; keep evidence relative.
|
|
41
|
+
const message = error.message
|
|
42
|
+
.replaceAll(`${context.cwd}/`, '')
|
|
43
|
+
.replaceAll(context.cwd, '.');
|
|
44
|
+
if (context.json)
|
|
45
|
+
context.logger.json({ status: 'error', message });
|
|
46
|
+
else
|
|
47
|
+
context.logger.error(message);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.30",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open Agent Toolkit CLI",
|
|
6
6
|
"homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"unified": "11.0.5",
|
|
43
43
|
"yaml": "2.8.2",
|
|
44
44
|
"zod": "^3.25.76",
|
|
45
|
-
"@open-agent-toolkit/control-plane": "0.3.
|
|
46
|
-
"@open-agent-toolkit/docs-transforms": "0.3.
|
|
45
|
+
"@open-agent-toolkit/control-plane": "0.3.30",
|
|
46
|
+
"@open-agent-toolkit/docs-transforms": "0.3.30"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/jsdom": "28.0.3",
|