@open-agent-toolkit/cli 0.2.30 → 0.2.32
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/configuration.md +41 -0
- package/assets/docs/contributing/code.md +19 -7
- package/assets/docs/contributing/explainer-kit-verification.md +9 -1
- package/assets/docs/contributing/skills.md +9 -0
- package/assets/docs/provider-sync/commands.md +15 -10
- package/assets/docs/provider-sync/manifest-and-drift.md +23 -0
- package/assets/docs/provider-sync/providers.md +8 -2
- package/assets/docs/provider-sync/scope-and-surface.md +3 -1
- package/assets/docs/reference/file-locations.md +5 -0
- package/assets/docs/reference/troubleshooting.md +18 -0
- package/assets/docs/workflows/skills/explainer-kit-providers.md +16 -5
- package/assets/docs/workflows/skills/explainer-kit.md +98 -38
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +34 -22
- package/assets/skills/explainer-kit/SKILL.md +33 -8
- package/assets/skills/explainer-kit/briefs/project-recap.md +25 -7
- package/assets/skills/explainer-kit/recipes/project-recap.v2.json +72 -0
- package/assets/skills/explainer-kit/references/contracts.md +49 -17
- package/assets/skills/explainer-kit/references/destination-contract.md +141 -25
- package/assets/skills/explainer-kit/references/extension-contract.md +19 -10
- package/assets/skills/explainer-kit/references/visual-authoring.md +24 -0
- package/assets/skills/explainer-kit/references/visual-review.md +19 -5
- package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +241 -0
- package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +215 -0
- package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +34 -0
- package/assets/skills/explainer-kit/schemas/run-request.schema.json +4 -1
- package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +81 -0
- package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +66 -0
- package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +109 -3
- package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +550 -17
- package/assets/skills/explainer-kit/scripts/lib/durability.mjs +90 -8
- package/assets/skills/explainer-kit/scripts/lib/fs-safe.mjs +5 -0
- package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +538 -0
- package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +129 -11
- package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +54 -0
- package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +2 -1
- package/assets/skills/explainer-kit/scripts/lib/records.mjs +139 -22
- package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +353 -0
- package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +237 -107
- package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +1 -0
- package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +157 -0
- package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +26 -6
- package/assets/skills/explainer-kit/scripts/run.mjs +1006 -144
- package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +14 -2
- package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +14 -2
- package/assets/skills/oat-explainer-kit/SKILL.md +16 -3
- package/assets/skills/oat-explainer-kit/references/config-contract.md +13 -8
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +50 -6
- package/assets/skills/oat-explainer-kit/references/migration.md +2 -1
- package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +11 -0
- package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +37 -15
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +83 -0
- package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +91 -0
- package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +66 -10
- package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +60 -21
- package/assets/skills/oat-explainer-kit/scripts/resolve-paths.mjs +52 -8
- package/assets/skills/oat-explainer-kit/scripts/run.mjs +271 -36
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +19 -3
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +8 -0
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +18 -0
- package/dist/commands/init/index.d.ts +2 -2
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +22 -13
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +57 -7
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +29 -0
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +1 -0
- package/dist/commands/project/archive/explainer-terminal-evidence.js +37 -0
- package/dist/commands/remove/skill/remove-skill.d.ts +4 -1
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +44 -5
- package/dist/commands/shared/adopt-stray.d.ts +5 -0
- package/dist/commands/shared/adopt-stray.d.ts.map +1 -1
- package/dist/commands/shared/adopt-stray.js +25 -4
- package/dist/commands/shared/native-skill-disposition.d.ts +22 -0
- package/dist/commands/shared/native-skill-disposition.d.ts.map +1 -0
- package/dist/commands/shared/native-skill-disposition.js +60 -0
- package/dist/commands/status/index.d.ts +2 -2
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +22 -13
- package/dist/config/oat-config.d.ts +2 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +4 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +1 -0
- package/dist/engine/compute-plan.d.ts +3 -2
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/providers/copilot/paths.d.ts.map +1 -1
- package/dist/providers/copilot/paths.js +6 -4
- package/package.json +2 -2
- package/dist/commands/shared/cursor-skill-disposition.d.ts +0 -17
- package/dist/commands/shared/cursor-skill-disposition.d.ts.map +0 -1
- package/dist/commands/shared/cursor-skill-disposition.js +0 -41
- /package/assets/skills/explainer-kit/recipes/{project-recap.json → project-recap.v1.json} +0 -0
- /package/assets/skills/explainer-kit/schemas/{publish-receipt.schema.json → publish-receipt.v1.schema.json} +0 -0
- /package/assets/skills/explainer-kit/schemas/{publish-request.schema.json → publish-request.v1.schema.json} +0 -0
|
@@ -7,6 +7,7 @@ import { CliError } from '../../../errors/cli-error.js';
|
|
|
7
7
|
import { copyDirectory, copySingleFile, dirExists, ensureDir, fileExists, } from '../../../fs/io.js';
|
|
8
8
|
import { loadExplainerPackageCoverage } from './explainer-package-coverage.js';
|
|
9
9
|
import { loadExplainerSourceBacklinks, } from './explainer-source-backlinks.js';
|
|
10
|
+
import { loadExplainerTerminalEvidence } from './explainer-terminal-evidence.js';
|
|
10
11
|
const execFileAsync = promisify(execFileCallback);
|
|
11
12
|
export const ARCHIVE_SNAPSHOT_METADATA_FILENAME = '.oat-archive-source.json';
|
|
12
13
|
/**
|
|
@@ -564,6 +565,25 @@ async function readVerifiedRunMode(runRoot) {
|
|
|
564
565
|
}
|
|
565
566
|
return request.mode;
|
|
566
567
|
}
|
|
568
|
+
async function verifyProjectRecapTerminalEvidence(runRoot, manifest, expected) {
|
|
569
|
+
if (!['built-needs-review', 'failed'].includes(manifest.outcome)) {
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
try {
|
|
573
|
+
const terminalEvidence = await loadExplainerTerminalEvidence();
|
|
574
|
+
const verified = await terminalEvidence.readTerminalEvidenceFile(runRoot, {
|
|
575
|
+
manifest,
|
|
576
|
+
...(expected && {
|
|
577
|
+
expectedBytes: expected.bytes,
|
|
578
|
+
expectedHash: expected.hash,
|
|
579
|
+
}),
|
|
580
|
+
});
|
|
581
|
+
return { bytes: verified.bytes, hash: verified.hash };
|
|
582
|
+
}
|
|
583
|
+
catch {
|
|
584
|
+
throw new CliError('Selected project recap requires valid confined terminal evidence before archival.');
|
|
585
|
+
}
|
|
586
|
+
}
|
|
567
587
|
async function loadVerifiedProjectRecap(projectPath, projectRecapRun) {
|
|
568
588
|
const sourceRunRoot = await resolveSelectedProjectRecapRun(projectPath, projectRecapRun);
|
|
569
589
|
const manifestContents = await readFile(join(sourceRunRoot, 'manifest.json'), 'utf8');
|
|
@@ -571,9 +591,6 @@ async function loadVerifiedProjectRecap(projectPath, projectRecapRun) {
|
|
|
571
591
|
if (manifest.recipe.id !== 'project-recap') {
|
|
572
592
|
throw new CliError('Selected project recap manifest recipe must be exactly `project-recap`.');
|
|
573
593
|
}
|
|
574
|
-
if (manifest.outcome === 'built-needs-review') {
|
|
575
|
-
throw new CliError('Selected project recap is built-needs-review and requires a passing visual review before archival.');
|
|
576
|
-
}
|
|
577
594
|
const verifiedArtifactCount = await verifyProjectRecapImmutableHashes(sourceRunRoot, manifest);
|
|
578
595
|
const runMode = await readVerifiedRunMode(sourceRunRoot);
|
|
579
596
|
const packageCoverage = await loadExplainerPackageCoverage();
|
|
@@ -605,11 +622,29 @@ async function loadVerifiedProjectRecap(projectPath, projectRecapRun) {
|
|
|
605
622
|
artifact.hash !== manifest.immutableHashes[artifact.renderedPath])) {
|
|
606
623
|
throw new CliError('Selected project recap artifact hashes do not match the immutable package.');
|
|
607
624
|
}
|
|
625
|
+
const terminalEvidence = await verifyProjectRecapTerminalEvidence(sourceRunRoot, manifest);
|
|
626
|
+
const exactCoverage = packageCoverage;
|
|
627
|
+
if (typeof exactCoverage.permissibleRunPackagePaths !== 'function' ||
|
|
628
|
+
typeof exactCoverage.enforceRunPackageInventory !== 'function') {
|
|
629
|
+
throw new CliError('Bundled explainer package coverage does not provide the exact run inventory.');
|
|
630
|
+
}
|
|
631
|
+
try {
|
|
632
|
+
await exactCoverage.enforceRunPackageInventory(sourceRunRoot, manifest, {
|
|
633
|
+
includeTerminalEvidence: terminalEvidence !== null,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
catch {
|
|
637
|
+
throw new CliError('Selected project recap package inventory is invalid.');
|
|
638
|
+
}
|
|
608
639
|
return {
|
|
609
640
|
sourceRunRoot,
|
|
610
641
|
manifestContents,
|
|
611
642
|
manifest,
|
|
612
643
|
verifiedArtifactCount,
|
|
644
|
+
terminalEvidence,
|
|
645
|
+
packagePaths: exactCoverage.permissibleRunPackagePaths(manifest, {
|
|
646
|
+
includeTerminalEvidence: terminalEvidence !== null,
|
|
647
|
+
}),
|
|
613
648
|
};
|
|
614
649
|
}
|
|
615
650
|
export async function verifySelectedProjectRecapForArchive(projectPath, projectRecapRun) {
|
|
@@ -621,25 +656,40 @@ async function exportSelectedProjectRecap(options, snapshotName, dependencies) {
|
|
|
621
656
|
return null;
|
|
622
657
|
}
|
|
623
658
|
const verified = await loadVerifiedProjectRecap(options.projectPath, selectedRun);
|
|
624
|
-
const { sourceRunRoot, manifestContents: sourceManifestContents,
|
|
659
|
+
const { sourceRunRoot, manifestContents: sourceManifestContents, terminalEvidence: sourceTerminalEvidence, packagePaths, } = verified;
|
|
625
660
|
const exportRoot = join(options.repoRoot, '.oat', 'repo', 'reference', 'project-recaps', snapshotName);
|
|
626
661
|
if (await pathExists(exportRoot)) {
|
|
627
662
|
throw new CliError(`Project recap export destination \`${exportRoot}\` already exists; refusing to overwrite it.`);
|
|
628
663
|
}
|
|
629
664
|
const temporaryRoot = `${exportRoot}.tmp-${randomUUID()}`;
|
|
630
665
|
const makeDir = dependencies.ensureDir ?? ensureDir;
|
|
631
|
-
const
|
|
666
|
+
const copyFile = dependencies.copySingleFile ?? copySingleFile;
|
|
632
667
|
const removePath = dependencies.removePath ??
|
|
633
668
|
(async (target, removeOptions) => rm(target, removeOptions));
|
|
634
669
|
const renamePath = dependencies.renamePath ?? rename;
|
|
635
670
|
await makeDir(dirname(exportRoot));
|
|
636
671
|
try {
|
|
637
|
-
|
|
672
|
+
for (const relativePath of packagePaths) {
|
|
673
|
+
const destination = join(temporaryRoot, relativePath);
|
|
674
|
+
await makeDir(dirname(destination));
|
|
675
|
+
await copyFile(join(sourceRunRoot, relativePath), destination);
|
|
676
|
+
}
|
|
638
677
|
const stagedManifestContents = await readFile(join(temporaryRoot, 'manifest.json'), 'utf8');
|
|
639
678
|
if (stagedManifestContents !== sourceManifestContents) {
|
|
640
679
|
throw new CliError('Selected project recap manifest changed while staging the export.');
|
|
641
680
|
}
|
|
642
|
-
const
|
|
681
|
+
const stagedManifest = await parseProjectRecapManifest(stagedManifestContents);
|
|
682
|
+
const verifiedArtifactCount = await verifyProjectRecapImmutableHashes(temporaryRoot, stagedManifest);
|
|
683
|
+
const stagedTerminalEvidence = await verifyProjectRecapTerminalEvidence(temporaryRoot, stagedManifest, sourceTerminalEvidence ?? undefined);
|
|
684
|
+
const exactCoverage = (await loadExplainerPackageCoverage());
|
|
685
|
+
try {
|
|
686
|
+
await exactCoverage.enforceRunPackageInventory(temporaryRoot, stagedManifest, {
|
|
687
|
+
includeTerminalEvidence: stagedTerminalEvidence !== null,
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
throw new CliError('Staged project recap package inventory is invalid.');
|
|
692
|
+
}
|
|
643
693
|
await renamePath(temporaryRoot, exportRoot);
|
|
644
694
|
return {
|
|
645
695
|
sourceRunRoot,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const TERMINAL_EVIDENCE_VERSION = "explainer-kit.terminal-evidence/v1";
|
|
2
|
+
export interface ExplainerTerminalEvidence {
|
|
3
|
+
TERMINAL_EVIDENCE_VERSION: typeof TERMINAL_EVIDENCE_VERSION;
|
|
4
|
+
assertTerminalEvidence: (evidence: unknown, context: {
|
|
5
|
+
manifest: unknown;
|
|
6
|
+
}) => unknown;
|
|
7
|
+
readTerminalEvidenceFile: (runRoot: string, context: {
|
|
8
|
+
manifest: unknown;
|
|
9
|
+
expectedBytes?: Uint8Array;
|
|
10
|
+
expectedHash?: string;
|
|
11
|
+
}) => Promise<{
|
|
12
|
+
evidence: unknown;
|
|
13
|
+
bytes: Buffer;
|
|
14
|
+
hash: string;
|
|
15
|
+
}>;
|
|
16
|
+
writeTerminalEvidence: (run: {
|
|
17
|
+
runId: string;
|
|
18
|
+
slug: string;
|
|
19
|
+
runRoot: string;
|
|
20
|
+
}, input: {
|
|
21
|
+
outcome: string;
|
|
22
|
+
manifest: unknown;
|
|
23
|
+
reasons: unknown[];
|
|
24
|
+
evidenceDisposition: string;
|
|
25
|
+
}) => Promise<string>;
|
|
26
|
+
}
|
|
27
|
+
export declare function loadExplainerTerminalEvidence(): Promise<ExplainerTerminalEvidence>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=explainer-terminal-evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainer-terminal-evidence.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/archive/explainer-terminal-evidence.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,yBAAyB,uCAAuC,CAAC;AAEvE,MAAM,WAAW,yBAAyB;IACxC,yBAAyB,EAAE,OAAO,yBAAyB,CAAC;IAC5D,sBAAsB,EAAE,CACtB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,KAC3B,OAAO,CAAC;IACb,wBAAwB,EAAE,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QACP,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,CAAC,EAAE,UAAU,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,KACE,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,qBAAqB,EAAE,CACrB,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EACrD,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,CAAC;QACnB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,KACE,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAID,wBAAgB,6BAA6B,IAAI,OAAO,CAAC,yBAAyB,CAAC,CAGlF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
import { CliError } from '../../../errors/cli-error.js';
|
|
4
|
+
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
5
|
+
const TERMINAL_EVIDENCE_VERSION = 'explainer-kit.terminal-evidence/v1';
|
|
6
|
+
let cachedTerminalEvidence;
|
|
7
|
+
export function loadExplainerTerminalEvidence() {
|
|
8
|
+
cachedTerminalEvidence ??= loadGeneratedTerminalEvidence();
|
|
9
|
+
return cachedTerminalEvidence;
|
|
10
|
+
}
|
|
11
|
+
async function loadGeneratedTerminalEvidence() {
|
|
12
|
+
const assetsRoot = await resolveAssetsRoot();
|
|
13
|
+
const skillRoot = join(assetsRoot, 'skills', 'explainer-kit');
|
|
14
|
+
let contract;
|
|
15
|
+
let records;
|
|
16
|
+
try {
|
|
17
|
+
[contract, records] = await Promise.all([
|
|
18
|
+
import(pathToFileURL(join(skillRoot, 'scripts', 'lib', 'terminal-evidence.mjs')).href),
|
|
19
|
+
import(pathToFileURL(join(skillRoot, 'scripts', 'lib', 'records.mjs')).href),
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new CliError('Bundled explainer terminal evidence could not be loaded.', 2);
|
|
24
|
+
}
|
|
25
|
+
if (contract.TERMINAL_EVIDENCE_VERSION !== TERMINAL_EVIDENCE_VERSION ||
|
|
26
|
+
typeof contract.assertTerminalEvidence !== 'function' ||
|
|
27
|
+
typeof contract.readTerminalEvidenceFile !== 'function' ||
|
|
28
|
+
typeof records.writeTerminalEvidence !== 'function') {
|
|
29
|
+
throw new CliError(`Bundled assets must provide ${TERMINAL_EVIDENCE_VERSION} validation and writing.`, 2);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
TERMINAL_EVIDENCE_VERSION,
|
|
33
|
+
assertTerminalEvidence: contract.assertTerminalEvidence,
|
|
34
|
+
readTerminalEvidenceFile: contract.readTerminalEvidenceFile,
|
|
35
|
+
writeTerminalEvidence: records.writeTerminalEvidence,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type CommandContext } from '../../../app/command-context.js';
|
|
2
2
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
3
3
|
import { type SyncConfig } from '../../../config/sync-config.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type RemovalSyncPlanEntry } from '../../../engine/index.js';
|
|
5
|
+
import { type Manifest, type ManifestEntry } from '../../../manifest/index.js';
|
|
5
6
|
import { type ConfigAwareAdaptersResult, type PathMapping, type ProviderAdapter } from '../../../providers/shared/index.js';
|
|
6
7
|
import type { AdoptionSource } from '../../../providers/shared/adapter.types.js';
|
|
7
8
|
import type { ConcreteScope, Scope } from '../../../shared/types.js';
|
|
@@ -16,7 +17,9 @@ export interface RemoveSkillDependencies {
|
|
|
16
17
|
getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<ConfigAwareAdaptersResult>;
|
|
17
18
|
getSyncMappings: (adapter: ProviderAdapter, scope: Scope) => PathMapping[];
|
|
18
19
|
getAdoptionSources: (adapter: ProviderAdapter, scope: Scope) => AdoptionSource[];
|
|
20
|
+
classifyObsoleteMappingRetirement: (manifestEntry: ManifestEntry, scopeRoot: string) => Promise<RemovalSyncPlanEntry>;
|
|
19
21
|
pathExists: (path: string) => Promise<boolean>;
|
|
22
|
+
pathEntryExists: (path: string) => Promise<boolean>;
|
|
20
23
|
removeDirectory: (path: string) => Promise<void>;
|
|
21
24
|
}
|
|
22
25
|
export declare function createDefaultRemoveSkillDependencies(): RemoveSkillDependencies;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove-skill.d.ts","sourceRoot":"","sources":["../../../../src/commands/remove/skill/remove-skill.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EACL,iBAAiB,EAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"remove-skill.d.ts","sourceRoot":"","sources":["../../../../src/commands/remove/skill/remove-skill.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EACL,iBAAiB,EAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAGvB,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAGnB,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EACL,KAAK,yBAAyB,EAG9B,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,KAC1C,cAAc,CAAC;IACpB,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5D,WAAW,EAAE,MAAM,eAAe,EAAE,CAAC;IACrC,sBAAsB,EAAE,CACtB,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,KACf,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACxC,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,KAAK,WAAW,EAAE,CAAC;IAC3E,kBAAkB,EAAE,CAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,KAAK,KACT,cAAc,EAAE,CAAC;IACtB,iCAAiC,EAAE,CACjC,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,oCAAoC,IAAI,uBAAuB,CA0C9E;AAwND,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,OAAO,CAAC,CAsDlB;AAED,wBAAgB,wBAAwB,CACtC,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwCT"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { rm } from 'node:fs/promises';
|
|
1
|
+
import { lstat, rm } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { buildCommandContext } from '../../../app/command-context.js';
|
|
4
4
|
import { withScopeOption } from '../../shared/scope-option.js';
|
|
5
5
|
import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
|
|
6
6
|
import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../../config/sync-config.js';
|
|
7
|
+
import { classifyObsoleteMappingRetirement, } from '../../../engine/index.js';
|
|
7
8
|
import { dirExists, fileExists } from '../../../fs/io.js';
|
|
8
|
-
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
9
|
+
import { resolveProjectRoot, resolveScopeRoot, toPosixPath } from '../../../fs/paths.js';
|
|
9
10
|
import { loadManifest, removeEntry, saveManifest, } from '../../../manifest/index.js';
|
|
10
11
|
import { claudeAdapter } from '../../../providers/claude/index.js';
|
|
11
12
|
import { codexAdapter } from '../../../providers/codex/index.js';
|
|
@@ -41,9 +42,19 @@ export function createDefaultRemoveSkillDependencies() {
|
|
|
41
42
|
getConfigAwareAdapters,
|
|
42
43
|
getSyncMappings,
|
|
43
44
|
getAdoptionSources,
|
|
45
|
+
classifyObsoleteMappingRetirement,
|
|
44
46
|
async pathExists(path) {
|
|
45
47
|
return (await fileExists(path)) || (await dirExists(path));
|
|
46
48
|
},
|
|
49
|
+
async pathEntryExists(path) {
|
|
50
|
+
try {
|
|
51
|
+
await lstat(path);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
47
58
|
async removeDirectory(path) {
|
|
48
59
|
await rm(path, { recursive: true, force: true });
|
|
49
60
|
},
|
|
@@ -77,6 +88,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
77
88
|
const { activeAdapters } = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
|
|
78
89
|
const managedProviderViews = [];
|
|
79
90
|
const unmanagedProviderViews = [];
|
|
91
|
+
const manifestProvidersToRemove = new Set();
|
|
80
92
|
for (const adapter of activeAdapters) {
|
|
81
93
|
const syncMappings = dependencies
|
|
82
94
|
.getSyncMappings(adapter, scope)
|
|
@@ -88,6 +100,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
88
100
|
entry.provider === adapter.name);
|
|
89
101
|
const providerPathExists = await dependencies.pathExists(absolutePath);
|
|
90
102
|
if (hasManifestEntry) {
|
|
103
|
+
manifestProvidersToRemove.add(adapter.name);
|
|
91
104
|
managedProviderViews.push({
|
|
92
105
|
provider: adapter.name,
|
|
93
106
|
absolutePath,
|
|
@@ -111,7 +124,32 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
111
124
|
for (const source of localAdoptionSources) {
|
|
112
125
|
const relativePath = join(source.directory, skillName);
|
|
113
126
|
const absolutePath = join(scopeRoot, relativePath);
|
|
114
|
-
|
|
127
|
+
const legacyManifestEntry = manifest.entries.find((entry) => adapter.name === 'copilot' &&
|
|
128
|
+
entry.canonicalPath === canonicalRelativePath &&
|
|
129
|
+
entry.provider === adapter.name &&
|
|
130
|
+
entry.providerPath === toPosixPath(relativePath));
|
|
131
|
+
if (legacyManifestEntry) {
|
|
132
|
+
manifestProvidersToRemove.add(adapter.name);
|
|
133
|
+
const [retirement, providerPathExists] = await Promise.all([
|
|
134
|
+
dependencies.classifyObsoleteMappingRetirement(legacyManifestEntry, scopeRoot),
|
|
135
|
+
dependencies.pathEntryExists(absolutePath),
|
|
136
|
+
]);
|
|
137
|
+
if (retirement.operation === 'remove') {
|
|
138
|
+
managedProviderViews.push({
|
|
139
|
+
provider: adapter.name,
|
|
140
|
+
absolutePath,
|
|
141
|
+
relativePath,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else if (providerPathExists) {
|
|
145
|
+
unmanagedProviderViews.push({
|
|
146
|
+
provider: adapter.name,
|
|
147
|
+
absolutePath,
|
|
148
|
+
relativePath,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (await dependencies.pathExists(absolutePath)) {
|
|
115
153
|
unmanagedProviderViews.push({
|
|
116
154
|
provider: adapter.name,
|
|
117
155
|
absolutePath,
|
|
@@ -129,6 +167,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
129
167
|
canonicalAbsolutePath,
|
|
130
168
|
managedProviderViews: dedupeViews(managedProviderViews),
|
|
131
169
|
unmanagedProviderViews: dedupeViews(unmanagedProviderViews),
|
|
170
|
+
manifestProvidersToRemove: [...manifestProvidersToRemove],
|
|
132
171
|
};
|
|
133
172
|
}
|
|
134
173
|
function logDryRun(context, plan) {
|
|
@@ -164,8 +203,8 @@ async function applyPlan(context, plan, dependencies) {
|
|
|
164
203
|
await dependencies.removeDirectory(view.absolutePath);
|
|
165
204
|
}
|
|
166
205
|
let nextManifest = plan.manifest;
|
|
167
|
-
for (const
|
|
168
|
-
nextManifest = removeEntry(nextManifest, plan.canonicalRelativePath,
|
|
206
|
+
for (const provider of plan.manifestProvidersToRemove) {
|
|
207
|
+
nextManifest = removeEntry(nextManifest, plan.canonicalRelativePath, provider);
|
|
169
208
|
}
|
|
170
209
|
await dependencies.saveManifest(plan.manifestPath, nextManifest);
|
|
171
210
|
context.logger.info(`[apply][${plan.scope}] removed ${plan.canonicalRelativePath}`);
|
|
@@ -17,6 +17,11 @@ interface AdoptStrayOptions {
|
|
|
17
17
|
replaceCanonical?: boolean;
|
|
18
18
|
}
|
|
19
19
|
export declare function isAdoptionConflictError(error: unknown): error is CliError;
|
|
20
|
+
export declare class AdoptionSourceUnavailableError extends CliError {
|
|
21
|
+
readonly kind: 'adoption-source-unavailable';
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
export declare function isAdoptionSourceUnavailableError(error: unknown): error is AdoptionSourceUnavailableError;
|
|
20
25
|
export declare function adoptStrayToCanonical<TCandidate extends StrayAdoptionCandidate>(scopeRoot: string, stray: TCandidate, manifest: Manifest, options?: AdoptStrayOptions): Promise<Manifest>;
|
|
21
26
|
export {};
|
|
22
27
|
//# sourceMappingURL=adopt-stray.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-stray.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/adopt-stray.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"adopt-stray.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/adopt-stray.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAMzE;AAED,qBAAa,8BAA+B,SAAQ,QAAQ;IAC1D,QAAQ,CAAC,IAAI,EAAG,6BAA6B,CAAU;IAEvD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,8BAA8B,CAEzC;AAWD,wBAAsB,qBAAqB,CACzC,UAAU,SAAS,sBAAsB,EAEzC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,QAAQ,CAAC,CA0FnB"}
|
|
@@ -9,7 +9,19 @@ import { addEntry } from '../../manifest/manager.js';
|
|
|
9
9
|
import { importCanonicalAgentFromCodexRole } from '../../providers/codex/codec/import-from-codex.js';
|
|
10
10
|
import { canonicalRuleNameForProviderEntry } from '../../rules/canonical/index.js';
|
|
11
11
|
export function isAdoptionConflictError(error) {
|
|
12
|
-
return error instanceof CliError &&
|
|
12
|
+
return (error instanceof CliError &&
|
|
13
|
+
!isAdoptionSourceUnavailableError(error) &&
|
|
14
|
+
error.message.startsWith('Cannot adopt '));
|
|
15
|
+
}
|
|
16
|
+
export class AdoptionSourceUnavailableError extends CliError {
|
|
17
|
+
kind = 'adoption-source-unavailable';
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'AdoptionSourceUnavailableError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function isAdoptionSourceUnavailableError(error) {
|
|
24
|
+
return error instanceof AdoptionSourceUnavailableError;
|
|
13
25
|
}
|
|
14
26
|
async function pathExists(path) {
|
|
15
27
|
try {
|
|
@@ -21,12 +33,21 @@ async function pathExists(path) {
|
|
|
21
33
|
}
|
|
22
34
|
}
|
|
23
35
|
export async function adoptStrayToCanonical(scopeRoot, stray, manifest, options = {}) {
|
|
36
|
+
const providerAbsolutePath = resolve(scopeRoot, stray.report.providerPath);
|
|
37
|
+
let providerStat;
|
|
38
|
+
try {
|
|
39
|
+
providerStat = await stat(providerAbsolutePath);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code !== 'ENOENT') {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
throw new AdoptionSourceUnavailableError(`Cannot adopt ${toPosixPath(relative(scopeRoot, providerAbsolutePath))}: the path is missing or a broken symlink. Remove it or restore its target, then run the command again.`);
|
|
46
|
+
}
|
|
47
|
+
const isFile = providerStat.isFile();
|
|
24
48
|
if (stray.adoption?.kind === 'codex_role') {
|
|
25
49
|
return adoptCodexRoleStrayToCanonical(scopeRoot, stray, manifest, options);
|
|
26
50
|
}
|
|
27
|
-
const providerAbsolutePath = resolve(scopeRoot, stray.report.providerPath);
|
|
28
|
-
const providerStat = await stat(providerAbsolutePath);
|
|
29
|
-
const isFile = providerStat.isFile();
|
|
30
51
|
if (isFile && stray.mapping.contentType === 'rule') {
|
|
31
52
|
return adoptRuleStrayToCanonical(scopeRoot, stray, manifest, options);
|
|
32
53
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Manifest } from '../../manifest/manifest.types.js';
|
|
2
|
+
import type { PathMapping } from '../../providers/shared/adapter.types.js';
|
|
3
|
+
export type NativeSkillDisposition = 'adopt' | 'keep';
|
|
4
|
+
export interface NativeSkillCandidate {
|
|
5
|
+
provider: string;
|
|
6
|
+
report: {
|
|
7
|
+
providerPath: string;
|
|
8
|
+
};
|
|
9
|
+
mapping: PathMapping;
|
|
10
|
+
}
|
|
11
|
+
export interface NativeSkillProviderDetails {
|
|
12
|
+
displayName: string;
|
|
13
|
+
sourceDir: string;
|
|
14
|
+
}
|
|
15
|
+
interface ApplyNativeSkillDispositionOptions {
|
|
16
|
+
replaceCanonical?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function getNativeSkillProviderDetails(candidate: NativeSkillCandidate): NativeSkillProviderDetails | null;
|
|
19
|
+
export declare function isNativeSkillCandidate(candidate: NativeSkillCandidate): boolean;
|
|
20
|
+
export declare function applyNativeSkillDisposition(scopeRoot: string, candidate: NativeSkillCandidate, manifest: Manifest, disposition: NativeSkillDisposition, syncConfigPath: string, options?: ApplyNativeSkillDispositionOptions): Promise<Manifest>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=native-skill-disposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-skill-disposition.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/native-skill-disposition.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAInE,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,kCAAkC;IAC1C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,oBAAoB,GAC9B,0BAA0B,GAAG,IAAI,CAqBnC;AAQD,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,oBAAoB,GAC9B,OAAO,CAET;AAED,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,oBAAoB,EAC/B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,QAAQ,CAAC,CAenB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
import { basename, relative, resolve } from 'node:path';
|
|
3
|
+
import { appendKnownStray } from '../../config/sync-config.js';
|
|
4
|
+
import { CliError } from '../../errors/index.js';
|
|
5
|
+
import { toPosixPath } from '../../fs/paths.js';
|
|
6
|
+
import { adoptStrayToCanonical } from './adopt-stray.js';
|
|
7
|
+
const NATIVE_SKILL_PROVIDER_DISPLAY_NAMES = {
|
|
8
|
+
copilot: 'Copilot',
|
|
9
|
+
cursor: 'Cursor',
|
|
10
|
+
};
|
|
11
|
+
export function getNativeSkillProviderDetails(candidate) {
|
|
12
|
+
if (candidate.mapping.contentType !== 'skill' ||
|
|
13
|
+
!candidate.mapping.nativeRead) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const providerPath = toPosixPath(candidate.report.providerPath);
|
|
17
|
+
const sourceDir = candidate.mapping.adoptionSourceDirs?.find((directory) => providerPath === directory || providerPath.startsWith(`${directory}/`));
|
|
18
|
+
if (!sourceDir) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const displayName = NATIVE_SKILL_PROVIDER_DISPLAY_NAMES[candidate.provider] ??
|
|
22
|
+
formatProviderName(candidate.provider);
|
|
23
|
+
return { displayName, sourceDir };
|
|
24
|
+
}
|
|
25
|
+
function formatProviderName(provider) {
|
|
26
|
+
return provider.length === 0
|
|
27
|
+
? 'Provider'
|
|
28
|
+
: `${provider.charAt(0).toUpperCase()}${provider.slice(1)}`;
|
|
29
|
+
}
|
|
30
|
+
export function isNativeSkillCandidate(candidate) {
|
|
31
|
+
return getNativeSkillProviderDetails(candidate) !== null;
|
|
32
|
+
}
|
|
33
|
+
export async function applyNativeSkillDisposition(scopeRoot, candidate, manifest, disposition, syncConfigPath, options = {}) {
|
|
34
|
+
const provider = getNativeSkillProviderDetails(candidate);
|
|
35
|
+
if (!provider) {
|
|
36
|
+
throw new CliError(`Cannot apply a native skill disposition to ${candidate.report.providerPath}.`);
|
|
37
|
+
}
|
|
38
|
+
if (disposition === 'adopt') {
|
|
39
|
+
return adoptStrayToCanonical(scopeRoot, candidate, manifest, options);
|
|
40
|
+
}
|
|
41
|
+
await assertProviderOnlyNameAvailable(scopeRoot, candidate, provider);
|
|
42
|
+
await appendKnownStray(syncConfigPath, candidate.report.providerPath);
|
|
43
|
+
return manifest;
|
|
44
|
+
}
|
|
45
|
+
async function assertProviderOnlyNameAvailable(scopeRoot, candidate, provider) {
|
|
46
|
+
const canonicalPath = resolve(scopeRoot, candidate.mapping.canonicalDir, basename(candidate.report.providerPath));
|
|
47
|
+
if (!(await pathExists(canonicalPath))) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw new CliError(`Cannot keep ${candidate.report.providerPath} ${provider.displayName}-only because canonical skill ${toPosixPath(relative(scopeRoot, canonicalPath))} has the same name. Rename one skill, then run the command again.`);
|
|
51
|
+
}
|
|
52
|
+
async function pathExists(path) {
|
|
53
|
+
try {
|
|
54
|
+
await access(path);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
2
|
import { type CodexRoleStray } from '../shared/codex-strays.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type NativeSkillDisposition } from '../shared/native-skill-disposition.js';
|
|
4
4
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
|
|
5
5
|
import { type SyncConfig } from '../../config/index.js';
|
|
6
6
|
import { type CopyTransform, type DriftReport } from '../../drift/index.js';
|
|
@@ -44,7 +44,7 @@ interface StatusDependencies {
|
|
|
44
44
|
adoptStray: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, options?: {
|
|
45
45
|
replaceCanonical?: boolean;
|
|
46
46
|
}) => Promise<Manifest>;
|
|
47
|
-
|
|
47
|
+
applyNativeSkillDisposition: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, disposition: NativeSkillDisposition, syncConfigPath: string, options?: {
|
|
48
48
|
replaceCanonical?: boolean;
|
|
49
49
|
}) => Promise<Manifest>;
|
|
50
50
|
formatStatusTable: (reports: DriftReport[]) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { basename, join, relative } from 'node:path';
|
|
2
2
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
3
|
-
import { adoptStrayToCanonical, isAdoptionConflictError, } from '../shared/adopt-stray.js';
|
|
3
|
+
import { adoptStrayToCanonical, isAdoptionConflictError, isAdoptionSourceUnavailableError, } from '../shared/adopt-stray.js';
|
|
4
4
|
import { detectCodexRoleStrays, filterMaterializationManagedStrays, regenerateCodexAfterAdoption, } from '../shared/codex-strays.js';
|
|
5
|
-
import {
|
|
5
|
+
import { applyNativeSkillDisposition, getNativeSkillProviderDetails, isNativeSkillCandidate, } from '../shared/native-skill-disposition.js';
|
|
6
6
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
7
7
|
import { confirmAction, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
|
|
8
8
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
@@ -64,7 +64,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
64
64
|
selectWithAbort,
|
|
65
65
|
confirmAction,
|
|
66
66
|
adoptStray: adoptStrayDefault,
|
|
67
|
-
|
|
67
|
+
applyNativeSkillDisposition,
|
|
68
68
|
formatStatusTable,
|
|
69
69
|
};
|
|
70
70
|
function entryInsideMapping(entryProviderPath, mappingProviderDir) {
|
|
@@ -355,19 +355,20 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
355
355
|
let manifestChanged = false;
|
|
356
356
|
let adoptedCount = 0;
|
|
357
357
|
let codexStrayAdopted = false;
|
|
358
|
-
const
|
|
359
|
-
const ordinaryStrays = scopeCollection.strayCandidates.filter((stray) => !
|
|
360
|
-
for (const strayCandidate of
|
|
361
|
-
const
|
|
358
|
+
const nativeSkillStrays = scopeCollection.strayCandidates.filter(isNativeSkillCandidate);
|
|
359
|
+
const ordinaryStrays = scopeCollection.strayCandidates.filter((stray) => !isNativeSkillCandidate(stray));
|
|
360
|
+
for (const strayCandidate of nativeSkillStrays) {
|
|
361
|
+
const provider = getNativeSkillProviderDetails(strayCandidate);
|
|
362
|
+
const disposition = await dependencies.selectWithAbort(`Migrate ${provider.displayName} skill [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}`, [
|
|
362
363
|
{
|
|
363
364
|
label: 'Adopt into canonical',
|
|
364
365
|
value: 'adopt',
|
|
365
366
|
description: `Move to ${strayCandidate.mapping.canonicalDir}.`,
|
|
366
367
|
},
|
|
367
368
|
{
|
|
368
|
-
label:
|
|
369
|
+
label: `Keep ${provider.displayName}-only`,
|
|
369
370
|
value: 'keep',
|
|
370
|
-
description:
|
|
371
|
+
description: `Leave in ${provider.sourceDir} and remember this choice.`,
|
|
371
372
|
},
|
|
372
373
|
], { interactive: context.interactive });
|
|
373
374
|
if (disposition === null) {
|
|
@@ -376,15 +377,19 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
376
377
|
}
|
|
377
378
|
try {
|
|
378
379
|
scopeCollection.manifest =
|
|
379
|
-
await dependencies.
|
|
380
|
+
await dependencies.applyNativeSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath);
|
|
380
381
|
if (disposition === 'adopt') {
|
|
381
382
|
adoptedCount += 1;
|
|
382
383
|
}
|
|
383
384
|
else {
|
|
384
|
-
context.logger.success(`Kept
|
|
385
|
+
context.logger.success(`Kept ${provider.displayName}-only [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
|
|
385
386
|
}
|
|
386
387
|
}
|
|
387
388
|
catch (error) {
|
|
389
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
390
|
+
context.logger.warn(error.message);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
388
393
|
if (error instanceof Error &&
|
|
389
394
|
error.message.startsWith('Cannot keep ')) {
|
|
390
395
|
context.logger.warn(error.message);
|
|
@@ -395,11 +400,11 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
395
400
|
}
|
|
396
401
|
const shouldReplace = await dependencies.confirmAction(`Conflict detected for ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}. Replace canonical with stray content?`, { interactive: context.interactive });
|
|
397
402
|
if (!shouldReplace) {
|
|
398
|
-
context.logger.warn(`Skipped adopting conflicting
|
|
403
|
+
context.logger.warn(`Skipped adopting conflicting ${provider.displayName} skill [${scopeCollection.scope}] ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
|
|
399
404
|
continue;
|
|
400
405
|
}
|
|
401
406
|
scopeCollection.manifest =
|
|
402
|
-
await dependencies.
|
|
407
|
+
await dependencies.applyNativeSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath, { replaceCanonical: true });
|
|
403
408
|
adoptedCount += 1;
|
|
404
409
|
}
|
|
405
410
|
}
|
|
@@ -426,6 +431,10 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
426
431
|
codexStrayAdopted || strayCandidate.provider === 'codex';
|
|
427
432
|
}
|
|
428
433
|
catch (error) {
|
|
434
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
435
|
+
context.logger.warn(error.message);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
429
438
|
if (!isAdoptionConflictError(error)) {
|
|
430
439
|
throw error;
|
|
431
440
|
}
|
|
@@ -26,11 +26,13 @@ export interface OatExplainerDefaultsConfig {
|
|
|
26
26
|
themeBundlePath?: string;
|
|
27
27
|
}
|
|
28
28
|
export type OatExplainerPublishProvider = 's3-static';
|
|
29
|
+
export type OatExplainerPublicAccess = 'public' | 'protected';
|
|
29
30
|
export interface OatExplainerPublishConfig {
|
|
30
31
|
provider?: OatExplainerPublishProvider;
|
|
31
32
|
s3Uri?: string;
|
|
32
33
|
publicBaseUrl?: string;
|
|
33
34
|
awsRegion?: string;
|
|
35
|
+
publicAccess?: OatExplainerPublicAccess;
|
|
34
36
|
awsProfile?: string;
|
|
35
37
|
}
|
|
36
38
|
export interface OatExplainersConfig {
|