create-agdf 0.13.6 → 0.13.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +26 -0
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  4. package/generated/plugins/agdf/hooks/hooks.json +3 -2
  5. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +24 -1
  6. package/generated/plugins/agdf/runtime/agdf-session-check.js +92 -0
  7. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +24 -1
  8. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/command-registry.js +9 -0
  9. package/generated/plugins/agdf/runtime/create-agdf/lib/cli/parse-args.js +17 -0
  10. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +71 -0
  11. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  12. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  13. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +19 -2
  14. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  15. package/generated/plugins/agdf/submission/openai/capability-matrix.json +8 -1
  16. package/generated/plugins/agdf/submission/openai/release-notes.md +12 -1
  17. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +23 -1
  18. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  19. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +24 -1
  20. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  21. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +8 -1
  22. package/generated/submissions/openai/agdf/submission/openai/inventory.json +9 -9
  23. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  24. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  25. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  26. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +12 -1
  27. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +23 -1
  28. package/lib/cli/application.js +228 -13
  29. package/lib/cli/command-registry.js +9 -0
  30. package/lib/cli/parse-args.js +17 -0
  31. package/lib/installers/local-marketplace.js +85 -21
  32. package/lib/installers/opencode.js +21 -5
  33. package/lib/installers/plugin-installers.js +10 -0
  34. package/lib/lifecycle/presentation.js +43 -2
  35. package/lib/lifecycle/result.js +9 -0
  36. package/lib/lifecycle/status.js +5 -1
  37. package/lib/runtime-check-consent/adapters.js +42 -0
  38. package/lib/runtime-check-consent/claude-settings.js +71 -0
  39. package/lib/runtime-check-consent/contract.js +71 -0
  40. package/lib/runtime-check-consent/coordinator.js +37 -0
  41. package/lib/runtime-check-consent/service.js +181 -0
  42. package/lib/runtime-check-consent/state.js +90 -0
  43. package/opencode-plugin.js +30 -15
  44. package/package.json +2 -1
@@ -0,0 +1,181 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { join } from "node:path";
5
+ import process from "node:process";
6
+ import { generatedRoot, pluginDefinition } from "../cli/runtime-context.js";
7
+ import { defaultOpenCodeConfigDir, resolveOpenCodeInstalledPackage } from "../installers/opencode.js";
8
+ import { defaultAgdfDataRoot } from "../installers/local-marketplace.js";
9
+ import { digestNormalizedPluginSource } from "../runtime/plugin-provenance.js";
10
+ import { fixedRuntimeCheckCommand, runtimeCheckCapabilityIdentity } from "./contract.js";
11
+ import { consentDisclosure, resolveRuntimeCheckDecision } from "./coordinator.js";
12
+ import { claudePermissionRule } from "./adapters.js";
13
+ import { configureClaudeExactRuntimeRule, defaultClaudeSettingsPath, revokeClaudeRuntimeRule } from "./claude-settings.js";
14
+ import { createRuntimeCheckReceipt, readRuntimeCheckReceipt, writeRuntimeCheckReceipt } from "./state.js";
15
+
16
+ export { fixedRuntimeCheckCommand } from "./contract.js";
17
+
18
+ export function prepareInstallConsent(surface, options = {}, adapters = {}) {
19
+ const explicit = options.runtimeChecksDecision;
20
+ const interactive = explicit === undefined && Boolean(adapters.interactive);
21
+ const answer = interactive ? adapters.ask?.(consentDisclosure(surface)) : undefined;
22
+ const decision = resolveRuntimeCheckDecision({ explicitValue: explicit ?? answer, interactive: false });
23
+ return { decision, persist: explicit !== undefined || interactive, disclosure: consentDisclosure(surface) };
24
+ }
25
+
26
+ function prospectiveRuntimeCheckIdentity(surface, platform = process.platform) {
27
+ if (surface === "opencode") {
28
+ const installed = resolveOpenCodeInstalledPackage(defaultOpenCodeConfigDir(), pluginDefinition.opencode.npmPackage);
29
+ if (!installed.loadable || !installed.digest) return null;
30
+ return runtimeCheckCapabilityIdentity({
31
+ capability: pluginDefinition.automaticRuntimeChecks,
32
+ surface,
33
+ runtimeDigest: installed.digest,
34
+ sourceDigest: installed.digest,
35
+ command: fixedRuntimeCheckCommand(surface, installed.root, platform),
36
+ });
37
+ }
38
+ if (!["codex", "claude"].includes(surface)) return null;
39
+ const pluginRoot = join(generatedRoot, "plugins", "agdf");
40
+ let runtimeManifest;
41
+ try { runtimeManifest = JSON.parse(readFileSync(join(pluginRoot, "runtime", "runtime-manifest.json"), "utf8")); } catch { return null; }
42
+ if (!/^[a-f0-9]{64}$/.test(runtimeManifest?.digest ?? "")) return null;
43
+ const sourceDigest = digestNormalizedPluginSource(pluginRoot, pluginDefinition.version);
44
+ const command = fixedRuntimeCheckCommand(surface, pluginRoot, platform);
45
+ return runtimeCheckCapabilityIdentity({
46
+ capability: pluginDefinition.automaticRuntimeChecks,
47
+ surface,
48
+ runtimeDigest: runtimeManifest.digest,
49
+ sourceDigest,
50
+ command,
51
+ });
52
+ }
53
+
54
+ export function retainCurrentInstallConsent(surface, dataRoot = defaultAgdfDataRoot(), platform = process.platform) {
55
+ const capabilityIdentity = prospectiveRuntimeCheckIdentity(surface, platform);
56
+ if (!capabilityIdentity) return null;
57
+ const current = readRuntimeCheckReceipt(dataRoot, surface);
58
+ if (current.status !== "valid" || current.receipt.capability_identity !== capabilityIdentity) return null;
59
+ return {
60
+ decision: current.receipt.requested_state === "enabled" ? "enable" : "manual",
61
+ persist: false,
62
+ retained: true,
63
+ disclosure: consentDisclosure(surface),
64
+ };
65
+ }
66
+
67
+ export function persistInstallConsent({ surface, decision, installed, dataRoot, platform, claudeSettingsPath }) {
68
+ if (decision === "cancel") return { requested: "cancelled", effective: "cancelled", reason: "consent_not_provided", capability_identity: null, verification: "not_attempted", mutation: "none", rollback: "none" };
69
+ const runtimeDigest = installed?.runtimeDigest ?? installed?.digest;
70
+ if (!installed?.pluginRoot || !runtimeDigest || !installed?.sourceDigest) {
71
+ return { requested: decision === "enable" ? "enabled" : "manual", effective: "manual", reason: "host_permission_unverified", capability_identity: null, verification: "unavailable", mutation: "none", rollback: "none" };
72
+ }
73
+ const command = fixedRuntimeCheckCommand(surface, installed.pluginRoot, platform);
74
+ const capabilityIdentity = runtimeCheckCapabilityIdentity({
75
+ capability: pluginDefinition.automaticRuntimeChecks,
76
+ surface,
77
+ runtimeDigest,
78
+ sourceDigest: installed.sourceDigest,
79
+ command,
80
+ });
81
+ const receipt = createRuntimeCheckReceipt({ surface, decision, capabilityIdentity, command });
82
+ let configured = null;
83
+ let configurationReason = null;
84
+ if (surface === "claude" && decision === "enable") {
85
+ configured = configureClaudeExactRuntimeRule({
86
+ path: claudeSettingsPath ?? defaultClaudeSettingsPath(),
87
+ rule: claudePermissionRule({ platform: platform ?? process.platform, command }),
88
+ });
89
+ if (configured.status !== "configured") {
90
+ configurationReason = configured.reason;
91
+ configured = null;
92
+ }
93
+ }
94
+ try {
95
+ writeRuntimeCheckReceipt(dataRoot ?? defaultAgdfDataRoot(), receipt);
96
+ } catch (error) {
97
+ configured?.rollback();
98
+ throw error;
99
+ }
100
+ if (configurationReason) return { requested: "enabled", effective: "degraded", reason: configurationReason, capability_identity: capabilityIdentity, verification: "conflict", mutation: "receipt_written", rollback: "none" };
101
+ return {
102
+ requested: receipt.requested_state,
103
+ effective: receipt.requested_state === "manual" ? "manual" : "decision_required",
104
+ reason: receipt.requested_state === "manual" ? "consent_not_provided" : "host_permission_unverified",
105
+ capability_identity: capabilityIdentity,
106
+ verification: receipt.requested_state === "manual" ? "not_required" : "host_unverified",
107
+ mutation: surface === "claude" && decision === "enable" ? "exact_rule_and_receipt_written" : "receipt_written",
108
+ rollback: "none",
109
+ };
110
+ }
111
+
112
+ export function setRuntimeChecksManual({ dataRoot = defaultAgdfDataRoot(), surface, platform = process.platform, claudeSettingsPath }) {
113
+ const result = readRuntimeCheckReceipt(dataRoot, surface);
114
+ if (result.status === "receipt_missing") return { requested: "manual", effective: "manual", reason: "consent_not_provided", capability_identity: null, verification: "not_required", mutation: "none", rollback: "none", path: result.path };
115
+ if (result.status !== "valid") return { requested: "manual", effective: result.status, reason: result.status, capability_identity: null, verification: "unavailable", mutation: "none", rollback: "none", path: result.path };
116
+ if (surface === "claude" && result.receipt.requested_state === "enabled") {
117
+ revokeClaudeRuntimeRule({
118
+ path: claudeSettingsPath ?? defaultClaudeSettingsPath(),
119
+ rule: claudePermissionRule({ platform, command: result.receipt.command }),
120
+ });
121
+ }
122
+ const receipt = createRuntimeCheckReceipt({
123
+ surface,
124
+ decision: "manual",
125
+ capabilityIdentity: result.receipt.capability_identity,
126
+ command: result.receipt.command,
127
+ });
128
+ writeRuntimeCheckReceipt(dataRoot, receipt);
129
+ return {
130
+ requested: "manual",
131
+ effective: "manual",
132
+ reason: "consent_not_provided",
133
+ capability_identity: receipt.capability_identity,
134
+ verification: "not_required",
135
+ mutation: surface === "claude" ? "exact_owned_rule_removed" : "receipt_updated",
136
+ rollback: "none",
137
+ path: result.path,
138
+ };
139
+ }
140
+
141
+ export function runtimeCheckStatus(dataRoot = defaultAgdfDataRoot(), surface, platform = process.platform) {
142
+ const result = readRuntimeCheckReceipt(dataRoot, surface);
143
+ if (result.status !== "valid") return { requested: "unknown", effective: result.status, reason: result.status, capability_identity: null, verification: "unavailable", mutation: "none", rollback: "none", path: result.path };
144
+ const currentIdentity = prospectiveRuntimeCheckIdentity(surface, platform);
145
+ if (currentIdentity && currentIdentity !== result.receipt.capability_identity) {
146
+ return { requested: result.receipt.requested_state, effective: "renewal_required", reason: "capability_identity_changed", capability_identity: result.receipt.capability_identity, verification: "identity_mismatch", mutation: "none", rollback: "none", path: result.path };
147
+ }
148
+ return { requested: result.receipt.requested_state, effective: result.receipt.requested_state === "manual" ? "manual" : "decision_required", reason: result.receipt.requested_state === "manual" ? "consent_not_provided" : "host_permission_unverified", capability_identity: result.receipt.capability_identity, verification: result.receipt.requested_state === "manual" ? "not_required" : "host_unverified", mutation: "none", rollback: "none", path: result.path };
149
+ }
150
+
151
+ export function executeOpenCodeAutomaticRuntimeCheck({
152
+ directory = process.cwd(),
153
+ dataRoot = defaultAgdfDataRoot(),
154
+ packageRoot = fileURLToPath(new URL("../../", import.meta.url)),
155
+ run = spawnSync,
156
+ executable = process.platform === "win32" ? "node.exe" : "node",
157
+ statusResolver = runtimeCheckStatus,
158
+ entrypointExists = existsSync,
159
+ } = {}) {
160
+ const status = statusResolver(dataRoot, "opencode");
161
+ if (status.requested !== "enabled" || status.effective !== "decision_required") {
162
+ return { ...status, ran: false, output: "" };
163
+ }
164
+ const entrypoint = join(packageRoot, "generated", "plugins", "agdf", "runtime", "agdf-session-check.js");
165
+ if (!entrypointExists(entrypoint)) {
166
+ return { ...status, effective: "unavailable", reason: "unsupported_host_capability", verification: "entrypoint_missing", ran: false, output: "" };
167
+ }
168
+ const child = run(executable, [entrypoint], {
169
+ cwd: directory,
170
+ env: { ...process.env, AGDF_SURFACE: "opencode" },
171
+ encoding: "utf8",
172
+ stdio: ["ignore", "pipe", "pipe"],
173
+ timeout: 10000,
174
+ maxBuffer: 1024 * 1024,
175
+ });
176
+ const output = String(child.stdout || "").trim().slice(0, 20000);
177
+ if (child.status !== 0 || !output.includes("AGDF automatic runtime check:")) {
178
+ return { ...status, effective: "degraded", reason: "host_permission_unverified", verification: "execution_failed", ran: true, output: "" };
179
+ }
180
+ return { ...status, effective: "enabled", reason: "none", verification: "host_observed", ran: true, output };
181
+ }
@@ -0,0 +1,90 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { renameSyncWithRetry } from "../fs-swap.js";
5
+
6
+ export function runtimeCheckReceiptPath(dataRoot, surface) {
7
+ if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
8
+ return join(resolve(dataRoot), "runtime-checks", `${surface}.json`);
9
+ }
10
+
11
+ export function createRuntimeCheckReceipt({ surface, decision, capabilityIdentity, command }) {
12
+ if (!["codex", "claude", "opencode"].includes(surface)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_SURFACE_INVALID");
13
+ if (!["enable", "manual"].includes(decision)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_DECISION_INVALID");
14
+ if (!/^[a-f0-9]{64}$/.test(capabilityIdentity)) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_IDENTITY_INVALID");
15
+ return Object.freeze({
16
+ schema_version: 1,
17
+ owner: "create-agdf",
18
+ capability_id: "automatic-runtime-checks",
19
+ surface,
20
+ requested_state: decision === "enable" ? "enabled" : "manual",
21
+ capability_identity: capabilityIdentity,
22
+ command,
23
+ });
24
+ }
25
+
26
+ export function validateRuntimeCheckReceipt(receipt) {
27
+ if (receipt?.schema_version !== 1 || receipt.owner !== "create-agdf"
28
+ || receipt.capability_id !== "automatic-runtime-checks") return { status: "receipt_unowned", receipt: null };
29
+ if (!["codex", "claude", "opencode"].includes(receipt.surface)
30
+ || !["enabled", "manual"].includes(receipt.requested_state)
31
+ || !/^[a-f0-9]{64}$/.test(receipt.capability_identity)
32
+ || typeof receipt.command !== "string" || !receipt.command.trim()) {
33
+ return { status: "receipt_invalid", receipt: null };
34
+ }
35
+ return { status: "valid", receipt };
36
+ }
37
+
38
+ export function readRuntimeCheckReceipt(dataRoot, surface) {
39
+ const path = runtimeCheckReceiptPath(dataRoot, surface);
40
+ if (!existsSync(path)) return { status: "receipt_missing", receipt: null, path };
41
+ try {
42
+ const file = lstatSync(path);
43
+ if (!file.isFile() || file.isSymbolicLink()) return { status: "receipt_unowned", receipt: null, path };
44
+ return { ...validateRuntimeCheckReceipt(JSON.parse(readFileSync(path, "utf8"))), path };
45
+ } catch {
46
+ return { status: "receipt_invalid", receipt: null, path };
47
+ }
48
+ }
49
+
50
+ export function writeRuntimeCheckReceipt(dataRoot, receipt, adapters = {}) {
51
+ const validated = validateRuntimeCheckReceipt(receipt);
52
+ if (validated.status !== "valid") throw new Error(`AGDF_RUNTIME_CHECK_${validated.status.toUpperCase()}`);
53
+ const path = runtimeCheckReceiptPath(dataRoot, receipt.surface);
54
+ const parent = dirname(path);
55
+ const fs = {
56
+ mkdir: adapters.mkdir ?? mkdirSync,
57
+ write: adapters.write ?? writeFileSync,
58
+ rename: adapters.rename ?? renameSyncWithRetry,
59
+ remove: adapters.remove ?? rmSync,
60
+ };
61
+ fs.mkdir(parent, { recursive: true });
62
+ const parentStats = lstatSync(parent);
63
+ if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) throw new Error("AGDF_RUNTIME_CHECK_RECEIPT_PARENT_UNOWNED");
64
+ const temp = `${path}.tmp-${process.pid}-${randomUUID()}`;
65
+ const backup = `${path}.bak-${process.pid}-${randomUUID()}`;
66
+ const hadPrevious = existsSync(path);
67
+ fs.write(temp, `${JSON.stringify(receipt, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
68
+ try {
69
+ if (hadPrevious && process.platform === "win32") fs.rename(path, backup);
70
+ fs.rename(temp, path);
71
+ if (hadPrevious && process.platform === "win32") fs.remove(backup, { force: true });
72
+ } catch (error) {
73
+ try { fs.remove(temp, { force: true }); } catch {}
74
+ if (hadPrevious && process.platform === "win32" && existsSync(backup) && !existsSync(path)) fs.rename(backup, path);
75
+ throw error;
76
+ }
77
+ return path;
78
+ }
79
+
80
+ export function deriveRuntimeCheckState({ receiptResult, surface, capabilityIdentity, hostEvidence }) {
81
+ if (receiptResult.status !== "valid") return { requested: "unknown", effective: receiptResult.status, reason: receiptResult.status };
82
+ const receipt = receiptResult.receipt;
83
+ if (receipt.surface !== surface) return { requested: receipt.requested_state, effective: "renewal_required", reason: "installed_identity_mismatch" };
84
+ if (receipt.capability_identity !== capabilityIdentity) return { requested: receipt.requested_state, effective: "renewal_required", reason: "capability_identity_changed" };
85
+ if (receipt.requested_state === "manual") return { requested: "manual", effective: "manual", reason: "consent_not_provided" };
86
+ if (hostEvidence?.status === "enabled" && hostEvidence.capability_identity === capabilityIdentity) {
87
+ return { requested: "enabled", effective: "enabled", reason: "none" };
88
+ }
89
+ return { requested: "enabled", effective: hostEvidence?.status || "decision_required", reason: hostEvidence?.reason || "host_permission_unverified" };
90
+ }
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { evaluateOpenCodeRepositoryActivation } from "./lib/installers/opencode-activation.js";
3
+ import { executeOpenCodeAutomaticRuntimeCheck } from "./lib/runtime-check-consent/service.js";
3
4
 
4
5
  const packageJson = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
5
6
 
@@ -15,7 +16,7 @@ const readValidatorExpectedVersion = () => {
15
16
  }
16
17
  };
17
18
 
18
- export const AGDFPlugin = async ({ directory, client }) => {
19
+ export const AGDFPlugin = async ({ directory, client }, dependencies = {}) => {
19
20
  const controlDir = `${directory}/.agdf/control`;
20
21
  const activation = () => evaluateOpenCodeRepositoryActivation(directory);
21
22
  const status = () => {
@@ -45,13 +46,11 @@ export const AGDFPlugin = async ({ directory, client }) => {
45
46
  const appendGuidance = async (output, key) => {
46
47
  if (!output || !Array.isArray(output[key])) {
47
48
  try {
48
- await client.app.log({
49
- body: {
50
- service: "agdf",
51
- level: "warn",
52
- message: `AGDF OpenCode guidance degraded: ${key} output is unavailable`,
53
- extra: { key, repositoryActivation: activation().state },
54
- },
49
+ await safeLog({
50
+ service: "agdf",
51
+ level: "warn",
52
+ message: `AGDF OpenCode guidance degraded: ${key} output is unavailable`,
53
+ extra: { key, repositoryActivation: activation().state },
55
54
  });
56
55
  } catch {}
57
56
  return;
@@ -65,17 +64,31 @@ export const AGDFPlugin = async ({ directory, client }) => {
65
64
  } catch {}
66
65
  };
67
66
 
67
+ const safeLog = async (body) => {
68
+ try {
69
+ const response = await client?.app?.log?.({ body });
70
+ if (response?.error) await client?.app?.log?.(body);
71
+ } catch {
72
+ try { await client?.app?.log?.(body); } catch {}
73
+ }
74
+ };
75
+
76
+ let automaticCheck;
77
+ const currentAutomaticCheck = () => {
78
+ automaticCheck ??= (dependencies.executeAutomaticRuntimeCheck ?? executeOpenCodeAutomaticRuntimeCheck)({ directory });
79
+ return automaticCheck;
80
+ };
81
+
68
82
  return {
69
83
  event: async ({ event }) => {
70
84
  if (event?.type === "session.created") {
71
85
  const currentStatus = status();
72
- await client.app.log({
73
- body: {
74
- service: "agdf",
75
- level: "info",
76
- message: currentStatus.active ? "AGDF OpenCode active through durable control" : "AGDF OpenCode global hook active without durable control",
77
- extra: currentStatus,
78
- },
86
+ const runtimeCheck = currentAutomaticCheck();
87
+ await safeLog({
88
+ service: "agdf",
89
+ level: "info",
90
+ message: currentStatus.active ? "AGDF OpenCode active through durable control" : "AGDF OpenCode global hook active without durable control",
91
+ extra: { ...currentStatus, automatic_runtime_check: { effective: runtimeCheck.effective, reason: runtimeCheck.reason, ran: runtimeCheck.ran } },
79
92
  });
80
93
  if (!currentStatus.active) {
81
94
  await safeToast(
@@ -112,6 +125,8 @@ export const AGDFPlugin = async ({ directory, client }) => {
112
125
 
113
126
  "experimental.chat.system.transform": async (_input, output) => {
114
127
  await appendGuidance(output, "system");
128
+ const runtimeCheck = currentAutomaticCheck();
129
+ if (runtimeCheck.ran && runtimeCheck.output && Array.isArray(output?.system)) output.system.push(runtimeCheck.output);
115
130
  },
116
131
 
117
132
  "experimental.session.compacting": async (_input, output) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.13.6",
3
+ "version": "0.13.8",
4
4
  "description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
5
5
  "type": "module",
6
6
  "files": [
@@ -32,6 +32,7 @@
32
32
  "test:delivery-path-search-unit": "node ./scripts/delivery-path-search-unit-test.js",
33
33
  "test:delivery-path-search-generator": "node ./scripts/delivery-path-search-generator-test.js",
34
34
  "test:opencode-hardening": "node ./scripts/opencode-hardening-test.js",
35
+ "test:runtime-check-consent": "node ./scripts/runtime-check-consent-test.js",
35
36
  "test:cli-modularization": "node ./scripts/cli-modularization-test.js",
36
37
  "test:local-validator": "node ./scripts/local-validator-test.js",
37
38
  "test:local-marketplace": "node ./scripts/local-marketplace-test.js",