@open-agent-toolkit/cli 0.2.50 → 0.2.52

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 (263) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/bootstrap.md +6 -2
  3. package/assets/docs/cli-utilities/tool-packs.md +87 -33
  4. package/assets/docs/provider-sync/commands.md +30 -2
  5. package/assets/docs/provider-sync/config.md +19 -0
  6. package/assets/docs/provider-sync/manifest-and-drift.md +37 -0
  7. package/assets/docs/provider-sync/providers.md +69 -2
  8. package/assets/docs/provider-sync/scope-and-surface.md +44 -0
  9. package/assets/docs/reference/cli-reference.md +21 -5
  10. package/assets/docs/reference/file-locations.md +8 -2
  11. package/assets/docs/reference/oat-directory-structure.md +25 -9
  12. package/assets/docs/workflows/projects/artifacts.md +9 -4
  13. package/assets/docs/workflows/projects/evidence-layers.md +110 -1
  14. package/assets/docs/workflows/projects/implementation-execution.md +13 -0
  15. package/assets/docs/workflows/projects/lifecycle.md +17 -5
  16. package/assets/docs/workflows/projects/orchestration-model.md +18 -0
  17. package/assets/docs/workflows/projects/picking-up-projects.md +26 -9
  18. package/assets/docs/workflows/projects/pr-flow.md +5 -3
  19. package/assets/docs/workflows/projects/reviewing-oat-prs.md +12 -8
  20. package/assets/public-package-versions.json +4 -4
  21. package/assets/skills/oat-dispatch-subagents/SKILL.md +57 -1
  22. package/assets/skills/oat-dispatch-subagents/references/record-schema.md +77 -1
  23. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +3 -3
  24. package/assets/skills/oat-project-complete/SKILL.md +193 -26
  25. package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +306 -0
  26. package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +125 -0
  27. package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +106 -0
  28. package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +110 -0
  29. package/assets/skills/oat-project-complete/scripts/resolve-synced-archive-entry.mjs +164 -0
  30. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +24 -1
  31. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +3 -3
  32. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +11 -0
  33. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +3 -3
  34. package/assets/skills/oat-project-plan-writing/SKILL.md +12 -1
  35. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +3 -3
  36. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +3 -3
  37. package/assets/skills/oat-project-review-provide/SKILL.md +12 -1
  38. package/assets/skills/oat-project-review-provide-remote/SKILL.md +12 -1
  39. package/dist/agents/canonical/index.d.ts +2 -0
  40. package/dist/agents/canonical/index.d.ts.map +1 -1
  41. package/dist/agents/canonical/index.js +1 -0
  42. package/dist/agents/canonical/resolve.d.ts +45 -0
  43. package/dist/agents/canonical/resolve.d.ts.map +1 -0
  44. package/dist/agents/canonical/resolve.js +175 -0
  45. package/dist/commands/decision/agents-guidance.d.ts +2 -2
  46. package/dist/commands/decision/agents-guidance.d.ts.map +1 -1
  47. package/dist/commands/decision/agents-guidance.js +1 -4
  48. package/dist/commands/decision/index.d.ts.map +1 -1
  49. package/dist/commands/decision/index.js +25 -6
  50. package/dist/commands/docs/init/index.d.ts +7 -1
  51. package/dist/commands/docs/init/index.d.ts.map +1 -1
  52. package/dist/commands/docs/init/index.js +53 -20
  53. package/dist/commands/doctor/index.d.ts +8 -2
  54. package/dist/commands/doctor/index.d.ts.map +1 -1
  55. package/dist/commands/doctor/index.js +157 -46
  56. package/dist/commands/init/index.d.ts +8 -3
  57. package/dist/commands/init/index.d.ts.map +1 -1
  58. package/dist/commands/init/index.js +64 -26
  59. package/dist/commands/init/tools/index.d.ts +12 -12
  60. package/dist/commands/init/tools/index.d.ts.map +1 -1
  61. package/dist/commands/init/tools/index.js +430 -99
  62. package/dist/commands/init/tools/install-state.d.ts +2 -0
  63. package/dist/commands/init/tools/install-state.d.ts.map +1 -1
  64. package/dist/commands/init/tools/install-state.js +11 -0
  65. package/dist/commands/init/tools/project-guidance.d.ts +49 -0
  66. package/dist/commands/init/tools/project-guidance.d.ts.map +1 -0
  67. package/dist/commands/init/tools/project-guidance.js +144 -0
  68. package/dist/commands/init/tools/workflows/index.d.ts +7 -0
  69. package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
  70. package/dist/commands/init/tools/workflows/index.js +160 -7
  71. package/dist/commands/pjm/index.d.ts.map +1 -1
  72. package/dist/commands/pjm/index.js +28 -3
  73. package/dist/commands/pjm/init.d.ts +5 -0
  74. package/dist/commands/pjm/init.d.ts.map +1 -1
  75. package/dist/commands/pjm/init.js +19 -3
  76. package/dist/commands/project/archive/archive-utils.d.ts +8 -1
  77. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  78. package/dist/commands/project/archive/archive-utils.js +147 -50
  79. package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
  80. package/dist/commands/project/archive/push-runner.js +15 -2
  81. package/dist/commands/project/dispatch/index.d.ts +10 -0
  82. package/dist/commands/project/dispatch/index.d.ts.map +1 -0
  83. package/dist/commands/project/dispatch/index.js +137 -0
  84. package/dist/commands/project/dispatch/record.d.ts +91 -0
  85. package/dist/commands/project/dispatch/record.d.ts.map +1 -0
  86. package/dist/commands/project/dispatch/record.js +402 -0
  87. package/dist/commands/project/index.d.ts.map +1 -1
  88. package/dist/commands/project/index.js +2 -0
  89. package/dist/commands/project/links/compute.d.ts +1 -0
  90. package/dist/commands/project/links/compute.d.ts.map +1 -1
  91. package/dist/commands/project/links/compute.js +5 -4
  92. package/dist/commands/project/links/index.d.ts +9 -0
  93. package/dist/commands/project/links/index.d.ts.map +1 -1
  94. package/dist/commands/project/links/index.js +71 -2
  95. package/dist/commands/project/list.d.ts +10 -2
  96. package/dist/commands/project/list.d.ts.map +1 -1
  97. package/dist/commands/project/list.js +205 -29
  98. package/dist/commands/project/open/index.d.ts +2 -0
  99. package/dist/commands/project/open/index.d.ts.map +1 -1
  100. package/dist/commands/project/open/index.js +16 -1
  101. package/dist/commands/project/prune/index.d.ts +10 -4
  102. package/dist/commands/project/prune/index.d.ts.map +1 -1
  103. package/dist/commands/project/prune/index.js +85 -15
  104. package/dist/commands/project/pull/index.d.ts +4 -0
  105. package/dist/commands/project/pull/index.d.ts.map +1 -1
  106. package/dist/commands/project/pull/index.js +82 -3
  107. package/dist/commands/project/sync/git.d.ts +9 -0
  108. package/dist/commands/project/sync/git.d.ts.map +1 -1
  109. package/dist/commands/project/sync/git.js +18 -0
  110. package/dist/commands/project/sync/ref-sync.d.ts +16 -1
  111. package/dist/commands/project/sync/ref-sync.d.ts.map +1 -1
  112. package/dist/commands/project/sync/ref-sync.js +288 -17
  113. package/dist/commands/project/sync/resolve-target.d.ts +10 -0
  114. package/dist/commands/project/sync/resolve-target.d.ts.map +1 -1
  115. package/dist/commands/project/sync/resolve-target.js +56 -1
  116. package/dist/commands/providers/inspect/inspect.d.ts +8 -1
  117. package/dist/commands/providers/inspect/inspect.d.ts.map +1 -1
  118. package/dist/commands/providers/inspect/inspect.js +146 -26
  119. package/dist/commands/providers/list/list.d.ts +8 -1
  120. package/dist/commands/providers/list/list.d.ts.map +1 -1
  121. package/dist/commands/providers/list/list.js +139 -23
  122. package/dist/commands/providers/providers.types.d.ts +25 -1
  123. package/dist/commands/providers/providers.types.d.ts.map +1 -1
  124. package/dist/commands/providers/set/index.d.ts +9 -1
  125. package/dist/commands/providers/set/index.d.ts.map +1 -1
  126. package/dist/commands/providers/set/index.js +43 -33
  127. package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
  128. package/dist/commands/remove/skill/remove-skill.js +11 -0
  129. package/dist/commands/shared/agents-md.d.ts +42 -14
  130. package/dist/commands/shared/agents-md.d.ts.map +1 -1
  131. package/dist/commands/shared/agents-md.js +364 -70
  132. package/dist/commands/shared/project-scope.d.ts +2 -0
  133. package/dist/commands/shared/project-scope.d.ts.map +1 -1
  134. package/dist/commands/shared/project-scope.js +5 -0
  135. package/dist/commands/state/generate.d.ts +2 -0
  136. package/dist/commands/state/generate.d.ts.map +1 -1
  137. package/dist/commands/state/generate.js +93 -28
  138. package/dist/commands/status/index.d.ts +8 -3
  139. package/dist/commands/status/index.d.ts.map +1 -1
  140. package/dist/commands/status/index.js +147 -32
  141. package/dist/commands/sync/apply.d.ts.map +1 -1
  142. package/dist/commands/sync/apply.js +220 -29
  143. package/dist/commands/sync/dry-run.d.ts.map +1 -1
  144. package/dist/commands/sync/dry-run.js +30 -6
  145. package/dist/commands/sync/index.d.ts +17 -2
  146. package/dist/commands/sync/index.d.ts.map +1 -1
  147. package/dist/commands/sync/index.js +106 -41
  148. package/dist/commands/sync/sync.types.d.ts +39 -2
  149. package/dist/commands/sync/sync.types.d.ts.map +1 -1
  150. package/dist/commands/sync/sync.utils.d.ts +5 -1
  151. package/dist/commands/sync/sync.utils.d.ts.map +1 -1
  152. package/dist/commands/sync/sync.utils.js +73 -0
  153. package/dist/commands/tools/info/info-tool.d.ts +2 -0
  154. package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
  155. package/dist/commands/tools/info/info-tool.js +34 -12
  156. package/dist/commands/tools/install/index.d.ts.map +1 -1
  157. package/dist/commands/tools/install/index.js +19 -3
  158. package/dist/commands/tools/list/list-tools.d.ts +2 -0
  159. package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
  160. package/dist/commands/tools/list/list-tools.js +36 -7
  161. package/dist/commands/tools/remove/index.d.ts.map +1 -1
  162. package/dist/commands/tools/remove/index.js +150 -21
  163. package/dist/commands/tools/remove/remove-tools.d.ts +20 -0
  164. package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
  165. package/dist/commands/tools/remove/remove-tools.js +122 -1
  166. package/dist/commands/tools/shared/format-pack-inventory.d.ts +19 -0
  167. package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -1
  168. package/dist/commands/tools/shared/format-pack-inventory.js +109 -0
  169. package/dist/commands/tools/shared/pack-evidence.d.ts +66 -0
  170. package/dist/commands/tools/shared/pack-evidence.d.ts.map +1 -0
  171. package/dist/commands/tools/shared/pack-evidence.js +132 -0
  172. package/dist/commands/tools/shared/pack-inventory.d.ts +1 -0
  173. package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
  174. package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts +44 -0
  175. package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts.map +1 -0
  176. package/dist/commands/tools/shared/pack-lifecycle-outcome.js +91 -0
  177. package/dist/commands/tools/update/index.d.ts.map +1 -1
  178. package/dist/commands/tools/update/index.js +74 -4
  179. package/dist/commands/tools/update/update-tools.d.ts +5 -0
  180. package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
  181. package/dist/commands/tools/update/update-tools.js +64 -2
  182. package/dist/config/oat-config.d.ts +5 -0
  183. package/dist/config/oat-config.d.ts.map +1 -1
  184. package/dist/config/oat-config.js +17 -5
  185. package/dist/config/user-sync-config.d.ts +1 -0
  186. package/dist/config/user-sync-config.d.ts.map +1 -1
  187. package/dist/config/user-sync-config.js +8 -0
  188. package/dist/drift/detector.d.ts +2 -2
  189. package/dist/drift/detector.d.ts.map +1 -1
  190. package/dist/drift/detector.js +18 -0
  191. package/dist/drift/strays.d.ts.map +1 -1
  192. package/dist/drift/strays.js +5 -0
  193. package/dist/engine/collection-sync.d.ts +14 -0
  194. package/dist/engine/collection-sync.d.ts.map +1 -0
  195. package/dist/engine/collection-sync.js +282 -0
  196. package/dist/engine/compute-plan.d.ts +8 -1
  197. package/dist/engine/compute-plan.d.ts.map +1 -1
  198. package/dist/engine/compute-plan.js +303 -12
  199. package/dist/engine/engine.types.d.ts +61 -0
  200. package/dist/engine/engine.types.d.ts.map +1 -1
  201. package/dist/engine/execute-plan.d.ts +22 -2
  202. package/dist/engine/execute-plan.d.ts.map +1 -1
  203. package/dist/engine/execute-plan.js +459 -27
  204. package/dist/engine/provider-path-safety.d.ts +1 -0
  205. package/dist/engine/provider-path-safety.d.ts.map +1 -1
  206. package/dist/engine/provider-path-safety.js +15 -0
  207. package/dist/engine/scanner.d.ts +2 -2
  208. package/dist/engine/scanner.d.ts.map +1 -1
  209. package/dist/engine/scanner.js +21 -4
  210. package/dist/fs/io.d.ts +67 -0
  211. package/dist/fs/io.d.ts.map +1 -1
  212. package/dist/fs/io.js +536 -3
  213. package/dist/manifest/index.d.ts +2 -2
  214. package/dist/manifest/index.d.ts.map +1 -1
  215. package/dist/manifest/index.js +1 -1
  216. package/dist/manifest/manager.d.ts +2 -2
  217. package/dist/manifest/manager.d.ts.map +1 -1
  218. package/dist/manifest/manager.js +20 -3
  219. package/dist/manifest/manifest.types.d.ts +704 -13
  220. package/dist/manifest/manifest.types.d.ts.map +1 -1
  221. package/dist/manifest/manifest.types.js +131 -15
  222. package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
  223. package/dist/providers/codex/codec/sync-extension.js +41 -10
  224. package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
  225. package/dist/providers/cursor/codec/sync-extension.js +41 -10
  226. package/dist/providers/identity/absolute-paths.d.ts +68 -0
  227. package/dist/providers/identity/absolute-paths.d.ts.map +1 -0
  228. package/dist/providers/identity/absolute-paths.js +144 -0
  229. package/dist/providers/identity/claude-runtime-observation.d.ts +105 -0
  230. package/dist/providers/identity/claude-runtime-observation.d.ts.map +1 -0
  231. package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts +40 -0
  232. package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts.map +1 -0
  233. package/dist/providers/identity/claude-runtime-observation.fixtures.js +146 -0
  234. package/dist/providers/identity/claude-runtime-observation.js +229 -0
  235. package/dist/providers/identity/codex-runtime-observation.d.ts +75 -0
  236. package/dist/providers/identity/codex-runtime-observation.d.ts.map +1 -0
  237. package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts +37 -0
  238. package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts.map +1 -0
  239. package/dist/providers/identity/codex-runtime-observation.fixtures.js +539 -0
  240. package/dist/providers/identity/codex-runtime-observation.js +255 -0
  241. package/dist/providers/identity/generic-dispatch-record.d.ts +313 -0
  242. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -0
  243. package/dist/providers/identity/generic-dispatch-record.js +539 -0
  244. package/dist/providers/identity/oat-dispatch-record.d.ts +1964 -0
  245. package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -0
  246. package/dist/providers/identity/oat-dispatch-record.js +691 -0
  247. package/dist/providers/identity/runtime-observation.d.ts +100 -0
  248. package/dist/providers/identity/runtime-observation.d.ts.map +1 -0
  249. package/dist/providers/identity/runtime-observation.js +169 -0
  250. package/dist/providers/shared/index.d.ts +2 -0
  251. package/dist/providers/shared/index.d.ts.map +1 -1
  252. package/dist/providers/shared/index.js +1 -0
  253. package/dist/providers/shared/materialization-extension.d.ts +12 -0
  254. package/dist/providers/shared/materialization-extension.d.ts.map +1 -1
  255. package/dist/providers/shared/registry.d.ts +69 -0
  256. package/dist/providers/shared/registry.d.ts.map +1 -0
  257. package/dist/providers/shared/registry.js +252 -0
  258. package/dist/providers/shared/restart-adviser.d.ts +26 -0
  259. package/dist/providers/shared/restart-adviser.d.ts.map +1 -0
  260. package/dist/providers/shared/restart-adviser.js +96 -0
  261. package/dist/shared/types.d.ts +4 -0
  262. package/dist/shared/types.d.ts.map +1 -1
  263. package/package.json +2 -2
@@ -0,0 +1,66 @@
1
+ import type { ConcreteScope } from '../../../shared/types.js';
2
+ import type { PackInventory, ScopedPackInventory } from './pack-inventory.js';
3
+ import type { PackCompleteness, PackName } from './types.js';
4
+ export type ScopeRealization = 'present' | 'absent' | 'unknown';
5
+ export type RealizedPackPlacement = 'project' | 'user' | 'both' | 'none' | 'unknown';
6
+ export type PackHealth = 'absent' | 'current' | 'drifted' | 'newer' | 'mixed' | 'unknown';
7
+ export interface PackScopeFacts {
8
+ scope: ConcreteScope;
9
+ intent: ScopedPackInventory['intent'];
10
+ inventory: {
11
+ state: 'available' | 'unavailable';
12
+ source: 'pack-inventory';
13
+ reason?: string;
14
+ };
15
+ completeness: PackCompleteness | 'unknown';
16
+ health: PackHealth;
17
+ realization: ScopeRealization;
18
+ }
19
+ export interface RecoveryAction {
20
+ code: string;
21
+ command?: string;
22
+ message: string;
23
+ }
24
+ export interface PackEvidenceDiagnostic {
25
+ code: 'inventory-unavailable' | 'declared-only' | 'partial-placement' | 'duplicate-placement' | 'provider-inactive' | 'provider-unsupported' | 'provider-materialization-missing' | 'provider-materialization-failed' | 'visibility-unknown' | 'refresh-required' | 'restart-required';
26
+ severity: 'info' | 'warning' | 'error';
27
+ pack: PackName;
28
+ scope?: ConcreteScope;
29
+ provider?: string;
30
+ contentKind?: 'skill' | 'agent' | 'rule' | 'directory';
31
+ affectedAssets: readonly string[];
32
+ source: string;
33
+ detail: string;
34
+ recovery: readonly RecoveryAction[];
35
+ }
36
+ export interface ProviderReachabilityEvidence {
37
+ provider: string;
38
+ scope: ConcreteScope;
39
+ contentKind: 'skill' | 'agent' | 'rule' | 'directory';
40
+ assets: readonly string[];
41
+ [key: string]: unknown;
42
+ }
43
+ export interface ToolPackEvidence {
44
+ schemaVersion: 1;
45
+ pack: PackName;
46
+ canonical: PackInventory | null;
47
+ scopes: readonly PackScopeFacts[];
48
+ knownRealizedScopes: readonly ConcreteScope[];
49
+ unknownScopes: readonly ConcreteScope[];
50
+ realizedPlacement: RealizedPackPlacement;
51
+ providers: readonly ProviderReachabilityEvidence[];
52
+ diagnostics: readonly PackEvidenceDiagnostic[];
53
+ }
54
+ export declare function packScopeFactsFromInventory(inventory: ScopedPackInventory): PackScopeFacts;
55
+ export declare function unavailablePackScopeFacts(input: {
56
+ scope: ConcreteScope;
57
+ intent: ScopedPackInventory['intent'];
58
+ reason: string;
59
+ }): PackScopeFacts;
60
+ export declare function hasScopedPackRealizationEvidence(inventory: ScopedPackInventory): boolean;
61
+ export declare function projectPackEvidence(input: {
62
+ canonical: PackInventory | null;
63
+ scopes: readonly PackScopeFacts[];
64
+ providers?: readonly ProviderReachabilityEvidence[];
65
+ }): ToolPackEvidence;
66
+ //# sourceMappingURL=pack-evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack-evidence.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ function healthForStatuses(statuses) {
2
+ const present = statuses.filter((status) => status !== 'missing');
3
+ if (present.length === 0)
4
+ return 'absent';
5
+ const states = new Set(present);
6
+ if (states.size === 1 && states.has('current'))
7
+ return 'current';
8
+ if (states.size === 1 && states.has('newer'))
9
+ return 'newer';
10
+ if (states.has('outdated'))
11
+ return states.size === 1 ? 'drifted' : 'mixed';
12
+ return states.size === 1 ? 'current' : 'mixed';
13
+ }
14
+ export function packScopeFactsFromInventory(inventory) {
15
+ return {
16
+ scope: inventory.scope,
17
+ intent: inventory.intent,
18
+ inventory: { state: 'available', source: 'pack-inventory' },
19
+ completeness: inventory.completeness,
20
+ health: healthForStatuses(inventory.assets
21
+ .filter(({ definition }) => definition.ownership[inventory.scope] === 'managed')
22
+ .map(({ status }) => status)),
23
+ realization: hasScopedPackRealizationEvidence(inventory)
24
+ ? 'present'
25
+ : 'absent',
26
+ };
27
+ }
28
+ export function unavailablePackScopeFacts(input) {
29
+ return {
30
+ scope: input.scope,
31
+ intent: input.intent,
32
+ inventory: {
33
+ state: 'unavailable',
34
+ source: 'pack-inventory',
35
+ reason: input.reason,
36
+ },
37
+ completeness: 'unknown',
38
+ health: 'unknown',
39
+ realization: 'unknown',
40
+ };
41
+ }
42
+ export function hasScopedPackRealizationEvidence(inventory) {
43
+ return inventory.assets.some(({ definition, status }) => definition.sharedOwner === undefined &&
44
+ definition.ownership[inventory.scope] === 'managed' &&
45
+ status !== 'missing');
46
+ }
47
+ function placementForScopes(scopes) {
48
+ if (scopes.some(({ realization }) => realization === 'unknown')) {
49
+ return 'unknown';
50
+ }
51
+ const realized = scopes
52
+ .filter(({ realization }) => realization === 'present')
53
+ .map(({ scope }) => scope);
54
+ if (realized.includes('project') && realized.includes('user'))
55
+ return 'both';
56
+ return realized[0] ?? 'none';
57
+ }
58
+ function canonicalDiagnostics(pack, scopes) {
59
+ const diagnostics = [];
60
+ for (const facts of scopes) {
61
+ if (facts.inventory.state === 'unavailable') {
62
+ diagnostics.push({
63
+ code: 'inventory-unavailable',
64
+ severity: 'error',
65
+ pack,
66
+ scope: facts.scope,
67
+ affectedAssets: [],
68
+ source: facts.inventory.source,
69
+ detail: facts.inventory.reason ?? `${facts.scope} inventory unavailable`,
70
+ recovery: [],
71
+ });
72
+ }
73
+ else if (facts.intent.enabled && facts.realization === 'absent') {
74
+ diagnostics.push({
75
+ code: 'declared-only',
76
+ severity: 'warning',
77
+ pack,
78
+ scope: facts.scope,
79
+ affectedAssets: [],
80
+ source: 'pack-inventory',
81
+ detail: `Pack ${pack} is declared at ${facts.scope} scope but has no realized managed assets`,
82
+ recovery: [],
83
+ });
84
+ }
85
+ if (facts.completeness === 'partial') {
86
+ diagnostics.push({
87
+ code: 'partial-placement',
88
+ severity: 'warning',
89
+ pack,
90
+ scope: facts.scope,
91
+ affectedAssets: [],
92
+ source: 'pack-inventory',
93
+ detail: `Pack ${pack} is only partially realized at ${facts.scope} scope`,
94
+ recovery: [],
95
+ });
96
+ }
97
+ }
98
+ if (scopes.filter(({ realization }) => realization === 'present').length === 2) {
99
+ diagnostics.push({
100
+ code: 'duplicate-placement',
101
+ severity: 'warning',
102
+ pack,
103
+ affectedAssets: [],
104
+ source: 'pack-inventory',
105
+ detail: `Pack ${pack} is realized at project and user scope`,
106
+ recovery: [],
107
+ });
108
+ }
109
+ return diagnostics;
110
+ }
111
+ export function projectPackEvidence(input) {
112
+ const pack = input.canonical?.pack ??
113
+ input.scopes[0]?.intent.pack ??
114
+ (() => {
115
+ throw new Error('Pack evidence requires canonical inventory or scope facts');
116
+ })();
117
+ return {
118
+ schemaVersion: 1,
119
+ pack,
120
+ canonical: input.canonical,
121
+ scopes: input.scopes,
122
+ knownRealizedScopes: input.scopes
123
+ .filter(({ realization }) => realization === 'present')
124
+ .map(({ scope }) => scope),
125
+ unknownScopes: input.scopes
126
+ .filter(({ realization }) => realization === 'unknown')
127
+ .map(({ scope }) => scope),
128
+ realizedPlacement: placementForScopes(input.scopes),
129
+ providers: input.providers ?? [],
130
+ diagnostics: canonicalDiagnostics(pack, input.scopes),
131
+ };
132
+ }
@@ -24,6 +24,7 @@ export interface ScopedPackInventory {
24
24
  }
25
25
  export interface PackInventory {
26
26
  pack: PackName;
27
+ /** @deprecated Use ToolPackEvidence.realizedPlacement for truthful placement. */
27
28
  placement: 'project' | 'user' | 'both' | 'unavailable';
28
29
  scopes: ScopedPackInventory[];
29
30
  diagnostics: PackDiagnostic[];
@@ -1 +1 @@
1
- {"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,uBAAuB,GACvB,iBAAiB,GACjB,0BAA0B,GAC1B,2BAA2B,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACvD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAiRD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CAwC9B;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAUT;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,aAAa,EAAE,GAC3B,aAAa,EAAE,CAgEjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,aAAa,CAAC,CAiDxB"}
1
+ {"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,uBAAuB,GACvB,iBAAiB,GACjB,0BAA0B,GAC1B,2BAA2B,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,iFAAiF;IACjF,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACvD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAiRD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CAwC9B;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAUT;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,aAAa,EAAE,GAC3B,aAAa,EAAE,CAgEjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,aAAa,CAAC,CAiDxB"}
@@ -0,0 +1,44 @@
1
+ import type { ConcreteScope } from '../../../shared/types.js';
2
+ import type { AutoSyncResult } from './auto-sync.js';
3
+ import { type ProviderReachabilityEvidence, type RecoveryAction, type ToolPackEvidence } from './pack-evidence.js';
4
+ import type { PackLifecycleResult } from './pack-lifecycle.js';
5
+ import type { PackName } from './types.js';
6
+ export interface PackScopeSelection {
7
+ pack: PackName;
8
+ requested: ConcreteScope | 'both';
9
+ retainedRealizedScopes: readonly ConcreteScope[];
10
+ targetScopes: readonly ConcreteScope[];
11
+ }
12
+ export interface ProviderSyncOutcome {
13
+ scopes: readonly ConcreteScope[];
14
+ status: 'not-run' | 'complete' | 'partial' | 'failed';
15
+ providers: readonly ProviderReachabilityEvidence[];
16
+ error?: string;
17
+ }
18
+ export interface PackLifecycleOutcome {
19
+ schemaVersion: 1;
20
+ selection: PackScopeSelection;
21
+ canonical: {
22
+ status: 'unchanged' | 'applied' | 'failed' | 'verification-failed';
23
+ results: readonly PackLifecycleResult[];
24
+ };
25
+ sync: ProviderSyncOutcome;
26
+ finalEvidence: ToolPackEvidence | null;
27
+ status: 'complete' | 'partial' | 'failed';
28
+ recovery: readonly RecoveryAction[];
29
+ }
30
+ export declare function resolveAdditivePackScopeSelection(input: {
31
+ pack: PackName;
32
+ requested: ConcreteScope | 'both';
33
+ knownRealizedScopes: readonly ConcreteScope[];
34
+ unknownScopes: readonly ConcreteScope[];
35
+ }): PackScopeSelection;
36
+ export declare function providerSyncOutcomeFromAutoSync(result: AutoSyncResult, providers?: readonly ProviderReachabilityEvidence[]): ProviderSyncOutcome;
37
+ export declare function evaluatePackLifecycleOutcome(input: {
38
+ selection: PackScopeSelection;
39
+ lifecycle: readonly PackLifecycleResult[];
40
+ sync: ProviderSyncOutcome;
41
+ finalEvidence: ToolPackEvidence | null;
42
+ canonicalFailure?: string;
43
+ }): PackLifecycleOutcome;
44
+ //# sourceMappingURL=pack-lifecycle-outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack-lifecycle-outcome.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-lifecycle-outcome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,aAAa,GAAG,MAAM,CAAC;IAClC,sBAAsB,EAAE,SAAS,aAAa,EAAE,CAAC;IACjD,YAAY,EAAE,SAAS,aAAa,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IACjC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtD,SAAS,EAAE,SAAS,4BAA4B,EAAE,CAAC;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,CAAC,CAAC;IACjB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE;QACT,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,qBAAqB,CAAC;QACnE,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;KACzC,CAAC;IACF,IAAI,EAAE,mBAAmB,CAAC;IAC1B,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC;AASD,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,aAAa,GAAG,MAAM,CAAC;IAClC,mBAAmB,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,aAAa,EAAE,SAAS,aAAa,EAAE,CAAC;CACzC,GAAG,kBAAkB,CAkBrB;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,cAAc,EACtB,SAAS,GAAE,SAAS,4BAA4B,EAAO,GACtD,mBAAmB,CAYrB;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC1C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,oBAAoB,CAqEvB"}
@@ -0,0 +1,91 @@
1
+ import { hasScopedPackRealizationEvidence, } from './pack-evidence.js';
2
+ const SCOPE_ORDER = ['project', 'user'];
3
+ function orderedScopes(scopes) {
4
+ const selected = new Set(scopes);
5
+ return SCOPE_ORDER.filter((scope) => selected.has(scope));
6
+ }
7
+ export function resolveAdditivePackScopeSelection(input) {
8
+ if (input.unknownScopes.length > 0) {
9
+ throw new Error(`Cannot select scope for ${input.pack}: inventory is unknown at ${input.unknownScopes.join(', ')} scope`);
10
+ }
11
+ const retainedRealizedScopes = orderedScopes(input.knownRealizedScopes);
12
+ const requestedScopes = input.requested === 'both' ? SCOPE_ORDER : [input.requested];
13
+ return {
14
+ pack: input.pack,
15
+ requested: input.requested,
16
+ retainedRealizedScopes,
17
+ targetScopes: orderedScopes([
18
+ ...retainedRealizedScopes,
19
+ ...requestedScopes,
20
+ ]),
21
+ };
22
+ }
23
+ export function providerSyncOutcomeFromAutoSync(result, providers = []) {
24
+ return {
25
+ scopes: result.scopes,
26
+ status: result.scopes.length === 0
27
+ ? 'not-run'
28
+ : result.synced
29
+ ? 'complete'
30
+ : 'failed',
31
+ providers,
32
+ ...(result.error ? { error: result.error } : {}),
33
+ };
34
+ }
35
+ export function evaluatePackLifecycleOutcome(input) {
36
+ const recovery = [];
37
+ let canonicalStatus;
38
+ if (input.canonicalFailure) {
39
+ canonicalStatus = 'failed';
40
+ recovery.push({
41
+ code: 'canonical-apply-failed',
42
+ message: input.canonicalFailure,
43
+ });
44
+ }
45
+ else if (input.lifecycle.length === 0) {
46
+ canonicalStatus = 'unchanged';
47
+ }
48
+ else if (input.lifecycle.some(({ apply }) => apply !== null && !hasScopedPackRealizationEvidence(apply.inventory))) {
49
+ canonicalStatus = 'verification-failed';
50
+ recovery.push({
51
+ code: 'canonical-verification-failed',
52
+ message: `Re-run installation for ${input.selection.pack} and inspect pack status`,
53
+ });
54
+ }
55
+ else {
56
+ canonicalStatus = input.lifecycle.some(({ apply }) => apply && apply.applied.length > 0)
57
+ ? 'applied'
58
+ : 'unchanged';
59
+ }
60
+ const verified = input.finalEvidence !== null &&
61
+ input.finalEvidence.unknownScopes.length === 0 &&
62
+ input.selection.targetScopes.every((scope) => input.finalEvidence.knownRealizedScopes.includes(scope));
63
+ if (!verified && canonicalStatus !== 'failed') {
64
+ canonicalStatus = 'verification-failed';
65
+ recovery.push({
66
+ code: 'final-inventory-unverified',
67
+ message: `Re-run status for ${input.selection.pack}; final placement could not be verified`,
68
+ });
69
+ }
70
+ if (input.sync.status === 'partial' || input.sync.status === 'failed') {
71
+ recovery.push({
72
+ code: 'provider-sync-incomplete',
73
+ message: input.sync.error ??
74
+ `Run oat sync for ${input.sync.scopes.join(', ') || 'the selected'} scope`,
75
+ });
76
+ }
77
+ const status = canonicalStatus === 'failed' || canonicalStatus === 'verification-failed'
78
+ ? 'failed'
79
+ : input.sync.status === 'partial' || input.sync.status === 'failed'
80
+ ? 'partial'
81
+ : 'complete';
82
+ return {
83
+ schemaVersion: 1,
84
+ selection: input.selection,
85
+ canonical: { status: canonicalStatus, results: input.lifecycle },
86
+ sync: input.sync,
87
+ finalEvidence: input.finalEvidence,
88
+ status,
89
+ recovery,
90
+ };
91
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAK1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAmBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CA8MT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAS7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAEL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAS1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAG7B,MAAM,gBAAgB,CAAC;AAmBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CAkPT;AAwCD;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAS7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
@@ -10,6 +10,7 @@ import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.u
10
10
  import { autoSync, } from '../../tools/shared/auto-sync.js';
11
11
  import { inventoryScopedPack } from '../../tools/shared/pack-inventory.js';
12
12
  import { reconcilePackLifecycles } from '../../tools/shared/pack-lifecycle.js';
13
+ import { evaluatePackLifecycleOutcome, } from '../../tools/shared/pack-lifecycle-outcome.js';
13
14
  import { reconcileProjectToolsConfig } from '../../tools/shared/project-tools-config.js';
14
15
  import { scanTools } from '../../tools/shared/scan-tools.js';
15
16
  import { readOatConfig, writeOatConfig } from '../../../config/oat-config.js';
@@ -17,7 +18,7 @@ import { resolveAssetsRoot } from '../../../fs/assets.js';
17
18
  import { fileExists } from '../../../fs/io.js';
18
19
  import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
19
20
  import { Command } from 'commander';
20
- import { updateTools, } from './update-tools.js';
21
+ import { failedUpdateLifecycleOutcomes, updateTools, } from './update-tools.js';
21
22
  const defaultDependencies = {
22
23
  scanTools,
23
24
  resolveScopeRoot: async (scope, cwd, home) => {
@@ -95,7 +96,29 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
95
96
  const target = targetResolution.target;
96
97
  const scopes = resolveConcreteScopes(context.scope);
97
98
  const dryRun = opts.dryRun ?? false;
98
- const result = await updateTools(target, scopes, context.cwd, context.home, dryRun, dependencies);
99
+ let result;
100
+ try {
101
+ result = await updateTools(target, scopes, context.cwd, context.home, dryRun, dependencies);
102
+ }
103
+ catch (error) {
104
+ if (target.kind === 'name')
105
+ throw error;
106
+ const lifecycle = failedUpdateLifecycleOutcomes(target, scopes, error);
107
+ const message = error instanceof Error ? error.message : String(error);
108
+ if (context.json) {
109
+ logger.json({
110
+ target: describeTarget(target),
111
+ dryRun,
112
+ result: createEmptyUpdateResult(),
113
+ lifecycle,
114
+ });
115
+ }
116
+ else {
117
+ logger.error(`Pack update failed: ${message}`);
118
+ }
119
+ process.exitCode = 1;
120
+ return;
121
+ }
99
122
  const assetsRoot = dryRun ? null : await dependencies.resolveAssetsRoot();
100
123
  if (!dryRun && shouldBackfillWorkflowGitignore(result)) {
101
124
  const repoRoot = await resolveProjectRoot(context.cwd);
@@ -162,6 +185,7 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
162
185
  return;
163
186
  }
164
187
  // Auto-sync after mutations (before output so sync errors are captured)
188
+ const syncResults = [];
165
189
  if (!dryRun && opts.sync !== false) {
166
190
  for (const scope of scopes) {
167
191
  const installedCanonicalPaths = [
@@ -172,16 +196,23 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
172
196
  const updatedAtScope = result.updated.some((tool) => tool.scope === scope);
173
197
  if (!updatedAtScope && installedCanonicalPaths.length === 0)
174
198
  continue;
175
- await autoSync([scope], context.cwd, context.home, logger, syncDependencies, { installedCanonicalPaths });
199
+ syncResults.push(await autoSync([scope], context.cwd, context.home, logger, syncDependencies, { installedCanonicalPaths }));
176
200
  }
177
201
  }
202
+ const lifecycle = finalizeUpdateLifecycle(result.lifecycle, syncResults);
203
+ const legacyResult = { ...result };
204
+ delete legacyResult.lifecycle;
178
205
  if (context.json) {
179
206
  logger.json({
180
207
  target: describeTarget(target),
181
208
  dryRun,
182
- result,
209
+ result: legacyResult,
183
210
  ...(adoptedPacks.length > 0 ? { adoptedPacks } : {}),
211
+ ...(lifecycle ? { lifecycle } : {}),
184
212
  });
213
+ if (lifecycle?.some(({ status }) => status !== 'complete')) {
214
+ process.exitCode = 1;
215
+ }
185
216
  return;
186
217
  }
187
218
  for (const pack of adoptedPacks) {
@@ -213,6 +244,45 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
213
244
  if (result.updated.length === 0 && result.assetRefreshes.length === 0) {
214
245
  logger.info('No tools to update.');
215
246
  }
247
+ for (const outcome of lifecycle ?? []) {
248
+ if (outcome.status === 'complete')
249
+ continue;
250
+ logger.warn(`Pack ${outcome.selection.pack} update ${outcome.status}: ${outcome.recovery.map(({ message }) => message).join('; ')}`);
251
+ process.exitCode = 1;
252
+ }
253
+ });
254
+ }
255
+ function createEmptyUpdateResult() {
256
+ return {
257
+ updated: [],
258
+ current: [],
259
+ newer: [],
260
+ notInstalled: [],
261
+ notBundled: [],
262
+ assetRefreshes: [],
263
+ plans: [],
264
+ };
265
+ }
266
+ function finalizeUpdateLifecycle(lifecycle, syncResults) {
267
+ if (!lifecycle || syncResults.length === 0)
268
+ return lifecycle;
269
+ return lifecycle.map((outcome) => {
270
+ const relevant = syncResults.filter(({ scopes }) => scopes.some((scope) => outcome.selection.targetScopes.includes(scope)));
271
+ if (relevant.length === 0)
272
+ return outcome;
273
+ return evaluatePackLifecycleOutcome({
274
+ selection: outcome.selection,
275
+ lifecycle: outcome.canonical.results,
276
+ sync: {
277
+ scopes: [...new Set(relevant.flatMap(({ scopes }) => scopes))],
278
+ status: relevant.every(({ synced }) => synced) ? 'complete' : 'failed',
279
+ providers: [],
280
+ ...(relevant.find(({ error }) => error)?.error
281
+ ? { error: relevant.find(({ error }) => error).error }
282
+ : {}),
283
+ },
284
+ finalEvidence: outcome.finalEvidence,
285
+ });
216
286
  });
217
287
  }
218
288
  /**
@@ -3,6 +3,7 @@ import type { ApplyOatCoreResult } from '../../init/gitignore.js';
3
3
  import type { CopyStatus } from '../../init/tools/shared/copy-helpers.js';
4
4
  import type { InventoryScopedPackInput, ScopedPackInventory } from '../../tools/shared/pack-inventory.js';
5
5
  import { type PackLifecycleRequest, type PackLifecycleResult } from '../../tools/shared/pack-lifecycle.js';
6
+ import { type PackLifecycleOutcome } from '../../tools/shared/pack-lifecycle-outcome.js';
6
7
  import type { PackReconcilePlan } from '../../tools/shared/pack-reconcile.js';
7
8
  import type { ScanToolsOptions } from '../../tools/shared/scan-tools.js';
8
9
  import type { PackName, ToolInfo } from '../../tools/shared/types.js';
@@ -31,6 +32,7 @@ export interface UpdateResult {
31
32
  notBundled: ToolInfo[];
32
33
  assetRefreshes: PackAssetRefresh[];
33
34
  plans: PackReconcilePlan[];
35
+ lifecycle?: PackLifecycleOutcome[];
34
36
  }
35
37
  export interface UpdateToolsDependencies {
36
38
  scanTools: (options: ScanToolsOptions) => Promise<ToolInfo[]>;
@@ -48,4 +50,7 @@ export interface UpdateToolsDependencies {
48
50
  }) => Promise<PackLifecycleResult[]>;
49
51
  }
50
52
  export declare function updateTools(target: UpdateTarget, scopes: ConcreteScope[], cwd: string, home: string, dryRun: boolean, dependencies: UpdateToolsDependencies): Promise<UpdateResult>;
53
+ export declare function failedUpdateLifecycleOutcomes(target: Exclude<UpdateTarget, {
54
+ kind: 'name';
55
+ }>, scopes: readonly ConcreteScope[], error: unknown): PackLifecycleOutcome[];
51
56
  //# sourceMappingURL=update-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/update-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-tools.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/update-tools.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { join } from 'node:path';
2
- import { hasScopedPackPlacementEvidence, inventoryScopedPack, } from '../../tools/shared/pack-inventory.js';
2
+ import { hasScopedPackRealizationEvidence, packScopeFactsFromInventory, projectPackEvidence, } from '../../tools/shared/pack-evidence.js';
3
+ import { inventoryScopedPack } from '../../tools/shared/pack-inventory.js';
3
4
  import {} from '../../tools/shared/pack-lifecycle.js';
5
+ import { evaluatePackLifecycleOutcome, resolveAdditivePackScopeSelection, } from '../../tools/shared/pack-lifecycle-outcome.js';
4
6
  import { getPackDefinition } from '../../tools/shared/pack-manifest.js';
5
7
  function getBundledPackAssets(pack, scope) {
6
8
  const assets = getPackDefinition(pack).assets.filter(({ scopes, ownership }) => scopes.includes(scope) && ownership[scope] === 'managed');
@@ -47,7 +49,7 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
47
49
  scopeRoot,
48
50
  assetsRoot,
49
51
  });
50
- if (!hasScopedPackPlacementEvidence(before))
52
+ if (!hasScopedPackRealizationEvidence(before))
51
53
  continue;
52
54
  requests.push({
53
55
  pack: definition.name,
@@ -63,6 +65,7 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
63
65
  return result;
64
66
  }
65
67
  const lifecycle = await dependencies.reconcilePacks(requests, { dryRun });
68
+ result.lifecycle = updateLifecycleOutcomes(lifecycle);
66
69
  result.plans.push(...lifecycle.map(({ plan }) => plan));
67
70
  for (const entry of lifecycle) {
68
71
  const definition = getPackDefinition(entry.request.pack);
@@ -243,6 +246,65 @@ export async function updateTools(target, scopes, cwd, home, dryRun, dependencie
243
246
  }
244
247
  return result;
245
248
  }
249
+ function updateLifecycleOutcomes(results) {
250
+ const verifiable = results.filter(({ apply }) => apply === null || ('inventory' in apply && apply.inventory !== undefined));
251
+ const packs = [...new Set(verifiable.map(({ request }) => request.pack))];
252
+ return packs.map((pack) => {
253
+ const lifecycle = verifiable.filter(({ request }) => request.pack === pack);
254
+ const requestedScopes = lifecycle.map(({ request }) => request.scope);
255
+ const finalScopes = lifecycle.map(({ apply, before }) => apply?.inventory ?? before);
256
+ const finalEvidence = projectPackEvidence({
257
+ canonical: null,
258
+ scopes: finalScopes.map(packScopeFactsFromInventory),
259
+ });
260
+ const selection = resolveAdditivePackScopeSelection({
261
+ pack,
262
+ requested: requestedScopes.includes('project') && requestedScopes.includes('user')
263
+ ? 'both'
264
+ : requestedScopes[0],
265
+ knownRealizedScopes: lifecycle
266
+ .filter(({ before }) => hasScopedPackRealizationEvidence(before))
267
+ .map(({ request }) => request.scope),
268
+ unknownScopes: [],
269
+ });
270
+ if (lifecycle.every(({ apply }) => apply === null)) {
271
+ return {
272
+ schemaVersion: 1,
273
+ selection,
274
+ canonical: { status: 'unchanged', results: lifecycle },
275
+ sync: { scopes: [], status: 'not-run', providers: [] },
276
+ finalEvidence,
277
+ status: 'complete',
278
+ recovery: [],
279
+ };
280
+ }
281
+ return evaluatePackLifecycleOutcome({
282
+ selection,
283
+ lifecycle,
284
+ sync: { scopes: [], status: 'not-run', providers: [] },
285
+ finalEvidence,
286
+ });
287
+ });
288
+ }
289
+ export function failedUpdateLifecycleOutcomes(target, scopes, error) {
290
+ const message = error instanceof Error ? error.message : String(error);
291
+ return getSelectedDefinitions(target).map(({ name: pack }) => ({
292
+ schemaVersion: 1,
293
+ selection: {
294
+ pack,
295
+ requested: scopes.includes('project') && scopes.includes('user')
296
+ ? 'both'
297
+ : scopes[0],
298
+ retainedRealizedScopes: [],
299
+ targetScopes: scopes,
300
+ },
301
+ canonical: { status: 'failed', results: [] },
302
+ sync: { scopes: [], status: 'not-run', providers: [] },
303
+ finalEvidence: null,
304
+ status: 'failed',
305
+ recovery: [{ code: 'canonical-apply-failed', message }],
306
+ }));
307
+ }
246
308
  function getSelectedDefinitions(target) {
247
309
  return target.kind === 'pack'
248
310
  ? [getPackDefinition(target.pack)]
@@ -10,6 +10,11 @@ export interface OatDocumentationConfig {
10
10
  export interface OatGitConfig {
11
11
  defaultBranch?: string;
12
12
  }
13
+ /**
14
+ * Known project config keys. Unknown siblings written by a newer OAT are not
15
+ * described here, but they are preserved verbatim across read-mutate-write:
16
+ * see the FR10 merge in `normalizeOatConfig`.
17
+ */
13
18
  export interface OatProjectsConfig {
14
19
  root?: string;
15
20
  defaultScope?: 'shared' | 'local' | 'synced';