@deftai/directive-core 0.79.4 → 0.81.0
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/dist/doctor/checks.d.ts +6 -0
- package/dist/doctor/checks.js +139 -0
- package/dist/doctor/main.js +2 -1
- package/dist/hooks/dispatcher.d.ts +18 -3
- package/dist/hooks/dispatcher.js +173 -62
- package/dist/hooks/readonly.d.ts +7 -0
- package/dist/hooks/readonly.js +83 -0
- package/dist/hooks/tools.d.ts +7 -0
- package/dist/hooks/tools.js +16 -0
- package/dist/init-deposit/agent-hooks.d.ts +4 -1
- package/dist/init-deposit/agent-hooks.js +77 -21
- package/dist/policy/index.d.ts +3 -0
- package/dist/policy/index.js +45 -1
- package/dist/policy/product-signal.d.ts +45 -0
- package/dist/policy/product-signal.js +210 -0
- package/dist/policy/runtime-authority.d.ts +54 -0
- package/dist/policy/runtime-authority.js +180 -0
- package/dist/policy/staleness-tickler.d.ts +20 -0
- package/dist/policy/staleness-tickler.js +151 -0
- package/dist/pr-merge-readiness/ci-gate.d.ts +7 -1
- package/dist/pr-merge-readiness/ci-gate.js +38 -5
- package/dist/pr-merge-readiness/gh.d.ts +4 -0
- package/dist/pr-merge-readiness/gh.js +10 -3
- package/dist/pr-merge-readiness/index.d.ts +2 -1
- package/dist/pr-merge-readiness/index.js +2 -1
- package/dist/pr-merge-readiness/runner-capacity-stall.d.ts +35 -0
- package/dist/pr-merge-readiness/runner-capacity-stall.js +46 -0
- package/dist/pr-watch/constants.d.ts +5 -0
- package/dist/pr-watch/constants.js +6 -1
- package/dist/pr-watch/main.js +8 -0
- package/dist/pr-watch/probe.js +8 -0
- package/dist/pr-watch/types.d.ts +7 -0
- package/dist/pr-watch/watch.js +8 -1
- package/dist/product-signal/actor-name.d.ts +18 -0
- package/dist/product-signal/actor-name.js +94 -0
- package/dist/product-signal/consent.d.ts +30 -0
- package/dist/product-signal/consent.js +116 -0
- package/dist/product-signal/gates.d.ts +17 -0
- package/dist/product-signal/gates.js +66 -0
- package/dist/product-signal/github-private-sink-adapter.d.ts +28 -0
- package/dist/product-signal/github-private-sink-adapter.js +274 -0
- package/dist/product-signal/headless.d.ts +8 -0
- package/dist/product-signal/headless.js +32 -0
- package/dist/product-signal/install-context.d.ts +13 -0
- package/dist/product-signal/install-context.js +41 -0
- package/dist/product-signal/local-signal-summary.d.ts +7 -0
- package/dist/product-signal/local-signal-summary.js +173 -0
- package/dist/product-signal/payload.d.ts +90 -0
- package/dist/product-signal/payload.js +124 -0
- package/dist/product-signal/sink-bootstrap.d.ts +29 -0
- package/dist/product-signal/sink-bootstrap.js +108 -0
- package/dist/product-signal/submit-adapter.d.ts +14 -0
- package/dist/product-signal/submit-adapter.js +2 -0
- package/dist/product-signal/submit.d.ts +54 -0
- package/dist/product-signal/submit.js +290 -0
- package/dist/scm/gh-rest.d.ts +3 -1
- package/dist/scm/gh-rest.js +22 -0
- package/dist/scope/main.js +12 -0
- package/dist/session/release-availability.d.ts +21 -0
- package/dist/session/release-availability.js +109 -0
- package/dist/session/ritual-sentinel.d.ts +14 -0
- package/dist/session/ritual-sentinel.js +28 -0
- package/dist/session/session-start.d.ts +10 -0
- package/dist/session/session-start.js +18 -0
- package/dist/staleness-tickler/escalation.d.ts +14 -0
- package/dist/staleness-tickler/escalation.js +106 -0
- package/dist/staleness-tickler/idle.d.ts +18 -0
- package/dist/staleness-tickler/idle.js +47 -0
- package/dist/staleness-tickler/index.d.ts +8 -0
- package/dist/staleness-tickler/index.js +8 -0
- package/dist/staleness-tickler/probe-directive.d.ts +32 -0
- package/dist/staleness-tickler/probe-directive.js +106 -0
- package/dist/staleness-tickler/probe-xbrief.d.ts +12 -0
- package/dist/staleness-tickler/probe-xbrief.js +103 -0
- package/dist/staleness-tickler/run.d.ts +31 -0
- package/dist/staleness-tickler/run.js +227 -0
- package/dist/staleness-tickler/state.d.ts +10 -0
- package/dist/staleness-tickler/state.js +46 -0
- package/dist/staleness-tickler/types.d.ts +85 -0
- package/dist/staleness-tickler/types.js +5 -0
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +50 -0
- package/dist/verify-env/agent-hooks.js +4 -2
- package/package.json +3 -3
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { HookHost } from "../hooks/dispatcher.js";
|
|
2
2
|
import type { InitDepositIo } from "./constants.js";
|
|
3
|
-
export
|
|
3
|
+
export { DIRECT_WRITE_HOOK_MATCHER, SPAWN_HOOK_MATCHER } from "../hooks/tools.js";
|
|
4
4
|
export declare const DEFT_HOOK_COMMAND_MARKER = "deft hook:dispatch";
|
|
5
5
|
export declare const AGENT_HOOK_PATHS: readonly [".claude/settings.json", ".grok/hooks/deft.json", ".cursor/hooks.json", ".codex/hooks.json"];
|
|
6
6
|
export type AgentHookPath = (typeof AGENT_HOOK_PATHS)[number];
|
|
7
7
|
export type AgentHookRegistrationStatus = "healthy" | "missing" | "drifted";
|
|
8
|
+
/** Whether the host receives a compact/resume hook deposit (#2113). */
|
|
9
|
+
export type AgentHookCompactSupport = "deposited" | "unsupported";
|
|
8
10
|
export interface AgentHookInspection {
|
|
9
11
|
readonly host: HookHost;
|
|
10
12
|
readonly path: AgentHookPath;
|
|
11
13
|
readonly status: AgentHookRegistrationStatus;
|
|
12
14
|
readonly detail: string;
|
|
15
|
+
readonly compactSupport: AgentHookCompactSupport;
|
|
13
16
|
}
|
|
14
17
|
export interface AgentHookDepositResult {
|
|
15
18
|
readonly changed: boolean;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { assertDepositContained } from "../deposit/contain.js";
|
|
4
|
-
import {
|
|
5
|
-
export
|
|
4
|
+
import { DIRECT_WRITE_HOOK_MATCHER, SPAWN_HOOK_MATCHER } from "../hooks/tools.js";
|
|
5
|
+
export { DIRECT_WRITE_HOOK_MATCHER, SPAWN_HOOK_MATCHER } from "../hooks/tools.js";
|
|
6
6
|
export const DEFT_HOOK_COMMAND_MARKER = "deft hook:dispatch";
|
|
7
7
|
export const AGENT_HOOK_PATHS = [
|
|
8
8
|
".claude/settings.json",
|
|
@@ -67,9 +67,9 @@ function isManagedCursorEntry(value) {
|
|
|
67
67
|
const entry = object(value);
|
|
68
68
|
return typeof entry?.command === "string" && entry.command.includes(DEFT_HOOK_COMMAND_MARKER);
|
|
69
69
|
}
|
|
70
|
-
function nestedGroup(host, event) {
|
|
70
|
+
function nestedGroup(host, event, matcher) {
|
|
71
71
|
return {
|
|
72
|
-
...(event === "tool.before" ? { matcher
|
|
72
|
+
...(event === "tool.before" && matcher !== undefined ? { matcher } : {}),
|
|
73
73
|
hooks: [
|
|
74
74
|
{
|
|
75
75
|
type: "command",
|
|
@@ -79,18 +79,29 @@ function nestedGroup(host, event) {
|
|
|
79
79
|
],
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
function mergeNestedConfig(config, path, host) {
|
|
82
|
+
function mergeNestedConfig(config, path, host, options = {}) {
|
|
83
83
|
const hooks = hooksObject(config, path);
|
|
84
84
|
const session = eventArray(hooks, "SessionStart", path).filter((entry) => !isManagedNestedGroup(entry));
|
|
85
85
|
const preTool = eventArray(hooks, "PreToolUse", path).filter((entry) => !isManagedNestedGroup(entry));
|
|
86
86
|
hooks.SessionStart = [...session, nestedGroup(host, "session.start")];
|
|
87
|
-
hooks.PreToolUse = [
|
|
87
|
+
hooks.PreToolUse = [
|
|
88
|
+
...preTool,
|
|
89
|
+
nestedGroup(host, "tool.before", DIRECT_WRITE_HOOK_MATCHER),
|
|
90
|
+
nestedGroup(host, "tool.before", SPAWN_HOOK_MATCHER),
|
|
91
|
+
];
|
|
92
|
+
if (options.compact) {
|
|
93
|
+
const preCompact = eventArray(hooks, "PreCompact", path).filter((entry) => !isManagedNestedGroup(entry));
|
|
94
|
+
const postCompact = eventArray(hooks, "PostCompact", path).filter((entry) => !isManagedNestedGroup(entry));
|
|
95
|
+
hooks.PreCompact = [...preCompact, nestedGroup(host, "session.compact")];
|
|
96
|
+
hooks.PostCompact = [...postCompact, nestedGroup(host, "session.compact")];
|
|
97
|
+
}
|
|
88
98
|
return { ...config, hooks };
|
|
89
99
|
}
|
|
90
100
|
function mergeCursorConfig(config, path) {
|
|
91
101
|
const hooks = hooksObject(config, path);
|
|
92
102
|
const session = eventArray(hooks, "sessionStart", path).filter((entry) => !isManagedCursorEntry(entry));
|
|
93
103
|
const preTool = eventArray(hooks, "preToolUse", path).filter((entry) => !isManagedCursorEntry(entry));
|
|
104
|
+
const preCompact = eventArray(hooks, "preCompact", path).filter((entry) => !isManagedCursorEntry(entry));
|
|
94
105
|
hooks.sessionStart = [...session, { command: command("cursor", "session.start"), timeout: 5 }];
|
|
95
106
|
hooks.preToolUse = [
|
|
96
107
|
...preTool,
|
|
@@ -100,7 +111,14 @@ function mergeCursorConfig(config, path) {
|
|
|
100
111
|
failClosed: true,
|
|
101
112
|
timeout: 5,
|
|
102
113
|
},
|
|
114
|
+
{
|
|
115
|
+
command: command("cursor", "tool.before"),
|
|
116
|
+
matcher: SPAWN_HOOK_MATCHER,
|
|
117
|
+
failClosed: true,
|
|
118
|
+
timeout: 5,
|
|
119
|
+
},
|
|
103
120
|
];
|
|
121
|
+
hooks.preCompact = [...preCompact, { command: command("cursor", "session.compact"), timeout: 5 }];
|
|
104
122
|
return { ...config, version: 1, hooks };
|
|
105
123
|
}
|
|
106
124
|
function writeJsonIfChanged(path, payload) {
|
|
@@ -119,16 +137,16 @@ export function writeAgentHookDeposit(projectRoot, io = { printf: () => undefine
|
|
|
119
137
|
const definitions = [
|
|
120
138
|
{
|
|
121
139
|
path: AGENT_HOOK_PATHS[0],
|
|
122
|
-
merge: (config, path) => mergeNestedConfig(config, path, "claude"),
|
|
140
|
+
merge: (config, path) => mergeNestedConfig(config, path, "claude", { compact: true }),
|
|
123
141
|
},
|
|
124
142
|
{
|
|
125
143
|
path: AGENT_HOOK_PATHS[1],
|
|
126
|
-
merge: (config, path) => mergeNestedConfig(config, path, "grok"),
|
|
144
|
+
merge: (config, path) => mergeNestedConfig(config, path, "grok", { compact: true }),
|
|
127
145
|
},
|
|
128
146
|
{ path: AGENT_HOOK_PATHS[2], merge: mergeCursorConfig },
|
|
129
147
|
{
|
|
130
148
|
path: AGENT_HOOK_PATHS[3],
|
|
131
|
-
merge: (config, path) => mergeNestedConfig(config, path, "codex"),
|
|
149
|
+
merge: (config, path) => mergeNestedConfig(config, path, "codex", { compact: false }),
|
|
132
150
|
},
|
|
133
151
|
];
|
|
134
152
|
const prepared = definitions.map((definition) => {
|
|
@@ -150,7 +168,7 @@ export function writeAgentHookDeposit(projectRoot, io = { printf: () => undefine
|
|
|
150
168
|
}
|
|
151
169
|
return { changed: changedPaths.length > 0, changedPaths };
|
|
152
170
|
}
|
|
153
|
-
function hasNestedRegistration(config, host) {
|
|
171
|
+
function hasNestedRegistration(config, host, options = {}) {
|
|
154
172
|
const hooks = object(config.hooks);
|
|
155
173
|
if (hooks === null)
|
|
156
174
|
return false;
|
|
@@ -158,11 +176,24 @@ function hasNestedRegistration(config, host) {
|
|
|
158
176
|
const preTool = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
159
177
|
const sessionCommand = command(host, "session.start");
|
|
160
178
|
const toolCommand = command(host, "tool.before");
|
|
161
|
-
|
|
179
|
+
const compactCommand = command(host, "session.compact");
|
|
180
|
+
const base = session.some((entry) => nestedCommands(entry).includes(sessionCommand)) &&
|
|
162
181
|
preTool.some((entry) => {
|
|
163
182
|
const group = object(entry);
|
|
164
183
|
return (group?.matcher === DIRECT_WRITE_HOOK_MATCHER && nestedCommands(entry).includes(toolCommand));
|
|
165
|
-
})
|
|
184
|
+
}) &&
|
|
185
|
+
preTool.some((entry) => {
|
|
186
|
+
const group = object(entry);
|
|
187
|
+
return group?.matcher === SPAWN_HOOK_MATCHER && nestedCommands(entry).includes(toolCommand);
|
|
188
|
+
});
|
|
189
|
+
if (!base)
|
|
190
|
+
return false;
|
|
191
|
+
if (!options.compact)
|
|
192
|
+
return true;
|
|
193
|
+
const preCompact = Array.isArray(hooks.PreCompact) ? hooks.PreCompact : [];
|
|
194
|
+
const postCompact = Array.isArray(hooks.PostCompact) ? hooks.PostCompact : [];
|
|
195
|
+
return (preCompact.some((entry) => nestedCommands(entry).includes(compactCommand)) &&
|
|
196
|
+
postCompact.some((entry) => nestedCommands(entry).includes(compactCommand)));
|
|
166
197
|
}
|
|
167
198
|
function hasCursorRegistration(config) {
|
|
168
199
|
const hooks = object(config.hooks);
|
|
@@ -170,13 +201,21 @@ function hasCursorRegistration(config) {
|
|
|
170
201
|
return false;
|
|
171
202
|
const session = Array.isArray(hooks.sessionStart) ? hooks.sessionStart : [];
|
|
172
203
|
const preTool = Array.isArray(hooks.preToolUse) ? hooks.preToolUse : [];
|
|
204
|
+
const preCompact = Array.isArray(hooks.preCompact) ? hooks.preCompact : [];
|
|
173
205
|
return (session.some((entry) => object(entry)?.command === command("cursor", "session.start")) &&
|
|
174
206
|
preTool.some((entry) => {
|
|
175
207
|
const hook = object(entry);
|
|
176
208
|
return (hook?.command === command("cursor", "tool.before") &&
|
|
177
209
|
hook.matcher === DIRECT_WRITE_HOOK_MATCHER &&
|
|
178
210
|
hook.failClosed === true);
|
|
179
|
-
})
|
|
211
|
+
}) &&
|
|
212
|
+
preTool.some((entry) => {
|
|
213
|
+
const hook = object(entry);
|
|
214
|
+
return (hook?.command === command("cursor", "tool.before") &&
|
|
215
|
+
hook.matcher === SPAWN_HOOK_MATCHER &&
|
|
216
|
+
hook.failClosed === true);
|
|
217
|
+
}) &&
|
|
218
|
+
preCompact.some((entry) => object(entry)?.command === command("cursor", "session.compact")));
|
|
180
219
|
}
|
|
181
220
|
/** Read-only registration probe shared by verify and doctor. */
|
|
182
221
|
export function inspectAgentHookDeposit(projectRoot) {
|
|
@@ -184,28 +223,40 @@ export function inspectAgentHookDeposit(projectRoot) {
|
|
|
184
223
|
{
|
|
185
224
|
host: "claude",
|
|
186
225
|
path: AGENT_HOOK_PATHS[0],
|
|
187
|
-
|
|
226
|
+
compactSupport: "deposited",
|
|
227
|
+
valid: (config) => hasNestedRegistration(config, "claude", { compact: true }),
|
|
188
228
|
},
|
|
189
229
|
{
|
|
190
230
|
host: "grok",
|
|
191
231
|
path: AGENT_HOOK_PATHS[1],
|
|
192
|
-
|
|
232
|
+
compactSupport: "deposited",
|
|
233
|
+
valid: (config) => hasNestedRegistration(config, "grok", { compact: true }),
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
host: "cursor",
|
|
237
|
+
path: AGENT_HOOK_PATHS[2],
|
|
238
|
+
compactSupport: "deposited",
|
|
239
|
+
valid: hasCursorRegistration,
|
|
193
240
|
},
|
|
194
|
-
{ host: "cursor", path: AGENT_HOOK_PATHS[2], valid: hasCursorRegistration },
|
|
195
241
|
{
|
|
196
242
|
host: "codex",
|
|
197
243
|
path: AGENT_HOOK_PATHS[3],
|
|
198
|
-
|
|
244
|
+
compactSupport: "unsupported",
|
|
245
|
+
valid: (config) => hasNestedRegistration(config, "codex", { compact: false }),
|
|
199
246
|
},
|
|
200
247
|
];
|
|
201
248
|
return definitions.map((definition) => {
|
|
202
249
|
const absolute = join(projectRoot, definition.path);
|
|
250
|
+
const compactNote = definition.compactSupport === "unsupported"
|
|
251
|
+
? " Compact re-arm is not deposited for Codex (no native compact hook surface)."
|
|
252
|
+
: " PreCompact/PostCompact or preCompact compact re-arm is deposited.";
|
|
203
253
|
if (!existsSync(absolute)) {
|
|
204
254
|
return {
|
|
205
255
|
host: definition.host,
|
|
206
256
|
path: definition.path,
|
|
207
257
|
status: "missing",
|
|
208
|
-
|
|
258
|
+
compactSupport: definition.compactSupport,
|
|
259
|
+
detail: `${definition.path} is missing.${compactNote}`,
|
|
209
260
|
};
|
|
210
261
|
}
|
|
211
262
|
try {
|
|
@@ -215,14 +266,18 @@ export function inspectAgentHookDeposit(projectRoot) {
|
|
|
215
266
|
host: definition.host,
|
|
216
267
|
path: definition.path,
|
|
217
268
|
status: "healthy",
|
|
218
|
-
|
|
269
|
+
compactSupport: definition.compactSupport,
|
|
270
|
+
detail: "SessionStart, direct-write + spawn PreToolUse, and compact re-arm registrations are current." +
|
|
271
|
+
(definition.compactSupport === "unsupported" ? compactNote : ""),
|
|
219
272
|
};
|
|
220
273
|
}
|
|
221
274
|
return {
|
|
222
275
|
host: definition.host,
|
|
223
276
|
path: definition.path,
|
|
224
277
|
status: "drifted",
|
|
225
|
-
|
|
278
|
+
compactSupport: definition.compactSupport,
|
|
279
|
+
detail: "Directive SessionStart, direct-write/spawn PreToolUse, or compact re-arm registration is missing/drifted." +
|
|
280
|
+
compactNote,
|
|
226
281
|
};
|
|
227
282
|
}
|
|
228
283
|
catch (cause) {
|
|
@@ -230,7 +285,8 @@ export function inspectAgentHookDeposit(projectRoot) {
|
|
|
230
285
|
host: definition.host,
|
|
231
286
|
path: definition.path,
|
|
232
287
|
status: "drifted",
|
|
233
|
-
|
|
288
|
+
compactSupport: definition.compactSupport,
|
|
289
|
+
detail: `${String(cause)}${compactNote}`,
|
|
234
290
|
};
|
|
235
291
|
}
|
|
236
292
|
});
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ export * from "./decisions.js";
|
|
|
5
5
|
export * from "./disclosure.js";
|
|
6
6
|
export * from "./plan-extensions.js";
|
|
7
7
|
export * from "./policy-invocation.js";
|
|
8
|
+
export * from "./product-signal.js";
|
|
8
9
|
export * from "./resolve.js";
|
|
10
|
+
export * from "./runtime-authority.js";
|
|
11
|
+
export * from "./staleness-tickler.js";
|
|
9
12
|
export * from "./value-feedback.js";
|
|
10
13
|
export * from "./wip.js";
|
|
11
14
|
export declare const FIELD_ALLOW_DIRECT_COMMITS = "plan.policy.allowDirectCommitsToMaster";
|
package/dist/policy/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { readPlanPolicy } from "./plan-extensions.js";
|
|
2
|
+
import { FIELD_PRODUCT_SIGNAL, FIELD_PRODUCT_SIGNAL_CLI_ALIAS, inspectProductSignal, } from "./product-signal.js";
|
|
2
3
|
import { coerceLegacyNarrative, LEGACY_NARRATIVE_KEY, loadProjectDefinition } from "./resolve.js";
|
|
4
|
+
import { FIELD_RUNTIME_AUTHORITY, FIELD_RUNTIME_AUTHORITY_CLI_ALIAS, inspectRuntimeAuthority, } from "./runtime-authority.js";
|
|
5
|
+
import { FIELD_STALENESS_TICKLER, FIELD_STALENESS_TICKLER_CLI_ALIAS, inspectStalenessTickler, } from "./staleness-tickler.js";
|
|
3
6
|
import { FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, inspectValueFeedback, } from "./value-feedback.js";
|
|
4
7
|
import { DEFAULT_WIP_CAP } from "./wip.js";
|
|
5
8
|
export * from "./agents-md-advisory.js";
|
|
@@ -9,7 +12,10 @@ export * from "./decisions.js";
|
|
|
9
12
|
export * from "./disclosure.js";
|
|
10
13
|
export * from "./plan-extensions.js";
|
|
11
14
|
export * from "./policy-invocation.js";
|
|
15
|
+
export * from "./product-signal.js";
|
|
12
16
|
export * from "./resolve.js";
|
|
17
|
+
export * from "./runtime-authority.js";
|
|
18
|
+
export * from "./staleness-tickler.js";
|
|
13
19
|
export * from "./value-feedback.js";
|
|
14
20
|
export * from "./wip.js";
|
|
15
21
|
export const FIELD_ALLOW_DIRECT_COMMITS = "plan.policy.allowDirectCommitsToMaster";
|
|
@@ -216,6 +222,15 @@ function inspectSwarmSubagentBackend(data) {
|
|
|
216
222
|
source: "default-on-error",
|
|
217
223
|
};
|
|
218
224
|
}
|
|
225
|
+
function inspectProductSignalField(data, projectRoot) {
|
|
226
|
+
const field = inspectProductSignal(data, projectRoot);
|
|
227
|
+
return {
|
|
228
|
+
name: field.name,
|
|
229
|
+
current: field.current,
|
|
230
|
+
default: field.default,
|
|
231
|
+
source: field.source,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
219
234
|
function inspectValueFeedbackField(data, projectRoot) {
|
|
220
235
|
const field = inspectValueFeedback(data, projectRoot);
|
|
221
236
|
return {
|
|
@@ -225,6 +240,24 @@ function inspectValueFeedbackField(data, projectRoot) {
|
|
|
225
240
|
source: field.source,
|
|
226
241
|
};
|
|
227
242
|
}
|
|
243
|
+
function inspectStalenessTicklerField(data) {
|
|
244
|
+
const field = inspectStalenessTickler(data);
|
|
245
|
+
return {
|
|
246
|
+
name: field.name,
|
|
247
|
+
current: field.current,
|
|
248
|
+
default: field.default,
|
|
249
|
+
source: field.source,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function inspectRuntimeAuthorityField(data) {
|
|
253
|
+
const field = inspectRuntimeAuthority(data);
|
|
254
|
+
return {
|
|
255
|
+
name: field.name,
|
|
256
|
+
current: field.current,
|
|
257
|
+
default: field.default,
|
|
258
|
+
source: field.source,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
228
261
|
const REGISTERED_POLICIES = [
|
|
229
262
|
inspectAllowDirectCommits,
|
|
230
263
|
inspectWipCap,
|
|
@@ -237,6 +270,9 @@ const REGISTERED_POLICIES = [
|
|
|
237
270
|
emptyIsTyped: true,
|
|
238
271
|
}),
|
|
239
272
|
inspectSwarmSubagentBackend,
|
|
273
|
+
inspectStalenessTicklerField,
|
|
274
|
+
inspectRuntimeAuthorityField,
|
|
275
|
+
inspectProductSignalField,
|
|
240
276
|
inspectValueFeedbackField,
|
|
241
277
|
];
|
|
242
278
|
/** Walk registered inspectors and return one row per field (#1148). */
|
|
@@ -246,7 +282,15 @@ export function inspectAllPolicies(projectRoot) {
|
|
|
246
282
|
}
|
|
247
283
|
/** Look up a single registered field by canonical dotted-path name (or CLI alias). */
|
|
248
284
|
export function inspectOnePolicy(name, projectRoot) {
|
|
249
|
-
const normalized = name === FIELD_VALUE_FEEDBACK_CLI_ALIAS
|
|
285
|
+
const normalized = name === FIELD_VALUE_FEEDBACK_CLI_ALIAS
|
|
286
|
+
? FIELD_VALUE_FEEDBACK
|
|
287
|
+
: name === FIELD_PRODUCT_SIGNAL_CLI_ALIAS
|
|
288
|
+
? FIELD_PRODUCT_SIGNAL
|
|
289
|
+
: name === FIELD_STALENESS_TICKLER_CLI_ALIAS
|
|
290
|
+
? FIELD_STALENESS_TICKLER
|
|
291
|
+
: name === FIELD_RUNTIME_AUTHORITY_CLI_ALIAS
|
|
292
|
+
? FIELD_RUNTIME_AUTHORITY
|
|
293
|
+
: name;
|
|
250
294
|
for (const field of inspectAllPolicies(projectRoot)) {
|
|
251
295
|
if (field.name === normalized)
|
|
252
296
|
return field;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Canonical registered policy field name (#2693). */
|
|
2
|
+
export declare const FIELD_PRODUCT_SIGNAL = "plan.policy.productSignal";
|
|
3
|
+
/** Short alias for `policy:show --field=productSignal`. */
|
|
4
|
+
export declare const FIELD_PRODUCT_SIGNAL_CLI_ALIAS = "productSignal";
|
|
5
|
+
export declare const DEFAULT_PRODUCT_SIGNAL_ENABLED = false;
|
|
6
|
+
/** Baked-in default private sink (#2693 D6). */
|
|
7
|
+
export declare const DEFAULT_PRODUCT_SIGNAL_SINK_REPO = "deftai/product-signal";
|
|
8
|
+
export interface ProductSignalConfig {
|
|
9
|
+
readonly enabled: boolean;
|
|
10
|
+
readonly sinkRepo: string;
|
|
11
|
+
}
|
|
12
|
+
export type ProductSignalSource = "typed" | "default" | "default-on-error";
|
|
13
|
+
export interface ProductSignalResolved extends ProductSignalConfig {
|
|
14
|
+
readonly source: ProductSignalSource;
|
|
15
|
+
readonly error: string | null;
|
|
16
|
+
}
|
|
17
|
+
export declare const PRODUCT_SIGNAL_CAPABILITY_COST_DISCLOSURE: string;
|
|
18
|
+
/** Validate a `plan.policy.productSignal` payload. */
|
|
19
|
+
export declare function validateProductSignal(value: unknown): string[];
|
|
20
|
+
/** Resolve `plan.policy.productSignal` from PROJECT-DEFINITION (#2693). */
|
|
21
|
+
export declare function resolveProductSignal(projectRoot: string): ProductSignalResolved;
|
|
22
|
+
/** Human-readable status line for CLI surfaces. */
|
|
23
|
+
export declare function formatProductSignalStatusLine(policy: ProductSignalResolved): string;
|
|
24
|
+
export interface ProductSignalPolicyField {
|
|
25
|
+
readonly name: typeof FIELD_PRODUCT_SIGNAL;
|
|
26
|
+
readonly current: ProductSignalConfig;
|
|
27
|
+
readonly default: ProductSignalConfig;
|
|
28
|
+
readonly source: string;
|
|
29
|
+
}
|
|
30
|
+
/** Inspector row for `policy:show --field=productSignal`. */
|
|
31
|
+
export declare function inspectProductSignal(data: Record<string, unknown> | null, projectRoot?: string): ProductSignalPolicyField;
|
|
32
|
+
export interface EnableProductSignalOptions {
|
|
33
|
+
readonly confirm: boolean;
|
|
34
|
+
readonly actor?: string;
|
|
35
|
+
readonly note?: string;
|
|
36
|
+
readonly sinkRepo?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface EnableProductSignalResult {
|
|
39
|
+
readonly exitCode: 0 | 1 | 2;
|
|
40
|
+
readonly stdout: string;
|
|
41
|
+
readonly changed: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Persist `productSignal.enabled=true` after capability-cost disclosure (#2693). */
|
|
44
|
+
export declare function enableProductSignal(projectRoot: string, options: EnableProductSignalOptions): EnableProductSignalResult;
|
|
45
|
+
//# sourceMappingURL=product-signal.d.ts.map
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { atomicWriteProjectDefinition, projectDefinitionMutationLock, } from "../vbrief-build/project-definition-io.js";
|
|
3
|
+
import { migrateLegacyPolicyKey, PLAN_POLICY_KEY, readPlanPolicy } from "./plan-extensions.js";
|
|
4
|
+
import { policyColonInvocation } from "./policy-invocation.js";
|
|
5
|
+
import { appendAuditLog, loadProjectDefinition, projectDefinitionPath } from "./resolve.js";
|
|
6
|
+
/** Canonical registered policy field name (#2693). */
|
|
7
|
+
export const FIELD_PRODUCT_SIGNAL = "plan.policy.productSignal";
|
|
8
|
+
/** Short alias for `policy:show --field=productSignal`. */
|
|
9
|
+
export const FIELD_PRODUCT_SIGNAL_CLI_ALIAS = "productSignal";
|
|
10
|
+
export const DEFAULT_PRODUCT_SIGNAL_ENABLED = false;
|
|
11
|
+
/** Baked-in default private sink (#2693 D6). */
|
|
12
|
+
export const DEFAULT_PRODUCT_SIGNAL_SINK_REPO = "deftai/product-signal";
|
|
13
|
+
export const PRODUCT_SIGNAL_CAPABILITY_COST_DISCLOSURE = "\u26a0 Capability-cost disclosure -- enabling product signal opts into " +
|
|
14
|
+
"consented qualitative check-ins that may submit minimized local summaries " +
|
|
15
|
+
"to a private GitHub sink when you also grant install-level consent.\n" +
|
|
16
|
+
" \u2022 Default OFF; no ambient consent nag while disabled.\n" +
|
|
17
|
+
" \u2022 Outbound requires enable + recorded consent (`product-signal:consent`).\n" +
|
|
18
|
+
" \u2022 Payloads include install context and windowed value/health/helped summaries " +
|
|
19
|
+
"(not raw ledgers or chat).\n" +
|
|
20
|
+
" \u2022 Inspect: `" +
|
|
21
|
+
policyColonInvocation("show", " --field=productSignal") +
|
|
22
|
+
"` and `task product-signal:status`.\n" +
|
|
23
|
+
" \u2022 Reversible: set `enabled: false` or revoke consent.\n" +
|
|
24
|
+
" \u2022 Changes are recorded to meta/policy-changes.log for auditability.";
|
|
25
|
+
function defaultResolved(source, error = null) {
|
|
26
|
+
return {
|
|
27
|
+
enabled: DEFAULT_PRODUCT_SIGNAL_ENABLED,
|
|
28
|
+
sinkRepo: DEFAULT_PRODUCT_SIGNAL_SINK_REPO,
|
|
29
|
+
source,
|
|
30
|
+
error,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Validate a `plan.policy.productSignal` payload. */
|
|
34
|
+
export function validateProductSignal(value) {
|
|
35
|
+
if (value === null || value === undefined) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
39
|
+
return [`${FIELD_PRODUCT_SIGNAL} must be an object; got ${typeof value}`];
|
|
40
|
+
}
|
|
41
|
+
const rec = value;
|
|
42
|
+
const errors = [];
|
|
43
|
+
if ("enabled" in rec && typeof rec.enabled !== "boolean") {
|
|
44
|
+
errors.push(`${FIELD_PRODUCT_SIGNAL}.enabled must be a boolean`);
|
|
45
|
+
}
|
|
46
|
+
if ("sinkRepo" in rec && typeof rec.sinkRepo !== "string") {
|
|
47
|
+
errors.push(`${FIELD_PRODUCT_SIGNAL}.sinkRepo must be a string`);
|
|
48
|
+
}
|
|
49
|
+
return errors;
|
|
50
|
+
}
|
|
51
|
+
function resolveFromPolicyBlock(raw) {
|
|
52
|
+
const errors = validateProductSignal(raw);
|
|
53
|
+
if (errors.length > 0) {
|
|
54
|
+
return defaultResolved("default-on-error", errors[0] ?? "invalid productSignal block");
|
|
55
|
+
}
|
|
56
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
57
|
+
return defaultResolved("default");
|
|
58
|
+
}
|
|
59
|
+
const block = raw;
|
|
60
|
+
const enabled = typeof block.enabled === "boolean" ? block.enabled : DEFAULT_PRODUCT_SIGNAL_ENABLED;
|
|
61
|
+
const sinkRepo = typeof block.sinkRepo === "string" && block.sinkRepo.trim().length > 0
|
|
62
|
+
? block.sinkRepo.trim()
|
|
63
|
+
: DEFAULT_PRODUCT_SIGNAL_SINK_REPO;
|
|
64
|
+
return {
|
|
65
|
+
enabled,
|
|
66
|
+
sinkRepo,
|
|
67
|
+
source: "typed",
|
|
68
|
+
error: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Resolve `plan.policy.productSignal` from PROJECT-DEFINITION (#2693). */
|
|
72
|
+
export function resolveProductSignal(projectRoot) {
|
|
73
|
+
const [data, err] = loadProjectDefinition(projectRoot);
|
|
74
|
+
if (data === null) {
|
|
75
|
+
return defaultResolved("default-on-error", err);
|
|
76
|
+
}
|
|
77
|
+
const policyBlock = readPlanPolicy(data.plan);
|
|
78
|
+
if (typeof policyBlock !== "object" ||
|
|
79
|
+
policyBlock === null ||
|
|
80
|
+
Array.isArray(policyBlock) ||
|
|
81
|
+
!("productSignal" in policyBlock)) {
|
|
82
|
+
return defaultResolved("default");
|
|
83
|
+
}
|
|
84
|
+
return resolveFromPolicyBlock(policyBlock.productSignal);
|
|
85
|
+
}
|
|
86
|
+
/** Human-readable status line for CLI surfaces. */
|
|
87
|
+
export function formatProductSignalStatusLine(policy) {
|
|
88
|
+
return (`[deft policy] productSignal enabled=${String(policy.enabled)} ` +
|
|
89
|
+
`sinkRepo=${policy.sinkRepo}.`);
|
|
90
|
+
}
|
|
91
|
+
function fieldFromResolved(resolved) {
|
|
92
|
+
return {
|
|
93
|
+
name: FIELD_PRODUCT_SIGNAL,
|
|
94
|
+
current: {
|
|
95
|
+
enabled: resolved.enabled,
|
|
96
|
+
sinkRepo: resolved.sinkRepo,
|
|
97
|
+
},
|
|
98
|
+
default: {
|
|
99
|
+
enabled: DEFAULT_PRODUCT_SIGNAL_ENABLED,
|
|
100
|
+
sinkRepo: DEFAULT_PRODUCT_SIGNAL_SINK_REPO,
|
|
101
|
+
},
|
|
102
|
+
source: resolved.source,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** Inspector row for `policy:show --field=productSignal`. */
|
|
106
|
+
export function inspectProductSignal(data, projectRoot) {
|
|
107
|
+
if (data === null) {
|
|
108
|
+
return fieldFromResolved(defaultResolved("default"));
|
|
109
|
+
}
|
|
110
|
+
const policyBlock = readPlanPolicy(data.plan);
|
|
111
|
+
if (typeof policyBlock !== "object" ||
|
|
112
|
+
policyBlock === null ||
|
|
113
|
+
Array.isArray(policyBlock) ||
|
|
114
|
+
!("productSignal" in policyBlock)) {
|
|
115
|
+
if (projectRoot !== undefined) {
|
|
116
|
+
return fieldFromResolved(resolveProductSignal(projectRoot));
|
|
117
|
+
}
|
|
118
|
+
return fieldFromResolved(defaultResolved("default"));
|
|
119
|
+
}
|
|
120
|
+
return fieldFromResolved(resolveFromPolicyBlock(policyBlock.productSignal));
|
|
121
|
+
}
|
|
122
|
+
/** Persist `productSignal.enabled=true` after capability-cost disclosure (#2693). */
|
|
123
|
+
export function enableProductSignal(projectRoot, options) {
|
|
124
|
+
if (!options.confirm) {
|
|
125
|
+
return {
|
|
126
|
+
exitCode: 1,
|
|
127
|
+
stdout: `${PRODUCT_SIGNAL_CAPABILITY_COST_DISCLOSURE}\n\n` +
|
|
128
|
+
`Re-run with --confirm to apply: task product-signal:enable -- --confirm\n`,
|
|
129
|
+
changed: false,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const path = projectDefinitionPath(projectRoot);
|
|
133
|
+
try {
|
|
134
|
+
const { changed } = projectDefinitionMutationLock(projectRoot, () => {
|
|
135
|
+
const parsed = JSON.parse(readFileSync(path, { encoding: "utf8" }));
|
|
136
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
137
|
+
throw new Error(`PROJECT-DEFINITION at ${path} top-level value is not a JSON object`);
|
|
138
|
+
}
|
|
139
|
+
const data = parsed;
|
|
140
|
+
if (typeof data.plan !== "object" || data.plan === null || Array.isArray(data.plan)) {
|
|
141
|
+
if (data.plan === undefined) {
|
|
142
|
+
data.plan = {};
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new Error("PROJECT-DEFINITION 'plan' is not an object");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const plan = data.plan;
|
|
149
|
+
migrateLegacyPolicyKey(plan);
|
|
150
|
+
const existingPolicy = plan[PLAN_POLICY_KEY];
|
|
151
|
+
if (typeof existingPolicy !== "object" ||
|
|
152
|
+
existingPolicy === null ||
|
|
153
|
+
Array.isArray(existingPolicy)) {
|
|
154
|
+
if (existingPolicy === undefined) {
|
|
155
|
+
plan[PLAN_POLICY_KEY] = {};
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
throw new Error("plan.policy is not an object");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const policyBlock = plan[PLAN_POLICY_KEY];
|
|
162
|
+
const previous = policyBlock.productSignal;
|
|
163
|
+
const prevObj = typeof previous === "object" && previous !== null && !Array.isArray(previous)
|
|
164
|
+
? previous
|
|
165
|
+
: {};
|
|
166
|
+
const sinkRepo = options.sinkRepo?.trim() ||
|
|
167
|
+
(typeof prevObj.sinkRepo === "string" && prevObj.sinkRepo.trim().length > 0
|
|
168
|
+
? prevObj.sinkRepo.trim()
|
|
169
|
+
: DEFAULT_PRODUCT_SIGNAL_SINK_REPO);
|
|
170
|
+
const nextBlock = { enabled: true, sinkRepo };
|
|
171
|
+
const previousNormalized = resolveFromPolicyBlock(previous);
|
|
172
|
+
const changedFlag = previousNormalized.enabled !== nextBlock.enabled ||
|
|
173
|
+
previousNormalized.sinkRepo !== nextBlock.sinkRepo;
|
|
174
|
+
policyBlock.productSignal = nextBlock;
|
|
175
|
+
if (changedFlag) {
|
|
176
|
+
atomicWriteProjectDefinition(path, data);
|
|
177
|
+
}
|
|
178
|
+
const actor = options.actor ?? "task product-signal:enable";
|
|
179
|
+
const note = options.note ?? "";
|
|
180
|
+
const parts = [
|
|
181
|
+
`actor=${actor}`,
|
|
182
|
+
"productSignal.enabled=true",
|
|
183
|
+
`sinkRepo=${sinkRepo}`,
|
|
184
|
+
`previous=${JSON.stringify(previous ?? null)}`,
|
|
185
|
+
];
|
|
186
|
+
if (note) {
|
|
187
|
+
parts.push(`note=${note.replace(/\n/g, " ").replace(/\r/g, " ")}`);
|
|
188
|
+
}
|
|
189
|
+
appendAuditLog(projectRoot, parts.join(" "));
|
|
190
|
+
return { changed: changedFlag };
|
|
191
|
+
});
|
|
192
|
+
const resolved = resolveProductSignal(projectRoot);
|
|
193
|
+
const lines = [
|
|
194
|
+
`\u2713 ${FIELD_PRODUCT_SIGNAL}.enabled=true (product-signal ON).`,
|
|
195
|
+
changed
|
|
196
|
+
? " audit: meta/policy-changes.log updated."
|
|
197
|
+
: " no-op: value already matched (audit entry still appended for trail).",
|
|
198
|
+
formatProductSignalStatusLine(resolved),
|
|
199
|
+
];
|
|
200
|
+
return { exitCode: 0, stdout: `${lines.join("\n")}\n`, changed };
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
204
|
+
if (message.includes("PROJECT-DEFINITION not found")) {
|
|
205
|
+
return { exitCode: 2, stdout: `\u274c ${message}\n`, changed: false };
|
|
206
|
+
}
|
|
207
|
+
return { exitCode: 2, stdout: `\u274c Config error: ${message}\n`, changed: false };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=product-signal.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export declare const FIELD_RUNTIME_AUTHORITY = "plan.policy.runtimeAuthority";
|
|
2
|
+
export declare const FIELD_RUNTIME_AUTHORITY_CLI_ALIAS = "runtimeAuthority";
|
|
3
|
+
/** Graduated permission scopes (#1394 steipete ladder). */
|
|
4
|
+
export interface RuntimeAuthorityScopes {
|
|
5
|
+
/** Direct edit/write tools (PreToolUse classifiable today). */
|
|
6
|
+
readonly edits: boolean;
|
|
7
|
+
/** git push / tag push — enforced only when Shell payload is classifiable (host gap). */
|
|
8
|
+
readonly push: boolean;
|
|
9
|
+
/** merge / close / release — enforced only when Shell payload is classifiable (host gap). */
|
|
10
|
+
readonly merge: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RuntimeAuthorityPolicy {
|
|
13
|
+
readonly enabled: boolean;
|
|
14
|
+
/** When non-empty, write targets must match at least one pattern. Empty = allow all paths. */
|
|
15
|
+
readonly allowPaths: readonly string[];
|
|
16
|
+
/** Deny wins over allow. */
|
|
17
|
+
readonly denyPaths: readonly string[];
|
|
18
|
+
readonly scopes: RuntimeAuthorityScopes;
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_RUNTIME_AUTHORITY_SCOPES: RuntimeAuthorityScopes;
|
|
21
|
+
/** Safe default: opt-in only — existing consumers see no runtime authority until enabled. */
|
|
22
|
+
export declare const DEFAULT_RUNTIME_AUTHORITY_POLICY: RuntimeAuthorityPolicy;
|
|
23
|
+
export interface RuntimeAuthorityPolicyField {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly current: RuntimeAuthorityPolicy;
|
|
26
|
+
readonly default: RuntimeAuthorityPolicy;
|
|
27
|
+
readonly source: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function resolveRuntimeAuthorityPolicy(raw: unknown): RuntimeAuthorityPolicy;
|
|
30
|
+
export declare function validateRuntimeAuthority(value: unknown): string[];
|
|
31
|
+
/** Inspector row for `policy:show --field=runtimeAuthority`. */
|
|
32
|
+
export declare function inspectRuntimeAuthority(data: Record<string, unknown> | null): RuntimeAuthorityPolicyField;
|
|
33
|
+
/** Resolve typed runtime authority policy from PROJECT-DEFINITION. */
|
|
34
|
+
export declare function loadRuntimeAuthorityPolicy(data: Record<string, unknown> | null): RuntimeAuthorityPolicy;
|
|
35
|
+
/** Load runtime authority from a project root (PROJECT-DEFINITION on disk). */
|
|
36
|
+
export declare function loadRuntimeAuthorityFromProject(projectRoot: string): RuntimeAuthorityPolicy;
|
|
37
|
+
export type RuntimeAuthorityPathVerdict = "allow" | "deny-allowlist" | "deny-denylist";
|
|
38
|
+
/** Evaluate a project-relative POSIX path against allow/deny globs. */
|
|
39
|
+
export declare function evaluateRuntimeAuthorityPath(policy: RuntimeAuthorityPolicy, relPathPosix: string): RuntimeAuthorityPathVerdict;
|
|
40
|
+
export interface RuntimeAuthorityDirectWriteInput {
|
|
41
|
+
readonly policy: RuntimeAuthorityPolicy;
|
|
42
|
+
readonly relPathPosix: string | null;
|
|
43
|
+
}
|
|
44
|
+
export interface RuntimeAuthorityDirectWriteResult {
|
|
45
|
+
readonly allowed: boolean;
|
|
46
|
+
readonly reason: string | null;
|
|
47
|
+
readonly code: "runtime-policy-deny-scope" | "runtime-policy-deny-path" | null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Evaluate direct-write runtime authority after ritual/scope gates (#1394).
|
|
51
|
+
* Unclassifiable paths (null) pass — host gap documented for Shell/MCP.
|
|
52
|
+
*/
|
|
53
|
+
export declare function evaluateRuntimeAuthorityDirectWrite(input: RuntimeAuthorityDirectWriteInput): RuntimeAuthorityDirectWriteResult;
|
|
54
|
+
//# sourceMappingURL=runtime-authority.d.ts.map
|