@lesliechan721/aw 0.1.0-beta.64 → 0.1.0-beta.65
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/dist/authoring/assets/aw-runtime-config.mjs +3 -3
- package/dist/authoring/assets/aw-runtime-config.mjs.map +1 -1
- package/dist/authoring/scripts/add-skill.mjs +3 -17
- package/dist/authoring/scripts/add-skill.mjs.map +1 -1
- package/dist/authoring/scripts/init-plugin.mjs +1 -0
- package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
- package/dist/authoring/scripts/lib/skill-scaffold.d.mts +2 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs +2 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +95 -698
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/aw-skill-eval-materializer.d.ts +2 -0
- package/dist/scripts/aw-skill-eval-materializer.js +74 -44
- package/dist/scripts/aw-skill-eval-materializer.js.map +1 -1
- package/dist/scripts/bundle-plugins.js +10 -2
- package/dist/scripts/bundle-plugins.js.map +1 -1
- package/dist/scripts/plugin-staging.d.ts +1 -1
- package/dist/scripts/plugin-staging.js +1 -1
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +31 -31
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +1 -1
- package/dist/src/commands/aw-capabilities.js +2 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/commands/console.js +4 -3
- package/dist/src/commands/console.js.map +1 -1
- package/dist/src/commands/intent-command.d.ts +30 -0
- package/dist/src/commands/intent-command.js +164 -0
- package/dist/src/commands/intent-command.js.map +1 -0
- package/dist/src/commands/operation-plan.d.ts +2 -0
- package/dist/src/commands/operation-plan.js +2 -1
- package/dist/src/commands/operation-plan.js.map +1 -1
- package/dist/src/commands/options.d.ts +3 -11
- package/dist/src/commands/options.js +11 -17
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +27 -33
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +108 -6
- package/dist/src/commands/rebuild-command.js +617 -1549
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +19 -3
- package/dist/src/commands/rebuild-integration.js +500 -459
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.js +1 -2
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/review-inspection.d.ts +2 -2
- package/dist/src/commands/review-inspection.js +30 -86
- package/dist/src/commands/review-inspection.js.map +1 -1
- package/dist/src/commands/review-preparation.js +16 -7
- package/dist/src/commands/review-preparation.js.map +1 -1
- package/dist/src/commands/skill-eval.d.ts +2 -0
- package/dist/src/commands/skill-eval.js +15 -9
- package/dist/src/commands/skill-eval.js.map +1 -1
- package/dist/src/commands/status-v6.d.ts +38 -5
- package/dist/src/commands/status-v6.js +269 -102
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/commands/targets-command.d.ts +27 -0
- package/dist/src/commands/targets-command.js +77 -0
- package/dist/src/commands/targets-command.js.map +1 -0
- package/dist/src/commands/write-commands.js +5 -5
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/eval/manifest-v1.d.ts +2 -0
- package/dist/src/eval/manifest-v1.js +7 -2
- package/dist/src/eval/manifest-v1.js.map +1 -1
- package/dist/src/generators/local-plugin.d.ts +2 -1
- package/dist/src/generators/local-plugin.js +111 -108
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +10 -17
- package/dist/src/index.js +585 -1349
- package/dist/src/index.js.map +1 -1
- package/dist/src/intent/deployment-preferences.d.ts +63 -0
- package/dist/src/intent/deployment-preferences.js +170 -0
- package/dist/src/intent/deployment-preferences.js.map +1 -0
- package/dist/src/intent/diagnostics.d.ts +11 -0
- package/dist/src/intent/diagnostics.js +14 -0
- package/dist/src/intent/diagnostics.js.map +1 -0
- package/dist/src/intent/intent-codec.d.ts +19 -0
- package/dist/src/intent/intent-codec.js +117 -0
- package/dist/src/intent/intent-codec.js.map +1 -0
- package/dist/src/intent/intent-store.d.ts +43 -0
- package/dist/src/intent/intent-store.js +118 -0
- package/dist/src/intent/intent-store.js.map +1 -0
- package/dist/src/intent/scope-context.d.ts +33 -0
- package/dist/src/intent/scope-context.js +145 -0
- package/dist/src/intent/scope-context.js.map +1 -0
- package/dist/src/intent/work-context.d.ts +13 -0
- package/dist/src/intent/work-context.js +22 -0
- package/dist/src/intent/work-context.js.map +1 -0
- package/dist/src/output/command-receipt.js +16 -9
- package/dist/src/output/command-receipt.js.map +1 -1
- package/dist/src/portable/commands.d.ts +18 -8
- package/dist/src/portable/commands.js +46 -562
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/historical-materialization.d.ts +22 -0
- package/dist/src/portable/historical-materialization.js +124 -0
- package/dist/src/portable/historical-materialization.js.map +1 -0
- package/dist/src/portable/materializer.d.ts +8 -0
- package/dist/src/portable/materializer.js +75 -44
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/portable/recovery-layout.d.ts +17 -0
- package/dist/src/portable/recovery-layout.js +55 -0
- package/dist/src/portable/recovery-layout.js.map +1 -0
- package/dist/src/portable/recovery.d.ts +143 -0
- package/dist/src/portable/recovery.js +339 -0
- package/dist/src/portable/recovery.js.map +1 -0
- package/dist/src/portable/writer.d.ts +64 -0
- package/dist/src/portable/writer.js +316 -0
- package/dist/src/portable/writer.js.map +1 -0
- package/dist/src/recovery/coordinator.d.ts +137 -0
- package/dist/src/recovery/coordinator.js +1198 -0
- package/dist/src/recovery/coordinator.js.map +1 -0
- package/dist/src/recovery/demand.d.ts +44 -0
- package/dist/src/recovery/demand.js +178 -0
- package/dist/src/recovery/demand.js.map +1 -0
- package/dist/src/recovery/joint-coordinator.d.ts +24 -0
- package/dist/src/recovery/joint-coordinator.js +770 -0
- package/dist/src/recovery/joint-coordinator.js.map +1 -0
- package/dist/src/recovery/joint-demand.d.ts +68 -0
- package/dist/src/recovery/joint-demand.js +166 -0
- package/dist/src/recovery/joint-demand.js.map +1 -0
- package/dist/src/recovery/receipt.d.ts +81 -0
- package/dist/src/recovery/receipt.js +2 -0
- package/dist/src/recovery/receipt.js.map +1 -0
- package/dist/src/recovery/retirement.d.ts +45 -0
- package/dist/src/recovery/retirement.js +366 -0
- package/dist/src/recovery/retirement.js.map +1 -0
- package/dist/src/recovery/status.d.ts +108 -0
- package/dist/src/recovery/status.js +417 -0
- package/dist/src/recovery/status.js.map +1 -0
- package/dist/src/recovery/types.d.ts +86 -0
- package/dist/src/recovery/types.js +2 -0
- package/dist/src/recovery/types.js.map +1 -0
- package/dist/src/review/review-profile.d.ts +2 -1
- package/dist/src/review/review-profile.js +15 -15
- package/dist/src/review/review-profile.js.map +1 -1
- package/dist/src/review/review-selection.d.ts +1 -2
- package/dist/src/review/review-selection.js +40 -114
- package/dist/src/review/review-selection.js.map +1 -1
- package/dist/src/review/review-types.d.ts +4 -4
- package/dist/src/review/review-types.js.map +1 -1
- package/dist/src/review/skill-materialization.js +15 -6
- package/dist/src/review/skill-materialization.js.map +1 -1
- package/dist/src/review/source-binding.d.ts +14 -4
- package/dist/src/review/source-binding.js +62 -117
- package/dist/src/review/source-binding.js.map +1 -1
- package/dist/src/tui/agent-management.d.ts +23 -0
- package/dist/src/tui/agent-management.js +217 -0
- package/dist/src/tui/agent-management.js.map +1 -0
- package/dist/src/tui/agent-settings.d.ts +44 -0
- package/dist/src/tui/agent-settings.js +98 -0
- package/dist/src/tui/agent-settings.js.map +1 -0
- package/dist/src/tui/components.d.ts +3 -0
- package/dist/src/tui/components.js +10 -1
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/config-references.d.ts +6 -3
- package/dist/src/tui/config-references.js +17 -12
- package/dist/src/tui/config-references.js.map +1 -1
- package/dist/src/tui/console-app-v4.d.ts +1 -2
- package/dist/src/tui/console-app-v4.js +1533 -1047
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +2 -1
- package/dist/src/tui/controller-runtime.js +405 -1626
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +131 -81
- package/dist/src/tui/controller.js +307 -227
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/entity-cards.d.ts +2 -2
- package/dist/src/tui/entity-cards.js +98 -20
- package/dist/src/tui/entity-cards.js.map +1 -1
- package/dist/src/tui/glossary.d.ts +2 -0
- package/dist/src/tui/glossary.js +20 -0
- package/dist/src/tui/glossary.js.map +1 -1
- package/dist/src/tui/model.d.ts +28 -10
- package/dist/src/tui/model.js +41 -41
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/operation-review-planner.d.ts +2 -0
- package/dist/src/tui/operation-review-planner.js +58 -122
- package/dist/src/tui/operation-review-planner.js.map +1 -1
- package/dist/src/tui/plugin-content.js +7 -4
- package/dist/src/tui/plugin-content.js.map +1 -1
- package/dist/src/tui/plugin-detail.d.ts +22 -3
- package/dist/src/tui/plugin-detail.js +113 -26
- package/dist/src/tui/plugin-detail.js.map +1 -1
- package/dist/src/tui/reader.d.ts +1 -0
- package/dist/src/tui/reader.js +3 -1
- package/dist/src/tui/reader.js.map +1 -1
- package/dist/src/tui/router.d.ts +23 -33
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/scoped-flow.d.ts +45 -0
- package/dist/src/tui/scoped-flow.js +96 -0
- package/dist/src/tui/scoped-flow.js.map +1 -0
- package/dist/src/tui/scoped-inventory.d.ts +122 -0
- package/dist/src/tui/scoped-inventory.js +225 -0
- package/dist/src/tui/scoped-inventory.js.map +1 -0
- package/dist/src/tui/screen-registry.d.ts +25 -25
- package/dist/src/tui/screen-registry.js +3 -7
- package/dist/src/tui/screen-registry.js.map +1 -1
- package/dist/src/tui/session-console-app.js +1 -1
- package/dist/src/tui/session-console-app.js.map +1 -1
- package/dist/src/tui/session-host.js +12 -2
- package/dist/src/tui/session-host.js.map +1 -1
- package/dist/src/types.d.ts +15 -12
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.js +2 -0
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/artifact-plan.js +13 -6
- package/dist/src/utils/artifact-plan.js.map +1 -1
- package/dist/src/utils/artifact-renderer.d.ts +6 -3
- package/dist/src/utils/artifact-renderer.js +27 -32
- package/dist/src/utils/artifact-renderer.js.map +1 -1
- package/dist/src/utils/artifact-request.d.ts +1 -0
- package/dist/src/utils/artifact-request.js +22 -12
- package/dist/src/utils/artifact-request.js.map +1 -1
- package/dist/src/utils/artifact-sources.d.ts +2 -2
- package/dist/src/utils/bundle-layout.js +18 -16
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-digests.js +2 -0
- package/dist/src/utils/catalog-digests.js.map +1 -1
- package/dist/src/utils/catalog-runtime-projection.d.ts +4 -3
- package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
- package/dist/src/utils/catalog-source-references.d.ts +5 -0
- package/dist/src/utils/catalog-source-references.js +42 -57
- package/dist/src/utils/catalog-source-references.js.map +1 -1
- package/dist/src/utils/claude-native-render-receipt.d.ts +14 -0
- package/dist/src/utils/claude-native-render-receipt.js +26 -0
- package/dist/src/utils/claude-native-render-receipt.js.map +1 -0
- package/dist/src/utils/claude-skills-root.js +14 -3
- package/dist/src/utils/claude-skills-root.js.map +1 -1
- package/dist/src/utils/codex-manager.js +6 -12
- package/dist/src/utils/codex-manager.js.map +1 -1
- package/dist/src/utils/codex-native-observation.js +29 -13
- package/dist/src/utils/codex-native-observation.js.map +1 -1
- package/dist/src/utils/codex-reconciler.d.ts +2 -5
- package/dist/src/utils/codex-reconciler.js +25 -1
- package/dist/src/utils/codex-reconciler.js.map +1 -1
- package/dist/src/utils/codex-surface-analysis.js +5 -3
- package/dist/src/utils/codex-surface-analysis.js.map +1 -1
- package/dist/src/utils/local-marketplace.d.ts +14 -2
- package/dist/src/utils/local-marketplace.js +209 -42
- package/dist/src/utils/local-marketplace.js.map +1 -1
- package/dist/src/utils/managed-command-evidence.js +1 -1
- package/dist/src/utils/managed-command-evidence.js.map +1 -1
- package/dist/src/utils/managed-command-materialization.d.ts +4 -0
- package/dist/src/utils/managed-command-materialization.js +15 -6
- package/dist/src/utils/managed-command-materialization.js.map +1 -1
- package/dist/src/utils/managed-command-store.d.ts +15 -0
- package/dist/src/utils/managed-command-store.js +73 -8
- package/dist/src/utils/managed-command-store.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +2 -0
- package/dist/src/utils/native-cli.js +22 -0
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/native-demand.d.ts +10 -0
- package/dist/src/utils/native-demand.js +4 -0
- package/dist/src/utils/native-demand.js.map +1 -0
- package/dist/src/utils/ownership.js +2 -0
- package/dist/src/utils/ownership.js.map +1 -1
- package/dist/src/utils/paths.js +1 -1
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/platform-support.d.ts +1 -1
- package/dist/src/utils/platform-support.js +1 -1
- package/dist/src/utils/platform-support.js.map +1 -1
- package/dist/src/utils/plugin-config-impact.d.ts +3 -0
- package/dist/src/utils/plugin-config-impact.js +115 -273
- package/dist/src/utils/plugin-config-impact.js.map +1 -1
- package/dist/src/utils/plugin-config-references.d.ts +9 -2
- package/dist/src/utils/plugin-config-references.js +75 -85
- package/dist/src/utils/plugin-config-references.js.map +1 -1
- package/dist/src/utils/plugin-config-write.d.ts +58 -1
- package/dist/src/utils/plugin-config-write.js +756 -809
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +47 -46
- package/dist/src/utils/plugin-config.js +292 -833
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +11 -6
- package/dist/src/utils/plugin-scripts.js +52 -35
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/runtime-config.js +5 -4
- package/dist/src/utils/runtime-config.js.map +1 -1
- package/dist/src/utils/runtime-skill-closure.d.ts +2 -2
- package/dist/src/utils/runtime-skill-closure.js.map +1 -1
- package/dist/src/utils/state-paths.d.ts +8 -3
- package/dist/src/utils/state-paths.js +53 -16
- package/dist/src/utils/state-paths.js.map +1 -1
- package/dist/src/utils/windows-npm-shim.d.ts +2 -0
- package/dist/src/utils/windows-npm-shim.js +5 -7
- package/dist/src/utils/windows-npm-shim.js.map +1 -1
- package/dist/vitest.config.js +1 -0
- package/dist/vitest.config.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/commands/sync-command.d.ts +0 -40
- package/dist/src/commands/sync-command.js +0 -254
- package/dist/src/commands/sync-command.js.map +0 -1
- package/dist/src/portable/skills-cli.d.ts +0 -51
- package/dist/src/portable/skills-cli.js +0 -202
- package/dist/src/portable/skills-cli.js.map +0 -1
- package/dist/src/tui/project-inventory.d.ts +0 -68
- package/dist/src/tui/project-inventory.js +0 -203
- package/dist/src/tui/project-inventory.js.map +0 -1
- package/dist/src/utils/plugin-intent-state.d.ts +0 -49
- package/dist/src/utils/plugin-intent-state.js +0 -320
- package/dist/src/utils/plugin-intent-state.js.map +0 -1
|
@@ -3,11 +3,11 @@ import { captureNativeToolChanges } from '../utils/native-tool-review.js';
|
|
|
3
3
|
import { forceOfflineCleanupEvidence } from './offline-cleanup-evidence.js';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
|
-
import { catalogFileMode } from '@lesliechan721/aw-plugin-core';
|
|
6
|
+
import { catalogFileMode, compilePluginConfigDefinition } from '@lesliechan721/aw-plugin-core';
|
|
7
7
|
import { COMMAND_PRODUCER_RECORD_FILE, getManagedCommandArtifactTargets, getCommandPackageId } from '@lesliechan721/aw-plugin-core/manifest';
|
|
8
8
|
import os from 'node:os';
|
|
9
9
|
import { injectNativeToolClosureFiles, nativeToolsForCommandSets, commandSetsForProducer, createManagedCommandReferenceResolver, discoverRetainedManagedCommandPackages, retainedManagedCommandPackageResult, managedCommandProducerIdentity, prepareManagedCommandPackage, resolveSkillManagedCommandReferences, } from '../utils/managed-command-materialization.js';
|
|
10
|
-
import { assertManagedCommandBindingIdentities, normalizeInstalledCommandProducer, managedCommandDiagnostic, ManagedCommandError, publishManagedCommandBindings, revokeManagedCommandBindings, syncManagedCommandPackage, readInstalledCommandProducer, listManagedCommands } from '../utils/managed-command-store.js';
|
|
10
|
+
import { assertManagedCommandBindingIdentities, captureManagedCommandBindingRecoveryEvidence, normalizeInstalledCommandProducer, managedCommandDiagnostic, ManagedCommandError, publishManagedCommandBindings, revokeManagedCommandBindings, syncManagedCommandPackage, readInstalledCommandProducer, listManagedCommands } from '../utils/managed-command-store.js';
|
|
11
11
|
import { injectInstalledRuntimeConfig, carryRuntimeConfigNativeReceipt } from '../utils/runtime-config.js';
|
|
12
12
|
import { resolveCodexSkillsRelativeRoot } from '../utils/codex-skills-root.js';
|
|
13
13
|
import { resolveClaudeSkillsRelativeRoot } from '../utils/claude-skills-root.js';
|
|
@@ -17,7 +17,7 @@ import { generateCodexPermissionArtifacts, mergeClaudePermissions, } from '../ge
|
|
|
17
17
|
import { buildGeneratedName } from '../generators/shared.js';
|
|
18
18
|
import { applyConditionalCodexConfigTransactionFile, applyCodexConfigTransactionFile, composeManagedDeveloperInstructionsBlock, readCodexConfigFile, } from '../utils/codex-config.js';
|
|
19
19
|
import { canonicalizePathThroughExistingAncestor, resolveClaudeProjectKey, resolveCodexProjectKey, } from '../utils/state-paths.js';
|
|
20
|
-
import {
|
|
20
|
+
import { createCodexSkillStagingTreeContentDigest, } from '../utils/codex-skill-staging.js';
|
|
21
21
|
import { AW_PLUGIN_REQUIREMENTS_RECEIPT_PATH, createDynamicSkillExpectedTree, createDynamicSkillTreeContentDigest, readDynamicSkillTree, validateSkillDirectory, writeDynamicSkillTree, } from '../utils/dynamic-skill-tree.js';
|
|
22
22
|
import { parseCodexSharedHooksFile, serializeTrackedHookGroupIdentity, } from '../utils/hooks-contract.js';
|
|
23
23
|
import { buildCodexMarketplaceAddInvocation, buildCodexMarketplaceRemoveInvocation, buildCodexPluginAddInvocation, buildCodexPluginRemoveInvocation, CodexProjectConfigNotEffectiveError, runNativeCliChecked, SYSTEM_CODEX_MANAGER, } from '../utils/native-cli.js';
|
|
@@ -26,7 +26,7 @@ import { OWNED_TEXT_HEADER_PREFIX, createSharedOwnerToken, createSkillOwnerMarke
|
|
|
26
26
|
import { resolveArtifactRenderConfig, resolveArtifactRendererTarget, runArtifactRenderer, } from '../utils/artifact-renderer.js';
|
|
27
27
|
import { createArtifactConfigDigest, validateArtifactPlan, } from '../utils/artifact-plan.js';
|
|
28
28
|
import { resolveAwDeliveredArtifactRequestBatches } from '../utils/artifact-request.js';
|
|
29
|
-
import { createAwPluginRequirementsReceipt, parseAwPluginRequirementsReceipt, tryParseStrictSemVer, } from '../utils/manifest.js';
|
|
29
|
+
import { createAwPluginRequirementsReceipt, parseAwPluginRequirementsReceipt, readPluginManifest, tryParseStrictSemVer, } from '../utils/manifest.js';
|
|
30
30
|
import { resolvePlatformEntries } from '../utils/platform-entries.js';
|
|
31
31
|
import { resolveAwHome, resolveClaudePaths, resolveCodexPaths, resolveRepoRoot, getCodexHome, } from '../utils/paths.js';
|
|
32
32
|
import { assertNoSensitiveConfigInFiles, collectSensitivePluginConfigValues, runPreApplyScript, } from '../utils/plugin-scripts.js';
|
|
@@ -34,11 +34,12 @@ import { validateRuntimeSkillClosure } from '../utils/runtime-skill-closure.js';
|
|
|
34
34
|
import { findSensitiveTokenPath } from '../utils/sensitive-content.js';
|
|
35
35
|
import { atomicRemoveConfigFile, atomicReplaceConfigFile, withConfigFileMutation, } from '../utils/plugin-config.js';
|
|
36
36
|
import { readCatalogSourcesConfigSnapshot } from '../utils/catalog-sources.js';
|
|
37
|
-
import { assertSafeNamespacedMarketplacePluginRoot, getNamespacedMarketplaceName, MarketplaceRootValidationError, projectMarketplaceManifestForPlatform, readStrictNamespacedMarketplaceRoot, replayNamespacedMarketplacePluginProjections, refreshPreservedPlatformReceipt, replayNamespacedCodexSkillOverlays, } from '../utils/local-marketplace.js';
|
|
37
|
+
import { assertSafeNamespacedMarketplacePluginRoot, getNamespacedMarketplaceName, MarketplaceRootValidationError, projectMarketplaceManifestForPlatform, readStrictNamespacedMarketplaceRoot, deferNativeMarketplacePublications, replayNamespacedMarketplacePluginProjections, refreshPreservedPlatformReceipt, replayNamespacedCodexSkillOverlays, } from '../utils/local-marketplace.js';
|
|
38
38
|
import { commitMarketplaceGenerationBackup } from '../utils/orphan-marketplace-cleanup.js';
|
|
39
39
|
import { readClaudeSettings, writeClaudeSettings } from '../adapters/helpers.js';
|
|
40
40
|
import { analyzeCodexSurface } from '../utils/codex-surface-analysis.js';
|
|
41
|
-
import {
|
|
41
|
+
import { codexNativeRenderProjectionsEqual, createCodexNativeRenderProjection, createCodexNativeRenderReceipt, } from '../utils/codex-native-render-receipt.js';
|
|
42
|
+
import { createClaudeNativeRenderReceipt, nativeSkillRenderReceiptPath, parseNativeSkillRenderReceipt, serializeNativeSkillRenderReceipt, } from '../utils/claude-native-render-receipt.js';
|
|
42
43
|
import { inspectCodexSharedNative, } from '../utils/codex-shared-native.js';
|
|
43
44
|
import { calculateCodexNativeRenderPayloadDigest } from '../utils/catalog-digests.js';
|
|
44
45
|
import { createCodexNativeObservationSession, } from '../utils/codex-native-observation.js';
|
|
@@ -74,11 +75,21 @@ function withoutVerifiedRequirementsReceipt(plugin, files) {
|
|
|
74
75
|
const commandPackagePreparationCaches = new WeakMap();
|
|
75
76
|
const staticCommandPreparationCaches = new WeakMap();
|
|
76
77
|
const dynamicArtifactPreparationCaches = new WeakMap();
|
|
78
|
+
function artifactRenderResults(context) {
|
|
79
|
+
if (context.preparedArtifactRenderResults)
|
|
80
|
+
return context.preparedArtifactRenderResults;
|
|
81
|
+
let results = dynamicArtifactPreparationCaches.get(context);
|
|
82
|
+
if (!results) {
|
|
83
|
+
results = new Map();
|
|
84
|
+
dynamicArtifactPreparationCaches.set(context, results);
|
|
85
|
+
}
|
|
86
|
+
return results;
|
|
87
|
+
}
|
|
77
88
|
async function prepareStaticCommandArtifacts(options) {
|
|
78
89
|
const targets = getManagedCommandArtifactTargets(options.plugin.manifest).filter((target) => target.producer.kind === 'static-skill' && target.platform === options.platform);
|
|
79
90
|
if (!targets.length)
|
|
80
91
|
return [];
|
|
81
|
-
const config = await resolveArtifactRenderConfig({ sourceId: options.plugin.sourceId, sourceIdentity: options.plugin.sourceIdentity, logicalIdentity: options.plugin.catalogLogicalIdentity, pluginName: options.plugin.manifest.name, manifest: options.plugin.manifest, scope: 'user', cwd: options.
|
|
92
|
+
const config = await resolveArtifactRenderConfig({ sourceId: options.plugin.sourceId, sourceIdentity: options.plugin.sourceIdentity, logicalIdentity: options.plugin.catalogLogicalIdentity, pluginName: options.plugin.manifest.name, manifest: options.plugin.manifest, platform: options.platform, scope: 'user', cwd: options.plugin.rootDir, env: options.env, referencePlugins: options.context.referencePlugins });
|
|
82
93
|
const key = JSON.stringify([options.plugin.rootDir, options.platform, config]);
|
|
83
94
|
let cache = staticCommandPreparationCaches.get(options.context);
|
|
84
95
|
if (!cache) {
|
|
@@ -88,7 +99,7 @@ async function prepareStaticCommandArtifacts(options) {
|
|
|
88
99
|
let prepared = cache.get(key);
|
|
89
100
|
if (!prepared) {
|
|
90
101
|
prepared = (async () => {
|
|
91
|
-
const rendered = await runArtifactRenderer({ plugin: options.plugin, referencePlugins: options.context.referencePlugins, event: 'install', platform: options.platform, scope: 'user', configScope: 'user', cwd: options.
|
|
102
|
+
const rendered = await runArtifactRenderer({ plugin: options.plugin, referencePlugins: options.context.referencePlugins, event: 'install', platform: options.platform, scope: 'user', configScope: 'user', cwd: options.plugin.rootDir, commandEnv: options.env, requestedArtifactIds: targets.map((target) => target.id), signal: options.context.signal, scriptTimeoutMs: options.context.scriptTimeoutMs });
|
|
92
103
|
return validateArtifactPlan({ manifest: options.plugin.manifest, plan: rendered.plan, platform: options.platform, scope: 'user', requestedArtifactIds: rendered.context.requestedArtifactIds, renderConfig: rendered.context.config, rendererDigest: rendered.target.rendererDigest, manifestDigest: rendered.target.manifestDigest }).artifacts;
|
|
93
104
|
})();
|
|
94
105
|
cache.set(key, prepared);
|
|
@@ -128,7 +139,7 @@ async function commandPackageActions(options) {
|
|
|
128
139
|
let preparation = cache.get(getCommandPackageId(producer));
|
|
129
140
|
if (!preparation) {
|
|
130
141
|
preparation = (async () => {
|
|
131
|
-
const prepared = await prepareManagedCommandPackage({ ...options, referencePlugins: options.context.referencePlugins, packageKey: declaration.key, scope: declaration.scope });
|
|
142
|
+
const prepared = await prepareManagedCommandPackage({ ...options, referencePlugins: options.context.referencePlugins, packageKey: declaration.key, scope: declaration.scope, signal: options.context.signal, scriptTimeoutMs: options.context.scriptTimeoutMs });
|
|
132
143
|
try {
|
|
133
144
|
const files = [];
|
|
134
145
|
async function visit(directory, prefix) {
|
|
@@ -194,7 +205,7 @@ async function prepareStaticNativeSkillActions(options) {
|
|
|
194
205
|
return producer.kind === 'static-skill' && target.platform === options.platform && !artifacts.some((artifact) => artifact.id === target.id) && !options.commandCandidates.some((candidate) => candidate.producer.kind === 'static-skill' && candidate.producer.key === producer.skillKey && candidate.producer.platform === options.platform && candidate.producer.scope === scope);
|
|
195
206
|
});
|
|
196
207
|
if (missingTargets.length) {
|
|
197
|
-
const rendered = await runArtifactRenderer({ plugin: options.plugin, event: 'install', platform: options.platform, scope, configScope: scope, cwd: options.
|
|
208
|
+
const rendered = await runArtifactRenderer({ plugin: options.plugin, event: 'install', platform: options.platform, scope, configScope: scope, cwd: options.plugin.rootDir, commandEnv: options.env, requestedArtifactIds: missingTargets.map((target) => target.id), signal: options.signal, scriptTimeoutMs: options.scriptTimeoutMs });
|
|
198
209
|
artifacts.push(...validateArtifactPlan({ manifest: options.plugin.manifest, plan: rendered.plan, platform: options.platform, scope, requestedArtifactIds: rendered.context.requestedArtifactIds, renderConfig: rendered.context.config, rendererDigest: rendered.target.rendererDigest, manifestDigest: rendered.target.manifestDigest }).artifacts);
|
|
199
210
|
}
|
|
200
211
|
for (const entry of await fs.readdir(root, { withFileTypes: true })) {
|
|
@@ -511,48 +522,9 @@ function pathComponent(options) {
|
|
|
511
522
|
validateHealth: true,
|
|
512
523
|
};
|
|
513
524
|
}
|
|
514
|
-
function pristineTreeDescriptor(tree) {
|
|
515
|
-
return Object.entries(tree.files)
|
|
516
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
517
|
-
.map(([relativePath, content]) => ({
|
|
518
|
-
relativePath,
|
|
519
|
-
contentDigest: `sha256:${crypto.createHash('sha256').update(content).digest('hex')}`,
|
|
520
|
-
...(tree.fileModes?.[relativePath] ? { mode: tree.fileModes[relativePath] } : {}),
|
|
521
|
-
}));
|
|
522
|
-
}
|
|
523
525
|
function pluginActionId(plugin) {
|
|
524
526
|
return plugin.pluginId ?? plugin.manifest.name;
|
|
525
527
|
}
|
|
526
|
-
function skillWriteAction(options) {
|
|
527
|
-
const files = [
|
|
528
|
-
...Object.entries(options.tree.files).map(([relativePath, content]) => ({
|
|
529
|
-
relativePath,
|
|
530
|
-
contentBase64: content.toString('base64'),
|
|
531
|
-
contentDigest: `sha256:${crypto.createHash('sha256').update(content).digest('hex')}`,
|
|
532
|
-
...(options.tree.fileModes?.[relativePath] ? { mode: options.tree.fileModes[relativePath] } : {}),
|
|
533
|
-
})),
|
|
534
|
-
{
|
|
535
|
-
relativePath: '.agent-workflows-owner.json',
|
|
536
|
-
contentBase64: Buffer.from(createSkillOwnerMarkerContent(options.identity)).toString('base64'),
|
|
537
|
-
contentDigest: `sha256:${crypto.createHash('sha256')
|
|
538
|
-
.update(createSkillOwnerMarkerContent(options.identity)).digest('hex')}`,
|
|
539
|
-
},
|
|
540
|
-
].sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
541
|
-
const contentDigest = `sha256:${crypto.createHash('sha256').update(JSON.stringify(files)).digest('hex')}`;
|
|
542
|
-
return {
|
|
543
|
-
kind: 'writeOwnedArtifact',
|
|
544
|
-
pluginId: pluginActionId(options.plugin),
|
|
545
|
-
platform: options.platform,
|
|
546
|
-
scope: options.scope,
|
|
547
|
-
path: options.path,
|
|
548
|
-
allowedRoot: options.allowedRoot,
|
|
549
|
-
owner: options.identity,
|
|
550
|
-
artifactKind: 'skill-directory',
|
|
551
|
-
files,
|
|
552
|
-
contentDigest,
|
|
553
|
-
allowPristineUnowned: options.allowPristineUnowned,
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
528
|
function finalizeOwnedArtifactActions(actions) {
|
|
557
529
|
for (const action of actions) {
|
|
558
530
|
if (action.kind !== 'writeOwnedArtifact' || !action.owner)
|
|
@@ -830,6 +802,29 @@ async function codexRoleRegistrationOwned(options) {
|
|
|
830
802
|
return false;
|
|
831
803
|
}
|
|
832
804
|
}
|
|
805
|
+
export async function removeForceCleanupCodexRoleRegistration(options) {
|
|
806
|
+
const component = options.component;
|
|
807
|
+
if (component.kind !== 'owned-text-file' || component.identity.platform !== 'codex')
|
|
808
|
+
return;
|
|
809
|
+
const paths = resolveCodexPaths(options.cwd, component.identity.scope, options.env);
|
|
810
|
+
const roleKey = component.identity.artifactKey;
|
|
811
|
+
const expectedPath = path.join(paths.agentsDir, `${buildGeneratedName(component.identity.plugin, roleKey)}.toml`);
|
|
812
|
+
if (path.resolve(component.path) !== path.resolve(expectedPath))
|
|
813
|
+
return;
|
|
814
|
+
await applyConditionalCodexConfigTransactionFile(paths.configTomlPath, async (snapshot) => {
|
|
815
|
+
const registration = snapshot.agents[roleKey];
|
|
816
|
+
if (!registration?.configFile
|
|
817
|
+
|| path.resolve(path.dirname(paths.configTomlPath), registration.configFile)
|
|
818
|
+
!== path.resolve(component.path))
|
|
819
|
+
return null;
|
|
820
|
+
// Force authorizes the existing exclusive file. The matching registration is
|
|
821
|
+
// removed before that evidence disappears; missing or foreign files grant no authority.
|
|
822
|
+
const inspected = await inspectOwnedComponents({ components: [component], forceExclusive: true });
|
|
823
|
+
return inspected.components[0]?.state === 'present'
|
|
824
|
+
? { removeAgentRegistrations: [roleKey] }
|
|
825
|
+
: null;
|
|
826
|
+
});
|
|
827
|
+
}
|
|
833
828
|
function createCodexRoleRegistrationComponent(options) {
|
|
834
829
|
return {
|
|
835
830
|
kind: 'shared-config',
|
|
@@ -1127,7 +1122,7 @@ function renderCodexRole(options) {
|
|
|
1127
1122
|
].join('\n');
|
|
1128
1123
|
}
|
|
1129
1124
|
async function resolveDynamicArtifacts(options) {
|
|
1130
|
-
const preparedArtifacts = options.
|
|
1125
|
+
const preparedArtifacts = options.context
|
|
1131
1126
|
? await prepareStaticCommandArtifacts({ ...options, context: options.context }) : [];
|
|
1132
1127
|
const preparedIds = new Set(preparedArtifacts.map((artifact) => artifact.id));
|
|
1133
1128
|
const requestBatches = (options.requestedArtifactIds
|
|
@@ -1141,11 +1136,7 @@ async function resolveDynamicArtifacts(options) {
|
|
|
1141
1136
|
return { artifacts: [], sourceDirs: () => [], sensitiveValues: [] };
|
|
1142
1137
|
}
|
|
1143
1138
|
const previousArtifacts = [...options.previousArtifacts];
|
|
1144
|
-
|
|
1145
|
-
if (options.context && !preparedResults) {
|
|
1146
|
-
preparedResults = new Map();
|
|
1147
|
-
dynamicArtifactPreparationCaches.set(options.context, preparedResults);
|
|
1148
|
-
}
|
|
1139
|
+
const preparedResults = options.context && artifactRenderResults(options.context);
|
|
1149
1140
|
const renders = [];
|
|
1150
1141
|
for (const requestedArtifactIds of requestBatches) {
|
|
1151
1142
|
renders.push(await runArtifactRenderer({
|
|
@@ -1159,6 +1150,7 @@ async function resolveDynamicArtifacts(options) {
|
|
|
1159
1150
|
previousArtifacts,
|
|
1160
1151
|
requestedArtifactIds,
|
|
1161
1152
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
1153
|
+
signal: options.signal,
|
|
1162
1154
|
preparedResults,
|
|
1163
1155
|
}));
|
|
1164
1156
|
}
|
|
@@ -1168,6 +1160,7 @@ async function resolveDynamicArtifacts(options) {
|
|
|
1168
1160
|
logicalIdentity: options.plugin.catalogLogicalIdentity,
|
|
1169
1161
|
pluginName: options.plugin.manifest.name,
|
|
1170
1162
|
manifest: options.plugin.manifest,
|
|
1163
|
+
platform: options.platform,
|
|
1171
1164
|
referencePlugins: options.referencePlugins ?? options.context?.referencePlugins,
|
|
1172
1165
|
scope: options.scope,
|
|
1173
1166
|
cwd: options.cwd,
|
|
@@ -1194,55 +1187,7 @@ async function resolveDynamicArtifacts(options) {
|
|
|
1194
1187
|
artifacts,
|
|
1195
1188
|
runtimeConfigSnapshots: Object.assign({}, ...renders.map((render) => render.runtimeConfigSnapshots)),
|
|
1196
1189
|
sourceDirs: (artifact) => sourceDirsByArtifact.get(`${artifact.id}\0${artifact.target}`) ?? [],
|
|
1197
|
-
sensitiveValues: collectSensitivePluginConfigValues(options.plugin.manifest, config.values),
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
function dynamicSkillWrite(options) {
|
|
1201
|
-
const skillKey = 'skillKey' in options.artifact ? options.artifact.skillKey : '';
|
|
1202
|
-
const identity = ownerIdentity(options.plugin.manifest.name, skillKey, options.platform, options.scope);
|
|
1203
|
-
const component = pathComponent({
|
|
1204
|
-
kind: 'skill-directory',
|
|
1205
|
-
path: options.skillPath,
|
|
1206
|
-
allowedRoot: options.allowedRoot,
|
|
1207
|
-
identity,
|
|
1208
|
-
...(options.platform === 'codex' && options.scope === 'user'
|
|
1209
|
-
? {
|
|
1210
|
-
pristineTree: pristineTreeDescriptor(options.tree),
|
|
1211
|
-
}
|
|
1212
|
-
: {}),
|
|
1213
|
-
});
|
|
1214
|
-
return {
|
|
1215
|
-
artifact: {
|
|
1216
|
-
path: options.skillPath,
|
|
1217
|
-
paths: Object.keys(options.tree.files).map((relativePath) => path.join(options.skillPath, relativePath.split('/').join(path.sep))),
|
|
1218
|
-
kind: 'skill',
|
|
1219
|
-
platform: options.platform,
|
|
1220
|
-
artifactKey: skillKey,
|
|
1221
|
-
id: options.artifact.id,
|
|
1222
|
-
target: options.artifact.target,
|
|
1223
|
-
state: options.artifact.state,
|
|
1224
|
-
...('disabledReason' in options.artifact && options.artifact.disabledReason
|
|
1225
|
-
? { disabledReason: options.artifact.disabledReason }
|
|
1226
|
-
: {}),
|
|
1227
|
-
refreshKeys: [...options.artifact.refreshKeys],
|
|
1228
|
-
configDigest: options.artifact.configDigest,
|
|
1229
|
-
contentDigest: options.platform === 'codex'
|
|
1230
|
-
? createCodexSkillStagingTreeContentDigest(options.tree)
|
|
1231
|
-
: createDynamicSkillTreeContentDigest(options.tree),
|
|
1232
|
-
},
|
|
1233
|
-
...(options.artifact.state === 'present' ? { component } : {}),
|
|
1234
|
-
...(options.artifact.state === 'present' ? {
|
|
1235
|
-
action: skillWriteAction({
|
|
1236
|
-
plugin: options.plugin,
|
|
1237
|
-
platform: options.platform,
|
|
1238
|
-
scope: options.scope,
|
|
1239
|
-
path: options.skillPath,
|
|
1240
|
-
allowedRoot: options.allowedRoot,
|
|
1241
|
-
identity,
|
|
1242
|
-
tree: options.tree,
|
|
1243
|
-
allowPristineUnowned: options.platform === 'codex' && options.scope === 'user',
|
|
1244
|
-
}),
|
|
1245
|
-
} : {}),
|
|
1190
|
+
sensitiveValues: collectSensitivePluginConfigValues(options.plugin.manifest, config.values, options.platform),
|
|
1246
1191
|
};
|
|
1247
1192
|
}
|
|
1248
1193
|
async function buildClaudeWrites(options) {
|
|
@@ -1254,38 +1199,10 @@ async function buildClaudeWrites(options) {
|
|
|
1254
1199
|
previousArtifacts: options.historicalArtifacts,
|
|
1255
1200
|
});
|
|
1256
1201
|
const commandCandidates = [...(options.commandCandidates ?? [])];
|
|
1257
|
-
const preparedSkills = [];
|
|
1258
|
-
for (const artifact of dynamic.artifacts.filter((entry) => entry.target === 'claude.skill')) {
|
|
1259
|
-
const tree = await createDynamicSkillExpectedTree({
|
|
1260
|
-
artifact,
|
|
1261
|
-
sourceDirs: dynamic.sourceDirs(artifact),
|
|
1262
|
-
requireReadme: true,
|
|
1263
|
-
requirementsReceipt: requirementsReceipt(options.plugin),
|
|
1264
|
-
sourceRequirementsReceiptPolicy: 'allow',
|
|
1265
|
-
});
|
|
1266
|
-
await injectInstalledRuntimeConfig(tree, dynamic.runtimeConfigSnapshots?.[artifact.id]);
|
|
1267
|
-
const candidate = await prepareSkillCommandCandidate({ ...options, producer: { kind: 'artifact', artifactId: artifact.id }, platform: 'claude', tree, artifacts: dynamic.artifacts });
|
|
1268
|
-
if (candidate)
|
|
1269
|
-
commandCandidates.push(candidate);
|
|
1270
|
-
preparedSkills.push({ artifact, tree });
|
|
1271
|
-
}
|
|
1272
1202
|
const staticSkills = await prepareStaticNativeSkillActions({ ...options, platform: 'claude', artifacts: dynamic.artifacts, commandCandidates });
|
|
1273
1203
|
commandCandidates.push(...staticSkills.candidates);
|
|
1274
1204
|
options.nativeSkillActions?.push(...staticSkills.actions);
|
|
1275
1205
|
const commandResolver = await createManagedCommandReferenceResolver({ ...options, platform: 'claude', candidates: commandCandidates });
|
|
1276
|
-
for (const { artifact, tree } of preparedSkills) {
|
|
1277
|
-
const skillKey = artifact.skillKey;
|
|
1278
|
-
resolveSkillManagedCommandReferences(tree, commandResolver);
|
|
1279
|
-
assertNoSensitiveConfigInFiles(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), dynamic.sensitiveValues, 'artifactRendererSensitiveConfigExposed: Final dynamic Skill contains sensitive config.');
|
|
1280
|
-
writes.push(dynamicSkillWrite({
|
|
1281
|
-
...options,
|
|
1282
|
-
platform: 'claude',
|
|
1283
|
-
artifact,
|
|
1284
|
-
skillPath: path.join(paths.configDir, 'skills', skillKey),
|
|
1285
|
-
allowedRoot: path.join(paths.configDir, 'skills'),
|
|
1286
|
-
tree,
|
|
1287
|
-
}));
|
|
1288
|
-
}
|
|
1289
1206
|
for (const artifact of generateInstructionArtifacts(options.plugin.manifest.name, resolvePlatformEntries(options.plugin.manifest.extensions?.instructions, 'claude'), 'claude')) {
|
|
1290
1207
|
writes.push(generatedTextWrite({
|
|
1291
1208
|
...options,
|
|
@@ -1333,43 +1250,11 @@ async function buildCodexWrites(options) {
|
|
|
1333
1250
|
});
|
|
1334
1251
|
const dynamicInstructions = dynamic.artifacts.filter((entry) => entry.target === 'codex.developerInstructionsBlock');
|
|
1335
1252
|
const dynamicRoles = dynamic.artifacts.filter((entry) => entry.target === 'codex.agentRole');
|
|
1336
|
-
const dynamicSkills = dynamic.artifacts.filter((entry) => entry.target === 'codex.skill');
|
|
1337
1253
|
const commandCandidates = [...(options.commandCandidates ?? [])];
|
|
1338
|
-
const preparedSkills = [];
|
|
1339
|
-
const repoRoot = await resolveRepoRoot(options.cwd);
|
|
1340
|
-
const skillRoot = options.scope === 'user'
|
|
1341
|
-
? path.join(getCodexHome(options.env), 'skills')
|
|
1342
|
-
: path.join(repoRoot, '.agents', 'skills');
|
|
1343
|
-
for (const artifact of dynamicSkills) {
|
|
1344
|
-
const tree = await createCodexSkillExpectedTree({
|
|
1345
|
-
artifact,
|
|
1346
|
-
sourceDirs: dynamic.sourceDirs(artifact),
|
|
1347
|
-
requireReadme: true,
|
|
1348
|
-
requirementsReceipt: requirementsReceipt(options.plugin),
|
|
1349
|
-
sourceRequirementsReceiptPolicy: 'allow',
|
|
1350
|
-
});
|
|
1351
|
-
await injectInstalledRuntimeConfig(tree, dynamic.runtimeConfigSnapshots?.[artifact.id]);
|
|
1352
|
-
const candidate = await prepareSkillCommandCandidate({ ...options, producer: { kind: 'artifact', artifactId: artifact.id }, platform: 'codex', tree, artifacts: dynamic.artifacts });
|
|
1353
|
-
if (candidate)
|
|
1354
|
-
commandCandidates.push(candidate);
|
|
1355
|
-
preparedSkills.push({ artifact, tree });
|
|
1356
|
-
}
|
|
1357
1254
|
const staticSkills = await prepareStaticNativeSkillActions({ ...options, platform: 'codex', artifacts: dynamic.artifacts, commandCandidates });
|
|
1358
1255
|
commandCandidates.push(...staticSkills.candidates);
|
|
1359
1256
|
options.nativeSkillActions?.push(...staticSkills.actions);
|
|
1360
1257
|
const commandResolver = await createManagedCommandReferenceResolver({ ...options, platform: 'codex', candidates: commandCandidates });
|
|
1361
|
-
for (const { artifact, tree } of preparedSkills) {
|
|
1362
|
-
resolveSkillManagedCommandReferences(tree, commandResolver);
|
|
1363
|
-
assertNoSensitiveConfigInFiles(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), dynamic.sensitiveValues, 'artifactRendererSensitiveConfigExposed: Final dynamic Skill contains sensitive config.');
|
|
1364
|
-
writes.push(dynamicSkillWrite({
|
|
1365
|
-
...options,
|
|
1366
|
-
platform: 'codex',
|
|
1367
|
-
artifact,
|
|
1368
|
-
skillPath: path.join(skillRoot, artifact.skillKey),
|
|
1369
|
-
allowedRoot: skillRoot,
|
|
1370
|
-
tree,
|
|
1371
|
-
}));
|
|
1372
|
-
}
|
|
1373
1258
|
const staticInstructions = dynamicInstructions.length > 0
|
|
1374
1259
|
? []
|
|
1375
1260
|
: resolvePlatformEntries(options.plugin.manifest.extensions?.instructions, 'codex');
|
|
@@ -1603,40 +1488,9 @@ async function buildInspectionWrites(options) {
|
|
|
1603
1488
|
}),
|
|
1604
1489
|
});
|
|
1605
1490
|
}
|
|
1606
|
-
for (const target of options.plugin.manifest.artifacts?.targets ?? []) {
|
|
1607
|
-
if (target.platform !== 'claude'
|
|
1608
|
-
|| !target.scopes.includes(options.scope)
|
|
1609
|
-
|| target.target !== 'claude.skill'
|
|
1610
|
-
|| !target.skillKey)
|
|
1611
|
-
continue;
|
|
1612
|
-
const state = target.states.includes('present') ? 'present' : 'disabled';
|
|
1613
|
-
const skillPath = path.join(paths.configDir, 'skills', target.skillKey);
|
|
1614
|
-
const component = pathComponent({
|
|
1615
|
-
kind: 'skill-directory',
|
|
1616
|
-
path: skillPath,
|
|
1617
|
-
allowedRoot: path.dirname(skillPath),
|
|
1618
|
-
identity: ownerIdentity(options.plugin.manifest.name, target.skillKey, 'claude', options.scope),
|
|
1619
|
-
});
|
|
1620
|
-
writes.push({
|
|
1621
|
-
artifact: {
|
|
1622
|
-
path: skillPath,
|
|
1623
|
-
kind: 'skill',
|
|
1624
|
-
platform: 'claude',
|
|
1625
|
-
artifactKey: target.skillKey,
|
|
1626
|
-
id: target.id,
|
|
1627
|
-
target: target.target,
|
|
1628
|
-
state,
|
|
1629
|
-
},
|
|
1630
|
-
...(state === 'present' ? { component } : {}),
|
|
1631
|
-
...(target.states.includes('present') && target.states.includes('disabled')
|
|
1632
|
-
? { optional: true }
|
|
1633
|
-
: {}),
|
|
1634
|
-
});
|
|
1635
|
-
}
|
|
1636
1491
|
return writes;
|
|
1637
1492
|
}
|
|
1638
1493
|
const paths = resolveCodexPaths(options.cwd, options.scope, options.env);
|
|
1639
|
-
const repoRoot = await resolveRepoRoot(options.cwd);
|
|
1640
1494
|
const instructions = resolvePlatformEntries(options.plugin.manifest.extensions?.instructions, 'codex');
|
|
1641
1495
|
const targets = (options.plugin.manifest.artifacts?.targets ?? []).filter((target) => target.platform === 'codex' && target.scopes.includes(options.scope));
|
|
1642
1496
|
const instructionTargets = targets.filter((target) => target.target === 'codex.developerInstructionsBlock');
|
|
@@ -1655,37 +1509,8 @@ async function buildInspectionWrites(options) {
|
|
|
1655
1509
|
...(instructions.length === 0 && instructionOptional ? { optional: true } : {}),
|
|
1656
1510
|
});
|
|
1657
1511
|
}
|
|
1658
|
-
const dynamicSkillRoot = options.scope === 'user'
|
|
1659
|
-
? path.join(getCodexHome(options.env), 'skills')
|
|
1660
|
-
: path.join(repoRoot, '.agents', 'skills');
|
|
1661
1512
|
for (const target of targets) {
|
|
1662
1513
|
const state = target.states.includes('present') ? 'present' : 'disabled';
|
|
1663
|
-
if (target.target === 'codex.skill'
|
|
1664
|
-
&& target.delivery?.mode === 'aw-extension'
|
|
1665
|
-
&& target.skillKey) {
|
|
1666
|
-
const skillPath = path.join(dynamicSkillRoot, target.skillKey);
|
|
1667
|
-
const component = pathComponent({
|
|
1668
|
-
kind: 'skill-directory',
|
|
1669
|
-
path: skillPath,
|
|
1670
|
-
allowedRoot: dynamicSkillRoot,
|
|
1671
|
-
identity: ownerIdentity(options.plugin.manifest.name, target.skillKey, 'codex', options.scope),
|
|
1672
|
-
});
|
|
1673
|
-
writes.push({
|
|
1674
|
-
artifact: {
|
|
1675
|
-
path: skillPath,
|
|
1676
|
-
kind: 'skill',
|
|
1677
|
-
platform: 'codex',
|
|
1678
|
-
artifactKey: target.skillKey,
|
|
1679
|
-
id: target.id,
|
|
1680
|
-
target: target.target,
|
|
1681
|
-
state,
|
|
1682
|
-
},
|
|
1683
|
-
...(state === 'present' ? { component } : {}),
|
|
1684
|
-
...(target.states.includes('present') && target.states.includes('disabled')
|
|
1685
|
-
? { optional: true }
|
|
1686
|
-
: {}),
|
|
1687
|
-
});
|
|
1688
|
-
}
|
|
1689
1514
|
if (target.target === 'codex.agentRole' && target.roleKey) {
|
|
1690
1515
|
const rolePath = path.join(paths.configDir, 'agents', `${buildGeneratedName(options.plugin.manifest.name, target.roleKey)}.toml`);
|
|
1691
1516
|
const roleComponent = pathComponent({
|
|
@@ -1919,9 +1744,9 @@ async function codexPayloadPathSafe(payloadRoot, allowedRoot = payloadRoot) {
|
|
|
1919
1744
|
}
|
|
1920
1745
|
return true;
|
|
1921
1746
|
}
|
|
1922
|
-
class
|
|
1747
|
+
class NativeSkillProjectionUnsafeError extends Error {
|
|
1923
1748
|
}
|
|
1924
|
-
async function
|
|
1749
|
+
async function resolveNativeSkillsRoot(payloadRoot, rawSkillsRoot, platform) {
|
|
1925
1750
|
const normalizedSeparators = rawSkillsRoot.replace(/\\/gu, '/');
|
|
1926
1751
|
const relativeRoot = path.posix.normalize(normalizedSeparators.replace(/^\.\//u, ''));
|
|
1927
1752
|
if (!relativeRoot
|
|
@@ -1930,21 +1755,33 @@ async function resolveCodexSkillsRoot(payloadRoot, rawSkillsRoot) {
|
|
|
1930
1755
|
|| relativeRoot.startsWith('../')
|
|
1931
1756
|
|| path.posix.isAbsolute(normalizedSeparators)
|
|
1932
1757
|
|| path.win32.isAbsolute(rawSkillsRoot)) {
|
|
1933
|
-
throw new
|
|
1758
|
+
throw new NativeSkillProjectionUnsafeError(`${platform}NativeSkillsRootInvalid: Native Skills root is invalid.`);
|
|
1934
1759
|
}
|
|
1935
1760
|
const root = path.join(payloadRoot, ...relativeRoot.split('/'));
|
|
1936
1761
|
if (!await codexReadPathSafe(payloadRoot, root)) {
|
|
1937
|
-
throw new
|
|
1762
|
+
throw new NativeSkillProjectionUnsafeError(`${platform}NativeSkillsRootInvalid: Native Skills root is unsafe.`);
|
|
1938
1763
|
}
|
|
1939
1764
|
return { relativeRoot, root };
|
|
1940
1765
|
}
|
|
1941
1766
|
function codexNativeRenderTargets(plugin) {
|
|
1942
1767
|
return (plugin.manifest.artifacts?.targets ?? []).filter((target) => target.platform === 'codex'
|
|
1943
|
-
&& target.target === 'codex.skill'
|
|
1944
|
-
&& target.delivery?.mode === 'codex-native');
|
|
1768
|
+
&& target.target === 'codex.skill');
|
|
1945
1769
|
}
|
|
1946
|
-
|
|
1947
|
-
const
|
|
1770
|
+
function nativeSkillRefreshKeys(plugin, target) {
|
|
1771
|
+
const commandKeys = getManagedCommandArtifactTargets(plugin.manifest).flatMap((command) => command.producer.kind === 'artifact'
|
|
1772
|
+
&& command.producer.artifactId === target.id
|
|
1773
|
+
&& command.platform === target.platform
|
|
1774
|
+
? command.refreshKeys
|
|
1775
|
+
: []);
|
|
1776
|
+
return [...new Set([...target.refreshKeys, ...commandKeys])];
|
|
1777
|
+
}
|
|
1778
|
+
function nativeSkillContentDigest(platform, tree) {
|
|
1779
|
+
return platform === 'codex'
|
|
1780
|
+
? createCodexSkillStagingTreeContentDigest(tree)
|
|
1781
|
+
: createDynamicSkillTreeContentDigest(tree);
|
|
1782
|
+
}
|
|
1783
|
+
async function readNativeSkillRenderReceiptEvidence(payloadRoot, platform) {
|
|
1784
|
+
const receiptPath = path.join(payloadRoot, nativeSkillRenderReceiptPath(platform));
|
|
1948
1785
|
const stats = await lstatIfPresent(receiptPath);
|
|
1949
1786
|
if (!stats)
|
|
1950
1787
|
return { state: 'absent' };
|
|
@@ -1958,16 +1795,16 @@ async function readCodexNativeRenderReceiptEvidence(payloadRoot) {
|
|
|
1958
1795
|
return { state: 'unreadable' };
|
|
1959
1796
|
}
|
|
1960
1797
|
try {
|
|
1961
|
-
return { state: 'present', receipt:
|
|
1798
|
+
return { state: 'present', receipt: parseNativeSkillRenderReceipt(platform, content) };
|
|
1962
1799
|
}
|
|
1963
1800
|
catch {
|
|
1964
1801
|
return { state: 'invalid' };
|
|
1965
1802
|
}
|
|
1966
1803
|
}
|
|
1967
|
-
function
|
|
1804
|
+
function nativeSkillRenderEvidenceIssue(reason, diagnostic) {
|
|
1968
1805
|
return { state: 'issue', reason, diagnostic };
|
|
1969
1806
|
}
|
|
1970
|
-
async function
|
|
1807
|
+
async function readNativeSkillProjectionManifest(manifestPath) {
|
|
1971
1808
|
let stats;
|
|
1972
1809
|
try {
|
|
1973
1810
|
stats = await lstatIfPresent(manifestPath);
|
|
@@ -1989,142 +1826,146 @@ async function readCodexNativeProjectionManifest(manifestPath) {
|
|
|
1989
1826
|
return { state: error instanceof SyntaxError ? 'invalid' : 'unreadable' };
|
|
1990
1827
|
}
|
|
1991
1828
|
}
|
|
1992
|
-
async function
|
|
1829
|
+
async function resolveNativeSkillRenderExpectedEvidence(options) {
|
|
1830
|
+
const { platform } = options;
|
|
1993
1831
|
const logicalPluginId = options.plugin.pluginId
|
|
1994
1832
|
?? (options.plugin.sourceId ? `${options.plugin.sourceId}/${options.plugin.manifest.name}` : undefined);
|
|
1995
1833
|
if (!logicalPluginId || !options.plugin.sourceId || !options.plugin.sourceIdentity) {
|
|
1996
|
-
throw new Error('
|
|
1834
|
+
throw new Error('Native Skill render projection requires namespaced source identity.');
|
|
1997
1835
|
}
|
|
1998
1836
|
const marketplace = await readStrictNamespacedMarketplaceRoot({
|
|
1999
1837
|
trustedMarketplaceRoot: path.join(resolveAwHome(options.env), 'marketplaces'),
|
|
2000
1838
|
rootDir: options.marketplaceRoot,
|
|
2001
1839
|
});
|
|
2002
1840
|
if (!marketplace) {
|
|
2003
|
-
return
|
|
1841
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionReceiptMissing');
|
|
2004
1842
|
}
|
|
2005
1843
|
if (marketplace.config.sourceId !== options.plugin.sourceId
|
|
2006
1844
|
|| marketplace.config.sourceIdentity !== options.plugin.sourceIdentity
|
|
2007
1845
|
|| marketplace.config.marketplaceName !== options.marketplaceName) {
|
|
2008
|
-
return
|
|
1846
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'projectionReceiptIdentityMismatch');
|
|
2009
1847
|
}
|
|
2010
1848
|
const payloadRoot = path.join(options.marketplaceRoot, 'plugins', options.plugin.manifest.name);
|
|
2011
1849
|
const payloadStats = await lstatIfPresent(payloadRoot);
|
|
2012
1850
|
if (!payloadStats) {
|
|
2013
|
-
return
|
|
1851
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionReceiptMissing');
|
|
2014
1852
|
}
|
|
2015
1853
|
if (!payloadStats.isDirectory() || payloadStats.isSymbolicLink()) {
|
|
2016
|
-
return
|
|
1854
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2017
1855
|
}
|
|
2018
1856
|
if (!await codexPayloadPathSafe(payloadRoot, options.marketplaceRoot)) {
|
|
2019
|
-
return
|
|
1857
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2020
1858
|
}
|
|
2021
|
-
const
|
|
2022
|
-
const [sourceManifestEvidence,
|
|
2023
|
-
|
|
2024
|
-
|
|
1859
|
+
const platformManifestPath = path.join(payloadRoot, `.${platform}-plugin`, 'plugin.json');
|
|
1860
|
+
const [sourceManifestEvidence, platformManifestEvidence] = await Promise.all([
|
|
1861
|
+
readNativeSkillProjectionManifest(path.join(payloadRoot, '.agents-plugin', 'plugin.json')),
|
|
1862
|
+
readNativeSkillProjectionManifest(platformManifestPath),
|
|
2025
1863
|
]);
|
|
2026
1864
|
if (sourceManifestEvidence.state === 'unsafe'
|
|
2027
|
-
||
|
|
2028
|
-
return
|
|
1865
|
+
|| platformManifestEvidence.state === 'unsafe') {
|
|
1866
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2029
1867
|
}
|
|
2030
1868
|
if ((sourceManifestEvidence.state === 'present'
|
|
2031
1869
|
&& sourceManifestEvidence.value.name !== options.plugin.manifest.name)
|
|
2032
|
-
|| (
|
|
2033
|
-
&&
|
|
1870
|
+
|| (platformManifestEvidence.state === 'present'
|
|
1871
|
+
&& platformManifestEvidence.value.name !== options.plugin.manifest.name)
|
|
2034
1872
|
|| (sourceManifestEvidence.state === 'present'
|
|
2035
|
-
&&
|
|
2036
|
-
&& sourceManifestEvidence.value.version !==
|
|
2037
|
-
return
|
|
1873
|
+
&& platformManifestEvidence.state === 'present'
|
|
1874
|
+
&& sourceManifestEvidence.value.version !== platformManifestEvidence.value.version)) {
|
|
1875
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'manifestIdentityMismatch');
|
|
2038
1876
|
}
|
|
2039
1877
|
if (sourceManifestEvidence.state === 'unreadable'
|
|
2040
|
-
||
|
|
2041
|
-
return
|
|
1878
|
+
|| platformManifestEvidence.state === 'unreadable') {
|
|
1879
|
+
return nativeSkillRenderEvidenceIssue('unreadable', 'manifestUnreadable');
|
|
2042
1880
|
}
|
|
2043
1881
|
if (sourceManifestEvidence.state === 'missing'
|
|
2044
|
-
||
|
|
2045
|
-
return
|
|
1882
|
+
|| platformManifestEvidence.state === 'missing') {
|
|
1883
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'manifestMissing');
|
|
2046
1884
|
}
|
|
2047
1885
|
if (sourceManifestEvidence.state === 'invalid'
|
|
2048
|
-
||
|
|
2049
|
-
return
|
|
1886
|
+
|| platformManifestEvidence.state === 'invalid') {
|
|
1887
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'manifestUnreadable');
|
|
2050
1888
|
}
|
|
2051
1889
|
if (sourceManifestEvidence.state !== 'present'
|
|
2052
|
-
||
|
|
2053
|
-
return
|
|
1890
|
+
|| platformManifestEvidence.state !== 'present') {
|
|
1891
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'manifestUnreadable');
|
|
2054
1892
|
}
|
|
2055
1893
|
const sourceManifest = sourceManifestEvidence.value;
|
|
2056
|
-
const
|
|
1894
|
+
const platformManifest = platformManifestEvidence.value;
|
|
2057
1895
|
if (typeof sourceManifest.version !== 'string'
|
|
2058
1896
|
|| !tryParseStrictSemVer(sourceManifest.version)) {
|
|
2059
|
-
return
|
|
2060
|
-
}
|
|
2061
|
-
const
|
|
2062
|
-
?
|
|
2063
|
-
: './
|
|
2064
|
-
const
|
|
1897
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'manifestVersionInvalid');
|
|
1898
|
+
}
|
|
1899
|
+
const defaultSkillsRoot = platform === 'codex'
|
|
1900
|
+
? './codex/skills'
|
|
1901
|
+
: `./claude/${(options.plugin.manifest.skills ?? './skills').replace(/^\.\//u, '')}`;
|
|
1902
|
+
const rawSkillsRoot = typeof platformManifest.skills === 'string' && platformManifest.skills.trim() !== ''
|
|
1903
|
+
? platformManifest.skills
|
|
1904
|
+
: defaultSkillsRoot;
|
|
1905
|
+
const { relativeRoot: skillsRelativeRoot } = await resolveNativeSkillsRoot(payloadRoot, rawSkillsRoot, platform);
|
|
2065
1906
|
const skillsRoot = path.join(payloadRoot, ...skillsRelativeRoot.split('/'));
|
|
2066
1907
|
const skillsRootStats = await lstatIfPresent(skillsRoot);
|
|
2067
1908
|
if (skillsRootStats && (!skillsRootStats.isDirectory() || skillsRootStats.isSymbolicLink())) {
|
|
2068
|
-
return
|
|
1909
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2069
1910
|
}
|
|
2070
|
-
const targets =
|
|
1911
|
+
const targets = nativeSkillRenderTargets(options.plugin, platform);
|
|
2071
1912
|
for (const target of targets) {
|
|
2072
1913
|
if (await lstatIfPresent(path.join(skillsRoot, target.skillKey, '.agent-workflows-owner.json'))) {
|
|
2073
|
-
return
|
|
1914
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2074
1915
|
}
|
|
2075
1916
|
}
|
|
2076
|
-
const receiptEvidence = await
|
|
1917
|
+
const receiptEvidence = await readNativeSkillRenderReceiptEvidence(payloadRoot, platform);
|
|
2077
1918
|
if (receiptEvidence.state === 'absent') {
|
|
2078
|
-
return
|
|
1919
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionReceiptMissing');
|
|
2079
1920
|
}
|
|
2080
1921
|
if (receiptEvidence.state === 'unsafe') {
|
|
2081
|
-
return
|
|
1922
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2082
1923
|
}
|
|
2083
1924
|
if (receiptEvidence.state === 'invalid') {
|
|
2084
|
-
return
|
|
1925
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionReceiptUnreadable');
|
|
2085
1926
|
}
|
|
2086
1927
|
if (receiptEvidence.state === 'unreadable') {
|
|
2087
|
-
return
|
|
1928
|
+
return nativeSkillRenderEvidenceIssue('unreadable', 'projectionReceiptUnreadable');
|
|
2088
1929
|
}
|
|
2089
1930
|
const receipt = receiptEvidence.receipt;
|
|
2090
1931
|
if (receipt.logicalPluginId !== logicalPluginId
|
|
2091
1932
|
|| receipt.strategy !== 'shared-user'
|
|
2092
1933
|
|| receipt.sourceIdentity !== marketplace.config.sourceIdentity
|
|
2093
1934
|
|| receipt.pluginVersion !== sourceManifest.version) {
|
|
2094
|
-
return
|
|
1935
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'projectionReceiptIdentityMismatch');
|
|
2095
1936
|
}
|
|
2096
|
-
const emptyArtifactDigest =
|
|
1937
|
+
const emptyArtifactDigest = nativeSkillContentDigest(platform, {
|
|
2097
1938
|
skillKey: 'empty',
|
|
2098
1939
|
files: {},
|
|
2099
1940
|
});
|
|
2100
1941
|
for (const receiptTarget of receipt.targets) {
|
|
2101
1942
|
const skillRoot = path.join(payloadRoot, ...skillsRelativeRoot.split('/'), receiptTarget.skillKey);
|
|
2102
1943
|
if (await lstatIfPresent(path.join(skillRoot, '.agent-workflows-owner.json'))) {
|
|
2103
|
-
return
|
|
1944
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2104
1945
|
}
|
|
2105
1946
|
const skillStats = await lstatIfPresent(skillRoot);
|
|
2106
1947
|
if (skillStats && (!skillStats.isDirectory() || skillStats.isSymbolicLink())) {
|
|
2107
|
-
return
|
|
1948
|
+
return nativeSkillRenderEvidenceIssue('foreign', 'payloadPathUnsafe');
|
|
2108
1949
|
}
|
|
2109
1950
|
let tree;
|
|
2110
1951
|
try {
|
|
2111
|
-
tree = skillStats ? await readDynamicSkillTree(skillRoot,
|
|
1952
|
+
tree = skillStats ? await readDynamicSkillTree(skillRoot, `${platform}.skill`) : null;
|
|
2112
1953
|
}
|
|
2113
1954
|
catch (error) {
|
|
2114
|
-
return
|
|
1955
|
+
return nativeSkillRenderEvidenceIssue(error instanceof Error && typeof error.code !== 'string'
|
|
2115
1956
|
? 'damaged'
|
|
2116
1957
|
: 'unreadable', 'projectionPayloadDigestMismatch');
|
|
2117
1958
|
}
|
|
2118
1959
|
const artifactDigest = tree
|
|
2119
|
-
?
|
|
1960
|
+
? nativeSkillContentDigest(platform, tree)
|
|
2120
1961
|
: emptyArtifactDigest;
|
|
2121
1962
|
if (artifactDigest !== receiptTarget.artifactDigest) {
|
|
2122
|
-
return
|
|
1963
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionPayloadDigestMismatch');
|
|
2123
1964
|
}
|
|
2124
1965
|
}
|
|
2125
1966
|
const payloadDigest = await calculateCodexNativeRenderPayloadDigest(payloadRoot);
|
|
2126
1967
|
if (payloadDigest !== receipt.payloadDigest) {
|
|
2127
|
-
return
|
|
1968
|
+
return nativeSkillRenderEvidenceIssue('damaged', 'projectionPayloadDigestMismatch');
|
|
2128
1969
|
}
|
|
2129
1970
|
const receiptTargets = new Map(receipt.targets.map((target) => [target.id, target]));
|
|
2130
1971
|
if (targets.length === 0
|
|
@@ -2134,7 +1975,7 @@ async function resolveCodexNativeRenderExpectedEvidence(options) {
|
|
|
2134
1975
|
}
|
|
2135
1976
|
const renderer = await resolveArtifactRendererTarget(options.plugin);
|
|
2136
1977
|
if (renderer.noOp || !renderer.rendererDigest) {
|
|
2137
|
-
throw new Error('
|
|
1978
|
+
throw new Error('Native Skill render projection requires an artifact renderer.');
|
|
2138
1979
|
}
|
|
2139
1980
|
const config = await resolveArtifactRenderConfig({
|
|
2140
1981
|
sourceId: options.plugin.sourceId,
|
|
@@ -2142,12 +1983,15 @@ async function resolveCodexNativeRenderExpectedEvidence(options) {
|
|
|
2142
1983
|
logicalIdentity: options.plugin.catalogLogicalIdentity,
|
|
2143
1984
|
pluginName: options.plugin.manifest.name,
|
|
2144
1985
|
manifest: options.plugin.manifest,
|
|
1986
|
+
platform,
|
|
1987
|
+
referencePlugins: options.referencePlugins,
|
|
2145
1988
|
scope: 'user',
|
|
2146
1989
|
cwd: options.plugin.rootDir,
|
|
2147
1990
|
env: options.env,
|
|
2148
1991
|
});
|
|
2149
1992
|
if (config.issues.length > 0) {
|
|
2150
|
-
|
|
1993
|
+
// Validated installed bytes remain live while configuration needs repair.
|
|
1994
|
+
return { state: 'present', payloadDigest, receipt, sourceProjection: 'drifted' };
|
|
2151
1995
|
}
|
|
2152
1996
|
const projection = createCodexNativeRenderProjection({
|
|
2153
1997
|
logicalPluginId,
|
|
@@ -2160,9 +2004,9 @@ async function resolveCodexNativeRenderExpectedEvidence(options) {
|
|
|
2160
2004
|
configDigest: createArtifactConfigDigest({
|
|
2161
2005
|
artifact: {
|
|
2162
2006
|
id: target.id,
|
|
2163
|
-
platform
|
|
2164
|
-
target:
|
|
2165
|
-
refreshKeys:
|
|
2007
|
+
platform,
|
|
2008
|
+
target: `${platform}.skill`,
|
|
2009
|
+
refreshKeys: nativeSkillRefreshKeys(options.plugin, target),
|
|
2166
2010
|
},
|
|
2167
2011
|
renderConfig: config,
|
|
2168
2012
|
digestSalt: renderer.rendererDigest,
|
|
@@ -2200,14 +2044,15 @@ async function assertNoSensitiveValuesInCanonicalCodexNativePayload(options) {
|
|
|
2200
2044
|
if (!await codexPayloadPathSafe(payloadRoot, options.marketplaceRoot)) {
|
|
2201
2045
|
throw new Error('Codex native sensitive scan payload path is unsafe.');
|
|
2202
2046
|
}
|
|
2203
|
-
const receiptEvidence = await
|
|
2047
|
+
const receiptEvidence = await readNativeSkillRenderReceiptEvidence(payloadRoot, 'codex');
|
|
2204
2048
|
if (receiptEvidence.state === 'unsafe') {
|
|
2205
2049
|
throw new Error('codexNativeRenderReceiptInvalid: Codex native render receipt path is unsafe.');
|
|
2206
2050
|
}
|
|
2207
2051
|
let verifiedRenderReceipt;
|
|
2208
2052
|
if (receiptEvidence.state === 'present') {
|
|
2209
|
-
const expected = await
|
|
2053
|
+
const expected = await resolveNativeSkillRenderExpectedEvidence({
|
|
2210
2054
|
plugin: options.plugin,
|
|
2055
|
+
platform: 'codex',
|
|
2211
2056
|
marketplaceRoot: options.marketplaceRoot,
|
|
2212
2057
|
marketplaceName: options.marketplaceName,
|
|
2213
2058
|
env: options.env,
|
|
@@ -2216,7 +2061,7 @@ async function assertNoSensitiveValuesInCanonicalCodexNativePayload(options) {
|
|
|
2216
2061
|
verifiedRenderReceipt = expected.receipt;
|
|
2217
2062
|
}
|
|
2218
2063
|
}
|
|
2219
|
-
await
|
|
2064
|
+
await assertNoSensitiveValuesInNativeSkillPayload({
|
|
2220
2065
|
plugin: options.plugin,
|
|
2221
2066
|
payloadRoot,
|
|
2222
2067
|
allowedRoot: options.marketplaceRoot,
|
|
@@ -2394,8 +2239,9 @@ export async function inspectCodexSharedNativeLive(options) {
|
|
|
2394
2239
|
&& pluginList.observation.value === 'installed';
|
|
2395
2240
|
if (installed && dynamicProjectionExpected && options.nativeRenderPlugin) {
|
|
2396
2241
|
try {
|
|
2397
|
-
const expected = await
|
|
2242
|
+
const expected = await resolveNativeSkillRenderExpectedEvidence({
|
|
2398
2243
|
plugin: options.nativeRenderPlugin,
|
|
2244
|
+
platform: 'codex',
|
|
2399
2245
|
marketplaceRoot,
|
|
2400
2246
|
marketplaceName,
|
|
2401
2247
|
env: options.env,
|
|
@@ -2421,8 +2267,8 @@ export async function inspectCodexSharedNativeLive(options) {
|
|
|
2421
2267
|
}
|
|
2422
2268
|
else {
|
|
2423
2269
|
sourceProjectionIssue = {
|
|
2424
|
-
reason: error instanceof
|
|
2425
|
-
diagnostic: error instanceof
|
|
2270
|
+
reason: error instanceof NativeSkillProjectionUnsafeError ? 'foreign' : 'unreadable',
|
|
2271
|
+
diagnostic: error instanceof NativeSkillProjectionUnsafeError
|
|
2426
2272
|
? 'payloadPathUnsafe'
|
|
2427
2273
|
: 'projectionReceiptUnreadable',
|
|
2428
2274
|
};
|
|
@@ -2471,6 +2317,23 @@ async function ensureCodexActiveSkillsManifest(options) {
|
|
|
2471
2317
|
await fs.outputJson(manifestPath, updated, { spaces: 2 });
|
|
2472
2318
|
return options.hasRequiredSkills ? relativeSkillsRoot : null;
|
|
2473
2319
|
}
|
|
2320
|
+
async function ensureNativeActiveSkillsManifest(options) {
|
|
2321
|
+
if (options.platform === 'codex') {
|
|
2322
|
+
await ensureCodexActiveSkillsManifest(options);
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
const pluginRoot = path.join(options.marketplaceRoot, 'plugins', options.plugin.manifest.name);
|
|
2326
|
+
const manifestPath = path.join(pluginRoot, '.claude-plugin', 'plugin.json');
|
|
2327
|
+
const manifest = await fs.readJson(manifestPath);
|
|
2328
|
+
const updated = { ...manifest, name: options.plugin.manifest.name, version: options.plugin.manifest.version };
|
|
2329
|
+
if (options.hasRequiredSkills) {
|
|
2330
|
+
await fs.ensureDir(path.join(pluginRoot, ...options.relativeSkillsRoot.split('/')));
|
|
2331
|
+
updated.skills = `./${options.relativeSkillsRoot}`;
|
|
2332
|
+
}
|
|
2333
|
+
else
|
|
2334
|
+
delete updated.skills;
|
|
2335
|
+
await fs.outputJson(manifestPath, updated, { spaces: 2 });
|
|
2336
|
+
}
|
|
2474
2337
|
function createCodexMarketplaceComponent(options) {
|
|
2475
2338
|
const configPath = resolveCodexPaths(options.cwd, 'user', options.env).configTomlPath;
|
|
2476
2339
|
return {
|
|
@@ -2802,21 +2665,29 @@ function createClaudeMarketplaceComponent(options) {
|
|
|
2802
2665
|
},
|
|
2803
2666
|
};
|
|
2804
2667
|
}
|
|
2805
|
-
const
|
|
2806
|
-
function
|
|
2807
|
-
let
|
|
2668
|
+
const nativeSkillRenderPreparationCaches = new WeakMap();
|
|
2669
|
+
function nativeSkillRenderPreparationCache(context, platform) {
|
|
2670
|
+
let platforms = nativeSkillRenderPreparationCaches.get(context);
|
|
2671
|
+
if (!platforms) {
|
|
2672
|
+
platforms = new Map();
|
|
2673
|
+
nativeSkillRenderPreparationCaches.set(context, platforms);
|
|
2674
|
+
}
|
|
2675
|
+
let cache = platforms.get(platform);
|
|
2808
2676
|
if (!cache) {
|
|
2809
2677
|
cache = new WeakMap();
|
|
2810
|
-
|
|
2678
|
+
platforms.set(platform, cache);
|
|
2811
2679
|
}
|
|
2812
2680
|
return cache;
|
|
2813
2681
|
}
|
|
2682
|
+
function nativeSkillRenderTargets(plugin, platform) {
|
|
2683
|
+
return (plugin.manifest.artifacts?.targets ?? []).filter((target) => target.platform === platform && target.target === `${platform}.skill`);
|
|
2684
|
+
}
|
|
2814
2685
|
function pluginHasCodexNativeSkillSurface(plugin) {
|
|
2815
2686
|
return plugin.manifest.skills !== undefined
|
|
2816
2687
|
|| codexNativeRenderTargets(plugin).length > 0;
|
|
2817
2688
|
}
|
|
2818
|
-
async function resolveSensitiveUserConfigValues(plugin, env, referencePlugins) {
|
|
2819
|
-
const hasSensitiveFields = Object.values(plugin.manifest.config
|
|
2689
|
+
async function resolveSensitiveUserConfigValues(plugin, env, referencePlugins, platform = 'codex') {
|
|
2690
|
+
const hasSensitiveFields = Object.values(plugin.manifest.config ? compilePluginConfigDefinition(plugin.manifest.config, platform).fields : {}).some((field) => field.sensitive === true);
|
|
2820
2691
|
if (!hasSensitiveFields)
|
|
2821
2692
|
return [];
|
|
2822
2693
|
const config = await resolveArtifactRenderConfig({
|
|
@@ -2824,20 +2695,22 @@ async function resolveSensitiveUserConfigValues(plugin, env, referencePlugins) {
|
|
|
2824
2695
|
sourceIdentity: plugin.sourceIdentity,
|
|
2825
2696
|
pluginName: plugin.manifest.name,
|
|
2826
2697
|
manifest: plugin.manifest,
|
|
2698
|
+
platform,
|
|
2827
2699
|
referencePlugins,
|
|
2828
2700
|
scope: 'user',
|
|
2829
2701
|
cwd: plugin.rootDir,
|
|
2830
2702
|
env,
|
|
2831
2703
|
});
|
|
2832
|
-
return collectSensitivePluginConfigValues(plugin.manifest, config.values);
|
|
2704
|
+
return collectSensitivePluginConfigValues(plugin.manifest, config.values, platform);
|
|
2833
2705
|
}
|
|
2834
|
-
async function
|
|
2706
|
+
async function assertNoSensitiveValuesInNativeSkillPayload(options) {
|
|
2835
2707
|
if (options.sensitiveValues.length === 0)
|
|
2836
2708
|
return;
|
|
2709
|
+
const platform = options.platform ?? 'codex';
|
|
2837
2710
|
if (!await codexPayloadPathSafe(options.payloadRoot, options.allowedRoot)) {
|
|
2838
2711
|
throw new Error('Codex native sensitive scan payload path is unsafe.');
|
|
2839
2712
|
}
|
|
2840
|
-
const codexManifestPath = path.join(options.payloadRoot,
|
|
2713
|
+
const codexManifestPath = path.join(options.payloadRoot, `.${platform}-plugin`, 'plugin.json');
|
|
2841
2714
|
const codexManifestStats = await lstatCodexResidueIfPresent(codexManifestPath);
|
|
2842
2715
|
if (!codexManifestStats?.isFile()) {
|
|
2843
2716
|
throw new Error('Codex native sensitive scan manifest is missing or unsafe.');
|
|
@@ -2853,7 +2726,7 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2853
2726
|
if (typeof rawSkillsRoot !== 'string' || rawSkillsRoot.trim() === '') {
|
|
2854
2727
|
throw new Error('Codex native sensitive scan Skills root is invalid.');
|
|
2855
2728
|
}
|
|
2856
|
-
const { root: skillsRoot } = await
|
|
2729
|
+
const { root: skillsRoot } = await resolveNativeSkillsRoot(options.payloadRoot, rawSkillsRoot, platform);
|
|
2857
2730
|
const skillsRootStats = await lstatCodexResidueIfPresent(skillsRoot);
|
|
2858
2731
|
if (!skillsRootStats?.isDirectory()) {
|
|
2859
2732
|
throw new Error('Codex native sensitive scan Skills root is missing or unsafe.');
|
|
@@ -2868,7 +2741,7 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2868
2741
|
if (!skillFileStats.isFile()) {
|
|
2869
2742
|
throw new Error('Codex native sensitive scan Skill entry is unsafe.');
|
|
2870
2743
|
}
|
|
2871
|
-
const tree = await readDynamicSkillTree(skillRoot,
|
|
2744
|
+
const tree = await readDynamicSkillTree(skillRoot, `${platform}.skill`);
|
|
2872
2745
|
if (!tree)
|
|
2873
2746
|
continue;
|
|
2874
2747
|
const leakedPath = findSensitiveTokenPath(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), options.sensitiveValues);
|
|
@@ -2878,7 +2751,7 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2878
2751
|
}
|
|
2879
2752
|
}
|
|
2880
2753
|
}
|
|
2881
|
-
const receiptPath = path.join(options.payloadRoot,
|
|
2754
|
+
const receiptPath = path.join(options.payloadRoot, nativeSkillRenderReceiptPath(platform));
|
|
2882
2755
|
const receiptStats = await lstatCodexResidueIfPresent(receiptPath);
|
|
2883
2756
|
if (receiptStats) {
|
|
2884
2757
|
if (!receiptStats.isFile()) {
|
|
@@ -2887,7 +2760,7 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2887
2760
|
const receiptContent = await fs.readFile(receiptPath);
|
|
2888
2761
|
let actualReceipt;
|
|
2889
2762
|
try {
|
|
2890
|
-
actualReceipt =
|
|
2763
|
+
actualReceipt = parseNativeSkillRenderReceipt(platform, receiptContent.toString('utf8'));
|
|
2891
2764
|
}
|
|
2892
2765
|
catch {
|
|
2893
2766
|
actualReceipt = undefined;
|
|
@@ -2895,7 +2768,7 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2895
2768
|
const verified = options.verifiedRenderReceipt
|
|
2896
2769
|
&& JSON.stringify(actualReceipt) === JSON.stringify(options.verifiedRenderReceipt);
|
|
2897
2770
|
if (!verified) {
|
|
2898
|
-
const receiptLeak = findSensitiveTokenPath({ [
|
|
2771
|
+
const receiptLeak = findSensitiveTokenPath({ [nativeSkillRenderReceiptPath(platform)]: receiptContent }, options.sensitiveValues);
|
|
2899
2772
|
if (receiptLeak) {
|
|
2900
2773
|
throw new Error(`codexNativeRenderSensitiveValue: Codex native render receipt exposes sensitive config in ` +
|
|
2901
2774
|
`"${receiptLeak}".`);
|
|
@@ -2903,47 +2776,41 @@ async function assertNoSensitiveValuesInCodexNativePayload(options) {
|
|
|
2903
2776
|
}
|
|
2904
2777
|
}
|
|
2905
2778
|
}
|
|
2906
|
-
async function
|
|
2779
|
+
async function prepareNativeSkillRender(options) {
|
|
2907
2780
|
const requested = options.requestedArtifactIds
|
|
2908
2781
|
? new Set(options.requestedArtifactIds)
|
|
2909
2782
|
: undefined;
|
|
2910
|
-
const targets =
|
|
2783
|
+
const targets = nativeSkillRenderTargets(options.plugin, options.platform)
|
|
2911
2784
|
.filter((target) => !requested || requested.has(target.id));
|
|
2912
2785
|
if (targets.length === 0)
|
|
2913
2786
|
return null;
|
|
2914
2787
|
let commandCandidates = [...(options.commandCandidates ?? [])];
|
|
2915
2788
|
if (!options.commandCandidates) {
|
|
2916
2789
|
for (const declaration of options.plugin.manifest.managedCommands?.packages ?? []) {
|
|
2917
|
-
if (declaration.scope !== 'user' || !declaration.platforms.includes(
|
|
2790
|
+
if (declaration.scope !== 'user' || !declaration.platforms.includes(options.platform))
|
|
2918
2791
|
continue;
|
|
2919
2792
|
const prepared = await prepareManagedCommandPackage({ ...options, packageKey: declaration.key, scope: 'user', cwd: options.plugin.rootDir });
|
|
2920
2793
|
commandCandidates.push({ producer: prepared.producer, sets: prepared.sets });
|
|
2921
2794
|
await prepared.cleanup();
|
|
2922
2795
|
}
|
|
2923
2796
|
}
|
|
2924
|
-
const
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
group.push(target);
|
|
2930
|
-
byScope.set(requestScope, group);
|
|
2931
|
-
}
|
|
2932
|
-
const skillsRelativeRoot = await resolveCodexSkillsRelativeRoot(options.plugin);
|
|
2933
|
-
const nativeReceiptPath = `${'../'.repeat(skillsRelativeRoot.split('/').length + 1)}${CODEX_NATIVE_RENDER_RECEIPT_PATH}`;
|
|
2797
|
+
const skillsRelativeRoot = options.platform === 'codex'
|
|
2798
|
+
? await resolveCodexSkillsRelativeRoot(options.plugin)
|
|
2799
|
+
: `claude/${(options.plugin.manifest.skills ?? './skills').replace(/^\.\//u, '')}`;
|
|
2800
|
+
const receiptPath = nativeSkillRenderReceiptPath(options.platform);
|
|
2801
|
+
const nativeReceiptPath = `${'../'.repeat(skillsRelativeRoot.split('/').length + 1)}${receiptPath}`;
|
|
2934
2802
|
const renderedArtifacts = [];
|
|
2935
2803
|
const receiptTargets = [];
|
|
2936
2804
|
const presentSkillKeys = [];
|
|
2937
2805
|
let rendererDigest;
|
|
2938
|
-
|
|
2939
|
-
const
|
|
2940
|
-
|
|
2941
|
-
continue;
|
|
2806
|
+
{
|
|
2807
|
+
const scope = 'user';
|
|
2808
|
+
const group = targets;
|
|
2942
2809
|
const rendered = await runArtifactRenderer({
|
|
2943
2810
|
referencePlugins: options.referencePlugins,
|
|
2944
2811
|
event: 'install',
|
|
2945
2812
|
plugin: options.plugin,
|
|
2946
|
-
platform:
|
|
2813
|
+
platform: options.platform,
|
|
2947
2814
|
scope,
|
|
2948
2815
|
configScope: 'user',
|
|
2949
2816
|
cwd: options.plugin.rootDir,
|
|
@@ -2953,13 +2820,15 @@ async function prepareCodexNativeRender(options) {
|
|
|
2953
2820
|
const producer = target.producer;
|
|
2954
2821
|
return producer.kind === 'artifact' && group.some((skill) => skill.id === producer.artifactId);
|
|
2955
2822
|
}).map((target) => target.id)],
|
|
2823
|
+
preparedResults: options.preparedResults,
|
|
2956
2824
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
2825
|
+
signal: options.signal,
|
|
2957
2826
|
});
|
|
2958
2827
|
rendererDigest = rendered.target.rendererDigest;
|
|
2959
2828
|
const validated = validateArtifactPlan({
|
|
2960
2829
|
manifest: options.plugin.manifest,
|
|
2961
2830
|
plan: rendered.plan,
|
|
2962
|
-
platform:
|
|
2831
|
+
platform: options.platform,
|
|
2963
2832
|
scope,
|
|
2964
2833
|
requestedArtifactIds: rendered.context.requestedArtifactIds,
|
|
2965
2834
|
renderConfig: rendered.context.config,
|
|
@@ -2969,11 +2838,12 @@ async function prepareCodexNativeRender(options) {
|
|
|
2969
2838
|
for (const artifact of validated.artifacts) {
|
|
2970
2839
|
if (artifact.target === 'aw.command-set')
|
|
2971
2840
|
continue;
|
|
2972
|
-
if (artifact.target !== 'codex.skill')
|
|
2841
|
+
if ((artifact.target !== 'codex.skill' && artifact.target !== 'claude.skill')
|
|
2842
|
+
|| artifact.target !== `${options.platform}.skill`) {
|
|
2973
2843
|
throw new Error(`Codex native renderer returned non-Skill artifact "${artifact.id}".`);
|
|
2974
2844
|
}
|
|
2975
2845
|
const sourceDirs = rendered.context.artifactSources.find((entry) => entry.id === artifact.id && entry.target === artifact.target)?.sourceDirs ?? [];
|
|
2976
|
-
const tree = await
|
|
2846
|
+
const tree = await createDynamicSkillExpectedTree({
|
|
2977
2847
|
artifact,
|
|
2978
2848
|
sourceDirs,
|
|
2979
2849
|
requireReadme: true,
|
|
@@ -2981,10 +2851,10 @@ async function prepareCodexNativeRender(options) {
|
|
|
2981
2851
|
sourceRequirementsReceiptPolicy: 'allow',
|
|
2982
2852
|
});
|
|
2983
2853
|
await injectInstalledRuntimeConfig(tree, rendered.runtimeConfigSnapshots[artifact.id], { nativeReceiptPath });
|
|
2984
|
-
const candidate = await prepareSkillCommandCandidate({ plugin: options.plugin, producer: { kind: 'artifact', artifactId: artifact.id }, platform:
|
|
2854
|
+
const candidate = await prepareSkillCommandCandidate({ plugin: options.plugin, producer: { kind: 'artifact', artifactId: artifact.id }, platform: options.platform, scope: 'user', cwd: options.plugin.rootDir, tree, artifacts: validated.artifacts });
|
|
2985
2855
|
if (candidate)
|
|
2986
2856
|
commandCandidates.push(candidate);
|
|
2987
|
-
assertNoSensitiveConfigInFiles(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), collectSensitivePluginConfigValues(options.plugin.manifest, rendered.context.config.values), 'artifactRendererSensitiveConfigExposed: Final dynamic Skill contains sensitive config.');
|
|
2857
|
+
assertNoSensitiveConfigInFiles(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), collectSensitivePluginConfigValues(options.plugin.manifest, rendered.context.config.values, options.platform), 'artifactRendererSensitiveConfigExposed: Final dynamic Skill contains sensitive config.');
|
|
2988
2858
|
const skillKey = artifact.skillKey;
|
|
2989
2859
|
renderedArtifacts.push({
|
|
2990
2860
|
artifact,
|
|
@@ -2996,8 +2866,12 @@ async function prepareCodexNativeRender(options) {
|
|
|
2996
2866
|
receiptTargets.push({
|
|
2997
2867
|
id: artifact.id,
|
|
2998
2868
|
skillKey,
|
|
2999
|
-
configDigest:
|
|
3000
|
-
|
|
2869
|
+
configDigest: createArtifactConfigDigest({
|
|
2870
|
+
artifact: { ...artifact, refreshKeys: nativeSkillRefreshKeys(options.plugin, artifact) },
|
|
2871
|
+
renderConfig: rendered.context.config,
|
|
2872
|
+
digestSalt: rendered.target.rendererDigest,
|
|
2873
|
+
}),
|
|
2874
|
+
artifactDigest: nativeSkillContentDigest(options.platform, tree),
|
|
3001
2875
|
});
|
|
3002
2876
|
}
|
|
3003
2877
|
}
|
|
@@ -3007,14 +2881,14 @@ async function prepareCodexNativeRender(options) {
|
|
|
3007
2881
|
if (options.prepareCommandReferences)
|
|
3008
2882
|
commandCandidates = await options.prepareCommandReferences(renderedArtifacts.map((entry) => entry.tree), commandCandidates);
|
|
3009
2883
|
else {
|
|
3010
|
-
const staticSkills = await prepareStaticNativeSkillActions({ plugin: options.plugin, platform:
|
|
2884
|
+
const staticSkills = await prepareStaticNativeSkillActions({ plugin: options.plugin, platform: options.platform, scope: 'user', cwd: options.plugin.rootDir, env: options.env, artifacts: [], commandCandidates, signal: options.signal, scriptTimeoutMs: options.scriptTimeoutMs });
|
|
3011
2885
|
commandCandidates.push(...staticSkills.candidates);
|
|
3012
2886
|
}
|
|
3013
|
-
const commandResolver = await createManagedCommandReferenceResolver({ plugin: options.plugin, platform:
|
|
2887
|
+
const commandResolver = await createManagedCommandReferenceResolver({ plugin: options.plugin, platform: options.platform, scope: 'user', cwd: options.plugin.rootDir, env: options.env, candidates: commandCandidates });
|
|
3014
2888
|
for (const rendered of renderedArtifacts) {
|
|
3015
2889
|
resolveSkillManagedCommandReferences(rendered.tree, commandResolver);
|
|
3016
2890
|
const receiptTarget = receiptTargets.find((target) => target.id === rendered.artifact.id);
|
|
3017
|
-
receiptTarget.artifactDigest =
|
|
2891
|
+
receiptTarget.artifactDigest = nativeSkillContentDigest(options.platform, rendered.tree);
|
|
3018
2892
|
}
|
|
3019
2893
|
const logicalPluginId = options.plugin.pluginId
|
|
3020
2894
|
?? (options.plugin.sourceId ? `${options.plugin.sourceId}/${options.plugin.manifest.name}` : undefined);
|
|
@@ -3029,6 +2903,7 @@ async function prepareCodexNativeRender(options) {
|
|
|
3029
2903
|
targets: receiptTargets,
|
|
3030
2904
|
});
|
|
3031
2905
|
return {
|
|
2906
|
+
platform: options.platform,
|
|
3032
2907
|
commandCandidates,
|
|
3033
2908
|
logicalPluginId,
|
|
3034
2909
|
sourceIdentity: options.plugin.sourceIdentity,
|
|
@@ -3041,14 +2916,17 @@ async function prepareCodexNativeRender(options) {
|
|
|
3041
2916
|
targetSkillKeys: targets.map((target) => target.skillKey).sort(),
|
|
3042
2917
|
};
|
|
3043
2918
|
}
|
|
3044
|
-
function
|
|
3045
|
-
const cache =
|
|
2919
|
+
function prepareNativeSkillRenderCached(options) {
|
|
2920
|
+
const cache = nativeSkillRenderPreparationCache(options.context, options.platform);
|
|
3046
2921
|
let preparation = cache.get(options.plugin);
|
|
3047
2922
|
if (!preparation) {
|
|
3048
|
-
preparation =
|
|
2923
|
+
preparation = prepareNativeSkillRender({
|
|
2924
|
+
preparedResults: artifactRenderResults(options.context),
|
|
3049
2925
|
referencePlugins: options.context.referencePlugins,
|
|
3050
2926
|
plugin: options.plugin,
|
|
2927
|
+
platform: options.platform,
|
|
3051
2928
|
env: options.context.env,
|
|
2929
|
+
signal: options.context.signal,
|
|
3052
2930
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
3053
2931
|
commandCandidates: options.context.managedCommandCandidates?.get(pluginActionId(options.plugin)),
|
|
3054
2932
|
});
|
|
@@ -3056,16 +2934,16 @@ function prepareCodexNativeRenderCached(options) {
|
|
|
3056
2934
|
}
|
|
3057
2935
|
return preparation;
|
|
3058
2936
|
}
|
|
3059
|
-
async function
|
|
3060
|
-
if (
|
|
2937
|
+
async function requirePreparedNativeSkillRender(options) {
|
|
2938
|
+
if (nativeSkillRenderTargets(options.plugin, options.platform).length === 0)
|
|
3061
2939
|
return null;
|
|
3062
|
-
const preparation =
|
|
2940
|
+
const preparation = nativeSkillRenderPreparationCache(options.context, options.platform).get(options.plugin);
|
|
3063
2941
|
if (!preparation) {
|
|
3064
2942
|
throw new Error('codexNativeRenderPreflightMissing: Codex native renderer was not prepared.');
|
|
3065
2943
|
}
|
|
3066
2944
|
return preparation;
|
|
3067
2945
|
}
|
|
3068
|
-
async function
|
|
2946
|
+
async function materializeNativeSkillRender(options) {
|
|
3069
2947
|
const skillsRoot = path.join(options.stagingRoot, 'plugins', options.plugin.manifest.name, ...options.prepared.skillsRelativeRoot.split('/'));
|
|
3070
2948
|
for (const { artifact, skillKey, tree } of options.prepared.renderedArtifacts) {
|
|
3071
2949
|
const skillRoot = path.join(skillsRoot, skillKey);
|
|
@@ -3076,14 +2954,17 @@ async function materializeCodexNativeRender(options) {
|
|
|
3076
2954
|
await fs.remove(skillRoot);
|
|
3077
2955
|
}
|
|
3078
2956
|
}
|
|
3079
|
-
|
|
2957
|
+
const platform = options.prepared.platform;
|
|
2958
|
+
await ensureNativeActiveSkillsManifest({
|
|
3080
2959
|
plugin: options.plugin,
|
|
2960
|
+
platform,
|
|
3081
2961
|
marketplaceRoot: options.stagingRoot,
|
|
3082
2962
|
hasRequiredSkills: options.hasStaticSkills || options.prepared.presentSkillKeys.length > 0,
|
|
2963
|
+
relativeSkillsRoot: options.prepared.skillsRelativeRoot,
|
|
3083
2964
|
});
|
|
3084
2965
|
const pluginRoot = path.join(options.stagingRoot, 'plugins', options.plugin.manifest.name);
|
|
3085
2966
|
const payloadDigest = await calculateCodexNativeRenderPayloadDigest(pluginRoot);
|
|
3086
|
-
const receipt = createCodexNativeRenderReceipt({
|
|
2967
|
+
const receipt = (platform === 'codex' ? createCodexNativeRenderReceipt : createClaudeNativeRenderReceipt)({
|
|
3087
2968
|
logicalPluginId: options.prepared.logicalPluginId,
|
|
3088
2969
|
sourceIdentity: options.prepared.sourceIdentity,
|
|
3089
2970
|
pluginVersion: options.plugin.manifest.version,
|
|
@@ -3091,7 +2972,7 @@ async function materializeCodexNativeRender(options) {
|
|
|
3091
2972
|
targets: options.prepared.receiptTargets,
|
|
3092
2973
|
payloadDigest,
|
|
3093
2974
|
});
|
|
3094
|
-
await fs.outputFile(path.join(pluginRoot,
|
|
2975
|
+
await fs.outputFile(path.join(pluginRoot, nativeSkillRenderReceiptPath(platform)), serializeNativeSkillRenderReceipt(receipt), 'utf8');
|
|
3095
2976
|
return {
|
|
3096
2977
|
payloadDigest,
|
|
3097
2978
|
projection: options.prepared.projection,
|
|
@@ -3113,13 +2994,12 @@ export async function materializeReviewNativeSkills(options) {
|
|
|
3113
2994
|
await fs.ensureDir(skillsRoot);
|
|
3114
2995
|
let commandCandidates = [];
|
|
3115
2996
|
const staticTrees = [];
|
|
3116
|
-
const directTrees = [];
|
|
3117
2997
|
const declarations = options.plugin.manifest.artifacts?.targets ?? [];
|
|
3118
2998
|
const dynamicSelections = options.skills.filter((skill) => skill.targetId !== null);
|
|
3119
2999
|
const selectedDeclarations = dynamicSelections.map((selection) => {
|
|
3120
3000
|
const matches = declarations.filter((target) => target.id === selection.targetId
|
|
3121
3001
|
&& target.platform === options.platform
|
|
3122
|
-
&& target.scopes.includes(
|
|
3002
|
+
&& target.scopes.includes('user')
|
|
3123
3003
|
&& target.skillKey === selection.skill
|
|
3124
3004
|
&& target.target === `${options.platform}.skill`);
|
|
3125
3005
|
if (matches.length !== 1) {
|
|
@@ -3145,84 +3025,14 @@ export async function materializeReviewNativeSkills(options) {
|
|
|
3145
3025
|
requirementsReceiptPolicy: 'allow',
|
|
3146
3026
|
}));
|
|
3147
3027
|
}
|
|
3148
|
-
const directTargetIds = requiredDeclarations
|
|
3149
|
-
.filter((target) => target.delivery?.mode !== 'codex-native')
|
|
3150
|
-
.map((target) => target.id);
|
|
3151
|
-
if (directTargetIds.length > 0) {
|
|
3152
|
-
const dynamic = await resolveDynamicArtifacts({
|
|
3153
|
-
referencePlugins: options.plugins,
|
|
3154
|
-
plugin: options.plugin,
|
|
3155
|
-
platform: options.platform,
|
|
3156
|
-
scope: options.scope,
|
|
3157
|
-
cwd: options.cwd,
|
|
3158
|
-
env: options.env,
|
|
3159
|
-
event: 'install',
|
|
3160
|
-
previousArtifacts: [],
|
|
3161
|
-
requestedArtifactIds: [
|
|
3162
|
-
...directTargetIds,
|
|
3163
|
-
...getManagedCommandArtifactTargets(options.plugin.manifest)
|
|
3164
|
-
.filter((target) => target.producer.kind === 'artifact'
|
|
3165
|
-
&& directTargetIds.includes(target.producer.artifactId))
|
|
3166
|
-
.map((target) => target.id),
|
|
3167
|
-
],
|
|
3168
|
-
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
3169
|
-
});
|
|
3170
|
-
for (const artifact of dynamic.artifacts) {
|
|
3171
|
-
if (artifact.target === 'aw.command-set')
|
|
3172
|
-
continue;
|
|
3173
|
-
if (artifact.state !== 'present') {
|
|
3174
|
-
throw new Error(`Selected Skill target "${artifact.id}" did not produce a present Skill.`);
|
|
3175
|
-
}
|
|
3176
|
-
if (artifact.target !== `${options.platform}.skill`) {
|
|
3177
|
-
throw new Error(`Selected target "${artifact.id}" did not produce a ${options.platform} Skill.`);
|
|
3178
|
-
}
|
|
3179
|
-
let tree;
|
|
3180
|
-
if (artifact.target === 'codex.skill') {
|
|
3181
|
-
tree = await createCodexSkillExpectedTree({
|
|
3182
|
-
artifact,
|
|
3183
|
-
sourceDirs: dynamic.sourceDirs(artifact),
|
|
3184
|
-
requireReadme: true,
|
|
3185
|
-
requirementsReceipt: requirementsReceipt(options.plugin),
|
|
3186
|
-
sourceRequirementsReceiptPolicy: 'allow',
|
|
3187
|
-
});
|
|
3188
|
-
}
|
|
3189
|
-
else if (artifact.target === 'claude.skill') {
|
|
3190
|
-
tree = await createDynamicSkillExpectedTree({
|
|
3191
|
-
artifact,
|
|
3192
|
-
sourceDirs: dynamic.sourceDirs(artifact),
|
|
3193
|
-
requireReadme: true,
|
|
3194
|
-
requirementsReceipt: requirementsReceipt(options.plugin),
|
|
3195
|
-
sourceRequirementsReceiptPolicy: 'allow',
|
|
3196
|
-
});
|
|
3197
|
-
}
|
|
3198
|
-
else {
|
|
3199
|
-
throw new Error(`Selected target "${artifact.id}" is not a Skill.`);
|
|
3200
|
-
}
|
|
3201
|
-
await injectInstalledRuntimeConfig(tree, dynamic.runtimeConfigSnapshots?.[artifact.id]);
|
|
3202
|
-
assertNoSensitiveConfigInFiles(withoutVerifiedRequirementsReceipt(options.plugin, tree.files), dynamic.sensitiveValues, 'artifactRendererSensitiveConfigExposed: Final dynamic Skill contains sensitive config.');
|
|
3203
|
-
const candidate = await prepareSkillCommandCandidate({
|
|
3204
|
-
...options, producer: { kind: 'artifact', artifactId: artifact.id },
|
|
3205
|
-
tree, artifacts: dynamic.artifacts,
|
|
3206
|
-
});
|
|
3207
|
-
if (candidate)
|
|
3208
|
-
commandCandidates.push(candidate);
|
|
3209
|
-
directTrees.push(tree);
|
|
3210
|
-
}
|
|
3211
|
-
}
|
|
3212
3028
|
const prepareReferences = async (trees, scope, copy, candidates = commandCandidates) => prepareIsolatedSkillCommandReferences({
|
|
3213
3029
|
...options, scope, candidates,
|
|
3214
3030
|
trees: copy ? trees.map((tree) => ({ ...tree, files: { ...tree.files } })) : trees,
|
|
3215
3031
|
});
|
|
3216
3032
|
const staticScope = 'user';
|
|
3217
3033
|
commandCandidates = await prepareReferences(staticTrees, staticScope, true);
|
|
3218
|
-
|
|
3219
|
-
const nativeTargetIds = requiredDeclarations
|
|
3220
|
-
.filter((target) => target.delivery?.mode === 'codex-native')
|
|
3221
|
-
.map((target) => target.id);
|
|
3034
|
+
const nativeTargetIds = requiredDeclarations.map((target) => target.id);
|
|
3222
3035
|
if (nativeTargetIds.length > 0) {
|
|
3223
|
-
if (options.platform !== 'codex') {
|
|
3224
|
-
throw new Error('Codex native Skill targets are only valid for the Codex platform.');
|
|
3225
|
-
}
|
|
3226
3036
|
const marketplaceRoot = path.join(options.outputRoot, '.native-marketplace');
|
|
3227
3037
|
const payloadRoot = path.join(marketplaceRoot, 'plugins', options.plugin.manifest.name);
|
|
3228
3038
|
await fs.copy(options.plugin.rootDir, payloadRoot, {
|
|
@@ -3230,9 +3040,10 @@ export async function materializeReviewNativeSkills(options) {
|
|
|
3230
3040
|
errorOnExist: true,
|
|
3231
3041
|
dereference: false,
|
|
3232
3042
|
});
|
|
3233
|
-
const prepared = await
|
|
3043
|
+
const prepared = await prepareNativeSkillRender({
|
|
3234
3044
|
referencePlugins: options.plugins,
|
|
3235
3045
|
plugin: options.plugin,
|
|
3046
|
+
platform: options.platform,
|
|
3236
3047
|
env: options.env,
|
|
3237
3048
|
requestedArtifactIds: nativeTargetIds,
|
|
3238
3049
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
@@ -3243,38 +3054,38 @@ export async function materializeReviewNativeSkills(options) {
|
|
|
3243
3054
|
throw new Error('Selected Codex native Skill targets did not produce a projection.');
|
|
3244
3055
|
}
|
|
3245
3056
|
commandCandidates = prepared.commandCandidates;
|
|
3246
|
-
const staged = await
|
|
3057
|
+
const staged = await materializeNativeSkillRender({
|
|
3247
3058
|
plugin: options.plugin,
|
|
3248
3059
|
stagingRoot: marketplaceRoot,
|
|
3249
3060
|
prepared,
|
|
3250
3061
|
hasStaticSkills: options.plugin.manifest.skills !== undefined,
|
|
3251
3062
|
});
|
|
3252
|
-
await
|
|
3063
|
+
await assertNoSensitiveValuesInNativeSkillPayload({
|
|
3253
3064
|
plugin: options.plugin,
|
|
3254
3065
|
payloadRoot,
|
|
3255
3066
|
allowedRoot: marketplaceRoot,
|
|
3256
|
-
|
|
3067
|
+
platform: options.platform,
|
|
3068
|
+
sensitiveValues: await resolveSensitiveUserConfigValues(options.plugin, options.env, options.plugins, options.platform),
|
|
3257
3069
|
verifiedRenderReceipt: staged.receipt,
|
|
3258
3070
|
});
|
|
3259
3071
|
const presentSkillKeys = new Set(staged.presentSkillKeys);
|
|
3260
3072
|
if (options.allowDisabledNativeSkills) {
|
|
3261
|
-
for (const target of requiredDeclarations.filter((entry) =>
|
|
3073
|
+
for (const target of requiredDeclarations.filter((entry) => !presentSkillKeys.has(entry.skillKey))) {
|
|
3262
3074
|
disabledNativeSkillNames.add(target.skillKey);
|
|
3263
3075
|
}
|
|
3264
3076
|
}
|
|
3265
|
-
for (const target of requiredDeclarations.filter((entry) =>
|
|
3077
|
+
for (const target of requiredDeclarations.filter((entry) => presentSkillKeys.has(entry.skillKey))) {
|
|
3266
3078
|
const sourceRoot = path.join(payloadRoot, ...prepared.skillsRelativeRoot.split('/'), target.skillKey);
|
|
3267
3079
|
await fs.copy(sourceRoot, path.join(skillsRoot, target.skillKey), {
|
|
3268
3080
|
overwrite: false,
|
|
3269
3081
|
errorOnExist: true,
|
|
3270
3082
|
dereference: false,
|
|
3271
3083
|
});
|
|
3272
|
-
await carryRuntimeConfigNativeReceipt(path.join(skillsRoot, target.skillKey), Buffer.from(
|
|
3084
|
+
await carryRuntimeConfigNativeReceipt(path.join(skillsRoot, target.skillKey), Buffer.from(serializeNativeSkillRenderReceipt(staged.receipt)));
|
|
3273
3085
|
}
|
|
3274
3086
|
await fs.remove(marketplaceRoot);
|
|
3275
3087
|
}
|
|
3276
3088
|
commandCandidates = await prepareReferences(staticTrees, staticScope, false);
|
|
3277
|
-
commandCandidates = await prepareReferences(directTrees, options.scope, false);
|
|
3278
3089
|
for (const tree of staticTrees) {
|
|
3279
3090
|
for (const [relativePath, content] of Object.entries(tree.files)) {
|
|
3280
3091
|
if (relativePath.endsWith('.md')) {
|
|
@@ -3282,9 +3093,6 @@ export async function materializeReviewNativeSkills(options) {
|
|
|
3282
3093
|
}
|
|
3283
3094
|
}
|
|
3284
3095
|
}
|
|
3285
|
-
for (const tree of directTrees) {
|
|
3286
|
-
await writeDynamicSkillTree(path.join(skillsRoot, tree.skillKey), tree);
|
|
3287
|
-
}
|
|
3288
3096
|
const skills = [];
|
|
3289
3097
|
for (const skill of selectedNames.sort((left, right) => left.localeCompare(right))) {
|
|
3290
3098
|
const skillRoot = path.join(skillsRoot, skill);
|
|
@@ -3554,6 +3362,71 @@ async function applyPlannedOperationAction(action) {
|
|
|
3554
3362
|
}
|
|
3555
3363
|
function createNativeDriver(options) {
|
|
3556
3364
|
const runner = options.context.nativeCliRunner;
|
|
3365
|
+
const nativeBindingRecoveryEvidence = new WeakMap();
|
|
3366
|
+
const captureNativeBindingRecoveryEvidence = async (target, producers) => {
|
|
3367
|
+
const captured = nativeBindingRecoveryEvidence.get(target);
|
|
3368
|
+
if (captured)
|
|
3369
|
+
return captured;
|
|
3370
|
+
const evidence = [];
|
|
3371
|
+
const finish = () => {
|
|
3372
|
+
nativeBindingRecoveryEvidence.set(target, evidence);
|
|
3373
|
+
return evidence;
|
|
3374
|
+
};
|
|
3375
|
+
const nativeProducers = producers.filter(({ producer }) => producer.sourceId === target.identity.sourceId
|
|
3376
|
+
&& producer.sourceIdentity === target.identity.sourceIdentity
|
|
3377
|
+
&& producer.pluginName === target.identity.pluginName
|
|
3378
|
+
&& producer.platform === target.identity.platform
|
|
3379
|
+
&& producer.scope === 'user' && producer.projectRoot === null
|
|
3380
|
+
&& producer.kind !== 'package');
|
|
3381
|
+
if (nativeProducers.length === 0)
|
|
3382
|
+
return finish();
|
|
3383
|
+
const marketplaceRoot = target.identity.marketplaceRoot ?? resolveAwHome(options.context.env);
|
|
3384
|
+
const marketplaceName = target.identity.marketplaceName ?? MARKETPLACE_NAME;
|
|
3385
|
+
const marketplace = await readStrictNamespacedMarketplaceRoot({
|
|
3386
|
+
rootDir: marketplaceRoot, sourceId: target.identity.sourceId,
|
|
3387
|
+
sourceIdentity: target.identity.sourceIdentity, marketplaceName,
|
|
3388
|
+
});
|
|
3389
|
+
if (!marketplace)
|
|
3390
|
+
return finish();
|
|
3391
|
+
const pluginRoot = await assertSafeNamespacedMarketplacePluginRoot(marketplaceRoot, target.identity.pluginName);
|
|
3392
|
+
const manifest = await readNativeSkillProjectionManifest(path.join(pluginRoot, `.${target.identity.platform}-plugin`, 'plugin.json'));
|
|
3393
|
+
if (manifest.state === 'unsafe' || manifest.state === 'unreadable') {
|
|
3394
|
+
throw new Error('commandOwnerMismatch: the previous Native platform manifest cannot authorize binding recovery.');
|
|
3395
|
+
}
|
|
3396
|
+
if (manifest.state !== 'present')
|
|
3397
|
+
return finish();
|
|
3398
|
+
if (manifest.value.name !== target.identity.pluginName) {
|
|
3399
|
+
throw new Error('commandOwnerMismatch: the previous Native platform belongs to another plugin.');
|
|
3400
|
+
}
|
|
3401
|
+
if (typeof manifest.value.skills !== 'string')
|
|
3402
|
+
return finish();
|
|
3403
|
+
const { root: skillsRoot } = await resolveNativeSkillsRoot(pluginRoot, manifest.value.skills, target.identity.platform);
|
|
3404
|
+
const dynamic = nativeProducers.some(({ producer }) => producer.kind === 'artifact')
|
|
3405
|
+
? await resolveNativeSkillRenderExpectedEvidence({
|
|
3406
|
+
plugin: target.plugin, platform: target.identity.platform,
|
|
3407
|
+
referencePlugins: options.context.referencePlugins,
|
|
3408
|
+
marketplaceRoot, marketplaceName, env: options.context.env,
|
|
3409
|
+
})
|
|
3410
|
+
: undefined;
|
|
3411
|
+
if (dynamic?.state === 'issue' && dynamic.reason !== 'damaged') {
|
|
3412
|
+
throw new Error(`commandOwnerMismatch: previous Native evidence is ${dynamic.reason}: ${dynamic.diagnostic}.`);
|
|
3413
|
+
}
|
|
3414
|
+
for (const { producer } of nativeProducers) {
|
|
3415
|
+
const skillKey = producer.kind === 'static-skill' ? producer.key
|
|
3416
|
+
: dynamic?.state === 'present'
|
|
3417
|
+
? dynamic.receipt.targets.find((entry) => entry.id === producer.key)?.skillKey
|
|
3418
|
+
: undefined;
|
|
3419
|
+
if (!skillKey)
|
|
3420
|
+
continue;
|
|
3421
|
+
const resourceRoot = path.join(skillsRoot, skillKey);
|
|
3422
|
+
if (!await lstatIfPresent(path.join(resourceRoot, COMMAND_PRODUCER_RECORD_FILE)))
|
|
3423
|
+
continue;
|
|
3424
|
+
evidence.push(await captureManagedCommandBindingRecoveryEvidence({
|
|
3425
|
+
producer, resourceRoot, env: options.context.env,
|
|
3426
|
+
}));
|
|
3427
|
+
}
|
|
3428
|
+
return finish();
|
|
3429
|
+
};
|
|
3557
3430
|
const preflightCommandBindings = async (targets) => {
|
|
3558
3431
|
const producers = [];
|
|
3559
3432
|
for (const target of targets)
|
|
@@ -3568,7 +3441,27 @@ function createNativeDriver(options) {
|
|
|
3568
3441
|
producers.push(normalizeInstalledCommandProducer(JSON.parse(Buffer.from(file.contentBase64, 'base64').toString('utf8'))));
|
|
3569
3442
|
}
|
|
3570
3443
|
}
|
|
3571
|
-
|
|
3444
|
+
const captured = targets.flatMap((target) => nativeBindingRecoveryEvidence.get(target) ?? []);
|
|
3445
|
+
try {
|
|
3446
|
+
await assertManagedCommandBindingIdentities({ producers, bindingRecoveryEvidence: captured, env: options.context.env });
|
|
3447
|
+
}
|
|
3448
|
+
catch (error) {
|
|
3449
|
+
if (!(error instanceof ManagedCommandError) || error.code !== 'commandBindingInvalid')
|
|
3450
|
+
throw error;
|
|
3451
|
+
const needsRecovery = [];
|
|
3452
|
+
for (const producer of producers) {
|
|
3453
|
+
try {
|
|
3454
|
+
await assertManagedCommandBindingIdentities({ producers: [producer], bindingRecoveryEvidence: captured, env: options.context.env });
|
|
3455
|
+
}
|
|
3456
|
+
catch (issue) {
|
|
3457
|
+
if (!(issue instanceof ManagedCommandError) || issue.code !== 'commandBindingInvalid')
|
|
3458
|
+
throw issue;
|
|
3459
|
+
needsRecovery.push(producer);
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
const bindingRecoveryEvidence = (await Promise.all(targets.map((target) => captureNativeBindingRecoveryEvidence(target, needsRecovery)))).flat();
|
|
3463
|
+
await assertManagedCommandBindingIdentities({ producers, bindingRecoveryEvidence, env: options.context.env });
|
|
3464
|
+
}
|
|
3572
3465
|
};
|
|
3573
3466
|
const revokeAtRoot = async (root, recursive = false, platform) => {
|
|
3574
3467
|
const listed = await listManagedCommands(options.context.env);
|
|
@@ -3637,7 +3530,68 @@ function createNativeDriver(options) {
|
|
|
3637
3530
|
}
|
|
3638
3531
|
};
|
|
3639
3532
|
const currentCodexManager = () => options.context.codexManager;
|
|
3533
|
+
const requireClaudeActivationOnlyProvider = async (target) => {
|
|
3534
|
+
const marketplaceName = target.identity.marketplaceName ?? MARKETPLACE_NAME;
|
|
3535
|
+
const marketplaceRoot = target.identity.marketplaceRoot ?? resolveAwHome(options.context.env);
|
|
3536
|
+
const marketplace = await readStrictNamespacedMarketplaceRoot({
|
|
3537
|
+
trustedMarketplaceRoot: path.join(resolveAwHome(options.context.env), 'marketplaces'),
|
|
3538
|
+
rootDir: marketplaceRoot,
|
|
3539
|
+
});
|
|
3540
|
+
if (!marketplace
|
|
3541
|
+
|| marketplace.config.sourceId !== target.identity.sourceId
|
|
3542
|
+
|| marketplace.config.sourceIdentity !== target.identity.sourceIdentity
|
|
3543
|
+
|| marketplace.config.marketplaceName !== marketplaceName) {
|
|
3544
|
+
throw new Error('nativeActivationOnlyRequiresHealthySharedPackage: the Claude marketplace owner does not match the requested source.');
|
|
3545
|
+
}
|
|
3546
|
+
const provider = await readClaudeNativeState({
|
|
3547
|
+
pluginName: target.identity.pluginName,
|
|
3548
|
+
scope: 'user',
|
|
3549
|
+
cwd: target.identity.cwd,
|
|
3550
|
+
env: options.context.env,
|
|
3551
|
+
marketplaceName,
|
|
3552
|
+
marketplaceRoot,
|
|
3553
|
+
});
|
|
3554
|
+
if (provider.marketplaceDeclaredState !== 'canonical'
|
|
3555
|
+
|| provider.marketplaceMaterializedState !== 'canonical'
|
|
3556
|
+
|| provider.pluginState !== 'present'
|
|
3557
|
+
|| !provider.pluginEnabled
|
|
3558
|
+
|| provider.pluginVersions.length === 0
|
|
3559
|
+
|| provider.pluginVersions.some((version) => version !== target.identity.pluginVersion)) {
|
|
3560
|
+
throw new Error('nativeActivationOnlyRequiresHealthySharedPackage: an enabled current User Claude provider is required.');
|
|
3561
|
+
}
|
|
3562
|
+
const pluginRoot = await assertSafeNamespacedMarketplacePluginRoot(marketplaceRoot, target.identity.pluginName);
|
|
3563
|
+
if (!await codexPayloadPathSafe(pluginRoot, marketplaceRoot)) {
|
|
3564
|
+
throw new Error('nativeActivationOnlyRequiresHealthySharedPackage: the Claude package has an unsafe payload path.');
|
|
3565
|
+
}
|
|
3566
|
+
const installed = await readPluginManifest(pluginRoot, { mode: 'bundle' });
|
|
3567
|
+
const platformManifest = await readNativeSkillProjectionManifest(path.join(pluginRoot, '.claude-plugin', 'plugin.json'));
|
|
3568
|
+
if (installed.manifest.name !== target.identity.pluginName
|
|
3569
|
+
|| installed.manifest.version !== target.identity.pluginVersion
|
|
3570
|
+
|| platformManifest.state !== 'present'
|
|
3571
|
+
|| platformManifest.value.name !== target.identity.pluginName
|
|
3572
|
+
|| platformManifest.value.version !== target.identity.pluginVersion) {
|
|
3573
|
+
throw new Error('nativeActivationOnlyRequiresHealthySharedPackage: the Claude package manifest is missing or outdated.');
|
|
3574
|
+
}
|
|
3575
|
+
if (nativeSkillRenderTargets(target.plugin, 'claude').length > 0) {
|
|
3576
|
+
const evidence = await resolveNativeSkillRenderExpectedEvidence({
|
|
3577
|
+
plugin: target.plugin, platform: 'claude', referencePlugins: options.context.referencePlugins,
|
|
3578
|
+
marketplaceRoot, marketplaceName, env: options.context.env,
|
|
3579
|
+
});
|
|
3580
|
+
if (evidence.state !== 'present' || evidence.sourceProjection !== 'current') {
|
|
3581
|
+
throw new Error('nativeActivationOnlyRequiresHealthySharedPackage: the Claude Skill projection is not current.');
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
const selected = await readClaudeNativeState({
|
|
3585
|
+
pluginName: target.identity.pluginName, scope: target.identity.scope,
|
|
3586
|
+
cwd: target.identity.cwd, env: options.context.env, marketplaceName, marketplaceRoot,
|
|
3587
|
+
});
|
|
3588
|
+
if (selected.marketplaceState === 'foreign' || selected.pluginState === 'foreign') {
|
|
3589
|
+
throw new Error('externalOwnershipPresent: the Claude activation target belongs to a foreign marketplace.');
|
|
3590
|
+
}
|
|
3591
|
+
return selected;
|
|
3592
|
+
};
|
|
3640
3593
|
const nativeGroupPreparations = new Map();
|
|
3594
|
+
const nativeGroupPublications = new Map();
|
|
3641
3595
|
const nativeTargetPreparations = new WeakMap();
|
|
3642
3596
|
const codexNativeStates = new Map();
|
|
3643
3597
|
const pendingCodexNativeStates = new Map();
|
|
@@ -3752,15 +3706,15 @@ function createNativeDriver(options) {
|
|
|
3752
3706
|
await fs.chmod(destination, file.mode ?? 0o644);
|
|
3753
3707
|
}
|
|
3754
3708
|
}
|
|
3755
|
-
|
|
3756
|
-
continue;
|
|
3709
|
+
const platform = candidate.identity.platform;
|
|
3757
3710
|
const hasStaticSkills = candidate.plugin.manifest.skills !== undefined;
|
|
3758
|
-
const preparedNativeRender = await
|
|
3711
|
+
const preparedNativeRender = await requirePreparedNativeSkillRender({
|
|
3759
3712
|
context: options.context,
|
|
3760
3713
|
plugin: candidate.plugin,
|
|
3714
|
+
platform,
|
|
3761
3715
|
});
|
|
3762
3716
|
const nativeRender = preparedNativeRender
|
|
3763
|
-
? await
|
|
3717
|
+
? await materializeNativeSkillRender({
|
|
3764
3718
|
plugin: candidate.plugin,
|
|
3765
3719
|
stagingRoot,
|
|
3766
3720
|
prepared: preparedNativeRender,
|
|
@@ -3769,25 +3723,36 @@ function createNativeDriver(options) {
|
|
|
3769
3723
|
: null;
|
|
3770
3724
|
if (nativeRender)
|
|
3771
3725
|
renderedReceipts.push({ pluginName: candidate.identity.pluginName, receipt: nativeRender.receipt });
|
|
3772
|
-
if (!nativeRender) {
|
|
3726
|
+
if (!nativeRender && platform === 'codex') {
|
|
3773
3727
|
await ensureCodexActiveSkillsManifest({
|
|
3774
3728
|
plugin: candidate.plugin,
|
|
3775
3729
|
marketplaceRoot: stagingRoot,
|
|
3776
3730
|
hasRequiredSkills: hasStaticSkills,
|
|
3777
3731
|
});
|
|
3778
3732
|
}
|
|
3779
|
-
if (
|
|
3780
|
-
await
|
|
3733
|
+
if (hasStaticSkills || nativeSkillRenderTargets(candidate.plugin, platform).length > 0) {
|
|
3734
|
+
await assertNoSensitiveValuesInNativeSkillPayload({
|
|
3781
3735
|
plugin: candidate.plugin,
|
|
3736
|
+
platform,
|
|
3782
3737
|
payloadRoot: path.join(stagingRoot, 'plugins', candidate.identity.pluginName),
|
|
3783
3738
|
allowedRoot: stagingRoot,
|
|
3784
|
-
sensitiveValues: await resolveSensitiveUserConfigValues(candidate.plugin, options.context.env, options.context.referencePlugins),
|
|
3739
|
+
sensitiveValues: await resolveSensitiveUserConfigValues(candidate.plugin, options.context.env, options.context.referencePlugins, platform),
|
|
3785
3740
|
...(nativeRender ? { verifiedRenderReceipt: nativeRender.receipt } : {}),
|
|
3786
3741
|
});
|
|
3787
3742
|
}
|
|
3788
3743
|
}
|
|
3789
3744
|
for (const receipt of renderedReceipts)
|
|
3790
3745
|
await refreshPreservedPlatformReceipt(stagingRoot, receipt);
|
|
3746
|
+
if (first.identity.sourceId && first.identity.sourceIdentity && first.identity.marketplaceRoot) {
|
|
3747
|
+
nativeGroupPublications.set(key, await deferNativeMarketplacePublications({
|
|
3748
|
+
sourceRoot: first.identity.marketplaceRoot,
|
|
3749
|
+
stagingRoot,
|
|
3750
|
+
sourceId: first.identity.sourceId,
|
|
3751
|
+
sourceIdentity: first.identity.sourceIdentity,
|
|
3752
|
+
marketplaceName: first.identity.marketplaceName ?? MARKETPLACE_NAME,
|
|
3753
|
+
requestedPlatforms,
|
|
3754
|
+
}));
|
|
3755
|
+
}
|
|
3791
3756
|
}, new Set(materializationTargets.map((candidate) => candidate.identity.pluginId ?? `${candidate.identity.sourceId}/${candidate.identity.pluginName}`)), requestedPlatforms);
|
|
3792
3757
|
try {
|
|
3793
3758
|
await transaction.commit();
|
|
@@ -3804,8 +3769,6 @@ function createNativeDriver(options) {
|
|
|
3804
3769
|
throw error;
|
|
3805
3770
|
}
|
|
3806
3771
|
committedNativeGroups.add(key);
|
|
3807
|
-
for (const candidate of materializationTargets)
|
|
3808
|
-
await revokeAtRoot(path.join(candidate.identity.marketplaceRoot ?? resolveAwHome(options.context.env), 'plugins', candidate.identity.pluginName), true, candidate.identity.platform);
|
|
3809
3772
|
})().catch((error) => {
|
|
3810
3773
|
throw asNativeGroupFailure(error);
|
|
3811
3774
|
});
|
|
@@ -4178,6 +4141,11 @@ function createNativeDriver(options) {
|
|
|
4178
4141
|
: 'user'))));
|
|
4179
4142
|
},
|
|
4180
4143
|
preflightMutation: async (target) => {
|
|
4144
|
+
if (target.identity.platform === 'claude'
|
|
4145
|
+
&& isNativeActivationOnlyTarget(options.context, target.identity)) {
|
|
4146
|
+
await requireClaudeActivationOnlyProvider(target);
|
|
4147
|
+
return;
|
|
4148
|
+
}
|
|
4181
4149
|
await preflightCommandBindings([target]);
|
|
4182
4150
|
if (!target.codexNativeObservationExpectation
|
|
4183
4151
|
&& !target.codexNativeSensitivePreflightRequired)
|
|
@@ -4238,10 +4206,13 @@ function createNativeDriver(options) {
|
|
|
4238
4206
|
|| (Object.hasOwn(config.snapshot.plugins, expectedPluginId) && !canonical)) {
|
|
4239
4207
|
throw new Error(`externalOwnershipPresent: Codex marketplace ${marketplaceName} has a foreign source instead of its canonical namespaced root.`);
|
|
4240
4208
|
}
|
|
4241
|
-
if (target.nativeOverlayDesired
|
|
4242
|
-
|
|
4209
|
+
if (target.nativeOverlayDesired
|
|
4210
|
+
&& options.targets.some((candidate) => nativeGroupKey(candidate) === nativeGroupKey(target)
|
|
4211
|
+
&& (candidate.writeNativeRequired ?? candidate.requiresNative))) {
|
|
4212
|
+
await prepareNativeSkillRenderCached({
|
|
4243
4213
|
context: options.context,
|
|
4244
4214
|
plugin: target.plugin,
|
|
4215
|
+
platform: target.identity.platform,
|
|
4245
4216
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
4246
4217
|
});
|
|
4247
4218
|
}
|
|
@@ -4302,7 +4273,25 @@ function createNativeDriver(options) {
|
|
|
4302
4273
|
});
|
|
4303
4274
|
if (state.pluginState !== 'present')
|
|
4304
4275
|
return state.pluginState;
|
|
4305
|
-
|
|
4276
|
+
if (!state.pluginEnabled)
|
|
4277
|
+
return 'partial';
|
|
4278
|
+
if (nativeSkillRenderTargets(target.plugin, 'claude').length === 0)
|
|
4279
|
+
return 'present';
|
|
4280
|
+
const evidence = await resolveNativeSkillRenderExpectedEvidence({
|
|
4281
|
+
plugin: target.plugin,
|
|
4282
|
+
platform: 'claude',
|
|
4283
|
+
referencePlugins: options.context.referencePlugins,
|
|
4284
|
+
marketplaceRoot: target.identity.marketplaceRoot ?? resolveAwHome(options.context.env),
|
|
4285
|
+
marketplaceName: target.identity.marketplaceName ?? MARKETPLACE_NAME,
|
|
4286
|
+
env: options.context.env,
|
|
4287
|
+
});
|
|
4288
|
+
if (evidence.state === 'issue') {
|
|
4289
|
+
if (evidence.reason === 'unreadable') {
|
|
4290
|
+
throw new Error(`claudeNativeRenderEvidenceUnreadable: ${evidence.diagnostic}`);
|
|
4291
|
+
}
|
|
4292
|
+
return evidence.reason === 'foreign' ? 'foreign' : 'partial';
|
|
4293
|
+
}
|
|
4294
|
+
return evidence.sourceProjection === 'current' ? 'present' : 'partial';
|
|
4306
4295
|
}
|
|
4307
4296
|
if (target.identity.platform === 'codex') {
|
|
4308
4297
|
const pluginId = `${target.identity.pluginName}@${target.identity.marketplaceName ?? MARKETPLACE_NAME}`;
|
|
@@ -4448,6 +4437,10 @@ function createNativeDriver(options) {
|
|
|
4448
4437
|
}
|
|
4449
4438
|
await prepareNativeGroup(target);
|
|
4450
4439
|
const pluginId = `${target.identity.pluginName}@${marketplaceName}`;
|
|
4440
|
+
const publishPreparedPlatform = async () => {
|
|
4441
|
+
await revokeAtRoot(path.join(expectedMarketplaceRoot, 'plugins', target.identity.pluginName), true, target.identity.platform);
|
|
4442
|
+
await nativeGroupPublications.get(nativeGroupKey(target))?.publish(expectedMarketplaceRoot, target.identity.pluginName, target.identity.platform);
|
|
4443
|
+
};
|
|
4451
4444
|
if (target.identity.platform === 'codex') {
|
|
4452
4445
|
const stateKey = codexStateKey(target, pluginId);
|
|
4453
4446
|
const codexRemovalRequired = pendingCodexNativeStates.get(stateKey)
|
|
@@ -4463,6 +4456,7 @@ function createNativeDriver(options) {
|
|
|
4463
4456
|
});
|
|
4464
4457
|
pendingCodexNativeStates.set(stateKey, 'absent');
|
|
4465
4458
|
}
|
|
4459
|
+
await publishPreparedPlatform();
|
|
4466
4460
|
const config = await readCodexConfigFile(resolveCodexPaths(target.identity.cwd, 'user', options.context.env).configTomlPath);
|
|
4467
4461
|
const marketplace = config.snapshot.marketplaces[marketplaceName];
|
|
4468
4462
|
if (path.normalize(marketplace?.source ?? '') !== path.normalize(expectedMarketplaceRoot)) {
|
|
@@ -4488,6 +4482,7 @@ function createNativeDriver(options) {
|
|
|
4488
4482
|
}
|
|
4489
4483
|
}
|
|
4490
4484
|
else {
|
|
4485
|
+
await publishPreparedPlatform();
|
|
4491
4486
|
await runNativeCliChecked({
|
|
4492
4487
|
command: 'claude',
|
|
4493
4488
|
args: ['plugin', 'marketplace', 'add', expectedMarketplaceRoot, '--scope', target.identity.scope],
|
|
@@ -4535,13 +4530,38 @@ function createNativeDriver(options) {
|
|
|
4535
4530
|
const installed = await readInstalledCommandProducer(resourceRoot).catch(() => null);
|
|
4536
4531
|
if (!installed)
|
|
4537
4532
|
continue;
|
|
4538
|
-
const commandIds = await publishManagedCommandBindings({ ...installed, resourceRoot,
|
|
4533
|
+
const commandIds = await publishManagedCommandBindings({ ...installed, resourceRoot,
|
|
4534
|
+
bindingRecoveryEvidence: nativeBindingRecoveryEvidence.get(target), env: options.context.env });
|
|
4539
4535
|
options.context.commandResults ??= [];
|
|
4540
4536
|
options.context.commandResults.push({ producer: installed.producer, state: 'completed', commandIds, removedCommandIds: [], errors: [], recoveryActions: [] });
|
|
4541
4537
|
}
|
|
4542
4538
|
}
|
|
4543
4539
|
},
|
|
4544
4540
|
writeArtifacts: async (target) => {
|
|
4541
|
+
if (target.identity.platform === 'claude'
|
|
4542
|
+
&& isNativeActivationOnlyTarget(options.context, target.identity)) {
|
|
4543
|
+
const before = await requireClaudeActivationOnlyProvider(target);
|
|
4544
|
+
if (!before.pluginEnabled || !before.pluginVersions.includes(target.identity.pluginVersion)) {
|
|
4545
|
+
await runNativeCliChecked({
|
|
4546
|
+
command: 'claude',
|
|
4547
|
+
args: ['plugin', before.pluginVersions.includes(target.identity.pluginVersion) ? 'enable' : 'install',
|
|
4548
|
+
`${target.identity.pluginName}@${target.identity.marketplaceName ?? MARKETPLACE_NAME}`,
|
|
4549
|
+
'--scope', target.identity.scope],
|
|
4550
|
+
cwd: target.identity.cwd,
|
|
4551
|
+
env: options.context.env,
|
|
4552
|
+
}, runner);
|
|
4553
|
+
}
|
|
4554
|
+
const after = await readClaudeNativeState({
|
|
4555
|
+
pluginName: target.identity.pluginName, scope: target.identity.scope,
|
|
4556
|
+
cwd: target.identity.cwd, env: options.context.env,
|
|
4557
|
+
marketplaceName: target.identity.marketplaceName, marketplaceRoot: target.identity.marketplaceRoot,
|
|
4558
|
+
});
|
|
4559
|
+
if (after.pluginState !== 'present' || !after.pluginEnabled
|
|
4560
|
+
|| !after.pluginVersions.includes(target.identity.pluginVersion)) {
|
|
4561
|
+
throw new Error('claudeActivationPostcheckFailed: the requested scope is not enabled at the expected version.');
|
|
4562
|
+
}
|
|
4563
|
+
return [];
|
|
4564
|
+
}
|
|
4545
4565
|
await preflightCommandBindings([target]);
|
|
4546
4566
|
await publishPackages(target);
|
|
4547
4567
|
for (const operationAction of target.operationActions ?? []) {
|
|
@@ -4611,7 +4631,13 @@ function createNativeDriver(options) {
|
|
|
4611
4631
|
},
|
|
4612
4632
|
};
|
|
4613
4633
|
}
|
|
4634
|
+
export function isNativeActivationOnlyTarget(context, identity) {
|
|
4635
|
+
return context.nativeActivationOnlyTargets?.some((target) => target.pluginId === identity.pluginId
|
|
4636
|
+
&& target.platform === identity.platform
|
|
4637
|
+
&& target.scope === identity.scope) === true;
|
|
4638
|
+
}
|
|
4614
4639
|
export function createRebuildIntegration(options) {
|
|
4640
|
+
options.context.scriptTimeoutMs ??= options.scriptTimeoutMs;
|
|
4615
4641
|
const targets = [...(options.preparedTargets ?? [])];
|
|
4616
4642
|
const driver = createNativeDriver({ targets, ...options });
|
|
4617
4643
|
return {
|
|
@@ -4626,6 +4652,13 @@ export function createRebuildIntegration(options) {
|
|
|
4626
4652
|
sourceIdentity: input.sourceIdentity ?? input.plugin.sourceIdentity,
|
|
4627
4653
|
pluginId: input.pluginId ?? input.plugin.pluginId,
|
|
4628
4654
|
};
|
|
4655
|
+
const activationOnly = isNativeActivationOnlyTarget(options.context, {
|
|
4656
|
+
pluginId: input.pluginId,
|
|
4657
|
+
platform: input.platform,
|
|
4658
|
+
scope: input.scope,
|
|
4659
|
+
}) && input.command !== 'cleanup' && input.command !== 'uninstall';
|
|
4660
|
+
if (activationOnly)
|
|
4661
|
+
input = { ...input, readOnlyInspectionPlan: true };
|
|
4629
4662
|
const materializing = input.command !== 'cleanup'
|
|
4630
4663
|
&& input.command !== 'uninstall'
|
|
4631
4664
|
&& input.readOnlyInspectionPlan !== true;
|
|
@@ -4652,8 +4685,8 @@ export function createRebuildIntegration(options) {
|
|
|
4652
4685
|
options.context.managedCommandCandidates ??= new Map();
|
|
4653
4686
|
options.context.managedCommandCandidates.set(pluginActionId(input.plugin), commands.candidates);
|
|
4654
4687
|
const nativeSkillActions = [];
|
|
4655
|
-
if (materializing && input.
|
|
4656
|
-
const native = await
|
|
4688
|
+
if (materializing && nativeSkillRenderTargets(input.plugin, input.platform).length) {
|
|
4689
|
+
const native = await prepareNativeSkillRenderCached({ context: options.context, plugin: input.plugin, platform: input.platform, scriptTimeoutMs: options.scriptTimeoutMs });
|
|
4657
4690
|
if (native) {
|
|
4658
4691
|
commands.candidates.push(...native.commandCandidates);
|
|
4659
4692
|
for (const { artifact, skillKey, tree } of native.renderedArtifacts) {
|
|
@@ -4663,7 +4696,7 @@ export function createRebuildIntegration(options) {
|
|
|
4663
4696
|
...(tree.fileModes?.[relativePath] ? { mode: tree.fileModes[relativePath] } : {}),
|
|
4664
4697
|
})).sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
4665
4698
|
nativeSkillActions.push({ kind: 'materializeNativeSkill', pluginId: pluginActionId(input.plugin),
|
|
4666
|
-
platform:
|
|
4699
|
+
platform: input.platform, scope: 'user', artifactId: artifact.id, skillKey, files,
|
|
4667
4700
|
contentDigest: `sha256:${crypto.createHash('sha256').update(JSON.stringify(files)).digest('hex')}` });
|
|
4668
4701
|
}
|
|
4669
4702
|
}
|
|
@@ -4690,6 +4723,7 @@ export function createRebuildIntegration(options) {
|
|
|
4690
4723
|
env: options.context.env,
|
|
4691
4724
|
event,
|
|
4692
4725
|
historicalArtifacts,
|
|
4726
|
+
signal: options.context.signal,
|
|
4693
4727
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
4694
4728
|
marketplaceName: input.marketplaceName,
|
|
4695
4729
|
userActivationDesired: options.context.codexUserActivationDesired,
|
|
@@ -4704,6 +4738,7 @@ export function createRebuildIntegration(options) {
|
|
|
4704
4738
|
env: options.context.env,
|
|
4705
4739
|
event,
|
|
4706
4740
|
historicalArtifacts,
|
|
4741
|
+
signal: options.context.signal,
|
|
4707
4742
|
scriptTimeoutMs: options.scriptTimeoutMs,
|
|
4708
4743
|
commandCandidates: commands.candidates,
|
|
4709
4744
|
nativeSkillActions,
|
|
@@ -4727,6 +4762,8 @@ export function createRebuildIntegration(options) {
|
|
|
4727
4762
|
...(write.component ? [write.component] : []),
|
|
4728
4763
|
]);
|
|
4729
4764
|
}
|
|
4765
|
+
if (activationOnly)
|
|
4766
|
+
writes = [];
|
|
4730
4767
|
const desiredComponents = writes.filter((write) => !write.optional).flatMap((write) => [
|
|
4731
4768
|
...(write.additionalComponents ?? []),
|
|
4732
4769
|
...(write.component ? [write.component] : []),
|
|
@@ -4867,16 +4904,14 @@ export function createRebuildIntegration(options) {
|
|
|
4867
4904
|
&& codexRegistration.observation.value === 'installed'
|
|
4868
4905
|
&& (codexRegistration.observation.entry.version === undefined
|
|
4869
4906
|
|| codexRegistration.observation.entry.version === input.plugin.manifest.version);
|
|
4870
|
-
const materializeNativeRequired = nativeDesired && (input.platform === 'claude'
|
|
4907
|
+
const materializeNativeRequired = !activationOnly && nativeDesired && (input.platform === 'claude'
|
|
4871
4908
|
|| input.command === 'reinstall'
|
|
4872
4909
|
|| !codexNativeExact
|
|
4910
|
+
|| (materializing && nativeSkillRenderTargets(input.plugin, input.platform).length > 0)
|
|
4873
4911
|
|| (materializing && await hasPreparedStaticNativeCommandDrift({ plugin: input.plugin, cwd: input.cwd, env: options.context.env, context: options.context, marketplaceRoot: input.marketplaceRoot ?? resolveAwHome(options.context.env) })));
|
|
4874
|
-
const nativeCleanupCandidate = input.
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
&& (nativeRequired || (input.removedPluginWhole === true
|
|
4878
|
-
&& input.includeNativeCleanupCandidate === true))
|
|
4879
|
-
&& (input.command === 'cleanup' || input.command === 'uninstall');
|
|
4912
|
+
const nativeCleanupCandidate = input.includeNativeCleanupCandidate !== false
|
|
4913
|
+
&& (input.command === 'cleanup' || input.command === 'uninstall')
|
|
4914
|
+
&& (input.platform === 'claude' || (input.platform === 'codex' && nativeRequired));
|
|
4880
4915
|
const nativePlugin = (nativeDesired || nativeCleanupCandidate)
|
|
4881
4916
|
? [{
|
|
4882
4917
|
kind: 'native-plugin',
|
|
@@ -4956,7 +4991,13 @@ export function createRebuildIntegration(options) {
|
|
|
4956
4991
|
...marketplace,
|
|
4957
4992
|
...activationCleanup,
|
|
4958
4993
|
...explicitActivationCleanup,
|
|
4959
|
-
])
|
|
4994
|
+
]).filter((component) => (!activationOnly
|
|
4995
|
+
|| component.kind === 'native-plugin'
|
|
4996
|
+
|| (input.platform === 'codex' && component.kind === 'shared-config'
|
|
4997
|
+
&& (component.identity.artifactKey.startsWith('marketplace-')
|
|
4998
|
+
|| component.identity.artifactKey.startsWith('activation-'))))
|
|
4999
|
+
&& (options.context.preserveLegacyNativeSkills !== true
|
|
5000
|
+
|| component.kind !== 'skill-directory'));
|
|
4960
5001
|
bindNamespacedOwnerIdentity(allComponents, input);
|
|
4961
5002
|
const desiredKeys = new Set(desiredComponents.map(componentIdentityKey));
|
|
4962
5003
|
const retainedPackages = input.command === 'cleanup' || input.command === 'uninstall'
|
|
@@ -5039,7 +5080,7 @@ export function createRebuildIntegration(options) {
|
|
|
5039
5080
|
optionalOwnedComponents: allComponents.filter((component) => optionalComponentKeys.has(componentIdentityKey(component))),
|
|
5040
5081
|
requiresNative: nativeDesired,
|
|
5041
5082
|
writeNativeRequired: materializeNativeRequired,
|
|
5042
|
-
nativeOverlayDesired: nativeDesired,
|
|
5083
|
+
nativeOverlayDesired: nativeDesired && !activationOnly,
|
|
5043
5084
|
artifacts: writes.map((write) => write.artifact),
|
|
5044
5085
|
operationActions,
|
|
5045
5086
|
catalog: input.catalog,
|