test / unit + widget + golden + a11y (push) Failing after 31s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 1m2s
pql 1.4.30 introduces a per-type subdirectory layout for decision
records: governance/{decisions,questions,rejected}/<domain>.md. The
parser infers record type from the parent subdir and domain from
the filename stem, replacing the flat decisions/<file>.md layout
with questions-X and rejected prefixes.
Moves:
- 6 D-files to governance/decisions/ (accessibility, architecture,
extensions, process, testing, tooling)
- 5 Q-files to governance/questions/ (stripped the questions- prefix)
- rejected.md split by domain to governance/rejected/{architecture
(5), process (4), accessibility (1), testing (1)}.md — split per
cross-reference target.
Drops:
- decisions/README.md (auto-regenerated as governance/README.md by
pql init below the records marker)
- decisions/questions.md (hand-curated index pointing at the per-
domain files; redundant once pql generates the index, and the
"load-bearing" curation was already present in each Q-record's
Context field).
Convention-driven; not a clide-specific change. Counts unchanged
across migration: 106 decisions, 95 tickets, 134 refs, 0 broken.
Co-Authored-By: Claude <noreply@anthropic.com>
2.5 KiB
2.5 KiB
Accessibility + i18n Decisions
A11y + i18n are Tier-0 contracts, not Tier-6 polish.
D-20: A11y is a Tier-0 contract
- Date: 2026-04-21
- Decision: Every widget primitive wraps its interaction surface in a
Semanticsnode at the point of creation. A11y coverage is a test-time gate (ci/test_a11y.sh), not a post-hoc polish pass.ensureSemantics()fires at app boot; Flutter's semantics tree is always populated. - Rationale: Retrofitting a11y onto a grown UI is what every project that skips this promises to do later and then doesn't. Making it a Tier-0 contract costs one
Semanticsline per primitive and a semantic-coverage test; postponing costs a rewrite. - Cost: Widget authors maintain correct labels; tests reject new primitives without semantics. Enforced by
test/a11y/coverage tests. - Raised by: 2026-04-21 planning.
D-21: i18n is a Tier-0 contract (fframe pattern + locale-fallback chain)
- Date: 2026-04-21
- Decision: All user-facing strings resolve through a namespaced i18n catalogue loader ported from fframe's text-driven pattern, extended with a locale-fallback chain fframe lacks. JSON per locale;
I18n.of(context).t('namespace.key', {vars}). Missing keys resolve down the chain (e.g.en_GB→en→ default), never fail silently; missing at the base locale logs a dev-mode error. - Rationale: Flutter's
intl+ ARB codegen is inflexible for plugin-contributed catalogs (see R-4) — we need per-extension catalogs that merge without a codegen step. fframe's shape fits; its silent-fallback behaviour does not, so we add the chain. - Cost: JSON has no comments and no trailing commas; translation tooling has to accept that. Separate
i18nfacade on every feature. - Raised by: 2026-04-21 planning.
D-22: WCAG-AA contrast gate on bundled themes
- Date: 2026-04-21
- Decision: Every bundled theme must pass a WCAG-AA contrast check on its canonical token pairs (text/background, link/background, focus-ring/background) at test time.
ci/test_a11y.shruns the gate; CI fails on regressions. - Rationale: Themes drift under "looks nicer" tweaks; contrast regressions land silently. Running the gate on every PR is the cheapest insurance. Ran the gate on initial themes — caught one summer-night muted token at 2.81:1 (below AA), fixed before landing.
- Cost: Third-party themes (Tier 6) won't be gated until an extension-time test hook lands. Bundled themes are gated today.
- Raised by: 2026-04-21 planning.