create-agdf 0.9.6 → 0.9.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 +5 -0
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/lib/cli/application.js +28 -17
- package/lib/cli/command-registry.js +1 -0
- package/lib/cli/parse-args.js +3 -0
- package/lib/installers/plugin-installers.js +14 -7
- package/lib/lifecycle/presentation.js +32 -24
- package/lib/lifecycle/result.js +22 -1
- package/lib/scaffold/presentation.js +38 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,11 +92,16 @@ Optional flags:
|
|
|
92
92
|
- `--dir <path>` write into a specific directory
|
|
93
93
|
- `--force` overwrite existing generated files
|
|
94
94
|
- `--language <tag>` or `--lang <tag>` persist a BCP 47 language tag such as `de`, `en` or `fr-CA`
|
|
95
|
+
- `--verbose` show captured host installer output and generated-file details after the concise lifecycle card
|
|
95
96
|
- `--scope <repository|global>` select an explicit lifecycle mutation scope
|
|
96
97
|
- `--confirm` apply a global uninstall after reviewing the default non-mutating preview
|
|
97
98
|
|
|
98
99
|
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`.
|
|
99
100
|
|
|
101
|
+
Lifecycle cards and CLI-owned status labels are always English so they remain comparable across
|
|
102
|
+
machines and coding agents. `--language` continues to control project chat and artefact language;
|
|
103
|
+
it does not localize the CLI lifecycle card.
|
|
104
|
+
|
|
100
105
|
## Targets and existing AGENTS.md
|
|
101
106
|
|
|
102
107
|
- `codex` installs the AGDF plugin globally for Codex
|
package/lib/cli/application.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
verifyRepositoryDisabled,
|
|
37
37
|
} from "../lifecycle/operations.js";
|
|
38
38
|
import { printGeneralStatus, printLifecycleResult } from "../lifecycle/presentation.js";
|
|
39
|
-
import { createLifecycleResult, lifecycleFailure } from "../lifecycle/result.js";
|
|
39
|
+
import { createLifecycleResult, globalInstallRestartAction, lifecycleFailure } from "../lifecycle/result.js";
|
|
40
40
|
import { evaluateGeneralStatus } from "../lifecycle/status.js";
|
|
41
41
|
import { agdfFragmentPath, generatedFilesForTarget, openCodeConfigFragmentPath } from "../scaffold/plan.js";
|
|
42
42
|
import { printNextSteps } from "../scaffold/presentation.js";
|
|
@@ -111,7 +111,7 @@ function createHandlers({ io, env, exec }) {
|
|
|
111
111
|
...options,
|
|
112
112
|
configDir: env.OPENCODE_CONFIG_DIR || defaultOpenCodeConfigDir(),
|
|
113
113
|
}, { exec });
|
|
114
|
-
printGeneralStatus(report, { json: options.json,
|
|
114
|
+
printGeneralStatus(report, { json: options.json, io });
|
|
115
115
|
return report.installation.status === "healthy" ? 0 : 1;
|
|
116
116
|
}],
|
|
117
117
|
["disable", (options) => runDisable(options, { io, exec })],
|
|
@@ -121,11 +121,12 @@ function createHandlers({ io, env, exec }) {
|
|
|
121
121
|
const installed = installCodexGlobalPlugin(installerAdapters);
|
|
122
122
|
printLifecycleResult(installResult(installed, {
|
|
123
123
|
restartRequired: true,
|
|
124
|
-
nextAction:
|
|
125
|
-
}), { json: options.json,
|
|
124
|
+
nextAction: globalInstallRestartAction(options.target).text,
|
|
125
|
+
}), { json: options.json, io });
|
|
126
|
+
printVerboseHostOutput(installed, options, io);
|
|
126
127
|
return 0;
|
|
127
128
|
} catch (error) {
|
|
128
|
-
printInstallFailure(
|
|
129
|
+
printInstallFailure(options.target, error, options, io);
|
|
129
130
|
return 1;
|
|
130
131
|
}
|
|
131
132
|
}],
|
|
@@ -134,11 +135,12 @@ function createHandlers({ io, env, exec }) {
|
|
|
134
135
|
const installed = installClaudeGlobalPlugin(installerAdapters);
|
|
135
136
|
printLifecycleResult(installResult(installed, {
|
|
136
137
|
restartRequired: true,
|
|
137
|
-
nextAction:
|
|
138
|
-
}), { json: options.json,
|
|
138
|
+
nextAction: globalInstallRestartAction(options.target).text,
|
|
139
|
+
}), { json: options.json, io });
|
|
140
|
+
printVerboseHostOutput(installed, options, io);
|
|
139
141
|
return 0;
|
|
140
142
|
} catch (error) {
|
|
141
|
-
printInstallFailure(
|
|
143
|
+
printInstallFailure(options.target, error, options, io);
|
|
142
144
|
return 1;
|
|
143
145
|
}
|
|
144
146
|
}],
|
|
@@ -154,7 +156,7 @@ function createHandlers({ io, env, exec }) {
|
|
|
154
156
|
printLifecycleResult(createLifecycleResult({
|
|
155
157
|
operation: result.transition.status === "updated" ? "update" : "install",
|
|
156
158
|
result: verificationHealthy ? "success" : "partial",
|
|
157
|
-
surface:
|
|
159
|
+
surface: options.target,
|
|
158
160
|
scope: "global",
|
|
159
161
|
version: {
|
|
160
162
|
expected: report.package.expected_version,
|
|
@@ -165,11 +167,11 @@ function createHandlers({ io, env, exec }) {
|
|
|
165
167
|
},
|
|
166
168
|
verification: { status: verificationHealthy ? "healthy" : "degraded", evidence: [report.global_config.path, report.global_native_surface.path] },
|
|
167
169
|
restart: { required: true, reason: "host_reload" },
|
|
168
|
-
next_action:
|
|
169
|
-
}), { json: options.json,
|
|
170
|
+
next_action: globalInstallRestartAction(options.target),
|
|
171
|
+
}), { json: options.json, io });
|
|
170
172
|
return verificationHealthy ? 0 : 1;
|
|
171
173
|
} catch (error) {
|
|
172
|
-
printInstallFailure(
|
|
174
|
+
printInstallFailure(options.target, error, options, io);
|
|
173
175
|
return 1;
|
|
174
176
|
}
|
|
175
177
|
}],
|
|
@@ -194,11 +196,20 @@ function installResult(installed, { restartRequired, nextAction }) {
|
|
|
194
196
|
scope: "global",
|
|
195
197
|
version: { expected: installed.expectedVersion, installed: installed.installedVersion, status: installed.installedVersion ? "verified" : "unknown" },
|
|
196
198
|
verification: { status: installed.verificationStatus, evidence: installed.evidence },
|
|
199
|
+
installation: { status: installed.verificationStatus },
|
|
200
|
+
activation: { status: restartRequired ? "pending_restart" : "active" },
|
|
201
|
+
delivery: { status: "not_evaluated" },
|
|
197
202
|
restart: { required: restartRequired, reason: restartRequired ? "host_reload" : "none" },
|
|
198
203
|
next_action: { kind: restartRequired ? "restart" : "prompt", text: nextAction },
|
|
199
204
|
});
|
|
200
205
|
}
|
|
201
206
|
|
|
207
|
+
function printVerboseHostOutput(installed, options, io) {
|
|
208
|
+
if (!options.verbose || options.json || !installed.nativeOutput?.length) return;
|
|
209
|
+
io.log("Host command output:");
|
|
210
|
+
for (const output of installed.nativeOutput) io.log(output);
|
|
211
|
+
}
|
|
212
|
+
|
|
202
213
|
function printInstallFailure(surface, error, options, io) {
|
|
203
214
|
const report = lifecycleFailure({
|
|
204
215
|
operation: "install",
|
|
@@ -212,7 +223,7 @@ function printInstallFailure(surface, error, options, io) {
|
|
|
212
223
|
if (options.json) printLifecycleResult(report, { json: true, io });
|
|
213
224
|
else {
|
|
214
225
|
io.error(error.message);
|
|
215
|
-
printLifecycleResult(report, {
|
|
226
|
+
printLifecycleResult(report, { io });
|
|
216
227
|
}
|
|
217
228
|
}
|
|
218
229
|
|
|
@@ -238,7 +249,7 @@ function runDisable(options, { io, exec }) {
|
|
|
238
249
|
? { phase: "repository_configuration", message: applied.error.message }
|
|
239
250
|
: result === "failed" ? { phase: "verification", message: "Repository disable postcondition was not observed." } : null,
|
|
240
251
|
});
|
|
241
|
-
printLifecycleResult(report, { json: options.json,
|
|
252
|
+
printLifecycleResult(report, { json: options.json, io });
|
|
242
253
|
return result === "success" ? 0 : 1;
|
|
243
254
|
} catch (error) {
|
|
244
255
|
io.error(error.message);
|
|
@@ -258,7 +269,7 @@ function runUninstall(options, { io, env, exec }) {
|
|
|
258
269
|
next_action: { kind: "confirm", text: `Review this preview, then rerun with --surface ${options.surface} --scope global --confirm; ownership is revalidated before apply.` },
|
|
259
270
|
changes: plan.mutations, retained: plan.retained,
|
|
260
271
|
});
|
|
261
|
-
printLifecycleResult(preview, { json: options.json,
|
|
272
|
+
printLifecycleResult(preview, { json: options.json, io });
|
|
262
273
|
return 0;
|
|
263
274
|
}
|
|
264
275
|
const applied = applyLifecyclePlan(plan, exec ? { exec } : {});
|
|
@@ -278,7 +289,7 @@ function runUninstall(options, { io, env, exec }) {
|
|
|
278
289
|
? { phase: "plugin_operation", message: applied.error.message }
|
|
279
290
|
: result === "failed" ? { phase: "verification", message: "Global uninstall postcondition was not observed." } : null,
|
|
280
291
|
});
|
|
281
|
-
printLifecycleResult(report, { json: options.json,
|
|
292
|
+
printLifecycleResult(report, { json: options.json, io });
|
|
282
293
|
return result === "success" ? 0 : 1;
|
|
283
294
|
} catch (error) {
|
|
284
295
|
io.error(error.message);
|
|
@@ -303,7 +314,7 @@ function runScaffold(options, io) {
|
|
|
303
314
|
return 1;
|
|
304
315
|
}
|
|
305
316
|
|
|
306
|
-
printNextSteps(options.target, options.dir, files, wroteAgentsFragment, wroteOpenCodeConfigFragment, removedOpenCodeAgents, io);
|
|
317
|
+
printNextSteps(options.target, options.dir, files, wroteAgentsFragment, wroteOpenCodeConfigFragment, removedOpenCodeAgents, { verbose: options.verbose, json: options.json, io });
|
|
307
318
|
return 0;
|
|
308
319
|
}
|
|
309
320
|
|
|
@@ -95,6 +95,7 @@ Options:
|
|
|
95
95
|
Set AGDF chat and artefact language. Defaults to detected system locale.
|
|
96
96
|
--lang <tag> Alias for --language
|
|
97
97
|
--json Print machine-readable command output as JSON
|
|
98
|
+
--verbose Print captured host command output and generated-file details
|
|
98
99
|
--status-card Print compact gate-check status-card output for interactive use
|
|
99
100
|
--run <run_id> Select one canonical run
|
|
100
101
|
--all-active Evaluate every active run (doctor and delivery-map only)
|
package/lib/cli/parse-args.js
CHANGED
|
@@ -27,6 +27,7 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
27
27
|
let dir = ".";
|
|
28
28
|
let force = false;
|
|
29
29
|
let json = false;
|
|
30
|
+
let verbose = false;
|
|
30
31
|
let statusCard = false;
|
|
31
32
|
let language;
|
|
32
33
|
let dirExplicit = false;
|
|
@@ -50,6 +51,7 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
50
51
|
if (arg === "--help" || arg === "-h") return { kind: "help" };
|
|
51
52
|
if (arg === "--force") { force = true; continue; }
|
|
52
53
|
if (arg === "--json") { json = true; continue; }
|
|
54
|
+
if (arg === "--verbose") { verbose = true; continue; }
|
|
53
55
|
if (arg === "--status-card") { statusCard = true; continue; }
|
|
54
56
|
if (arg === "--persist") { persist = true; continue; }
|
|
55
57
|
if (arg === "--generate-candidates") { generateCandidates = true; continue; }
|
|
@@ -129,6 +131,7 @@ export function parseArgs(argv, dependencies = {}) {
|
|
|
129
131
|
dir: resolve(cwd, dir),
|
|
130
132
|
force,
|
|
131
133
|
json,
|
|
134
|
+
verbose,
|
|
132
135
|
statusCard,
|
|
133
136
|
dirExplicit,
|
|
134
137
|
language: languagePreference(language),
|
|
@@ -3,24 +3,26 @@ import { pluginDefinition } from "../cli/runtime-context.js";
|
|
|
3
3
|
|
|
4
4
|
export function installCodexGlobalPlugin({ exec = execFileSync, io = console } = {}) {
|
|
5
5
|
const expectedVersion = pluginDefinition.version;
|
|
6
|
-
|
|
7
|
-
runPluginPhase(exec, "codex", ["plugin", "marketplace", "
|
|
8
|
-
runPluginPhase(exec, "codex", ["plugin", "
|
|
6
|
+
const nativeOutput = [];
|
|
7
|
+
nativeOutput.push(runPluginPhase(exec, "codex", ["plugin", "marketplace", "add", "arndtgold/ai-native-governance-delivery-framework"], "marketplace", captureOptions()));
|
|
8
|
+
nativeOutput.push(runPluginPhase(exec, "codex", ["plugin", "marketplace", "upgrade", "agdf"], "marketplace", captureOptions()));
|
|
9
|
+
nativeOutput.push(runPluginPhase(exec, "codex", ["plugin", "add", "agdf", "--marketplace", "agdf"], "plugin_operation", captureOptions()));
|
|
9
10
|
const listOutput = runPluginPhase(exec, "codex", ["plugin", "list"], "verification", { encoding: "utf8", stdio: "pipe" });
|
|
10
11
|
const installedVersion = pluginVersionFromList(listOutput, "agdf@agdf");
|
|
11
12
|
if (installedVersion !== expectedVersion) {
|
|
12
13
|
throw lifecycleAdapterError("version", versionMismatchMessage("Codex", "agdf@agdf", expectedVersion, installedVersion, "codex plugin marketplace upgrade agdf && codex plugin add agdf --marketplace agdf"));
|
|
13
14
|
}
|
|
14
|
-
return { surface: "codex", expectedVersion, installedVersion, verificationStatus: "healthy", evidence: ["codex plugin list"] };
|
|
15
|
+
return { surface: "codex", expectedVersion, installedVersion, verificationStatus: "healthy", evidence: ["codex plugin list"], nativeOutput: nativeOutput.filter(Boolean).map(String) };
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export function installClaudeGlobalPlugin({ exec = execFileSync, io = console } = {}) {
|
|
18
19
|
const expectedVersion = pluginDefinition.version;
|
|
19
|
-
|
|
20
|
-
runPluginPhase(exec, "claude", ["plugin", "marketplace", "
|
|
20
|
+
const nativeOutput = [];
|
|
21
|
+
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "marketplace", "add", "arndtgold/ai-native-governance-delivery-framework"], "marketplace", captureOptions()));
|
|
22
|
+
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", "marketplace", "update", "agdf"], "marketplace", captureOptions()));
|
|
21
23
|
const beforeList = runPluginPhase(exec, "claude", ["plugin", "list"], "verification", { encoding: "utf8", stdio: "pipe" });
|
|
22
24
|
const alreadyInstalled = pluginListHasPlugin(beforeList, "agdf@agdf");
|
|
23
|
-
runPluginPhase(exec, "claude", ["plugin", alreadyInstalled ? "update" : "install", "agdf@agdf"], "plugin_operation",
|
|
25
|
+
nativeOutput.push(runPluginPhase(exec, "claude", ["plugin", alreadyInstalled ? "update" : "install", "agdf@agdf"], "plugin_operation", captureOptions()));
|
|
24
26
|
const afterList = runPluginPhase(exec, "claude", ["plugin", "list"], "verification", { encoding: "utf8", stdio: "pipe" });
|
|
25
27
|
const installedVersion = pluginVersionFromList(afterList, "agdf@agdf");
|
|
26
28
|
if (installedVersion && installedVersion !== expectedVersion) {
|
|
@@ -32,9 +34,14 @@ export function installClaudeGlobalPlugin({ exec = execFileSync, io = console }
|
|
|
32
34
|
installedVersion,
|
|
33
35
|
verificationStatus: installedVersion ? "healthy" : "degraded",
|
|
34
36
|
evidence: ["claude plugin list", ...(installedVersion ? [] : ["host_did_not_expose_version"])],
|
|
37
|
+
nativeOutput: nativeOutput.filter(Boolean).map(String),
|
|
35
38
|
};
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
function captureOptions() {
|
|
42
|
+
return { encoding: "utf8", stdio: "pipe" };
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
export function inspectPluginSurface(surface, exec = execFileSync) {
|
|
39
46
|
const executable = surface === "claude" ? "claude" : "codex";
|
|
40
47
|
const pluginId = "agdf@agdf";
|
|
@@ -1,36 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
const surfaceLabels = Object.freeze({
|
|
2
|
+
codex: "Codex",
|
|
3
|
+
claude: "Claude Code",
|
|
4
|
+
copilot: "GitHub Copilot",
|
|
5
|
+
opencode: "OpenCode",
|
|
6
|
+
generic: "Generic coding agent",
|
|
7
|
+
});
|
|
2
8
|
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
function titleFor(report) {
|
|
10
|
+
if (report.result === "failed") return "AGDF installation failed";
|
|
11
|
+
if (report.result === "partial") return "AGDF installation partially completed";
|
|
12
|
+
if (report.operation === "repository_setup") return "AGDF repository setup complete";
|
|
13
|
+
return "AGDF installation complete";
|
|
6
14
|
}
|
|
7
15
|
|
|
8
|
-
export function lifecycleCardLines(report
|
|
9
|
-
const c = copy(locale);
|
|
16
|
+
export function lifecycleCardLines(report) {
|
|
10
17
|
const version = report.version.transition === "updated" && report.version.previous && report.version.installed
|
|
11
18
|
? `${report.version.previous} -> ${report.version.installed}`
|
|
12
|
-
: report.version.installed || (report.version.expected ?
|
|
19
|
+
: report.version.installed || (report.version.expected ? `unknown; expected ${report.version.expected}` : "unknown");
|
|
13
20
|
const versionStatus = report.version.transition && report.version.transition !== "updated"
|
|
14
21
|
? `${report.version.status}; transition ${report.version.transition}`
|
|
15
22
|
: report.version.status;
|
|
16
23
|
return [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
titleFor(report),
|
|
25
|
+
`Surface: ${surfaceLabels[report.surface]}`,
|
|
26
|
+
`Version: ${version} (${versionStatus})`,
|
|
27
|
+
`Installation scope: ${report.scope}`,
|
|
28
|
+
`Installation: ${report.installation.status}`,
|
|
29
|
+
`Activation: ${report.activation.status}`,
|
|
30
|
+
`Repository delivery: ${report.delivery.status}`,
|
|
31
|
+
`Verification: ${report.verification.status}`,
|
|
32
|
+
`Restart required: ${report.restart.required ? "yes" : "no"}${report.restart.reason !== "none" ? ` (${report.restart.reason})` : ""}`,
|
|
33
|
+
`Next action: ${report.next_action.text}`,
|
|
25
34
|
];
|
|
26
35
|
}
|
|
27
36
|
|
|
28
|
-
export function printLifecycleResult(report, { json = false,
|
|
37
|
+
export function printLifecycleResult(report, { json = false, io = console } = {}) {
|
|
29
38
|
if (json) {
|
|
30
39
|
io.log(JSON.stringify(report, null, 2));
|
|
31
40
|
return;
|
|
32
41
|
}
|
|
33
|
-
for (const line of lifecycleCardLines(report
|
|
42
|
+
for (const line of lifecycleCardLines(report)) io.log(line);
|
|
34
43
|
if (report.failure) io.log(`Failure phase: ${report.failure.phase}: ${report.failure.message}`);
|
|
35
44
|
if (report.retained.length) {
|
|
36
45
|
io.log("Retained:");
|
|
@@ -38,15 +47,14 @@ export function printLifecycleResult(report, { json = false, locale = "en", io =
|
|
|
38
47
|
}
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
export function printGeneralStatus(report, { json = false,
|
|
50
|
+
export function printGeneralStatus(report, { json = false, io = console } = {}) {
|
|
42
51
|
if (json) {
|
|
43
52
|
io.log(JSON.stringify(report, null, 2));
|
|
44
53
|
return;
|
|
45
54
|
}
|
|
46
|
-
|
|
47
|
-
io.log(
|
|
48
|
-
io.log(
|
|
49
|
-
io.log(
|
|
50
|
-
io.log(
|
|
51
|
-
io.log(`${c.next}: ${report.next_action.text}`);
|
|
55
|
+
io.log("AGDF status");
|
|
56
|
+
io.log(`Installation: ${report.installation.status}${report.installation.version ? ` (${report.installation.version})` : ""}`);
|
|
57
|
+
io.log(`Repository: ${report.repository.status}`);
|
|
58
|
+
io.log(`Delivery: ${report.delivery.status}${report.delivery.current_gate ? ` (${report.delivery.current_gate})` : ""}`);
|
|
59
|
+
io.log(`Next action: ${report.next_action.text}`);
|
|
52
60
|
}
|
package/lib/lifecycle/result.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const OPERATIONS = new Set(["install", "update", "status", "disable", "uninstall", "repository_setup"]);
|
|
2
2
|
const RESULTS = new Set(["success", "partial", "failed", "preview"]);
|
|
3
3
|
const SCOPES = new Set(["global", "repository"]);
|
|
4
|
+
const SURFACES = new Set(["codex", "claude", "copilot", "opencode", "generic"]);
|
|
5
|
+
const GLOBAL_INSTALL_RESTART_ACTIONS = Object.freeze({
|
|
6
|
+
codex: "Restart Codex.",
|
|
7
|
+
claude: "Restart Claude Code.",
|
|
8
|
+
opencode: "Restart OpenCode.",
|
|
9
|
+
});
|
|
4
10
|
|
|
5
11
|
function text(value) {
|
|
6
12
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -24,6 +30,15 @@ export function createLifecycleResult(input = {}) {
|
|
|
24
30
|
status: text(input.verification?.status) || "unknown",
|
|
25
31
|
evidence: [...(input.verification?.evidence ?? [])].map(String),
|
|
26
32
|
},
|
|
33
|
+
installation: {
|
|
34
|
+
status: text(input.installation?.status) || text(input.verification?.status) || "unknown",
|
|
35
|
+
},
|
|
36
|
+
activation: {
|
|
37
|
+
status: text(input.activation?.status) || (input.restart?.required ? "pending_restart" : "active"),
|
|
38
|
+
},
|
|
39
|
+
delivery: {
|
|
40
|
+
status: text(input.delivery?.status) || "not_evaluated",
|
|
41
|
+
},
|
|
27
42
|
restart: {
|
|
28
43
|
required: Boolean(input.restart?.required),
|
|
29
44
|
reason: text(input.restart?.reason) || "none",
|
|
@@ -44,7 +59,7 @@ export function assertLifecycleResult(value) {
|
|
|
44
59
|
if (value?.schema_version !== 1) throw new Error("Lifecycle result requires schema_version 1.");
|
|
45
60
|
if (!OPERATIONS.has(value.operation)) throw new Error(`Unsupported lifecycle operation: ${value.operation || "missing"}.`);
|
|
46
61
|
if (!RESULTS.has(value.result)) throw new Error(`Unsupported lifecycle result: ${value.result || "missing"}.`);
|
|
47
|
-
if (!value.surface) throw new Error(
|
|
62
|
+
if (!SURFACES.has(value.surface)) throw new Error(`Unsupported lifecycle surface: ${value.surface || "missing"}.`);
|
|
48
63
|
if (!SCOPES.has(value.scope)) throw new Error(`Unsupported lifecycle scope: ${value.scope || "missing"}.`);
|
|
49
64
|
if (!value.next_action || Array.isArray(value.next_action) || !text(value.next_action.text)) {
|
|
50
65
|
throw new Error("Lifecycle result requires exactly one next action.");
|
|
@@ -56,6 +71,12 @@ export function assertLifecycleResult(value) {
|
|
|
56
71
|
return value;
|
|
57
72
|
}
|
|
58
73
|
|
|
74
|
+
export function globalInstallRestartAction(surface) {
|
|
75
|
+
const action = GLOBAL_INSTALL_RESTART_ACTIONS[surface];
|
|
76
|
+
if (!action) throw new Error(`Unsupported global installation restart surface: ${surface || "missing"}.`);
|
|
77
|
+
return Object.freeze({ kind: "restart", text: action });
|
|
78
|
+
}
|
|
79
|
+
|
|
59
80
|
export function lifecycleFailure({ operation, surface, scope, phase, message, evidence = [], nextAction }) {
|
|
60
81
|
return createLifecycleResult({
|
|
61
82
|
operation,
|
|
@@ -7,14 +7,43 @@ import { agdfFragmentPath, openCodeConfigFragmentPath } from "./plan.js";
|
|
|
7
7
|
|
|
8
8
|
const pluginInstallCommand = "npx --yes @agdf/cli@latest claude";
|
|
9
9
|
|
|
10
|
-
export function printNextSteps(target, destination, files, wroteAgentsFragment, wroteOpenCodeConfigFragment, removedOpenCodeAgents = [], io = console) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
export function printNextSteps(target, destination, files, wroteAgentsFragment, wroteOpenCodeConfigFragment, removedOpenCodeAgents = [], { verbose = false, json = false, io = console } = {}) {
|
|
11
|
+
const repositorySurface = { "codex-repo": "codex", "opencode-repo": "opencode", copilot: "copilot" }[target];
|
|
12
|
+
const verified = files.every((file) => {
|
|
13
|
+
const path = join(destination, file.path);
|
|
14
|
+
return existsSync(path) && readFileSync(path, "utf8") === file.content;
|
|
15
|
+
});
|
|
16
|
+
if (repositorySurface) {
|
|
17
|
+
const nextAction = repositorySurface === "codex"
|
|
18
|
+
? "Restart Codex, open /plugins, select This repository and install agdf; then start a new task with: Run an AGDF gate check for this request."
|
|
19
|
+
: repositorySurface === "opencode"
|
|
20
|
+
? "Restart OpenCode in this repository so it loads the generated AGDF repository configuration."
|
|
21
|
+
: "Run /instructions in GitHub Copilot CLI to confirm that the generated AGDF repository instructions are visible.";
|
|
22
|
+
printLifecycleResult(createLifecycleResult({
|
|
23
|
+
operation: "repository_setup",
|
|
24
|
+
result: verified ? "success" : "partial",
|
|
25
|
+
surface: repositorySurface,
|
|
26
|
+
scope: "repository",
|
|
27
|
+
version: { expected: pluginDefinition.version, status: "expected" },
|
|
28
|
+
verification: { status: verified ? "healthy" : "degraded", evidence: files.map((file) => file.path) },
|
|
29
|
+
installation: { status: verified ? "healthy" : "degraded" },
|
|
30
|
+
activation: { status: "pending_restart" },
|
|
31
|
+
delivery: { status: "not_evaluated" },
|
|
32
|
+
restart: { required: true, reason: "host_reload_and_repository_plugin_activation" },
|
|
33
|
+
next_action: { kind: "host_action", text: nextAction },
|
|
34
|
+
}), { json, io });
|
|
35
|
+
if (!verbose || json) return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (verbose) {
|
|
39
|
+
io.log("");
|
|
40
|
+
io.log(`AGDF bootstrap complete in ${destination}`);
|
|
41
|
+
io.log("");
|
|
42
|
+
io.log("Generated:");
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
const action = file.action ? `${file.action}: ` : "";
|
|
45
|
+
io.log(`- ${action}${file.path}`);
|
|
46
|
+
}
|
|
18
47
|
}
|
|
19
48
|
|
|
20
49
|
if (removedOpenCodeAgents.length > 0) {
|
|
@@ -30,26 +59,7 @@ export function printNextSteps(target, destination, files, wroteAgentsFragment,
|
|
|
30
59
|
for (const preserved of preservedFiles) io.log(`- ${preserved}`);
|
|
31
60
|
}
|
|
32
61
|
|
|
33
|
-
if (
|
|
34
|
-
const verified = files.every((file) => {
|
|
35
|
-
const path = join(destination, file.path);
|
|
36
|
-
return existsSync(path) && readFileSync(path, "utf8") === file.content;
|
|
37
|
-
});
|
|
38
|
-
printLifecycleResult(createLifecycleResult({
|
|
39
|
-
operation: "repository_setup",
|
|
40
|
-
result: verified ? "success" : "partial",
|
|
41
|
-
surface: "codex",
|
|
42
|
-
scope: "repository",
|
|
43
|
-
version: { expected: pluginDefinition.version, status: "expected" },
|
|
44
|
-
verification: { status: verified ? "healthy" : "degraded", evidence: files.map((file) => file.path) },
|
|
45
|
-
restart: { required: true, reason: "host_reload_and_repository_plugin_activation" },
|
|
46
|
-
next_action: {
|
|
47
|
-
kind: "host_action",
|
|
48
|
-
text: "Restart Codex, open /plugins, select This repository and install agdf; then start a new task with: Run an AGDF gate check for this request.",
|
|
49
|
-
},
|
|
50
|
-
}), { locale: JSON.parse(files.find((file) => file.path === join(".agdf", "control", "config.json"))?.content ?? "{}").chat_language, io });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
62
|
+
if (repositorySurface && !verbose) return;
|
|
53
63
|
|
|
54
64
|
io.log("");
|
|
55
65
|
io.log("Next steps:");
|
package/package.json
CHANGED