Skip to content

Scope threat models to the current run instead of caching them on disk - #1178

Merged
0xallam merged 2 commits into
mainfrom
devin/1787782654-run-scoped-threat-model
Aug 26, 2026
Merged

Scope threat models to the current run instead of caching them on disk#1178
0xallam merged 2 commits into
mainfrom
devin/1787782654-run-scoped-threat-model

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Threat models were persisted to ~/.strix/threat-models/<sha>.json, keyed by target identity rather than run id, so any later scan against the same host or checkout on the same machine read back a model an earlier run derived. This makes the model scan-scoped: it lives in memory for the run and is mirrored into that run's own state directory, exactly like the coverage ledger, so a resumed scan keeps the baseline its earlier agents agreed on while a new scan against the same target starts with found: false and derives its own.

-_CACHE_DIR = Path.home() / ".strix" / "threat-models"      # shared by every run on the box
+_MODELS: dict[str, dict[str, Any]] = {}                    # identity -> model
+_store_path: Path | None = None                            # {state_dir}/threat_models.json

hydrate_threat_models_from_disk(state_dir) is called from the runner next to the todo/notes/coverage hydration, and save/amend mirror under the same lock they mutate under (serialize + rename in one critical section, so a writer holding an older serialization cannot roll back a concurrent agent's amendment).

Everything that only existed to keep a cross-run cache honest is gone:

  • revision pinning (_target_identity returns just the identity now, no HEAD) and the stale / cached_revision / created_at response fields;
  • the 14-day age-out for unversioned targets (_MAX_AGE_DAYS, _is_expired, _staleness).

Target-identity normalization and _snap_to_scan_target stay: within one run agents still spell the same target several ways (handed URL, page under test, checkout path) and must converge on one document. A side effect of dropping revision pinning is that a commit mid-run no longer drops the model — covered by a test.

Prompt and copy updates so agents and the UI no longer describe the model as cached across scans: system_prompt.jinja, skills/coordination/root_agent.md, and the TUI/viewer renderers (empty state is now "No model derived for this target yet"; stale/revision rendering removed).

Tests assert the three properties that matter: nothing lands outside the run (empty $HOME), a resumed run in a fresh process reads back the model and its amendments, and a different run's state dir starts with no model.

Link to Devin session: https://app.devin.ai/sessions/7e0f68d368e545da8d701d92009cc474

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR replaces the target-wide threat-model cache with scan-owned state while preserving that state across an interrupted scan.

  • Stores threat models in the current run’s state directory and hydrates them during runner initialization.
  • Removes revision and age-based staleness handling from the tool responses and user interfaces.
  • Updates agent guidance and tests for fresh-run isolation, same-run resume, and in-run sharing.

Confidence Score: 5/5

The PR appears safe to merge.

The previously reported resume failure is resolved because threat models and amendments are now mirrored under the scan’s state directory and rehydrated when that scan resumes; no blocking failure remains.

Important Files Changed

Filename Overview
strix/tools/threat_model/tools.py Replaces the cross-run cache with an in-memory store mirrored atomically into the current run’s state directory, including resume hydration.
strix/core/runner.py Hydrates the run-owned threat-model mirror alongside other durable shared scan state before agent execution.
tests/test_threat_model_tool.py Covers fresh-run isolation, same-run resume, amendments, and behavior across repository revisions.
strix/agents/prompts/system_prompt.jinja Updates agent instructions to describe threat models as shared only within the current scan.
strix/skills/coordination/root_agent.md Aligns root-agent coordination guidance with scan-scoped threat-model ownership.
strix/interface/tui/internal/render/threat_model.go Removes obsolete revision and staleness presentation from terminal threat-model output.
strix/interface/viewer/frontend/src/components/live/tool-renderers/ThreatModelRenderer.tsx Removes obsolete cached-revision and stale-state rendering from the web viewer.

Reviews (2): Last reviewed commit: "Mirror the run's threat models into its ..." | Re-trigger Greptile

Comment thread strix/tools/threat_model/tools.py
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

@greptile

@0xallam
0xallam merged commit 8b655de into main Aug 26, 2026
2 checks passed
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.

1 participant