create-agdf 0.13.7 → 0.14.1
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 +31 -7
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +2 -4
- package/generated/plugins/agdf/hooks/copilot-hooks.json +15 -0
- package/generated/plugins/agdf/hooks/hooks.json +3 -2
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +44 -2
- package/generated/plugins/agdf/plugin.json +22 -0
- package/generated/plugins/agdf/runtime/agdf-local.js +1 -1
- package/generated/plugins/agdf/runtime/agdf-session-check.js +97 -0
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +44 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +10 -2
- 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 +73 -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 +50 -5
- 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 -2
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +44 -2
- 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 +291 -20
- package/lib/cli/command-registry.js +10 -2
- package/lib/cli/parse-args.js +17 -0
- package/lib/installers/copilot-precedence.js +34 -0
- package/lib/installers/copilot-settings.js +84 -0
- package/lib/installers/local-marketplace.js +2 -0
- package/lib/installers/opencode.js +21 -5
- package/lib/installers/plugin-installers.js +155 -4
- package/lib/lifecycle/operations.js +3 -0
- package/lib/lifecycle/presentation.js +43 -2
- package/lib/lifecycle/result.js +10 -0
- package/lib/lifecycle/status.js +7 -3
- package/lib/public-plugin/manifest.js +34 -2
- package/lib/public-plugin/validator.js +1 -1
- package/lib/release/version-coherence.js +1 -0
- 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 +73 -0
- package/lib/runtime-check-consent/coordinator.js +38 -0
- package/lib/runtime-check-consent/service.js +181 -0
- package/lib/runtime-check-consent/state.js +90 -0
- package/lib/scaffold/plan.js +3 -89
- package/lib/scaffold/presentation.js +3 -22
- package/opencode-plugin.js +30 -15
- 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/AGENTS.md +0 -113
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-brownfield-analysis/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-clean-implementation-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-code-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-delivery-closeout/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-delivery-path-search/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-gate-check/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-interaction-locales.json +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-qa-gate/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-release-or/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-runtime-contract.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-task-plan-review/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/agdf-ux-intent-definition/SKILL.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/closeout.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/context-graph.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/control-scaffold.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/gate-transition.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/interaction.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/modes.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/quality.md +0 -0
- /package/generated/{.github/skills → plugins/agdf/copilot-skills}/contracts/task-target-resolution.md +0 -0
package/README.md
CHANGED
|
@@ -24,11 +24,36 @@ Use a different target when Codex is not your agent surface:
|
|
|
24
24
|
| Surface or goal | Start with | What it gives you |
|
|
25
25
|
|---|---|---|
|
|
26
26
|
| Claude Code | `npx --yes @agdf/cli@latest claude` | The AGDF plugin for Claude Code. |
|
|
27
|
+
| GitHub Copilot | `npx --yes @agdf/cli@latest copilot` | The AGDF plugin with prefixed skills and a consent-bound session hook. |
|
|
27
28
|
| OpenCode, user-wide discovery | `npx --yes @agdf/cli@latest opencode` | The npm plugin and global native skills; repository governance remains opt-in. |
|
|
28
29
|
| OpenCode, one repository | `npx --yes @agdf/cli@latest opencode-repo` | Durable control configuration that activates the once-installed global runtime. |
|
|
29
|
-
| GitHub Copilot | `npx --yes @agdf/cli@latest copilot` | Repository instructions, visible skills and control templates. |
|
|
30
30
|
| Durable control state in an existing setup | `npx --yes @agdf/cli@latest init` | Live `.agdf/control/` state when the repository explicitly needs it. |
|
|
31
31
|
|
|
32
|
+
The runtime-bearing `codex`, `claude`, `copilot` and `opencode` installers ask before enabling narrow automatic
|
|
33
|
+
local checks on an interactive terminal. The choices are `enable`, `manual` and `cancel`; enablement
|
|
34
|
+
is never preselected. Every interactive installation or update asks again. A previous choice is
|
|
35
|
+
shown only as intent, never as proof of effective host permission. The prompt shows the target AGDF
|
|
36
|
+
version and the result shows the verified installed version or transition. Matching capability
|
|
37
|
+
identity may preserve host-native trust, but it never
|
|
38
|
+
suppresses the installer choice. Non-interactive installation defaults to manual unless the exact
|
|
39
|
+
option is provided:
|
|
40
|
+
|
|
41
|
+
Interactive terminals accept `1` or `E` for enable, `2` or `M` for manual, `D` for technical
|
|
42
|
+
details and `Esc` for immediate cancel without Enter. The primary choice uses beginner-safe language,
|
|
43
|
+
keeps the material consent facts visible and has no preselected option. Manual mode explains that
|
|
44
|
+
AGDF remains available on request; invalid keys redisplay the valid choices.
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npx --yes @agdf/cli@latest claude --runtime-checks enable
|
|
48
|
+
npx --yes @agdf/cli@latest runtime-checks status --surface claude --json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The check is argument-free, read-only and offline. Consent is content-bound, reversible and separate
|
|
52
|
+
from AGDF gate approval. A receipt alone never proves effective host permission. Codex native trust,
|
|
53
|
+
Claude deny/ask precedence and all explicit OpenCode permissions remain authoritative. The public
|
|
54
|
+
Skills-only OpenAI candidate has no runtime or hooks and therefore remains manual/external for this
|
|
55
|
+
capability.
|
|
56
|
+
|
|
32
57
|
For prerequisites, all surface-specific flows and operational boundaries, use the authoritative [installation guide](../INSTALL.md). Do not run `init` merely to ask a fresh question: an agent can first clarify the request and ask for `Approval: UR` when durable control state is needed.
|
|
33
58
|
|
|
34
59
|
## Command overview
|
|
@@ -41,6 +66,7 @@ Installation, activation and explicit lifecycle changes:
|
|
|
41
66
|
npx --yes @agdf/cli@latest codex
|
|
42
67
|
npx --yes @agdf/cli@latest codex-repo
|
|
43
68
|
npx --yes @agdf/cli@latest claude
|
|
69
|
+
npx --yes @agdf/cli@latest copilot
|
|
44
70
|
npx --yes @agdf/cli@latest opencode
|
|
45
71
|
npx --yes @agdf/cli@latest opencode-status
|
|
46
72
|
npx --yes @agdf/cli@latest opencode-repo
|
|
@@ -79,11 +105,9 @@ Backward-compatible scaffold usage:
|
|
|
79
105
|
npm create agdf@latest -- codex
|
|
80
106
|
npm create agdf@latest -- codex-repo
|
|
81
107
|
npm create agdf@latest -- claude
|
|
82
|
-
npm create agdf@latest -- copilot
|
|
83
108
|
npm create agdf@latest -- opencode
|
|
84
109
|
npm create agdf@latest -- opencode-status
|
|
85
110
|
npm create agdf@latest -- opencode-repo
|
|
86
|
-
npm create agdf@latest -- both
|
|
87
111
|
npm create agdf@latest -- init
|
|
88
112
|
npm create agdf@latest -- config --language en
|
|
89
113
|
npm create agdf@latest -- doctor
|
|
@@ -113,17 +137,17 @@ it does not localize the CLI lifecycle card.
|
|
|
113
137
|
- `codex` installs the AGDF plugin globally for Codex
|
|
114
138
|
- `codex-repo` writes a repository-local Codex marketplace under `.agents/plugins/` and a local AGDF plugin copy under `plugins/agdf/`
|
|
115
139
|
- `claude` installs the AGDF plugin globally for Claude Code
|
|
116
|
-
- `copilot`
|
|
140
|
+
- `copilot` registers the AGDF-owned local Marketplace and installs `agdf@agdf` through Copilot CLI; when `copilot` is not on `PATH`, it runs the pinned official `@github/copilot` CLI package through npm, then verifies AGDF in Copilot's own plugin list
|
|
117
141
|
- `opencode` installs the AGDF npm plugin and ten native skills as a user-wide OpenCode surface
|
|
118
142
|
- `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
143
|
- `status` reports installation, repository activation and delivery separately without mutating state
|
|
144
|
+
- `runtime-checks status|enable|manual` reports the requested/effective automatic-check state or gives the exact reinstall route needed to change it
|
|
120
145
|
- `disable` writes a supported repository-local opt-out while retaining global capability and durable control state
|
|
121
146
|
- `uninstall` previews and, only with `--confirm`, applies a selected global removal through supported native/owned operations
|
|
122
147
|
- `opencode-repo` writes durable AGDF control configuration and templates under `.agdf/control/`; it does not copy a second OpenCode runtime surface
|
|
123
|
-
- `both` writes the Codex repository-local marketplace plus the Copilot-facing repository files
|
|
124
148
|
- `config` writes or updates only `.agdf/control/config.json` for an already installed plugin or an existing repository
|
|
125
149
|
|
|
126
|
-
The `codex` and `
|
|
150
|
+
The `codex`, `claude` and `copilot` commands install from the complete plugin built into the released
|
|
127
151
|
`create-agdf` package. They atomically stage it under an AGDF-owned user-data marketplace, register
|
|
128
152
|
that stable local path through the host CLI and verify the exposed version. Source `plugin/` therefore
|
|
129
153
|
contains no generated runtime bytes and the source checkout exposes no installable root marketplace.
|
|
@@ -133,7 +157,7 @@ checkout, npm cache, PATH or registry. Rerunning either command performs the exp
|
|
|
133
157
|
migrates only the exact known legacy AGDF GitHub marketplace; foreign same-name registrations fail
|
|
134
158
|
closed and failed host operations restore the prior owned stage.
|
|
135
159
|
|
|
136
|
-
|
|
160
|
+
The Copilot installer does not create, rewrite or remove repository files. Existing `AGENTS.md`, `.github/` and `.agdf/control/` content remains untouched. Use `init` separately when a repository should own surface-neutral durable AGDF control state.
|
|
137
161
|
|
|
138
162
|
Use the `codex-repo` target when AGDF should be available only inside one repository instead of being installed as a personal/global Codex plugin.
|
|
139
163
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
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.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Arndt Gold",
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"websiteURL": "https://agdf.iself.eu",
|
|
31
31
|
"privacyPolicyURL": "https://agdf.iself.eu/privacy",
|
|
32
32
|
"termsOfServiceURL": "https://agdf.iself.eu/terms",
|
|
33
|
-
"supportURL": "https://agdf.iself.eu/support",
|
|
34
33
|
"composerIcon": "./assets/agdf-icon.svg",
|
|
35
34
|
"logo": "./assets/agdf-logo.svg",
|
|
36
35
|
"defaultPrompt": [
|
|
@@ -39,6 +38,5 @@
|
|
|
39
38
|
"Close this delivery run with an auditable AGDF report."
|
|
40
39
|
],
|
|
41
40
|
"brandColor": "#14B8A6"
|
|
42
|
-
}
|
|
43
|
-
"hooks": "./hooks/hooks.json"
|
|
41
|
+
}
|
|
44
42
|
}
|
|
@@ -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.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -50,7 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"copilot": {
|
|
52
52
|
"skillPrefix": "agdf-",
|
|
53
|
-
"runtimeContractFileName": "agdf-runtime-contract.md"
|
|
53
|
+
"runtimeContractFileName": "agdf-runtime-contract.md",
|
|
54
|
+
"pluginManifest": "plugin.json",
|
|
55
|
+
"skills": "copilot-skills/",
|
|
56
|
+
"hooks": "hooks/copilot-hooks.json"
|
|
54
57
|
},
|
|
55
58
|
"opencode": {
|
|
56
59
|
"skillPrefix": "agdf-",
|
|
@@ -68,6 +71,30 @@
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
},
|
|
74
|
+
"automaticRuntimeChecks": {
|
|
75
|
+
"schemaVersion": 1,
|
|
76
|
+
"capabilityId": "automatic-runtime-checks",
|
|
77
|
+
"adapterContractVersion": 1,
|
|
78
|
+
"entrypoint": "runtime/agdf-session-check.js",
|
|
79
|
+
"operations": [
|
|
80
|
+
"resolve-local-runtime",
|
|
81
|
+
"inspect-control-state",
|
|
82
|
+
"render-bounded-orientation"
|
|
83
|
+
],
|
|
84
|
+
"constraints": {
|
|
85
|
+
"arguments": "forbidden",
|
|
86
|
+
"filesystemWrites": "forbidden",
|
|
87
|
+
"network": "forbidden",
|
|
88
|
+
"gateAuthority": "none"
|
|
89
|
+
},
|
|
90
|
+
"surfaces": {
|
|
91
|
+
"codex": "native-hook-review",
|
|
92
|
+
"claude": "exact-command-rule",
|
|
93
|
+
"copilot": "plugin-hook-review",
|
|
94
|
+
"opencode": "plugin-internal",
|
|
95
|
+
"portable-skills": "manual-external-required"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
71
98
|
"interactions": {
|
|
72
99
|
"fallback": "exact_text",
|
|
73
100
|
"localeRegistry": "meta/agdf-interaction-locales.json",
|
|
@@ -120,6 +147,21 @@
|
|
|
120
147
|
"authorizationPath": "exact_text",
|
|
121
148
|
"technicalPermissionOwner": "claude_host"
|
|
122
149
|
},
|
|
150
|
+
"copilot": {
|
|
151
|
+
"questionAdapter": "exact_text",
|
|
152
|
+
"availability": "always",
|
|
153
|
+
"gateSafety": "wait_for_deliberate_user_input",
|
|
154
|
+
"explicitOutcomes": [
|
|
155
|
+
"approve",
|
|
156
|
+
"revise",
|
|
157
|
+
"decline",
|
|
158
|
+
"cancel"
|
|
159
|
+
],
|
|
160
|
+
"approvalValueTransport": "exact_option_value",
|
|
161
|
+
"waitSafety": "deliberate_no_auto_resolution",
|
|
162
|
+
"authorizationPath": "exact_text",
|
|
163
|
+
"technicalPermissionOwner": "copilot_host"
|
|
164
|
+
},
|
|
123
165
|
"opencode": {
|
|
124
166
|
"questionAdapter": "question",
|
|
125
167
|
"availability": "when_permission_question_allows",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agdf",
|
|
3
|
+
"version": "0.14.1",
|
|
4
|
+
"description": "Control layer for governed AI-assisted delivery.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Arndt Gold",
|
|
7
|
+
"url": "https://agdf.iself.eu"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://agdf.iself.eu",
|
|
10
|
+
"repository": "https://github.com/arndtgold/ai-native-governance-delivery-framework",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"agentic",
|
|
14
|
+
"governance",
|
|
15
|
+
"delivery",
|
|
16
|
+
"ai-native",
|
|
17
|
+
"brownfield"
|
|
18
|
+
],
|
|
19
|
+
"category": "Productivity",
|
|
20
|
+
"skills": "copilot-skills/",
|
|
21
|
+
"hooks": "hooks/copilot-hooks.json"
|
|
22
|
+
}
|
|
@@ -12,7 +12,7 @@ const manifest = JSON.parse(readFileSync(new URL("./runtime-manifest.json", impo
|
|
|
12
12
|
process.exitCode = runLocalValidator({
|
|
13
13
|
runtimeRoot,
|
|
14
14
|
pluginRoot,
|
|
15
|
-
expectedPluginRoot: process.env.CLAUDE_PLUGIN_ROOT || undefined,
|
|
15
|
+
expectedPluginRoot: process.env.CLAUDE_PLUGIN_ROOT || process.env.PLUGIN_ROOT || undefined,
|
|
16
16
|
expectedVersion: manifest.version,
|
|
17
17
|
surface: process.env.AGDF_SURFACE || "plugin",
|
|
18
18
|
}, process.argv.slice(2));
|
|
@@ -0,0 +1,97 @@
|
|
|
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.COPILOT_PLUGIN_DATA ? "copilot" : 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", "copilot", "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", "copilot"].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
|
+
const additionalContext = [
|
|
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
|
+
if (surface === "copilot") {
|
|
92
|
+
console.log(JSON.stringify({ additionalContext }));
|
|
93
|
+
} else {
|
|
94
|
+
console.log(additionalContext);
|
|
95
|
+
}
|
|
96
|
+
process.exitCode = 0;
|
|
97
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "agdf",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"displayName": "AI Governance & Delivery Framework",
|
|
6
6
|
"developerName": "Arndt Gold",
|
|
7
7
|
"description": "Control layer for governed AI-assisted delivery.",
|
|
@@ -50,7 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"copilot": {
|
|
52
52
|
"skillPrefix": "agdf-",
|
|
53
|
-
"runtimeContractFileName": "agdf-runtime-contract.md"
|
|
53
|
+
"runtimeContractFileName": "agdf-runtime-contract.md",
|
|
54
|
+
"pluginManifest": "plugin.json",
|
|
55
|
+
"skills": "copilot-skills/",
|
|
56
|
+
"hooks": "hooks/copilot-hooks.json"
|
|
54
57
|
},
|
|
55
58
|
"opencode": {
|
|
56
59
|
"skillPrefix": "agdf-",
|
|
@@ -68,6 +71,30 @@
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
},
|
|
74
|
+
"automaticRuntimeChecks": {
|
|
75
|
+
"schemaVersion": 1,
|
|
76
|
+
"capabilityId": "automatic-runtime-checks",
|
|
77
|
+
"adapterContractVersion": 1,
|
|
78
|
+
"entrypoint": "runtime/agdf-session-check.js",
|
|
79
|
+
"operations": [
|
|
80
|
+
"resolve-local-runtime",
|
|
81
|
+
"inspect-control-state",
|
|
82
|
+
"render-bounded-orientation"
|
|
83
|
+
],
|
|
84
|
+
"constraints": {
|
|
85
|
+
"arguments": "forbidden",
|
|
86
|
+
"filesystemWrites": "forbidden",
|
|
87
|
+
"network": "forbidden",
|
|
88
|
+
"gateAuthority": "none"
|
|
89
|
+
},
|
|
90
|
+
"surfaces": {
|
|
91
|
+
"codex": "native-hook-review",
|
|
92
|
+
"claude": "exact-command-rule",
|
|
93
|
+
"copilot": "plugin-hook-review",
|
|
94
|
+
"opencode": "plugin-internal",
|
|
95
|
+
"portable-skills": "manual-external-required"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
71
98
|
"interactions": {
|
|
72
99
|
"fallback": "exact_text",
|
|
73
100
|
"localeRegistry": "meta/agdf-interaction-locales.json",
|
|
@@ -120,6 +147,21 @@
|
|
|
120
147
|
"authorizationPath": "exact_text",
|
|
121
148
|
"technicalPermissionOwner": "claude_host"
|
|
122
149
|
},
|
|
150
|
+
"copilot": {
|
|
151
|
+
"questionAdapter": "exact_text",
|
|
152
|
+
"availability": "always",
|
|
153
|
+
"gateSafety": "wait_for_deliberate_user_input",
|
|
154
|
+
"explicitOutcomes": [
|
|
155
|
+
"approve",
|
|
156
|
+
"revise",
|
|
157
|
+
"decline",
|
|
158
|
+
"cancel"
|
|
159
|
+
],
|
|
160
|
+
"approvalValueTransport": "exact_option_value",
|
|
161
|
+
"waitSafety": "deliberate_no_auto_resolution",
|
|
162
|
+
"authorizationPath": "exact_text",
|
|
163
|
+
"technicalPermissionOwner": "copilot_host"
|
|
164
|
+
},
|
|
123
165
|
"opencode": {
|
|
124
166
|
"questionAdapter": "question",
|
|
125
167
|
"availability": "when_permission_question_allows",
|
|
@@ -13,14 +13,14 @@ export const commandRegistry = Object.freeze([
|
|
|
13
13
|
command("codex", { preferred: [""], scaffold: [""] }),
|
|
14
14
|
command("codex-repo", { preferred: [""], scaffold: [""] }),
|
|
15
15
|
command("claude", { preferred: [""], scaffold: [""] }),
|
|
16
|
-
command("copilot", { preferred: [""]
|
|
16
|
+
command("copilot", { preferred: [""] }),
|
|
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|copilot|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: [""] }),
|
|
23
|
-
command("both", { scaffold: [""] }),
|
|
24
24
|
command("init", { preferred: [""], scaffold: [""] }),
|
|
25
25
|
command("config", { scaffold: [" --language de"] }),
|
|
26
26
|
command("doctor", { local: [""], scaffold: [""], legacy: [" --json"] }),
|
|
@@ -65,6 +65,12 @@ export function validateCommandOptions(options) {
|
|
|
65
65
|
throw new Error("uninstall requires explicit --scope global");
|
|
66
66
|
}
|
|
67
67
|
if (options.confirm && options.target !== "uninstall") throw new Error("--confirm is supported only by uninstall");
|
|
68
|
+
if (options.runtimeChecksDecision && !["codex", "claude", "copilot", "opencode"].includes(options.target)) {
|
|
69
|
+
throw new Error("--runtime-checks is supported only by codex, claude, copilot and opencode installation commands");
|
|
70
|
+
}
|
|
71
|
+
if (options.target === "runtime-checks" && !["codex", "claude", "copilot", "opencode"].includes(options.surface)) {
|
|
72
|
+
throw new Error("runtime-checks requires --surface codex, claude, copilot or opencode");
|
|
73
|
+
}
|
|
68
74
|
if (options.approvalEnvelope && options.target !== "gate-check") throw new Error("--approval-envelope is supported only by gate-check");
|
|
69
75
|
if (options.approvalEnvelope && (options.json || options.statusCard || options.allActive)) {
|
|
70
76
|
throw new Error("--approval-envelope cannot be combined with --json, --status-card or --all-active");
|
|
@@ -120,6 +126,8 @@ Options:
|
|
|
120
126
|
--scope <repository|global>
|
|
121
127
|
Select the lifecycle mutation scope
|
|
122
128
|
--confirm Apply a previously previewed global uninstall plan
|
|
129
|
+
--runtime-checks <enable|manual|cancel>
|
|
130
|
+
Make the installation-time automatic-check decision explicitly; no TTY defaults to manual
|
|
123
131
|
--fixture <path>
|
|
124
132
|
Use deterministic evaluator/candidate fixtures instead of a live evaluator
|
|
125
133
|
--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,73 @@
|
|
|
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.copilot !== "plugin-hook-review"
|
|
36
|
+
|| surfaces.opencode !== "plugin-internal"
|
|
37
|
+
|| surfaces["portable-skills"] !== "manual-external-required") {
|
|
38
|
+
throw new Error("AGDF_RUNTIME_CHECK_CAPABILITY_INVALID: surface contract");
|
|
39
|
+
}
|
|
40
|
+
return capability;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function runtimeCheckCapabilityIdentity({ capability, surface, runtimeDigest, sourceDigest, command }) {
|
|
44
|
+
validateRuntimeCheckCapability(capability);
|
|
45
|
+
if (!["codex", "claude", "copilot", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_SURFACE_INVALID");
|
|
46
|
+
for (const [name, value] of Object.entries({ runtimeDigest, sourceDigest })) {
|
|
47
|
+
if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) throw new Error(`AGDF_RUNTIME_CHECK_IDENTITY_INVALID: ${name}`);
|
|
48
|
+
}
|
|
49
|
+
if (typeof command !== "string" || !command.trim()) throw new Error("AGDF_RUNTIME_CHECK_IDENTITY_INVALID: command");
|
|
50
|
+
const payload = stable({
|
|
51
|
+
schema_version: 1,
|
|
52
|
+
surface,
|
|
53
|
+
capability,
|
|
54
|
+
runtime_digest: runtimeDigest,
|
|
55
|
+
source_digest: sourceDigest,
|
|
56
|
+
command: command.trim(),
|
|
57
|
+
});
|
|
58
|
+
return createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function fixedRuntimeCheckCommand(surface, pluginRoot, platform = process.platform) {
|
|
62
|
+
if (surface === "opencode") return "plugin:agdf:automatic-runtime-checks";
|
|
63
|
+
if (surface === "copilot") return 'node "${PLUGIN_ROOT}/runtime/agdf-session-check.js"';
|
|
64
|
+
if (surface === "codex" || surface === "claude") {
|
|
65
|
+
return platform === "win32"
|
|
66
|
+
? "node \"$([Environment]::GetEnvironmentVariable('PLUGIN_ROOT') + [Environment]::GetEnvironmentVariable('CLAUDE_PLUGIN_ROOT'))\\runtime\\agdf-session-check.js\""
|
|
67
|
+
: "node \"${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/runtime/agdf-session-check.js\"";
|
|
68
|
+
}
|
|
69
|
+
const normalizedRoot = platform === "win32" ? pluginRoot.replaceAll("/", "\\") : pluginRoot;
|
|
70
|
+
return `node \"${normalizedRoot}${platform === "win32" ? "\\" : "/"}runtime${platform === "win32" ? "\\" : "/"}agdf-session-check.js\"`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
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.
|
|
5
|
+
"version": "0.14.1",
|
|
6
6
|
"entrypoint": "create-agdf/bin/agdf-validator.js",
|
|
7
|
-
"digest": "
|
|
7
|
+
"digest": "724174653ad423b30654aa64a34e1699a18cc67037172c10aa249d1d61087116"
|
|
8
8
|
}
|