Commit Graph

57 Commits

Author SHA1 Message Date
Ken 1805a870c9 feat: publish "A Compromised Server Can't Inject Code" (Cloudpack series #6) 2026-05-27 07:10:19 +00:00
Ken a7990c283a feat: publish "604ms Rebuilds at 50,000 Modules" (Cloudpack series #1) 2026-05-27 07:05:29 +00:00
Ken 6871f3f852 feat: publish "We Shipped 40% Less JavaScript" (Cloudpack series #3) 2026-05-27 07:00:20 +00:00
Ken d81b868246 feat: publish "50KB Down to 2KB" (Cloudpack series #2) 2026-05-27 06:56:53 +00:00
Ken a0bebd8a60 fix: retitle rage posts to outcomes-first framing 2026-05-27 06:51:26 +00:00
Ken 250107df4f docs: add rage author motivation + cloudpack synthetic benchmarking approach
Rage: The real story is combining lage's dev ergonomics with BuildXL's
correctness at scale. Ken has wanted this synthesis for years since
co-creating lage. Frame the series around ergonomics vs correctness.

Cloudpack benchmarking: synthetic codebases generated from observed
attributes of real shipping code. Pipeline: observe real repo → produce
BenchProfile JSON → corpus_gen creates deterministic synthetic codebase
(same seed = byte-identical) → corpus_verify confirms conformance →
benchmark at various scales (100 to 50k modules).

Three TypeScript module variants (barrel, intermediate, leaf) with
realistic import structures, side effects, and ambient refs. JSON
configs, markdown docs fill out the shape. Tolerances: 2% file count,
5% byte/line count.

This solves 'we can't share the real codebase' for public benchmarks.
Worth a blog post on its own.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 06:49:20 +00:00
Ken 0cd4d590b8 docs: capture 'graph as database, bundle as query' as cloudpack's unifying concept
The novel insight: traditional bundlers are compilers (source in, file out,
start over). Cloudpack is a database: the module graph is the schema, bundle
requests are queries, every output form is a materialization. One truth,
many views. No separate dev/prod pipeline. No divergence.

This concept is the unifying thread of the entire cloudpack series.

From the architect brief: 'The module graph is the software. The bundle is
a query.'

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 06:45:15 +00:00
Ken a7f2e71a4a docs: reframe both series to lead with outcomes, not internals
Key principle added to standing rules: 'Lead with outcomes, not internals.
Nobody cares about a fingerprinting algorithm. They care that their builds
stop lying.'

Rage series retitled:
- 'Two-Phase Fingerprinting: BuildXL's Deep Magic' → 'How We Made the Cache Stop Lying'
- 'Hooking Syscalls Without a Kernel Driver' → 'Zero-Config File Watching Across Three Operating Systems'
- 'TypeScript 7 Makes the Build Harness More Important' → 'TypeScript 7 Is 10x Faster. Your Builds Aren't.'
- 'node_modules in a Content-Addressed Store' → '90 Seconds to 300 Milliseconds: Fixing CI Install Times'
- 'What I Learned Maintaining Lage and Why I Rewrote It' → 'The Architecture Mistake I Made in Lage'

Cloudpack series retitled:
- 'The Bundle Is Not a File' → '604ms Rebuilds at 50,000 Modules'
- 'The 2KB Module Summary' → '50KB Down to 2KB: Why We Stopped Parsing Source Files'
- 'Dead Code That Actually Stays Dead' → 'We Shipped 40% Less JavaScript and Nobody Noticed'
- 'The Service Worker as ld.so' → '50% Less Bandwidth Per Deploy'
- 'Signing Manifests, Not Code' → 'A Compromised Server Can\'t Inject Code'

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 06:42:25 +00:00
Ken 6241656f55 docs: plan cloudpack series (6 posts) with visuals and key numbers
Cloudpack series maps native linker innovations to JS bundling at
Microsoft Teams scale (50k+ modules). Source: ~/workspace/wundler/
(kenotron-ms/cloudpack on GitHub).

Series plan:
1. The Bundle Is Not a File (ThinLTO/mold/BOLT analogy)
2. The 2KB Module Summary (25x compression, content-addressed)
3. Dead Code That Actually Stays Dead (two-layer tree-shaking)
4. The Service Worker as ld.so (ABS delta delivery)
5. Your Users Are Teaching the Bundler (PGO from browser sessions)
6. Signing Manifests, Not Code (ed25519, threat model)

Key receipts: 604ms warm rebuild at 10k modules, ~100MB for 50k
module summaries (fits L3), ~50% CDN bandwidth saved per deploy.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 06:36:49 +00:00
Ken cde305e44a feat: complete Rage series (6/6 posts), all linked on homepage
All 6 Rage posts now published and linked on the homepage:
1. Your Build Cache Is Lying to You
2. Two-Phase Fingerprinting: BuildXL's Deep Magic
3. Hooking Syscalls Without a Kernel Driver
4. TypeScript 7 Makes the Build Harness More Important
5. node_modules in a Content-Addressed Store
6. What I Learned Maintaining Lage and Why I Rewrote It

Zero 'Coming soon' items remain. 10 pages total, 9 posts.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 05:49:08 +00:00
Ken 8fab0c1952 feat: publish "What I Learned Maintaining Lage and Why I Rewrote It" (Rage series #6) 2026-05-27 05:45:56 +00:00
Ken e178f02abe feat: publish "node_modules in a Content-Addressed Store" (Rage series #5) 2026-05-27 05:37:08 +00:00
Ken ba575005cf fix: remove blank lines inside SVGs that broke markdown rendering
Markdown treats blank lines as paragraph separators, which splits
inline SVGs apart mid-element. The text and rect elements after
the first blank line leaked out as raw HTML instead of rendering
as part of the diagram.

Fixed in:
- two-phase-fingerprinting (ABI Early-Cutoff diagram - 34 blank lines removed)
- typescript-7 (Parallelism Stack + tsgo comparison - 19 blank lines removed)

Also: replaced clipart SVG hero with generated concept art image,
fixed hero illustration CSS for img element.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 05:26:13 +00:00
Ken aea20d335d feat: redesign homepage as multi-column visual landing page
- Full-width hero with CSS grid: site title/tagline (left) + hand-coded
  SVG workbench illustration (right), stacks on mobile
- Featured excerpt section with terracotta left border and inline
  diagram from 'Your Build Cache Is Lying to You'
- Rage series as 2-column card grid at container width (1100px):
  each card shows number, title, description, reading time or
  'Coming soon' badge
- All posts as 2-column grid at reading width (720px)
- Three-tier width system: hero (100%), series (--width-container),
  all-posts (--width-prose)
- Responsive: collapses to single column below 768px
- Updated tests to verify multi-column layout, SVG illustration,
  card grid structure, and responsive breakpoints (41 tests, all pass)
2026-05-27 04:57:55 +00:00
Ken f7851fb3a7 fix: homepage now links published rage posts, fix author name
- Fixed author name from 'Ken Hiatt' to 'Ken Chau'
- Rage series items now dynamically link to published posts
  (4 linked with reading times, 2 still 'Coming soon')
- Published items show reading time and have hover states
- Series items matched to posts by slug lookup

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 04:46:33 +00:00
Ken 7f0453949e feat: publish "TypeScript 7 Makes the Build Harness More Important" (Rage series #4) 2026-05-27 04:09:32 +00:00
Ken 72ee90daca feat: publish "Hooking Syscalls Without a Kernel Driver" (Rage series #3) 2026-05-27 04:08:39 +00:00
Ken 2de78e3f3c feat: publish "Two-Phase Fingerprinting" (Rage series #2) 2026-05-27 04:08:17 +00:00
Ken eaef3f8e84 feat: implement three-width layout system (reading, wide, full-bleed)
Replace the narrow 720px column layout with a three-width breakout system:

- Reading width (--width-prose, 720px): prose paragraphs, lists, blockquotes
- Wide width (--width-code, 840px): code blocks, inline SVGs, figures, .wide/.breakout
- Full width (--width-container, 1100px): hero diagrams, .full elements

The outer container is wide; individual content blocks self-constrain via
max-width + margin: auto. This creates the narrow-wide-narrow rhythm.

Changes:
- prose.css: Add .prose > * breakout pattern for three widths, SVG styling
- BaseLayout.astro: Remove max-width from main (children handle their own widths)
- [...slug].astro: Remove --width-prose constraint from .prose-wrapper
- prose.css: Remove old left:50%/translateX(-50%) code block hack
2026-05-27 04:02:12 +00:00
Ken 84bf9e706b feat: add inline SVG diagrams to judgment essay
Two diagrams in the warm palette (paper bg, terracotta accent):

1. Floor and Ceiling: before/after comparison showing AI raises the
   floor (what's functional) while the ceiling (excellence, judgment)
   stays where it is. The gap between them IS the argument.

2. Lagged Failure Timeline: decision → invisible degradation →
   failure surfaces 12-18 months later → misattributed to market
   conditions. Makes the delay visible as a four-node flow.

Both use SVG primitives (rect, line, text, circle) following the
diagram design spec: warm palette, Inter for labels, Source Serif
for descriptions, terracotta for accents.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 03:53:02 +00:00
Ken b0960ec71c feat: publish "Your Build Cache Is Lying to You" (Rage series #1) 2026-05-27 01:32:39 +00:00
Ken 29b7dcc51d feat: redesign homepage from flat card list to book-style pitch page 2026-05-27 01:25:52 +00:00
Ken adc487e63b docs: book-not-blog organization, rage series plan with 6 posts
Content model inspired by makingsoftware.com:
- Topics not dates (grouped by investigation theme)
- Homepage as pitch not index (show quality before navigation)
- Series are first-class (landing pages, progress, cross-links)
- Figure density: 1 visual per 300-500 words for technical posts
- No blog chrome (no comments, shares, newsletter popups)

Rage series plan (6 posts, all sourced from kenotron-ms/rage):
1. Your Build Cache Is Lying to You (the stale cache problem)
2. Two-Phase Fingerprinting: BuildXL's Deep Magic (WF/SF algorithm)
3. Hooking Syscalls Without a Kernel Driver (3 OS, 3 mechanisms)
4. TypeScript 7 Makes the Build Harness More Important (counter-intuitive)
5. node_modules in a Content-Addressed Store (CI kill shot)
6. What I Learned Maintaining Lage and Why I Rewrote It (meta narrative)

Each post has planned visuals (diagrams, flows, animations via Remotion).

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 01:14:55 +00:00
Ken d4a9f8b16f docs: plan visuals upfront, not as afterthought; note Remotion for animations
Content pipeline now starts with visual planning before drafting:
- What diagrams does this piece need?
- Static SVG? Animated (Remotion)? Interactive (d3-graphviz)?
- Plan alongside the outline, not as a decoration pass at the end

Cleaned up duplicate Project Context section in AGENTS.md.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 01:01:53 +00:00
Ken c4e013fbce docs: add visualization pass as mandatory content pipeline step
Every post must be considered for diagrams before publishing.
The question is not 'does this need a diagram?' but 'what would
illustrate this better than prose?'

Visualization approach:
- Claude hand-codes SVGs using primitives following design spec
- Warm palette (paper bg, brown-black ink, terracotta accent)
- Diagrams break wider than prose (840px breakout)
- DOT + d3-graphviz for interactive architecture graphs
- Image generation for concept art / visual targets

Rule: 1000+ words with zero visuals is a warning. The consideration
is mandatory. The diagrams are not.

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 00:59:12 +00:00
Ken 69390e319b fix: add unnecessary negative contrast detection to voice linting
- New lint check: 'doesn't just X. They Y' pattern (Claude rhetorical crutch)
- Fixed last instance in judgment essay: 'doesn't just lose income. They lose'
  → 'loses the acknowledgment... The income is secondary.'
- Updated voice-check skill dimension 2 with the pattern description
- Updated AGENTS.md with the new check
- Tightened regex to avoid false positives on legitimate 'isn't only' framing

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 00:46:21 +00:00
Ken a951c00e35 fix: purge AI slop from judgment essay, add voice linting pipeline
- Killed 16 em-dashes (Claude fingerprint, 15.9/1000 words -> 0)
- Replaced all clause-dash-elaboration patterns with periods, colons, restructuring
- Removed 'The One-Sentence Version' section (restated the intro, voice anti-pattern)
- Broke tricolon at lines 56-58 (too-clean parallel structure)
- Collapsed 'How to Actually Help' listicle into connective prose
- Added receipt link for ~100x inference cost claim
- Heading dashes replaced with colons (Tradesman Analogy, Excellence vs Functional)

New tooling:
- scripts/lint-voice.sh: mechanical anti-slop linter (em-dashes, trigger words,
  hedging, filler, receipts, sentence uniformity)
- .amplifier/skills/voice-check/SKILL.md: LLM-as-judge voice authenticity check
  (8 dimensions against VOICE.md profile)
- .amplifier/AGENTS.md: standing rule requiring both checks before any publish

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 00:42:18 +00:00
Ken 917c78a6b3 feat: publish "AI Commoditizes Features, But Judgment Compounds" 2026-05-27 00:13:09 +00:00
Ken 508b2030f7 fix: normalize BASE_URL trailing slash in post links and RSS feed
The Astro BASE_URL (/crashtestdev) lacked a trailing slash, causing
post URLs to render as /crashtestdevposts/... instead of
/crashtestdev/posts/... Breaking article card navigation and RSS feed
links.

Applied the same .replace(/\/?$/, '/') normalization pattern already
used in BaseLayout.astro to:
- ArticleCard.astro (card link hrefs)
- NavBar.astro (isActive path matching)
- rss.xml.ts (item link generation)

Also adds final-verification.test.mjs with 31 tests covering:
- Clean build output structure
- Index page cards, shadows, hover states, URL format
- Post page NavBar active state, PostHeader centering
- Three typography voices (prose/structure/evidence)
- Code block breakout width, warm background, terracotta border
- Design token color compliance
- Responsive behavior (nav stacking, title shrinking, gutter respect)
- RSS feed validity and URL correctness
2026-05-26 23:33:35 +00:00
Ken c416eb232e feat: configure GitHub Pages deployment workflow
Add .github/workflows/deploy.yml with build and deploy jobs for GitHub Pages. Triggers on push to master and workflow_dispatch. Uses Node 22 with npm cache, uploads dist/ artifact, and deploys via deploy-pages@v4. Add comprehensive tests verifying workflow structure.

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 23:27:40 +00:00
Ken b836b68ceb feat: add RSS feed endpoint with sorted posts and metadata 2026-05-26 23:25:10 +00:00
Ken 10804705bc feat: build index page with sorted post listing and ArticleCard components
This replaces the smoke test index with a real page that:
- Imports getCollection, BaseLayout, NavBar, ArticleCard, getReadingTime
- Fetches all posts and sorts descending by date
- Maps posts to ArticleCard components with title, date, type, summary, slug, readingTime
- Styles .post-list with prose max-width, space-6/space-12 margins, flex column, space-2 gap

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 23:21:07 +00:00
Ken 6b754d1646 feat: add ArticleCard component with card layout, hover/active/focus states, and design tokens
- ArticleCard.astro: Props {title, date, type, summary?, slug, readingTime?}
- HTML: article.card > a.card-link wrapping badge-row, h2.title, p.summary, time
- Uses BASE_URL for link construction: {base}posts/{slug}/
- Hover: shadow-md, title accent-primary; Active: translateY(1px); Focus-visible: focus-ring
- All styles reference design tokens (fonts, sizes, colors, spacing, shadows, motion)
- 32 tests covering props, structure, date formatting, and styles
2026-05-26 23:18:15 +00:00
Ken 62fe16623b feat: migrate existing posts to Astro content collection
Copy two existing blog posts from content/posts/ (old Gatsby location)
to src/content/posts/ with updated frontmatter:

- localize-react-without-bloating-the-bundle.md
- speeding-up-webpack-typescript-incremental-builds-by-7x.md (was .mdx)

Frontmatter changes: removed path/heroImage fields, added type/tags/summary,
simplified date to YYYY-MM-DD format. Body content preserved verbatim.
2026-05-26 23:11:49 +00:00
Ken 8849f638a5 feat: create post page template with dynamic routing and prose wrapper 2026-05-26 23:06:36 +00:00
Ken 2597afd472 feat: add content collection with schema and reading-time utility
- Created src/content.config.ts with Astro defineCollection using glob loader, pattern '**/*.{md,mdx}', base './src/content/posts', and Zod schema with 5 fields (title, date, type, tags, summary)
- Created src/content/posts/ directory for content storage
- Created src/utils/reading-time.ts with getReadingTime function (split whitespace, 200 WPM, Math.max(1, Math.ceil))
- All 23 new tests pass, all 61 total tests pass, npm run build succeeds

Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 23:03:44 +00:00
Ken 25fd0ea9fe feat: add Callout component with 5 types, semantic HTML, and design tokens 2026-05-26 23:01:09 +00:00
Ken 3fd814256e feat: configure Shiki syntax highlighting with warm workbench theme 2026-05-26 22:57:57 +00:00
Ken a1065364d8 feat: add prose styling for markdown content with full typographic treatment 2026-05-26 22:54:38 +00:00
Ken 3175f27c8a feat: replace index with foundation smoke test page
- Import BaseLayout, NavBar, and PostHeader components
- PostHeader with title 'Speeding Up Webpack Typescript Incremental Builds by 7x',
  date 2019-08-16, type post, readingTime 12
- Three typography voices in prose-width container:
  - Prose voice: Source Serif 4 at 18px (font-prose)
  - Structure voice: Inter at 14px in secondary color (font-structure)
  - Evidence voice: JetBrains Mono with code-text color, surface-code bg,
    rounded-md, accent-primary left border (font-evidence)
- Add build verification test (tests/verify-smoke-page.mjs)
- npm run build succeeds clean
2026-05-26 22:51:49 +00:00
Ken 42373521f0 feat: add PostHeader component with badge, title, meta, and responsive styles
Built the PostHeader.astro component per the design spec. It accepts props {title, date, type, readingTime}, formats dates with toLocaleDateString, renders a centered header with content type badge, h1 title, and meta line with date/reading time. Has responsive typography stepping down at 719px and 479px breakpoints. All 39 tests pass and npm run build succeeds.

Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 22:49:09 +00:00
Ken d4b7eeb403 feat: add NavBar component with site name, Posts link, and responsive layout
Created NavBar.astro component with:
- Site name link 'Crash Test Dev' and Posts nav link with active state detection
- aria-label='Site navigation' and aria-current='page' accessibility attributes
- Responsive stacking at 599px breakpoint
- Design token-based styling (structure font, border-subtle, etc.)
- Updated index.astro to include NavBar in nav slot
- Added comprehensive build-output tests (24 assertions)

Generated with Amplifier
Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 22:46:16 +00:00
Ken 4455a5ed01 feat: create BaseLayout component with global styles and skip navigation
- Created src/layouts/BaseLayout.astro as the site's base layout component
- Imports tokens.css and fonts.css for design system and typography
- Accepts Props {title: string, description?: string}
- Computes page title (appends ' — Crash Test Dev' unless title is already 'Crash Test Dev')
- Reads import.meta.env.BASE_URL for RSS link generation
- HTML structure: doctype, html lang=en, head with charset/viewport/description meta, computed title, RSS link alternate
- Body: skip-to-content link, named nav slot, main#main-content with default slot
- Global styles: CSS reset, body typography, link styles, skip-link, main container, ::selection
- Updated src/pages/index.astro to use BaseLayout with inline style placeholders demonstrating tokens/fonts
- Added tests/check-base-layout.mjs build-output test with 23 assertions, all passing
2026-05-26 22:43:02 +00:00
Ken e100119e3b feat: download and self-host Google Fonts woff2 files
- Created scripts/download-fonts.py: downloads Google Fonts woff2 files (latin subset only) using urllib.request with Chrome User-Agent header
- Parses CSS response for latin @font-face blocks, extracts family/weight/style/URL metadata
- Downloads to src/fonts/ with naming convention {family}-{weight}{-italic}.woff2
- Created src/styles/fonts.css: 8 @font-face declarations for:
  * Source Serif 4 (400, 600, 400-italic) — prose voice
  * Inter (400, 500, 600, 700) — structure voice
  * JetBrains Mono (400) — evidence voice
- All fonts use format('woff2'), font-display: swap, and relative URLs
- Fonts placed in src/fonts/ for Vite processing at build time

Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-26 22:39:10 +00:00
Ken b302f8d910 feat: add design tokens as CSS custom properties
Create src/styles/tokens.css with complete design token system including:
- Surface, text, accent, code, border, focus colors
- State colors (success, warning, error, info)
- Shadow definitions
- Typography families with full fallback stacks
- Typography scale (xs through 3xl) and line heights
- Spacing scale (0 through 12)
- Border radius tokens
- Layout constraints (prose, code, container widths)
- Motion tokens with reduced-motion media query

All values sourced from .design/specs/design-tokens-2026-05-26.md.
Includes verification test with 56 assertions across all categories.
2026-05-26 22:35:59 +00:00
Ken cf0c07f2a9 feat: scaffold Astro project replacing Gatsby
- Remove gatsby-config.js, yarn.lock, src/gatsby-theme-blog/
- Create package.json with astro, @astrojs/mdx, @astrojs/rss deps
- Create astro.config.mjs with site/base for GitHub Pages
- Create tsconfig.json extending astro/tsconfigs/strict
- Create src/env.d.ts with astro/client reference
- Create minimal src/pages/index.astro placeholder
- Update .gitignore: replace gatsby section with astro (dist/, .astro/)
- Add scaffold verification tests
- Verified: npm run build succeeds with output in dist/
2026-05-26 22:32:22 +00:00
Kenneth Chau c36c48b684 Update azure-static-web-apps-salmon-sea-0f0c8771e.yml 2020-07-11 08:47:17 -07:00
Azure Static Web Apps c9fc8d621a ci: add Azure Static Web Apps workflow file 2020-07-11 08:42:24 -07:00
Ken 91d67d21f3 no link 2019-08-16 20:40:33 -07:00
Ken b4f5e90447 yo blog 2019-08-16 20:35:55 -07:00