# Changelog

Every change to a rule, rate or source gets a row here — whether a human made it
or the weekly pipeline did. Nothing is edited silently.

Newest first. Rows dated on or before 28 Aug 2026 were seeded from Part 7 of the
index doc during the Phase 1 migration.

| Date | ID | Change | Authority | By |
|---|---|---|---|---|
| 2026-09-09 | — | **The site is live at rules.backofficestars.ca.** Production deployment `4a8e20d1` from `main`, verified by content against the live URL: all expected pages present, no editorial string anywhere, `anchors.json` publishing all 96 anchors. The preview deployment `ba5601f2` was verified the same way before the merge. AI-crawler access re-tested on a real rule page rather than the holding page — GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, Claude-SearchBot, PerplexityBot, Bingbot, Googlebot and bare `curl` all return HTTP 200 with the real rule text. `site/placeholder/` deleted afterwards, in that order, taking its `noindex` tag with it | — | deployment 4a8e20d1 |
| 2026-09-09 | — | **The publish surface cannot live in the repo on Cloudflare Pages' Git integration, and `wrangler.jsonc` is removed.** Adding it makes Pages treat that file as the only source of build configuration; the Pages schema has no build-command field ("Configuration file for Pages projects does not support `build`"), so the dashboard's `npm run build` is ignored, nothing is built, and the deploy fails on a missing `site/dist`. Both halves confirmed against real preview deployments — `c8feba4e` failed with "No build command specified. Skipping build step" followed by "Output directory site/dist not found", and `a58a2c8b` failed schema validation when a build command was added to the file. Production was untouched throughout. Plan Correction 9's first requirement is therefore **not satisfiable this way**; validator check 8 is repointed to fail if any Wrangler config file reappears, since its presence silently breaks every deploy. Prevention is weaker than Phase 3 intended and detection carries the load instead — `verify-published.mjs` checks the deployed site by content. Restoring prevention means building in GitHub Actions and uploading directly, which is Phase 2 work | — | preview deployments c8feba4e, a58a2c8b |
| 2026-09-09 | — | **Search now fails loudly instead of quietly.** `build-site.mjs` empties `site/dist/` on every run, which deletes the Pagefind index with it — so running the build without re-running Pagefind left a search box that looked correct, returned nothing, and reported no error. The home page now detects a missing index and says search is unavailable, pointing at the rules list. Pagefind's own stylesheet was also missing, so the search UI was rendering unstyled and effectively invisible. Separately, the build's `noindex` assertion was matching the word rather than the tag, and went red on the changelog page because the changelog discusses `noindex` in prose; it now matches the robots meta tag, and was re-tested against the holding page to confirm it still catches a real one | — | build-site.mjs |
| 2026-09-09 | — | **Phase 3: the public site is built.** `scripts/build-site.mjs` renders `records/` and `data/` into 158 static pages — 96 anchor permalinks, 51 source-document pages, the do-not-cite / commonly-wrong / gaps lists, the changelog, and the how-to-use, about and status pages — plus Pagefind search and the AI-readable surface (`robots.txt` naming nine crawlers, `llms.txt`, `llms-full.txt`, `anchors.json`, `do-not-cite.json`, `status.json`, `sitemap.xml`, `feed.xml`, and a Markdown twin for every page). The build is deterministic — two consecutive runs produce identical bytes — and asserts its own claims: anchor-page count against record count, the attribution banner and canada.ca canonical on all 51 mirrored pages, a Markdown twin for every page, and no `noindex` anywhere. No rule, figure, date or flag was changed | — | build-site.mjs |
| 2026-09-09 | — | **The publish surface moved into git.** `wrangler.jsonc` names `site/dist` as the published directory, and `validate.mjs` gained check 8, which fails the build if that value is anything else. On 9 September this setting was an empty text field in the Cloudflare dashboard and the whole repository was published as a result — invisible to check 7, because nothing published that day passed through `site/dist/`. Check 7 was tightened at the same time: it now asserts the built site is actually present before reporting that no editorial strings were found in it, since an empty directory contains no editorial strings either. Both guards were negative-tested — a planted editorial file and a repointed output directory each turn the validator red | — | validate.mjs |
| 2026-09-09 | — | **`scripts/verify-published.mjs` checks the deployed site by content.** Asserts both halves: expected pages present, identified by text only the real build emits, and no editorial string anywhere. A status code decides nothing — Pages answers unknown paths with 200 and the fallback page, which is why the 9 September leak test returned identical results whether the site was leaking or fixed. The first draft of the needle list repeated that mistake: "CRA and provincial accounting rules" and "GPTBot" both matched the holding page, which describes itself in those words and names the crawlers in a comment. Needles are now strings only the real build emits. Proven in both directions — it fails against the live holding page and passes against the real build served locally | — | verify-published.mjs |
| 2026-09-09 | — | **17 of the 51 source documents had frontmatter that had never parsed as YAML.** Values such as `issued: January 2025 (CRA publication record: 2025-01-10)` contain `": "`, which YAML reads as a nested mapping. Nothing had ever read these files — `validate.mjs` parses `records/` and `data/`, not `sources/` — so the defect was silent until the site build tried to open them. Repaired by single-quoting only the 21 offending lines, with each value verified to survive unchanged after re-parsing. 21 insertions, 21 deletions, all inside frontmatter; no Crown text in any document body was touched. **Sixth instance of the silent-success pattern** in this project, after the security hook, the truncated mirrors, `api.io.canada.ca`, the mtime staleness check and the status-code leak test | — | frontmatter repair |
| 2026-09-09 | — | **Deployment `54bb6fd0` re-checked and is still leaking.** HTTP 200, 8,294 bytes, serving `editorial/routing.yaml` in full. It has now survived a corrected redeploy and deletion of the entire Pages project. Recorded in the setup checklist with the re-check command; a free Cloudflare support ticket is the next lever | — | verify-published.mjs |
| 2026-09-05 | — | Migration: index doc imported to 96 anchor records. | — | import-corpus.mjs |
| 28 Aug 2026 | — | **ITC-01 restored — the previous day's correction was itself wrong.** The 20 April 2021 date was right. CRA states in Excise and GST/HST News No. 118 (January 2025) that the $100/$500 thresholds are "effective April 20, 2021"; 2024, c. 15, s. 142 enacted the change on 20 June 2024 and applies it retroactively. The 27 Aug correction reasoned from the Justice point-in-time consolidation, whose version boundaries record **coming into force**, not the period a provision applies to — that inference was invalid. ITC-01 now carries the date, the enacting provision, the retroactivity, and explicit 2021–2024 catch-up guidance. Flag back to `Current`. Part 5 row updated to match. **Standing lesson: a consolidation timeline cannot establish an application rule.** For any date, the authorities are the amending Act's application provision and CRA's own statement of it — not the point-in-time index | — | index doc Part 7 |
| 28 Aug 2026 | — | **Added local mirror paths to every anchor whose CRA source is actually held in `Sources/`, so the index no longer depends on the "grep by anchor ID" step to find a document.** Checked each of the 96 anchors' Source URLs against the 51 documents in the library (36 mirrors with provenance front-matter, 15 plain-converted guides with none) and against the front-matter `anchors:` field where one exists. Where a plain guide has no front-matter (T4012, T4002, RC188, P113, 5000-G and others), verified the match by grepping the guide's own text for the anchor's specific figures or section titles before adding the path — e.g., T4012's "List of CCA rates and classes" section for TAX-09, T4002's line 8523/9945/9281 sections for TAX-05 to TAX-07 and TAX-11, P113's "advantage"/"eligible amount"/80% definitions for NPO-06 and NPO-07. Two claims were checked and rejected rather than added: RC188 itself warns against extending its six-year/location text to REC-02 and REC-03, so those keep only the live source; P113's "Official donation receipts" section defers to the charities-giving page rather than listing receipt contents, so NPO-08 keeps only the live source; and P113 contains no $75/10% de minimis figure, flagged inline on NPO-07 rather than silently added. **Deliberately left unmirrored, per the library's existing design:** the 34 living CRA topic pages (REG-04 to REG-08, RATE-01, most of PAY, TAX-13, NPO-03/04, ITC-02 to ITC-04, XB-01/03), the 7 rate pages (all of Part 3), the 5 provincial pages (all of Part 2.11), and SOR/91-45 (external legislation, not part of this library) — these are living-only by design and a snapshot would misrepresent them as fixed. TIM-05 and NPO-05 each gained two mirror paths, one per source cited. No rule, figure, date or flag was changed — this pass only adds path metadata already implied by the front-matter and by Part 4's "Still valid for" columns | — | index doc Part 7 |
| 28 Aug 2026 | — | **More stale Nova Scotia figures, this time hidden in worked examples rather than rate boxes.** GI-067's rate box is wrong on three provinces (NB, NL and PEI moved in 2016; NS in 2025) and still lists a spent 57% British Columbia PSB rate. RC4082 has **no rate box at all** — CRA pushes rates off-page — yet both of its direct-cost T-shirt examples compute NS at 15% ($20 plus $3 HST, direct cost $23; at 14% those are $2.80 and $22.80). A document can be clean on rate boxes and still wrong in its arithmetic | — | index doc Part 7 |
| 28 Aug 2026 | — | **A third silent truncation.** The RC4082 fetch cut mid-sentence inside "Improvements to real property" ("…not the use of the improvement itself in such activities. For I"), losing roughly 44,000 characters — the rest of Improvements, Real property changes in use, the entire Election for real property section, Subsidized housing and the closing sections. Recovered from the live DOM. That is three of 36 mirrors truncated without any error being raised (RC4081, RC4034, RC4082), all in the largest documents. **Never trust a single fetch of a long guide** — confirm the text ends at the document's real closing section, and note that the failure is silent, not signalled | — | index doc Part 7 |
| 28 Aug 2026 | — | **Mirrored GI-067 and RC4082 and closed the charity net-tax gap.** Both are **live and uncancelled** — record pages checked in English and French, no banner either side. **RC4082 is still Rev. 23**, so the derived BOS charities file was built from the current edition; there is no Rev. 24 or 25 (`rc4082-24e.pdf` and `rc4082-25e.pdf` both 404). Added **NPO-09 to NPO-12** covering the 60% net tax calculation, the GST488 election out, designated charities, and the $250,000 gross revenue test. Correction to the derived file's own header: GI-067 is dated **June 2015**, not May 2015 | — | index doc Part 7 |
| 28 Aug 2026 | — | **Flagged the charities file as derived, not primary.** `Basic GST:HST Guidelines for Charities.md` is not a CRA publication — it is a synthesis of three (GI-067 May 2015, RC4081 Rev. 23, RC4082 Rev. 23) with overlapping material merged. Renamed `DERIVED — GST-HST for Non-Profits and Charities (combined from GI-067, RC4081, RC4082).md` so it cannot be mistaken for a mirror. **Never cite it as a CRA source** — cite the underlying publication. It also overlaps the freshly mirrored RC4081; where the two disagree, the mirror wins. Its filename previously contained a colon, which is how macOS stores a forward slash — a portability hazard now removed | — | index doc Part 7 |
| 28 Aug 2026 | — | **Consolidated all source material into `Sources/`.** The 16 CRA guides moved out of the parent folder and were renamed to the same convention as the mirrors, keeping the edition year (`Guide T4012 — T2 Corporation Income Tax Guide (2025).md`). The parent folder now holds only the three index files. `Sources/` holds **50 documents, 5.2 MB** — 34 mirrored memoranda, notices, policy statements, info sheets and non-guide guides, 15 CRA guides, and one derived reference. Only one external reference to an old filename existed (a historical prompt in `Fixing guides.md`), so nothing live was broken | — | index doc Part 7 |
| 28 Aug 2026 | — | **Stale rate boxes are now quantified.** Of 34 mirrored documents, the NS-at-15% box appears in **11**: Notice 311, Notice 334, B-105, B-110, 17-9, 3-6, 18-4, 4-5-3, 8-4, GI-176 and GI-184. Worse in the older texts — Memorandum 3-1 and 19-1 state GST at 7%, P-182R bills GST at 7% in a worked example, and RC4081's Nova Scotia example computes HST at 15% throughout. Only **RC4034 (Rev. 25), RC4058 (Rev. 25) and 3-3-6 (April 2026)** are rate-current, each showing NS at 14%. Rates come from ANN-01 only | — | index doc Part 7 |
| 28 Aug 2026 | — | **Mirroring complete — all 34 non-guide sources now held in `Sources/`** with provenance front-matter and descriptive filenames. Confirmed against source: RC4110 cancelled **2026-01-30** (exact wording on the record page); REG-09's Quick Method exclusion list verbatim, so BOS itself cannot elect it; REC-01's six-year rule, which runs from the end of the last tax year the records relate to; T4117 unrevised since 2020-02-28 (Rev. 19); the 8-4 ban (11×$30, 8×$150, 0×$500); 17-1 reproduces neither (l) nor (n)–(t); TIM-05's agency rule and CRA's rejection of mere labelling. Corrected: the "public purpose" phrase does not appear in 18-4 and 23 June 2022 is a publication-record date, not an in-document one. Closed: the NPO-05 worksheet gap, resolved by RC4034 Rev. 25 | — | index doc Part 7 |
| 28 Aug 2026 | — | **Began mirroring the non-guide sources** to `Sources/`, with provenance front-matter (source URL, issue date, CRA page-details date, fetch date, anchors, caveats). 14 documents mirrored in the first pass. Findings: (a) **Notice 334 was cancelled 2026-04-22** and replaced by Memorandum 25-3 — EXM-H01 re-anchored, Notice 334 added to Part 4; (b) **TIM-02's deposit limb is unsourced** — Memorandum 3-1 contains no s.168(9) and never uses the word "deposit", flag set to Unconfirmed for that half; (c) **stale rate boxes are systemic** — the NS-at-15% box appears in six mirrored documents and two older ones still state GST at 7%, so a general warning was added to Part 4; (d) TIM-06's holdback rule and EXM-H02's 11 February 2014 date and EXM-H06's 2013 dates all **confirmed verbatim** against source | — | index doc Part 7 |
| 28 Aug 2026 | — | Added the **banned source's own URL** to the Source column of 8 Part 4 rows. The Confirm at URLs alone were not matchable: they point at the *replacement* authority, so a checker matching on them would have rejected the correct source and passed the banned one. With Source URLs in place, exactly two rows are true dual-listings — Memorandum 3-6 (also XB-04) and RC4022 (also REG-03, TIM-01), the two the `SCOPED` design exists for. The remaining 6 rows have no live URL because the source is cancelled, 404 or fictional; those stay a manual name check | — | index doc Part 7 |
| 28 Aug 2026 | — | **Restructured Part 4 as source-plus-purpose.** Each row now carries `ALL` or `SCOPED` in a **Banned for** column and a **Still valid for** column naming the anchors the source legitimately supports. 8 rows are `ALL`, 6 are `SCOPED`. The change exists because Memorandum 3-6 and RC4022 are banned here *and* anchor live rows in Part 2 — a checker treating every row as an outright ban would reject correct citations | — | index doc Part 7 |
| 28 Aug 2026 | — | Both open items from the Part 4 column work are now closed. Standing lesson: **an effective date is a calendar fact, not a rule.** Dates embedded in Part 2 rows inherit a `Current` flag that nothing re-checks. Verify any date before it appears in a published post, on the same footing as a figure | — | index doc Part 7 |
| 28 Aug 2026 | — | **Corrected ITC-01 (Part 2).** Previously stated the $100/$500 thresholds were effective 20 April 2021. Now cites s.3 of SOR/91-45 as the authority and attributes the change to 2024, c. 15, s. 142 (Regulations last amended 2024-06-20). No 2021 instrument appears in the amendment history; Budget 2021 proposed the increase, enactment appears to be June 2024. Retroactive application unconfirmed. Flag split to Current (amounts) · Unconfirmed (effective date). The matching Part 5 row was carrying the same 2021 date and has had it removed | — | index doc Part 7 |
| 28 Aug 2026 | — | **Corrected the RC4110 row (Part 4).** Previously said the URL "shows only a cancellation notice." It does not — the content page serves the complete Rev.23 guide with no banner in the body, page-details date 2023-10-06; only the landing page is labelled CANCELLED. Row now records both URLs and flags the 30 January 2026 cancellation date as unverified | — | index doc Part 7 |
| 28 Aug 2026 | — | Added a **Confirm at** column to Part 4, giving a verification URL for each of the 14 banned sources | — | index doc Part 7 |
| 27 Aug 2026 | — | Rebuilt from the original four-topic anchor library. Added Parts 0, 1, 4, 5, 6, 7. Added anchor IDs, confidence flags and jurisdiction tags. Added 60+ anchors covering health and financial service exemptions, place of supply, ITC documentation, timing of tax, cross-border and marketplace rules, payroll and employment status, income tax filing and deductions, NPO filings, and Ontario EHT and WSIB. Split rates into Part 3 | — | index doc Part 7 |
