Skip to content

[BUG] --scope-mode and --diff-base are silently ignored on --resume, and run.json/coverage.json then contradict themselves #1508

Open

Description

@hdp01

Describe the bug

--scope-mode is documented as 'full' disables diff-scope (strix/interface/cli_args.py:233), but on a resume it is a silent no-op, and the run record then contradicts itself about what was scanned.

Two things go wrong together:

1. The flag is never consulted on resume. prepare_run() returns early for resumes:

# strix/interface/scan_setup.py:245-246
if args.resume:
    return

resolve_diff_scope_context(..., scope_mode=args.scope_mode, diff_base=args.diff_base, ...) sits at line 257, after that return, so it never runs. Meanwhile load_resume_state() restores the persisted scope verbatim, without reference to args.scope_mode:

# strix/interface/cli_args.py:530-531
if state.get("diff_scope"):
    args.diff_scope = state.get("diff_scope")

So resuming a diff-scoped run with --scope-mode full still runs diff-scoped. strix/core/runner.py:393-394 derives is_diff_scoped from the restored diff_scope["active"], which adds the scan_modes/diff skill to the root agent's and every child's system prompt (strix/agents/prompt.py:55) and keeps the diff-scope preamble. --diff-base is ignored the same way.

Unlike --scan-mode (see #1507), there is no sentinel ambiguity here: --scope-mode has default="auto", so full is unmistakably explicit. The code simply never looks at it on this path.

2. The published record then asserts two incompatible things. args.scope_mode is forwarded into scan_config and persisted, while diff_scope comes from the old run:

# strix/interface/cli.py
"diff_scope": getattr(args, "diff_scope", {"active": False}),   # :93  — restored, old
"scope_mode": getattr(args, "scope_mode", "auto"),              # :98  — new, from the flag

strix/report/state.py:780,783 writes both side by side, so run.json and coverage.json's scope block end up recording scope_mode: "full" next to diff_scope: {"active": true}.

This second part is a defect regardless of how the first is resolved: whichever behaviour is intended for the flag on resume, a published artifact should not claim full scope and active diff-scope at the same time.

To Reproduce

  1. Start a diff-scoped scan over a local repo, so run.json carries "scope_mode": "diff" and "diff_scope": {"active": true, ...}.
  2. Resume it asking for the full repository: strix --resume <run_name> --scope-mode full
  3. The agents still carry the diff-scope skill and preamble, and run.json / coverage.json record scope_mode: "full" together with diff_scope.active: true.

Reproduced without launching a sandbox by writing a minimal run.json and calling parse_arguments() with ["strix", "--resume", "<name>", "--scope-mode", "full"]:

args.scope_mode        = full
args.diff_scope        = {'active': True, 'base': 'origin/main', 'repos': []}
is_diff_scoped would be: True

Expected behavior

--scope-mode full on a resume should widen the scan to the full repository as --help promises, and --diff-base should be honoured — or both should be rejected with a clear error when combined with --resume, the way --target already is. In no case should the persisted scope_mode and diff_scope be written out contradicting each other.

Suggested fix

In load_resume_state(), let an explicit --scope-mode/--diff-base re-resolve the scope — at minimum honour scope_mode == "full" by forcing args.diff_scope = {"active": False}. If preserving the original scope across a resume is deliberate, parser.error() on either flag with --resume instead. Either way, keep the two fields consistent in the record.

System Information:

  • OS: Ubuntu 24.04.4 LTS
  • Strix Version or Commit: f7a32ae (main, v1.7.0)
  • Python Version: 3.12.3
  • LLM Used: n/a — argument parsing only

Additional context

Separate from #1507, which is about --scan-mode deep being masked by its own default value in the same function. This one needs no sentinel work; the flag is already unambiguous.

Activity

  1. added a commit that references this issue on Oct 18, 2026
    645174f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions