Skip to content

docs(design): de-slop + enrich DESIGN.md (#539 bundle 3) - #557

Merged
thomasluizon merged 2 commits into
mainfrom
feature/539-design-md-deslop
Jul 17, 2026
Merged

thomasluizon merged 2 commits into
mainfrom
feature/539-design-md-deslop

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Bundle 3 of #539. Docs only: no application code changed. Two files touched, DESIGN.md and the CLAUDE.md docs-registry row (plus its Brand & design pointer, which the repo requires to move in the same edit).

DESIGN.md is rewritten against two inputs: the owner-approved 2026-07-17 Today-view design freeze (spec .claude/specs/issue-539.spec.md, Decisions section) and the vault canonical note Orbit skill harvest - canonical rule set (#539). The freeze wins over every harvested rule.

Removed (the de-slop)

  • The primary glow token (0 8px 28px rgba(var(--primary-rgb),0.45)) and every "pill CTAs with glow" instruction, on the PillButton primary variant, the FAB, and the identity line. Purged as a concept, not softened. The 0.45 glow alpha is gone from the primary-tint list.
  • --gradient-header (both modes), the GradientTop primitive, the gradient-header usage list, and the per-scheme gradient-stop derivation rule + hand-tune entry.
  • The violet-tinted canvas anchor (neutralHue 265.1322, #020618 slate-950) and the old accent #7f46f7.
  • The "navy-cosmic, violet-glow character" target in the scene-sentence test.

Added

  • Frozen tokens: canvas #070910, the white-alpha surface ladder resolved (#111319 card / #16181E well / #1F2128 elev-2), fg ramp #F6F7F9/#C7CBD2/#888E99/#565C67, hairlines 0.08 / 0.10 ghost / 0.16, accent #8659EA + --primary-soft #B69BF8 + --primary-dim + --primary-pressed.
  • The accent split and WHY it exists: the two AA floors contradict (white-on-accent needs a dark violet, accent-as-text needs a light one), so the roles split rather than the colour compromising. Carries the three measured ratios (4.54 / 4.38 / 8.6) and states explicitly that a blanket "primary as text >= 4.5" assertion would false-fail a fill-only accent. This is exactly what the accent-AA gate asserts.
  • The habit-list grouped tonal-panel treatment, the 2-levels-inline + violet-› drill-in, zero connector lines, and both fidelity carve-outs (the per-row ⋮ stays; emoji render in full colour).
  • Accent rationing as an explicit closed list. Ring indicators / logo / Astra glyph as the only identity carriers.
  • A base-4 spacing scale (there was none), with gap-only mechanics and one honest exemption for BUTTON_SIZES.
  • A 45-75ch measure rule (~65ch), plus text-wrap balance/pretty and the <br> ban.
  • The loading / empty / error triad, wired to the Satellite glyph primitive that already existed to serve it.
  • A motion frequency gate and a closed list of legitimate animation purposes, plus the removal test and the delete-outranks-tuning remediation order. This is a net subtraction of motion, matching the Design restraint pass: less glow, fewer dividers, spacing + de-slop DESIGN.md + improve-ui/emil #539 direction.
  • A full ## Accessibility section (perception / keyboard+focus / semantics / forms / announcements). Orbit has no a11y gate today.
  • A squint test alongside the AI-slop and scene-sentence tests, and a rewritten scene-sentence target.
  • ## Enforcement: which rules are gate-backed (with the concrete mechanism), which are design-reviewer judgment, and which need the live DOM. Bundle 4 implements against this table. No lint rule or hook was written here.

Harvested rules landed

86 total: 62 routed to DESIGN.md, 24 routed to DESIGN.md:a11y. Every row of both tables landed; nothing was dropped for taste.

Note the canonical note's own section headers say "46 rules" and "22 rules" (and the spec's routing tally repeats those figures), but the tables actually carry 62 and 24 rows. The headers are stale; the rows are the real set and are what shipped.

Contradictions with the freeze

None survived into my two buckets. The harvest's upstream drop pass held: the ~40 skills that attacked the de-decorated base, the ~12 that attacked the purple accent, and the ~14 that attacked Inter were all dropped before routing. Two near-misses worth recording, both already resolved upstream and encoded here consistently:

  • Overshoot / bounce easing was independently proposed by 4 skills and dropped every time. It lands here as a ban plus a bundle-4 lint (local/no-overshoot-easing), and the spring rule is stated as critically-damped-by-default with no overshoot.
  • OKLCH chroma matching conflicts with locked derivation rule 2 and was dropped; only the L-only contrast fix survives, which is now the documented method for reaching AA without drifting a locked hue.

Known follow-ups (not this PR)

  • local/no-arbitrary-zindex is blocked: the semantic stacking scale does not exist in the theme tokens, so the gate has nothing to allowlist against. Flagged in ## Enforcement; bundle 4 must land the scale first.
  • Every per-scheme byte and every AA measurement other than the purple/dark ones stated in the doc must be recomputed against the new anchors in bundle 5. An explicit recompute note says so rather than letting a pre-freeze byte be assumed still valid.
  • orbit-landing-page's mirrored token block still carries the #22094f → transparent gradient header and the glow CTAs. That is a sibling-repo code change and belongs to bundle 5's paired PR.

Refs #539

🤖 Generated with Claude Code

https://claude.ai/code/session_01VPZnJcT1ZHoxUkxw7uhxY2

Rewrites DESIGN.md against the owner-approved 2026-07-17 Today-view
design freeze and the 193-skill harvest canonical rule set.

Removed: the primary-glow token and every "pill CTAs with glow"
instruction, the --gradient-header wash + the GradientTop primitive,
and the violet-tinted canvas anchor.

Added: the frozen tokens (#070910 canvas, #8659EA accent, #B69BF8
primary-soft, the 0.08/0.10/0.16 hairline set), the accent-split
rationale the accent-AA gate asserts, the habit-list tonal-panel
treatment, a base-4 spacing scale, a 65ch measure rule, the
loading/empty/error triad, a motion frequency gate + closed purpose
list, a full Accessibility section, a squint test, and an
## Enforcement section mapping gate-backed vs reviewer-judgment rules
so bundle 4 has a contract to implement against.

Docs only. No application code changed.

Refs #539

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPZnJcT1ZHoxUkxw7uhxY2
@vercel

vercel Bot commented Jul 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jul 17, 2026 5:32am

Request Review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #557

Scope: PR #557 in thomasluizon/orbit-ui-mobile
Recommendation: APPROVE

Summary

Docs-only PR (bundle 3 of #539): rewrites DESIGN.md against the 2026-07-17 owner-approved design freeze, adding ## Enforcement, ## Accessibility, ## Layout & spacing, and motion-governance sections, plus updates the CLAUDE.md docs-registry row and Brand & design pointer to match. No application code changed (confirmed against the diff: only CLAUDE.md and DESIGN.md touched). The rewrite is internally consistent, its load-bearing accessibility contrast math checks out under independent recomputation, and its file/tool references (hooks, ESLint rule, theme files) all resolve to real paths in the repo. One Medium finding: the new "Sections:" list in the At-a-glance header omits three real ## sections.

Findings

Critical

None.

High

None.

Medium

```
[MEDIUM] "At a glance" Sections list omits 3 real H2 sections

  • dimension: Correctness
  • location: orbit-ui-mobile/DESIGN.md:9
  • issue: The newly-added "Sections:" enumeration in the At-a-glance header lists 15 names (Identity, Tokens, Type, Layout & spacing, Primitives, Buttons, Surfaces, Habit list, States, Copy, Motion, Accessibility, Bans, Working model, Enforcement) but the file actually has 18 H2 sections. Missing: "Desktop density & orientation", "Sub-screen navigation", and "Special surfaces" (which carries the Paywall and Landing-hero rules).
  • risk: Root CLAUDE.md's docs registry explicitly instructs readers to "grep a doc's At a glance header before loading the whole file" -- a reader grepping this line for "paywall" or "special surfaces" guidance won't find it and may wrongly conclude DESIGN.md has no rule for that surface (it does, at lines 417-421 of the current file).
  • fix: Extend the Sections bullet to include the three missing entries, e.g. "... Copy, Desktop density, Sub-screen navigation, Motion, Accessibility, Special surfaces, Bans, Working model, Enforcement."
  • reference: root CLAUDE.md docs registry ("Grep a doc's At a glance header before loading the whole file")
    ```

Low / Info

  • The Tokens section states "the accent-AA gate asserts it directly" (present tense) in both DESIGN.md and the CLAUDE.md Brand & design pointer, while the new ## Enforcement table correctly lists the accent-AA test as bundle-4 future work. Not blocking -- the Enforcement section's own "Prose is not enforcement" disclaimer resolves the ambiguity -- but a future pass could soften the earlier mentions to "is designed to assert" for tense consistency.

Subagents

Agent Verdict
parity-checker N/A -- no apps/web or apps/mobile file changed
i18n-syncer N/A -- no i18n json or other user-facing strings changed
contract-aligner N/A -- no shared types / endpoints / orbit-api DTO changed
security-reviewer N/A -- no orbit-api code changed
design-reviewer N/A -- gate is apps/* / orbit-landing-page UI files; this diff only touches the spec doc itself

Validation

Check Result
Lint N/A -- docs-only PR, no lintable source files changed
Type check N/A -- no .ts/.tsx changed
Tests N/A -- no test-relevant code changed
Build (api) N/A -- orbit-api untouched

Deferred -- N/A dimensions & files not verdicted

  • Dimensions 2 (Dead/stale code), 3 (SOLID/clean-arch), 5 (No-workaround), 6 (Type safety), 7 (No console.log): N/A -- diff contains no application source code, only Markdown prose.
  • Dimension 4 (Comment policy): N/A -- local/no-comments targets code comments; Markdown prose is out of its scope.
  • Dimension 8 (DESIGN.md/AI-slop): N/A per the rubric's own literal gate ("only when the diff touches apps/* UI files") -- this diff is the spec document itself, not a UI implementation.
  • Dimensions 9 (Parity), 10 (i18n), 11 (Contract drift), 12 (Security), 13 (Backend hard rules): N/A -- surfaces untouched by this diff.
  • Dimension 14 (FEATURES.md parity): N/A -- a design-language/spec rewrite with zero shipped behavior change; the rubric explicitly N/As "visual polish with no behavior change."
  • Both changed files (CLAUDE.md, DESIGN.md) were read in full (pre- and post-diff) and given a verdict above. Nothing changed was left unverdicted.
  • Spot-verified (not merely trusted): the three WCAG contrast-ratio claims in the new accent-split table (white/#8659EA = 4.54:1, #8659EA/#070910 = 4.38:1, #B69BF8/#070910 = 8.6:1, plus the light-mode 6.71:1 claim) all recompute correctly by the WCAG relative-luminance formula. Also verified every newly-referenced file path (packages/shared/src/theme/button.ts, apps/web/app/globals.css, apps/mobile/lib/theme.ts, gradient-top.tsx, habit-row.tsx, satellite-glyph.tsx, color-schemes.ts) and every hook/lint rule marked "Already shipping" in the new Enforcement table (forbid-em-dashes.mjs, forbid-hardcoded-brand-color.mjs, no-fullbleed-button.cjs) exist in the repo as claimed.

What's good

  • The rewrite is unusually rigorous for a docs PR: the PR body self-discloses a stale figure in an upstream vault note (46/22 rules vs. the actual 62/24 rows) rather than silently carrying the error forward.
  • The new Enforcement table is exactly the right structure for a spec this large -- it stops the doc from being "prose as aspiration" by explicitly marking what's gate-backed today, what's bundle-4 future work, what's design-reviewer judgment, and what needs a live DOM.
  • Every deleted concept (--gradient-header, GradientTop, the primary-glow shadow, the 0.45 glow alpha) is called out explicitly as deleted rather than merely omitted, preventing the doc from silently going stale when a reader diffs old vs. new.
  • No em dashes survive anywhere in the ~500 added lines, consistent with the doc's own em-dash ban and the forbid-em-dashes.mjs hook.
  • The accent-split rationale (why --primary and --primary-soft must be two tokens) is the single most load-bearing decision in the doc, and its three cited contrast ratios are all mathematically correct -- exactly the kind of claim that's easy to eyeball wrong, and this one is right.

Recommendation

Merge as-is; the one Medium finding is a one-line fix to the At-a-glance header's Sections list and does not block. Fold it in now or in bundle 4/5 when the doc is next touched.

- MEDIUM: the At-a-glance "Sections:" list omitted 3 real H2 sections
  (Desktop density & orientation, Sub-screen navigation, Special surfaces).
  Root CLAUDE.md tells readers to grep this header before loading the file,
  so an omission means a reader looking for the paywall rule concludes there
  isn't one. Now lists all 18 using the exact ## names, so the line is
  actually greppable rather than approximately so.
- LOW: softened two present-tense claims that the accent-AA gate asserts the
  token split. It does not exist yet; bundle 4 builds it.
@sonarqubecloud

Copy link
Copy Markdown

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #557

Scope: docs(design): de-slop + enrich DESIGN.md (#539 bundle 3) — docs-only, CLAUDE.md (4 lines) + DESIGN.md (513 lines) against the 2026-07-17 owner-approved design freeze. No application code changed.
Recommendation: APPROVE (no Critical/High findings)

This is a re-review after the follow-up commit bcadbf4e ("address review findings on #557"), which folded in fixes for the prior review's Medium/Low findings. I re-verified those fixes rather than re-flagging what was already reported, and re-derived the load-bearing accessibility contrast-ratio math independently (white-on-#8659EA = 4.54:1, #8659EA-on-canvas = 4.38:1, #B69BF8-on-canvas = 8.6:1) — all correct.

Findings

Critical / High

None.

Medium

1. The "fixed" At-a-glance Sections list still doesn't match the real ## header text (DESIGN.md:9)
bcadbf4e's commit message claims the Sections line now uses "the exact ## names, so the line is actually greppable." It doesn't, for 3 of 18 entries:

  • Line lists Identity & anchor — real header is ## Identity & anchor (locked)
  • Line lists Habit list — real header is ## Habit list (frozen treatment)
  • Line lists Special surfaces (paywall, landing hero) — real header is plain ## Special surfaces
    Root CLAUDE.md tells readers to grep this line before loading the file; a reader grepping the literal header text for (locked), (frozen treatment), or the paywall/landing-hero parenthetical won't find it. Low severity given the doc is still readable end-to-end, but worth a follow-up one-line fix since this is the second pass at the same line.

2. apps/web/app/globals.css:6 still claims design/handoff/ is the token source of truth
This PR removes every reference to design/handoff/ from DESIGN.md and CLAUDE.md, making DESIGN.md itself (+ globals.css/theme.ts) the sole authority — but globals.css:5-6 still reads ORBIT DESIGN SYSTEM — navy+violet (design/handoff canon) / Token source of truth: design/handoff/orbit/project/orbit-fig.css. That's now a direct, unresolved contradiction of this PR's own new authority model, in a file this PR didn't touch.

3. design/handoff/ (~30 vendored Figma-export files) is now fully orphaned
After this PR, nothing in the repo references it as authoritative (previously DESIGN.md itself pointed here for token/dimension canon). It wasn't deleted or marked historical, so it will silently rot as stale "shadow" documentation.

Low / Info

None outstanding — the prior review's Low finding (present-tense claims about the not-yet-built accent-AA gate) was fixed correctly in bcadbf4e.

Subagents

All N/A — diff is limited to CLAUDE.md + DESIGN.md; no parity/i18n/contract/security/design-reviewer gate fires on a spec-doc-only change.

Validation

N/A per this workflow's CI adaptation — Build / Unit Tests / SonarCloud run as separate required checks on this PR.

Recommendation

Merge as-is. The three Medium findings are docs-consistency gaps (a greppability regression that survived its own fix pass, plus a newly-orphaned directory and a newly-contradicted comment elsewhere in the repo) — none touch application behavior, security, or contracts. Worth folding into the next bundle (4/5) when DESIGN.md or globals.css is next touched.

thomasluizon added a commit that referenced this pull request Jul 17, 2026
Turns the checkable half of the #539 skill harvest into real gates. The
canonical rule set (brain vault, "Orbit skill harvest — canonical rule set
(#539)") routed 217 rules to durable homes; this lands the gate: and
rules: buckets. DESIGN.md prose (bundle 3, #557) is the intent; this is the
enforcement.

ESLint local/* (21 hand-written rules + the enable-don't-write jsx-a11y set),
wired into all three flat configs, 100 RuleTester assertions:
- Severity is STAGED against measurement, never by weakening a rule. Rules
  the codebase already passes land at error. no-decorative-glow (19 web /
  10 mobile) and no-raw-gradient (27/26) land at warn because bundle 5 has
  not de-decorated the code yet; that PR flips them to error. Pre-existing
  backlogs (no-space-x-y 63, require-focus-replacement 17 real WCAG 2.4.7
  bugs, react19-api 18, ...) are surfaced at warn rather than silenced.
- Found a real production bug: apps/web/app/(auth)/login/login-atoms.tsx:3
  builds a dynamic Tailwind class that is purged from the production
  stylesheet. Green locally, unstyled in prod.

Hooks (logic in _lib/, mirrored into .opencode/plugin/orbit-guardrails.js,
registered in settings.json, covered in test-hooks.mjs):
forbid-ai-cliche-copy, forbid-placeholder-content, forbid-typed-uppercase,
forbid-secret-in-argv (PreToolUse, fails closed). Each was run against the
real 2466-string i18n corpus; the FP rate is pinned as a corpus guard.

Rules tier: .claude/rules/ created (it did not exist) with the 39 standing
non-checkable rules, themed by activity. design-reviewer resynced to
DESIGN.md's Reviewer-judgment list.

Deliberately NOT shipped, with evidence:
- forbid-straight-punctuation: the corpus refutes it (148 straight
  apostrophes vs 1 curly; DESIGN.md mandates nothing here). It would block
  shipped copy. Needs a design decision first.
- no-arbitrary-zindex: blocked on a semantic stacking scale that does not
  exist; inventing it is a design decision on a frozen doc.
- the barrel ban: contradicts packages/shared/CLAUDE.md, which mandates
  barrel imports.
- half of animate-presence-exit: statically undecidable (fired 2-for-2 on
  correct code). The sound half found a real silent bug.

Fixture note: the secret-in-argv tests use EXAMPLE-NOT-A-REAL-TOKEN values.
The patterns match the flag, not the value, so nothing that reads as a
credential needs to exist in this repo's history.

Verification: test-hooks 193/193 PASS · turbo run lint 3/3, 0 errors ·
turbo run test web 2536/2536 + eslint-rules 100/100.
thomasluizon added a commit that referenced this pull request Jul 17, 2026
Turns the checkable half of the #539 skill harvest into real gates. The
canonical rule set (brain vault, "Orbit skill harvest — canonical rule set
(#539)") routed 217 rules to durable homes; this lands the gate: and
rules: buckets. DESIGN.md prose (bundle 3, #557) is the intent; this is the
enforcement.

ESLint local/* (21 hand-written rules + the enable-don't-write jsx-a11y set),
wired into all three flat configs, 100 RuleTester assertions:
- Severity is STAGED against measurement, never by weakening a rule. Rules
  the codebase already passes land at error. no-decorative-glow (19 web /
  10 mobile) and no-raw-gradient (27/26) land at warn because bundle 5 has
  not de-decorated the code yet; that PR flips them to error. Pre-existing
  backlogs (no-space-x-y 63, require-focus-replacement 17 real WCAG 2.4.7
  bugs, react19-api 18, ...) are surfaced at warn rather than silenced.
- Found a real production bug: apps/web/app/(auth)/login/login-atoms.tsx:3
  builds a dynamic Tailwind class that is purged from the production
  stylesheet. Green locally, unstyled in prod.

Hooks (logic in _lib/, mirrored into .opencode/plugin/orbit-guardrails.js,
registered in settings.json, covered in test-hooks.mjs):
forbid-ai-cliche-copy, forbid-placeholder-content, forbid-typed-uppercase,
forbid-secret-in-argv (PreToolUse, fails closed). Each was run against the
real 2466-string i18n corpus; the FP rate is pinned as a corpus guard.

Rules tier: .claude/rules/ created (it did not exist) with the 39 standing
non-checkable rules, themed by activity. design-reviewer resynced to
DESIGN.md's Reviewer-judgment list.

Deliberately NOT shipped, with evidence:
- forbid-straight-punctuation: the corpus refutes it (148 straight
  apostrophes vs 1 curly; DESIGN.md mandates nothing here). It would block
  shipped copy. Needs a design decision first.
- no-arbitrary-zindex: blocked on a semantic stacking scale that does not
  exist; inventing it is a design decision on a frozen doc.
- the barrel ban: contradicts packages/shared/CLAUDE.md, which mandates
  barrel imports.
- half of animate-presence-exit: statically undecidable (fired 2-for-2 on
  correct code). The sound half found a real silent bug.

The secret-in-argv fixtures are assembled from parts rather than spelled
out, the same idiom this file already uses for NV / MARK / EM: a test file
cannot contain the literal strings its own guards detect. Here the detector
is the required GitGuardian check, which matches a credential's SHAPE, not
its entropy, so no real value is needed and none exists.

Verification: test-hooks 193/193 PASS · turbo run lint 3/3, 0 errors ·
turbo run test web 2536/2536 + eslint-rules 100/100.
thomasluizon added a commit that referenced this pull request Jul 17, 2026
Turns the checkable half of the #539 skill harvest into real gates. The
canonical rule set (brain vault, "Orbit skill harvest — canonical rule set
(#539)") routed 217 rules to durable homes; this lands the gate: and
rules: buckets. DESIGN.md prose (bundle 3, #557) is the intent; this is the
enforcement.

ESLint local/* (21 hand-written rules + the enable-don't-write jsx-a11y set),
wired into all three flat configs, 100 RuleTester assertions:
- Severity is STAGED against measurement, never by weakening a rule. Rules
  the codebase already passes land at error. no-decorative-glow (19 web /
  10 mobile) and no-raw-gradient (27/26) land at warn because bundle 5 has
  not de-decorated the code yet; that PR flips them to error. Pre-existing
  backlogs (no-space-x-y 63, require-focus-replacement 17 real WCAG 2.4.7
  bugs, react19-api 18, ...) are surfaced at warn rather than silenced.
- Found a real production bug: apps/web/app/(auth)/login/login-atoms.tsx:3
  builds a dynamic Tailwind class that is purged from the production
  stylesheet. Green locally, unstyled in prod.

Hooks (logic in _lib/, mirrored into .opencode/plugin/orbit-guardrails.js,
registered in settings.json, covered in test-hooks.mjs):
forbid-ai-cliche-copy, forbid-placeholder-content, forbid-typed-uppercase,
forbid-secret-in-argv (PreToolUse, fails closed). Each was run against the
real 2466-string i18n corpus; the FP rate is pinned as a corpus guard.

Rules tier: .claude/rules/ created (it did not exist) with the 39 standing
non-checkable rules, themed by activity. design-reviewer resynced to
DESIGN.md's Reviewer-judgment list.

Deliberately NOT shipped, with evidence:
- forbid-straight-punctuation: the corpus refutes it (148 straight
  apostrophes vs 1 curly; DESIGN.md mandates nothing here). It would block
  shipped copy. Needs a design decision first.
- no-arbitrary-zindex: blocked on a semantic stacking scale that does not
  exist; inventing it is a design decision on a frozen doc.
- the barrel ban: contradicts packages/shared/CLAUDE.md, which mandates
  barrel imports.
- half of animate-presence-exit: statically undecidable (fired 2-for-2 on
  correct code). The sound half found a real silent bug.

The secret-in-argv fixtures are assembled from parts rather than spelled
out, the same idiom this file already uses for NV / MARK / EM: a test file
cannot contain the literal strings its own guards detect. Here the detector
is the required GitGuardian check, which matches a credential's SHAPE, not
its entropy, so no real value is needed and none exists.

Verification: test-hooks 193/193 PASS · turbo run lint 3/3, 0 errors ·
turbo run test web 2536/2536 + eslint-rules 100/100.
thomasluizon added a commit that referenced this pull request Jul 17, 2026
Turns the checkable half of the #539 skill harvest into real gates. The
canonical rule set (brain vault, "Orbit skill harvest — canonical rule set
(#539)") routed 217 rules to durable homes; this lands the gate: and
rules: buckets. DESIGN.md prose (bundle 3, #557) is the intent; this is the
enforcement.

ESLint local/* (21 hand-written rules + the enable-don't-write jsx-a11y set),
wired into all three flat configs, 100 RuleTester assertions:
- Severity is STAGED against measurement, never by weakening a rule. Rules
  the codebase already passes land at error. no-decorative-glow (19 web /
  10 mobile) and no-raw-gradient (27/26) land at warn because bundle 5 has
  not de-decorated the code yet; that PR flips them to error. Pre-existing
  backlogs (no-space-x-y 63, require-focus-replacement 17 real WCAG 2.4.7
  bugs, react19-api 18, ...) are surfaced at warn rather than silenced.
- Found a real production bug: apps/web/app/(auth)/login/login-atoms.tsx:3
  builds a dynamic Tailwind class that is purged from the production
  stylesheet. Green locally, unstyled in prod.

Hooks (logic in _lib/, mirrored into .opencode/plugin/orbit-guardrails.js,
registered in settings.json, covered in test-hooks.mjs):
forbid-ai-cliche-copy, forbid-placeholder-content, forbid-typed-uppercase,
forbid-secret-in-argv (PreToolUse, fails closed). Each was run against the
real 2466-string i18n corpus; the FP rate is pinned as a corpus guard.

Rules tier: .claude/rules/ created (it did not exist) with the 39 standing
non-checkable rules, themed by activity. design-reviewer resynced to
DESIGN.md's Reviewer-judgment list.

Deliberately NOT shipped, with evidence:
- forbid-straight-punctuation: the corpus refutes it (148 straight
  apostrophes vs 1 curly; DESIGN.md mandates nothing here). It would block
  shipped copy. Needs a design decision first.
- no-arbitrary-zindex: blocked on a semantic stacking scale that does not
  exist; inventing it is a design decision on a frozen doc.
- the barrel ban: contradicts packages/shared/CLAUDE.md, which mandates
  barrel imports.
- half of animate-presence-exit: statically undecidable (fired 2-for-2 on
  correct code). The sound half found a real silent bug.

The secret-in-argv fixtures are assembled from parts rather than spelled
out, the same idiom this file already uses for NV / MARK / EM: a test file
cannot contain the literal strings its own guards detect. Here the detector
is the required GitGuardian check, which matches a credential's SHAPE, not
its entropy, so no real value is needed and none exists.

Verification: test-hooks 193/193 PASS · turbo run lint 3/3, 0 errors ·
turbo run test web 2536/2536 + eslint-rules 100/100.
@thomasluizon
thomasluizon marked this pull request as ready for review July 17, 2026 15:49
@thomasluizon
thomasluizon merged commit f68bd29 into main Jul 17, 2026
21 checks passed
@thomasluizon
thomasluizon deleted the feature/539-design-md-deslop branch July 17, 2026 15:49
thomasluizon added a commit that referenced this pull request Jul 17, 2026
Turns the checkable half of the #539 skill harvest into real gates. The
canonical rule set (brain vault, "Orbit skill harvest — canonical rule set
(#539)") routed 217 rules to durable homes; this lands the gate: and
rules: buckets. DESIGN.md prose (bundle 3, #557) is the intent; this is the
enforcement.

ESLint local/* (21 hand-written rules + the enable-don't-write jsx-a11y set),
wired into all three flat configs, 100 RuleTester assertions:
- Severity is STAGED against measurement, never by weakening a rule. Rules
  the codebase already passes land at error. no-decorative-glow (19 web /
  10 mobile) and no-raw-gradient (27/26) land at warn because bundle 5 has
  not de-decorated the code yet; that PR flips them to error. Pre-existing
  backlogs (no-space-x-y 63, require-focus-replacement 17 real WCAG 2.4.7
  bugs, react19-api 18, ...) are surfaced at warn rather than silenced.
- Found a real production bug: apps/web/app/(auth)/login/login-atoms.tsx:3
  builds a dynamic Tailwind class that is purged from the production
  stylesheet. Green locally, unstyled in prod.

Hooks (logic in _lib/, mirrored into .opencode/plugin/orbit-guardrails.js,
registered in settings.json, covered in test-hooks.mjs):
forbid-ai-cliche-copy, forbid-placeholder-content, forbid-typed-uppercase,
forbid-secret-in-argv (PreToolUse, fails closed). Each was run against the
real 2466-string i18n corpus; the FP rate is pinned as a corpus guard.

Rules tier: .claude/rules/ created (it did not exist) with the 39 standing
non-checkable rules, themed by activity. design-reviewer resynced to
DESIGN.md's Reviewer-judgment list.

Deliberately NOT shipped, with evidence:
- forbid-straight-punctuation: the corpus refutes it (148 straight
  apostrophes vs 1 curly; DESIGN.md mandates nothing here). It would block
  shipped copy. Needs a design decision first.
- no-arbitrary-zindex: blocked on a semantic stacking scale that does not
  exist; inventing it is a design decision on a frozen doc.
- the barrel ban: contradicts packages/shared/CLAUDE.md, which mandates
  barrel imports.
- half of animate-presence-exit: statically undecidable (fired 2-for-2 on
  correct code). The sound half found a real silent bug.

The secret-in-argv fixtures are assembled from parts rather than spelled
out, the same idiom this file already uses for NV / MARK / EM: a test file
cannot contain the literal strings its own guards detect. Here the detector
is the required GitGuardian check, which matches a credential's SHAPE, not
its entropy, so no real value is needed and none exists.

Verification: test-hooks 193/193 PASS · turbo run lint 3/3, 0 errors ·
turbo run test web 2536/2536 + eslint-rules 100/100.
thomasluizon added a commit that referenced this pull request Sep 25, 2026
* fix(mobile): recover elapsed Android sessions (#994)

* fix(mobile): recover expired sessions

* fix(mobile): show session refresh progress

* fix(mobile): coordinate session recovery

* fix(mobile): require a plan for onboarding login

* fix(mobile): protect rotated sessions from stale teardown

* fix(mobile): preserve recoverable refresh sessions

* fix(mobile): make session transitions atomic

* fix(mobile): guard every credential transition

* fix(mobile): gate authentication on session setup

* fix(mobile): finish session phase ownership

* fix(mobile): separate session and credential versions

* fix(mobile): fence auth teardown by credential version

* fix(mobile): fence stale session continuations

* test(mobile): prove the store produces superseded

Round 14 split `unauthorized` into a real rejection and a lost session race,
and covered every consumer of the new `superseded` outcome. Nothing covered
the producer.

Collapsing `auth-store.ts`'s one `superseded` return back to `unauthorized`
left all four new tests green, because each one mocks `refreshSession` or
drives a consumer of its result. The defect would have returned invisibly.

This test drives the real path: a server refresh succeeds while a sign out
lands mid-flight, so publication loses the epoch and the outcome must be
`superseded`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(mobile): capture auth ownership at entry

* fix(mobile): distinguish session teardown authority

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit ce5ad59)

* fix: fence stale logout completion after replacement login

* fix: sequence web auth cookies and recover rejected mobile refresh

* test: update web login mock for logout sequencing

* fix(web): coordinate session cookie writes across tabs

* Fence stale mobile refresh and login profile effects

* Fence stale mobile login continuations and web session reads

* fix(mobile): fence post-login effects to current session

* fix(mobile): scope auth return URLs to login attempts

* fix(mobile): preserve Google callback and return URL ownership

* chore: re-baseline the contract snapshot on main (intervalWeeks, lastFreezeCoveredOrigin)

orbit-api PR 539 added optional intervalWeeks to POST /api/habits/bulk and
PR 540 added optional lastFreezeCoveredOrigin to both streak repair
responses. Generated with orval 8.37.0, the version main's lockfile pins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant