Files
Open_Ultra_SAST/PATHFINDER-2026-10-13/01-flowcharts/U1-scan.md
T
Marius CiepluchandClaude Fable 5.1 d2010d0693 docs: Pathfinder map of src, duplication report, unified proposal, and the breadth ledger
PATHFINDER-2026-10-13/: feature inventory, ten per-unit flowcharts with
file:line evidence, cross-feature and within-unit duplication reports, a
proposal that keeps every package on one of the four active lines, and
copy-ready plan prompts in order. .kiro/breadth.toml: every spec and
capability with a status and the deletion that closes it. No code changed.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-13 09:55:21 +02:00

6.7 KiB

U1 Scan orchestration and reports (ousast scan)

Traced read-only on 2026-10-13. Three premises from discovery were wrong and are corrected here: run_hunter_pool (cli.py:670) is the standard branch and is the same regex matcher as quick, with no model call; the tool hunter runs in standard as well as deep whenever MAP runs; scoring and fusion run before MAP, so model-layer, overlay, obligation and tool-hunter findings never reach score.json or fusion.json.

Happy path, --mode standard

  1. main → _main (cli.py:126, 134); load_dotenv() (cli.py:139); parser scan (cli.py:226-230).
  2. _scan (cli.py:613) → _run_scan (cli.py:619) → plan_for_mode standard = (STATIC, MAP) (stages.py:13-17, 28); load_config (cli.py:624).
  3. create_scan_run makes the run dir (run.py:18-26); HarnessRuntime with no processors, write_harness_config (cli.py:627-633); stages run through run_stage (harness.py:103-111).
  4. load_policy, load_ruleset, assert_rules_resolve (cli.py:634-638); _load_static_hints (cli.py:1037); preprocess_repository (cli.py:641-644).
  5. analyze_entry_points, attach_reachability_hints (cli.py:656-659); provenance.fingerprint (cli.py:660, provenance.py:66).
  6. rank_targets, calibrate_rankings (cli.py:661-666).
  7. Standard: run_hunter_pool (cli.py:667-673) = thread pool of quick_scan_findings (hunter.py:103-160). Quick/deep: quick_scan_findings directly (cli.py:674-687).
  8. write_findings (cli.py:708); verify_findings deterministic (verification.py:73-123, cli.py:711); _persist_calibration_feedback (cli.py:1011).
  9. Fusion only when standard and enabled: fuse_findings (cli.py:720-726, fusion.py:191); decisions do not change findings.
  10. Scoring: build_score_artifact → score.json (cli.py:731-746); record_completed(STATIC) (cli.py:747).
  11. MAP (cli.py:757-835): build_complexity_map (758), load_facts (769), overlay adjudicate (774), _check_obligations (789, 1388), _run_model_layer (804, 1286-1347), _attach_tool_hunter if hunter_model set (816, 962-1008).
  12. Deep adds REGRESS (cli.py:839-880): sandbox probe → run_regression → write_verdicts, persist_verdicts. Deep skips fusion (cli.py:720).
  13. write_markdown_report (886), write_sarif_report (905), write_manifest (915); scan_exit_code (reports.py:281-296).
flowchart TD
  A[main/_main<br/>cli.py:126] --> B[parse scan args<br/>cli.py:226]
  B --> C[_scan<br/>cli.py:613] --> D[_run_scan<br/>cli.py:619] --> E[plan_for_mode<br/>stages.py:28]
  E --> F[create_scan_run<br/>run.py:18] --> G[HarnessRuntime + write_harness_config<br/>cli.py:627]
  G --> H[load_policy / load_ruleset<br/>cli.py:634] --> I[_load_static_hints<br/>cli.py:1037]
  I --> J[preprocess_repository<br/>cli.py:641] --> K[analyze_entry_points<br/>cli.py:656]
  K --> L[fingerprint<br/>provenance.py:66] --> M[rank_targets + calibrate_rankings<br/>cli.py:661]
  M --> N{mode == standard<br/>cli.py:667}
  N -- standard --> O[run_hunter_pool<br/>hunter.py:103]
  N -- quick/deep --> P[quick_scan_findings<br/>findings.py:45]
  O --> Q[write_findings<br/>cli.py:708]
  P --> Q
  Q --> R[verify_findings<br/>verification.py:117] --> S[_persist_calibration_feedback<br/>cli.py:1011]
  S --> T{standard and fusion.enabled<br/>cli.py:720}
  T -- yes --> U[fuse_findings<br/>fusion.py:191] --> V
  T -- no --> V[build_score_artifact<br/>cli.py:732]
  V --> W{MAP requested<br/>cli.py:757}
  W -- quick --> AC
  W -- standard/deep --> X[build_complexity_map<br/>cli.py:758] --> Y[adjudicate overlay<br/>cli.py:774]
  Y --> Z[_check_obligations<br/>cli.py:1388] --> AA[_run_model_layer<br/>cli.py:1286] --> AB[_attach_tool_hunter<br/>cli.py:962]
  AB --> AR{REGRESS requested<br/>cli.py:839}
  AR -- deep, sandbox ok --> AS[run_regression<br/>cli.py:856] --> AC
  AR -- no --> AC[write_markdown_report<br/>cli.py:886]
  AC --> AD[write_sarif_report<br/>cli.py:905] --> AE[write_manifest<br/>cli.py:915] --> AF[scan_exit_code<br/>reports.py:281]

Side effects

Run dir <target>/<runs_dir>/<scan_id>/: resolved_config.json (run.py:24), harness.json (cli.py:632), trace/events.jsonl (harness.py:76), mapping/static_hints.json and entry_points.json (cli.py:640, 657), preprocess/file_targets.json, rank/ranking.json, calibration/*.json, shadow_findings.json, findings.json (rewritten up to 6 times: cli.py:708, 788, 801, 814, 877, 1005), traces/hunter_trajectories.jsonl, verification.json, fusion.json, score.json, complexity_map.json, overlay.json, verdicts.json, report.md, report.sarif, manifest.json. Into the scanned repo itself: .openultrasast/calibration/false_positive_learnings.json (cli.py:1021) and complexity_ledger.json (cli.py:765, 872). Subprocesses: git log (provenance.py:102-108), Joern via JoernBackend (cpg/backend.py:1817), Docker in deep mode (sandbox/runner.py:64). Model calls: scan_repository with resolve_chat_endpoint (cli.py:1321-1336), adjudicate_intent with resolve_hunter_client (cli.py:1450), run_tool_hunter (cli.py:976-989).

External dependencies

Core: preprocess_repository (cli.py:643), load_ruleset (637), load_policy (634), analyze_entry_points (656), rank_targets (661), quick_scan_findings (677). Engine: resolve_cpg_backend (1309), regions_for (1315), coverage_rows (1323), scan_repository (1333). Semantic: load_facts (770), adjudicate (777), check_obligations (1426-1450), filter_promoted_hotspots (847). LLM hunter: run_tool_hunter (976-982). Complexity: build_complexity_map (760). Sandbox/regress: resolve_sandbox_runner (845), run_regression (858).

Never touched by the scan path (removal candidates)

  • calibration.compute_ranking_metrics (calibration.py:108): only tests/test_calibration.py.
  • findings.build_quick_hunter_prompt (findings.py:102): only tests/test_findings.py.
  • verification.validate_evidence_transition (verification.py:39): only tests/test_verification.py.
  • fusion.should_fuse (fusion.py:94): only in __all__.
  • Processor machinery in harness.py (Processor, ProcessorSpec, _run_processor, _contract_violation, harness.py:41-55, 125-166): the runtime is always built with no processors (cli.py:627-632).
  • fusion.json decisions never feed findings or score; the quick-rule fallback to PATTERN_RULES (findings.py:55-56) never triggers from the CLI.
  • Kept: profiling.py is opt-in by env var (profiling.py:40-42).

Likely bugs (statement order, unconfirmed)

Scoring (cli.py:732) and verification (cli.py:711) run before MAP (cli.py:757), so MAP findings are absent from score.json and unverified, which affects --fail-on verified. Deep skips fusion (cli.py:720). A stage exception aborts with no report (harness.py:107-109).

Confidence

High for cli.py:613-959 and stages.py; medium for side effects inside other units (not read here).