patchwork-os 1.2.0-beta.3.canary.889 → 1.2.0-beta.3.canary.890
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/dist/drivers/claude/subprocess.d.ts +34 -0
- package/dist/drivers/claude/subprocess.js +79 -8
- package/dist/drivers/claude/subprocess.js.map +1 -1
- package/dist/drivers/claude/subprocessSettings.d.ts +16 -4
- package/dist/drivers/claude/subprocessSettings.js +49 -12
- package/dist/drivers/claude/subprocessSettings.js.map +1 -1
- package/dist/governance/doctorReport.js +1 -1
- package/dist/governance/doctorReport.js.map +1 -1
- package/dist/governance/profile.d.ts +33 -4
- package/dist/governance/profile.js +38 -4
- package/dist/governance/profile.js.map +1 -1
- package/dist/recipes/yamlRunner.d.ts +8 -0
- package/dist/recipes/yamlRunner.js +45 -9
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,7 +30,9 @@ import { fileURLToPath } from "node:url";
|
|
|
30
30
|
import { parse as parseYaml } from "yaml";
|
|
31
31
|
import { approvalIdentityMatches, computeApprovedActionIdentity, executionEvidence, } from "../approvalIdentity.js";
|
|
32
32
|
import { captureFixture } from "../connectors/fixtureRecorder.js";
|
|
33
|
-
import { sanitizeEnv } from "../drivers/claude/envSanitizer.js";
|
|
33
|
+
import { allowlistEnv, sanitizeEnv } from "../drivers/claude/envSanitizer.js";
|
|
34
|
+
import { CLAUDE_PROVIDER_ENV_KEYS, containedPermissionArgs, } from "../drivers/claude/subprocess.js";
|
|
35
|
+
import { createSubprocessSettings, readWorkspaceDenies, } from "../drivers/claude/subprocessSettings.js";
|
|
34
36
|
import { FLAG_CIRCUIT_BREAKER, FLAG_ENFORCE_ALLOWWRITES, isEnabled, } from "../featureFlags.js";
|
|
35
37
|
import { computeEffectivePolicy } from "../governance/effectivePolicy.js";
|
|
36
38
|
import { readKillSwitch } from "../governance/killSwitchPolicy.js";
|
|
@@ -3411,7 +3413,12 @@ export function defaultClaudeCodeFn(prompt, opts) {
|
|
|
3411
3413
|
// silently falling back to no-MCP spawn — the recipe explicitly asked
|
|
3412
3414
|
// for bridge tools and should be routed through SubprocessDriver via
|
|
3413
3415
|
// the runtime injector instead.
|
|
3414
|
-
|
|
3416
|
+
// Only a STRICT (governed) containment takes the contained branch. A compat
|
|
3417
|
+
// `sandbox: true` opt-in keeps the legacy branch below, byte-identical.
|
|
3418
|
+
const containment = opts?.containment?.enforced === true && opts.containment.strict === true
|
|
3419
|
+
? opts.containment
|
|
3420
|
+
: undefined;
|
|
3421
|
+
if (opts?.mcpAccess === true || containment?.mcpAccess === true) {
|
|
3415
3422
|
return Promise.resolve("[agent step failed: recipe_mcp_unsupported — defaultClaudeCodeFn does not support mcpAccess:true; route via SubprocessDriver or unset the mcpAccess flag on this step]");
|
|
3416
3423
|
}
|
|
3417
3424
|
// P0-5 opt-in tool sandbox on the `recipe run --local` / non-bridge path.
|
|
@@ -3421,6 +3428,22 @@ export function defaultClaudeCodeFn(prompt, opts) {
|
|
|
3421
3428
|
// and always apply --disallowed-tools regardless of mode.
|
|
3422
3429
|
const sandboxAllowed = (Array.isArray(opts?.allowedTools) ? opts.allowedTools : []).filter((t) => typeof t === "string" && t.length > 0 && !t.startsWith("-"));
|
|
3423
3430
|
const sandboxDenied = (Array.isArray(opts?.disallowedTools) ? opts.disallowedTools : []).filter((t) => typeof t === "string" && t.length > 0 && !t.startsWith("-"));
|
|
3431
|
+
// A contained run gets the same settings deny file the driver writes. If it
|
|
3432
|
+
// cannot be written, refuse rather than run the agent uncontained.
|
|
3433
|
+
let containedSettingsPath;
|
|
3434
|
+
// The workspace's own deny rules: applied by us, because a strict run does
|
|
3435
|
+
// not load the workspace's settings sources (their hooks and allows could
|
|
3436
|
+
// widen it).
|
|
3437
|
+
const workspaceDenies = containment
|
|
3438
|
+
? readWorkspaceDenies(workspace.path)
|
|
3439
|
+
: [];
|
|
3440
|
+
if (containment) {
|
|
3441
|
+
const settings = createSubprocessSettings(() => { }, [...containment.deniedTools, ...workspaceDenies], { strict: true });
|
|
3442
|
+
if (!settings.write()) {
|
|
3443
|
+
return Promise.resolve("[agent step failed: contained_settings_unwritable — could not write the contained run's settings file; refusing to run the agent uncontained]");
|
|
3444
|
+
}
|
|
3445
|
+
containedSettingsPath = settings.path;
|
|
3446
|
+
}
|
|
3424
3447
|
const localArgs = [
|
|
3425
3448
|
"-p",
|
|
3426
3449
|
prompt,
|
|
@@ -3440,13 +3463,22 @@ export function defaultClaudeCodeFn(prompt, opts) {
|
|
|
3440
3463
|
: RECIPE_SYSTEM_PROMPT_COMPAT),
|
|
3441
3464
|
"--no-session-persistence",
|
|
3442
3465
|
];
|
|
3443
|
-
if (
|
|
3444
|
-
localArgs.push("--
|
|
3445
|
-
localArgs.push(
|
|
3466
|
+
if (containment && containedSettingsPath) {
|
|
3467
|
+
localArgs.push("--settings", containedSettingsPath);
|
|
3468
|
+
localArgs.push(...containedPermissionArgs(containment, [
|
|
3469
|
+
...sandboxDenied,
|
|
3470
|
+
...workspaceDenies,
|
|
3471
|
+
]));
|
|
3446
3472
|
}
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3473
|
+
else {
|
|
3474
|
+
if (opts?.sandbox === true && sandboxAllowed.length > 0) {
|
|
3475
|
+
localArgs.push("--permission-mode", "dontAsk");
|
|
3476
|
+
localArgs.push("--allowed-tools", ...sandboxAllowed);
|
|
3477
|
+
}
|
|
3478
|
+
// Deny rules apply in ANY mode.
|
|
3479
|
+
if (sandboxDenied.length > 0) {
|
|
3480
|
+
localArgs.push("--disallowed-tools", ...sandboxDenied);
|
|
3481
|
+
}
|
|
3450
3482
|
}
|
|
3451
3483
|
try {
|
|
3452
3484
|
const result = spawnSync(binary, localArgs, {
|
|
@@ -3455,7 +3487,11 @@ export function defaultClaudeCodeFn(prompt, opts) {
|
|
|
3455
3487
|
// child so the spawn doesn't re-authenticate as, or nest under,
|
|
3456
3488
|
// the parent Claude Code session. Mirrors SubprocessDriver.run
|
|
3457
3489
|
// hygiene. Preserves CLAUDE_CODE_OAUTH_TOKEN (subscription auth).
|
|
3458
|
-
|
|
3490
|
+
// Contained: the same env allowlist the driver uses (no connector
|
|
3491
|
+
// tokens, bridge secrets or PATCHWORK_* settings reach the child).
|
|
3492
|
+
env: containment?.envAllowlist
|
|
3493
|
+
? allowlistEnv(process.env, { providerKeys: CLAUDE_PROVIDER_ENV_KEYS })
|
|
3494
|
+
: sanitizeEnv(process.env),
|
|
3459
3495
|
encoding: "utf-8",
|
|
3460
3496
|
timeout: 600_000,
|
|
3461
3497
|
maxBuffer: 10 * 1024 * 1024,
|