@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.
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/bootstrap.md +6 -2
- package/assets/docs/cli-utilities/tool-packs.md +87 -33
- package/assets/docs/provider-sync/commands.md +30 -2
- package/assets/docs/provider-sync/config.md +19 -0
- package/assets/docs/provider-sync/manifest-and-drift.md +37 -0
- package/assets/docs/provider-sync/providers.md +69 -2
- package/assets/docs/provider-sync/scope-and-surface.md +44 -0
- package/assets/docs/reference/cli-reference.md +21 -5
- package/assets/docs/reference/file-locations.md +8 -2
- package/assets/docs/reference/oat-directory-structure.md +25 -9
- package/assets/docs/workflows/projects/artifacts.md +9 -4
- package/assets/docs/workflows/projects/evidence-layers.md +110 -1
- package/assets/docs/workflows/projects/implementation-execution.md +13 -0
- package/assets/docs/workflows/projects/lifecycle.md +17 -5
- package/assets/docs/workflows/projects/orchestration-model.md +18 -0
- package/assets/docs/workflows/projects/picking-up-projects.md +26 -9
- package/assets/docs/workflows/projects/pr-flow.md +5 -3
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +12 -8
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-dispatch-subagents/SKILL.md +57 -1
- package/assets/skills/oat-dispatch-subagents/references/record-schema.md +77 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +3 -3
- package/assets/skills/oat-project-complete/SKILL.md +193 -26
- package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +306 -0
- package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +125 -0
- package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +106 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +110 -0
- package/assets/skills/oat-project-complete/scripts/resolve-synced-archive-entry.mjs +164 -0
- package/assets/skills/oat-project-dispatch-subagents/SKILL.md +24 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +11 -0
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-plan-writing/SKILL.md +12 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-review-provide/SKILL.md +12 -1
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +12 -1
- package/dist/agents/canonical/index.d.ts +2 -0
- package/dist/agents/canonical/index.d.ts.map +1 -1
- package/dist/agents/canonical/index.js +1 -0
- package/dist/agents/canonical/resolve.d.ts +45 -0
- package/dist/agents/canonical/resolve.d.ts.map +1 -0
- package/dist/agents/canonical/resolve.js +175 -0
- package/dist/commands/decision/agents-guidance.d.ts +2 -2
- package/dist/commands/decision/agents-guidance.d.ts.map +1 -1
- package/dist/commands/decision/agents-guidance.js +1 -4
- package/dist/commands/decision/index.d.ts.map +1 -1
- package/dist/commands/decision/index.js +25 -6
- package/dist/commands/docs/init/index.d.ts +7 -1
- package/dist/commands/docs/init/index.d.ts.map +1 -1
- package/dist/commands/docs/init/index.js +53 -20
- package/dist/commands/doctor/index.d.ts +8 -2
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +157 -46
- package/dist/commands/init/index.d.ts +8 -3
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +64 -26
- package/dist/commands/init/tools/index.d.ts +12 -12
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +430 -99
- 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-guidance.d.ts +49 -0
- package/dist/commands/init/tools/project-guidance.d.ts.map +1 -0
- package/dist/commands/init/tools/project-guidance.js +144 -0
- package/dist/commands/init/tools/workflows/index.d.ts +7 -0
- package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
- package/dist/commands/init/tools/workflows/index.js +160 -7
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +28 -3
- package/dist/commands/pjm/init.d.ts +5 -0
- package/dist/commands/pjm/init.d.ts.map +1 -1
- package/dist/commands/pjm/init.js +19 -3
- package/dist/commands/project/archive/archive-utils.d.ts +8 -1
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +147 -50
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +15 -2
- package/dist/commands/project/dispatch/index.d.ts +10 -0
- package/dist/commands/project/dispatch/index.d.ts.map +1 -0
- package/dist/commands/project/dispatch/index.js +137 -0
- package/dist/commands/project/dispatch/record.d.ts +91 -0
- package/dist/commands/project/dispatch/record.d.ts.map +1 -0
- package/dist/commands/project/dispatch/record.js +402 -0
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/project/links/compute.d.ts +1 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -1
- package/dist/commands/project/links/compute.js +5 -4
- package/dist/commands/project/links/index.d.ts +9 -0
- package/dist/commands/project/links/index.d.ts.map +1 -1
- package/dist/commands/project/links/index.js +71 -2
- package/dist/commands/project/list.d.ts +10 -2
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +205 -29
- package/dist/commands/project/open/index.d.ts +2 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +16 -1
- package/dist/commands/project/prune/index.d.ts +10 -4
- package/dist/commands/project/prune/index.d.ts.map +1 -1
- package/dist/commands/project/prune/index.js +85 -15
- package/dist/commands/project/pull/index.d.ts +4 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -1
- package/dist/commands/project/pull/index.js +82 -3
- package/dist/commands/project/sync/git.d.ts +9 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -1
- package/dist/commands/project/sync/git.js +18 -0
- package/dist/commands/project/sync/ref-sync.d.ts +16 -1
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -1
- package/dist/commands/project/sync/ref-sync.js +288 -17
- package/dist/commands/project/sync/resolve-target.d.ts +10 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -1
- package/dist/commands/project/sync/resolve-target.js +56 -1
- package/dist/commands/providers/inspect/inspect.d.ts +8 -1
- package/dist/commands/providers/inspect/inspect.d.ts.map +1 -1
- package/dist/commands/providers/inspect/inspect.js +146 -26
- package/dist/commands/providers/list/list.d.ts +8 -1
- package/dist/commands/providers/list/list.d.ts.map +1 -1
- package/dist/commands/providers/list/list.js +139 -23
- package/dist/commands/providers/providers.types.d.ts +25 -1
- package/dist/commands/providers/providers.types.d.ts.map +1 -1
- package/dist/commands/providers/set/index.d.ts +9 -1
- package/dist/commands/providers/set/index.d.ts.map +1 -1
- package/dist/commands/providers/set/index.js +43 -33
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +11 -0
- package/dist/commands/shared/agents-md.d.ts +42 -14
- package/dist/commands/shared/agents-md.d.ts.map +1 -1
- package/dist/commands/shared/agents-md.js +364 -70
- package/dist/commands/shared/project-scope.d.ts +2 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -1
- package/dist/commands/shared/project-scope.js +5 -0
- package/dist/commands/state/generate.d.ts +2 -0
- package/dist/commands/state/generate.d.ts.map +1 -1
- package/dist/commands/state/generate.js +93 -28
- package/dist/commands/status/index.d.ts +8 -3
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +147 -32
- package/dist/commands/sync/apply.d.ts.map +1 -1
- package/dist/commands/sync/apply.js +220 -29
- package/dist/commands/sync/dry-run.d.ts.map +1 -1
- package/dist/commands/sync/dry-run.js +30 -6
- package/dist/commands/sync/index.d.ts +17 -2
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +106 -41
- package/dist/commands/sync/sync.types.d.ts +39 -2
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.d.ts +5 -1
- package/dist/commands/sync/sync.utils.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.js +73 -0
- package/dist/commands/tools/info/info-tool.d.ts +2 -0
- package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
- package/dist/commands/tools/info/info-tool.js +34 -12
- package/dist/commands/tools/install/index.d.ts.map +1 -1
- package/dist/commands/tools/install/index.js +19 -3
- package/dist/commands/tools/list/list-tools.d.ts +2 -0
- package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
- package/dist/commands/tools/list/list-tools.js +36 -7
- package/dist/commands/tools/remove/index.d.ts.map +1 -1
- package/dist/commands/tools/remove/index.js +150 -21
- package/dist/commands/tools/remove/remove-tools.d.ts +20 -0
- package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
- package/dist/commands/tools/remove/remove-tools.js +122 -1
- package/dist/commands/tools/shared/format-pack-inventory.d.ts +19 -0
- package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/format-pack-inventory.js +109 -0
- package/dist/commands/tools/shared/pack-evidence.d.ts +66 -0
- package/dist/commands/tools/shared/pack-evidence.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-evidence.js +132 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts +1 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts +44 -0
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-lifecycle-outcome.js +91 -0
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +74 -4
- package/dist/commands/tools/update/update-tools.d.ts +5 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/commands/tools/update/update-tools.js +64 -2
- package/dist/config/oat-config.d.ts +5 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +17 -5
- package/dist/config/user-sync-config.d.ts +1 -0
- package/dist/config/user-sync-config.d.ts.map +1 -1
- package/dist/config/user-sync-config.js +8 -0
- package/dist/drift/detector.d.ts +2 -2
- package/dist/drift/detector.d.ts.map +1 -1
- package/dist/drift/detector.js +18 -0
- package/dist/drift/strays.d.ts.map +1 -1
- package/dist/drift/strays.js +5 -0
- package/dist/engine/collection-sync.d.ts +14 -0
- package/dist/engine/collection-sync.d.ts.map +1 -0
- package/dist/engine/collection-sync.js +282 -0
- package/dist/engine/compute-plan.d.ts +8 -1
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +303 -12
- package/dist/engine/engine.types.d.ts +61 -0
- package/dist/engine/engine.types.d.ts.map +1 -1
- package/dist/engine/execute-plan.d.ts +22 -2
- package/dist/engine/execute-plan.d.ts.map +1 -1
- package/dist/engine/execute-plan.js +459 -27
- package/dist/engine/provider-path-safety.d.ts +1 -0
- package/dist/engine/provider-path-safety.d.ts.map +1 -1
- package/dist/engine/provider-path-safety.js +15 -0
- package/dist/engine/scanner.d.ts +2 -2
- package/dist/engine/scanner.d.ts.map +1 -1
- package/dist/engine/scanner.js +21 -4
- package/dist/fs/io.d.ts +67 -0
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +536 -3
- package/dist/manifest/index.d.ts +2 -2
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +1 -1
- package/dist/manifest/manager.d.ts +2 -2
- package/dist/manifest/manager.d.ts.map +1 -1
- package/dist/manifest/manager.js +20 -3
- package/dist/manifest/manifest.types.d.ts +704 -13
- package/dist/manifest/manifest.types.d.ts.map +1 -1
- package/dist/manifest/manifest.types.js +131 -15
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +41 -10
- package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/cursor/codec/sync-extension.js +41 -10
- package/dist/providers/identity/absolute-paths.d.ts +68 -0
- package/dist/providers/identity/absolute-paths.d.ts.map +1 -0
- package/dist/providers/identity/absolute-paths.js +144 -0
- package/dist/providers/identity/claude-runtime-observation.d.ts +105 -0
- package/dist/providers/identity/claude-runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts +40 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts.map +1 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.js +146 -0
- package/dist/providers/identity/claude-runtime-observation.js +229 -0
- package/dist/providers/identity/codex-runtime-observation.d.ts +75 -0
- package/dist/providers/identity/codex-runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts +37 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts.map +1 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.js +539 -0
- package/dist/providers/identity/codex-runtime-observation.js +255 -0
- package/dist/providers/identity/generic-dispatch-record.d.ts +313 -0
- package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -0
- package/dist/providers/identity/generic-dispatch-record.js +539 -0
- package/dist/providers/identity/oat-dispatch-record.d.ts +1964 -0
- package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -0
- package/dist/providers/identity/oat-dispatch-record.js +691 -0
- package/dist/providers/identity/runtime-observation.d.ts +100 -0
- package/dist/providers/identity/runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/runtime-observation.js +169 -0
- package/dist/providers/shared/index.d.ts +2 -0
- package/dist/providers/shared/index.d.ts.map +1 -1
- package/dist/providers/shared/index.js +1 -0
- package/dist/providers/shared/materialization-extension.d.ts +12 -0
- package/dist/providers/shared/materialization-extension.d.ts.map +1 -1
- package/dist/providers/shared/registry.d.ts +69 -0
- package/dist/providers/shared/registry.d.ts.map +1 -0
- package/dist/providers/shared/registry.js +252 -0
- package/dist/providers/shared/restart-adviser.d.ts +26 -0
- package/dist/providers/shared/restart-adviser.d.ts.map +1 -0
- package/dist/providers/shared/restart-adviser.js +96 -0
- package/dist/shared/types.d.ts +4 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -3,19 +3,22 @@ import { buildCommandContext, } from '../../../app/command-context.js';
|
|
|
3
3
|
import { copyDirWithStatus } from '../../init/tools/shared/copy-helpers.js';
|
|
4
4
|
import { applyGitignore } from '../../local/apply.js';
|
|
5
5
|
import { addLocalPaths } from '../../local/manage.js';
|
|
6
|
-
import {
|
|
6
|
+
import { formatAgentsMdGuidanceResult, formatAgentsMdMutationFailure, upsertAgentsMdSection, } from '../../shared/agents-md.js';
|
|
7
7
|
import { withScopeOption } from '../../shared/scope-option.js';
|
|
8
|
-
import { selectManyWithAbort, selectWithAbort, } from '../../shared/shared.prompts.js';
|
|
8
|
+
import { confirmAction, selectManyWithAbort, selectWithAbort, } from '../../shared/shared.prompts.js';
|
|
9
9
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
10
10
|
import { canonicalPathsForPacks, getInstalledCanonicalPaths, setInstalledCanonicalPaths, } from '../../tools/shared/install-sync-context.js';
|
|
11
|
+
import { packScopeFactsFromInventory, projectPackEvidence, } from '../../tools/shared/pack-evidence.js';
|
|
11
12
|
import { inventoryPack, } from '../../tools/shared/pack-inventory.js';
|
|
12
13
|
import { reconcilePackLifecycles, } from '../../tools/shared/pack-lifecycle.js';
|
|
14
|
+
import { evaluatePackLifecycleOutcome, resolveAdditivePackScopeSelection, } from '../../tools/shared/pack-lifecycle-outcome.js';
|
|
13
15
|
import { getPackDefinition } from '../../tools/shared/pack-manifest.js';
|
|
14
16
|
import { reconcileProjectToolsConfig } from '../../tools/shared/project-tools-config.js';
|
|
15
17
|
import { scanTools } from '../../tools/shared/scan-tools.js';
|
|
16
18
|
import { readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../../config/oat-config.js';
|
|
17
19
|
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
18
20
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
21
|
+
import { adviseProviderRefresh, } from '../../../providers/shared/restart-adviser.js';
|
|
19
22
|
import { Command } from 'commander';
|
|
20
23
|
import { createInitToolsBrainstormCommand } from './brainstorm/index.js';
|
|
21
24
|
import { installBrainstorm as defaultInstallBrainstorm, } from './brainstorm/install-brainstorm.js';
|
|
@@ -25,7 +28,8 @@ import { createInitToolsDocsCommand } from './docs/index.js';
|
|
|
25
28
|
import { installDocs as defaultInstallDocs, } from './docs/install-docs.js';
|
|
26
29
|
import { createInitToolsIdeasCommand } from './ideas/index.js';
|
|
27
30
|
import { installIdeas as defaultInstallIdeas, } from './ideas/install-ideas.js';
|
|
28
|
-
import { buildPackInstallStateMap,
|
|
31
|
+
import { buildPackInstallStateMap, buildPackInstallStateMapFromEvidence, } from './install-state.js';
|
|
32
|
+
import { commandProjectGuidanceChoice, planProjectGuidance, reportableProjectGuidance, withProjectGuidanceOptions, } from './project-guidance.js';
|
|
29
33
|
import { createInitToolsProjectManagementCommand } from './project-management/index.js';
|
|
30
34
|
import { installProjectManagement as defaultInstallProjectManagement, } from './project-management/install-project-management.js';
|
|
31
35
|
import { createInitToolsResearchCommand } from './research/index.js';
|
|
@@ -50,6 +54,7 @@ const ALL_TOOL_PACKS = [
|
|
|
50
54
|
];
|
|
51
55
|
let lastRunInitToolsMetadata = null;
|
|
52
56
|
const appliedScopesByCommand = new WeakMap();
|
|
57
|
+
const syncHandledByCommand = new WeakSet();
|
|
53
58
|
const DEFAULT_DEPENDENCIES = {
|
|
54
59
|
buildCommandContext,
|
|
55
60
|
resolveProjectRoot,
|
|
@@ -58,6 +63,8 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
58
63
|
scanTools,
|
|
59
64
|
selectManyWithAbort,
|
|
60
65
|
selectWithAbort,
|
|
66
|
+
confirmAction,
|
|
67
|
+
planProjectGuidance,
|
|
61
68
|
installCore: defaultInstallCore,
|
|
62
69
|
installDocs: defaultInstallDocs,
|
|
63
70
|
installIdeas: defaultInstallIdeas,
|
|
@@ -73,7 +80,6 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
73
80
|
writeOatConfig,
|
|
74
81
|
resolveLocalPaths,
|
|
75
82
|
upsertAgentsMdSection,
|
|
76
|
-
removeAgentsMdSection,
|
|
77
83
|
reconcilePacks: reconcilePackLifecycles,
|
|
78
84
|
inventoryPack,
|
|
79
85
|
};
|
|
@@ -89,6 +95,24 @@ const USER_ELIGIBLE_PACKS = new Set([
|
|
|
89
95
|
function isUserEligiblePack(pack) {
|
|
90
96
|
return USER_ELIGIBLE_PACKS.has(pack);
|
|
91
97
|
}
|
|
98
|
+
async function loadPackEvidence(pack, projectRoot, userRoot, assetsRoot, inventory) {
|
|
99
|
+
const canonical = await inventory({
|
|
100
|
+
pack,
|
|
101
|
+
assetsRoot,
|
|
102
|
+
...(projectRoot ? { projectRoot } : {}),
|
|
103
|
+
userRoot,
|
|
104
|
+
});
|
|
105
|
+
return projectPackEvidence({
|
|
106
|
+
canonical,
|
|
107
|
+
scopes: canonical.scopes.map(packScopeFactsFromInventory),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function assertVerifiedPackScopes(evidence, expected) {
|
|
111
|
+
if (evidence.unknownScopes.length > 0 ||
|
|
112
|
+
expected.some((scope) => !evidence.knownRealizedScopes.includes(scope))) {
|
|
113
|
+
throw new Error(`Pack ${evidence.pack} placement verification failed for ${expected.join(', ')} scope`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
92
116
|
/**
|
|
93
117
|
* Concrete scopes implied by a desired end-state placement.
|
|
94
118
|
*/
|
|
@@ -167,7 +191,10 @@ async function loadInstalledPackStates(projectRoot, userRoot, assetsRoot, depend
|
|
|
167
191
|
...(projectRoot ? { projectRoot } : {}),
|
|
168
192
|
userRoot,
|
|
169
193
|
})));
|
|
170
|
-
return
|
|
194
|
+
return buildPackInstallStateMapFromEvidence(ALL_TOOL_PACKS, inventories.map((canonical) => projectPackEvidence({
|
|
195
|
+
canonical,
|
|
196
|
+
scopes: canonical.scopes.map(packScopeFactsFromInventory),
|
|
197
|
+
})));
|
|
171
198
|
}
|
|
172
199
|
const [projectTools, userTools] = await Promise.all([
|
|
173
200
|
projectRoot
|
|
@@ -249,6 +276,9 @@ export function consumeInitToolsRunMetadata() {
|
|
|
249
276
|
lastRunInitToolsMetadata = null;
|
|
250
277
|
return metadata;
|
|
251
278
|
}
|
|
279
|
+
export function wasInstallSyncHandled(command) {
|
|
280
|
+
return syncHandledByCommand.has(command);
|
|
281
|
+
}
|
|
252
282
|
/**
|
|
253
283
|
* Resolve a possibly-deferred scope-selection signal into a concrete mode.
|
|
254
284
|
*
|
|
@@ -389,12 +419,16 @@ function buildPackEndStateChoices(pack, currentLocation, defaultEndState) {
|
|
|
389
419
|
{
|
|
390
420
|
label: `Project scope (${pack})`,
|
|
391
421
|
value: 'project',
|
|
392
|
-
description: '
|
|
422
|
+
description: currentLocation === 'user' || currentLocation === 'both'
|
|
423
|
+
? 'Add or refresh project scope; keep user scope'
|
|
424
|
+
: 'Install at project scope',
|
|
393
425
|
},
|
|
394
426
|
{
|
|
395
427
|
label: `User scope (${pack})`,
|
|
396
428
|
value: 'user',
|
|
397
|
-
description: '
|
|
429
|
+
description: currentLocation === 'project' || currentLocation === 'both'
|
|
430
|
+
? 'Add or refresh user scope; keep project scope'
|
|
431
|
+
: 'Install at user scope',
|
|
398
432
|
},
|
|
399
433
|
{
|
|
400
434
|
label: `Project + user (${pack})`,
|
|
@@ -411,13 +445,31 @@ function buildPackEndStateChoices(pack, currentLocation, defaultEndState) {
|
|
|
411
445
|
const rest = annotated.filter((choice) => choice.value !== defaultEndState);
|
|
412
446
|
return defaultChoice ? [defaultChoice, ...rest] : annotated;
|
|
413
447
|
}
|
|
414
|
-
function reportSuccess(context, packs, syncScopes, adoptedPacks) {
|
|
448
|
+
function reportSuccess(context, packs, syncScopes, adoptedPacks, lifecycle, projectGuidance) {
|
|
449
|
+
const providerVisibility = initProviderVisibility(syncScopes);
|
|
415
450
|
if (context.json) {
|
|
451
|
+
if (projectGuidance.action === 'blocked' ||
|
|
452
|
+
projectGuidance.action === 'manual-required') {
|
|
453
|
+
context.logger.json({
|
|
454
|
+
status: 'partial',
|
|
455
|
+
installedPacks: packs,
|
|
456
|
+
syncScopes,
|
|
457
|
+
lifecycle: lifecycle.map(({ selection, status }) => ({
|
|
458
|
+
pack: selection.pack,
|
|
459
|
+
status,
|
|
460
|
+
})),
|
|
461
|
+
projectGuidance: reportableProjectGuidance(projectGuidance),
|
|
462
|
+
});
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
416
465
|
context.logger.json({
|
|
417
466
|
status: 'ok',
|
|
418
467
|
installedPacks: packs,
|
|
419
468
|
syncScopes,
|
|
420
469
|
...(adoptedPacks.length > 0 ? { adoptedPacks } : {}),
|
|
470
|
+
lifecycle,
|
|
471
|
+
projectGuidance: reportableProjectGuidance(projectGuidance),
|
|
472
|
+
...(providerVisibility ? { providerVisibility } : {}),
|
|
421
473
|
});
|
|
422
474
|
return;
|
|
423
475
|
}
|
|
@@ -431,6 +483,117 @@ function reportSuccess(context, packs, syncScopes, adoptedPacks) {
|
|
|
431
483
|
if (syncScopes.length === 0) {
|
|
432
484
|
context.logger.info('No sync needed.');
|
|
433
485
|
}
|
|
486
|
+
else if (providerVisibility) {
|
|
487
|
+
context.logger.info(`Provider catalog visibility: ${providerVisibility.state} — ${providerVisibility.reason}`);
|
|
488
|
+
}
|
|
489
|
+
for (const outcome of lifecycle) {
|
|
490
|
+
context.logger.info(`Lifecycle ${outcome.selection.pack}: ${outcome.status} (${outcome.canonical.status})`);
|
|
491
|
+
}
|
|
492
|
+
const guidanceMessage = `Project guidance: ${projectGuidance.action} — ${projectGuidance.reason}`;
|
|
493
|
+
if (projectGuidance.action === 'blocked' ||
|
|
494
|
+
projectGuidance.action === 'manual-required') {
|
|
495
|
+
context.logger.warn(guidanceMessage);
|
|
496
|
+
if (projectGuidance.manualPatch) {
|
|
497
|
+
for (const line of formatAgentsMdGuidanceResult({
|
|
498
|
+
action: 'manual-required',
|
|
499
|
+
manualPatch: projectGuidance.manualPatch,
|
|
500
|
+
})) {
|
|
501
|
+
context.logger.info(line);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
context.logger.info(guidanceMessage);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async function applyProjectGuidance(plan, dependencies) {
|
|
510
|
+
if (plan.action !== 'create' || !plan.repoRoot)
|
|
511
|
+
return plan;
|
|
512
|
+
try {
|
|
513
|
+
const sectionResult = await dependencies.upsertAgentsMdSection(plan.repoRoot, plan.sectionKey, plan.body, plan.legacySectionAction === 'remove'
|
|
514
|
+
? { removeSectionKeys: ['workflows'] }
|
|
515
|
+
: undefined);
|
|
516
|
+
if (sectionResult.action === 'manual-required') {
|
|
517
|
+
return {
|
|
518
|
+
...plan,
|
|
519
|
+
action: 'manual-required',
|
|
520
|
+
reason: 'Accepted project guidance requires the reported manual AGENTS.md patch. Capability placement and PJM adoption were unchanged.',
|
|
521
|
+
manualPatch: sectionResult.manualPatch,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (sectionResult.action === 'blocked') {
|
|
525
|
+
return {
|
|
526
|
+
...plan,
|
|
527
|
+
action: 'blocked',
|
|
528
|
+
reason: `Accepted project guidance was blocked: ${sectionResult.blocked?.reason ?? 'AGENTS.md could not be planned safely.'} ${sectionResult.blocked?.action ?? ''}`.trim(),
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
...plan,
|
|
533
|
+
action: sectionResult.action === 'created' ? 'create' : 'no-change',
|
|
534
|
+
reason: `Accepted project guidance ${sectionResult.action}. Capability placement and PJM adoption were unchanged.`,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
return {
|
|
539
|
+
...plan,
|
|
540
|
+
action: 'blocked',
|
|
541
|
+
reason: `Accepted project guidance was blocked: ${formatAgentsMdMutationFailure(error)}`,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
async function planAndApplyProjectGuidanceAfterInstall(context, assetsRoot, installedProjectRoot, explicitChoice, dependencies) {
|
|
546
|
+
const initialPlan = await dependencies.planProjectGuidance({
|
|
547
|
+
repoRoot: installedProjectRoot,
|
|
548
|
+
packs: [],
|
|
549
|
+
explicitChoice,
|
|
550
|
+
interactive: context.interactive,
|
|
551
|
+
confirmAction: dependencies.confirmAction,
|
|
552
|
+
});
|
|
553
|
+
if (initialPlan.choice.choice !== 'accepted')
|
|
554
|
+
return initialPlan;
|
|
555
|
+
try {
|
|
556
|
+
const repoRoot = installedProjectRoot ??
|
|
557
|
+
(await dependencies.resolveProjectRoot(context.cwd));
|
|
558
|
+
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
559
|
+
const finalPackStates = await loadInstalledPackStates(repoRoot, userRoot, assetsRoot, dependencies);
|
|
560
|
+
const realizedPacks = ALL_TOOL_PACKS.flatMap((pack) => {
|
|
561
|
+
const scope = finalPackStates[pack].location;
|
|
562
|
+
return scope === 'not-installed'
|
|
563
|
+
? []
|
|
564
|
+
: [{ pack, scope }];
|
|
565
|
+
});
|
|
566
|
+
const completePlan = await dependencies.planProjectGuidance({
|
|
567
|
+
repoRoot,
|
|
568
|
+
packs: realizedPacks,
|
|
569
|
+
explicitChoice: true,
|
|
570
|
+
interactive: false,
|
|
571
|
+
confirmAction: dependencies.confirmAction,
|
|
572
|
+
});
|
|
573
|
+
return applyProjectGuidance(completePlan, dependencies);
|
|
574
|
+
}
|
|
575
|
+
catch (error) {
|
|
576
|
+
return {
|
|
577
|
+
...initialPlan,
|
|
578
|
+
action: 'blocked',
|
|
579
|
+
reason: `Accepted project guidance was blocked: ${formatAgentsMdMutationFailure(error)}`,
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function initProviderVisibility(syncScopes) {
|
|
584
|
+
if (syncScopes.length === 0)
|
|
585
|
+
return null;
|
|
586
|
+
return adviseProviderRefresh({
|
|
587
|
+
policy: {
|
|
588
|
+
state: 'unknown',
|
|
589
|
+
reason: 'Init does not select one provider/content refresh contract for the aggregate sync',
|
|
590
|
+
},
|
|
591
|
+
materialization: 'unknown',
|
|
592
|
+
observation: {
|
|
593
|
+
state: 'not-reported',
|
|
594
|
+
reference: 'oat init records provider sync completion but does not query any active provider catalog',
|
|
595
|
+
},
|
|
596
|
+
});
|
|
434
597
|
}
|
|
435
598
|
function reportOutdatedSkills(context, outdatedSkills) {
|
|
436
599
|
if (outdatedSkills.length === 0) {
|
|
@@ -451,47 +614,12 @@ async function updateOutdatedSkills(outdatedSkills, assetsRoot, dependencies) {
|
|
|
451
614
|
}
|
|
452
615
|
return updatedNames;
|
|
453
616
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
docs: 'Documentation and instruction governance workflows',
|
|
457
|
-
workflows: 'Project lifecycle (create, discover, plan, implement, review, complete)',
|
|
458
|
-
ideas: 'Idea capture and refinement',
|
|
459
|
-
'project-management': 'Local backlog, roadmap, and reference doc management (oat-pjm-* skills)',
|
|
460
|
-
utility: 'Standalone utilities (skill authoring, maintainability review, code reviews)',
|
|
461
|
-
research: 'Research, analysis, verification, and synthesis',
|
|
462
|
-
brainstorm: 'Always-on brainstorming entry point with visual companion',
|
|
463
|
-
};
|
|
464
|
-
export function buildToolPacksSectionBody(packs) {
|
|
465
|
-
const userPacks = packs.filter((p) => p.scope === 'user' || p.scope === 'both');
|
|
466
|
-
const hasWorkflows = packs.some((p) => p.pack === 'workflows');
|
|
467
|
-
const lines = [
|
|
468
|
-
'## Tool Packs',
|
|
469
|
-
'',
|
|
470
|
-
'- **Skills directory:** `.agents/skills/`',
|
|
471
|
-
'- **Discover available skills:** scan `.agents/skills/*/SKILL.md`',
|
|
472
|
-
'- **Refresh provider views:** `oat sync --scope all`',
|
|
473
|
-
'- **Update skills to latest versions:** `oat tools update`',
|
|
474
|
-
];
|
|
475
|
-
if (userPacks.length > 0) {
|
|
476
|
-
const userPackNames = userPacks.map((p) => p.pack).join(', ');
|
|
477
|
-
lines.push(`- **User-scoped skills:** \`~/.agents/skills/\` (${userPackNames} packs installed at user scope)`);
|
|
478
|
-
}
|
|
479
|
-
lines.push('', '### Installed Packs', '');
|
|
480
|
-
for (const { pack, scope } of packs) {
|
|
481
|
-
const suffix = scope === 'user'
|
|
482
|
-
? ' _(user scope)_'
|
|
483
|
-
: scope === 'both'
|
|
484
|
-
? ' _(project + user scope)_'
|
|
485
|
-
: '';
|
|
486
|
-
lines.push(`- **${pack}** — ${PACK_DESCRIPTIONS[pack]}${suffix}`);
|
|
487
|
-
}
|
|
488
|
-
if (hasWorkflows) {
|
|
489
|
-
lines.push('', '### Workflow Execution Continuation', '', '- This guidance applies only to OAT project lifecycle execution, such as `oat-project-implement`, and OAT project review/receive flows. It does not apply to non-OAT tasks or ad-hoc work outside the OAT project workflow.', '- When executing an OAT project implementation or OAT project review workflow, do not stop at task boundaries, phase boundaries, or other clean checkpoints unless the configured HiLL checkpoint has been reached, a real blocker exists, or explicit user input is required.', '- Status summaries, completed bookkeeping, and "clean boundary" pauses are not valid stop reasons. After updating tracking artifacts, continue execution until an allowed stop condition applies.');
|
|
490
|
-
}
|
|
491
|
-
return lines.join('\n');
|
|
492
|
-
}
|
|
493
|
-
export async function runInitTools(context, dependencies) {
|
|
617
|
+
export { buildToolPacksSectionBody } from './project-guidance.js';
|
|
618
|
+
export async function runInitTools(context, dependencies, explicitProjectGuidance) {
|
|
494
619
|
lastRunInitToolsMetadata = null;
|
|
620
|
+
let attemptedPacks = [];
|
|
621
|
+
let attemptedSelections = [];
|
|
622
|
+
let lifecycleOutcomes = [];
|
|
495
623
|
try {
|
|
496
624
|
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
497
625
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
@@ -518,11 +646,13 @@ export async function runInitTools(context, dependencies) {
|
|
|
518
646
|
if (!context.interactive) {
|
|
519
647
|
selectedPacks.push('project-management');
|
|
520
648
|
}
|
|
649
|
+
attemptedPacks = selectedPacks;
|
|
521
650
|
if (selectedPacks.length === 0) {
|
|
522
651
|
lastRunInitToolsMetadata = {
|
|
523
652
|
affectedScopes: [],
|
|
524
653
|
appliedScopes: [],
|
|
525
654
|
adoptedPacks: [],
|
|
655
|
+
syncHandled: dependencies.syncAfterInstall !== undefined,
|
|
526
656
|
};
|
|
527
657
|
if (!context.json) {
|
|
528
658
|
context.logger.info('No tool packs selected.');
|
|
@@ -531,6 +661,12 @@ export async function runInitTools(context, dependencies) {
|
|
|
531
661
|
return [];
|
|
532
662
|
}
|
|
533
663
|
const packScopes = await resolvePackScopes(context, selectedPacks, initialPackStates, dependencies);
|
|
664
|
+
attemptedSelections = selectedPacks.map((pack) => resolveAdditivePackScopeSelection({
|
|
665
|
+
pack,
|
|
666
|
+
requested: pack === 'core' ? 'user' : packScopes[pack],
|
|
667
|
+
knownRealizedScopes: scopesForLocation(initialPackStates[pack].location),
|
|
668
|
+
unknownScopes: [],
|
|
669
|
+
}));
|
|
534
670
|
function scopeRoot(scope) {
|
|
535
671
|
if (scope === 'user')
|
|
536
672
|
return userRoot;
|
|
@@ -565,6 +701,25 @@ export async function runInitTools(context, dependencies) {
|
|
|
565
701
|
if (plan.operations.length > 0)
|
|
566
702
|
affectedScopes.add(plan.scope);
|
|
567
703
|
}
|
|
704
|
+
if (dependencies.inventoryPack) {
|
|
705
|
+
const finalEvidence = await Promise.all(selectedPacks.map((pack) => loadPackEvidence(pack, projectRoot, userRoot, assetsRoot, dependencies.inventoryPack)));
|
|
706
|
+
lifecycleOutcomes = finalEvidence.map((evidence) => {
|
|
707
|
+
const packResults = lifecycle.filter(({ request }) => request.pack === evidence.pack);
|
|
708
|
+
const selection = attemptedSelections.find(({ pack }) => pack === evidence.pack);
|
|
709
|
+
return evaluatePackLifecycleOutcome({
|
|
710
|
+
selection,
|
|
711
|
+
lifecycle: packResults,
|
|
712
|
+
sync: { scopes: [], status: 'not-run', providers: [] },
|
|
713
|
+
finalEvidence: evidence,
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
for (const evidence of finalEvidence) {
|
|
717
|
+
const target = evidence.pack === 'core'
|
|
718
|
+
? ['user']
|
|
719
|
+
: scopesForEndState(packScopes[evidence.pack]);
|
|
720
|
+
assertVerifiedPackScopes(evidence, target);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
568
723
|
if (requests.some(({ pack, scope }) => pack === 'workflows' && scope === 'project')) {
|
|
569
724
|
const repoRoot = scopeRoot('project');
|
|
570
725
|
const existingConfig = await dependencies.readOatConfig(repoRoot);
|
|
@@ -828,20 +983,6 @@ export async function runInitTools(context, dependencies) {
|
|
|
828
983
|
pack,
|
|
829
984
|
scope: packScopes[pack],
|
|
830
985
|
}));
|
|
831
|
-
const adoptsProject = packScopeInfo.some(({ scope }) => scope !== 'user');
|
|
832
|
-
const sectionBody = buildToolPacksSectionBody(packScopeInfo);
|
|
833
|
-
const sectionResult = adoptsProject
|
|
834
|
-
? await dependencies.upsertAgentsMdSection(scopeRoot('project'), 'tools', sectionBody)
|
|
835
|
-
: { action: 'no-change' };
|
|
836
|
-
// Pack placement never writes the project-management or decisions AGENTS
|
|
837
|
-
// sections. Those belong to explicit repository adoption (`oat pjm init`,
|
|
838
|
-
// via `initializeRepoReference`), which owns the `pjm.initialized` marker.
|
|
839
|
-
if (adoptsProject) {
|
|
840
|
-
await dependencies.removeAgentsMdSection(scopeRoot('project'), 'workflows');
|
|
841
|
-
}
|
|
842
|
-
if (!context.json && sectionResult.action !== 'no-change') {
|
|
843
|
-
context.logger.info(`AGENTS.md tool packs section ${sectionResult.action}.`);
|
|
844
|
-
}
|
|
845
986
|
const affectedScopesList = [...affectedScopes];
|
|
846
987
|
const appliedScopes = [
|
|
847
988
|
...new Set(packScopeInfo.flatMap(({ scope }) => scopesForEndState(scope))),
|
|
@@ -853,20 +994,86 @@ export async function runInitTools(context, dependencies) {
|
|
|
853
994
|
home: context.home,
|
|
854
995
|
}, dependencies)).adoptedPacks
|
|
855
996
|
: [];
|
|
997
|
+
const finalPackStates = await loadInstalledPackStates(projectRoot, userRoot, assetsRoot, dependencies);
|
|
998
|
+
const realizedPacks = ALL_TOOL_PACKS.flatMap((pack) => {
|
|
999
|
+
const scope = finalPackStates[pack].location;
|
|
1000
|
+
return scope === 'not-installed'
|
|
1001
|
+
? []
|
|
1002
|
+
: [{ pack, scope }];
|
|
1003
|
+
});
|
|
1004
|
+
const plannedGuidance = await dependencies.planProjectGuidance({
|
|
1005
|
+
repoRoot: projectRoot,
|
|
1006
|
+
packs: realizedPacks,
|
|
1007
|
+
explicitChoice: explicitProjectGuidance,
|
|
1008
|
+
interactive: context.interactive,
|
|
1009
|
+
confirmAction: dependencies.confirmAction,
|
|
1010
|
+
});
|
|
1011
|
+
const guidancePlan = await applyProjectGuidance(plannedGuidance, dependencies);
|
|
1012
|
+
if (dependencies.syncAfterInstall) {
|
|
1013
|
+
const sync = await dependencies.syncAfterInstall(affectedScopesList, context, canonicalPathsForPacks(selectedPacks));
|
|
1014
|
+
lifecycleOutcomes = lifecycleOutcomes.map((outcome) => evaluatePackLifecycleOutcome({
|
|
1015
|
+
selection: outcome.selection,
|
|
1016
|
+
lifecycle: outcome.canonical.results,
|
|
1017
|
+
sync: {
|
|
1018
|
+
scopes: sync.scopes.filter((scope) => outcome.selection.targetScopes.includes(scope)),
|
|
1019
|
+
status: sync.scopes.length === 0
|
|
1020
|
+
? 'not-run'
|
|
1021
|
+
: sync.synced
|
|
1022
|
+
? 'complete'
|
|
1023
|
+
: 'failed',
|
|
1024
|
+
providers: [],
|
|
1025
|
+
...(sync.error ? { error: sync.error } : {}),
|
|
1026
|
+
},
|
|
1027
|
+
finalEvidence: outcome.finalEvidence,
|
|
1028
|
+
}));
|
|
1029
|
+
}
|
|
856
1030
|
lastRunInitToolsMetadata = {
|
|
857
1031
|
affectedScopes: affectedScopesList,
|
|
858
1032
|
appliedScopes,
|
|
859
1033
|
adoptedPacks,
|
|
1034
|
+
syncHandled: dependencies.syncAfterInstall !== undefined,
|
|
860
1035
|
};
|
|
861
|
-
reportSuccess(context, packScopeInfo, affectedScopesList, adoptedPacks);
|
|
862
|
-
process.exitCode =
|
|
1036
|
+
reportSuccess(context, packScopeInfo, affectedScopesList, adoptedPacks, lifecycleOutcomes, guidancePlan);
|
|
1037
|
+
process.exitCode =
|
|
1038
|
+
lifecycleOutcomes.some(({ status }) => status !== 'complete') ||
|
|
1039
|
+
guidancePlan.action === 'blocked' ||
|
|
1040
|
+
guidancePlan.action === 'manual-required'
|
|
1041
|
+
? 1
|
|
1042
|
+
: 0;
|
|
863
1043
|
return selectedPacks;
|
|
864
1044
|
}
|
|
865
1045
|
catch (error) {
|
|
866
1046
|
lastRunInitToolsMetadata = null;
|
|
867
1047
|
const message = error instanceof Error ? error.message : String(error);
|
|
868
1048
|
if (context.json) {
|
|
869
|
-
context.logger.json({
|
|
1049
|
+
context.logger.json({
|
|
1050
|
+
status: 'error',
|
|
1051
|
+
message,
|
|
1052
|
+
...(attemptedPacks.length > 0
|
|
1053
|
+
? {
|
|
1054
|
+
lifecycle: lifecycleOutcomes.length > 0
|
|
1055
|
+
? lifecycleOutcomes
|
|
1056
|
+
: attemptedPacks.map((pack) => ({
|
|
1057
|
+
schemaVersion: 1,
|
|
1058
|
+
selection: attemptedSelections.find((selection) => selection.pack === pack) ?? {
|
|
1059
|
+
pack,
|
|
1060
|
+
requested: 'user',
|
|
1061
|
+
retainedRealizedScopes: [],
|
|
1062
|
+
targetScopes: [],
|
|
1063
|
+
},
|
|
1064
|
+
canonical: { status: 'failed', results: [] },
|
|
1065
|
+
sync: {
|
|
1066
|
+
scopes: [],
|
|
1067
|
+
status: 'not-run',
|
|
1068
|
+
providers: [],
|
|
1069
|
+
},
|
|
1070
|
+
finalEvidence: null,
|
|
1071
|
+
status: 'failed',
|
|
1072
|
+
recovery: [{ code: 'canonical-apply-failed', message }],
|
|
1073
|
+
})),
|
|
1074
|
+
}
|
|
1075
|
+
: {}),
|
|
1076
|
+
});
|
|
870
1077
|
}
|
|
871
1078
|
else {
|
|
872
1079
|
context.logger.error(message);
|
|
@@ -875,8 +1082,8 @@ export async function runInitTools(context, dependencies) {
|
|
|
875
1082
|
return [];
|
|
876
1083
|
}
|
|
877
1084
|
}
|
|
878
|
-
export async function runInitToolsWithDefaults(context) {
|
|
879
|
-
return runInitTools(context, { ...DEFAULT_DEPENDENCIES });
|
|
1085
|
+
export async function runInitToolsWithDefaults(context, explicitProjectGuidance) {
|
|
1086
|
+
return runInitTools(context, { ...DEFAULT_DEPENDENCIES }, explicitProjectGuidance);
|
|
880
1087
|
}
|
|
881
1088
|
/**
|
|
882
1089
|
* Scopes a bare `oat tools install <pack>` (no explicit `--scope`) should
|
|
@@ -888,30 +1095,46 @@ export async function runInitToolsWithDefaults(context) {
|
|
|
888
1095
|
* `defaultScope`. Falls back to the configured default only when placement
|
|
889
1096
|
* cannot be observed (no inventory dependency, or an inventory failure).
|
|
890
1097
|
*/
|
|
891
|
-
async function
|
|
1098
|
+
async function resolvePackCommandSelection(pack, context, assetsRoot, dependencies, requested) {
|
|
892
1099
|
const definition = getPackDefinition(pack);
|
|
893
1100
|
const inventory = dependencies.inventoryPack;
|
|
894
|
-
if (!inventory)
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
const projectRoot = definition.allowedScopes.includes('project')
|
|
899
|
-
? await dependencies
|
|
900
|
-
.resolveProjectRoot(context.cwd)
|
|
901
|
-
.catch(() => undefined)
|
|
902
|
-
: undefined;
|
|
903
|
-
const packInventory = await inventory({
|
|
1101
|
+
if (!inventory) {
|
|
1102
|
+
const fallback = requested ?? definition.defaultScope;
|
|
1103
|
+
const fallbackScopes = fallback === 'both' ? ['project', 'user'] : [fallback];
|
|
1104
|
+
return {
|
|
904
1105
|
pack,
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
const states = buildPackInstallStateMapFromInventory([pack], [packInventory]);
|
|
910
|
-
return scopesForEndState(resolvePackDefaultEndState(pack, states[pack].location)).filter((scope) => definition.allowedScopes.includes(scope));
|
|
911
|
-
}
|
|
912
|
-
catch {
|
|
913
|
-
return [definition.defaultScope];
|
|
1106
|
+
requested: fallback,
|
|
1107
|
+
retainedRealizedScopes: [],
|
|
1108
|
+
targetScopes: fallbackScopes.filter((scope) => definition.allowedScopes.includes(scope)),
|
|
1109
|
+
};
|
|
914
1110
|
}
|
|
1111
|
+
const userRoot = dependencies.resolveScopeRoot('user', context.cwd, context.home);
|
|
1112
|
+
const projectRoot = definition.allowedScopes.includes('project')
|
|
1113
|
+
? await dependencies.resolveProjectRoot(context.cwd).catch(() => undefined)
|
|
1114
|
+
: undefined;
|
|
1115
|
+
const canonical = await inventory({
|
|
1116
|
+
pack,
|
|
1117
|
+
assetsRoot,
|
|
1118
|
+
...(projectRoot ? { projectRoot } : {}),
|
|
1119
|
+
userRoot,
|
|
1120
|
+
});
|
|
1121
|
+
const evidence = projectPackEvidence({
|
|
1122
|
+
canonical,
|
|
1123
|
+
scopes: canonical.scopes.map(packScopeFactsFromInventory),
|
|
1124
|
+
});
|
|
1125
|
+
const defaultRequest = evidence.knownRealizedScopes.length === 2
|
|
1126
|
+
? 'both'
|
|
1127
|
+
: (evidence.knownRealizedScopes[0] ?? definition.defaultScope);
|
|
1128
|
+
const selection = resolveAdditivePackScopeSelection({
|
|
1129
|
+
pack,
|
|
1130
|
+
requested: requested ?? defaultRequest,
|
|
1131
|
+
knownRealizedScopes: evidence.knownRealizedScopes,
|
|
1132
|
+
unknownScopes: evidence.unknownScopes,
|
|
1133
|
+
});
|
|
1134
|
+
return {
|
|
1135
|
+
...selection,
|
|
1136
|
+
targetScopes: selection.targetScopes.filter((scope) => definition.allowedScopes.includes(scope)),
|
|
1137
|
+
};
|
|
915
1138
|
}
|
|
916
1139
|
function createReconciledPackCommand(pack, dependencies) {
|
|
917
1140
|
const definition = getPackDefinition(pack);
|
|
@@ -926,22 +1149,31 @@ function createReconciledPackCommand(pack, dependencies) {
|
|
|
926
1149
|
brainstorm: 'Install OAT brainstorm skill (always-on entry point with visual companion)',
|
|
927
1150
|
};
|
|
928
1151
|
const base = new Command(pack).description(descriptions[pack]);
|
|
929
|
-
const
|
|
1152
|
+
const scopedCommand = pack === 'core' ? base : withScopeOption(base);
|
|
1153
|
+
const packCommand = pack === 'workflows'
|
|
1154
|
+
? withProjectGuidanceOptions(scopedCommand)
|
|
1155
|
+
: scopedCommand;
|
|
930
1156
|
return packCommand
|
|
931
1157
|
.allowUnknownOption(false)
|
|
932
1158
|
.action(async (_options, command) => {
|
|
933
1159
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
1160
|
+
let lifecycleOutcome = null;
|
|
1161
|
+
let selection = null;
|
|
934
1162
|
try {
|
|
1163
|
+
const explicitProjectGuidance = pack === 'workflows'
|
|
1164
|
+
? commandProjectGuidanceChoice(command)
|
|
1165
|
+
: undefined;
|
|
935
1166
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
936
1167
|
const explicitScope = command.getOptionValueSourceWithGlobals('scope') === 'cli';
|
|
937
1168
|
const requestedScope = context.scope === 'project' || context.scope === 'user'
|
|
938
1169
|
? context.scope
|
|
939
1170
|
: null;
|
|
940
|
-
|
|
941
|
-
?
|
|
942
|
-
: requestedScope
|
|
943
|
-
?
|
|
944
|
-
:
|
|
1171
|
+
selection = await resolvePackCommandSelection(pack, context, assetsRoot, dependencies, explicitScope && context.scope === 'all'
|
|
1172
|
+
? 'both'
|
|
1173
|
+
: explicitScope && requestedScope
|
|
1174
|
+
? requestedScope
|
|
1175
|
+
: undefined);
|
|
1176
|
+
const scopes = [...selection.targetScopes];
|
|
945
1177
|
for (const scope of scopes) {
|
|
946
1178
|
if (!definition.allowedScopes.includes(scope)) {
|
|
947
1179
|
throw new Error(`Pack ${pack} does not allow ${scope} scope`);
|
|
@@ -957,8 +1189,46 @@ function createReconciledPackCommand(pack, dependencies) {
|
|
|
957
1189
|
action: 'install',
|
|
958
1190
|
})));
|
|
959
1191
|
const results = await dependencies.reconcilePacks(requests);
|
|
960
|
-
|
|
1192
|
+
let finalEvidence = null;
|
|
1193
|
+
if (dependencies.inventoryPack) {
|
|
1194
|
+
finalEvidence = await loadPackEvidence(pack, requests.some(({ scope }) => scope === 'project')
|
|
1195
|
+
? await dependencies.resolveProjectRoot(context.cwd)
|
|
1196
|
+
: null, dependencies.resolveScopeRoot('user', context.cwd, context.home), assetsRoot, dependencies.inventoryPack);
|
|
1197
|
+
}
|
|
1198
|
+
lifecycleOutcome = evaluatePackLifecycleOutcome({
|
|
1199
|
+
selection,
|
|
1200
|
+
lifecycle: results,
|
|
1201
|
+
sync: { scopes: [], status: 'not-run', providers: [] },
|
|
1202
|
+
finalEvidence,
|
|
1203
|
+
});
|
|
1204
|
+
if (finalEvidence)
|
|
1205
|
+
assertVerifiedPackScopes(finalEvidence, scopes);
|
|
1206
|
+
appliedScopesByCommand.set(command, results
|
|
1207
|
+
.filter(({ plan }) => plan.operations.length > 0)
|
|
1208
|
+
.map(({ request }) => request.scope));
|
|
961
1209
|
setInstalledCanonicalPaths(command, canonicalPathsForPacks([pack]));
|
|
1210
|
+
if (dependencies.syncAfterInstall) {
|
|
1211
|
+
syncHandledByCommand.add(command);
|
|
1212
|
+
const changedScopes = results
|
|
1213
|
+
.filter(({ plan }) => plan.operations.length > 0)
|
|
1214
|
+
.map(({ request }) => request.scope);
|
|
1215
|
+
const sync = await dependencies.syncAfterInstall(changedScopes, context, canonicalPathsForPacks([pack]));
|
|
1216
|
+
lifecycleOutcome = evaluatePackLifecycleOutcome({
|
|
1217
|
+
selection,
|
|
1218
|
+
lifecycle: results,
|
|
1219
|
+
sync: {
|
|
1220
|
+
scopes: sync.scopes,
|
|
1221
|
+
status: sync.scopes.length === 0
|
|
1222
|
+
? 'not-run'
|
|
1223
|
+
: sync.synced
|
|
1224
|
+
? 'complete'
|
|
1225
|
+
: 'failed',
|
|
1226
|
+
providers: [],
|
|
1227
|
+
...(sync.error ? { error: sync.error } : {}),
|
|
1228
|
+
},
|
|
1229
|
+
finalEvidence,
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
962
1232
|
// Project-scope placement installs capability only. The
|
|
963
1233
|
// project-management and decisions AGENTS sections are written by the
|
|
964
1234
|
// explicit adoption action (`oat pjm init`), never by pack placement.
|
|
@@ -969,12 +1239,28 @@ function createReconciledPackCommand(pack, dependencies) {
|
|
|
969
1239
|
home: context.home,
|
|
970
1240
|
}, dependencies)).adoptedPacks
|
|
971
1241
|
: [];
|
|
1242
|
+
const providerVisibility = initProviderVisibility(results
|
|
1243
|
+
.filter(({ plan }) => plan.operations.length > 0)
|
|
1244
|
+
.map(({ request }) => request.scope));
|
|
1245
|
+
const projectGuidance = pack === 'workflows'
|
|
1246
|
+
? await planAndApplyProjectGuidanceAfterInstall(context, assetsRoot, requests.find(({ scope }) => scope === 'project')?.scopeRoot ??
|
|
1247
|
+
null, explicitProjectGuidance, dependencies)
|
|
1248
|
+
: null;
|
|
972
1249
|
if (context.json) {
|
|
1250
|
+
const guidanceIncomplete = projectGuidance?.action === 'blocked' ||
|
|
1251
|
+
projectGuidance?.action === 'manual-required';
|
|
973
1252
|
context.logger.json({
|
|
974
|
-
status: 'ok',
|
|
1253
|
+
status: guidanceIncomplete ? 'partial' : 'ok',
|
|
975
1254
|
pack,
|
|
976
1255
|
scopes,
|
|
977
1256
|
results,
|
|
1257
|
+
lifecycle: lifecycleOutcome,
|
|
1258
|
+
...(projectGuidance
|
|
1259
|
+
? {
|
|
1260
|
+
projectGuidance: reportableProjectGuidance(projectGuidance),
|
|
1261
|
+
}
|
|
1262
|
+
: {}),
|
|
1263
|
+
...(providerVisibility ? { providerVisibility } : {}),
|
|
978
1264
|
...(adoptedPacks.length > 0 ? { adoptedPacks } : {}),
|
|
979
1265
|
});
|
|
980
1266
|
}
|
|
@@ -983,6 +1269,28 @@ function createReconciledPackCommand(pack, dependencies) {
|
|
|
983
1269
|
context.logger.info(`Adopted project tool pack: ${adoptedPack}`);
|
|
984
1270
|
}
|
|
985
1271
|
context.logger.info(`Installed ${pack} tool pack.`);
|
|
1272
|
+
context.logger.info(`Lifecycle: ${lifecycleOutcome.status} (${lifecycleOutcome.canonical.status})`);
|
|
1273
|
+
if (providerVisibility) {
|
|
1274
|
+
context.logger.info(`Provider catalog visibility: ${providerVisibility.state} — ${providerVisibility.reason}`);
|
|
1275
|
+
}
|
|
1276
|
+
if (projectGuidance) {
|
|
1277
|
+
const guidanceMessage = `Project guidance: ${projectGuidance.action} — ${projectGuidance.reason}`;
|
|
1278
|
+
if (projectGuidance.action === 'blocked' ||
|
|
1279
|
+
projectGuidance.action === 'manual-required') {
|
|
1280
|
+
context.logger.warn(guidanceMessage);
|
|
1281
|
+
if (projectGuidance.manualPatch) {
|
|
1282
|
+
for (const line of formatAgentsMdGuidanceResult({
|
|
1283
|
+
action: 'manual-required',
|
|
1284
|
+
manualPatch: projectGuidance.manualPatch,
|
|
1285
|
+
})) {
|
|
1286
|
+
context.logger.info(line);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
else {
|
|
1291
|
+
context.logger.info(guidanceMessage);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
986
1294
|
for (const result of results) {
|
|
987
1295
|
context.logger.info(`Scope: ${result.request.scope}`);
|
|
988
1296
|
context.logger.info(`Target root: ${result.request.scopeRoot}`);
|
|
@@ -990,12 +1298,35 @@ function createReconciledPackCommand(pack, dependencies) {
|
|
|
990
1298
|
context.logger.info(`Run: oat sync --scope ${result.request.scope}`);
|
|
991
1299
|
}
|
|
992
1300
|
}
|
|
993
|
-
process.exitCode =
|
|
1301
|
+
process.exitCode =
|
|
1302
|
+
lifecycleOutcome.status === 'complete' &&
|
|
1303
|
+
projectGuidance?.action !== 'blocked' &&
|
|
1304
|
+
projectGuidance?.action !== 'manual-required'
|
|
1305
|
+
? 0
|
|
1306
|
+
: 1;
|
|
994
1307
|
}
|
|
995
1308
|
catch (error) {
|
|
996
1309
|
const message = error instanceof Error ? error.message : String(error);
|
|
1310
|
+
lifecycleOutcome ??= {
|
|
1311
|
+
schemaVersion: 1,
|
|
1312
|
+
selection: selection ?? {
|
|
1313
|
+
pack,
|
|
1314
|
+
requested: 'user',
|
|
1315
|
+
retainedRealizedScopes: [],
|
|
1316
|
+
targetScopes: [],
|
|
1317
|
+
},
|
|
1318
|
+
canonical: { status: 'failed', results: [] },
|
|
1319
|
+
sync: { scopes: [], status: 'not-run', providers: [] },
|
|
1320
|
+
finalEvidence: null,
|
|
1321
|
+
status: 'failed',
|
|
1322
|
+
recovery: [{ code: 'canonical-apply-failed', message }],
|
|
1323
|
+
};
|
|
997
1324
|
if (context.json)
|
|
998
|
-
context.logger.json({
|
|
1325
|
+
context.logger.json({
|
|
1326
|
+
status: 'error',
|
|
1327
|
+
message,
|
|
1328
|
+
lifecycle: lifecycleOutcome,
|
|
1329
|
+
});
|
|
999
1330
|
else
|
|
1000
1331
|
context.logger.error(message);
|
|
1001
1332
|
process.exitCode = 1;
|
|
@@ -1079,13 +1410,13 @@ export function createInitToolsCommand(overrides = {}) {
|
|
|
1079
1410
|
});
|
|
1080
1411
|
}
|
|
1081
1412
|
}
|
|
1082
|
-
const command = new Command('tools').description('Install OAT tool packs (core, ideas, docs, workflows, utility, project-management, research, brainstorm)');
|
|
1413
|
+
const command = withProjectGuidanceOptions(new Command('tools').description('Install OAT tool packs (core, ideas, docs, workflows, utility, project-management, research, brainstorm)'));
|
|
1083
1414
|
for (const packCommand of packCommands) {
|
|
1084
1415
|
command.addCommand(packCommand);
|
|
1085
1416
|
}
|
|
1086
1417
|
command.action(async (_options, actionCommand) => {
|
|
1087
1418
|
const context = dependencies.buildCommandContext(readGlobalOptions(actionCommand));
|
|
1088
|
-
const selectedPacks = await runInitTools(context, dependencies);
|
|
1419
|
+
const selectedPacks = await runInitTools(context, dependencies, commandProjectGuidanceChoice(actionCommand));
|
|
1089
1420
|
appliedScopesByCommand.set(actionCommand, lastRunInitToolsMetadata?.appliedScopes ?? []);
|
|
1090
1421
|
setInstalledCanonicalPaths(actionCommand, canonicalPathsForPacks(selectedPacks));
|
|
1091
1422
|
});
|