@open-agent-toolkit/cli 0.2.41 → 0.2.46

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 (212) hide show
  1. package/assets/agents/oat-phase-implementer.md +11 -1
  2. package/assets/bundle-metadata.json +1 -1
  3. package/assets/docs/cli-utilities/configuration.md +11 -1
  4. package/assets/docs/cli-utilities/tool-packs.md +55 -9
  5. package/assets/docs/quickstart.md +9 -0
  6. package/assets/docs/reference/cli-reference.md +56 -1
  7. package/assets/docs/reference/file-locations.md +18 -1
  8. package/assets/docs/reference/oat-directory-structure.md +20 -4
  9. package/assets/docs/reference/troubleshooting.md +18 -11
  10. package/assets/docs/workflows/projects/artifacts.md +27 -1
  11. package/assets/docs/workflows/projects/implementation-execution.md +22 -0
  12. package/assets/docs/workflows/projects/index.md +6 -0
  13. package/assets/docs/workflows/projects/lifecycle.md +19 -5
  14. package/assets/docs/workflows/projects/picking-up-projects.md +75 -0
  15. package/assets/docs/workflows/projects/pr-flow.md +22 -1
  16. package/assets/docs/workflows/projects/reviewing-oat-prs.md +60 -0
  17. package/assets/public-package-versions.json +4 -4
  18. package/assets/skills/oat-brainstorm/SKILL.md +135 -32
  19. package/assets/skills/oat-brainstorm/references/destinations.md +9 -6
  20. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +11 -1
  21. package/assets/skills/oat-doctor/SKILL.md +8 -1
  22. package/assets/skills/oat-project-autonomous/SKILL.md +45 -1
  23. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +8 -8
  24. package/assets/skills/oat-project-capture/SKILL.md +29 -9
  25. package/assets/skills/oat-project-complete/SKILL.md +610 -38
  26. package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +265 -0
  27. package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +764 -0
  28. package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +134 -0
  29. package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +160 -0
  30. package/assets/skills/oat-project-design/SKILL.md +33 -9
  31. package/assets/skills/oat-project-discover/SKILL.md +16 -3
  32. package/assets/skills/oat-project-document/SKILL.md +10 -4
  33. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +8 -8
  34. package/assets/skills/oat-project-implement/SKILL.md +14 -3
  35. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +18 -6
  36. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +8 -8
  37. package/assets/skills/oat-project-implement/references/phase-execution.md +9 -3
  38. package/assets/skills/oat-project-implement/references/plan-and-resume.md +3 -0
  39. package/assets/skills/oat-project-import-plan/SKILL.md +15 -9
  40. package/assets/skills/oat-project-new/SKILL.md +7 -5
  41. package/assets/skills/oat-project-next/SKILL.md +32 -10
  42. package/assets/skills/oat-project-plan/SKILL.md +18 -3
  43. package/assets/skills/oat-project-pr-final/SKILL.md +23 -2
  44. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +8 -8
  45. package/assets/skills/oat-project-pr-progress/SKILL.md +23 -2
  46. package/assets/skills/oat-project-progress/SKILL.md +23 -9
  47. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +20 -2
  48. package/assets/skills/oat-project-quick-start/SKILL.md +48 -18
  49. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +8 -8
  50. package/assets/skills/oat-project-reconcile/SKILL.md +14 -10
  51. package/assets/skills/oat-project-retro/SKILL.md +3 -3
  52. package/assets/skills/oat-project-retro/references/apply-procedure.md +102 -6
  53. package/assets/skills/oat-project-retro-file/SKILL.md +57 -6
  54. package/assets/skills/oat-project-review-provide/SKILL.md +45 -4
  55. package/assets/skills/oat-project-review-receive/SKILL.md +16 -7
  56. package/assets/skills/oat-project-review-receive-remote/SKILL.md +9 -3
  57. package/assets/skills/oat-project-revise/SKILL.md +12 -3
  58. package/assets/skills/oat-project-spec/SKILL.md +16 -3
  59. package/assets/skills/oat-project-summary/SKILL.md +113 -13
  60. package/assets/skills/oat-wave-execute/SKILL.md +34 -2
  61. package/assets/skills/oat-worktree-bootstrap/SKILL.md +13 -1
  62. package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +13 -1
  63. package/dist/commands/config/index.d.ts +1 -0
  64. package/dist/commands/config/index.d.ts.map +1 -1
  65. package/dist/commands/config/index.js +34 -3
  66. package/dist/commands/doctor/index.d.ts +2 -0
  67. package/dist/commands/doctor/index.d.ts.map +1 -1
  68. package/dist/commands/doctor/index.js +27 -3
  69. package/dist/commands/doctor/synced-projects.d.ts +12 -0
  70. package/dist/commands/doctor/synced-projects.d.ts.map +1 -0
  71. package/dist/commands/doctor/synced-projects.js +208 -0
  72. package/dist/commands/init/gitattributes.d.ts +4 -0
  73. package/dist/commands/init/gitattributes.d.ts.map +1 -0
  74. package/dist/commands/init/gitattributes.js +12 -0
  75. package/dist/commands/init/gitignore.d.ts +8 -1
  76. package/dist/commands/init/gitignore.d.ts.map +1 -1
  77. package/dist/commands/init/gitignore.js +146 -41
  78. package/dist/commands/init/index.d.ts +2 -0
  79. package/dist/commands/init/index.d.ts.map +1 -1
  80. package/dist/commands/init/index.js +3 -0
  81. package/dist/commands/init/managed-block.d.ts +10 -0
  82. package/dist/commands/init/managed-block.d.ts.map +1 -0
  83. package/dist/commands/init/managed-block.js +40 -0
  84. package/dist/commands/init/tools/index.d.ts +1 -0
  85. package/dist/commands/init/tools/index.d.ts.map +1 -1
  86. package/dist/commands/init/tools/index.js +37 -9
  87. package/dist/commands/init/tools/workflows/install-workflows.js +1 -1
  88. package/dist/commands/local/index.d.ts.map +1 -1
  89. package/dist/commands/local/index.js +5 -1
  90. package/dist/commands/local/sync.d.ts +4 -0
  91. package/dist/commands/local/sync.d.ts.map +1 -1
  92. package/dist/commands/local/sync.js +123 -2
  93. package/dist/commands/pjm/adoption.d.ts +2 -0
  94. package/dist/commands/pjm/adoption.d.ts.map +1 -1
  95. package/dist/commands/pjm/adoption.js +1 -1
  96. package/dist/commands/project/archive/archive-utils.d.ts +24 -0
  97. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  98. package/dist/commands/project/archive/archive-utils.js +349 -22
  99. package/dist/commands/project/archive/index.d.ts.map +1 -1
  100. package/dist/commands/project/archive/index.js +1 -0
  101. package/dist/commands/project/archive/push-runner.d.ts +5 -1
  102. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  103. package/dist/commands/project/archive/push-runner.js +33 -4
  104. package/dist/commands/project/complete-state/index.d.ts.map +1 -1
  105. package/dist/commands/project/complete-state/index.js +3 -1
  106. package/dist/commands/project/index.d.ts.map +1 -1
  107. package/dist/commands/project/index.js +12 -0
  108. package/dist/commands/project/links/compute.d.ts +9 -0
  109. package/dist/commands/project/links/compute.d.ts.map +1 -0
  110. package/dist/commands/project/links/compute.js +27 -0
  111. package/dist/commands/project/links/index.d.ts +17 -0
  112. package/dist/commands/project/links/index.d.ts.map +1 -0
  113. package/dist/commands/project/links/index.js +72 -0
  114. package/dist/commands/project/links/refresh.d.ts +26 -0
  115. package/dist/commands/project/links/refresh.d.ts.map +1 -0
  116. package/dist/commands/project/links/refresh.js +92 -0
  117. package/dist/commands/project/links/render.d.ts +24 -0
  118. package/dist/commands/project/links/render.d.ts.map +1 -0
  119. package/dist/commands/project/links/render.js +68 -0
  120. package/dist/commands/project/list.d.ts +5 -0
  121. package/dist/commands/project/list.d.ts.map +1 -1
  122. package/dist/commands/project/list.js +182 -9
  123. package/dist/commands/project/migrate/index.d.ts +22 -0
  124. package/dist/commands/project/migrate/index.d.ts.map +1 -0
  125. package/dist/commands/project/migrate/index.js +79 -0
  126. package/dist/commands/project/new/index.d.ts +2 -0
  127. package/dist/commands/project/new/index.d.ts.map +1 -1
  128. package/dist/commands/project/new/index.js +14 -2
  129. package/dist/commands/project/new/scaffold.d.ts +22 -1
  130. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  131. package/dist/commands/project/new/scaffold.js +287 -69
  132. package/dist/commands/project/open/index.d.ts +16 -0
  133. package/dist/commands/project/open/index.d.ts.map +1 -1
  134. package/dist/commands/project/open/index.js +151 -19
  135. package/dist/commands/project/pause/index.d.ts +8 -0
  136. package/dist/commands/project/pause/index.d.ts.map +1 -1
  137. package/dist/commands/project/pause/index.js +129 -19
  138. package/dist/commands/project/prune/index.d.ts +21 -0
  139. package/dist/commands/project/prune/index.d.ts.map +1 -0
  140. package/dist/commands/project/prune/index.js +95 -0
  141. package/dist/commands/project/pull/index.d.ts +28 -0
  142. package/dist/commands/project/pull/index.d.ts.map +1 -0
  143. package/dist/commands/project/pull/index.js +157 -0
  144. package/dist/commands/project/push/index.d.ts +22 -0
  145. package/dist/commands/project/push/index.d.ts.map +1 -0
  146. package/dist/commands/project/push/index.js +100 -0
  147. package/dist/commands/project/scope/index.d.ts +17 -0
  148. package/dist/commands/project/scope/index.d.ts.map +1 -0
  149. package/dist/commands/project/scope/index.js +107 -0
  150. package/dist/commands/project/split/run.d.ts +4 -0
  151. package/dist/commands/project/split/run.d.ts.map +1 -1
  152. package/dist/commands/project/split/run.js +48 -10
  153. package/dist/commands/project/sync/git.d.ts +18 -0
  154. package/dist/commands/project/sync/git.d.ts.map +1 -0
  155. package/dist/commands/project/sync/git.js +60 -0
  156. package/dist/commands/project/sync/record.d.ts +22 -0
  157. package/dist/commands/project/sync/record.d.ts.map +1 -0
  158. package/dist/commands/project/sync/record.js +133 -0
  159. package/dist/commands/project/sync/ref-sync.d.ts +120 -0
  160. package/dist/commands/project/sync/ref-sync.d.ts.map +1 -0
  161. package/dist/commands/project/sync/ref-sync.js +962 -0
  162. package/dist/commands/project/sync/resolve-target.d.ts +27 -0
  163. package/dist/commands/project/sync/resolve-target.d.ts.map +1 -0
  164. package/dist/commands/project/sync/resolve-target.js +159 -0
  165. package/dist/commands/shared/oat-paths.d.ts +4 -1
  166. package/dist/commands/shared/oat-paths.d.ts.map +1 -1
  167. package/dist/commands/shared/oat-paths.js +2 -2
  168. package/dist/commands/shared/project-scope.d.ts +23 -0
  169. package/dist/commands/shared/project-scope.d.ts.map +1 -0
  170. package/dist/commands/shared/project-scope.js +106 -0
  171. package/dist/commands/tools/migrate/index.js +1 -1
  172. package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
  173. package/dist/commands/tools/shared/pack-inventory.js +79 -8
  174. package/dist/commands/tools/shared/pack-lifecycle.js +1 -1
  175. package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -1
  176. package/dist/commands/tools/shared/pack-reconcile.js +4 -1
  177. package/dist/commands/tools/shared/project-tools-config.d.ts +6 -2
  178. package/dist/commands/tools/shared/project-tools-config.d.ts.map +1 -1
  179. package/dist/commands/tools/shared/project-tools-config.js +7 -5
  180. package/dist/commands/tools/update/index.d.ts.map +1 -1
  181. package/dist/commands/tools/update/index.js +38 -14
  182. package/dist/commands/tools/update/update-tools.d.ts +2 -0
  183. package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
  184. package/dist/config/oat-config.d.ts +6 -3
  185. package/dist/config/oat-config.d.ts.map +1 -1
  186. package/dist/config/oat-config.js +41 -7
  187. package/dist/config/resolve.d.ts.map +1 -1
  188. package/dist/config/resolve.js +2 -1
  189. package/dist/fs/io.d.ts +2 -1
  190. package/dist/fs/io.d.ts.map +1 -1
  191. package/dist/fs/io.js +5 -2
  192. package/dist/projects/split/finalize.d.ts.map +1 -1
  193. package/dist/projects/split/finalize.js +55 -2
  194. package/dist/projects/split/resume.d.ts +3 -0
  195. package/dist/projects/split/resume.d.ts.map +1 -1
  196. package/dist/projects/split/resume.js +34 -7
  197. package/dist/projects/split/seed-children.d.ts.map +1 -1
  198. package/dist/projects/split/seed-children.js +6 -0
  199. package/dist/projects/split/write-parent.d.ts +7 -0
  200. package/dist/projects/split/write-parent.d.ts.map +1 -1
  201. package/dist/projects/split/write-parent.js +7 -4
  202. package/dist/release/public-package-contract.d.ts.map +1 -1
  203. package/dist/release/public-package-contract.js +1 -0
  204. package/dist/validation/skills.d.ts.map +1 -1
  205. package/dist/validation/skills.js +434 -0
  206. package/package.json +4 -4
  207. package/dist/__tests__/skills/split-flow-fixtures.d.ts +0 -50
  208. package/dist/__tests__/skills/split-flow-fixtures.d.ts.map +0 -1
  209. package/dist/__tests__/skills/split-flow-fixtures.js +0 -161
  210. package/dist/commands/__tests__/helpers.d.ts +0 -12
  211. package/dist/commands/__tests__/helpers.d.ts.map +0 -1
  212. package/dist/commands/__tests__/helpers.js +0 -36
@@ -2,13 +2,14 @@ import { readFile as readFileDefault } from 'node:fs/promises';
2
2
  import { isAbsolute, join } from 'node:path';
3
3
  import { buildCommandContext } from '../../app/command-context.js';
4
4
  import { resolveProjectsRoot } from '../shared/oat-paths.js';
5
+ import { PROJECT_SCOPES } from '../shared/project-scope.js';
5
6
  import { confirmAction, } from '../shared/shared.prompts.js';
6
7
  import { readGlobalOptions } from '../shared/shared.utils.js';
7
8
  import { compileDispatchCeilingPreset } from '../../config/dispatch-ceiling-preset.js';
8
9
  import { normalizeDispatchMatrix, validateDispatchRouteTarget, walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
9
10
  import { formatDispatchNotices, terminalReviewerNoticesForMatrix, } from '../../config/dispatch-notices.js';
10
11
  import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
11
- import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, normalizeWorkflowPostImplementSequence, readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
12
+ import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, normalizeWorkflowPostImplementSequence, readOatConfig, readOatConfigForDefaultScopeRepair, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
12
13
  import { resolveEffectiveConfig, } from '../../config/resolve.js';
13
14
  import { resolveAssetsRoot } from '../../fs/assets.js';
14
15
  import { resolveProjectRoot } from '../../fs/paths.js';
@@ -50,6 +51,7 @@ const KEY_ORDER = [
50
51
  'explainers.publish.awsProfile',
51
52
  'git.defaultBranch',
52
53
  'projects.root',
54
+ 'projects.defaultScope',
53
55
  'tools.brainstorm',
54
56
  'tools.core',
55
57
  'tools.docs',
@@ -98,6 +100,17 @@ const CONFIG_CATALOG = [
98
100
  owningCommand: 'oat config set projects.root <value>',
99
101
  description: 'Root directory for tracked OAT projects in this repository.',
100
102
  },
103
+ {
104
+ key: 'projects.defaultScope',
105
+ group: 'Shared Repo (.oat/config.json)',
106
+ file: '.oat/config.json',
107
+ scope: 'shared repo',
108
+ type: 'enum',
109
+ defaultValue: 'synced',
110
+ mutability: 'read/write',
111
+ owningCommand: 'oat config set projects.defaultScope <shared|local|synced>',
112
+ description: 'Scope used by `oat project new` when `--scope` is omitted.',
113
+ },
101
114
  {
102
115
  key: 'worktrees.root',
103
116
  group: 'Shared Repo (.oat/config.json)',
@@ -840,6 +853,7 @@ const DEFAULT_DEPENDENCIES = {
840
853
  buildCommandContext,
841
854
  resolveProjectRoot,
842
855
  readOatConfig,
856
+ readOatConfigForDefaultScopeRepair,
843
857
  writeOatConfig,
844
858
  readOatLocalConfig,
845
859
  writeOatLocalConfig,
@@ -953,6 +967,7 @@ function parseExplainerValue(key, rawValue, surface) {
953
967
  return value;
954
968
  }
955
969
  const WORKFLOW_ENUM_VALUES = {
970
+ 'projects.defaultScope': PROJECT_SCOPES,
956
971
  'workflow.hillCheckpointDefault': ['every', 'final'],
957
972
  'workflow.postImplementSequence': ['wait', 'summary', 'pr', 'docs-pr'],
958
973
  'workflow.reviewExecutionModel': ['subagent', 'inline', 'fresh-session'],
@@ -1006,6 +1021,7 @@ function isStateKey(key) {
1006
1021
  }
1007
1022
  function isStructuralKey(key) {
1008
1023
  return (key === 'projects.root' ||
1024
+ key === 'projects.defaultScope' ||
1009
1025
  key === 'worktrees.root' ||
1010
1026
  key === 'git.defaultBranch' ||
1011
1027
  key.startsWith('documentation.') ||
@@ -1605,6 +1621,18 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
1605
1621
  });
1606
1622
  return { key, value: nextValue, source: 'shared' };
1607
1623
  }
1624
+ if (key === 'projects.defaultScope') {
1625
+ const defaultScope = parseWorkflowValue(key, rawValue);
1626
+ const config = await dependencies.readOatConfigForDefaultScopeRepair(repoRoot);
1627
+ await dependencies.writeOatConfig(repoRoot, {
1628
+ ...config,
1629
+ projects: {
1630
+ ...config.projects,
1631
+ defaultScope,
1632
+ },
1633
+ });
1634
+ return { key, value: defaultScope, source: 'shared' };
1635
+ }
1608
1636
  const config = await dependencies.readOatConfig(repoRoot);
1609
1637
  if (key.startsWith('documentation.')) {
1610
1638
  const doc = { ...config.documentation };
@@ -1673,8 +1701,11 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
1673
1701
  }
1674
1702
  if (key.startsWith('tools.')) {
1675
1703
  const packName = key.slice('tools.'.length);
1704
+ if (rawValue.trim().toLowerCase() !== 'true') {
1705
+ throw new Error(`Pack intent '${key}' can only be declared with true. To remove the pack and clear its intent, run: oat tools remove --pack ${packName} --scope project`);
1706
+ }
1676
1707
  const tools = { ...config.tools };
1677
- tools[packName] = rawValue.trim().toLowerCase() === 'true';
1708
+ tools[packName] = true;
1678
1709
  await dependencies.writeOatConfig(repoRoot, {
1679
1710
  ...config,
1680
1711
  tools,
@@ -1719,7 +1750,7 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
1719
1750
  if (key === 'projects.root') {
1720
1751
  await dependencies.writeOatConfig(repoRoot, {
1721
1752
  ...config,
1722
- projects: { root: normalizedValue },
1753
+ projects: { ...config.projects, root: normalizedValue },
1723
1754
  });
1724
1755
  }
1725
1756
  else {
@@ -23,6 +23,7 @@ interface DoctorDependencies {
23
23
  readFile: (path: string) => Promise<string>;
24
24
  resolveAssetsRoot: () => Promise<string>;
25
25
  readOatConfig: (repoRoot: string) => Promise<OatConfig>;
26
+ readOatConfigForDefaultScopeRepair: (repoRoot: string) => Promise<OatConfig>;
26
27
  readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
27
28
  readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
28
29
  validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
@@ -35,6 +36,7 @@ interface DoctorDependencies {
35
36
  inventoryPack: (input: InventoryPackInput) => Promise<PackInventory>;
36
37
  checkSkillVersions: (scopeRoot: string, assetsRoot: string, pathExists: (path: string) => Promise<boolean>) => Promise<SkillVersionReport>;
37
38
  checkStaleInvocations: (repoRoot: string) => Promise<DoctorCheck>;
39
+ checkSyncedProjects: (repoRoot: string) => Promise<DoctorCheck[]>;
38
40
  }
39
41
  interface OutdatedSkillVersion {
40
42
  skill: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,yBAAyB,EAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,uCAAuC,CAAC;AAa/C,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAQ9D,OAAO,EAGL,KAAK,iCAAiC,EAEtC,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,mCAAmC,EACnC,0BAA0B,EAC3B,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,KACd,OAAO,CACV,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CACnE,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kCAAkC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7E,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;IAC/D,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,gCAAgC,EAAE,CAChC,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,iCAAiC,EAAE,CAAC,CAAC;IAClD,mCAAmC,EAAE,OAAO,mCAAmC,CAAC;IAChF,0BAA0B,EAAE,OAAO,0BAA0B,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,gBAAgB,KACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAClB,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1B,aAAa,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACrE,kBAAkB,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAClE,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CACnE;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,cAAc,EAAE,oBAAoB,EAAE,CAAC;CACxC;AA4qCD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC1C,OAAO,CAcT"}
@@ -12,7 +12,7 @@ import { hasScopedPackPlacementEvidence, inventoryPack, } from '../tools/shared/
12
12
  import { PACK_NAMES } from '../tools/shared/pack-manifest.js';
13
13
  import { formatPackPaths, updatePackRecovery, } from '../tools/shared/pack-paths.js';
14
14
  import { walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
15
- import { readOatConfig, readOatLocalConfig, readUserConfig, } from '../../config/oat-config.js';
15
+ import { readOatConfig, readOatConfigForDefaultScopeRepair, readOatLocalConfig, readUserConfig, } from '../../config/oat-config.js';
16
16
  import { resolveAssetsRoot } from '../../fs/assets.js';
17
17
  import { resolveProjectRoot, resolveScopeRoot } from '../../fs/paths.js';
18
18
  import TOML from '@iarna/toml';
@@ -29,6 +29,7 @@ import { createDispatchValidationPassContext, validateDispatchMatrixRefs, } from
29
29
  import { formatDoctorResults } from '../../ui/output.js';
30
30
  import { Command } from 'commander';
31
31
  import { checkStaleInvocations } from './stale-invocations.js';
32
+ import { checkSyncedProjects } from './synced-projects.js';
32
33
  async function pathExistsDefault(path) {
33
34
  try {
34
35
  await access(path);
@@ -139,6 +140,7 @@ function createDependencies() {
139
140
  readFile: async (path) => readFile(path, 'utf8'),
140
141
  resolveAssetsRoot,
141
142
  readOatConfig,
143
+ readOatConfigForDefaultScopeRepair,
142
144
  readOatLocalConfig,
143
145
  readUserConfig,
144
146
  validateMatrixCell,
@@ -153,6 +155,7 @@ function createDependencies() {
153
155
  // provided pathExists dependency from runChecksForScope when available.
154
156
  checkSkillVersions: (scopeRoot, assetsRoot, pathExists = pathExistsDefault) => checkSkillVersionsDefault(scopeRoot, assetsRoot, pathExists),
155
157
  checkStaleInvocations,
158
+ checkSyncedProjects,
156
159
  };
157
160
  }
158
161
  async function createCursorMaterializedModelsCheck(scopeRoot, dependencies) {
@@ -763,6 +766,7 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
763
766
  checks.push(...(await runCodexChecksForScope(scope, scopeRoot, dirname(userConfigDir), dependencies)));
764
767
  if (scope === 'project') {
765
768
  checks.push(await dependencies.checkStaleInvocations(scopeRoot));
769
+ checks.push(...(await dependencies.checkSyncedProjects(scopeRoot)));
766
770
  try {
767
771
  const assetsRoot = await dependencies.resolveAssetsRoot();
768
772
  const skillVersions = await dependencies.checkSkillVersions(scopeRoot, assetsRoot, dependencies.pathExists);
@@ -812,11 +816,30 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
812
816
  });
813
817
  }
814
818
  const repoReferenceRoot = join(scopeRoot, '.oat', 'repo');
815
- const [userConfig, config, localConfig] = await Promise.all([
819
+ const [userConfig, configResult, localConfig] = await Promise.all([
816
820
  dependencies.readUserConfig(userConfigDir),
817
- dependencies.readOatConfig(scopeRoot),
821
+ dependencies.readOatConfig(scopeRoot).then((config) => ({ config }), async (error) => {
822
+ if (!(error instanceof Error) ||
823
+ !error.message.startsWith('Invalid projects.defaultScope in ')) {
824
+ throw error;
825
+ }
826
+ return {
827
+ config: await dependencies.readOatConfigForDefaultScopeRepair(scopeRoot),
828
+ defaultScopeError: error.message,
829
+ };
830
+ }),
818
831
  dependencies.readOatLocalConfig(scopeRoot),
819
832
  ]);
833
+ if ('defaultScopeError' in configResult) {
834
+ checks.push({
835
+ name: 'project:projects_default_scope',
836
+ description: 'Project creation default scope',
837
+ status: 'fail',
838
+ message: configResult.defaultScopeError,
839
+ fix: 'Run `oat config set projects.defaultScope <shared|local|synced>`.',
840
+ });
841
+ }
842
+ const config = configResult.config;
820
843
  checks.push(await createDispatchMatrixDoctorCheck(scopeRoot, [
821
844
  { source: 'user-config', config: userConfig },
822
845
  { source: 'repo-config', config },
@@ -834,6 +857,7 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
834
857
  const adoption = await dependencies.resolvePjmAdoption({
835
858
  projectRoot: scopeRoot,
836
859
  repoRoot: repoReferenceRoot,
860
+ config,
837
861
  });
838
862
  if (adoption.state !== 'none') {
839
863
  checks.push(...(await dependencies.runPjmDoctorChecks(repoReferenceRoot, {
@@ -0,0 +1,12 @@
1
+ import { type GitRunner } from '../project/sync/git.js';
2
+ import { resolveProjectsRoot } from '../shared/oat-paths.js';
3
+ import type { DoctorCheck } from '../../ui/output.js';
4
+ interface SyncedDoctorDependencies {
5
+ git: GitRunner;
6
+ resolveProjectsRoot: typeof resolveProjectsRoot;
7
+ env: NodeJS.ProcessEnv;
8
+ }
9
+ export declare function syncedRecordSlug(recordPath: string): string;
10
+ export declare function checkSyncedProjects(repoRoot: string, overrides?: Partial<SyncedDoctorDependencies>): Promise<DoctorCheck[]>;
11
+ export {};
12
+ //# sourceMappingURL=synced-projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synced-projects.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/synced-projects.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,UAAU,wBAAwB;IAChC,GAAG,EAAE,SAAS,CAAC;IACf,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAsBD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAqDD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,OAAO,CAAC,WAAW,EAAE,CAAC,CAsMxB"}
@@ -0,0 +1,208 @@
1
+ import { readdir, readFile, stat } from 'node:fs/promises';
2
+ import { basename, join, relative, resolve, sep } from 'node:path';
3
+ import { defaultGitRunner } from '../project/sync/git.js';
4
+ import { readSyncedRecord, } from '../project/sync/record.js';
5
+ import { resolveProjectsRoot } from '../shared/oat-paths.js';
6
+ import { resolveScopeRoot } from '../shared/project-scope.js';
7
+ import { readOatConfigForDefaultScopeRepair } from '../../config/oat-config.js';
8
+ const DEFAULT_DEPENDENCIES = {
9
+ git: defaultGitRunner,
10
+ resolveProjectsRoot: (repoRoot, env) => resolveProjectsRoot(repoRoot, env, readOatConfigForDefaultScopeRepair),
11
+ env: process.env,
12
+ };
13
+ async function pathExists(path) {
14
+ try {
15
+ await stat(path);
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ function repoRelative(repoRoot, path) {
23
+ return relative(resolve(repoRoot), resolve(path)).split(sep).join('/');
24
+ }
25
+ export function syncedRecordSlug(recordPath) {
26
+ return basename(recordPath.replaceAll('\\', sep), '.json');
27
+ }
28
+ function check(slug, kind, status, message, fix) {
29
+ return {
30
+ name: `project:synced_${slug}_${kind}`,
31
+ description: `Synced project ${slug}: ${kind.replaceAll('_', ' ')}`,
32
+ status,
33
+ message,
34
+ ...(fix ? { fix } : {}),
35
+ };
36
+ }
37
+ async function recordEntries(syncedRoot) {
38
+ try {
39
+ return (await readdir(syncedRoot, { withFileTypes: true }))
40
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
41
+ .map((entry) => join(syncedRoot, entry.name))
42
+ .sort();
43
+ }
44
+ catch {
45
+ return [];
46
+ }
47
+ }
48
+ async function editorHint(repoRoot) {
49
+ for (const editorDirectory of ['.vscode', '.cursor']) {
50
+ const directory = join(repoRoot, editorDirectory);
51
+ if (!(await pathExists(directory)))
52
+ continue;
53
+ let settings = {};
54
+ try {
55
+ settings = JSON.parse(await readFile(join(directory, 'settings.json'), 'utf8'));
56
+ }
57
+ catch {
58
+ // Missing or non-JSON settings still receive the non-blocking hint.
59
+ }
60
+ if (!('git.scanRepositories' in settings)) {
61
+ return {
62
+ name: 'project:synced_editor_hint',
63
+ description: 'Nested synced-project repository discovery',
64
+ status: 'pass',
65
+ message: `${editorDirectory} can set git.scanRepositories to include nested synced project checkouts.`,
66
+ };
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ export async function checkSyncedProjects(repoRoot, overrides = {}) {
72
+ const dependencies = { ...DEFAULT_DEPENDENCIES, ...overrides };
73
+ const projectsRoot = await dependencies.resolveProjectsRoot(repoRoot, dependencies.env);
74
+ const syncedRoot = resolveScopeRoot(repoRoot, projectsRoot, 'synced');
75
+ const syncedRelative = repoRelative(repoRoot, syncedRoot);
76
+ const checks = [];
77
+ const tracked = await dependencies.git.run(['ls-files', '--', syncedRelative], { cwd: repoRoot, allowFailure: true });
78
+ const missingRepository = tracked.code !== 0 &&
79
+ /not a git repository/i.test(`${tracked.stderr}\n${tracked.stdout}`);
80
+ const trackedCheckoutArtifacts = tracked.stdout
81
+ .split('\n')
82
+ .map((path) => path.trim())
83
+ .filter((path) => {
84
+ const nestedPath = path.slice(`${syncedRelative}/`.length);
85
+ return path.startsWith(`${syncedRelative}/`) && nestedPath.includes('/');
86
+ });
87
+ if (tracked.code !== 0 && !missingRepository) {
88
+ checks.push({
89
+ name: 'project:synced_tracked_artifacts',
90
+ description: 'Synced artifacts excluded from the parent branch',
91
+ status: 'fail',
92
+ message: `Unable to inspect tracked synced artifacts: ${tracked.stderr || tracked.stdout || `git ls-files exited ${tracked.code}`}.`,
93
+ fix: 'Resolve the Git error, then rerun `oat doctor --scope project`.',
94
+ });
95
+ }
96
+ else if (tracked.code === 0 && trackedCheckoutArtifacts.length > 0) {
97
+ checks.push({
98
+ name: 'project:synced_tracked_artifacts',
99
+ description: 'Synced artifacts excluded from the parent branch',
100
+ status: 'fail',
101
+ message: `Tracked synced artifact files: ${trackedCheckoutArtifacts.join(', ')}`,
102
+ fix: 'Run `oat project migrate` or remove them with `git rm --cached`.',
103
+ });
104
+ }
105
+ const entries = (await pathExists(syncedRoot))
106
+ ? await recordEntries(syncedRoot)
107
+ : [];
108
+ const ignoreProbeSlug = entries[0]
109
+ ? syncedRecordSlug(entries[0])
110
+ : '__probe__';
111
+ const ignored = await dependencies.git.run([
112
+ 'check-ignore',
113
+ '--quiet',
114
+ '--no-index',
115
+ `${syncedRelative}/${ignoreProbeSlug}/`,
116
+ ], { cwd: repoRoot, allowFailure: true });
117
+ if (ignored.code === 1) {
118
+ checks.push({
119
+ name: 'project:synced_gitignore',
120
+ description: 'Managed synced-project gitignore rule',
121
+ status: 'warn',
122
+ message: 'The managed gitignore block does not ignore synced project directories.',
123
+ fix: 'Run `oat tools update`.',
124
+ });
125
+ }
126
+ const hint = await editorHint(repoRoot);
127
+ if (hint)
128
+ checks.push(hint);
129
+ if (entries.length === 0 && checks.length === 0) {
130
+ return [
131
+ {
132
+ name: 'project:synced_projects',
133
+ description: 'Synced project health',
134
+ status: 'pass',
135
+ message: 'No synced projects found.',
136
+ },
137
+ ];
138
+ }
139
+ const records = [];
140
+ for (const entry of entries) {
141
+ const slug = syncedRecordSlug(entry);
142
+ try {
143
+ const record = await readSyncedRecord(entry);
144
+ if (record)
145
+ records.push(record);
146
+ }
147
+ catch (error) {
148
+ checks.push(check(slug, 'record_schema', 'fail', error instanceof Error ? error.message : String(error), 'Upgrade the OAT CLI before reading this synced project record.'));
149
+ }
150
+ }
151
+ for (const record of records) {
152
+ const checkoutPath = join(syncedRoot, record.slug);
153
+ const checkoutExists = await pathExists(checkoutPath);
154
+ if (!checkoutExists) {
155
+ checks.push(check(record.slug, 'checkout', 'warn', `Synced project ${record.slug} checkout is absent.`, `Run \`oat project pull ${record.slug}\`.`));
156
+ }
157
+ else {
158
+ const status = await dependencies.git.run(['status', '--porcelain'], {
159
+ cwd: checkoutPath,
160
+ allowFailure: true,
161
+ });
162
+ if (status.code === 0 && status.stdout.trim()) {
163
+ checks.push(check(record.slug, 'working_tree', 'warn', `Synced project ${record.slug} has uncommitted changes.`, `Run \`oat project push ${record.slug}\`.`));
164
+ }
165
+ }
166
+ const [local, remote] = await Promise.all([
167
+ dependencies.git.run(['show-ref', '--hash', record.ref], {
168
+ cwd: repoRoot,
169
+ allowFailure: true,
170
+ }),
171
+ dependencies.git.run(['ls-remote', record.remote, record.ref], {
172
+ cwd: repoRoot,
173
+ allowFailure: true,
174
+ }),
175
+ ]);
176
+ const localQuerySucceeded = local.code === 0 || local.code === 1;
177
+ if (!localQuerySucceeded) {
178
+ checks.push(check(record.slug, 'local_ref', 'pass', `Local ref comparison skipped: ${local.stderr || local.stdout || `git show-ref exited ${local.code}`}.`));
179
+ }
180
+ if (remote.code !== 0) {
181
+ checks.push(check(record.slug, 'remote_ref', 'pass', `Remote comparison skipped: ${remote.stderr || remote.stdout || 'offline'}.`));
182
+ }
183
+ else {
184
+ const remoteSha = remote.stdout.trim().split(/\s+/)[0] ?? '';
185
+ const localSha = local.code === 0 ? local.stdout.trim() : '';
186
+ if (localQuerySucceeded &&
187
+ (localSha || remoteSha) &&
188
+ localSha !== remoteSha) {
189
+ const relation = localSha
190
+ ? remoteSha
191
+ ? 'differs from origin'
192
+ : 'exists locally but is absent from origin'
193
+ : 'is absent locally but exists on origin';
194
+ checks.push(check(record.slug, 'ref_sync', 'warn', `Local ref for ${record.slug} ${relation}.`, `Run \`oat project pull ${record.slug}\` or \`oat project push ${record.slug}\`.`));
195
+ }
196
+ }
197
+ }
198
+ return checks.length > 0
199
+ ? checks
200
+ : [
201
+ {
202
+ name: 'project:synced_projects',
203
+ description: 'Synced project health',
204
+ status: 'pass',
205
+ message: `Checked ${records.length} synced project(s).`,
206
+ },
207
+ ];
208
+ }
@@ -0,0 +1,4 @@
1
+ import { type ApplyManagedBlockResult } from './managed-block.js';
2
+ export type ApplyOatCoreGitattributesResult = ApplyManagedBlockResult;
3
+ export declare function applyOatCoreGitattributes(repoRoot: string): Promise<ApplyOatCoreGitattributesResult>;
4
+ //# sourceMappingURL=gitattributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitattributes.d.ts","sourceRoot":"","sources":["../../../src/commands/init/gitattributes.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,iBAAiB,CAAC;AAMzB,MAAM,MAAM,+BAA+B,GAAG,uBAAuB,CAAC;AAEtE,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,+BAA+B,CAAC,CAM1C"}
@@ -0,0 +1,12 @@
1
+ import { join } from 'node:path';
2
+ import { applyManagedBlock, } from './managed-block.js';
3
+ const GITATTRIBUTES_ENTRIES = [
4
+ '.oat/projects/shared/** linguist-generated=true',
5
+ ];
6
+ export async function applyOatCoreGitattributes(repoRoot) {
7
+ return applyManagedBlock(join(repoRoot, '.gitattributes'), {
8
+ start: '# OAT core',
9
+ end: '# END OAT core',
10
+ entries: GITATTRIBUTES_ENTRIES,
11
+ });
12
+ }
@@ -1,9 +1,16 @@
1
+ import type { GitRunner } from '../project/sync/git.js';
1
2
  export interface ApplyOatCoreResult {
2
3
  action: 'created' | 'updated' | 'no-change';
3
4
  entries: string[];
4
5
  stateDashboardIndexAction: 'untracked' | 'not-tracked' | 'not-git-repo';
5
6
  }
6
- export declare function applyOatCoreGitignore(repoRoot: string): Promise<ApplyOatCoreResult>;
7
+ export interface EnsureScopedRootGitignoreResult {
8
+ before: string | null | undefined;
9
+ changed: boolean;
10
+ }
11
+ export declare function isSyncedRuleApplied(repoRoot: string): Promise<boolean>;
12
+ export declare function applyOatCoreGitignore(repoRoot: string, additionalEntries?: readonly string[]): Promise<ApplyOatCoreResult>;
13
+ export declare function ensureScopedRootGitignore(repoRoot: string, scopeRoot: string, scope: 'local' | 'synced', git: GitRunner, dirtyMessage?: string | null): Promise<EnsureScopedRootGitignoreResult>;
7
14
  /**
8
15
  * Removes the generated repo dashboard from the git index once the OAT core
9
16
  * ignore rule is present, while leaving the working-tree file intact.
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../../src/commands/init/gitignore.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yBAAyB,EAAE,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;CACzE;AAMD,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAgD7B;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,2BAA2B,CAAC,CAAC,CAyB1D"}
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../../src/commands/init/gitignore.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAkC5D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yBAAyB,EAAE,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;CACzE;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB;AA0BD,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB5E;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,GAAE,SAAS,MAAM,EAAO,GACxC,OAAO,CAAC,kBAAkB,CAAC,CAoB7B;AAED,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GAAG,QAAQ,EACzB,GAAG,EAAE,SAAS,EACd,YAAY,GACR,MAAM,GACN,IAAqJ,GACxJ,OAAO,CAAC,+BAA+B,CAAC,CAyG1C;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,2BAA2B,CAAC,CAAC,CAyB1D"}