# Phase: Live corpus inventory (ACQUIRE_CORPUS)
Build a **complete, validated inventory** of every live Well-Architected
question and best practice **before any assessment begins**. `ASSESS` MUST NOT
start until the corpus validator passes.
## Retrieval mechanism
Prefer the AWS MCP server's documentation reader — `aws___read_documentation`
(call shape: `{"requests":[{"url": "...", "max_length": 100000}]}`) — when it is
available. When the AWS MCP server is unavailable, fetch the same
`docs.aws.amazon.com` URLs over HTTPS with the environment's web-fetch tool (the
TOC index below is plain JSON that any HTTPS fetch returns intact). If no
documentation access exists at all, enumerate from internal knowledge and disclose
that the inventory could not be verified live. Do not depend on any
non-public/internal MCP, and do not use semantic search to enumerate.
Two facts that determine the method (both verified live):
- The reader **strips markdown link targets** from HTML/MD pages, so you cannot
follow links between pages and MUST NOT guess or abbreviate page slugs.
- The framework publishes a machine-readable **table-of-contents index**, and the
reader returns it verbatim. This index is the corpus source.
## Primary source — the TOC index (one call)
Read the framework table of contents:
```
https://docs.aws.amazon.com/wellarchitected/latest/framework/toc-contents.json
```
It returns a JSON tree of the whole framework:
```json
{ "contents": [
{ "title": "Operational excellence", "href": "operational-excellence.html", "contents": [
{ "title": "OPS 1. How do you determine what your priorities are?", "href": "ops-01.html", "contents": [
{ "title": "OPS01-BP01 Evaluate external customer needs", "href": "ops_priorities_ext_cust_needs.html" },
{ "title": "OPS01-BP02 Evaluate internal customer needs", "href": "ops_priorities_int_cust_needs.html" }
] }
] }
] }
```
Walk the tree recursively. Classify each node by its `title` / `href` using
general patterns — do NOT hardcode the pillar prefixes, so any pillar AWS adds or
renames is picked up automatically:
- **Best-practice node** — `title` matches `^[A-Z]{2,5}\d{2}-BP\d{2}\b`.
Record: `bp_id` (the matched ID), `bp_title` (the remainder of the title),
`bp_url` (base + `href`), `question_id` (the `PILLAR##` prefix of the matched ID),
`pillar_id`/`pillar_name` (derived from the prefix and the enclosing pillar node's
title).
- **Question node** — `href` matches `^[a-z]{2,5}-\d{2}\.html$` (the lowercased
pillar stem plus question number). Record its `title` and `href` to enrich the
question's `question_title` and `question_url`.
Base for relative `href`s: `https://docs.aws.amazon.com/wellarchitected/latest/framework/`.
Notes:
- Derive the set of questions from the **BP prefixes** (every `SEC02-BP0x` implies
question `SEC02`); enrich each with the title/URL from its question node when
present. This is robust to the index listing best practices under both the pillar
and appendix branches — **dedupe best practices by `bp_id`**.
- Everything needed for the ledger (canonical IDs + titles + URLs + question mapping)
is in this one document. Do NOT read the individual best-practice pages here; fetch a
single best-practice page later (during assessment) only when its title is
insufficient to judge status or when writing a Critical/High recommendation.
## Immediate reduction (context discipline)
Parse the index into records in one pass and MUST NOT re-quote the raw index
afterward. Persist records as you go; do not narrate the tree.
## Records
Write one record per best practice to `corpus/best-practices.jsonl` and one per
question to `corpus/questions.jsonl`, in the run-local working directory you create at
the start of this stage (the `corpus/` folder — scratch state only, never part of the
delivered report). If that working directory is backed by persistent storage, ensure
encryption at rest is enabled (see [security considerations](security-considerations.md)).
Best-practice record (`wa-review.corpus.v1`):
```json
{
"schema_version": "wa-review.corpus.v1",
"pillar_id": "operational-excellence",
"pillar_name": "Operational Excellence",
"question_id": "OPS01",
"question_title": "OPS 1. How do you determine what your priorities are?",
"question_url": "https://docs.aws.amazon.com/wellarchitected/latest/framework/ops-01.html",
"bp_id": "OPS01-BP01",
"bp_title": "Evaluate external customer needs",
"bp_url": "https://docs.aws.amazon.com/wellarchitected/latest/framework/ops_priorities_ext_cust_needs.html",
"retrieved_at": "2026-09-08T12:00:00Z"
}
```
## Validation gate (must pass before ASSESS)
Write `corpus/manifest.json` with counts, per-pillar question counts, provenance
(index URL + UTC retrieval time), and a validation verdict. The validator MUST
confirm:
- Every pillar discovered in the TOC top-level entries is represented, and each
discovered pillar carries at least one best practice (do not assert a fixed pillar
count — a newly added pillar must not fail this check).
- Every BP ID matches canonical `PILLAR##-BP##`; BP IDs are unique after dedupe.
- Question IDs are unique; every question has at least one BP.
- Every BP refers to a discovered question and pillar.
- The global BP set equals the union of per-question BP sets.
- Provenance (index URL, retrieval time) is recorded; no stale/cached manifest is
silently reused as live content.
A parse that yields **zero** BP IDs, or fewer than a sanity floor, is an acquisition
failure — go to Recovery. **Never invent a BP ID to fill a gap.** As a **post-hoc
sanity check** recorded in the manifest, confirm each discovered pillar carries a
non-trivial number of best practices (> 0, with a plausible spread across pillars
rather than one pillar holding almost all of them) — do not pin the check to specific
question or BP totals. The parsed live index is the sole source of truth for the
inventory.
## Recovery (fallback traversal)
If `toc-contents.json` is unavailable (HTTP/parse error) or yields no best practices:
1. Retry the index read once.
2. If still failing, fall back to **construct-and-iterate** over question pages, which
the reader supports even though it strips links. First discover the current set of
pillar stems dynamically: read the framework `appendix` page (or the framework landing
page) and take the lowercased stem of each pillar it lists — do not start from a
hardcoded stem list, so a newly added pillar is still covered. Then, for each
discovered stem, read `-01`, `-02`, … (i.e. `-NN`), incrementing
until the page is missing — that missing page is the clean pillar boundary, wherever
it falls, so do not assume a fixed per-pillar question count. Each question page lists
its `PILLAR##-BP##` IDs as text; derive `question_id` from the BP prefix (not the
heading, which varies: `SEC 2.` vs `SUS 6`).
**The page suffix and the missing-page signal depend on the retrieval tool.** The
canonical pages are served as `.html` (e.g. `operational-excellence.html`, `ops-01.html`):
- **`aws___read_documentation`:** request the markdown-suffixed form the reader accepts
(verified live) — `appendix.md`, then `-NN.md` — and stop when a read
returns the reader's sentinel string `"Documentation page not found."`.
- **Non-MCP HTTPS web-fetch fallback:** request the canonical `.html` form —
`appendix.html`, then `-NN.html` (a plain HTTPS fetch of a `.md`
suffix 404s because the site serves `.html`) — and stop on an HTTP 404.
3. To relocate a specific moved page, use `aws___search_documentation` when the AWS MCP server is
available; otherwise use the environment's web-search tool scoped to `docs.aws.amazon.com` over
HTTPS; if neither is available, skip the relocated page and note the gap in the coverage audit.
Use this ONLY to relocate a moved page — never to supply BP IDs.
## Freshness
Read the index live for every review. Do not reuse a prior run's manifest as current
content unless the user explicitly authorizes a cache whose freshness policy is
disclosed in the coverage audit.
## Transition
`ACQUIRE_CORPUS -> ASSESS` only when `corpus/manifest.json` reports `valid: true`. The
frozen manifest is the sole authority for the expected question and BP sets used by
per-question validation, derivation, and the final report validator.