# Rule: External web source tags

ADR: [docs/adr/0011-web-source-tags-with-central-mapping.md](../docs/adr/0011-web-source-tags-with-central-mapping.md).

## When this applies

Working on ADRs or markdown under `docs/` that cite external web sources.

## Tags and mapping

| Item | Rule |
|------|------|
| Tag format | `[web:NNN]` — three-digit zero-padded sequential ID (`web:001`, `web:042`) |
| Registry | [docs/web-source-mapping.md](../docs/web-source-mapping.md) |
| Entry format | `### web:NNN — Human label` followed by one or more `- https://…` bullets |
| Canonical URL | **First** bullet under an entry is canonical for AI fetch; later bullets are alternates or supplements |
| Internal links | Keep normal relative markdown links for in-repo docs; do not replace with `[web:*]` |

## Authoring

- Do **not** inline raw external URLs when a `[web:NNN]` tag plus mapping entry is available.
- When introducing a new `[web:NNN]`:
  1. Search for an appropriate canonical URL (official docs, primary spec, or stable article).
  2. Allocate the next free sequential ID in the mapping file.
  3. Add the entry under an appropriate editorial section with label and URL(s).
  4. Use the tag inline in the ADR or doc.
- **Same commit** must include both the doc tag and the mapping entry.

## Soft adoption

- **New material** and **material edits that add external references** must use `[web:NNN]`.
- **Accepted ADRs** and existing docs may keep legacy inline URLs; do not bulk-convert without an explicit maintenance task.
- When fixing a broken external link on an Accepted ADR, prefer updating the mapping entry for an existing tag over rewriting ADR substance.

## Proposal intake (normalize on write)

External AI tools and pasted ADRs may arrive with footnotes (`[^1]`), raw URLs, non-sequential tags (`[web:3]`), or a **separate** mapping file. **Intake format ≠ stored format.**

Before committing into this repository:

1. Normalize body text to `[web:NNN]` per rules above.
2. Merge any sidecar URL list into `docs/web-source-mapping.md`.
3. Reuse existing mapping entries when the canonical URL already exists.
4. Same commit must include doc tags and mapping entries.
5. Run the checker (or optional `check-web-sources` pre-commit hook).

Do **not** require upstream tools to emit A2C format; the assistant normalizes at the git boundary. Process prompt: [prompts/phases/adr-create-update.md](../prompts/phases/adr-create-update.md).

## Pre-commit / CI

Before committing doc changes:

1. Run `python scripts/check_web_source_tags.py` (or rely on `workflow-docs:contract` in CI).
2. Optionally enable **`check-web-sources`** from [a2c-pre-commit-hooks](https://gitlab.com/libesys/ai-workflows/a2c-pre-commit-hooks) (`v0.3.0`+) when `docs/web-source-mapping.md` exists — local pre-commit guard for the same rules.
3. Fix **unmapped tags** (tag in doc, no mapping entry).
4. Fix **orphan mapping entries** (mapping entry not referenced in any scoped doc).

Treat `[web:*]` tags as part of the architecture log: they must resolve, and mappings live in version control alongside ADRs.

## Recovery mode

When `check_web_source_tags.py` fails, or the mapping file is incomplete or corrupted, run the **web source recovery** task ([prompts/maintenance/web-source-recovery.md](../prompts/maintenance/web-source-recovery.md)):

1. Scan scoped ADRs and docs for `[web:NNN]` tags.
2. List tags missing from `docs/web-source-mapping.md`.
3. For each unmapped tag, read nearby paragraph context to infer the topic and label.
4. Perform a targeted web search for a canonical URL (official docs, primary spec, or stable article).
5. Append proposed entries under a `## Proposed (recovery)` section at the end of the mapping file.
6. Present proposals to the human operator for review — **do not commit** until confirmed.

Recovery repairs **tag↔mapping consistency**. It does not:

- bulk-convert legacy inline URLs in Accepted ADRs (soft adoption);
- auto-commit search results without human confirmation;
- remove orphan mapping entries (fix those manually or delete unused entries).

After confirmation, move entries from `## Proposed (recovery)` into the appropriate editorial section, re-run `python scripts/check_web_source_tags.py`, then commit.
