@guilz-dev/belay 0.4.0 → 0.7.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/README.md +27 -2
- package/dist/adapters/claude/runtime-entry.js +54 -25
- package/dist/adapters/layouts/scope.js +3 -2
- package/dist/adapters/shared/gate-runtime.d.ts +8 -2
- package/dist/adapters/shared/gate-runtime.js +579 -181
- package/dist/bundle/claude-runtime.mjs +13574 -6334
- package/dist/bundle/codex-runtime.mjs +13108 -5903
- package/dist/bundle/cursor-runtime.mjs +12676 -5476
- package/dist/cli.js +80 -2
- package/dist/commands/approve.js +34 -10
- package/dist/commands/classify-for-report.js +1 -1
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.js +134 -11
- package/dist/commands/doctor.js +87 -1
- package/dist/commands/explain.js +11 -1
- package/dist/commands/judge.js +3 -2
- package/dist/commands/recovery-checkpoints.d.ts +164 -0
- package/dist/commands/recovery-checkpoints.js +347 -0
- package/dist/commands/revoke.js +19 -7
- package/dist/commands/session.d.ts +20 -0
- package/dist/commands/session.js +51 -0
- package/dist/commands/status.js +7 -0
- package/dist/config-io.js +91 -23
- package/dist/conformance/guarantee-posture.d.ts +21 -0
- package/dist/conformance/guarantee-posture.js +46 -0
- package/dist/conformance/guarantee-table.d.ts +1 -0
- package/dist/conformance/guarantee-table.js +20 -9
- package/dist/conformance/types.d.ts +1 -0
- package/dist/core/approval-replay.d.ts +1 -1
- package/dist/core/approval-replay.js +4 -1
- package/dist/core/approval-service.d.ts +6 -1
- package/dist/core/approval-service.js +87 -24
- package/dist/core/approval.d.ts +4 -0
- package/dist/core/approval.js +19 -5
- package/dist/core/audit-types.d.ts +13 -0
- package/dist/core/capability/approval-state-mutation.d.ts +32 -0
- package/dist/core/capability/approval-state-mutation.js +165 -0
- package/dist/core/capability/approval-v3.d.ts +32 -0
- package/dist/core/capability/approval-v3.js +114 -0
- package/dist/core/capability/attestation.d.ts +16 -0
- package/dist/core/capability/attestation.js +62 -0
- package/dist/core/capability/boundary-attestation-sign.d.ts +21 -0
- package/dist/core/capability/boundary-attestation-sign.js +84 -0
- package/dist/core/capability/boundary-driver-container.d.ts +19 -0
- package/dist/core/capability/boundary-driver-container.js +189 -0
- package/dist/core/capability/boundary-driver.d.ts +29 -0
- package/dist/core/capability/boundary-driver.js +44 -0
- package/dist/core/capability/boundary-egress.d.ts +21 -0
- package/dist/core/capability/boundary-egress.js +109 -0
- package/dist/core/capability/boundary-grant-materialize.d.ts +14 -0
- package/dist/core/capability/boundary-grant-materialize.js +93 -0
- package/dist/core/capability/boundary-profile.d.ts +15 -0
- package/dist/core/capability/boundary-profile.js +25 -0
- package/dist/core/capability/boundary-run.d.ts +48 -0
- package/dist/core/capability/boundary-run.js +51 -0
- package/dist/core/capability/boundary-session.d.ts +61 -0
- package/dist/core/capability/boundary-session.js +138 -0
- package/dist/core/capability/boundary-workspace-mount.d.ts +5 -0
- package/dist/core/capability/boundary-workspace-mount.js +68 -0
- package/dist/core/capability/capability-request-hash.d.ts +2 -0
- package/dist/core/capability/capability-request-hash.js +8 -0
- package/dist/core/capability/gate-latency-ratchet.d.ts +7 -0
- package/dist/core/capability/gate-latency-ratchet.js +18 -0
- package/dist/core/capability/gate-policy-shadow.d.ts +25 -0
- package/dist/core/capability/gate-policy-shadow.js +130 -0
- package/dist/core/capability/gate-shadow-audit.d.ts +1 -0
- package/dist/core/capability/gate-shadow-audit.js +1 -0
- package/dist/core/capability/gate-shadow-ratchet.d.ts +14 -0
- package/dist/core/capability/gate-shadow-ratchet.js +81 -0
- package/dist/core/capability/grant-consumption.d.ts +4 -0
- package/dist/core/capability/grant-consumption.js +11 -0
- package/dist/core/capability/grant-lease.d.ts +44 -0
- package/dist/core/capability/grant-lease.js +243 -0
- package/dist/core/capability/grant-loader.d.ts +12 -0
- package/dist/core/capability/grant-loader.js +23 -0
- package/dist/core/capability/grant-match.d.ts +6 -0
- package/dist/core/capability/grant-match.js +96 -0
- package/dist/core/capability/grant.d.ts +16 -0
- package/dist/core/capability/grant.js +16 -0
- package/dist/core/capability/index.d.ts +8 -0
- package/dist/core/capability/index.js +7 -0
- package/dist/core/capability/limits.d.ts +7 -0
- package/dist/core/capability/limits.js +55 -0
- package/dist/core/capability/policy-bridge.d.ts +18 -0
- package/dist/core/capability/policy-bridge.js +51 -0
- package/dist/core/capability/policy-engine.d.ts +77 -0
- package/dist/core/capability/policy-engine.js +663 -0
- package/dist/core/capability/policy-types.d.ts +20 -0
- package/dist/core/capability/policy-types.js +1 -0
- package/dist/core/capability/request.d.ts +48 -0
- package/dist/core/capability/request.js +1 -0
- package/dist/core/capability/resolver.d.ts +4 -0
- package/dist/core/capability/resolver.js +4 -0
- package/dist/core/classify-subagent.d.ts +2 -1
- package/dist/core/classify-subagent.js +38 -2
- package/dist/core/classify-tool.js +126 -62
- package/dist/core/config.d.ts +34 -3
- package/dist/core/config.js +118 -3
- package/dist/core/effect-ir/audit.d.ts +9 -0
- package/dist/core/effect-ir/audit.js +86 -0
- package/dist/core/effect-ir/build.d.ts +31 -0
- package/dist/core/effect-ir/build.js +277 -0
- package/dist/core/effect-ir/index.d.ts +8 -0
- package/dist/core/effect-ir/index.js +7 -0
- package/dist/core/effect-ir/normalize.d.ts +4 -0
- package/dist/core/effect-ir/normalize.js +104 -0
- package/dist/core/effect-ir/package-exec-eval.d.ts +8 -0
- package/dist/core/effect-ir/package-exec-eval.js +152 -0
- package/dist/core/effect-ir/package-exec.d.ts +29 -0
- package/dist/core/effect-ir/package-exec.js +292 -0
- package/dist/core/effect-ir/policy.d.ts +13 -0
- package/dist/core/effect-ir/policy.js +77 -0
- package/dist/core/effect-ir/types.d.ts +55 -0
- package/dist/core/effect-ir/types.js +1 -0
- package/dist/core/egress/allowlist.d.ts +1 -0
- package/dist/core/egress/allowlist.js +8 -0
- package/dist/core/egress-approval.js +45 -51
- package/dist/core/gate-contract.d.ts +5 -0
- package/dist/core/gate-contract.js +5 -0
- package/dist/core/gate-engine.js +30 -8
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.js +2 -1
- package/dist/core/judge-cloud-consent.js +29 -15
- package/dist/core/judge-doctor.js +39 -14
- package/dist/core/judge-fallback-hints.d.ts +13 -0
- package/dist/core/judge-fallback-hints.js +108 -0
- package/dist/core/network-endpoint.d.ts +10 -0
- package/dist/core/network-endpoint.js +51 -0
- package/dist/core/path-utils.d.ts +1 -0
- package/dist/core/path-utils.js +5 -2
- package/dist/core/process-runner.d.ts +10 -0
- package/dist/core/process-runner.js +124 -0
- package/dist/core/recover-advice.js +2 -1
- package/dist/core/recovery/artifact-store.d.ts +29 -0
- package/dist/core/recovery/artifact-store.js +336 -0
- package/dist/core/recovery/capability.d.ts +3 -0
- package/dist/core/recovery/capability.js +22 -0
- package/dist/core/recovery/checkpoint.d.ts +25 -0
- package/dist/core/recovery/checkpoint.js +260 -0
- package/dist/core/recovery/fail-closed.d.ts +6 -0
- package/dist/core/recovery/fail-closed.js +25 -0
- package/dist/core/recovery/index.d.ts +5 -0
- package/dist/core/recovery/index.js +4 -0
- package/dist/core/recovery/operator-guidance.d.ts +7 -0
- package/dist/core/recovery/operator-guidance.js +39 -0
- package/dist/core/recovery/reconcile.d.ts +3 -0
- package/dist/core/recovery/reconcile.js +48 -0
- package/dist/core/recovery/resource-identity.d.ts +4 -0
- package/dist/core/recovery/resource-identity.js +34 -0
- package/dist/core/recovery/restore.d.ts +13 -0
- package/dist/core/recovery/restore.js +114 -0
- package/dist/core/recovery/snapshot-node.d.ts +27 -0
- package/dist/core/recovery/snapshot-node.js +261 -0
- package/dist/core/recovery/types.d.ts +104 -0
- package/dist/core/recovery/types.js +1 -0
- package/dist/core/standing-allow.js +3 -0
- package/dist/core/transactional/apply-observed-changes.d.ts +13 -0
- package/dist/core/transactional/apply-observed-changes.js +275 -0
- package/dist/core/transactional/backend-selector.d.ts +8 -0
- package/dist/core/transactional/backend-selector.js +118 -0
- package/dist/core/transactional/backend.d.ts +55 -0
- package/dist/core/transactional/backend.js +1 -0
- package/dist/core/transactional/diff-evaluator.js +4 -1
- package/dist/core/transactional/eligibility.js +4 -0
- package/dist/core/transactional/file-checkpoint-backend.d.ts +3 -0
- package/dist/core/transactional/file-checkpoint-backend.js +278 -0
- package/dist/core/transactional/file-checkpoint-git.d.ts +11 -0
- package/dist/core/transactional/file-checkpoint-git.js +217 -0
- package/dist/core/transactional/file-checkpoint-staging.d.ts +13 -0
- package/dist/core/transactional/file-checkpoint-staging.js +54 -0
- package/dist/core/transactional/file-clone.d.ts +15 -0
- package/dist/core/transactional/file-clone.js +139 -0
- package/dist/core/transactional/file-tree-path.d.ts +7 -0
- package/dist/core/transactional/file-tree-path.js +50 -0
- package/dist/core/transactional/file-tree.d.ts +41 -0
- package/dist/core/transactional/file-tree.js +186 -0
- package/dist/core/transactional/git-worktree-backend.d.ts +2 -0
- package/dist/core/transactional/git-worktree-backend.js +50 -0
- package/dist/core/transactional/git-worktree.d.ts +14 -9
- package/dist/core/transactional/git-worktree.js +62 -87
- package/dist/core/transactional/index.d.ts +11 -0
- package/dist/core/transactional/index.js +10 -0
- package/dist/core/transactional/reasons.d.ts +1 -0
- package/dist/core/transactional/reasons.js +5 -0
- package/dist/core/transactional/runner.js +171 -23
- package/dist/core/transactional/snapshot-node.d.ts +26 -0
- package/dist/core/transactional/snapshot-node.js +87 -0
- package/dist/core/transactional/types.d.ts +21 -1
- package/dist/core/types.d.ts +30 -3
- package/dist/core/verdict/adapter.d.ts +3 -4
- package/dist/core/verdict/adapter.js +24 -12
- package/dist/core/verdict/cursor-acp-client.d.ts +67 -0
- package/dist/core/verdict/cursor-acp-client.js +345 -0
- package/dist/core/verdict/egress-classify.d.ts +2 -2
- package/dist/core/verdict/egress-classify.js +2 -2
- package/dist/core/verdict/git-classifier.d.ts +26 -0
- package/dist/core/verdict/git-classifier.js +533 -0
- package/dist/core/verdict/judge-audit.js +1 -0
- package/dist/core/verdict/judge-baseline.d.ts +1 -1
- package/dist/core/verdict/judge-baseline.js +1 -0
- package/dist/core/verdict/judge-broker-service.js +12 -0
- package/dist/core/verdict/judge-catalog.js +1 -0
- package/dist/core/verdict/judge-cli-fingerprint.d.ts +1 -0
- package/dist/core/verdict/judge-cli-fingerprint.js +6 -0
- package/dist/core/verdict/judge-cli.js +5 -3
- package/dist/core/verdict/judge-provider-matrix.js +1 -1
- package/dist/core/verdict/judge-runtime-config.d.ts +2 -0
- package/dist/core/verdict/judge-runtime-config.js +10 -6
- package/dist/core/verdict/judge-session-broker.d.ts +1 -1
- package/dist/core/verdict/judge-session-broker.js +10 -5
- package/dist/core/verdict/judge-transport.d.ts +5 -1
- package/dist/core/verdict/judge-transport.js +24 -14
- package/dist/core/verdict/judge.d.ts +2 -15
- package/dist/core/verdict/judge.js +5 -68
- package/dist/core/verdict/launcher-resolve.d.ts +2 -0
- package/dist/core/verdict/launcher-resolve.js +14 -16
- package/dist/core/verdict/prescan.d.ts +15 -0
- package/dist/core/verdict/prescan.js +68 -0
- package/dist/core/verdict/shell-policy.d.ts +26 -0
- package/dist/core/verdict/shell-policy.js +40 -0
- package/dist/core/verdict/shell-semantics.d.ts +24 -0
- package/dist/core/verdict/shell-semantics.js +225 -0
- package/dist/core/verdict/types.d.ts +18 -1
- package/dist/core/verdict/verdict.js +313 -178
- package/dist/corpus/evaluate.js +3 -7
- package/dist/corpus/gate-latency-budget.d.ts +39 -0
- package/dist/corpus/gate-latency-budget.js +33 -0
- package/dist/corpus/mutators.d.ts +1 -1
- package/dist/corpus/mutators.js +11 -0
- package/dist/corpus/runtime-match.js +1 -3
- package/dist/corpus/standing-allow-catalog.generated.js +29 -9
- package/dist/judge-broker-daemon.js +15 -1
- package/dist/services/sandbox-service.d.ts +4 -0
- package/dist/services/sandbox-service.js +28 -2
- package/dist/types.d.ts +13 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/belay/SKILL.md +8 -3
- package/skills/belay/belay-approve.md +10 -7
package/README.md
CHANGED
|
@@ -109,6 +109,16 @@ When an action is denied, approve the **next matching action once** by sending:
|
|
|
109
109
|
/belay-approve <approval-id>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
With the default `approval.flow: one_step`, an editor approval immediately replays the exact denied
|
|
113
|
+
shell action; no follow-up prompt is required. Tool and subagent approvals still require retrying
|
|
114
|
+
the original action unchanged. The one-shot grant is claimed before shell replay, so a failed or
|
|
115
|
+
timed-out replay requires a fresh approval. Replay runs through the configured `BoundaryDriver`.
|
|
116
|
+
After replay succeeds, the approval prompt continues the current host turn so the agent can report
|
|
117
|
+
the result and resume its workflow without another user message.
|
|
118
|
+
You may put a follow-up instruction on the lines after `/belay-approve <id>`; Belay replays the
|
|
119
|
+
approved shell action first, then lets the remaining prompt continue. CLI replay remains explicit:
|
|
120
|
+
`belay approve <approval-id> --replay`.
|
|
121
|
+
|
|
112
122
|
Approvals are one-shot and expire after 15 minutes by default. Every decision is
|
|
113
123
|
written to `.cursor/belay/audit.ndjson`, `.claude/belay/audit.ndjson`, or
|
|
114
124
|
`.codex/belay/audit.ndjson` (depending on the adapter).
|
|
@@ -239,12 +249,23 @@ Notable settings:
|
|
|
239
249
|
current OS user. `upgrade` migrates repo-local approvals in; disabling merges
|
|
240
250
|
them back. File-mutation tools and shell redirects cannot write control-plane
|
|
241
251
|
paths while it is enabled.
|
|
252
|
+
- **`policy.transactional.checkpoint.enabled: true`** — after enabling the
|
|
253
|
+
transactional git-worktree runner, persist repo-local pre-images and expose them through
|
|
254
|
+
`belay recover list`. Restore is conflict-checked and always requires a signed
|
|
255
|
+
out-of-band, exact one-shot approval. Network, remote Git, databases, processes, and
|
|
256
|
+
repo-external effects are outside this guarantee.
|
|
242
257
|
- **Cloud judge** — configure with `belay config` (interactive) or `belay config set judge.providerId <id>`.
|
|
243
258
|
Providers: `ollama`, `codex`, `claude`, `cursor`. **Provider** is the vendor/service
|
|
244
259
|
(`judge.providerId`); **driver** is the API compatibility layer (`judge.provider`:
|
|
245
260
|
`ollama`, `openai-compatible`, or `anthropic`); **host** is where hooks install
|
|
246
261
|
(`config.adapter`: `cursor`, `claude`, `codex`). Set `judge.endpoint` when needed;
|
|
247
|
-
credentials via `belay config credential mode project|apiKey` or env vars.
|
|
262
|
+
credentials via `belay config credential mode project|apiKey` or env vars. **`project`**
|
|
263
|
+
reads API keys from the shell environment at runtime (`BELAY_JUDGE_API_KEY`, then provider
|
|
264
|
+
vars such as `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `CURSOR_API_KEY`); Belay does **not**
|
|
265
|
+
load `.env` files for Judge. When the native CLI is available, `project` can also use the
|
|
266
|
+
host login session without a stored key. **`apiKey`** stores a key in Belay's credential store
|
|
267
|
+
(`credentials.json`, mode `0600`; under `~/.config/belay/` when control plane is enabled).
|
|
268
|
+
Record egress
|
|
248
269
|
consent during `belay config` or via `belay judge consent` → `belay approve` →
|
|
249
270
|
`belay judge use … --cloud-consent-approval-id`. Cloud providers can use native CLI
|
|
250
271
|
transport without `judge.endpoint` when the host CLI is available (`codex-cli`,
|
|
@@ -275,7 +296,11 @@ belay doctor [--fix] # check (and repair) floor health
|
|
|
275
296
|
belay status # show install scope / skill-only state
|
|
276
297
|
belay metrics # would-block / verdict summary
|
|
277
298
|
belay report # audit log report
|
|
278
|
-
belay recover [--command "rm important.ts"]
|
|
299
|
+
belay recover [advice] [--command "rm important.ts"] # advisory candidates only
|
|
300
|
+
belay recover status # checkpoint backend and state counts
|
|
301
|
+
belay recover list # proven repo-local recovery points
|
|
302
|
+
belay recover show <checkpoint-id>
|
|
303
|
+
belay recover apply <checkpoint-id> # signed OOB exact one-shot approval required
|
|
279
304
|
belay explain -- <shell-command> # inspect a verdict
|
|
280
305
|
belay explain --kind subagent -- "deploy to production"
|
|
281
306
|
belay explain --kind tool --tool Write -- .env
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
|
+
import { effectPlanAuditFields } from '../../core/effect-ir/audit.js';
|
|
3
|
+
import { buildCapabilityEffectPlan } from '../../core/effect-ir/build.js';
|
|
4
|
+
import { hashValue, toolFingerprint } from '../../core/fingerprint.js';
|
|
2
5
|
import { unnormalizedGateVerdict } from '../../core/gate-contract.js';
|
|
3
6
|
import { claudeLayout } from '../layouts/claude.js';
|
|
4
7
|
import { appendObservedAudit, createDefaultGateRuntimeDeps, evaluateGatedAction, gateVerdictToClaudePreToolUseResponse, gateVerdictToClaudeUserPromptResponse, processApprovalPrompt, resolveGateConfig, } from '../shared/gate-runtime.js';
|
|
@@ -22,6 +25,23 @@ async function readStdinJson() {
|
|
|
22
25
|
function jsonResponse(value) {
|
|
23
26
|
process.stdout.write(`${JSON.stringify(value)}\n`);
|
|
24
27
|
}
|
|
28
|
+
function claudeFallbackToolVerdict(params) {
|
|
29
|
+
return {
|
|
30
|
+
...unnormalizedGateVerdict({
|
|
31
|
+
reason: params.reason,
|
|
32
|
+
mode: params.mode,
|
|
33
|
+
user_message: params.userMessage,
|
|
34
|
+
agent_message: params.agentMessage,
|
|
35
|
+
}),
|
|
36
|
+
effectPlan: buildCapabilityEffectPlan({
|
|
37
|
+
actionKind: 'tool',
|
|
38
|
+
summary: params.toolName,
|
|
39
|
+
inputFingerprint: hashValue(`claude-fallback:${params.reason}:${toolFingerprint(params.toolName, params.payload, params.repoRoot)}`),
|
|
40
|
+
requests: [],
|
|
41
|
+
effectFree: false,
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
25
45
|
async function loadRuntimeContext(cwd) {
|
|
26
46
|
const repoRoot = findRepoRoot(cwd, claudeLayout);
|
|
27
47
|
const configPath = claudeLayout.configPath(repoRoot);
|
|
@@ -120,13 +140,10 @@ export async function runBeforeSubmitPromptHook() {
|
|
|
120
140
|
jsonResponse(gateVerdictToClaudeUserPromptResponse(result));
|
|
121
141
|
}
|
|
122
142
|
catch {
|
|
123
|
-
jsonResponse({
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
user_message: 'belay failed while processing approval state. Run belay doctor, then retry.',
|
|
128
|
-
},
|
|
129
|
-
});
|
|
143
|
+
jsonResponse(gateVerdictToClaudeUserPromptResponse({
|
|
144
|
+
continue: false,
|
|
145
|
+
user_message: 'belay failed while processing approval state. Run belay doctor, then retry.',
|
|
146
|
+
}));
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
export async function runShellGateHook() {
|
|
@@ -167,6 +184,15 @@ export async function runToolGateHook(_eventName) {
|
|
|
167
184
|
const toolName = String(payload.tool_name ?? '');
|
|
168
185
|
const mappedKind = mapClaudeToolName(toolName);
|
|
169
186
|
if (mappedKind === 'mcp') {
|
|
187
|
+
const verdict = claudeFallbackToolVerdict({
|
|
188
|
+
toolName,
|
|
189
|
+
payload,
|
|
190
|
+
repoRoot: ctx.repoRoot,
|
|
191
|
+
reason: 'unsupported_mcp_tool',
|
|
192
|
+
mode: ctx.config.mode,
|
|
193
|
+
userMessage: 'belay blocked this MCP tool because Claude MCP payloads are not normalized safely yet.',
|
|
194
|
+
agentMessage: 'Belay denied this MCP tool because its payload shape is unsupported.',
|
|
195
|
+
});
|
|
170
196
|
await deps.appendAudit(ctx, {
|
|
171
197
|
event: 'preToolUse',
|
|
172
198
|
kind: 'tool',
|
|
@@ -176,17 +202,21 @@ export async function runToolGateHook(_eventName) {
|
|
|
176
202
|
wouldBlock: true,
|
|
177
203
|
permission: 'deny',
|
|
178
204
|
summary: toolName,
|
|
179
|
-
|
|
180
|
-
const verdict = unnormalizedGateVerdict({
|
|
181
|
-
reason: 'unsupported_mcp_tool',
|
|
182
|
-
mode: ctx.config.mode,
|
|
183
|
-
user_message: 'belay blocked this MCP tool because Claude MCP payloads are not normalized safely yet.',
|
|
184
|
-
agent_message: 'Belay denied this MCP tool because its payload shape is unsupported.',
|
|
205
|
+
...effectPlanAuditFields(verdict.effectPlan),
|
|
185
206
|
});
|
|
186
207
|
jsonResponse(gateVerdictToClaudePreToolUseResponse(verdict));
|
|
187
208
|
return;
|
|
188
209
|
}
|
|
189
210
|
if (!mappedKind) {
|
|
211
|
+
const verdict = claudeFallbackToolVerdict({
|
|
212
|
+
toolName,
|
|
213
|
+
payload,
|
|
214
|
+
repoRoot: ctx.repoRoot,
|
|
215
|
+
reason: 'unmapped_tool',
|
|
216
|
+
mode: ctx.config.mode,
|
|
217
|
+
userMessage: 'belay does not recognize this tool action. Run belay doctor, then retry.',
|
|
218
|
+
agentMessage: 'Belay denied this action because the tool could not be normalized.',
|
|
219
|
+
});
|
|
190
220
|
await deps.appendAudit(ctx, {
|
|
191
221
|
event: 'preToolUse',
|
|
192
222
|
kind: 'tool',
|
|
@@ -196,18 +226,22 @@ export async function runToolGateHook(_eventName) {
|
|
|
196
226
|
wouldBlock: true,
|
|
197
227
|
permission: 'deny',
|
|
198
228
|
summary: toolName,
|
|
199
|
-
|
|
200
|
-
const verdict = unnormalizedGateVerdict({
|
|
201
|
-
reason: 'unmapped_tool',
|
|
202
|
-
mode: ctx.config.mode,
|
|
203
|
-
user_message: 'belay does not recognize this tool action. Run belay doctor, then retry.',
|
|
204
|
-
agent_message: 'Belay denied this action because the tool could not be normalized.',
|
|
229
|
+
...effectPlanAuditFields(verdict.effectPlan),
|
|
205
230
|
});
|
|
206
231
|
jsonResponse(gateVerdictToClaudePreToolUseResponse(verdict));
|
|
207
232
|
return;
|
|
208
233
|
}
|
|
209
234
|
const normalizedPayload = normalizeClaudeToolPayload(toolName, payload);
|
|
210
235
|
if (!normalizedPayload) {
|
|
236
|
+
const verdict = claudeFallbackToolVerdict({
|
|
237
|
+
toolName,
|
|
238
|
+
payload,
|
|
239
|
+
repoRoot: ctx.repoRoot,
|
|
240
|
+
reason: 'normalization_failed',
|
|
241
|
+
mode: ctx.config.mode,
|
|
242
|
+
userMessage: 'belay could not normalize this Claude tool payload. Run belay doctor, then retry.',
|
|
243
|
+
agentMessage: 'Belay denied this action because the Claude tool payload could not be normalized.',
|
|
244
|
+
});
|
|
211
245
|
await deps.appendAudit(ctx, {
|
|
212
246
|
event: 'preToolUse',
|
|
213
247
|
kind: 'tool',
|
|
@@ -217,12 +251,7 @@ export async function runToolGateHook(_eventName) {
|
|
|
217
251
|
wouldBlock: true,
|
|
218
252
|
permission: 'deny',
|
|
219
253
|
summary: toolName,
|
|
220
|
-
|
|
221
|
-
const verdict = unnormalizedGateVerdict({
|
|
222
|
-
reason: 'normalization_failed',
|
|
223
|
-
mode: ctx.config.mode,
|
|
224
|
-
user_message: 'belay could not normalize this Claude tool payload. Run belay doctor, then retry.',
|
|
225
|
-
agent_message: 'Belay denied this action because the Claude tool payload could not be normalized.',
|
|
254
|
+
...effectPlanAuditFields(verdict.effectPlan),
|
|
226
255
|
});
|
|
227
256
|
jsonResponse(gateVerdictToClaudePreToolUseResponse(verdict));
|
|
228
257
|
return;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { isPathOutsideRoot } from '../../core/path-utils.js';
|
|
3
4
|
function agentHomeDir(adapter) {
|
|
4
5
|
const home = os.homedir();
|
|
5
6
|
if (adapter === 'cursor') {
|
|
@@ -23,13 +24,13 @@ export function isPathInside(child, parent) {
|
|
|
23
24
|
const resolvedChild = path.resolve(child);
|
|
24
25
|
const resolvedParent = path.resolve(parent);
|
|
25
26
|
const relative = path.relative(resolvedParent, resolvedChild);
|
|
26
|
-
return relative === '' || (!relative
|
|
27
|
+
return relative === '' || (!isPathOutsideRoot(relative) && !path.isAbsolute(relative));
|
|
27
28
|
}
|
|
28
29
|
export function buildRunnerInvocation(platform, hooksDir, repoRoot, hookScript, ...args) {
|
|
29
30
|
const runnerFile = platform === 'win32' ? 'belay-runner.cmd' : 'belay-runner';
|
|
30
31
|
const runnerAbs = path.resolve(hooksDir, runnerFile);
|
|
31
32
|
const relative = path.relative(path.resolve(repoRoot), runnerAbs);
|
|
32
|
-
const useRelative = relative.length > 0 && !relative
|
|
33
|
+
const useRelative = relative.length > 0 && !isPathOutsideRoot(relative) && !path.isAbsolute(relative);
|
|
33
34
|
const runnerRef = useRelative
|
|
34
35
|
? platform === 'win32'
|
|
35
36
|
? `.\\${relative.split(path.sep).join('\\')}`
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ApprovalReplayHint } from '../../core/approval-replay.js';
|
|
2
|
-
import type
|
|
3
|
-
import { type GatePermissionResponse, type GateVerdict } from '../../core/gate-contract.js';
|
|
2
|
+
import { type GatedActionKind, type GatePermissionResponse, type GateVerdict } from '../../core/gate-contract.js';
|
|
4
3
|
import { GateNormalizationError } from '../../core/gate-engine.js';
|
|
5
4
|
import { type BelayConfigV3 } from '../../core/index.js';
|
|
6
5
|
import type { ApprovalStateFile, ClassifierOptions } from '../../core/types.js';
|
|
@@ -24,6 +23,13 @@ export interface GateRuntimeDeps {
|
|
|
24
23
|
state: ApprovalStateFile;
|
|
25
24
|
}>;
|
|
26
25
|
writeApprovals: (filePath: string, state: ApprovalStateFile) => Promise<void>;
|
|
26
|
+
replayApprovedShell: (ctx: GateRuntimeContext, command: string, cwd: string, timeoutMs: number) => Promise<{
|
|
27
|
+
exitCode: number | null;
|
|
28
|
+
timedOut: boolean;
|
|
29
|
+
signal: string | null;
|
|
30
|
+
stdout?: string;
|
|
31
|
+
stderr?: string;
|
|
32
|
+
}>;
|
|
27
33
|
}
|
|
28
34
|
export declare function createDefaultGateRuntimeDeps(): GateRuntimeDeps;
|
|
29
35
|
export declare function resolveGateConfig(ctx: Pick<GateRuntimeContext, 'layout' | 'repoRoot' | 'configPath'>, deps: GateRuntimeDeps): Promise<BelayConfigV3>;
|