Skip to content
Draft
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
116 changes: 116 additions & 0 deletions .bootstrap/managed-files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"schemaVersion": 1,
"owner": "bootstrap",
"templateVersion": "2026.03.28.2",
"regenerationCommand": "bootstrap apply repo --manifest ./project.bootstrap.yaml",
"managedFiles": {
".devcontainer/devcontainer.json": {
"sha256": "c8cd91bc1d2df220508bd84051723d480fe16d7bf8d93a8c3fa0beac403083ad",
"source": "bootstrap"
},
".githooks/pre-commit": {
"sha256": "992bc9b04d62f84df70ba1e42d7159a1d976190eae41597810aaafaa30252a4d",
"source": "bootstrap"
},
".github/PULL_REQUEST_TEMPLATE.md": {
"sha256": "b95b973bf0e6f5cdf77ad9d84e2f623525e493beed185d7d7b3093a4f50ec59d",
"source": "bootstrap"
},
".github/workflows/claude.yml": {
"sha256": "8334876d6611aa25ec784e1e4560d8de3fa71efda129c1478f1d38e721d37d23",
"source": "bootstrap"
},
".github/workflows/extended-validation.yml": {
"sha256": "119a7b0a4a5382c9ffc0226b1100660bf76bba42e9fb89020650272269c06058",
"source": "bootstrap"
},
".github/workflows/pr-fast-ci.yml": {
"sha256": "91b158e63a648aad0639e2f18b3d97ff3798a2f490de477080551b3366965e69",
"source": "bootstrap"
},
"AGENTS.md": {
"sha256": "8acfcb8fe4d902e7892abdee9db7073c4f5fe33ac4733813c83a83434885a997",
"source": "bootstrap"
},
"CLAUDE.md": {
"sha256": "fa083f9f4b9b5a42c3179c0320070314ca7ae120dcf593b85677196e4914cdfe",
"source": "bootstrap"
},
"CODEOWNERS": {
"sha256": "d5b88668ece5258a10e66ab476d2135250623474ff24d14748d071c5076559b0",
"source": "bootstrap"
},
"docs/bootstrap/claude-environment.md": {
"sha256": "707dac647e02b7811f0ad99c367fbe9fc946aad3b0dd85366162eb10f39d2bb8",
"source": "bootstrap"
},
"docs/bootstrap/codex-cloud-environment.md": {
"sha256": "d523693384512cd1b07a2e3467afba4ad45c6a41bc00ae69c01601f6af85f10e",
"source": "bootstrap"
},
"docs/bootstrap/issue-hygiene.md": {
"sha256": "039344533cc90b966fd7ef6501bf6cfb956b5edc61126ad9c14aad545c315580",
"source": "bootstrap"
},
"docs/bootstrap/next-steps.md": {
"sha256": "4e471faef1858d9f2c36328f10621dccd6b01fdc2fd33bd6547d494518b469b9",
"source": "bootstrap"
},
"docs/bootstrap/onboarding.md": {
"sha256": "a223890f60a3d38cd68d320980f4e80c529a5c271053cb24639c68839d2dc92b",
"source": "bootstrap"
},
"docs/bootstrap/security.md": {
"sha256": "d8deb9aa1b5e91177145b3bdf8b7e329abe3da574c6bf7f92e535f6e28b331e8",
"source": "bootstrap"
},
"project.bootstrap.yaml": {
"sha256": "36db2b94523ad7f5925a97fe78840028061eab0be9af28e39492c186d5735258",
"source": "bootstrap"
},
"scripts/check-detect-secrets.sh": {
"sha256": "7f94837cceed656f03390b3af615d260558ae71ed6e88c1580239b90d5115fa8",
"source": "bootstrap"
},
"scripts/ci/check-action-pins.sh": {
"sha256": "4aaf63706ea4ba1754077fb449ffca310d971b9879ec999d26a3f942122788f8",
"source": "bootstrap"
},
"scripts/ci/check-pr-governance.sh": {
"sha256": "296a576f96a19af3785a31a472640bf5e342113f64a366f7ca3292883c46f17c",
"source": "bootstrap"
},
"scripts/ci/report-issue-hygiene.mjs": {
"sha256": "53bc2252f82e388ec4ba182cab500b78b3f429c304501a55c205ad3f0e534087",
"source": "bootstrap"
},
"scripts/ci/run-extended-validation.sh": {
"sha256": "f2adbf95dde8933d554389d596ca874e48b81c7b58b9da2e64011042bb75d3a0",
"source": "bootstrap"
},
"scripts/ci/run-fast-checks.sh": {
"sha256": "c7086acffa784b4249f0bb004a80f9ec93f6bee4004b06d897e702ff613892f3",
"source": "bootstrap"
},
"scripts/claude-cloud/setup.sh": {
"sha256": "77a9e57f3dde3cbdbaa2b7385667392463236d79a1cf84b355f1944e08a72eaf",
"source": "bootstrap"
},
"scripts/claude/setup-devcontainer.sh": {
"sha256": "4ad6cbff01875e6d1cb58e32460d10ca941defa0e02482dd20de65f15ba55211",
"source": "bootstrap"
},
"scripts/codex-cloud/maintenance.sh": {
"sha256": "8a4f5e11b133539c46dd9d45e74d49b19e0fb092e3620f2af8552e07cf94dabc",
"source": "bootstrap"
},
"scripts/codex-cloud/setup.sh": {
"sha256": "debc23607cccb92ed096941adc7da777ff794ec8c97d4efa842e592b33c29d10",
"source": "bootstrap"
},
"SECURITY.md": {
"sha256": "74daa1c5bb75938c109739135fa6c15d948928936b37830e378ad6fc92bc414e",
"source": "bootstrap"
}
}
}
3 changes: 2 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ while IFS= read -r -d '' staged_file; do
staged_files+=("$staged_file")
done < <(git diff --cached --name-only --diff-filter=ACMR -z)

for f in "${staged_files[@]}"; do
for f in "${staged_files[@]:-}"; do
[[ -n "$f" ]] || continue
case "$f" in
*.env|.env.*)
if [[ "$f" != *.example ]]; then
Expand Down
5 changes: 5 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Refs #<issue-number> <!-- use Closes/Fixes/Resolves only when this PR fully com
## Validation

- [ ] Relevant local checks passed
- [ ] Agent-authored changes passed `autoreview` against the intended PR diff with no accepted/actionable findings
- Autoreview command and result:
- [ ] Required PR checks are expected to satisfy `CI Gate`
- [ ] Skipped checks are explained below

Expand All @@ -19,6 +21,9 @@ Refs #<issue-number> <!-- use Closes/Fixes/Resolves only when this PR fully com
- [ ] PR author enabled auto-merge where GitHub allows it, or GitHub plan-limit evidence/unavailable reason is recorded and the fallback merge-readiness policy applies
- [ ] No real secrets, runtime auth, or machine-local env files are committed

Material change: no
ADR: docs/decisions/ADR-<number>-<slug>.md <!-- required when Material change is yes; ADR status must be Accepted -->



## Merge Automation
Expand Down
60 changes: 13 additions & 47 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ on:
workflow_dispatch:
inputs:
prompt:
description: 'Task for Claude to run in this repository'
required: true
default: 'Review the current branch changes for bugs, CI regressions, and missing tests.'
description: Optional manual task prompt
required: false
type: string
issue_comment:
types: [created]
pull_request_review_comment:
Expand All @@ -20,61 +20,27 @@ concurrency:

permissions:
contents: read
pull-requests: read
pull-requests: write
issues: write

jobs:
claude:
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') &&
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') &&
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') &&
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.review.author_association))
# Claude has write permissions and reads ANTHROPIC_API_KEY, so keep it on a
# trusted private runner instead of the public shell-only fleet.
runs-on: ['self-hosted', 'private', 'macOS', 'ARM64', 'xcode']
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude'))
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Require Claude auth
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
if [[ -z "${ANTHROPIC_API_KEY}" ]]; then
echo "Missing repository secret ANTHROPIC_API_KEY. Run /install-github-app in Claude Code or add the secret before using this workflow." >&2
exit 1
fi

- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Run Claude Code
uses: anthropics/claude-code-action@v1
uses: anthropics/claude-code-action@e90deca47693f9457b72f2b53c17d7c445a87342 # v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
track_progress: true
use_sticky_comment: true
additional_permissions: "actions: read"
prompt: |
REPO: ${{ github.repository }}
DEFAULT BRANCH: main

Use CLAUDE.md and docs/bootstrap/onboarding.md as repo policy context.
Keep required PR status checks aligned with CI Gate.
Preserve the split fast and extended validation model.
Shell-safe jobs must use `[self-hosted, linux, shell-only, public]`.
Secret-bearing automation must stay on a trusted private runner.
Docker, service-container, browser, and `container:` jobs require a dedicated self-hosted pool with matching capability labels.
Prefer the smallest safe change and add tests for behavior changes.

REQUIRED CHECKS: CI Gate
Use CLAUDE.md, AGENTS.md, and docs/bootstrap/onboarding.md as policy context.
MANUAL TASK: ${{ github.event.inputs.prompt }}
If this is not a manual run, ignore the MANUAL TASK line and respond to the current `@claude` request instead.
40 changes: 16 additions & 24 deletions .github/workflows/extended-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
ci: ${{ steps.preset.outputs.ci || steps.filter.outputs.ci || 'false' }}
extended: ${{ steps.preset.outputs.extended || steps.filter.outputs.extended || 'false' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
if: github.event_name == 'push'
with:
fetch-depth: 0
Expand All @@ -40,20 +40,22 @@ jobs:
id: preset
if: github.event_name != 'push'
run: |
echo "app=true" >> "$GITHUB_OUTPUT"
echo "ci=true" >> "$GITHUB_OUTPUT"
echo "extended=true" >> "$GITHUB_OUTPUT"
cat >>"$GITHUB_OUTPUT" <<'EOF'
app=true
ci=true
extended=true
EOF

- uses: dorny/paths-filter@v4
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4
id: filter
if: github.event_name == 'push'
with:
filters: |
app:
- 'project.bootstrap.yaml'
- 'AGENTS.md'
- 'CLAUDE.md'
- '.devcontainer/**'
- 'CONTRIBUTING.md'
- '.github/PULL_REQUEST_TEMPLATE.md'
- '.githooks/**'
- '.github/workflows/**'
- 'scripts/**'
Expand All @@ -63,8 +65,8 @@ jobs:
ci:
- 'project.bootstrap.yaml'
- 'AGENTS.md'
- 'CLAUDE.md'
- '.devcontainer/**'
- 'CONTRIBUTING.md'
- '.github/PULL_REQUEST_TEMPLATE.md'
- '.githooks/**'
- '.github/workflows/**'
- 'scripts/**'
Expand All @@ -82,29 +84,19 @@ jobs:
needs: changes
if: needs.changes.outputs.app == 'true' || needs.changes.outputs.ci == 'true'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Run fast checks
run: bash scripts/ci/run-fast-checks.sh

extended-checks:
name: Extended Checks
runs-on: ['self-hosted', 'private', 'macOS', 'ARM64', 'xcode']
timeout-minutes: 40
runs-on: ['self-hosted', 'linux', 'shell-only', 'public']
timeout-minutes: 20
needs: changes
if: needs.changes.outputs.extended == 'true' || needs.changes.outputs.app == 'true'
steps:
- uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Verify vendored OpenSSL build inputs
# Issue #40: Rust now builds OpenSSL through the openssl crate's
# vendored feature, so the macOS runner no longer needs Homebrew,
# pkg-config, or a system OpenSSL prefix. This step keeps clean
# runner failures explicit before the longer Rust build starts.
run: bash scripts/ci/run-extended-validation.sh --check-build-inputs
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Run extended validation
run: bash scripts/ci/run-extended-validation.sh
Expand All @@ -114,7 +106,7 @@ jobs:
runs-on: ['self-hosted', 'linux', 'shell-only', 'public']
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Scan repository for secret patterns
run: bash scripts/check-detect-secrets.sh --all-files

Expand Down
Loading
Loading