@open-agent-toolkit/cli 0.2.55 → 0.2.57
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/assets/agents/oat-phase-implementer.md +123 -9
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +12 -2
- package/assets/docs/docs-tooling/commands.md +36 -5
- package/assets/docs/reference/oat-directory-structure.md +56 -4
- package/assets/docs/workflows/projects/implementation-execution.md +5 -1
- package/assets/docs/workflows/skills/explainer-kit.md +8 -5
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/analyze/SKILL.md +18 -17
- package/assets/skills/oat-brainstorm/SKILL.md +2 -2
- package/assets/skills/oat-doctor/SKILL.md +49 -36
- package/assets/skills/oat-idea-summarize/SKILL.md +2 -2
- package/assets/skills/oat-project-autonomous/SKILL.md +17 -10
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +3 -3
- package/assets/skills/oat-project-complete/SKILL.md +18 -8
- package/assets/skills/oat-project-discover/SKILL.md +3 -3
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +12 -3
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-implement/references/phase-execution.md +218 -4
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +5 -2
- package/assets/skills/oat-project-implement/scripts/capture-dirty-tree.mjs +1069 -0
- package/assets/skills/oat-project-import-plan/SKILL.md +12 -6
- package/assets/skills/oat-project-next/SKILL.md +7 -5
- package/assets/skills/oat-project-plan/SKILL.md +24 -12
- package/assets/skills/oat-project-pr-final/SKILL.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-quick-start/SKILL.md +11 -6
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-retro/SKILL.md +4 -2
- package/assets/skills/oat-project-review-receive/SKILL.md +9 -5
- package/assets/skills/oat-project-revise/SKILL.md +6 -6
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +51 -4
- package/dist/commands/docs/index-generate/generator.d.ts +43 -1
- package/dist/commands/docs/index-generate/generator.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/generator.js +169 -3
- package/dist/commands/docs/index-generate/index.d.ts +8 -3
- package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/index.js +340 -24
- package/dist/commands/docs/init/scaffold.d.ts +11 -1
- package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
- package/dist/commands/docs/init/scaffold.js +11 -2
- package/dist/config/oat-config.d.ts +14 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +61 -0
- package/dist/fs/assets.d.ts +33 -4
- package/dist/fs/assets.d.ts.map +1 -1
- package/dist/fs/assets.js +127 -12
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-phase-implementer
|
|
3
|
-
version: 1.1.
|
|
3
|
+
version: 1.1.2
|
|
4
4
|
description: Implements one plan phase end-to-end, commits each task separately, self-checks between tasks, and handles bounded review fixes when resumed by oat-project-implement.
|
|
5
5
|
tools: Read, Write, Edit, Bash, Grep, Glob, Task
|
|
6
6
|
color: cyan
|
|
@@ -37,7 +37,8 @@ The root supplies:
|
|
|
37
37
|
candidates, and formal dispatch stamp;
|
|
38
38
|
- `phase_recovery_limit`, `phase_recovery_attempts_used`,
|
|
39
39
|
`original_request_id`, and the root-resolved recovery authorization source;
|
|
40
|
-
- optional `parallel_group`, `expected_base_sha`, and
|
|
40
|
+
- optional `parallel_group`, `expected_base_sha`, `recovered_patch`, and
|
|
41
|
+
smoke run metadata.
|
|
41
42
|
|
|
42
43
|
Fix mode also supplies:
|
|
43
44
|
|
|
@@ -341,6 +342,16 @@ use ancestry from `expected_base_sha` as a substitute for the exact
|
|
|
341
342
|
`phase_base_head` check. For a plan-declared parallel group, verify this before
|
|
342
343
|
any task edit.
|
|
343
344
|
|
|
345
|
+
A fresh child never starts on a dirty tree. The one exception is a supplied
|
|
346
|
+
`recovered_patch`, which carries work a lost child left behind: verify it,
|
|
347
|
+
apply it, review it, and commit it as your first action before task one,
|
|
348
|
+
exactly as `## Mode: Recover` steps 2 and 4 describe, and only after every
|
|
349
|
+
precondition that can park the phase has passed. That single commit is a
|
|
350
|
+
recovery commit rather than a planned task commit, so it does not consume any
|
|
351
|
+
task's one-commit budget; report it under `### Recovery Events` with the
|
|
352
|
+
artifact reference and manifest digest. Without a verified `recovered_patch`,
|
|
353
|
+
any dirt blocks.
|
|
354
|
+
|
|
344
355
|
When smoke containment, ownership registration, expected base, or fixture
|
|
345
356
|
readiness proves the run invalid, return `INVALID_RUN_ABORT` with the evidence.
|
|
346
357
|
Do not launch a child, continue sequentially, review, or repair the invalid run.
|
|
@@ -462,8 +473,18 @@ phase_verification: { relevant phase command }
|
|
|
462
473
|
dispatch_target: { exact original launcher-owned target }
|
|
463
474
|
dispatch_axes: { unchanged original launcher-owned axes }
|
|
464
475
|
dispatch_stamp: { original formal Dispatch line }
|
|
476
|
+
recovered_patch: { artifact, manifest_digest, size, stat, components }
|
|
465
477
|
```
|
|
466
478
|
|
|
479
|
+
`recovered_patch` is optional. It is present only when a lost child left
|
|
480
|
+
uncommitted work that the lifecycle captured before restoring the worktree to
|
|
481
|
+
its clean base. Its `artifact` is a readable path outside the worktree, never a
|
|
482
|
+
mutable worktree path; `manifest_digest` and `size` are the capture's recorded
|
|
483
|
+
values; `stat` is the captured `git diff --cached --stat` summary; and
|
|
484
|
+
`components` lists the `index`, `worktree`, and `untracked` entries the
|
|
485
|
+
artifact holds. The same field may arrive on a same-target `implement`
|
|
486
|
+
continuation.
|
|
487
|
+
|
|
467
488
|
1. Validate every recover input. Confirm the exact launcher-owned target equals
|
|
468
489
|
the original target and the generic `continuation_events` record links
|
|
469
490
|
`continuation_event` to `original_request_id`.
|
|
@@ -471,23 +492,116 @@ dispatch_stamp: { original formal Dispatch line }
|
|
|
471
492
|
remains immutable at the same history position; and the worktree contains
|
|
472
493
|
only the reconciled pending ledger reservation plus an optional mechanically
|
|
473
494
|
bounded diff inside `bounded_files`. Any other dirt or history change
|
|
474
|
-
blocks.
|
|
495
|
+
blocks. Compare against the briefed `recovery_base_head`, never a remembered
|
|
496
|
+
earlier value: once a recovery-patch commit has landed, the retry's
|
|
497
|
+
`recovery_base_head` is the reconciled current HEAD, which includes that
|
|
498
|
+
recovery commit and any candidate or ledger-only commit already durably
|
|
499
|
+
made, and the brief omits the already-committed artifact because re-applying
|
|
500
|
+
it would duplicate the work. Beyond that reconciled reservation and its
|
|
501
|
+
bounded diff, a supplied `recovered_patch` is the only permitted
|
|
502
|
+
pre-existing dirt, and only after it verifies. Verification is read-only and
|
|
503
|
+
happens here; the apply and the commit wait for step 4, so every precondition
|
|
504
|
+
that can park the phase resolves before anything is written. When the brief
|
|
505
|
+
carries no `recovered_patch` — an ordinary resume, or a retry after the
|
|
506
|
+
recovery commit already landed — the ordinary permitted-dirt invariant above
|
|
507
|
+
is the whole of this step: there is no artifact to resolve a script for, so
|
|
508
|
+
the continuation skips verification and continues to the ledger
|
|
509
|
+
reconciliation in step 3, and step 4 is a no-op. Resolve
|
|
510
|
+
`capture-dirty-tree.mjs` through installed scope rather than a
|
|
511
|
+
repository-relative path, probing in order and binding the first match, and
|
|
512
|
+
only when an artifact was briefed:
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
set -eu
|
|
516
|
+
# `recovered_patch` is optional and all-or-nothing. Without one there is
|
|
517
|
+
# nothing to verify and nothing to apply, so the verifier is skipped
|
|
518
|
+
# entirely; a partial brief is a named stop rather than an unbound-variable
|
|
519
|
+
# death. Never dereference an artifact variable outside the branch: under
|
|
520
|
+
# `set -u` an unset one exits here, and an empty one fails verification —
|
|
521
|
+
# either way an artifact-free retry parks before the ledger reconciliation
|
|
522
|
+
# it needs to reach.
|
|
523
|
+
if [ -z "${ARTIFACT_DIR:-}${MANIFEST_DIGEST:-}${ARTIFACT_SIZE:-}" ]; then
|
|
524
|
+
: # No recovered_patch: continue to the ledger reconciliation.
|
|
525
|
+
elif [ -z "${ARTIFACT_DIR:-}" ] || [ -z "${MANIFEST_DIGEST:-}" ] ||
|
|
526
|
+
[ -z "${ARTIFACT_SIZE:-}" ]; then
|
|
527
|
+
echo "artifact-verification-failed: a partial recovered_patch is unusable; artifact, manifest_digest and size travel together" >&2
|
|
528
|
+
exit 1
|
|
529
|
+
else
|
|
530
|
+
CAPTURE_SCRIPT=""
|
|
531
|
+
REPO_ROOT=$(git -C "$PHASE_WORKTREE" rev-parse --show-toplevel 2>/dev/null || true)
|
|
532
|
+
for CAPTURE_ROOT in "${HOME:-}/.agents/skills/oat-project-implement" \
|
|
533
|
+
"${REPO_ROOT:+$REPO_ROOT/.agents/skills/oat-project-implement}"; do
|
|
534
|
+
[ -n "$CAPTURE_ROOT" ] || continue
|
|
535
|
+
[ -f "$CAPTURE_ROOT/scripts/capture-dirty-tree.mjs" ] || continue
|
|
536
|
+
CAPTURE_SCRIPT="$CAPTURE_ROOT/scripts/capture-dirty-tree.mjs"
|
|
537
|
+
break
|
|
538
|
+
done
|
|
539
|
+
[ -n "$CAPTURE_SCRIPT" ] || {
|
|
540
|
+
echo "capture-script-unavailable" >&2
|
|
541
|
+
exit 1
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
EXPECTED_HEAD=$(git -C "$PHASE_WORKTREE" rev-parse --verify HEAD)
|
|
545
|
+
node "$CAPTURE_SCRIPT" --verify \
|
|
546
|
+
--artifact-dir "$ARTIFACT_DIR" \
|
|
547
|
+
--manifest-digest "$MANIFEST_DIGEST" \
|
|
548
|
+
--size "$ARTIFACT_SIZE" \
|
|
549
|
+
--expected-head "$EXPECTED_HEAD"
|
|
550
|
+
fi
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
`ARTIFACT_DIR`, `MANIFEST_DIGEST`, and `ARTIFACT_SIZE` are the
|
|
554
|
+
`recovered_patch` fields; bind them as shell variables rather than pasting
|
|
555
|
+
`<placeholder>` tokens, which a shell reads as input redirections. The guard
|
|
556
|
+
terminates rather than warning: `node ""` reads its program from stdin and
|
|
557
|
+
exits zero at EOF, so a fall-through would report an unverified artifact as
|
|
558
|
+
verified. Every block that runs the script repeats the resolution and the
|
|
559
|
+
guard, because shell variables do not survive across separate tool
|
|
560
|
+
invocations. `--expected-head` and the
|
|
561
|
+
apply below both resolve against `$PHASE_WORKTREE`, never the ambient
|
|
562
|
+
working directory. An empty `CAPTURE_SCRIPT` is a
|
|
563
|
+
`capture-script-unavailable` stop: report it verbatim with the probed roots
|
|
564
|
+
and the recovery command
|
|
565
|
+
`oat tools install workflows --scope <user|project>` or
|
|
566
|
+
`oat tools update --pack workflows --scope <user|project>`, and never fall
|
|
567
|
+
back to a repository-relative path. With an artifact briefed, verify before
|
|
568
|
+
touching the tree and stop on any `artifact-verification-failed` mismatch, including the base mismatch
|
|
569
|
+
`--expected-head` catches: integrity is not base agreement, and a hunk whose
|
|
570
|
+
context happens to match applies cleanly at the wrong commit. Report an
|
|
571
|
+
`active-writer`, `unsupported-dirt`, `round-trip-failed`, or
|
|
572
|
+
`artifact-verification-failed` reason verbatim and stop; never improvise a
|
|
573
|
+
partial or best-effort restore. Without a verified `recovered_patch` you
|
|
574
|
+
start on a clean tree.
|
|
575
|
+
|
|
475
576
|
3. Reconcile the authoritative `pending_attempt` and nonzero
|
|
476
577
|
`phase_recovery_attempts_used` with `state.md`. Recover mode continues that
|
|
477
578
|
same consumed attempt and must not increment usage again. Missing,
|
|
478
|
-
contradictory, or unreconciled state blocks before editing.
|
|
479
|
-
|
|
579
|
+
contradictory, or unreconciled state blocks before editing. Nothing has been
|
|
580
|
+
applied or committed yet, so this block leaves the branch exactly at
|
|
581
|
+
`recovery_base_head` with the artifact untouched and re-verifiable; the root
|
|
582
|
+
re-briefs from current authoritative state once the ledger is repaired.
|
|
583
|
+
4. Only now apply the verified `recovered_patch`, if one was supplied:
|
|
584
|
+
`git apply --index` for the `index` component, `git apply` for the
|
|
585
|
+
`worktree` component, and byte copies plus the manifest's recorded
|
|
586
|
+
executable bit for the `untracked` component. Review the result and commit
|
|
587
|
+
it as your first action. That commit is immutable, and so is every commit
|
|
588
|
+
this mode durably makes after it: if anything later parks the phase, the
|
|
589
|
+
retry's `recovery_base_head` is the reconciled current HEAD, which includes
|
|
590
|
+
that recovery commit and any candidate or ledger-only commit already made.
|
|
591
|
+
That brief omits the already-committed artifact; dirt that accumulated
|
|
592
|
+
afterwards travels as its own newly captured `recovered_patch`.
|
|
593
|
+
5. Apply or complete only `bounded_correction_scope`. Recover mode must not
|
|
480
594
|
replay planned tasks and must not require, fabricate, or consume a review
|
|
481
595
|
artifact.
|
|
482
|
-
|
|
596
|
+
6. Apply the bounded correction, then run `focused_verification` and
|
|
483
597
|
`phase_verification` before creating a candidate commit. If either check
|
|
484
598
|
fails, restore `bounded_files` to their original committed content,
|
|
485
599
|
atomically mark the pending entry `failed`, durably commit only that
|
|
486
600
|
ledger transition, emit one `failed-attempt` event, and stop.
|
|
487
|
-
|
|
601
|
+
7. When both pre-commit checks pass, atomically mark the pending entry
|
|
488
602
|
`completed` and create one append-only candidate recovery commit containing
|
|
489
603
|
only `bounded_files` plus that ledger transition.
|
|
490
|
-
|
|
604
|
+
8. Immediately rerun `focused_verification` and `phase_verification` against the
|
|
491
605
|
committed HEAD; these reruns are authoritative. On pass, emit one `recovered`
|
|
492
606
|
event and report the candidate as the successful recovery commit. On
|
|
493
607
|
failure, atomically replace `completed` with `failed`, durably commit that
|
|
@@ -496,7 +610,7 @@ dispatch_stamp: { original formal Dispatch line }
|
|
|
496
610
|
commit. If terminal evidence cannot be committed, report an unreconciled
|
|
497
611
|
block that root must reject before bookkeeping. Never amend history or
|
|
498
612
|
launch fallback.
|
|
499
|
-
|
|
613
|
+
9. Return the report below. `DONE` is accepted success;
|
|
500
614
|
`DONE_WITH_CONCERNS` and `BLOCKED` may be accepted terminal stops and must
|
|
501
615
|
still report provenance, accounting, immutable history, and the event.
|
|
502
616
|
|
|
@@ -90,6 +90,7 @@ Common keys in `.oat/config.json`:
|
|
|
90
90
|
- `worktrees.root` — where OAT-managed worktrees live
|
|
91
91
|
- `git.defaultBranch` — base branch fallback for PR workflows
|
|
92
92
|
- `documentation.root`, `documentation.tooling`, `documentation.config` — docs-surface ownership
|
|
93
|
+
- `documentation.excludes` — a JSON array of globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. `oat config set` takes the list as one comma-separated value (`"a/**,b.md"`) and stores it as an array; repeated `--exclude` flags extend it, and an empty value clears the key
|
|
93
94
|
- `documentation.requireForProjectCompletion` — whether docs sync is a completion gate
|
|
94
95
|
- `archive.s3Uri` — base S3 archive prefix
|
|
95
96
|
- `archive.s3SyncOnComplete` — upload archived projects to S3 during completion
|
|
@@ -242,8 +243,17 @@ packaged `assets/` directory next to the installed CLI. Setting a non-empty
|
|
|
242
243
|
directory.
|
|
243
244
|
- The override is validated exactly like the packaged root and fails closed:
|
|
244
245
|
the path must be a directory containing bundle metadata whose version matches
|
|
245
|
-
the running CLI (`OAT_VERSION`)
|
|
246
|
-
|
|
246
|
+
the running CLI (`OAT_VERSION`) **and** the seven top-level directories the
|
|
247
|
+
bundle producer creates (`skills`, `agents`, `templates`, `scripts`, `docs`,
|
|
248
|
+
`migration`, `config`), each of which must be a directory. A missing,
|
|
249
|
+
malformed, version-mismatched, or structurally incomplete override is an
|
|
250
|
+
error with exit code 2 that names the first offending path — the CLI never
|
|
251
|
+
silently falls back to packaged assets, and a metadata-only directory is no
|
|
252
|
+
longer accepted as an empty installation.
|
|
253
|
+
- Remedies are source-aware: an `OAT_ASSETS_DIR` failure tells you to fix or
|
|
254
|
+
unset the override, never to rebuild or reinstall the CLI; a packaged-bundle
|
|
255
|
+
failure keeps the rebuild/reinstall guidance. A directory that exists but
|
|
256
|
+
cannot be read reports the underlying error code.
|
|
247
257
|
- Produce a matching bundle with `bash packages/cli/scripts/bundle-assets.sh`
|
|
248
258
|
while `OAT_ASSETS_DIR` points at the target directory (the script already
|
|
249
259
|
honors the variable as its destination).
|
|
@@ -128,23 +128,54 @@ Key behavior:
|
|
|
128
128
|
- recursively walks the docs directory
|
|
129
129
|
- extracts page titles from frontmatter (falls back to first `# heading`, then filename title-case)
|
|
130
130
|
- includes descriptions from frontmatter when present
|
|
131
|
-
-
|
|
132
|
-
-
|
|
131
|
+
- resolves omitted paths from `.oat/config.json` rather than the current directory: `--docs-dir` defaults to `<documentation.root>/docs` when that directory exists and to `<documentation.root>` otherwise, and `--output` defaults to the app-root manifest `<documentation.root>/index.md`
|
|
132
|
+
- treats explicitly supplied `--docs-dir` / `--output` paths as overrides resolved from the current directory
|
|
133
|
+
- fails with exit code `2` before generating or writing anything when an omitted path has no non-empty `documentation.root` to resolve against, or when the configured root is not a directory
|
|
134
|
+
- refuses unsafe output targets with exit code `1` before generation, for derived and explicit paths alike, comparing symlink-resolved paths: inside the docs directory it indexes, equal to `documentation.config`, or ending in `.yml` / `.yaml` in any case. A derived output whose existing file lacks the `AUTOGENERATED` header is refused too; naming that path with `--output` overwrites it explicitly. A refused target is an actionable flag error (`1`); unusable path configuration is a separate condition and exits `2`, so scripts can branch on the two
|
|
135
|
+
- writes configuration only for the Fumadocs manifest transition — recording the manifest it just wrote inside `documentation.root` in `documentation.index`, when `documentation.tooling` is `fumadocs` or the config declares neither `tooling` nor `config`. MkDocs configurations are never written, and `documentation.root` and `documentation.config` are never modified
|
|
133
136
|
- prepends an `AUTOGENERATED` warning comment to the output and rewrites the file on every run; do not hand-edit the generated `index.md`
|
|
134
137
|
- should be freshness-checked against authored `docs/**/index.md` `## Contents` maps before treating it as navigation evidence
|
|
135
138
|
- sorting: `index.md` first, then directories before files, then lexical
|
|
139
|
+
- reports the derived docs directory in human output and as `docsDir` / `docsDirSource` under `--json`
|
|
140
|
+
- omits pages matching the exclusion list. Nothing is excluded by default; once listed, non-page Markdown such as `CLAUDE.md` or `AGENTS.md` stops reaching the manifest. Patterns come from `documentation.excludes` in `.oat/config.json` and from repeated `--exclude` flags, and the flags **extend** the configured list rather than replacing it. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all
|
|
136
141
|
|
|
137
142
|
Supported flags:
|
|
138
143
|
|
|
139
|
-
- `--docs-dir <path>` (default:
|
|
140
|
-
- `--output <path>` (default:
|
|
144
|
+
- `--docs-dir <path>` (default: `<documentation.root>/docs`, falling back to `<documentation.root>`)
|
|
145
|
+
- `--output <path>` (default: `<documentation.root>/index.md`)
|
|
146
|
+
- `--exclude <glob>` (repeatable; additive to `documentation.excludes`)
|
|
147
|
+
|
|
148
|
+
### Exclusion patterns
|
|
149
|
+
|
|
150
|
+
Patterns match the path of each candidate **relative to the docs directory being indexed** — `api/auth.md`, `api/nested` — never an absolute or current-directory-relative path, and never the repository-relative path.
|
|
151
|
+
|
|
152
|
+
| Pattern | Matches |
|
|
153
|
+
| -------------- | -------------------------------------------------------- |
|
|
154
|
+
| `CLAUDE.md` | only the root-level `CLAUDE.md`; patterns are anchored |
|
|
155
|
+
| `**/CLAUDE.md` | `CLAUDE.md` at any depth, including the docs root |
|
|
156
|
+
| `*.md` | root-level Markdown only; `*` never crosses `/` |
|
|
157
|
+
| `drafts/` | the `drafts` directory and everything beneath it |
|
|
158
|
+
| `drafts` | the same directory; the trailing `/` only forbids a file |
|
|
159
|
+
| `api/**/*.md` | Markdown at any depth under `api/`, including `api/x.md` |
|
|
160
|
+
|
|
161
|
+
A trailing `/` restricts a pattern to directories and never matches a file; without it, a pattern that matches a directory path still prunes that directory. `**` spans `/` only as a whole path segment — inside a segment (`a**b`) it is an ordinary single-segment wildcard. Matching is case-sensitive, `/` is the separator on every platform, and only `*` and `**` are metacharacters — every other character, `.` included, is literal. A leading `./` or `/` is stripped, so both spellings anchor at the docs root.
|
|
141
162
|
|
|
142
163
|
Example:
|
|
143
164
|
|
|
144
165
|
```bash
|
|
145
|
-
|
|
166
|
+
# Resolve both paths from .oat/config.json
|
|
167
|
+
oat docs generate-index
|
|
168
|
+
|
|
169
|
+
# Portable explicit form, resolved from the current directory
|
|
170
|
+
oat docs generate-index --docs-dir apps/oat-docs/docs --output apps/oat-docs/index.md
|
|
171
|
+
|
|
172
|
+
# Persist the repository's own exclusions, then add a one-off
|
|
173
|
+
oat config set documentation.excludes "**/CLAUDE.md,**/AGENTS.md"
|
|
174
|
+
oat docs generate-index --exclude 'drafts/'
|
|
146
175
|
```
|
|
147
176
|
|
|
177
|
+
See [Documentation path resolution](../reference/oat-directory-structure.md#documentation-path-resolution) for the app-root meaning of `documentation.root` and the legacy source-root compatibility rule.
|
|
178
|
+
|
|
148
179
|
The Fumadocs scaffold runs this automatically via `predev`/`prebuild` npm
|
|
149
180
|
script hooks.
|
|
150
181
|
|
|
@@ -117,10 +117,11 @@ Current schema keys:
|
|
|
117
117
|
| `projects.root` | `string` | `".oat/projects/shared"` | Default root directory for OAT projects |
|
|
118
118
|
| `projects.defaultScope` | `string` | `"synced"` | Scope used by project creation when `--scope` is omitted: `shared`, `local`, or `synced`. Environment override: `OAT_PROJECTS_DEFAULT_SCOPE`. |
|
|
119
119
|
| `localPaths` | `string[]` | - | Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via `oat local add/remove`. |
|
|
120
|
-
| `documentation.root` | `string` | - |
|
|
120
|
+
| `documentation.root` | `string` | - | Docs **app root** — the directory `oat docs init` scaffolds (e.g., `apps/docs`). Authored pages live under `<root>/docs`. See [Documentation path resolution](#documentation-path-resolution). |
|
|
121
121
|
| `documentation.tooling` | `string` | - | Documentation framework identifier (`mkdocs` or `fumadocs`) |
|
|
122
122
|
| `documentation.config` | `string` | - | Path to the documentation framework config file (e.g., `mkdocs.yml`, `next.config.js`) |
|
|
123
|
-
| `documentation.index` | `string` | - | Path to the docs surface entry point
|
|
123
|
+
| `documentation.index` | `string` | - | Path to the docs surface entry point: the generated app-root manifest `<root>/index.md` for Fumadocs, `mkdocs.yml` for MkDocs. Set by `oat docs init`. `oat docs generate-index` writes it only for the Fumadocs manifest transition and never for MkDocs. |
|
|
124
|
+
| `documentation.excludes` | `string[]` | - | Globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. See [Excluding pages from the generated index](#excluding-pages-from-the-generated-index). |
|
|
124
125
|
| `documentation.requireForProjectCompletion` | `boolean` | `false` | When `true`, OAT project completion gates require documentation to be updated |
|
|
125
126
|
| `git.defaultBranch` | `string` | `"main"` | Default branch for PR creation. Auto-detected during `oat init` via `gh repo view` or `origin/HEAD`. Used by `oat-project-pr-final` and `oat-project-pr-progress`. |
|
|
126
127
|
| `workflow.autoReviewAtHillCheckpoints` | `boolean` | unset | When `true`, completing a HiLL checkpoint automatically runs the extra lifecycle review. Does not control Tier 1 per-phase `oat-reviewer` gates. Can be overridden per-project via `oat_auto_review_at_hill_checkpoints` in `plan.md` frontmatter. Legacy `autoReviewAtCheckpoints` remains a fallback. |
|
|
@@ -157,14 +158,65 @@ Example:
|
|
|
157
158
|
"root": ".worktrees"
|
|
158
159
|
},
|
|
159
160
|
"documentation": {
|
|
160
|
-
"root": "apps/docs
|
|
161
|
+
"root": "apps/docs",
|
|
161
162
|
"tooling": "mkdocs",
|
|
162
|
-
"config": "mkdocs.yml",
|
|
163
|
+
"config": "apps/docs/mkdocs.yml",
|
|
164
|
+
"index": "apps/docs/mkdocs.yml",
|
|
163
165
|
"requireForProjectCompletion": false
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
```
|
|
167
169
|
|
|
170
|
+
### Documentation path resolution
|
|
171
|
+
|
|
172
|
+
`documentation.root` canonically names the docs **app root** — exactly the directory `oat docs init` scaffolds. Authored Markdown lives under `<root>/docs`, and the generated Fumadocs manifest is written to `<root>/index.md`, outside the tree it indexes.
|
|
173
|
+
|
|
174
|
+
`oat docs generate-index` resolves omitted options from this configuration:
|
|
175
|
+
|
|
176
|
+
| Option | Omitted | Supplied |
|
|
177
|
+
| ------------ | ---------------------------------------------------------------------------------------- | ----------------------------------- |
|
|
178
|
+
| `--docs-dir` | `<documentation.root>/docs` when that directory exists, otherwise `<documentation.root>` | Resolved from the current directory |
|
|
179
|
+
| `--output` | `<documentation.root>/index.md` | Resolved from the current directory |
|
|
180
|
+
|
|
181
|
+
If an omitted option has no non-empty `documentation.root` to resolve against, or the configured root is not a directory, the command fails with exit code `2` before generating or writing anything.
|
|
182
|
+
|
|
183
|
+
**Compatibility behavior.** Preferring `<root>/docs` exists for legacy configs whose `root` names a docs _source_ directory rather than an app root; it is not a second meaning of the key. Because the rule is a plain directory-existence test, a source root that happens to contain its own `docs` subdirectory is narrowed to it. The command prints the directory it derived in both human and JSON output (`docsDir`, `docsDirSource`), and `--docs-dir` is the escape hatch when the derivation is wrong.
|
|
184
|
+
|
|
185
|
+
A legacy source root with no `docs` child resolves `--docs-dir` and `--output` to the same tree, so a bare run is refused rather than allowed to overwrite an authored page. Pass an explicit `--output` outside the source tree, or repoint `documentation.root` at the app root.
|
|
186
|
+
|
|
187
|
+
**Refused output targets.** Checked before generation for derived and explicit paths alike, the command refuses to write an output that is inside the docs directory it indexes, equals `documentation.config`, or ends in `.yml` / `.yaml`. A derived output whose existing file lacks the `AUTOGENERATED by oat docs generate-index` header is also refused; naming that same path with `--output` overwrites it explicitly.
|
|
188
|
+
|
|
189
|
+
**Configuration writes.** The only configuration write generation performs is the Fumadocs manifest transition: when the written manifest lies inside `documentation.root` and `documentation.tooling` is `fumadocs`, the repo-relative output path is recorded in `documentation.index`. A config that declares neither `documentation.tooling` nor `documentation.config` is treated as the same Fumadocs-shaped case. Any other declared tooling — `mkdocs` included — is never written, and neither are `documentation.root` and `documentation.config`. The value is always repo-relative: when `documentation.root` points outside the repository, the manifest is still generated but the key is left untouched rather than recording a machine-specific path.
|
|
190
|
+
|
|
191
|
+
### Excluding pages from the generated index
|
|
192
|
+
|
|
193
|
+
`documentation.excludes` and the repeatable `--exclude <glob>` flag feed one matcher. Flags **extend** the configured list rather than replacing it, so a one-off exclusion cannot silently republish pages the repository deliberately excluded. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all.
|
|
194
|
+
|
|
195
|
+
Patterns are matched against each candidate's path **relative to the docs directory being indexed** — the directory `--docs-dir` resolved to, not `documentation.root` and not the repository root.
|
|
196
|
+
|
|
197
|
+
| Pattern | Matches |
|
|
198
|
+
| -------------- | -------------------------------------------------------- |
|
|
199
|
+
| `CLAUDE.md` | only the root-level `CLAUDE.md`; patterns are anchored |
|
|
200
|
+
| `**/CLAUDE.md` | `CLAUDE.md` at any depth, including the docs root |
|
|
201
|
+
| `*.md` | root-level Markdown only; `*` never crosses `/` |
|
|
202
|
+
| `drafts/` | the `drafts` directory and everything beneath it |
|
|
203
|
+
| `api/**/*.md` | Markdown at any depth under `api/`, including `api/x.md` |
|
|
204
|
+
|
|
205
|
+
A trailing `/` restricts a pattern to directories and never matches a file; without it, a pattern that matches a directory path still prunes that directory. `**` spans `/` only as a whole path segment — inside a segment (`a**b`) it is an ordinary single-segment wildcard. Matching is case-sensitive, `/` is the separator on every platform, and only `*` and `**` are metacharacters — every other character, `.` included, is literal. A leading `./` or `/` is stripped, so both spellings anchor at the docs root. Entries are trimmed and de-duplicated; a malformed `documentation.excludes` (a non-array, or an empty or non-string entry) is rejected rather than silently ignored. `oat docs generate-index` reports it with exit code `2`; `oat config` surfaces the same error as an ordinary exit-`1` user error. `oat config set documentation.excludes` can still replace or clear a malformed value, so the repair the error names always works.
|
|
206
|
+
|
|
207
|
+
Set the list with the comma-separated grammar, and clear it with an empty value:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
oat config set documentation.excludes "**/CLAUDE.md,**/AGENTS.md"
|
|
211
|
+
oat config set documentation.excludes ""
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
This repository pins the invocation explicitly, which is the portable fallback anywhere the configured defaults are not what you want:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
oat docs generate-index --docs-dir apps/oat-docs/docs --output apps/oat-docs/index.md
|
|
218
|
+
```
|
|
219
|
+
|
|
168
220
|
### Worktree root precedence
|
|
169
221
|
|
|
170
222
|
When resolving the worktree root directory, `oat-worktree-bootstrap` uses this strict precedence (stops at the first match):
|
|
@@ -152,7 +152,11 @@ by the phase's standing authority. The important distinctions are:
|
|
|
152
152
|
boundary, not for every eligible defect;
|
|
153
153
|
- a **continuation** preserves the original request and exact target, either in
|
|
154
154
|
the accepted handle or through an explicitly linked fresh same-target
|
|
155
|
-
recovery launch
|
|
155
|
+
recovery launch, and never starts on a dirty tree: uncommitted work a lost
|
|
156
|
+
child left behind is first captured into a digest-verified artifact,
|
|
157
|
+
restored out of the worktree, handed forward as `recovered_patch`, and
|
|
158
|
+
committed by the continuation as its first action, while unverified or
|
|
159
|
+
unsupported dirt still blocks; and
|
|
156
160
|
- a **successful repair** produces one immutable append-only recovery commit.
|
|
157
161
|
|
|
158
162
|
This recovery is not accepted-launch fallback. After a launch is accepted,
|
|
@@ -434,11 +434,14 @@ typed adapter settings.
|
|
|
434
434
|
Private integrations use the core boundary directly: resolve private inputs
|
|
435
435
|
before the run, construct one versioned request, invoke the core once, then
|
|
436
436
|
publish or link the versioned manifest after the run. Wrapper acceptance reads
|
|
437
|
-
the complete post-run `publish-receipt/v2`,
|
|
438
|
-
|
|
439
|
-
remains readable for replay of older runs only.
|
|
440
|
-
|
|
441
|
-
|
|
437
|
+
the complete post-run `publish-receipt/v2`, requires complete manifest and
|
|
438
|
+
catalog evidence, verifies the core run ID, and rejects foreign or stale
|
|
439
|
+
receipts; `publish-receipt/v1` remains readable for replay of older runs only.
|
|
440
|
+
Public and protected v2 receipts must each provide exactly one entry for every
|
|
441
|
+
finalized manifest artifact and exactly one generated catalog entry. The
|
|
442
|
+
`explainer-kit` wrapper extension contract owns this rule; this page restates
|
|
443
|
+
it for integrators. Presets, private source systems, external-document
|
|
444
|
+
synchronization, and personal destinations remain wrapper-owned.
|
|
442
445
|
|
|
443
446
|
V1 exposes no plugin registry or private mid-pipeline hook. Unsupported
|
|
444
447
|
contract majors and identity mismatches fail closed instead of being guessed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: analyze
|
|
3
|
-
version: 0.
|
|
3
|
+
version: 0.2.0
|
|
4
4
|
description: Multi-angle analysis of existing artifacts, codebases, documents, or systems. Examines what you have from six analysis angles and produces structured findings with prioritized recommendations.
|
|
5
5
|
argument-hint: 'target [--context path]'
|
|
6
6
|
user-invocable: true
|
|
@@ -49,15 +49,16 @@ Print this banner once at start:
|
|
|
49
49
|
|
|
50
50
|
Then print step indicators before beginning work:
|
|
51
51
|
|
|
52
|
-
- `[1/
|
|
53
|
-
- `[2/
|
|
54
|
-
- `[3/
|
|
55
|
-
- `[4/
|
|
56
|
-
- `[5/
|
|
57
|
-
- `[6/
|
|
58
|
-
- `[7/
|
|
59
|
-
- `[8/
|
|
60
|
-
- `[9/
|
|
52
|
+
- `[1/10] Parsing arguments…`
|
|
53
|
+
- `[2/10] Reading context…` (if applicable)
|
|
54
|
+
- `[3/10] Classifying input type…`
|
|
55
|
+
- `[4/10] Selecting analysis angles…`
|
|
56
|
+
- `[5/10] Checking sub-agent availability…`
|
|
57
|
+
- `[6/10] Executing analysis angles…`
|
|
58
|
+
- `[7/10] Checking for comparisons…` (if applicable)
|
|
59
|
+
- `[8/10] Cross-angle synthesis…`
|
|
60
|
+
- `[9/10] Resolving output destination…`
|
|
61
|
+
- `[10/10] Writing artifact…`
|
|
61
62
|
|
|
62
63
|
For long-running operations, print a start line and a completion line:
|
|
63
64
|
|
|
@@ -72,7 +73,7 @@ Keep it concise; don't print a line for every shell command.
|
|
|
72
73
|
|
|
73
74
|
### Step 1: Parse arguments
|
|
74
75
|
|
|
75
|
-
`[1/
|
|
76
|
+
`[1/10] Parsing arguments…`
|
|
76
77
|
|
|
77
78
|
Parse from `$ARGUMENTS`:
|
|
78
79
|
|
|
@@ -91,7 +92,7 @@ The prompt should ask: _"What would you like me to analyze? Provide a file path,
|
|
|
91
92
|
|
|
92
93
|
### Step 2: Read context (if provided)
|
|
93
94
|
|
|
94
|
-
`[2/
|
|
95
|
+
`[2/10] Reading context…`
|
|
95
96
|
|
|
96
97
|
If `--context` is specified:
|
|
97
98
|
|
|
@@ -107,7 +108,7 @@ If `--context` is not specified, skip this step.
|
|
|
107
108
|
|
|
108
109
|
### Step 3: Input type classification
|
|
109
110
|
|
|
110
|
-
`[3/
|
|
111
|
+
`[3/10] Classifying input type…`
|
|
111
112
|
|
|
112
113
|
Classify the target to determine analysis angle emphasis:
|
|
113
114
|
|
|
@@ -126,7 +127,7 @@ Log: `→ Input type: {type}`
|
|
|
126
127
|
|
|
127
128
|
### Step 4: Analysis angle selection
|
|
128
129
|
|
|
129
|
-
`[4/
|
|
130
|
+
`[4/10] Selecting analysis angles…`
|
|
130
131
|
|
|
131
132
|
All six angles are ALWAYS run. The input type determines emphasis weighting (primary angles get deeper investigation):
|
|
132
133
|
|
|
@@ -157,7 +158,7 @@ Log the selected emphasis: `→ Primary: {angles} · Secondary: {angles}`
|
|
|
157
158
|
### Step 5: Sub-agent availability probe
|
|
158
159
|
|
|
159
160
|
```
|
|
160
|
-
[5/
|
|
161
|
+
[5/10] Checking sub-agent availability…
|
|
161
162
|
→ analysis workers: {available | not resolved} ({reason})
|
|
162
163
|
→ Selected: Execution Tier {1|2|3} — {description}
|
|
163
164
|
```
|
|
@@ -184,7 +185,7 @@ Log the selected emphasis: `→ Primary: {angles} · Secondary: {angles}`
|
|
|
184
185
|
|
|
185
186
|
### Step 6: Execute analysis angles
|
|
186
187
|
|
|
187
|
-
`[6/
|
|
188
|
+
`[6/10] Executing analysis angles…`
|
|
188
189
|
|
|
189
190
|
For each angle, the worker (sub-agent or self) receives:
|
|
190
191
|
|
|
@@ -209,7 +210,7 @@ Print progress for each angle:
|
|
|
209
210
|
|
|
210
211
|
### Step 7: Conditional /compare dispatch
|
|
211
212
|
|
|
212
|
-
`[7/
|
|
213
|
+
`[7/10] Checking for comparisons…`
|
|
213
214
|
|
|
214
215
|
If any angle surfaces comparables (e.g. "this component could use library A or B"):
|
|
215
216
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-brainstorm
|
|
3
|
-
version: 1.3.
|
|
3
|
+
version: 1.3.5
|
|
4
4
|
description: Use when the user explicitly invokes the `brainstorm` verb, including `/oat-brainstorm`, "let's brainstorm", "brainstorm this", "can we brainstorm X", or "help me brainstorm X". For ambiguous exploratory phrasing ("I've been thinking", "what if", "help me think through"), do NOT auto-enter; respond conversationally and offer mode only after ≥2 sustained exploratory turns. Do NOT use for review, debug, PR, status, implementation, or active-workflow questions.
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
@@ -191,7 +191,7 @@ Classify the opening brainstorm topic before running the Node preflight or print
|
|
|
191
191
|
command -v node >/dev/null 2>&1 && echo "available" || echo "missing"
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
- If `node` is **missing**: skip the offer entirely. Do not print the offer message. Log a one-line note in the conversation
|
|
194
|
+
- If `node` is **missing**: skip the offer entirely. Do not print the offer message. Log a one-line note in the conversation for this session only: "visual companion suppressed — node not on PATH". Nothing persists that note, so no later diagnostic run can report it. Proceed with `VISUAL_COMPANION = "unavailable"`.
|
|
195
195
|
- If `node` is **available**: print the offer as its own message. Suggested wording (adapt freely; the constraint is "own message, no other content"):
|
|
196
196
|
|
|
197
197
|
> "Some of what we're working on might be easier to explain if I can show it in a local web browser — mockups, diagrams, side-by-side comparisons. The visual companion is bundled with this skill (a small Node-based local server). Want me to start it? (Requires opening a `localhost` URL.)"
|