@open-agent-toolkit/cli 0.2.41 → 0.2.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agents/oat-phase-implementer.md +11 -1
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +11 -1
- package/assets/docs/cli-utilities/tool-packs.md +55 -9
- package/assets/docs/quickstart.md +9 -0
- package/assets/docs/reference/cli-reference.md +56 -1
- package/assets/docs/reference/file-locations.md +18 -1
- package/assets/docs/reference/oat-directory-structure.md +20 -4
- package/assets/docs/reference/troubleshooting.md +18 -11
- package/assets/docs/workflows/projects/artifacts.md +27 -1
- package/assets/docs/workflows/projects/implementation-execution.md +22 -0
- package/assets/docs/workflows/projects/index.md +6 -0
- package/assets/docs/workflows/projects/lifecycle.md +19 -5
- package/assets/docs/workflows/projects/picking-up-projects.md +75 -0
- package/assets/docs/workflows/projects/pr-flow.md +22 -1
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +60 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-brainstorm/SKILL.md +135 -32
- package/assets/skills/oat-brainstorm/references/destinations.md +9 -6
- package/assets/skills/oat-cursor-cloud-projects/SKILL.md +11 -1
- package/assets/skills/oat-doctor/SKILL.md +8 -1
- package/assets/skills/oat-project-autonomous/SKILL.md +45 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +8 -8
- package/assets/skills/oat-project-capture/SKILL.md +29 -9
- package/assets/skills/oat-project-complete/SKILL.md +610 -38
- package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +265 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +764 -0
- package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +134 -0
- package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +160 -0
- package/assets/skills/oat-project-design/SKILL.md +33 -9
- package/assets/skills/oat-project-discover/SKILL.md +16 -3
- package/assets/skills/oat-project-document/SKILL.md +10 -4
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/SKILL.md +14 -3
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +18 -6
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/references/phase-execution.md +9 -3
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +3 -0
- package/assets/skills/oat-project-import-plan/SKILL.md +15 -9
- package/assets/skills/oat-project-new/SKILL.md +7 -5
- package/assets/skills/oat-project-next/SKILL.md +32 -10
- package/assets/skills/oat-project-plan/SKILL.md +18 -3
- package/assets/skills/oat-project-pr-final/SKILL.md +23 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-pr-progress/SKILL.md +23 -2
- package/assets/skills/oat-project-progress/SKILL.md +23 -9
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +20 -2
- package/assets/skills/oat-project-quick-start/SKILL.md +48 -18
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-reconcile/SKILL.md +14 -10
- package/assets/skills/oat-project-retro/SKILL.md +3 -3
- package/assets/skills/oat-project-retro/references/apply-procedure.md +102 -6
- package/assets/skills/oat-project-retro-file/SKILL.md +57 -6
- package/assets/skills/oat-project-review-provide/SKILL.md +45 -4
- package/assets/skills/oat-project-review-receive/SKILL.md +16 -7
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +9 -3
- package/assets/skills/oat-project-revise/SKILL.md +12 -3
- package/assets/skills/oat-project-spec/SKILL.md +16 -3
- package/assets/skills/oat-project-summary/SKILL.md +113 -13
- package/assets/skills/oat-wave-execute/SKILL.md +34 -2
- package/assets/skills/oat-worktree-bootstrap/SKILL.md +13 -1
- package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +13 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +34 -3
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +27 -3
- package/dist/commands/doctor/synced-projects.d.ts +12 -0
- package/dist/commands/doctor/synced-projects.d.ts.map +1 -0
- package/dist/commands/doctor/synced-projects.js +208 -0
- package/dist/commands/init/gitattributes.d.ts +4 -0
- package/dist/commands/init/gitattributes.d.ts.map +1 -0
- package/dist/commands/init/gitattributes.js +12 -0
- package/dist/commands/init/gitignore.d.ts +8 -1
- package/dist/commands/init/gitignore.d.ts.map +1 -1
- package/dist/commands/init/gitignore.js +146 -41
- package/dist/commands/init/index.d.ts +2 -0
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +3 -0
- package/dist/commands/init/managed-block.d.ts +10 -0
- package/dist/commands/init/managed-block.d.ts.map +1 -0
- package/dist/commands/init/managed-block.js +40 -0
- package/dist/commands/init/tools/index.d.ts +1 -0
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +37 -9
- package/dist/commands/init/tools/workflows/install-workflows.js +1 -1
- package/dist/commands/local/index.d.ts.map +1 -1
- package/dist/commands/local/index.js +5 -1
- package/dist/commands/local/sync.d.ts +4 -0
- package/dist/commands/local/sync.d.ts.map +1 -1
- package/dist/commands/local/sync.js +123 -2
- package/dist/commands/pjm/adoption.d.ts +2 -0
- package/dist/commands/pjm/adoption.d.ts.map +1 -1
- package/dist/commands/pjm/adoption.js +1 -1
- package/dist/commands/project/archive/archive-utils.d.ts +24 -0
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +349 -22
- package/dist/commands/project/archive/index.d.ts.map +1 -1
- package/dist/commands/project/archive/index.js +1 -0
- package/dist/commands/project/archive/push-runner.d.ts +5 -1
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +33 -4
- package/dist/commands/project/complete-state/index.d.ts.map +1 -1
- package/dist/commands/project/complete-state/index.js +3 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +12 -0
- package/dist/commands/project/links/compute.d.ts +9 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -0
- package/dist/commands/project/links/compute.js +27 -0
- package/dist/commands/project/links/index.d.ts +17 -0
- package/dist/commands/project/links/index.d.ts.map +1 -0
- package/dist/commands/project/links/index.js +72 -0
- package/dist/commands/project/links/refresh.d.ts +26 -0
- package/dist/commands/project/links/refresh.d.ts.map +1 -0
- package/dist/commands/project/links/refresh.js +92 -0
- package/dist/commands/project/links/render.d.ts +24 -0
- package/dist/commands/project/links/render.d.ts.map +1 -0
- package/dist/commands/project/links/render.js +68 -0
- package/dist/commands/project/list.d.ts +5 -0
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +182 -9
- package/dist/commands/project/migrate/index.d.ts +22 -0
- package/dist/commands/project/migrate/index.d.ts.map +1 -0
- package/dist/commands/project/migrate/index.js +79 -0
- package/dist/commands/project/new/index.d.ts +2 -0
- package/dist/commands/project/new/index.d.ts.map +1 -1
- package/dist/commands/project/new/index.js +14 -2
- package/dist/commands/project/new/scaffold.d.ts +22 -1
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +287 -69
- package/dist/commands/project/open/index.d.ts +16 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +151 -19
- package/dist/commands/project/pause/index.d.ts +8 -0
- package/dist/commands/project/pause/index.d.ts.map +1 -1
- package/dist/commands/project/pause/index.js +129 -19
- package/dist/commands/project/prune/index.d.ts +21 -0
- package/dist/commands/project/prune/index.d.ts.map +1 -0
- package/dist/commands/project/prune/index.js +95 -0
- package/dist/commands/project/pull/index.d.ts +28 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -0
- package/dist/commands/project/pull/index.js +157 -0
- package/dist/commands/project/push/index.d.ts +22 -0
- package/dist/commands/project/push/index.d.ts.map +1 -0
- package/dist/commands/project/push/index.js +100 -0
- package/dist/commands/project/scope/index.d.ts +17 -0
- package/dist/commands/project/scope/index.d.ts.map +1 -0
- package/dist/commands/project/scope/index.js +107 -0
- package/dist/commands/project/split/run.d.ts +4 -0
- package/dist/commands/project/split/run.d.ts.map +1 -1
- package/dist/commands/project/split/run.js +48 -10
- package/dist/commands/project/sync/git.d.ts +18 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -0
- package/dist/commands/project/sync/git.js +60 -0
- package/dist/commands/project/sync/record.d.ts +22 -0
- package/dist/commands/project/sync/record.d.ts.map +1 -0
- package/dist/commands/project/sync/record.js +133 -0
- package/dist/commands/project/sync/ref-sync.d.ts +120 -0
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -0
- package/dist/commands/project/sync/ref-sync.js +962 -0
- package/dist/commands/project/sync/resolve-target.d.ts +27 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -0
- package/dist/commands/project/sync/resolve-target.js +159 -0
- package/dist/commands/shared/oat-paths.d.ts +4 -1
- package/dist/commands/shared/oat-paths.d.ts.map +1 -1
- package/dist/commands/shared/oat-paths.js +2 -2
- package/dist/commands/shared/project-scope.d.ts +23 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -0
- package/dist/commands/shared/project-scope.js +106 -0
- package/dist/commands/tools/migrate/index.js +1 -1
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-inventory.js +79 -8
- package/dist/commands/tools/shared/pack-lifecycle.js +1 -1
- package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-reconcile.js +4 -1
- package/dist/commands/tools/shared/project-tools-config.d.ts +6 -2
- package/dist/commands/tools/shared/project-tools-config.d.ts.map +1 -1
- package/dist/commands/tools/shared/project-tools-config.js +7 -5
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +38 -14
- package/dist/commands/tools/update/update-tools.d.ts +2 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/config/oat-config.d.ts +6 -3
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +41 -7
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +2 -1
- package/dist/fs/io.d.ts +2 -1
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +5 -2
- package/dist/projects/split/finalize.d.ts.map +1 -1
- package/dist/projects/split/finalize.js +55 -2
- package/dist/projects/split/resume.d.ts +3 -0
- package/dist/projects/split/resume.d.ts.map +1 -1
- package/dist/projects/split/resume.js +34 -7
- package/dist/projects/split/seed-children.d.ts.map +1 -1
- package/dist/projects/split/seed-children.js +6 -0
- package/dist/projects/split/write-parent.d.ts +7 -0
- package/dist/projects/split/write-parent.d.ts.map +1 -1
- package/dist/projects/split/write-parent.js +7 -4
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +1 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +434 -0
- package/package.json +4 -4
- package/dist/__tests__/skills/split-flow-fixtures.d.ts +0 -50
- package/dist/__tests__/skills/split-flow-fixtures.d.ts.map +0 -1
- package/dist/__tests__/skills/split-flow-fixtures.js +0 -161
- package/dist/commands/__tests__/helpers.d.ts +0 -12
- package/dist/commands/__tests__/helpers.d.ts.map +0 -1
- package/dist/commands/__tests__/helpers.js +0 -36
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { realpath } from 'node:fs/promises';
|
|
2
|
+
import { type GitRunner } from '../../project/sync/git.js';
|
|
3
|
+
import { resolveProjectsRoot } from '../../shared/oat-paths.js';
|
|
4
|
+
import { type OatLocalConfig } from '../../../config/oat-config.js';
|
|
5
|
+
import { classifyAdoptionRecord, type AdoptionRecordState, type SyncTarget } from './ref-sync.js';
|
|
6
|
+
export interface ResolveSyncedTargetContext {
|
|
7
|
+
repoRoot: string;
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
}
|
|
10
|
+
export interface ResolveSyncedTargetOptions {
|
|
11
|
+
allowMissingCheckout?: boolean;
|
|
12
|
+
allowStagedPruneDeletion?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ResolveSyncedTargetDependencies {
|
|
15
|
+
resolveProjectsRoot: typeof resolveProjectsRoot;
|
|
16
|
+
classifyAdoptionRecord: typeof classifyAdoptionRecord;
|
|
17
|
+
readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
|
|
18
|
+
pathExists: (path: string) => Promise<boolean>;
|
|
19
|
+
realpath: typeof realpath;
|
|
20
|
+
gitRunner: GitRunner;
|
|
21
|
+
}
|
|
22
|
+
export interface ResolvedSyncTarget extends SyncTarget {
|
|
23
|
+
adopt: boolean;
|
|
24
|
+
adoptionRecord: AdoptionRecordState;
|
|
25
|
+
}
|
|
26
|
+
export declare function resolveSyncedTarget(context: ResolveSyncedTargetContext, pathOrSlug?: string, overrides?: Partial<ResolveSyncedTargetDependencies>, options?: ResolveSyncedTargetOptions): Promise<ResolvedSyncTarget>;
|
|
27
|
+
//# sourceMappingURL=resolve-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-target.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/sync/resolve-target.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAOjE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAIL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,+BAA+B;IAC9C,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,mBAAmB,CAAC;CACrC;AAsFD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,EACnC,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,GAAE,OAAO,CAAC,+BAA+B,CAAM,EACxD,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,kBAAkB,CAAC,CA+H7B"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { defaultGitRunner } from '../../project/sync/git.js';
|
|
4
|
+
import { resolveProjectsRoot } from '../../shared/oat-paths.js';
|
|
5
|
+
import { assertValidProjectSlug, resolveProjectScope, resolveScopeRoot, syncedRecordPath, } from '../../shared/project-scope.js';
|
|
6
|
+
import { readOatLocalConfig } from '../../../config/oat-config.js';
|
|
7
|
+
import { CliError } from '../../../errors/cli-error.js';
|
|
8
|
+
import { assertCanonicalSyncTargetIdentity, buildSyncTarget, classifyRemoteRefLookup, classifyAdoptionRecord, } from './ref-sync.js';
|
|
9
|
+
async function pathExists(path) {
|
|
10
|
+
try {
|
|
11
|
+
await stat(path);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function isStagedPruneDeletion(target, git) {
|
|
22
|
+
const recordPath = syncedRecordPath(target.syncedRoot, target.slug);
|
|
23
|
+
const relativeRecord = relative(target.repoRoot, recordPath)
|
|
24
|
+
.split('\\')
|
|
25
|
+
.join('/');
|
|
26
|
+
const [localRef, remoteRef, stagedDeletion, priorRecord] = await Promise.all([
|
|
27
|
+
git.run(['show-ref', '--verify', '--quiet', target.ref], {
|
|
28
|
+
cwd: target.repoRoot,
|
|
29
|
+
allowFailure: true,
|
|
30
|
+
}),
|
|
31
|
+
git.run(['ls-remote', '--exit-code', target.remote, target.ref], {
|
|
32
|
+
cwd: target.repoRoot,
|
|
33
|
+
allowFailure: true,
|
|
34
|
+
}),
|
|
35
|
+
git.run([
|
|
36
|
+
'diff',
|
|
37
|
+
'--cached',
|
|
38
|
+
'--diff-filter=D',
|
|
39
|
+
'--name-only',
|
|
40
|
+
'--',
|
|
41
|
+
relativeRecord,
|
|
42
|
+
], { cwd: target.repoRoot, allowFailure: true }),
|
|
43
|
+
git.run(['show', `HEAD:${relativeRecord}`], {
|
|
44
|
+
cwd: target.repoRoot,
|
|
45
|
+
allowFailure: true,
|
|
46
|
+
}),
|
|
47
|
+
]);
|
|
48
|
+
const remoteState = classifyRemoteRefLookup(remoteRef, target.remote, target.ref);
|
|
49
|
+
if (localRef.code === 0 ||
|
|
50
|
+
remoteState === 'present' ||
|
|
51
|
+
stagedDeletion.code !== 0 ||
|
|
52
|
+
stagedDeletion.stdout !== relativeRecord ||
|
|
53
|
+
priorRecord.code !== 0) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const record = JSON.parse(priorRecord.stdout);
|
|
58
|
+
return (record.slug === target.slug &&
|
|
59
|
+
record.ref === target.ref &&
|
|
60
|
+
record.scope === 'synced');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const DEFAULT_DEPENDENCIES = {
|
|
67
|
+
resolveProjectsRoot,
|
|
68
|
+
classifyAdoptionRecord,
|
|
69
|
+
readOatLocalConfig,
|
|
70
|
+
pathExists,
|
|
71
|
+
realpath,
|
|
72
|
+
gitRunner: defaultGitRunner,
|
|
73
|
+
};
|
|
74
|
+
export async function resolveSyncedTarget(context, pathOrSlug, overrides = {}, options = {}) {
|
|
75
|
+
const dependencies = { ...DEFAULT_DEPENDENCIES, ...overrides };
|
|
76
|
+
const projectsRoot = await dependencies.resolveProjectsRoot(context.repoRoot, context.env ?? process.env);
|
|
77
|
+
const syncedRoot = resolveScopeRoot(context.repoRoot, projectsRoot, 'synced');
|
|
78
|
+
let requested = pathOrSlug;
|
|
79
|
+
if (!requested) {
|
|
80
|
+
requested =
|
|
81
|
+
(await dependencies.readOatLocalConfig(context.repoRoot)).activeProject ??
|
|
82
|
+
undefined;
|
|
83
|
+
if (!requested) {
|
|
84
|
+
throw new CliError('No active project is configured.', 1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const bareSlug = !isAbsolute(requested) && !/[\\/]/.test(requested);
|
|
88
|
+
if (bareSlug) {
|
|
89
|
+
assertValidProjectSlug(requested, 1);
|
|
90
|
+
}
|
|
91
|
+
const projectPath = bareSlug
|
|
92
|
+
? resolve(syncedRoot, requested)
|
|
93
|
+
: isAbsolute(requested)
|
|
94
|
+
? resolve(requested)
|
|
95
|
+
: resolve(context.repoRoot, requested);
|
|
96
|
+
let slug = requested;
|
|
97
|
+
if (!bareSlug) {
|
|
98
|
+
const scope = resolveProjectScope(projectPath, resolve(context.repoRoot, projectsRoot), context.repoRoot);
|
|
99
|
+
if (scope && scope !== 'synced') {
|
|
100
|
+
throw new CliError(`Project ${requested} is in ${scope} scope; this command requires synced scope.`, 1);
|
|
101
|
+
}
|
|
102
|
+
if (!scope) {
|
|
103
|
+
throw new CliError(`Project path is outside the synced project root: ${requested}`, 1);
|
|
104
|
+
}
|
|
105
|
+
const directChild = relative(syncedRoot, projectPath);
|
|
106
|
+
if (directChild === '' ||
|
|
107
|
+
directChild === '..' ||
|
|
108
|
+
directChild.startsWith(`..${sep}`) ||
|
|
109
|
+
isAbsolute(directChild) ||
|
|
110
|
+
directChild.includes(sep)) {
|
|
111
|
+
throw new CliError(`Project path must identify exactly one direct child of the synced project root: ${requested}`, 1);
|
|
112
|
+
}
|
|
113
|
+
assertValidProjectSlug(directChild, 1);
|
|
114
|
+
slug = directChild;
|
|
115
|
+
}
|
|
116
|
+
const target = buildSyncTarget(context.repoRoot, projectsRoot, slug);
|
|
117
|
+
const checkoutExists = await assertCanonicalSyncTargetIdentity(target, {
|
|
118
|
+
pathExists: dependencies.pathExists,
|
|
119
|
+
realpath: dependencies.realpath,
|
|
120
|
+
exitCode: 1,
|
|
121
|
+
});
|
|
122
|
+
if (!bareSlug &&
|
|
123
|
+
!checkoutExists &&
|
|
124
|
+
options.allowStagedPruneDeletion &&
|
|
125
|
+
(await isStagedPruneDeletion(target, dependencies.gitRunner))) {
|
|
126
|
+
return {
|
|
127
|
+
...target,
|
|
128
|
+
adopt: false,
|
|
129
|
+
adoptionRecord: 'durable',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const adoptionRecord = await dependencies.classifyAdoptionRecord(target, dependencies.gitRunner);
|
|
133
|
+
let adopt = adoptionRecord === 'pending';
|
|
134
|
+
if (!checkoutExists && adoptionRecord === 'create') {
|
|
135
|
+
if (options.allowMissingCheckout) {
|
|
136
|
+
const remote = await dependencies.gitRunner.run(['ls-remote', '--exit-code', target.remote, target.ref], { cwd: context.repoRoot, allowFailure: true });
|
|
137
|
+
if (remote.code === 0) {
|
|
138
|
+
adopt = true;
|
|
139
|
+
}
|
|
140
|
+
else if (!(remote.code === 2 &&
|
|
141
|
+
remote.stdout.trim() === '' &&
|
|
142
|
+
remote.stderr.trim() === '')) {
|
|
143
|
+
throw new CliError(`git ls-remote ${target.remote} ${target.ref} failed (exit ${remote.code}): ${remote.stderr || remote.stdout || 'unknown Git error'}`, 2);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!adopt) {
|
|
147
|
+
throw new CliError(`No synced project named ${slug} locally or on origin.`, 1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (!checkoutExists && !options.allowMissingCheckout) {
|
|
151
|
+
throw new CliError(`No synced project named ${slug}.`, 1);
|
|
152
|
+
}
|
|
153
|
+
else if (checkoutExists &&
|
|
154
|
+
adoptionRecord === 'create' &&
|
|
155
|
+
options.allowMissingCheckout) {
|
|
156
|
+
adopt = true;
|
|
157
|
+
}
|
|
158
|
+
return { ...target, adopt, adoptionRecord };
|
|
159
|
+
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { type OatConfig } from '../../config/oat-config.js';
|
|
2
|
+
type OatConfigReader = (repoRoot: string) => Promise<OatConfig>;
|
|
3
|
+
export declare function resolveProjectsRoot(repoRoot: string, env: NodeJS.ProcessEnv, readConfig?: OatConfigReader): Promise<string>;
|
|
4
|
+
export {};
|
|
2
5
|
//# sourceMappingURL=oat-paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oat-paths.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/oat-paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oat-paths.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/oat-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEnE,KAAK,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhE,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,UAAU,GAAE,eAA+B,GAC1C,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readOatConfig } from '../../config/oat-config.js';
|
|
2
|
-
export async function resolveProjectsRoot(repoRoot, env) {
|
|
2
|
+
export async function resolveProjectsRoot(repoRoot, env, readConfig = readOatConfig) {
|
|
3
3
|
const envRoot = env.OAT_PROJECTS_ROOT?.trim();
|
|
4
4
|
if (envRoot) {
|
|
5
5
|
return envRoot.replace(/\/+$/, '');
|
|
6
6
|
}
|
|
7
|
-
const config = await
|
|
7
|
+
const config = await readConfig(repoRoot);
|
|
8
8
|
const configRoot = config.projects?.root?.trim();
|
|
9
9
|
if (configRoot) {
|
|
10
10
|
return configRoot.replace(/\/+$/, '');
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type ProjectScope = 'shared' | 'local' | 'synced';
|
|
2
|
+
export declare const PROJECT_SCOPES: readonly ["shared", "local", "synced"];
|
|
3
|
+
export declare const SYNCED_REF_NAMESPACE = "refs/oat/projects";
|
|
4
|
+
export declare const SYNCED_REMOTE = "origin";
|
|
5
|
+
export declare function canonicalizePath(path: string): string;
|
|
6
|
+
interface EffectiveConfigResult {
|
|
7
|
+
resolved: Record<string, {
|
|
8
|
+
value: unknown;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
interface ProjectScopeDependencies {
|
|
12
|
+
resolveEffectiveConfig: (repoRoot: string, userConfigDir: string, env: NodeJS.ProcessEnv) => Promise<EffectiveConfigResult>;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveProjectsParent(repoRoot: string, projectsRoot: string): string;
|
|
15
|
+
export declare function resolveScopeRoot(repoRoot: string, projectsRoot: string, scope: ProjectScope): string;
|
|
16
|
+
export declare function resolveProjectScope(projectPath: string, projectsRoot: string, repoRoot: string): ProjectScope | null;
|
|
17
|
+
export declare function assertValidProjectSlug(slug: string, exitCode?: 1 | 2): void;
|
|
18
|
+
export declare function syncedRefName(slug: string): string;
|
|
19
|
+
export declare function syncedRecordPath(scopeRoot: string, slug: string): string;
|
|
20
|
+
export declare function isSyncedCheckout(projectPath: string): Promise<boolean>;
|
|
21
|
+
export declare function resolveDefaultScope(repoRoot: string, env: NodeJS.ProcessEnv, dependencies?: Partial<ProjectScopeDependencies>): Promise<ProjectScope>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=project-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-scope.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/project-scope.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEzD,eAAO,MAAM,cAAc,wCAIiB,CAAC;AAC7C,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AACxD,eAAO,MAAM,aAAa,WAAW,CAAC;AAItC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBrD;AAED,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9C;AAED,UAAU,wBAAwB;IAChC,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrC;AAMD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,CAKR;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,YAAY,GAClB,MAAM,CAOR;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,YAAY,GAAG,IAAI,CAmBrB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,CAAC,GAAG,CAAK,GAClB,IAAI,CAON;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxE;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa5E;AAeD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,YAAY,GAAE,OAAO,CAAC,wBAAwB,CAAM,GACnD,OAAO,CAAC,YAAY,CAAC,CAqBvB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from 'node:path';
|
|
5
|
+
import { resolveEffectiveConfig as defaultResolveEffectiveConfig } from '../../config/resolve.js';
|
|
6
|
+
import { CliError } from '../../errors/cli-error.js';
|
|
7
|
+
export const PROJECT_SCOPES = [
|
|
8
|
+
'shared',
|
|
9
|
+
'local',
|
|
10
|
+
'synced',
|
|
11
|
+
];
|
|
12
|
+
export const SYNCED_REF_NAMESPACE = 'refs/oat/projects';
|
|
13
|
+
export const SYNCED_REMOTE = 'origin';
|
|
14
|
+
const PROJECT_SLUG_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
15
|
+
export function canonicalizePath(path) {
|
|
16
|
+
const absolute = resolve(path);
|
|
17
|
+
try {
|
|
18
|
+
return realpathSync(absolute);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) {
|
|
22
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
23
|
+
throw new CliError(`Unable to resolve canonical path \`${absolute}\`: ${detail}`, 2);
|
|
24
|
+
}
|
|
25
|
+
const parent = dirname(absolute);
|
|
26
|
+
if (parent === absolute) {
|
|
27
|
+
return absolute;
|
|
28
|
+
}
|
|
29
|
+
return join(canonicalizePath(parent), basename(absolute));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const DEFAULT_DEPENDENCIES = {
|
|
33
|
+
resolveEffectiveConfig: defaultResolveEffectiveConfig,
|
|
34
|
+
};
|
|
35
|
+
export function resolveProjectsParent(repoRoot, projectsRoot) {
|
|
36
|
+
const resolvedRoot = isAbsolute(projectsRoot)
|
|
37
|
+
? canonicalizePath(projectsRoot)
|
|
38
|
+
: resolve(repoRoot, projectsRoot);
|
|
39
|
+
return dirname(resolvedRoot);
|
|
40
|
+
}
|
|
41
|
+
export function resolveScopeRoot(repoRoot, projectsRoot, scope) {
|
|
42
|
+
const resolvedSharedRoot = isAbsolute(projectsRoot)
|
|
43
|
+
? canonicalizePath(projectsRoot)
|
|
44
|
+
: resolve(repoRoot, projectsRoot);
|
|
45
|
+
return scope === 'shared'
|
|
46
|
+
? resolvedSharedRoot
|
|
47
|
+
: join(dirname(resolvedSharedRoot), scope);
|
|
48
|
+
}
|
|
49
|
+
export function resolveProjectScope(projectPath, projectsRoot, repoRoot) {
|
|
50
|
+
const canonicalProjectPath = canonicalizePath(isAbsolute(projectPath) ? projectPath : resolve(repoRoot, projectPath));
|
|
51
|
+
for (const scope of PROJECT_SCOPES) {
|
|
52
|
+
const scopeRoot = canonicalizePath(resolveScopeRoot(repoRoot, projectsRoot, scope));
|
|
53
|
+
const projectRelative = relative(scopeRoot, canonicalProjectPath);
|
|
54
|
+
if (projectRelative !== '' &&
|
|
55
|
+
projectRelative !== '..' &&
|
|
56
|
+
!projectRelative.startsWith(`..${sep}`) &&
|
|
57
|
+
!isAbsolute(projectRelative)) {
|
|
58
|
+
return scope;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
export function assertValidProjectSlug(slug, exitCode = 2) {
|
|
64
|
+
if (slug.startsWith('-') || !PROJECT_SLUG_PATTERN.test(slug)) {
|
|
65
|
+
throw new CliError(`Invalid project slug "${slug}". Use letters, numbers, dash, and underscore, and do not start with a dash.`, exitCode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function syncedRefName(slug) {
|
|
69
|
+
assertValidProjectSlug(slug);
|
|
70
|
+
return `${SYNCED_REF_NAMESPACE}/${slug}`;
|
|
71
|
+
}
|
|
72
|
+
export function syncedRecordPath(scopeRoot, slug) {
|
|
73
|
+
assertValidProjectSlug(slug);
|
|
74
|
+
return join(scopeRoot, `${slug}.json`);
|
|
75
|
+
}
|
|
76
|
+
export async function isSyncedCheckout(projectPath) {
|
|
77
|
+
try {
|
|
78
|
+
return (await stat(join(projectPath, '.git'))).isFile();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof Error &&
|
|
82
|
+
'code' in error &&
|
|
83
|
+
(error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function parseScope(value, source) {
|
|
90
|
+
if (value === undefined || value === null || value === '') {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
if (PROJECT_SCOPES.includes(value)) {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
throw new CliError(`Invalid project scope from ${source}: "${String(value)}". Expected one of: ${PROJECT_SCOPES.join(', ')}.`, 2);
|
|
97
|
+
}
|
|
98
|
+
export async function resolveDefaultScope(repoRoot, env, dependencies = {}) {
|
|
99
|
+
const envScope = parseScope(env.OAT_PROJECTS_DEFAULT_SCOPE?.trim(), 'OAT_PROJECTS_DEFAULT_SCOPE');
|
|
100
|
+
if (envScope) {
|
|
101
|
+
return envScope;
|
|
102
|
+
}
|
|
103
|
+
const deps = { ...DEFAULT_DEPENDENCIES, ...dependencies };
|
|
104
|
+
const effective = await deps.resolveEffectiveConfig(repoRoot, join(homedir(), '.oat'), env);
|
|
105
|
+
return (parseScope(effective.resolved['projects.defaultScope']?.value, 'projects.defaultScope') ?? 'synced');
|
|
106
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pack-inventory.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-inventory.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,uBAAuB,GACvB,iBAAiB,GACjB,0BAA0B,GAC1B,2BAA2B,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACvD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA8QD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CAmC9B;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAUT;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,aAAa,CAAC,CA0DxB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { lstat } from 'node:fs/promises';
|
|
1
|
+
import { lstat, readdir, readlink } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { compareVersions } from '../../init/tools/shared/version.js';
|
|
4
4
|
import { getAgentVersion, getSkillVersion } from '../../shared/frontmatter.js';
|
|
5
|
-
import {
|
|
5
|
+
import { readOatConfig } from '../../../config/oat-config.js';
|
|
6
|
+
import { resolveManagedScopeRoots, validateManagedPath, validateRealPathWithinScope, } from '../../../fs/paths.js';
|
|
6
7
|
import { USER_SCOPE_MANAGED_AGENT_FILES, } from '../../../shared/types.js';
|
|
7
8
|
import { digestDirectory, digestFile } from './content-digest.js';
|
|
8
9
|
import { getPackDefinition } from './pack-manifest.js';
|
|
@@ -28,14 +29,62 @@ async function inventoryVersionedAsset(definition, installedPath, bundledPath) {
|
|
|
28
29
|
readVersion(installedPath),
|
|
29
30
|
readVersion(bundledPath),
|
|
30
31
|
]);
|
|
32
|
+
const versionStatus = compareVersions(installedVersion, bundledVersion);
|
|
33
|
+
const contentMatches = versionStatus !== 'current'
|
|
34
|
+
? null
|
|
35
|
+
: definition.kind === 'skill'
|
|
36
|
+
? await canonicalDirectoryMatches(installedPath, bundledPath)
|
|
37
|
+
: await canonicalFileMatches(installedPath, bundledPath);
|
|
31
38
|
return {
|
|
32
39
|
definition,
|
|
33
40
|
path: installedPath,
|
|
34
|
-
status:
|
|
41
|
+
status: versionStatus === 'current' && !contentMatches
|
|
42
|
+
? 'outdated'
|
|
43
|
+
: versionStatus,
|
|
35
44
|
installedVersion,
|
|
36
45
|
bundledVersion,
|
|
37
46
|
};
|
|
38
47
|
}
|
|
48
|
+
async function canonicalFileMatches(installedPath, bundledPath) {
|
|
49
|
+
const [installedDigest, bundledDigest] = await Promise.all([
|
|
50
|
+
digestFile(installedPath, 0o644),
|
|
51
|
+
digestFile(bundledPath, 0o644),
|
|
52
|
+
]);
|
|
53
|
+
return installedDigest === bundledDigest;
|
|
54
|
+
}
|
|
55
|
+
async function canonicalDirectoryMatches(installedRoot, bundledRoot) {
|
|
56
|
+
const entries = await readdir(bundledRoot, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const installedPath = join(installedRoot, entry.name);
|
|
59
|
+
const bundledPath = join(bundledRoot, entry.name);
|
|
60
|
+
if (!(await pathExists(installedPath)))
|
|
61
|
+
return false;
|
|
62
|
+
const installedMetadata = await lstat(installedPath);
|
|
63
|
+
if (entry.isDirectory()) {
|
|
64
|
+
if (!installedMetadata.isDirectory() ||
|
|
65
|
+
!(await canonicalDirectoryMatches(installedPath, bundledPath))) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (entry.isFile()) {
|
|
71
|
+
if (!installedMetadata.isFile() ||
|
|
72
|
+
!(await canonicalFileMatches(installedPath, bundledPath))) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (entry.isSymbolicLink()) {
|
|
78
|
+
if (!installedMetadata.isSymbolicLink() ||
|
|
79
|
+
(await readlink(installedPath)) !== (await readlink(bundledPath))) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Unsupported filesystem entry in pack asset: ${bundledPath}`);
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
39
88
|
async function inventoryStaticAsset(definition, installedPath, bundledPath) {
|
|
40
89
|
const [installedDigest, bundledDigest] = definition.kind === 'directory'
|
|
41
90
|
? await Promise.all([
|
|
@@ -71,18 +120,40 @@ async function inventoryAsset(definition, scope, scopeRoot, assetsRoot, managedR
|
|
|
71
120
|
};
|
|
72
121
|
}
|
|
73
122
|
if (definition.ownership[scope] === 'seed-if-missing') {
|
|
123
|
+
if (definition.generation) {
|
|
124
|
+
if (definition.generation === 'projects-config-default') {
|
|
125
|
+
const config = await readOatConfig(scopeRoot);
|
|
126
|
+
return {
|
|
127
|
+
definition,
|
|
128
|
+
path: installedPath,
|
|
129
|
+
status: config.projects?.root?.trim() ? 'present' : 'outdated',
|
|
130
|
+
installedVersion: null,
|
|
131
|
+
bundledVersion: null,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
definition,
|
|
136
|
+
path: installedPath,
|
|
137
|
+
status: 'present',
|
|
138
|
+
installedVersion: null,
|
|
139
|
+
bundledVersion: null,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (!definition.source) {
|
|
143
|
+
throw new Error(`Seeded pack asset ${definition.id} has no materialized source`);
|
|
144
|
+
}
|
|
145
|
+
const { realPath: bundledPath } = await validateRealPathWithinScope(join(assetsRoot, definition.source), assetsRoot);
|
|
146
|
+
const inventory = await inventoryStaticAsset(definition, realPath, bundledPath);
|
|
74
147
|
return {
|
|
75
|
-
|
|
148
|
+
...inventory,
|
|
76
149
|
path: installedPath,
|
|
77
|
-
status: 'present',
|
|
78
|
-
installedVersion: null,
|
|
79
|
-
bundledVersion: null,
|
|
150
|
+
status: inventory.status === 'current' ? 'current' : 'present',
|
|
80
151
|
};
|
|
81
152
|
}
|
|
82
153
|
if (!definition.source) {
|
|
83
154
|
throw new Error(`Managed pack asset ${definition.id} has no materialized source`);
|
|
84
155
|
}
|
|
85
|
-
const bundledPath = join(assetsRoot, definition.source);
|
|
156
|
+
const { realPath: bundledPath } = await validateRealPathWithinScope(join(assetsRoot, definition.source), assetsRoot);
|
|
86
157
|
if (definition.kind === 'skill' || definition.kind === 'agent') {
|
|
87
158
|
const inventory = await inventoryVersionedAsset(definition, realPath, bundledPath);
|
|
88
159
|
return { ...inventory, path: installedPath };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-reconcile.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,KAAK,EAEV,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,qBAAqB,CAAC;AAE1B,MAAM,MAAM,sBAAsB,GAC9B;IACE,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,mBAAmB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrE;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEN,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,oBAAoB,EAAE,gBAAgB,CAAC;IACvC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,cAAc,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IAChC,MAAM,EAAE,uBAAuB,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,CACpB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAmDrC;
|
|
1
|
+
{"version":3,"file":"pack-reconcile.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,KAAK,EAEV,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,qBAAqB,CAAC;AAE1B,MAAM,MAAM,sBAAsB,GAC9B;IACE,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,mBAAmB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrE;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEN,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,oBAAoB,EAAE,gBAAgB,CAAC;IACvC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,cAAc,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IAChC,MAAM,EAAE,uBAAuB,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,CACpB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAmDrC;AAqFD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,CA4EnB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAE1E"}
|
|
@@ -49,7 +49,10 @@ function materializationOperations(asset, input) {
|
|
|
49
49
|
const observed = input.inventory.assets.find(({ definition }) => definition.id === asset.id);
|
|
50
50
|
const ownership = asset.ownership[input.scope];
|
|
51
51
|
const isMissing = observed?.status === 'missing';
|
|
52
|
-
if (ownership === 'seed-if-missing' &&
|
|
52
|
+
if (ownership === 'seed-if-missing' &&
|
|
53
|
+
!isMissing &&
|
|
54
|
+
!(asset.generation === 'projects-config-default' &&
|
|
55
|
+
observed?.status === 'outdated'))
|
|
53
56
|
return [];
|
|
54
57
|
if (ownership === 'managed' && observed?.status === 'current')
|
|
55
58
|
return [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type OatConfig } from '../../../config/oat-config.js';
|
|
2
2
|
import { type ScanToolsOptions } from './scan-tools.js';
|
|
3
|
-
import type { ToolInfo } from './types.js';
|
|
3
|
+
import type { PackName, ToolInfo } from './types.js';
|
|
4
4
|
export interface ReconcileProjectToolsOptions {
|
|
5
5
|
repoRoot: string;
|
|
6
6
|
cwd: string;
|
|
@@ -12,5 +12,9 @@ export interface ProjectToolsConfigDependencies {
|
|
|
12
12
|
readOatConfig: (repoRoot: string) => Promise<OatConfig>;
|
|
13
13
|
writeOatConfig: (repoRoot: string, config: OatConfig) => Promise<void>;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
15
|
+
export interface ReconcileProjectToolsResult {
|
|
16
|
+
action: 'written' | 'unchanged';
|
|
17
|
+
adoptedPacks: PackName[];
|
|
18
|
+
}
|
|
19
|
+
export declare function reconcileProjectToolsConfig(options: ReconcileProjectToolsOptions, dependencies?: ProjectToolsConfigDependencies): Promise<ReconcileProjectToolsResult>;
|
|
16
20
|
//# sourceMappingURL=project-tools-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tools-config.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/project-tools-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"project-tools-config.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/project-tools-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAChC,YAAY,EAAE,QAAQ,EAAE,CAAC;CAC1B;AASD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,4BAA4B,EACrC,YAAY,GAAE,8BAAoD,GACjE,OAAO,CAAC,2BAA2B,CAAC,CA6BtC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readOatConfig, writeOatConfig, } from '../../../config/oat-config.js';
|
|
2
2
|
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
3
|
+
import { PACK_NAMES } from './pack-manifest.js';
|
|
3
4
|
import { scanTools } from './scan-tools.js';
|
|
4
5
|
const defaultDependencies = {
|
|
5
6
|
resolveAssetsRoot,
|
|
@@ -16,18 +17,19 @@ export async function reconcileProjectToolsConfig(options, dependencies = defaul
|
|
|
16
17
|
});
|
|
17
18
|
const config = await dependencies.readOatConfig(options.repoRoot);
|
|
18
19
|
const tools = { ...config.tools };
|
|
19
|
-
|
|
20
|
+
const adopted = new Set();
|
|
20
21
|
for (const tool of projectTools) {
|
|
21
22
|
if (tool.scope === 'project' &&
|
|
22
23
|
tool.pack !== 'custom' &&
|
|
23
24
|
tools[tool.pack] !== true) {
|
|
24
25
|
tools[tool.pack] = true;
|
|
25
|
-
|
|
26
|
+
adopted.add(tool.pack);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const adoptedPacks = PACK_NAMES.filter((pack) => adopted.has(pack));
|
|
30
|
+
if (adoptedPacks.length === 0) {
|
|
31
|
+
return { action: 'unchanged', adoptedPacks };
|
|
30
32
|
}
|
|
31
33
|
await dependencies.writeOatConfig(options.repoRoot, { ...config, tools });
|
|
32
|
-
return 'written';
|
|
34
|
+
return { action: 'written', adoptedPacks };
|
|
33
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAK1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAmBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CA8MT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAS7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
|