feat: scanner dispatch extensions + monitoring — phases 3-6 (Ossprey, CLI monitoring, full-chain validation) - #100
Merged
neomatrix369 merged 5 commits intoAug 22, 2026
Conversation
…SEARCH-labeled (Phase 3)
Second dispatch extension per ADR-0005/ADR-0017, registered after DepShield
in SCANNER_GROUPS (applies_to both):
- run_ossprey: `ossprey scan <workdir> -o <ossbom.json>` subprocess adapter.
Credential gate FIRST — skipped_missing_credential is the default runtime
path today (OSSPREY_API_KEY / API_KEY absent; Ossprey access provisioning
is OPEN, slice 35 BLOCKED). Adapter activates when a key lands.
- Exit-code disambiguation (vendor contract: 0 = clean/skipped, 1 = malware
OR scan failure): exit 0 is authoritative-clean; nonzero emits red
'malware' findings ONLY on a positive signal (malicious OSSBOM component,
or an unambiguous verdict line with negation guard) — a scan failure
degrades to unreachable, never a phantom red that would block a clean
artifact. OSSBOM parsing tolerates list and {components|packages:[...]}
shapes with defensive access.
- RESEARCH evidence label per the module's discipline: OSSBOM schema and
verdict wording are vendor-doc-sourced, NOT live-probed — needs
reconciliation against the pinned ossprey-cli before VERIFIED.
- Trust-strip gate deliberately preserved: no Ossprey mention in README/
QUICKSTART/CONTRIBUTING/STATUS/ARCHITECTURE (no user-usable capability
yet — "badges only when functionality exists"). Documented instead in
scanner-output-adapters.md §8, DECISIONS rows, ADR-0017 addendum,
OPTIONAL_SCANNER_KEYS + env-vars (key marked access-OPEN).
- Modal image: guarded best-effort release-binary install (absent binary
degrades to unreachable, acceptable while provisioning is OPEN).
Rebased onto post-merge main (PR neomatrix369#83 + slices 40-43). Gates: 232 sandbox
tests @ 97.03% coverage, 111 guard, 129 cli; ruff/mypy/bandit clean; xenon
split ceilings met; trust-strip rg clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
code-review-graph reviewOverall risk: 0.40 (MEDIUM) — 101 changed function(s)/class(es), 3 affected flow(s), 48 test gap(s) Risk-scored changes
Affected execution flows
Test gaps
Token savings: this graph-backed report used ~58,734 fewer tokens (~80%) than reading every changed file in full (estimated, chars/4 approximation). Powered by code-review-graph — local-first analysis; no code leaves the CI runner. |
…ility (Phase 4, slice 37) CLI monitoring per slice-37's spec (operator observability, extending the existing CLI — not a second truth store): - `tripwire status [--json] [--limit <n>]`: hooks state (~/.tripwire/config.json enable/validity, PreToolUse registration in ~/.claude/settings.json, Supabase monitoring_enabled/threshold, §3 two-switch disagreement warning, and a tamper callout when the hook is registered but config.json is missing — that state DENIES all matched tools); items heatmap distribution via per-status head-counts (immune to PostgREST's 1000-row cap); recent scan-run health with fleet-wide stranded-running detection (dedicated head-count query, not page-local — a strand older than the newest --limit runs is exactly the busy-system case) naming the reconcile remedy; per-scanner latest status with unreachable/skipped tallies. - GWT 2 (enforcement unchanged) proven by test: recorded Supabase calls are select-family only (zero insert/update/upsert/delete/rpc), zero fs writes. - GWT 3: invalid --limit exits nonzero with an actionable example; missing Supabase env degrades to local-hooks-only output (exit 0) instead of hard-failing observability. - Docs: user-guide monitoring section + troubleshooting, DECISIONS rows (surface choice; Bash-interception explicitly not slice-37 scope — the upstream handler already gates skills-path Bash), slice-37 Before-Check name-sketch ticked (gate status left PLANNED for maintainer rituals), CHANGELOG entry. Adversarial verify confirmed 1 major (stranded pagination blind spot) + 4 minors (row-cap counts, missing-config understatement, prototype-key drop, user-scope-only registration claim) — all fixed with regression tests. Gates: 138 cli tests pass, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ecture note (Phases 5-6, slices 38-39) Phase 5 (slice 38): scripts/full-chain-validation.sh — staged checklist with a single accountable result (exit 0 only when every required stage passes): preflight, credentials, hooks-installed, demo-artifacts, scan-dispatch, verify-status, depshield-dispatch, ossprey-dispatch, cli-monitoring, and a LIVE /tw-self-check stage invoked via `claude -p` (never mocked, output captured into evidence) per the slice-38 GWTs and the original SEQUENCE-13 expectation. `ossprey-dispatch: SKIPPED(access)` is explicit while slice 35 remains BLOCKED. Stages needing Supabase/Modal creds report BLOCKED(.env) honestly; degraded-mode run verified on this machine (evidence JSON written to .test-results/full-chain-evidence.json; gate evidence stays a maintainer ritual — the script never fabricates it). Phase 6 (slice 39): deferred by default per the slice's own spec (Could, hackathon-too-large). Deliverable is docs/research/fe-be-target-architecture.md: current three-plane boundary map, the two pressures worth solving on pull-in (single-implementation six-state machine; anon read path to retire the client-side service-role key), and pinned non-goals. DECISIONS rows recorded for both; slice files left at maintainer-owned gate states. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…chain harness, escaped pipes in a DECISIONS table row - scripts/full-chain-validation.sh: interpolate $CONFIG_JSON instead of a quoted tilde path (SC2088); move `|| true` outside the command substitutions so the A && B || C pattern disappears (SC2015) - docs/plan/DECISIONS.md: escape regex pipes in the slice-37 HOOK_MATCHER code span — raw pipes split the markdown table cells (MD056/MD038) Verified locally via `uvx pre-commit run --all-files`: shellcheck, markdownlint, actionlint, gitleaks, ruff(+format), mypy, bandit, xenon, vulture, pylint, pytest-testmon, CLI node tests + ESLint all pass. The eslint-dashboard hook fails only locally (dashboard node_modules not installed on this machine); untouched by this branch and green on main CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
neomatrix369
marked this pull request as ready for review
August 21, 2026 23:51
Owner
Review follow-up — critical/high fixes (branch
|
| ID | Issue | Fix |
|---|---|---|
| H1 | Broad stdout negation regex (\bnot\b, \bclean\b) could suppress real malware lines |
Narrowed to clean-summary patterns only (no/not/zero/none/0 malicious, clean scan/result); regression test for "not a false positive" wording |
| H2 | claude -p in full-chain harness had no wall-clock cap |
run_with_timeout (120s; timeout / gtimeout / Python fallback); exit 124 → BLOCKED(timeout) |
| H4 | Generic API_KEY could activate or confuse Ossprey gate |
Adapter accepts OSSPREY_API_KEY only; docs + harness aligned |
| C1 | DepShield + Ossprey timeouts exceeded SCAN_TIMEOUT envelope |
OSSPREY_TIMEOUT 200→100; CI gate scripts/check-scanner-timeout-budget.sh; budget table in docs/ARCHITECTURE.md |
| H3 | Unverified Ossprey binary tag | Pinned v0.12.0 (verified linux-amd64 asset); image build emits WARNING when binary missing |
| H5 | RESEARCH adapter activation gate | Live CLI reconcile After-Checks added to slice 35/36 stubs |
Still intentional (not changed)
- Ossprey remains in
SCANNER_GROUPS(credential-gated; DECISIONS rows stand) - Trust-strip on five gated docs remains clean
- Adapter stays RESEARCH until slice 35/36 live reconcile passes
Verification
sandbox/tests/test_scanners_ossprey.py: 47 passedscripts/check-scanner-timeout-budget.sh: OK (120+100 ≤ 240)
Maintainers: cherry-pick or merge fix/pr-100-review onto frontline-hack-phases-3-6 before marking PR ready.
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Continuation of the phased Claude Code integration (Phases 1–2 merged in #83). Fresh branch off post-#98
main; one commit per phase, all phases complete:c703f66): registered after DepShield inSCANNER_GROUPS; credential-gated (skipped_missing_credentialis the default runtime path while access provisioning stays OPEN — slice 35 BLOCKED); exit-code disambiguation so a scan failure can never masquerade as a malware finding (red only on a positive OSSBOM/verdict signal, elseunreachable); honestly RESEARCH-labeled per ADR-0005; trust-strip gate deliberately preserved (no Ossprey mention in the five gated docs until provisioning + live verification exist).tripwire statusobservability (91fecdf, slice 37): read-only hooks + scan/dispatch health; fleet-wide stranded-run detection via head-count (immune to the recent-page and PostgREST 1000-row caps); §3 two-switch disagreement warning + missing-config tamper callout; enforcement preservation proven by test (select-family calls only, zero fs writes); invalid input exits nonzero with actionable guidance; degrades to local-only output without Supabase creds.63af5cf, slices 38–39):scripts/full-chain-validation.shstaged checklist with a single accountable exit code, LIVE/tw-self-checkas a named never-mocked stage, explicitossprey: SKIPPED(access), honestBLOCKED(.env)for live stages until Supabase/Modal creds exist; slice 39 stays deferred per its own spec, delivered asdocs/research/fe-be-target-architecture.md.Every phase was adversarially reviewed before its commit (Phase 3: 45 dedicated tests incl. disambiguation both ways; Phase 4: 1 major + 4 minors confirmed by repro and fixed with regression tests).
Test Results
As of
63af5cf(on post-#98main):scanners.pyD/C/B;scan_app.pyC/–/A);ruff/mypy/banditcleanrg -i 'ossprey|overmind'empty across all five gated filesChecklist
./scripts/quality-gates.shpasses locally🤖 Generated with Claude Code