{
  "checker": {
    "claims": [
      {
        "claim": "One-command CLI crawl exits non-zero when the crawl finds errors at that severity",
        "command": "<guest-path> main.py --crawl https://example.com --fail-on error --report <guest-path>",
        "evidence": "FAILED: 4 issue(s) at severity 'error' or worse\n  [error] Missing Meta Description - https://example.com/\n  [error] Missing H1 Tag - https://example.com/\n  [error] No Structured Data - https://example.com/\n  [error] Sitemap File Error - https://example.com/sitemap.xml\n",
        "expected": "exit code 1 and a FAILED line listing the error count",
        "input": "python main.py --crawl https://example.com --fail-on error --report <guest-path>",
        "kind": "claim",
        "outcome": "Real input produced the expected result: FAILED: 4 issue(s) at severity 'error' or worse",
        "returncode": 1,
        "source": "Exits non-zero when the crawl finds an open issue at that severity or worse, so",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      },
      {
        "claim": "Findings returned over MCP carry the same shape with the finding details",
        "command": "<guest-path> main.py --local --port 5058 tools/call {\"tool\": \"list_issues\", \"arguments\": {\"crawl_id\": 1, \"limit\": 5}}",
        "evidence": "Page has no H1 heading\\\",\\n      \\\"evidence\\\": {},\\n      \\\"how_to_fix\\\": \\\"\\\",\\n      \\\"docs_url\\\": \\\"/checks#missing_h1\\\",\\n      \\\"first_seen_crawl\\\": 1,\\n      \\\"status\\\": \\\"open\\\",\\n      \\\"accepted_reason\\\": null\\n    },\\n    {\\n      \\\"id\\\": \\\"df360f6877b6219dd2945bf98b4b9f12eca0a24d\\\",\\n      \\\"url\\\": \\\"https://example.com/\\\",\\n      \\\"check\\\": \\\"missing_meta_description\\\",\\n      \\\"type\\\": \\\"error\\\",\\n      \\\"category\\\": \\\"SEO\\\",\\n      \\\"issue\\\": \\\"Missing Meta Description\\\",\\n      \\\"details\\\": \\\"Page has no meta description\\\",\\n      \\\"evidence\\\": {},\\n      \\\"how_to_fix\\\": \\\"\\\",\\n",
        "expected": "the missing H1 finding with its details text",
        "input": "{\"tool\": \"list_issues\", \"arguments\": {\"crawl_id\": 1, \"limit\": 5}}",
        "kind": "claim",
        "outcome": "Real input produced the expected result: Page has no H1 heading",
        "source": "Every finding, wherever it surfaces \u2014 UI, API, export, MCP \u2014 carries the same",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      }
    ],
    "cycle_checks": [
      {
        "claim": "Standing crawls run on a schedule without opening the UI",
        "command": "",
        "evidence": "Not run: the scheduler runs only inside the long-lived server process (main.py _start_scheduler). Its only trigger is Scheduler.tick(now) called from a background loop, and there is no documented one-shot command or CLI to trigger one cycle. Triggering it needs a stored standing-crawl job plus a fake clock wrapper, which was not built in this run.",
        "expected": "",
        "input": "",
        "kind": "cycle",
        "method": "",
        "outcome": "Not run: the scheduler runs only inside the long-lived server process (main.py _start_scheduler). Its only trigger is Scheduler.tick(now) called from a background loop, and there is no documented one-shot command or CLI to trigger one cycle. Triggering it needs a stored standing-crawl job plus a fake clock wrapper, which was not built in this run.",
        "schedule": "",
        "source": "src/core/scheduler.py",
        "verdict": "blocked"
      }
    ],
    "details": {
      "argv": [
        "<guest-path>",
        "main.py",
        "--local",
        "--port",
        "5058"
      ],
      "hosting": "local",
      "kind": "mcp_http",
      "protocolVersion": "2025-06-18",
      "scope": "remote hosted MCP initialize + tools/list",
      "serverInfo": {
        "name": "toadstone",
        "version": "1.0.0"
      },
      "tool_result": {
        "content": [
          {
            "text": "{\n  \"crawl_id\": 1,\n  \"total\": 16,\n  \"offset\": 0,\n  \"count\": 5,\n  \"by_severity\": {\n    \"error\": 4,\n    \"warning\": 1\n  },\n  \"by_check\": {\n    \"missing_canonical\": 1,\n    \"missing_h1\": 1,\n    \"missing_meta_description\": 1,\n    \"no_structured_data\": 1,\n    \"sitemap_file_error\": 1\n  },\n  \"issues\": [\n    {\n      \"id\": \"6bd8aa5a38cc4ea7df918d053682b4f530adecca\",\n      \"url\": \"https://example.com/\",\n      \"check\": \"missing_h1\",\n      \"type\": \"error\",\n      \"category\": \"SEO\",\n      \"issue\": \"Missing H1 Tag\",\n      \"details\": \"Page has no H1 heading\",\n      \"evidence\": {},\n      \"how_to_fix\": \"\",\n      \"docs_url\": \"/checks#missing_h1\",\n      \"first_seen_crawl\": 1,\n      \"status\": \"open\",\n      \"accepted_reason\": null\n    },\n    {\n      \"id\": \"df360f6877b6219dd2945bf98b4b9f12eca0a24d\",\n      \"url\": \"https://example.com/\",\n      \"check\": \"missing_meta_description\",\n      \"type\": \"error\",\n      \"category\": \"SEO\",\n      \"issue\": \"Missing Meta Description\",\n      \"details\": \"Page has no meta description\",\n      \"evidence\": {},\n      \"how_to_fix\": \"\",\n      \"docs_url\": \"/checks#missing_meta_description\",\n      \"first_seen_crawl\": 1,\n      \"status\": \"open\",\n      \"accepted_reason\": null\n    },\n    {\n      \"id\": \"c1e37dec7818a900afe6dee2e183bac133f245f8\",\n      \"url\": \"https://example.com/\",\n      \"check\": \"no_structured_data\",\n      \"type\": \"error\",\n      \"category\": \"Structured Data\",\n      \"issue\": \"No Structured Data\",\n      \"details\": \"Page has no JSON-LD or Schema.org markup\",\n      \"evidence\": {},\n      \"how_to_fix\": \"\",\n      \"docs_url\": \"/checks#no_structured_data\",\n      \"first_seen_crawl\": 1,\n      \"status\": \"open\",\n      \"accepted_reason\": null\n    },\n    {\n      \"id\": \"75d7f5db156cc9f2d9ea93d393e19c8e3ad4b3d0\",\n      \"url\": \"https://example.com/sitemap.xml\",\n      \"check\": \"sitemap_file_error\",\n      \"type\": \"error\",\n      \"category\": \"Sitemap\",\n      \"issue\": \"Sitemap File Error\",\n      \"details\": \"Sitemap file could not be read (HTTP 404).\",\n      \"evidence\": {\n        \"found\": \"HTTP 404\"\n      },\n      \"how_to_fix\": \"Serve every sitemap file listed in robots.txt and in the index with HTTP 200 and valid XML.\",\n      \"docs_url\": \"/checks#sitemap_file_error\",\n      \"first_seen_crawl\": 1,\n      \"status\": \"open\",\n      \"accepted_reason\": null\n    },\n    {\n      \"id\": \"e591c0dddfb515c96c2e57f5b893c3326f65f12b\",\n      \"url\": \"https://example.com/\",\n      \"check\": \"missing_canonical\",\n      \"type\": \"warning\",\n      \"category\": \"Technical\",\n      \"issue\": \"Missing Canonical URL\",\n      \"details\": \"Page has no canonical URL specified\",\n      \"evidence\": {},\n      \"how_to_fix\": \"\",\n      \"docs_url\": \"/checks#missing_canonical\",\n      \"first_seen_crawl\": 1,\n      \"status\": \"open\",\n      \"accepted_reason\": null\n    }\n  ]\n}",
            "type": "text"
          }
        ],
        "isError": false
      },
      "tool_result_checked": true,
      "tool_schema_bytes": 6572,
      "tools": [
        "list_crawls",
        "crawl_status",
        "start_crawl",
        "list_issues",
        "issue_detail",
        "page_detail",
        "regression_diff",
        "export_dataset",
        "check_reference",
        "accept_issue"
      ],
      "transport": "streamable-http",
      "url": "http://127.0.0.1:5058/api/mcp",
      "working": true
    },
    "evidence_strength": "readme_checked",
    "example_checks": [
      {
        "claim": "Fixture coverage sweep runs the real crawler over six broken-site modes",
        "command": "",
        "deferred": true,
        "evidence": "Deferred on purpose: python tools/coverage_sweep.py runs about six full crawls of a local fixture site, a long run outside this check. The one-command CLI crawl and the MCP list_issues call were run instead.",
        "expected": "documented command completes successfully",
        "input": "",
        "kind": "example",
        "outcome": "Deferred on purpose: python tools/coverage_sweep.py runs about six full crawls of a local fixture site, a long run outside this check. The one-command CLI crawl and the MCP list_issues call were run instead.",
        "source": "README.md",
        "verdict": "deferred"
      }
    ],
    "status": "PASS"
  },
  "deviations": [
    "Skipped the README Chromium browser-setup step because browser downloads are forbidden; the crawl ran without JS rendering.",
    "The shared CDP endpoint is not used by the product, which launches its own Chromium via Playwright.",
    "The one-command crawl does not write a database row, so MCP could not see it. Used the documented /api/start_crawl route to create crawl 1 for MCP reads.",
    "MCP probe uses mcp_http with the app as its server argv, because the checker stops servers before replay.",
    "tools/coverage_sweep.py was not run; deferred as a long multi-crawl run.",
    "Scheduler cycle not triggered: no documented one-shot entry point."
  ],
  "fault_owner": null,
  "main_blocker": null,
  "operation": "Crawl a site from the command line with --fail-on error and --report, then read its findings back through the MCP server (list_issues)",
  "operation_scope": "Python 3.12.3 venv with requirements.txt; outbound HTTPS to example.com; local app on a loopback port. No Chromium or JS rendering. The shared CDP endpoint was reachable but the product does not use CDP.",
  "outcome": "working",
  "plain_failure": null,
  "steps": [
    "git init; git remote add origin https://github.com/spcaeo/toadstone; git fetch --depth 1 origin 4841d0bb9faba944661217542f13710582c66bbc; git reset --mixed FETCH_HEAD",
    "python3 -m venv <guest-path> and pip install -r requirements.txt into it",
    "venv python main.py --crawl https://example.com --fail-on error --report <file>",
    "venv python main.py --local --port 5058 (background, for MCP/API)",
    "POST /api/start_crawl then poll /api/crawl_status until complete",
    "MCP HTTP /api/mcp tools/call list_issues crawl_id 1 (probe)"
  ],
  "stuck_step": null,
  "suggested_fix": "Optional: have the CLI --crawl path persist its crawl so MCP/API can list it. The README browser-setup step needs a browser download, which the guest disallowed."
}
