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
10 changes: 10 additions & 0 deletions .captain/review/loop-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Review loop log

Track escapes, fixer regressions, and routing misses so the review policy
can be recalibrated with evidence (not vibes). One row per non-trivial
incident or completed high-risk unit.

| Date | Unit / PR | Tier | Reviewers used | Escaped bug? | Fixer regression? | Notes / policy change |
|---|---|---|---|---|---|---|
| | | | | | | |
Also see specs/reviews/loop-log.md for historical review notes.
23 changes: 23 additions & 0 deletions .captain/review/prompts/fix-verify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Fix verify — finding-owner re-check

You filed or owned the original finding(s). A fixer has landed changes. Your
job is to verify each finding is actually resolved **without new regressions**.
You are not the implementer of the fix.

## For each original finding
1. Restate the finding in one line.
2. Point at the fix (path + symbol).
3. Verdict: **resolved** | **partial** | **not fixed** | **regressed**
4. Evidence: test/command output, or a concrete scenario that still fails.
5. If severity was critical/high: confirm a **regression test** exists and fails
without the fix (or explain why an oracle already covered it).

## Also check
- Fix did not weaken the oracle to go green
- Fix did not expand scope beyond the finding
- No new trust-boundary holes adjacent to the change

## Output
A short checklist per finding + an overall **approve-to-gate** or
**return-to-fixer** (with remaining items). After two fixer cycles without
clearance, escalate to a human — do not start a third cycle.
28 changes: 28 additions & 0 deletions .captain/review/prompts/implementation-adversary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Pass B — implementation adversary

You are an adversarial reviewer focused on **how** the change is built. You
did **not** write this code. Assume Pass A (or the spec) already covers
product intent — you hunt integration and engineering defects.

## Inputs you must use
1. Diff / changed files
2. Surrounding call sites and existing primitives (reuse-first)
3. Spec only where needed to judge API contracts
4. Bugbot flags as a suspect map

## Look for
- API / lifecycle misuse (init order, cancel, resource cleanup, thread/actor isolation)
- Integration assumptions that can fail in production
- Duplicated or near-duplicated primitives that should have been reused
- Error handling that swallows, misclassifies, or loses context at boundaries
- Maintainability traps that will force a paragraph-long comment later
(if justifying a workaround needs a paragraph, the code is wrong — flag it)

## Output format
For each finding (or "no findings"):
- **Severity:** critical | high | medium | low
- **Location:** path + symbol / line range
- **Failure mode:** what breaks, under what condition
- **Fix direction:** one sentence (do not implement)

Do **not** re-litigate product scope. Do **not** implement fixes on this pass.
30 changes: 30 additions & 0 deletions .captain/review/prompts/semantic-adversary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Pass A — semantic adversary

You are an adversarial reviewer. You did **not** write this code. Your job is
to find real correctness bugs against the **locked spec and oracle**, not to
nitpick style.

## Inputs you must use
1. Spec / plan sections named in the PR
2. Oracle (tests, goldens, property cases) — ground truth
3. Diff / changed files only (unless a dependency is required to understand a call)
4. Bugbot flags (suspect map only — do not treat as settled)

## Look for
- Spec mismatch / missing states / wrong transitions
- Failure and recovery paths (crash, retry, partial write, cancel)
- Concurrency / ordering / idempotency hazards
- Privilege / trust-boundary violations (authz, grants, egress, redaction)
- Oracle gaps: behavior the spec requires but no test asserts

## Output format
For each finding (or "no findings"):
- **Severity:** critical | high | medium | low
- **Location:** path + symbol / line range
- **Failing scenario:** concrete inputs → wrong observable outcome
- **Spec/oracle cite:** which requirement or test is violated (or missing)
- **Fix direction:** one sentence (do not implement)

Do **not** rewrite the code. Do **not** weaken the oracle. If the oracle is
wrong, say so as a finding ("oracle amendment required") rather than blessing
the implementation.
21 changes: 21 additions & 0 deletions .cursor/BUGBOT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Bugbot project context (captain-workflow)

Mechanical first-pass only. Do **not** spend review budget on style, naming
nits, or formatting — the deterministic gate already owns those.

## Prioritize
- Correctness bugs with a concrete failing scenario
- Security / trust-boundary issues (authz, grants, secrets, egress, injection)
- Missing or weakened tests for new behavior
- Crash / data-loss / concurrency hazards

## How to report
- Severity + confidence
- Exact location
- Concrete inputs → wrong observable outcome
- Skip low-confidence style comments

## Never treat this pass as
Semantic approval, spec conformance, or a substitute for Pass A / Pass B /
human Judge on trust-critical paths. See `review-policy.yaml` and
`~/.claude/skills/captain-workflow/REVIEW.md`.
42 changes: 42 additions & 0 deletions .cursor/rules/model-routing.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
description: Model routing + gate discipline for this repo (captain-workflow)
alwaysApply: true
---

# Model routing (captain-workflow)

This repo is gated by `scripts/check_all.py` / `scripts/check-all.mjs`,
wired to run on every `git commit` via `core.hooksPath`. That gate applies
no matter which model generated the diff — never bypass it (`--no-verify`)
without a declared emergency.

Full policy + rationale: `~/.claude/skills/captain-workflow/MODEL-ROUTING.md`.

## Default model choice here

- **Routine/small build tasks** (extends an existing pattern, one reasonable
approach, contained to one file or a small set): default to Grok 4.5 or
GPT-5.6 Terra. Plan and build in one prompt — no separate planning pass
needed for this class.
- **Correctness-critical pieces** (auth, payments, data integrity, a tricky
algorithm, anything the spec doc flags as load-bearing or risky): escalate
to Opus 4.8, selected manually.
- **Stuck / hard cases** (Grok/Terra already failed 1-2 tries, math-heavy or
algorithm-heavy work, a large multi-file refactor): escalate to GPT-5.6
Sol, selected manually — never as an Auto default.
- Run Bugbot before human review on `semantic` / `trust-critical` changes
(and on routine PRs ≥50 lines). Bugbot is mechanical only — never
semantic approval. See `review-policy.yaml` + `.cursor/rules/review.mdc`.

## Scope discipline

Treat any spec/plan doc in this repo's spec/plan directory (e.g. `specs/`,
`docs/specs/` — check what this repo actually uses) as locked scope — it was
written in the Frame/Spec phase, typically in Claude. Don't improvise
outside it.

If a task turns out to have no precedent in the codebase, real tradeoffs
between valid approaches, multi-file/system reach, or touches
auth/payments/data-integrity — that's "big/new," not routine. Flag it back
rather than building ad hoc; that class of work should get planned first
(Claude, Frame/Spec phases), not executed straight from a prompt here.
36 changes: 36 additions & 0 deletions .cursor/rules/review.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
description: Adversarial review loop + risk tiers (captain-workflow)
alwaysApply: true
---

# Review discipline (captain-workflow)

Full policy: `~/.claude/skills/captain-workflow/REVIEW.md`.
Per-repo path → risk map: `review-policy.yaml` at repo root.

## Loop (do not skip)

`implementer → Pass A (semantic) + Pass B (impl) → fixer → finding-owner
verifies → gate → human Judge if trust-critical`

- Implementers do not review their own unit.
- Fixer never has the last word — original finding-owner verifies.
- Max 2 fixer cycles, then human escalate.
- Critical findings need a regression test with the fix.

## Risk (path floor, not LOC)

Compute minimum tier from `review-policy.yaml` globs. Trust-critical paths
(grants/policy/auth/event-log/protocol/redaction/payments) **cannot** be
declared `routine`. Bugbot is mechanical only — never semantic approval.

## Oracle

For `semantic` / `trust-critical`: oracle author ≠ implementer. Do not
weaken tests to go green; amend oracle + spec as a separate change.

## Prompts

Use `.captain/review/prompts/` — `semantic-adversary.md`,
`implementation-adversary.md`, `fix-verify.md`. Do not run two identical
“review this diff” agents.
35 changes: 35 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CODEOWNERS — human approval on trust-critical paths
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
#
# Replace @akminx with your GitHub username or team (captain-init tries to
# fill this from `gh api user` when available). Customize path globs to match
# review-policy.yaml trust_critical_paths for this repo.

# Default owner for everything (optional — remove if you only want critical paths)
# * @akminx

# Trust-critical defaults — edit to match this repo
**/auth/** @akminx
**/authz/** @akminx
**/grants/** @akminx
**/policy/** @akminx
**/permissions/** @akminx
**/billing/** @akminx
**/payment*/** @akminx
**/redaction/** @akminx
**/eventlog/** @akminx
**/event-log/** @akminx
**/protocol/** @akminx

# Gilly trust-critical (INVARIANTS)
specs/grants.md @akminx
core/**/grants/** @akminx
core/**/policy/** @akminx
core/**/eventlog/** @akminx
core/**/event-log/** @akminx
core/src/session/** @akminx
specs/protocol/** @akminx
**/redaction/** @akminx
**/redaction*.ts @akminx
core/src/surface/redaction.ts @akminx
INVARIANTS.md @akminx
39 changes: 39 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## Summary
<!-- 1-3 bullets: what changed and why -->

## Risk tier
<!-- Must be ≥ path-derived minimum from review-policy.yaml. Trust-critical
paths (grants/policy/auth/event-log/protocol/redaction/payments) cannot
be declared routine. -->

- [ ] `routine`
- [ ] `semantic`
- [ ] `trust-critical`

Path-derived minimum (if known): ___________

## Oracle / evidence
<!-- For semantic + trust-critical: oracle author ≠ implementer. -->

- Spec section(s):
- Oracle path (tests/goldens/properties):
- Command run + result:

## Review topology (from review-policy.yaml)

- [ ] Deterministic gate green (`check_all` / CI)
- [ ] Bugbot (mechanical only — not semantic approval)
- [ ] Pass A — semantic adversary
- [ ] Pass B — implementation adversary (required for semantic+)
- [ ] Finding-owner verified fixer changes (if any)
- [ ] Human Judge (required for trust-critical)
- [ ] CODEOWNERS approval (trust-critical paths)

## Implementer model family
<!-- For routing recalibration — e.g. Grok/Terra, Opus, Sol, Fable -->

## Unresolved assumptions
<!-- Anything reviewers should not assume is settled -->

## Test plan
- [ ]
36 changes: 36 additions & 0 deletions .github/branch-protection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Branch protection checklist (GitHub)

Local hooks are bypassable (`--no-verify`). Mirror the gate in CI and lock
the default branch so trust-critical review cannot be skipped when someone
is tired.

Run once per repo (Settings → Branches → Branch protection rules), or via
`gh api` if you prefer automation. captain-init does **not** apply these
automatically — they need repo admin rights.

## Required settings

- [ ] Require a pull request before merging
- [ ] Require status checks to pass: `check-all-node` and `check-all-swift`
(the jobs `.github/workflows/check-all.yml` defines — the Swift job runs
the client gate on macOS)
- [ ] Require branches to be up to date before merging (optional but good)
- [ ] Require review from Code Owners (uses `CODEOWNERS`)
- [ ] Dismiss stale pull request approvals when new commits are pushed
- [ ] Do **not** allow author self-approval (GitHub: disable bypass for
admins on critical repos if you can live with it)
- [ ] Block force pushes and deletions on the default branch

## Trust-critical extra

For repos with money / authz / safety surface: require at least one
approving review from someone other than the PR author, even when CI is
green. CODEOWNERS on paths listed in `review-policy.yaml` is the mechanism.

## Verify

```sh
gh api "repos/{owner}/{repo}/branches/{branch}/protection" --jq .
```

If this 404s, protection is not configured yet.
53 changes: 52 additions & 1 deletion .github/workflows/check-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
# core/package.json requires >=22; the Pi SDK (0.80.10) needs
Expand All @@ -13,8 +15,57 @@ jobs:
node-version: "22"
- name: Install project deps (CI parity with local node_modules)
run: |
for pj in $(find . -name node_modules -prune -o -name package.json -print); do
for pj in $(find . \( -name node_modules -o -name .git -o -name .claude -o -name .worktrees -o -name worktrees \) -prune -o -name package.json -print); do
(cd "$(dirname "$pj")" && (npm ci || npm install))
done
- run: node scripts/check-all.mjs
- run: node scripts/arch-checks.mjs
- name: Path-derived risk tier
if: github.event_name == 'pull_request'
env:
GILLY_TIER_RANGE: "origin/${{ github.base_ref }}...HEAD"
run: node scripts/check-tier.mjs --ci
- name: Path-derived risk tier (push)
if: github.event_name == 'push'
env:
BEFORE: "${{ github.event.before }}"
# Diff the pushed commits (not the clean checkout working tree).
GILLY_TIER_RANGE: "${{ github.event.before }}...${{ github.sha }}"
run: |
# Brand-new branch: github.event.before is all-zeros and the range is
# unresolvable. Skip here (informational) and rely on the pull_request
# tier check, which resolves against base_ref. Any other unresolvable
# range still fails loudly inside check-tier.mjs.
case "$BEFORE" in
""|0000000000000000000000000000000000000000)
echo "check-tier: new-branch push (before=$BEFORE); skipping — the PR tier check enforces the floor."
exit 0
;;
esac
# Direct pushes must declare via commit trailer when above routine:
# Risk-Tier: semantic|trust-critical
TIER=$(git log -1 --pretty=%B | sed -nE 's/^Risk-Tier:[[:space:]]*(routine|semantic|trust-critical)[[:space:]]*$/\1/ip' | head -1)
if [ -n "$TIER" ]; then
node scripts/check-tier.mjs --ci --declare="$TIER"
else
# --ci with GILLY_TIER_RANGE set: still uses the range for files;
# missing declaration fails when path minimum > routine.
node scripts/check-tier.mjs --ci
fi

check-all-swift:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install Swift lint tooling
run: |
brew install swiftlint || true
# swift-format ships with the Xcode/Swift toolchain on macos-latest
- name: Install Node deps for protocol codegen parity
run: |
(cd core && (npm ci || npm install))
- name: Swift gate (full client)
run: ./scripts/check-swift.sh --all
Loading
Loading