Trust

The whole proof machinery, in the open: every promise in a registry with its gate and its negative control, a mutation score measured over the full suite, and every decision and lesson on record. Nothing on this page is typed — it is read from the repository at build time.

83

of 98 promises enforced — 15 partial, 0 gaps, each with a recorded deadline

88.86%

mutation score — 10012 of 11267 mutants killed by the unit suite

29

hand-written gates, each with a negative control proving it can fire

103

decision records · 257 logged lessons

The conformance report

WCAG 2.2, levels A and AA, one row per criterion — rendered from the gates below and never typed, and honest about the one pass no gate can run: the Accessibility Conformance Report.

The gates

Every gate reads tracked files and runs in CI; a promise without a gate does not ship. By name:

acrariabenchbridgebrowsersbundleconsumercoveragedistancedocsfilesflakeformsharnessiconsindexlanguagemutationpartsprosereachsincestylessupporttextstokenstoolstypecheckzoneless

The promise registry

One row per requirement: the promise it makes, the gate that holds it and the negative control that proves the gate can fire. The component cards link straight into these anchors.

axis

requirementstategatecontrol
req-axisNothing breaks silently enforced req-quality-registry — the promise → gate → control registry, read …req-quality-negative-control — the rule that a gate without proof o…

accessibility

requirementstategatecontrol
req-a11y-wcagWCAG 2.2 AA as the minimum enforced req-a11y-axe (the rendered DOM) + req-token-contrast (the values …see both gates above > **Formal conformance does not mean good qualit…
req-a11y-built-inAccessibility built into the component enforced libs/components/*/src/*.spec.ts — ARIA relations checked per compon…`a11y.spec.ts › "the a11y gate really does detect violations (a contr…
req-a11y-touchTouch target ≥ 24×24 px, outright enforced apps/sandbox-e2e/src/field-hitarea.spec.ts, `apps/sandbox-e2e/src/c…the gate has two documented runs in which it fired: lesson-25 (a wr…
req-a11y-axeAutomated axe-core audit enforced apps/sandbox-e2e/src/a11y.spec.ts — every audit reads the page at *…`a11y.spec.ts › "the a11y gate really does detect violations (a contr…
req-a11y-motionReduced motion is a token axis, not a rule in a stylesheet enforced apps/sandbox-e2e/src/preferences.spec.ts — the axis itself, in the …`preferences.spec.ts › "with no preference the motion axis stands at …
req-a11y-forced-colorsForced colours mode enforced apps/sandbox-e2e/src/forced-colors.spec.ts — what the browser paint…emulation goes through page.emulateMedia() in the visit() helper,…
req-a11y-acrThe conformance report is rendered from the gates enforced tools/check-acr.mjs — eight points: the catalogue is the standard's…tools/check-acr.fixtures/ — one hundred and eighty-two prepared inp…

API

requirementstategatecontrol
req-api-namesNaming per the new style guide partial libs/components/eslint.config.mjs — `@angular-eslint/component-sele…none — deliberately: an ESLint rule has no quiet-pass mode ---
req-api-foundationStandalone, OnPush, zoneless-safe enforced tools/check-zoneless.mjs (target check-zoneless, in CI) — measuri…tools/check-zoneless.fixtures/ — doctored inputs, one per way of di…
req-api-signalsInputs and outputs through signals partial libs/components/button/src/button.spec.ts, `libs/components/checkbo…none — deliberately: a wrong transform shows up as a wrong type in th…
req-api-attributesState as data-pct-*, not CSS classes partial apps/sandbox-e2e/src/states.spec.ts — the cross-cutting states view…none — deliberately: a selector matching nothing yields an empty loca…
req-api-configGlobal configuration via providePctConfig partial libs/components/button/src/button.spec.ts — the default size from…none — deliberately: the test compares two different values, so i…
req-api-signal-formsControls are native signal-forms controls enforced tools/check-forms.mjs (target check-forms in the root project, in…the tests start from a non-empty initial value — with an empty mo…
req-api-dayA day is a calendar day, the same in every timezone enforced libs/components/date/src/day.spec.ts › in a hostile timezone — the …the same cases build the day the old way beside the new — `new Date(2…
req-api-timeA time of day is a wall clock, the same in every timezone enforced libs/components/time/src/time.spec.ts › in a hostile timezone — the…the same cases build the time the old way beside the new — in Warsaw …
req-api-datetimeA day with a time is a wall clock with a date, the same in every timezone enforced `libs/components/datetime/src/datetime.spec.ts › in a hostile timezon…the same cases build the pair the old way beside the new — in Warsaw …
req-api-containerIn a composite component the control is the container partial libs/components/radio/src/radio.spec.tsnone — deliberately: the violation would be a second `FormValueContro…
req-api-wrapperForm controls are a wrapper plus a control enforced libs/components/field/src/field.spec.ts — the chrome's own cases pl…field-hitarea.spec.ts — a cursor map over a grid of points (`elemen…
req-api-no-wrapperThe wrapper is optional partial libs/components/field/src/field-controls.spec.ts — every control is…none — deliberately: the standalone mode is the default, so its f…
req-api-messageOne message line, and the error takes it enforced libs/components/field/src/field-controls.spec.ts — the controls tha…tools/check-aria.fixtures/hint-beside-error — the same two messages…
req-api-warningA warning stands where an error would, and vetoes nothing enforced libs/components/core/src/warnings.spec.ts — the seven cases of 0087…libs/components/core/src/warnings.spec.ts › "one validator, as an e…
req-api-frameThe control tells the wrapper whether it wants a frame enforced apps/sandbox-e2e/src/field.spec.ts, req-a11y-touchthe touch-target test caught the regression described in lesson-25 …
req-api-native-inputThe text field stands on a native <input> partial libs/components/field/src/field-controls.spec.tsnone — deliberately: swapping <input> for an element of our own kno…
req-api-platformWe do not implement what the platform gives us enforced apps/sandbox-e2e/src/radio.spec.ts — keyboard navigation; `apps/san…the keyboard half has none — deliberately: a navigation test has no m…
req-api-numberThe number field does not stand on <input type="number"> enforced libs/components/field/src/number.spec.ts, `apps/sandbox-e2e/src/num…recorded rather than prepared, because each mechanism is one line and…
req-api-genericA choice control's value is of type T, not a string enforced libs/components/select/src/select.spec.ts — the generic contract, p…the probe from lesson-37 — five deliberately contradictory bindings…
req-api-partsThe data-pct-part contract is public styling API enforced tools/check-parts.mjs (target check-parts in the root project, in…tools/check-parts.fixtures/ — 87 inputs, each rejected on its own p…
req-api-parts-uniquePart names are unambiguous under nesting enforced tools/check-parts.mjs point 6 — a component whose parts share a pre…tools/check-parts.fixtures/part-outside-namespace, and a run agains…
req-api-harnessA harness per component, on the parts contract enforced tools/check-harness.mjs (target check-harness in the components…tools/check-harness.fixtures/ — 27 prepared inputs, each rejected o…
req-api-templatesCustomisation through projection and templates enforced libs/components/core/src/core.spec.ts — pctReportOrphanSlot under…two recorded runs that fail on different cases. pctReportOrphanSlot…
req-api-iconsEasy use of somebody else's icons enforced tools/check-icons.mjs (target check-icons) — six points over the …tools/check-icons.fixtures/ — thirty-two prepared inputs, each reje…
req-api-icons-customThe library ships no icon set of its own partial libs/components/check-package.mjs — the absence of icon files in th…none — deliberately: the violation here is adding something, not …
req-api-textsThe library's strings are exposed for translation enforced tools/check-texts.mjs (target check-texts) — six points: a string…tools/check-texts.fixtures/ — 113 doctored inputs, each rejected on…
req-api-catalogueThe contract is machine-readable, from the same sources as the pages enforced apps/docs/tools/build-content.mjs (target content of the docs p…the content pass's tripwires fired twice while the cards' owed readin…
req-api-overlayThe overlay comes out of the control's visible edge enforced apps/sandbox-e2e/src/select.spec.ts — measuring the panel's width a…the measurement from lesson-35 (a 301 px field ⇒ a 275 px panel, of…
req-api-sizeSize is one axis for the whole library enforced apps/sandbox-e2e/src/size.spec.ts — measured in the browserthe test checks that the heights are equal *_and what that height is_…
req-api-animationsAnimation without @angular/animations enforced libs/components/check-package.mjs point 7, rule forbidden — the b…tools/check-package.fixtures/ — five prepared packages, each reject…

project

requirementstategatecontrol
req-project-monorepoThe workspace is an NX monorepo partial .github/workflows/ci.yml — the entire run goes through nx affectednone — deliberately: the failure is immediate and total (CI has nothi…
req-project-latestBefore 1.0 the newest versions; from the first release, the matrix enforced tools/check-support.mjs (point 2) — the declared Angular window equ…tools/check-support.fixtures/window-narrower-than-the-manifest.json…
req-project-dependenciesMinimum runtime dependencies enforced point 7 of libs/components/check-package.mjs, over the packed m…tools/check-package.fixtures/ — nine prepared packages for point 7 …
req-project-appsWhat lives in the workspace enforced apps/docs/project.json, apps/docs-e2e/project.json — the two proj…`apps/docs-e2e/src/shell.spec.ts › "renders the home page from the li…
req-project-packageOne npm package enforced libs/components/check-package.mjs (target check-package, in CI) —…tools/check-package.fixtures/ — a doctored package for every point …
req-project-entrypointsSecondary entrypoints canonically through ng-packagr enforced libs/components/check-package.mjs — the exports map in the packed…tools/check-package.fixtures/theme-outside-exports/ — a file presen…
req-project-coreShared code in core partial libs/components/field/src/field-controls.spec.ts — the shared messa…none — deliberately: the violation here is duplication, not a fai…
req-project-tokens-libTokens are a separate library enforced libs/components/project.json → implicitDependencies: ["tokens"] +…tools/check-package.fixtures/theme-missing/ — a package without `th…
req-project-tree-shakingThe primary entrypoint is minimal enforced tools/check-bundle.mjs (target check-bundle in components, in C…tools/check-bundle.fixtures/ — 47 doctored inputs, each rejected on…
req-project-filesA fixed component file structure enforced tools/check-files.mjs (target check-files, in CI) — ten points ov…tools/check-files.fixtures/ — 49 prepared trees, each rejected on i…
req-project-prefixThe pct prefix partial libs/components/eslint.config.mjs — the `@angular-eslint/component-…none — deliberately: an ESLint rule fires on the first violation and …
req-project-languageThe repository speaks one language: English enforced tools/check-language.mjs (target check-language in the root proje…tools/check-language.fixtures/ — 35 doctored inputs, each rejected …
req-project-conciseText in the repository carries weight enforced tools/check-prose.mjs (target check-prose in the root project, in…tools/check-prose.fixtures/ — fifty-five prepared inputs, each reje…
req-project-angularThe newest Angular mechanisms enforced tools/check-zoneless.mjs (target check-zoneless, in CI) — three p…tools/check-zoneless.fixtures/ — doctored inputs, one per way for z…
req-project-ssrComponents work under SSR enforced apps/sandbox-e2e/src/hydration.spec.ts — the check sits in the `vis…`hydration.spec.ts › "the gate really does detect a hydration error (…
req-project-layoutDirectory layout partial apps/docs/project.json, apps/sandbox/project.json, `apps/sandbox-…none — deliberately: the violation is immediate and total — a project…
req-project-reachEvery tracked file has a reader enforced tools/check-reach.mjs (target check-reach in the root project, in…tools/check-reach.fixtures/ — 33 prepared inputs, each rejected on …

quality

requirementstategatecontrol
req-quality-negative-controlEvery gate has a negative control enforced tools/check-docs.mjs — the Control field is required on every r…tools/check-docs.fixtures/ — a requirement with a gate but no contr…
req-quality-inheritanceA gate that reads a class reads the whole of it enforced the list, one entry per gate that reads a class: `tools/check-aria.mj…tools/check-aria.fixtures/base-not-read/, `tools/check-texts.fixtur…
req-quality-registryThe promise → gate → control registry enforced tools/check-docs.mjs (target check-docs, in CI) — the six checks …tools/check-docs.fixtures/ — a set of deliberately broken requireme…
req-quality-indexA list that describes a directory is derived from it enforced tools/check-index.mjs (target check-index in the root project, in…tools/check-index.fixtures/ — 23 prepared inputs, each rejected on …
req-quality-typecheckEvery project has a typecheck target enforced tools/check-typecheck.mjs (target check-typecheck, in CI) — four …tools/check-typecheck.fixtures/ — eleven doctored inputs, each reje…
req-quality-unitUnit tests on Vitest enforced in three parts, because "the tests run", "how many pass" and "how man…tools/check-mutation.fixtures/ — 91 doctored inputs on a fake libra…
req-quality-coverageCoverage ≥ 80% of lines enforced in three parts, because the percentage, its denominator and the templ…tools/check-coverage.fixtures/ — twenty-two doctored inputs, one pe…
req-quality-e2ee2e tests on Playwright, visual ones included enforced apps/sandbox-e2e/src/visual.spec.ts and the remaining e2e specs; an…there are two thresholds and both come from measurement. The pixe…
req-quality-hydrationA hydration gate in e2e enforced apps/sandbox-e2e/src/hydration.spec.ts + the visit() helper in `a…`hydration.spec.ts › "the gate really does detect a hydration error (…
req-quality-packageA gate that examines the packed artifact enforced libs/components/check-package.mjs (target check-package, in CI)tools/check-package.fixtures/ — seven doctored packages, one per po…
req-quality-consumerA consumer test on a local registry enforced tools/check-consumer.mjs (target check-consumer, in CI) — seven p…tools/check-consumer.fixtures/ — 28 doctored inputs, each rejected …
req-quality-browsersThe browser matrix enforced apps/sandbox-e2e/playwright.config.mts — three projects (chromium, …tools/check-browsers.fixtures/ — 44 doctored inputs, each rejected …
req-quality-benchmarkWhat a component costs is a published number enforced tools/check-bench.mjs (target check-bench of the docs project, …tools/check-bench.fixtures/ — 17 prepared inputs, each rejected on …
req-quality-viewsThe sandbox is split into views enforced apps/sandbox-e2e/src/a11y.spec.ts, hydration.spec.ts — both itera…apps/sandbox/src/app/app.spec.ts — the view registry against the ro…
req-quality-cardThe shared sbx-demo card enforced apps/sandbox/src/app/ui/demo.spec.ts; tools/check-docs.mjs — ever…tools/check-docs.fixtures/ — a card with a non-existent identifier …
req-quality-stageThe page theme is a scoped theme too enforced apps/sandbox-e2e/src/theme.spec.ts, `apps/sandbox-e2e/src/shell.spe…`preferences.spec.ts › "with no dark preference :root stays light (th…
req-quality-prefixSandbox infrastructure uses the sbx prefix partial apps/sandbox/eslint.config.mjs — selector rules with the prefixesnone — deliberately: an ESLint rule has no quiet-pass mode

release

requirementstategatecontrol
req-release-semverSemVer with pre-release channels enforced libs/components/check-package.mjs (point 4: PCT_VERSION == `versi…stamp-version is not a dependency of build — if it were, the …
req-release-ng-addng add and the migration collection enforced libs/components/check-package.mjs (point 5) — the collections are i…tools/check-package.fixtures/schematic-missing/ — a package whose c…
req-release-metadataThe package carries complete metadata enforced libs/components/check-package.mjs (point 6) — two different severit…tools/check-package.fixtures/repository-missing/ — a manifest witho…
req-release-supportSupport and deprecation policy enforced tools/check-support.mjs (five points) over docs/support.md, which…tools/check-support.fixtures/ — fifteen prepared inputs, each rejec…
req-release-sinceThe public surface says since when enforced tools/check-since.mjs (points 1–4: every item dated; a value that i…tools/check-since.fixtures/ — seven prepared inputs, each rejected …

tokens

requirementstategatecontrol
req-token-dtcgThe source of truth is the DTCG format partial libs/tokens/build.mjs — the build will not start on a malformed sou…none — deliberately: a parse error is immediate and loud
req-token-bridgeThe sources round-trip through Tokens Studio enforced tools/check-bridge.mjs (target check-bridge in the root project, …tools/check-bridge.fixtures/ — 19 prepared inputs, each rejected on…
req-token-artifactsThe build generates artifacts from the source enforced the typecheck target of the sandbox-e2e project — the tokenOf /…swapping one name for a wrong one produces 6 type errors — a run docu…
req-token-tiersThree tiers of tokens enforced tools/check-tokens.mjs (target check-tokens in the root project, …tools/check-tokens.fixtures/ — one input per rule: `colour-under-se…
req-token-referencesReferences stay as var() enforced apps/sandbox-e2e/src/theme.spec.ts — overriding a semantic token ch…the test compares the component token in :root and in a scope —…
req-token-closureA theme block contains the transitive closure enforced apps/sandbox-e2e/src/theme.spec.ts — a component token compared…the run from lesson-17: before the fix --pct-surface was correctl…
req-token-namesA token name can be guessed enforced tools/check-tokens.mjs (target check-tokens in the root project, …tools/check-tokens.fixtures/ — 34 inputs, each rejected on its own …
req-token-text-pairsA surface has a matching text token enforced tools/check-tokens.mjs (target check-tokens in the root project, …tools/check-tokens.fixtures/ — unmeasured-colour (a stylesheet pa…
req-token-contrastThe contrast gate as a skin policy enforced libs/tokens/build.mjs (target tokens:build, in CI through `^build…the run from lesson-6: the original guard let disabled through at…
req-token-no-opacityStates do not use opacity enforced tools/check-styles.mjs (target check-styles, in CI) — point 6: `o…tools/check-styles.fixtures/partial-opacity/ (a state expressed thr…
req-token-cssTokens compile to native custom properties enforced apps/sandbox-e2e/src/theme.spec.ts, `libs/components/check-package.…tools/check-package.fixtures/token-without-declaration/ — a package…
req-token-scssInternally we use SCSS partial none — deliberately: the file extension is visible in review, and a s…not applicable ---
req-token-overrideTokens can be overridden for chosen components enforced apps/sandbox-e2e/src/theme.spec.tsas in req-token-closure — comparing the component token, not the se…
req-token-layersThe stacking order is a list, and every number in it is read enforced tools/check-tokens.mjs (target check-tokens in the root project, …tools/check-tokens.fixtures/ — layer-in-the-order-undefined (an o…
req-token-scopedA theme for part of an app enforced apps/sandbox-e2e/src/theme.spec.ts, `apps/sandbox-e2e/src/a11y.spec…see req-token-closure
req-token-directiveThe [pctTheme] sugar directive enforced libs/components/theme/src/theme.spec.ts — the attribute written, fo…`theme.spec.ts › "the directive and the raw attribute are the same th…
req-token-systemThe theme follows the system until somebody says otherwise enforced apps/sandbox-e2e/src/preferences.spec.ts`preferences.spec.ts › "with no dark preference :root stays light (th…
req-token-skinThe skin is fully parameterised enforced libs/tokens/build.mjs — but only for the built-in skinsee req-token-contrast
req-token-distributionThemes as ordinary CSS files enforced libs/components/check-package.mjs — points 1 and 2: the skin is in …tools/check-package.fixtures/theme-missing/ — a package with no ski…
req-token-densityThe density axis enforced tools/check-tokens.mjs (target check-tokens in the root project, …tools/check-tokens.fixtures/ — four prepared inputs, each rejected …
req-token-logicalStylesheets use logical properties only enforced tools/check-styles.mjs (target check-styles, in CI) — point 5: a …tools/check-styles.fixtures/physical-padding/ (a property name) and…

103 decisions

Why this way and what it costs — an ADR per irreversible choice, kept even when the plan that scheduled it is long gone.

  1. 0001Template and styles in separate filesread ↗
  2. 0002The skin ships in the packageread ↗
  3. 0003Wrapper and controlread ↗
  4. 0004Height stated outright, not derived from paddingread ↗
  5. 0005Signal forms without ControlValueAccessorread ↗
  6. 0006The anchor and inheritance in an overlayread ↗
  7. 0007Configuration apart from textsread ↗
  8. 0008The motion axis in tokensread ↗
  9. 0009The number field on type="text"read ↗
  10. 0010A generic value and NoInferread ↗
  11. 0011Icons through a template and PCT_ICONSread ↗
  12. 0012The transitive closure in a theme blockread ↗
  13. 0013No headless core / skin splitread ↗
  14. 0014Texts as a signal, read at render timeread ↗
  15. 0015MIT everywhere, rights to the entity, no CLAread ↗
  16. 0016Releasing under MIT is irreversible, so the order is a decisionread ↗
  17. 0017One home per fact: the concision criterion and its budgetread ↗
  18. 0018No Sass entry point: the token surface is custom properties and typesread ↗
  19. 0019A primitive colour is not the contract; a primitive scale isread ↗
  20. 0020The palette carries no spare stepsread ↗
  21. 0021An index is generated where every column is derivable, measured where one is notread ↗
  22. 0022One message line, and it is the error that takes itread ↗
  23. 0023A tolerance is for a measurement that wobblesread ↗
  24. 0024The overlay layer carries what an overlay severs, and borrows the closing stackread ↗
  25. 0025A panel says whether it takes focus, and the rest of the focus layer waits for a consumerread ↗
  26. 0026One channel per politeness, and a message with a home announces from itread ↗
  27. 0027A slot is a directive of its own, not a name in a stringread ↗
  28. 0028An icon set is a component, and an icon's box is the contractread ↗
  29. 0029A modal is an overlay, not a <dialog> — the platform's modal is not composable with oursread ↗
  30. 0030A name is an attribute, a description is a referenceread ↗
  31. 0031A panel's tab order belongs to its triggerread ↗
  32. 0032A menu moves focus, a listbox points at itread ↗
  33. 0033An option is a row of data, not a component the consumer projectsread ↗
  34. 0034Multiplicity is a type, so it is a tagread ↗
  35. 0035A filter is a question, not a valueread ↗
  36. 0036A clear takes back what the trigger showsread ↗
  37. 0037Loading is a fact about the list, and a cursor names an optionread ↗
  38. 0038A window is measured, and its spacer is not an elementread ↗
  39. 0039A state the platform publishes is not ours to writeread ↗
  40. 0040A lockfile is repository material, the tree it locks is notread ↗
  41. 0041A height the platform computes, and a measurement only where it does notread ↗
  42. 0042A slider is the platform's range, and only the value it cannot pronounce is oursread ↗
  43. 0043A day is not an instant, and the field that takes one is text the application formatsread ↗
  44. 0044A toast is a change in a region that was already there, and its place is the top layerread ↗
  45. 0045A panel nobody chose is still text in the documentread ↗
  46. 0046A disclosure is the platform's, and so is the group it belongs toread ↗
  47. 0047A drawer is a region of the page, not a layer over itread ↗
  48. 0048A pagination owns its page number, and the folding is the only thing it computesread ↗
  49. 0049A progress bar is the platform's element under our own paintread ↗
  50. 0050A skeleton is a picture of a wait, and the wait belongs to the regionread ↗
  51. 0051Chips are a list the user shortens, and focus outlives the button it stood onread ↗
  52. 0052An avatar is a picture beside a name, and never the name itselfread ↗
  53. 0053A badge is a word wearing a tone, and the tone never speaks aloneread ↗
  54. 0054A breadcrumb is the way here, told in the platform's own linksread ↗
  55. 0055A stepper is a map of a journey the application steersread ↗
  56. 0056A tree is a walk the platform does not haveread ↗
  57. 0057Layout is three entrypoints, not a frameworkread ↗
  58. 0058The hero face is paint, and a gradient is three contrast checksread ↗
  59. 0059A theme is an attribute the skin reads, and the directive only spells itread ↗
  60. 0060The site is static by construction, and the shell is the library's first pageread ↗
  61. 0061The landing speaks in measurements, and says "machine-audited" until the ACRread ↗
  62. 0062The pages render a form, not markdown, and a demo file is its own code tabread ↗
  63. 0063The theme names its scheme to the platformread ↗
  64. 0064A face the consumer cannot reach without undoing ours is a variantread ↗
  65. 0065A treatment that paints is a component, because a directive cannotread ↗
  66. 0066A panel is a layer or a region, and the consumer says whichread ↗
  67. 0067A disc is a shape, because a radius does not draw oneread ↗
  68. 0068A harness is a declaration over the parts contractread ↗
  69. 0069A message about the list is not an item in itread ↗
  70. 0070What the control knows and the form cannot is a second channelread ↗
  71. 0071A link in button's clothes is a linkread ↗
  72. 0072A region key is the consumer's to installread ↗
  73. 0073The stop a long wait needs is the page's to throwread ↗
  74. 0074Density is a scope that re-points metrics, not an input a component readsread ↗
  75. 0075The push and the premiere are two moments, and only the second has an audienceread ↗
  76. 0076A tone is two channels and four names, settled onceread ↗
  77. 0077A number about the run is not a number about the coderead ↗
  78. 0078The site has an address, and it deploys behind a green CIread ↗
  79. 0079The first release is a measurement, and the history staysread ↗
  80. 0080An API is dated next until the release names itread ↗
  81. 0081A shard is a machine, not a second workerread ↗
  82. 0082A tone on a button is a face, and the label is what speaksread ↗
  83. 0083An icon source answers a name with data, and the box renders itread ↗
  84. 0084A fallback stays while Angular supports an engine without the feature, and e2e forces itread ↗
  85. 0085An icon-only button is a face, and its name is written on itread ↗
  86. 0086A time of day is a wall clock, and the field that takes one is text the application formatsread ↗
  87. 0087A warning is a verdict without a veto, and it is metadata the form does not graderead ↗
  88. 0088A row is measured by its own run, and the whole is measured at nightread ↗
  89. 0089One value, more than one control, and the consumer chooses whichread ↗
  90. 0090A day with a time is a wall clock with a date, and the field that takes one is two texts under one labelread ↗
  91. 0091The ring's runway is the cycle three times in the tree, because a mandatory snap refuses a windowread ↗
  92. 0092A control's reset takes back what the form cannot see, and the value stays the form'sread ↗
  93. 0093A bound of the field's own type reaches it through the platform's limit key, and the module ships the ruleread ↗
  94. 0094The release reaches main as a pull request, and the tag follows the mergeread ↗
  95. 0095Every component is released under MIT, and the order is what a consumer needsread ↗
  96. 0096A table is the consumer's markup or the library's rows, and the first is dressed element by elementread ↗
  97. 0097A data table is a typed engine under the first layer, and it grows into a grid by directivesread ↗
  98. 0098A table's window is opt-in, and the rows it skips are two rows the body draws without elementsread ↗
  99. 0099A chart is scales the marks share, a mark is a slot, and a ready chart is a reciperead ↗
  100. 0100A chart draws in layers, and its data are decimated to the pixelread ↗
  101. 0101The window, the cursor and the selection are the application's modelsread ↗
  102. 0102A series owns its colour, and the colour is never its only channelread ↗
  103. 0103A chart is a named picture, and its cursor is the platform's rangeread ↗

257 lessons

What building this taught us, one entry per surprise — the builder's diary, published because an audit reads character from how mistakes are handled.

  1. 1Angular does not support the NX "TS-solution" layoutread ↗
  2. 2Test discovery globs from projectSourceRootread ↗
  3. 3Test target: vite:test for apps, test for the libraryread ↗
  4. 4The token build is a transform of our own, not Style Dictionaryread ↗
  5. 5A coverage threshold needs coverageIncluderead ↗
  6. 6The contrast guard let through a disabled state made with opacityread ↗
  7. 7Zoneless is declared explicitlyread ↗
  8. 8zone.js removed from the dependencies entirelyread ↗
  9. 9ControlValueAccessor turned out to be unnecessaryread ↗
  10. 10The contrast gate took in non-text pairs (SC 1.4.11)read ↗
  11. 11The Angular CLI MCP gives version-matched guidanceread ↗
  12. 12FormCheckboxControl requires checked, not valueread ↗
  13. 13getComputedStyle from a preview panel can be staleread ↗
  14. 14Formal conformance does not mean good qualityread ↗
  15. 15A part-name collision only surfaced in e2eread ↗
  16. 16Options in a group are projected content, not viewChildrenread ↗
  17. 17The scoped theme was broken at the component tierread ↗
  18. 18An overlay panel renders outside the host treeread ↗
  19. 19CSS.escape does not exist in jsdomread ↗
  20. 20On a native element DefaultValueAccessor leadsread ↗
  21. 21The same message logic in four controlsread ↗
  22. 22The frame's padding created a dead zoneread ↗
  23. 23page.mouse.click() does not scroll the pageread ↗
  24. 24The part-name collision repeated itself with the wrapperread ↗
  25. 25A wrapped select had a 19.6 px touch targetread ↗
  26. 26FormField supplies an NgControl itselfread ↗
  27. 27Patching the symptom left a dead zone visible in the cursorread ↗
  28. 28jsdom does not parse :has() with a relative combinatorread ↗
  29. 29A height computed from padding cannot be lined upread ↗
  30. 30A test can click server HTML before hydrationread ↗
  31. 31The id generator was unsafe under SSRread ↗
  32. 32A number field step computed from the DOM dropped keypressesread ↗
  33. 33The states view found a disallowed ARIA attributeread ↗
  34. 34The stylesheet guessed intent from a slot's contentread ↗
  35. 35The control handed the wrapper its frame but not its panelread ↗
  36. 36The package carried no skin while the pipeline shone greenread ↗
  37. 37A generic in a component does not mean the template checks itread ↗
  38. 38Playwright's idiomatic emulation silently does nothingread ↗
  39. 39A visual test can be born dead in two waysread ↗
  40. 40A state carried by background alone disappears in high contrastread ↗
  41. 41The tool had a "before" hook where a "after" one was neededread ↗
  42. 42The e2e project had never been typecheckedread ↗
  43. 43Reading a non-existent token gives an empty stringread ↗
  44. 44.nxignore does not disable a project, it removes a file from countingread ↗
  45. 45Removing a test raised coverageread ↗
  46. 46A partial declaration omits defaults, so OnPush can only be measured after linkingread ↗
  47. 47An inferred target is somebody else's decision about scope and looks exactly like your ownread ↗
  48. 48Two measurements guarding each other have to be INDEPENDENT, or they go dark togetherread ↗
  49. 49A snapshot does not close a promise about names, it freezes itread ↗
  50. 50A negative control proves a gate FIRES, not that it tells the truthread ↗
  51. 51A default a tool writes in cannot be removed, so a gate on its absence has no way to fireread ↗
  52. 52A pair nobody put in the policy is a pair the gate has no opinion aboutread ↗
  53. 53The visual gate has two budgets and only one was measuredread ↗
  54. 54An input's default value is a read at construction, even though the input is a signalread ↗
  55. 55A file that is in the package and a file that can be loaded are two different measurementsread ↗
  56. 56A media query fires even in an engine that cannot do what it asks aboutread ↗
  57. 57Coverage measures execution, not checking: 96.62% of lines is 63.54% of mutantsread ↗
  58. 58A gate that can fire and a gate that will fire are two different states — Stryker starts in the secondread ↗
  59. 59A task flaky under nx affected points at a shared directory, not at a time limitread ↗
  60. 60A scan is only as wide as its word list, and a hand-written list is narrower than its author thinksread ↗
  61. 61A copy carries its citations with it, so "is this file mentioned?" cannot see a dead treeread ↗
  62. 62A condition in a template is measured by nobodyread ↗
  63. 63A gate whose input is not a file cannot be cached, and a cached one answers from before the changeread ↗
  64. 64The published manifest is not the manifest anybody wroteread ↗
  65. 65An audit of the rendered page measures the pages you wrote, not the component you shippedread ↗
  66. 66When the only witness of a defect is somebody else's diagnostic, the cheap fix silences itread ↗
  67. 67A comment in a template is shipped; a comment in TypeScript is notread ↗
  68. 68A warning about a second one needs to be told when the first one leftread ↗
  69. 69A rule that fires on the way to something else is not the rule you think you haveread ↗
  70. 70A media query adds no specificity, and the browser it is written for hides thatread ↗
  71. 71Four coverage metrics, and each was blind to what another one caughtread ↗
  72. 72A content query sees the option before its inputs are boundread ↗
  73. 73A partially compiled package is not what an application carriesread ↗
  74. 74The obvious denominator for "used" would have deleted a live axisread ↗
  75. 75Eleven of twenty rows were wrong in the list a hand had just fixedread ↗
  76. 76Both modes were tested; that the two disagree belonged to neither testread ↗
  77. 77Two dictionaries, and the word that belongs to neitherread ↗
  78. 78A threshold decides two things and is argued about oneread ↗
  79. 79The message that names what moved is the message that stopped comparing the fileread ↗
  80. 80A shape may be named to see a class, never to stop seeing oneread ↗
  81. 81A gate reading modules cannot answer a question about bytesread ↗
  82. 82The wider event is not the safer guardread ↗
  83. 83The hiding was in a stylesheet nobody shipsread ↗
  84. 84A template's name and a template's context are two different checks, and no one shape gives bothread ↗
  85. 85A registry of markup is a registry of components, and a name in a string is checked when the string is a valueread ↗
  86. 86A shared kernel is where a cost stops being visibleread ↗
  87. 87The dependency a library can require without depending on itread ↗
  88. 88A gate's order is the repair it advisesread ↗
  89. 89The platform's modal is not composable with the library's overlaysread ↗
  90. 90What a modal must NOT silenceread ↗
  91. 91The name of a control is often in another elementread ↗
  92. 92A name that comes and goes is not a nameread ↗
  93. 93The outside press and the trigger's press are one eventread ↗
  94. 94An effect that reads what it writes: one consumer pays a pass, two never finishread ↗
  95. 95A host listener cannot stop a listener the template registered firstread ↗
  96. 96Projected content keeps the encapsulation of the template that declared itread ↗
  97. 97Two elements of one template are two instantiations, and neither is evidence about the otherread ↗
  98. 98Projected rows belong to the consumer's view, so the panel never owns how many existread ↗
  99. 99A two-way binding is checked in the read direction onlyread ↗
  100. 100A base class hides half a component from every gate that reads one class bodyread ↗
  101. 101Whether an accent is a letter is a question of language, and the trick that pretends otherwise folds half the alphabetread ↗
  102. 102An exception outlives the reason it names, and reads as a limit of the environmentread ↗
  103. 103A template reference inside a control-flow block cannot be seen from outside itread ↗
  104. 104A <button> inside a <button> is two buttons, and only the parser says soread ↗
  105. 105A positioning context is a paint layer, and the text inside one loses its subpixel antialiasingread ↗
  106. 106An empty listbox is a critical violation, and aria-busy is the specification's way of saying "not yet"read ↗
  107. 107A cursor kept as a number survives only a list that changes on a keystrokeread ↗
  108. 108offsetHeight is an integer, and a list is arithmetic over a fractionread ↗
  109. 109Two repairs in one run, and the count of red cases cannot say which one workedread ↗
  110. 110An effect that follows the cursor must be woken by the cursor aloneread ↗
  111. 111Two engines lay out on two grids, so a measured value is compared with a tolerance and never roundedread ↗
  112. 112An ARIA attribute over a native state is written by us and read by nobodyread ↗
  113. 113A finding written down is an input to the gate that found itread ↗
  114. 114NgControl.valueChanges is null for the whole of a sibling directive's constructorread ↗
  115. 115Build the optional part of a fallback last, or its absence takes the rest with itread ↗
  116. 116An element screenshot's height depends on where the element startsread ↗
  117. 117The forms interop writes null into a model typed number, and nothing says soread ↗
  118. 118getComputedStyle(el, '::before') answers for an element that renders no ::beforeread ↗
  119. 119Forced-colors mode is a request, and each engine honours a different part of itread ↗
  120. 120A fallback checked against the platform it falls back FROM is checked against nothingread ↗
  121. 121A control that vanishes on a timer takes the user's place on the page with itread ↗
  122. 122A z-index cannot get above the top layer, and the number that says it can is the dependency'sread ↗
  123. 123An ignored mutant is still instrumented, and a static attribute is where that showsread ↗
  124. 124A required input read from a sibling's host binding throws, and @for is where that happensread ↗
  125. 125The testing tool's accessibility tree is not the browser'sread ↗
  126. 126overflow: auto makes an element focusable in two engines of threeread ↗
  127. 127A heading inside a <summary> survives, because a <summary> is not a buttonread ↗
  128. 128preventDefault() is the only way to refuse a disclosure, and it takes the keyboard with itread ↗
  129. 129A page the browser is not rendering has a frozen clock, and every transition on it reads as brokenread ↗
  130. 130A state attribute lands when the motion starts, not when it endsread ↗
  131. 131A clamp swallows the change it was written to correctread ↗
  132. 132An apostrophe in a comment is a quote to a scanner, and the gate then names an innocent fileread ↗
  133. 133A switch that turns a drawing off turns a behaviour off with it, and the three engines disagree about what is leftread ↗
  134. 134Forced colours keep a background colour and drop a gradient, so what a state is painted WITH decides whether it survivesread ↗
  135. 135A spy on an already-spied method is the same spy, so a per-case spy without a restore is one spy for the fileread ↗
  136. 136A placeholder measured in 1lh holds exactly the space the text will take, and one measured in pixels holds a guessread ↗
  137. 137overflow: hidden takes focus in no engine, where overflow: auto takes it in two of threeread ↗
  138. 138An empty list passes the audit that fails an empty listbox, so the machinery has to be sized to the exact roleread ↗
  139. 139WCAG 2.5.8's inline exception ends where the sentence does, and axe measures the bar you thought was typographyread ↗
  140. 140A listitem computes no name from its contents, so what a reader "hears" is measured as content, not as accessible nameread ↗
  141. 141Playwright's visibility is not the platform's checkVisibility(), and content-visibility is where they partread ↗
  142. 142A bare file name reaches a file only while the name is unique, and the first copied app tree ends thatread ↗
  143. 143A scoped formatter on a clean tree formats nothing, and a green battery says nothing about itread ↗
  144. 144A box that overhangs a scroll container by one pixel is a scrollbarread ↗
  145. 145A container query answers for an ancestor, never for the element that asksread ↗
  146. 146Inline-size containment makes a box's intrinsic width zero, and a column in a parent sized by its content collapses to its gutterread ↗
  147. 147A part-dressing rule scoped by the shared part name leaks onto every projected component that parts the same nameread ↗
  148. 148A component's token overrides, set on a host that contains a projected instance of the same component, inherit into itread ↗
  149. 149Two equal readings are not stillness: a scroll comes to rest in frames, not in round tripsread ↗
  150. 150content-visibility: hidden hides the contents; the box, and its padding, stayread ↗
  151. 151Encapsulation scopes a selector to a COMPONENT, not to an instance: a component that can hold itself must reach its parts by structureread ↗
  152. 152A click returns before the panel it opened has taken focus, and the key pressed on that round trip goes to the openerread ↗
  153. 153A key pressed where the handler cannot hear it proves the opposite of what the case claims: the drawer's closeOnEscape=falseread ↗
  154. 154A generated file the hasher cannot see is a build that goes stale without ever going redread ↗
  155. 155A screenshot freezes the animation, not the class that starts itread ↗
  156. 156A -webkit- shorthand is an alias, and an alias undoes the longhand above itread ↗
  157. 157Emulated encapsulation rewrites the selector, so it rewrites the specificityread ↗
  158. 158A box painted over a transparent control is the box the pointer lands onread ↗
  159. 159The router scrolls to an anchor by arithmetic, and reads no CSS while doing itread ↗
  160. 160A demo whose content has no width of its own has no width in a centred stageread ↗
  161. 161A signal written after the first render is a second render for everybody, and so is a view attached thenread ↗
  162. 162A rule on the inputs of an imprecise read is the workaround written downread ↗
  163. 163A platform rule written from memory is a claim, and the platform's own answer is the detectorread ↗
  164. 164A flake's record names the line the stack names, not the line the story ends onread ↗
  165. 165A blanked element is still a layer, and taking the layer away moved four pictures in another columnread ↗
  166. 166A host listener cannot get in front of the consumer's own, and a disabled link needs it toread ↗
  167. 167A drifting gradient's travel is its size written twice, and one frozen picture cannot see the differenceread ↗
  168. 168A reader keyed on the property name cannot see the colour inside a valueread ↗
  169. 169A comment is input, and one repository can need it read both waysread ↗
  170. 170An interface whose members are all optional proves nothing, and implements looks like proofread ↗
  171. 171A string equal to a selector is not a component, and a probe that skips the linker measures the wrong packageread ↗
  172. 172Half a cache is not half a speed-up: one half restores nothing, the other restores a green with no artifactread ↗
  173. 173providers on a component pin it into its entrypoint, and a consumer who never named it pays for it wholeread ↗
  174. 174Twelve mechanisms taken out one at a time: what a suite holds is not what its case names sayread ↗
  175. 175The four criteria nobody measured: three defects, and two of them belonged to the harnessread ↗
  176. 176The template that has no parent: a report that had to stop asking DIread ↗
  177. 177Eleven floors, and every one of them measured for the first timeread ↗
  178. 178Motion that ends, and the order of three ways to stop itread ↗
  179. 179Thirty-five bytes with three suspects, all three refutedread ↗
  180. 180Four names at once, and the gate that could not see inside a switchread ↗
  181. 181A key nobody may install, and the hole in the honest defaultread ↗
  182. 182A gate that cannot start is a gate nobody hears stopread ↗
  183. 183A pause is true before it is visible, and webkit reports it in that orderread ↗
  184. 184The server under the suite is a client of the page, and it can navigate itread ↗
  185. 185A day's string is not fixed-width, and two functions had assumed it wasread ↗
  186. 186A sweep's seed belongs to the mutation snapshot, and its shrink is a leadread ↗
  187. 187Nine green properties, four mutants aliveread ↗
  188. 188The battery is a habit, not a list, and what it omits goes red in silenceread ↗
  189. 189A plan item can be stale in the direction of DONEread ↗
  190. 190"Enabled somewhere" is not a placement ruleread ↗
  191. 191The backstop named in the rules has not run in 144 commitsread ↗
  192. 192A measurement taken once became a constant, and the constant was the flakeread ↗
  193. 193A gate's reader is shared, so its blind spot is every point'sread ↗
  194. 194A denominator counted in the unit the code declares is not the unit the promise is aboutread ↗
  195. 195Determinism is not a statement about a generatorread ↗
  196. 196A list that decides what a gate looks at is a denominator nobody measuresread ↗
  197. 197A closed drawer is not an empty oneread ↗
  198. 198A case that asserts on the grid the real clock draws is a bomb with a date on itread ↗
  199. 199Proving a mutant equivalent by hand means compiling it, and a kill can still be reported as a survivorread ↗
  200. 200The mutation run's worker count is a fact about this machine, and it stands in no fileread ↗
  201. 201Which mutant the clock is holding says whether the wobble is a timing defect or a missing assertionread ↗
  202. 202There is a family of cases that fails only under the suite, and it is a shape, not a componentread ↗
  203. 203An accepted sketch is transferred, not interpreted, and the suite cannot tell the differenceread ↗
  204. 204A property sweep's gain can be invisible to the mutation scoreread ↗
  205. 205A survivor is a span, not a line: three mutants shared a start column and only one of them livedread ↗
  206. 206A dry run three seconds under its ceiling is a gate whose verdict the machine decidesread ↗
  207. 207A case built on the live input has to pin both sides of what it comparesread ↗
  208. 208A screen reader driven headlessly stands between you and the keyboardread ↗
  209. 209Three hypotheses about a flaky instrument, and all three were wrongread ↗
  210. 210The guard fired correctly and handed over a false causeread ↗
  211. 211When the symptom alternates, vary the count, not the magnituderead ↗
  212. 212A file name can make a repository un-clonable, and only a machine you do not own will say soread ↗
  213. 213A keystroke the instrument did not make is one it cannot reportread ↗
  214. 214Two jobs of one run gave two verdicts on the same four casesread ↗
  215. 215Uniting two walks made an absent field present, and ?? reads absenceread ↗
  216. 216The register counted one spelling of a row, and the criterion counted a fourthread ↗
  217. 217Focus moved in the keypress; the tab ORDER moved one render laterread ↗
  218. 218The template argued what a reader hears, and no reader agreedread ↗
  219. 219The reader was asked what it had said, and answered with its bufferread ↗
  220. 220The release commit carried the changelog and nothing elseread ↗
  221. 221The report changed, and two cache keys did not noticeread ↗
  222. 222Nine green ticks, and nx had said nothingread ↗
  223. 223The consumer gate published to a registry that knew the public oneread ↗
  224. 224The window had focus and did not know itread ↗
  225. 225The link was there, and the pointer could not reach itread ↗
  226. 226The gate had not read the file, because git had notread ↗
  227. 227The shell held the stage, and the desktop never showed itread ↗
  228. 228The pipe dropped the verdictread ↗
  229. 229The gate's judge had a control; its readers had noneread ↗
  230. 230A target passed because the directory happened to be thereread ↗
  231. 231Four silent minutes, and two readings of themread ↗
  232. 232The ceiling named the moment, and the case it named was innocentread ↗
  233. 233Twice a superlative was put on a population that had been narrowedread ↗
  234. 234A shorthand is a reset, and it reached over a face that had drawnread ↗
  235. 235The absence had a reason, and the gate's comment had guessed itread ↗
  236. 236Six defects, one cause: the scan was a second lexerread ↗
  237. 237A guard is invisible to every case that carries what it filtersread ↗
  238. 238A false measurement is worse than none, because it closes the questionread ↗
  239. 239A measurement nobody looked at the machine for is a measurement of the machineread ↗
  240. 240One cache for every worktree, and a report that names its ownread ↗
  241. 241A repair made to one case of a file, and the file kept its other copiesread ↗
  242. 242The rehearsal was held to a stamp it cannot makeread ↗
  243. 243The release commit moved the manifest, and the rendering that embeds it stood stillread ↗
  244. 244The table cited a spec by the component's name, and nothing ever opened the specread ↗
  245. 245The key followed the window, and two readings had blamed the keyread ↗
  246. 246The rule saw a shape and the repair a cause, and neither walked the causeread ↗
  247. 247The index was the input, and the hash was the tree'sread ↗
  248. 248A component in a barrel is paid for by every importer, measured a second timeread ↗
  249. 249A centred stage that shrink-wraps its demo moves the control the reader just pressedread ↗
  250. 250A static mutant is priced by the tests it runs, not by its countread ↗
  251. 251A narrow run measures a file as the full one does, and the desk paid for the wholeread ↗
  252. 252A mutant that stops a module from loading is recorded as a survivor that ran nothingread ↗
  253. 253A factory call at the top of the shared chunk is paid by every entrypoint, until it is marked pureread ↗
  254. 254A spec file that fails outside its tests is one failed test, under either runnerread ↗
  255. 255A cache step that repeats the tool's default path keeps saving it after the tool movesread ↗
  256. 256Two hooks that place focus in one render: the later one wins, and a unit suite renders between keysread ↗
  257. 257Making a name unique among decorated classes does not make it mean one classread ↗