@open-agent-toolkit/cli 0.2.36 → 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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { buildCommandContext } from '../../app/command-context.js';
|
|
3
|
+
import { resolvePjmAdoption } from '../pjm/adoption.js';
|
|
3
4
|
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
5
|
+
import { CliError } from '../../errors/index.js';
|
|
4
6
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
5
7
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
6
8
|
import { Command } from 'commander';
|
|
@@ -13,6 +15,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
13
15
|
buildCommandContext,
|
|
14
16
|
resolveProjectRoot,
|
|
15
17
|
resolveAssetsRoot,
|
|
18
|
+
resolvePjmAdoption,
|
|
16
19
|
initializeDecisionAgentsGuidance,
|
|
17
20
|
initializeDecisionRecords,
|
|
18
21
|
regenerateDecisionIndex,
|
|
@@ -41,6 +44,18 @@ function reportError(context, error) {
|
|
|
41
44
|
}
|
|
42
45
|
process.exitCode = 1;
|
|
43
46
|
}
|
|
47
|
+
async function requireRepositoryPjm(context, dependencies) {
|
|
48
|
+
const projectRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
49
|
+
const repoRoot = resolve(projectRoot, '.oat', 'repo');
|
|
50
|
+
const adoption = await dependencies.resolvePjmAdoption({
|
|
51
|
+
projectRoot,
|
|
52
|
+
repoRoot,
|
|
53
|
+
});
|
|
54
|
+
if (adoption.state !== 'declared' && adoption.state !== 'inferred-legacy') {
|
|
55
|
+
throw new CliError(`PJM is not initialized for repository ${repoRoot}. Run \`oat pjm init\` before writing PJM state.`, 1);
|
|
56
|
+
}
|
|
57
|
+
return projectRoot;
|
|
58
|
+
}
|
|
44
59
|
export function createDecisionCommand(overrides = {}) {
|
|
45
60
|
const dependencies = {
|
|
46
61
|
...DEFAULT_DEPENDENCIES,
|
|
@@ -54,7 +69,7 @@ export function createDecisionCommand(overrides = {}) {
|
|
|
54
69
|
.action(async (options, command) => {
|
|
55
70
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
56
71
|
try {
|
|
57
|
-
const projectRoot = await
|
|
72
|
+
const projectRoot = await requireRepositoryPjm(context, dependencies);
|
|
58
73
|
const decisionsRoot = await resolveDecisionsRoot(context, projectRoot, options.decisionsRoot);
|
|
59
74
|
const result = await dependencies.initializeDecisionRecords(decisionsRoot);
|
|
60
75
|
let guidance;
|
|
@@ -94,7 +109,7 @@ export function createDecisionCommand(overrides = {}) {
|
|
|
94
109
|
.action(async (options, command) => {
|
|
95
110
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
96
111
|
try {
|
|
97
|
-
const projectRoot = await
|
|
112
|
+
const projectRoot = await requireRepositoryPjm(context, dependencies);
|
|
98
113
|
const decisionsRoot = await resolveDecisionsRoot(context, projectRoot, options.decisionsRoot);
|
|
99
114
|
await dependencies.regenerateDecisionIndex(decisionsRoot);
|
|
100
115
|
if (context.json) {
|
|
@@ -122,13 +137,14 @@ export function createDecisionCommand(overrides = {}) {
|
|
|
122
137
|
.action(async (title, options, command) => {
|
|
123
138
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
124
139
|
try {
|
|
125
|
-
const projectRoot = await
|
|
140
|
+
const projectRoot = await requireRepositoryPjm(context, dependencies);
|
|
126
141
|
const decisionsRoot = await resolveDecisionsRoot(context, projectRoot, options.decisionsRoot);
|
|
127
142
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
128
143
|
const result = await dependencies.createDecisionRecord({
|
|
129
144
|
decisionsRoot,
|
|
130
145
|
assetsRoot,
|
|
131
146
|
templatesRoot: resolve(projectRoot, '.oat', 'templates'),
|
|
147
|
+
home: context.home,
|
|
132
148
|
title,
|
|
133
149
|
status: options.status,
|
|
134
150
|
context: options.context,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type PjmTemplateTier } from '../pjm/template-source.js';
|
|
1
2
|
export interface CreateDecisionRecordOptions {
|
|
2
3
|
decisionsRoot: string;
|
|
3
4
|
assetsRoot: string;
|
|
4
5
|
templatesRoot?: string;
|
|
6
|
+
home?: string;
|
|
5
7
|
title: string;
|
|
6
8
|
status?: string;
|
|
7
9
|
context?: string;
|
|
@@ -13,6 +15,8 @@ export interface CreateDecisionRecordResult {
|
|
|
13
15
|
id: string;
|
|
14
16
|
decisionsRoot: string;
|
|
15
17
|
filePath: string;
|
|
18
|
+
templatePath: string;
|
|
19
|
+
templateTier: PjmTemplateTier;
|
|
16
20
|
}
|
|
17
21
|
export declare function createDecisionRecord(options: CreateDecisionRecordOptions): Promise<CreateDecisionRecordResult>;
|
|
18
22
|
//# sourceMappingURL=new.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/decision/new.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/decision/new.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AAUvC,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,eAAe,CAAC;CAC/B;AAkFD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CAoDrC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { access, mkdir,
|
|
1
|
+
import { access, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
|
+
import { resolvePjmTemplate, } from '../pjm/template-source.js';
|
|
3
4
|
import { stripTemplateFrontmatter } from '../shared/strip-template-frontmatter.js';
|
|
4
5
|
import YAML from 'yaml';
|
|
5
6
|
import { assertDecisionIndexScaffold, regenerateDecisionIndex, } from './regenerate-index.js';
|
|
@@ -19,33 +20,6 @@ async function pathExists(path) {
|
|
|
19
20
|
return false;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
|
-
async function readIfExists(path) {
|
|
23
|
-
try {
|
|
24
|
-
return await readFile(path, 'utf8');
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
const code = error && typeof error === 'object' && 'code' in error
|
|
28
|
-
? String(error.code)
|
|
29
|
-
: null;
|
|
30
|
-
if (code !== 'ENOENT') {
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async function resolveDecisionTemplate(assetsRoot, templatesRoot) {
|
|
37
|
-
if (templatesRoot) {
|
|
38
|
-
const localTemplate = await readIfExists(join(templatesRoot, 'decision.md'));
|
|
39
|
-
if (localTemplate !== null) {
|
|
40
|
-
return localTemplate;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const bundledTemplate = await readIfExists(join(assetsRoot, 'templates', 'decision.md'));
|
|
44
|
-
if (bundledTemplate !== null) {
|
|
45
|
-
return bundledTemplate;
|
|
46
|
-
}
|
|
47
|
-
throw new Error('Template decision.md was not found in repo-local templates or bundled assets.');
|
|
48
|
-
}
|
|
49
23
|
function normalizeCreatedAt(createdAt) {
|
|
50
24
|
const date = new Date(createdAt);
|
|
51
25
|
if (Number.isNaN(date.getTime())) {
|
|
@@ -88,8 +62,13 @@ export async function createDecisionRecord(options) {
|
|
|
88
62
|
if (await pathExists(filePath)) {
|
|
89
63
|
throw new Error(`Decision record ${id} already exists. Use a more specific title to disambiguate.`);
|
|
90
64
|
}
|
|
91
|
-
const template = await
|
|
92
|
-
|
|
65
|
+
const template = await resolvePjmTemplate({
|
|
66
|
+
name: 'decision.md',
|
|
67
|
+
assetsRoot: options.assetsRoot,
|
|
68
|
+
templatesRoot: options.templatesRoot,
|
|
69
|
+
home: options.home,
|
|
70
|
+
});
|
|
71
|
+
const content = renderDecisionRecord(template.content, {
|
|
93
72
|
id,
|
|
94
73
|
title: options.title,
|
|
95
74
|
date: createdAt.date,
|
|
@@ -116,5 +95,7 @@ export async function createDecisionRecord(options) {
|
|
|
116
95
|
id,
|
|
117
96
|
decisionsRoot: options.decisionsRoot,
|
|
118
97
|
filePath,
|
|
98
|
+
templatePath: template.path,
|
|
99
|
+
templateTier: template.tier,
|
|
119
100
|
};
|
|
120
101
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
|
+
import { type PjmAdoption, type ResolvePjmAdoptionOptions } from '../pjm/adoption.js';
|
|
2
3
|
import { type PjmDoctorOptions } from '../pjm/doctor.js';
|
|
4
|
+
import { type InventoryPackInput, type PackInventory } from '../tools/shared/pack-inventory.js';
|
|
3
5
|
import { type OatConfig, type OatLocalConfig, type UserConfig } from '../../config/oat-config.js';
|
|
4
6
|
import { type Manifest } from '../../manifest/index.js';
|
|
5
7
|
import { type CursorMaterializedModelDiagnostic, type MatrixCellAvailabilityResponse, type ValidateMatrixCellOptions } from '../../providers/identity/availability.js';
|
|
@@ -29,6 +31,8 @@ interface DoctorDependencies {
|
|
|
29
31
|
validateDispatchMatrixRefs: typeof validateDispatchMatrixRefs;
|
|
30
32
|
processEnv: NodeJS.ProcessEnv;
|
|
31
33
|
runPjmDoctorChecks: (repoRoot: string, options?: PjmDoctorOptions) => Promise<DoctorCheck[]>;
|
|
34
|
+
resolvePjmAdoption: (options: ResolvePjmAdoptionOptions) => Promise<PjmAdoption>;
|
|
35
|
+
inventoryPack: (input: InventoryPackInput) => Promise<PackInventory>;
|
|
32
36
|
checkSkillVersions: (scopeRoot: string, assetsRoot: string, pathExists: (path: string) => Promise<boolean>) => Promise<SkillVersionReport>;
|
|
33
37
|
checkStaleInvocations: (repoRoot: string) => Promise<DoctorCheck>;
|
|
34
38
|
}
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,10 +3,14 @@ import { tmpdir } from 'node:os';
|
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
5
5
|
import { compareVersions } from '../init/tools/shared/version.js';
|
|
6
|
-
import {
|
|
6
|
+
import { resolvePjmAdoption, } from '../pjm/adoption.js';
|
|
7
|
+
import { runPjmDoctorChecks, } from '../pjm/doctor.js';
|
|
7
8
|
import { getSkillVersion } from '../shared/frontmatter.js';
|
|
8
9
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
9
10
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
11
|
+
import { hasScopedPackPlacementEvidence, inventoryPack, } from '../tools/shared/pack-inventory.js';
|
|
12
|
+
import { PACK_NAMES } from '../tools/shared/pack-manifest.js';
|
|
13
|
+
import { formatPackPaths, updatePackRecovery, } from '../tools/shared/pack-paths.js';
|
|
10
14
|
import { walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
|
|
11
15
|
import { readOatConfig, readOatLocalConfig, readUserConfig, } from '../../config/oat-config.js';
|
|
12
16
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
@@ -143,6 +147,8 @@ function createDependencies() {
|
|
|
143
147
|
validateDispatchMatrixRefs,
|
|
144
148
|
processEnv: process.env,
|
|
145
149
|
runPjmDoctorChecks,
|
|
150
|
+
resolvePjmAdoption,
|
|
151
|
+
inventoryPack,
|
|
146
152
|
// Default binding remains self-contained, but still honors the caller-
|
|
147
153
|
// provided pathExists dependency from runChecksForScope when available.
|
|
148
154
|
checkSkillVersions: (scopeRoot, assetsRoot, pathExists = pathExistsDefault) => checkSkillVersionsDefault(scopeRoot, assetsRoot, pathExists),
|
|
@@ -462,6 +468,219 @@ async function runCodexChecksForScope(scope, scopeRoot, userHome, dependencies)
|
|
|
462
468
|
});
|
|
463
469
|
return checks;
|
|
464
470
|
}
|
|
471
|
+
function collectPackStateFindings(inventories) {
|
|
472
|
+
const findings = [];
|
|
473
|
+
for (const inventory of inventories) {
|
|
474
|
+
for (const scoped of inventory.scopes) {
|
|
475
|
+
const { scope } = scoped;
|
|
476
|
+
if (!hasScopedPackPlacementEvidence(scoped)) {
|
|
477
|
+
const sharedPresent = scoped.assets.filter((asset) => asset.definition.sharedOwner !== undefined &&
|
|
478
|
+
asset.status !== 'missing');
|
|
479
|
+
if (sharedPresent.length > 0) {
|
|
480
|
+
findings.push({
|
|
481
|
+
pack: inventory.pack,
|
|
482
|
+
scope,
|
|
483
|
+
code: 'shared-owner-observation',
|
|
484
|
+
detail: 'shared managed assets are present without pack ownership evidence',
|
|
485
|
+
paths: sharedPresent.map(({ path }) => path),
|
|
486
|
+
recovery: null,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
const managed = scoped.assets.filter((asset) => asset.definition.ownership[scope] === 'managed');
|
|
492
|
+
if (scoped.completeness !== 'complete') {
|
|
493
|
+
const missing = managed.filter(({ status }) => status === 'missing');
|
|
494
|
+
findings.push({
|
|
495
|
+
pack: inventory.pack,
|
|
496
|
+
scope,
|
|
497
|
+
code: 'partial',
|
|
498
|
+
detail: scoped.completeness === 'absent'
|
|
499
|
+
? 'declared intent with no installed managed assets'
|
|
500
|
+
: `missing ${missing.length} of ${managed.length} managed asset(s)`,
|
|
501
|
+
paths: missing.map(({ path }) => path),
|
|
502
|
+
recovery: updatePackRecovery(inventory.pack, scope),
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
const stale = scoped.assets.filter(({ status }) => status === 'outdated');
|
|
506
|
+
if (stale.length > 0) {
|
|
507
|
+
findings.push({
|
|
508
|
+
pack: inventory.pack,
|
|
509
|
+
scope,
|
|
510
|
+
code: 'stale',
|
|
511
|
+
detail: `${stale.length} managed asset(s) behind the bundled release`,
|
|
512
|
+
paths: stale.map(({ path }) => path),
|
|
513
|
+
recovery: updatePackRecovery(inventory.pack, scope),
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
const newer = scoped.assets.filter(({ status }) => status === 'newer');
|
|
517
|
+
if (newer.length > 0) {
|
|
518
|
+
findings.push({
|
|
519
|
+
pack: inventory.pack,
|
|
520
|
+
scope,
|
|
521
|
+
code: 'newer',
|
|
522
|
+
detail: `${newer.length} installed asset(s) are newer than the bundled release`,
|
|
523
|
+
paths: newer.map(({ path }) => path),
|
|
524
|
+
recovery: null,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
const retained = scoped.assets.filter((asset) => asset.definition.ownership[scope] === 'seed-if-missing' &&
|
|
528
|
+
asset.status === 'present');
|
|
529
|
+
if (retained.length > 0) {
|
|
530
|
+
findings.push({
|
|
531
|
+
pack: inventory.pack,
|
|
532
|
+
scope,
|
|
533
|
+
code: 'retained-override',
|
|
534
|
+
detail: `${retained.length} owner-owned override(s) retained; managed defaults are not applied here`,
|
|
535
|
+
paths: retained.map(({ path }) => path),
|
|
536
|
+
recovery: null,
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
for (const diagnostic of scoped.diagnostics) {
|
|
540
|
+
if (diagnostic.code === 'legacy-false-conflict') {
|
|
541
|
+
findings.push({
|
|
542
|
+
pack: inventory.pack,
|
|
543
|
+
scope,
|
|
544
|
+
code: 'legacy-false-conflict',
|
|
545
|
+
detail: 'legacy false intent with installed managed assets; adopt or remove the install',
|
|
546
|
+
paths: diagnostic.paths,
|
|
547
|
+
recovery: updatePackRecovery(inventory.pack, scope),
|
|
548
|
+
});
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
if (diagnostic.code === 'user-agent-unmaterialized') {
|
|
552
|
+
// A documented scope limitation rather than drift: `oat tools update`
|
|
553
|
+
// cannot repair it, so no recovery command is offered and the check
|
|
554
|
+
// stays a pass. The message still names every affected agent so the
|
|
555
|
+
// absent capability is not reported as a complete pack.
|
|
556
|
+
findings.push({
|
|
557
|
+
pack: inventory.pack,
|
|
558
|
+
scope,
|
|
559
|
+
code: 'user-agent-unmaterialized',
|
|
560
|
+
detail: `${diagnostic.paths.length} user-scope agent(s) reach no provider; user-scope agent materialization is limited to the bundled managed role files, so install this pack at project scope to use them`,
|
|
561
|
+
paths: diagnostic.paths,
|
|
562
|
+
recovery: null,
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
for (const diagnostic of inventory.diagnostics) {
|
|
568
|
+
if (diagnostic.code !== 'duplicate-scope')
|
|
569
|
+
continue;
|
|
570
|
+
findings.push({
|
|
571
|
+
pack: inventory.pack,
|
|
572
|
+
scope: null,
|
|
573
|
+
code: 'duplicate-scope',
|
|
574
|
+
detail: 'installed at project and user scope; provider precedence is not inferred',
|
|
575
|
+
paths: diagnostic.paths,
|
|
576
|
+
recovery: `oat tools migrate --pack ${inventory.pack} --from project --to user`,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return findings;
|
|
581
|
+
}
|
|
582
|
+
function formatPackFinding(finding, roots) {
|
|
583
|
+
const paths = formatPackPaths(finding.paths, roots);
|
|
584
|
+
return paths.length > 0
|
|
585
|
+
? `${finding.pack} [${finding.code}]: ${finding.detail} (${paths})`
|
|
586
|
+
: `${finding.pack} [${finding.code}]: ${finding.detail}`;
|
|
587
|
+
}
|
|
588
|
+
function uniqueRecoveries(findings) {
|
|
589
|
+
return [
|
|
590
|
+
...new Set(findings
|
|
591
|
+
.map(({ recovery }) => recovery)
|
|
592
|
+
.filter((recovery) => recovery !== null)),
|
|
593
|
+
];
|
|
594
|
+
}
|
|
595
|
+
function createScopedPackStateCheck(scope, findings, roots) {
|
|
596
|
+
const scoped = findings.filter((finding) => finding.scope === scope);
|
|
597
|
+
if (scoped.length === 0) {
|
|
598
|
+
return {
|
|
599
|
+
name: `${scope}:pack_state`,
|
|
600
|
+
description: 'Managed pack completeness and drift',
|
|
601
|
+
status: 'pass',
|
|
602
|
+
message: 'All installed managed packs are complete and current.',
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
const recoveries = uniqueRecoveries(scoped);
|
|
606
|
+
return {
|
|
607
|
+
name: `${scope}:pack_state`,
|
|
608
|
+
description: 'Managed pack completeness and drift',
|
|
609
|
+
status: recoveries.length > 0 ? 'warn' : 'pass',
|
|
610
|
+
message: scoped
|
|
611
|
+
.map((finding) => formatPackFinding(finding, roots))
|
|
612
|
+
.join('; '),
|
|
613
|
+
fix: recoveries.length > 0 ? recoveries.join('; ') : undefined,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
function createPackDuplicationCheck(findings, roots) {
|
|
617
|
+
const duplicates = findings.filter((finding) => finding.code === 'duplicate-scope');
|
|
618
|
+
if (duplicates.length === 0) {
|
|
619
|
+
return {
|
|
620
|
+
name: 'packs:scope_duplication',
|
|
621
|
+
description: 'Cross-scope pack duplication',
|
|
622
|
+
status: 'pass',
|
|
623
|
+
message: 'No managed pack is installed at both project and user scope.',
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
name: 'packs:scope_duplication',
|
|
628
|
+
description: 'Cross-scope pack duplication',
|
|
629
|
+
status: 'warn',
|
|
630
|
+
message: duplicates
|
|
631
|
+
.map((finding) => formatPackFinding(finding, roots))
|
|
632
|
+
.join('; '),
|
|
633
|
+
fix: uniqueRecoveries(duplicates).join('; '),
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
async function createPackStateChecks(scopeRoots, dependencies) {
|
|
637
|
+
if (scopeRoots.size === 0) {
|
|
638
|
+
return [];
|
|
639
|
+
}
|
|
640
|
+
const roots = {
|
|
641
|
+
...(scopeRoots.has('project')
|
|
642
|
+
? { projectRoot: scopeRoots.get('project') }
|
|
643
|
+
: {}),
|
|
644
|
+
...(scopeRoots.has('user') ? { userRoot: scopeRoots.get('user') } : {}),
|
|
645
|
+
};
|
|
646
|
+
let findings;
|
|
647
|
+
try {
|
|
648
|
+
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
649
|
+
const inventories = await Promise.all(PACK_NAMES.map((pack) => dependencies.inventoryPack({ pack, assetsRoot, ...roots })));
|
|
650
|
+
findings = collectPackStateFindings(inventories);
|
|
651
|
+
}
|
|
652
|
+
catch (error) {
|
|
653
|
+
return [
|
|
654
|
+
{
|
|
655
|
+
name: 'packs:inventory',
|
|
656
|
+
description: 'Managed pack inventory availability',
|
|
657
|
+
status: 'warn',
|
|
658
|
+
message: error instanceof Error
|
|
659
|
+
? `Unable to inventory managed packs: ${error.message}`
|
|
660
|
+
: 'Unable to inventory managed packs.',
|
|
661
|
+
fix: 'Run `pnpm build` and rerun `oat doctor`.',
|
|
662
|
+
},
|
|
663
|
+
];
|
|
664
|
+
}
|
|
665
|
+
const checks = [];
|
|
666
|
+
for (const scope of scopeRoots.keys()) {
|
|
667
|
+
checks.push(createScopedPackStateCheck(scope, findings, roots));
|
|
668
|
+
}
|
|
669
|
+
if (scopeRoots.has('project') && scopeRoots.has('user')) {
|
|
670
|
+
checks.push(createPackDuplicationCheck(findings, roots));
|
|
671
|
+
}
|
|
672
|
+
return checks;
|
|
673
|
+
}
|
|
674
|
+
function createScopeUnavailableCheck(scope, error) {
|
|
675
|
+
const reason = error instanceof Error ? `: ${error.message}` : '.';
|
|
676
|
+
return {
|
|
677
|
+
name: `${scope}:scope_availability`,
|
|
678
|
+
description: `${scope === 'project' ? 'Project' : 'User'} scope availability`,
|
|
679
|
+
status: 'warn',
|
|
680
|
+
message: `${scope === 'project' ? 'Project' : 'User'} scope is unavailable${reason}`,
|
|
681
|
+
fix: `Run \`oat doctor --scope ${scope === 'project' ? 'user' : 'project'}\`, or rerun inside a directory where ${scope} scope resolves.`,
|
|
682
|
+
};
|
|
683
|
+
}
|
|
465
684
|
async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies) {
|
|
466
685
|
const checks = [];
|
|
467
686
|
const skillsPath = join(scopeRoot, '.agents', 'skills');
|
|
@@ -603,25 +822,51 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
603
822
|
{ source: 'repo-config', config },
|
|
604
823
|
{ source: 'local-config', config: localConfig },
|
|
605
824
|
], dependencies));
|
|
606
|
-
|
|
607
|
-
|
|
825
|
+
// PJM capability now normally lives at user scope, so repository pack
|
|
826
|
+
// intent is no longer evidence of repository adoption. Adoption state is
|
|
827
|
+
// authoritative and already covers every case where a PJM canonical file
|
|
828
|
+
// exists (`partial-initialization` is returned whenever any is present), so
|
|
829
|
+
// the presence of `.oat/repo` adds nothing. Keying off it as well would fire
|
|
830
|
+
// only when `.oat/repo` exists with zero PJM canonical files — a repository
|
|
831
|
+
// that uses `.oat/repo` for non-PJM content such as `oat index` knowledge,
|
|
832
|
+
// and deliberately declined PJM. That is a false positive, and it made
|
|
833
|
+
// `oat doctor` disagree with `oat status`'s `shouldReportPjmAdoption`.
|
|
834
|
+
const adoption = await dependencies.resolvePjmAdoption({
|
|
835
|
+
projectRoot: scopeRoot,
|
|
836
|
+
repoRoot: repoReferenceRoot,
|
|
837
|
+
});
|
|
838
|
+
if (adoption.state !== 'none') {
|
|
608
839
|
checks.push(...(await dependencies.runPjmDoctorChecks(repoReferenceRoot, {
|
|
609
|
-
|
|
840
|
+
projectRoot: scopeRoot,
|
|
841
|
+
adoption,
|
|
610
842
|
})));
|
|
611
843
|
}
|
|
612
|
-
else if (await dependencies.pathExists(repoReferenceRoot)) {
|
|
613
|
-
checks.push(createPjmDisabledCheck());
|
|
614
|
-
}
|
|
615
844
|
}
|
|
616
845
|
return checks;
|
|
617
846
|
}
|
|
618
847
|
async function runDoctorCommand(context, dependencies) {
|
|
619
848
|
const checks = [];
|
|
620
|
-
|
|
621
|
-
|
|
849
|
+
const scopes = resolveConcreteScopes(context.scope);
|
|
850
|
+
const scopeRoots = new Map();
|
|
851
|
+
for (const scope of scopes) {
|
|
852
|
+
let scopeRoot;
|
|
853
|
+
try {
|
|
854
|
+
scopeRoot = await dependencies.resolveScopeRoot(scope, context);
|
|
855
|
+
}
|
|
856
|
+
catch (error) {
|
|
857
|
+
// `--scope all` outside a Git repository still completes user-scope
|
|
858
|
+
// diagnostics; an explicitly requested scope stays a hard failure.
|
|
859
|
+
if (scope === 'project' && scopes.includes('user')) {
|
|
860
|
+
checks.push(createScopeUnavailableCheck(scope, error));
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
throw error;
|
|
864
|
+
}
|
|
865
|
+
scopeRoots.set(scope, scopeRoot);
|
|
622
866
|
const scopeChecks = await runChecksForScope(scope, scopeRoot, join(context.home, '.oat'), dependencies);
|
|
623
867
|
checks.push(...scopeChecks);
|
|
624
868
|
}
|
|
869
|
+
checks.push(...(await createPackStateChecks(scopeRoots, dependencies)));
|
|
625
870
|
if (context.json) {
|
|
626
871
|
context.logger.json({ scope: context.scope, checks });
|
|
627
872
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/brainstorm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAM9B,KAAK,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvC,UAAU,+BAA+B;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,iBAAiB,EAAE,CACjB,OAAO,EAAE,wBAAwB,KAC9B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACtC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;CAC/D;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/brainstorm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAM9B,KAAK,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvC,UAAU,+BAA+B;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,iBAAiB,EAAE,CACjB,OAAO,EAAE,wBAAwB,KAC9B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACtC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;CAC/D;AA2KD,wBAAgB,gCAAgC,CAC9C,SAAS,GAAE,OAAO,CAAC,+BAA+B,CAAM,GACvD,OAAO,CA2BT"}
|
|
@@ -31,11 +31,13 @@ async function resolveInstallScope(context, projectRoot, userRoot, assetsRoot, d
|
|
|
31
31
|
// defaultScope is consulted, so re-installing a pack already placed at
|
|
32
32
|
// a particular scope never silently migrates the user across scopes.
|
|
33
33
|
const [projectTools, userTools] = await Promise.all([
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
projectRoot
|
|
35
|
+
? dependencies.scanTools({
|
|
36
|
+
scope: 'project',
|
|
37
|
+
scopeRoot: projectRoot,
|
|
38
|
+
assetsRoot,
|
|
39
|
+
})
|
|
40
|
+
: Promise.resolve([]),
|
|
39
41
|
dependencies.scanTools({
|
|
40
42
|
scope: 'user',
|
|
41
43
|
scopeRoot: userRoot,
|
|
@@ -80,10 +82,22 @@ function reportSuccess(context, scope, targetRoot, assetsRoot, result) {
|
|
|
80
82
|
}
|
|
81
83
|
async function runInitToolsBrainstorm(context, options, dependencies) {
|
|
82
84
|
try {
|
|
83
|
-
|
|
85
|
+
let projectRoot = null;
|
|
86
|
+
if (context.scope !== 'user') {
|
|
87
|
+
try {
|
|
88
|
+
projectRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (context.scope === 'project')
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
84
95
|
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
85
96
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
86
97
|
const { scope } = await resolveInstallScope(context, projectRoot, userRoot, assetsRoot, dependencies);
|
|
98
|
+
if (scope === 'project' && !projectRoot) {
|
|
99
|
+
throw new Error('Project scope is unavailable outside a repository');
|
|
100
|
+
}
|
|
87
101
|
const targetRoot = scope === 'project' ? projectRoot : userRoot;
|
|
88
102
|
if (options.force && context.interactive) {
|
|
89
103
|
const confirmed = await dependencies.confirmAction(`Force overwrite existing brainstorm assets in ${scope} scope?`, { interactive: context.interactive });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/docs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/docs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,iCAAiC,CAAC;AASzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAC;AAMxB,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1E,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,WAAW,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzE,mBAAmB,EAAE,CAAC,CAAC,SAAS,MAAM,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAC/B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACzB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAyID,wBAAgB,0BAA0B,CACxC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAeT"}
|
|
@@ -3,6 +3,7 @@ import { withScopeOption } from '../../../shared/scope-option.js';
|
|
|
3
3
|
import { confirmAction, selectManyWithAbort, } from '../../../shared/shared.prompts.js';
|
|
4
4
|
import { readGlobalOptions } from '../../../shared/shared.utils.js';
|
|
5
5
|
import { canonicalSkillPaths, setInstalledCanonicalPaths, } from '../../../tools/shared/install-sync-context.js';
|
|
6
|
+
import { getPackDefinition } from '../../../tools/shared/pack-manifest.js';
|
|
6
7
|
import { resolveAssetsRoot } from '../../../../fs/assets.js';
|
|
7
8
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../../fs/paths.js';
|
|
8
9
|
import { Command } from 'commander';
|
|
@@ -17,7 +18,9 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
17
18
|
confirmAction,
|
|
18
19
|
};
|
|
19
20
|
function resolveScope(context) {
|
|
20
|
-
return context.scope === '
|
|
21
|
+
return context.scope === 'project' || context.scope === 'user'
|
|
22
|
+
? context.scope
|
|
23
|
+
: getPackDefinition('docs').defaultScope;
|
|
21
24
|
}
|
|
22
25
|
function reportSuccess(context, scope, targetRoot, assetsRoot, selectedSkills, result) {
|
|
23
26
|
if (context.json) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/ideas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/ideas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AASzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAMzB,KAAK,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvC,UAAU,0BAA0B;IAClC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,YAAY,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC5E,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAyGD,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,0BAA0B,CAAM,GAClD,OAAO,CAsBT"}
|
|
@@ -3,6 +3,7 @@ import { withScopeOption } from '../../../shared/scope-option.js';
|
|
|
3
3
|
import { confirmAction, } from '../../../shared/shared.prompts.js';
|
|
4
4
|
import { readGlobalOptions } from '../../../shared/shared.utils.js';
|
|
5
5
|
import { canonicalPathsForPack, setInstalledCanonicalPaths, } from '../../../tools/shared/install-sync-context.js';
|
|
6
|
+
import { getPackDefinition } from '../../../tools/shared/pack-manifest.js';
|
|
6
7
|
import { resolveAssetsRoot } from '../../../../fs/assets.js';
|
|
7
8
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../../fs/paths.js';
|
|
8
9
|
import { Command } from 'commander';
|
|
@@ -16,7 +17,9 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
16
17
|
confirmAction,
|
|
17
18
|
};
|
|
18
19
|
function resolveInstallScope(context) {
|
|
19
|
-
return context.scope === '
|
|
20
|
+
return context.scope === 'project' || context.scope === 'user'
|
|
21
|
+
? context.scope
|
|
22
|
+
: getPackDefinition('ideas').defaultScope;
|
|
20
23
|
}
|
|
21
24
|
function getCountSummary(result) {
|
|
22
25
|
return {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../../app/command-context.js';
|
|
2
2
|
import { type UpsertSectionResult } from '../../shared/agents-md.js';
|
|
3
3
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../../shared/shared.prompts.js';
|
|
4
|
+
import { type InventoryPackInput, type PackInventory } from '../../tools/shared/pack-inventory.js';
|
|
5
|
+
import { type PackLifecycleRequest, type PackLifecycleResult } from '../../tools/shared/pack-lifecycle.js';
|
|
4
6
|
import type { ScanToolsOptions } from '../../tools/shared/scan-tools.js';
|
|
5
7
|
import type { ToolInfo } from '../../tools/shared/types.js';
|
|
6
8
|
import { type OatConfig } from '../../../config/oat-config.js';
|
|
@@ -34,8 +36,10 @@ export interface InitToolsDependencies {
|
|
|
34
36
|
installResearch: (options: InstallResearchOptions) => Promise<InstallResearchResult>;
|
|
35
37
|
installBrainstorm: (options: InstallBrainstormOptions) => Promise<InstallBrainstormResult>;
|
|
36
38
|
copyDirWithStatus: (source: string, destination: string, force: boolean) => Promise<'copied' | 'updated' | 'skipped'>;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
/** @deprecated Phase 2 installs are additive; retained for test-harness compatibility. */
|
|
40
|
+
removeDirectory?: (target: string) => Promise<void>;
|
|
41
|
+
/** @deprecated Phase 2 installs are additive; retained for test-harness compatibility. */
|
|
42
|
+
removeFile?: (target: string) => Promise<void>;
|
|
39
43
|
addLocalPaths: (repoRoot: string, paths: string[]) => Promise<{
|
|
40
44
|
added: string[];
|
|
41
45
|
all: string[];
|
|
@@ -48,9 +52,14 @@ export interface InitToolsDependencies {
|
|
|
48
52
|
resolveLocalPaths: (config: OatConfig) => string[];
|
|
49
53
|
upsertAgentsMdSection: (repoRoot: string, key: string, body: string) => Promise<UpsertSectionResult>;
|
|
50
54
|
removeAgentsMdSection: (repoRoot: string, key: string) => Promise<boolean>;
|
|
55
|
+
reconcilePacks?: (requests: readonly PackLifecycleRequest[], options?: {
|
|
56
|
+
dryRun?: boolean;
|
|
57
|
+
}) => Promise<PackLifecycleResult[]>;
|
|
58
|
+
inventoryPack?: (input: InventoryPackInput) => Promise<PackInventory>;
|
|
51
59
|
}
|
|
52
60
|
interface InitToolsRunMetadata {
|
|
53
61
|
affectedScopes: ConcreteScope[];
|
|
62
|
+
appliedScopes: ConcreteScope[];
|
|
54
63
|
}
|
|
55
64
|
interface PackScopeChange {
|
|
56
65
|
pack: ToolPack;
|