Skip to content

fix(cli): preserve dangerouslyBypassApprovalsAndSandbox on standalone personas#125

Merged
khaliqgant merged 2 commits into
mainfrom
fix/cli-standalone-bypass-flag
May 18, 2026
Merged

fix(cli): preserve dangerouslyBypassApprovalsAndSandbox on standalone personas#125
khaliqgant merged 2 commits into
mainfrom
fix/cli-standalone-bypass-flag

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

@khaliqgant khaliqgant commented May 18, 2026

Problem

A standalone local persona (one with intent + no extends) that sets harnessSettings.dangerouslyBypassApprovalsAndSandbox: true still had codex prompt for confirmations at runtime — including MCP tool-call approval prompts (e.g. the nango docs MCP server).

Root cause: the standalone local-persona harness-settings path was rebuilding the resolved HarnessSettings object field-by-field and did not share persona-kit's canonical harness-settings parser, so new settings could be dropped or validated differently from packaged persona specs.

The extends/overlay merge path was unaffected by the original drop because it uses object spread ({ ...base.harnessSettings, ...override.harnessSettings }). Only the standalone path dropped the field.

Fix

  • Delegate standalone harnessSettings materialization to persona-kit's canonical parseHarnessSettings parser.
  • Preserve dangerouslyBypassApprovalsAndSandbox on standalone local personas.
  • Apply the same mutual-exclusion validation as persona-kit for dangerouslyBypassApprovalsAndSandbox versus explicit codex sandbox/approval settings.
  • Add regression coverage for both preserving the bypass flag and rejecting contradictory standalone settings.

Review feedback addressed

  • Replaced the hand-maintained standalone HarnessSettings allowlist with the shared persona-kit parser.
  • Added regression coverage for the Devin finding around dangerouslyBypassApprovalsAndSandbox and explicit sandboxMode conflicts.

Verification

  • corepack pnpm -r build
  • corepack pnpm --filter @agentworkforce/cli test → 188/188 pass
  • corepack pnpm --filter @agentworkforce/cli lint

🤖 Generated with Claude Code

… personas

assertStandaloneHarnessSettings rebuilt the resolved HarnessSettings object
field-by-field (reasoning, timeoutSeconds, sandboxMode, approvalPolicy,
workspaceWriteNetworkAccess, webSearch) but never copied
dangerouslyBypassApprovalsAndSandbox. Standalone local personas (intent +
no extends) silently lost the flag before codex launch, so codex started
with its default approval policy and kept prompting for confirmations —
including MCP tool-call approvals. The extends/overlay merge path was
unaffected (object spread preserves it); only the standalone path dropped it.

Also adds the boolean type check to assertPartialHarnessSettingsShape for
parity with the other codex-only settings, and a regression test asserting
the flag survives standalone resolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 12f055e6-f338-412c-874e-6304bdb96547

📥 Commits

Reviewing files that changed from the base of the PR and between 72ef0a0 and 2141cd5.

📒 Files selected for processing (2)
  • packages/cli/src/local-personas.test.ts
  • packages/cli/src/local-personas.ts

📝 Walkthrough

Walkthrough

Accepts and validates dangerouslyBypassApprovalsAndSandbox in partial harness settings, delegates standalone harness-settings parsing to parseHarnessSettings, and adds two tests: one preserving the flag on load and one rejecting a persona that sets both the flag and sandboxMode.

Changes

Harness settings flag propagation

Layer / File(s) Summary
Validation imports and delegation
packages/cli/src/local-personas.ts
Adds parseHarnessSettings import; assertPartialHarnessSettingsShape now destructures dangerouslyBypassApprovalsAndSandbox and enforces it is boolean when present; assertStandaloneHarnessSettings delegates parsing to parseHarnessSettings.
Regression tests for standalone personas
packages/cli/src/local-personas.test.ts
Adds a test asserting dangerouslyBypassApprovalsAndSandbox is preserved after loading a standalone persona fixture, and a test that a persona with both dangerouslyBypassApprovalsAndSandbox: true and sandboxMode is rejected and emits a mutual-exclusion warning.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • AgentWorkforce/workforce#73: Related persona-kit refactor that introduced the shared parseHarnessSettings API used by this change.
  • AgentWorkforce/workforce#53: Also modifies packages/cli/src/local-personas.ts harness-settings validation/merge paths and related tests.
  • AgentWorkforce/workforce#86: Persona-kit parseHarnessSettings changes that add/validate dangerouslyBypassApprovalsAndSandbox, which this PR delegates to.

Suggested reviewers

  • willwashburn

Poem

🐰 A tiny rabbit hops through code and tests so bright,
It keeps a fearless flag safe in the night,
Two checks, one warning, tidy and small —
Boolean guards stand steady for all,
Happy builds now hop and delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: preserving the dangerouslyBypassApprovalsAndSandbox flag on standalone personas, which is the core fix addressed by the changeset.
Description check ✅ Passed The description provides clear context about the problem, root cause, solution, and verification steps, all directly related to the changeset modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cli-standalone-bypass-flag

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment thread packages/cli/src/local-personas.ts Outdated
Comment on lines +756 to +759
if (settings.dangerouslyBypassApprovalsAndSandbox !== undefined) {
out.dangerouslyBypassApprovalsAndSandbox =
settings.dangerouslyBypassApprovalsAndSandbox as boolean;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing mutual exclusion validation for dangerouslyBypassApprovalsAndSandbox in assertStandaloneHarnessSettings

The assertStandaloneHarnessSettings function now preserves dangerouslyBypassApprovalsAndSandbox but does not enforce the mutual exclusion constraint with sandboxMode, approvalPolicy, and workspaceWriteNetworkAccess. The canonical validator at packages/persona-kit/src/parse.ts:189-196 rejects any configuration where dangerouslyBypassApprovalsAndSandbox is present alongside those fields (even when false), and the type documentation at packages/persona-kit/src/types.ts:47-49 explicitly declares them mutually exclusive. A standalone local persona declaring both dangerouslyBypassApprovalsAndSandbox: true and sandboxMode: 'workspace-write' would pass validation silently, and at runtime the bypass flag wins (packages/persona-kit/src/interactive-spec.ts:256), causing sandboxMode/approvalPolicy/workspaceWriteNetworkAccess to be silently ignored without warning.

Suggested change
if (settings.dangerouslyBypassApprovalsAndSandbox !== undefined) {
out.dangerouslyBypassApprovalsAndSandbox =
settings.dangerouslyBypassApprovalsAndSandbox as boolean;
}
if (settings.dangerouslyBypassApprovalsAndSandbox !== undefined) {
const conflicts: string[] = [];
if (settings.sandboxMode !== undefined) conflicts.push('sandboxMode');
if (settings.approvalPolicy !== undefined) conflicts.push('approvalPolicy');
if (settings.workspaceWriteNetworkAccess !== undefined) conflicts.push('workspaceWriteNetworkAccess');
if (conflicts.length > 0) {
throw new Error(
`${context}.dangerouslyBypassApprovalsAndSandbox is mutually exclusive with: ${conflicts.join(', ')}`
);
}
out.dangerouslyBypassApprovalsAndSandbox =
settings.dangerouslyBypassApprovalsAndSandbox as boolean;
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/cli/src/local-personas.ts (1)

756-759: ⚡ Quick win

Avoid another hand-maintained HarnessSettings allowlist.

assertStandaloneHarnessSettings still rebuilds the object field-by-field. The next HarnessSettings property added upstream can validate and merge fine elsewhere, but still get silently dropped for standalone personas here—the same class of regression this PR just fixed. Please centralize the materialization so validation and standalone construction share one source of truth.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/local-personas.ts` around lines 756 - 759,
assertStandaloneHarnessSettings currently rebuilds a HarnessSettings object
field-by-field (e.g., the manual assignment to
out.dangerouslyBypassApprovalsAndSandbox), which risks dropping new properties;
refactor it to centralize materialization by delegating to a single
constructor/utility that merges/validates partial settings (for example a
HarnessSettings.from/merge/normalize function or a new
createHarnessSettingsFromPartial(settings) helper) and then validate/return that
canonical object instead of manually copying fields—replace the manual per-field
assignments in assertStandaloneHarnessSettings with a single call to that shared
materializer so validation and standalone construction use the same source of
truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/cli/src/local-personas.ts`:
- Around line 756-759: assertStandaloneHarnessSettings currently rebuilds a
HarnessSettings object field-by-field (e.g., the manual assignment to
out.dangerouslyBypassApprovalsAndSandbox), which risks dropping new properties;
refactor it to centralize materialization by delegating to a single
constructor/utility that merges/validates partial settings (for example a
HarnessSettings.from/merge/normalize function or a new
createHarnessSettingsFromPartial(settings) helper) and then validate/return that
canonical object instead of manually copying fields—replace the manual per-field
assignments in assertStandaloneHarnessSettings with a single call to that shared
materializer so validation and standalone construction use the same source of
truth.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6e465bb-3e05-4962-aec8-ad2e31fd5ad0

📥 Commits

Reviewing files that changed from the base of the PR and between 1a9352e and 72ef0a0.

📒 Files selected for processing (2)
  • packages/cli/src/local-personas.test.ts
  • packages/cli/src/local-personas.ts

@khaliqgant khaliqgant merged commit aca0761 into main May 18, 2026
2 of 3 checks passed
@khaliqgant khaliqgant deleted the fix/cli-standalone-bypass-flag branch May 18, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant