Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .asf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ github:
# would block the PR). Excluded for that reason:
# `asf-allowlist-check` (paths: `.github/**`) and
# `lint .claude/settings.json against baseline` from
# sandbox-lint (paths: `.claude/settings.json`,
# sandbox-lint (paths: `.claude/settings.json`, `.claude/settings.local.json`,
# `tools/agent-isolation/claude-settings.local.template.json`,
# `plugins/magpie-setup/skills/setup/family-mcp-allows.json`,
# `.gemini/**` and `tools/sandbox-lint/**`; see `paths:` in
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/sandbox-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ on: # yamllint disable-line rule:truthy
pull_request:
paths:
- ".claude/settings.json"
# Each contributor's own layer, never tracked: a change here means
# someone committed one, and the job must run to refuse it.
- ".claude/settings.local.json"
- "tools/agent-isolation/claude-settings.local.template.json"
- "plugins/magpie-setup/skills/setup/family-mcp-allows.json"
- ".gemini/**"
Expand All @@ -37,6 +40,9 @@ on: # yamllint disable-line rule:truthy
branches: [main]
paths:
- ".claude/settings.json"
# Each contributor's own layer, never tracked: a change here means
# someone committed one, and the job must run to refuse it.
- ".claude/settings.local.json"
- "tools/agent-isolation/claude-settings.local.template.json"
- "plugins/magpie-setup/skills/setup/family-mcp-allows.json"
- ".gemini/**"
Expand Down Expand Up @@ -85,6 +91,17 @@ jobs:
# repo root, which is what the linter expects so
# `.claude/settings.json` and `tools/sandbox-lint/expected.json`
# resolve relative to cwd.
# `.claude/settings.local.json` is each contributor's own layer over the
# committed floor, reconciled from the local template. Claude Code
# loads it for everyone who checks the repository out, and a local
# scalar overrides the floor's (`sandbox.enabled: false`), but CI lints
# only the floor and the template. Refuse a committed copy outright.
- name: Refuse a committed .claude/settings.local.json
run: |
if git ls-files --error-unmatch .claude/settings.local.json >/dev/null 2>&1; then
echo "::error file=.claude/settings.local.json::.claude/settings.local.json is each contributor's own layer and must not be committed. Shared settings go in the floor (.claude/settings.json) or the local template (tools/agent-isolation/claude-settings.local.template.json); remove the file with 'git rm --cached .claude/settings.local.json'."
exit 1
fi
- name: Run sandbox-lint
run: uv run sandbox-lint
- name: Check Gemini sandbox and policy profile
Expand Down