@guilz-dev/belay 0.2.0 → 0.3.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 +39 -12
- package/dist/adapters/shared/gate-runtime.js +13 -5
- package/dist/bundle/claude-runtime.mjs +1659 -371
- package/dist/bundle/codex-runtime.mjs +1658 -371
- package/dist/bundle/cursor-runtime.mjs +1659 -371
- package/dist/cli.js +198 -8
- package/dist/commands/approve.js +11 -0
- package/dist/commands/config.d.ts +70 -0
- package/dist/commands/config.js +494 -0
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/health-snapshot.d.ts +6 -0
- package/dist/commands/health-snapshot.js +34 -0
- package/dist/commands/judge.d.ts +90 -0
- package/dist/commands/judge.js +285 -0
- package/dist/commands/status.js +2 -2
- package/dist/commands/stdin-key.d.ts +1 -0
- package/dist/commands/stdin-key.js +8 -0
- package/dist/conformance/guarantee-table.js +12 -0
- package/dist/conformance/types.d.ts +2 -0
- package/dist/core/audit-io.d.ts +2 -0
- package/dist/core/audit-io.js +14 -0
- package/dist/core/capability/index.d.ts +2 -2
- package/dist/core/capability/index.js +2 -2
- package/dist/core/capability/paths.d.ts +1 -0
- package/dist/core/capability/paths.js +74 -6
- package/dist/core/capability/reasons.d.ts +3 -0
- package/dist/core/capability/reasons.js +8 -0
- package/dist/core/classify-tool.js +97 -27
- package/dist/core/config-layers.js +2 -1
- package/dist/core/config.d.ts +22 -2
- package/dist/core/config.js +110 -11
- package/dist/core/credential-store.d.ts +11 -0
- package/dist/core/credential-store.js +60 -0
- package/dist/core/gate-engine.js +104 -13
- package/dist/core/integrity.d.ts +2 -0
- package/dist/core/integrity.js +13 -0
- package/dist/core/judge-api-key.d.ts +19 -0
- package/dist/core/judge-api-key.js +74 -0
- package/dist/core/judge-cloud-consent.d.ts +13 -0
- package/dist/core/judge-cloud-consent.js +38 -0
- package/dist/core/judge-config.d.ts +41 -4
- package/dist/core/judge-config.js +263 -57
- package/dist/core/judge-doctor.d.ts +6 -1
- package/dist/core/judge-doctor.js +147 -96
- package/dist/core/judge-model-discovery.d.ts +24 -0
- package/dist/core/judge-model-discovery.js +168 -0
- package/dist/core/judge-model-policy.d.ts +5 -0
- package/dist/core/judge-model-policy.js +21 -0
- package/dist/core/judge-runtime-detection.d.ts +9 -0
- package/dist/core/judge-runtime-detection.js +68 -0
- package/dist/core/transactional/diff-evaluator.js +1 -19
- package/dist/core/types.d.ts +2 -0
- package/dist/core/verdict/adapter.d.ts +1 -0
- package/dist/core/verdict/adapter.js +7 -1
- package/dist/core/verdict/containment.d.ts +5 -0
- package/dist/core/verdict/containment.js +32 -2
- package/dist/core/verdict/judge-catalog.d.ts +40 -0
- package/dist/core/verdict/judge-catalog.js +148 -0
- package/dist/core/verdict/judge-cli.d.ts +23 -0
- package/dist/core/verdict/judge-cli.js +280 -0
- package/dist/core/verdict/judge-factory.d.ts +15 -4
- package/dist/core/verdict/judge-factory.js +117 -14
- package/dist/core/verdict/judge.d.ts +20 -1
- package/dist/core/verdict/judge.js +83 -14
- package/dist/core/verdict/persistent-paths.d.ts +8 -0
- package/dist/core/verdict/persistent-paths.js +52 -0
- package/dist/core/verdict/types.d.ts +6 -2
- package/dist/core/verdict/verdict.js +161 -47
- package/dist/installer.js +66 -15
- package/dist/types.d.ts +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/belay/SKILL.md +8 -7
- package/dist/commands/init-wizard.d.ts +0 -21
- package/dist/commands/init-wizard.js +0 -63
package/README.md
CHANGED
|
@@ -34,8 +34,8 @@ policy to maintain.
|
|
|
34
34
|
| **Claude Code** | Supported | `.claude/settings.json` | `.claude/belay.config.json` |
|
|
35
35
|
| **Codex** | Experimental | `.codex/config.toml` | `.codex/belay.config.json` |
|
|
36
36
|
|
|
37
|
-
Pick the adapter at install time with `--adapter cursor|claude|codex` (or
|
|
38
|
-
`
|
|
37
|
+
Pick the adapter at install time with `--adapter cursor|claude|codex` (or use
|
|
38
|
+
`belay config` interactively). Hosts use different hook event names, but Belay registers
|
|
39
39
|
the same runners (`belay-tool-gate`, `belay-before-submit`, `belay-audit`) at
|
|
40
40
|
equivalent lifecycle points:
|
|
41
41
|
|
|
@@ -68,8 +68,8 @@ audit instead of guessing.
|
|
|
68
68
|
## Quick start
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
# Interactive setup (
|
|
72
|
-
|
|
71
|
+
# Interactive setup (adapter, scope, skill, judge provider, credentials)
|
|
72
|
+
belay config
|
|
73
73
|
|
|
74
74
|
# Or non-interactive
|
|
75
75
|
npx @guilz-dev/belay init --adapter claude # Claude Code
|
|
@@ -131,6 +131,9 @@ Belay is a layered hook gate, not a static denylist. Higher layers are opt-in.
|
|
|
131
131
|
- L3 command lists are **not security boundaries** by themselves — see
|
|
132
132
|
[docs/ops/semver-policy.md](./docs/ops/semver-policy.md) and
|
|
133
133
|
[docs/guarantee-table.md](./docs/guarantee-table.md).
|
|
134
|
+
- At default L3, **local-recoverable mutations outside the repo** pass after Tier1
|
|
135
|
+
(e.g. IDE plan files). To deny repo-external writes at the OS boundary, enable L1-full
|
|
136
|
+
(`sandbox.runtime` ≠ `none`). Tier1 requires a working judge (local Ollama by default).
|
|
134
137
|
- Adversarial resistance requires the full L1 stack:
|
|
135
138
|
`belay init --preset l1-full-recommended`, verified with `belay sandbox status`.
|
|
136
139
|
|
|
@@ -236,20 +239,37 @@ Notable settings:
|
|
|
236
239
|
current OS user. `upgrade` migrates repo-local approvals in; disabling merges
|
|
237
240
|
them back. File-mutation tools and shell redirects cannot write control-plane
|
|
238
241
|
paths while it is enabled.
|
|
239
|
-
- **Cloud judge** —
|
|
240
|
-
`
|
|
241
|
-
|
|
242
|
-
`
|
|
243
|
-
|
|
242
|
+
- **Cloud judge** — configure with `belay config` (interactive) or `belay config set judge.providerId <id>`.
|
|
243
|
+
Providers: `ollama`, `codex`, `claude`, `cursor`. **Provider** is the vendor/service
|
|
244
|
+
(`judge.providerId`); **driver** is the API compatibility layer (`judge.provider`:
|
|
245
|
+
`ollama`, `openai-compatible`, or `anthropic`); **host** is where hooks install
|
|
246
|
+
(`config.adapter`: `cursor`, `claude`, `codex`). Set `judge.endpoint` when needed;
|
|
247
|
+
credentials via `belay config credential mode project|apiKey` or env vars. Record egress
|
|
248
|
+
consent during `belay config` or via `belay judge consent` → `belay approve` →
|
|
249
|
+
`belay judge use … --cloud-consent-approval-id`. Cloud providers can use native CLI
|
|
250
|
+
transport without `judge.endpoint` when the host CLI is available (`codex-cli`,
|
|
251
|
+
`cursor-cli`, `claude-cli`); HTTP transport still requires endpoint and recorded consent.
|
|
252
|
+
Fresh installs default to the
|
|
253
|
+
host-matched provider (`cursor` → `cursor`, etc.). `belay judge use` remains available
|
|
254
|
+
as a secondary path.
|
|
255
|
+
|
|
256
|
+
Legacy `judge.model: auto` in config files is normalized to the provider catalog default on load
|
|
257
|
+
(with a warning); new `auto` values are rejected on CLI, `belay config set`, and `belay judge use`.
|
|
258
|
+
On an installed repo, interactive `belay config` defaults to judge-only setup without re-running
|
|
259
|
+
`init`. Model discovery is covered by unit tests with mocks; set `BELAY_LIVE_CLI_DISCOVERY=1` locally
|
|
260
|
+
for optional live CLI probes. Cloud egress consent is enforced for HTTP transport; native CLI
|
|
261
|
+
transport uses the host session and does not require `judge.endpoint`. `BELAY_JUDGE_MODEL_RESOLVED`
|
|
262
|
+
applies only under Vitest (test overrides).
|
|
244
263
|
|
|
245
264
|
## Command reference
|
|
246
265
|
|
|
247
266
|
```bash
|
|
248
267
|
belay init [--adapter cursor|claude|codex] [--scope project|global]
|
|
249
268
|
[--preset strict|standard|audit-first|l1-full-recommended]
|
|
250
|
-
[--with-skill] [--dogfood]
|
|
251
|
-
belay
|
|
252
|
-
belay
|
|
269
|
+
[--migrate-judge-default] [--with-skill] [--dogfood]
|
|
270
|
+
belay config # interactive setup (primary)
|
|
271
|
+
belay config list|get|set|unset|judge|credential …
|
|
272
|
+
belay upgrade [--migrate-judge-default] # refresh hooks + runtime, migrate config
|
|
253
273
|
belay dogfood [--enforce] # toggle audit / enforce mode
|
|
254
274
|
belay doctor [--fix] # check (and repair) floor health
|
|
255
275
|
belay status # show install scope / skill-only state
|
|
@@ -263,6 +283,13 @@ belay egress <start|stop|status|env>
|
|
|
263
283
|
belay sandbox status
|
|
264
284
|
belay approve <approval-id> [--scope once|domain|path]
|
|
265
285
|
belay revoke <approval-id>
|
|
286
|
+
belay judge status
|
|
287
|
+
belay judge list
|
|
288
|
+
belay judge use <ollama|codex|claude|cursor> [--model <id>] [--endpoint <url>]
|
|
289
|
+
[--accept-cloud] [--cloud-consent-approval-id <id>]
|
|
290
|
+
[--credential project|apiKey] [--key-stdin] [--key-env <NAME>]
|
|
291
|
+
belay judge test
|
|
292
|
+
belay judge consent <provider-id> [--endpoint <url>]
|
|
266
293
|
```
|
|
267
294
|
|
|
268
295
|
## Coexisting with existing hooks
|
|
@@ -4,7 +4,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { recordApproval } from '../../core/approval-service.js';
|
|
6
6
|
import { issueApprovalToken } from '../../core/approval-token.js';
|
|
7
|
-
import { fsScopeAllowlistPath, isCapabilityBrokerDemotionActive, loadFsScopeAllowlistSync, shouldSkipBrokerApprovedOnce, } from '../../core/capability/index.js';
|
|
7
|
+
import { fsScopeAllowlistPath, isCapabilityBrokerDemotionActive, loadFsScopeAllowlistSync, shouldSkipBrokerApprovedOnce, shouldSkipBrokerApprovedRecord, } from '../../core/capability/index.js';
|
|
8
8
|
import { resolveLayeredConfig, teamConfigPath } from '../../core/config-layers.js';
|
|
9
9
|
import { classifyResultToGateVerdict, unnormalizedGateVerdict, } from '../../core/gate-contract.js';
|
|
10
10
|
import { classifyGatedActionAsync, extractAgentAssessment, GateNormalizationError, gateEnabledForAction, normalizeGatedAction, } from '../../core/gate-engine.js';
|
|
@@ -322,10 +322,18 @@ async function gateDecisionToVerdict(ctx, deps, kind, result, auditExtras = {})
|
|
|
322
322
|
});
|
|
323
323
|
}
|
|
324
324
|
const brokerActive = isCapabilityBrokerDemotionActive(ctx.config);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
let approved = null;
|
|
326
|
+
if (!TRANSACTIONAL_APPROVAL_BYPASS_REASONS.has(result.reason) &&
|
|
327
|
+
!shouldSkipBrokerApprovedOnce(brokerActive, result.reason)) {
|
|
328
|
+
const approvedState = await deps.loadApprovals(ctx, 'approved-approvals.json');
|
|
329
|
+
approvedState.state = compactApprovals(approvedState.state);
|
|
330
|
+
const matchedApproval = approvedState.state.approvals.find((entry) => entry.kind === kind &&
|
|
331
|
+
entry.fingerprint === result.fingerprint &&
|
|
332
|
+
entry.repoRoot === ctx.repoRoot);
|
|
333
|
+
if (!shouldSkipBrokerApprovedRecord(brokerActive, matchedApproval?.reason)) {
|
|
334
|
+
approved = await consumeApprovedApproval(ctx, deps, kind, result.fingerprint);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
329
337
|
if (approved) {
|
|
330
338
|
await deps.appendAudit(ctx, {
|
|
331
339
|
...gateBase,
|