@open-agent-toolkit/cli 0.2.40 → 0.2.45

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 (213) hide show
  1. package/assets/agents/oat-codebase-mapper.md +15 -3
  2. package/assets/agents/oat-phase-implementer.md +34 -9
  3. package/assets/agents/oat-reviewer.md +2 -2
  4. package/assets/bundle-metadata.json +1 -1
  5. package/assets/docs/cli-utilities/configuration.md +11 -1
  6. package/assets/docs/cli-utilities/tool-packs.md +8 -0
  7. package/assets/docs/contributing/skills.md +67 -14
  8. package/assets/docs/quickstart.md +9 -0
  9. package/assets/docs/reference/cli-reference.md +56 -1
  10. package/assets/docs/reference/file-locations.md +18 -1
  11. package/assets/docs/reference/oat-directory-structure.md +20 -4
  12. package/assets/docs/workflows/projects/artifacts.md +27 -1
  13. package/assets/docs/workflows/projects/implementation-execution.md +22 -0
  14. package/assets/docs/workflows/projects/index.md +6 -0
  15. package/assets/docs/workflows/projects/lifecycle.md +19 -5
  16. package/assets/docs/workflows/projects/picking-up-projects.md +75 -0
  17. package/assets/docs/workflows/projects/pr-flow.md +22 -1
  18. package/assets/docs/workflows/projects/reviewing-oat-prs.md +60 -0
  19. package/assets/public-package-versions.json +4 -4
  20. package/assets/skills/analyze/SKILL.md +13 -5
  21. package/assets/skills/compare/SKILL.md +11 -2
  22. package/assets/skills/oat-brainstorm/SKILL.md +135 -32
  23. package/assets/skills/oat-brainstorm/references/destinations.md +9 -6
  24. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +11 -1
  25. package/assets/skills/oat-dispatch-subagents/SKILL.md +19 -6
  26. package/assets/skills/oat-doctor/SKILL.md +8 -1
  27. package/assets/skills/oat-project-autonomous/SKILL.md +45 -1
  28. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +8 -8
  29. package/assets/skills/oat-project-capture/SKILL.md +29 -9
  30. package/assets/skills/oat-project-complete/SKILL.md +610 -38
  31. package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +265 -0
  32. package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +764 -0
  33. package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +134 -0
  34. package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +160 -0
  35. package/assets/skills/oat-project-design/SKILL.md +33 -9
  36. package/assets/skills/oat-project-discover/SKILL.md +16 -3
  37. package/assets/skills/oat-project-document/SKILL.md +10 -4
  38. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +8 -8
  39. package/assets/skills/oat-project-implement/SKILL.md +14 -3
  40. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +18 -6
  41. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +8 -8
  42. package/assets/skills/oat-project-implement/references/phase-execution.md +9 -3
  43. package/assets/skills/oat-project-implement/references/plan-and-resume.md +3 -0
  44. package/assets/skills/oat-project-import-plan/SKILL.md +15 -9
  45. package/assets/skills/oat-project-new/SKILL.md +7 -5
  46. package/assets/skills/oat-project-next/SKILL.md +32 -10
  47. package/assets/skills/oat-project-plan/SKILL.md +18 -3
  48. package/assets/skills/oat-project-pr-final/SKILL.md +23 -2
  49. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +8 -8
  50. package/assets/skills/oat-project-pr-progress/SKILL.md +23 -2
  51. package/assets/skills/oat-project-progress/SKILL.md +23 -9
  52. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +20 -2
  53. package/assets/skills/oat-project-quick-start/SKILL.md +48 -18
  54. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +8 -8
  55. package/assets/skills/oat-project-reconcile/SKILL.md +14 -10
  56. package/assets/skills/oat-project-retro/SKILL.md +3 -3
  57. package/assets/skills/oat-project-retro/references/apply-procedure.md +102 -6
  58. package/assets/skills/oat-project-retro-file/SKILL.md +57 -6
  59. package/assets/skills/oat-project-review-provide/SKILL.md +56 -6
  60. package/assets/skills/oat-project-review-receive/SKILL.md +16 -7
  61. package/assets/skills/oat-project-review-receive-remote/SKILL.md +9 -3
  62. package/assets/skills/oat-project-revise/SKILL.md +12 -3
  63. package/assets/skills/oat-project-spec/SKILL.md +16 -3
  64. package/assets/skills/oat-project-summary/SKILL.md +113 -13
  65. package/assets/skills/oat-repo-improve/SKILL.md +18 -7
  66. package/assets/skills/oat-review-provide-remote/SKILL.md +11 -2
  67. package/assets/skills/oat-wave-execute/SKILL.md +34 -2
  68. package/assets/skills/oat-worktree-bootstrap/SKILL.md +13 -1
  69. package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +13 -1
  70. package/dist/commands/config/index.d.ts +1 -0
  71. package/dist/commands/config/index.d.ts.map +1 -1
  72. package/dist/commands/config/index.js +30 -2
  73. package/dist/commands/doctor/index.d.ts +2 -0
  74. package/dist/commands/doctor/index.d.ts.map +1 -1
  75. package/dist/commands/doctor/index.js +27 -3
  76. package/dist/commands/doctor/synced-projects.d.ts +12 -0
  77. package/dist/commands/doctor/synced-projects.d.ts.map +1 -0
  78. package/dist/commands/doctor/synced-projects.js +208 -0
  79. package/dist/commands/init/gitattributes.d.ts +4 -0
  80. package/dist/commands/init/gitattributes.d.ts.map +1 -0
  81. package/dist/commands/init/gitattributes.js +12 -0
  82. package/dist/commands/init/gitignore.d.ts +8 -1
  83. package/dist/commands/init/gitignore.d.ts.map +1 -1
  84. package/dist/commands/init/gitignore.js +146 -41
  85. package/dist/commands/init/index.d.ts +2 -0
  86. package/dist/commands/init/index.d.ts.map +1 -1
  87. package/dist/commands/init/index.js +3 -0
  88. package/dist/commands/init/managed-block.d.ts +10 -0
  89. package/dist/commands/init/managed-block.d.ts.map +1 -0
  90. package/dist/commands/init/managed-block.js +40 -0
  91. package/dist/commands/init/tools/workflows/install-workflows.js +1 -1
  92. package/dist/commands/local/index.d.ts.map +1 -1
  93. package/dist/commands/local/index.js +5 -1
  94. package/dist/commands/local/sync.d.ts +4 -0
  95. package/dist/commands/local/sync.d.ts.map +1 -1
  96. package/dist/commands/local/sync.js +123 -2
  97. package/dist/commands/pjm/adoption.d.ts +2 -0
  98. package/dist/commands/pjm/adoption.d.ts.map +1 -1
  99. package/dist/commands/pjm/adoption.js +1 -1
  100. package/dist/commands/project/archive/archive-utils.d.ts +24 -0
  101. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  102. package/dist/commands/project/archive/archive-utils.js +349 -22
  103. package/dist/commands/project/archive/index.d.ts.map +1 -1
  104. package/dist/commands/project/archive/index.js +1 -0
  105. package/dist/commands/project/archive/push-runner.d.ts +5 -1
  106. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  107. package/dist/commands/project/archive/push-runner.js +33 -4
  108. package/dist/commands/project/complete-state/index.d.ts.map +1 -1
  109. package/dist/commands/project/complete-state/index.js +3 -1
  110. package/dist/commands/project/index.d.ts.map +1 -1
  111. package/dist/commands/project/index.js +12 -0
  112. package/dist/commands/project/links/compute.d.ts +9 -0
  113. package/dist/commands/project/links/compute.d.ts.map +1 -0
  114. package/dist/commands/project/links/compute.js +27 -0
  115. package/dist/commands/project/links/index.d.ts +17 -0
  116. package/dist/commands/project/links/index.d.ts.map +1 -0
  117. package/dist/commands/project/links/index.js +72 -0
  118. package/dist/commands/project/links/refresh.d.ts +26 -0
  119. package/dist/commands/project/links/refresh.d.ts.map +1 -0
  120. package/dist/commands/project/links/refresh.js +92 -0
  121. package/dist/commands/project/links/render.d.ts +24 -0
  122. package/dist/commands/project/links/render.d.ts.map +1 -0
  123. package/dist/commands/project/links/render.js +68 -0
  124. package/dist/commands/project/list.d.ts +5 -0
  125. package/dist/commands/project/list.d.ts.map +1 -1
  126. package/dist/commands/project/list.js +182 -9
  127. package/dist/commands/project/migrate/index.d.ts +22 -0
  128. package/dist/commands/project/migrate/index.d.ts.map +1 -0
  129. package/dist/commands/project/migrate/index.js +79 -0
  130. package/dist/commands/project/new/index.d.ts +2 -0
  131. package/dist/commands/project/new/index.d.ts.map +1 -1
  132. package/dist/commands/project/new/index.js +14 -2
  133. package/dist/commands/project/new/scaffold.d.ts +22 -1
  134. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  135. package/dist/commands/project/new/scaffold.js +287 -69
  136. package/dist/commands/project/open/index.d.ts +16 -0
  137. package/dist/commands/project/open/index.d.ts.map +1 -1
  138. package/dist/commands/project/open/index.js +151 -19
  139. package/dist/commands/project/pause/index.d.ts +8 -0
  140. package/dist/commands/project/pause/index.d.ts.map +1 -1
  141. package/dist/commands/project/pause/index.js +129 -19
  142. package/dist/commands/project/prune/index.d.ts +21 -0
  143. package/dist/commands/project/prune/index.d.ts.map +1 -0
  144. package/dist/commands/project/prune/index.js +95 -0
  145. package/dist/commands/project/pull/index.d.ts +28 -0
  146. package/dist/commands/project/pull/index.d.ts.map +1 -0
  147. package/dist/commands/project/pull/index.js +157 -0
  148. package/dist/commands/project/push/index.d.ts +22 -0
  149. package/dist/commands/project/push/index.d.ts.map +1 -0
  150. package/dist/commands/project/push/index.js +100 -0
  151. package/dist/commands/project/scope/index.d.ts +17 -0
  152. package/dist/commands/project/scope/index.d.ts.map +1 -0
  153. package/dist/commands/project/scope/index.js +107 -0
  154. package/dist/commands/project/split/run.d.ts +4 -0
  155. package/dist/commands/project/split/run.d.ts.map +1 -1
  156. package/dist/commands/project/split/run.js +48 -10
  157. package/dist/commands/project/sync/git.d.ts +18 -0
  158. package/dist/commands/project/sync/git.d.ts.map +1 -0
  159. package/dist/commands/project/sync/git.js +60 -0
  160. package/dist/commands/project/sync/record.d.ts +22 -0
  161. package/dist/commands/project/sync/record.d.ts.map +1 -0
  162. package/dist/commands/project/sync/record.js +133 -0
  163. package/dist/commands/project/sync/ref-sync.d.ts +120 -0
  164. package/dist/commands/project/sync/ref-sync.d.ts.map +1 -0
  165. package/dist/commands/project/sync/ref-sync.js +962 -0
  166. package/dist/commands/project/sync/resolve-target.d.ts +27 -0
  167. package/dist/commands/project/sync/resolve-target.d.ts.map +1 -0
  168. package/dist/commands/project/sync/resolve-target.js +159 -0
  169. package/dist/commands/shared/oat-paths.d.ts +4 -1
  170. package/dist/commands/shared/oat-paths.d.ts.map +1 -1
  171. package/dist/commands/shared/oat-paths.js +2 -2
  172. package/dist/commands/shared/project-scope.d.ts +23 -0
  173. package/dist/commands/shared/project-scope.d.ts.map +1 -0
  174. package/dist/commands/shared/project-scope.js +106 -0
  175. package/dist/commands/tools/migrate/index.js +1 -1
  176. package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
  177. package/dist/commands/tools/shared/pack-inventory.js +11 -0
  178. package/dist/commands/tools/shared/pack-lifecycle.js +1 -1
  179. package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -1
  180. package/dist/commands/tools/shared/pack-reconcile.js +4 -1
  181. package/dist/commands/tools/update/index.d.ts.map +1 -1
  182. package/dist/commands/tools/update/index.js +20 -10
  183. package/dist/commands/tools/update/update-tools.d.ts +2 -0
  184. package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
  185. package/dist/config/oat-config.d.ts +6 -3
  186. package/dist/config/oat-config.d.ts.map +1 -1
  187. package/dist/config/oat-config.js +41 -7
  188. package/dist/config/resolve.d.ts.map +1 -1
  189. package/dist/config/resolve.js +2 -1
  190. package/dist/fs/io.d.ts +2 -1
  191. package/dist/fs/io.d.ts.map +1 -1
  192. package/dist/fs/io.js +5 -2
  193. package/dist/projects/split/finalize.d.ts.map +1 -1
  194. package/dist/projects/split/finalize.js +55 -2
  195. package/dist/projects/split/resume.d.ts +3 -0
  196. package/dist/projects/split/resume.d.ts.map +1 -1
  197. package/dist/projects/split/resume.js +34 -7
  198. package/dist/projects/split/seed-children.d.ts.map +1 -1
  199. package/dist/projects/split/seed-children.js +6 -0
  200. package/dist/projects/split/write-parent.d.ts +7 -0
  201. package/dist/projects/split/write-parent.d.ts.map +1 -1
  202. package/dist/projects/split/write-parent.js +7 -4
  203. package/dist/release/public-package-contract.d.ts.map +1 -1
  204. package/dist/release/public-package-contract.js +1 -0
  205. package/dist/validation/skills.d.ts.map +1 -1
  206. package/dist/validation/skills.js +434 -0
  207. package/package.json +4 -4
  208. package/dist/__tests__/skills/split-flow-fixtures.d.ts +0 -50
  209. package/dist/__tests__/skills/split-flow-fixtures.d.ts.map +0 -1
  210. package/dist/__tests__/skills/split-flow-fixtures.js +0 -161
  211. package/dist/commands/__tests__/helpers.d.ts +0 -12
  212. package/dist/commands/__tests__/helpers.d.ts.map +0 -1
  213. package/dist/commands/__tests__/helpers.js +0 -36
@@ -1,6 +1,7 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { lstat, readFile } from 'node:fs/promises';
3
3
  import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
+ import { CliError } from '../errors/cli-error.js';
4
5
  import { atomicWriteJson, dirExists, fileExists } from '../fs/io.js';
5
6
  import { normalizeToPosixPath, validateRealPathWithinScope } from '../fs/paths.js';
6
7
  import { normalizeDispatchMatrix, } from './dispatch-matrix.js';
@@ -606,7 +607,7 @@ async function normalizeReadableProjectPath(repoRoot, pathValue) {
606
607
  return null;
607
608
  }
608
609
  }
609
- function normalizeOatConfig(parsed) {
610
+ function normalizeOatConfig(parsed, configPath = '.oat/config.json') {
610
611
  const next = { ...DEFAULT_OAT_CONFIG };
611
612
  if (!isRecord(parsed)) {
612
613
  return next;
@@ -616,10 +617,25 @@ function normalizeOatConfig(parsed) {
616
617
  parsed.worktrees.root.trim()) {
617
618
  next.worktrees = { root: parsed.worktrees.root.trim() };
618
619
  }
619
- if (isRecord(parsed.projects) &&
620
- typeof parsed.projects.root === 'string' &&
621
- parsed.projects.root.trim()) {
622
- next.projects = { root: parsed.projects.root.trim() };
620
+ if (isRecord(parsed.projects)) {
621
+ const root = typeof parsed.projects.root === 'string' && parsed.projects.root.trim()
622
+ ? parsed.projects.root.trim()
623
+ : undefined;
624
+ const rawDefaultScope = parsed.projects.defaultScope;
625
+ const defaultScope = rawDefaultScope === 'shared' ||
626
+ rawDefaultScope === 'local' ||
627
+ rawDefaultScope === 'synced'
628
+ ? rawDefaultScope
629
+ : undefined;
630
+ if (rawDefaultScope !== undefined && defaultScope === undefined) {
631
+ throw new CliError(`Invalid projects.defaultScope in ${configPath}: "${String(rawDefaultScope)}". Expected one of: shared, local, synced. Repair it with oat config set projects.defaultScope <shared|local|synced>.`, 2);
632
+ }
633
+ if (root || defaultScope) {
634
+ next.projects = {
635
+ ...(root ? { root } : {}),
636
+ ...(defaultScope ? { defaultScope } : {}),
637
+ };
638
+ }
623
639
  }
624
640
  if (isRecord(parsed.git)) {
625
641
  const git = {};
@@ -754,7 +770,25 @@ export async function readOatConfig(repoRoot) {
754
770
  const configPath = getConfigPath(repoRoot);
755
771
  try {
756
772
  const raw = await readFile(configPath, 'utf8');
757
- return normalizeOatConfig(parseJsonConfig(raw, configPath));
773
+ return normalizeOatConfig(parseJsonConfig(raw, configPath), configPath);
774
+ }
775
+ catch (error) {
776
+ if (isMissingFileError(error)) {
777
+ return { ...DEFAULT_OAT_CONFIG };
778
+ }
779
+ throw error;
780
+ }
781
+ }
782
+ export async function readOatConfigForDefaultScopeRepair(repoRoot) {
783
+ const configPath = getConfigPath(repoRoot);
784
+ try {
785
+ const raw = await readFile(configPath, 'utf8');
786
+ const parsed = parseJsonConfig(raw, configPath);
787
+ if (isRecord(parsed) && isRecord(parsed.projects)) {
788
+ const { defaultScope: _invalidDefaultScope, ...projects } = parsed.projects;
789
+ return normalizeOatConfig({ ...parsed, projects }, configPath);
790
+ }
791
+ return normalizeOatConfig(parsed, configPath);
758
792
  }
759
793
  catch (error) {
760
794
  if (isMissingFileError(error)) {
@@ -782,7 +816,7 @@ export async function readOatLocalConfig(repoRoot) {
782
816
  }
783
817
  export async function writeOatConfig(repoRoot, config) {
784
818
  const configPath = getConfigPath(repoRoot);
785
- const normalized = normalizeOatConfig(config);
819
+ const normalized = normalizeOatConfig(config, configPath);
786
820
  await atomicWriteJson(configPath, normalized);
787
821
  }
788
822
  export async function writeOatLocalConfig(repoRoot, config) {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,OAAO,GACP,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,kCAAkC;IACjD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAChE;AAkHD,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,GAAE,OAAO,CAAC,kCAAkC,CAAM,GAC1D,OAAO,CAAC,cAAc,CAAC,CAgFzB;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,GAChB,UAAU,GAAG,IAAI,CAcnB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAY5B;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAoDxC"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,OAAO,GACP,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,kCAAkC;IACjD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAChE;AAmHD,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,GAAE,OAAO,CAAC,kCAAkC,CAAM,GAC1D,OAAO,CAAC,cAAc,CAAC,CAgFzB;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,GAChB,UAAU,GAAG,IAAI,CAcnB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAY5B;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAoDxC"}
@@ -6,7 +6,7 @@ const DEFAULT_DEPENDENCIES = {
6
6
  readUserConfig,
7
7
  };
8
8
  const DEFAULT_SHARED_CONFIG = {
9
- projects: { root: '.oat/projects/shared' },
9
+ projects: { root: '.oat/projects/shared', defaultScope: 'synced' },
10
10
  worktrees: { root: '.worktrees' },
11
11
  git: { defaultBranch: 'main' },
12
12
  archive: {
@@ -104,6 +104,7 @@ const DEFAULT_WORKFLOW_CONFIG = {
104
104
  };
105
105
  const ENV_OVERRIDE_MAP = {
106
106
  'projects.root': 'OAT_PROJECTS_ROOT',
107
+ 'projects.defaultScope': 'OAT_PROJECTS_DEFAULT_SCOPE',
107
108
  'worktrees.root': 'OAT_WORKTREES_ROOT',
108
109
  };
109
110
  export async function resolveEffectiveConfig(repoRoot, userConfigDir, env = process.env, overrides = {}) {
package/dist/fs/io.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export declare function fileExists(path: string): Promise<boolean>;
2
2
  export declare function dirExists(path: string): Promise<boolean>;
3
3
  export type LinkStrategy = 'symlink' | 'copy';
4
+ export type CopyDirectoryFilter = (sourcePath: string, relativePath: string) => boolean | Promise<boolean>;
4
5
  export declare function ensureDir(dirPath: string): Promise<void>;
5
- export declare function copyDirectory(src: string, dest: string): Promise<void>;
6
+ export declare function copyDirectory(src: string, dest: string, filter?: CopyDirectoryFilter, sourceRoot?: string): Promise<void>;
6
7
  export declare function copySingleFile(src: string, dest: string): Promise<void>;
7
8
  export declare function createSymlink(target: string, linkPath: string, onFallback?: (error: unknown) => void, isFile?: boolean): Promise<LinkStrategy>;
8
9
  export declare function atomicWriteJson(filePath: string, data: unknown): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/fs/io.ts"],"names":[],"mappings":"AAaA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9D;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9C,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB5E;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACrC,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,YAAY,CAAC,CAuBvB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,CAAC,CAKf"}
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/fs/io.ts"],"names":[],"mappings":"AAaA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9D;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,mBAAmB,GAAG,CAChC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,KACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,mBAAmB,EAC5B,UAAU,SAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACrC,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,YAAY,CAAC,CAuBvB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,CAAC,CAKf"}
package/dist/fs/io.js CHANGED
@@ -21,14 +21,17 @@ export async function dirExists(path) {
21
21
  export async function ensureDir(dirPath) {
22
22
  await mkdir(dirPath, { recursive: true });
23
23
  }
24
- export async function copyDirectory(src, dest) {
24
+ export async function copyDirectory(src, dest, filter, sourceRoot = src) {
25
25
  await ensureDir(dest);
26
26
  const entries = await readdir(src, { withFileTypes: true });
27
27
  for (const entry of entries) {
28
28
  const sourcePath = join(src, entry.name);
29
29
  const destPath = join(dest, entry.name);
30
+ const relativePath = relative(sourceRoot, sourcePath);
31
+ if (filter && !(await filter(sourcePath, relativePath)))
32
+ continue;
30
33
  if (entry.isDirectory()) {
31
- await copyDirectory(sourcePath, destPath);
34
+ await copyDirectory(sourcePath, destPath, filter, sourceRoot);
32
35
  continue;
33
36
  }
34
37
  if (entry.isFile()) {
@@ -1 +1 @@
1
- {"version":3,"file":"finalize.d.ts","sourceRoot":"","sources":["../../../src/projects/split/finalize.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CAoB9B"}
1
+ {"version":3,"file":"finalize.d.ts","sourceRoot":"","sources":["../../../src/projects/split/finalize.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAiB1D,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAeD,wBAAsB,aAAa,CACjC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CAsE9B"}
@@ -1,8 +1,11 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
+ import { defaultGitRunner } from '../../commands/project/sync/git.js';
4
+ import { buildSyncTarget, pendingRebaseConflicts, pushSynced as defaultPushSynced, } from '../../commands/project/sync/ref-sync.js';
3
5
  import { getFrontmatterBlock } from '../../commands/shared/frontmatter.js';
4
6
  import { replaceFrontmatter } from '../../commands/shared/frontmatter-write.js';
5
7
  import { setActiveProject } from '../../config/oat-config.js';
8
+ import { CliError } from '../../errors/cli-error.js';
6
9
  import YAML from 'yaml';
7
10
  function readObjectFrontmatter(content, filePath) {
8
11
  const block = getFrontmatterBlock(content);
@@ -15,16 +18,66 @@ function readObjectFrontmatter(content, filePath) {
15
18
  }
16
19
  return parsed;
17
20
  }
21
+ function shellQuote(value) {
22
+ return `'${value.replaceAll("'", `'\\''`)}'`;
23
+ }
24
+ function conflictError(target, conflicts) {
25
+ const detail = conflicts.length > 0 ? ` (${conflicts.join(', ')})` : '';
26
+ const targetArg = shellQuote(target.projectPath);
27
+ return new CliError(`Failed to publish synced split project ${target.slug}: conflict${detail}. Resolve the files, then run oat project pull ${targetArg} --continue; or run oat project pull ${targetArg} --abort. After recovery, rerun split with --resume.`, 1);
28
+ }
18
29
  export async function finalizeSplit(plan, context) {
19
30
  const projectsRoot = context.projectsRoot ?? '.oat/projects/shared';
20
- const parentPath = join(projectsRoot, plan.parentSlug).split('\\').join('/');
31
+ const scopeRoot = context.scopeRoot ?? projectsRoot;
32
+ const parentPath = join(scopeRoot, plan.parentSlug).split('\\').join('/');
21
33
  const statePath = join(context.repoRoot, parentPath, 'state.md');
22
34
  const stateContent = await readFile(statePath, 'utf8');
23
35
  const frontmatter = readObjectFrontmatter(stateContent, statePath);
36
+ const gitRunner = context.gitRunner ?? defaultGitRunner;
37
+ const syncTargets = context.scope === 'synced'
38
+ ? [
39
+ plan.parentSlug,
40
+ ...plan.children
41
+ .slice()
42
+ .sort((left, right) => left.order - right.order)
43
+ .map((child) => child.slug),
44
+ ].map((slug) => buildSyncTarget(context.repoRoot, projectsRoot, slug))
45
+ : [];
46
+ for (const target of syncTargets) {
47
+ const conflicts = await pendingRebaseConflicts(target, gitRunner);
48
+ if (conflicts !== null) {
49
+ throw conflictError(target, conflicts);
50
+ }
51
+ }
24
52
  frontmatter['oat_phase'] = 'decomposition';
25
53
  frontmatter['oat_phase_status'] = 'complete';
26
54
  await writeFile(statePath, replaceFrontmatter(stateContent, YAML.stringify(frontmatter).trimEnd()), 'utf8');
27
- const activeProjectPath = join(projectsRoot, plan.initialActiveChild)
55
+ if (context.scope === 'synced') {
56
+ const pushSynced = context.pushSynced ?? defaultPushSynced;
57
+ try {
58
+ for (const target of syncTargets) {
59
+ const result = await pushSynced(target, gitRunner, {
60
+ message: `chore(oat): finalize split ${plan.parentSlug}`,
61
+ });
62
+ if (result.status !== 'pushed' && result.status !== 'up-to-date') {
63
+ if (result.status === 'conflict') {
64
+ throw conflictError(target, result.conflicts ?? []);
65
+ }
66
+ throw new CliError(`Failed to publish synced split project ${target.slug}: ${result.status}`, 1);
67
+ }
68
+ }
69
+ }
70
+ catch (error) {
71
+ try {
72
+ await writeFile(statePath, stateContent, 'utf8');
73
+ }
74
+ catch (rollbackError) {
75
+ throw new CliError(`Failed to restore resumable split state after publication failure: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}. Original failure: ${error instanceof Error ? error.message : String(error)}`, 2);
76
+ }
77
+ throw error;
78
+ }
79
+ }
80
+ const activeProjectPath = join(scopeRoot, plan.initialActiveChild)
28
81
  .split('\\')
29
82
  .join('/');
30
83
  await setActiveProject(context.repoRoot, activeProjectPath);
@@ -1,3 +1,4 @@
1
+ import { type ProjectScope } from '../../commands/shared/project-scope.js';
1
2
  import type { ChildPlan, SplitPlanDocument } from './child-plan.js';
2
3
  import type { SplitProjectContext } from './write-parent.js';
3
4
  export declare class SplitResumeError extends Error {
@@ -9,6 +10,8 @@ export interface PartialSplit {
9
10
  missingChildren: string[];
10
11
  parentProjectPath: string;
11
12
  projectsRoot: string;
13
+ scope: ProjectScope;
14
+ scopeRoot: string;
12
15
  }
13
16
  export interface ResumeSplitOptions {
14
17
  confirmed?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/projects/split/resume.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAKjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA6CD,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,YAAY,CAAC,CA8DvB;AAED,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAQvB;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAavB"}
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/projects/split/resume.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAKjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAoED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAwEvB;AAED,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAQvB;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAoBvB"}
@@ -1,6 +1,7 @@
1
1
  import { readFile, stat } from 'node:fs/promises';
2
- import { isAbsolute, join, relative } from 'node:path';
2
+ import { dirname, isAbsolute, join, relative } from 'node:path';
3
3
  import { getFrontmatterBlock } from '../../commands/shared/frontmatter.js';
4
+ import { resolveProjectScope, } from '../../commands/shared/project-scope.js';
4
5
  import YAML from 'yaml';
5
6
  import { validateSplitPlanDocumentShape } from './document-validation.js';
6
7
  import { finalizeSplit } from './finalize.js';
@@ -39,12 +40,26 @@ function resolveParentPaths(parentPath, context) {
39
40
  const parentProjectPath = relative(context.repoRoot, absoluteParentPath)
40
41
  .split('\\')
41
42
  .join('/');
42
- const segments = parentProjectPath.split('/');
43
- const projectsRoot = segments.slice(0, -1).join('/');
44
- return { absoluteParentPath, parentProjectPath, projectsRoot };
43
+ const scopeRoot = dirname(parentProjectPath).split('\\').join('/');
44
+ const projectsRoot = context.projectsRoot ??
45
+ join(dirname(scopeRoot), 'shared').split('\\').join('/');
46
+ const absoluteProjectsRoot = isAbsolute(projectsRoot)
47
+ ? projectsRoot
48
+ : join(context.repoRoot, projectsRoot);
49
+ const scope = resolveProjectScope(absoluteParentPath, absoluteProjectsRoot, context.repoRoot);
50
+ if (!scope) {
51
+ throw new SplitResumeError(`Cannot derive project scope from persisted parent path: ${parentProjectPath}`);
52
+ }
53
+ return {
54
+ absoluteParentPath,
55
+ parentProjectPath,
56
+ projectsRoot,
57
+ scope,
58
+ scopeRoot,
59
+ };
45
60
  }
46
61
  export async function detectPartialSplit(parentPath, context) {
47
- const { absoluteParentPath, parentProjectPath, projectsRoot } = resolveParentPaths(parentPath, context);
62
+ const { absoluteParentPath, parentProjectPath, projectsRoot, scope, scopeRoot, } = resolveParentPaths(parentPath, context);
48
63
  const statePath = join(absoluteParentPath, 'state.md');
49
64
  const state = readObjectFrontmatter(await readFile(statePath, 'utf8'), statePath);
50
65
  if (state['oat_kind'] !== 'coordination') {
@@ -75,8 +90,11 @@ export async function detectPartialSplit(parentPath, context) {
75
90
  .join('; ')}`);
76
91
  }
77
92
  const missingChildren = [];
93
+ const absoluteScopeRoot = isAbsolute(scopeRoot)
94
+ ? scopeRoot
95
+ : join(context.repoRoot, scopeRoot);
78
96
  for (const child of document.plan.children) {
79
- if (!(await exists(join(context.repoRoot, projectsRoot, child.slug)))) {
97
+ if (!(await exists(join(absoluteScopeRoot, child.slug)))) {
80
98
  missingChildren.push(child.slug);
81
99
  }
82
100
  }
@@ -86,6 +104,8 @@ export async function detectPartialSplit(parentPath, context) {
86
104
  missingChildren,
87
105
  parentProjectPath,
88
106
  projectsRoot,
107
+ scope,
108
+ scopeRoot,
89
109
  };
90
110
  }
91
111
  export async function resumeSplit(parentPath, context, options = {}) {
@@ -97,11 +117,18 @@ export async function resumeSplit(parentPath, context, options = {}) {
97
117
  }
98
118
  export async function continueSplitResume(partial, context) {
99
119
  if (partial.missingChildren.length > 0) {
100
- await seedChildren(partial.plan, { ...context, projectsRoot: partial.projectsRoot }, new Set(partial.missingChildren));
120
+ await seedChildren(partial.plan, {
121
+ ...context,
122
+ projectsRoot: partial.projectsRoot,
123
+ scope: partial.scope,
124
+ scopeRoot: partial.scopeRoot,
125
+ }, new Set(partial.missingChildren));
101
126
  }
102
127
  await finalizeSplit(partial.plan, {
103
128
  ...context,
104
129
  projectsRoot: partial.projectsRoot,
130
+ scope: partial.scope,
131
+ scopeRoot: partial.scopeRoot,
105
132
  });
106
133
  return partial;
107
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"seed-children.d.ts","sourceRoot":"","sources":["../../../src/projects/split/seed-children.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,QAAA,MAAM,eAAe,YACnB,QAAQ,EACR,mBAAmB,EACnB,qCAAqC,EACrC,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,CACV,CAAC;AA0GX,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAoD7B;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"seed-children.d.ts","sourceRoot":"","sources":["../../../src/projects/split/seed-children.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,QAAA,MAAM,eAAe,YACnB,QAAQ,EACR,mBAAmB,EACnB,qCAAqC,EACrC,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,CACV,CAAC;AA0GX,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA8D7B;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -3,6 +3,7 @@ import { join } from 'node:path';
3
3
  import { scaffoldProject as defaultScaffoldProject } from '../../commands/project/new/scaffold.js';
4
4
  import { getFrontmatterBlock } from '../../commands/shared/frontmatter.js';
5
5
  import { replaceFrontmatter } from '../../commands/shared/frontmatter-write.js';
6
+ import { resolveProjectScope } from '../../commands/shared/project-scope.js';
6
7
  import YAML from 'yaml';
7
8
  const SEEDED_SECTIONS = [
8
9
  'Origin',
@@ -106,6 +107,10 @@ function renderSeededDiscovery(plan, child) {
106
107
  }
107
108
  export async function seedChildren(plan, context, onlySlugs) {
108
109
  const scaffoldProject = context.scaffoldProject ?? defaultScaffoldProject;
110
+ const projectsRoot = context.projectsRoot ?? '.oat/projects/shared';
111
+ const scope = context.scope ??
112
+ resolveProjectScope(join(projectsRoot, plan.parentSlug), projectsRoot, context.repoRoot) ??
113
+ 'shared';
109
114
  const childProjectPaths = [];
110
115
  const orderedChildren = plan.children
111
116
  .slice()
@@ -115,6 +120,7 @@ export async function seedChildren(plan, context, onlySlugs) {
115
120
  const scaffold = await scaffoldProject({
116
121
  repoRoot: context.repoRoot,
117
122
  projectName: child.slug,
123
+ scope,
118
124
  mode: 'quick',
119
125
  setActive: false,
120
126
  refreshDashboard: false,
@@ -1,4 +1,7 @@
1
1
  import { scaffoldProject as defaultScaffoldProject, type ScaffoldProjectResult } from '../../commands/project/new/scaffold.js';
2
+ import type { GitRunner } from '../../commands/project/sync/git.js';
3
+ import type { pushSynced } from '../../commands/project/sync/ref-sync.js';
4
+ import { type ProjectScope } from '../../commands/shared/project-scope.js';
2
5
  import type { SplitPlanDocument } from './child-plan.js';
3
6
  export interface SplitProjectContext {
4
7
  repoRoot: string;
@@ -6,7 +9,11 @@ export interface SplitProjectContext {
6
9
  today?: string;
7
10
  nowUtc?: string;
8
11
  env?: NodeJS.ProcessEnv;
12
+ scope?: ProjectScope;
13
+ scopeRoot?: string;
9
14
  scaffoldProject?: typeof defaultScaffoldProject;
15
+ gitRunner?: GitRunner;
16
+ pushSynced?: typeof pushSynced;
10
17
  }
11
18
  export interface WriteCoordinationParentResult {
12
19
  parentProjectPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"write-parent.d.ts","sourceRoot":"","sources":["../../../src/projects/split/write-parent.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,IAAI,sBAAsB,EACzC,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAC;AAMxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,sBAAsB,CAAC;CACjD;AA6JD,MAAM,WAAW,6BAA6B;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,qBAAqB,CAAC;CACjC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,6BAA6B,CAAC,CA4DxC"}
1
+ {"version":3,"file":"write-parent.d.ts","sourceRoot":"","sources":["../../../src/projects/split/write-parent.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,IAAI,sBAAsB,EACzC,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAChD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,UAAU,CAAC;CAChC;AAyJD,MAAM,WAAW,6BAA6B;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,qBAAqB,CAAC;CACjC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,6BAA6B,CAAC,CAmExC"}
@@ -3,6 +3,7 @@ import { join } from 'node:path';
3
3
  import { scaffoldProject as defaultScaffoldProject, } from '../../commands/project/new/scaffold.js';
4
4
  import { getFrontmatterBlock } from '../../commands/shared/frontmatter.js';
5
5
  import { replaceFrontmatter } from '../../commands/shared/frontmatter-write.js';
6
+ import { resolveProjectScope, } from '../../commands/shared/project-scope.js';
6
7
  import { assertValidProjectStateFilesystemContent } from '../../validation/project-state.js';
7
8
  import YAML from 'yaml';
8
9
  function readObjectFrontmatter(content, filePath) {
@@ -22,9 +23,6 @@ async function writeObjectFrontmatter(filePath, updates) {
22
23
  updates(frontmatter);
23
24
  await writeFile(filePath, replaceFrontmatter(content, YAML.stringify(frontmatter).trimEnd()), 'utf8');
24
25
  }
25
- function projectPathFor(projectsRoot, slug) {
26
- return join(projectsRoot, slug).split('\\').join('/');
27
- }
28
26
  function renderParentDiscovery(document) {
29
27
  const { plan } = document;
30
28
  const orderedChildren = plan.children
@@ -138,9 +136,14 @@ async function replaceMarkdownBody(filePath, body) {
138
136
  }
139
137
  export async function writeCoordinationParent(document, context) {
140
138
  const scaffoldProject = context.scaffoldProject ?? defaultScaffoldProject;
139
+ const projectsRoot = context.projectsRoot ?? '.oat/projects/shared';
140
+ const scope = context.scope ??
141
+ resolveProjectScope(join(projectsRoot, document.plan.parentSlug), projectsRoot, context.repoRoot) ??
142
+ 'shared';
141
143
  const scaffold = await scaffoldProject({
142
144
  repoRoot: context.repoRoot,
143
145
  projectName: document.plan.parentSlug,
146
+ scope,
144
147
  mode: 'quick',
145
148
  setActive: false,
146
149
  refreshDashboard: false,
@@ -170,7 +173,7 @@ export async function writeCoordinationParent(document, context) {
170
173
  projectPath: parentRoot,
171
174
  });
172
175
  return {
173
- parentProjectPath: projectPathFor(context.projectsRoot ?? scaffold.projectsRoot, document.plan.parentSlug),
176
+ parentProjectPath: scaffold.projectPath,
174
177
  scaffold,
175
178
  };
176
179
  }
@@ -1 +1 @@
1
- {"version":3,"file":"public-package-contract.d.ts","sourceRoot":"","sources":["../../src/release/public-package-contract.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,cAAc,GAAG,iBAAiB,CAAC;IACjD,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;IACrD,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,4BAA4B,EAAE,MAAM,EAAE,CAAC;IACvC,2BAA2B,EAAE,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AA4KD,wBAAgB,yBAAyB,IAAI,qBAAqB,EAAE,CAenE;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAMV;AAED,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACjD,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAoBV;AAED,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,EAAE,CAmBV;AAED,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,qBAAqB,EAAE,SAAS,MAAM,EAAE,GACvC,MAAM,EAAE,CA0BV"}
1
+ {"version":3,"file":"public-package-contract.d.ts","sourceRoot":"","sources":["../../src/release/public-package-contract.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,cAAc,GAAG,iBAAiB,CAAC;IACjD,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;IACrD,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,4BAA4B,EAAE,MAAM,EAAE,CAAC;IACvC,2BAA2B,EAAE,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AA6KD,wBAAgB,yBAAyB,IAAI,qBAAqB,EAAE,CAenE;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAIV;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAMV;AAED,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACjD,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,EAAE,CAoBV;AAED,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,EAAE,CAmBV;AAED,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,qBAAqB,EAAE,SAAS,MAAM,EAAE,GACvC,MAAM,EAAE,CA0BV"}
@@ -10,6 +10,7 @@ const COMMON_METADATA_FIELDS = [
10
10
  const COMMON_FORBIDDEN_PATH_PATTERNS = [
11
11
  'src/**',
12
12
  '**/*.test.*',
13
+ '**/__tests__/**',
13
14
  'tsconfig.tsbuildinfo',
14
15
  ];
15
16
  const PACKED_DEPENDENCY_FIELDS = [
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sCAAsC;IACrD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChD,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAuSD,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,EAChD,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,sCAAsC,CAAC,CAoBjD;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,EACtC,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,CAmIlC"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sCAAsC;IACrD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChD,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AA04BD,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,EAChD,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,sCAAsC,CAAC,CAoBjD;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,EACtC,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,CAqIlC"}