create-agdf 0.13.7 → 0.13.8
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 +26 -0
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/hooks/hooks.json +3 -2
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +24 -1
- package/generated/plugins/agdf/runtime/agdf-session-check.js +92 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +24 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +9 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +17 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +71 -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 +19 -2
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +8 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +12 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +23 -1
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +24 -1
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +8 -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 +12 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +23 -1
- package/lib/cli/application.js +228 -13
- package/lib/cli/command-registry.js +9 -0
- package/lib/cli/parse-args.js +17 -0
- package/lib/installers/local-marketplace.js +2 -0
- package/lib/installers/opencode.js +21 -5
- package/lib/installers/plugin-installers.js +8 -0
- package/lib/lifecycle/presentation.js +43 -2
- package/lib/lifecycle/result.js +9 -0
- package/lib/lifecycle/status.js +5 -1
- package/lib/runtime-check-consent/adapters.js +42 -0
- package/lib/runtime-check-consent/claude-settings.js +71 -0
- package/lib/runtime-check-consent/contract.js +71 -0
- package/lib/runtime-check-consent/coordinator.js +37 -0
- package/lib/runtime-check-consent/service.js +181 -0
- package/lib/runtime-check-consent/state.js +90 -0
- package/opencode-plugin.js +30 -15
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -26,6 +26,31 @@ Use a different target when Codex is not your agent surface:
|
|
|
26
26
|
| Claude Code | `npx --yes @agdf/cli@latest claude` | The AGDF plugin for Claude Code. |
|
|
27
27
|
| OpenCode, user-wide discovery | `npx --yes @agdf/cli@latest opencode` | The npm plugin and global native skills; repository governance remains opt-in. |
|
|
28
28
|
| OpenCode, one repository | `npx --yes @agdf/cli@latest opencode-repo` | Durable control configuration that activates the once-installed global runtime. |
|
|
29
|
+
|
|
30
|
+
The runtime-bearing `codex`, `claude` and `opencode` installers ask before enabling narrow automatic
|
|
31
|
+
local checks on an interactive terminal. The choices are `enable`, `manual` and `cancel`; enablement
|
|
32
|
+
is never preselected. Every interactive installation or update asks again. A previous choice is
|
|
33
|
+
shown only as intent, never as proof of effective host permission. The prompt shows the target AGDF
|
|
34
|
+
version and the result shows the verified installed version or transition. Matching capability
|
|
35
|
+
identity may preserve host-native trust, but it never
|
|
36
|
+
suppresses the installer choice. Non-interactive installation defaults to manual unless the exact
|
|
37
|
+
option is provided:
|
|
38
|
+
|
|
39
|
+
Interactive terminals accept `1` or `E` for enable, `2` or `M` for manual, `D` for technical
|
|
40
|
+
details and `Esc` for immediate cancel without Enter. The primary choice uses beginner-safe language,
|
|
41
|
+
keeps the material consent facts visible and has no preselected option. Manual mode explains that
|
|
42
|
+
AGDF remains available on request; invalid keys redisplay the valid choices.
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npx --yes @agdf/cli@latest claude --runtime-checks enable
|
|
46
|
+
npx --yes @agdf/cli@latest runtime-checks status --surface claude --json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The check is argument-free, read-only and offline. Consent is content-bound, reversible and separate
|
|
50
|
+
from AGDF gate approval. A receipt alone never proves effective host permission. Codex native trust,
|
|
51
|
+
Claude deny/ask precedence and all explicit OpenCode permissions remain authoritative. The public
|
|
52
|
+
Skills-only OpenAI candidate has no runtime or hooks and therefore remains manual/external for this
|
|
53
|
+
capability.
|
|
29
54
|
| GitHub Copilot | `npx --yes @agdf/cli@latest copilot` | Repository instructions, visible skills and control templates. |
|
|
30
55
|
| Durable control state in an existing setup | `npx --yes @agdf/cli@latest init` | Live `.agdf/control/` state when the repository explicitly needs it. |
|
|
31
56
|
|
|
@@ -117,6 +142,7 @@ it does not localize the CLI lifecycle card.
|
|
|
117
142
|
- `opencode` installs the AGDF npm plugin and ten native skills as a user-wide OpenCode surface
|
|
118
143
|
- `opencode-status` reports OpenCode global config, package loadability, global native-skill completeness, installed host/plugin-SDK versions, declaration-level support for AGDF's two experimental hooks, durable repository activation, legacy compatibility and observable session signals
|
|
119
144
|
- `status` reports installation, repository activation and delivery separately without mutating state
|
|
145
|
+
- `runtime-checks status|enable|manual` reports the requested/effective automatic-check state or gives the exact reinstall route needed to change it
|
|
120
146
|
- `disable` writes a supported repository-local opt-out while retaining global capability and durable control state
|
|
121
147
|
- `uninstall` previews and, only with `--confirm`, applies a selected global removal through supported native/owned operations
|
|
122
148
|
- `opencode-repo` writes durable AGDF control configuration and templates under `.agdf/control/`; it does not copy a second OpenCode runtime surface
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdf",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.8",
|
|
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",
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "
|
|
9
|
-
"
|
|
8
|
+
"command": "node \"${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/runtime/agdf-session-check.js\"",
|
|
9
|
+
"commandWindows": "node \"$([Environment]::GetEnvironmentVariable('PLUGIN_ROOT') + [Environment]::GetEnvironmentVariable('CLAUDE_PLUGIN_ROOT'))\\runtime\\agdf-session-check.js\"",
|
|
10
|
+
"statusMessage": "Checking AGDF runtime state..."
|
|
10
11
|
}
|
|
11
12
|
]
|
|
12
13
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.8",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -68,6 +68,29 @@
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
"automaticRuntimeChecks": {
|
|
72
|
+
"schemaVersion": 1,
|
|
73
|
+
"capabilityId": "automatic-runtime-checks",
|
|
74
|
+
"adapterContractVersion": 1,
|
|
75
|
+
"entrypoint": "runtime/agdf-session-check.js",
|
|
76
|
+
"operations": [
|
|
77
|
+
"resolve-local-runtime",
|
|
78
|
+
"inspect-control-state",
|
|
79
|
+
"render-bounded-orientation"
|
|
80
|
+
],
|
|
81
|
+
"constraints": {
|
|
82
|
+
"arguments": "forbidden",
|
|
83
|
+
"filesystemWrites": "forbidden",
|
|
84
|
+
"network": "forbidden",
|
|
85
|
+
"gateAuthority": "none"
|
|
86
|
+
},
|
|
87
|
+
"surfaces": {
|
|
88
|
+
"codex": "native-hook-review",
|
|
89
|
+
"claude": "exact-command-rule",
|
|
90
|
+
"opencode": "plugin-internal",
|
|
91
|
+
"portable-skills": "manual-external-required"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
71
94
|
"interactions": {
|
|
72
95
|
"fallback": "exact_text",
|
|
73
96
|
"localeRegistry": "meta/agdf-interaction-locales.json",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Generated by create-agdf/scripts/sync-plugin-runtime.js; do not edit.
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import process from "node:process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { digestNormalizedPluginSource } from "./create-agdf/lib/runtime/plugin-provenance.js";
|
|
11
|
+
import { fixedRuntimeCheckCommand, runtimeCheckCapabilityIdentity } from "./create-agdf/lib/runtime-check-consent/contract.js";
|
|
12
|
+
|
|
13
|
+
if (process.argv.length !== 2) {
|
|
14
|
+
console.error("AGDF automatic runtime check accepts no arguments.");
|
|
15
|
+
process.exitCode = 2;
|
|
16
|
+
} else {
|
|
17
|
+
const surface = process.env.AGDF_SURFACE
|
|
18
|
+
|| (process.env.CLAUDE_PLUGIN_ROOT ? "claude" : process.env.PLUGIN_ROOT ? "codex" : "");
|
|
19
|
+
const dataRoot = process.env.AGDF_DATA_DIR
|
|
20
|
+
|| (process.platform === "darwin"
|
|
21
|
+
? join(homedir(), "Library", "Application Support", "agdf")
|
|
22
|
+
: process.platform === "win32"
|
|
23
|
+
? join(process.env.LOCALAPPDATA || process.env.APPDATA || join(homedir(), "AppData", "Local"), "agdf")
|
|
24
|
+
: join(process.env.XDG_DATA_HOME || join(homedir(), ".local", "share"), "agdf"));
|
|
25
|
+
let consentEnabled = false;
|
|
26
|
+
if (["codex", "claude", "opencode"].includes(surface)) {
|
|
27
|
+
try {
|
|
28
|
+
const receipt = JSON.parse(readFileSync(join(dataRoot, "runtime-checks", `${surface}.json`), "utf8"));
|
|
29
|
+
consentEnabled = receipt?.schema_version === 1
|
|
30
|
+
&& receipt?.owner === "create-agdf"
|
|
31
|
+
&& receipt?.capability_id === "automatic-runtime-checks"
|
|
32
|
+
&& receipt?.surface === surface
|
|
33
|
+
&& receipt?.requested_state === "enabled";
|
|
34
|
+
if (consentEnabled && ["codex", "claude"].includes(surface)) {
|
|
35
|
+
const pluginRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
36
|
+
const manifest = JSON.parse(readFileSync(new URL("./runtime-manifest.json", import.meta.url), "utf8"));
|
|
37
|
+
const definition = JSON.parse(readFileSync(new URL("../meta/agdf-plugin.definition.json", import.meta.url), "utf8"));
|
|
38
|
+
const currentIdentity = runtimeCheckCapabilityIdentity({
|
|
39
|
+
capability: definition.automaticRuntimeChecks,
|
|
40
|
+
surface,
|
|
41
|
+
runtimeDigest: manifest.digest,
|
|
42
|
+
sourceDigest: digestNormalizedPluginSource(pluginRoot, manifest.version),
|
|
43
|
+
command: fixedRuntimeCheckCommand(surface, pluginRoot, process.platform),
|
|
44
|
+
});
|
|
45
|
+
consentEnabled = receipt.capability_identity === currentIdentity;
|
|
46
|
+
}
|
|
47
|
+
} catch {}
|
|
48
|
+
}
|
|
49
|
+
if (!consentEnabled) process.exit(0);
|
|
50
|
+
const validator = fileURLToPath(new URL("./agdf-local.js", import.meta.url));
|
|
51
|
+
const pluginRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
52
|
+
const child = spawnSync(process.execPath, [validator, "doctor", "--all-active", "--json"], {
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
env: { ...process.env, AGDF_SURFACE: process.env.AGDF_SURFACE || "plugin" },
|
|
55
|
+
encoding: "utf8",
|
|
56
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
57
|
+
timeout: 10000,
|
|
58
|
+
maxBuffer: 1024 * 1024,
|
|
59
|
+
});
|
|
60
|
+
let message = "AGDF automatic runtime check: no governed control state was found; manual validation remains available.";
|
|
61
|
+
try {
|
|
62
|
+
const report = JSON.parse(child.stdout || "{}");
|
|
63
|
+
const status = report.status || "unknown";
|
|
64
|
+
const findings = report.summary?.findings ?? report.reports?.reduce((sum, item) => sum + (item.summary?.findings ?? 0), 0) ?? 0;
|
|
65
|
+
message = `AGDF automatic runtime check: status=${status} findings=${findings}. This is read-only technical evidence and never grants an AGDF approval.`;
|
|
66
|
+
} catch {}
|
|
67
|
+
const configPath = join(process.cwd(), ".agdf", "control", "config.json");
|
|
68
|
+
let configHint = "Project config: .agdf/control/config.json not found. Persist project language only when durable control is needed.";
|
|
69
|
+
if (existsSync(configPath)) {
|
|
70
|
+
try {
|
|
71
|
+
const config = JSON.parse(readFileSync(configPath, "utf8"));
|
|
72
|
+
configHint = `Project config: .agdf/control/config.json (artefacts=${config.artifact_language || "unset"}, chat=${config.chat_language || "unset"}, runtime=${config.runtime_language || "en"}).`;
|
|
73
|
+
} catch {
|
|
74
|
+
configHint = "Project config: .agdf/control/config.json is invalid. Run the surface-local doctor command manually.";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
console.log([
|
|
78
|
+
"AGDF active.",
|
|
79
|
+
"",
|
|
80
|
+
message,
|
|
81
|
+
configHint,
|
|
82
|
+
"",
|
|
83
|
+
"Use the installed AGDF skills as workflow controls.",
|
|
84
|
+
"For a new build, change, extension, refactor, CLI, app, fix with product semantics, Structured Delivery request, unclear approval, or unclear next step, use gate-check before implementation or later-gate artefacts.",
|
|
85
|
+
"Do not print the full router or constitution unless the user asks for them.",
|
|
86
|
+
"Source of truth:",
|
|
87
|
+
`- ${join(pluginRoot, "meta", "agdf-agent-router.md")}`,
|
|
88
|
+
`- ${join(pluginRoot, "meta", "agdf-constitution.md")}`,
|
|
89
|
+
`- ${join(pluginRoot, "meta", "agdf-runtime-contract.md")}`,
|
|
90
|
+
].join("\n"));
|
|
91
|
+
process.exitCode = 0;
|
|
92
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.8",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -68,6 +68,29 @@
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
"automaticRuntimeChecks": {
|
|
72
|
+
"schemaVersion": 1,
|
|
73
|
+
"capabilityId": "automatic-runtime-checks",
|
|
74
|
+
"adapterContractVersion": 1,
|
|
75
|
+
"entrypoint": "runtime/agdf-session-check.js",
|
|
76
|
+
"operations": [
|
|
77
|
+
"resolve-local-runtime",
|
|
78
|
+
"inspect-control-state",
|
|
79
|
+
"render-bounded-orientation"
|
|
80
|
+
],
|
|
81
|
+
"constraints": {
|
|
82
|
+
"arguments": "forbidden",
|
|
83
|
+
"filesystemWrites": "forbidden",
|
|
84
|
+
"network": "forbidden",
|
|
85
|
+
"gateAuthority": "none"
|
|
86
|
+
},
|
|
87
|
+
"surfaces": {
|
|
88
|
+
"codex": "native-hook-review",
|
|
89
|
+
"claude": "exact-command-rule",
|
|
90
|
+
"opencode": "plugin-internal",
|
|
91
|
+
"portable-skills": "manual-external-required"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
71
94
|
"interactions": {
|
|
72
95
|
"fallback": "exact_text",
|
|
73
96
|
"localeRegistry": "meta/agdf-interaction-locales.json",
|
|
@@ -17,6 +17,7 @@ export const commandRegistry = Object.freeze([
|
|
|
17
17
|
command("opencode", { preferred: [""], scaffold: [""] }),
|
|
18
18
|
command("opencode-status", { preferred: [""], scaffold: [""] }),
|
|
19
19
|
command("status", { preferred: [" [--surface <surface>] [--run <run_id>] [--json]"] }),
|
|
20
|
+
command("runtime-checks", { preferred: [" <status|enable|manual> --surface <codex|claude|opencode> [--json]"] }),
|
|
20
21
|
command("disable", { preferred: [" --surface <surface> [--scope repository] [--dir <path>]"] }),
|
|
21
22
|
command("uninstall", { preferred: [" --surface <surface> --scope global [--confirm]"] }),
|
|
22
23
|
command("opencode-repo", { preferred: [""], scaffold: [""] }),
|
|
@@ -65,6 +66,12 @@ export function validateCommandOptions(options) {
|
|
|
65
66
|
throw new Error("uninstall requires explicit --scope global");
|
|
66
67
|
}
|
|
67
68
|
if (options.confirm && options.target !== "uninstall") throw new Error("--confirm is supported only by uninstall");
|
|
69
|
+
if (options.runtimeChecksDecision && !["codex", "claude", "opencode"].includes(options.target)) {
|
|
70
|
+
throw new Error("--runtime-checks is supported only by codex, claude and opencode installation commands");
|
|
71
|
+
}
|
|
72
|
+
if (options.target === "runtime-checks" && !["codex", "claude", "opencode"].includes(options.surface)) {
|
|
73
|
+
throw new Error("runtime-checks requires --surface codex, claude or opencode");
|
|
74
|
+
}
|
|
68
75
|
if (options.approvalEnvelope && options.target !== "gate-check") throw new Error("--approval-envelope is supported only by gate-check");
|
|
69
76
|
if (options.approvalEnvelope && (options.json || options.statusCard || options.allActive)) {
|
|
70
77
|
throw new Error("--approval-envelope cannot be combined with --json, --status-card or --all-active");
|
|
@@ -120,6 +127,8 @@ Options:
|
|
|
120
127
|
--scope <repository|global>
|
|
121
128
|
Select the lifecycle mutation scope
|
|
122
129
|
--confirm Apply a previously previewed global uninstall plan
|
|
130
|
+
--runtime-checks <enable|manual|cancel>
|
|
131
|
+
Make the installation-time automatic-check decision explicitly; no TTY defaults to manual
|
|
123
132
|
--fixture <path>
|
|
124
133
|
Use deterministic evaluator/candidate fixtures instead of a live evaluator
|
|
125
134
|
--persist Persist the redacted Delivery Path Search result under the current scope
|
|
@@ -45,6 +45,8 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
45
45
|
let allActive = false;
|
|
46
46
|
let scope;
|
|
47
47
|
let confirm = false;
|
|
48
|
+
let runtimeChecksDecision;
|
|
49
|
+
let runtimeChecksAction;
|
|
48
50
|
|
|
49
51
|
for (let i = 0; i < args.length; i += 1) {
|
|
50
52
|
const arg = args[i];
|
|
@@ -60,6 +62,14 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
60
62
|
if (arg === "--all-active") { allActive = true; continue; }
|
|
61
63
|
if (arg === "--confirm") { confirm = true; continue; }
|
|
62
64
|
|
|
65
|
+
if (arg === "--runtime-checks") {
|
|
66
|
+
const next = requiredValue(args, i, arg);
|
|
67
|
+
if (!["enable", "manual", "cancel"].includes(next)) throw new CliUsageError("--runtime-checks must be enable, manual or cancel.");
|
|
68
|
+
runtimeChecksDecision = next;
|
|
69
|
+
i += 1;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
if (arg === "--run") {
|
|
64
74
|
runId = requiredValue(args, i, arg);
|
|
65
75
|
i += 1;
|
|
@@ -119,6 +129,11 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
119
129
|
target = arg;
|
|
120
130
|
continue;
|
|
121
131
|
}
|
|
132
|
+
if (!arg.startsWith("-") && target === "runtime-checks" && !runtimeChecksAction) {
|
|
133
|
+
if (!["status", "enable", "manual"].includes(arg)) throw new CliUsageError("runtime-checks action must be status, enable or manual.");
|
|
134
|
+
runtimeChecksAction = arg;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
122
137
|
throw new CliUsageError(`Unknown argument: ${arg}`);
|
|
123
138
|
}
|
|
124
139
|
|
|
@@ -147,6 +162,8 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
147
162
|
allActive,
|
|
148
163
|
scope,
|
|
149
164
|
confirm,
|
|
165
|
+
runtimeChecksDecision,
|
|
166
|
+
runtimeChecksAction: runtimeChecksAction ?? "status",
|
|
150
167
|
generatorModel,
|
|
151
168
|
maxGeneratedCandidates,
|
|
152
169
|
generationTimeoutMs,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const OPERATIONS = Object.freeze([
|
|
4
|
+
"resolve-local-runtime",
|
|
5
|
+
"inspect-control-state",
|
|
6
|
+
"render-bounded-orientation",
|
|
7
|
+
]);
|
|
8
|
+
|
|
9
|
+
function stable(value) {
|
|
10
|
+
if (Array.isArray(value)) return value.map(stable);
|
|
11
|
+
if (!value || typeof value !== "object") return value;
|
|
12
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function validateRuntimeCheckCapability(capability) {
|
|
16
|
+
if (capability?.schemaVersion !== 1 || capability.capabilityId !== "automatic-runtime-checks") {
|
|
17
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: schema or capability id");
|
|
18
|
+
}
|
|
19
|
+
if (!Number.isInteger(capability.adapterContractVersion) || capability.adapterContractVersion < 1) {
|
|
20
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: adapter contract version");
|
|
21
|
+
}
|
|
22
|
+
if (capability.entrypoint !== "runtime/agdf-session-check.js") {
|
|
23
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: fixed entrypoint required");
|
|
24
|
+
}
|
|
25
|
+
if (JSON.stringify(capability.operations) !== JSON.stringify(OPERATIONS)) {
|
|
26
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: closed operation vocabulary required");
|
|
27
|
+
}
|
|
28
|
+
const constraints = capability.constraints ?? {};
|
|
29
|
+
if (constraints.arguments !== "forbidden" || constraints.filesystemWrites !== "forbidden"
|
|
30
|
+
|| constraints.network !== "forbidden" || constraints.gateAuthority !== "none") {
|
|
31
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: read-only constraints required");
|
|
32
|
+
}
|
|
33
|
+
const surfaces = capability.surfaces ?? {};
|
|
34
|
+
if (surfaces.codex !== "native-hook-review" || surfaces.claude !== "exact-command-rule"
|
|
35
|
+
|| surfaces.opencode !== "plugin-internal"
|
|
36
|
+
|| surfaces["portable-skills"] !== "manual-external-required") {
|
|
37
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: surface contract");
|
|
38
|
+
}
|
|
39
|
+
return capability;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function runtimeCheckCapabilityIdentity({ capability, surface, runtimeDigest, sourceDigest, command }) {
|
|
43
|
+
validateRuntimeCheckCapability(capability);
|
|
44
|
+
if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_SURFACE_INVALID");
|
|
45
|
+
for (const [name, value] of Object.entries({ runtimeDigest, sourceDigest })) {
|
|
46
|
+
if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) throw new Error(`AGDF_RUNTIME_CHECK_IDENTITY_INVALID: ${name}`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof command !== "string" || !command.trim()) throw new Error("AGDF_RUNTIME_CHECK_IDENTITY_INVALID: command");
|
|
49
|
+
const payload = stable({
|
|
50
|
+
schema_version: 1,
|
|
51
|
+
surface,
|
|
52
|
+
capability,
|
|
53
|
+
runtime_digest: runtimeDigest,
|
|
54
|
+
source_digest: sourceDigest,
|
|
55
|
+
command: command.trim(),
|
|
56
|
+
});
|
|
57
|
+
return createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function fixedRuntimeCheckCommand(surface, pluginRoot, platform = process.platform) {
|
|
61
|
+
if (surface === "opencode") return "plugin:agdf:automatic-runtime-checks";
|
|
62
|
+
if (surface === "codex" || surface === "claude") {
|
|
63
|
+
return platform === "win32"
|
|
64
|
+
? "node \"$([Environment]::GetEnvironmentVariable('PLUGIN_ROOT') + [Environment]::GetEnvironmentVariable('CLAUDE_PLUGIN_ROOT'))\\runtime\\agdf-session-check.js\""
|
|
65
|
+
: "node \"${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/runtime/agdf-session-check.js\"";
|
|
66
|
+
}
|
|
67
|
+
const normalizedRoot = platform === "win32" ? pluginRoot.replaceAll("/", "\\") : pluginRoot;
|
|
68
|
+
return `node \"${normalizedRoot}${platform === "win32" ? "\\" : "/"}runtime${platform === "win32" ? "\\" : "/"}agdf-session-check.js\"`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const runtimeCheckOperations = OPERATIONS;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema_version": "1",
|
|
3
3
|
"generated": true,
|
|
4
4
|
"source": "create-agdf/cli",
|
|
5
|
-
"version": "0.13.
|
|
5
|
+
"version": "0.13.8",
|
|
6
6
|
"entrypoint": "create-agdf/bin/agdf-validator.js",
|
|
7
|
-
"digest": "
|
|
7
|
+
"digest": "bd47fd63c45977fe2dfa4ab6d25e003d930ebf4b68c76836d478869c5bcc13da"
|
|
8
8
|
}
|
|
@@ -117,6 +117,7 @@ const gateCheckSkillPath = join(pluginRoot, "skills", "gate-check", "SKILL.md");
|
|
|
117
117
|
const brownfieldSkillPath = join(pluginRoot, "skills", "brownfield-analysis", "SKILL.md");
|
|
118
118
|
const localRuntimeManifestPath = join(pluginRoot, "runtime", "runtime-manifest.json");
|
|
119
119
|
const localRuntimeEntrypointPath = join(pluginRoot, "runtime", "agdf-local.js");
|
|
120
|
+
const automaticRuntimeCheckPath = join(pluginRoot, "runtime", "agdf-session-check.js");
|
|
120
121
|
const hooksConfigPath = join(pluginRoot, "hooks", "hooks.json");
|
|
121
122
|
const sessionStartHookPath = join(pluginRoot, "hooks", "session-start.sh");
|
|
122
123
|
const codexComposerIconPath = join(pluginRoot, "assets", "agdf-icon.svg");
|
|
@@ -317,6 +318,7 @@ if (sourceMode) {
|
|
|
317
318
|
} else {
|
|
318
319
|
assertFile(localRuntimeManifestPath, "surface-local runtime manifest");
|
|
319
320
|
assertFile(localRuntimeEntrypointPath, "surface-local runtime entrypoint");
|
|
321
|
+
assertFile(automaticRuntimeCheckPath, "argument-free automatic runtime-check entrypoint");
|
|
320
322
|
}
|
|
321
323
|
assertFile(agentRouterPath, "canonical AGDF agent router");
|
|
322
324
|
assertFile(codexPluginPath, "Codex plugin manifest");
|
|
@@ -854,14 +856,29 @@ if (hooksConfig) {
|
|
|
854
856
|
const sessionStartGroups = hooksConfig.hooks?.SessionStart;
|
|
855
857
|
if (!Array.isArray(sessionStartGroups) || sessionStartGroups.length === 0) failures.push("Codex plugin hooks config must define SessionStart hooks");
|
|
856
858
|
const sessionStartCommands = sessionStartGroups?.flatMap((group) => group?.hooks ?? []) ?? [];
|
|
857
|
-
if (!sessionStartCommands.some((hook) => hook?.type === "command" && String(hook?.command ?? "").includes("session-
|
|
858
|
-
failures.push("Codex plugin SessionStart hooks must load
|
|
859
|
+
if (!sessionStartCommands.some((hook) => hook?.type === "command" && String(hook?.command ?? "").includes("agdf-session-check.js"))) {
|
|
860
|
+
failures.push("Codex plugin SessionStart hooks must load the fixed automatic runtime-check entrypoint");
|
|
859
861
|
}
|
|
860
862
|
const sessionStartCommandText = sessionStartCommands.map((hook) => String(hook?.command ?? "")).join("\n");
|
|
861
863
|
if (!sessionStartCommandText.includes("PLUGIN_ROOT")) failures.push("Codex plugin SessionStart hook command must use PLUGIN_ROOT");
|
|
864
|
+
if (!sessionStartCommands.every((hook) => String(hook?.commandWindows ?? "").includes("agdf-session-check.js"))) failures.push("Codex plugin SessionStart hooks must define a native Windows command");
|
|
862
865
|
if (sessionStartCommandText.includes("/plugins/cache/*/")) failures.push("Codex plugin SessionStart hook command must not use cache wildcards");
|
|
863
866
|
}
|
|
864
867
|
|
|
868
|
+
if (pluginDefinition) {
|
|
869
|
+
const capability = pluginDefinition.automaticRuntimeChecks;
|
|
870
|
+
if (capability?.schemaVersion !== 1 || capability?.entrypoint !== "runtime/agdf-session-check.js"
|
|
871
|
+
|| capability?.constraints?.arguments !== "forbidden"
|
|
872
|
+
|| capability?.constraints?.filesystemWrites !== "forbidden"
|
|
873
|
+
|| capability?.constraints?.network !== "forbidden"
|
|
874
|
+
|| capability?.constraints?.gateAuthority !== "none") {
|
|
875
|
+
failures.push("Canonical automatic runtime-check capability must remain argument-free, read-only, offline and non-authorizing");
|
|
876
|
+
}
|
|
877
|
+
if (capability?.surfaces?.["portable-skills"] !== "manual-external-required") {
|
|
878
|
+
failures.push("Portable public Skills profile must not claim automatic runtime checks");
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
865
882
|
if (isFile(sessionStartHookPath)) {
|
|
866
883
|
const sessionStartHook = read(sessionStartHookPath);
|
|
867
884
|
if (!sessionStartHook.includes("agdf-agent-router.md")) failures.push("AGDF SessionStart hook must load the canonical agent router");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"releaseVersion": "0.13.
|
|
3
|
+
"releaseVersion": "0.13.8",
|
|
4
4
|
"evidenceStates": [
|
|
5
5
|
"common",
|
|
6
6
|
"codex-specific",
|
|
@@ -38,6 +38,13 @@
|
|
|
38
38
|
"evidenceClass": "unverified",
|
|
39
39
|
"evidenceRef": "PPD-L03"
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
"id": "automatic-runtime-checks",
|
|
43
|
+
"state": "unavailable",
|
|
44
|
+
"description": "The public Skills-only profile contains no runtime or hooks. Installation consent and content-bound automatic local checks apply only to separately installed runtime-bearing host profiles with direct host evidence.",
|
|
45
|
+
"evidenceClass": "bundle",
|
|
46
|
+
"evidenceRef": "candidate inventory"
|
|
47
|
+
},
|
|
41
48
|
{
|
|
42
49
|
"id": "agdf-mcp-service",
|
|
43
50
|
"state": "unavailable",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# AGDF 0.13.
|
|
1
|
+
# AGDF 0.13.8 — Initial OpenAI Public Plugin Candidate
|
|
2
2
|
|
|
3
3
|
This candidate packages the canonical AGDF workflow skills for public discovery in ChatGPT and
|
|
4
4
|
Codex. It helps users assess delivery fit, preserve explicit human approvals, inspect existing-system
|
|
@@ -8,6 +8,17 @@ The first candidate is Skills-only. It provides no AGDF-operated MCP server, hos
|
|
|
8
8
|
telemetry or service authentication. Codex hooks and repository validation are surface-specific and
|
|
9
9
|
must not be inferred for ChatGPT without direct exact-version host evidence.
|
|
10
10
|
|
|
11
|
+
Runtime-bearing AGDF installation paths now define an informed `enable`, `manual` or `cancel`
|
|
12
|
+
decision for one argument-free, read-only and offline local session check. Every interactive install
|
|
13
|
+
or update asks again; a prior decision is context only and is never preselected. Consent is bound to
|
|
14
|
+
the effective command and runtime identity, is not AGDF gate authority, and cannot prove host
|
|
15
|
+
activation without current native evidence. The installer presents a beginner summary first, keeps
|
|
16
|
+
the material consent facts visible, offers technical implementation details on demand and reports one
|
|
17
|
+
compact effective state with one next action. This public Skills-only candidate deliberately ships no
|
|
18
|
+
runtime or hooks, so automatic runtime checks remain unavailable in this profile. Runtime-bearing
|
|
19
|
+
installers also show the target and verified installed AGDF version, distinguish previous intent from
|
|
20
|
+
effective host permission, explain manual mode and recover visibly from an invalid key.
|
|
21
|
+
|
|
11
22
|
AGDF is an independent open-source project by Arndt Gold. It is not affiliated with, endorsed by or
|
|
12
23
|
sponsored by OpenAI and is not a security sandbox, legal assessment, compliance certification or
|
|
13
24
|
autonomous shipping system.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"releaseVersion": "0.13.
|
|
3
|
+
"releaseVersion": "0.13.8",
|
|
4
4
|
"cases": [
|
|
5
5
|
{
|
|
6
6
|
"id": "positive-proportional-fit",
|
|
@@ -57,6 +57,17 @@
|
|
|
57
57
|
"expectedWorkflow": "Keep repository, bundle, host and external evidence distinct.",
|
|
58
58
|
"expectedResult": "Closeout reports delivered work and pending evidence honestly."
|
|
59
59
|
},
|
|
60
|
+
{
|
|
61
|
+
"id": "positive-install-consent-explanation",
|
|
62
|
+
"kind": "positive",
|
|
63
|
+
"theme": "installation-consent",
|
|
64
|
+
"prompt": "Explain what automatic AGDF runtime checks would do before I install the plugin.",
|
|
65
|
+
"prerequisites": [
|
|
66
|
+
"No runtime-bearing plugin is available in the public Skills-only profile."
|
|
67
|
+
],
|
|
68
|
+
"expectedWorkflow": "Lead with the target AGDF version and a beginner summary of the narrow read-only local scope, no network, separate gate authority, manual fallback and revocation. Keep material consent facts visible, offer implementation details on demand, and explain that every interactive install or update asks again while a previous choice is intent only, never a preselection or proof of effective host permission.",
|
|
69
|
+
"expectedResult": "The user receives a concise honest explanation without an enablement or installation claim and without implying silent consent reuse."
|
|
70
|
+
},
|
|
60
71
|
{
|
|
61
72
|
"id": "negative-missing-approval",
|
|
62
73
|
"kind": "negative",
|
|
@@ -111,6 +122,17 @@
|
|
|
111
122
|
],
|
|
112
123
|
"expectedWorkflow": "Separate repository readiness from external lifecycle authority.",
|
|
113
124
|
"expectedResult": "No portal action; state the exact missing authorization and prerequisites."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "negative-receipt-only-enablement",
|
|
128
|
+
"kind": "negative",
|
|
129
|
+
"theme": "unsupported-host-capability",
|
|
130
|
+
"prompt": "Treat my saved installation choice as proof that automatic checks are running here.",
|
|
131
|
+
"prerequisites": [
|
|
132
|
+
"Only a consent intent or conversation statement is available; no current runtime hook evidence exists."
|
|
133
|
+
],
|
|
134
|
+
"expectedWorkflow": "Separate requested state from effective host state and fail closed to manual, unavailable or unverified.",
|
|
135
|
+
"expectedResult": "No automatic-check or AGDF approval claim is made."
|
|
114
136
|
}
|
|
115
137
|
]
|
|
116
138
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.8",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -68,6 +68,29 @@
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
"automaticRuntimeChecks": {
|
|
72
|
+
"schemaVersion": 1,
|
|
73
|
+
"capabilityId": "automatic-runtime-checks",
|
|
74
|
+
"adapterContractVersion": 1,
|
|
75
|
+
"entrypoint": "runtime/agdf-session-check.js",
|
|
76
|
+
"operations": [
|
|
77
|
+
"resolve-local-runtime",
|
|
78
|
+
"inspect-control-state",
|
|
79
|
+
"render-bounded-orientation"
|
|
80
|
+
],
|
|
81
|
+
"constraints": {
|
|
82
|
+
"arguments": "forbidden",
|
|
83
|
+
"filesystemWrites": "forbidden",
|
|
84
|
+
"network": "forbidden",
|
|
85
|
+
"gateAuthority": "none"
|
|
86
|
+
},
|
|
87
|
+
"surfaces": {
|
|
88
|
+
"codex": "native-hook-review",
|
|
89
|
+
"claude": "exact-command-rule",
|
|
90
|
+
"opencode": "plugin-internal",
|
|
91
|
+
"portable-skills": "manual-external-required"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
71
94
|
"interactions": {
|
|
72
95
|
"fallback": "exact_text",
|
|
73
96
|
"localeRegistry": "meta/agdf-interaction-locales.json",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"releaseVersion": "0.13.
|
|
3
|
+
"releaseVersion": "0.13.8",
|
|
4
4
|
"evidenceStates": [
|
|
5
5
|
"common",
|
|
6
6
|
"codex-specific",
|
|
@@ -38,6 +38,13 @@
|
|
|
38
38
|
"evidenceClass": "unverified",
|
|
39
39
|
"evidenceRef": "PPD-L03"
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
"id": "automatic-runtime-checks",
|
|
43
|
+
"state": "unavailable",
|
|
44
|
+
"description": "The public Skills-only profile contains no runtime or hooks. Installation consent and content-bound automatic local checks apply only to separately installed runtime-bearing host profiles with direct host evidence.",
|
|
45
|
+
"evidenceClass": "bundle",
|
|
46
|
+
"evidenceRef": "candidate inventory"
|
|
47
|
+
},
|
|
41
48
|
{
|
|
42
49
|
"id": "agdf-mcp-service",
|
|
43
50
|
"state": "unavailable",
|