Skip to content

feat: blast radius preflight gate via charter blast (#20)#22

Merged
stackbilt-admin merged 2 commits intomainfrom
feat/blast-radius-preflight
Apr 9, 2026
Merged

feat: blast radius preflight gate via charter blast (#20)#22
stackbilt-admin merged 2 commits intomainfrom
feat/blast-radius-preflight

Conversation

@stackbilt-admin
Copy link
Copy Markdown
Member

Summary

  • Closes feat: blast radius preflight gate via charter blast #20 — adds a deterministic autonomous-safety gate that refuses to execute auto_safe tasks targeting architectural hubs.
  • Runs charter blast --format json on file paths extracted from the task prompt; classifies severity on a 4-level ladder; blocks execution when critical.
  • High/critical severities also inject a ## Blast Radius Warning section into the mission brief so the agent understands scope even when the task is allowed to proceed.
  • Zero runtime dependencies beyond charter CLI 0.10.0 being on PATH. Gracefully no-ops when charter is unavailable.
  • Applied symmetrically to taskrunner.sh and plugin/taskrunner.sh.

Severity ladder

Affected files Severity Behavior
0–4 low silent
5–19 medium silent
20–49 high warning injected into mission brief
50+ critical warning injected; auto_safe tasks refused

Environment knobs

CC_DISABLE_BLAST=1        # opt out entirely
CC_BLAST_WARN=20          # high threshold (default)
CC_BLAST_BLOCK=50         # critical threshold (default)
CC_BLAST_TIMEOUT=60       # charter blast timeout in seconds (default)

Graceful degradation

All of these are no-ops that let the task run as before:

  • Charter CLI not installed
  • CC_DISABLE_BLAST=1 set
  • No recognizable file paths in the prompt (.ts / .tsx / .js / .jsx / .mjs / .cjs)
  • charter blast fails or times out
  • Target repo doesn't exist on this runner

How the gate fires

# Before
task { authority: auto_safe, prompt: "Refactor src/kernel/dispatch.ts ..." }
  → runs Claude, burns ~30 turns, produces 72-file PR, reviewer cries

# After
task { authority: auto_safe, prompt: "Refactor src/kernel/dispatch.ts ..." }
  → compute_blast_radius extracts dispatch.ts
  → charter blast reports 72 affected files (critical)
  → gate logs "⚠ GATE: blast radius critical — refusing auto_safe execution"
  → update_task_status("failed", "TASK_BLOCKED: blast_radius_critical — 72 files affected")
  → returns without spawning Claude

Operator can still force execution by changing the task's authority to operator and re-queuing. The gate only refuses auto_safe.

Real-world validation

Tested against a 263-file TypeScript Cloudflare Worker codebase:

Seed file Affected Severity Gate action
version.ts (leaf) 5 medium proceed
chat-session.ts (isolated DO) 1 low proceed
dispatch.ts (orchestrator) 72 critical refuse
types.ts (central types) 127 critical refuse

Also tested:

  • Prompt with no file paths → no-op, no blast data returned
  • Prompt with .ts file that doesn't exist in repo → no-op, file filtered out
  • High severity (20–49) → warning rendered, not blocked
  • Low severity (0–4) → warning empty, not blocked

Seed count cap

The helper caps seed files at 10 to prevent runaway prompts from exploding the blast call. If a prompt lists 47 .ts files, only the first 10 (after sort) are fed to charter.

Prompt brief excerpt

When a high or critical severity fires, the mission brief looks like:

# MISSION BRIEF — Autonomous Task

You are operating autonomously in an unattended Claude Code session.
Read files before modifying them. Be thorough.

## Task
Refactor the dispatcher to use the new executor interface

## Blast Radius Warning
- Severity: **CRITICAL** — 72 files affected
- Seed files: src/kernel/dispatch.ts
- One or more seeds are in the top 20 most-imported files (architectural hub)
- Treat this as CROSS_CUTTING: review carefully before merging

## Project Context (auto-generated)
...

Test plan

  • Bash syntax validated via bash -n on both taskrunner.sh and plugin/taskrunner.sh
  • compute_blast_radius verified across low / medium / high / critical scenarios
  • render_blast_warning verified for low (empty) and critical (full section) cases
  • No-op path verified (no files in prompt)
  • Charter CLI 0.10.0 with blast command on PATH confirmed working
  • Gate logic (authority=auto_safe + critical) simulated in isolation

Related

🤖 Generated with Claude Code

stackbilt-admin and others added 2 commits April 9, 2026 07:39
Adds an autonomous-safety gate to the taskrunner that refuses to execute
auto_safe tasks targeting architectural hubs.

How it works:

1. compute_blast_radius() — new helper that extracts file paths from
   the task prompt via regex, filters to ones that exist in the target
   repo, and runs `charter blast <files> --format json` with a
   configurable timeout. Summarizes to {seeds, affected, severity,
   hot_file, top_hot_files} with a 4-level severity ladder:
     low      0-4  affected
     medium   5-19 affected
     high     20-49 affected
     critical 50+ affected

2. Execution gate — right before mission brief assembly, check the
   severity. If critical + auto_safe, log, mark the task failed with
   TASK_BLOCKED: blast_radius_critical, and return. Claude is never
   spawned, no turns burned, no wrong changes committed.

3. render_blast_warning() — for high/critical severities, injects a
   ## Blast Radius Warning section into the mission brief so the agent
   knows the scope it's operating in. For low/medium severities the
   section is empty.

Environment knobs:
  CC_DISABLE_BLAST=1         — opt out entirely
  CC_BLAST_WARN=<n>          — high threshold (default: 20)
  CC_BLAST_BLOCK=<n>         — critical threshold (default: 50)
  CC_BLAST_TIMEOUT=<sec>     — charter blast timeout (default: 60)

Graceful degradation:
  - Charter not installed       → no-op, task runs as before
  - No file paths in prompt     → no-op
  - charter blast fails/timeout → no-op, task runs as before
  - authority != auto_safe      → warning injected but task runs

Seed count is capped at 10 to prevent runaway prompts from exploding
the blast call.

Applied symmetrically to taskrunner.sh and plugin/taskrunner.sh.
Depends on @stackbilt/cli >= 0.10.0 (for `charter blast`).

Validated against a real 263-file TypeScript Worker codebase:
  version.ts (leaf)          → 5 affected, medium, no gate
  chat-session.ts (isolated) → 1 affected, low, no gate
  dispatch.ts (orchestrator) → 72 affected, CRITICAL, gate fires
  types.ts (central types)   → 127 affected, CRITICAL, gate fires

Closes #20.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new "Charter Integration (optional)" section documenting both:
- Project fingerprint via `charter surface` (shipped in 1.4.0, never docs'd)
- Blast radius preflight gate via `charter blast` (this PR)

Also adds the corresponding env vars to the Environment Variables table:
- CC_DISABLE_FINGERPRINT, CC_FINGERPRINT_TIMEOUT (from 1.4.0/1.4.1)
- CC_DISABLE_BLAST, CC_BLAST_WARN, CC_BLAST_BLOCK, CC_BLAST_TIMEOUT (this PR)

Includes:
- Severity ladder table (low/medium/high/critical)
- Gate firing behavior + how operators unblock tasks
- Sample mission brief warning section
- Pointer to the charter CLI install command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@stackbilt-admin stackbilt-admin force-pushed the feat/blast-radius-preflight branch from 7eed3f8 to 04dbff2 Compare April 9, 2026 12:39
@stackbilt-admin stackbilt-admin merged commit e05658a into main Apr 9, 2026
@stackbilt-admin stackbilt-admin deleted the feat/blast-radius-preflight branch April 9, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: blast radius preflight gate via charter blast

1 participant