{
 "tool": "hostinger",
 "raw_files": [
  "raw/hostinger_lab2.txt",
  "raw/hostinger_lab2-clean.txt"
 ],
 "reach": {
  "fetched_paths": [
   "/",
   "/robots.txt",
   "/llms.txt",
   "/services",
   "/.well-known/mcp/server-card.json (404)",
   "/__agent-readiness-probe-* (404 probe)",
   "/unavailable (after ClaudeBot 302)",
   "/assets/*, /img/* (headless render)",
   "(clean only: /sitemap.xml)"
  ],
  "agents": [
   "Hostinger-Web2Agent/1.0 (incl. Accept: text/markdown)",
   "ClaudeBot/1.0 (302 -> /unavailable)",
   "HeadlessChrome 155 render"
  ],
  "reach_classes": "home: D1 I5 J2 L1 P5 S1 S2 S3 S4 S5 S6 T1 T4; files fetched: robots, llms; no fault-bearing subpage fetched"
 },
 "faults": {
  "R1": {
   "v": "caught",
   "quote": "AI crawlers are not blocked 6/7 — What we found: \"Blocked by robots.txt: ClaudeBot.\"",
   "where": "Crawl permission (read with only that row open, so attribution is reliable)"
  },
  "R2": {
   "v": "missed"
  },
  "R3": {
   "v": "missed"
  },
  "R4": {
   "v": "missed"
  },
  "R5": {
   "v": "missed"
  },
  "R6": {
   "v": "partial",
   "quote": "Declared: /sitemap.xml. ... The sitemap probe could not be completed, so this could not be assessed.",
   "where": "sitemap rows (\"Not checked\"). Log: no sitemap request on lab2, /sitemap.xml fetched on clean. Symptom visible and the relative value shown, but \"Sitemap declared in robots.txt 3/3\" credits the faulty line and never says it must be absolute."
  },
  "R7": {
   "v": "missed"
  },
  "S1": {
   "v": "missed"
  },
  "S2": {
   "v": "missed"
  },
  "S3": {
   "v": "missed"
  },
  "S4": {
   "v": "wrong",
   "quote": "Not blocked by bot detection 6/6 pts",
   "where": "Crawl permission. Its own ClaudeBot probe got 302 -> /unavailable (\"This page is unavailable.\"), a UA-based block, yet the row passes with full marks. Doubt: no \"What we found\" text could be attributed to this row, so the probe feeding it may have been its own Web2Agent UA only.",
   "note": "Verifier: the tool's only crawler probe on lab2 was one ClaudeBot fetch (302 to /unavailable, per the lab log), which can only feed this row."
  },
  "S5": {
   "v": "missed"
  },
  "S6": {
   "v": "missed"
  },
  "S7": {
   "v": "unreached"
  },
  "I1": {
   "v": "unreached"
  },
  "I2": {
   "v": "unreached"
  },
  "I3": {
   "v": "unreached"
  },
  "I4": {
   "v": "unreached"
  },
  "I5": {
   "v": "missed"
  },
  "I6": {
   "v": "unreached"
  },
  "I7": {
   "v": "unreached"
  },
  "J1": {
   "v": "wrong",
   "quote": "Prices are reachable without JavaScript or login 4/4 ... A pricing page is linked from the homepage.",
   "where": "Commercial legibility. The log shows it never fetched /pricing, where prices exist only after JavaScript (\"Loading prices…\"); it asserted the opposite from a link alone. Counted wrong but NOT counted as reached."
  },
  "J2": {
   "v": "missed"
  },
  "J3": {
   "v": "unreached"
  },
  "J4": {
   "v": "unreached"
  },
  "J5": {
   "v": "unreached"
  },
  "J6": {
   "v": "unreached"
  },
  "D1": {
   "v": "caught",
   "quote": "No valid JSON-LD found on the homepage.",
   "where": "\"JSON-LD structured data is present 0/6\". Says no VALID JSON-LD (true), unlike \"no JSON-LD found\". Statement taken from the expanded-row set; it can only belong to the JSON-LD rows."
  },
  "D2": {
   "v": "unreached"
  },
  "D3": {
   "v": "unreached"
  },
  "D4": {
   "v": "unreached"
  },
  "D5": {
   "v": "unreached"
  },
  "D6": {
   "v": "unreached"
  },
  "D7": {
   "v": "unreached"
  },
  "M1": {
   "v": "caught",
   "quote": "llms.txt is missing a top-level \"# \" heading.",
   "where": "\"llms.txt is well-formed 1/3\""
  },
  "M2": {
   "v": "missed"
  },
  "M3": {
   "v": "unreached"
  },
  "M4": {
   "v": "unreached"
  },
  "M5": {
   "v": "unreached"
  },
  "X1": {
   "v": "unreached"
  },
  "X2": {
   "v": "unreached"
  },
  "X3": {
   "v": "unreached"
  },
  "X4": {
   "v": "unreached"
  },
  "X5": {
   "v": "unreached"
  },
  "X6": {
   "v": "unreached"
  },
  "L1": {
   "v": "missed"
  },
  "L2": {
   "v": "unreached"
  },
  "L3": {
   "v": "unreached"
  },
  "L4": {
   "v": "unreached"
  },
  "L5": {
   "v": "unreached"
  },
  "L6": {
   "v": "unreached"
  },
  "L7": {
   "v": "unreached"
  },
  "P1": {
   "v": "unreached"
  },
  "P2": {
   "v": "unreached"
  },
  "P3": {
   "v": "unreached"
  },
  "P4": {
   "v": "unreached"
  },
  "P5": {
   "v": "missed"
  },
  "P6": {
   "v": "unreached"
  },
  "P7": {
   "v": "unreached"
  },
  "T1": {
   "v": "missed"
  },
  "T2": {
   "v": "unreached"
  },
  "T3": {
   "v": "unreached"
  },
  "T4": {
   "v": "missed"
  }
 },
 "score": {
  "caught": 3,
  "partial": 1,
  "points": 3.5,
  "wrong": 2,
  "reached": 23,
  "points_of_reached": 0.152,
  "pct_of_63": 5.6
 },
 "clean": {
  "false_alarms": [],
  "advisories": [
   {
    "claim": "no Content-Signal",
    "quote": "Content Signals declared 0/3",
    "why": "true; emerging/optional"
   },
   {
    "claim": "no markdown negotiation",
    "quote": "Serves Markdown when an agent asks for it 0/2",
    "why": "true; optional"
   },
   {
    "claim": "no Link headers",
    "quote": "Homepage advertises resources via Link headers 0/1",
    "why": "true; optional"
   },
   {
    "claim": "no WebMCP",
    "quote": "Site exposes WebMCP tools to in-browser agents 0/6",
    "why": "true; emerging"
   },
   {
    "claim": "no MCP card",
    "quote": "MCP Server Card is published 0/4",
    "why": "true (404); emerging"
   },
   {
    "claim": "few schema types",
    "quote": "Structured data covers several schema types 1/2",
    "why": "true (LocalBusiness + PostalAddress only); optional"
   }
  ]
 },
 "other_false_claims_lab2": [
  {
   "claim": "No sameAs in structured data",
   "quote": "No sameAs links in the structured data.",
   "note": "Not counted as a false alarm: a cascade of D1 (the only JSON-LD block, which does contain sameAs, does not parse). Listed so the cascade is visible."
  }
 ],
 "evidence_quality": {
  "score": 1,
  "why": "Findings are named (\"Blocked by robots.txt: ClaudeBot.\", missing \"# \" heading, no valid JSON-LD) without the rule, line, status code or raw response; observed values appear only on passing or advisory rows (byte counts, Content-Type for Accept: text/markdown)."
 },
 "strengths_not_scored": [
  "Actually tests markdown negotiation and reports the observed response: \"Homepage returned 'text/html; charset=utf-8' for Accept: text/markdown.\"",
  "Probes a random URL for a real 404 and checks for an MCP server card.",
  "Measures readable text in raw HTML: \"Raw HTML contains 1830 characters of readable text.\"",
  "Clean twin: zero false alarms; point losses there are all optional/emerging items."
 ],
 "notes": "Reached home + robots.txt + llms.txt (22 faults; /services carries no fault). Did not fetch sitemap on lab2 (blocked by R6 itself), security.txt, or /pricing. Two wrong verdicts: S4 (doubt noted) and J1 (a claim about a page it never fetched; wrong verdict, excluded from reached). The \"Not blocked by bot detection\" pass is also untrue at site level for PerplexityBot/GPTBot/Applebot, which it never probed; graded once, under S4. M2 missed: it did not fetch /warranty or /financing and the 2-point llms deduction is explained only by the missing heading."
}