Changelog

What we shipped.

Page 15 of 15 — completed tasks for 2026-10-30.

Tasks logged

991+

across all rounds

Since

Jan 2026

founding month

Showing

2026-10-30

page 15 of 15

2026-10-30

Completed tasks for this batch, with the status, priority, difficulty, time taken, value score and what changed.
#StatusPriorityDifficultyTimeValueCompleted Task
2697doneP2easy10mhigh#2697 chore(reviews): refresh reviews.json from the live GBP listing. 40 reviews at 4.9, 1/39 split, extractedAt 2026-10-30.
2700doneP2easy15mhigh#2700 chore(gbp): submit GBP hours Mon-Sat 10:00-19:00, Sunday closed. Google shows the edit pending review.
2470doneP1med20mhigh#2470 docs: repoint #1717 references at the open #2568 DOM harness.
2497doneP1med20mhigh#2497 chore(audit): ci runs audit:brand-tokens --strict.
2514doneP1med20mhigh#2514 fix(schema): blog Person blocks carry a profile url and @id.
2518doneP1med20mhigh#2518 fix(content): posts credit the founder, who has a profile page.
2523doneP1med20mhigh#2523 fix(content): the tools-library post says 49 tools.
2549doneP1med20mhigh#2549 a11y(cards): the tools card CTA no longer repeats the tool name.
2575doneP1med20mhigh#2575 fix(audit): audit-page-meta-seo resolves the repo root.
2590doneP1med20mhigh#2590 chore(scripts): the fragments auditor defaults to production like the link auditor.
2591doneP1med20mhigh#2591 chore(scripts): both link auditors share linkAuditorUserAgent().
2610doneP1med20mhigh#2610 fix(prompt): the assistant prompt reads brand, tagline and currency from SITE.
2622doneP1med20mhigh#2622 chore(gate): the palette fixer and auditor both exempt globals.css.
2624doneP1med20mhigh#2624 fix(audit): audit-lib-exports matches export { A, B } lists.
2625doneP1med20mhigh#2625 fix(audit): list-lib-exports walks .astro and .svelte.
2626doneP1med20mhigh#2626 chore(audit): audit-lib-exports drops the deleted src/app root.
2637doneP1med20mhigh#2637 chore(audit): audit-rendered-copy scans .astro and .svelte.
2638doneP1med20mhigh#2638 chore(audit): audit-pricing-copy walks .astro, .svelte and .mdx; fenced code is exempt.
2639doneP1med20mhigh#2639 chore(audit): rule-check walks .astro, .svelte and .mdx.
2640doneP1med20mhigh#2640 fix(price): the price gate skips code comments.
2692doneP1med20mhigh#2692 chore(audit): console-errors-audit, test-active-widgets and audit-site skip the Umami origin.
2696doneP1med20mhigh#2696 docs(blocked): the GA4 data caveats are historical only.
2703doneP1med20mhigh#2703 docs(blocked): the resolved #1528 row is retired.
2711doneP1med20mhigh#2711 chore(home): remove the unused featuredCase const.
2712doneP1med20mhigh#2712 fix(header): megaColumns() guards a null servicesMega.
2713doneP1med20mhigh#2713 fix(audit): audit-page-jsonld fails when src/pages is missing.
2714doneP1med20mhigh#2714 chore(repo): untrack and ignore .openchamber audit snapshots.
2717doneP1med20mhigh#2717 fix(scripts): rule-check writes under reports/.
2718doneP1med20mhigh#2718 docs(e2e): the tools-routes docblock names Umami.
2719doneP1med20mhigh#2719 fix(copy): tools pages say twelve server tools.
2721doneP1med20mhigh#2721 fix(origin): broken-link-checker and twitter-card-validator call botUserAgent().
2722doneP1med20mhigh#2722 docs(seo): the home title docblock says 51 chars.
2710doneP0easy20mhigh#2710 fix(test): `npm run test` no longer hangs on the two Playwright visual audits. The vitest shim (`tests/unit/audit-scripts.test.ts`) exports `WG24_SKIP_PLAYWRIGHT_AUDITS=1` for runs without Chromium or a live dev server, but `scripts/audit-visual-2105.test.cjs` and `scripts/audit-visual-screen.test.cjs` ignored it and spawned `execFileSync` against `http://127.0.0.1:3737`, which no server listens on. The audit then waited on Playwright navigation until the shim's 400s timeout, leaving orphaned Chromium children and a stuck vitest worker - the goal session's "test suite still running" turns were this hang. Both sibling tests now honour the flag, print `audit-visual-2105: skipped (WG24_SKIP_PLAYWRIGHT_AUDITS=1)` / `audit-visual-screen: skipped (...)` and exit 0 immediately; the registry `successLine` patterns in `tests/unit/audit-scripts.registry.ts` accept either the pass line or the skip line. Verified: both scripts exit 0 in under a second with the flag, and `npx vitest run tests/unit/audit-scripts.test.ts -t "audit-visual"` passes 4/4 in 371ms.
2424doneP1med20mhigh#2424 perf(schema): the home Organization node drops address, contactPoint and award.
2434doneP2easy10mhigh#2434 fix(seo): the home title sits in the 50-60 char band with `| WebGrow24`.
2446doneP1med30mhigh#2446 perf(seo): the home page emits one JSON-LD `@graph` instead of six blocks.
2500doneP2med20mhigh#2500 a11y(islands): tech-grid and industry-grid scope their tab and panel ids.
2502doneP2med20mhigh#2502 a11y(islands): faq-search and site-search scope their fixed ids.
2529doneP2easy10mmed#2529 chore(origin): the indexnow key-not-found message reads SITE_URL.
2541doneP2easy10mmed#2541 docs(schema): organizationSchema() carries a docblock describing what it publishes.
2553doneP2easy10mhigh#2553 fix(content): the tools-library post says nine months, not two years.
2586doneP1easy15mhigh#2586 a11y(search): stale search rows use text-fg/70 instead of opacity-60.
2595doneP2easy10mhigh#2595 fix(content): src/data/blog.ts says 49 tools, not 50.
2601doneP2med20mhigh#2601 chore(scripts): check-brand-classes.cjs walks .astro and .svelte files.
2611doneP2med20mhigh#2611 a11y(ids): services-tabs scopes its document-wide tab and panel ids.
2623doneP1easy10mhigh#2623 fix(lib): hrefsIn is module-private; check:lib-exports passes.
2635doneP1med20mhigh#2635 fix(tools): the Core Web Vitals endpoint uses the shared metrics module.
2642doneP1med20mhigh#2642 fix(origin): the tool API routes call botUserAgent() instead of hand-typing it.
2643doneP1med20mhigh#2643 fix(origin): schema.ts, metadata.ts and the schema island read normalizeSiteOrigin().
2644doneP1med20mhigh#2644 fix(cards): the service card carries one anchor, not a stretched overlay.
2683doneP1med20mhigh#2683 feat(analytics): Base.astro carries the Umami tracker with the hardcoded id.
2684doneP2easy10mhigh#2684 feat(analytics): the Umami tag carries data-do-not-track="true".
2685doneP1easy15mhigh#2685 chore(analytics): the GA4 gtag stub, scroll-depth events and gtag.js are gone.
2686doneP1med20mhigh#2686 fix(csp): analytics.webgrow24.com is allowlisted for script-src and connect-src.
2687doneP1easy10mhigh#2687 fix(csp): build-csp.mjs no longer lists GA4 or Google Fonts origins.
2688doneP2easy5mmed#2688 chore(types): window.gtag and window.dataLayer are gone from globals.d.ts.
2690doneP2med20mhigh#2690 fix(copy): cookies, privacy and infrastructure pages name Umami, not GA4.
2693doneP2med20mhigh#2693 test(analytics): no GA4 id in src/ and one Umami tag per page.
2695doneP2easy10mhigh#2695 fix(data): technologies and company copy name Umami, not GA4.
2705doneP3easy5mmed#2705 chore(todo): course tasks 2650-2669 are retired into changelog rows.
2604doneP2med20mhigh#2604 test(audit): the source-paths test cleans its fixture when killed.
2618doneP2easy10mmed#2618 fix(copy): the tool TL;DR keeps "We do not store it." capitalised.
2629doneP1med20mhigh#2629 fix(schema): schema.ts restores founderPersonId, founderPersonUrl, teamMemberId and homeSpeakableSchema.
2631doneP1easy10mhigh#2631 fix(reviews): reviews.ts restores reviewPublishedDate.
2632doneP1med20mhigh#2632 fix(tools): tools.ts restores the processing field for eleven server tools.
2633doneP1med20mhigh#2633 fix(tools): the tool page privacy note branches on processing.
2634doneP2easy10mhigh#2634 fix(tools): the tools hub FAQ says eleven tools call an API.
2645doneP1med20mhigh#2645 fix(cards): the tools-grid tile carries one anchor, not an article wrapper.
2646doneP1easy10mhigh#2646 a11y(cards): the service card ordinal clears 4.5:1.
2648doneP1med20mhigh#2648 feat(schema): the home page wires homeSpeakableSchema() back in.
2689doneP2med20mhigh#2689 feat(analytics): scroll_depth events go through umami.track.
2691doneP2med20mhigh#2691 test(build): the CSP and tools-routes e2e no longer pin google-analytics origins.
2707doneP1easy25mhigh#2707 fix(hero): the strip layout stops crushing its cards on a phone. `highlightsLayout="strip"` pinned `grid-template-columns: repeat(4, minmax(0, 1fr))` outside any media query, so on a 390-412px viewport each of the four highlight cards was about 76px wide: the value wrapped one character per line ("24 / m / o / n / t / h / s"), the label ran past the card and was clipped by its `overflow: hidden`, and the row read as broken rather than compact. Four pages render the strip - `/ai-coding-course`, `/company`, `/industries` and `/technologies` - so the defect was site-wide. `src/styles/globals.css` now keeps the strip on the base two-track grid and starts the four-track row at `min-width: 1024px`, which is the first width where a card clears the 32px icon, the 12px gap, the 16px deco-dot clearance and the 32px padding and still holds a three-word label on one line. The highlight card also took `min-width: 0` so a long value cannot push an `fr` track wider than the container (the same fix task #2119 applied to page grids). A second rule stacks the icon above the text below 640px, because `/technologies` carries single words at 20px bold ("Frontend", "Senior-led") that do not fit 80px of text column and broke mid-word; stacking gives them the full card width. Verified in Chrome at 390px, 768px and 1440px on `/ai-coding-course` and `/technologies`: 2x2 cards with the icon on top at 390px, 2x2 side-by-side at 768px, the four-across strip at 1440px, and no horizontal overflow. `tests/unit/page-hero-contract.test.ts` gained a five-case responsive block that fails if the four-track rule returns to the base rule, if the 1024px breakpoint moves, if the card stacking rule is dropped, or if the card loses `min-width: 0`.
2650doneP2med20mhigh#2650 feat(data): add src/data/courses.ts as the only home for course figures.
2651doneP2med20mhigh#2651 fix(data): unit-test that year-one total equals the year-two stipend payout.
2652doneP2med20mhigh#2652 chore(gate): confirm both price gates pass with no exemption and no literal.
2653doneP2med20mhigh#2653 feat(course): scaffold /ai-coding-course with metadata, canonical and breadcrumb.
2654doneP2med20mhigh#2654 feat(course): build the hero with keyword H1 and two CTAs.
2655doneP2med20mhigh#2655 feat(course): add the at-a-glance duration, fee, stipend and seats table.
2656doneP2med20mhigh#2656 feat(course): add the three-step zero-fee timeline including its conditions.
2657doneP2med20mhigh#2657 feat(course): add the six-track curriculum with the brochure tool names.
2658doneP2med20mhigh#2658 feat(course): add the months 1-24 arc from fundamentals to paid client work.
2659doneP2med20mhigh#2659 feat(course): add the live-projects and portfolio proof section.
2660doneP2med20mhigh#2660 feat(course): add who-it-is-for and who-it-is-not-for sections.
2661doneP2med20mhigh#2661 feat(course): add the AI-assisted development section for Cursor and Minimax.
2662doneP2med20mhigh#2662 feat(course): add the fee and payment table reading courses.ts.
2663doneP2med20mhigh#2663 feat(course): add month-24 outcomes with no placement guarantee.
2664doneP2med20mhigh#2664 feat(course): add the four-step admission process.
2665doneP2med20mhigh#2665 feat(course): add the FAQ with FAQPage schema.
2666doneP2med20mhigh#2666 feat(schema): add courseSchema() plus a unit test.
2667doneP2med20mhigh#2667 feat(course): add the WhatsApp apply CTA with a pre-filled message.
2668doneP2med20mhigh#2668 chore(sitemap): list /ai-coding-course in the misc sitemap section.
2669doneP2med20mhigh#2669 chore(nav): decide and wire the course page into site navigation.

This log reflects completed tasks only. Pending work is tracked in todo.md at the root of this repository.