create-agdf 0.13.5 → 0.13.6
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 +7 -1
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -3
- package/generated/plugins/agdf/hooks/session-start.sh +31 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +30 -9
- package/generated/plugins/agdf/runtime/agdf-local.js +8 -1
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +30 -9
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +116 -31
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +206 -0
- 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 +64 -19
- 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/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +30 -9
- 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 +9 -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 +4 -3
- package/lib/fs-swap.js +26 -0
- package/lib/installers/local-development.js +202 -0
- package/lib/installers/local-marketplace.js +181 -36
- package/lib/installers/opencode.js +17 -2
- package/lib/installers/plugin-installers.js +86 -22
- package/lib/lifecycle/operations.js +9 -5
- package/lib/lifecycle/status.js +10 -2
- package/lib/public-plugin/builder.js +5 -4
- package/lib/runtime/local-validator.js +116 -31
- package/lib/runtime/plugin-provenance.js +206 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -126,7 +126,9 @@ it does not localize the CLI lifecycle card.
|
|
|
126
126
|
The `codex` and `claude` commands install from the complete plugin built into the released
|
|
127
127
|
`create-agdf` package. They atomically stage it under an AGDF-owned user-data marketplace, register
|
|
128
128
|
that stable local path through the host CLI and verify the exposed version. Source `plugin/` therefore
|
|
129
|
-
contains no generated runtime bytes
|
|
129
|
+
contains no generated runtime bytes and the source checkout exposes no installable root marketplace.
|
|
130
|
+
The staged plugin contains one installation-provenance marker and the shared exact-version runtime;
|
|
131
|
+
routine installed validation does not depend on the GitHub
|
|
130
132
|
checkout, npm cache, PATH or registry. Rerunning either command performs the explicit update and
|
|
131
133
|
migrates only the exact known legacy AGDF GitHub marketplace; foreign same-name registrations fail
|
|
132
134
|
closed and failed host operations restore the prior owned stage.
|
|
@@ -137,6 +139,10 @@ Use the `codex-repo` target when AGDF should be available only inside one reposi
|
|
|
137
139
|
|
|
138
140
|
After `npm create agdf@latest -- codex-repo`, restart Codex in that repository, open `/plugins`, select `This repository` and install `agdf`.
|
|
139
141
|
|
|
142
|
+
`codex-repo` is a generated runtime-complete repository projection. It is distinct from this
|
|
143
|
+
runtime-free source checkout and is validated before lifecycle status treats `agdf@agdf-repo` as
|
|
144
|
+
active.
|
|
145
|
+
|
|
140
146
|
Use the `opencode` target to install the AGDF npm plugin as a user-wide OpenCode hook:
|
|
141
147
|
|
|
142
148
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdf",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"description": "AI Governance & Delivery Framework (AGDF) is a governance framework for agentic work. Its first implementation provides a control layer for governed AI-assisted software delivery. It combines workflow skills, explicit gates, control templates and machine-readable repository checks to keep work aligned with approved scope and make evidence a prerequisite for consequential gate transitions. Supported workflows include brownfield analysis, task-plan review, QA decisions, durable run state and auditable delivery closeout. AGDF is an independent open-source project, not a security sandbox, compliance certification or autonomous release system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentic",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdf",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Arndt Gold",
|
|
@@ -34,9 +34,8 @@
|
|
|
34
34
|
"composerIcon": "./assets/agdf-icon.svg",
|
|
35
35
|
"logo": "./assets/agdf-logo.svg",
|
|
36
36
|
"defaultPrompt": [
|
|
37
|
-
"Assess whether AGDF
|
|
37
|
+
"Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
|
|
38
38
|
"Start this request under AGDF governance.",
|
|
39
|
-
"Create durable AGDF control state for this repository.",
|
|
40
39
|
"Close this delivery run with an auditable AGDF report."
|
|
41
40
|
],
|
|
42
41
|
"brandColor": "#14B8A6"
|
|
@@ -3,11 +3,40 @@
|
|
|
3
3
|
# Activates a compact AGDF runtime reminder for the agent session.
|
|
4
4
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
PLUGIN_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
6
7
|
META_DIR="$(cd "${SCRIPT_DIR}/../meta" && pwd)"
|
|
7
8
|
ROUTER="${META_DIR}/agdf-agent-router.md"
|
|
8
9
|
CONSTITUTION="${META_DIR}/agdf-constitution.md"
|
|
9
10
|
RUNTIME_CONTRACT="${META_DIR}/agdf-runtime-contract.md"
|
|
10
11
|
CONFIG_PATH="${PWD}/.agdf/control/config.json"
|
|
12
|
+
LOCAL_RUNTIME="${PLUGIN_DIR}/runtime/agdf-local.js"
|
|
13
|
+
|
|
14
|
+
RUNTIME_HINT="AGDF runtime: profile=source-development evidence=source_checkout machine_validation=unavailable provenance=not_applicable."
|
|
15
|
+
if [[ -f "${PLUGIN_DIR}/.agdf-installation.json" && ! -f "${LOCAL_RUNTIME}" ]]; then
|
|
16
|
+
RUNTIME_HINT="AGDF runtime: profile=runtime-plugin evidence=installed_plugin_root machine_validation=unavailable provenance=unverified. Use the supported AGDF install/update command, then restart the host and retry in a fresh session."
|
|
17
|
+
fi
|
|
18
|
+
if [[ -f "${LOCAL_RUNTIME}" ]]; then
|
|
19
|
+
RUNTIME_HINT="AGDF runtime: profile=runtime-plugin evidence=unverified machine_validation=unavailable provenance=unverified. Retry the surface-local runtime probe or use the supported AGDF install/update command."
|
|
20
|
+
RUNTIME_JSON="$(AGDF_SURFACE="${AGDF_SURFACE:-plugin}" node "${LOCAL_RUNTIME}" --resolve-only --json 2>/dev/null || true)"
|
|
21
|
+
RUNTIME_RENDERED="$(RUNTIME_JSON="${RUNTIME_JSON}" node <<'NODE' 2>/dev/null || true
|
|
22
|
+
try {
|
|
23
|
+
const value = JSON.parse(process.env.RUNTIME_JSON || "{}");
|
|
24
|
+
const profile = value.distribution_profile || "runtime-plugin";
|
|
25
|
+
const evidence = value.evidence_plane || "unverified";
|
|
26
|
+
const version = value.plugin_version || value.observed_version || value.expected_version || "unknown";
|
|
27
|
+
const provenance = value.provenance_status || "unverified";
|
|
28
|
+
const validation = value.machine_validation || "unavailable";
|
|
29
|
+
const root = value.plugin_root || "unavailable";
|
|
30
|
+
console.log(`AGDF runtime: profile=${profile} evidence=${evidence} version=${version} provenance=${provenance} machine_validation=${validation} root=${root}.`);
|
|
31
|
+
} catch {
|
|
32
|
+
console.log("AGDF runtime: profile=runtime-plugin evidence=unverified machine_validation=unavailable provenance=invalid. Retry the surface-local runtime probe or use the supported AGDF install/update command.");
|
|
33
|
+
}
|
|
34
|
+
NODE
|
|
35
|
+
)"
|
|
36
|
+
if [[ -n "${RUNTIME_RENDERED}" ]]; then
|
|
37
|
+
RUNTIME_HINT="${RUNTIME_RENDERED}"
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
11
40
|
|
|
12
41
|
CONFIG_HINT="Project config: .agdf/control/config.json not found. Use npx --yes @agdf/cli@latest config --language de|en to persist the project language."
|
|
13
42
|
if [[ -f "${CONFIG_PATH}" ]]; then
|
|
@@ -33,6 +62,8 @@ fi
|
|
|
33
62
|
cat <<EOF
|
|
34
63
|
AGDF active.
|
|
35
64
|
|
|
65
|
+
${RUNTIME_HINT}
|
|
66
|
+
|
|
36
67
|
Use the installed AGDF skills as workflow controls.
|
|
37
68
|
For a new build, change, extension, refactor, CLI, app, fix with product semantics, unclear approval, or unclear next step, use gate-check before implementation or later-gate artefacts.
|
|
38
69
|
${CONFIG_HINT}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.6",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -33,9 +33,8 @@
|
|
|
33
33
|
"Write"
|
|
34
34
|
],
|
|
35
35
|
"defaultPrompt": [
|
|
36
|
-
"Assess whether AGDF
|
|
36
|
+
"Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
|
|
37
37
|
"Start this request under AGDF governance.",
|
|
38
|
-
"Create durable AGDF control state for this repository.",
|
|
39
38
|
"Close this delivery run with an auditable AGDF report."
|
|
40
39
|
],
|
|
41
40
|
"hooks": "hooks/hooks.json"
|
|
@@ -44,9 +43,8 @@
|
|
|
44
43
|
"skillPrefix": "",
|
|
45
44
|
"agentRouter": "meta/agdf-agent-router.md",
|
|
46
45
|
"defaultPrompt": [
|
|
47
|
-
"Assess whether AGDF
|
|
46
|
+
"Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
|
|
48
47
|
"Start this request under AGDF governance.",
|
|
49
|
-
"Create durable AGDF control state for this repository.",
|
|
50
48
|
"Close this delivery run with an auditable AGDF report."
|
|
51
49
|
]
|
|
52
50
|
},
|
|
@@ -254,10 +252,33 @@
|
|
|
254
252
|
"boundary": "supports Quality Readiness; no final QA decision"
|
|
255
253
|
}
|
|
256
254
|
],
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
|
|
260
|
-
"
|
|
255
|
+
"distributionProfiles": {
|
|
256
|
+
"schemaVersion": 1,
|
|
257
|
+
"marketplaceIdentities": {
|
|
258
|
+
"durable": "agdf",
|
|
259
|
+
"generatedRepository": "agdf-repo"
|
|
260
|
+
},
|
|
261
|
+
"profiles": {
|
|
262
|
+
"source-development": {
|
|
263
|
+
"runtime": "absent",
|
|
264
|
+
"installable": false,
|
|
265
|
+
"machineValidation": "unavailable"
|
|
266
|
+
},
|
|
267
|
+
"runtime-plugin": {
|
|
268
|
+
"runtime": "required",
|
|
269
|
+
"installable": true,
|
|
270
|
+
"machineValidation": "local_exact_version_digest"
|
|
271
|
+
},
|
|
272
|
+
"opencode-config-local": {
|
|
273
|
+
"runtime": "config_local_package",
|
|
274
|
+
"installable": true,
|
|
275
|
+
"machineValidation": "local_exact_version"
|
|
276
|
+
},
|
|
277
|
+
"portable-skills": {
|
|
278
|
+
"runtime": "absent",
|
|
279
|
+
"installable": true,
|
|
280
|
+
"machineValidation": "unavailable_or_external_required"
|
|
281
|
+
}
|
|
261
282
|
}
|
|
262
283
|
}
|
|
263
284
|
}
|
|
@@ -7,5 +7,12 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { runLocalValidator } from "./create-agdf/lib/runtime/local-validator.js";
|
|
8
8
|
|
|
9
9
|
const runtimeRoot = fileURLToPath(new URL(".", import.meta.url));
|
|
10
|
+
const pluginRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
10
11
|
const manifest = JSON.parse(readFileSync(new URL("./runtime-manifest.json", import.meta.url), "utf8"));
|
|
11
|
-
process.exitCode = runLocalValidator({
|
|
12
|
+
process.exitCode = runLocalValidator({
|
|
13
|
+
runtimeRoot,
|
|
14
|
+
pluginRoot,
|
|
15
|
+
expectedPluginRoot: process.env.CLAUDE_PLUGIN_ROOT || undefined,
|
|
16
|
+
expectedVersion: manifest.version,
|
|
17
|
+
surface: process.env.AGDF_SURFACE || "plugin",
|
|
18
|
+
}, process.argv.slice(2));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.6",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -33,9 +33,8 @@
|
|
|
33
33
|
"Write"
|
|
34
34
|
],
|
|
35
35
|
"defaultPrompt": [
|
|
36
|
-
"Assess whether AGDF
|
|
36
|
+
"Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
|
|
37
37
|
"Start this request under AGDF governance.",
|
|
38
|
-
"Create durable AGDF control state for this repository.",
|
|
39
38
|
"Close this delivery run with an auditable AGDF report."
|
|
40
39
|
],
|
|
41
40
|
"hooks": "hooks/hooks.json"
|
|
@@ -44,9 +43,8 @@
|
|
|
44
43
|
"skillPrefix": "",
|
|
45
44
|
"agentRouter": "meta/agdf-agent-router.md",
|
|
46
45
|
"defaultPrompt": [
|
|
47
|
-
"Assess whether AGDF
|
|
46
|
+
"Assess whether AGDF fits this request and recommend the lightest safe path before proposing implementation.",
|
|
48
47
|
"Start this request under AGDF governance.",
|
|
49
|
-
"Create durable AGDF control state for this repository.",
|
|
50
48
|
"Close this delivery run with an auditable AGDF report."
|
|
51
49
|
]
|
|
52
50
|
},
|
|
@@ -254,10 +252,33 @@
|
|
|
254
252
|
"boundary": "supports Quality Readiness; no final QA decision"
|
|
255
253
|
}
|
|
256
254
|
],
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
|
|
260
|
-
"
|
|
255
|
+
"distributionProfiles": {
|
|
256
|
+
"schemaVersion": 1,
|
|
257
|
+
"marketplaceIdentities": {
|
|
258
|
+
"durable": "agdf",
|
|
259
|
+
"generatedRepository": "agdf-repo"
|
|
260
|
+
},
|
|
261
|
+
"profiles": {
|
|
262
|
+
"source-development": {
|
|
263
|
+
"runtime": "absent",
|
|
264
|
+
"installable": false,
|
|
265
|
+
"machineValidation": "unavailable"
|
|
266
|
+
},
|
|
267
|
+
"runtime-plugin": {
|
|
268
|
+
"runtime": "required",
|
|
269
|
+
"installable": true,
|
|
270
|
+
"machineValidation": "local_exact_version_digest"
|
|
271
|
+
},
|
|
272
|
+
"opencode-config-local": {
|
|
273
|
+
"runtime": "config_local_package",
|
|
274
|
+
"installable": true,
|
|
275
|
+
"machineValidation": "local_exact_version"
|
|
276
|
+
},
|
|
277
|
+
"portable-skills": {
|
|
278
|
+
"runtime": "absent",
|
|
279
|
+
"installable": true,
|
|
280
|
+
"machineValidation": "unavailable_or_external_required"
|
|
281
|
+
}
|
|
261
282
|
}
|
|
262
283
|
}
|
|
263
284
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { existsSync, readFileSync,
|
|
2
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
4
3
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
4
|
import process from "node:process";
|
|
5
|
+
import {
|
|
6
|
+
INSTALLATION_PROVENANCE_FILE,
|
|
7
|
+
digestDirectory,
|
|
8
|
+
inspectGeneratedRepositoryMarketplace,
|
|
9
|
+
inspectInstallationProvenance,
|
|
10
|
+
validateDistributionProfiles,
|
|
11
|
+
} from "./plugin-provenance.js";
|
|
6
12
|
|
|
7
13
|
function readJson(path) {
|
|
8
14
|
try {
|
|
@@ -12,27 +18,12 @@ function readJson(path) {
|
|
|
12
18
|
}
|
|
13
19
|
}
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function visit(directory) {
|
|
18
|
-
for (const name of readdirSync(directory).sort()) {
|
|
19
|
-
const path = join(directory, name);
|
|
20
|
-
const stats = statSync(path);
|
|
21
|
-
if (stats.isDirectory()) visit(path);
|
|
22
|
-
else if (stats.isFile()) files.push(path);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
visit(root);
|
|
26
|
-
const hash = createHash("sha256");
|
|
27
|
-
for (const path of files) {
|
|
28
|
-
hash.update(relative(root, path).replaceAll("\\", "/"));
|
|
29
|
-
hash.update("\0");
|
|
30
|
-
hash.update(readFileSync(path));
|
|
31
|
-
hash.update("\0");
|
|
32
|
-
}
|
|
33
|
-
return hash.digest("hex");
|
|
21
|
+
function canonicalPath(path) {
|
|
22
|
+
try { return realpathSync(path); } catch { return resolve(path); }
|
|
34
23
|
}
|
|
35
24
|
|
|
25
|
+
export { digestDirectory };
|
|
26
|
+
|
|
36
27
|
function envelope(machineValidation, options, evidence = {}) {
|
|
37
28
|
return {
|
|
38
29
|
schema_version: "1",
|
|
@@ -42,6 +33,14 @@ function envelope(machineValidation, options, evidence = {}) {
|
|
|
42
33
|
observed_version: evidence.observedVersion ?? null,
|
|
43
34
|
source: evidence.source ?? null,
|
|
44
35
|
registry_access: false,
|
|
36
|
+
distribution_profile: evidence.distributionProfile ?? null,
|
|
37
|
+
evidence_plane: evidence.evidencePlane ?? null,
|
|
38
|
+
canonical_version: evidence.canonicalVersion ?? options.expectedVersion ?? null,
|
|
39
|
+
plugin_version: evidence.pluginVersion ?? null,
|
|
40
|
+
runtime_digest: evidence.runtimeDigest ?? null,
|
|
41
|
+
source_digest: evidence.sourceDigest ?? null,
|
|
42
|
+
plugin_root: evidence.pluginRoot ?? null,
|
|
43
|
+
provenance_status: evidence.provenanceStatus ?? null,
|
|
45
44
|
...(evidence.reason ? { reason: evidence.reason } : {}),
|
|
46
45
|
};
|
|
47
46
|
}
|
|
@@ -51,17 +50,17 @@ export function resolveLocalValidator(options) {
|
|
|
51
50
|
const packageManifest = readJson(join(options.ownedPackageRoot, "package.json"));
|
|
52
51
|
const observedVersion = packageManifest?.version ?? null;
|
|
53
52
|
if (!packageManifest) {
|
|
54
|
-
return { envelope: envelope("unavailable", options, { source: "config_local_package", reason: "package_missing" }) };
|
|
53
|
+
return { envelope: envelope("unavailable", options, { source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", reason: "package_missing" }) };
|
|
55
54
|
}
|
|
56
55
|
if (observedVersion !== options.expectedVersion) {
|
|
57
|
-
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "config_local_package" }) };
|
|
56
|
+
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local" }) };
|
|
58
57
|
}
|
|
59
58
|
const entrypoint = join(options.ownedPackageRoot, "bin", "create-agdf.js");
|
|
60
59
|
if (!existsSync(entrypoint)) {
|
|
61
|
-
return { envelope: envelope("unavailable", options, { observedVersion, source: "config_local_package", reason: "entrypoint_missing" }) };
|
|
60
|
+
return { envelope: envelope("unavailable", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", reason: "entrypoint_missing" }) };
|
|
62
61
|
}
|
|
63
62
|
return {
|
|
64
|
-
envelope: envelope("owned_version_matched", options, { observedVersion, source: "config_local_package" }),
|
|
63
|
+
envelope: envelope("owned_version_matched", options, { observedVersion, source: "config_local_package", evidencePlane: "opencode_config_local", distributionProfile: "opencode-config-local", provenanceStatus: "matched" }),
|
|
65
64
|
executable: process.execPath,
|
|
66
65
|
prefixArgs: [entrypoint],
|
|
67
66
|
};
|
|
@@ -73,30 +72,116 @@ export function resolveLocalValidator(options) {
|
|
|
73
72
|
return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", reason: "manifest_invalid" }) };
|
|
74
73
|
}
|
|
75
74
|
if (manifest) {
|
|
75
|
+
const pluginRoot = canonicalPath(options.pluginRoot ?? join(options.runtimeRoot, ".."));
|
|
76
|
+
if (options.expectedPluginRoot && canonicalPath(options.expectedPluginRoot) !== pluginRoot) {
|
|
77
|
+
return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, evidencePlane: "loaded_session", distributionProfile: "runtime-plugin", provenanceStatus: "mismatch", reason: "plugin_root_mismatch" }) };
|
|
78
|
+
}
|
|
79
|
+
const definition = readJson(join(pluginRoot, "meta", "agdf-plugin.definition.json"));
|
|
80
|
+
const profile = validateDistributionProfiles(definition);
|
|
81
|
+
if (profile.status !== "matched") {
|
|
82
|
+
return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, distributionProfile: "runtime-plugin", provenanceStatus: "invalid", reason: "profile_invalid" }) };
|
|
83
|
+
}
|
|
84
|
+
const codexManifest = readJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
|
|
85
|
+
const claudeManifest = readJson(join(pluginRoot, ".claude-plugin", "plugin.json"));
|
|
86
|
+
const pluginVersion = codexManifest?.version ?? null;
|
|
87
|
+
if (!codexManifest || !claudeManifest || claudeManifest.version !== definition.version) {
|
|
88
|
+
return { envelope: envelope("version_mismatch", options, { source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile: "runtime-plugin", provenanceStatus: "invalid", reason: "manifest_invalid" }) };
|
|
89
|
+
}
|
|
76
90
|
const packageRoot = join(options.runtimeRoot, "create-agdf");
|
|
77
91
|
if (!existsSync(packageRoot)) {
|
|
78
|
-
return { envelope: envelope("unavailable", options, { source: "plugin_bundle", reason: "
|
|
92
|
+
return { envelope: envelope("unavailable", options, { source: "plugin_bundle", pluginRoot, pluginVersion, distributionProfile: "runtime-plugin", reason: "runtime_missing" }) };
|
|
79
93
|
}
|
|
80
94
|
const packageManifest = readJson(join(packageRoot, "package.json"));
|
|
81
95
|
const observedVersion = packageManifest?.version ?? manifest.version ?? null;
|
|
82
96
|
if (observedVersion !== options.expectedVersion || manifest.version !== options.expectedVersion) {
|
|
83
|
-
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle" }) };
|
|
97
|
+
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, distributionProfile: "runtime-plugin" }) };
|
|
84
98
|
}
|
|
85
99
|
let observedDigest = null;
|
|
86
100
|
try { observedDigest = digestDirectory(packageRoot); } catch {}
|
|
87
101
|
if (!observedDigest || manifest.digest !== observedDigest) {
|
|
88
|
-
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", reason: "
|
|
102
|
+
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "runtime_digest_mismatch" }) };
|
|
89
103
|
}
|
|
90
104
|
const entrypoint = resolve(options.runtimeRoot, manifest.entrypoint ?? "");
|
|
91
105
|
const entrypointRelative = relative(options.runtimeRoot, entrypoint);
|
|
92
106
|
if (!manifest.entrypoint || entrypointRelative === ".." || entrypointRelative.startsWith(`..${sep}`) || isAbsolute(entrypointRelative)) {
|
|
93
|
-
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", reason: "invalid_entrypoint" }) };
|
|
107
|
+
return { envelope: envelope("version_mismatch", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "invalid_entrypoint" }) };
|
|
94
108
|
}
|
|
95
109
|
if (!existsSync(entrypoint)) {
|
|
96
|
-
return { envelope: envelope("unavailable", options, { observedVersion, source: "plugin_bundle", reason: "entrypoint_missing" }) };
|
|
110
|
+
return { envelope: envelope("unavailable", options, { observedVersion, source: "plugin_bundle", pluginRoot, pluginVersion, canonicalVersion: definition.version, runtimeDigest: observedDigest, distributionProfile: "runtime-plugin", reason: "entrypoint_missing" }) };
|
|
111
|
+
}
|
|
112
|
+
const installed = existsSync(join(pluginRoot, INSTALLATION_PROVENANCE_FILE));
|
|
113
|
+
let provenanceStatus = "not_applicable";
|
|
114
|
+
let sourceDigest = null;
|
|
115
|
+
let evidencePlane = "loaded_session";
|
|
116
|
+
if (installed) {
|
|
117
|
+
const provenance = inspectInstallationProvenance(pluginRoot, {
|
|
118
|
+
definition,
|
|
119
|
+
runtimeManifest: manifest,
|
|
120
|
+
pluginVersion,
|
|
121
|
+
});
|
|
122
|
+
provenanceStatus = provenance.status;
|
|
123
|
+
sourceDigest = provenance.marker?.source_digest ?? null;
|
|
124
|
+
if (provenance.status !== "matched") {
|
|
125
|
+
return { envelope: envelope("version_mismatch", options, {
|
|
126
|
+
observedVersion,
|
|
127
|
+
source: "plugin_bundle",
|
|
128
|
+
pluginRoot,
|
|
129
|
+
pluginVersion,
|
|
130
|
+
canonicalVersion: definition.version,
|
|
131
|
+
runtimeDigest: observedDigest,
|
|
132
|
+
sourceDigest,
|
|
133
|
+
distributionProfile: "runtime-plugin",
|
|
134
|
+
evidencePlane: "loaded_session",
|
|
135
|
+
provenanceStatus,
|
|
136
|
+
reason: provenance.reason,
|
|
137
|
+
}) };
|
|
138
|
+
}
|
|
139
|
+
} else if (existsSync(join(pluginRoot, ".agdf-local-install.json"))) {
|
|
140
|
+
return { envelope: envelope("unavailable", options, {
|
|
141
|
+
observedVersion,
|
|
142
|
+
source: "plugin_bundle",
|
|
143
|
+
pluginRoot,
|
|
144
|
+
pluginVersion,
|
|
145
|
+
canonicalVersion: definition.version,
|
|
146
|
+
runtimeDigest: observedDigest,
|
|
147
|
+
distributionProfile: "runtime-plugin",
|
|
148
|
+
evidencePlane: "loaded_session",
|
|
149
|
+
provenanceStatus: "missing",
|
|
150
|
+
reason: "installation_provenance_missing",
|
|
151
|
+
}) };
|
|
152
|
+
} else {
|
|
153
|
+
const generatedRepository = inspectGeneratedRepositoryMarketplace(resolve(pluginRoot, "..", ".."));
|
|
154
|
+
if (pluginVersion !== definition.version
|
|
155
|
+
|| generatedRepository.status !== "matched"
|
|
156
|
+
|| canonicalPath(generatedRepository.pluginRoot) !== pluginRoot) {
|
|
157
|
+
return { envelope: envelope("unavailable", options, {
|
|
158
|
+
observedVersion,
|
|
159
|
+
source: "plugin_bundle",
|
|
160
|
+
pluginRoot,
|
|
161
|
+
pluginVersion,
|
|
162
|
+
canonicalVersion: definition.version,
|
|
163
|
+
runtimeDigest: observedDigest,
|
|
164
|
+
distributionProfile: "runtime-plugin",
|
|
165
|
+
evidencePlane: "installed_plugin_root",
|
|
166
|
+
provenanceStatus: "missing",
|
|
167
|
+
reason: "installation_provenance_missing",
|
|
168
|
+
}) };
|
|
169
|
+
}
|
|
170
|
+
evidencePlane = "generated_bundle";
|
|
97
171
|
}
|
|
98
172
|
return {
|
|
99
|
-
envelope: envelope("owned_version_matched", options, {
|
|
173
|
+
envelope: envelope("owned_version_matched", options, {
|
|
174
|
+
observedVersion,
|
|
175
|
+
source: "plugin_bundle",
|
|
176
|
+
pluginRoot,
|
|
177
|
+
pluginVersion,
|
|
178
|
+
canonicalVersion: definition.version,
|
|
179
|
+
runtimeDigest: observedDigest,
|
|
180
|
+
sourceDigest,
|
|
181
|
+
distributionProfile: "runtime-plugin",
|
|
182
|
+
evidencePlane,
|
|
183
|
+
provenanceStatus,
|
|
184
|
+
}),
|
|
100
185
|
executable: process.execPath,
|
|
101
186
|
prefixArgs: [entrypoint],
|
|
102
187
|
};
|