create-agdf 0.9.3 → 0.9.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 +11 -1
- package/generated/.github/skills/agdf-gate-check/SKILL.md +5 -0
- package/generated/.github/skills/agdf-interaction-locales.json +36 -0
- package/generated/.github/skills/contracts/interaction.md +9 -1
- package/generated/.opencode/agdf-interaction-locales.json +36 -0
- package/generated/.opencode/contracts/interaction.md +9 -1
- package/generated/.opencode/skills/agdf-gate-check/SKILL.md +5 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-interaction-locales.json +36 -0
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/contracts/interaction.md +9 -1
- package/generated/plugins/agdf/skills/gate-check/SKILL.md +5 -0
- package/lib/cli/application.js +168 -17
- package/lib/cli/command-registry.js +21 -3
- package/lib/cli/parse-args.js +9 -1
- package/lib/installers/opencode.js +31 -7
- package/lib/installers/plugin-installers.js +60 -31
- package/lib/lifecycle/operations.js +177 -0
- package/lib/lifecycle/presentation.js +52 -0
- package/lib/lifecycle/result.js +69 -0
- package/lib/lifecycle/status.js +108 -0
- package/lib/scaffold/presentation.js +25 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Use a different target when Codex is not your agent surface:
|
|
|
21
21
|
| Claude Code | `npx --yes @agdf/cli@latest claude` | The AGDF plugin for Claude Code. |
|
|
22
22
|
| OpenCode, user-wide discovery | `npx --yes @agdf/cli@latest opencode` | The npm plugin and global native skills; repository governance remains opt-in. |
|
|
23
23
|
| OpenCode, one repository | `npx --yes @agdf/cli@latest opencode-repo` | Repository instructions, native skills, permissions and control templates. |
|
|
24
|
-
| GitHub Copilot | `
|
|
24
|
+
| GitHub Copilot | `npx --yes @agdf/cli@latest copilot` | Repository instructions, visible skills and control templates. |
|
|
25
25
|
| Durable control state in an existing setup | `npx --yes @agdf/cli@latest init` | Live `.agdf/control/` state when the repository explicitly needs it. |
|
|
26
26
|
|
|
27
27
|
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.
|
|
@@ -39,6 +39,9 @@ npx --yes @agdf/cli@latest claude
|
|
|
39
39
|
npx --yes @agdf/cli@latest opencode
|
|
40
40
|
npx --yes @agdf/cli@latest opencode-status
|
|
41
41
|
npx --yes @agdf/cli@latest opencode-repo
|
|
42
|
+
npx --yes @agdf/cli@latest status --surface codex
|
|
43
|
+
npx --yes @agdf/cli@latest disable --surface codex --scope repository
|
|
44
|
+
npx --yes @agdf/cli@latest uninstall --surface codex --scope global
|
|
42
45
|
npx --yes @agdf/cli@latest init
|
|
43
46
|
npx --yes @agdf/cli@latest config --language en
|
|
44
47
|
npx --yes @agdf/cli@latest doctor
|
|
@@ -62,6 +65,8 @@ npx --yes @agdf/cli@latest run-migrate [--run <run_id>]
|
|
|
62
65
|
npx --yes @agdf/cli@latest run-render-legacy --run <run_id>
|
|
63
66
|
```
|
|
64
67
|
|
|
68
|
+
### Advanced / Compatibility
|
|
69
|
+
|
|
65
70
|
Backward-compatible scaffold usage:
|
|
66
71
|
|
|
67
72
|
```bash
|
|
@@ -87,6 +92,8 @@ Optional flags:
|
|
|
87
92
|
- `--dir <path>` write into a specific directory
|
|
88
93
|
- `--force` overwrite existing generated files
|
|
89
94
|
- `--language <tag>` or `--lang <tag>` persist a BCP 47 language tag such as `de`, `en` or `fr-CA`
|
|
95
|
+
- `--scope <repository|global>` select an explicit lifecycle mutation scope
|
|
96
|
+
- `--confirm` apply a global uninstall after reviewing the default non-mutating preview
|
|
90
97
|
|
|
91
98
|
If no language is provided, `create-agdf` derives the preference from the local system locale (`LC_ALL`, `LC_MESSAGES`, `LANG`, `LANGUAGE` or the Node.js runtime locale) and falls back to `en`.
|
|
92
99
|
|
|
@@ -98,6 +105,9 @@ If no language is provided, `create-agdf` derives the preference from the local
|
|
|
98
105
|
- `copilot` writes `AGENTS.md`, Copilot custom instructions under `.github/`, visible repository skills under `.github/skills/`, and AGDF control templates under `.agdf/control/`
|
|
99
106
|
- `opencode` installs the AGDF npm plugin and nine native skills as a user-wide OpenCode surface
|
|
100
107
|
- `opencode-status` reports OpenCode global config, package loadability, global native-skill completeness, session signals and repository surface presence
|
|
108
|
+
- `status` reports installation, repository activation and delivery separately without mutating state
|
|
109
|
+
- `disable` writes a supported repository-local opt-out while retaining global capability and durable control state
|
|
110
|
+
- `uninstall` previews and, only with `--confirm`, applies a selected global removal through supported native/owned operations
|
|
101
111
|
- `opencode-repo` writes `opencode.json`, `.opencode/AGDF.md`, prefixed native OpenCode skills under `.opencode/skills/`, explicit question/edit/bash/skill permissions, and AGDF control templates under `.agdf/control/`
|
|
102
112
|
- `both` writes the Codex repository-local marketplace plus the Copilot-facing repository files
|
|
103
113
|
- `config` writes or updates only `.agdf/control/config.json` for an already installed plugin or an existing repository
|
|
@@ -64,6 +64,11 @@ Use the Runtime Contract's Native Interaction Contract to classify every candida
|
|
|
64
64
|
|
|
65
65
|
Prefer inspection over asking. Do not invoke a structured question for status reporting, facts available in the repository, routine read-only work or a gate that is not ready. Do not repeatedly prompt for the same non-ready gate.
|
|
66
66
|
|
|
67
|
+
For a fresh request classified as read-only with no required run decision, emit the locale pack's
|
|
68
|
+
`primary.readOnlyOrientationDescription` sentence once before the findings. This path creates no run, persists
|
|
69
|
+
nothing, requests no approval and reuses the existing status projection. Do not repeat the sentence
|
|
70
|
+
during the same request.
|
|
71
|
+
|
|
67
72
|
For a ready `gate_approval`:
|
|
68
73
|
|
|
69
74
|
1. Resolve exactly one selected run and evaluate the current gate.
|
|
@@ -109,6 +109,24 @@
|
|
|
109
109
|
"notYetCreated": "not yet created"
|
|
110
110
|
},
|
|
111
111
|
"primary": {
|
|
112
|
+
"readOnlyOrientationDescription": "Read-only check — no new AGDF run and no approval required.",
|
|
113
|
+
"lifecycleResult": {
|
|
114
|
+
"title": "AGDF lifecycle result",
|
|
115
|
+
"statusTitle": "AGDF status",
|
|
116
|
+
"result": "Result",
|
|
117
|
+
"surface": "Surface",
|
|
118
|
+
"scope": "Installation scope",
|
|
119
|
+
"version": "AGDF version",
|
|
120
|
+
"verification": "Verification",
|
|
121
|
+
"restart": "Restart required",
|
|
122
|
+
"installation": "Installation",
|
|
123
|
+
"repository": "Repository",
|
|
124
|
+
"delivery": "Delivery",
|
|
125
|
+
"next": "Next action",
|
|
126
|
+
"yes": "yes",
|
|
127
|
+
"no": "no",
|
|
128
|
+
"unknown": "unknown"
|
|
129
|
+
},
|
|
112
130
|
"status": {
|
|
113
131
|
"open": "open",
|
|
114
132
|
"blocked": "blocked",
|
|
@@ -278,6 +296,24 @@
|
|
|
278
296
|
"notYetCreated": "noch nicht erstellt"
|
|
279
297
|
},
|
|
280
298
|
"primary": {
|
|
299
|
+
"readOnlyOrientationDescription": "Read-only Prüfung – kein neuer AGDF-Run und keine Freigabe erforderlich.",
|
|
300
|
+
"lifecycleResult": {
|
|
301
|
+
"title": "AGDF-Lifecycle-Ergebnis",
|
|
302
|
+
"statusTitle": "AGDF-Status",
|
|
303
|
+
"result": "Ergebnis",
|
|
304
|
+
"surface": "Oberfläche",
|
|
305
|
+
"scope": "Installationsscope",
|
|
306
|
+
"version": "AGDF-Version",
|
|
307
|
+
"verification": "Verifikation",
|
|
308
|
+
"restart": "Neustart erforderlich",
|
|
309
|
+
"installation": "Installation",
|
|
310
|
+
"repository": "Repository",
|
|
311
|
+
"delivery": "Delivery",
|
|
312
|
+
"next": "Nächste Aktion",
|
|
313
|
+
"yes": "ja",
|
|
314
|
+
"no": "nein",
|
|
315
|
+
"unknown": "unbekannt"
|
|
316
|
+
},
|
|
281
317
|
"status": {
|
|
282
318
|
"open": "offen",
|
|
283
319
|
"blocked": "blockiert",
|
|
@@ -274,6 +274,15 @@ Surface adapter rules:
|
|
|
274
274
|
|
|
275
275
|
Native structured questions are for real decision points. Prefer repository inspection over clarification and do not show them for status reporting, discoverable facts, routine read-only work or repeated non-ready gate prompts.
|
|
276
276
|
|
|
277
|
+
### Read-only request orientation
|
|
278
|
+
|
|
279
|
+
For a newly classified read-only request that does not require a run decision, render the localized
|
|
280
|
+
`primary.readOnlyOrientationDescription` sentence exactly once before the findings. This is a visible
|
|
281
|
+
orientation, not durable state: do not create a run, write control files, request gate approval or
|
|
282
|
+
repeat the sentence later in the same request. Existing-run status inspection remains read-only and
|
|
283
|
+
uses the existing status projection; this branch must not create a second status-card or narration
|
|
284
|
+
owner.
|
|
285
|
+
|
|
277
286
|
Exact textual approvals remain canonical and fully supported on every surface. If native capability availability or safety is unknown, use the textual fallback. Host permission, plan approval, native question presentation, timeout/default behavior, hook output and agent messages never carry AGDF gate authority by themselves.
|
|
278
287
|
|
|
279
288
|
### Interaction Locale Contract
|
|
@@ -367,4 +376,3 @@ Missing input, timeout, cancellation and empty input are not decline. Only
|
|
|
367
376
|
`approve` backed by the exact revalidated `Approval: <GateName>` value may
|
|
368
377
|
advance a gate. Clarification, blocked, internal-step and status-only
|
|
369
378
|
interactions must not display gate-approval controls.
|
|
370
|
-
|
|
@@ -109,6 +109,24 @@
|
|
|
109
109
|
"notYetCreated": "not yet created"
|
|
110
110
|
},
|
|
111
111
|
"primary": {
|
|
112
|
+
"readOnlyOrientationDescription": "Read-only check — no new AGDF run and no approval required.",
|
|
113
|
+
"lifecycleResult": {
|
|
114
|
+
"title": "AGDF lifecycle result",
|
|
115
|
+
"statusTitle": "AGDF status",
|
|
116
|
+
"result": "Result",
|
|
117
|
+
"surface": "Surface",
|
|
118
|
+
"scope": "Installation scope",
|
|
119
|
+
"version": "AGDF version",
|
|
120
|
+
"verification": "Verification",
|
|
121
|
+
"restart": "Restart required",
|
|
122
|
+
"installation": "Installation",
|
|
123
|
+
"repository": "Repository",
|
|
124
|
+
"delivery": "Delivery",
|
|
125
|
+
"next": "Next action",
|
|
126
|
+
"yes": "yes",
|
|
127
|
+
"no": "no",
|
|
128
|
+
"unknown": "unknown"
|
|
129
|
+
},
|
|
112
130
|
"status": {
|
|
113
131
|
"open": "open",
|
|
114
132
|
"blocked": "blocked",
|
|
@@ -278,6 +296,24 @@
|
|
|
278
296
|
"notYetCreated": "noch nicht erstellt"
|
|
279
297
|
},
|
|
280
298
|
"primary": {
|
|
299
|
+
"readOnlyOrientationDescription": "Read-only Prüfung – kein neuer AGDF-Run und keine Freigabe erforderlich.",
|
|
300
|
+
"lifecycleResult": {
|
|
301
|
+
"title": "AGDF-Lifecycle-Ergebnis",
|
|
302
|
+
"statusTitle": "AGDF-Status",
|
|
303
|
+
"result": "Ergebnis",
|
|
304
|
+
"surface": "Oberfläche",
|
|
305
|
+
"scope": "Installationsscope",
|
|
306
|
+
"version": "AGDF-Version",
|
|
307
|
+
"verification": "Verifikation",
|
|
308
|
+
"restart": "Neustart erforderlich",
|
|
309
|
+
"installation": "Installation",
|
|
310
|
+
"repository": "Repository",
|
|
311
|
+
"delivery": "Delivery",
|
|
312
|
+
"next": "Nächste Aktion",
|
|
313
|
+
"yes": "ja",
|
|
314
|
+
"no": "nein",
|
|
315
|
+
"unknown": "unbekannt"
|
|
316
|
+
},
|
|
281
317
|
"status": {
|
|
282
318
|
"open": "offen",
|
|
283
319
|
"blocked": "blockiert",
|
|
@@ -274,6 +274,15 @@ Surface adapter rules:
|
|
|
274
274
|
|
|
275
275
|
Native structured questions are for real decision points. Prefer repository inspection over clarification and do not show them for status reporting, discoverable facts, routine read-only work or repeated non-ready gate prompts.
|
|
276
276
|
|
|
277
|
+
### Read-only request orientation
|
|
278
|
+
|
|
279
|
+
For a newly classified read-only request that does not require a run decision, render the localized
|
|
280
|
+
`primary.readOnlyOrientationDescription` sentence exactly once before the findings. This is a visible
|
|
281
|
+
orientation, not durable state: do not create a run, write control files, request gate approval or
|
|
282
|
+
repeat the sentence later in the same request. Existing-run status inspection remains read-only and
|
|
283
|
+
uses the existing status projection; this branch must not create a second status-card or narration
|
|
284
|
+
owner.
|
|
285
|
+
|
|
277
286
|
Exact textual approvals remain canonical and fully supported on every surface. If native capability availability or safety is unknown, use the textual fallback. Host permission, plan approval, native question presentation, timeout/default behavior, hook output and agent messages never carry AGDF gate authority by themselves.
|
|
278
287
|
|
|
279
288
|
### Interaction Locale Contract
|
|
@@ -367,4 +376,3 @@ Missing input, timeout, cancellation and empty input are not decline. Only
|
|
|
367
376
|
`approve` backed by the exact revalidated `Approval: <GateName>` value may
|
|
368
377
|
advance a gate. Clarification, blocked, internal-step and status-only
|
|
369
378
|
interactions must not display gate-approval controls.
|
|
370
|
-
|
|
@@ -64,6 +64,11 @@ Use the Runtime Contract's Native Interaction Contract to classify every candida
|
|
|
64
64
|
|
|
65
65
|
Prefer inspection over asking. Do not invoke a structured question for status reporting, facts available in the repository, routine read-only work or a gate that is not ready. Do not repeatedly prompt for the same non-ready gate.
|
|
66
66
|
|
|
67
|
+
For a fresh request classified as read-only with no required run decision, emit the locale pack's
|
|
68
|
+
`primary.readOnlyOrientationDescription` sentence once before the findings. This path creates no run, persists
|
|
69
|
+
nothing, requests no approval and reuses the existing status projection. Do not repeat the sentence
|
|
70
|
+
during the same request.
|
|
71
|
+
|
|
67
72
|
For a ready `gate_approval`:
|
|
68
73
|
|
|
69
74
|
1. Resolve exactly one selected run and evaluate the current gate.
|
|
@@ -109,6 +109,24 @@
|
|
|
109
109
|
"notYetCreated": "not yet created"
|
|
110
110
|
},
|
|
111
111
|
"primary": {
|
|
112
|
+
"readOnlyOrientationDescription": "Read-only check — no new AGDF run and no approval required.",
|
|
113
|
+
"lifecycleResult": {
|
|
114
|
+
"title": "AGDF lifecycle result",
|
|
115
|
+
"statusTitle": "AGDF status",
|
|
116
|
+
"result": "Result",
|
|
117
|
+
"surface": "Surface",
|
|
118
|
+
"scope": "Installation scope",
|
|
119
|
+
"version": "AGDF version",
|
|
120
|
+
"verification": "Verification",
|
|
121
|
+
"restart": "Restart required",
|
|
122
|
+
"installation": "Installation",
|
|
123
|
+
"repository": "Repository",
|
|
124
|
+
"delivery": "Delivery",
|
|
125
|
+
"next": "Next action",
|
|
126
|
+
"yes": "yes",
|
|
127
|
+
"no": "no",
|
|
128
|
+
"unknown": "unknown"
|
|
129
|
+
},
|
|
112
130
|
"status": {
|
|
113
131
|
"open": "open",
|
|
114
132
|
"blocked": "blocked",
|
|
@@ -278,6 +296,24 @@
|
|
|
278
296
|
"notYetCreated": "noch nicht erstellt"
|
|
279
297
|
},
|
|
280
298
|
"primary": {
|
|
299
|
+
"readOnlyOrientationDescription": "Read-only Prüfung – kein neuer AGDF-Run und keine Freigabe erforderlich.",
|
|
300
|
+
"lifecycleResult": {
|
|
301
|
+
"title": "AGDF-Lifecycle-Ergebnis",
|
|
302
|
+
"statusTitle": "AGDF-Status",
|
|
303
|
+
"result": "Ergebnis",
|
|
304
|
+
"surface": "Oberfläche",
|
|
305
|
+
"scope": "Installationsscope",
|
|
306
|
+
"version": "AGDF-Version",
|
|
307
|
+
"verification": "Verifikation",
|
|
308
|
+
"restart": "Neustart erforderlich",
|
|
309
|
+
"installation": "Installation",
|
|
310
|
+
"repository": "Repository",
|
|
311
|
+
"delivery": "Delivery",
|
|
312
|
+
"next": "Nächste Aktion",
|
|
313
|
+
"yes": "ja",
|
|
314
|
+
"no": "nein",
|
|
315
|
+
"unknown": "unbekannt"
|
|
316
|
+
},
|
|
281
317
|
"status": {
|
|
282
318
|
"open": "offen",
|
|
283
319
|
"blocked": "blockiert",
|
|
@@ -274,6 +274,15 @@ Surface adapter rules:
|
|
|
274
274
|
|
|
275
275
|
Native structured questions are for real decision points. Prefer repository inspection over clarification and do not show them for status reporting, discoverable facts, routine read-only work or repeated non-ready gate prompts.
|
|
276
276
|
|
|
277
|
+
### Read-only request orientation
|
|
278
|
+
|
|
279
|
+
For a newly classified read-only request that does not require a run decision, render the localized
|
|
280
|
+
`primary.readOnlyOrientationDescription` sentence exactly once before the findings. This is a visible
|
|
281
|
+
orientation, not durable state: do not create a run, write control files, request gate approval or
|
|
282
|
+
repeat the sentence later in the same request. Existing-run status inspection remains read-only and
|
|
283
|
+
uses the existing status projection; this branch must not create a second status-card or narration
|
|
284
|
+
owner.
|
|
285
|
+
|
|
277
286
|
Exact textual approvals remain canonical and fully supported on every surface. If native capability availability or safety is unknown, use the textual fallback. Host permission, plan approval, native question presentation, timeout/default behavior, hook output and agent messages never carry AGDF gate authority by themselves.
|
|
278
287
|
|
|
279
288
|
### Interaction Locale Contract
|
|
@@ -367,4 +376,3 @@ Missing input, timeout, cancellation and empty input are not decline. Only
|
|
|
367
376
|
`approve` backed by the exact revalidated `Approval: <GateName>` value may
|
|
368
377
|
advance a gate. Clarification, blocked, internal-step and status-only
|
|
369
378
|
interactions must not display gate-approval controls.
|
|
370
|
-
|
|
@@ -64,6 +64,11 @@ Use the Runtime Contract's Native Interaction Contract to classify every candida
|
|
|
64
64
|
|
|
65
65
|
Prefer inspection over asking. Do not invoke a structured question for status reporting, facts available in the repository, routine read-only work or a gate that is not ready. Do not repeatedly prompt for the same non-ready gate.
|
|
66
66
|
|
|
67
|
+
For a fresh request classified as read-only with no required run decision, emit the locale pack's
|
|
68
|
+
`primary.readOnlyOrientationDescription` sentence once before the findings. This path creates no run, persists
|
|
69
|
+
nothing, requests no approval and reuses the existing status projection. Do not repeat the sentence
|
|
70
|
+
during the same request.
|
|
71
|
+
|
|
67
72
|
For a ready `gate_approval`:
|
|
68
73
|
|
|
69
74
|
1. Resolve exactly one selected run and evaluate the current gate.
|
package/lib/cli/application.js
CHANGED
|
@@ -28,6 +28,16 @@ import {
|
|
|
28
28
|
installClaudeGlobalPlugin,
|
|
29
29
|
installCodexGlobalPlugin,
|
|
30
30
|
} from "../installers/plugin-installers.js";
|
|
31
|
+
import {
|
|
32
|
+
applyLifecyclePlan,
|
|
33
|
+
planGlobalUninstall,
|
|
34
|
+
planRepositoryDisable,
|
|
35
|
+
verifyGlobalUninstall,
|
|
36
|
+
verifyRepositoryDisabled,
|
|
37
|
+
} from "../lifecycle/operations.js";
|
|
38
|
+
import { printGeneralStatus, printLifecycleResult } from "../lifecycle/presentation.js";
|
|
39
|
+
import { createLifecycleResult, lifecycleFailure } from "../lifecycle/result.js";
|
|
40
|
+
import { evaluateGeneralStatus } from "../lifecycle/status.js";
|
|
31
41
|
import { agdfFragmentPath, generatedFilesForTarget, openCodeConfigFragmentPath } from "../scaffold/plan.js";
|
|
32
42
|
import { printNextSteps } from "../scaffold/presentation.js";
|
|
33
43
|
import { assertGeneratedWritePlan, removeOwnedLegacyOpenCodeAgents, writeGeneratedFile } from "../scaffold/write.js";
|
|
@@ -96,45 +106,186 @@ function createHandlers({ io, env, exec }) {
|
|
|
96
106
|
printOpenCodeStatus(report, options.json, io);
|
|
97
107
|
return report.status === "configured" ? 0 : 1;
|
|
98
108
|
}],
|
|
99
|
-
["
|
|
109
|
+
["status", (options) => {
|
|
110
|
+
const report = evaluateGeneralStatus(options.dir, {
|
|
111
|
+
...options,
|
|
112
|
+
configDir: env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir(),
|
|
113
|
+
}, { exec });
|
|
114
|
+
printGeneralStatus(report, { json: options.json, locale: options.language.chat_language, io });
|
|
115
|
+
return report.installation.status === "healthy" ? 0 : 1;
|
|
116
|
+
}],
|
|
117
|
+
["disable", (options) => runDisable(options, { io, exec })],
|
|
118
|
+
["uninstall", (options) => runUninstall(options, { io, env, exec })],
|
|
119
|
+
["codex", (options) => {
|
|
100
120
|
try {
|
|
101
|
-
installCodexGlobalPlugin(installerAdapters);
|
|
102
|
-
|
|
103
|
-
|
|
121
|
+
const installed = installCodexGlobalPlugin(installerAdapters);
|
|
122
|
+
printLifecycleResult(installResult(installed, {
|
|
123
|
+
restartRequired: true,
|
|
124
|
+
nextAction: "Restart Codex, then run npx --yes @agdf/cli@latest codex-repo in a repository where AGDF should be active.",
|
|
125
|
+
}), { json: options.json, locale: options.language.chat_language, io });
|
|
104
126
|
return 0;
|
|
105
127
|
} catch (error) {
|
|
106
|
-
|
|
128
|
+
printInstallFailure("codex", error, options, io);
|
|
107
129
|
return 1;
|
|
108
130
|
}
|
|
109
131
|
}],
|
|
110
|
-
["claude", () => {
|
|
132
|
+
["claude", (options) => {
|
|
111
133
|
try {
|
|
112
|
-
installClaudeGlobalPlugin(installerAdapters);
|
|
113
|
-
|
|
134
|
+
const installed = installClaudeGlobalPlugin(installerAdapters);
|
|
135
|
+
printLifecycleResult(installResult(installed, {
|
|
136
|
+
restartRequired: true,
|
|
137
|
+
nextAction: "Restart Claude Code, then verify the plugin in a new session.",
|
|
138
|
+
}), { json: options.json, locale: options.language.chat_language, io });
|
|
114
139
|
return 0;
|
|
115
140
|
} catch (error) {
|
|
116
|
-
|
|
141
|
+
printInstallFailure("claude", error, options, io);
|
|
117
142
|
return 1;
|
|
118
143
|
}
|
|
119
144
|
}],
|
|
120
145
|
["opencode", (options) => {
|
|
121
146
|
const configDir = options.dirExplicit ? options.dir : defaultOpenCodeConfigDir();
|
|
122
147
|
try {
|
|
123
|
-
const result = installOpenCodeGlobalPlugin(configDir);
|
|
124
|
-
installOpenCodeGlobalSurface(configDir);
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
const result = runLifecyclePhase("plugin_operation", () => installOpenCodeGlobalPlugin(configDir));
|
|
149
|
+
runLifecyclePhase("global_surface", () => installOpenCodeGlobalSurface(configDir));
|
|
150
|
+
const report = runLifecyclePhase("verification", () => evaluateOpenCodeStatus(options.dir, configDir, result.transition));
|
|
151
|
+
const verificationHealthy = report.status === "configured"
|
|
152
|
+
&& report.package.version_status === "current"
|
|
153
|
+
&& report.global_native_surface.complete;
|
|
154
|
+
printLifecycleResult(createLifecycleResult({
|
|
155
|
+
operation: result.transition.status === "updated" ? "update" : "install",
|
|
156
|
+
result: verificationHealthy ? "success" : "partial",
|
|
157
|
+
surface: "opencode",
|
|
158
|
+
scope: "global",
|
|
159
|
+
version: {
|
|
160
|
+
expected: report.package.expected_version,
|
|
161
|
+
installed: report.package.installed_version,
|
|
162
|
+
previous: result.transition.previous_version,
|
|
163
|
+
status: report.package.version_status === "current" ? "verified" : "unknown",
|
|
164
|
+
transition: result.transition.status,
|
|
165
|
+
},
|
|
166
|
+
verification: { status: verificationHealthy ? "healthy" : "degraded", evidence: [report.global_config.path, report.global_native_surface.path] },
|
|
167
|
+
restart: { required: true, reason: "host_reload" },
|
|
168
|
+
next_action: { kind: "restart", text: "Restart OpenCode so it loads the updated global plugin config." },
|
|
169
|
+
}), { json: options.json, locale: options.language.chat_language, io });
|
|
170
|
+
return verificationHealthy ? 0 : 1;
|
|
130
171
|
} catch (error) {
|
|
131
|
-
|
|
172
|
+
printInstallFailure("opencode", error, options, io);
|
|
132
173
|
return 1;
|
|
133
174
|
}
|
|
134
175
|
}],
|
|
135
176
|
]);
|
|
136
177
|
}
|
|
137
178
|
|
|
179
|
+
function runLifecyclePhase(phase, operation) {
|
|
180
|
+
try {
|
|
181
|
+
return operation();
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (!error.phase) error.phase = phase;
|
|
184
|
+
if (!error.evidence) error.evidence = {};
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function installResult(installed, { restartRequired, nextAction }) {
|
|
190
|
+
return createLifecycleResult({
|
|
191
|
+
operation: "install",
|
|
192
|
+
result: "success",
|
|
193
|
+
surface: installed.surface,
|
|
194
|
+
scope: "global",
|
|
195
|
+
version: { expected: installed.expectedVersion, installed: installed.installedVersion, status: installed.installedVersion ? "verified" : "unknown" },
|
|
196
|
+
verification: { status: installed.verificationStatus, evidence: installed.evidence },
|
|
197
|
+
restart: { required: restartRequired, reason: restartRequired ? "host_reload" : "none" },
|
|
198
|
+
next_action: { kind: restartRequired ? "restart" : "prompt", text: nextAction },
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function printInstallFailure(surface, error, options, io) {
|
|
203
|
+
const report = lifecycleFailure({
|
|
204
|
+
operation: "install",
|
|
205
|
+
surface,
|
|
206
|
+
scope: "global",
|
|
207
|
+
phase: error.phase || "plugin_operation",
|
|
208
|
+
message: error.message,
|
|
209
|
+
evidence: [error.evidence ?? {}],
|
|
210
|
+
nextAction: `Resolve the ${error.phase || "plugin operation"} failure and rerun npx --yes @agdf/cli@latest ${surface}.`,
|
|
211
|
+
});
|
|
212
|
+
if (options.json) printLifecycleResult(report, { json: true, io });
|
|
213
|
+
else {
|
|
214
|
+
io.error(error.message);
|
|
215
|
+
printLifecycleResult(report, { locale: options.language.chat_language, io });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function runDisable(options, { io, exec }) {
|
|
220
|
+
try {
|
|
221
|
+
const plan = planRepositoryDisable(options.dir, options.surface);
|
|
222
|
+
const applied = applyLifecyclePlan(plan, exec ? { exec } : {});
|
|
223
|
+
const verified = applied.status === "success" ? verifyRepositoryDisabled(options.dir) : { status: "failed", evidence: [] };
|
|
224
|
+
const result = applied.status === "success" && verified.status !== "healthy" ? "failed" : applied.status;
|
|
225
|
+
const report = createLifecycleResult({
|
|
226
|
+
operation: "disable",
|
|
227
|
+
result,
|
|
228
|
+
surface: options.surface,
|
|
229
|
+
scope: "repository",
|
|
230
|
+
verification: { status: verified.status === "healthy" ? "healthy" : "degraded", evidence: [...applied.completed.map((item) => item.path || item.executable), ...verified.evidence] },
|
|
231
|
+
restart: { required: result === "success", reason: result === "success" ? "host_reload" : "none" },
|
|
232
|
+
next_action: result === "success"
|
|
233
|
+
? { kind: "restart", text: "Restart the host in this repository; global AGDF availability and .agdf/control are retained." }
|
|
234
|
+
: { kind: "verify", text: "Inspect the reported repository configuration failure before retrying disable." },
|
|
235
|
+
changes: applied.completed,
|
|
236
|
+
retained: applied.retained,
|
|
237
|
+
failure: applied.error
|
|
238
|
+
? { phase: "repository_configuration", message: applied.error.message }
|
|
239
|
+
: result === "failed" ? { phase: "verification", message: "Repository disable postcondition was not observed." } : null,
|
|
240
|
+
});
|
|
241
|
+
printLifecycleResult(report, { json: options.json, locale: options.language.chat_language, io });
|
|
242
|
+
return result === "success" ? 0 : 1;
|
|
243
|
+
} catch (error) {
|
|
244
|
+
io.error(error.message);
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function runUninstall(options, { io, env, exec }) {
|
|
250
|
+
try {
|
|
251
|
+
const configDir = env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir();
|
|
252
|
+
const plan = planGlobalUninstall(options.surface, { configDir });
|
|
253
|
+
if (!options.confirm) {
|
|
254
|
+
const preview = createLifecycleResult({
|
|
255
|
+
operation: "uninstall", result: "preview", surface: options.surface, scope: "global",
|
|
256
|
+
verification: { status: "unknown", evidence: ["non_mutating_preview"] },
|
|
257
|
+
restart: { required: false },
|
|
258
|
+
next_action: { kind: "confirm", text: `Review this preview, then rerun with --surface ${options.surface} --scope global --confirm; ownership is revalidated before apply.` },
|
|
259
|
+
changes: plan.mutations, retained: plan.retained,
|
|
260
|
+
});
|
|
261
|
+
printLifecycleResult(preview, { json: options.json, locale: options.language.chat_language, io });
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
const applied = applyLifecyclePlan(plan, exec ? { exec } : {});
|
|
265
|
+
const verified = applied.status === "success"
|
|
266
|
+
? verifyGlobalUninstall(plan, options.dir, { configDir, exec })
|
|
267
|
+
: { status: "failed", evidence: [] };
|
|
268
|
+
const result = applied.status === "success" && verified.status !== "healthy" ? "failed" : applied.status;
|
|
269
|
+
const report = createLifecycleResult({
|
|
270
|
+
operation: "uninstall", result, surface: options.surface, scope: "global",
|
|
271
|
+
verification: { status: verified.status === "healthy" ? "healthy" : "degraded", evidence: [...applied.completed.map((item) => item.path || item.executable), ...verified.evidence] },
|
|
272
|
+
restart: { required: result === "success", reason: result === "success" ? "host_reload" : "none" },
|
|
273
|
+
next_action: result === "success"
|
|
274
|
+
? { kind: "restart", text: "Restart the host; the uninstall postcondition has already been verified." }
|
|
275
|
+
: { kind: "verify", text: "Inspect the reported uninstall or verification failure before retrying." },
|
|
276
|
+
changes: applied.completed, retained: applied.retained,
|
|
277
|
+
failure: applied.error
|
|
278
|
+
? { phase: "plugin_operation", message: applied.error.message }
|
|
279
|
+
: result === "failed" ? { phase: "verification", message: "Global uninstall postcondition was not observed." } : null,
|
|
280
|
+
});
|
|
281
|
+
printLifecycleResult(report, { json: options.json, locale: options.language.chat_language, io });
|
|
282
|
+
return result === "success" ? 0 : 1;
|
|
283
|
+
} catch (error) {
|
|
284
|
+
io.error(error.message);
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
138
289
|
function runScaffold(options, io) {
|
|
139
290
|
const files = generatedFilesForTarget(options.target, options.dir, options.force, options.language);
|
|
140
291
|
const wroteAgentsFragment = files.some((file) => file.path === agdfFragmentPath);
|
|
@@ -13,9 +13,12 @@ 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", { scaffold: [""] }),
|
|
16
|
+
command("copilot", { preferred: [""], scaffold: [""] }),
|
|
17
17
|
command("opencode", { preferred: [""], scaffold: [""] }),
|
|
18
18
|
command("opencode-status", { preferred: [""], scaffold: [""] }),
|
|
19
|
+
command("status", { preferred: [" [--surface <surface>] [--run <run_id>] [--json]"] }),
|
|
20
|
+
command("disable", { preferred: [" --surface <surface> [--scope repository] [--dir <path>]"] }),
|
|
21
|
+
command("uninstall", { preferred: [" --surface <surface> --scope global [--confirm]"] }),
|
|
19
22
|
command("opencode-repo", { preferred: [""], scaffold: [""] }),
|
|
20
23
|
command("both", { scaffold: [""] }),
|
|
21
24
|
command("init", { preferred: [""], scaffold: [""] }),
|
|
@@ -52,6 +55,16 @@ export function validateCommandOptions(options) {
|
|
|
52
55
|
if (options.target === "run-render-legacy" && !options.runId) {
|
|
53
56
|
throw new Error("run-render-legacy requires --run");
|
|
54
57
|
}
|
|
58
|
+
if (["disable", "uninstall"].includes(options.target) && ["", "generic", undefined].includes(options.surface)) {
|
|
59
|
+
throw new Error(`${options.target} requires an explicit --surface`);
|
|
60
|
+
}
|
|
61
|
+
if (options.target === "disable" && options.scope && options.scope !== "repository") {
|
|
62
|
+
throw new Error("disable supports repository scope only");
|
|
63
|
+
}
|
|
64
|
+
if (options.target === "uninstall" && options.scope !== "global") {
|
|
65
|
+
throw new Error("uninstall requires explicit --scope global");
|
|
66
|
+
}
|
|
67
|
+
if (options.confirm && options.target !== "uninstall") throw new Error("--confirm is supported only by uninstall");
|
|
55
68
|
return options;
|
|
56
69
|
}
|
|
57
70
|
|
|
@@ -62,11 +75,13 @@ function usageLines(group, prefix) {
|
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
export function renderUsage() {
|
|
65
|
-
return `
|
|
78
|
+
return `AGDF CLI
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
Primary commands:
|
|
68
81
|
${usageLines("preferred", "npx --yes @agdf/cli@latest ")}
|
|
69
82
|
|
|
83
|
+
Advanced / Compatibility
|
|
84
|
+
|
|
70
85
|
Scaffold-compatible npm create usage:
|
|
71
86
|
${usageLines("scaffold", "npm create agdf@latest -- ")}
|
|
72
87
|
|
|
@@ -85,6 +100,9 @@ Options:
|
|
|
85
100
|
--all-active Evaluate every active run (doctor and delivery-map only)
|
|
86
101
|
--surface <codex|claude|copilot|opencode|generic>
|
|
87
102
|
Declare the active Delivery Path Search surface
|
|
103
|
+
--scope <repository|global>
|
|
104
|
+
Select the lifecycle mutation scope
|
|
105
|
+
--confirm Apply a previously previewed global uninstall plan
|
|
88
106
|
--fixture <path>
|
|
89
107
|
Use deterministic evaluator/candidate fixtures instead of a live evaluator
|
|
90
108
|
--persist Persist the redacted Delivery Path Search result under the current scope
|
package/lib/cli/parse-args.js
CHANGED
|
@@ -41,6 +41,8 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
41
41
|
let generationCostUnits = 5;
|
|
42
42
|
let runId;
|
|
43
43
|
let allActive = false;
|
|
44
|
+
let scope;
|
|
45
|
+
let confirm = false;
|
|
44
46
|
|
|
45
47
|
for (let i = 0; i < args.length; i += 1) {
|
|
46
48
|
const arg = args[i];
|
|
@@ -52,6 +54,7 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
52
54
|
if (arg === "--persist") { persist = true; continue; }
|
|
53
55
|
if (arg === "--generate-candidates") { generateCandidates = true; continue; }
|
|
54
56
|
if (arg === "--all-active") { allActive = true; continue; }
|
|
57
|
+
if (arg === "--confirm") { confirm = true; continue; }
|
|
55
58
|
|
|
56
59
|
if (arg === "--run") {
|
|
57
60
|
runId = requiredValue(args, i, arg);
|
|
@@ -59,13 +62,16 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
59
62
|
continue;
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
if (["--surface", "--fixture", "--model", "--generator-model", "--max-generated-candidates", "--generation-timeout-ms", "--generation-cost-units"].includes(arg)) {
|
|
65
|
+
if (["--surface", "--scope", "--fixture", "--model", "--generator-model", "--max-generated-candidates", "--generation-timeout-ms", "--generation-cost-units"].includes(arg)) {
|
|
63
66
|
const next = requiredValue(args, i, arg);
|
|
64
67
|
if (arg === "--surface") {
|
|
65
68
|
if (!["codex", "claude", "copilot", "opencode", "generic"].includes(next)) {
|
|
66
69
|
throw new CliUsageError("Unsupported surface. Use codex, claude, copilot, opencode or generic.");
|
|
67
70
|
}
|
|
68
71
|
surface = next;
|
|
72
|
+
} else if (arg === "--scope") {
|
|
73
|
+
if (!["repository", "global"].includes(next)) throw new CliUsageError("Unsupported scope. Use repository or global.");
|
|
74
|
+
scope = next;
|
|
69
75
|
} else if (arg === "--fixture") fixture = next;
|
|
70
76
|
else if (arg === "--model") model = next;
|
|
71
77
|
else if (arg === "--generator-model") generatorModel = next;
|
|
@@ -133,6 +139,8 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
133
139
|
generateCandidates,
|
|
134
140
|
runId,
|
|
135
141
|
allActive,
|
|
142
|
+
scope,
|
|
143
|
+
confirm,
|
|
136
144
|
generatorModel,
|
|
137
145
|
maxGeneratedCandidates,
|
|
138
146
|
generationTimeoutMs,
|