Skip to content

Commit a8111b4

Browse files
committed
Merge main into feat/metaprogramming-guardrails
2 parents 989fbb5 + 1f96dab commit a8111b4

186 files changed

Lines changed: 12201 additions & 1198 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cargo/audit.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# cargo-audit configuration for the Rust workspace.
2+
#
3+
# Path matters: cargo-audit reads `.cargo/audit.toml`, not a root-level
4+
# `audit.toml`. A file at the repo root is silently ignored.
5+
#
6+
# The `audit` job in .github/workflows/rust.yml is a BLOCKING gate. It runs on
7+
# every PR touching Rust and nightly on the schedule (the `rust-changes` job
8+
# reports `rust=true` for `schedule`/`workflow_dispatch`, so a newly-disclosed
9+
# advisory surfaces without anyone touching Rust code).
10+
#
11+
# It was `continue-on-error: true` until the change that added this file, which meant it reported findings
12+
# nobody saw: RUSTSEC-2026-0258 (h2, unbounded empty DATA frames) sat in a green
13+
# run. Anything ignored here has to be listed explicitly, with a reason.
14+
15+
[advisories]
16+
ignore = [
17+
# `paste` is unmaintained — an advisory of project status, not a
18+
# vulnerability; there is no patched version to move to. It is transitive
19+
# and unavoidable at our layer: tokenizers -> paste and rav1e -> paste,
20+
# both reached via fastembed. Re-evaluate when tokenizers moves to
21+
# `pastey` (the maintained drop-in fork).
22+
"RUSTSEC-2024-0436",
23+
]

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
},
66
"metadata": {
77
"description": "Headroom marketplace for Claude Code and GitHub Copilot CLI plugins.",
8-
"version": "0.35.0"
8+
"version": "0.36.0"
99
},
1010
"plugins": [
1111
{
1212
"name": "headroom",
1313
"source": "./plugins/headroom-agent-hooks",
1414
"description": "Headroom startup hooks for Claude Code and GitHub Copilot CLI.",
15-
"version": "0.35.0",
15+
"version": "0.36.0",
1616
"author": {
1717
"name": "Headroom Contributors",
1818
"url": "https://github.com/chopratejas/headroom"

.env.example

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1-
# Copy this file to .env and fill in real values before running in production.
2-
# IMPORTANT: Change NEO4J_AUTH before deploying — default credentials are insecure.
1+
# Copy this file to .env and fill in real values before running.
2+
# docker-compose.yml requires these — it will refuse to start with defaults.
3+
4+
# Neo4j credentials for the graph memory backend (format: user/password).
35
NEO4J_AUTH=neo4j/CHANGEME
6+
# Password only, for library / non-Docker use of the Neo4j memory backend.
7+
NEO4J_PASSWORD=CHANGEME
8+
9+
# Proxy token — gates the data plane whenever the proxy is not loopback-only.
10+
# Generate: openssl rand -hex 32
11+
HEADROOM_PROXY_TOKEN=CHANGEME
12+
13+
# Optional: set to 0.0.0.0 to expose the proxy on the network (requires a token).
14+
# HEADROOM_BIND_ADDR=127.0.0.1

.github/plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
},
66
"metadata": {
77
"description": "Headroom marketplace for Claude Code and GitHub Copilot CLI plugins.",
8-
"version": "0.35.0"
8+
"version": "0.36.0"
99
},
1010
"plugins": [
1111
{
1212
"name": "headroom",
1313
"source": "./plugins/headroom-agent-hooks",
1414
"description": "Headroom startup hooks for Claude Code and GitHub Copilot CLI.",
15-
"version": "0.35.0",
15+
"version": "0.36.0",
1616
"author": {
1717
"name": "Headroom Contributors",
1818
"url": "https://github.com/chopratejas/headroom"

.github/workflows/release-metadata-sync.yml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,26 @@ jobs:
5050
runs-on: ubuntu-latest
5151
timeout-minutes: 10
5252
steps:
53+
# Prefer a short-lived, repo-scoped GitHub App installation token over a
54+
# personal PAT. Gated on the repo variable so an unconfigured app simply
55+
# falls through to the existing chain instead of breaking the release.
56+
- name: Mint installation token
57+
id: app-token
58+
if: ${{ vars.RELEASE_APP_ID != '' }}
59+
continue-on-error: true
60+
uses: actions/create-github-app-token@v3
61+
with:
62+
app-id: ${{ vars.RELEASE_APP_ID }}
63+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
64+
5365
- uses: actions/checkout@v7
5466
with:
5567
ref: ${{ github.ref_name }}
56-
# PAT (not GITHUB_TOKEN) for the same reason release-please.yml uses one:
57-
# a push made with GITHUB_TOKEN does not trigger workflows, so the release
58-
# PR's checks would never re-run against the synced commit and would stay
59-
# red. Falls back to GITHUB_TOKEN, where the sync still lands and a manual
60-
# re-run of the PR's checks picks it up.
61-
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
68+
# Do NOT persist the credential into .git/config. The next step runs
69+
# scripts/version-sync.py *from the checked-out branch*, and this job
70+
# triggers on a push to the unprotected glob release-please--branches--**.
71+
# A persisted token would be readable by that script.
72+
persist-credentials: false
6273

6374
- uses: actions/setup-python@v6
6475
with:
@@ -72,6 +83,14 @@ jobs:
7283
run: python scripts/verify-versions.py
7384

7485
- name: Commit and push if anything changed
86+
env:
87+
# An app installation token if one was minted, else the existing
88+
# chain. A PAT (not GITHUB_TOKEN) is still preferred here for the same
89+
# reason release-please.yml wants one: a push made with GITHUB_TOKEN
90+
# does not trigger workflows, so the release PR's checks would never
91+
# re-run against the synced commit and would stay red. Supplied only
92+
# to this step, after the branch-supplied script has already run.
93+
SYNC_TOKEN: ${{ steps.app-token.outputs.token || secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
7594
run: |
7695
if git diff --quiet; then
7796
echo "Already in sync — nothing to commit."
@@ -81,7 +100,12 @@ jobs:
81100
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
82101
git add -A
83102
git commit -m "chore: sync generated version metadata"
103+
# Push via an explicit remote URL because the checkout no longer
104+
# persists credentials. Passed on stdin-free env expansion so the
105+
# token is not written to the command line or into .git/config.
84106
# This push re-triggers this workflow. version-sync.py is idempotent, so
85107
# the next run finds no diff and exits above without pushing — the loop
86108
# terminates after one no-op run.
87-
git push origin HEAD:"${GITHUB_REF_NAME}"
109+
git push \
110+
"https://x-access-token:${SYNC_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \
111+
HEAD:"${GITHUB_REF_NAME}"

.github/workflows/release-please.yml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,31 @@ jobs:
4242
release-please:
4343
runs-on: ubuntu-latest
4444
steps:
45+
# Prefer a short-lived, repo-scoped GitHub App installation token. A
46+
# personal PAT carries the maintainer's whole account — with a classic
47+
# `repo` scope that reaches every other repository they can access — and
48+
# this credential can tag past branch protection and reaches PyPI, npm and
49+
# GHCR through the `release: published` publishes. An installation token is
50+
# scoped to this repository and expires in an hour. Gated on the repo
51+
# variable so an unconfigured app falls through instead of blocking a
52+
# release. See #2955.
53+
- name: Mint installation token
54+
id: app-token
55+
if: ${{ vars.RELEASE_APP_ID != '' }}
56+
continue-on-error: true
57+
uses: actions/create-github-app-token@v3
58+
with:
59+
app-id: ${{ vars.RELEASE_APP_ID }}
60+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
61+
4562
- uses: googleapis/release-please-action@v5
4663
with:
47-
# PAT (not GITHUB_TOKEN): a release/tag created by GITHUB_TOKEN does
48-
# NOT emit events that trigger other workflows, so release.yml
49-
# (PyPI/npm) and docker.yml — which fire on `release: published` —
50-
# never ran, and releases had to be cut by hand. A PAT is treated as a
51-
# real user, so the release it creates DOES trigger those publishes; it
52-
# also lets the bot tag past branch/tag protection. Falls back to
53-
# GITHUB_TOKEN when the secret is unset (the release PR still opens; it
54-
# just won't trigger the downstream publishes).
55-
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
64+
# Neither an app token nor a PAT is GITHUB_TOKEN, and that matters: a
65+
# release/tag created by GITHUB_TOKEN does NOT emit events that trigger
66+
# other workflows, so release.yml (PyPI/npm) and docker.yml — which fire
67+
# on `release: published` — never ran, and releases had to be cut by
68+
# hand. Falls back to GITHUB_TOKEN when nothing else is set (the release
69+
# PR still opens; it just won't trigger the downstream publishes).
70+
token: ${{ steps.app-token.outputs.token || secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
5671
config-file: .release-please-config.json
5772
manifest-file: .release-please-manifest.json

.github/workflows/rust.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ jobs:
224224
uses: taiki-e/install-action@v2
225225
with:
226226
tool: cargo-audit,cargo-deny
227-
- name: cargo audit (soft-fail)
228-
continue-on-error: true
227+
# Blocking. Soft-failing this made it useless: RUSTSEC-2026-0258 (h2,
228+
# unbounded empty DATA frames -> unbounded memory or a panic) was
229+
# reported by this job for as long as it existed and never turned a run
230+
# red, so nobody acted on it. Accepted advisories go in audit.toml with
231+
# a written reason rather than being swallowed wholesale here.
232+
- name: cargo audit
229233
run: cargo audit
230234
- name: cargo deny check licenses
231235
continue-on-error: true
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: tools-hash-refresh
2+
3+
# Enforce that headroom/tools.json SHA-256 pins match the published assets for
4+
# the currently pinned tool versions. Fails if a version was bumped without
5+
# refreshing pins (run scripts/refresh_tool_hashes.py locally). See WEB-03.
6+
7+
on:
8+
pull_request:
9+
paths:
10+
- "headroom/tools.json"
11+
- "scripts/refresh_tool_hashes.py"
12+
- ".github/workflows/tools-hash-refresh.yml"
13+
schedule:
14+
- cron: "0 6 * * 1" # Mondays 06:00 UTC
15+
workflow_dispatch: {}
16+
17+
permissions:
18+
contents: read
19+
20+
jobs:
21+
verify-pins:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: actions/setup-python@v5
26+
with:
27+
python-version: "3.12"
28+
- name: Verify tool SHA-256 pins
29+
run: python scripts/refresh_tool_hashes.py --check

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ scripts/*
3838
!scripts/audit_wheel_glibc_symbols.py
3939
!scripts/replay_codex_ws_load.py
4040
!scripts/export_kompress_v2_onnx.py
41+
!scripts/refresh_tool_hashes.py
4142
!scripts/record_kompress_fixtures.py
4243
!scripts/record_code_compressor_fixtures.py
4344

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ repos:
3333
# unconditionally, so installing hooks is not required for enforcement.
3434
args: [--assume-in-merge]
3535
- repo: https://github.com/astral-sh/ruff-pre-commit
36-
rev: v0.15.22
36+
rev: v0.16.2
3737
hooks:
3838
- id: ruff
3939
args: [--fix]

0 commit comments

Comments
 (0)