@open-agent-toolkit/cli 0.3.15 → 0.3.17

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 (189) hide show
  1. package/assets/NOTICES.md +48 -0
  2. package/assets/agents/oat-phase-implementer.md +26 -6
  3. package/assets/agents/oat-reviewer.md +51 -1
  4. package/assets/bundle-metadata.json +1 -1
  5. package/assets/docs/contributing/documentation.md +4 -0
  6. package/assets/docs/contributing/skills.md +3 -1
  7. package/assets/docs/getting-started/bootstrap.md +1 -1
  8. package/assets/docs/getting-started/index.md +0 -4
  9. package/assets/docs/getting-started/tool-packs.md +0 -7
  10. package/assets/docs/provider-sync/commands.md +21 -0
  11. package/assets/docs/reference/cli-reference.md +44 -2
  12. package/assets/docs/reference/config-and-local-state.md +11 -2
  13. package/assets/docs/reference/configuration.md +10 -2
  14. package/assets/docs/reference/project-artifacts.md +43 -8
  15. package/assets/docs/skills/index.md +1 -0
  16. package/assets/docs/skills/recon.md +8 -5
  17. package/assets/docs/skills/repo-improve.md +9 -7
  18. package/assets/docs/workflows/advanced/autonomy.md +50 -0
  19. package/assets/docs/workflows/advanced/workflow-gates.md +109 -10
  20. package/assets/docs/workflows/approvals-and-automation.md +3 -1
  21. package/assets/docs/workflows/backlog-and-planning/backlog-lifecycle.md +25 -24
  22. package/assets/docs/workflows/backlog-and-planning/remote-project-management.md +0 -7
  23. package/assets/docs/workflows/ideas/lifecycle.md +2 -7
  24. package/assets/docs/workflows/projects/closeout/closeout-skills.md +62 -1
  25. package/assets/docs/workflows/projects/execution/implementation-execution.md +23 -3
  26. package/assets/docs/workflows/projects/execution/project-log.md +6 -0
  27. package/assets/docs/workflows/projects/lifecycle.md +7 -0
  28. package/assets/docs/workflows/projects/reviews/index.md +63 -1
  29. package/assets/docs/workflows/projects/reviews/review-flavors.md +8 -0
  30. package/assets/docs/workflows/waves/wave-workflows.md +11 -3
  31. package/assets/public-package-versions.json +4 -4
  32. package/assets/skills/oat-agent-instructions-apply/SKILL.md +14 -4
  33. package/assets/skills/oat-brainstorm/SKILL.md +17 -13
  34. package/assets/skills/oat-docs-apply/SKILL.md +13 -3
  35. package/assets/skills/oat-doctor/SKILL.md +11 -1
  36. package/assets/skills/oat-explainer-kit/SKILL.md +1 -1
  37. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +6 -3
  38. package/assets/skills/oat-pjm-review-backlog/SKILL.md +2 -2
  39. package/assets/skills/oat-pjm-update-repo-reference/SKILL.md +28 -3
  40. package/assets/skills/oat-project-autonomous/SKILL.md +60 -5
  41. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +210 -165
  42. package/assets/skills/oat-project-capture/SKILL.md +7 -3
  43. package/assets/skills/oat-project-complete/SKILL.md +39 -34
  44. package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +106 -28
  45. package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +30 -3
  46. package/assets/skills/oat-project-complete-auto/SKILL.md +388 -0
  47. package/assets/skills/oat-project-design/SKILL.md +12 -9
  48. package/assets/skills/oat-project-discover/SKILL.md +8 -4
  49. package/assets/skills/oat-project-document/SKILL.md +14 -5
  50. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +210 -165
  51. package/assets/skills/oat-project-implement/SKILL.md +6 -1
  52. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +34 -7
  53. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +210 -165
  54. package/assets/skills/oat-project-implement/references/docs/complexity-review-fallback.md +262 -0
  55. package/assets/skills/oat-project-implement/references/docs/gate-approval-record.md +80 -0
  56. package/assets/skills/oat-project-implement/references/phase-execution.md +38 -6
  57. package/assets/skills/oat-project-import-plan/SKILL.md +20 -6
  58. package/assets/skills/oat-project-lite/SKILL.md +7 -5
  59. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +210 -165
  60. package/assets/skills/oat-project-new/SKILL.md +6 -2
  61. package/assets/skills/oat-project-next/SKILL.md +19 -2
  62. package/assets/skills/oat-project-next/references/docs/gate-approval-record.md +80 -0
  63. package/assets/skills/oat-project-plan/SKILL.md +14 -6
  64. package/assets/skills/oat-project-pr-final/SKILL.md +4 -3
  65. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +210 -165
  66. package/assets/skills/oat-project-progress/SKILL.md +27 -1
  67. package/assets/skills/oat-project-progress/references/docs/gate-approval-record.md +80 -0
  68. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +7 -3
  69. package/assets/skills/oat-project-quick-start/SKILL.md +47 -14
  70. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +210 -165
  71. package/assets/skills/oat-project-quick-start/references/docs/complexity-review-fallback.md +262 -0
  72. package/assets/skills/oat-project-quick-start/references/docs/gate-approval-record.md +80 -0
  73. package/assets/skills/oat-project-reconcile/SKILL.md +8 -4
  74. package/assets/skills/oat-project-retro/SKILL.md +1 -1
  75. package/assets/skills/oat-project-retro/references/apply-procedure.md +6 -6
  76. package/assets/skills/oat-project-retro-file/SKILL.md +7 -3
  77. package/assets/skills/oat-project-review-provide/SKILL.md +23 -4
  78. package/assets/skills/oat-project-review-provide-remote/SKILL.md +19 -1
  79. package/assets/skills/oat-project-review-receive/SKILL.md +57 -14
  80. package/assets/skills/oat-project-review-receive/references/docs/complexity-review-fallback.md +262 -0
  81. package/assets/skills/oat-project-review-receive-remote/SKILL.md +7 -3
  82. package/assets/skills/oat-project-revise/SKILL.md +13 -5
  83. package/assets/skills/oat-project-spec/SKILL.md +8 -4
  84. package/assets/skills/oat-project-summary/SKILL.md +11 -7
  85. package/assets/skills/oat-repo-knowledge-index/SKILL.md +54 -20
  86. package/assets/skills/oat-repo-knowledge-index/scripts/refresh-owned.mjs +118 -0
  87. package/assets/skills/oat-review-provide/SKILL.md +7 -3
  88. package/assets/skills/oat-review-receive-remote/SKILL.md +14 -4
  89. package/assets/skills/oat-wave-execute/SKILL.md +72 -38
  90. package/assets/skills/oat-wave-execute/assets/wrapper-plan-template.md +16 -2
  91. package/assets/skills/oat-wave-program/SKILL.md +15 -6
  92. package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +45 -17
  93. package/assets/skills/oat-wrap-up/SKILL.md +9 -3
  94. package/assets/skills/oat-wrap-up/references/report-template.md +1 -1
  95. package/assets/skills/recon/SKILL.md +1 -1
  96. package/assets/skills/recon/references/packet-contract.md +18 -3
  97. package/assets/skills/recon/scripts/lib/contracts.mjs +16 -2
  98. package/assets/skills/recon/scripts/reconcile-ledger.mjs +20 -10
  99. package/assets/skills/recon/scripts/render-packet.mjs +31 -3
  100. package/assets/skills/recon/scripts/validate-packet.mjs +5 -5
  101. package/assets/templates/pjm-agents.md +38 -8
  102. package/assets/templates/repo-agents.md +5 -0
  103. package/assets/templates/repo-readme.md +5 -0
  104. package/assets/templates/state.md +7 -0
  105. package/dist/commands/backlog/archive.d.ts +3 -0
  106. package/dist/commands/backlog/archive.d.ts.map +1 -1
  107. package/dist/commands/backlog/archive.js +63 -26
  108. package/dist/commands/backlog/index.d.ts.map +1 -1
  109. package/dist/commands/backlog/index.js +3 -0
  110. package/dist/commands/backlog/rewrite-references.d.ts +5 -0
  111. package/dist/commands/backlog/rewrite-references.d.ts.map +1 -1
  112. package/dist/commands/backlog/rewrite-references.js +39 -1
  113. package/dist/commands/config/index.d.ts.map +1 -1
  114. package/dist/commands/config/index.js +13 -0
  115. package/dist/commands/gate/index.d.ts +5 -0
  116. package/dist/commands/gate/index.d.ts.map +1 -1
  117. package/dist/commands/gate/index.js +270 -9
  118. package/dist/commands/init/index.d.ts.map +1 -1
  119. package/dist/commands/init/index.js +1 -0
  120. package/dist/commands/internal/commit-paths.d.ts +3 -0
  121. package/dist/commands/internal/commit-paths.d.ts.map +1 -0
  122. package/dist/commands/internal/commit-paths.js +31 -0
  123. package/dist/commands/internal/index.d.ts.map +1 -1
  124. package/dist/commands/internal/index.js +2 -0
  125. package/dist/commands/pjm/init.d.ts.map +1 -1
  126. package/dist/commands/pjm/init.js +37 -8
  127. package/dist/commands/project/archive/archive-utils.d.ts +6 -3
  128. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  129. package/dist/commands/project/archive/archive-utils.js +510 -104
  130. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  131. package/dist/commands/project/archive/push-runner.js +1 -0
  132. package/dist/commands/project/log/append.d.ts +2 -3
  133. package/dist/commands/project/log/append.d.ts.map +1 -1
  134. package/dist/commands/project/log/append.js +55 -101
  135. package/dist/commands/project/migrate/index.d.ts +1 -2
  136. package/dist/commands/project/migrate/index.d.ts.map +1 -1
  137. package/dist/commands/project/migrate/index.js +8 -2
  138. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  139. package/dist/commands/project/new/scaffold.js +4 -4
  140. package/dist/commands/project/promote/promote.d.ts +8 -0
  141. package/dist/commands/project/promote/promote.d.ts.map +1 -1
  142. package/dist/commands/project/promote/promote.js +37 -6
  143. package/dist/commands/project/status.d.ts.map +1 -1
  144. package/dist/commands/project/status.js +3 -0
  145. package/dist/commands/project/sync/ref-sync.d.ts +12 -1
  146. package/dist/commands/project/sync/ref-sync.d.ts.map +1 -1
  147. package/dist/commands/project/sync/ref-sync.js +347 -23
  148. package/dist/commands/shared/exact-path-commit.d.ts +32 -0
  149. package/dist/commands/shared/exact-path-commit.d.ts.map +1 -0
  150. package/dist/commands/shared/exact-path-commit.js +691 -0
  151. package/dist/commands/shared/frontmatter.d.ts +1 -1
  152. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  153. package/dist/commands/shared/frontmatter.js +1 -0
  154. package/dist/commands/state/generate.d.ts +1 -1
  155. package/dist/commands/state/generate.d.ts.map +1 -1
  156. package/dist/commands/state/generate.js +87 -8
  157. package/dist/commands/sync/apply.d.ts.map +1 -1
  158. package/dist/commands/sync/apply.js +31 -5
  159. package/dist/commands/sync/dry-run.d.ts.map +1 -1
  160. package/dist/commands/sync/dry-run.js +28 -11
  161. package/dist/commands/sync/sync.utils.d.ts +13 -0
  162. package/dist/commands/sync/sync.utils.d.ts.map +1 -1
  163. package/dist/commands/sync/sync.utils.js +21 -1
  164. package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
  165. package/dist/commands/tools/shared/pack-manifest.js +1 -0
  166. package/dist/config/oat-config.d.ts +1 -0
  167. package/dist/config/oat-config.d.ts.map +1 -1
  168. package/dist/config/oat-config.js +3 -0
  169. package/dist/config/resolve.d.ts.map +1 -1
  170. package/dist/config/resolve.js +1 -0
  171. package/dist/drift/detector.js +6 -6
  172. package/dist/engine/compute-plan.d.ts.map +1 -1
  173. package/dist/engine/compute-plan.js +87 -2
  174. package/dist/engine/engine.types.d.ts +10 -1
  175. package/dist/engine/engine.types.d.ts.map +1 -1
  176. package/dist/engine/engine.types.js +4 -0
  177. package/dist/engine/execute-plan.d.ts.map +1 -1
  178. package/dist/engine/execute-plan.js +42 -5
  179. package/dist/engine/managed-copy-hash.d.ts +4 -3
  180. package/dist/engine/managed-copy-hash.d.ts.map +1 -1
  181. package/dist/engine/managed-copy-hash.js +4 -3
  182. package/dist/fs/assets.d.ts.map +1 -1
  183. package/dist/fs/assets.js +7 -1
  184. package/dist/manifest/hash.d.ts +8 -10
  185. package/dist/manifest/hash.d.ts.map +1 -1
  186. package/dist/ui/output.js +1 -1
  187. package/dist/validation/skills.d.ts.map +1 -1
  188. package/dist/validation/skills.js +151 -11
  189. package/package.json +3 -2
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  user-invocable: true
6
6
  allowed-tools: Read, Write, Bash(git:*), Glob, Grep, AskUserQuestion, Task
7
7
  metadata:
8
- version: 1.3.2
8
+ version: 1.3.3
9
9
  ---
10
10
 
11
11
  # Knowledge Base Generation
@@ -42,20 +42,39 @@ EXISTING_MD=$(find .oat/repo/knowledge -name "*.md" -type f 2>/dev/null | head -
42
42
  **If `$EXISTING_MD` is non-empty (actual content exists):**
43
43
 
44
44
  - List current files: `ls -la .oat/repo/knowledge/*.md 2>/dev/null`
45
- - Ask: "Refresh (delete + regenerate) or Skip?"
46
- - If Refresh: `rm -rf .oat/repo/knowledge/*.md && mkdir -p .oat/repo/knowledge`
45
+ - Ask: "Refresh generated knowledge or Skip? Hand-written files will be kept; unmarked output-name collisions stop refresh."
46
+ - If Refresh: Continue to the owned-output preflight in Step 2; do not delete files by a wildcard.
47
47
  - If Skip: Exit
48
48
 
49
49
  **If `$EXISTING_MD` is empty (no content or only .gitkeep):**
50
50
 
51
51
  - Continue to Step 2
52
52
 
53
- ### Step 2: Create Knowledge Directory
53
+ ### Step 2: Prepare Only Owned Generated Outputs
54
+
55
+ Set `SKILL_DIR` to the absolute directory containing this loaded `SKILL.md`.
56
+ Resolve the repository root, then run the deterministic ownership preflight
57
+ before thin-index generation or mapper writes. It checks every expected
58
+ output name before deleting anything: an unmarked file, symlink or directory
59
+ collision stops the run and remains intact. Only regular Markdown files with
60
+ frontmatter `oat_generated: true` are removed; other files and manual notes
61
+ survive. Symlinked directories in `.oat/repo/knowledge` are refused.
54
62
 
55
63
  ```bash
56
- mkdir -p .oat/repo/knowledge
64
+ REPO_ROOT=$(git rev-parse --show-toplevel) || exit 1
65
+ node "$SKILL_DIR/scripts/refresh-owned.mjs" --prepare "$REPO_ROOT" || exit 1
57
66
  ```
58
67
 
68
+ Retain the printed JSON report's exact `affectedPaths` (removed generated paths
69
+ plus the eight expected outputs) through generation and commit, including
70
+ across separate shell calls. The report is operation evidence, not a persistent
71
+ ownership manifest; no temporary report file is created. Do not broaden
72
+ ownership to the whole directory. Expected outputs are `project-index.md`,
73
+ `stack.md`, `architecture.md`, `structure.md`, `integrations.md`, `testing.md`,
74
+ `conventions.md` and `concerns.md`; mappers must write only their declared
75
+ outputs, retaining the generated frontmatter. Relocate an authored collision
76
+ only with the operator's direction, then rerun the preflight.
77
+
59
78
  ### Step 3: Get Git SHAs for Frontmatter
60
79
 
61
80
  ```bash
@@ -655,23 +674,38 @@ cat .oat/repo/knowledge/project-index.md | head -50
655
674
 
656
675
  Expected: Complete overview with frontmatter and links
657
676
 
658
- ### Step 10: Commit Knowledge Base
677
+ ### Step 10: Commit Only Generated Knowledge Paths
678
+
679
+ Verify all eight generated outputs, then format their existing supported text
680
+ using the repository's documented write command. Retain removed tracked
681
+ generated paths from the preparation report, including filenames outside the
682
+ current eight-output set. Resolve the repository root again with
683
+ `git rev-parse --show-toplevel`, then convert the report's absolute paths to
684
+ literal repository-relative files using that root, deduplicate them, and populate
685
+ the next shell call's positional arguments; the snippet below initializes
686
+ `KNOWLEDGE_OWNED_FILES` from that retained exact array. Resolve `SKILL_DIR` again
687
+ in each shell call rather than relying on prior shell variables. Omit a removed
688
+ path only if Git proves it was never tracked; never omit a tracked generated
689
+ deletion. Do not add manual files,
690
+ collisions or the tracking/dashboard files below to this commit.
659
691
 
660
692
  ```bash
661
- git add .oat/repo/knowledge/
662
- git commit -m "docs: generate knowledge base
663
-
664
- - project-index.md - High-level codebase overview
665
- - stack.md - Technologies and dependencies
666
- - architecture.md - System design and patterns
667
- - structure.md - Directory layout
668
- - conventions.md - Code style and patterns
669
- - testing.md - Test structure and practices
670
- - integrations.md - External services and APIs
671
- - concerns.md - Technical debt and issues
672
-
673
- Generated from commit: {MERGE_BASE_SHA}"
674
- ```
693
+ REPO_ROOT=$(git rev-parse --show-toplevel) || exit 1
694
+ KNOWLEDGE_OWNED_FILES=("$@")
695
+ [ "${#KNOWLEDGE_OWNED_FILES[@]}" -gt 0 ] || { echo "Missing retained knowledge affectedPaths; refusing to commit" >&2; exit 1; }
696
+ node "$SKILL_DIR/scripts/refresh-owned.mjs" --verify "$REPO_ROOT" || exit 1
697
+ oat internal commit-paths --help || exit 1
698
+ # KNOWLEDGE_OWNED_FILES is the exact retained affectedPaths list after verification.
699
+ # Format existing generated text members using the repository write command.
700
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:knowledge-index" --message "docs: generate knowledge base from $MERGE_BASE_SHA" -- "${KNOWLEDGE_OWNED_FILES[@]}" || exit 1
701
+ ```
702
+
703
+ Set a unique `COMMIT_IDENTITY` before the first commit attempt and retain the
704
+ identity, message and literal file list for retries. If the shared command is
705
+ unavailable, stop and update the CLI; a blocked/failed result stops this run
706
+ and retains its receipt for the reported recovery. Hooks stay enabled;
707
+ unrelated staged entries and unstaged bytes remain preserved. Verify the
708
+ owned paths match the committed hook-final content before proceeding.
675
709
 
676
710
  ### Step 10b: Update Tracking Manifest
677
711
 
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ lstat,
4
+ mkdir,
5
+ readdir,
6
+ readFile,
7
+ realpath,
8
+ unlink,
9
+ } from 'node:fs/promises';
10
+ import { join, resolve } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ export const GENERATED_OUTPUTS = Object.freeze([
14
+ 'project-index.md',
15
+ 'stack.md',
16
+ 'architecture.md',
17
+ 'structure.md',
18
+ 'integrations.md',
19
+ 'testing.md',
20
+ 'conventions.md',
21
+ 'concerns.md',
22
+ ]);
23
+
24
+ function generated(content) {
25
+ const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(content);
26
+ const markers = frontmatter?.[1].match(/^oat_generated:.*$/gmu) ?? [];
27
+ return (
28
+ markers.length === 1 &&
29
+ /^oat_generated:[ \t]*true[ \t]*(?:#[^\r\n]*)?\r?$/u.test(markers[0])
30
+ );
31
+ }
32
+
33
+ async function knowledgeDirectory(repoRoot, create) {
34
+ const root = await realpath(repoRoot);
35
+ let path = root;
36
+ // Only this repo's known knowledge directory is owned. Never follow a
37
+ // symlink in the .oat/repo/knowledge directory chain.
38
+ for (const component of ['.oat', 'repo', 'knowledge']) {
39
+ path = join(path, component);
40
+ if (create) {
41
+ await mkdir(path).catch((error) => {
42
+ if (error.code !== 'EEXIST') throw error;
43
+ });
44
+ }
45
+ const identity = await lstat(path);
46
+ if (!identity.isDirectory() || identity.isSymbolicLink()) {
47
+ throw new Error(`Knowledge path is not an owned directory: ${path}`);
48
+ }
49
+ }
50
+ return path;
51
+ }
52
+
53
+ /** Validate every collision before deleting only explicitly generated files. */
54
+ export async function prepareOwnedRefresh(repoRoot) {
55
+ const directory = await knowledgeDirectory(repoRoot, true);
56
+ const entries = await readdir(directory, { withFileTypes: true });
57
+ const owned = [];
58
+ for (const entry of entries) {
59
+ const expected = GENERATED_OUTPUTS.includes(entry.name);
60
+ if (!expected && (!entry.isFile() || !entry.name.endsWith('.md'))) continue;
61
+ const path = join(directory, entry.name);
62
+ const marked = entry.isFile() && generated(await readFile(path, 'utf8'));
63
+ if (expected && !marked) {
64
+ throw new Error(
65
+ `Unmarked knowledge output collision: ${path}; preserve or relocate the authored file before refreshing.`,
66
+ );
67
+ }
68
+ if (marked) owned.push(path);
69
+ }
70
+ // Preflight above is all-or-nothing: collisions leave every old file intact.
71
+ for (const path of owned.sort()) await unlink(path);
72
+ const outputPaths = GENERATED_OUTPUTS.map((name) => join(directory, name));
73
+ return {
74
+ removedPaths: owned,
75
+ outputPaths,
76
+ affectedPaths: [...new Set([...owned, ...outputPaths])].sort(),
77
+ };
78
+ }
79
+
80
+ /** Run after generation and before formatting/committing the retained list. */
81
+ export async function verifyOwnedOutputs(repoRoot) {
82
+ const directory = await knowledgeDirectory(repoRoot, false);
83
+ const outputPaths = GENERATED_OUTPUTS.map((name) => join(directory, name));
84
+ for (const path of outputPaths) {
85
+ const identity = await lstat(path);
86
+ if (
87
+ !identity.isFile() ||
88
+ identity.isSymbolicLink() ||
89
+ !generated(await readFile(path, 'utf8'))
90
+ ) {
91
+ throw new Error(`Expected marked generated knowledge output: ${path}`);
92
+ }
93
+ }
94
+ return { outputPaths };
95
+ }
96
+
97
+ if (
98
+ process.argv[1] &&
99
+ (await realpath(process.argv[1]).catch(() => resolve(process.argv[1]))) ===
100
+ fileURLToPath(import.meta.url)
101
+ ) {
102
+ try {
103
+ const [mode, root, ...extra] = process.argv.slice(2);
104
+ if (!root || extra.length || !['--prepare', '--verify'].includes(mode)) {
105
+ throw new Error(
106
+ 'Usage: refresh-owned.mjs <--prepare|--verify> <repo-root>',
107
+ );
108
+ }
109
+ const result =
110
+ mode === '--prepare'
111
+ ? await prepareOwnedRefresh(root)
112
+ : await verifyOwnedOutputs(root);
113
+ process.stdout.write(`${JSON.stringify(result)}\n`);
114
+ } catch (error) {
115
+ process.stderr.write(`${error.message}\n`);
116
+ process.exitCode = 1;
117
+ }
118
+ }
@@ -6,13 +6,17 @@ disable-model-invocation: true
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
8
8
  metadata:
9
- version: 1.2.5
9
+ version: 1.2.6
10
10
  ---
11
11
 
12
12
  # Ad-Hoc Review
13
13
 
14
14
  Request and execute a code/file review that is not tied to an OAT project lifecycle.
15
15
 
16
+ ## Hook-safe exact-path commits
17
+
18
+ Before a parent-branch commit, verify `oat internal commit-paths --help` succeeds. If unavailable, stop and update the OAT CLI; never fall back to a staged-index or pathspec-only commit. Set `COMMIT_IDENTITY` to a unique operation/artifact identity before the first attempt and retain it for every retry; use a new identity for a new operation. Pass only the exact produced file list, including tracked removals and both names of a rename. A blocked/failed result stops the workflow; retain its receipt and follow its diagnostics. Hooks remain enabled. Synced project artifacts continue through `oat project push`.
19
+
16
20
  ## Prerequisites
17
21
 
18
22
  - Git repository with changes/files to review.
@@ -207,8 +211,8 @@ If artifact is in tracked storage (e.g., `.oat/repo/reviews`), ask whether to co
207
211
  Suggested commit (when approved):
208
212
 
209
213
  ```bash
210
- git add "{artifact-path}"
211
- git commit -m "chore(oat): record ad-hoc review artifact"
214
+ OWNED_COMMIT_PATHS=("{artifact-path}")
215
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:oat-review-provide:1" --message "chore(oat): record ad-hoc review artifact" -- "${OWNED_COMMIT_PATHS[@]}" || exit 1
212
216
  ```
213
217
 
214
218
  For local-active or inline modes, do not commit unless user explicitly requests.
@@ -5,13 +5,17 @@ disable-model-invocation: true
5
5
  user-invocable: true
6
6
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
7
7
  metadata:
8
- version: 1.3.2
8
+ version: 1.3.3
9
9
  ---
10
10
 
11
11
  # Remote Review Receive (Ad-hoc GitHub PR)
12
12
 
13
13
  Process unresolved GitHub PR review feedback into normalized findings and standalone tasks without requiring an active OAT project.
14
14
 
15
+ ## Hook-safe exact-path commits
16
+
17
+ Before a parent-branch commit, verify `oat internal commit-paths --help` succeeds. If unavailable, stop and update the OAT CLI; never fall back to a staged-index or pathspec-only commit. Set `COMMIT_IDENTITY` to a unique operation/artifact identity before the first attempt and retain it for every retry; use a new identity for a new operation. Pass only the exact produced file list, including tracked removals and both names of a rename. A blocked/failed result stops the workflow; retain its receipt and follow its diagnostics. Hooks remain enabled. Synced project artifacts continue through `oat project push`.
18
+
15
19
  ## Prerequisites
16
20
 
17
21
  - `npx agent-reviews` is available.
@@ -172,6 +176,12 @@ Also output deferred and dismissed lists with reasons.
172
176
 
173
177
  ### Step 6: Optional Fix Implementation
174
178
 
179
+ Before the first approved write, initialize `OWNED_OUTPUT_FILES=()`. Append
180
+ each exact successfully created, modified or removed path at that write,
181
+ including both names of a rename and any generated navigation/index file this
182
+ step actually changes. Retain the complete list through verification and commit
183
+ retries; do not substitute a directory or staged-index diff.
184
+
175
185
  After the task list is confirmed, ask:
176
186
 
177
187
  `Would you like me to address these fixes, commit, and push the changes? [yes/no]`
@@ -183,10 +193,10 @@ If yes:
183
193
  3. Stage and commit with a descriptive message referencing the PR:
184
194
 
185
195
  ```bash
186
- git add {changed-files}
187
- git commit -m "fix: address PR #<N> review feedback
196
+ OWNED_COMMIT_PATHS=("${OWNED_OUTPUT_FILES[@]}")
197
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:oat-review-receive-remote:1" --message "fix: address PR #<N> review feedback
188
198
 
189
- Resolved findings: {list of finding IDs and titles}"
199
+ Resolved findings: {list of finding IDs and titles}" -- "${OWNED_COMMIT_PATHS[@]}" || exit 1
190
200
  ```
191
201
 
192
202
  4. Push to the current branch:
@@ -6,7 +6,7 @@ disable-model-invocation: false
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
8
8
  metadata:
9
- version: 1.9.5
9
+ version: 1.9.7
10
10
  ---
11
11
 
12
12
  # Execute a Wave of External Plans
@@ -25,6 +25,10 @@ Historical `DR-*` and `BL-*` slugs in this skill (including the provenance
25
25
  record above) are evidence citations in the source program's repository; they
26
26
  are not required artifacts in the consuming repo.
27
27
 
28
+ ## Hook-safe exact-path commits
29
+
30
+ Before a parent-branch commit, verify `oat internal commit-paths --help` succeeds. If unavailable, stop and update the OAT CLI; never fall back to a staged-index or pathspec-only commit. Set `COMMIT_IDENTITY` to a unique operation/artifact identity before the first attempt and retain it for every retry; use a new identity for a new operation. Pass only the exact produced file list, including tracked removals and both names of a rename. A blocked/failed result stops the workflow; retain its receipt and follow its diagnostics. Hooks remain enabled. Synced project artifacts continue through `oat project push`.
31
+
28
32
  ## Progress Indicators (User-Facing)
29
33
 
30
34
  Print this banner once when execution starts:
@@ -256,6 +260,12 @@ terminal state for gate rows (Orc operator-audit S8).
256
260
  Persist the gate artifact and its dispositions through the wrapper project's
257
261
  scope-aware bookkeeping route:
258
262
 
263
+ Before running the gate, initialize `WAVE_GATE_OUTPUT_PATHS=()` and append the
264
+ exact plan, state, implementation, review and receive-receipt files each gate
265
+ producer actually writes. Include tracked removals and both rename sides, omit
266
+ ignored outputs, and retain the list through retries. Do not discover ownership
267
+ from a project-directory or staged-index diff.
268
+
259
269
  ```bash
260
270
  PROJECT_PATH=$(oat config get activeProject 2>/dev/null || true)
261
271
  if [ -z "$PROJECT_PATH" ]; then
@@ -267,14 +277,9 @@ PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat
267
277
  if [ "$PROJECT_SCOPE" = "synced" ]; then
268
278
  oat project push "$PROJECT_PATH" --message "chore(oat): record wave plan gate" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
269
279
  else
270
- PROJECT_OUTPUT_PATHS=()
271
- while IFS= read -r output_path; do
272
- PROJECT_OUTPUT_PATHS+=("$output_path")
273
- done < <(git diff --name-only -- "$PROJECT_PATH")
274
- [ "${#PROJECT_OUTPUT_PATHS[@]}" -gt 0 ] || exit 1
275
- git add -- "${PROJECT_OUTPUT_PATHS[@]}"
276
- git diff --cached --quiet -- "${PROJECT_OUTPUT_PATHS[@]}" ||
277
- git commit --only -m "chore(oat): record wave plan gate" -- "${PROJECT_OUTPUT_PATHS[@]}"
280
+ : "${WAVE_GATE_OUTPUT_PATHS:?retain the exact gate producer file list}"
281
+ OWNED_COMMIT_PATHS=("${WAVE_GATE_OUTPUT_PATHS[@]}")
282
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:oat-wave-execute:1" --message "chore(oat): record wave plan gate" -- "${OWNED_COMMIT_PATHS[@]}" || exit 1
278
283
  fi
279
284
  ```
280
285
 
@@ -392,8 +397,16 @@ archive anything first.
392
397
  `summary.md`** (this is the "before any archive step" gate): convention
393
398
  verdicts with evidence, adjustments-as-rules for later waves, graduated-entries
394
399
  ledger, rolled into `summary.md` `## Workflow Observations`.
395
- 3. **Serialized backlog archival** — `oat backlog archive` with real summaries,
396
- one commit.
400
+ 3. **Serialized backlog archival** — run `oat backlog archive --json` for
401
+ each item with its real outcome summary. Union and deduplicate all returned
402
+ `affectedPaths`, including tracked old item deletions, new destinations,
403
+ ledger/index and rewritten references; append owned handoff filesystem
404
+ deletions. Format existing supported text with the repository command,
405
+ then use `oat internal commit-paths` for one exact-operation commit with
406
+ enabled hooks and the unique retained `COMMIT_IDENTITY`. Stop if the helper
407
+ is unavailable or blocked/failed; unrelated staged/unstaged work survives.
408
+ A settled noop returns only actual repairs; do not infer paths from every
409
+ archived link or commit only the old missing path.
397
410
  4. **Closeout gate run** — after the archival commit, and after ANY later commit
398
411
  that touches a gated surface (`.oat/repo/**`, `.agents/**`, `packages/**`,
399
412
  `apps/**`), re-run the integration DoD gates with cache bypass. The last
@@ -417,35 +430,56 @@ archive anything first.
417
430
  HiLL. File follow-up-ledger backlog items at closeout (on main post-merge, or
418
431
  pre-gate if the operator prefers them in the PR).
419
432
  8. **The full `oat-project-complete` PROCESS, with an explicit autonomous
420
- deferral branch.** Interactive runs retain the standing per-wave order
421
- review → complete → merge (an open PR is expected, not a blocker — the
422
- archive-aware PR body sync handles it). The requirement remains the whole
423
- completion process, named explicitly: `oat project complete-state` →
424
- `oat project archive` (the CLI owns the local archive move, the summary
425
- export, and the S3 sync when `s3SyncOnComplete` is configured) →
426
- active-project pointer clear → the completion bookkeeping commit. Running
427
- `oat project complete-state` ALONE does NOT satisfy this step: in the Orc
428
- first run all four wrapper projects were left lifecycle-complete but
429
- unarchived until an operator audit asked (S10).
430
-
431
- Under autonomous execution, each wave MUST still run
432
- `oat project complete-state` and its then-current project bookkeeping. The
433
- archive tail — `oat project archive` (including configured S3 sync) →
434
- active-project pointer clear → completion bookkeeping commit — MAY be
435
- deferred to the program boundary so the wave can merge and execution can
436
- continue. Record every such choice in the wave ledger exactly as
437
- `completion tail: deferred to program close`; deferral is an outstanding
438
- disposition, never satisfaction of the full-tail requirement. Interactive
439
- per-wave full-tail completion remains valid.
433
+ companion and deferral branch.** Interactive runs retain the standing
434
+ per-wave order review → complete → merge (an open PR is expected, not a
435
+ blocker — the archive-aware PR body sync handles it). The requirement
436
+ remains the whole completion process, named explicitly:
437
+ `oat project complete-state` → `oat project archive` (the CLI owns the local
438
+ archive move, the summary export, and the S3 sync when `s3SyncOnComplete` is
439
+ configured) → active-project pointer clear → the completion bookkeeping
440
+ commit. Running `oat project complete-state` ALONE does NOT satisfy this
441
+ step: in the Orc first run all four wrapper projects were left
442
+ lifecycle-complete but unarchived until an operator audit asked (S10).
440
443
 
441
444
  The interactive completion skill is model-invisible
442
- (`disable-model-invocation: true`), so an autonomous orchestrator executes
443
- its `SKILL.md` as a document, resolving its gates from config
444
- (`workflow.archiveOnComplete`, `workflow.createPrOnComplete`), until an
445
- `oat-project-complete-auto` companion ships
446
- (BL-260720-add-oat-project-complete-auto). If the archive tail is deferred,
447
- that execution occurs after the one human-gated program-end checkpoint in
448
- `oat-wave-program`, across every deferred wave wrapper.
445
+ (`disable-model-invocation: true`). Under autonomous execution, invoke
446
+ `oat-project-complete-auto` for the wave wrapper project with this step's
447
+ completion-before-merge provenance:
448
+ `--requested-by oat-wave-execute:closeout-step-8 --completion-before-merge --reason "wave <wave-id> completes before its merge handoff" <wrapper-project-path>`.
449
+ The companion runs only with `workflow.autonomousComplete: true`, preflights
450
+ the wrapper, records the completion-before-merge exception for the open,
451
+ tracked wave PR in the wrapper's `implementation.md`, and then runs the full
452
+ completion process. Record its run-report outcome in the wave ledger.
453
+
454
+ Fall back to the deferral below only when the run report's `refused_check`
455
+ is `opt-in` (`interactive completion required`), `preflight:4` (the PR
456
+ precondition), or `preflight:7` (a completion question with no recorded
457
+ answer). Any other refusal — an objective preflight failure, namely
458
+ `preflight:1` (post-implement sequence incomplete), `preflight:2`
459
+ (incomplete tasks), `preflight:3` (final review not passed), `preflight:5`
460
+ (unresolved blockers), or `preflight:6` (project-log gate unsatisfied), or
461
+ an `activation` refusal — stops wave closeout at a boundary: report the
462
+ failing check and run neither `oat project complete-state` nor the merge
463
+ handoff. `oat project complete-state` checks only the closeout snapshot, so
464
+ running it after an objective refusal would mark an unhealthy wrapper
465
+ complete. A `preflight:1` refusal whose reason is
466
+ `project directory absent (archived?); resume with oat-project-complete`
467
+ means an earlier run archived the wrapper and a later completion step
468
+ failed: the boundary report names `oat-project-complete` as the next owner,
469
+ whose archive-resume branches finish the tail, and never another companion
470
+ run.
471
+
472
+ On a deferrable stop, the wave MUST still run `oat project complete-state`
473
+ and its then-current project bookkeeping, and the archive tail —
474
+ `oat project archive` (including configured S3 sync) → active-project
475
+ pointer clear → completion bookkeeping commit — MAY be deferred to the
476
+ program boundary so the wave can merge and execution can continue. Record
477
+ every such choice in the wave ledger exactly as
478
+ `completion tail: deferred to program close`, with the companion's stated
479
+ reason; deferral is an outstanding disposition, never satisfaction of the
480
+ full-tail requirement. Interactive per-wave full-tail completion remains
481
+ valid. A deferred tail runs after the one human-gated program-end
482
+ checkpoint in `oat-wave-program`, across every deferred wave wrapper.
449
483
 
450
484
  9. **After the operator merges:** reconcile (squash-merge means content-diff the
451
485
  branch vs main; cherry-pick stragglers), reset the working branch, clean stale
@@ -119,8 +119,16 @@ disposition every finding in the phase report. }
119
119
 
120
120
  **Step { N }: Commit**
121
121
 
122
+ Before task edits, initialize `TASK_OWNED_FILES=()` and append the exact files
123
+ at each source-plan producer, including created files, tracked removals and both
124
+ rename sides. Retain the complete list and a stable unique `COMMIT_IDENTITY`
125
+ for this wrapper task through retries; each task uses its own identity/suffix.
126
+ Never infer ownership from the staged index or pass directories. Verify
127
+ `oat internal commit-paths --help` first; if unavailable, stop and update the CLI.
128
+ A nonzero result stops with its receipt and diagnostic; hooks remain enabled.
129
+
122
130
  ```bash
123
- git commit -m "{type}(p{NN}-t01): { description }"
131
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:oat-wave-execute:wrapper-plan-template:p{NN}-t01" --message "{type}(p{NN}-t01): { description }" -- "${TASK_OWNED_FILES[@]}" || exit 1
124
132
  ```
125
133
 
126
134
  ---
@@ -144,7 +152,13 @@ git commit -m "{type}(p{NN}-t01): { description }"
144
152
  - [ ] { N }/{ N } phases, { M }/{ M } tasks complete
145
153
  - [ ] Every source plan's `## Done criteria` confirmed (recorded in `implementation.md`)
146
154
  - [ ] **Serialized backlog bookkeeping** (integration branch, after all merges):
147
- `oat backlog archive` with real outcome summaries for { backlog IDs }, one commit
155
+ `oat backlog archive --json` with real outcome summaries for { backlog IDs }.
156
+ Union complete returned `affectedPaths` (tracked old deletions, new
157
+ destinations, ledger/index/references), append owned handoff filesystem
158
+ deletions, format existing text with the repo command, and create one
159
+ `oat internal commit-paths` commit with enabled hooks and a retained unique
160
+ identity. Stop on unavailable/blocked/failed helper; preserve unrelated
161
+ staged/unstaged work.
148
162
  - [ ] Orchestration-log end-of-run synthesis written; roll-up into `summary.md`
149
163
  before any archive step
150
164
  - [ ] Full DoD gates green on the integration branch
@@ -6,7 +6,7 @@ disable-model-invocation: false
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
8
8
  metadata:
9
- version: 1.5.3
9
+ version: 1.5.4
10
10
  ---
11
11
 
12
12
  # Program a Corpus of External Plans into Waves
@@ -124,11 +124,20 @@ target (same disclaimer as the plan indexes).
124
124
  including in autonomous runs:
125
125
  "All waves are merged and the program is complete. Run the completion tail
126
126
  (oat-project-complete: archive + S3 + pointer clear) across all N wave wrapper
127
- projects now?" On yes, run the full deferred tail for each wrapper via
128
- `oat-project-complete-auto` when it ships, or execute the interactive skill's
129
- `SKILL.md` as a document until then, and flip every
130
- `completion tail: deferred to program close` ledger disposition to `done`. On
131
- no or defer, record the standing deferral and its owner in the program ledger.
127
+ projects now?" On yes, record the answer in the program ledger and invoke
128
+ `oat-project-complete-auto` once in batch mode with
129
+ `--requested-by oat-wave-program:program-completion-checkpoint --batch --program-checkpoint <ledger-ref>`
130
+ and every deferred wrapper project path. Flip each wrapper the run report
131
+ lists as `completed` from `completion tail: deferred to program close` to
132
+ `done`; a refused or failed wrapper keeps its deferral with the reported
133
+ reason. When the companion stops with `interactive completion required`, the
134
+ operator completes the wrappers with `oat-project-complete`. List every
135
+ wrapper refused for a deferrable reason (`preflight:4` or `preflight:7`)
136
+ with its next step: the operator completes it with `oat-project-complete`,
137
+ or sets the missing config and answers the checkpoint again. A wrapper
138
+ refused for an objective reason keeps its deferral and reports the failing
139
+ check. On no or defer,
140
+ record the standing deferral and its owner in the program ledger.
132
141
  This is the program completion gate; never answer it autonomously or repeat
133
142
  it once per wave.
134
143
 
@@ -6,7 +6,7 @@ disable-model-invocation: false
6
6
  user-invocable: false
7
7
  allowed-tools: Read, Write, Bash, Glob, Grep
8
8
  metadata:
9
- version: 1.6.2
9
+ version: 1.6.3
10
10
  ---
11
11
 
12
12
  # Autonomous Worktree Bootstrap
@@ -17,6 +17,10 @@ This skill is **model-invocable** (`disable-model-invocation: false`): orchestra
17
17
 
18
18
  > ⚠️ **When not to substitute.** This skill is the **only** supported mechanism for orchestrator-driven worktree creation in OAT skills. Host-native isolation primitives — Claude Code's `Agent({ isolation: "worktree" })`, Cursor's worktree-isolated agent invocations, and equivalents in other hosts — are **not** substitutes. They may use the primary repo's checkout (often `main`) as the base regardless of the caller's current branch, silently producing a worktree at the wrong base. OAT orchestrators dispatching mid-run from a feature branch MUST go through this skill with an explicit `--base` so the resulting worktree contains the orchestrator's prior commits.
19
19
 
20
+ ## Hook-safe exact-path commits
21
+
22
+ Before a parent-branch commit, verify `oat internal commit-paths --help` succeeds. If unavailable, stop and update the OAT CLI; never fall back to a staged-index or pathspec-only commit. Set `COMMIT_IDENTITY` to a unique operation/artifact identity before the first attempt and retain it for every retry; use a new identity for a new operation. Pass only the exact produced file list, including tracked removals and both names of a rename. A blocked/failed result stops the workflow; retain its receipt and follow its diagnostics. Hooks remain enabled. Synced project artifacts continue through `oat project push`.
23
+
20
24
  ## Relationship to oat-worktree-bootstrap
21
25
 
22
26
  This skill is the **autonomous companion** to `oat-worktree-bootstrap`. Key differences:
@@ -358,28 +362,52 @@ Create them if missing, run the `git_clean` baseline check, and then run sync:
358
362
  mkdir -p "{target-path}/.claude/skills"
359
363
  mkdir -p "{target-path}/.cursor/rules"
360
364
  git status --porcelain
361
- oat sync --scope all
365
+ SYNC_PLAN_JSON=$(oat sync --scope all --dry-run --json) || exit 1
366
+ SYNC_OUTPUT_FILES=()
367
+ # Populate the exact list from the producer evidence described below before apply.
368
+ SYNC_RESULT_JSON=$(oat sync --scope all --json) || exit 1
362
369
  ```
363
370
 
364
- After sync completes, commit sync-managed output if any scoped path is dirty:
371
+ Before the apply invocation, populate `SYNC_OUTPUT_FILES` from the supported
372
+ `SYNC_PLAN_JSON.plans[]` entries/removals for `scope: project`:
373
+
374
+ - `providerPath` is the planned target, and `canonical.isFile` identifies file
375
+ assets. Include that exact file for a mutating operation; include old tracked
376
+ paths for removals. Skip `operation: skip` unless the manifest was restamped.
377
+ - A symlink projection owns the single provider symlink path. A copy projection
378
+ of a directory owns concrete copied members: enumerate the canonical producer
379
+ files before applying and map each relative member to its provider destination.
380
+ Capture the exact existing tracked members with literal `git ls-files -z`
381
+ before a planned removal. Do not discover this list from the staged index.
382
+ - Include `.oat/sync/manifest.json` when the project manifest is written. Omit
383
+ ignored output files and user-scope paths, which are outside the worktree.
384
+ - `operationResults[]` reports scope/provider/contentKind/asset/action/status,
385
+ **not file paths**. Match those identities to the planned entries/removals and
386
+ require successful/current results before committing. Materialization
387
+ extensions expose their own `operations[].path`; include only verified
388
+ concrete project files. Collection/directory outcomes require complete
389
+ producer member evidence. Stop on unknown, failed, incomplete or changed
390
+ inventories; never pass a directory to the helper.
391
+
392
+ Append each exact planned output to `SYNC_OUTPUT_FILES` before mutation and
393
+ verify it against the actual result after sync. Include both rename sides and
394
+ retain the list and identity through a retry. The helper never expands a
395
+ provider directory or invents a producer inventory.
396
+
397
+ After sync completes, commit the retained exact list:
365
398
 
366
399
  ```bash
367
- SYNC_PATHS=(.oat/sync/manifest.json .claude .cursor .codex)
368
- SYNC_STAGE_PATHS=(existing-or-tracked sync paths)
369
- git status --porcelain -- "${SYNC_STAGE_PATHS[@]}"
370
- git add -A -- "${SYNC_STAGE_PATHS[@]}"
371
- STAGED_SYNC_FILES=(staged sync-managed files from git diff --cached)
372
- git commit -m "chore: run sync" -- "${STAGED_SYNC_FILES[@]}"
400
+ if [ "${#SYNC_OUTPUT_FILES[@]}" -gt 0 ]; then
401
+ oat internal commit-paths --identity "${COMMIT_IDENTITY:?set once and retain for retries}:oat-worktree-bootstrap-auto:1" --message "chore: run sync" -- "${SYNC_OUTPUT_FILES[@]}" || exit 1
402
+ else
403
+ echo "sync_commit: skip"
404
+ fi
373
405
  ```
374
406
 
375
- Use a staged-diff guard so no empty commit is created. After scoped staging,
376
- derive the concrete staged sync-managed files from
377
- `git diff --cached --name-only --no-renames -- "${SYNC_STAGE_PATHS[@]}"` and
378
- commit only those file paths. Do not pass provider directory pathspecs to
379
- `git commit`, because empty provider directories can make the commit fail. This
380
- file-list isolation is what keeps `chore: run sync` limited to sync-managed
381
- paths even if unrelated files were already staged. If no scoped path is dirty,
382
- or staging produces no diff, report `sync_commit: skip`.
407
+ A `nothing` result reports `sync_commit: skip`; blocked/failed results
408
+ stop bootstrap and retain the helper's resumable diagnostic. Never use directory
409
+ pathspecs, staged-diff discovery, or an empty broad commit. Smoke mode continues
410
+ to skip sync and this commit entirely.
383
411
 
384
412
  ### Step 5: Return Structured Status
385
413