///|
fn web_first_rules_section(topic : String) -> Array[String] {
  [
    "## Rules",
    "",
    "- Start with web discovery before local file discovery. Use native `web_search` when it is available.",
    web_first_native_search_rule(),
    web_first_command_discovery_rule(),
    "- Run at least three web queries for this topic.",
    web_first_source_depth_rule(),
    web_first_discovery_artifact_rule(),
    web_first_front_door_rule(),
    web_first_harvest_rule(),
    web_first_source_depth_blocker_rule(),
    web_first_authority_rule(topic),
    "- After search, inspect at least two highest-signal pages before writing conclusions. Use native `web_fetch` if available; otherwise use bounded command-line fetches.",
    web_first_result_page_rule(),
    "- Write durable notes into `\{@research_policy.search_log_path()}` and `\{@research_policy.source_screen_path()}` before inspecting the local repo.",
    web_first_local_rule(topic),
    "- If all web access paths are unavailable, write `\{@research_policy.tool_blockers_path()}` and continue only with clearly provisional evidence instead of silently skipping the phase.",
    "- Do not cite search snippets as verified evidence unless fetch is blocked and the source is clearly labeled provisional.",
    "- Do not mark a source page verified unless it contains inspected source content, extracted claims, and provenance.",
    "",
  ]
}

///|
fn web_first_native_search_rule() -> String {
  web_first_text([
    "- If native `web_search` or `web_fetch` is disabled, unavailable, stalls,",
    "returns only search-engine/redirect pages, or leaves the source base below",
    "\{@research_policy.min_included_sources()} included inspected sources, use bounded `execute_command` discovery",
    "such as `curl -L --max-time 12` against LLM-chosen search-result pages",
    "and candidate URLs before local file discovery.",
  ])
}

///|
fn web_first_command_discovery_rule() -> String {
  web_first_text([
    "- In command-line discovery mode, first write the planned",
    "query/source-screening strategy to `\{@research_policy.search_log_path()}`, then",
    "run a small bounded command batch. Do not spend a long model turn",
    "planning before the first durable write or command.",
  ])
}

///|
fn web_first_source_depth_rule() -> String {
  web_first_text([
    "- For comparative or technology-route research, try to cover at least",
    "\{@research_policy.min_included_sources()} high-signal sources across",
    "\{@research_policy.core_source_classes()} classes before",
    "synthesis. \{@research_policy.preferred_included_sources()} or more included sources is preferred for a 12k-15k",
    "dossier.",
  ])
}

///|
fn web_first_discovery_artifact_rule() -> String {
  web_first_text([
    "- Do not count search pages, site search pages, hub pages, or index pages",
    "as included evidence just because they were fetched. Use", "`discovery_only`, `candidate`, or `exclude` unless the page itself",
    "contains substantive inspected claims.",
  ])
}

///|
fn web_first_front_door_rule() -> String {
  web_first_text([
    "- Keep discovery bounded but serious. Do not stop below \{@research_policy.min_included_sources()} included",
    "inspected sources merely because generic search-result pages are blocked.",
    "First try source-class front-door discovery, domain sitemaps, on-site",
    "search/index pages, and link harvesting.",
  ])
}

///|
fn web_first_harvest_rule() -> String {
  web_first_text([
    "- When sitemap/front-door harvesting yields candidate content URLs:",
    "convert the harvest into inspected sources, fetch at least \{@research_policy.harvest_candidate_fetch_count()}",
    "high-signal candidates, or every harvested candidate when fewer than",
    "\{@research_policy.harvest_candidate_fetch_count()}, before declaring the source base thin.",
  ])
}

///|
fn web_first_source_depth_blocker_rule() -> String {
  web_first_text([
    "- Stop below \{@research_policy.min_included_sources()} included sources only after \{@research_policy.discovery_attempt_limit()} web/discovery",
    "attempts and an explicit source-depth blocker. In that case write",
    "`ready_for_12k_dossier: false` into `\{@research_policy.source_screen_path()}`.",
  ])
}

///|
fn web_first_result_page_rule() -> String {
  web_first_text([
    "- If native `web_search` returns only a search-engine URL or weak result", "page, fetch the result page with native fetch; if that cannot extract",
    "candidates, use `execute_command`/`curl`, extract candidates when", "possible, and retry query variants before writing a blocker.",
  ])
}

///|
fn web_first_authority_rule(topic : String) -> String {
  if is_external_domain_research_topic(topic) {
    web_first_text([
      "- Prefer reputable current coverage, primary-source pages,", "official/regulatory material, research reports, expert essays, and",
      "clearly dated news. Do not prefer code repositories unless the topic is",
      "actually a software project.",
    ])
  } else {
    "- Prefer authoritative pages: official docs, repo pages, maintainer docs, and project READMEs."
  }
}

///|
fn web_first_local_rule(topic : String) -> String {
  if is_external_domain_research_topic(topic) {
    web_first_text([
      "- Do not inspect a local repository by guessing from the topic name.", "Use local files only when explicitly listed in `SOURCE_HINTS.md` or",
      "when web evidence points to a concrete local artifact.",
    ])
  } else {
    "- Only then inspect the local repo to corroborate architecture, implementation, and file-level details."
  }
}