Expedify AI Content Engine — build tracker

Plan v1.0 (signed 2026-09-02) · generated 2026-09-03 22:05 · refreshes every 5 min · redeploys when sources change (≤15 min) · status.json

What this is. A live status page for the Expedify content engine. The engine writes ready-to-build page files — facts verified against government and embassy sources, then human-approved — which the Expedify Astro build takes live. The engine never publishes by itself.

Current phasePhase B engine work complete pending human captures
Plan complete25 / 4654 % of the plan's checklist
Fee & time figures verified0 / 187target ≥ 95 % · 0 % toward target
Figures with a source lead94 %6 % have no lead — human source queue covers them
Driving-rule contradictions00 pages self-contradict · convention fix batches applied
Unclassified source sites0all source sites tiered

Needs your input

1 open decisions· Expedify / site25 files in staged fixes· John110 URL decisions· John700 Source money figures· Agency (us)4 Publish to live· Site devs551 live pages in the hotfix PR· Site devs

What the engine is waiting on — each chip counts rows that need a human and names the role that owns it. Open: Astro content-collection schema — requested 2026-09-02; which `m

Roles: Expedify / site = decisions and access from the client side · John = owner approvals · Agency (us) = our content operations team.

Phases

Phase A — Plan to v1.0 (no build)

Complete

7/9 steps

Steps
  • John answers v0.4 §8 open items 1–6 — DONE 2026-09-02: files-only; legal read = Expedify (we supply claim list); cap + short post-mortem; Expedify names reviewer; request Astro read access; prototype deleted
  • Fill v0.4 §9 numbers — DONE 2026-09-02 (cap 10/wk + 5 %; floor indexed+90d+200 impr; cohort 80/50/≤30; margin +15 % or −3 pos; review 8 min/25 pp/wk; Opus ≤20/wk; max-age 90/90/180/365; fail-closed fallbacks; 3 deferrals with triggers) — ADR 0005
  • Measurement source — direct GSC API via service account (Ahrefs = reference only); request added to developer requests §1b
  • Obtain Astro content-collection schema; record its field list in findings.md — moved to Phase C prerequisites (requested, pending Expedify)
  • Client PRD aligned to v1.0 (§6 post-mortem, §7 asks incl. GSC service account)
  • ADRs written in expedify docs/adr/: 0001 files-never-deploys, 0002 legal read = Expedify, 0003 cap + post-mortem, 0004 named reviewer (growth-cap numbers ADR waits on §9)
  • Developer requests drafted: docs/Expedify_Developer_Requests_2026-09-02.md (repo access, reviewer, legal sign-off, release safety, footprint, cap/cohort/conversion)
  • Send the requests to Expedify — John to forward docs/Expedify_Handover_Cover_Note_2026-09-03.md (decided 2026-09-03: Claude does not send client-facing mail; note is forward-ready)
  • John signs v1.0 → unfreeze (2026-09-02; file renamed to _v1.0.md)

Phase B — Truth layer (plan P1 → components C1)

In progress

started 2026-09-02 · 12/15 steps

Gate: ≥ 95 % of money figures carry a tier 1/2 source; remainder suppressed. Falsified otherwise → Phase D shrinks to sourced pages only.

Steps
  • Define facts: schema — DONE 2026-09-02 docs/content engine/facts.schema.json (tiers 0–3, statuses incl. not_stated, conditional source/second_source/sign_off requirements): {id, claim_type: fee|processing_time|eligibility|convention|validity, value, unit, source_url, authority_tier: 1 govt|2 embassy|3 aggregator, captured_at, max_age_days, verification_status, second_source_url?}; sections reference facts by {{fact:id}} instead of literal numbers
  • scripts/engine/extract_facts.py — DONE 2026-09-02, read-only, 745 pages → 7,521 candidates in data/facts/candidates/, report reports/facts-extraction-2026-09-02.md; 5 unit tests in tests/test_extract_facts.py. Money gate baseline: 3,316 fee facts = 1,658 first-party + 997 not_stated + 550 with a tier-1/2 candidate on page + 111 with none → 661 third-party figures need real sourcing
  • Independent challenge round 1 (12 findings: 3 blockers — empty convention DB, misleading gate arithmetic, tier heuristic; 7 majors) → INCORPORATED 2026-09-02: extractor v2 + schema v0.2 + data/facts/authority_registry.json (112 hosts) + 11 tests on real data. Gate baseline (v2.1): 187 distinct third-party money figures, 0 % captured, 92 % with a scoped lead, 8 % none. 25 convention disagreements (17 stale hubs + 8 self-contradicting driving guides)
  • Independent challenge round 2 → 4 majors + 4 minors (incl. 2 v2 regressions) → INCORPORATED (v2.1, 16 tests, every page schema-validated)
  • Round 3: all 8 confirmed fixed, verdict COMMIT; 3 follow-ups (money ranges, FAQ-question votes, 'in any N-day' windows, road-authority hosts) folded in → v2.2, 17 tests → COMMITTED + pushed 2026-09-02
  • Tier the unknown source hosts — DONE 2026-09-03: 127 hosts tiered (registry 112 → 224 hosts, ccTLD map 140), 0 unknown left; leads 92 % → 94 %, no-lead 11 figures; idaoffice.org registered as related property, never a source
  • Capture script scripts/engine/capture_facts.py — DONE 2026-09-03: fetches lead URLs (cached, polite, honest UA), matches value near a currency/unit marker, confidence = claim word nearby (weak matches never count). First full run: 21 hits / 546 fetches; money gate 0 → ~2 %; travel.state.gov + mofa.go.jp + immi.homeaffairs.gov.au block bots (403), VFS/moi.gov.ae are JS shells, most ministry leads are sections not fee pages
  • Human source queue scripts/engine/source_queue.pyreports/source-queue-2026-09-03.md (~180 figures grouped by lead host and failure reason: value_not_on_lead_page / blocked_403 / js_or_thin_page / no_lead / weak_match_confirm)
  • Source the candidates: convention facts from data/idp-countries-by-convention.json (audited 2026-08-30, tier 1 via UN treaty lists); fees/times from data/genuine_fees_*.json + VisaHQ matrix (tier 3 → needs tier 1/2 confirmation); everything else → human source queue card
  • scripts/engine/truth_gate.py — DONE 2026-09-03 (R1 provenance, R2 second source, R3 max-age, R4 disagreement; merges captures; per-page verdict PASS/HOLD/FAIL + corpus gate). First run: corpus gate NOT YET, 4/187 money figures sourced. Remaining design gap: the 'every rendered number has a fact id' check needs the facts block retrofit (step 7)
  • scripts/engine/staleness.py — DONE 2026-09-03: ages every dated claim vs §9 max-age, stages 1/2/3 (suppress figure = TODO until the {{fact:id}} retrofit / banner / noindex), stage 2-3 as staged whole-file copies under handoff/demotions-<date>/. Today: 0 stale; 271 fee facts fall due 2026-11, 762 in 2027-02, 1,527 in 2027-08 (the corpus's single last_verified date makes staleness arrive in waves — a reason to capture, not just re-date)
  • scripts/engine/source_watch.py — DONE 2026-09-03: watch list = 56 lead URLs that fetch cleanly (ranked by facts backed), sentence-level diff of numeric lines vs stored snapshot, aos-notify warning on change, report per run; weekly user timer expedify-source-watch.timer (Agentic-OS ops/systemd). Opens no W2 card yet (W2 not built)
  • Legal claim checklist (ADR 0002 deliverable) — DONE 2026-09-03: reports/legal-claim-checklist-2026-09-03.{md,csv}, 2,279 claims / 5 sections with provenance + blank sign-off columns. Expedify's reviewer signs; not yet sent
  • Retrofit run on the corpus; commit facts blocks in tranches (≤ 50 files per PR, playbook order: visa hubs → driving guides → country hubs → tuples)
  • Ledger: SYSTEM.md entry for the timer + scripts

Phase C — Contract + gates (plan P2 → C2, C3 single-brief, C4, C5, C9)

In progress

started 2026-09-03 · 6/10 steps

Gate: dry-run batch builds clean on the site; applied set == manifest.

Steps
  • docs/policies/corpus-admission.md + scripts/engine/admit_brief.py — DONE 2026-09-03 (T1–T7; first brief b-20260903-japan-driving-guide-refresh = HOLD awaiting approver). Original: docs/policies/corpus-admission.md (right-to-exist test) + scripts/engine/admit_brief.py (mechanical parts: sibling payload check, refresh-not-new lookup, query-overlap check vs reports/ SERP data, commercial-value flag from a per-page-type value table)
  • briefs/_template.yaml with facts_plan: — DONE 2026-09-03 (which fact ids the page will carry and their planned sources)
  • C5 exporter scripts/engine/export_site.py — DONE 2026-09-03 for the three routed page types: 191 driving guides + 191 visa hubs + 191 country hubs → site markdown; site parsers: 0 gaps except visa border/refusals (v2 has no such sections — playbook components borderReality/refusalReasons still to author). Driving-guide Astro build passed; full 573-page build running. TODO: idp_nationality (site has only 2 hand-built nationality pages — needs a site route), visa_tuple (site has no route)
  • Create path scripts/engine/create_page.py: brief → registry-composed draft via luna-content (Gemma) → validate_page.pytruth_gate.pydedup_gate.py (siblings + competitor corpus via pipelines/query_competitor_corpus.py) → citation_gate.py (only where the page type warrants) → kanban_request_review (opus-reviewer, evidence-ID contract, ≤ 3 rounds)
  • scripts/engine/approve_batch.py — DONE 2026-09-03 (sample/record, earned batch size, review-time alarm; smoke-tested incl. rejection). Original: Sampled approval scripts/engine/approve_batch.py: picks k files (start k = batch = 5), prints the 3 questions per file, records verdicts + time-on-page to reviews/approvals/<batch_id>.json; batch-size rule (double after 2 clean, halve on any rejection, any rejection rejects the batch); alarm when median review time < threshold
  • scripts/engine/handoff.py + manifest.schema.json v0 — DONE 2026-09-03 (idempotent, cap-recorded; pin to the real site schema later). Original: Handoff scripts/engine/handoff.py: copies approved files to handoff/<batch_id>/, writes manifest.json (file, sha256, action, approver, verdicts, redirect_from), idempotent re-run; pin manifest.schema.json
  • scripts/engine/cap.py — DONE 2026-09-03 (10 new/week, 5 % of 568 modified/week, audit log). Original: Growth-cap + audit log scripts/engine/cap.py: refuses a handoff that would exceed URLs/week or %-modified/week; appends every handoff to reviews/audit-log.jsonl
  • Site-side §6 items 1–6 landed by Expedify's developer (schema read access, build-diff == manifest, atomic release + rollback, kill switch, deploy checks vs indexation watcher, build close-out) — track as one blocked card per item
  • Dry run: 20-page batch through the whole path into handoff/, developer builds it on a preview → measures writer throughput (pages/day) for §9
  • Ledger entries for scripts, board conventions, handoff folder

Phase D — Validation cohort (plan P3 → C6)

Pending

0/5 steps

Gate: ≥ 80 % indexed @ 30 d; ≥ 50 % with ≥ 1 impression-bearing query @ 90 d; no manual action. Fail ⇒ STOP.

Steps
  • Pick 30–60 URLs (page types + hardest tuples) with John/client; record list in findings.md
  • Measurement scripts/engine/measure.py: pull GSC (source per Phase A decision), URL-inspection indexation, conversion events; write data/measure/; per-page cost ledger from Phase C logs
  • Per-page (not sampled) approval for every cohort file
  • Release in tranches over several weeks; robots lifted incrementally by the developer; indexation watcher reporting to aos-notify
  • Hold 8–12 weeks; weekly readout card

Phase E — Improve loop on the cohort (plan P4 → C7, W3, W5)

Pending

0/4 steps

Gate: refreshed beats control at 90 d by the §9 margin; else keep only FIX-FACT/TECHNICAL.

Steps
  • scripts/engine/triage.py: evidence floor check → deterministic typed decision (NO-ACTION default; FIX-FACT / REFRESH / CONSOLIDATE / PRUNE / REWORK-INTENT / TECHNICAL-ONLY) with a stated hypothesis and evidence IDs; cannibalization detection (same query, multiple URLs)
  • Randomized 30–40 % held-out control; weekly site-wide change cap enforced by cap.py
  • Decisions → W2/W5 cards; Opus only on ambiguous cases
  • Optionally rebuild the diagnostic half (SERP top-3 gap analysis) from the deleted prototype's design notes in memory — only after the evidence-ID contract is generalised

Phase F — Scale, research, citation (plan P5–P7 → parameterized C3, C8, W4, W6)

Pending

0/3 steps

Gate: only if D and E passed.

Steps
  • Parameterize create_page.py into build_family.py ("visa|IDP|passport family for [country set]") under cap.py + commercial gate
  • scripts/engine/research.py: source-watch events + SERP-shift detection as primary triggers → candidate briefs → admit_brief.py; keyword sweep secondary, low-frequency; idempotency rule vs in-flight W2 cards
  • Citation experiment: metric + baseline on the cohort, A/B on a subset, rich-result eligibility re-verified first

Waiting on decisions / inputs

  • Delivery model → files-only, confirmed 2026-09-02 (ADR 0001).
  • Measurement source → direct GSC API on Expedify's property; service account requested.
  • Named reviewer → Expedify names a real person (ADR 0004); name itself pending from Expedify.
  • ?Astro content-collection schema — requested 2026-09-02; which meta keys does the site read (incl. last_verified)? PENDING EXPEDIFY
  • Legal read owner → Expedify, we supply the claim checklist (ADR 0002).
  • Disclosure → cap presented with a short non-identifying post-mortem (ADR 0003).
  • §9 numbers → all agreed 2026-09-02 (plan §9 table). Deferred with triggers: writer throughput (dry run), cohort pick (client), manifest schema (Astro schema).
  • v1.0 sign-off → signed 2026-09-02; execution unfrozen.

Staged fixes (not applied to live)

  • fix-fact-2026-09-03 — 19 files staged, awaiting John (e.g. driving-document/for-swiss/index.yaml, driving-document/for-egyptians/index.yaml, driving-document/for-argentines/index.yaml, driving-document/for-spaniards/index.yaml)
  • fix-fact-2026-09-03b — 6 files staged, awaiting John (e.g. united-arab-emirates/index.yaml, bahrain/index.yaml, united-arab-emirates/driving-guide/index.yaml, driving-document/for-emiratis/index.yaml)

Work log

2026-09-02Phase A: Plan to v1.0complete
  • Audited project state; found PRD (v0.2-derived, publishes) vs v0.3 (files, no publish) conflict and v0.3 internal contradictions.
  • John: pause all execution, solidify the plan first. Verified nothing running (no procs/timers/cron; no running/ready/review cards).
  • Archived t_e87b5d09 (japan improve) + t_6b4a559a, t_872c6ed1, t_7f8140a6, t_54478ab4, t_714daa4d on luna-expedify; commented on parent t_d3e2c562.
  • Wrote docs/AI_Content_Engine_Project_Plan_v0.4.md (components C1–C9, workflows W1–W6, site-side contract, decisions ledger, §9 blanks). Committed 78764724, pushed to expedify-hk/content-workspace main.
  • Deleted parked prototype pipelines/page-content-audit/ on John's instruction.
  • Revised client PRD to v0.4 (handoff not publish; 0–7 phases; open decisions). Unversioned (outbound/ gitignored).
  • Created these planning files (task_plan.md, findings.md, progress.md) per planning-with-files; added them to the expedify repo .gitignore.
  • docs/AI_Content_Engine_Project_Plan_v0.4.md (new, committed)
  • ~/Agentic-OS/outbound/Expedify/Expedify_AI_Content_Engine_PRD.md (revised)
  • task_plan.md, findings.md, progress.md (new, ignored)
  • .gitignore (+3 planning files)
  • docs/adr/0001..0004-*.md, docs/Expedify_Developer_Requests_2026-09-02.md (new)
  • docs/AI_Content_Engine_Project_Plan_v0.4.md, docs/Expedify_AI_Content_Engine_PRD.md (decisions recorded)
  • Decision session with John: v0.4 §8 items 1–5 resolved (see task_plan Decisions). Plan §8 + PRD §6/§7 updated; ADRs 0001–0004 written to docs/adr/; developer requests drafted.
  • §9 session with John: all 13 lines + measurement source agreed; plan §9 rewritten as AGREED table; ADR 0005 (growth cap); dev requests §1b (GSC service account); PRD §7 item 7. Plan marked v1.0 CANDIDATE pending John's explicit sign-off.
  • John signed v1.0 (file renamed, status line updated, ADR/PRD references bumped). Phase A complete; execution unfrozen; Phase B not started.
2026-09-02Phase B: Truth layerin_progress
  • Discovery: mapped where facts live (verdict prose, roadRules table, pricingBox, visaTable, requirements rows); recorded in findings.md.
  • Wrote docs/content engine/facts.schema.json (draft 2020-12; validated with jsonschema).
  • Wrote scripts/engine/extract_facts.py (read-only) + tests/test_extract_facts.py (5 tests, pass).
  • Run 1: 745 pages, 7,498 candidates; found 203 gov fees mis-tagged first_party (row text "+ Expedify fee") and 23 hedged guides with no convention fact. Fixed both (first-party = quote box / expedify_fee prop / amount adjacent to "Expedify"; hedged guide → not_stated fact). Run 2: 7,521 candidates, 1 residual mis-tag (canada/visa/for-indians CAD 185).
  • Disagreements vs data files: 0 (content was generated from the same DBs — expected; the DBs themselves are the thing to source).
  • Independent adversarial review (subagent, 24 tool calls): 12 findings, 3 blockers. All blockers + majors incorporated: extractor v2, schema v0.2, authority registry (112 hosts), 11 tests incl. real-data loaders + schema validation of real output. Run 3: 6,280 facts; gate 0.0 % captured / 76 % scoped lead / 24 % none; 23 real convention disagreements (13 stale country hubs + India bug etc.). Round-2 re-check dispatched.
  • Review round 2: blockers 1/2/3/5 confirmed fixed, ids partially; 4 majors (value-bearing ids + 10 schema failures, voter tie-breaks masking inconsistent pages, fx/$0 inflating the denominator, generic-gov + dubai/schengen country scoping) + 4 minors. ALL incorporated (v2.1): value-free ids claim_type.<subject-key>, per-path convention votes with inconsistent pages reported as disagreement, fx inside any "(~ …)" group incl. "/"-separated, $0 by row subject, rolling windows → qualifier, generic gov ^gov.<cc>$ + .gv.at, country aliases (dubai→UAE, schengen→None), own-country advice → tier 1, no invented captured_at, dead code removed, unknown hosts fully listed. Tests 16 (every page validated with FormatChecker; no duplicate ids). Run 4: 187 distinct third-party money figures, 0 % captured, 92 % scoped lead, 8 % none; 25 disagreements of which 8 are self-contradicting driving guides.
  • Review round 3: all 8 confirmed fixed; verdict commit. Folded in its 3 follow-ups + registry road hosts (lto.gov.ph, nhtsa.gov, …) + europa.eu → v2.2, 17 tests. Final run: 187 distinct third-party figures / 0 % / 92 % lead / 8 % none; 25 disagreements, 7 self-contradicting guides.
  • Committed + pushed (expedify main) with data/facts/candidates/ gitignored as regenerable output.
2026-09-03Phase B step 3a — FIX-FACT convention statementscomplete (committed + pushed 2026-09-03; round-2 diff review clean)
  • Dumped all 25 flagged pages' convention sentences via x_votes; found Ireland's verdict ("either type") that the voter treated as ambiguous.
  • Wrote scripts/fixes/fix_convention_statements_2026-09-03.py: exact-match/regex replacements with per-file expected counts; dry-run ABORTED on first pass (hubs had 4 occurrences not 3; Indonesia guide 3 not 2) → located the extra occurrences (families[] block, requirements row note) → counts corrected → applied to 24 files with backups.
  • Re-ran extractor (reports/facts-extraction-2026-09-03.md): disagreements 0, self-contradictions 0, all YAML valid, 17 tests OK. Residual-wording grep: clean.
  • Diff review round 1: 1 blocker (Indonesia rows), 2 majors (leftover FAQ sentences; review metadata), minors (voice, script anchors). Restored the 24 backups, extended the script (Indonesia rows via non-party template, 7 FAQ edits, last_reviewed + next_review, anchored+asserted date bumps, three-sentence neither wording), re-applied. Extractor: 0/0 again; 17 tests OK; YAML valid. Round 2 dispatched.
2026-09-03Phase B step 3a2 — nationality pages + IDP routes (2026-09-03)complete (staged, not applied to live; committed + pushed 2026-09-03 after 2 review rounds)
  • Found root cause: generator reads data/idp-routes.json, never updated after the 08-30 audit (19 lcc / 20 dest discrepancies; routes = 12 licence × 23 dest subset, 55 routes with a changed destination).
  • John's rule: fixes to NEW files. Built data/idp-routes.corrected-2026-09-03.json (script clones existing route templates per status pair; authored copy for the new non-party-destination case). Wrapper scripts/gen_idp_nationality_staged.py stages pages from the corrected file without touching the generator or content/.
  • Staged 19 pages; 19/19 verdicts match the corrected status. Review round 1: 8 findings (3 substantive in the routes recomputation) → all but the generator-internal ones fixed; rebuilt + restaged; round 2 found the Nepal→Indonesia name clobber in sub_names → placeholder fix + Indonesia diagonal + next_review/sources-note polish; rebuilt, restaged, verified (0 clobbers, 19/19 parse) → committed.
2026-09-03Progress tracker (2026-09-03)complete
    2026-09-03Phase B step 3b–4 — host tiering, capture, source queue, truth gate (2026-09-03)complete
    • Tiered all 127 unknown source hosts into the registry (224 hosts, 140 ccTLD mappings; idaoffice.org = related property, never a source). Leads 92 % → 94 %; 11 figures without a lead.
    • Wrote scripts/engine/capture_facts.py (fetch lead URL, visible text, value-near-marker match, cached, polite). Smoke test 0/12: 403 (immi.homeaffairs.gov.au), JS shells (punetejashtme.gov.al), and a matcher miss on mfa.am. Full run (546 fetches, 120 hosts): 21 raw hits; added confidence scoring (claim word near the value; weak matches never count) → 17 strong captures, 4 of them money figures → gate 0 → 2.1 %. 403 bot-blocks: travel.state.gov (80 attempts), mofa.go.jp, immi.homeaffairs.gov.au; JS shells: visa.vfsglobal.com, moi.gov.ae; 26 of our own source links return 404 (content defect).
    • scripts/engine/source_queue.pyreports/source-queue-2026-09-03.md: 642 figures (fee+processing+stay) by lead host and reason (value_not_on_lead_page 229, blocked_403 123, no_lead 113, fetch_failed 94, js_or_thin_page 53, lead_url_404 26, weak_match_confirm 4).
    • scripts/engine/truth_gate.py (R1 provenance, R2 second source, R3 max-age, R4 disagreement): 623 PASS (mostly pages with no third-party money), 122 FAIL on R1; corpus gate NOT YET (4/187).
    • Committed + pushed.
    2026-09-03Phase B step 5–6 — staleness + source watch (2026-09-03)complete
      2026-09-03Dead source links (2026-09-03)complete (staged, committed)
        2026-09-03Legal checklist + generator v2.1 (2026-09-03)complete
          2026-09-03Staged batches applied to live (2026-09-03)complete — John: "do what you recommend". 19 nationality pages + 10 dead-link pages copied from handoff/ over content/; YAML valid; extractor 0 disagreements; committed + pushed. Corrected IDP routes file HELD (checker must render non_party first).
            2026-09-03Phase C (schema-independent pieces) — 2026-09-03in_progress
              2026-09-03Site repo found + two-corpus finding (2026-09-03)complete (finding; decision with John)
                2026-09-03Option C — site hotfix + DB correction (2026-09-03)complete (branch pushed, PR via compare link; v2 UAE/Bahrain re-staged + applied, commit a24b976b)
                  2026-09-03Tracker: URL inventory & agent-view tab (2026-09-03)complete — second tab on the tracker: 869 URLs (live = what the Astro routes serve: 571; v2: 745; both 544; live-only 27; v2-only 201; 97 mirror files with no route), per-URL gate/sourced/fixes/agent/needs/complete, filters. Commit 8f2845e9; deployed.
                    2026-09-03C5 exporter — driving guides (2026-09-03)complete for driving guides — 191 exported, parser 0 gaps, Astro build exit 0 (195 pages), Japan verified; scratch branch deleted; commit e5aca3eb
                      2026-09-03C5 exporter — visa hubs + country hubs (2026-09-03)complete — 573 pages export, parsers clean (except visa border/refusals = v2 gap), full Astro build exit 0 (195/197/206 pages), clone cleaned. Commit ff7b7b74.
                        2026-09-03v2 enrichment: visa border + refusal sections (2026-09-03)complete — 191 visa hubs gained borderReality + refusalReasons (generic scaffolding, staged then applied); registry updated; exporter emits them; site parsers 0 gaps on all 573 exports; extractor 0 disagreements. Commit pushed.
                          2026-09-03v2 driving-guide artefact clean-up (2026-09-03)complete — 23 guides cleaned (14 dash brand tokens, 69 stray bullet dashes / duplicate self-drive bullets, advice-as-route entries moved to notes, Japan toll sentence recovered from the v1 mirror); extractor 0 disagreements; 573 exports re-run, site parsers 0 gaps. Committed + pushed.
                            2026-09-03HANDOVER NOTE (2026-09-03, Fable near its weekly limit — John switching to Opus 5)
                              2026-09-03Content-optimization flow + batch 1 (2026-09-03)complete (staged, committed 06d06405) — the flow John asked for: template + research + SERP competitor analysis + verified facts -> an edited version of the page, ready for ChatGPT + human review.

                                Recent commits (expedify repo)

                                a0daf45d2026-09-03fix: local writer presented OUR processing fee as the government visa fee — hardened writer + gate
                                5c104aaa2026-09-03content: batch 3 on the LOCAL fleet — research in Python, copy on qwen-content
                                f7d9a9ad2026-09-03tracker: SEO/dev rebuild v1.3.0 — guide tab, trust banner, pipeline, glossary, role-labelled needs, client-safe mode, readme
                                9b1621422026-09-03content(ad-lander): make travel-visa-assistance indexable
                                74cf50f82026-09-03content(ad-lander): align outline wireframe with travel-visa-assistance.yaml
                                ec9812022026-09-03tracker: alert tiles, needs-input panel, next-step lede, sortable inventory (v1.2.0)
                                4534ed602026-09-03docs: run optimization writers on Sonnet, not the session default
                                f0d9861b2026-09-03content: batch 2 of the content-optimization flow — 10 more priority visa hubs (staged)
                                22b49f6f2026-09-03content: batch 1 final — china rewritten by its writer after first commit, australia research report added
                                fe023d3b2026-09-03content(ad-lander): enrich reviewStrip to 12 simulated reviews
                                849c28482026-09-03docs: write up the content-optimization flow as the standing process
                                06d064052026-09-03content: batch 1 of the content-optimization flow — 10 priority visa hubs optimized (staged)