# Per-page coverage and reviewed facts

Run `coverage.py` with a finite watchlist and one dated observation file. It feeds only the facts linked to successfully acquired and specifically reviewed pages into the existing comparison/FAQ engine. It does not confuse a successful page read with review of all its statements.

```text
python coverage.py --input coverage-sample-15 --output next-coverage-15
python coverage.py --input coverage-sample-25 --output next-coverage-25
python -m unittest -v test_sales test_coverage
```

The sample scope supports up to3 named competitors and15 pages; the monthly scope supports up to5 and25. `configured_pages` is the denominator. The package capacity is shown separately. An entry omitted from the observation file becomes `not_attempted`, never unchanged. Each round is an explicit local command; no schedule, browser extension, paid monitor or external communication is created.

## Input contract

`targets.json` lists watchlist ID, scope_limit, page IDs, exact URLs, competitor/product identity, named fact IDs, acquisition method and rights basis. Stable page IDs cannot change product or URL when comparing with the previous round. Create a new target ID and document the scope change instead. A record of permission is not legal certification; assess the actual page/contract before obtaining or reusing data.

`observations.json` has one record per attempted target: status (`observed`, `failed`, `redirected` or `not_attempted`), observation time with timezone, HTTP status, source byte SHA-256 where acquired, named reviewer, fact-review state and reviewed fact IDs. Record source hashes from the acquired permitted page/export bytes; do not mirror full competitor pages in a client report. A redirect records its target but is not automatically followed or called a successful fact review. Failed/missing pages cannot supply fresh reviewed facts.

Fact-review states are `complete_for_named_facts`, `partial`, and `not_reviewed`. Complete means every fact ID expressly named for that target was checked. It never means the entire webpage was audited. New facts must match the reviewed observation's ID, product, URL and time. A supplied fact without that link is withheld and remains unknown for the current comparison. Unreviewed, missing or uncertain facts cannot support a proposed FAQ claim.

`old-facts.json`, `new-facts.json` and `customer-questions.json` use the existing `build_report.py` schemas and permission rules. The assistant obtains/reads permitted sources, records short relevant facts, performs the comparison and prepares the client's review draft. The client supplies its target priorities and authorized own-product statements; it is not expected to perform our whole research job. Paid white-label data has not been procured by this package.

## Next round without losing history

Keep each round input/output in a new dated folder. `next-round-template.json` prepopulates target identities and prior success hashes but resets every observation to not_attempted. `next-baseline-facts.json` retains last-known reviewed facts, including older facts for pages that failed this round; it is not evidence that those facts remain current. Copy it as the next round's old-facts.json. Pass `--previous PRIOR/coverage-report.json` when running the next round. The code checks identity and backwards observation times, compares content hashes, and keeps page-byte changes separate from reviewed fact changes.

A no-change conclusion is only called `no_named_fact_changes_with_complete_coverage` when all configured pages were acquired and all named fact sets reviewed. Otherwise the report explicitly says incomplete coverage. A first round with no old facts is baseline, not proof a feature was newly introduced. Hash equality proves only equal acquired bytes, not correctness or completeness of extracted facts.

## Actual records in this kit

The 15-page original fixture has12 successful page observations and11 complete named-fact reviews, plus one failed, one redirected and one missing page. The25-page fixture has22 observations and21 complete named-fact reviews with the same failure classes. These are synthetic test records, not real competitor coverage.

`owned-public-baseline/` and `owned-public-report/` record a real one-time read of3 first-party pages on workfolio-studio.pages.dev. Only response metadata, byte hashes and their short title strings are retained; raw HTML is not mirrored. The title strings were reviewed as those three named facts by the assistant, not by a client or independent analyst. These are our own public demonstration pages, not a client's competitors or a niche market case. All three succeeded on the recorded date; no future availability or monitoring cadence is promised.

Remaining client acceptance is bounded: agree3–5 actual competitors, their source/permission route, up to15/25 exact pages, the client's5/10 priority questions, and a reviewer for its own claims. Then run real dated rounds and check that the client finds the proposed updates useful. No real client, two-week client study, paid order, recurring monitor, FAQ publication or profit is represented by this completed local workflow.
