@haposoft/cafekit 0.18.0 → 0.18.2
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 +12 -1
- package/bin/__tests__/claude-settings.test.js +123 -0
- package/bin/__tests__/codex-ask-guard.test.js +123 -0
- package/bin/__tests__/codex-ask-projection.test.js +51 -0
- package/bin/__tests__/codex-hooks-ownership.test.js +80 -1
- package/bin/__tests__/codex-hooks.test.js +938 -237
- package/bin/__tests__/codex-native-hook-boundaries.test.js +136 -0
- package/bin/__tests__/codex-native.test.js +222 -149
- package/bin/__tests__/codex-projection-parity.test.js +314 -0
- package/bin/__tests__/codex-quiet-hooks.test.js +170 -0
- package/bin/__tests__/codex-research-projection.test.js +70 -0
- package/bin/__tests__/codex-specs-projection.test.js +76 -0
- package/bin/__tests__/develop-contract.test.js +102 -1362
- package/bin/__tests__/docs-sync-on-demand.test.js +25 -20
- package/bin/__tests__/inspect-paths.test.js +183 -0
- package/bin/__tests__/installer-safety.test.js +335 -0
- package/bin/__tests__/legacy-authority-decoupled.test.js +14 -19
- package/bin/__tests__/legacy-hooks-retired.test.js +18 -8
- package/bin/__tests__/omp-bridge.test.js +66 -12
- package/bin/__tests__/omp-hooks.test.js +11 -5
- package/bin/__tests__/orca-session.test.js +7 -0
- package/bin/__tests__/package-inventory.test.js +1 -395
- package/bin/__tests__/privacy-paths.test.js +317 -0
- package/bin/__tests__/spec-narrowing.test.js +30 -134
- package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -372
- package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
- package/bin/__tests__/usage-hook-retired.test.js +5 -3
- package/bin/__tests__/validator-grounding.test.js +17 -2929
- package/bin/install.js +25 -0
- package/bin/lib/codex-install.js +134 -12
- package/bin/lib/context.js +1 -1
- package/bin/lib/managed-writer.js +2 -3
- package/bin/phases/claude-runtime.js +91 -25
- package/bin/phases/claude-settings.js +22 -1
- package/bin/phases/codex-hooks.js +96 -33
- package/bin/phases/codex-runtime.js +45 -49
- package/bin/phases/copy-payload.js +11 -28
- package/bin/phases/omp-runtime.js +6 -3
- package/package.json +2 -3
- package/src/claude/CLAUDE.md +4 -0
- package/src/claude/agents/code-auditor.md +9 -6
- package/src/claude/agents/debugger.md +3 -9
- package/src/claude/agents/docs-keeper.md +4 -7
- package/src/claude/agents/git-ops.md +2 -4
- package/src/claude/agents/implementer.md +6 -7
- package/src/claude/agents/inspector.md +2 -0
- package/src/claude/agents/project-manager.md +2 -2
- package/src/claude/agents/spec-maker.md +4 -4
- package/src/claude/agents/test-runner.md +8 -11
- package/src/claude/agents/ui-ux-designer.md +0 -1
- package/src/claude/gitignore +3 -0
- package/src/claude/hooks/__tests__/installed-root.test.js +111 -0
- package/src/claude/hooks/__tests__/precompact.test.js +206 -10
- package/src/claude/hooks/__tests__/privacy-block.test.js +27 -0
- package/src/claude/hooks/__tests__/session-writeenv.test.js +25 -0
- package/src/claude/hooks/__tests__/spec-gate.test.js +311 -340
- package/src/claude/hooks/__tests__/spec-state-touched.test.js +230 -8
- package/src/claude/hooks/__tests__/state.test.js +207 -7
- package/src/claude/hooks/__tests__/update-check.test.js +88 -0
- package/src/claude/hooks/agent.cjs +7 -6
- package/src/claude/hooks/inspect-block.cjs +15 -63
- package/src/claude/hooks/lib/inspect-paths.cjs +304 -0
- package/src/claude/hooks/lib/parser.cjs +1 -1
- package/src/claude/hooks/lib/privacy-command-analysis.cjs +191 -17
- package/src/claude/hooks/lib/privacy-paths.cjs +313 -0
- package/src/claude/hooks/lib/project-root.cjs +15 -0
- package/src/claude/hooks/lib/rules-reservation.cjs +36 -0
- package/src/claude/hooks/lib/spec-touch.cjs +67 -0
- package/src/claude/hooks/lib/update-check.cjs +77 -0
- package/src/claude/hooks/precompact.cjs +8 -15
- package/src/claude/hooks/privacy-block.cjs +23 -205
- package/src/claude/hooks/rules.cjs +6 -28
- package/src/claude/hooks/session.cjs +34 -117
- package/src/claude/hooks/spec-gate.cjs +17 -89
- package/src/claude/hooks/spec-state.cjs +89 -96
- package/src/claude/hooks/state.cjs +96 -51
- package/src/claude/migration-manifest.json +20 -8
- package/src/claude/output-styles/coding-level-0-eli5.md +9 -9
- package/src/claude/output-styles/coding-level-1-junior.md +3 -3
- package/src/claude/output-styles/coding-level-2-mid.md +3 -3
- package/src/claude/output-styles/coding-level-3-senior.md +2 -2
- package/src/claude/output-styles/coding-level-4-lead.md +5 -5
- package/src/claude/output-styles/coding-level-5-god.md +6 -6
- package/src/claude/rules/ai-dev-rules.md +1 -2
- package/src/claude/rules/hook-protocols.md +1 -1
- package/src/claude/rules/workflow.md +1 -1
- package/src/claude/runtime.json +0 -3
- package/src/claude/scripts/generate-skill-catalog.cjs +2 -2
- package/src/claude/scripts/provenance.cjs +14 -0
- package/src/claude/scripts/spec-receipt.cjs +0 -114
- package/src/claude/scripts/spec-resolver.cjs +41 -457
- package/src/claude/scripts/workflow-policy.cjs +3 -1801
- package/src/claude/settings/settings.json +1 -1
- package/src/claude/skills/agent-browser/SKILL.md +1 -1
- package/src/claude/skills/ai-multimodal/scripts/check_setup.py +8 -68
- package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +6 -28
- package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
- package/src/claude/skills/code-review/SKILL.md +25 -108
- package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -7
- package/src/claude/skills/develop/SKILL.md +22 -70
- package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
- package/src/claude/skills/git/SKILL.md +1 -1
- package/src/claude/skills/git/references/worktree-blueprint.md +1 -1
- package/src/claude/skills/research/SKILL.md +24 -55
- package/src/claude/skills/sync/SKILL.md +12 -34
- package/src/claude/skills/sync/references/rebind-and-audit.md +2 -2
- package/src/claude/skills/test/SKILL.md +39 -123
- package/src/claude/skills/test/references/execution-strategy.md +11 -22
- package/src/claude/skills/ui-ux/SKILL.md +1 -1
- package/src/claude/skills/ui-ux-pro-max/SKILL.md +24 -79
- package/src/claude/skills/web-testing/SKILL.md +2 -20
- package/src/codex/AGENTS.md +8 -0
- package/src/codex/hooks/ask-guard.cjs +54 -0
- package/src/codex/hooks/inspect-block.cjs +11 -7
- package/src/codex/hooks/lib/inspect-paths.cjs +1 -199
- package/src/codex/hooks/lib/privacy-paths.cjs +1 -0
- package/src/codex/hooks/lib/privacy-state.cjs +98 -16
- package/src/codex/hooks/lib/rules-reservation.cjs +38 -0
- package/src/codex/hooks/lib/secret-keywords.cjs +1 -0
- package/src/codex/hooks/lib/spec-receipt.cjs +2 -30
- package/src/codex/hooks/lib/spec-session-touch.cjs +100 -0
- package/src/codex/hooks/lib/spec-touch.cjs +3 -0
- package/src/codex/hooks/lib/spec-utils.cjs +6 -45
- package/src/codex/hooks/lib/update-check.cjs +1 -0
- package/src/codex/hooks/precompact.cjs +39 -0
- package/src/codex/hooks/privacy-approval.cjs +28 -17
- package/src/codex/hooks/privacy-block.cjs +9 -215
- package/src/codex/hooks/rules.cjs +4 -30
- package/src/codex/hooks/secret-output-guardrail.cjs +1 -1
- package/src/codex/hooks/session.cjs +47 -11
- package/src/codex/hooks/spec-gate.cjs +32 -74
- package/src/codex/hooks/spec-state.cjs +68 -46
- package/src/codex/hooks/state.cjs +25 -4
- package/src/codex/hooks.json +39 -7
- package/src/codex/rules/hook-protocols.md +13 -6
- package/src/common/AGENTS.md +4 -10
- package/src/omp/extensions/cafekit-bridge.mjs +12 -4
- package/src/omp/hooks/privacy-block.cjs +24 -206
- package/bin/__tests__/change-firewall.semantic-firewall.test.js +0 -2133
- package/bin/__tests__/finalizer-pass-gate.semantic-firewall.test.js +0 -342
- package/bin/__tests__/release-preflight.semantic-firewall.test.js +0 -586
- package/bin/__tests__/review-receipt-c2.semantic-firewall.test.js +0 -378
- package/bin/__tests__/specs-v2-policy-and-scaffold.test.js +0 -665
- package/bin/__tests__/specs-v2-validator-grounder-contract.test.js +0 -1132
- package/src/claude/hooks/lib/context.cjs +0 -527
- package/src/claude/hooks/lib/detect.cjs +0 -474
- package/src/claude/scripts/change-firewall.cjs +0 -1748
- package/src/claude/scripts/spec-authoring-digest.cjs +0 -151
- package/src/claude/scripts/spec-authoring-validation.cjs +0 -126
- package/src/claude/scripts/spec-final-state.cjs +0 -290
- package/src/claude/scripts/spec-ground.cjs +0 -650
- package/src/claude/scripts/spec-readiness.cjs +0 -425
- package/src/claude/scripts/spec-scaffold.cjs +0 -2317
- package/src/claude/scripts/spec-semantic-model.cjs +0 -396
- package/src/claude/scripts/validate-spec-output.cjs +0 -3914
- package/src/claude/skills/code-review/references/verification-gate.md +0 -41
- package/src/claude/skills/specs/templates/design.md +0 -82
- package/src/claude/skills/specs/templates/requirements-init.md +0 -8
- package/src/claude/skills/specs/templates/requirements.md +0 -42
- package/src/claude/skills/specs/templates/spec-state.json +0 -56
- package/src/claude/skills/specs/templates/task.md +0 -47
- package/src/codex/rules/state-sync.md +0 -60
|
@@ -14,32 +14,23 @@
|
|
|
14
14
|
* Exit: 0 (the JSON hook output carries the permission decision)
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
const fs = require('fs');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
const { commandAccess } = require('./lib/privacy-command-analysis.cjs');
|
|
17
|
+
const EVALUATION_FAILURE = 'Sensitive access could not be evaluated safely.';
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/\.pgpass$/i,
|
|
33
|
-
/kubeconfig/i,
|
|
34
|
-
/\.keystore$/i,
|
|
35
|
-
/\.jks$/i,
|
|
36
|
-
/auth\.json$/i,
|
|
37
|
-
/token(s)?\.json$/i
|
|
38
|
-
];
|
|
19
|
+
function askForPermission(reason) {
|
|
20
|
+
process.stdout.write(JSON.stringify({
|
|
21
|
+
hookSpecificOutput: {
|
|
22
|
+
hookEventName: 'PreToolUse',
|
|
23
|
+
// omp has no ask state on tool_call, so an ask under Claude becomes a denial here.
|
|
24
|
+
permissionDecision: 'deny',
|
|
25
|
+
permissionDecisionReason: reason
|
|
26
|
+
}
|
|
27
|
+
}) + '\n');
|
|
28
|
+
}
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
try {
|
|
31
|
+
const fs = require('fs');
|
|
32
|
+
const { sensitivePaths, displayNames } = require('./lib/privacy-paths.cjs');
|
|
33
|
+
const { projectRoot: resolveProjectRoot } = require('./lib/project-root.cjs');
|
|
43
34
|
|
|
44
35
|
const { runtimeDirName, runtimeDir, runtimePath } = require('./lib/runtime-dir.cjs');
|
|
45
36
|
function readRuntime(cwd) {
|
|
@@ -51,200 +42,27 @@ try {
|
|
|
51
42
|
}
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
function isSafe(filePath) {
|
|
55
|
-
const base = path.basename(filePath);
|
|
56
|
-
return ALLOWED_EXEMPTIONS.some((rule) => rule.test(base) || rule.test(filePath));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function isSensitive(filePath) {
|
|
60
|
-
const base = path.basename(filePath);
|
|
61
|
-
return RESTRICTED_PATTERNS.some((rule) => rule.test(base) || rule.test(filePath));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Resolve a symlink to its real target so a harmless-looking name that points
|
|
66
|
-
* at a sensitive file cannot slip through the basename check. Returns null
|
|
67
|
-
* when the path cannot be resolved (missing file, broken link) — fail-open to
|
|
68
|
-
* the original-path check in that case. See isSymlinkToSensitive for dangling handling.
|
|
69
|
-
*/
|
|
70
|
-
function resolveTarget(filePath, cwd) {
|
|
71
|
-
try {
|
|
72
|
-
const requested = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
73
|
-
return fs.realpathSync(requested);
|
|
74
|
-
} catch {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* When realpath fails, check whether the requested path is a symlink (or chain)
|
|
81
|
-
* whose lexical target is sensitive. Dangling link to protected target -> true (fail-closed ask);
|
|
82
|
-
* dangling benign link or link to allowed example/template -> false (allow).
|
|
83
|
-
* Limit hops to avoid loops; malformed/looping -> fail closed.
|
|
84
|
-
* TOCTOU note: check and use are not atomic; target could be swapped between this check and the actual read.
|
|
85
|
-
* This is a best-effort guardrail, not an arbitrary-shell security boundary. For strong isolation use OS sandbox.
|
|
86
|
-
*/
|
|
87
|
-
function isSymlinkToSensitive(filePath, cwd) {
|
|
88
|
-
try {
|
|
89
|
-
const requested = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
90
|
-
let current = requested;
|
|
91
|
-
let hops = 0;
|
|
92
|
-
const MAX_HOPS = 8;
|
|
93
|
-
while (hops < MAX_HOPS) {
|
|
94
|
-
let stat;
|
|
95
|
-
try {
|
|
96
|
-
stat = fs.lstatSync(current);
|
|
97
|
-
} catch {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
if (!stat.isSymbolicLink()) return false;
|
|
101
|
-
let linkTarget;
|
|
102
|
-
try {
|
|
103
|
-
linkTarget = fs.readlinkSync(current);
|
|
104
|
-
} catch {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
if (isSensitive(linkTarget) && !isSafe(linkTarget)) return true;
|
|
108
|
-
if (isSafe(linkTarget)) return false;
|
|
109
|
-
const next = path.isAbsolute(linkTarget) ? linkTarget : path.resolve(path.dirname(current), linkTarget);
|
|
110
|
-
if (next === current) return true;
|
|
111
|
-
try {
|
|
112
|
-
const real = fs.realpathSync(next);
|
|
113
|
-
if (isSensitive(real) && !isSafe(real)) return true;
|
|
114
|
-
if (isSafe(real)) return false;
|
|
115
|
-
return false;
|
|
116
|
-
} catch {
|
|
117
|
-
current = next;
|
|
118
|
-
hops += 1;
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return true;
|
|
123
|
-
} catch {
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function extractBashPaths(command) {
|
|
129
|
-
// The analyzer parses the command and returns the operands of every reading
|
|
130
|
-
// command it recognises, nested shells and `find -exec` included. Treating
|
|
131
|
-
// every unresolved expansion as sensitive, as this did before, asked on
|
|
132
|
-
// `cat $FILE`, `wc -l *.cjs` and `cat ~/.zshrc` alike. Noise is what trains
|
|
133
|
-
// people to click through the prompt that matters.
|
|
134
|
-
// A heredoc whose delimiter is quoted (<<'BODY') is inert: the shell
|
|
135
|
-
// expands nothing inside it, so no word in the body is ever read. The
|
|
136
|
-
// analyzer has no notion of heredocs and parses the body as shell, so prose
|
|
137
|
-
// that quotes a command -- a PR body carrying `cat .env` in backticks --
|
|
138
|
-
// came back as a real command substitution. Blank those bodies out first.
|
|
139
|
-
// An unquoted delimiter (<<BODY) does expand, so it is left to the
|
|
140
|
-
// analyzer.
|
|
141
|
-
const scrubbed = String(command).replace(
|
|
142
|
-
/(<<-?[ \t]*)(['"])([A-Za-z_]\w*)\2[^\n]*\n[\s\S]*?\n[ \t]*\3\b/g,
|
|
143
|
-
'$1$2$3$2'
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
const paths = new Set(commandAccess(scrubbed).paths);
|
|
147
|
-
|
|
148
|
-
// Two shapes the analyzer cannot return. It drops any word carrying an
|
|
149
|
-
// expansion, so `~/.ssh/id_rsa` and `certs/*.pem` still have to be matched
|
|
150
|
-
// by name. And it only walks commands it recognises, so an unknown tool
|
|
151
|
-
// handed a secret through a file-shaped option, such as
|
|
152
|
-
// `docker compose --env-file .env`, is invisible to it.
|
|
153
|
-
const FILE_OPTION = /^--?[\w-]*(?:file|config|key|cert|identity)$/i;
|
|
154
|
-
const tokens = scrubbed.split(/[\s|;&<>"'()`]+/);
|
|
155
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
156
|
-
const token = tokens[index];
|
|
157
|
-
const shaped = /^~|[*?[{]/.test(token);
|
|
158
|
-
const optionFed = index > 0 && FILE_OPTION.test(tokens[index - 1]);
|
|
159
|
-
if (!shaped && !optionFed) continue;
|
|
160
|
-
const value = token.replace(/^~/, '').replace(/^["'()`]+|["'(),]+$/g, '');
|
|
161
|
-
if (value && isSensitive(value) && !isSafe(value)) paths.add(value);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return [...paths];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function extractPaths(toolName, input) {
|
|
168
|
-
const paths = [];
|
|
169
|
-
if (!input) return paths;
|
|
170
|
-
|
|
171
|
-
for (const key of ['file_path', 'path']) {
|
|
172
|
-
if (typeof input[key] === 'string' && input[key].trim()) {
|
|
173
|
-
paths.push(input[key].trim());
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
for (const key of ['paths', 'search_paths']) {
|
|
178
|
-
if (Array.isArray(input[key])) {
|
|
179
|
-
paths.push(...input[key].filter(Boolean));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (toolName === 'Bash' && typeof input.command === 'string') {
|
|
184
|
-
paths.push(...extractBashPaths(input.command));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return paths.filter(Boolean);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function askForPermission(filePath) {
|
|
191
|
-
const basename = path.basename(filePath);
|
|
192
|
-
process.stdout.write(JSON.stringify({
|
|
193
|
-
hookSpecificOutput: {
|
|
194
|
-
hookEventName: 'PreToolUse',
|
|
195
|
-
// omp has no ask state on tool_call, so an ask under Claude becomes a denial here.
|
|
196
|
-
permissionDecision: 'deny',
|
|
197
|
-
permissionDecisionReason: `Sensitive file access requires approval: ${basename}`
|
|
198
|
-
}
|
|
199
|
-
}) + '\n');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
45
|
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
203
|
-
if (!stdin)
|
|
46
|
+
if (!stdin) {
|
|
47
|
+
askForPermission(EVALUATION_FAILURE);
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
204
50
|
|
|
205
51
|
const { normalizeHookPayload } = require('./lib/hook-payload.cjs');
|
|
206
52
|
const data = normalizeHookPayload(JSON.parse(stdin));
|
|
207
53
|
const toolName = data.tool_name || '';
|
|
208
54
|
const toolInput = data.tool_input || {};
|
|
209
55
|
const cwd = typeof data.cwd === 'string' && data.cwd.trim() ? data.cwd : process.cwd();
|
|
210
|
-
const
|
|
56
|
+
const projectRoot = resolveProjectRoot(data);
|
|
57
|
+
const runtime = readRuntime(projectRoot);
|
|
211
58
|
|
|
212
59
|
if (runtime.privacyBlock === false) process.exit(0);
|
|
213
60
|
|
|
214
|
-
const paths =
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
for (const filePath of paths) {
|
|
218
|
-
const target = resolveTarget(filePath, cwd);
|
|
219
|
-
|
|
220
|
-
// The real target is authoritative: an exempt-looking alias must not hide
|
|
221
|
-
// a sensitive target, while a real .env.example target remains safe.
|
|
222
|
-
if (target) {
|
|
223
|
-
if (isSensitive(target) && !isSafe(target)) {
|
|
224
|
-
askForPermission(filePath);
|
|
225
|
-
process.exit(0);
|
|
226
|
-
}
|
|
227
|
-
if (isSafe(target)) continue;
|
|
228
|
-
} else {
|
|
229
|
-
if (isSymlinkToSensitive(filePath, cwd)) {
|
|
230
|
-
askForPermission(filePath);
|
|
231
|
-
process.exit(0);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (isSafe(filePath) || !isSensitive(filePath)) continue;
|
|
236
|
-
askForPermission(filePath);
|
|
237
|
-
process.exit(0);
|
|
238
|
-
}
|
|
61
|
+
const paths = sensitivePaths(toolName, toolInput, cwd);
|
|
62
|
+
if (paths.length) askForPermission(`Sensitive file access requires approval: ${displayNames(paths)}`);
|
|
239
63
|
|
|
240
64
|
process.exit(0);
|
|
241
65
|
} catch (_) {
|
|
242
|
-
|
|
243
|
-
hookSpecificOutput: {
|
|
244
|
-
hookEventName: 'PreToolUse',
|
|
245
|
-
permissionDecision: 'deny',
|
|
246
|
-
permissionDecisionReason: 'Sensitive access could not be evaluated safely.'
|
|
247
|
-
}
|
|
248
|
-
}) + '\n');
|
|
66
|
+
askForPermission(EVALUATION_FAILURE);
|
|
249
67
|
process.exit(0);
|
|
250
68
|
}
|