vouchington-tooling 0.29.0 → 0.30.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 (141) hide show
  1. package/README.md +64 -16
  2. package/dist/api-contract-discovery/header-contract-registry.mjs +2 -0
  3. package/dist/api-contract-discovery/protocol-body-status.d.mts +2 -0
  4. package/dist/api-contract-discovery/protocol-body-status.mjs +4 -0
  5. package/dist/api-contract-discovery/protocol-callback-argument-bindings.d.mts +7 -0
  6. package/dist/api-contract-discovery/protocol-callback-argument-bindings.mjs +33 -0
  7. package/dist/api-contract-discovery/protocol-callback-invocation.d.mts +5 -0
  8. package/dist/api-contract-discovery/protocol-callback-invocation.mjs +103 -0
  9. package/dist/api-contract-discovery/protocol-callback-mutations.d.mts +5 -0
  10. package/dist/api-contract-discovery/protocol-callback-mutations.mjs +42 -0
  11. package/dist/api-contract-discovery/protocol-callback-registration.d.mts +3 -0
  12. package/dist/api-contract-discovery/protocol-callback-registration.mjs +27 -0
  13. package/dist/api-contract-discovery/protocol-callback-values.d.mts +17 -0
  14. package/dist/api-contract-discovery/protocol-callback-values.mjs +114 -0
  15. package/dist/api-contract-discovery/protocol-context-alias.d.mts +3 -0
  16. package/dist/api-contract-discovery/protocol-context-alias.mjs +20 -0
  17. package/dist/api-contract-discovery/protocol-contract-extraction.d.mts +9 -0
  18. package/dist/api-contract-discovery/protocol-contract-extraction.mjs +87 -0
  19. package/dist/api-contract-discovery/protocol-contract-keys.d.mts +1 -0
  20. package/dist/api-contract-discovery/protocol-contract-keys.mjs +8 -0
  21. package/dist/api-contract-discovery/protocol-contract-registry.d.mts +5 -0
  22. package/dist/api-contract-discovery/protocol-contract-registry.mjs +133 -0
  23. package/dist/api-contract-discovery/protocol-executable-path.d.mts +3 -0
  24. package/dist/api-contract-discovery/protocol-executable-path.mjs +64 -0
  25. package/dist/api-contract-discovery/protocol-execution-path.d.mts +3 -0
  26. package/dist/api-contract-discovery/protocol-execution-path.mjs +16 -0
  27. package/dist/api-contract-discovery/protocol-http-association.d.mts +7 -0
  28. package/dist/api-contract-discovery/protocol-http-association.mjs +97 -0
  29. package/dist/api-contract-discovery/protocol-http-body-kinds.d.mts +3 -0
  30. package/dist/api-contract-discovery/protocol-http-body-kinds.mjs +19 -0
  31. package/dist/api-contract-discovery/protocol-http-context-callers.d.mts +6 -0
  32. package/dist/api-contract-discovery/protocol-http-context-callers.mjs +34 -0
  33. package/dist/api-contract-discovery/protocol-http-context.d.mts +9 -0
  34. package/dist/api-contract-discovery/protocol-http-context.mjs +108 -0
  35. package/dist/api-contract-discovery/protocol-http-emission.d.mts +3 -0
  36. package/dist/api-contract-discovery/protocol-http-emission.mjs +76 -0
  37. package/dist/api-contract-discovery/protocol-http-implicit-taint.d.mts +7 -0
  38. package/dist/api-contract-discovery/protocol-http-implicit-taint.mjs +26 -0
  39. package/dist/api-contract-discovery/protocol-http-registration.d.mts +12 -0
  40. package/dist/api-contract-discovery/protocol-http-registration.mjs +53 -0
  41. package/dist/api-contract-discovery/protocol-marker-analysis.d.mts +7 -0
  42. package/dist/api-contract-discovery/protocol-marker-analysis.mjs +50 -0
  43. package/dist/api-contract-discovery/protocol-opaque-callback.d.mts +3 -0
  44. package/dist/api-contract-discovery/protocol-opaque-callback.mjs +107 -0
  45. package/dist/api-contract-discovery/protocol-platform-callbacks.d.mts +5 -0
  46. package/dist/api-contract-discovery/protocol-platform-callbacks.mjs +72 -0
  47. package/dist/api-contract-discovery/protocol-platform-mutation-targets.d.mts +5 -0
  48. package/dist/api-contract-discovery/protocol-platform-mutation-targets.mjs +89 -0
  49. package/dist/api-contract-discovery/protocol-platform-writes.d.mts +3 -0
  50. package/dist/api-contract-discovery/protocol-platform-writes.mjs +92 -0
  51. package/dist/api-contract-discovery/protocol-requested-keys.d.mts +5 -0
  52. package/dist/api-contract-discovery/protocol-requested-keys.mjs +45 -0
  53. package/dist/api-contract-discovery/protocol-sse-callers.d.mts +7 -0
  54. package/dist/api-contract-discovery/protocol-sse-callers.mjs +67 -0
  55. package/dist/api-contract-discovery/protocol-sse-emission.d.mts +11 -0
  56. package/dist/api-contract-discovery/protocol-sse-emission.mjs +61 -0
  57. package/dist/api-contract-discovery/protocol-sse-feasible-status.d.mts +3 -0
  58. package/dist/api-contract-discovery/protocol-sse-feasible-status.mjs +24 -0
  59. package/dist/api-contract-discovery/protocol-sse-raw-writes.d.mts +9 -0
  60. package/dist/api-contract-discovery/protocol-sse-raw-writes.mjs +70 -0
  61. package/dist/api-contract-discovery/protocol-sse-status.d.mts +3 -0
  62. package/dist/api-contract-discovery/protocol-sse-status.mjs +84 -0
  63. package/dist/api-contract-discovery/protocol-sse-write-access.d.mts +9 -0
  64. package/dist/api-contract-discovery/protocol-sse-write-access.mjs +42 -0
  65. package/dist/api-contract-discovery/protocol-sse-write-helpers.d.mts +6 -0
  66. package/dist/api-contract-discovery/protocol-sse-write-helpers.mjs +66 -0
  67. package/dist/api-contract-discovery/protocol-sse-write-mutations.d.mts +9 -0
  68. package/dist/api-contract-discovery/protocol-sse-write-mutations.mjs +36 -0
  69. package/dist/api-contract-discovery/protocol-sse-write-resolution.d.mts +14 -0
  70. package/dist/api-contract-discovery/protocol-sse-write-resolution.mjs +79 -0
  71. package/dist/api-contract-discovery/protocol-status-dominance.d.mts +5 -0
  72. package/dist/api-contract-discovery/protocol-status-dominance.mjs +35 -0
  73. package/dist/api-contract-discovery/protocol-write-receiver.d.mts +9 -0
  74. package/dist/api-contract-discovery/protocol-write-receiver.mjs +79 -0
  75. package/dist/api-contract-discovery/query-contract-registry.mjs +2 -0
  76. package/dist/api-contract-discovery/registered-route-binding-writes.d.mts +3 -0
  77. package/dist/api-contract-discovery/registered-route-binding-writes.mjs +30 -0
  78. package/dist/api-contract-discovery/registered-route-catalog.mjs +11 -7
  79. package/dist/api-contract-discovery/registered-route-factory-returns.d.mts +3 -0
  80. package/dist/api-contract-discovery/registered-route-factory-returns.mjs +29 -0
  81. package/dist/api-contract-discovery/registered-route-handler-analysis.d.mts +5 -1
  82. package/dist/api-contract-discovery/registered-route-handler-analysis.mjs +79 -35
  83. package/dist/api-contract-discovery/registered-route-runtime-parameters.d.mts +3 -0
  84. package/dist/api-contract-discovery/registered-route-runtime-parameters.mjs +5 -0
  85. package/dist/api-contract-discovery/registered-route-terminal-error.d.mts +3 -0
  86. package/dist/api-contract-discovery/registered-route-terminal-error.mjs +98 -0
  87. package/dist/api-contract-discovery/request-contract-registry.mjs +2 -0
  88. package/dist/api-contract-discovery/response-contract-implicit.mjs +28 -10
  89. package/dist/api-contract-discovery/response-contract-registry.mjs +14 -1
  90. package/dist/api-contract-discovery/response-contract-route-analysis.d.mts +1 -1
  91. package/dist/api-contract-discovery/response-contract-route-analysis.mjs +22 -4
  92. package/dist/api-contract-discovery/response-contract-status.d.mts +1 -1
  93. package/dist/api-contract-discovery/response-contract-status.mjs +10 -8
  94. package/dist/api-contract-discovery/response-contract-types.d.mts +7 -0
  95. package/dist/cli/index.mjs +0 -3
  96. package/dist/cli/parse-forwarded-commands.d.mts +0 -3
  97. package/dist/cli/parse-forwarded-commands.mjs +0 -2
  98. package/dist/cli/parse.d.mts +0 -3
  99. package/dist/cli/usage.d.mts +1 -1
  100. package/dist/cli/usage.mjs +0 -5
  101. package/dist/contract-schema/contract-schema-bounded-array.d.mts +1 -3
  102. package/dist/contract-schema/contract-schema-bounded-array.mjs +5 -0
  103. package/dist/contract-schema/contract-schema-object-tuple.mjs +7 -5
  104. package/dist/contract-schema/contract-schema-type-extractor.mjs +13 -0
  105. package/dist/contract-schema/contract-schema-validator.mjs +2 -2
  106. package/dist/index.d.mts +0 -2
  107. package/dist/index.mjs +0 -1
  108. package/dist/openapi-document/build-openapi-catalog-sse.d.mts +4 -0
  109. package/dist/openapi-document/build-openapi-catalog-sse.mjs +27 -0
  110. package/dist/openapi-document/build-openapi-document.mjs +5 -2
  111. package/dist/openapi-document/build-openapi-response.d.mts +2 -2
  112. package/dist/openapi-document/build-openapi-response.mjs +33 -3
  113. package/dist/openapi-document/build-openapi-sse-events.d.mts +11 -0
  114. package/dist/openapi-document/build-openapi-sse-events.mjs +46 -0
  115. package/dist/openapi-document/contract-schema-intersection-merge.mjs +11 -11
  116. package/dist/openapi-document/contract-schema-to-openapi.mjs +3 -3
  117. package/dist/openapi-document/openapi-route-helpers.mjs +1 -3
  118. package/dist/openapi-document/openapi-types.d.mts +3 -0
  119. package/dist/openapi-document/operation-types.d.mts +7 -0
  120. package/package.json +3 -8
  121. package/dist/agent-harness-config/apply.d.mts +0 -4
  122. package/dist/agent-harness-config/apply.mjs +0 -72
  123. package/dist/agent-harness-config/cli.d.mts +0 -10
  124. package/dist/agent-harness-config/cli.mjs +0 -100
  125. package/dist/agent-harness-config/index.d.mts +0 -4
  126. package/dist/agent-harness-config/index.mjs +0 -3
  127. package/dist/agent-harness-config/merge-json.d.mts +0 -5
  128. package/dist/agent-harness-config/merge-json.mjs +0 -62
  129. package/dist/agent-harness-config/merge-toml.d.mts +0 -6
  130. package/dist/agent-harness-config/merge-toml.mjs +0 -132
  131. package/dist/agent-harness-config/paths.d.mts +0 -3
  132. package/dist/agent-harness-config/paths.mjs +0 -117
  133. package/dist/agent-harness-config/policy.d.mts +0 -14
  134. package/dist/agent-harness-config/policy.mjs +0 -51
  135. package/dist/agent-harness-config/prerequisites.d.mts +0 -2
  136. package/dist/agent-harness-config/prerequisites.mjs +0 -67
  137. package/dist/agent-harness-config/toml-value.d.mts +0 -6
  138. package/dist/agent-harness-config/toml-value.mjs +0 -69
  139. package/dist/agent-harness-config/types.d.mts +0 -90
  140. package/dist/agent-harness-config/types.mjs +0 -2
  141. package/docs/agent-harness-config.md +0 -134
@@ -1,51 +0,0 @@
1
- export const DEFAULT_EXTRA_WRITABLE_ROOTS = [
2
- '~/.cargo',
3
- '~/Library/pnpm',
4
- '~/.local/share/pnpm',
5
- '~/.pnpm-store',
6
- '~/Library/Caches/no-mistakes',
7
- '~/Library/Caches/pnpm',
8
- '~/.pnpm-state',
9
- '~/.cache/no-mistakes',
10
- '~/.cache/pnpm',
11
- '~/.local/state/pnpm',
12
- '/var/folders',
13
- '/private/var/folders',
14
- ];
15
- export const CLAUDE_DEFAULT_MODE = 'auto';
16
- export const CODEX_APPROVAL_POLICY = 'on-request';
17
- export const CODEX_APPROVALS_REVIEWER = 'auto_review';
18
- export const CODEX_SANDBOX_MODE = 'workspace-write';
19
- export const GROK_PERMISSION_MODE = 'auto';
20
- export const GROK_SANDBOX_PROFILE = 'workspace-write';
21
- export const GROK_AUTO_MODE_ENABLED = true;
22
- export const GROK_DEFAULT_AUTO_MODE = true;
23
- export const CURSOR_APPROVAL_MODE = 'auto-review';
24
- export const CURSOR_SANDBOX_MODE = 'enabled';
25
- export function dumpHarnessPolicy(extraWritableRoots = DEFAULT_EXTRA_WRITABLE_ROOTS) {
26
- return {
27
- claude: {
28
- defaultMode: CLAUDE_DEFAULT_MODE,
29
- sandboxEnabled: true,
30
- sandboxFailIfUnavailable: true,
31
- useAutoModeDuringPlan: true,
32
- },
33
- codex: {
34
- approval_policy: CODEX_APPROVAL_POLICY,
35
- approvals_reviewer: CODEX_APPROVALS_REVIEWER,
36
- sandbox_mode: CODEX_SANDBOX_MODE,
37
- },
38
- cursor: { approvalMode: CURSOR_APPROVAL_MODE, sandboxMode: CURSOR_SANDBOX_MODE },
39
- extraWritableRoots: [...extraWritableRoots],
40
- grok: {
41
- auto_mode_enabled: GROK_AUTO_MODE_ENABLED,
42
- default_auto_mode: GROK_DEFAULT_AUTO_MODE,
43
- permission_mode: GROK_PERMISSION_MODE,
44
- sandbox_profile_defined: GROK_SANDBOX_PROFILE,
45
- sandbox_profile_requires_cli_selection: true,
46
- },
47
- };
48
- }
49
- export function sameValue(left, right) {
50
- return JSON.stringify(left) === JSON.stringify(right);
51
- }
@@ -1,2 +0,0 @@
1
- import type { HarnessConfigOptions, HarnessPrerequisite } from './types.mts';
2
- export declare function checkHarnessPrerequisites(root: string | undefined, options?: HarnessConfigOptions): Promise<HarnessPrerequisite[]>;
@@ -1,67 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { homedir } from 'node:os';
3
- import { join, resolve } from 'node:path';
4
- import { readTomlKey } from './merge-toml.mjs';
5
- import { CURSOR_APPROVAL_MODE } from './policy.mjs';
6
- import { HARNESS_IDS } from './types.mjs';
7
- async function readOptional(path) {
8
- try {
9
- return await readFile(path, 'utf8');
10
- }
11
- catch (error) {
12
- if (error.code === 'ENOENT')
13
- return '';
14
- throw error;
15
- }
16
- }
17
- function selected(options, harness) {
18
- return (options?.harnesses ?? HARNESS_IDS).includes(harness);
19
- }
20
- function homeDir(options) {
21
- return resolve(options?.home ?? homedir());
22
- }
23
- async function codexTrust(root, options) {
24
- const source = await readOptional(join(homeDir(options), '.codex', 'config.toml'));
25
- const table = `projects.${JSON.stringify(resolve(root))}`;
26
- return {
27
- harness: 'codex',
28
- key: 'trusted-project',
29
- message: 'trust this project in Codex before relying on its .codex/config.toml',
30
- satisfied: readTomlKey(source, table, 'trust_level') === 'trusted',
31
- };
32
- }
33
- async function cursorApproval(options) {
34
- const source = await readOptional(join(homeDir(options), '.cursor', 'cli-config.json'));
35
- let satisfied = false;
36
- try {
37
- const parsed = JSON.parse(source);
38
- satisfied = parsed.approvalMode === CURSOR_APPROVAL_MODE;
39
- }
40
- catch {
41
- // A missing or invalid user config leaves the prerequisite unsatisfied.
42
- }
43
- return {
44
- harness: 'cursor',
45
- key: 'global-auto-review',
46
- message: 'set approvalMode=auto-review in ~/.cursor/cli-config.json',
47
- satisfied,
48
- };
49
- }
50
- function grokSandbox() {
51
- return {
52
- harness: 'grok',
53
- key: 'sandbox-profile-selection',
54
- message: 'start Grok with --sandbox workspace-write to activate the defined profile',
55
- satisfied: false,
56
- };
57
- }
58
- export async function checkHarnessPrerequisites(root, options) {
59
- const prerequisites = [];
60
- if (selected(options, 'grok'))
61
- prerequisites.push(grokSandbox());
62
- if (root !== undefined && selected(options, 'codex'))
63
- prerequisites.push(await codexTrust(root, options));
64
- if (root !== undefined && selected(options, 'cursor'))
65
- prerequisites.push(await cursorApproval(options));
66
- return prerequisites;
67
- }
@@ -1,6 +0,0 @@
1
- import type { TomlValue } from './types.mts';
2
- export declare function formatTomlValue(value: TomlValue): string;
3
- export declare function parseTomlValue(text: string, start: number): {
4
- end: number;
5
- value: boolean | string | string[];
6
- };
@@ -1,69 +0,0 @@
1
- export function formatTomlValue(value) {
2
- if (typeof value === 'boolean')
3
- return value ? 'true' : 'false';
4
- if (typeof value === 'string')
5
- return JSON.stringify(value);
6
- const items = value.map((entry) => ` ${JSON.stringify(entry)},`).join('\n');
7
- return `[\n${items}\n]`;
8
- }
9
- function skipSpaceAndComments(text, start) {
10
- let index = start;
11
- while (index < text.length) {
12
- const char = text[index];
13
- if (char === ' ' || char === '\t' || char === '\n' || char === '\r' || char === ',') {
14
- index += 1;
15
- continue;
16
- }
17
- if (char === '#') {
18
- while (index < text.length && text[index] !== '\n')
19
- index += 1;
20
- continue;
21
- }
22
- break;
23
- }
24
- return index;
25
- }
26
- function parseTomlString(text, start) {
27
- const quote = text[start];
28
- let index = start + 1;
29
- let value = '';
30
- while (index < text.length) {
31
- const char = text[index];
32
- if (char === quote)
33
- return { end: index + 1, value };
34
- if (quote === '"' && char === '\\') {
35
- const next = text[index + 1];
36
- if (next === undefined)
37
- break;
38
- value += next === 'n' ? '\n' : next === 't' ? '\t' : next;
39
- index += 2;
40
- continue;
41
- }
42
- value += char;
43
- index += 1;
44
- }
45
- throw new Error('unterminated TOML string');
46
- }
47
- export function parseTomlValue(text, start) {
48
- const index = skipSpaceAndComments(text, start);
49
- if (text.startsWith('true', index))
50
- return { end: index + 4, value: true };
51
- if (text.startsWith('false', index))
52
- return { end: index + 5, value: false };
53
- if (text[index] === '"' || text[index] === "'")
54
- return parseTomlString(text, index);
55
- if (text[index] !== '[')
56
- throw new Error('unsupported TOML value');
57
- const items = [];
58
- let cursor = index + 1;
59
- for (;;) {
60
- cursor = skipSpaceAndComments(text, cursor);
61
- if (text[cursor] === ']')
62
- return { end: cursor + 1, value: items };
63
- if (text[cursor] !== '"' && text[cursor] !== "'")
64
- throw new Error('unsupported TOML array value');
65
- const parsed = parseTomlString(text, cursor);
66
- items.push(parsed.value);
67
- cursor = parsed.end;
68
- }
69
- }
@@ -1,90 +0,0 @@
1
- import { HARNESS_IDS } from '../agent-harness-identity/index.mts';
2
- import type { HarnessId } from '../agent-harness-identity/index.mts';
3
- export { HARNESS_IDS };
4
- export type { HarnessId };
5
- export type ApplyTarget = {
6
- readonly kind: 'global';
7
- } | {
8
- readonly kind: 'repo';
9
- readonly root: string;
10
- };
11
- export interface JsonPatch {
12
- readonly merge?: 'union';
13
- readonly path: readonly string[];
14
- readonly value: unknown;
15
- }
16
- export type TomlValue = boolean | string | readonly string[];
17
- export interface TomlPatch {
18
- readonly key: string;
19
- readonly table: string;
20
- readonly value: TomlValue;
21
- }
22
- export type FilePlan = {
23
- readonly format: 'json';
24
- readonly patches: readonly JsonPatch[];
25
- readonly path: string;
26
- } | {
27
- readonly format: 'toml';
28
- readonly patches: readonly TomlPatch[];
29
- readonly path: string;
30
- };
31
- export interface KeyDrift {
32
- readonly current: unknown;
33
- readonly desired: unknown;
34
- readonly key: string;
35
- readonly path: string;
36
- }
37
- export interface FileResult {
38
- readonly action: 'create' | 'update' | 'ok' | 'missing';
39
- readonly drifts: readonly KeyDrift[];
40
- readonly path: string;
41
- }
42
- export interface HarnessPlan {
43
- readonly files: readonly FilePlan[];
44
- readonly target: ApplyTarget;
45
- }
46
- export interface HarnessCheckResult {
47
- readonly compliant: boolean;
48
- readonly files: readonly FileResult[];
49
- readonly prerequisites: readonly HarnessPrerequisite[];
50
- readonly target: ApplyTarget;
51
- }
52
- export interface HarnessPrerequisite {
53
- readonly harness: HarnessId;
54
- readonly key: string;
55
- readonly message: string;
56
- readonly satisfied: boolean;
57
- }
58
- export interface HarnessApplyResult extends HarnessCheckResult {
59
- readonly written: readonly string[];
60
- }
61
- export interface HarnessConfigOptions {
62
- readonly extraWritableRoots?: readonly string[];
63
- readonly harnesses?: readonly HarnessId[];
64
- readonly home?: string;
65
- }
66
- export interface HarnessPolicyDump {
67
- readonly claude: {
68
- readonly defaultMode: 'auto';
69
- readonly sandboxEnabled: true;
70
- readonly sandboxFailIfUnavailable: true;
71
- readonly useAutoModeDuringPlan: true;
72
- };
73
- readonly codex: {
74
- readonly approval_policy: 'on-request';
75
- readonly approvals_reviewer: 'auto_review';
76
- readonly sandbox_mode: 'workspace-write';
77
- };
78
- readonly cursor: {
79
- readonly approvalMode: 'auto-review';
80
- readonly sandboxMode: 'enabled';
81
- };
82
- readonly extraWritableRoots: readonly string[];
83
- readonly grok: {
84
- readonly auto_mode_enabled: true;
85
- readonly default_auto_mode: true;
86
- readonly permission_mode: 'auto';
87
- readonly sandbox_profile_defined: 'workspace-write';
88
- readonly sandbox_profile_requires_cli_selection: true;
89
- };
90
- }
@@ -1,2 +0,0 @@
1
- import { HARNESS_IDS } from '../agent-harness-identity/index.mjs';
2
- export { HARNESS_IDS };
@@ -1,134 +0,0 @@
1
- # Agent harness config
2
-
3
- `vouchington agent-harness-config` merges a portable **classifier-auto + sandbox**
4
- policy into Claude, Codex, Grok, and Cursor config files. It does not copy
5
- allowlists, hooks, plugins, MCP servers, or models.
6
-
7
- Use it to keep local interactive sessions on a permission classifier (routine
8
- work proceeds, risky calls still prompt) with an OS sandbox enabled.
9
-
10
- ## Classifier vs always-approve
11
-
12
- Always-approve / YOLO is not the same as classifier auto. Cursor
13
- `unrestricted` also forces the sandbox off.
14
-
15
- | Harness | Classifier (this tool writes) | Do not use | Sandbox |
16
- | ------- | ------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------ |
17
- | Claude | `permissions.defaultMode = "auto"` | `bypassPermissions` | `sandbox.enabled = true`, fail closed if unavailable |
18
- | Codex | `approval_policy = "on-request"` and `approvals_reviewer = "auto_review"` | `approval_policy = "never"` | `sandbox_mode = "workspace-write"` plus extra writable roots |
19
- | Grok | `ui.permission_mode = "auto"` | `always-approve` / `bypassPermissions` / `--yolo` | defines `workspace-write`; invoke with `--sandbox workspace-write` |
20
- | Cursor | `approvalMode = "auto-review"` | `unrestricted` (`--force` / `--yolo`) | `sandbox.mode = "enabled"` |
21
-
22
- Grok Auto is a separate mode from plan. Shift+Tab is `Normal → Plan → Auto
23
- (when enabled) → Always-approve`. The tool also writes `auto_mode.enabled =
24
- true` and `default_auto_mode = true` so Auto is available by default and
25
- stays the permission classifier under plan mode. Plan-file edits remain
26
- auto-approved; other file edits stay blocked. That is not YOLO.
27
-
28
- Repo Claude settings set `sandbox.enabled` and `sandbox.failIfUnavailable`.
29
- They do not change a
30
- project `permissions.defaultMode` of `"plan"`.
31
-
32
- Grok config can define a sandbox profile but cannot activate it for a future
33
- session. Start Grok with `--sandbox workspace-write`; `check` reports this as
34
- an unmet manual prerequisite so it never claims the profile is active.
35
-
36
- ## CLI
37
-
38
- ```bash
39
- vouchington agent-harness-config dump
40
- vouchington agent-harness-config check --global
41
- vouchington agent-harness-config check --repo /path/to/checkout
42
- vouchington agent-harness-config apply --global --repo /path --repo /other
43
- vouchington agent-harness-config apply --global --harness grok --harness cursor
44
- ```
45
-
46
- - `dump` prints the canonical key map as JSON. It does not need `--global` or `--repo`.
47
- - `check` and `apply` require at least one of `--global` or `--repo` (repeatable).
48
- - `--harness` filters to `claude`, `codex`, `grok`, or `cursor`. Default is all four.
49
- - `--home` overrides the user home directory (tests and nonstandard layouts).
50
- - `check` exits `0` when every targeted file and prerequisite matches, `1` on drift or an unmet prerequisite, and `2` on usage errors.
51
- - `apply` writes only drifted keys, then exits `1` when a prerequisite remains unmet and `2` on I/O or usage errors.
52
-
53
- ## Library
54
-
55
- ```ts
56
- import {
57
- applyHarnessConfig,
58
- checkHarnessConfig,
59
- dumpHarnessPolicy,
60
- planHarnessConfig,
61
- } from 'vouchington-tooling/agent-harness-config'
62
-
63
- const dump = dumpHarnessPolicy()
64
- await checkHarnessConfig({ kind: 'global' }, { home: '/tmp/isolated-home' })
65
- await applyHarnessConfig({ kind: 'repo', root: '/path/to/checkout' }, { harnesses: ['grok'] })
66
- ```
67
-
68
- Pass `home` in options so tests never touch the real `~/.claude` or `~/.cursor`.
69
- `extraWritableRoots` replaces the shipped toolchain cache list.
70
-
71
- ## Files
72
-
73
- Global (`--global`, under `$HOME` or `--home`):
74
-
75
- | File | Keys |
76
- | ------------------------- | -------------------------------------------------------------------------------------------------- |
77
- | `.claude/settings.json` | `permissions.defaultMode`, `sandbox.enabled`, `sandbox.failIfUnavailable`, `useAutoModeDuringPlan` |
78
- | `.codex/config.toml` | `approval_policy`, `approvals_reviewer`, `sandbox_mode`, `[sandbox_workspace_write]` |
79
- | `.grok/sandbox.toml` | `[profiles.workspace-write]` extra roots (written first) |
80
- | `.grok/config.toml` | `ui.permission_mode`, `auto_mode.enabled`, `default_auto_mode` |
81
- | `.cursor/cli-config.json` | `approvalMode`, `sandbox.mode` |
82
-
83
- The Grok profile is selected per invocation with `--sandbox workspace-write`.
84
-
85
- Repo (`--repo`):
86
-
87
- | File | Keys |
88
- | ----------------------- | ------------------------------------------------------------------------------- |
89
- | `.claude/settings.json` | `sandbox.enabled`, `sandbox.failIfUnavailable`, `sandbox.filesystem.allowWrite` |
90
- | `.codex/config.toml` | same Codex keys as global |
91
- | `.grok/sandbox.toml` | extra roots only (project config cannot set the default profile) |
92
- | `.cursor/sandbox.json` | `workspace_readwrite` extra roots and `networkPolicy.default = allow` |
93
-
94
- Repo-local classifier settings have user-level prerequisites:
95
-
96
- - Codex loads `.codex/config.toml` only after the absolute checkout path has
97
- `trust_level = "trusted"` in `~/.codex/config.toml`. This command checks that
98
- entry but never creates or changes it.
99
- - Cursor approval mode belongs in `~/.cursor/cli-config.json`; the repo command
100
- checks for global `auto-review` and intentionally leaves `.cursor/cli.json`
101
- untouched.
102
- - Grok sandbox activation is per invocation as described above.
103
-
104
- These scope boundaries follow the current vendor references for
105
- [Claude sandboxing](https://code.claude.com/docs/en/sandboxing),
106
- [Codex project config](https://developers.openai.com/codex/config-reference),
107
- [Grok settings](https://docs.x.ai/build/settings),
108
- [Grok permissions](https://docs.x.ai/build/features/permissions),
109
- [Cursor CLI config](https://prod.cursor.com/docs/cli/reference/configuration), and
110
- [Cursor repo sandbox config](https://prod.cursor.com/docs/reference/sandbox).
111
-
112
- Missing files are created with only these keys. Sibling keys are preserved.
113
- JSON is pretty-printed with a trailing newline. TOML upserts named keys
114
- without rewriting unrelated tables such as `[[marketplace.sources]]` or
115
- `[projects."…"]`.
116
-
117
- ## Extra writable roots
118
-
119
- The default list is toolchain caches, not product paths:
120
-
121
- - `~/.cargo`
122
- - `~/Library/pnpm`, `~/.local/share/pnpm`, `~/.pnpm-store`
123
- - `~/Library/Caches/pnpm`, `~/.cache/pnpm`
124
- - `~/.pnpm-state`, `~/.local/state/pnpm`
125
- - `~/Library/Caches/no-mistakes`, `~/.cache/no-mistakes`
126
- - `/var/folders`, `/private/var/folders`
127
-
128
- Replace the list through `extraWritableRoots` when a checkout needs different roots.
129
-
130
- ## Out of scope
131
-
132
- The tool does not copy permission allow/deny lists, `sandbox.excludedCommands`,
133
- hooks, plugins, MCP servers, or model settings. Those stay in each checkout
134
- or user config.