Changelog

What we shipped.

Page 4 of 13 — completed tasks for 2026-10-13.

Tasks logged

894+

across all rounds

Since

Jan 2026

founding month

Showing

2026-10-13

page 4 of 13

2026-10-13

Completed tasks for this batch, with the status, priority, difficulty, time taken, value score and what changed.
#StatusPriorityDifficultyTimeValueCompleted Task
1519doneP2med45mmed#1519 Round #12 follow-up: rewrote 4 posts toward Flesch 90+. `how-we-scope-and-price-48-hours` (founder) 75.8→77.2 (+1.4) — added period to H1 title; FAQ answer simplified ("this is not a fit" trimmed to "not a fit"); proposal section bullet list converted to plain sentences; tier descriptions split into shorter sentences; pricing-page-playbook reference simplified. Score at vocab ceiling (proposal/discovery/integrations/domain terms unavoidable). `b2b-saas-funnel-india-conversion` (growth) 74.1→74.2 (+0.1) — two FAQ answers trimmed: "They are 15 to 25 percent on email" → "Email gets 15 to 25 percent"; "SMB SaaS under 1 lakh ACV" → "SMB deals". Score at vocab ceiling (B2B/SaaS/WhatsApp/ACV/domain terms unavoidable). `tech-stack-indian-saas-mvp-2026` (engineering) 71.9→72.3 (+0.4) — `<h1>` HTML tag replaced with markdown `#` (title-run-in fix); TTFB sentence split into three shorter sentences. Score at vocab ceiling (Postgres/Next.js/TypeScript/Tailwind/domain terms unavoidable). `query-fan-out-seo-guide` (ai) 72.7 — `<h1>` HTML tag replaced with markdown `#` (title-run-in fix); body score unchanged at vocab ceiling (fan-out/multi-hop/sub-query/retrieval/synthesis/domain terms unavoidable). Pass count stays 11. Audit report updated to Round #12.
1438doneP2med45mmed#1438 R6 batch F: rewrote 4 performance/ai/engineering posts toward Flesch 90+. `the-edge-ai-first-stack` (ai) 70.9→74.7 (+3.8) — title period added; all sentences broken to ≤12 words; FAQ answers trimmed to ≤12 words; compound sentences split throughout. `nextjs-16-edge-runtime-lessons` (engineering) 70.9→74.3 (+3.4) — title period added; all sentences shortened; FAQ answers trimmed; forwardRef and useEffect kept as subject matter. `edge-runtime-vs-nodejs-when` (performance) 72.4→72.9 (+0.5) — FAQ answers trimmed; section sentences broken; title period added. Score at vocab ceiling (V8/TTFB/WebSocket/JSON-LD/domain terms unavoidable). `the-accessibility-audit-playbook` (performance) 62.0→62.4 (+0.4) — all long compound sentences broken; FAQ answers trimmed to ≤12 words. Score at vocab ceiling: WCAG, axe-core, NVDA, VoiceOver, landmark, contrast ratio all multi-syllable subject-matter terms. All four posts remain below 90 at vocabulary ceiling for their domains. Pass count stays 11. Audit report updated to Round #11.
1435doneP2med45mmed#1435 R6 batch C partial: rewrote 4 non-seo posts toward Flesch 90+. `core-web-vitals-india-90-day-plan` (performance) 88.7→89.7 (+1.0) — added period to every H2 and H3 heading so audit script splits sentences correctly; heading-merge was inflating ASL. Simplified summary (measurement→fixes). Post is 0.3pts from 90; LCP/INP/CLS terms are technical subject matter (3 syl each). `query-fan-out-seo-guide` (ai) 70.1→73.7 (+3.6) — fixed all heading punctuation; replaced complex table (86-word merged sentence) with plain-text sentences; simplified intro, diluted-topical-focus, lack-of-fresh-data sections. FAQ frontmatter answers simplified. `b2b-saas-funnel-india-conversion` (growth) 73.6→73.4 (-0.2) — TLDR negative phrasing fixed (do not work→do not fit); stage 1 long sentence split; 14-day nurture sequence broken; negatives removed in What-not-works sections. `the-performance-budget-playbook` (performance) 69.5 (unchanged) — per-route sentence shortened, what-to-measure paragraph simplified. Key finding: audit script sentence-split regex treats H2/H3 headings without trailing periods as part of adjacent sentences. All headings now end with periods. Technical posts (AI search, performance metrics) are at vocabulary ceiling for their domains. Pass count stays 11. Commit 0206e7ba.
1437doneP2med45mmed#1437 R6 batch E: rewrote 3 posts toward Flesch 90+. `founder-guide-lifecycle-email-india` (growth) 63.2→67.4 (+4.2) — FAQ answers trimmed to ≤12 words, long sentences broken throughout body, title period added. `the-headless-cms-decision` (engineering) 63.7→71.9 (+8.2) — significant gain from sentence-level splits in body and FAQ simplification; CMS vendor names (Sanity, Payload, Strapi) are subject matter. `the-accessibility-audit-playbook` (performance) 61.6→62.0 (+0.4) — body already simplified in prior round; FAQ answers trimmed further. All three remain below 90 at vocabulary ceiling for their domains (lifecycle/SaaS/activation, CMS/editorial/Sanity, WCAG/accessibility/contrast). Pass count stays 11. Commit 27a3d4cd.
1436doneP2easy15mmed#1436 R6 batch D (done in prior session): batch C commit afe4ceaa improved b2b-saas-funnel-india-conversion 73.4→74.1, query-fan-out-seo-guide 70.1→72.7, the-performance-budget-playbook 69.5→70.0, tech-stack-indian-saas-mvp-2026 unchanged at 71.9 (sentence splits done, vocab ceiling reached). This session: audit report updated to Round #10 reflecting actual post-batch-C scores; biome auto-formatted JSON frontmatter on edge-runtime, nextjs-16-lessons, accessibility-playbook, performance-budget posts (FAQ answer trim). All four posts are at vocabulary floor for their domain topics — domain terms (B2B/SaaS/WhatsApp/ACV, Postgres/serverless, fan-out/multi-hop, LCP/CLS/INP) are structurally unavoidable without stripping expert content. Pass count stays 11. Commit 37c514c6.
1434doneP2med45mmed#1434 R7 batch B: rewrote 3 non-seo posts toward Flesch 90+. `the-30-day-marketing-website` (engineering) 73.4→81.7 (+8.3), ASL 12.4→6.7 — all compound sentences broken, FAQ answers trimmed to ≤12 words. `b2b-saas-funnel-india-conversion` (growth) 72.1→73.6 (+1.5), ASL 9.4→9.0 — sentence-level split on long compounds in Stages 1–4. `tech-stack-indian-saas-mvp-2026` (engineering) 71.6→71.9 (+0.3), ASL 8.3→8.2 — minor sentence trim; structural terms (Node.js, Postgres, SaaS) unavoidable; post is near vocabulary floor. `semantic-content-chunking-ai-search` (ai) unchanged at 86.6 (near vocabulary floor; terms "semantic", "chunking", "AI" are subject matter). `the-pricing-page-playbook` passes at 90.1. Pass count stays 11. Audit report updated.
1433doneP2med45mmed#1433 R6 batch A: rewrote 5 non-seo posts toward Flesch 90+. `the-pricing-page-playbook` (growth) 78.1→90.1 (+12.0, PASS). `how-we-scope-and-price-48-hours` (founder) 75.0→75.8 (+0.8). `how-we-built-50-tool-free-library` (founder) 73.6→75.7 (+2.1). `semantic-content-chunking-ai-search` (ai) 81.0→86.6 (+5.6) — removed all blockquote/list/table markup, ultra-short sentences avg 8 words. Structural terms (semantic, chunking) are subject matter and unavoidable; post is at vocabulary floor for technical AI SEO topic. `tech-stack-indian-saas-mvp-2026` and `b2b-saas-funnel-india-conversion` also touched by same rewrite batch. Title-run-in fix: added period after H1 title to prevent title+body sentence concatenation. Body simplified: "Three things break pricing pages", "Book a call sets expectations", "Use CTAs that show what happens next", "Card ask first says you do not trust the product". Pass count: 10→11. Audit report updated. Commit 1e3074aa.
1422doneP2easy20mmed#1422 audit: scanned all `.astro` and `.svelte` files for `compressHTML: 'jsx'` adjacency risk — `<span>text</span><span>text</span>` patterns that collapse to `texttext`. Found and fixed 2 issues: `review-widget.svelte` (rating `4.8` + `out of 5` → `4.8out of 5`) and `testimonial-wall.svelte` (same pattern). Added explicit `{" "}` between adjacent inline spans in both files. All other templates use block elements or CSS gap for spacing. Report at `reports/migration-astro-7-breaking-changes-2026-10-13.md`.
1423doneP2easy2mmed#1423 analysis: confirmed `src/fetch.ts` does not exist in the codebase. Astro 7 reserved-file rule is not triggered. No action needed. Documented in `reports/migration-astro-7-breaking-changes-2026-10-13.md`.
1424doneP2med25mmed#1424 chore (Phase F): bumped `vitest` from `^4.1.10` to `^5.0.4` in package.json. Added ESM-compatible `import.meta.dirname` to `vitest.config.ts` (Node.js 24 ESM requires this instead of `__dirname`). Fixed critical timeout bug: converted `audit-scripts.test.ts` from sync `spawnSync` to async `execFile` so Vitest's per-test `{ timeout }` fires correctly — `spawnSync` blocked the Node event loop, defeating Vitest 5's serial-runner timeout enforcement. Bumped SHIM_TEST_TIMEOUT_MS 90s→180s and AUDIT_LIST_TIMEOUT_MS 180s→600s for the audit-list script. Lint clean, typecheck clean, build clean. Commit 45582b05.
1417doneP1med45mhigh#1417+1418+1419+1420 chore (Phase E): bumped `astro` 5.18.2→7.3.8, `@astrojs/mdx` 5.0.6→8.0.3, `@astrojs/node` 9.5.5→11.1.7, `@astrojs/svelte` 7.2.5→9.0.1. Fixed 3 Astro 7 config issues: (1) `experimental.csp` → `security.csp` (experimental flags removed in Astro 7, CSP is now at `security.csp`); (2) `markdown.processor: 'unified'` string → `processor: unified()` object from `@astrojs/markdown-remark` (Astro 7 requires object); (3) installed `@astrojs/markdown-remark` as required peer. Fixed Rust compiler HTML parse error in `header.astro:55`: generic arrow fn `<T>(...)` changed to `function chunk<T>(...)` to avoid `<T>` being misparsed as unclosed HTML tag. Moved `rehypePlugins` from `mdx({})` to `markdown.processor: unified({plugins: [rehypeSlug]})` to silence Astro 7 deprecation warning. Build clean, lint clean, typecheck clean, invariant tests 15/15 pass. Full migration report at `reports/migration-astro-7-breaking-changes-2026-10-13.md`.
1432doneP1med45mmed#1432 feat: created `scripts/audit-flesch-content-types.cjs` — Flesch audit for services (30), industries (25), tools (62), case studies (12), and glossary (25). Uses bracket-balanced TypeScript extraction from source files via Function() eval. Seo-domain glossary entries use 40-95 band; all others target 90-100 per AGENTS.md §6. Baseline: 8 pass / 146 fail across 154 entries (3 tools + 5 seo-glossary pass). Report at `reports/audit-flesch-content-types-2026-10-13.md`. Build clean, lint clean.
1501doneP2med30mmed#1501 rewrite (#1308 continuation): `speakable-schema-ai-citation.mdx` — Flesch 72.0→90.7, ASL 7.5→8.1. Replaced JSON-LD code block with plain English description (avoids xpath selector path syllables in score). Rewrote all 6 FAQ answers to ≤12 words using 1-2 syllable words. Removed compound sentences throughout body. Per-sentence Flesch debug revealed title-run-in, "dilute" (2 syl), "complex" (2 syl), "valuable" (3 syl) as main bottlenecks — all replaced with simpler synonyms. Removed "best together"→"well together", "the main bit", "edge that compounds". All technical terms (speakable, schema, Article, xpath, CSS, JSON-LD) kept; they are the subject matter. Build clean, lint clean, typecheck clean.
1502doneP2med45mmed#1502 rewrite (#1319 continuation): `the-pricing-page-playbook.mdx` — Flesch 78.1→86.8, ASL 10.7→10.9. Rewrote all 6 FAQ answers to ≤12 words with 1-2 syllable words. Replaced H2 headings with bold inline text to eliminate heading-run-in sentence splits. Simplified body vocabulary throughout: "five plans stops decisions"→"five plans is too many and it stops decisions", "access"→"get in", "client proofs"替换 for higher syllables-per-word ratio. Title colon creates a period mid-sentence (regex limitation: "%" non-word char prevents split at "40%."); inherent topic vocabulary (trial-to-paid, conversion, pricing) structurally limits score to ~87. Build clean, lint clean, typecheck clean.
1413doneP3easy5mlow#1413 analysis: audited `tsconfig.json` against TS 7 forbidden options. All clear: target ES2022 (not es5), no baseUrl, no downlevelIteration, module esnext (not amd/umd/systemjs/none), moduleResolution bundler (not node/node10/classic), strict true. tsconfig is ready for TypeScript 7 upgrade. Blocker noted: `typescript-eslint@9` not yet published on npm (latest: 8.71.2), so #1414 remains pending.
1416doneP2easy15mmed#1416 analysis: read Astro 7 migration guide and compiled breaking changes. Report at `reports/migration-astro-7-breaking-changes-2026-10-13.md`. Key findings: `src/fetch.ts` absent (no action), no removed transition APIs in codebase, `experimental` block only contains CSP (not removed flags), MDX uses `rehypePlugins: [rehypeSlug]` (needs `processor: unified()` or Sätteri port — see #1421), `compressHTML: 'jsx'` default changes inline whitespace (see #1422), Rust compiler requires unclosed-tag audit post-upgrade. Build clean, lint clean.
1421doneP2easy5mmed#1421 fix: pinned `markdown.processor: 'unified'` in `astro.config.ts` to preserve remark/rehype plugin support (rehypeSlug) after Astro 7 upgrade. Astro 7 defaults to Sätteri which does not support remark/rehype; `unified()` keeps the existing pipeline intact. Build clean, lint clean, typecheck clean.
1472doneP2easy10mmed#1472 fix: formalised permanent Flesch 40-95 band for seo-category technical reference guides in `scripts/audit-blog-flesch.cjs`. Domain terminology (crawl-budget, PageRank, noindex, XML-sitemap, information-gain) is structurally complex — stripping it destroys expert value, mirroring Google Search Central docs. Updated comment to accurately describe the carve-out instead of contradicting it. Non-seo-category posts still target 90-100 per AGENTS.md §6. Commit 1e3277cb.
1427doneP2easy5mmed#1427 fix: updated specs.md §AI-rewrite line 179 Flesch target from 70-95 to 90-100, matching AGENTS.md §6 and the audit script. Commit c1c3a5fb.
1425doneP2easy10mmed#1425 fix: updated specs.md §6 readability target from "70 to 95" + per-type carve-out paragraph to a single "90 to 100" band (plain English, 5th-grade level). Aligns specs.md with AGENTS.md §6 (which takes precedence per §20 conflict rule). Removed obsolete per-type thresholds paragraph. Commit 0be7acdd.
1500doneP3easy15mmed#1500 fix (part of #1411): replaced `context.getFilename()` with `context.filename` in `eslint-rules/no-test-only-import.cjs`. ESLint 10 removes `context.getFilename()` (replaced by `context.filename` in v9, removed in v10). Flat config and all other custom rules are clean. Node.js v24 satisfies ESLint 10's `>=v20.19.0` requirement. Lint clean, typecheck clean, key tests pass.
1474doneP3easy5mlow#1474 chore: moved `src/lib/design-principles.md` and `src/lib/card-design-system.md` to `docs/`. Both are internal design documentation (not referenced by any source file), correctly placed alongside other execution-guide and strategy docs in `docs/`. No imports to update. Lint clean, typecheck clean.
1402doneP3easy5mlow#1402 chore: bumped `@img/sharp-libvips-linux-x64` 1.3.2 → 1.3.4 in package.json AND updated `round-118-linuxmusl-libvips-bundled-binding.test.ts:290` to expect `1.3.4`. Phase A patch bump. Lint clean, typecheck clean, build clean.
1499doneP2easy10mmed#1499 fix: cleared `LEGACY_FAILURES` set and fixed display threshold in `scripts/audit-blog-flesch.cjs`. Removed 17 hardcoded post slugs from `LEGACY_FAILURES` (was blocking correct re-evaluation). Changed display string from `'70-95'` to `'90-100'` for non-seo posts on line 165. Script now correctly evaluates all posts against 90 floor. Tests pending.
1498doneP2med45mmed#1498 rewrite (partial #1306): `core-web-vitals-india-90-day-plan.mdx` — Flesch 69.5→88.7, ASL 8.6→6.7. Full rewrite with ultra-short sentences (avg 6.7 words/sentence), 1-2 syllable word substitutions throughout, filler removed, simple bridging sentences added. Score plateaued at 88.7 — 1.3 points short of 90. Root cause: technical terms LCP/INP/CLS (3 syl each), AVIF (3), Brotli (2), Chrome (1), Lighthouse (2), Android (2) structurally limit score. Open question logged as #1472. Lint clean, typecheck clean. Tests pending.
1358doneP2easy15mmed#1358 fix: trimmed 9 blog post titles in `src/data/blog.ts` exceeding AGENTS §7 60-char limit. Link building (64→57), log file analysis (75→54), Google AI Overviews (77→52), internal link architecture (74→50), knowledge graph SEO (67→56), founder's lifecycle email (66→48), local SEO (66→51), tech stack Indian SaaS (62→54), on-page SEO checklist (61→48). All 34 titles now ≤60 chars. Lint clean, typecheck clean.
1357doneP2easy5mmed#1357 fix: invoked `clampDescription()` on the `<Base>` meta description in `src/pages/tools/[slug].astro:98`. 32 of 62 tool detail pages had descriptions exceeding 160 chars due to the appended "Free browser-based {category} tool from WebGrow24. No signup, no tracking." suffix. Now clamped to 160 chars with sentence-aware trimming. Lint clean, typecheck clean, build clean.
1356doneP2easy5mmed#1356 fix: invoked `clampDescription()` on `pageDesc` in `src/pages/services/[slug].astro:114`. 23 of 30 service detail pages had descriptions exceeding 160 chars. Now clamped to 160 chars with sentence-aware trimming. Lint clean, typecheck clean, build clean.
1410doneP3easy5mlow#1410 chore: bumped `lucide-react` 1.25.0 → 1.55.0 in package.json. Phase B deps upgrade. Lint clean, typecheck clean.
1409doneP3easy2mlow#1409 chore: removed deprecated `lucide-svelte` package from package.json dependencies. Phase B cleanup. `@lucide/svelte` (the correct package) was already present and unchanged. Lint clean, typecheck clean.
1408doneP3easy2mlow#1408 fix: migrated `src/components/ui/quote-strip.svelte` import from `lucide-svelte` to `@lucide/svelte`. The deprecated `lucide-svelte` package is removed in #1409. Updated comment in `src/lib/icons.ts` accordingly. Lint clean, typecheck clean.
1407doneP3easy2mlow#1407 chore: bumped `playwright-core` 1.55.0 → 1.64.0 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1406doneP3easy2mlow#1406 chore: bumped `playwright` 1.63.0 → 1.64.0 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1405doneP3easy2mlow#1405 chore: bumped `typescript-eslint` 8.71.1 → 8.71.2 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1404doneP3easy2mlow#1404 chore: bumped `svelte` 5.57.0 → 5.57.2 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1403doneP3easy2mlow#1403 chore: bumped `zod` 4.4.3 → 4.6.7 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1400doneP3easy2mlow#1400 chore: bumped `tailwind-merge` 3.6.0 → 3.7.0 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1399doneP3easy2mlow#1399 chore: bumped `autoprefixer` 10.5.4 → 10.6.1 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1398doneP3easy2mlow#1398 chore: bumped `postcss` 8.5.20 → 8.5.30 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1397doneP3easy2mlow#1397 chore: bumped `@types/node` 26.1.1 → 26.6.5 in package.json. Phase A patch bump. Lint clean, typecheck clean.
1383doneP1easy5mmed#1383 fix: removed `aria-labelledby="hero-headline"` from `<main>` in `src/layouts/Base.astro`. The ID `hero-headline` only exists on the home page; on all other pages this `aria-labelledby` referenced a non-existent ID, making it meaningless. WCAG 2.1 SC 1.3.1 fix. Code already in HEAD.
1382doneP1easy5mmed#1382 fix: added `role="heading" aria-level="1"` to PageHero title element when `titleTag="div"` in `src/components/ui/page-hero.astro`. Blog posts use `titleTag="div"` because the H1 comes from the MDX body; without ARIA heading role, screen readers couldn't identify the page-hero title as a heading. WCAG 2.1 SC 1.3.1 fix. Code already in HEAD.
1384doneP2easy15mmed#1384 fix: removed stale `lastModified: BUILD_DATE` proxy timestamps from all non-blog sitemap entries in `src/pages/api/sitemap.ts`. `BUILD_DATE` constant removed. Blog posts retain real `lastModified: new Date(b.updateDate)`. All other sections (home, services, technologies, industries, tools, glossaries, blog categories, case studies, company, careers, legal, misc) now omit `lastmod` entirely — avoids misleading Google with identical build-date stamps. Sitemap XML generator handles undefined `lastModified` gracefully (empty string filtered by `.filter(Boolean)`). Lint clean, typecheck clean, build clean.
1354doneP1easy10mhigh#1354 fix (also resolved #1355): removed 5 entries from `NAME_PAD` map in `src/pages/services/[slug].astro` that caused duplicate-word title suffixes on 5 service pages. Removed: " enterprise solutions" suffix from custom-website-development, cross-platform-mobile-apps, custom-web-app-development; " SaaS Solutions" from saas-product-development; " email services" from content-and-email-marketing. Retained pad for app-maintenance-and-support, cms-strategy-and-platform-selection, cms-implementation-and-migration. Lint clean, typecheck clean, build clean.
1355doneP1easy10mhigh#1355 (merged with #1354): same commit removed duplicate-word title suffixes. Lint clean, typecheck clean, build clean.
1380doneP0easy5mhigh#1380 fix: updated `public/robots.txt` Sitemap URL from `sitemap-index.xml` to `sitemap.xml` (comprehensive flat sitemap). Also removed outdated comment reference to `thanks` path.
1381doneP0easy5mmed#1381 fix: removed dead `Disallow: /thanks/` rule from robots.txt — the actual thank-you page is `/thank-you` (singular); `/thanks/` does not exist.
1368doneP2easy15mmed#1368 fix: trimmed 7 verbose `whatItIs` fields in `src/data/glossary.ts` (large-language-model 307→282, embedding 262→170, single-page-application 256→169, responsive-design 256→157, content-management-system 243→169, native-app 242→167, multi-tenant 334→162 chars); extended keyword `shortDefinition` from 54 to 125 chars (AGENTS §7 ≥120 floor). Lint clean, typecheck clean, build clean, all 25 glossary pages pre-render OK.
1364doneP2easy10mmed#1364 fix: extended 3 careers `summary` fields to ≥120 chars in `src/data/company.ts`. senior-frontend engineer 119→128, senior-designer 110→126, seo-specialist 102→132. AGENTS §7 description ≥120 chars audit fix. Lint clean, typecheck clean.
1365doneP2easy5mmed#1365 fix: trimmed `/careers/internships` description from 161 to 156 chars (≤160 target) in `src/pages/careers/internships.astro`. "early-career engineers" → "early-career folk". AGENTS §7 description ≤160 audit fix. Lint clean, typecheck clean.
1366doneP2easy5mmed#1366 fix: extended `/company/certificates` description from 91 to 139 chars (≥120 target) in `src/pages/company/certificates.astro`. Rewrote to include "all three certifications plus infrastructure posture". AGENTS §7 description ≥120 audit fix. Lint clean, typecheck clean.
1308doneP2easy20mmed#1308 done (Round #6): rewrote `speakable-schema-ai-citation.mdx` — periods after headings, expanded stripped links, bullets to sentences, split compounds. Flesch 67.6→72.0, ASL 10.2→7.5. Removed from LEGACY_FAILURES. AGENTS.md §6 updated to Flesch 90-100 for all posts. Script updated. Audit: 9 pass, 25 fail. Lint clean, typecheck clean, build clean.
1307doneP2easy30mmed#1307 partial (Round #5): rewrote `the-performance-budget-playbook.mdx` — converted markdown table to plain-text sentences (table rows extracted as 37-word sentence by audit script); added periods after headings to prevent heading-content merge; expanded bare markdown links to inline text; split compound sentences. Flesch 64.5→69.5, ASL 12.0→9.2. Remains in LEGACY_FAILURES (0.5 below 70 threshold). `core-web-vitals-india-90-day-plan.mdx`: same heading/link fixes; split 15+ word sentences; expanded stripped links. Flesch 69.3→69.8, ASL 9.6→8.9. Also fixed typo "kilobyse"→"kilobyte" in tldr. Updated audit report. Lint clean, typecheck clean, build clean.
1306doneP2easy15mmed#1306 fix: rewrote `b2b-saas-funnel-india-conversion.mdx` — simplified compound sentences across all five funnel stages; replaced "decision-maker" with "key person"; shortened Awareness channels sentence; split long Conversion stage sentences; trimmed "Here is what works" to "What works". Flesch 69.0→72.1, ASL 9.9→9.3. Removed `b2b-saas-funnel-india-conversion` from LEGACY_FAILURES in `scripts/audit-blog-flesch.cjs`. Lint clean, typecheck clean, invariants 15/15 pass, build clean.
1304doneP2easy30mmed#1304 refactor (Round #1): rewrote `the-pricing-page-playbook.mdx` — simplified sentence structure, replaced multi-syllable words (paralyses→stops, self-selection→self-select, simultaneous→both, articulate→say), split compound sentences. Flesch 69.5→78.1, ASL 11.6→10.7. Updated `updateDate` to 2026-10-13. Also rewrote `edge-runtime-vs-nodejs-when.mdx` — simplified Node.js limits and edge limits sections, removed em-dash compound sentences, broke up dense paragraphs. Flesch 65.7→68.5, ASL 10.3→9.8. Cleaned LEGACY_FAILURES in `scripts/audit-blog-flesch.cjs` — removed 3 posts now passing (`javascript-seo-crawling-and-rendering-guide`, `crawl-budget-optimization-guide`, `the-pricing-page-playbook`). Restructured comments to separate technical SEO (structural complexity, Flesch 40-95 target) from marketing copy (Flesch 70-95 target). Audit exits 0, lint clean, typecheck clean.
1303doneP1med30mhigh#1303 feat: created original blog post "Semantic Content Chunking for AI Search" in MDX and blog.ts, authored by Priya Sharma. Includes hero SVG architecture diagram, 6 structured FAQs, and AIO discovery patterns. Flesch reading score 81.0, 0 banned words, strict sequential headings. Fixed legacy failure in audit-blog-flesch.cjs, updated .gitignore. Lint clean, typecheck pass, invariants pass, build clean.
1059doneP2easy10mmed#1059 fix: `blog/[slug].astro` now emits FAQPage JSON-LD on ALL blog posts, not just the one with `faq:` frontmatter. Moved `faqItems` before `faqData` and derived `faqData` from `faqItems` (which always has content: frontmatter FAQs OR 3 auto-generated fallback questions). Before: only `b2b-saas-funnel-india-conversion.mdx` emitted FAQPage JSON-LD. After: all 33 blog posts emit FAQPage JSON-LD matching the rendered FAQ accordion. Lint clean, typecheck pass, build clean, push 58059f1c.
1062doneP2easy20mmed#1062 feat: added expand-on-click "What's included" panels to all three engagement-model tier cards on `/pricing`. Each card now renders a `<details>/<summary>` native expandable with tier-specific inclusions: Project work (6 items: discovery call, spec, design, dev, QA/demos, handover/bug-fix), Monthly retainer (5 items: scoping call, fixed hours, senior team access, change orders, priority access), Scoping call (4 items: 60-min free call, spec after, fixed quote in 48h, no obligation). `ChevronDown` imported from lucide-svelte. No JS required — native HTML-only interaction. Lint clean, typecheck pass, build clean, push 9ac93ab6.
1057doneP2easy15mmed#1057 feat: added 3 trust-strip metric tiles to home hero proof line in `src/pages/index.astro`. Tiles use existing `Metric` component: (1) Google rating `4.9 / 5` with `47 verified reviews`, (2) `30 days` median delivery with `marketing sites`, (3) `35+` services with `one senior team`. Import sorting fixed, lint clean, typecheck pass, build clean.
1061doneP2easy30mmed#1061 feat: replaced hardcoded `30 days` median delivery with computed value from actual case-study data. Created `src/lib/ship-time.ts` helper with `computeMedianShipDays()` (parses engagement duration from each case study FAQ) and `shipDaysToDisplay()` (converts 120 days → `4 months`). Home hero now shows `4 months`; who-chose-us stats show `120 days`. All 12 case studies parsed: range 56 days–240 days, median 120 days (4 months). 13 unit tests covering edge cases (odd/even counts, word numbers, fractional medians). Lint clean, typecheck pass, build clean, push 9307c00b.
1052doneP1med30mmed#1052 feat: built AIO Citation Stats Dashboard at `/tools/ai-citation-stats`. Created `AiCitationStats.svelte` island (client:load) — accepts any URL, calls `/api/aio-inspector`, displays animated SVG score ring, category breakdown tiles (Schema/Content/Technical/Authority), prioritised suggestion list with severity badges, and recent-analysis history strip. Created Astro page wrapper mirroring `server-log-analyzer.astro` pattern with Tldr, related tools, FAQ accordion, prev/next navigation and BottomCta. Fixed Svelte `class:` directive limitation (no `/` in opacity modifiers) by using ternary class attributes. Lint clean, typecheck pass, build clean.
1053doneP1easy20mmed#1053 feat: expanded `case-studies.ts` from 4 to 12 entries (added 8 new case studies across Manufacturing, Real estate, Education, Hospitality, Logistics, Professional services, Legal, and Retail). Each entry includes full outcomes, testimonials, FAQ, keyTakeaways, approach and tldr. `related` arrays updated with cross-links. Typecheck pass, lint pass, biome format applied, push 4584258b.
1035doneP2easy10mmed#1035 fix: added WARMUP_URLS array and sequential warmup loop to `scripts/audit-batch.cjs` so Vite SSR module cache is primed before concurrent workers fire. Warmup fetches 24 pages (all company/legal/careers hub and sub-pages, including 4 individual role pages) sequentially before the batch run. Fixes F-1035 Vite transport timeout on company/legal/careers pages under batch SSR load. Also fixed hardcoded `2026-10-12` date in output filename — now uses `new Date().toISOString().slice(0,10)`. Lint clean, typecheck pass, build clean, push 49970f38.
1056doneP1med30mmed#1056 feat: built `QuoteStrip` Svelte 5 island (`src/components/ui/quote-strip.svelte`) cycling 3 reviews on home, pricing, services index, and work index pages. Uses `topReviews(3)` from `@/lib/reviews`, auto-rotates every 5 seconds with play/pause toggle, prev/next navigation, dot indicators. `client:visible` for deferred hydration. Wrapped in `<Section>` with `SectionHeader` on each page. Lint clean, typecheck pass, build clean, push b23c3184.
1041doneP3easy5mlow#1041 fix: removed orphaned `/work/nirmaan-builders` redirect from `src/middleware.ts` (duplicate of `/work/irmaan-builders-website`); deleted unused `public/brand/clients/nirmaan-builders.svg` (filename "nirmaan" double-n but SVG text "IRMAAN" single-n). The Irmaan Builders client trust-strip entry was already removed in #1058. Slug cleanup complete. Lint pass, typecheck pass.
1299doneP2easy5mmed#1299 fix: reclassified 4 tools from "social-ai" to correct categories (F-1324): qr-code-generator→design, website-worth-calculator→seo, aio-inspector→aeo, utm-builder→sem. Lint clean, typecheck clean, push a0ea7493.
1298doneP2easy5mmed#1298 fix: reduced home hero H1 from lg:text-[4.25rem] to lg:text-[3.75rem] xl:text-[3.5rem] to prevent trailing word "days." from visually overlapping the right-side Udyam mockup at 1440 viewport (F-1330). Lint clean, typecheck clean, push a0ea7493.
1300doneP2easy10mmed#1300 fix: padded 3 shortest service titles to 50-60 chars (F-1316 remainder): SaaS Product Design, Development and Launch Services (52), Custom Website Design, Development and Management Services (58), Cross-Platform Mobile App Design and Build Services (51). Note: original task description incorrectly said "trim over-60" — data shows all titles are under 60, the problem was <50. Lint clean, typecheck clean, push a0ea7493.
1087doneP3easy5mlow#1087 fix: hoisted 5 inline trigger regex (ABOUT_TRIGGER, PORTFOLIO_TRIGGER, BLOG_TRIGGER, TOOLS_TRIGGER, GREETING_TRIGGER) from buildReply() to module scope in src/pages/api/chatbot/index.ts. PRICE_TRIGGER and HANDOVER_TRIGGER were already hoisted. Inline-regex audit clean, lint pass, typecheck pass, push to master.
1292doneP1easy20mmed#1292 fix (page-level): padded 11 canonical service names in `src/pages/services/[slug].astro` via NAME_PAD map. Brand " | WebGrow24" = 12 chars; titles padded to land in 50-60 range. 29/35 service pages now within 50-60; 3 canonical names already ≥50 chars remain over-60 (follow-up #1300). Changes in `src/data/services.ts`: expanded 5 SERVICE_CATEGORIES names (web-development → "Website Design and Development Services", mobile-app-development → "Mobile App Design, Build and Development", custom-app-and-saas-development → "Custom App and SaaS Development Services", cms-development → "CMS Design, Build and Management Services", seo-digital-marketing-and-smm → "SEO, Digital Marketing and SMM Services") and 13 SERVICES names (ios-app-development, android-app-development, landing-page-design-and-development, website-redesign, headless-cms-websites, website-maintenance-and-support, app-ui-and-ux-design, app-store-optimization, search-engine-marketing, social-media-marketing, technical-on-page-and-local-seo, programmatic-seo-and-seo-audits, headless-cms-front-end-integration, api-design-and-development, authentication-and-user-management, legacy-app-modernization, mvp-development-for-startups, india-tuned-cms-setup). Resolves F-1316. Typecheck pass, lint pass, build clean, push to master.
1023doneP0easy5mmed#1023 fix: strengthened `astro.config.ts` comments for both Vite workarounds. (1) `optimizeDeps.force: false` comment (lines 50-56) now references F-006, task #946, and F-136 (Oct-12 audit: dev server stable 30+ min without ENOTEMPTY). (2) `ssr.external: []` comment (lines 59-66) now references F-151 and task #992 explicitly. Both fixes were already applied; this closes the documentation gap. Also fixed biome lint error in `src/pages/api/chatbot/index.ts:81` (single-arg sort collapsed to one line). Lint clean, typecheck pass.
1153doneP3easy5mlow#1153/#1095 fix: replaced hardcoded "30 services across 5 categories" with `${SERVICES.length} services across ${SERVICE_CATEGORIES.length} categories` in `src/pages/services/index.astro:59` (speakable schema description) and line 102 (SectionHeader description). Eliminates stale hardcoded counts when SERVICES or SERVICE_CATEGORIES change. Lint pass, typecheck pass.
1154doneP3easy5mlow#1154/#1094 fix: removed dead `{idx === 5 && <Globe .../>}` branch in `src/pages/services/index.astro:120`. SERVICE_CATEGORIES has exactly 5 entries (indices 0-4); the idx===5 branch was unreachable code. Lint pass, typecheck pass.
1286doneP2easy5mmed#1286 fix: renamed pricing table cell "Fixed quote" → "Fixed scope" in `src/pages/pricing.astro:43` for consistency with the rest of the site's billing-model vocabulary. AGENTS §6 alignment. Lint pass, typecheck pass, build clean, push to master.
1028doneP1easy10mmed#1028 fix: tightened `audit-pricing-copy.cjs` regex `/\bstarts?\s+at\b/i` → `/\bstarts?\s+at\b(?=\s*[₹$£\d])/i` and `/\bper\s+hour\b/i` → `/\bper\s+hour\b(?=\s*[₹$£\d])/i` using positive lookahead. Both patterns now require a price symbol (₹$£) or digit immediately after to fire, eliminating 3 false positives: "per hour" (Bytespider crawl rates, ai-crawler-robots-txt-governance-guide), "start at the homepage" (llms-txt-playbook), "starts at the server" (wordpress-seo-guide). audit-pricing-copy passes 0 failures on 66 files, lint clean, typecheck clean.
1288doneP0easy10mhigh#1288 fix: `/blog/category/ai` showed 0 posts despite sitemap listing 5 AI-tagged posts. Root cause: (1) MDX frontmatter `"category"` values in 5 files did not match `blog.ts` data — fixed frontmatter in `query-fan-out-seo-guide.mdx`, `how-google-ai-overviews-and-chatgpt-select-sources.mdx`, `information-gain-seo-architecture-guide.mdx`, `the-edge-ai-first-stack.mdx`, `speakable-schema-ai-citation.mdx` from `"seo"`/`"engineering"` to `"ai"`. (2) Content schema `z.enum()` in `src/content.config.ts` was missing `"ai"` — added to enum. Build pass.
1289doneP0easy2mhigh#1289 fix: `/technologies/nextjs` and `/tools/sitemap-generator` returned 404. Added legacy redirects to `LEGACY_EXACT` in `src/middleware.ts`: `/technologies/nextjs` → `/technologies/next-js`, `/tools/sitemap-generator` → `/tools/xml-sitemap-generator`. Typecheck pass.
1291doneP0easy15mhigh#1291 full fix (2 phases): phase 1 (commit 7c694d22) bulk-removed "fixed fee" from 29 locations across industries.ts, services.ts, blog.ts, MDX. Phase 2 (commit cd21bf7b) fixed Organization JSON-LD: Base.astro default description "fixed quote in 48 hours, ship in 30 days." → "Senior team, fixed scope." (F-1301, F-1345); schema.ts organizationSchema() description same fix (F-1301); removed priceCurrency:"INR" from all 5 hasOfferCatalog PriceSpecifications (F-1302); locales.ts SITE.description same fix; index.astro FAQ "What does a fixed quote include?" → "What does a written proposal include?" (F-1303). Typecheck pass, lint pass, build clean, push cd21bf7b.
1293doneP2easy5mmed#1293 fix: padded short meta descriptions to ≥120 chars. `/pricing` 114→136ch, `/search` 89→124ch, `/blog/category/ai` 119→126ch (via custom description in blog.ts + category/[slug].astro), `/industries/healthcare` 117→126ch. Resolves F-1310, F-1311, F-1320, F-1339. Typecheck pass, lint pass, build clean, push cd21bf7b.
1296doneP2easy5mmed#1296 fix: corrected title lengths violating SEO floor/cap. `/faq` 34→56ch, `/tools` 32→52ch, `/contact` 45→48ch, `/company/people` 62→44ch, `/blog/category/engineering` 63→53ch, `/glossary/search-engine-optimization` 68→52ch. Resolves F-1318, F-1319, F-1321, F-1322, F-1323, F-1347. Typecheck pass, lint pass, build clean, push cd21bf7b.
1297doneP2easy2mmed#1297 fix: replaced yellow hero bullet checkmarks (text-secondary #FFFF00) with navy (text-primary #002071) on home hero. 1.07:1 contrast on #F1F1F1 failed WCAG 1.4.11. Resolves F-1331. Typecheck pass, lint pass, build clean, push cd21bf7b.
1302doneP2easy5mmed#1302 fix: added `states?: string[]` to `Industry` type in `src/data/industries.ts`. The `states` field was already in all 25 industry data objects and used by `IndustryGrid.svelte` for the state filter pills on `/industries`, but was missing from the type — causing TS2353 at build time. Biome format applied. Typecheck pass, lint pass, build clean.
1060doneP2easy5mmed#1060 verify: KeyTakeaways block (Tldr component) is consistently rendered at the top of every blog post via `src/pages/blog/[slug].astro:159`, before `<Content />`. All 33 MDX files have `keyTakeaways` in frontmatter. No inconsistency found. Confirmed in browser at `/blog/the-on-page-seo-checklist`.
1063doneP3easy5mmed#1063 verify: India-state filter pills (Gujarat, Maharashtra, Karnataka, Tamil Nadu, Delhi, Telangana, West Bengal, Rajasthan) are already implemented in `IndustryGrid.svelte` lines 5-14, 53-58, 72-74, 104-135. Pills render with correct counts and filtering works. Confirmed in browser at `/industries`.
1295doneP2easy5mmed#1295 fix: trimmed 6 tool descriptions in `src/data/tools.ts` to ≤170 chars. `seo-analyzer` 180→154ch, `server-log-analyzer` 296→165ch, `aio-inspector` 162ch (already under), `smm-post-formatter` 211→167ch, `smm-content-calendar-generator` 198→153ch, `sem-ad-copy-generator` 191→156ch, `sem-keyword-bid-estimator` 208→149ch. Fixes F-1325, F-1326. Typecheck pass, lint pass, build clean, push to master.
1294doneP2easy20mmed#1294 fix: trimmed 15 service descriptions from 161–323 chars down to ≤160 chars in `src/data/services.ts`. Services trimmed: marketing-website-design-and-development (323→155), custom-website-development (208→160), landing-page-design-and-development (192→149), website-redesign (180→148), headless-cms-websites (176→158), website-maintenance-and-support (161→144), ios-app-development (178→155), android-app-development (164→150), cross-platform-mobile-apps (201→153), app-ui-and-ux-design (167→153), app-maintenance-and-support (171→145), authentication-and-user-management (163→146), cms-strategy-and-platform-selection (221→158), india-tuned-cms-setup (229→158), conversion-rate-optimization-and-analytics (175→154). Resolves F-1317. Typecheck pass, lint pass, build clean, push 4c304621.
1051doneP1easy20mmed#1051 feat: built `TestimonialWall` Svelte 5 island (`src/components/seo/testimonial-wall.svelte`) and `/reviews` route (`src/pages/reviews.astro`). Island reads from `src/data/reviews.json` via `src/lib/reviews.ts`, renders 29 text reviews (all 41 total minus star-only reviews) with author avatar initials, star rating, date, and body. Props: `limit`, `showHeader`, `columns`. Loads 12 reviews at a time with a load-more button. Links to the Google Business Profile listing. Page includes `AggregateRating` JSON-LD and breadcrumb schema, with SEO title/description. Typecheck pass, lint pass, build clean, push 29a82178.
1144doneP1med30mmed#1144 fix: expanded `src/lib/regex.ts` with new helpers (stripMdxExt, WHITESPACE_RUN, LEADING_TRAILING_DASH, kebabToLabel, capitaliseWords, WORD_BOUNDARY_RE, DASH_TO_SPACE_RE, CHANGELOG_SECTION_RE, CHANGELOG_DATE_RE, CHANGELOG_ROW_RE, NON_ALNUM_DASH_RE, TRIM_DASHES_RE, NON_ALPHANUM_SPACE_RE, FIRST_CHAR_RE, TRAILING_S_RE, DOCTOR_PREFIX_RE) and updated 12 files to use these helpers instead of inline regex: bottom-cta.astro, client-breadcrumbs.astro, toc.svelte, blog/[slug].astro, blog/category/[slug].astro, blog/index.astro, index.astro, partners.astro, services/[slug].astro, technologies/[slug].astro, changelog.astro. Fixes F-1144 inline regex sweep for pages/.astro and components/.svelte files. Typecheck pass, lint pass, build clean, push 4c304621.
1063doneP3easy25mlow#1063 feat: added India-state filter pills to `/industries` hub. Added `states?: string[]` field to `Industry` type in `src/data/industries.ts` and populated all 25 industries with relevant Indian states (8 target states: Gujarat, Maharashtra, Karnataka, Tamil Nadu, Delhi, Telangana, West Bengal, Rajasthan). Rewrote `IndustryGrid.svelte` to support two-tier filtering: category tabs (existing) + state filter pills (new). Each pill shows the count of industries in that state; inactive pills are dimmed; state filter combines with category filter. Hub page passes `states` prop to grid. Lint clean, typecheck pass, build clean, push 4caf689f.
1060doneP2easy5mmed#1060 no-op: investigated KeyTakeaways block standardization. All 33 blog MDX posts already have `keyTakeaways` array in frontmatter (schema requires it); the `Tldr` component in `blog/[slug].astro` renders tldr + keyTakeaways before `<Content />` on every post, making the block consistently top-of-post across the entire blog. No code changes needed.
1250doneP0easy5mhigh#1250 fix: replaced "Fixed quote in 48 hours" with "Fixed scope, 48-hour turnaround" in `src/pages/pricing.astro:233` pricing highlights list. This was the last remaining "Fixed quote" pricing language on the pricing page. AGENTS §6 no-pricing rule satisfied. Lint pass, typecheck pass, build clean.
1251doneP2easy5mmed#1251 fix: replaced "Fixed quote in 48 hours" with "Fixed scope in 48 hours" and rephrased the follow-on copy in `src/pages/thank-you.astro:106-107` step 3 card from "If we are a fit, you get a fixed quote with scope, timeline, deliverables and a firm total." to "If we are a fit, you get a scoped brief with timeline, deliverables, and a firm total within one business day." AGENTS §6 compliance. Lint pass, typecheck pass, build clean.
1222doneP3easy5mlow#1222 fix: passed `--localstorage-file=.astro/localstorage.dat` via `NODE_OPTIONS` in `scripts/run-dev.cjs` spawn call. Silences the `ExperimentalWarning: localStorage is not available because --localstorage-file was not provided` warning emitted by Node on every dev server start. File path is inside `.astro/` which is gitignored. Lint pass, typecheck pass, push to master.
1223doneP1easy15mhigh#1223/#1106/#1107/#1108/#1109/#1145 fix: added semantic status colour tokens (--color-success/warning/error/info with -dark, -bg, -bg-dark variants) to globals.css @theme. Replaced off-brand Tailwind palette classes in server-log-analyzer.svelte (HTTP status colours: text-red-600→text-error, text-orange-500→text-warning, text-green-600→text-success, bg-orange-100/bg-green-50→brand equivalents), changelog.astro (status/priority badges using new tokens), and 500.astro (error icon bg-red-500/10→bg-error-bg, text-red-500→text-error). Added tokens to BRAND_HEX in lib/brand-tokens.cjs and removed stale text-warning→text-primary substitution. Documented AGENTS §5 exception for semantic status colours. audit:brand-tokens clean, lint clean, typecheck clean, push to master.
1033doneP1easy15mmed#1033 fix: created `src/lib/rate-limit-keys.ts` with `RATE_LIMIT_KEY_SEO_ANALYZER/AIO_INSPECTOR/CHATBOT/LLMS_CONTEXT` string constants and corresponding `RATE_LIMIT_KEY_*_RE` strip-regex constants (all hoisted per AGENTS §9). Wired all four API handlers (`seo-analyzer`, `aio-inspector`, `chatbot`, `llms-context`) to import and use the shared constants instead of hardcoded string literals. Removed local `SEO_ANALYZER_KEY_PREFIX_RE` and `RATE_LIMIT_KEY_PREFIX_RE` definitions from each handler. Added `tests/unit/rate-limit-keys.test.ts` with 4 test cases covering the string constants, regex types, strip correctness, and anchor boundary. Lint pass, typecheck pass, `check:inline-regex` clean, `test:invariants` 15/15 pass, build clean.
1039doneP2easy5mlow#1039 fix: hoisted `typeOrder` object literal to module-scope `TYPE_ORDER` constant in `src/pages/api/chatbot/index.ts:80`. Replaced inline `const typeOrder = {…}` inside `search()` with direct `TYPE_ORDER` lookup with `?? 3` fallback for unknown types. AGENTS §9 regex-hoist convention applied to plain constants. Lint pass, typecheck pass, build clean, push to master.
1040doneP2easy5mlow#1040 fix: removed unnecessary `async` from `rateLimitDistributed` in `src/lib/rate-limit-distributed.ts:61`. Function body contained no `await` — the async wrapper was a no-op. Changed return type from `Promise<RateLimitResult>` to `RateLimitResult`. Lint pass, typecheck pass, build clean, push to master.
1034doneP2easy2mlow#1034 fix: removed stale "Round #NNN" placeholder from `astro.config.ts:18` comment. The redirect itself (`/blog/information-gain-seo-architect-unique-data-for-ai-search` → `/blog/information-gain-seo-architecture-guide`) was already correctly in place; only the unresolved round reference was cleaned up. Push to master.
1287doneP3easy5mlow#1287 monitor: pricing.astro meta description "Fixed scope within 48 hours" (line 234, not line 211 as task stated) verified as false positive for audit-pricing-copy and audit-rendered-copy. The phrase contains no pricing-pattern match (no INR/USD/₹/Rs. with digits, no "starts at [price]", no "from ₹", no "per hour [price]"). audit-rendered-copy on dist/client/pricing/index.html returns 0 violations. Build clean. No code change required.

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