@open-agent-toolkit/cli 0.3.21 → 0.3.23

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 (130) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/docs-tooling/add-docs-to-a-repo.md +3 -9
  3. package/assets/docs/reference/cli-reference.md +8 -3
  4. package/assets/docs/reference/configuration.md +3 -0
  5. package/assets/docs/reference/oat-directory-structure.md +1 -1
  6. package/assets/docs/reference/project-artifacts.md +141 -2
  7. package/assets/docs/reference/project-state-machine.md +2 -2
  8. package/assets/docs/workflows/advanced/autonomy.md +29 -12
  9. package/assets/docs/workflows/advanced/cursor-cloud.md +20 -6
  10. package/assets/docs/workflows/advanced/workflow-gates.md +9 -0
  11. package/assets/docs/workflows/projects/closeout/closeout-skills.md +24 -5
  12. package/assets/docs/workflows/projects/closeout/retro.md +6 -2
  13. package/assets/docs/workflows/projects/execution/implementation-execution.md +18 -4
  14. package/assets/docs/workflows/projects/execution/index.md +1 -1
  15. package/assets/docs/workflows/projects/execution/picking-up-projects.md +3 -2
  16. package/assets/docs/workflows/projects/execution/project-log.md +100 -11
  17. package/assets/docs/workflows/projects/lifecycle.md +3 -3
  18. package/assets/docs/workflows/projects/reviews/index.md +18 -0
  19. package/assets/public-package-versions.json +4 -4
  20. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +12 -8
  21. package/assets/skills/oat-cursor-cloud-projects/references/cursor-cloud-mechanics.md +63 -2
  22. package/assets/skills/oat-docs/SKILL.md +14 -28
  23. package/assets/skills/oat-docs-analyze/SKILL.md +4 -2
  24. package/assets/skills/oat-docs-analyze/references/legacy-scaffold-checks.md +16 -0
  25. package/assets/skills/oat-docs-apply/SKILL.md +2 -2
  26. package/assets/skills/oat-docs-authoring/SKILL.md +2 -2
  27. package/assets/skills/oat-docs-authoring/references/lifecycle-boundaries.md +1 -2
  28. package/assets/skills/oat-docs-authoring/references/mkdocs-to-oat-fumadocs-refactor-guide.md +73 -0
  29. package/assets/skills/oat-docs-bootstrap/SKILL.md +44 -310
  30. package/assets/skills/oat-project-autonomous/SKILL.md +88 -26
  31. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  32. package/assets/skills/oat-project-brief/SKILL.md +1 -1
  33. package/assets/skills/oat-project-brief/references/brief-contract.md +33 -27
  34. package/assets/skills/oat-project-brief/references/docs/autonomy-contract.md +1 -1
  35. package/assets/skills/oat-project-complete/SKILL.md +142 -25
  36. package/assets/skills/oat-project-complete-auto/SKILL.md +4 -4
  37. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +10 -5
  38. package/assets/skills/oat-project-document/SKILL.md +1 -1
  39. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  40. package/assets/skills/oat-project-goal/SKILL.md +63 -15
  41. package/assets/skills/oat-project-goal/references/docs/autonomy-contract.md +1 -1
  42. package/assets/skills/oat-project-implement/SKILL.md +6 -6
  43. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +28 -7
  44. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +10 -5
  45. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  46. package/assets/skills/oat-project-implement/references/phase-execution.md +23 -9
  47. package/assets/skills/oat-project-implement/references/plan-and-resume.md +4 -4
  48. package/assets/skills/oat-project-lite/SKILL.md +1 -1
  49. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
  50. package/assets/skills/oat-project-pr-final/SKILL.md +6 -1
  51. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  52. package/assets/skills/oat-project-pr-progress/SKILL.md +6 -1
  53. package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
  54. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  55. package/assets/skills/oat-project-reconcile/SKILL.md +13 -19
  56. package/assets/skills/oat-project-retro/SKILL.md +5 -2
  57. package/assets/skills/oat-project-retro/references/evidence-and-lanes.md +9 -3
  58. package/assets/skills/oat-project-review-provide/SKILL.md +28 -3
  59. package/assets/skills/oat-project-review-receive/SKILL.md +32 -18
  60. package/assets/skills/oat-project-review-receive-remote/SKILL.md +10 -6
  61. package/assets/skills/oat-project-revise/SKILL.md +9 -2
  62. package/assets/skills/oat-project-summary/SKILL.md +166 -37
  63. package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +3 -3
  64. package/assets/templates/docs-app-fuma/docs/contributing.md +6 -0
  65. package/assets/templates/docs-app-fuma/docs/getting-started.md +1 -1
  66. package/assets/templates/docs-app-fuma/next.config.js +5 -1
  67. package/assets/templates/implementation-brief.md +5 -36
  68. package/assets/templates/implementation.md +11 -81
  69. package/assets/templates/project-log.md +2 -31
  70. package/assets/templates/project-retro.md +4 -1
  71. package/assets/templates/summary.md +13 -5
  72. package/dist/commands/config/index.d.ts.map +1 -1
  73. package/dist/commands/config/index.js +44 -1
  74. package/dist/commands/docs/analyze.js +1 -1
  75. package/dist/commands/docs/apply.js +1 -1
  76. package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
  77. package/dist/commands/docs/init/scaffold.js +35 -2
  78. package/dist/commands/project/archive/archive-utils.d.ts +205 -8
  79. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  80. package/dist/commands/project/archive/archive-utils.js +708 -44
  81. package/dist/commands/project/archive/index.d.ts.map +1 -1
  82. package/dist/commands/project/archive/index.js +1 -0
  83. package/dist/commands/project/archive/push-runner.d.ts +9 -1
  84. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  85. package/dist/commands/project/archive/push-runner.js +56 -18
  86. package/dist/commands/project/archive/sync-runner.d.ts +28 -0
  87. package/dist/commands/project/archive/sync-runner.d.ts.map +1 -1
  88. package/dist/commands/project/archive/sync-runner.js +44 -22
  89. package/dist/commands/project/complete-state/index.d.ts.map +1 -1
  90. package/dist/commands/project/complete-state/index.js +45 -0
  91. package/dist/commands/project/dispatch/index.d.ts.map +1 -1
  92. package/dist/commands/project/dispatch/index.js +24 -2
  93. package/dist/commands/project/dispatch/record.d.ts +54 -1
  94. package/dist/commands/project/dispatch/record.d.ts.map +1 -1
  95. package/dist/commands/project/dispatch/record.js +229 -1
  96. package/dist/commands/project/index.d.ts.map +1 -1
  97. package/dist/commands/project/index.js +2 -0
  98. package/dist/commands/project/journal-check/evaluator.d.ts +17 -0
  99. package/dist/commands/project/journal-check/evaluator.d.ts.map +1 -0
  100. package/dist/commands/project/journal-check/evaluator.js +140 -0
  101. package/dist/commands/project/journal-check/index.d.ts +34 -0
  102. package/dist/commands/project/journal-check/index.d.ts.map +1 -0
  103. package/dist/commands/project/journal-check/index.js +163 -0
  104. package/dist/commands/project/journal-check/rules.d.ts +68 -0
  105. package/dist/commands/project/journal-check/rules.d.ts.map +1 -0
  106. package/dist/commands/project/journal-check/rules.js +994 -0
  107. package/dist/commands/project/journal-check/types.d.ts +63 -0
  108. package/dist/commands/project/journal-check/types.d.ts.map +1 -0
  109. package/dist/commands/project/journal-check/types.js +26 -0
  110. package/dist/commands/project/log/append.d.ts +6 -0
  111. package/dist/commands/project/log/append.d.ts.map +1 -1
  112. package/dist/commands/project/log/append.js +114 -6
  113. package/dist/commands/project/log/check.d.ts +23 -1
  114. package/dist/commands/project/log/check.d.ts.map +1 -1
  115. package/dist/commands/project/log/check.js +20 -3
  116. package/dist/commands/project/log/grammar.d.ts +37 -0
  117. package/dist/commands/project/log/grammar.d.ts.map +1 -1
  118. package/dist/commands/project/log/grammar.js +72 -0
  119. package/dist/commands/project/log/rollup.d.ts +87 -1
  120. package/dist/commands/project/log/rollup.d.ts.map +1 -1
  121. package/dist/commands/project/log/rollup.js +257 -5
  122. package/dist/config/oat-config.d.ts +14 -0
  123. package/dist/config/oat-config.d.ts.map +1 -1
  124. package/dist/config/oat-config.js +17 -0
  125. package/dist/config/resolve.d.ts.map +1 -1
  126. package/dist/config/resolve.js +5 -1
  127. package/dist/providers/identity/generic-dispatch-record.d.ts +33 -0
  128. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -1
  129. package/dist/providers/identity/generic-dispatch-record.js +60 -1
  130. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "oatVersion": "0.3.21"
3
+ "oatVersion": "0.3.23"
4
4
  }
@@ -68,21 +68,15 @@ For framework apps, it wraps `oat docs init` with a seven-step guided flow: pref
68
68
  What the framework path adds over the raw CLI:
69
69
 
70
70
  - **Preflight + conflict resolution.** Detects existing `documentation` config / docs app dir / root `AGENTS.md` section and walks a deliberate resolution choice (replace, abort, repair, or deferred second-app) before any mutation.
71
- - **Richer inputs.** Asks for a **site name** separate from the package name, so `createDocsConfig()` / layout branding / page metadata all converge on the same display title.
72
- - **Post-scaffold patches for open CLI gaps.** Applied only when capability detection shows the CLI hasn't closed the gap. Each patch is labeled (e.g., `<!-- FP-12 patch -->`) so it can be removed deterministically when the upstream fix lands:
73
- - **FP-11** — Turbopack `root` for nested-standalone Fumadocs apps (suppresses the multiple-lockfile warning)
74
- - **FP-12** — `export const metadata = { title, description }` in `app/layout.tsx` (the only thing that populates page `<title>`, meta description, and Open Graph — `DocsLayout.branding.title` only renders nav chrome, and `createDocsConfig()` ignores `title` / `description` entirely)
75
- - **FP-13** — four scaffold-content fixes (empty per-page `description:` frontmatter, bare install/build commands missing `--filter` or `cd`-prefix for monorepo/nested shapes, false `docs:lint` claim when `lint=none`, Node version line that doesn't match the consuming repo's `.nvmrc` / `engines.node`)
76
- - **FP-15** — writes a task-framed `<appRoot>/AGENTS.md` bridge file when the CLI hasn't scaffolded one. The bridge is the docs app's runtime agent reference (separate audience from `docs/contributing.md`)
77
- - **FP-16** — rewrites `docs/index.md` `## Contents` links to the `.md`-suffixed form that `@open-agent-toolkit/docs-transforms` normalizes at build time (agent-friendlier than extension-less; routes correctly)
78
- - **FP-17** — trims `docs/contributing.md`'s "Agent guidance" section to a one-line pointer at the docs-app `AGENTS.md`, restoring the three-surfaces separation
71
+ - **Richer inputs.** Asks for a **site name** separate from the package name, so layout branding and page metadata converge on the same display title. `createDocsConfig()` handles runtime configuration, not titles.
72
+ - **AGENTS.md bridge.** FP-15 writes a task-framed `<appRoot>/AGENTS.md` only when the CLI does not scaffold it and no file already exists. Template content, metadata, command context, Node requirements, Contents links and generated-files guidance are CLI-owned. For nested-standalone repos only, the Fumadocs template passes an ESM-safe Turbopack root through `createDocsConfig` while preserving static export settings. Monorepo and single-package scaffolds use Next.js root discovery. Older scaffold shapes become analyze findings rather than post-patches.
79
73
  - **Build verification.** Runs install + build, classifies failures against known patterns, stops on unknown errors rather than guessing.
80
74
  - **Config inspection.** Reads `.oat/config.json` back, verifies paths exist on disk, handles the nested-standalone dual-config case, and collects the `requireForProjectCompletion` opt-in explicitly.
81
75
  - **Root-build explanation.** When the CLI safely patches a compatible Turbo root `build` script, the walkthrough explains why the filter was added, shows the diff shape, and documents how to adjust or revert it. When the CLI skips the patch, the walkthrough relays the recommended manual snippet.
82
76
  - **Educational walkthrough.** Seven sections covering the `documentation` config, the authored-source/generated-navigation model, the `## Contents` contract (with extension discipline), the three agent-instruction surfaces (root `AGENTS.md` pointer / docs-app `AGENTS.md` / `docs/contributing.md`), Fumadocs internals (or MkDocs Minimum Contract), and the OAT docs ecosystem (`oat-project-document`, `oat-docs-analyze`, `oat-docs-apply`).
83
77
  - **Optional content kickoff.** Hands off to `oat-docs-analyze` + `oat-docs-apply` if you want to populate initial repo-specific content immediately.
84
78
 
85
- Capability-gated: every post-patch self-ratchets off as CLI fixes land upstream. The skill's labeled markers (`<!-- FP-NN patch -->`) are how you find them later when the CLI catches up.
79
+ Capability detection gates the remaining AGENTS bridge. Existing files are preserved; use analyze and reviewed recommendations to address older scaffold output.
86
80
 
87
81
  ### 3b. Direct CLI (deterministic / non-interactive)
88
82
 
@@ -203,13 +203,18 @@ Notable commands introduced in the current CLI surface:
203
203
  - `oat project closeout-check <project-path> [--autonomous] [--json]` - read-only check of the closeout invariant: a closeout that must snapshot its post-implementation sequence cannot reach terminal completion until its `oat_post_implement_sequence` snapshot exists, every stored step is recorded complete, approval is recorded, and the snapshot reached `status: complete`. A snapshot is required when the effective layered `workflow.postImplementSequence` is configured, when the closeout is autonomous (`--autonomous`, or `OAT_AUTONOMOUS=1` in the environment even without the flag), or when `oat_workflow_mode` is `lite`. Once a snapshot exists its recorded state is authoritative and current configuration is not consulted. JSON output reports `status` (`complete`, `not_required`, or `incomplete`), the missing `invariant` (`snapshot_missing`, `snapshot_malformed`, `sequence_failed`, `pre_approval_step_pending`, `approval_pending`, `post_approval_step_pending`, or `sequence_not_complete`), `route` (`oat-project-implement` when incomplete), `nextOwner` (the next stored step and its skill, or the approval), and the evaluated `inputs`. An incomplete or malformed result exits 1. For a goal project (`oat_workflow_mode: goal`) the goal boundary is checked first and read-only: it requires `oat_goal_status: declared_met`, a valid exhaustive `oat_goal_outcome_audit`, resolved extractions, a successful `gh pr view` observation of every terminal delivery member, and delivery coverage of every accepted phase (each in a terminal delivery's effective scope with a passed, fresh integrated review and its persisted `exit_gate`); refusals report `goal_inputs_unreadable`, `goal_not_declared`, `goal_audit_invalid`, `goal_extraction_unresolved`, `goal_observation_failed`, or `goal_coverage_incomplete`, and `nextOwner` is `{ kind: "goal", skill, reasons }`, where each reason is `{ code, message, subject? }` and `skill` is the owner of the first reason: for example `not-declared` and `audit-invalid` route to `oat-project-goal`, `review-not-fresh` to `oat-project-review-provide`, `exit-carrier-not-fresh` to `oat-project-implement`, delivery and endpoint reasons such as `endpoint-unmet` to `oat-project-pr-progress`, and `phase-uncovered` to `oat-project-pr-final`. A goal snapshot may record its `pr` step as satisfied by delivery coverage (`satisfied_by: { pr: delivery-coverage }`) only once `pr` is in the completed prefix.
204
204
  - `oat project delivery refresh --project <path> [--json]` - goal only. Observes every registered delivery member with `gh pr view <url> --json state,headRefOid,baseRefOid` and persists, in `state.md`, only the observations (`observed_head`, `observed_base`, member `status`), the delivery `status` (`open` or `at_endpoint`), the first observed `endpoint_attainment`, and derived staleness (`integrated_review.disposition: stale`, the milestone exit carrier's `freshness: stale` with `freshness_reason`). It never rewrites a reviewed revision, a member base, or the first endpoint attainment, never writes `oat_milestone_status` or `oat_goal_recovery`, and never manufactures a passed review or a fresh carrier. `oat-project-pr-progress` and `oat-project-goal` run it before registration and re-alignment.
205
205
  - `oat project delivery check --project <path> --subject <mNN|dNN> [--json]` - goal only, read-only. Reports whether a milestone (before registration, against the branch head) or a registered delivery (against its observed member revisions) is deliverable: a passed integrated review that is still fresh under the bookkeeping-successor rule and an allowed, fresh milestone exit carrier (reported as `exit.source: milestone-carrier`; the closeout boundary judges each delivery's persisted `exit_gate` instead). Evidence reviewed at R covers a later head only when every intervening commit changes permitted bookkeeping in this project's tracking files (`state.md`, `plan.md`, `implementation.md`, `project-log.md`, `summary.md`) and review artifacts (including those of deliveries sharing the same member pull request); any change to `summary.md` is bookkeeping because it is derived memory, never the authority for the brief's content; code changes, edits to approved brief content, and a substantive change followed by its revert fail. JSON output carries `status` (`ok` or `undeliverable`), the subject, its ordered `scope`, `publishedHeads`, `review`, `exit`, and `deliverable`; an undeliverable subject exits 1 with the full report. A stale `review` or `exit` result carries a `reason` that starts with a code, such as `review-missing`, `review-scope-narrow`, `member-unobserved`, `base-changed`, `bound-revision-mismatch` (a bound revision differs from its member's set-once `reviewed_head`), `subject-changed`, `configuration-changed`, or a bookkeeping-successor failure: `missing-revision`, `missing-object`, `not-ancestor`, `inspection-failed`, `disallowed-path`, or `substantive-change`.
206
- - `oat project complete-state <project-path> [--archived] [--autonomous]` - apply the canonical completed-state mutation to a project's `state.md`; used by `oat-project-complete` during lifecycle closeout. It first evaluates the same closeout invariant as `oat project closeout-check` and refuses, with the same message and without writing, a configured, autonomous, or lite closeout whose snapshot is absent, malformed, or incomplete. A project whose implementation finished before closeout snapshots existed recovers by running `oat-project-implement`, which persists the snapshot (`completion-and-closeout.md` Step 15) and completes its stored steps; there is no override flag. An unconfigured, interactive, non-lite closeout without a snapshot completes as before. A goal project is also refused, without writing, by the goal boundary that `closeout-check` describes.
207
- - `oat project archive [project-path] [--project-recap-run <project-relative-path>] [--no-commit]` - archive a tracked project through the same local move, summary export, and configured S3 upload path used by completion. When omitted, the project path falls back to the active project. The optional recap path must identify a `project-recap` run inside the project's `explainers/` directory. Archive verifies the complete selected package and every immutable file byte, then atomically exports one self-contained `.oat/repo/reference/project-recaps/<YYYYMMDD-project-slug>.html` page before deleting the active project. The full original package remains in the archived project. JSON `projectRecapExport` identifies `runId`, `page.sourceRelativePath`, `page.originalSha256`, `page.exportedSha256`, `verifiedArtifactCount`, and the flat `exportRoot`. No tracked sidecar is created. Matching dated pages are adopted on retry; conflicting destinations, incomplete inventory coverage, stale bytes, path escapes, and recipe mismatches fail without removing the active project. Summary and PR links point to the tracked page. For synced projects, a configured S3 upload must succeed before terminal cleanup. Successful closeout makes `refs/oat/completed/<project>` authoritative, deletes the tracked JSON record and nested checkout, and leaves archive metadata sufficient for an idempotent recordless retry. With `--json`, the terminal receipt reports `completedRef`, `verifiedSourceSha`, whether `activeAliasDisposition` was `retained` or `removed`, whether `recordRetired` completed, and the parent `lifecycleCommit`. `--no-commit` is a manual/library-only option: for a synced project it still removes the checkout but deliberately leaves `lifecycleCommit` null. Never pass it through `oat-project-complete`, which requires that receipt.
208
- - `oat repo archive sync [project-name]` - hydrate archived project snapshots from the configured repo-scoped S3 archive into `.oat/projects/archived/`. The old `oat project archive sync` path remains as a deprecated shim.
206
+ - `oat project complete-state <project-path> [--archived] [--autonomous]` - apply the canonical completed-state mutation to a project's `state.md`; used by `oat-project-complete` during lifecycle closeout. It first evaluates the same closeout invariant as `oat project closeout-check` and refuses, with the same message and without writing, a configured, autonomous, or lite closeout whose snapshot is absent, malformed, or incomplete. A project whose implementation finished before closeout snapshots existed recovers by running `oat-project-implement`, which persists the snapshot (`completion-and-closeout.md` Step 15) and completes its stored steps; there is no override flag. An unconfigured, interactive, non-lite closeout without a snapshot completes as before. A goal project is also refused, without writing, by the goal boundary that `closeout-check` describes. When the project has an `implementation.md`, `complete-state` then runs the final journal evaluator (`oat project journal check --at completion`) on the same bytes immediately before its write, and refuses with the evaluator's reasons, writing nothing, when the journal does not hold its terminal shape; an override line covers only its eligible gap and never the closeout invariant. A project with a `plan.md` but no `implementation.md` is refused with `journal-missing`; only a plan-less project completes on the closeout invariant alone.
207
+ - `oat project archive [project-path] [--project-recap-run <project-relative-path>] [--no-commit] [--new-generation <reason>]` - archive a tracked project through the same local move, summary export, and configured S3 upload path used by completion. When omitted, the project path falls back to the active project. The optional recap path must identify a `project-recap` run inside the project's `explainers/` directory. Archive verifies the complete selected package and every immutable file byte, then atomically exports one self-contained `.oat/repo/reference/project-recaps/<YYYYMMDD-project-slug>.html` page before deleting the active project. The full original package remains in the archived project. JSON `projectRecapExport` identifies `runId`, `page.sourceRelativePath`, `page.originalSha256`, `page.exportedSha256`, `verifiedArtifactCount`, and the flat `exportRoot`. No tracked sidecar is created. Matching dated pages are adopted on retry; conflicting destinations, incomplete inventory coverage, stale bytes, path escapes, and recipe mismatches fail without removing the active project. Summary and PR links point to the tracked page. For synced projects, a configured S3 upload must succeed before terminal cleanup. Successful closeout makes `refs/oat/completed/<project>` authoritative, deletes the tracked JSON record and nested checkout, and leaves archive metadata sufficient for an idempotent recordless retry. With `--json`, the terminal receipt reports `completedRef`, `verifiedSourceSha`, whether `activeAliasDisposition` was `retained` or `removed`, whether `recordRetired` completed, and the parent `lifecycleCommit`. `--no-commit` is a manual/library-only option: for a synced project it still removes the checkout but deliberately leaves `lifecycleCommit` null. Never pass it through `oat-project-complete`, which requires that receipt. Retry identity: one read-only evaluator, shared by apply and `--dry-run`, resolves the archive before any write. An identical retry (the project's retained-artifact manifest matches exactly one same-scope archive) reuses that snapshot's local path, dated export identity (summary export file and S3 key) and receipt on any later date, and a source-absent retry resumes the single same-scope archive; changed content, several matching archives, or an unverifiable non-empty directory at the archive path refuse before export, copy, overwrite or S3 upload, with follow-up-project guidance. The dry-run reports the identity the apply would use. `.oat-archive-source.json` records `manifestHash` and `generation` beside the project name, scope, snapshot and synced source SHA. The exported summary rewrites `oat-project:<project>#<entry-id>` locators to `oat-archive:<snapshot>#<entry-id>` and turns relative `project-log.md` or `oat-execution-learnings.md` links into plain text; see [Archive identity](project-artifacts.md#archive-identity). `--new-generation <reason>` archives reopened work of a shared or local project as the next generation instead of refusing it: it requires a non-empty single-line reason and exactly one latest generation of the same project and scope as predecessor (otherwise it refuses), never overwrites that predecessor, and persists the new generation (`<project>-gN` locally, `<YYYYMMDD>-<project>-gN` as export identity; when the same project's archive from another scope already holds that path or identity, both carry the scope: `<project>-gN-<scope>` and `<YYYYMMDD>-<project>-gN-<scope>`) with its predecessor, reason and `generationRequest` id before any export, copy or S3 side effect, so a retry reuses it. Replaying the same predecessor and content resolves to the same generation; synced projects refuse the option. JSON adds `generation` and `predecessorSnapshot`, and `--dry-run` reports the proposed generation without writing it.
208
+ - `oat repo archive sync [project-name]` - hydrate archived project snapshots from the configured repo-scoped S3 archive into `.oat/projects/archived/`. A name resolves as an exact snapshot, then a full generation name such as `demo-g2`, then the project (or `<project>-<scope>` family), restoring its latest generation and then its latest date; see [Project Artifacts](project-artifacts.md) for the `<project>[-gN][-<scope>]` naming contract. The old `oat project archive sync` path remains as a deprecated shim.
209
209
  - `oat project dispatch record --event-file <json-file-or-dash>` - validate one generic dispatch record plus its namespaced OAT evidence event and print the result with `status: validated-only`. The command writes nothing; launches are recorded in the calling workflow's run record. Managed, effort-pinned Claude launches run it before launch: the input carries `claudeLaunch` with the real resolver result, generated definition, and proposed payload, plus `recordBase` and `event`. The command validates their agreement and derives the configured invocation fields; callers cannot copy those fields into `recordBase`. One validation run reports every violation across `claudeLaunch`, `recordBase`, and `event` in a single error message, one `stage path: message` line each; the `recordBase` cross-field rules run even when a required field is missing, checks that need a value that failed to parse are skipped and named on a final line, secret-shaped values and absolute paths are scrubbed from the message, and the exit code stays 1. A validated input per role is published at `.agents/skills/oat-dispatch-subagents/references/managed-claude-example.json`. The command validates evidence only — it never launches a provider. A `runtime-observation` event may carry either a finished `observation` or the provider `metadata` envelope (`provider`, `observedAt`, `entries`) to normalize, but not both. `entries` may be raw provider output: they are projected through the owning parser's allowlist, are never echoed in the output, and both forms have their `match` derived from the record's configured invocation rather than trusted from the caller, with the observation's `provider` bound to the record's. With `--json`, the result adds `runtimeIdentity` with separate `configured` and `observed` objects plus a `match` of `matching`, `mismatching`, `not-comparable`, or `null`; observation is corroboration only and never overrides configured invocation. Error output is redacted on a best-effort basis; absolute paths in identity fields are rejected outright, while some prose forms (colon-prefixed, URL routes) can survive. See [Evidence Layers](../workflows/advanced/evidence-layers.md).
210
+ - `oat project dispatch record --event-file <json-file-or-dash> --format line [--dispatch-stamp <line>]` - print the one-line journal run record for the same validated, redacted record and event (projection `run/v1`), and write nothing; standard input still works. The line is `run/v1` followed by named fields in a fixed order, joined by a space-padded `·`: `request`, `scope`, `action`, `role`, configured `target`, `model` and `effort`, `stamp` (the formal `Dispatch:` stamp passed verbatim through `--dispatch-stamp`; a stamp without the canonical prefix is refused), `launch` (`planned`, `accepted`, or `blocked-before-start`), the raw child `outcome`, `terminal` (`yes` or `no`) and its `class` (`completed`, `terminal-stop`, `blocked-before-start`, `live`, or `unrecognized`), `continuation` references, and the optional `observed` identity with its `match`, which never replaces the configured fields. Inside a value, `\\` is a literal backslash and `\·`, `\~`, `\n`, and `\r` escape the delimiter, a tilde, a newline, and a carriage return; a bare `~` is null. Terminality comes from one producer-to-outcome mapping: a successful completion (`completed`, `DONE`, `DONE_WITH_CONCERNS`), a terminal stop (`BLOCKED`, `failed`, `cancelled`, `INVALID_RUN_ABORT`) and `blocked-before-start` are terminal; `planned`, `running`, `pending`, and `NEEDS_CONTEXT` with its handle still open are not, and an outcome outside the mapping is `unrecognized`, never success. The owning skill writes one line per request id under `## Orchestration Runs` and updates it in place. `--json` keeps `status: validated-only`, the record and `runtimeIdentity`, and adds `runLine` (`version`, `line`, `fields`, `classification`, `terminal`).
210
211
  - `oat project dispatch canonical-role --role <name> --request-id <id> --skill-dir <dir> [--json]` - resolve a canonical role through the loaded, user (`$HOME/.agents`), and project (`<repo>/.agents`) tiers and print the `canonical-role-resolution` event that `oat project dispatch record` accepts unchanged: redacted `canonicalPath` and `selectedPath` in the form `<loaded|user|project>/agents/<name>.md`, the role's `contentDigest`, and `candidateMisses`. `--skill-dir` is required because the loaded tier is derived from the loaded skill's directory; a missing or invalid directory exits 1 with a redacted error. An unknown role prints `missing` evidence with its recovery commands. Read-only; the dependency is the `workflows` pack.
211
212
  - `oat project validate-plan --project-path <path>` - validates `oat_plan_parallel_groups` metadata in `plan.md`; exits non-zero on invalid. Lite plans must contain exactly one phase, declare no parallel groups, and give every Validation Criteria bullet either a backticked command or a `manual:` instruction. Brief plans (`oat_workflow_mode: brief`) are validated with the brief profile: phases need non-empty `**Intent:**` and `**Exit evidence:**`, a `**Provisional:**` value of `yes` or `no`, unique IDs, and a concrete first phase; `### Task` headings in a brief are reported as a warning, and taskless parallel groups are valid. Goal plans add the goal profile: `oat_plan_source: goal`, a valid `## Milestones` table (`goal-milestones-missing`, `goal-milestones-malformed`, `goal-duplicate-milestone`, `goal-milestone-empty`, `goal-milestone-unknown-phase`, `goal-phase-in-multiple-milestones`, `goal-phase-without-milestone`), no parallel group spanning milestones (`goal-group-crosses-milestone`), canonical persisted phase IDs (`goal-noncanonical-phase-id`), and no change to a shipped milestone or a registered delivery's frozen scope (`goal-shipped-milestone-changed`, `goal-delivered-scope-changed`); phases the journal marks `extracted` need no milestone. See [Implementation Execution](../workflows/projects/execution/implementation-execution.md#parallel-phase-groups).
213
+ - `oat project journal check --at <implement-preflight|review|completion> [--project <path>] [--scope pNN[,pNN]] [--json]` - read-only journal evaluator: it reads `plan.md`, `implementation.md`, and `state.md` and writes nothing. `implement-preflight` is implement's call before its Step 16: it validates the accepted task and phase evidence while the terminal headers and pointers Step 16 owns may still be unwritten. `review` requires an explicit `--scope` of phases the plan declares and ignores future phases; a live run line warns there instead of refusing. `completion` (oat-project-complete, before roll-up, seal, or any lifecycle write) also requires the terminal journal shape: journal `oat_status: complete` and a cleared `oat_current_task_id`, `state.md` `oat_phase_status` `complete` or `pr_open` and a cleared `oat_current_task`. Task modes read journal records through the shared heading-only reader (fenced and indented code excluded, a block ends at the next heading of equal or higher level): every plan task heading is unique and sits under its own phase (`plan-task-duplicate`, `plan-task-misplaced`, routed to the plan owner and never override-eligible), and every plan task has exactly one journal block in its phase with exactly one owned `**Status:** completed` and one owned `**Commit:**` SHA; tables and checklists are never completion evidence, and overview totals must match. Brief and goal read phase units: an accepted phase carries its `**Head:**`, execution records close as `completed` with a commit or as `failed`, `cancelled`, or `no-change` without one, an extracted goal phase and a phase the goal outcome audit defers or retires stay valid and incomplete. Everywhere: `## References` is last, review receipts sit in their phase or `## Reviews and Gates`, deferrals in `## Deferred Findings`, dispatch payloads are refused unless marked `quoted-evidence`, every run line parses as `run/v1` under `## Orchestration Runs`, carries a valid `request` identifier, and is terminal at implement-preflight and completion, and no template placeholder survives, including one left in an inline-code slot such as ``- `{path}` - …`` unless the line is marked `quoted-evidence`. An override is one line under `## Deviations from Plan / Design`: `**Override:** <scope-disposition-approved|evidence-lost|operator-accepted-gap> · **Authorized by:** <decision id> · **Scope:** <pNN-tNN|pNN> · <reason>`; it covers only a missing task block, an incomplete task, missing commit evidence, or (for `scope-disposition-approved`) an unaccepted phase within its scope, and a malformed or misplaced override is refused. Output is `{ status: ok | refused, reasons: [{ code, path, line, owner, message }], warnings, overrides }`; a refusal exits 1. Delivery coverage and the post-implementation sequence stay with `closeout-check`.
212
214
  - `oat project log append|check|synthesize|rollup` - manage the optional append-only project observation log: append validated judgment or structural entries, inspect grammar and synthesis status, complete end-of-run synthesis, and roll observations into `summary.md` plus the configured repository ledger. See [Project Log](../workflows/projects/execution/project-log.md).
215
+ - `oat project log append --category <category> --source <id> [--origin <producer>]` - record a learning on a judgment entry. The category is one of `gotcha`, `efficiency`, `documentation-gap`, `candidate-skill-content`, `decision`, or `environment-limited`; any other value, `--category` without `--source`, a `--source` containing whitespace, and these flags on a `--structural` entry are refused. The flags write a `**Category:**`, `**Source:**`, `**Origin:**`, `**Recorded:**` body head above the body; the heading grammar is unchanged and an entry without them is stored as before. Passing the source id as `--idempotency-key` makes a retry report `already-appended` and write nothing.
216
+ - `oat project log check` - JSON adds `learnings`: `legacy` when the project still has `oat-execution-learnings.md`, which summary and retro read after the log, and `none` otherwise, in every status.
217
+ - `oat project log rollup [--json]` - writes a bounded Workflow Observations digest, not a copy: judgment entries only (structural entries are counted, never rendered), newest first with `decision` and `gotcha` ahead, capped by `workflow.projectLogDigest.maxEntries` and `.maxLines` with an omitted-count trailer, one concise item per entry carrying the non-link locator `oat-project:<slug>#<entry-id>`, and live project paths labelled. `summarySection` is `written`, `updated`, or `omitted` (no judgment entry: an existing section is removed and none is created). `entriesRolledUp` counts every entry read. JSON adds `digest` with the bounds, `rendered`, `omitted` (`overBound`, `structural`, `malformed`), the over-bound `omittedEntries` tokens and `byProducer` counts. Ledger graduation still reads the complete judgment set.
213
218
  - `oat project set-mode` — deprecated no-op. Execution mode is no longer user-selectable; emits a deprecation warning and preserves the `--json` contract.
214
219
  - `oat gate review <prompt...>` - run a stateful, headless OAT review through the target registry, parse the produced review artifact, and exit nonzero for configured blocking findings. `--timeout-ms <milliseconds>` overrides target, `workflow.gateTimeouts`, environment, and scope defaults; accepted values are 1,000–14,400,000. Final/phase/range code reviews and artifact reviews default to 30 minutes, while task code reviews default to 15 minutes. With `--json`, the result envelope on exit is the canonical completion signal: `status` is `ok` | `blocked` | `review_failed` | `artifact_missing` | `artifact_validation_failed` | `targeting_correlation_failed`, alongside `runId`, `generatedAt`, and `artifactPath` when available. `artifact_missing` means an accepted child exited cleanly without an artifact; fix synchronous review/artifact completion and start a new run, without review-receive or same-run remediation. For `targeting_correlation_failed`, correct the project declaration or artifact routing and start a new run; do not run review-receive even if an artifact path is present. For `artifact_validation_failed`, correct the artifact and rerun the gate until it revalidates as `ok` or `blocked`. Invoke `oat-project-review-receive` only when all three conditions hold: `status` is `ok` or `blocked`, `receiveEligible` is `true`, and `handoff` is non-null. `review_failed` may include structured `refusal`, `noOutputProduced`, and metadata-only `activityEvidence`; these diagnostic fields never make a run receive-eligible. After a timeout, a validated run-correlated artifact returns the ordinary `ok` or `blocked` envelope with additive `lateCompletion: true`. When post-selection work fails after the reviewer already committed a run-correlated artifact, the gate re-validates that selected snapshot through the same eligibility path rather than re-parsing whatever the path now holds, never re-dispatching, and returns the ordinary `ok` or `blocked` envelope with additive `postSelectionRecovery: true`; the artifact must still be present and unchanged for re-validation to succeed. When nothing recovers, `review_failed` names the failing sub-step in `postSelection.step` and its cause in `postSelection.code`. Duplicate run-ID matches or a changed artifact with a mismatched run ID retain `targeting_correlation_failed` and `receiveEligible: false`. Orchestrators should read the structured result rather than poll the filesystem. See [Workflow Gates](../workflows/advanced/workflow-gates.md).
215
220
  - `oat gate route --expect-runtime <runtime> --expect-model <model> --can-await <true|false> --json` - return the headless child route (`inline`, `delegate-sync`, or `refuse`) from provider-marker and model evidence. Ambiguous or contradictory evidence never routes inline.
@@ -731,6 +731,8 @@ Workflow preference keys live under the `workflow.*` namespace:
731
731
  - `workflow.autoArtifactReview.analysis` — boolean, default `true`. Automatically run the bounded accuracy-review loop for generated docs and agent-instructions analysis artifacts before the matching apply workflow consumes them.
732
732
  - `workflow.projectLog` — `auto`, `true`, or `false`; default `auto`. `auto` creates the append-only `project-log.md` on the first lifecycle append, `true` also enables scaffold-time creation, and `false` skips appends when no log exists. An existing artifact remains enabled regardless of the current setting.
733
733
  - `workflow.projectLogLedgerPath` — repository-relative string; default `.oat/repo/reference/project-observations.md`. Sets the durable ledger target for `general` judgments written by `oat project log rollup`.
734
+ - `workflow.projectLogDigest.maxEntries` — positive integer; default `12`. The most judgment entries `oat project log rollup` renders in the `## Workflow Observations` digest it writes into `summary.md`; entries beyond the bound are counted, not copied, and every `general` judgment still graduates to the ledger.
735
+ - `workflow.projectLogDigest.maxLines` — positive integer; default `60`. The most rendered lines in that digest. The bound counts the omitted-count trailer and the cross-reference line (two lines each with their blank separator), which are reserved before any item is placed, so the minimum useful value is about 6: a two-line first item plus that reserve. Below it the digest renders no item, only the trailer and cross-reference; at `1` or `2` the cross-reference is left out (and at `1` the trailer is the whole section), so the bound always holds. Both bounds sit beside `workflow.projectLog` rather than inside it and resolve independently of it (local > shared > user > default); a value that is not a positive integer is refused by `oat config set` and ignored when read from a config file, so the default applies.
734
736
  - `workflow.dispatchPolicy.mode` — `managed` or `inherit`. `managed` means OAT selects model/effort controls from `workflow.dispatchPolicy.policy`; `inherit` means OAT leaves controls to host/provider defaults.
735
737
  - `workflow.dispatchPolicy.policy` — `economy`, `balanced`, `high`, `frontier`, or `uncapped`. `economy` through `frontier` are capped managed policies; `uncapped` keeps OAT-managed preferred selection without provider caps. It is distinct from `workflow.dispatchPolicy.mode=inherit`, which leaves controls to the host/provider.
736
738
  - `workflow.dispatchCeiling.preset` — legacy compatibility alias (`balanced`, `maximum`, or `cost-conscious`) for capped managed policy setup.
@@ -836,6 +838,7 @@ oat config set workflow.dispatchCeiling.providers.cursor.high composer-2.5 --sha
836
838
  oat config set workflow.autoArtifactReview.plan false --shared
837
839
  oat config set workflow.projectLog auto --shared
838
840
  oat config set workflow.projectLogLedgerPath .oat/repo/reference/project-observations.md --shared
841
+ oat config set workflow.projectLogDigest.maxEntries 12 --shared
839
842
 
840
843
  # Repo-local: personal override for this repo (default when no flag)
841
844
  oat config set workflow.hillCheckpointDefault every
@@ -269,7 +269,7 @@ Completion and archive sync behavior:
269
269
  commits the tracked record as complete.
270
270
  - If `archive.s3SyncOnComplete=true` and `archive.s3Uri` is configured, completion must successfully upload a dated snapshot such as `<archive.s3Uri>/<repo-slug>/projects/20260401-<project>/` before it retires the active record and checkout.
271
271
  - `oat repo archive sync` syncs all repo archived projects down from S3 into `.oat/projects/archived/`.
272
- - `oat repo archive sync <project-name>` syncs the latest dated remote snapshot for a single project into `.oat/projects/archived/<project-name>/`.
272
+ - `oat repo archive sync <project-name>` syncs every generation family of a single project (the unqualified one and each scope-qualified `<project-name>-<scope>` one) at its latest generation, then latest dated remote snapshot, into its full local name: `.oat/projects/archived/<project-name>/` for generation 1, `.oat/projects/archived/<project-name>-gN/` for generation N, `.oat/projects/archived/<project-name>-gN-<scope>/` for a scope-qualified one. `<project-name>-<scope>` selects only that family; an exact snapshot name or a full `<project-name>-gN[-<scope>]` name selects that archive instead.
273
273
  - Default archive sync is non-destructive toward unrelated local-only archive data, but it does replace a local project archive when a newer dated remote snapshot is selected for that same project.
274
274
  - `oat project prune` is separate and destructive: for a terminal project it
275
275
  removes the completed ref and any matching active alias, while leaving local
@@ -45,7 +45,7 @@ archive metadata own terminal reachability and retry identity.
45
45
  - `spec.md`: requirements + acceptance criteria
46
46
  - `design.md`: architecture and implementation approach (full in spec-driven mode; optional lightweight version in quick mode covering architecture, components, and testing strategy)
47
47
  - `plan.md`: phase/task breakdown and review tracking
48
- - `implementation.md`: execution log, verification, final summary
48
+ - `implementation.md`: the execution journal — phase sections with task blocks, run lines, review and gate receipts, deferred findings, deviations, and the final summary (see [The implementation journal](#the-implementation-journal))
49
49
  - `summary.md`: institutional memory artifact — generated from project artifacts at closeout, used as PR description source and archive cover page
50
50
 
51
51
  Mode-sensitive notes:
@@ -146,6 +146,144 @@ brief and journal targets must match. The outcome audit requires the child to
146
146
  be complete or its outstanding obligation to carry an approved deferral, and
147
147
  promotion of the goal to quick refuses any extracted phase.
148
148
 
149
+ ## The implementation journal
150
+
151
+ `implementation.md` has fixed slots, and every writer targets them:
152
+
153
+ - **Phase sections** (`## Phase …`) hold each phase's `**Status:**`, one
154
+ `### Task pNN-tNN:` block per plan task with exactly one `**Status:**` and,
155
+ once completed, one `**Commit:**` SHA (brief and goal: execution records and
156
+ the phase's `**Base:**`/`**Head:**` anchors), one free-text verification
157
+ line, and the phase's review receipt. Tables and checklists are display,
158
+ never completion evidence.
159
+ - `## Orchestration Runs` holds one run line per dispatch request ID, rendered
160
+ by `oat project dispatch record --format line` (`run/v1 · request=… · stamp=Dispatch: … · launch=… · outcome=… · terminal=…`)
161
+ and updated in place with the terminal outcome. Record and event JSON is
162
+ never pasted into the journal.
163
+ - `## Reviews and Gates` holds final and multi-phase review receipts and one
164
+ terminal line per gate run (`**Gate:** … · **Scope:** … · **Outcome:** …`).
165
+ `state.md` owns gate transitions; the journal keeps the outcome, waivers and
166
+ operator choices.
167
+ - `## Deferred Findings` holds one line per approved deferral, excluded
168
+ parallel phase, and unmerged worktree.
169
+ - `## Deviations from Plan / Design` holds deviations, exception blocks, and
170
+ override lines:
171
+ `**Override:** <scope-disposition-approved|evidence-lost|operator-accepted-gap> · **Authorized by:** <decision id> · **Scope:** <pNN-tNN|pNN> · <reason>`.
172
+ - `## Final Summary (for PR/docs)` is rewritten at closeout from observed
173
+ facts, and `## References` is always the last section.
174
+
175
+ A receipt carries the finding identity and substance, the disposition and its
176
+ rationale, the fix task or approved deferral it links to, and the final
177
+ outcome, so the journal and plan stand without the review file. Review paths
178
+ are local-only citations: reviews are not archived, so an unresolved review
179
+ path is never a completion defect. `oat project journal check` validates these
180
+ slots at implement's pre-Step-16 boundary, at review with an explicit phase
181
+ scope, and at completion; see the [CLI reference](cli-reference.md).
182
+
183
+ `oat-project-complete` writes `oat_pr_status_observed_at` (UTC) beside
184
+ `oat_pr_status` before archive: in an archived `state.md`, `oat_pr_status` and
185
+ `oat_pr_url` are observations at that time, not live PR state.
186
+
187
+ ## Archive identity
188
+
189
+ `oat project archive` (and completion's archive step) records each archive's
190
+ identity in `.oat-archive-source.json` inside the local snapshot: the project
191
+ name, its originating scope, the dated export identity `<YYYYMMDD>-<project>`
192
+ (the summary export file stem and the S3 key), the synced source-ref SHA where
193
+ one applies, the generation (`1` for the first archive), and `manifestHash`.
194
+ The manifest hash covers every retained file of the project as sorted
195
+ `<sha256> <path>` lines; it excludes the top-level `reviews/` and `pr/`
196
+ directories (review and PR evidence are process artifacts and are never
197
+ archived), a synced checkout's `.git`, and the archive-owned
198
+ `.oat-archive-source.json` itself, so a project and its archive hash equal.
199
+ One retention set defines the archive: the local copy, the manifest, the S3
200
+ upload and `oat repo archive sync` all leave out `reviews/`, `pr/` and `.git`,
201
+ so an archive restored from S3 hashes equal to the one that was uploaded.
202
+
203
+ A retry resolves to that identity before anything is written:
204
+
205
+ - an identical retry (the source's manifest matches exactly one archive of the
206
+ same project and scope) reuses its local snapshot, dated export identity, S3
207
+ destination and receipt, on a later date too;
208
+ - a retry whose source is gone resumes the single archive of that project and
209
+ scope;
210
+ - changed content, more than one matching archive, or a non-empty directory at
211
+ the project's archive path that does not identify itself refuses before any
212
+ export, copy, overwrite or S3 upload, and points reopened work at a
213
+ follow-up project;
214
+ - the same slug from a different scope is a separate identity; when the other
215
+ archive already holds the project's archive path or the dated export
216
+ identity, the new one is qualified with the scope in both: local path
217
+ `<project>-<scope>` and export identity `<YYYYMMDD>-<project>-<scope>`. An
218
+ empty directory at the archive path is reused. Local paths always derive
219
+ from the identity, never from the clock.
220
+
221
+ Reopened work can instead be archived as a new generation with
222
+ `oat project archive --new-generation <reason>` (shared and local projects).
223
+ The option needs exactly one latest generation of the same project and scope as
224
+ its predecessor and refuses otherwise. The new generation lives at
225
+ `<project>-gN` with export identity `<YYYYMMDD>-<project>-gN`. Both carry the
226
+ scope (`<project>-gN-<scope>` and `<YYYYMMDD>-<project>-gN-<scope>`) when the
227
+ predecessor's own name carries it, so a family qualified at its first archive
228
+ stays qualified in every generation, or when the same project's archive from
229
+ another scope already holds that path or identity. Anything else at the path refuses. `oat repo
230
+ archive sync` reads the same `<project>[-gN][-<scope>]` contract: by name,
231
+ `<project>-<scope>` restores that scope's latest generation and `<project>`
232
+ restores every family of the project at its latest generation. Its
233
+ metadata records `predecessor`, `generationReason` and `generationRequest`, the
234
+ `sha256` of the project, scope, predecessor snapshot and manifest. That
235
+ metadata is written with `allocation: pending` before any export, copy or S3
236
+ upload, so an interrupted run resumes the same generation; the marker is
237
+ removed once the copy completes. A first archive writes the same pending
238
+ marker. The marker exists so an interrupted run resumes the same identity: a
239
+ run killed mid-copy leaves a pending allocation that the next identical archive
240
+ resumes. OAT does not serialize concurrent archive runs of one project and does
241
+ not attempt to. A stray occupant that is not this run's archive (content at the
242
+ path when the marker would be written) refuses as `archive-occupant-unverifiable`
243
+ and is not touched, and an archive whose metadata is final is never removed or
244
+ overwritten. Running the request again with the same
245
+ content resolves to the same generation, while changed content after it
246
+ completes becomes the next generation. Without the option, changed content
247
+ still refuses.
248
+
249
+ `--dry-run` runs the same read-only evaluation and reports the identity an
250
+ apply would use, so a retry previews the persisted snapshot rather than
251
+ today's date. The synced protections (recordless retry by completed ref,
252
+ stale-source refusal, exact project-root checks) are unchanged.
253
+
254
+ Every refusal fails closed before any write. Its message starts with a stable
255
+ reason code, and `--json` reports the same code as `code` in the error object:
256
+
257
+ | Code | Refused when |
258
+ | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
259
+ | `archive-retry-ambiguous` | more than one same-scope archive matches the retry, or a persisted snapshot resolves to several local archives |
260
+ | `archive-retry-conflict` | the retained artifacts differ from the project's archive |
261
+ | `archive-occupant-unverifiable` | a non-empty directory at the archive path does not identify itself as this project; if it is a partial copy left by an interrupted archive from before pending allocations were written, inspect and remove it, then retry |
262
+ | `archive-generation-synced` | `--new-generation` was given for a synced project |
263
+ | `archive-generation-reason` | the `--new-generation` reason is empty, multi-line or longer than 200 characters |
264
+ | `archive-generation-source-absent` | `--new-generation` was given but the project directory is absent |
265
+ | `archive-generation-no-predecessor` | `--new-generation` found no archive of the project and scope |
266
+ | `archive-generation-ambiguous-predecessor` | more than one archive holds the latest generation |
267
+ | `archive-generation-pending` | the latest generation is still allocated but not copied |
268
+ | `archive-generation-path-occupied` | the `<project>-gN` path is held by something other than another scope's archive of the project (or its scope-qualified path is occupied) |
269
+ | `archive-synced-recordless-unbound` | a synced project without a record has no archive whose identity matches its authoritative completed ref |
270
+ | `archive-synced-recordless-ambiguous` | a synced project without a record has several archives matching its completed ref |
271
+ | `archive-retry-candidate-damaged` | the matched archive's current bytes no longer match the manifest recorded when it was written (or the project it would replace); restore it from S3 (`oat repo archive sync <snapshot> --force`, naming the archive's exact snapshot) or backup, then retry |
272
+
273
+ When `--new-generation` content is identical to an existing archive, the
274
+ command resolves to that generation and warns that no new generation was
275
+ allocated, naming the persisted reason when that archive was itself an
276
+ explicit generation (otherwise the warning says the reason was not recorded).
277
+
278
+ The exported summary finalizes source locators: each
279
+ `oat-project:<project>#<entry-id>` token becomes
280
+ `oat-archive:<YYYYMMDD>-<project>#<entry-id>`, and a relative link to the
281
+ archived-only `project-log.md` or legacy `oat-execution-learnings.md` becomes
282
+ plain text naming the archive identity. A relative link into `reviews/` or
283
+ `pr/` becomes its label plus the review or PR artifact file name, marked local
284
+ to the project and not archived, since neither is ever archived; external
285
+ links are kept. The summary inside the archive keeps its original bytes.
286
+
149
287
  ## Blockers in state.md
150
288
 
151
289
  `oat_blockers` accepts legacy reason strings and structured workflow records:
@@ -176,7 +314,8 @@ or the state refresh command's existing raw-frontmatter handling.
176
314
 
177
315
  ## Supporting artifacts
178
316
 
179
- - `summary.md`: generated by `oat-project-summary` — re-runnable, tracks its own state via frontmatter for incremental updates after revisions
317
+ - `summary.md`: generated by `oat-project-summary` — re-runnable, tracks its own state via frontmatter for incremental updates after revisions. Its `## Workflow Observations` section is written only by `oat project log rollup`: a bounded digest of judgment entries, omitted when none qualifies
318
+ - `project-log.md`: the append-only observation log, written only with `oat project log append`. Learnings from autonomous, cloud and goal runs are judgment entries whose body opens with `**Category:**`, `**Source:**`, `**Origin:**` and `**Recorded:**` lines (see [Project Log](../workflows/projects/execution/project-log.md)). A legacy `oat-execution-learnings.md` from an older project is still read by summary and retro after the log, and no new run creates one; with the log disabled, learnings are not recorded
180
319
  - `reviews/*.md`: phase/final review files
181
320
  - `pr/*.md`: generated PR descriptions
182
321
  - `references/imported-plan.md`: preserved source plan for import mode
@@ -77,9 +77,9 @@ Typical progression:
77
77
  8. Ready for implement
78
78
  9. Implement in progress
79
79
  10. Implement complete (final review passed)
80
- 11. PR open (`pr_open`) — post-PR review posture; actual PR existence is tracked via `oat_pr_status` / `oat_pr_url`
80
+ 11. PR open (`pr_open`) — post-PR review posture; actual PR existence is tracked via `oat_pr_status` / `oat_pr_url`. `pr_open` is a valid posture for the completion journal check
81
81
  12. Revision loop (optional): `pr_open` → revise → `in_progress` → implement → `pr_open`
82
- 13. Complete
82
+ 13. Complete — `oat project journal check --at completion` passes (terminal journal shape: every plan task block completed with commit evidence or an authorized override, terminal run lines, receipts and deferrals in their slots, no template residue), then `oat project complete-state` rechecks the closeout invariant and that evaluator before it writes; `oat_pr_status_observed_at` records when the archived PR fields were observed
83
83
 
84
84
  Lite progression:
85
85
 
@@ -230,22 +230,39 @@ sequences retain their documented meaning.
230
230
 
231
231
  ## Execution-learnings loop
232
232
 
233
- Autonomous runs keep an append-only project-local
234
- `oat-execution-learnings.md`. Dated entries record an observation, impact, and
235
- recommendation under the source taxonomy: `gotcha`, `efficiency`,
233
+ Autonomous runs record learnings in the project log, not in a separate file.
234
+ Each learning is a judgment entry written with `oat project log append`
235
+ carrying `--category` (the source taxonomy: `gotcha`, `efficiency`,
236
236
  `documentation-gap`, `candidate-skill-content`, `decision`, or
237
- `environment-limited`.
238
-
239
- When the file exists, `oat-project-summary` synthesizes actionable
240
- recommendations into `## Autonomous Execution Learnings`, grouped as:
237
+ `environment-limited`), a stable per-observation `--source` id that is also
238
+ the `--idempotency-key`, and `--origin oat-project-autonomous`. The category
239
+ maps to the judgment type: `gotcha` and `environment-limited` become
240
+ `friction`, `efficiency` and `candidate-skill-content` become `worked-well`,
241
+ and `documentation-gap` and `decision` become `feedback`. The body records an
242
+ observation, impact, recommendation and, where it applies, uncertainty. A
243
+ retried write with the same source id appends nothing. `oat-cursor-cloud-projects`
244
+ and `oat-project-goal` use the same write with their own origin.
245
+
246
+ When the project log is disabled (`workflow.projectLog: false`) and
247
+ `project-log.md` does not exist yet, the append creates nothing: the producer
248
+ prints one warning line and continues, and no learning is persisted anywhere.
249
+ The flag only stops the log's creation; an existing `project-log.md` keeps
250
+ accepting learnings. No
251
+ producer creates `oat-execution-learnings.md` any more; summary and retro
252
+ still read an existing legacy file after the log.
253
+
254
+ When category-bearing entries (or a legacy file) exist, `oat-project-summary`
255
+ synthesizes actionable recommendations into `## Autonomous Execution
256
+ Learnings`, grouped as:
241
257
 
242
258
  - agent-instruction updates;
243
259
  - cloud-environment improvements;
244
- - code follow-ups;
260
+ - code follow-ups; and
245
261
  - workflow issues.
246
262
 
247
- Each recommendation links back to its source entry. Projects without the
248
- learnings file render normal summaries with no autonomous-learnings section.
263
+ Each recommendation names its source entry with a plain-text
264
+ `oat-project:<slug>#<entry-id>` token rather than a link. Projects without
265
+ learnings render normal summaries with no autonomous-learnings section.
249
266
  The summary export keeps the synthesized recommendations after project
250
267
  archival.
251
268
 
@@ -279,7 +296,7 @@ gates or creating another implementation coordinator.
279
296
  > [!WARNING]
280
297
  > **What it does without asking:** after every lifecycle phase, an autonomous
281
298
  > run commits its work and pushes the current branch to its remote (never with
282
- > force). It also commits its own state and learnings-log updates, dispatches
299
+ > force). It also commits its own state and project-log learning updates, dispatches
283
300
  > worker and reviewer subagents under one authorization for the whole run,
284
301
  > generates a project recap, and opens the final pull request. None of these
285
302
  > steps asks for confirmation. It never merges the pull request.
@@ -352,7 +369,7 @@ a product-judgment boundary. A brief records no HiLL checkpoints unless it
352
369
  lists phases explicitly.
353
370
 
354
371
  **Expected output:** Session-only autonomy signals, persisted lifecycle
355
- progress, reviewed task commits, and project-local execution learnings. Existing
372
+ progress, reviewed task commits, and category-bearing project-log learnings. Existing
356
373
  projects retain their mode. A successful run reports the actual final PR and
357
374
  review evidence. A blocked run names the boundary, durable completed work,
358
375
  operator action, and resumable project.
@@ -121,8 +121,8 @@ For skills, compare frontmatter versions as a freshness check:
121
121
 
122
122
  - user version at or above the repository version is the expected state;
123
123
  - a higher repository version is an environment anomaly;
124
- - even in that anomaly, keep the user copy as the execution source, log the
125
- mismatch in `oat-execution-learnings.md`, and refresh the user tier before
124
+ - even in that anomaly, keep the user copy as the execution source, record the
125
+ mismatch as a project-log learning, and refresh the user tier before
126
126
  safety-critical work.
127
127
 
128
128
  Version comparison verifies provisioning. It never switches execution to the
@@ -150,13 +150,27 @@ For an explicitly autonomous cloud run:
150
150
  3. Invoke `oat-project-autonomous`; it activates the session-scoped autonomy
151
151
  signals.
152
152
  4. Use the same policy boundaries and review contract as local autonomy.
153
- 5. Append cloud setup gaps, degraded checks, and freshness anomalies to the
154
- project-local execution-learnings log.
153
+ 5. Record cloud setup gaps, degraded checks, and freshness anomalies as
154
+ category-bearing learnings in the project log (see
155
+ [learnings](#learnings)).
155
156
 
156
157
  Missing credentials, repository-policy approval, destructive changes,
157
158
  unresolved blocking reviews, and material product ambiguity remain boundaries.
158
159
  See [Autonomous Project Execution](autonomy.md).
159
160
 
161
+ ## Learnings
162
+
163
+ The cloud skill records learnings with the same write as autonomous runs:
164
+ `oat project log append` with `--category` (one of `gotcha`, `efficiency`,
165
+ `documentation-gap`, `candidate-skill-content`, `decision`,
166
+ `environment-limited`), a stable per-observation `--source` id that is also
167
+ the `--idempotency-key`, and `--origin oat-cursor-cloud-projects`. A retried
168
+ write appends nothing. When the project log is disabled and does not exist yet, the append creates
169
+ nothing: the skill prints one warning line and continues, and the learning is
170
+ not persisted. An existing `project-log.md` keeps accepting learnings. It never creates `oat-execution-learnings.md`. See
171
+ [Autonomous Project Execution](autonomy.md#execution-learnings-loop) for the
172
+ category-to-type mapping and how summary reads the entries.
173
+
160
174
  ## Related
161
175
 
162
176
  - [Autonomous Project Execution](autonomy.md) — activation, boundaries, review,
@@ -196,8 +210,8 @@ stops.
196
210
  globally, and stops only if that install fails. If the active project is a
197
211
  synced project, it runs `oat project pull` to bring its artifacts into the
198
212
  checkout. When a repository skill is newer than the user-scope copy, or an
199
- expected skill, MCP server, CLI, or credential is missing, it appends an entry
200
- to the active project's `oat-execution-learnings.md`. It activates autonomy
213
+ expected skill, MCP server, CLI, or credential is missing, it records a
214
+ learning in the active project's `project-log.md`. It activates autonomy
201
215
  only by loading `oat-project-autonomous` when you explicitly asked for an
202
216
  autonomous end-to-end run.
203
217
 
@@ -180,6 +180,15 @@ This mechanism covers configured lifecycle skill gates only. It does not affect
180
180
  the optional `oat_phase_review_gate`, HiLL policy, or autonomous design-gate
181
181
  behavior, and it cannot disable every gate with one project-wide boolean.
182
182
 
183
+ ### Gate lines in the journal
184
+
185
+ `state.md` owns every gate transition (`pending`, `allowed`, `blocked`,
186
+ `stale`, waivers). `implementation.md` keeps one terminal line per gate run
187
+ under `## Reviews and Gates`, updated in place for that run:
188
+ `**Gate:** <gate> · **Scope:** <scope> · **Outcome:** <outcome> · <attempt, waiver or operator choice>`.
189
+ The journal line is evidence for readers; routing reads `state.md`. See
190
+ [Project Artifacts](../../reference/project-artifacts.md#the-implementation-journal).
191
+
183
192
  ### Implementation exit-gate closeout
184
193
 
185
194
  For `oat-project-implement`, the configured skill gate is a final, resumable
@@ -509,8 +509,11 @@ changed is kept. The `oat project log` command, not the skill, rolls project-log
509
509
  entries up into the Workflow Observations section. A project log the skill
510
510
  cannot read clearly is reported rather than treated as empty, and a sealed
511
511
  (closed) log accepts no new entries. An Autonomous Execution Learnings section
512
- appears only when the project has an `oat-execution-learnings.md` file with
513
- actionable recommendations. Recorded exit-gate waivers stay explicit; the
512
+ appears only when the project has actionable learnings: category-bearing
513
+ project-log entries written by autonomous, cloud or goal runs, or a legacy
514
+ `oat-execution-learnings.md` file from an older project, which is still read
515
+ after the log. New runs never create that file; with the project log disabled and never created they record no learnings,
516
+ and the summary has no such section. Recorded exit-gate waivers stay explicit; the
514
517
  skill does not infer them.
515
518
 
516
519
  **What it does without asking:** when the repository has adopted PJM, every
@@ -580,7 +583,11 @@ project (or keeps it until an archive succeeds), commits the completion
580
583
  bookkeeping, and pushes it. A yes to the PR question, or
581
584
  `workflow.createPrOnComplete: true` when no PR is tracked, creates a new PR
582
585
  against `main`. If a PR is already open, the skill updates its description
583
- with `gh pr edit` when archiving or for a synced project. A summary refresh
586
+ with `gh pr edit` when archiving or for a synced project. Archives keep no
587
+ `pr/` directory, so when archiving the skill carries the regenerated PR body in
588
+ a temporary file until the PR is created or updated; a run that resumes an
589
+ interrupted archive has no such body and reports that it skipped the
590
+ description sync. A summary refresh
584
591
  runs `oat-project-summary`, with its own commit and decision promotion, and an
585
592
  archive runs `oat project archive`, including an S3 upload when
586
593
  `archive.s3SyncOnComplete` is enabled.
@@ -605,8 +612,20 @@ non-archive completion. Shared and synced projects use the configured archive
605
612
  preference or an explicit answer.
606
613
 
607
614
  Completion changes lifecycle state through the `oat` CLI, checks whether the
608
- summary is current, runs any retro and recap work you selected, and seals
609
- (closes) the project log through the project-log command. When a shared or
615
+ summary is current (including the learnings fingerprint), runs any retro and
616
+ recap work you selected, and seals (closes) the project log through the
617
+ project-log command. Before any of that writes, it rewrites the journal's Final
618
+ Summary and `summary.md` prose from observed facts, runs the summary staged
619
+ (`staged: true`), and validates the journal with
620
+ `oat project journal check --at completion`; only when that passes does the
621
+ summary resume its roll-up (`resume: roll-up`). A refusal stops completion with
622
+ the reason, line and owner: the prose refresh may remain, but no promotion
623
+ append, roll-up, ledger graduation, seal, archive or lifecycle change happens.
624
+ An authorized override is written as one line under
625
+ `## Deviations from Plan / Design` (idempotent on code, scope and decision id),
626
+ never by an autonomous run, and never bypasses the closeout invariant. Before
627
+ archive, completion records `oat_pr_status_observed_at` beside
628
+ `oat_pr_status`. When a shared or
610
629
  synced project will be archived, the active project stays set until the
611
630
  archive succeeds, so an archive or S3 failure leaves the completion
612
631
  resumable. Every other completion clears the active project right away. Synced
@@ -28,8 +28,12 @@ in the project log when that log exists.
28
28
 
29
29
  Evidence is read in this order:
30
30
 
31
- 1. `project-log.md`
32
- 2. `oat-execution-learnings.md`, when present
31
+ 1. `project-log.md`, including the unified learnings: judgment entries whose
32
+ body opens with a `**Category:**` head, written by autonomous, cloud and
33
+ goal runs
34
+ 2. `oat-execution-learnings.md`, the legacy learnings file, when present; an
35
+ entry that is a proven twin of a unified entry (same recorded timestamp,
36
+ category and title) is read once
33
37
  3. Lifecycle artifacts such as `implementation.md`, `state.md`, `plan.md`,
34
38
  design and discovery artifacts, reviews, and evidence ledgers
35
39
  4. The current session or run transcript when the environment makes it
@@ -89,9 +89,12 @@ The root does not implement phase tasks while an accepted phase launch owns
89
89
  that scope.
90
90
 
91
91
  Before a native launch, the root constructs and redacts the complete generic
92
- dispatch record and OAT role event. When the host returns, it writes the
93
- request ID, the `Dispatch:` stamp, and the accepted or `blocked-before-start`
94
- result into the run record in `implementation.md`, the only launch record.
92
+ dispatch record and OAT role event. When the host returns `accepted` or
93
+ `blocked-before-start`, it renders the run line with
94
+ `oat project dispatch record --format line --dispatch-stamp "<Dispatch: …>"`
95
+ and writes it under `## Orchestration Runs` in `implementation.md`; after the
96
+ terminal outcome it re-renders that line and replaces it in place. One line per
97
+ request ID is the run record and the only launch record.
95
98
  Before an effort-pinned managed Claude launch, the root must run
96
99
  `oat project dispatch record`, which writes nothing, as a validation-only
97
100
  boundary. It supplies the real
@@ -262,13 +265,24 @@ commit range, task IDs and boundaries, project artifacts, and verification
262
265
  evidence. The root commits the phase's task ledger — task rows, the resume
263
266
  pointer, and any settled recovery marker — before it dispatches the reviewer,
264
267
  so the reviewed head is never stale by construction. Review-outcome
265
- bookkeeping — the Reviews row and its disposition, the Orchestration Run, and
268
+ bookkeeping — the Reviews row and its disposition, the run-line update, and
266
269
  the deferred project-log entries — is out of scope at the reviewed head: the
267
270
  root writes it after the review returns. In a parallel group the phase worktree
268
271
  does not carry the root ledger, so the reviewer brief names the task ledger out
269
272
  of scope as well. The review passes with zero Critical and zero High findings.
270
273
  Medium and Low findings are recorded without blocking the phase.
271
274
 
275
+ ## Journal slots and the pre-Step-16 check
276
+
277
+ The root writes each phase's task blocks, receipts and verification line in
278
+ that phase's section, run lines under `## Orchestration Runs`, gate lines and
279
+ multi-phase receipts under `## Reviews and Gates`, and excluded parallel phases
280
+ and unmerged worktrees under `## Deferred Findings`. Before Step 16 writes the
281
+ terminal journal headers, implement runs the closeout invariant and then
282
+ `oat project journal check --at implement-preflight`; a refusal names the
283
+ reason, line and owner, and implementation stays in progress until the journal
284
+ is corrected. See [Project Artifacts](../../../reference/project-artifacts.md#the-implementation-journal).
285
+
272
286
  ## Final Exit-Gate Boundary
273
287
 
274
288
  After every planned phase and review round finishes, the project root runs final
@@ -11,5 +11,5 @@ Use these guides while implementing, recording observations or picking up a trac
11
11
 
12
12
  - [Execution and Reconciliation Skills](execution-skills.md) - Implement a ready plan or reconcile existing committed work.
13
13
  - [Project Log](project-log.md) - Append-only project observations, synthesis, inspection, and durable roll-up.
14
- - [Implementation Execution](implementation-execution.md) - Phase dispatch, runtime selection, review/fix loop, and dry-run behavior.
14
+ - [Implementation Execution](implementation-execution.md) - Phase dispatch, runtime selection, review/fix loop, dry-run behavior, journal slots and run lines, and the pre-Step-16 journal check.
15
15
  - [Picking Up Projects](picking-up-projects.md) - Continue a synced project on another machine or from another user.
@@ -137,8 +137,9 @@ refuses to delete either ref when their SHAs differ.
137
137
 
138
138
  When archive is selected, completion copies a synced project into
139
139
  `.oat/projects/archived/<project>/` without the nested checkout's `.git`
140
- pointer or `reviews/`. S3 snapshots also omit `pr/`, following the existing
141
- archive policy. When archive is disabled or declined, the active synced
140
+ pointer, `reviews/` or `pr/`. S3 snapshots and `oat repo archive sync`
141
+ restores leave out the same entries, so a restored archive matches the one
142
+ that was uploaded. When archive is disabled or declined, the active synced
142
143
  checkout remains in place. Successful archived closeout instead uploads the S3
143
144
  snapshot first when configured, makes the completed ref authoritative, removes
144
145
  the checkout, and deletes the tracked JSON record. The local archive metadata