@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.
Files changed (107) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +41 -0
  3. package/assets/docs/contributing/code.md +19 -7
  4. package/assets/docs/contributing/explainer-kit-verification.md +9 -1
  5. package/assets/docs/contributing/skills.md +9 -0
  6. package/assets/docs/provider-sync/commands.md +15 -10
  7. package/assets/docs/provider-sync/manifest-and-drift.md +23 -0
  8. package/assets/docs/provider-sync/providers.md +8 -2
  9. package/assets/docs/provider-sync/scope-and-surface.md +3 -1
  10. package/assets/docs/reference/file-locations.md +5 -0
  11. package/assets/docs/reference/troubleshooting.md +18 -0
  12. package/assets/docs/workflows/skills/explainer-kit-providers.md +16 -5
  13. package/assets/docs/workflows/skills/explainer-kit.md +98 -38
  14. package/assets/public-package-versions.json +4 -4
  15. package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +34 -22
  16. package/assets/skills/explainer-kit/SKILL.md +33 -8
  17. package/assets/skills/explainer-kit/briefs/project-recap.md +25 -7
  18. package/assets/skills/explainer-kit/recipes/project-recap.v2.json +72 -0
  19. package/assets/skills/explainer-kit/references/contracts.md +49 -17
  20. package/assets/skills/explainer-kit/references/destination-contract.md +141 -25
  21. package/assets/skills/explainer-kit/references/extension-contract.md +19 -10
  22. package/assets/skills/explainer-kit/references/visual-authoring.md +24 -0
  23. package/assets/skills/explainer-kit/references/visual-review.md +19 -5
  24. package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +241 -0
  25. package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +215 -0
  26. package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +34 -0
  27. package/assets/skills/explainer-kit/schemas/run-request.schema.json +4 -1
  28. package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +81 -0
  29. package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +66 -0
  30. package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +109 -3
  31. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +550 -17
  32. package/assets/skills/explainer-kit/scripts/lib/durability.mjs +90 -8
  33. package/assets/skills/explainer-kit/scripts/lib/fs-safe.mjs +5 -0
  34. package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +538 -0
  35. package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +129 -11
  36. package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +54 -0
  37. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +2 -1
  38. package/assets/skills/explainer-kit/scripts/lib/records.mjs +139 -22
  39. package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +353 -0
  40. package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +237 -107
  41. package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +1 -0
  42. package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +157 -0
  43. package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +26 -6
  44. package/assets/skills/explainer-kit/scripts/run.mjs +1006 -144
  45. package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +14 -2
  46. package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +14 -2
  47. package/assets/skills/oat-explainer-kit/SKILL.md +16 -3
  48. package/assets/skills/oat-explainer-kit/references/config-contract.md +13 -8
  49. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +50 -6
  50. package/assets/skills/oat-explainer-kit/references/migration.md +2 -1
  51. package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +11 -0
  52. package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +37 -15
  53. package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +83 -0
  54. package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +91 -0
  55. package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +66 -10
  56. package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +60 -21
  57. package/assets/skills/oat-explainer-kit/scripts/resolve-paths.mjs +52 -8
  58. package/assets/skills/oat-explainer-kit/scripts/run.mjs +271 -36
  59. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
  60. package/assets/skills/oat-project-complete/SKILL.md +19 -3
  61. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
  62. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +8 -0
  63. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
  64. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
  65. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
  66. package/dist/commands/config/index.d.ts.map +1 -1
  67. package/dist/commands/config/index.js +18 -0
  68. package/dist/commands/init/index.d.ts +2 -2
  69. package/dist/commands/init/index.d.ts.map +1 -1
  70. package/dist/commands/init/index.js +22 -13
  71. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  72. package/dist/commands/project/archive/archive-utils.js +57 -7
  73. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +29 -0
  74. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +1 -0
  75. package/dist/commands/project/archive/explainer-terminal-evidence.js +37 -0
  76. package/dist/commands/remove/skill/remove-skill.d.ts +4 -1
  77. package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
  78. package/dist/commands/remove/skill/remove-skill.js +44 -5
  79. package/dist/commands/shared/adopt-stray.d.ts +5 -0
  80. package/dist/commands/shared/adopt-stray.d.ts.map +1 -1
  81. package/dist/commands/shared/adopt-stray.js +25 -4
  82. package/dist/commands/shared/native-skill-disposition.d.ts +22 -0
  83. package/dist/commands/shared/native-skill-disposition.d.ts.map +1 -0
  84. package/dist/commands/shared/native-skill-disposition.js +60 -0
  85. package/dist/commands/status/index.d.ts +2 -2
  86. package/dist/commands/status/index.d.ts.map +1 -1
  87. package/dist/commands/status/index.js +22 -13
  88. package/dist/config/oat-config.d.ts +2 -0
  89. package/dist/config/oat-config.d.ts.map +1 -1
  90. package/dist/config/oat-config.js +4 -0
  91. package/dist/config/resolve.d.ts.map +1 -1
  92. package/dist/config/resolve.js +1 -0
  93. package/dist/engine/compute-plan.d.ts +3 -2
  94. package/dist/engine/compute-plan.d.ts.map +1 -1
  95. package/dist/engine/compute-plan.js +1 -1
  96. package/dist/engine/index.d.ts +1 -1
  97. package/dist/engine/index.d.ts.map +1 -1
  98. package/dist/engine/index.js +1 -1
  99. package/dist/providers/copilot/paths.d.ts.map +1 -1
  100. package/dist/providers/copilot/paths.js +6 -4
  101. package/package.json +2 -2
  102. package/dist/commands/shared/cursor-skill-disposition.d.ts +0 -17
  103. package/dist/commands/shared/cursor-skill-disposition.d.ts.map +0 -1
  104. package/dist/commands/shared/cursor-skill-disposition.js +0 -41
  105. /package/assets/skills/explainer-kit/recipes/{project-recap.json → project-recap.v1.json} +0 -0
  106. /package/assets/skills/explainer-kit/schemas/{publish-receipt.schema.json → publish-receipt.v1.schema.json} +0 -0
  107. /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, manifest: sourceManifest, } = verified;
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 copyProjectDirectory = dependencies.copyDirectory ?? copyDirectory;
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
- await copyProjectDirectory(sourceRunRoot, temporaryRoot);
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 verifiedArtifactCount = await verifyProjectRecapImmutableHashes(temporaryRoot, sourceManifest);
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 Manifest } from '../../../manifest/index.js';
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;AAG7B,OAAO,EAEL,KAAK,QAAQ,EAGd,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;AA8BpC,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,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,oCAAoC,IAAI,uBAAuB,CAiC9E;AAuLD,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
+ {"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
- if (await dependencies.pathExists(absolutePath)) {
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 view of plan.managedProviderViews) {
168
- nextManifest = removeEntry(nextManifest, plan.canonicalRelativePath, view.provider);
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,CAEzE;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,CA8EnB"}
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 && error.message.startsWith('Cannot adopt ');
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 CursorSkillDisposition } from '../shared/cursor-skill-disposition.js';
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
- applyCursorSkillDisposition: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, disposition: CursorSkillDisposition, syncConfigPath: string, options?: {
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":"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"}
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 { applyCursorSkillDisposition, isCursorSkillCandidate, } from '../shared/cursor-skill-disposition.js';
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
- applyCursorSkillDisposition,
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 cursorSkillStrays = scopeCollection.strayCandidates.filter(isCursorSkillCandidate);
359
- const ordinaryStrays = scopeCollection.strayCandidates.filter((stray) => !isCursorSkillCandidate(stray));
360
- for (const strayCandidate of cursorSkillStrays) {
361
- const disposition = await dependencies.selectWithAbort(`Migrate Cursor skill [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}`, [
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: 'Keep Cursor-only',
369
+ label: `Keep ${provider.displayName}-only`,
369
370
  value: 'keep',
370
- description: 'Leave in .cursor/skills and remember this choice.',
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.applyCursorSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath);
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 Cursor-only [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
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 Cursor skill [${scopeCollection.scope}] ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
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.applyCursorSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath, { replaceCanonical: true });
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 {