create-agdf 0.13.8 → 0.14.2
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/README.md +14 -10
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -4
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +26 -2
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +7 -0
- package/generated/plugins/agdf/runtime/agdf-local.js +1 -1
- package/generated/plugins/agdf/runtime/agdf-session-check.js +10 -5
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +26 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +6 -7
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +29 -17
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +50 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +3 -1
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +32 -3
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +771 -0
- package/generated/plugins/copilot/agdf/LICENSE +201 -0
- package/generated/plugins/copilot/agdf/hooks/copilot-hooks.json +15 -0
- package/generated/{AGENTS.md → plugins/copilot/agdf/meta/agdf-agent-router.md} +49 -33
- package/generated/plugins/copilot/agdf/meta/agdf-constitution.md +329 -0
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +331 -0
- package/generated/plugins/copilot/agdf/meta/agdf-runtime-contract.md +16 -0
- package/generated/plugins/copilot/agdf/plugin.json +22 -0
- package/generated/plugins/copilot/agdf/runtime/agdf-local.js +18 -0
- package/generated/plugins/copilot/agdf/runtime/agdf-session-check.js +97 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/NOTICE +10 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +512 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +331 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +144 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +139 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +173 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +46 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +301 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +272 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +455 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +305 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +345 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +265 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +35 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +44 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +155 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +27 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +842 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/local-validator.js +239 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +255 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +73 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +6 -0
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +8 -0
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -2
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +26 -2
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +7 -0
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +13 -9
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/cli/application.js +64 -8
- package/lib/cli/command-registry.js +6 -7
- package/lib/installers/copilot-precedence.js +34 -0
- package/lib/installers/copilot-settings.js +84 -0
- package/lib/installers/local-marketplace.js +112 -30
- package/lib/installers/plugin-installers.js +184 -5
- package/lib/lifecycle/operations.js +3 -0
- package/lib/lifecycle/result.js +1 -0
- package/lib/lifecycle/status.js +3 -3
- package/lib/public-plugin/copilot-profile.js +126 -0
- package/lib/public-plugin/manifest.js +34 -2
- package/lib/public-plugin/validator.js +1 -1
- package/lib/release/version-coherence.js +4 -0
- package/lib/runtime/local-validator.js +29 -17
- package/lib/runtime/plugin-provenance.js +50 -1
- package/lib/runtime-check-consent/contract.js +3 -1
- package/lib/runtime-check-consent/coordinator.js +1 -0
- package/lib/runtime-check-consent/service.js +1 -1
- package/lib/runtime-check-consent/state.js +3 -3
- package/lib/scaffold/plan.js +3 -89
- package/lib/scaffold/presentation.js +3 -22
- package/package.json +6 -3
- package/generated/.github/copilot-instructions.md +0 -16
- package/generated/.github/instructions/agdf-governance.instructions.md +0 -14
- package/generated/.github/skills/README.md +0 -20
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-brownfield-analysis/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-clean-implementation-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-code-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-delivery-closeout/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-delivery-path-search/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-gate-check/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-interaction-locales.json +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-qa-gate/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-release-or/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-runtime-contract.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-task-plan-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/agdf-ux-intent-definition/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/closeout.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/context-graph.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/control-scaffold.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/gate-transition.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/interaction.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/modes.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/quality.md +0 -0
- /package/generated/{.github/skills → plugins/copilot/agdf/copilot-skills}/contracts/task-target-resolution.md +0 -0
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
INSTALLATION_PROVENANCE_FILE,
|
|
16
16
|
LEGACY_LOCAL_INSTALL_FILE,
|
|
17
17
|
digestDirectory,
|
|
18
|
+
inspectCopilotPayloadInventory,
|
|
18
19
|
digestNormalizedPluginSource,
|
|
19
20
|
inspectInstallationProvenance,
|
|
20
21
|
validateDistributionProfiles,
|
|
@@ -141,20 +142,39 @@ function claudeMarketplace(definition = pluginDefinition) {
|
|
|
141
142
|
};
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
function copilotMarketplace(definition = pluginDefinition) {
|
|
146
|
+
return {
|
|
147
|
+
name: MARKETPLACE_ID,
|
|
148
|
+
owner: { name: definition.displayName, email: "" },
|
|
149
|
+
metadata: { description: definition.description, version: definition.version },
|
|
150
|
+
plugins: [{
|
|
151
|
+
name: definition.id,
|
|
152
|
+
description: definition.copilotDescription || definition.longDescription,
|
|
153
|
+
version: definition.version,
|
|
154
|
+
source: "./plugins/agdf",
|
|
155
|
+
}],
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
144
159
|
function validateBuiltPlugin(pluginRoot, expectedVersion, expectedCodexInstallVersion = expectedVersion, sourceDigest = "", {
|
|
145
160
|
requireInstallationProvenance = false,
|
|
146
161
|
allowLegacyProvenanceForMigration = false,
|
|
147
162
|
allowPreProvenanceShape = false,
|
|
163
|
+
profileId = "runtime-plugin",
|
|
148
164
|
} = {}) {
|
|
149
165
|
const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"), "built plugin definition");
|
|
150
166
|
const runtime = readJson(join(pluginRoot, "runtime", "runtime-manifest.json"), "built runtime manifest");
|
|
151
|
-
const
|
|
152
|
-
const
|
|
167
|
+
const copilotProfile = profileId === "copilot-runtime-plugin";
|
|
168
|
+
const codex = copilotProfile ? null : readJson(join(pluginRoot, ".codex-plugin", "plugin.json"), "built Codex plugin manifest");
|
|
169
|
+
const claude = copilotProfile ? null : readJson(join(pluginRoot, ".claude-plugin", "plugin.json"), "built Claude plugin manifest");
|
|
170
|
+
const copilot = copilotProfile ? readJson(join(pluginRoot, "plugin.json"), "built Copilot plugin manifest") : null;
|
|
153
171
|
for (const required of [
|
|
154
|
-
join(pluginRoot, ".
|
|
155
|
-
|
|
172
|
+
...(copilotProfile ? [join(pluginRoot, "plugin.json"), join(pluginRoot, ".agdf-payload-inventory.json")] : [
|
|
173
|
+
join(pluginRoot, ".codex-plugin", "plugin.json"),
|
|
174
|
+
join(pluginRoot, ".claude-plugin", "plugin.json"),
|
|
175
|
+
join(pluginRoot, "scripts", "check-runtime-integrity.mjs"),
|
|
176
|
+
]),
|
|
156
177
|
join(pluginRoot, "runtime", "agdf-local.js"),
|
|
157
|
-
join(pluginRoot, "scripts", "check-runtime-integrity.mjs"),
|
|
158
178
|
]) {
|
|
159
179
|
if (!existsSync(required)) throw new Error(`Built plugin is incomplete: ${required}`);
|
|
160
180
|
}
|
|
@@ -178,13 +198,20 @@ function validateBuiltPlugin(pluginRoot, expectedVersion, expectedCodexInstallVe
|
|
|
178
198
|
if (profile.status !== "matched" && provenance?.status !== "legacy" && !isPreProvenanceShape) {
|
|
179
199
|
throw new Error("Built plugin distribution profile contract is invalid.");
|
|
180
200
|
}
|
|
181
|
-
if (codex.version !== expectedCodexInstallVersion) {
|
|
201
|
+
if (!copilotProfile && codex.version !== expectedCodexInstallVersion) {
|
|
182
202
|
throw new Error(`Built Codex plugin version mismatch: expected ${expectedCodexInstallVersion}, observed ${codex.version}`);
|
|
183
203
|
}
|
|
184
|
-
if (claude.version !== expectedVersion) {
|
|
204
|
+
if (!copilotProfile && claude.version !== expectedVersion) {
|
|
185
205
|
throw new Error(`Built Claude plugin version mismatch: expected ${expectedVersion}, observed ${claude.version}`);
|
|
186
206
|
}
|
|
187
|
-
if (
|
|
207
|
+
if (copilotProfile && copilot.version !== expectedVersion) {
|
|
208
|
+
throw new Error(`Built Copilot plugin version mismatch: expected ${expectedVersion}, observed ${copilot.version}`);
|
|
209
|
+
}
|
|
210
|
+
const copilotInventory = copilotProfile ? inspectCopilotPayloadInventory(pluginRoot, expectedVersion) : null;
|
|
211
|
+
if (copilotProfile && copilotInventory.status !== "matched") {
|
|
212
|
+
throw new Error(`Built Copilot plugin inventory is invalid: ${copilotInventory.reason}`);
|
|
213
|
+
}
|
|
214
|
+
if (!copilotProfile && expectedCodexInstallVersion !== expectedVersion) {
|
|
188
215
|
if (!isCodexLocalInstallVersion(expectedVersion, expectedCodexInstallVersion, sourceDigest)) {
|
|
189
216
|
throw new Error(`Invalid AGDF Codex local install version: ${expectedCodexInstallVersion}`);
|
|
190
217
|
}
|
|
@@ -199,6 +226,8 @@ function validateBuiltPlugin(pluginRoot, expectedVersion, expectedCodexInstallVe
|
|
|
199
226
|
runtimeManifest: runtime,
|
|
200
227
|
pluginVersion: expectedCodexInstallVersion,
|
|
201
228
|
allowLegacy: allowLegacyProvenanceForMigration,
|
|
229
|
+
profileId,
|
|
230
|
+
inventoryDigest: copilotInventory?.inventoryDigest ?? null,
|
|
202
231
|
});
|
|
203
232
|
if (provenance.status !== "matched"
|
|
204
233
|
&& !(allowLegacyProvenanceForMigration && provenance.status === "legacy")) {
|
|
@@ -208,11 +237,15 @@ function validateBuiltPlugin(pluginRoot, expectedVersion, expectedCodexInstallVe
|
|
|
208
237
|
return definition;
|
|
209
238
|
}
|
|
210
239
|
|
|
211
|
-
function validateMarketplaceRoot(root, definition = pluginDefinition) {
|
|
212
|
-
const
|
|
213
|
-
const
|
|
240
|
+
function validateMarketplaceRoot(root, definition = pluginDefinition, { profileId = "runtime-plugin" } = {}) {
|
|
241
|
+
const copilotProfile = profileId === "copilot-runtime-plugin";
|
|
242
|
+
const codex = copilotProfile ? null : readJson(join(root, ".agents", "plugins", "marketplace.json"), "Codex local marketplace manifest");
|
|
243
|
+
const copilot = copilotProfile ? readJson(join(root, ".github", "plugin", "marketplace.json"), "Copilot local marketplace manifest") : null;
|
|
244
|
+
const claude = copilotProfile ? null : readJson(join(root, ".claude-plugin", "marketplace.json"), "Claude local marketplace manifest");
|
|
214
245
|
const serializedCodex = JSON.stringify(codex);
|
|
215
|
-
const codexShape =
|
|
246
|
+
const codexShape = copilotProfile
|
|
247
|
+
? "current"
|
|
248
|
+
: serializedCodex === JSON.stringify(codexMarketplace(definition))
|
|
216
249
|
? "current"
|
|
217
250
|
: serializedCodex === JSON.stringify(legacyCodexMarketplace(definition))
|
|
218
251
|
? "legacy_full_product_label"
|
|
@@ -220,15 +253,19 @@ function validateMarketplaceRoot(root, definition = pluginDefinition) {
|
|
|
220
253
|
if (codexShape === "invalid") {
|
|
221
254
|
throw new Error(`Codex local marketplace manifest is not owned by ${MARKETPLACE_ID}: ${root}`);
|
|
222
255
|
}
|
|
223
|
-
if (JSON.stringify(claude) !== JSON.stringify(claudeMarketplace(definition))) {
|
|
256
|
+
if (!copilotProfile && JSON.stringify(claude) !== JSON.stringify(claudeMarketplace(definition))) {
|
|
224
257
|
throw new Error(`Claude local marketplace manifest is not owned by ${MARKETPLACE_ID}: ${root}`);
|
|
225
258
|
}
|
|
259
|
+
if (copilotProfile && JSON.stringify(copilot) !== JSON.stringify(copilotMarketplace(definition))) {
|
|
260
|
+
throw new Error(`Copilot local marketplace manifest is not owned by ${MARKETPLACE_ID}: ${root}`);
|
|
261
|
+
}
|
|
226
262
|
return Object.freeze({ codexShape });
|
|
227
263
|
}
|
|
228
264
|
|
|
229
|
-
function classifyExistingMarketplace(stableRoot, marker) {
|
|
265
|
+
function classifyExistingMarketplace(stableRoot, marker, { profileId = "runtime-plugin" } = {}) {
|
|
230
266
|
const existingPluginRoot = join(stableRoot, "plugins", MARKETPLACE_ID);
|
|
231
|
-
const
|
|
267
|
+
const copilotProfile = profileId === "copilot-runtime-plugin";
|
|
268
|
+
const existingCodexInstallVersion = copilotProfile ? marker.version : marker.codex_install_version ?? marker.version;
|
|
232
269
|
if (!isSemanticVersion(marker.version)
|
|
233
270
|
|| !/^[a-f0-9]{64}$/.test(marker.plugin_digest ?? "")) {
|
|
234
271
|
throw new Error(`Refusing invalid AGDF marketplace ownership evidence: ${stableRoot}`);
|
|
@@ -238,7 +275,7 @@ function classifyExistingMarketplace(stableRoot, marker) {
|
|
|
238
275
|
"built plugin definition",
|
|
239
276
|
);
|
|
240
277
|
const hasCurrentProvenance = existsSync(join(existingPluginRoot, INSTALLATION_PROVENANCE_FILE));
|
|
241
|
-
const hasLegacyProvenance = existsSync(join(existingPluginRoot, LEGACY_LOCAL_INSTALL_FILE));
|
|
278
|
+
const hasLegacyProvenance = !copilotProfile && existsSync(join(existingPluginRoot, LEGACY_LOCAL_INSTALL_FILE));
|
|
242
279
|
const preProvenanceCandidate = !hasCurrentProvenance
|
|
243
280
|
&& !hasLegacyProvenance
|
|
244
281
|
&& !Object.hasOwn(definition, "distributionProfiles");
|
|
@@ -249,9 +286,9 @@ function classifyExistingMarketplace(stableRoot, marker) {
|
|
|
249
286
|
marker.source_digest ?? "",
|
|
250
287
|
preProvenanceCandidate
|
|
251
288
|
? { allowPreProvenanceShape: true }
|
|
252
|
-
: { requireInstallationProvenance: true, allowLegacyProvenanceForMigration: true },
|
|
289
|
+
: { requireInstallationProvenance: true, allowLegacyProvenanceForMigration: true, profileId },
|
|
253
290
|
);
|
|
254
|
-
const marketplace = validateMarketplaceRoot(stableRoot, existingDefinition);
|
|
291
|
+
const marketplace = validateMarketplaceRoot(stableRoot, existingDefinition, { profileId });
|
|
255
292
|
if (digestDirectory(existingPluginRoot) !== marker.plugin_digest) {
|
|
256
293
|
throw new Error(`Refusing tampered AGDF marketplace root: ${stableRoot}`);
|
|
257
294
|
}
|
|
@@ -287,25 +324,30 @@ function recoverInterruptedTransaction(stableRoot, stageRoot, backupRoot, failed
|
|
|
287
324
|
|
|
288
325
|
export function prepareLocalMarketplace({
|
|
289
326
|
dataRoot = defaultAgdfDataRoot(),
|
|
290
|
-
builtPluginRoot
|
|
327
|
+
builtPluginRoot,
|
|
291
328
|
expectedVersion = pluginDefinition.version,
|
|
292
329
|
codexInstallVersion = expectedVersion,
|
|
293
330
|
codexRegistrationRevision = null,
|
|
331
|
+
profileId = "runtime-plugin",
|
|
294
332
|
} = {}) {
|
|
295
333
|
dataRoot = resolve(dataRoot);
|
|
334
|
+
const copilotProfile = profileId === "copilot-runtime-plugin";
|
|
335
|
+
if (!builtPluginRoot) builtPluginRoot = copilotProfile
|
|
336
|
+
? join(generatedRoot, "plugins", "copilot", "agdf")
|
|
337
|
+
: join(generatedRoot, "plugins", "agdf");
|
|
296
338
|
builtPluginRoot = resolve(builtPluginRoot);
|
|
297
|
-
const stableRoot = join(dataRoot, "marketplaces", MARKETPLACE_ID);
|
|
339
|
+
const stableRoot = join(dataRoot, "marketplaces", copilotProfile ? "agdf-copilot" : MARKETPLACE_ID);
|
|
298
340
|
const parent = dirname(stableRoot);
|
|
299
341
|
const stageRoot = `${stableRoot}.stage`;
|
|
300
342
|
const backupRoot = `${stableRoot}.backup`;
|
|
301
343
|
const failedRoot = `${stableRoot}.failed`;
|
|
302
344
|
if (!pathInside(dataRoot, stableRoot) || dirname(stableRoot) !== parent) throw new Error(`Unsafe AGDF marketplace root: ${stableRoot}`);
|
|
303
345
|
const sourceDigest = digestPluginSource(builtPluginRoot, expectedVersion);
|
|
304
|
-
if (codexInstallVersion !== expectedVersion
|
|
346
|
+
if (!copilotProfile && codexInstallVersion !== expectedVersion
|
|
305
347
|
&& !isCodexLocalInstallVersion(expectedVersion, codexInstallVersion, sourceDigest)) {
|
|
306
348
|
throw new Error(`Invalid AGDF Codex local install version: ${codexInstallVersion}`);
|
|
307
349
|
}
|
|
308
|
-
const targetDefinition = validateBuiltPlugin(builtPluginRoot, expectedVersion);
|
|
350
|
+
const targetDefinition = validateBuiltPlugin(builtPluginRoot, expectedVersion, expectedVersion, "", { profileId });
|
|
309
351
|
mkdirSync(parent, { recursive: true });
|
|
310
352
|
recoverInterruptedTransaction(stableRoot, stageRoot, backupRoot, failedRoot);
|
|
311
353
|
|
|
@@ -313,6 +355,7 @@ export function prepareLocalMarketplace({
|
|
|
313
355
|
if (existsSync(stableRoot)) {
|
|
314
356
|
try {
|
|
315
357
|
existing = ownership(stableRoot);
|
|
358
|
+
if ((existing.profile_id ?? "runtime-plugin") !== profileId) throw new Error(`AGDF marketplace profile mismatch: ${stableRoot}`);
|
|
316
359
|
} catch (error) {
|
|
317
360
|
throw invalidExistingMarketplace(error);
|
|
318
361
|
}
|
|
@@ -325,7 +368,7 @@ export function prepareLocalMarketplace({
|
|
|
325
368
|
if (existing) {
|
|
326
369
|
let classified;
|
|
327
370
|
try {
|
|
328
|
-
classified = classifyExistingMarketplace(stableRoot, existing);
|
|
371
|
+
classified = classifyExistingMarketplace(stableRoot, existing, { profileId });
|
|
329
372
|
} catch (error) {
|
|
330
373
|
throw invalidExistingMarketplace(error);
|
|
331
374
|
}
|
|
@@ -338,6 +381,7 @@ export function prepareLocalMarketplace({
|
|
|
338
381
|
schema_version: 1,
|
|
339
382
|
owner: "create-agdf",
|
|
340
383
|
marketplace_id: MARKETPLACE_ID,
|
|
384
|
+
profile_id: profileId,
|
|
341
385
|
codex_registration_revision: targetCodexRegistrationRevision,
|
|
342
386
|
version: expectedVersion,
|
|
343
387
|
codex_install_version: codexInstallVersion,
|
|
@@ -348,8 +392,8 @@ export function prepareLocalMarketplace({
|
|
|
348
392
|
});
|
|
349
393
|
const stagedPluginRoot = join(stageRoot, "plugins", MARKETPLACE_ID);
|
|
350
394
|
cpSync(builtPluginRoot, stagedPluginRoot, { recursive: true });
|
|
351
|
-
validateBuiltPlugin(stagedPluginRoot, expectedVersion);
|
|
352
|
-
if (codexInstallVersion !== expectedVersion) {
|
|
395
|
+
validateBuiltPlugin(stagedPluginRoot, expectedVersion, expectedVersion, "", { profileId });
|
|
396
|
+
if (!copilotProfile && codexInstallVersion !== expectedVersion) {
|
|
353
397
|
const codexManifestPath = join(stagedPluginRoot, ".codex-plugin", "plugin.json");
|
|
354
398
|
writeJson(codexManifestPath, { ...readJson(codexManifestPath, "built Codex plugin manifest"), version: codexInstallVersion });
|
|
355
399
|
}
|
|
@@ -357,25 +401,31 @@ export function prepareLocalMarketplace({
|
|
|
357
401
|
writeJson(join(stagedPluginRoot, INSTALLATION_PROVENANCE_FILE), {
|
|
358
402
|
schema_version: 1,
|
|
359
403
|
owner: "create-agdf",
|
|
360
|
-
profile_id:
|
|
404
|
+
profile_id: profileId,
|
|
361
405
|
marketplace_id: MARKETPLACE_ID,
|
|
362
406
|
canonical_version: expectedVersion,
|
|
363
407
|
codex_install_version: codexInstallVersion,
|
|
364
408
|
source_digest: sourceDigest,
|
|
365
409
|
runtime_digest: runtimeManifest.digest,
|
|
410
|
+
...(copilotProfile ? { inventory_digest: inspectCopilotPayloadInventory(stagedPluginRoot, expectedVersion).inventoryDigest } : {}),
|
|
366
411
|
});
|
|
367
412
|
if (existsSync(join(stagedPluginRoot, LEGACY_LOCAL_INSTALL_FILE))) {
|
|
368
413
|
rmSync(join(stagedPluginRoot, LEGACY_LOCAL_INSTALL_FILE));
|
|
369
414
|
}
|
|
370
|
-
validateBuiltPlugin(stagedPluginRoot, expectedVersion, codexInstallVersion, sourceDigest, { requireInstallationProvenance: true });
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
415
|
+
validateBuiltPlugin(stagedPluginRoot, expectedVersion, copilotProfile ? expectedVersion : codexInstallVersion, sourceDigest, { requireInstallationProvenance: true, profileId });
|
|
416
|
+
if (copilotProfile) {
|
|
417
|
+
writeJson(join(stageRoot, ".github", "plugin", "marketplace.json"), copilotMarketplace(targetDefinition));
|
|
418
|
+
} else {
|
|
419
|
+
writeJson(join(stageRoot, ".agents", "plugins", "marketplace.json"), codexMarketplace(targetDefinition));
|
|
420
|
+
writeJson(join(stageRoot, ".claude-plugin", "marketplace.json"), claudeMarketplace(targetDefinition));
|
|
421
|
+
}
|
|
422
|
+
validateMarketplaceRoot(stageRoot, targetDefinition, { profileId });
|
|
374
423
|
const pluginDigest = digestDirectory(stagedPluginRoot);
|
|
375
424
|
const marker = {
|
|
376
425
|
schema_version: 1,
|
|
377
426
|
owner: "create-agdf",
|
|
378
427
|
marketplace_id: MARKETPLACE_ID,
|
|
428
|
+
profile_id: profileId,
|
|
379
429
|
codex_registration_revision: targetCodexRegistrationRevision,
|
|
380
430
|
version: expectedVersion,
|
|
381
431
|
codex_install_version: codexInstallVersion,
|
|
@@ -448,6 +498,10 @@ export function prepareLocalMarketplace({
|
|
|
448
498
|
}
|
|
449
499
|
}
|
|
450
500
|
|
|
501
|
+
export function prepareCopilotMarketplace(options = {}) {
|
|
502
|
+
return prepareLocalMarketplace({ ...options, profileId: "copilot-runtime-plugin", codexInstallVersion: options.expectedVersion ?? pluginDefinition.version });
|
|
503
|
+
}
|
|
504
|
+
|
|
451
505
|
export function inspectLocalMarketplaceProjection({
|
|
452
506
|
dataRoot = defaultAgdfDataRoot(),
|
|
453
507
|
expectedVersion = pluginDefinition.version,
|
|
@@ -478,6 +532,34 @@ export function inspectLocalMarketplaceProjection({
|
|
|
478
532
|
});
|
|
479
533
|
}
|
|
480
534
|
|
|
535
|
+
export function inspectOwnedSharedMarketplaceForCopilotMigration({
|
|
536
|
+
dataRoot = defaultAgdfDataRoot(),
|
|
537
|
+
expectedVersion = pluginDefinition.version,
|
|
538
|
+
} = {}) {
|
|
539
|
+
const root = join(resolve(dataRoot), "marketplaces", MARKETPLACE_ID);
|
|
540
|
+
if (!existsSync(root)) return null;
|
|
541
|
+
const marker = ownership(root);
|
|
542
|
+
if ((marker.profile_id ?? "runtime-plugin") !== "runtime-plugin"
|
|
543
|
+
|| marker.version !== expectedVersion
|
|
544
|
+
|| !/^[a-f0-9]{64}$/.test(marker.plugin_digest ?? "")) {
|
|
545
|
+
throw new Error(`Refusing incompatible AGDF shared marketplace migration source: ${root}`);
|
|
546
|
+
}
|
|
547
|
+
const pluginRoot = join(root, "plugins", MARKETPLACE_ID);
|
|
548
|
+
const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"), "shared plugin definition");
|
|
549
|
+
const runtime = readJson(join(pluginRoot, "runtime", "runtime-manifest.json"), "shared runtime manifest");
|
|
550
|
+
const codex = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"), "shared Codex manifest");
|
|
551
|
+
const claude = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"), "shared Claude manifest");
|
|
552
|
+
if (definition.id !== MARKETPLACE_ID
|
|
553
|
+
|| definition.version !== expectedVersion
|
|
554
|
+
|| runtime.version !== expectedVersion
|
|
555
|
+
|| claude.version !== expectedVersion
|
|
556
|
+
|| (codex.version !== expectedVersion && !isCodexLocalInstallVersion(expectedVersion, codex.version))
|
|
557
|
+
|| digestDirectory(pluginRoot) !== marker.plugin_digest) {
|
|
558
|
+
throw new Error(`Refusing stale or tampered AGDF shared marketplace migration source: ${root}`);
|
|
559
|
+
}
|
|
560
|
+
return Object.freeze({ root, pluginRoot, version: marker.version, digest: marker.plugin_digest });
|
|
561
|
+
}
|
|
562
|
+
|
|
481
563
|
function normalizedLegacySource(value) {
|
|
482
564
|
if (typeof value !== "string") return "";
|
|
483
565
|
return value.trim().toLowerCase()
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
2
5
|
import { pluginDefinition } from "../cli/runtime-context.js";
|
|
3
|
-
import {
|
|
6
|
+
import { digestNormalizedPluginSource } from "../runtime/plugin-provenance.js";
|
|
7
|
+
import { CODEX_REGISTRATION_REVISION, classifyMarketplaceList, inspectLocalMarketplaceProjection, inspectOwnedSharedMarketplaceForCopilotMigration, isCodexLocalInstallVersion, prepareCopilotMarketplace, prepareLocalMarketplace } from "./local-marketplace.js";
|
|
8
|
+
|
|
9
|
+
export const COPILOT_CLI_NPM_PACKAGE = "@github/copilot@1.0.80";
|
|
4
10
|
|
|
5
11
|
export function installCodexGlobalPlugin({ exec = execFileSync, prepare = prepareLocalMarketplace, dataRoot } = {}) {
|
|
6
12
|
const expectedVersion = pluginDefinition.version;
|
|
@@ -93,6 +99,178 @@ export function installClaudeGlobalPlugin({ exec = execFileSync, prepare = prepa
|
|
|
93
99
|
}
|
|
94
100
|
}
|
|
95
101
|
|
|
102
|
+
export function installCopilotGlobalPlugin({ exec = execFileSync, packagedCopilotExec = execFileSync, prepare = prepareCopilotMarketplace, dataRoot, pluginRoot } = {}) {
|
|
103
|
+
const expectedVersion = pluginDefinition.version;
|
|
104
|
+
const transaction = pluginRoot ? null : prepare({ expectedVersion, ...(dataRoot ? { dataRoot } : {}) });
|
|
105
|
+
const effectivePluginRoot = pluginRoot ?? transaction?.pluginRoot;
|
|
106
|
+
if (!effectivePluginRoot) throw lifecycleAdapterError("package", "AGDF Copilot plugin root is required.");
|
|
107
|
+
let runtimeManifest;
|
|
108
|
+
try {
|
|
109
|
+
runtimeManifest = JSON.parse(readFileSync(join(effectivePluginRoot, "runtime", "runtime-manifest.json"), "utf8"));
|
|
110
|
+
} catch (error) {
|
|
111
|
+
transaction?.rollback();
|
|
112
|
+
throw lifecycleAdapterError("package", `AGDF Copilot runtime manifest is unavailable: ${error.message}`);
|
|
113
|
+
}
|
|
114
|
+
const sourceDigest = transaction?.sourceDigest || digestNormalizedPluginSource(effectivePluginRoot, expectedVersion);
|
|
115
|
+
let before = "";
|
|
116
|
+
let activeExec = exec;
|
|
117
|
+
const bootstrapEvidence = [];
|
|
118
|
+
try {
|
|
119
|
+
before = activeExec("copilot", ["plugin", "list"], captureOptions());
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error?.code !== "ENOENT") {
|
|
122
|
+
transaction?.rollback();
|
|
123
|
+
throw lifecycleAdapterError("verification", commandErrorText(error), { executable: "copilot", args: ["plugin", "list"] });
|
|
124
|
+
}
|
|
125
|
+
const invocation = copilotNpmInvocation();
|
|
126
|
+
activeExec = (_executable, args, options) => packagedCopilotExec(invocation.executable, [...invocation.args, ...args], options);
|
|
127
|
+
try {
|
|
128
|
+
before = activeExec("copilot", ["plugin", "list"], captureOptions());
|
|
129
|
+
bootstrapEvidence.push("copilot_cli_not_found", `copilot_cli_npm_package:${COPILOT_CLI_NPM_PACKAGE}`);
|
|
130
|
+
} catch (bootstrapError) {
|
|
131
|
+
transaction?.commit();
|
|
132
|
+
return {
|
|
133
|
+
surface: "copilot", operation: "install", expectedVersion, installedVersion: null,
|
|
134
|
+
verificationStatus: "unavailable", manualHandoff: true,
|
|
135
|
+
evidence: ["copilot_cli_not_found", `copilot_cli_npm_bootstrap_failed:${commandErrorText(bootstrapError)}`, "durable_local_plugin_stage", `local_plugin_root:${effectivePluginRoot}`, `source_digest:${sourceDigest}`],
|
|
136
|
+
pluginRoot: effectivePluginRoot, runtimeDigest: runtimeManifest.digest, sourceDigest, nativeOutput: [],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const directInstalled = pluginListHasPlugin(before, "agdf");
|
|
141
|
+
const marketplaceInstalled = pluginListHasPlugin(before, "agdf@agdf");
|
|
142
|
+
let legacySharedProjection = null;
|
|
143
|
+
if (transaction) {
|
|
144
|
+
try { legacySharedProjection = inspectOwnedSharedMarketplaceForCopilotMigration({ ...(dataRoot ? { dataRoot } : {}), expectedVersion }); } catch {}
|
|
145
|
+
}
|
|
146
|
+
let marketplaceAdded = false;
|
|
147
|
+
let legacyMarketplaceRemoved = false;
|
|
148
|
+
let marketplacePluginRemoved = false;
|
|
149
|
+
let directRemoved = false;
|
|
150
|
+
try {
|
|
151
|
+
const nativeOutput = [];
|
|
152
|
+
const marketplaceOutput = runPluginPhase(activeExec, "copilot", ["plugin", "marketplace", "list"], "marketplace", captureOptions());
|
|
153
|
+
const marketplace = classifyCopilotMarketplaceList(
|
|
154
|
+
marketplaceOutput,
|
|
155
|
+
transaction?.root ?? resolve(effectivePluginRoot, "..", ".."),
|
|
156
|
+
{ ownedLegacyRoots: legacySharedProjection ? [legacySharedProjection.root] : [] },
|
|
157
|
+
);
|
|
158
|
+
if (marketplace.state === "conflict") {
|
|
159
|
+
throw lifecycleAdapterError("marketplace", `Refusing to replace non-AGDF Copilot marketplace registration agdf (${marketplace.source || "unknown source"}).`);
|
|
160
|
+
}
|
|
161
|
+
if (marketplace.state === "owned_legacy_shared") {
|
|
162
|
+
if (marketplaceInstalled) {
|
|
163
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "uninstall", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
164
|
+
marketplacePluginRemoved = true;
|
|
165
|
+
}
|
|
166
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "marketplace", "remove", "agdf"], "marketplace", captureOptions()));
|
|
167
|
+
legacyMarketplaceRemoved = true;
|
|
168
|
+
}
|
|
169
|
+
if (["absent", "owned_legacy_shared"].includes(marketplace.state)) {
|
|
170
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "marketplace", "add", transaction?.root ?? resolve(effectivePluginRoot, "..", "..")], "marketplace", captureOptions()));
|
|
171
|
+
marketplaceAdded = true;
|
|
172
|
+
}
|
|
173
|
+
if (marketplace.state === "owned_local_current" && marketplaceInstalled) {
|
|
174
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "uninstall", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
175
|
+
marketplacePluginRemoved = true;
|
|
176
|
+
}
|
|
177
|
+
if (directInstalled) {
|
|
178
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "uninstall", "agdf"], "plugin_operation", captureOptions()));
|
|
179
|
+
directRemoved = true;
|
|
180
|
+
}
|
|
181
|
+
nativeOutput.push(runPluginPhase(activeExec, "copilot", ["plugin", "install", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
182
|
+
const after = runPluginPhase(activeExec, "copilot", ["plugin", "list"], "verification", captureOptions());
|
|
183
|
+
const installed = pluginListHasPlugin(after, "agdf@agdf");
|
|
184
|
+
const installedVersion = installed ? pluginVersionFromList(after, "agdf@agdf") : "";
|
|
185
|
+
if (!installed) throw lifecycleAdapterError("verification", "AGDF was not present in copilot plugin list after installation.");
|
|
186
|
+
if (installedVersion && installedVersion !== expectedVersion) {
|
|
187
|
+
throw lifecycleAdapterError("version", versionMismatchMessage("GitHub Copilot", "agdf", expectedVersion, installedVersion, "npx --yes @agdf/cli@latest copilot"));
|
|
188
|
+
}
|
|
189
|
+
transaction?.commit();
|
|
190
|
+
return {
|
|
191
|
+
surface: "copilot", operation: directInstalled || marketplaceInstalled ? "update" : "install", expectedVersion,
|
|
192
|
+
installedVersion: installedVersion || null, verificationStatus: installedVersion ? "healthy" : "degraded",
|
|
193
|
+
manualHandoff: false,
|
|
194
|
+
evidence: [...bootstrapEvidence, "durable_local_plugin_stage", "copilot plugin marketplace list", ...(marketplaceAdded ? ["copilot plugin marketplace add"] : ["marketplace:owned_local_current"]), ...(legacyMarketplaceRemoved ? ["shared_marketplace_registration_migrated"] : []), ...(directRemoved ? ["direct_install_migrated"] : []), "copilot plugin install agdf@agdf", "copilot plugin list", `local_plugin_root:${effectivePluginRoot}`, `source_digest:${sourceDigest}`, ...(installedVersion ? [] : ["host_did_not_expose_version"])],
|
|
195
|
+
pluginRoot: effectivePluginRoot, runtimeDigest: runtimeManifest.digest, sourceDigest, nativeOutput: nativeOutput.filter(Boolean).map(String),
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
transaction?.rollback();
|
|
199
|
+
if (directRemoved) {
|
|
200
|
+
try {
|
|
201
|
+
activeExec("copilot", ["plugin", "install", effectivePluginRoot], captureOptions());
|
|
202
|
+
} catch (recoveryError) {
|
|
203
|
+
error.evidence = { ...(error.evidence ?? {}), direct_install_recovery: commandErrorText(recoveryError) };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (marketplaceAdded) {
|
|
207
|
+
try {
|
|
208
|
+
activeExec("copilot", ["plugin", "marketplace", "remove", "agdf"], captureOptions());
|
|
209
|
+
} catch (recoveryError) {
|
|
210
|
+
error.evidence = { ...(error.evidence ?? {}), marketplace_recovery: commandErrorText(recoveryError) };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (legacyMarketplaceRemoved && legacySharedProjection) {
|
|
214
|
+
try {
|
|
215
|
+
activeExec("copilot", ["plugin", "marketplace", "add", legacySharedProjection.root], captureOptions());
|
|
216
|
+
if (marketplacePluginRemoved) activeExec("copilot", ["plugin", "install", "agdf@agdf"], captureOptions());
|
|
217
|
+
} catch (recoveryError) {
|
|
218
|
+
error.evidence = { ...(error.evidence ?? {}), legacy_marketplace_recovery: commandErrorText(recoveryError) };
|
|
219
|
+
}
|
|
220
|
+
} else if (marketplacePluginRemoved) {
|
|
221
|
+
try {
|
|
222
|
+
activeExec("copilot", ["plugin", "install", "agdf@agdf"], captureOptions());
|
|
223
|
+
} catch (recoveryError) {
|
|
224
|
+
error.evidence = { ...(error.evidence ?? {}), marketplace_plugin_recovery: commandErrorText(recoveryError) };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function classifyCopilotMarketplaceList(output, expectedRoot, { ownedLegacyRoots = [] } = {}) {
|
|
232
|
+
const line = String(output || "").split(/\r?\n/).find((entry) => /^\s*[◆•]?\s*agdf\s+\(/.test(entry));
|
|
233
|
+
if (!line) return { state: "absent", source: "" };
|
|
234
|
+
const local = line.match(/\(Local:\s*(.+)\)\s*$/);
|
|
235
|
+
if (!local) return { state: "conflict", source: line.trim() };
|
|
236
|
+
if (resolve(local[1]) === resolve(expectedRoot)) return { state: "owned_local_current", source: local[1] };
|
|
237
|
+
if (ownedLegacyRoots.some((root) => resolve(root) === resolve(local[1]))) return { state: "owned_legacy_shared", source: local[1] };
|
|
238
|
+
return { state: "conflict", source: local[1] };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function copilotNpmInvocation({ env = process.env, platform = process.platform, execPath = process.execPath } = {}) {
|
|
242
|
+
const args = ["exec", "--yes", `--package=${COPILOT_CLI_NPM_PACKAGE}`, "--", "copilot"];
|
|
243
|
+
if (env.npm_execpath) return { executable: execPath, args: [env.npm_execpath, ...args] };
|
|
244
|
+
return { executable: platform === "win32" ? "npm.cmd" : "npm", args };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function setCopilotPluginEnabled({ enabled, exec = execFileSync } = {}) {
|
|
248
|
+
if (typeof enabled !== "boolean") throw lifecycleAdapterError("plugin_operation", "Copilot plugin enabled state must be boolean.");
|
|
249
|
+
const operation = enabled ? "enable" : "disable";
|
|
250
|
+
try {
|
|
251
|
+
const nativeOutput = runPluginPhase(exec, "copilot", ["plugin", operation, "agdf"], "plugin_operation", captureOptions());
|
|
252
|
+
const listOutput = runPluginPhase(exec, "copilot", ["plugin", "list"], "verification", captureOptions());
|
|
253
|
+
if (!pluginListHasPlugin(listOutput, "agdf") && !pluginListHasPlugin(listOutput, "agdf@agdf")) {
|
|
254
|
+
throw lifecycleAdapterError("verification", "AGDF was not present in copilot plugin list after the state change.");
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
surface: "copilot",
|
|
258
|
+
requestedState: enabled ? "enabled" : "disabled",
|
|
259
|
+
status: "command_accepted_host_state_unverified",
|
|
260
|
+
evidence: [`copilot plugin ${operation} agdf`, "copilot plugin list", "fresh_session_required"],
|
|
261
|
+
nativeOutput: String(nativeOutput || ""),
|
|
262
|
+
};
|
|
263
|
+
} catch (error) {
|
|
264
|
+
if (/\bmanaged\b/i.test(commandErrorText(error))) {
|
|
265
|
+
return {
|
|
266
|
+
surface: "copilot", requestedState: enabled ? "enabled" : "disabled", status: "managed",
|
|
267
|
+
evidence: ["managed_policy_precedence", commandErrorText(error)], nativeOutput: "",
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
96
274
|
function migrateMarketplace({ surface, exec, output, root, nativeOutput, migration, refreshOwnedLocal = false }) {
|
|
97
275
|
const classification = classifyMarketplaceList(surface, output, root);
|
|
98
276
|
Object.assign(migration, classification);
|
|
@@ -176,10 +354,10 @@ function captureOptions() {
|
|
|
176
354
|
}
|
|
177
355
|
|
|
178
356
|
export function inspectPluginSurface(surface, exec = execFileSync, options = {}) {
|
|
179
|
-
const executable = surface === "claude" ? "claude" : "codex";
|
|
180
|
-
const pluginId = "agdf@agdf";
|
|
357
|
+
const executable = surface === "claude" ? "claude" : surface === "copilot" ? "copilot" : "codex";
|
|
181
358
|
try {
|
|
182
359
|
const output = exec(executable, ["plugin", "list"], { encoding: "utf8", stdio: "pipe" });
|
|
360
|
+
const pluginId = surface === "copilot" && !pluginListHasPlugin(output, "agdf@agdf") ? "agdf" : "agdf@agdf";
|
|
183
361
|
const installed = pluginListHasPlugin(output, pluginId);
|
|
184
362
|
const version = installed ? pluginVersionFromList(output, pluginId) : "";
|
|
185
363
|
let localDevelopmentVersion = false;
|
|
@@ -227,12 +405,13 @@ function commandErrorText(error) {
|
|
|
227
405
|
}
|
|
228
406
|
|
|
229
407
|
export function pluginListHasPlugin(output, pluginId) {
|
|
408
|
+
const escapedPluginId = pluginId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
230
409
|
return output
|
|
231
410
|
.split(/\r?\n/)
|
|
232
|
-
.some((line) =>
|
|
411
|
+
.some((line) => new RegExp(`(^|\\s)${escapedPluginId}(\\s|$)`).test(line));
|
|
233
412
|
}
|
|
234
413
|
|
|
235
|
-
const VERSION_PATTERN = "(\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?)";
|
|
414
|
+
const VERSION_PATTERN = "v?(\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?)";
|
|
236
415
|
|
|
237
416
|
export function pluginVersionFromList(output, pluginId) {
|
|
238
417
|
const escapedPluginId = pluginId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -85,6 +85,9 @@ export function planGlobalUninstall(surface, { configDir } = {}) {
|
|
|
85
85
|
if (surface === "claude") {
|
|
86
86
|
return nativeUninstallPlan(surface, "claude", ["plugin", "uninstall", "agdf@agdf", "--scope", "user"]);
|
|
87
87
|
}
|
|
88
|
+
if (surface === "copilot") {
|
|
89
|
+
return nativeUninstallPlan(surface, "copilot", ["plugin", "uninstall", "agdf"]);
|
|
90
|
+
}
|
|
88
91
|
if (surface === "opencode") {
|
|
89
92
|
if (!configDir) throw new Error("OpenCode uninstall requires its explicit config directory.");
|
|
90
93
|
const configPath = join(configDir, "opencode.json");
|
package/lib/lifecycle/result.js
CHANGED
|
@@ -5,6 +5,7 @@ const SURFACES = new Set(["codex", "claude", "copilot", "opencode", "generic"]);
|
|
|
5
5
|
const GLOBAL_INSTALL_RESTART_ACTIONS = Object.freeze({
|
|
6
6
|
codex: "Restart Codex.",
|
|
7
7
|
claude: "Restart Claude Code.",
|
|
8
|
+
copilot: "Restart GitHub Copilot.",
|
|
8
9
|
opencode: "Restart OpenCode.",
|
|
9
10
|
});
|
|
10
11
|
|
package/lib/lifecycle/status.js
CHANGED
|
@@ -63,7 +63,7 @@ function inspectInstallation(surface, targetDir, options, deps, exec) {
|
|
|
63
63
|
evidence: [report.global_config.path],
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
if (["codex", "claude"].includes(surface)) return deps.inspectPluginSurface(surface, exec);
|
|
66
|
+
if (["codex", "claude", "copilot"].includes(surface)) return deps.inspectPluginSurface(surface, exec);
|
|
67
67
|
return { status: "unknown", surface, version: null, evidence: [`unsupported_status_probe:${surface}`] };
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -79,7 +79,7 @@ export function evaluateGeneralStatus(targetDir, options = {}, dependencies = {}
|
|
|
79
79
|
if (surface) {
|
|
80
80
|
installation = inspectInstallation(surface, targetDir, options, deps, dependencies.exec);
|
|
81
81
|
} else {
|
|
82
|
-
const probes = ["codex", "claude", "opencode"].map((candidate) => inspectInstallation(candidate, targetDir, options, deps, dependencies.exec));
|
|
82
|
+
const probes = ["codex", "claude", "copilot", "opencode"].map((candidate) => inspectInstallation(candidate, targetDir, options, deps, dependencies.exec));
|
|
83
83
|
const observed = probes.filter((probe) => ["healthy", "degraded"].includes(probe.status));
|
|
84
84
|
if (observed.length === 1) {
|
|
85
85
|
installation = observed[0];
|
|
@@ -96,7 +96,7 @@ export function evaluateGeneralStatus(targetDir, options = {}, dependencies = {}
|
|
|
96
96
|
}
|
|
97
97
|
const repository = repositoryStatus(targetDir, surface);
|
|
98
98
|
const delivery = deliveryStatus(targetDir, { runId: options.runId }, deps);
|
|
99
|
-
const runtimeChecks = ["codex", "claude", "opencode"].includes(surface)
|
|
99
|
+
const runtimeChecks = ["codex", "claude", "copilot", "opencode"].includes(surface)
|
|
100
100
|
? runtimeCheckStatus(options.dataRoot, surface)
|
|
101
101
|
: { requested: "unknown", effective: "unavailable", reason: "unsupported_host_capability" };
|
|
102
102
|
const nextText = surface === "multiple"
|