From a6897a777ff112d290e96682c66a1f716160fd03 Mon Sep 17 00:00:00 2001 From: NagyVikt Date: Mon, 13 Apr 2026 22:43:48 +0200 Subject: [PATCH] Allow VS Code Source Control writes on protected branches by default This flips the protected-branch VS Code gate to opt-out mode so non-Codex VS Code Source Control users can commit/push to protected branches immediately in this repo setup, while Codex sessions remain blocked on protected branches and still require agent/* flow. Constraint: Must keep Codex protected-branch guardrails intact even when VS Code manual writes are enabled Rejected: Removing protected-branch guardrails entirely | would allow terminal/manual bypasses beyond VS Code scope Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep template and installed hook defaults aligned whenever protected-branch write policy changes Tested: bash -n .githooks/pre-commit .githooks/pre-push templates/githooks/pre-commit templates/githooks/pre-push; node --test test/install.test.js; npm test Not-tested: Live VS Code GUI commit/push path in this exact checkout --- .githooks/pre-commit | 6 +++--- .githooks/pre-push | 6 +++--- README.md | 4 ++-- templates/githooks/pre-commit | 6 +++--- templates/githooks/pre-push | 6 +++--- test/install.test.js | 29 ++++++++++++++--------------- 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 8ae9fe1..96b1492 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -30,7 +30,7 @@ fi allow_vscode_protected_raw="${MUSAFETY_ALLOW_VSCODE_PROTECTED_BRANCH_WRITES:-$(git config --get multiagent.allowVscodeProtectedBranchWrites || true)}" if [[ -z "$allow_vscode_protected_raw" ]]; then - allow_vscode_protected_raw="false" + allow_vscode_protected_raw="true" fi allow_vscode_protected="$(printf '%s' "$allow_vscode_protected_raw" | tr '[:upper:]' '[:lower:]')" @@ -144,8 +144,8 @@ Use an agent branch first: After finishing work: bash scripts/agent-branch-finish.sh -Optional repo override for manual VS Code protected-branch commits: - git config multiagent.allowVscodeProtectedBranchWrites true +Optional repo hard-block for VS Code protected-branch commits: + git config multiagent.allowVscodeProtectedBranchWrites false Temporary bypass (not recommended): ALLOW_COMMIT_ON_PROTECTED_BRANCH=1 git commit ... diff --git a/.githooks/pre-push b/.githooks/pre-push index a0f066a..80a3240 100755 --- a/.githooks/pre-push +++ b/.githooks/pre-push @@ -12,7 +12,7 @@ fi allow_vscode_protected_raw="${MUSAFETY_ALLOW_VSCODE_PROTECTED_BRANCH_WRITES:-$(git config --get multiagent.allowVscodeProtectedBranchWrites || true)}" if [[ -z "$allow_vscode_protected_raw" ]]; then - allow_vscode_protected_raw="false" + allow_vscode_protected_raw="true" fi allow_vscode_protected="$(printf '%s' "$allow_vscode_protected_raw" | tr '[:upper:]' '[:lower:]')" @@ -77,8 +77,8 @@ if [[ "${#blocked_refs[@]}" -gt 0 ]]; then echo "[agent-branch-guard] Push to protected branch blocked." echo "[agent-branch-guard] Protected target(s): ${blocked_refs[*]}" echo "[agent-branch-guard] Use an agent branch and merge via PR." - echo "[agent-branch-guard] Optional VS Code override:" - echo " git config multiagent.allowVscodeProtectedBranchWrites true" + echo "[agent-branch-guard] Optional repo hard-block for VS Code protected-branch push:" + echo " git config multiagent.allowVscodeProtectedBranchWrites false" echo echo "Temporary bypass (not recommended):" echo " ALLOW_PUSH_ON_PROTECTED_BRANCH=1 git push ..." diff --git a/README.md b/README.md index 6f854d2..67e92d6 100644 --- a/README.md +++ b/README.md @@ -143,8 +143,8 @@ Note: the monitor dispatches Codex through explicit `--task/--agent/--base` flag - `gx setup` checks GitHub CLI (`gh`) and prints install guidance if missing. - Interactive self-update prompt defaults to **No** (`[y/N]`). - In initialized repos, `setup`/`install`/`fix` block protected-base writes unless explicitly overridden. -- Direct commits/pushes to protected branches are blocked by default (including VS Code Source Control). -- Optional repo override for manual VS Code protected-branch writes: `git config multiagent.allowVscodeProtectedBranchWrites true`. +- VS Code Source Control can commit/push protected branches for non-Codex sessions by default. +- Optional repo hard-block for VS Code protected-branch writes: `git config multiagent.allowVscodeProtectedBranchWrites false`. - Codex/agent sessions stay blocked on protected branches and must use `agent/*` branch + PR workflow. - On protected `main`, `gx doctor` auto-runs in a sandbox agent branch/worktree. - `scripts/agent-branch-start.sh` hydrates `scripts/codex-agent.sh` into new sandbox worktrees when missing, so auto-finish launcher flow stays available. diff --git a/templates/githooks/pre-commit b/templates/githooks/pre-commit index 8ae9fe1..96b1492 100755 --- a/templates/githooks/pre-commit +++ b/templates/githooks/pre-commit @@ -30,7 +30,7 @@ fi allow_vscode_protected_raw="${MUSAFETY_ALLOW_VSCODE_PROTECTED_BRANCH_WRITES:-$(git config --get multiagent.allowVscodeProtectedBranchWrites || true)}" if [[ -z "$allow_vscode_protected_raw" ]]; then - allow_vscode_protected_raw="false" + allow_vscode_protected_raw="true" fi allow_vscode_protected="$(printf '%s' "$allow_vscode_protected_raw" | tr '[:upper:]' '[:lower:]')" @@ -144,8 +144,8 @@ Use an agent branch first: After finishing work: bash scripts/agent-branch-finish.sh -Optional repo override for manual VS Code protected-branch commits: - git config multiagent.allowVscodeProtectedBranchWrites true +Optional repo hard-block for VS Code protected-branch commits: + git config multiagent.allowVscodeProtectedBranchWrites false Temporary bypass (not recommended): ALLOW_COMMIT_ON_PROTECTED_BRANCH=1 git commit ... diff --git a/templates/githooks/pre-push b/templates/githooks/pre-push index a0f066a..80a3240 100644 --- a/templates/githooks/pre-push +++ b/templates/githooks/pre-push @@ -12,7 +12,7 @@ fi allow_vscode_protected_raw="${MUSAFETY_ALLOW_VSCODE_PROTECTED_BRANCH_WRITES:-$(git config --get multiagent.allowVscodeProtectedBranchWrites || true)}" if [[ -z "$allow_vscode_protected_raw" ]]; then - allow_vscode_protected_raw="false" + allow_vscode_protected_raw="true" fi allow_vscode_protected="$(printf '%s' "$allow_vscode_protected_raw" | tr '[:upper:]' '[:lower:]')" @@ -77,8 +77,8 @@ if [[ "${#blocked_refs[@]}" -gt 0 ]]; then echo "[agent-branch-guard] Push to protected branch blocked." echo "[agent-branch-guard] Protected target(s): ${blocked_refs[*]}" echo "[agent-branch-guard] Use an agent branch and merge via PR." - echo "[agent-branch-guard] Optional VS Code override:" - echo " git config multiagent.allowVscodeProtectedBranchWrites true" + echo "[agent-branch-guard] Optional repo hard-block for VS Code protected-branch push:" + echo " git config multiagent.allowVscodeProtectedBranchWrites false" echo echo "Temporary bypass (not recommended):" echo " ALLOW_PUSH_ON_PROTECTED_BRANCH=1 git push ..." diff --git a/test/install.test.js b/test/install.test.js index d9f69cf..833d9fd 100644 --- a/test/install.test.js +++ b/test/install.test.js @@ -1086,7 +1086,7 @@ test('protect command manages configured protected branches', () => { assert.match(result.stdout, /reset to defaults/); }); -test('pre-commit blocks non-codex VS Code commits on custom protected branches by default', () => { +test('pre-commit allows non-codex VS Code commits on custom protected branches by default', () => { const repoDir = initRepoOnBranch('release'); seedCommit(repoDir); @@ -1100,11 +1100,10 @@ test('pre-commit blocks non-codex VS Code commits on custom protected branches b ALLOW_COMMIT_ON_PROTECTED_BRANCH: '0', VSCODE_GIT_IPC_HANDLE: '1', }); - assert.equal(hookResult.status, 1, hookResult.stderr || hookResult.stdout); - assert.match(hookResult.stderr, /\[agent-branch-guard\] Direct commits on protected branches are blocked\./); + assert.equal(hookResult.status, 0, hookResult.stderr || hookResult.stdout); }); -test('pre-commit blocks non-codex protected branch commits from VS Code Source Control env by default', () => { +test('pre-commit allows non-codex protected branch commits from VS Code Source Control env by default', () => { const repoDir = initRepo(); seedCommit(repoDir); @@ -1122,11 +1121,10 @@ test('pre-commit blocks non-codex protected branch commits from VS Code Source C VSCODE_IPC_HOOK_CLI: '1', }, ); - assert.equal(hookResult.status, 1, hookResult.stderr || hookResult.stdout); - assert.match(hookResult.stderr, /\[agent-branch-guard\] Direct commits on protected branches are blocked\./); + assert.equal(hookResult.status, 0, hookResult.stderr || hookResult.stdout); }); -test('pre-push blocks non-codex protected branch pushes from VS Code Source Control env by default', () => { +test('pre-push allows non-codex protected branch pushes from VS Code Source Control env by default', () => { const repoDir = initRepoOnBranch('main'); seedCommit(repoDir); @@ -1146,11 +1144,10 @@ test('pre-push blocks non-codex protected branch pushes from VS Code Source Cont VSCODE_IPC_HOOK_CLI: '1', }, ); - assert.equal(hookResult.status, 1, hookResult.stderr || hookResult.stdout); - assert.match(hookResult.stderr, /\[agent-branch-guard\] Push to protected branch blocked\./); + assert.equal(hookResult.status, 0, hookResult.stderr || hookResult.stdout); }); -test('pre-commit allows non-codex protected branch commits from VS Code Source Control env when explicitly enabled', () => { +test('pre-commit blocks non-codex protected branch commits from VS Code Source Control env when explicitly disabled', () => { const repoDir = initRepo(); seedCommit(repoDir); @@ -1159,7 +1156,7 @@ test('pre-commit allows non-codex protected branch commits from VS Code Source C let configResult = runCmd( 'git', - ['config', 'multiagent.allowVscodeProtectedBranchWrites', 'true'], + ['config', 'multiagent.allowVscodeProtectedBranchWrites', 'false'], repoDir, ); assert.equal(configResult.status, 0, configResult.stderr || configResult.stdout); @@ -1175,10 +1172,11 @@ test('pre-commit allows non-codex protected branch commits from VS Code Source C VSCODE_IPC_HOOK_CLI: '1', }, ); - assert.equal(hookResult.status, 0, hookResult.stderr || hookResult.stdout); + assert.equal(hookResult.status, 1, hookResult.stderr || hookResult.stdout); + assert.match(hookResult.stderr, /\[agent-branch-guard\] Direct commits on protected branches are blocked\./); }); -test('pre-push allows non-codex protected branch pushes from VS Code Source Control env when explicitly enabled', () => { +test('pre-push blocks non-codex protected branch pushes from VS Code Source Control env when explicitly disabled', () => { const repoDir = initRepoOnBranch('main'); seedCommit(repoDir); @@ -1187,7 +1185,7 @@ test('pre-push allows non-codex protected branch pushes from VS Code Source Cont let configResult = runCmd( 'git', - ['config', 'multiagent.allowVscodeProtectedBranchWrites', 'true'], + ['config', 'multiagent.allowVscodeProtectedBranchWrites', 'false'], repoDir, ); assert.equal(configResult.status, 0, configResult.stderr || configResult.stdout); @@ -1205,7 +1203,8 @@ test('pre-push allows non-codex protected branch pushes from VS Code Source Cont VSCODE_IPC_HOOK_CLI: '1', }, ); - assert.equal(hookResult.status, 0, hookResult.stderr || hookResult.stdout); + assert.equal(hookResult.status, 1, hookResult.stderr || hookResult.stdout); + assert.match(hookResult.stderr, /\[agent-branch-guard\] Push to protected branch blocked\./); }); test('pre-push blocks codex protected branch pushes even from VS Code Source Control env', () => {