{
  "checker": {
    "claims": [
      {
        "claim": "Each run discovers devices on the LAN and checks TCP ports, then writes a plain-English report",
        "command": "python3 netguard.py --config <guest-path>",
        "evidence": "Observed device at <internal-ip>: 22. Next step: review these ports and the device owner.\n\n## Coverage\n\n- Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources.\n- Local model triage is unavailable. Next step: check the model service; the findings below still apply.\n\nProposed actions require human review. No actions executed.\n\nPhone notifications are disabled.\n\n",
        "expected": "report lists the observed device with its open port",
        "input": "config <guest-path> (lan <internal-ip>/24, ports 1-1024 and listed ports, fresh output_dir)",
        "kind": "claim",
        "outcome": "Real input produced the expected result: Observed device at <internal-ip>: 22",
        "returncode": 1,
        "source": "Each run discovers devices on your LAN, checks an explicit list of TCP ports,",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      },
      {
        "claim": "The baseline is never promoted automatically; a fresh run with no approved baseline says so",
        "command": "python3 netguard.py --config <guest-path>",
        "evidence": "No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference.\n- Observed device at <internal-ip>: 22. Next step: review these ports and the device owner.\n\n## Coverage\n\n- Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources.\n- Local model triage is unavailable. Next step: check the model service; the findings below still apply.\n\nProposed actions require human review. No actions executed.\n\nPhone notifications are disabled.\n\n",
        "expected": "report states no approved network reference exists",
        "input": "config <guest-path> (fresh output_dir, no approve-baseline run)",
        "kind": "claim",
        "outcome": "Real input produced the expected result: No approved network reference exists.",
        "returncode": 1,
        "source": "The baseline is an explicit snapshot and is never promoted automatically.",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      }
    ],
    "cycle_checks": [
      {
        "claim": "A scheduled netguard run executes the scanner with a config every 30 minutes",
        "command": "python3 netguard.py --config <guest-path>",
        "evidence": "# Attention needed\n\nNetguard 20261027T121308.934903Z\n\n- No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference.\n- Observed device at <internal-ip>: 22. Next step: review these ports and the device owner.\n\n## Coverage\n\n- Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources.\n- Local model triage is unavailable. Next step: check the model service; the findings below still apply.\n\nProposed actions require human review. No actions executed.\n\nPhone notifications are disabled.",
        "expected": "one complete scan cycle writes a report reporting the observed device",
        "input": "config <guest-path> (fresh output_dir <guest-path>, no systemd or /opt install)",
        "kind": "cycle",
        "method": "run-once: manual invocation of the same netguard.service ExecStart command (with a fresh config path) instead of waiting for systemd",
        "outcome": "Triggered one cycle by hand (run-once: manual invocation of the same netguard.service ExecStart command (with a fresh config path) instead of waiting for systemd; normal trigger: systemd timer fires netguard.service 30 minutes after each completed run): # Attention needed\n\nNetguard 20261027T121308.934903Z\n\n- No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference.\n- Observed device at <internal-ip>: 22. Next step: review these ports and the device owner.\n\n## Coverage\n\n- Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources.\n- Local model triage is unavailable. Next step: check the model service; the findings below still apply.\n\nProposed actions require human review. No actions executed.\n\nPhone notifications are disabled.",
        "returncode": 1,
        "schedule": "systemd timer fires netguard.service 30 minutes after each completed run",
        "source": "systemd/netguard.timer",
        "verdict": "yes"
      }
    ],
    "details": {
      "argv": [
        "python3",
        "netguard.py",
        "--config",
        "<guest-path>"
      ],
      "kind": "cli",
      "needs_browser": false,
      "needs_credentials": false,
      "returncode": 1,
      "scope": "product operation",
      "stderr": "",
      "stdout": "# Attention needed\n\nNetguard 20261027T121129.382613Z\n\n- No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference.\n- Observed device at <internal-ip>: 22. Next step: review these ports and the device owner.\n\n## Coverage\n\n- Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources.\n- Local model triage is unavailable. Next step: check the model service; the findings below still apply.\n\n[excerpt truncated]",
      "working": true
    },
    "evidence_strength": "readme_checked",
    "example_checks": [
      {
        "claim": "Run unit tests with python3 -m unittest discover -s tests -v",
        "command": "python3 -m unittest discover -s tests -v",
        "deferred": false,
        "evidence": "known_fields_never_appear_in_markdown (test_netguard.PersistenceTests.test_report_unknown_fields_never_appear_in_markdown) ... ok\ntest_config_rejects_scope_and_options (test_netguard.ScopeTests.test_config_rejects_scope_and_options) ... ok\ntest_discovery_excludes_offline_inventory_and_scan_is_bounded (test_netguard.ScopeTests.test_discovery_excludes_offline_inventory_and_scan_is_bounded) ... ok\ntest_xml_diff_and_closed_only_host (test_netguard.ScopeTests.test_xml_diff_and_closed_only_host) ... ok\n\n----------------------------------------------------------------------\nRan 37 tests in 7.248s\n\nOK",
        "expected": "all 37 unit tests pass",
        "input": "repository tests directory",
        "kind": "example",
        "outcome": "command completed successfully",
        "returncode": 0,
        "source": "README.md Quick start step 4",
        "verdict": "yes"
      }
    ],
    "status": "PASS"
  },
  "deviations": [
    "nmap was not installed in the guest; installed with sudo apt-get -o DPkg::Lock::Timeout=300 install -y nmap (nmap 7.94SVN).",
    "First scan used lan_cidr <internal-ip>/20 (guest address <internal-ip> in /20). Discovery reported 'Local network discovery failed' with 0 hosts because the nmap -sn sweep of 4094 addresses hit the 90-second limit in netguard.py. Narrowed lan_cidr to <internal-ip>/24 and reran; discovery then completed.",
    "config.example.json hosts (192.168.1.x) and /var/lib/netguard output_dir were replaced with the guest's own address and a /tmp output directory, since the README's Quick start does not require the example addresses.",
    "Probes, claims and cycle runs use separate fresh configs in <guest-path> with fresh output_dirs under <guest-path> so replay does not reuse the approved baseline.",
    "Cycle: the systemd timer (netguard.service every 30 min) was not installed; one cycle was triggered by hand using the same ExecStart command with a fresh config.",
    "Local model triage was unavailable (Ollama not installed), so reports say so; the README states findings still apply.",
    "Notifications disabled (no ntfy topic). DNS checks not exercised (no dns_hosts).",
    "verify_live.py (README Live verification) was not run; it would listen on TCP 47653 and needs extra setup."
  ],
  "fault_owner": null,
  "main_blocker": null,
  "operation": "Run a local network scan with netguard.py, review the report, and approve the baseline; then rescan and confirm no new findings",
  "operation_scope": "Single host on a /24 LAN (<internal-ip>/24), discovery plus TCP port check of 1-1024,3389,5432,6379,8080,8443,11434, Python 3.12.3 standard library, nmap 7.94. Local model triage (Ollama), DNS/AdGuard, ntfy notifications, and systemd installation were not set up (optional in the README).",
  "outcome": "working",
  "plain_failure": null,
  "steps": [
    "sudo apt-get -o DPkg::Lock::Timeout=300 install -y nmap",
    "python3 -m unittest discover -s tests -v",
    "Copy config.example.json to config.json and edit it (lan_cidr <internal-ip>/24, hosts server=<internal-ip>, local_host server, empty dns_hosts/optional_hosts, output_dir absolute)",
    "python3 netguard.py --config config.json",
    "python3 netguard.py --config config.json --approve-baseline",
    "python3 netguard.py --config config.json"
  ],
  "stuck_step": null,
  "suggested_fix": "None required for the documented operation. For full coverage: install Ollama with the model dolphin3:8b, configure ntfy and DNS hosts if wanted, and widen lan_cidr only with enough nmap time (the /20 sweep exceeds the 90-second discovery limit in netguard.py)."
}
