Commit 2371ee3
committed
feat(app+boj): loopback HTTP backend, shared fight crate, expert summoning
Push #2 — wire the army and make the squabbler summonable, keeping the core
detachable and every hand-off honest.
squabble-fight (new crate):
- The host-side fight brain, extracted from squabble-cli so the CLI and the
App serve ONE planner and cannot drift: ecosystem-context reader
(context.rs) + workflow ground-truth (workflows.rs) + the pure planner
(plan / plan_at_root). git-mv'd to preserve history; tests moved along and
extended (fail-safe on missing repo root; every red accounted for).
squabble-app (stub → real):
- Loopback-only axum server on 127.0.0.1:${SQUABBLE_PORT:-7741}:
GET /health, POST /api/v1/diagnose (Gate → Diagnosis),
POST /api/v1/fight ({slug, gate, repo_root?} → Outcome/Report manifest).
This is the process the boj-server `cicd-squabbler-mcp` cartridge proxies
to — cartridge gateways run in a Deno sandbox with --allow-net only (no
subprocess), so the squabbler must be reachable over loopback HTTP.
- The GitHub App *webhook* leg (check_run.requested_action + octocrab)
remains honestly absent: no webhook route is registered; a delivery gets a
plain 404, never a fake 200. Refuses non-loopback binding (no auth layer).
squabble-cli:
- `squabble fight --summon` (feature `boj`, ureq; the default build compiles
the client out entirely and gains zero deps): maps each EscalateToExpert to
its specialist cartridge via POST {BOJ_URL:-http://localhost:7700}
/cartridge/<name>/invoke — Security→panic-attack-mcp/panic_attack_scan,
Proof→echidna-llm-mcp/consult, Hypatia*→hypatia-mcp/hypatia_scan_repo.
- Honest actuation: dispatch-fix is recorded as assessed (actuation external
— no fixer cartridge exists today); a summon can only ADD evidence, never
remove or downgrade an escalation, and never changes the outcome colour.
- Fail-closed (AGENTIC no-silent-skip): unreachable server/expert appends
explicit evidence to every escalation and the blockers list; a build
without the feature refuses `--summon` loudly (exit 2) instead of
pretending.
squabble-core:
- Diagnosis gains Serialize/Deserialize so hosts can emit it as evidence.
No engine semantics changed; the SPARK-mirrored gate invariant is
untouched.
Verified: 42 default-feature tests + boj-feature tests green; fmt + clippy
clean in both configs; live end-to-end — the App served /health, /diagnose,
and /fight over the real ipv6-only checkout (the fight correctly no longer
flags the AGPL label that PR ipv6-only#45 removed — the loop observes its
own completed work); --summon verified fail-closed against a dead port and
loudly-refusing without the feature.
Companion: hyperpolymath/boj-server-cartridges cartridge
`cartridges/domains/ci-cd/cicd-squabbler-mcp` (same branch name).
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SUURnQUnzTXYftzWFs5pfZ1 parent a9bbf20 commit 2371ee3
14 files changed
Lines changed: 1768 additions & 364 deletions
File tree
- .machine_readable/descriptiles
- crates
- squabble-app
- src
- squabble-cli
- src
- squabble-core/src
- squabble-fight
- src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
32 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
33 | 35 | | |
34 | 36 | | |
35 | 37 | | |
| |||
39 | 41 | | |
40 | 42 | | |
41 | 43 | | |
42 | | - | |
43 | | - | |
| 44 | + | |
| 45 | + | |
44 | 46 | | |
45 | 47 | | |
46 | 48 | | |
| |||
0 commit comments