@guilz-dev/belay 0.7.0 → 0.8.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.
Files changed (75) hide show
  1. package/README.md +19 -19
  2. package/dist/adapters/shared/gate-runtime.js +23 -5
  3. package/dist/bundle/claude-runtime.mjs +4909 -3504
  4. package/dist/bundle/codex-runtime.mjs +5050 -3645
  5. package/dist/bundle/cursor-runtime.mjs +5050 -3645
  6. package/dist/commands/doctor.js +7 -0
  7. package/dist/commands/dogfood.js +1 -1
  8. package/dist/commands/explain.js +2 -2
  9. package/dist/commands/harvest.d.ts +0 -1
  10. package/dist/commands/harvest.js +1 -4
  11. package/dist/commands/metrics.js +6 -0
  12. package/dist/commands/quality.js +1 -3
  13. package/dist/conformance/guarantee-table.js +133 -11
  14. package/dist/conformance/types.d.ts +1 -0
  15. package/dist/core/audit-metrics.d.ts +1 -0
  16. package/dist/core/audit-metrics.js +12 -4
  17. package/dist/core/audit-types.d.ts +3 -0
  18. package/dist/core/capability/index.d.ts +1 -1
  19. package/dist/core/capability/policy-engine.d.ts +31 -1
  20. package/dist/core/capability/policy-engine.js +186 -0
  21. package/dist/core/capability/request.d.ts +9 -0
  22. package/dist/core/capability/resolver.d.ts +0 -1
  23. package/dist/core/capability/resolver.js +0 -1
  24. package/dist/core/config.js +0 -2
  25. package/dist/core/effect-ir/audit.js +1 -0
  26. package/dist/core/effect-ir/build.js +5 -1
  27. package/dist/core/effect-ir/index.d.ts +6 -1
  28. package/dist/core/effect-ir/index.js +2 -0
  29. package/dist/core/effect-ir/normalize.js +9 -3
  30. package/dist/core/effect-ir/policy.d.ts +2 -1
  31. package/dist/core/effect-ir/policy.js +93 -6
  32. package/dist/core/effect-ir/shell-build.d.ts +43 -0
  33. package/dist/core/effect-ir/shell-build.js +77 -0
  34. package/dist/core/effect-ir/shell-lower.d.ts +14 -0
  35. package/dist/core/effect-ir/shell-lower.js +1509 -0
  36. package/dist/core/effect-ir/types.d.ts +9 -2
  37. package/dist/core/gate-engine.js +63 -23
  38. package/dist/core/git-resource-identity.d.ts +26 -0
  39. package/dist/core/git-resource-identity.js +284 -0
  40. package/dist/core/harvest.d.ts +3 -7
  41. package/dist/core/harvest.js +4 -27
  42. package/dist/core/index.d.ts +2 -0
  43. package/dist/core/index.js +1 -0
  44. package/dist/core/path-utils.js +42 -23
  45. package/dist/core/shell-substitution.d.ts +1 -0
  46. package/dist/core/shell-substitution.js +61 -0
  47. package/dist/core/standing-allow.d.ts +1 -2
  48. package/dist/core/standing-allow.js +3 -20
  49. package/dist/core/types.d.ts +4 -1
  50. package/dist/core/verdict/adapter.js +15 -15
  51. package/dist/core/verdict/containment.js +4 -0
  52. package/dist/core/verdict/egress-classify.d.ts +12 -0
  53. package/dist/core/verdict/egress-classify.js +746 -0
  54. package/dist/core/verdict/git-classifier.d.ts +12 -0
  55. package/dist/core/verdict/git-classifier.js +320 -0
  56. package/dist/core/verdict/launcher-resolve.js +77 -17
  57. package/dist/core/verdict/parser.d.ts +2 -0
  58. package/dist/core/verdict/parser.js +95 -1
  59. package/dist/core/verdict/types.d.ts +2 -3
  60. package/dist/core/verdict/verdict.js +103 -952
  61. package/dist/corpus/must-allow-commands.d.ts +2 -1
  62. package/dist/corpus/must-allow-commands.js +2 -1
  63. package/dist/corpus/runtime-match.d.ts +2 -1
  64. package/dist/corpus/runtime-match.js +2 -1
  65. package/dist/corpus/types.d.ts +2 -2
  66. package/dist/templates.js +7 -2
  67. package/dist/version.d.ts +1 -1
  68. package/dist/version.js +1 -1
  69. package/package.json +2 -2
  70. package/dist/core/verdict/overrides.d.ts +0 -7
  71. package/dist/core/verdict/overrides.js +0 -37
  72. package/dist/core/verdict/shell-policy.d.ts +0 -26
  73. package/dist/core/verdict/shell-policy.js +0 -40
  74. package/dist/corpus/standing-allow-catalog.generated.d.ts +0 -13
  75. package/dist/corpus/standing-allow-catalog.generated.js +0 -99
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Structural-suite MUST-ALLOW ledger — keep in sync with standing-allow catalog generation.
2
+ * Structural-suite MUST-ALLOW CI expectations.
3
+ * These commands guard classifier availability in tests and never grant runtime authority.
3
4
  * @see src/__tests__/verdict/structural-suite.test.ts
4
5
  */
5
6
  export declare const MUST_ALLOW_SHELL_COMMANDS: readonly ["npm test", "npm run build", "pnpm test", "pnpm build", "pnpm vitest run src/example.test.ts", "bash -lc 'git status'", "belay approve belay_deadbeef1234"];
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Structural-suite MUST-ALLOW ledger — keep in sync with standing-allow catalog generation.
2
+ * Structural-suite MUST-ALLOW CI expectations.
3
+ * These commands guard classifier availability in tests and never grant runtime authority.
3
4
  * @see src/__tests__/verdict/structural-suite.test.ts
4
5
  */
5
6
  export const MUST_ALLOW_SHELL_COMMANDS = [
@@ -11,8 +11,9 @@ export declare function defaultCorpusEvalPaths(repoRoot?: string): {
11
11
  */
12
12
  export declare function deriveShellCorpusRuntimeKey(command: string, repoRoot?: string, cwd?: string): Promise<string>;
13
13
  /**
14
- * Attach derived `runtimeKey` to provably-benign shell cases that omit it.
14
+ * Attach derived stable CI `runtimeKey` to provably-benign shell cases that omit it.
15
15
  * When `runtimeKey` is precomputed in the fixture, verify it matches the derived fingerprint.
16
+ * The key is retained for corpus compatibility and is not runtime authorization.
16
17
  */
17
18
  export declare function enrichProvablyBenignRuntimeKeys(cases: CorpusCase[], repoRoot?: string, cwd?: string): Promise<CorpusCase[]>;
18
19
  /** Runtime-consumable keys from enriched provably-benign shell fixtures. */
@@ -17,8 +17,9 @@ export async function deriveShellCorpusRuntimeKey(command, repoRoot = DEFAULT_CO
17
17
  return result.fingerprint;
18
18
  }
19
19
  /**
20
- * Attach derived `runtimeKey` to provably-benign shell cases that omit it.
20
+ * Attach derived stable CI `runtimeKey` to provably-benign shell cases that omit it.
21
21
  * When `runtimeKey` is precomputed in the fixture, verify it matches the derived fingerprint.
22
+ * The key is retained for corpus compatibility and is not runtime authorization.
22
23
  */
23
24
  export async function enrichProvablyBenignRuntimeKeys(cases, repoRoot = DEFAULT_CORPUS_REPO_ROOT, cwd = path.join(repoRoot, 'src')) {
24
25
  return Promise.all(cases.map(async (testCase) => {
@@ -29,9 +29,9 @@ export interface CorpusCase {
29
29
  verdict: HookVerdict;
30
30
  reason?: string;
31
31
  /**
32
- * Stable runtime-facing key for `provably-benign` shell cases (verdict fingerprint).
32
+ * Stable CI/deduplication key for `provably-benign` shell cases (verdict fingerprint).
33
33
  * Offline fixtures may omit this; loaders derive it via `deriveShellCorpusRuntimeKey`.
34
- * Consumed by future standing-allow / catalog code — not used by evaluation harness alone.
34
+ * This key is not runtime authorization.
35
35
  */
36
36
  runtimeKey?: string;
37
37
  /** Optional case origin metadata for quality-loop ratchet and harvest audit. */
package/dist/templates.js CHANGED
@@ -45,12 +45,17 @@ async function readRuntimeBundle(adapter = 'cursor') {
45
45
  }
46
46
  export async function renderRuntimeCore(adapter = 'cursor') {
47
47
  const bundle = await readRuntimeBundle(adapter);
48
- const stamp = `export const RUNTIME_BUILD_STAMP = ${JSON.stringify(`${PACKAGE_VERSION}@${new Date().toISOString()}`)};\n`;
48
+ const runtimeBuildStamp = `${PACKAGE_VERSION}@${new Date().toISOString()}`;
49
+ const stamp = `export const RUNTIME_BUILD_STAMP = ${JSON.stringify(runtimeBuildStamp)};\n`;
49
50
  const versionLine = `export const RUNTIME_PACKAGE_VERSION = ${JSON.stringify(PACKAGE_VERSION)};\n`;
51
+ const provenance = `globalThis[Symbol.for("agent-belay.runtime-provenance")] = ${JSON.stringify({
52
+ runtimeVersion: PACKAGE_VERSION,
53
+ runtimeBuildStamp,
54
+ })};\n`;
50
55
  const withoutStamp = bundle
51
56
  .replace(/^export const RUNTIME_BUILD_STAMP = .*;\n/gm, '')
52
57
  .replace(/^export const RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
53
58
  .replace(/^var RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
54
59
  .replace(/\n {2}RUNTIME_PACKAGE_VERSION,\n/, '\n');
55
- return `${versionLine}${stamp}${withoutStamp}`;
60
+ return `${versionLine}${stamp}${provenance}${withoutStamp}`;
56
61
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "0.7.0";
1
+ export declare const PACKAGE_VERSION = "0.8.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by scripts/sync-version.mjs — do not edit.
2
- export const PACKAGE_VERSION = '0.7.0';
2
+ export const PACKAGE_VERSION = '0.8.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guilz-dev/belay",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Belay-style approval and audit gating for agent runtimes.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "agent-belay-logo.png"
49
49
  ],
50
50
  "scripts": {
51
- "build": "rm -rf dist && node scripts/sync-version.mjs && tsc -p tsconfig.build.json && node scripts/generate-standing-allow-catalog.mjs && tsc -p tsconfig.build.json && node scripts/build-runtime.mjs",
51
+ "build": "rm -rf dist && node scripts/sync-version.mjs && tsc -p tsconfig.build.json && node scripts/build-runtime.mjs",
52
52
  "check:version": "node scripts/check-cli-version.mjs",
53
53
  "dogfood": "./scripts/dev-dogfood.sh",
54
54
  "dev-refresh": "./scripts/dev-refresh.sh",
@@ -1,7 +0,0 @@
1
- import type { ParsedSegment } from './parser.js';
2
- import type { InternalSegmentVerdict, VerdictContext } from './types.js';
3
- export declare function matchesCustomPatterns(command: string, segment: ParsedSegment, patterns: string[] | undefined): boolean;
4
- export declare function customAllowMatch(command: string, segment: ParsedSegment, context: VerdictContext): boolean;
5
- export declare function customExternalMatch(command: string, segment: ParsedSegment, context: VerdictContext): boolean;
6
- export declare function allowFromCustomOverride(opacity: InternalSegmentVerdict['opacity']): InternalSegmentVerdict;
7
- export declare function askFromCustomExternal(opacity: InternalSegmentVerdict['opacity']): InternalSegmentVerdict;
@@ -1,37 +0,0 @@
1
- import { matchesCustomCommand } from '../custom-command-match.js';
2
- export function matchesCustomPatterns(command, segment, patterns) {
3
- if (!patterns || patterns.length === 0) {
4
- return false;
5
- }
6
- const normalized = command.trim();
7
- return patterns.some((pattern) => matchesCustomCommand(normalized, segment.key, pattern) ||
8
- matchesCustomCommand(segment.normalized, segment.key, pattern));
9
- }
10
- export function customAllowMatch(command, segment, context) {
11
- return matchesCustomPatterns(command, segment, context.customAllowCommands);
12
- }
13
- export function customExternalMatch(command, segment, context) {
14
- return matchesCustomPatterns(command, segment, context.customExternalCommands);
15
- }
16
- export function allowFromCustomOverride(opacity) {
17
- return {
18
- permission: 'allow',
19
- location: 'repo_local',
20
- opacity,
21
- effect: 'unknown',
22
- confidence: 'deterministic',
23
- reason: 'custom_allow',
24
- signals: ['custom_allow'],
25
- };
26
- }
27
- export function askFromCustomExternal(opacity) {
28
- return {
29
- permission: 'ask',
30
- location: 'external',
31
- opacity,
32
- effect: 'remote_mutation',
33
- confidence: 'deterministic',
34
- reason: 'custom_external',
35
- signals: ['custom_external'],
36
- };
37
- }
@@ -1,26 +0,0 @@
1
- import { type ShellCapabilityAnalysis } from '../capability/policy-engine.js';
2
- import type { PolicyDecision } from '../capability/policy-types.js';
3
- import type { CapabilityRequestV1 } from '../capability/request.js';
4
- import type { VerdictContext, VerdictEffect, VerdictLocation, VerdictOpacity } from './types.js';
5
- export interface SegmentShellPolicyInput {
6
- command: string;
7
- segmentHead: string;
8
- effect: VerdictEffect;
9
- location: VerdictLocation;
10
- opacity: VerdictOpacity;
11
- egressClass?: ShellCapabilityAnalysis['egressClass'];
12
- pathArgs: string[];
13
- resolvedPathTargets?: string[];
14
- signals: string[];
15
- context: VerdictContext;
16
- }
17
- export declare function evaluateSegmentShellPolicy(input: SegmentShellPolicyInput): {
18
- request: CapabilityRequestV1;
19
- requests: CapabilityRequestV1[];
20
- decision: PolicyDecision;
21
- };
22
- /** Attach capability metadata without influencing the verdict (audit / shadow only). */
23
- export declare function shellPolicyMetadata(input: SegmentShellPolicyInput): {
24
- capabilityRequests: CapabilityRequestV1[];
25
- authorizationDecision: PolicyDecision;
26
- };
@@ -1,40 +0,0 @@
1
- import { evaluateShellPolicy } from '../capability/policy-engine.js';
2
- import { cwdRelative } from './containment.js';
3
- import { verdictFingerprint } from './fingerprint.js';
4
- import { redactCommand } from './parser.js';
5
- function toShellCapabilityAnalysis(input) {
6
- const relative = cwdRelative(input.context.repoRoot, input.context.cwd);
7
- return {
8
- command: input.command,
9
- hookKind: 'shell',
10
- segmentHead: input.segmentHead,
11
- effect: input.effect,
12
- location: input.location,
13
- opacity: input.opacity,
14
- egressClass: input.egressClass,
15
- pathArgs: input.pathArgs,
16
- resolvedPathTargets: input.resolvedPathTargets,
17
- signals: input.signals,
18
- cwd: input.context.cwd,
19
- repoRoot: input.context.repoRoot,
20
- inputFingerprint: verdictFingerprint(relative, redactCommand(input.command)),
21
- trustedWorkspaceRoots: input.context.trustedWorkspaceRoots,
22
- sensitivePaths: input.context.sensitivePaths,
23
- protectedArtifactRoots: input.context.protectedArtifactRoots,
24
- };
25
- }
26
- export function evaluateSegmentShellPolicy(input) {
27
- return evaluateShellPolicy(toShellCapabilityAnalysis(input), input.context.config, {
28
- grants: input.context.grants,
29
- attestation: input.context.attestation,
30
- egressProxyActive: input.context.egressProxyActive,
31
- });
32
- }
33
- /** Attach capability metadata without influencing the verdict (audit / shadow only). */
34
- export function shellPolicyMetadata(input) {
35
- const result = evaluateSegmentShellPolicy(input);
36
- return {
37
- capabilityRequests: result.requests,
38
- authorizationDecision: result.decision,
39
- };
40
- }
@@ -1,13 +0,0 @@
1
- export interface StandingAllowCatalogShellEntry {
2
- command: string;
3
- normalizedCommand: string;
4
- runtimeKey: string;
5
- }
6
- export interface StandingAllowCatalog {
7
- version: 1;
8
- shell: {
9
- provablyBenign: StandingAllowCatalogShellEntry[];
10
- mustAllow: StandingAllowCatalogShellEntry[];
11
- };
12
- }
13
- export declare const STANDING_ALLOW_CATALOG: StandingAllowCatalog;
@@ -1,99 +0,0 @@
1
- export const STANDING_ALLOW_CATALOG = {
2
- version: 1,
3
- shell: {
4
- provablyBenign: [
5
- {
6
- command: 'git status',
7
- normalizedCommand: 'git status',
8
- runtimeKey: '37e6be21e63e6268ee6e4212ad811f6f48ab3c3c10ce1b971c1a90d92c753a2a',
9
- },
10
- {
11
- command: 'git branch',
12
- normalizedCommand: 'git branch',
13
- runtimeKey: 'd7f8388c566e751503ab82ba1ed22787389803eb32d8b5f2294cc7ca448fa285',
14
- },
15
- {
16
- command: 'git branch --show-current',
17
- normalizedCommand: 'git branch --show-current',
18
- runtimeKey: '98d585412d3cd7c3b5a87a417d91bc36d7b6791e11451b52ced7888e003d9d33',
19
- },
20
- {
21
- command: 'rg plan src',
22
- normalizedCommand: 'rg plan src',
23
- runtimeKey: '68ae7a96158719235d9314da7b00a5f8b2f40668e5d4f7f02e91f22284140a68',
24
- },
25
- {
26
- command: 'ls -la',
27
- normalizedCommand: 'ls -la',
28
- runtimeKey: '3a665991b52b5f18069889960b957ea37b087859c23e2c87b76ef8d2a1b338fe',
29
- },
30
- {
31
- command: "find . -name '*.ts'",
32
- normalizedCommand: "find . -name '*.ts'",
33
- runtimeKey: '782298e3015fcb9c17bee2dad12a395a8859043481f93f0ca596499028bb8af2',
34
- },
35
- {
36
- command: 'git -C /workspace/project status',
37
- normalizedCommand: 'git -C /workspace/project status',
38
- runtimeKey: '9f88bd017c52277f5dbfeafec7d845460035a7a14bfb37b55724d7e2a9fc238b',
39
- },
40
- {
41
- command: 'git show-ref --heads',
42
- normalizedCommand: 'git show-ref --heads',
43
- runtimeKey: 'aa5aa0106dc7647003f254524becbf549673610d3672f28408ac0f60481124b7',
44
- },
45
- {
46
- command: 'git reflog -5',
47
- normalizedCommand: 'git reflog -5',
48
- runtimeKey: '9213a9357953c24886a4e82c2c8cdc6db2d106c7ff98af525f7fbc2b70a58ff9',
49
- },
50
- {
51
- command: 'grep -R pattern src',
52
- normalizedCommand: 'grep -R pattern src',
53
- runtimeKey: '40f5e0328e668909241aa0cd13ce2a51af269aa7ae600cc493dceae7b90dd9d8',
54
- },
55
- {
56
- command: 'jq . package.json',
57
- normalizedCommand: 'jq . package.json',
58
- runtimeKey: 'dd7b14d350b84a41e0e73eae0d1a643c1b6c262df8d9007696987354f4f993e9',
59
- },
60
- ],
61
- mustAllow: [
62
- {
63
- command: 'npm test',
64
- normalizedCommand: 'npm test',
65
- runtimeKey: '1bcafcfef8e1b0138297885032c5e222c4aed19bdcde00e2539aa397fdc877cb',
66
- },
67
- {
68
- command: 'npm run build',
69
- normalizedCommand: 'npm run build',
70
- runtimeKey: '3138d8a3e9afb60574e29d16c2967f70bb42475e02eadb261f5f2340f376c188',
71
- },
72
- {
73
- command: 'pnpm test',
74
- normalizedCommand: 'pnpm test',
75
- runtimeKey: 'eaecc988be421de36044932e32d4be807e45baccaa94c2d29d30a34204656551',
76
- },
77
- {
78
- command: 'pnpm build',
79
- normalizedCommand: 'pnpm build',
80
- runtimeKey: 'a1ec94b6b1f7f17ab0fe468e41c6dc59e04266d34772abcaa9538123601cb46d',
81
- },
82
- {
83
- command: 'pnpm vitest run src/example.test.ts',
84
- normalizedCommand: 'pnpm vitest run src/example.test.ts',
85
- runtimeKey: '011e12e902154e7cf598f390fc08a50e885b34893deb97d242cf7470e23e617e',
86
- },
87
- {
88
- command: "bash -lc 'git status'",
89
- normalizedCommand: "bash -lc 'git status'",
90
- runtimeKey: 'dbcc63715f4a8cca2aff988470bb1d52a4841542af9c86776ff2414509508a1f',
91
- },
92
- {
93
- command: 'belay approve belay_deadbeef1234',
94
- normalizedCommand: 'belay approve belay_deadbeef1234',
95
- runtimeKey: 'bb3f0f1dac3d6c4ef79e17ef4e36f9430195596490bb736cdb8b25a5944d6f81',
96
- },
97
- ],
98
- },
99
- };