@open-agent-toolkit/cli 0.2.35 → 0.2.37
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.
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/backlog-lifecycle.md +18 -0
- package/assets/docs/cli-utilities/bootstrap.md +6 -3
- package/assets/docs/cli-utilities/config-and-local-state.md +26 -12
- package/assets/docs/cli-utilities/configuration.md +36 -13
- package/assets/docs/cli-utilities/tool-packs.md +423 -51
- package/assets/docs/provider-sync/scope-and-surface.md +4 -1
- package/assets/docs/reference/cli-reference.md +5 -3
- package/assets/docs/reference/file-locations.md +28 -4
- package/assets/docs/reference/troubleshooting.md +132 -2
- package/assets/docs/workflows/projects/lifecycle.md +21 -2
- package/assets/public-package-versions.json +4 -4
- package/assets/scripts/generate-oat-state.sh +441 -0
- package/assets/scripts/generate-thin-index.sh +200 -0
- package/assets/skills/oat-agent-instructions-analyze/SKILL.md +10 -5
- package/assets/skills/oat-agent-instructions-apply/SKILL.md +30 -5
- package/assets/skills/oat-brainstorm/SKILL.md +34 -8
- package/assets/skills/oat-brainstorm/references/destinations.md +6 -1
- package/assets/skills/oat-docs-analyze/SKILL.md +9 -4
- package/assets/skills/oat-docs-apply/SKILL.md +6 -3
- package/assets/skills/oat-pjm-add-backlog-item/SKILL.md +14 -1
- package/assets/skills/oat-pjm-decision/SKILL.md +22 -10
- package/assets/skills/oat-pjm-review-backlog/SKILL.md +20 -3
- package/assets/skills/oat-pjm-update-repo-reference/SKILL.md +20 -10
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
- package/assets/skills/oat-project-document/SKILL.md +21 -3
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-summary/SKILL.md +23 -11
- package/assets/skills/oat-repo-knowledge-index/SKILL.md +6 -3
- package/dist/commands/backlog/index.d.ts +2 -0
- package/dist/commands/backlog/index.d.ts.map +1 -1
- package/dist/commands/backlog/index.js +67 -23
- package/dist/commands/backlog/new.d.ts +3 -0
- package/dist/commands/backlog/new.d.ts.map +1 -1
- package/dist/commands/backlog/new.js +8 -21
- package/dist/commands/decision/agents-guidance.d.ts.map +1 -1
- package/dist/commands/decision/agents-guidance.js +2 -1
- package/dist/commands/decision/index.d.ts +2 -0
- package/dist/commands/decision/index.d.ts.map +1 -1
- package/dist/commands/decision/index.js +19 -3
- package/dist/commands/decision/new.d.ts +4 -0
- package/dist/commands/decision/new.d.ts.map +1 -1
- package/dist/commands/decision/new.js +11 -30
- package/dist/commands/doctor/index.d.ts +4 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +254 -9
- package/dist/commands/init/tools/brainstorm/index.d.ts.map +1 -1
- package/dist/commands/init/tools/brainstorm/index.js +20 -6
- package/dist/commands/init/tools/docs/index.d.ts.map +1 -1
- package/dist/commands/init/tools/docs/index.js +4 -1
- package/dist/commands/init/tools/ideas/index.d.ts.map +1 -1
- package/dist/commands/init/tools/ideas/index.js +4 -1
- package/dist/commands/init/tools/index.d.ts +11 -2
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +459 -351
- package/dist/commands/init/tools/install-state.d.ts +2 -0
- package/dist/commands/init/tools/install-state.d.ts.map +1 -1
- package/dist/commands/init/tools/install-state.js +11 -0
- package/dist/commands/init/tools/project-management/agents-guidance.d.ts.map +1 -1
- package/dist/commands/init/tools/project-management/agents-guidance.js +3 -1
- package/dist/commands/init/tools/project-management/index.d.ts +1 -0
- package/dist/commands/init/tools/project-management/index.d.ts.map +1 -1
- package/dist/commands/init/tools/project-management/index.js +24 -55
- package/dist/commands/init/tools/project-management/install-project-management.d.ts +4 -0
- package/dist/commands/init/tools/project-management/install-project-management.d.ts.map +1 -1
- package/dist/commands/init/tools/project-management/install-project-management.js +4 -1
- package/dist/commands/init/tools/research/index.d.ts.map +1 -1
- package/dist/commands/init/tools/research/index.js +4 -1
- package/dist/commands/init/tools/shared/copy-helpers.d.ts.map +1 -1
- package/dist/commands/init/tools/shared/copy-helpers.js +10 -0
- package/dist/commands/init/tools/shared/skill-manifest.d.ts +15 -15
- package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
- package/dist/commands/init/tools/shared/skill-manifest.js +17 -122
- package/dist/commands/init/tools/utility/index.d.ts.map +1 -1
- package/dist/commands/init/tools/utility/index.js +4 -1
- package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
- package/dist/commands/init/tools/workflows/index.js +4 -1
- package/dist/commands/init/tools/workflows/install-workflows.d.ts.map +1 -1
- package/dist/commands/init/tools/workflows/install-workflows.js +2 -4
- package/dist/commands/pjm/adoption.d.ts +12 -0
- package/dist/commands/pjm/adoption.d.ts.map +1 -0
- package/dist/commands/pjm/adoption.js +47 -0
- package/dist/commands/pjm/doctor.d.ts +3 -2
- package/dist/commands/pjm/doctor.d.ts.map +1 -1
- package/dist/commands/pjm/doctor.js +28 -13
- package/dist/commands/pjm/index.d.ts +2 -0
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +11 -3
- package/dist/commands/pjm/init.d.ts +3 -0
- package/dist/commands/pjm/init.d.ts.map +1 -1
- package/dist/commands/pjm/init.js +37 -32
- package/dist/commands/pjm/migrate.d.ts +1 -0
- package/dist/commands/pjm/migrate.d.ts.map +1 -1
- package/dist/commands/pjm/migrate.js +1 -0
- package/dist/commands/pjm/template-source.d.ts +14 -0
- package/dist/commands/pjm/template-source.d.ts.map +1 -0
- package/dist/commands/pjm/template-source.js +56 -0
- package/dist/commands/remove/skills/remove-skills.d.ts.map +1 -1
- package/dist/commands/remove/skills/remove-skills.js +10 -19
- package/dist/commands/status/index.d.ts +5 -0
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +203 -2
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +40 -7
- package/dist/commands/sync/sync.types.d.ts +4 -0
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/commands/tools/has/has-pack.d.ts +11 -2
- package/dist/commands/tools/has/has-pack.d.ts.map +1 -1
- package/dist/commands/tools/has/has-pack.js +33 -20
- package/dist/commands/tools/index.d.ts.map +1 -1
- package/dist/commands/tools/index.js +3 -1
- package/dist/commands/tools/info/info-tool.d.ts +3 -0
- package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
- package/dist/commands/tools/info/info-tool.js +29 -4
- package/dist/commands/tools/list/list-tools.d.ts +3 -0
- package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
- package/dist/commands/tools/list/list-tools.js +31 -4
- package/dist/commands/tools/migrate/index.d.ts +26 -0
- package/dist/commands/tools/migrate/index.d.ts.map +1 -0
- package/dist/commands/tools/migrate/index.js +312 -0
- package/dist/commands/tools/migrate/migrate-pack.d.ts +81 -0
- package/dist/commands/tools/migrate/migrate-pack.d.ts.map +1 -0
- package/dist/commands/tools/migrate/migrate-pack.js +324 -0
- package/dist/commands/tools/outdated/outdated-tools.d.ts +11 -0
- package/dist/commands/tools/outdated/outdated-tools.d.ts.map +1 -1
- package/dist/commands/tools/outdated/outdated-tools.js +33 -5
- package/dist/commands/tools/remove/index.d.ts.map +1 -1
- package/dist/commands/tools/remove/index.js +73 -20
- package/dist/commands/tools/remove/remove-tools.d.ts +28 -0
- package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
- package/dist/commands/tools/remove/remove-tools.js +156 -26
- package/dist/commands/tools/shared/apply-pack-reconcile.d.ts +41 -0
- package/dist/commands/tools/shared/apply-pack-reconcile.d.ts.map +1 -0
- package/dist/commands/tools/shared/apply-pack-reconcile.js +126 -0
- package/dist/commands/tools/shared/auto-sync.d.ts +5 -2
- package/dist/commands/tools/shared/auto-sync.d.ts.map +1 -1
- package/dist/commands/tools/shared/auto-sync.js +1 -0
- package/dist/commands/tools/shared/content-digest.d.ts +3 -0
- package/dist/commands/tools/shared/content-digest.d.ts.map +1 -0
- package/dist/commands/tools/shared/content-digest.js +57 -0
- package/dist/commands/tools/shared/format-pack-inventory.d.ts +3 -0
- package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -0
- package/dist/commands/tools/shared/format-pack-inventory.js +21 -0
- package/dist/commands/tools/shared/install-sync-context.d.ts.map +1 -1
- package/dist/commands/tools/shared/install-sync-context.js +2 -25
- package/dist/commands/tools/shared/pack-inventory.d.ts +46 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-inventory.js +207 -0
- package/dist/commands/tools/shared/pack-lifecycle.d.ts +34 -0
- package/dist/commands/tools/shared/pack-lifecycle.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-lifecycle.js +67 -0
- package/dist/commands/tools/shared/pack-manifest.d.ts +11 -0
- package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-manifest.js +384 -0
- package/dist/commands/tools/shared/pack-paths.d.ts +21 -0
- package/dist/commands/tools/shared/pack-paths.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-paths.js +35 -0
- package/dist/commands/tools/shared/pack-reconcile.d.ts +64 -0
- package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-reconcile.js +158 -0
- package/dist/commands/tools/shared/project-tools-config.d.ts.map +1 -1
- package/dist/commands/tools/shared/project-tools-config.js +12 -38
- package/dist/commands/tools/shared/scan-tools.js +2 -2
- package/dist/commands/tools/shared/scoped-pack-intent.d.ts +34 -0
- package/dist/commands/tools/shared/scoped-pack-intent.d.ts.map +1 -0
- package/dist/commands/tools/shared/scoped-pack-intent.js +116 -0
- package/dist/commands/tools/shared/types.d.ts +22 -0
- package/dist/commands/tools/shared/types.d.ts.map +1 -1
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +30 -5
- package/dist/commands/tools/update/update-tools.d.ts +9 -1
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/commands/tools/update/update-tools.js +176 -64
- package/dist/config/oat-config.d.ts +6 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +49 -20
- package/dist/fs/paths.d.ts +12 -0
- package/dist/fs/paths.d.ts.map +1 -1
- package/dist/fs/paths.js +87 -1
- package/package.json +2 -2
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { isAbsolute, posix } from 'node:path';
|
|
2
|
+
export const PACK_NAMES = [
|
|
3
|
+
'core',
|
|
4
|
+
'ideas',
|
|
5
|
+
'docs',
|
|
6
|
+
'workflows',
|
|
7
|
+
'utility',
|
|
8
|
+
'project-management',
|
|
9
|
+
'research',
|
|
10
|
+
'brainstorm',
|
|
11
|
+
];
|
|
12
|
+
export function isPackName(value) {
|
|
13
|
+
return PACK_NAMES.includes(value);
|
|
14
|
+
}
|
|
15
|
+
const BOTH_SCOPES = ['project', 'user'];
|
|
16
|
+
const BOTH_MANAGED = { project: 'managed', user: 'managed' };
|
|
17
|
+
const TEMPLATE_OWNERSHIP = {
|
|
18
|
+
project: 'seed-if-missing',
|
|
19
|
+
user: 'managed',
|
|
20
|
+
};
|
|
21
|
+
function skill(name, scopes = BOTH_SCOPES) {
|
|
22
|
+
return {
|
|
23
|
+
id: `skill:${name}`,
|
|
24
|
+
kind: 'skill',
|
|
25
|
+
source: `skills/${name}`,
|
|
26
|
+
destination: `.agents/skills/${name}`,
|
|
27
|
+
scopes,
|
|
28
|
+
ownership: scopes.length === 1 ? { user: 'managed' } : BOTH_MANAGED,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function agent(name) {
|
|
32
|
+
return {
|
|
33
|
+
id: `agent:${name}`,
|
|
34
|
+
kind: 'agent',
|
|
35
|
+
source: `agents/${name}`,
|
|
36
|
+
destination: `.agents/agents/${name}`,
|
|
37
|
+
scopes: BOTH_SCOPES,
|
|
38
|
+
ownership: BOTH_MANAGED,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function template(name, kind = 'template') {
|
|
42
|
+
return {
|
|
43
|
+
id: `template:${name}`,
|
|
44
|
+
kind,
|
|
45
|
+
source: `templates/${name}`,
|
|
46
|
+
destination: `.oat/templates/${name}`,
|
|
47
|
+
scopes: BOTH_SCOPES,
|
|
48
|
+
ownership: TEMPLATE_OWNERSHIP,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function script(name, sharedOwner) {
|
|
52
|
+
return {
|
|
53
|
+
id: `script:${name}`,
|
|
54
|
+
kind: 'script',
|
|
55
|
+
source: `scripts/${name}`,
|
|
56
|
+
destination: `.oat/scripts/${name}`,
|
|
57
|
+
scopes: BOTH_SCOPES,
|
|
58
|
+
ownership: BOTH_MANAGED,
|
|
59
|
+
executable: true,
|
|
60
|
+
sharedOwner,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function seed(id, destination, options) {
|
|
64
|
+
const scopes = options.scopes ?? BOTH_SCOPES;
|
|
65
|
+
return {
|
|
66
|
+
id: `seed:${id}`,
|
|
67
|
+
kind: 'seed',
|
|
68
|
+
source: options.source,
|
|
69
|
+
generation: options.generation,
|
|
70
|
+
destination,
|
|
71
|
+
scopes,
|
|
72
|
+
ownership: Object.fromEntries(scopes.map((scope) => [scope, 'seed-if-missing'])),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const WORKFLOW_SKILL_NAMES = [
|
|
76
|
+
'oat-cursor-cloud-projects',
|
|
77
|
+
'oat-explainer-kit',
|
|
78
|
+
'oat-project-autonomous',
|
|
79
|
+
'oat-project-capture',
|
|
80
|
+
'oat-project-clear-active',
|
|
81
|
+
'oat-project-complete',
|
|
82
|
+
'oat-project-design',
|
|
83
|
+
'oat-project-dispatch-subagents',
|
|
84
|
+
'oat-project-discover',
|
|
85
|
+
'oat-project-document',
|
|
86
|
+
'oat-project-implement',
|
|
87
|
+
'oat-project-import-plan',
|
|
88
|
+
'oat-project-new',
|
|
89
|
+
'oat-project-next',
|
|
90
|
+
'oat-project-open',
|
|
91
|
+
'oat-project-plan',
|
|
92
|
+
'oat-project-plan-writing',
|
|
93
|
+
'oat-project-pr-final',
|
|
94
|
+
'oat-project-pr-progress',
|
|
95
|
+
'oat-project-progress',
|
|
96
|
+
'oat-project-promote-spec-driven',
|
|
97
|
+
'oat-project-quick-start',
|
|
98
|
+
'oat-project-reconcile',
|
|
99
|
+
'oat-project-retro',
|
|
100
|
+
'oat-project-retro-file',
|
|
101
|
+
'oat-project-revise',
|
|
102
|
+
'oat-project-review-provide',
|
|
103
|
+
'oat-project-review-provide-remote',
|
|
104
|
+
'oat-project-review-receive',
|
|
105
|
+
'oat-project-review-receive-remote',
|
|
106
|
+
'oat-project-spec',
|
|
107
|
+
'oat-project-split',
|
|
108
|
+
'oat-project-summary',
|
|
109
|
+
'oat-repo-knowledge-index',
|
|
110
|
+
'oat-worktree-bootstrap',
|
|
111
|
+
'oat-worktree-bootstrap-auto',
|
|
112
|
+
'oat-wave-execute',
|
|
113
|
+
'oat-wave-program',
|
|
114
|
+
'oat-wrap-up',
|
|
115
|
+
];
|
|
116
|
+
export const PACK_MANIFEST = [
|
|
117
|
+
{
|
|
118
|
+
name: 'core',
|
|
119
|
+
allowedScopes: ['user'],
|
|
120
|
+
defaultScope: 'user',
|
|
121
|
+
assets: [
|
|
122
|
+
skill('oat-docs', ['user']),
|
|
123
|
+
skill('oat-doctor', ['user']),
|
|
124
|
+
{
|
|
125
|
+
id: 'directory:docs',
|
|
126
|
+
kind: 'directory',
|
|
127
|
+
source: 'docs',
|
|
128
|
+
destination: '.oat/docs',
|
|
129
|
+
scopes: ['user'],
|
|
130
|
+
ownership: { user: 'managed' },
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: 'ideas',
|
|
136
|
+
allowedScopes: BOTH_SCOPES,
|
|
137
|
+
defaultScope: 'user',
|
|
138
|
+
assets: [
|
|
139
|
+
...[
|
|
140
|
+
'oat-idea-new',
|
|
141
|
+
'oat-idea-ideate',
|
|
142
|
+
'oat-idea-summarize',
|
|
143
|
+
'oat-idea-scratchpad',
|
|
144
|
+
].map((name) => skill(name)),
|
|
145
|
+
seed('ideas-backlog', '.oat/ideas/backlog.md', {
|
|
146
|
+
source: 'templates/ideas/ideas-backlog.md',
|
|
147
|
+
}),
|
|
148
|
+
seed('ideas-scratchpad', '.oat/ideas/scratchpad.md', {
|
|
149
|
+
source: 'templates/ideas/ideas-scratchpad.md',
|
|
150
|
+
}),
|
|
151
|
+
template('ideas/idea-discovery.md'),
|
|
152
|
+
template('ideas/idea-summary.md'),
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'docs',
|
|
157
|
+
allowedScopes: BOTH_SCOPES,
|
|
158
|
+
defaultScope: 'user',
|
|
159
|
+
assets: [
|
|
160
|
+
...[
|
|
161
|
+
'authoring-docs',
|
|
162
|
+
'oat-agent-instructions-analyze',
|
|
163
|
+
'oat-agent-instructions-apply',
|
|
164
|
+
'oat-docs-analyze',
|
|
165
|
+
'oat-docs-apply',
|
|
166
|
+
'oat-docs-authoring',
|
|
167
|
+
'oat-docs-bootstrap',
|
|
168
|
+
].map((name) => skill(name)),
|
|
169
|
+
template('docs-app-mkdocs', 'directory'),
|
|
170
|
+
template('docs-app-fuma', 'directory'),
|
|
171
|
+
script('resolve-tracking.sh', 'resolve-tracking'),
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'workflows',
|
|
176
|
+
allowedScopes: BOTH_SCOPES,
|
|
177
|
+
defaultScope: 'user',
|
|
178
|
+
assets: [
|
|
179
|
+
...WORKFLOW_SKILL_NAMES.map((name) => skill(name)),
|
|
180
|
+
...[
|
|
181
|
+
'oat-codebase-mapper.md',
|
|
182
|
+
'oat-phase-implementer.md',
|
|
183
|
+
'oat-reviewer.md',
|
|
184
|
+
].map((name) => agent(name)),
|
|
185
|
+
...[
|
|
186
|
+
'state.md',
|
|
187
|
+
'discovery.md',
|
|
188
|
+
'spec.md',
|
|
189
|
+
'design.md',
|
|
190
|
+
'plan.md',
|
|
191
|
+
'implementation.md',
|
|
192
|
+
'summary.md',
|
|
193
|
+
'project-log.md',
|
|
194
|
+
'project-retro.md',
|
|
195
|
+
].map((name) => template(name)),
|
|
196
|
+
...[
|
|
197
|
+
'generate-oat-state.sh',
|
|
198
|
+
'generate-thin-index.sh',
|
|
199
|
+
'resolve-tracking.sh',
|
|
200
|
+
].map((name) => script(name, name === 'resolve-tracking.sh' ? 'resolve-tracking' : undefined)),
|
|
201
|
+
seed('projects-root', '.oat/projects-root', {
|
|
202
|
+
generation: 'projects-root-default',
|
|
203
|
+
scopes: ['project'],
|
|
204
|
+
}),
|
|
205
|
+
seed('projects-config', '.oat/config.json', {
|
|
206
|
+
generation: 'projects-config-default',
|
|
207
|
+
scopes: ['project'],
|
|
208
|
+
}),
|
|
209
|
+
seed('projects-local-gitkeep', '.oat/projects/local/.gitkeep', {
|
|
210
|
+
generation: 'empty-file',
|
|
211
|
+
scopes: ['project'],
|
|
212
|
+
}),
|
|
213
|
+
seed('projects-archived-gitkeep', '.oat/projects/archived/.gitkeep', {
|
|
214
|
+
generation: 'empty-file',
|
|
215
|
+
scopes: ['project'],
|
|
216
|
+
}),
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: 'utility',
|
|
221
|
+
allowedScopes: BOTH_SCOPES,
|
|
222
|
+
defaultScope: 'user',
|
|
223
|
+
assets: [
|
|
224
|
+
...[
|
|
225
|
+
'create-agnostic-skill',
|
|
226
|
+
'explainer-kit',
|
|
227
|
+
'oat-dispatch-subagents',
|
|
228
|
+
'subagent-orchestration',
|
|
229
|
+
'oat-repo-improve',
|
|
230
|
+
'oat-repo-maintainability-review',
|
|
231
|
+
'oat-review-provide',
|
|
232
|
+
'oat-review-provide-remote',
|
|
233
|
+
'oat-review-receive',
|
|
234
|
+
'oat-review-receive-remote',
|
|
235
|
+
].map((name) => skill(name)),
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: 'project-management',
|
|
240
|
+
allowedScopes: BOTH_SCOPES,
|
|
241
|
+
defaultScope: 'user',
|
|
242
|
+
assets: [
|
|
243
|
+
...[
|
|
244
|
+
'oat-pjm-add-backlog-item',
|
|
245
|
+
'oat-pjm-decision',
|
|
246
|
+
'oat-pjm-update-repo-reference',
|
|
247
|
+
'oat-pjm-review-backlog',
|
|
248
|
+
].map((name) => skill(name)),
|
|
249
|
+
...[
|
|
250
|
+
'backlog-item.md',
|
|
251
|
+
'roadmap.md',
|
|
252
|
+
'current-state.md',
|
|
253
|
+
'decision.md',
|
|
254
|
+
'repo-agents.md',
|
|
255
|
+
'pjm-agents.md',
|
|
256
|
+
'reference-agents.md',
|
|
257
|
+
'repo-readme.md',
|
|
258
|
+
'pjm-handoffs-readme.md',
|
|
259
|
+
].map((name) => template(name)),
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'research',
|
|
264
|
+
allowedScopes: BOTH_SCOPES,
|
|
265
|
+
defaultScope: 'user',
|
|
266
|
+
assets: [
|
|
267
|
+
...['analyze', 'compare', 'deep-research', 'skeptic', 'synthesize'].map((name) => skill(name)),
|
|
268
|
+
agent('skeptical-evaluator.md'),
|
|
269
|
+
],
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: 'brainstorm',
|
|
273
|
+
allowedScopes: BOTH_SCOPES,
|
|
274
|
+
defaultScope: 'user',
|
|
275
|
+
assets: [skill('oat-brainstorm')],
|
|
276
|
+
},
|
|
277
|
+
];
|
|
278
|
+
export function getPackDefinition(pack) {
|
|
279
|
+
const definition = PACK_MANIFEST.find(({ name }) => name === pack);
|
|
280
|
+
if (!definition) {
|
|
281
|
+
throw new Error(`Unknown pack: ${pack}`);
|
|
282
|
+
}
|
|
283
|
+
return definition;
|
|
284
|
+
}
|
|
285
|
+
export function getPackAssets(pack, kind) {
|
|
286
|
+
const assets = getPackDefinition(pack).assets;
|
|
287
|
+
return kind ? assets.filter((asset) => asset.kind === kind) : assets;
|
|
288
|
+
}
|
|
289
|
+
export function getPackMemberNames(pack, kind) {
|
|
290
|
+
return getPackAssets(pack, kind).map(({ source }) => {
|
|
291
|
+
if (!source) {
|
|
292
|
+
throw new Error(`Pack ${pack} ${kind} asset has no materialized source`);
|
|
293
|
+
}
|
|
294
|
+
const prefix = `${kind === 'template' ? 'templates' : `${kind}s`}/`;
|
|
295
|
+
return source.slice(prefix.length);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
export function getCanonicalProviderPaths(pack) {
|
|
299
|
+
return getPackDefinition(pack)
|
|
300
|
+
.assets.filter(({ kind }) => kind === 'skill' || kind === 'agent')
|
|
301
|
+
.map(({ destination }) => destination);
|
|
302
|
+
}
|
|
303
|
+
function validateRelativePath(pack, asset, field) {
|
|
304
|
+
const value = asset[field];
|
|
305
|
+
if (value === undefined)
|
|
306
|
+
return;
|
|
307
|
+
const segments = value.replaceAll('\\', '/').split('/');
|
|
308
|
+
if (value.length === 0 ||
|
|
309
|
+
isAbsolute(value) ||
|
|
310
|
+
/^[A-Za-z]:[\\/]/.test(value) ||
|
|
311
|
+
segments.includes('..') ||
|
|
312
|
+
posix.normalize(value).startsWith('../')) {
|
|
313
|
+
throw new Error(`Pack ${pack} asset ${asset.id} ${field} must be relative to its scope and contain no parent traversal: ${value}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function validateAsset(pack, asset) {
|
|
317
|
+
if ((asset.source === undefined) === (asset.generation === undefined)) {
|
|
318
|
+
throw new Error(`Pack ${pack.name} asset ${asset.id} must declare exactly one source or generation contract`);
|
|
319
|
+
}
|
|
320
|
+
validateRelativePath(pack.name, asset, 'source');
|
|
321
|
+
validateRelativePath(pack.name, asset, 'destination');
|
|
322
|
+
if (asset.scopes.length === 0) {
|
|
323
|
+
throw new Error(`Pack ${pack.name} asset ${asset.id} has no scopes`);
|
|
324
|
+
}
|
|
325
|
+
for (const scope of asset.scopes) {
|
|
326
|
+
if (!pack.allowedScopes.includes(scope)) {
|
|
327
|
+
throw new Error(`Pack ${pack.name} asset ${asset.id} uses disallowed scope ${scope}`);
|
|
328
|
+
}
|
|
329
|
+
if (!asset.ownership[scope]) {
|
|
330
|
+
throw new Error(`Pack ${pack.name} asset ${asset.id} has no ownership for ${scope}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
for (const scope of Object.keys(asset.ownership)) {
|
|
334
|
+
if (!asset.scopes.includes(scope)) {
|
|
335
|
+
throw new Error(`Pack ${pack.name} asset ${asset.id} declares ownership outside scope ${scope}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
export function validatePackManifest(manifest = PACK_MANIFEST) {
|
|
340
|
+
const packNames = new Set();
|
|
341
|
+
const destinations = new Map();
|
|
342
|
+
for (const pack of manifest) {
|
|
343
|
+
if (packNames.has(pack.name)) {
|
|
344
|
+
throw new Error(`Duplicate pack name: ${pack.name}`);
|
|
345
|
+
}
|
|
346
|
+
packNames.add(pack.name);
|
|
347
|
+
if (!pack.allowedScopes.includes(pack.defaultScope)) {
|
|
348
|
+
throw new Error(`Pack ${pack.name} default scope ${pack.defaultScope} is not allowed`);
|
|
349
|
+
}
|
|
350
|
+
const assetIds = new Set();
|
|
351
|
+
for (const asset of pack.assets) {
|
|
352
|
+
if (assetIds.has(asset.id)) {
|
|
353
|
+
throw new Error(`Duplicate asset ID in pack ${pack.name}: ${asset.id}`);
|
|
354
|
+
}
|
|
355
|
+
assetIds.add(asset.id);
|
|
356
|
+
validateAsset(pack, asset);
|
|
357
|
+
for (const scope of asset.scopes) {
|
|
358
|
+
const key = `${scope}:${asset.destination}`;
|
|
359
|
+
const entries = destinations.get(key) ?? [];
|
|
360
|
+
entries.push({ pack: pack.name, asset });
|
|
361
|
+
destinations.set(key, entries);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
for (const [destination, entries] of destinations) {
|
|
366
|
+
if (entries.length < 2)
|
|
367
|
+
continue;
|
|
368
|
+
const [first, ...rest] = entries;
|
|
369
|
+
const compatible = first.asset.sharedOwner !== undefined &&
|
|
370
|
+
rest.every(({ asset }) => asset.sharedOwner === first.asset.sharedOwner &&
|
|
371
|
+
asset.source === first.asset.source &&
|
|
372
|
+
asset.kind === first.asset.kind);
|
|
373
|
+
if (!compatible) {
|
|
374
|
+
throw new Error(`Pack assets collide at ${destination} without a compatible shared owner: ${entries.map(({ pack, asset }) => `${pack}/${asset.id}`).join(', ')}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (manifest === PACK_MANIFEST) {
|
|
378
|
+
const missing = PACK_NAMES.filter((name) => !packNames.has(name));
|
|
379
|
+
if (missing.length > 0 || packNames.size !== PACK_NAMES.length) {
|
|
380
|
+
throw new Error(`Pack manifest must cover every PackName exactly once; missing: ${missing.join(', ') || 'none'}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
validatePackManifest();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ConcreteScope } from '../../../shared/types.js';
|
|
2
|
+
import type { PackName } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Path presentation for managed pack diagnostics. `oat status` and `oat doctor`
|
|
5
|
+
* both render the same inventory model, and this is the code that implements
|
|
6
|
+
* the "diagnostics never echo unrelated home content" guarantee, so it lives in
|
|
7
|
+
* one place rather than being duplicated per command.
|
|
8
|
+
*/
|
|
9
|
+
export interface PackPathRoots {
|
|
10
|
+
projectRoot?: string;
|
|
11
|
+
userRoot?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const MAX_REPORTED_PACK_PATHS = 3;
|
|
14
|
+
/**
|
|
15
|
+
* Renders a managed path relative to the scope root that owns it. User-scope
|
|
16
|
+
* paths collapse to `~/...` so diagnostics never echo unrelated home content.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatPackPath(path: string, roots: PackPathRoots): string;
|
|
19
|
+
export declare function formatPackPaths(paths: string[], roots: PackPathRoots): string;
|
|
20
|
+
export declare function updatePackRecovery(pack: PackName, scope: ConcreteScope): string;
|
|
21
|
+
//# sourceMappingURL=pack-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-paths.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-paths.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAgBzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAQ7E;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,aAAa,GACnB,MAAM,CAER"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { normalizeToPosixPath } from '../../../fs/paths.js';
|
|
3
|
+
export const MAX_REPORTED_PACK_PATHS = 3;
|
|
4
|
+
/**
|
|
5
|
+
* Renders a managed path relative to the scope root that owns it. User-scope
|
|
6
|
+
* paths collapse to `~/...` so diagnostics never echo unrelated home content.
|
|
7
|
+
*/
|
|
8
|
+
export function formatPackPath(path, roots) {
|
|
9
|
+
const normalized = normalizeToPosixPath(path);
|
|
10
|
+
for (const [root, prefix] of [
|
|
11
|
+
[roots.projectRoot, ''],
|
|
12
|
+
[roots.userRoot, '~/'],
|
|
13
|
+
]) {
|
|
14
|
+
if (!root)
|
|
15
|
+
continue;
|
|
16
|
+
const normalizedRoot = normalizeToPosixPath(root);
|
|
17
|
+
if (normalized === normalizedRoot ||
|
|
18
|
+
normalized.startsWith(`${normalizedRoot}/`)) {
|
|
19
|
+
return `${prefix}${normalizeToPosixPath(relative(root, path))}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
}
|
|
24
|
+
export function formatPackPaths(paths, roots) {
|
|
25
|
+
const shown = paths
|
|
26
|
+
.slice(0, MAX_REPORTED_PACK_PATHS)
|
|
27
|
+
.map((path) => formatPackPath(path, roots));
|
|
28
|
+
const remaining = paths.length - shown.length;
|
|
29
|
+
return remaining > 0
|
|
30
|
+
? `${shown.join(', ')}, +${remaining} more`
|
|
31
|
+
: shown.join(', ');
|
|
32
|
+
}
|
|
33
|
+
export function updatePackRecovery(pack, scope) {
|
|
34
|
+
return `oat tools update --pack ${pack} --scope ${scope}`;
|
|
35
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ConcreteScope } from '../../../shared/types.js';
|
|
2
|
+
import type { ScopedPackInventory } from './pack-inventory.js';
|
|
3
|
+
import type { PackAssetGeneration, PackCompleteness, PackName } from './types.js';
|
|
4
|
+
export type PackReconcileAction = 'install' | 'update' | 'remove' | 'migrate-destination';
|
|
5
|
+
export type PackReconcileOperation = {
|
|
6
|
+
kind: 'copy-dir' | 'copy-file';
|
|
7
|
+
assetId: string;
|
|
8
|
+
source: string;
|
|
9
|
+
destination: string;
|
|
10
|
+
force: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'write-generated';
|
|
13
|
+
assetId: string;
|
|
14
|
+
generation: PackAssetGeneration;
|
|
15
|
+
destination: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'chmod';
|
|
18
|
+
assetId: string;
|
|
19
|
+
path: string;
|
|
20
|
+
mode: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'remove-dir' | 'remove-file';
|
|
23
|
+
assetId: string;
|
|
24
|
+
path: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'write-intent';
|
|
27
|
+
pack: PackName;
|
|
28
|
+
scope: ConcreteScope;
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
};
|
|
31
|
+
export interface PackReconcilePlan {
|
|
32
|
+
pack: PackName;
|
|
33
|
+
scope: ConcreteScope;
|
|
34
|
+
action: PackReconcileAction;
|
|
35
|
+
operations: readonly PackReconcileOperation[];
|
|
36
|
+
expectedCompleteness: PackCompleteness;
|
|
37
|
+
changedCanonicalPaths: readonly string[];
|
|
38
|
+
retainedAssets: readonly PackSharedOwnerRetention[];
|
|
39
|
+
}
|
|
40
|
+
export interface PackSharedOwnerRetention {
|
|
41
|
+
assetId: string;
|
|
42
|
+
path: string;
|
|
43
|
+
retainedBy: readonly PackName[];
|
|
44
|
+
reason: 'retained-shared-owner';
|
|
45
|
+
}
|
|
46
|
+
export interface PlanPackReconcileInput {
|
|
47
|
+
pack: PackName;
|
|
48
|
+
scope: ConcreteScope;
|
|
49
|
+
scopeRoot: string;
|
|
50
|
+
assetsRoot: string;
|
|
51
|
+
action: PackReconcileAction;
|
|
52
|
+
inventory: ScopedPackInventory;
|
|
53
|
+
retainedAssets?: readonly PackSharedOwnerRetention[];
|
|
54
|
+
}
|
|
55
|
+
export interface ResolveSharedOwnerRetentionsInput {
|
|
56
|
+
packs: readonly PackName[];
|
|
57
|
+
scope: ConcreteScope;
|
|
58
|
+
scopeRoot: string;
|
|
59
|
+
hasOwnershipEvidence: (pack: PackName, scope: ConcreteScope, scopeRoot: string) => Promise<boolean>;
|
|
60
|
+
}
|
|
61
|
+
export declare function resolveSharedOwnerRetentions(input: ResolveSharedOwnerRetentionsInput): Promise<PackSharedOwnerRetention[]>;
|
|
62
|
+
export declare function planPackReconcile(input: PlanPackReconcileInput): PackReconcilePlan;
|
|
63
|
+
export declare function serializePackReconcilePlan(plan: PackReconcilePlan): string;
|
|
64
|
+
//# sourceMappingURL=pack-reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-reconcile.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,KAAK,EAEV,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,qBAAqB,CAAC;AAE1B,MAAM,MAAM,sBAAsB,GAC9B;IACE,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,mBAAmB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrE;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEN,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,oBAAoB,EAAE,gBAAgB,CAAC;IACvC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,cAAc,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IAChC,MAAM,EAAE,uBAAuB,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,CACpB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAmDrC;AA6ED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,CA4EnB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAE1E"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { getPackDefinition, PACK_MANIFEST } from './pack-manifest.js';
|
|
3
|
+
export async function resolveSharedOwnerRetentions(input) {
|
|
4
|
+
const selected = new Set(input.packs);
|
|
5
|
+
const retentions = [];
|
|
6
|
+
const seen = new Set();
|
|
7
|
+
for (const definition of PACK_MANIFEST.filter(({ name }) => selected.has(name))) {
|
|
8
|
+
for (const asset of definition.assets) {
|
|
9
|
+
if (!asset.sharedOwner ||
|
|
10
|
+
!asset.scopes.includes(input.scope) ||
|
|
11
|
+
asset.ownership[input.scope] !== 'managed' ||
|
|
12
|
+
seen.has(asset.destination)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const otherOwners = PACK_MANIFEST.filter(({ name, assets }) => !selected.has(name) &&
|
|
16
|
+
assets.some((candidate) => candidate.sharedOwner === asset.sharedOwner &&
|
|
17
|
+
candidate.destination === asset.destination &&
|
|
18
|
+
candidate.scopes.includes(input.scope) &&
|
|
19
|
+
candidate.ownership[input.scope] === 'managed'));
|
|
20
|
+
const evidence = await Promise.all(otherOwners.map(async ({ name }) => ({
|
|
21
|
+
name,
|
|
22
|
+
retained: await input.hasOwnershipEvidence(name, input.scope, input.scopeRoot),
|
|
23
|
+
})));
|
|
24
|
+
const retainedBy = evidence
|
|
25
|
+
.filter(({ retained }) => retained)
|
|
26
|
+
.map(({ name }) => name);
|
|
27
|
+
if (retainedBy.length === 0)
|
|
28
|
+
continue;
|
|
29
|
+
seen.add(asset.destination);
|
|
30
|
+
retentions.push({
|
|
31
|
+
assetId: asset.id,
|
|
32
|
+
path: join(input.scopeRoot, asset.destination),
|
|
33
|
+
retainedBy,
|
|
34
|
+
reason: 'retained-shared-owner',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return retentions;
|
|
39
|
+
}
|
|
40
|
+
function isDirectoryAsset(asset) {
|
|
41
|
+
return asset.kind === 'skill' || asset.kind === 'directory';
|
|
42
|
+
}
|
|
43
|
+
function canonicalPath(asset) {
|
|
44
|
+
return asset.kind === 'skill' || asset.kind === 'agent'
|
|
45
|
+
? asset.destination
|
|
46
|
+
: null;
|
|
47
|
+
}
|
|
48
|
+
function materializationOperations(asset, input) {
|
|
49
|
+
const observed = input.inventory.assets.find(({ definition }) => definition.id === asset.id);
|
|
50
|
+
const ownership = asset.ownership[input.scope];
|
|
51
|
+
const isMissing = observed?.status === 'missing';
|
|
52
|
+
if (ownership === 'seed-if-missing' && !isMissing)
|
|
53
|
+
return [];
|
|
54
|
+
if (ownership === 'managed' && observed?.status === 'current')
|
|
55
|
+
return [];
|
|
56
|
+
const destination = join(input.scopeRoot, asset.destination);
|
|
57
|
+
if (asset.generation) {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
kind: 'write-generated',
|
|
61
|
+
assetId: asset.id,
|
|
62
|
+
generation: asset.generation,
|
|
63
|
+
destination,
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
if (!asset.source) {
|
|
68
|
+
throw new Error(`Pack asset ${asset.id} has no source or generation`);
|
|
69
|
+
}
|
|
70
|
+
const operations = [
|
|
71
|
+
{
|
|
72
|
+
kind: isDirectoryAsset(asset) ? 'copy-dir' : 'copy-file',
|
|
73
|
+
assetId: asset.id,
|
|
74
|
+
source: join(input.assetsRoot, asset.source),
|
|
75
|
+
destination,
|
|
76
|
+
force: ownership === 'managed',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
if (asset.executable) {
|
|
80
|
+
operations.push({
|
|
81
|
+
kind: 'chmod',
|
|
82
|
+
assetId: asset.id,
|
|
83
|
+
path: destination,
|
|
84
|
+
mode: 0o755,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return operations;
|
|
88
|
+
}
|
|
89
|
+
function removalOperation(asset, input) {
|
|
90
|
+
if (asset.ownership[input.scope] !== 'managed')
|
|
91
|
+
return null;
|
|
92
|
+
if (input.retainedAssets?.some(({ assetId }) => assetId === asset.id)) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const observed = input.inventory.assets.find(({ definition }) => definition.id === asset.id);
|
|
96
|
+
if (!observed || observed.status === 'missing')
|
|
97
|
+
return null;
|
|
98
|
+
return {
|
|
99
|
+
kind: isDirectoryAsset(asset) ? 'remove-dir' : 'remove-file',
|
|
100
|
+
assetId: asset.id,
|
|
101
|
+
path: join(input.scopeRoot, asset.destination),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function planPackReconcile(input) {
|
|
105
|
+
if (input.inventory.pack !== input.pack ||
|
|
106
|
+
input.inventory.scope !== input.scope) {
|
|
107
|
+
throw new Error('Pack reconcile inventory does not match requested pack and scope');
|
|
108
|
+
}
|
|
109
|
+
const packDefinition = getPackDefinition(input.pack);
|
|
110
|
+
if (!packDefinition.allowedScopes.includes(input.scope)) {
|
|
111
|
+
throw new Error(`Pack ${input.pack} does not allow ${input.scope} scope`);
|
|
112
|
+
}
|
|
113
|
+
const applicableAssets = packDefinition.assets.filter(({ scopes }) => scopes.includes(input.scope));
|
|
114
|
+
const changedCanonicalPaths = [];
|
|
115
|
+
const operations = [];
|
|
116
|
+
const retainedAssets = input.retainedAssets ?? [];
|
|
117
|
+
for (const asset of applicableAssets) {
|
|
118
|
+
const assetOperations = input.action === 'remove'
|
|
119
|
+
? [removalOperation(asset, input)].filter((operation) => operation !== null)
|
|
120
|
+
: materializationOperations(asset, input);
|
|
121
|
+
operations.push(...assetOperations);
|
|
122
|
+
if (assetOperations.length > 0) {
|
|
123
|
+
const path = canonicalPath(asset);
|
|
124
|
+
if (path)
|
|
125
|
+
changedCanonicalPaths.push(path);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const desiredIntent = input.action !== 'remove';
|
|
129
|
+
if (input.inventory.intent.enabled !== desiredIntent ||
|
|
130
|
+
(desiredIntent && input.inventory.intent.source !== 'declared')) {
|
|
131
|
+
operations.push({
|
|
132
|
+
kind: 'write-intent',
|
|
133
|
+
pack: input.pack,
|
|
134
|
+
scope: input.scope,
|
|
135
|
+
enabled: desiredIntent,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const managedAssets = applicableAssets.filter((asset) => asset.ownership[input.scope] === 'managed');
|
|
139
|
+
const retainedPresent = managedAssets.filter((asset) => retainedAssets.some(({ assetId }) => assetId === asset.id) &&
|
|
140
|
+
input.inventory.assets.some(({ definition, status }) => definition.id === asset.id && status !== 'missing')).length;
|
|
141
|
+
const expectedRemovalCompleteness = retainedPresent === 0
|
|
142
|
+
? 'absent'
|
|
143
|
+
: retainedPresent === managedAssets.length
|
|
144
|
+
? 'complete'
|
|
145
|
+
: 'partial';
|
|
146
|
+
return {
|
|
147
|
+
pack: input.pack,
|
|
148
|
+
scope: input.scope,
|
|
149
|
+
action: input.action,
|
|
150
|
+
operations,
|
|
151
|
+
expectedCompleteness: input.action === 'remove' ? expectedRemovalCompleteness : 'complete',
|
|
152
|
+
changedCanonicalPaths: [...new Set(changedCanonicalPaths)],
|
|
153
|
+
retainedAssets,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
export function serializePackReconcilePlan(plan) {
|
|
157
|
+
return JSON.stringify(plan, null, 2);
|
|
158
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tools-config.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/project-tools-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"project-tools-config.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/project-tools-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AASD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,4BAA4B,EACrC,YAAY,GAAE,8BAAoD,GACjE,OAAO,CAAC,SAAS,GAAG,WAAW,CAAC,CA2BlC"}
|