Skip to content

Rename the product to PsychSift, and let the symbol stand without a tile - #2453

Merged
BigSimmo merged 20 commits into
mainfrom
claude/psychiatry-sift-logo-vector-nd3615
Aug 29, 2026
Merged

Rename the product to PsychSift, and let the symbol stand without a tile#2453
BigSimmo merged 20 commits into
mainfrom
claude/psychiatry-sift-logo-vector-nd3615

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • The mark loses its tile in the app. It was a white S inside a filled accent-blue rounded tile, which on a white page reads as an app-store icon pasted into the chrome rather than as a logo. The roles are now reversed: the symbol carries the accent colour and the ground behind it is simply the surface it stands on. BrandMark draws the glyph alone, filled --clinical-accent, in light and dark alike.
  • A new BRAND_GLYPH_TRANSFORM_BARE scales the untiled glyph to fill its box, so the mark occupies exactly the slot the tiled version used to instead of shrinking by the tile's old 20% margin. It is derived from the same construction as the tiled transform, not hand-tuned.
  • The tile survives only where the format cannot be transparent and something has to be painted: favicon.ico, the Apple touch icon, and the PWA raster icons. Those now render as the blue symbol on white rather than white-on-blue.
  • The point drops 7 units clear of the S's tip. It sat level with the upper stroke's sharp tip, and the nearest thing to it anywhere on the S was that tip, aimed straight at it from 13.65 units — 2.2 px at a 16 px icon, which antialiasing closes. A sharp point aimed at a circle reads as contact even when the numbers say it is clear. The drop opens that approach to 18.46 units (+35%) while the lower stroke, a broad flank rather than a point, still keeps 14.95. It also moves the point from 17% to 24% of the glyph's height — where the bowl of a P closes back onto its stem — so the mark now carries a hint of the P in PsychSift alongside the S. The move is purely vertical because the point defines the glyph's right edge; the ink bounding box is unchanged to four decimal places against both cuts, so every lockup layout, placement transform and maskable safe-zone regenerates identically.
  • The design-token contract test gets stricter, not looser. It previously pinned only tile to --clinical-accent. It now pins ink to --clinical-accent and tile to --surface-raised, in both themes — four assertions where there were two.
  • Fixes a bug introduced while regenerating the favicon: written as RGB, Next.js refuses to decode the embedded PNG (Format error decoding Ico: The PNG is not in RGBA format!) and every page returns 500. It is now RGBA.
  • The product is renamed to PsychSift everywhere a person can see it: browser tab and page titles, the installed-app name and its shortcuts, the sidebar and header, the guide centre, the privacy pages, the safety-plan tool, the offline page, and the messages the local tooling prints.
  • The live domain monitor greps the served page for <title>Clinical KB</title>, so it is updated in the same change; leaving it would fail the moment this deploys.
  • The service-worker CACHE_VERSION is bumped to 2026-08-28-v1 because the precached offline document changed. An edit that ships without that bump strands installed clients on the old copy (docs/pwa.md rules 1 and 5), and tests/pwa-manifest.test.ts pins the pairing.

What is deliberately not renamed

  • The Supabase project stays Clinical KB Database. That is the live database's name, pinned by AGENTS.md and checked by check:supabase-project — not a user-facing product name. Every remaining occurrence of the old name in src, tests, scripts, worker and public is this one string.
  • Lowercase identifiers stay: the clinical-kb plugin directory, the package name, cache keys and paths. Renaming those changes nothing a person reads and breaks things that resolve by string.
  • docs/ keeps the old name where it is a dated record — plans, specs, archives, audit reports, and the frozen review and issue ledgers. Those describe what the app was called when they were written, and several are immutable by repository rule (check:ledger-write-discipline). Generated current-state docs are regenerated by the pre-commit hook.

The rename lands in one commit rather than two because the pre-commit documentation hook refuses to regenerate the generated docs while any of their inputs is still dirty, and the rename touches those inputs.

Verification

  • npm run typecheck — exit 0
  • npm run lint — exit 0
  • npm run brand:checksrc/app/icon.svg matches the brand-mark source, re-run after the point move
  • npm run check:assets — OK, themed favicon markers present
  • npm run check:repo-awareness-snapshot — in step (190 pages, 483 documents, 2646 reviews)
  • npx vitest run tests/design-token-contract.test.ts tests/pwa-manifest.test.ts — 56 passed, against the stricter four-assertion brand contract and the re-pinned offline-document/cache-version pairing
  • npm run format — no changes to commit
  • Full offline unit suite: Test Files 3 failed | 900 passed (903), Tests 3 failed | 10965 passed | 1 skipped. The one real failure this change caused — tests/pwa-manifest.test.ts — is fixed and re-run green. The three that remain are shallow-clone artefacts in this container: tests/clinical-hazard-controls.test.ts and tests/privacy-readiness-contract.test.ts report reviewedCommit does not exist 883f100…, and tests/rag-plan-package-parity.test.ts reports manifest reconciledBase is unavailable locally: f3d1a3c…. This checkout is shallow, so those historical commits are absent; they pass on GitHub where the full history exists.
  • Point clearance measured rather than eyeballed: 4,000-sample outlines of both strokes, minimum centre distance less the radius, computed for the ordinary (4.2) and small (7.2) cuts. Before: upper 13.648, lower 19.960, nearest point on the S = the tip at (41.37, 2.66). After: upper 18.455, lower 14.945. Ink bounding box x[0.0000, 70.9302] y[0.0000, 100.3813] in every case.
  • Browser check on the running dev server, light and dark: the untiled mark renders correctly in the sidebar rail and the header, and the renamed title, sidebar and header copy are correct in both.
  • Generated icon routes fetched and inspected as images — /icons/icon-192, /apple-icon, /icons/maskable-512 all render the blue symbol on white; /icon.svg, /favicon.ico, /opengraph-image, /icons/monochrome-192 and /manifest.webmanifest all return 200.
  • npm run check:production-readinessfails, and not because of this change. Its --release privacy gate reports the same shallow-clone reviewedCommit does not exist: 883f100… plus eight pre-existing release-blocking register entries (HMAC secret, retention-schedule parity, OpenAI ZDR, the OpenAI/Railway DPAs, the APP8 cross-border basis, the APP1–APP5 notice, and PHI minimisation), all recorded as pending or partial. No privacy or readiness manifest is in this diff, and every privacy-path file it touches changes prose only — the product's name inside a sentence. Those register debts are tracked work, not a regression introduced here.
  • UI verification not run: npm run verify:ui was skipped. The visual change is one component that drops a <rect>, a regenerated symbol, and copy strings; no layout, routing, composer, scroll-chrome or interaction surface moves. The affected surfaces were proved directly in the browser in both themes instead. CI's Production UI jobs cover the rest.
  • Verification not run: npm run verify:release — no release or handoff confidence is claimed here.

Risk and rollout

  • Risk: Low, and almost entirely cosmetic. The behavioural surface is three things: the untiled BrandMark, the regenerated icon files, and the service-worker cache-version bump. The rename is string substitution in copy, comments and log lines. The one thing worth watching on deploy is the PWA cache bump, which is exactly what it is for — installed clients pick up the new offline document instead of keeping the old one.
  • Rollback: Revert the merge commit. No schema, no migration, no data, no route and no provider configuration is touched, so a revert is complete.
  • Provider or production effects: None executed. No Supabase, OpenAI, Railway or hosted-CI command was run, and the Supabase project name and ref are unchanged. The live domain monitor's expected page title changes with the deploy, by design.
  • RAG impact: none

Clinical Governance Preflight

This is classified as clinical-risk because the rename touches the privacy pages, the safety-plan tool and the crawler policy. In every one of those files the change is the product's name inside a sentence or a comment — no logic, no data flow, no control. The diffs are reviewable line by line on that basis.

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Taking those in turn: nothing in this change touches answer generation, citation rendering, source governance or the document-access path, so linked-source verification stays exactly as strict as it was. No document workflow is added or widened, so no patient-identifiable handling changes — the safety-plan tool still keeps its working content in the browser tab and still omits a patient-identifier field, and the only edit to it is the name in its copy. The Supabase project name and ref are untouched, and are in fact the one string the rename deliberately preserves. No credential or server-only boundary moves. The demo corpus and the real clinical sources remain as separate as they were. Source metadata, review status and the conservative behaviour for outdated or unknown sources are all untouched. And on deployment classification: no clinical decision-support behaviour changed here at all, so the SaMD/TGA assessment position is unaffected.

Notes

  • PR Rebuild the PsychSift mark as exact vector geometry, and use it for the site icons #2452 squash-merged while this branch was still open, so its head was deleted and re-pushed. The branch was reconciled by merging origin/main back in. The five conflicts were all files the newer commit already supersedes, and the resolution was verified rather than assumed: git diff origin/main eb3dcf9 is empty (main's tree equals the pre-merge branch tree, confirming the squash carried everything), and git diff a971dec after resolving is also empty (the merge result equals the new commit exactly). Nothing was lost from either side.
  • The construction record in docs/brand/psychsift-logo.md and the two construction diagrams in docs/brand/preview.html are updated to the new point, including why it moved and why the move is vertical only.
  • The stacked-lockup descender fix that Codex raised on Rebuild the PsychSift mark as exact vector geometry, and use it for the site icons #2452 is already on main and is not part of this diff.

Note

Low Risk
Mostly branding, copy, and asset regeneration; the main operational note is the PWA cache-version bump so installed clients refresh the offline shell after deploy.

Overview
Renames the product to PsychSift across user-visible surfaces: document titles and metadata, PWA manifest and shortcuts, layout defaults, offline/PWA copy, opengraph, guide and search strings, and the live-domain monitor’s root title assertion (Clinical KBPsychSift).

Changes how the mark appears in the app. BrandMark no longer draws a rounded accent tile; it renders the glyph alone, filled with --clinical-accent, using BRAND_GLYPH_TRANSFORM_BARE so it still fills the same chrome slot. Tiled marks remain only for opaque formats (favicon, Apple touch icon, PWA PNGs), with updated centring after geometry changes.

Updates PsychSift logo geometry: the accent circle moves to the throat-arc centre (44.8724, 20.0286) (documented in psychsift-logo.md and construction preview). The small-size favicon set widens the stroke cut, shifts the point outward, and uses its own centring transform; app/icon.svg follows that set and inverts tile/ink colours (accent symbol on surface-coloured ground).

Regenerates public/brand/* SVGs and bumps the service worker CACHE_VERSION to 2026-08-28-v1 so precached offline HTML picks up the new naming.

Design-system docs now describe the bare vs tiled mark split and the coupled small-size constants; internal plugin paths and the Supabase project name are intentionally unchanged.

Reviewed by Cursor Bugbot for commit 42b1c39. Configure here.

claude added 15 commits August 28, 2026 18:16
The only artwork we had was the small white-on-navy mark on the brand
sheet plus a low-fidelity raster enlargement of it. Measuring the small
mark showed the design is genuinely circle-based: the outer sweep of
each stroke sits on a circle of radius 30 (glyph units, S height 100) to
within a quarter of a unit across its whole length.

So this reconstructs those circles rather than tracing pixels. Each
stroke is six circular arcs — a rounded head tip, a throat, an elbow, a
long tail sweep, a rounded tail tip, and the outer sweep — with exact
tangency at every junction, and the second stroke is a 180 degree
rotation of the first about (27.4, 50). The primary file is 965 bytes.

Three corrections to the original, all recorded in the doc:

- The two strokes are now identical. In the raster the lower one was
  heavier than the upper one, and irregularly so.
- The glyph is centred in the tile, which previously sat hard against
  the right edge (26% left margin against 9% right).
- Every junction is tangent-continuous, so enlargement reveals no kinks.

Adds a separate optical cut for 32px and below: the navy channel between
the strokes closes up at favicon sizes, so that file widens the channel
by 60%, drops the two blue points, and enlarges the S.

The wordmark is Inter Display SemiBold with its outlines embedded, so
the lockups render identically without Inter installed.

docs/brand/psychsift-logo.md records every centre and radius, the weight
parameter, the colours, and the usage rules; docs/brand/preview.html is
a contact sheet for the whole set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The first pass fitted the terminals from the brand sheet's raster, where
a sharp point of that size necessarily blurs into a rounded blob. It
read that blur as the design and gave both strokes rounded club-ends.
Enlarging the original shows the opposite: a clean horn at the head and
a taper at the tail.

Refitting the inner edge across both source renderings, with the tip
region included and the terminals left open, gives a simpler and better
construction. Each stroke is now four arcs instead of six:

  outer sweep   (30.00, 30.00) r 30.0
  throat        (46.25, 20.45) r 20.0
  elbow         (27.49, 35.74) r  4.2   derived from tangency
  tail inner    (59.30, 67.85) r 41.0

The head cusp falls out at (39.6152, 1.5826) where the outer sweep runs
into the throat, and the tail cusp at (19.4776, 58.0941) where the tail
inner arc runs back into the outer sweep. Both were previously truncated
by cap arcs of radius 2.0 and 2.2. Fit RMS against the measured inner
edge is 0.84 units in 100, inside the disagreement between the two
source renderings.

Weight is now controlled by the tail radius alone rather than a uniform
offset. That matters because the uniform offset also shrank the throat,
which is what sets the head cusp — thickening the stroke used to drag
the horn out to x=43.3. At r 41.0 the channel between the strokes is
5.8 units at its narrowest and the stroke is 31.3 at its widest, both
matching the original.

The small-size cut follows: tail radius 43.5 and rotation centre
(28.0, 50), which doubles the channel while widening the silhouette by
2%.

The primary file drops from 965 to 851 bytes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
A much larger view of the original artwork became available, so the
geometry is refitted against it at sub-pixel accuracy rather than
against the 90-pixel crop from the brand sheet. Contours were extracted
with marching squares and the four-arc model fitted by Nelder-Mead over
a symmetric Chamfer distance. The result lands within 0.33 units in 100
of the measured outline — inside the softness of the source.

Master stroke:

  outer sweep   (30.567, 30.567) r 30.567
  throat        (46.447, 20.746) r 19.061
  elbow         (29.974, 34.186) r  2.199   derived from tangency
  tail inner    (60.692, 67.165) r 42.870

Head cusp (41.9881, 2.2139), tail cusp (18.6620, 58.7204). The outer
sweep is centred at (r, r) for its own radius, so it is tangent to the
top and left of the stroke's bounding box — a self-check the earlier fit
had also found, and the reason the construction reconstructs cleanly.

Two substantive changes beyond precision.

The two blue points below the white one are removed at the owner's
direction. The mark is now a single colour on its tile.

The lower stroke is no longer forced to be identical to the upper one.
It is the same path at 1.06 scale — `translate(54.84 100) scale(-1.06)`.
Fitting each stroke independently and fitting a single
rotation-plus-scale between them agree on that figure, and forcing them
equal both worsens the match (Chamfer RMS 1.59 against 1.26) and opens
the channel between the strokes from 4.0 units to well over 9. That
channel is the tension the mark depends on, so the difference is kept
and documented rather than corrected away.

The small-size cut follows by stepping the second stroke out 3.5 units
in both directions, which widens the channel to 8.9 while changing the
silhouette's proportion by 3%.

Primary file drops from 851 to 814 bytes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The colour table still described brand blue as "the two falling points"
and carried a Light Blue row that existed only to tint those points on
the blue tile. Neither is used by any file any more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The four-arc model put each stroke's entire outer edge on one circle.
Measuring the original against that circle shows it is not: the edge
tracks it to within a tenth of a unit down to about two-thirds of the
stroke's height, then peels away and keeps peeling — 0.4 units out at
y=52, 1.3 at y=56, 2.7 at y=60, 3.3 at the tip. That departure is a
second arc, and it is what draws the tail into a long fine point.
Without it the tail stops short and the whole stroke reads heavy and
blunt, which is what the owner was seeing.

Nearest-point (Chamfer) fitting had hidden this. Every point of a
slightly wrong outline still sits close to some point of the right one,
so a uniformly thick stroke or a displaced channel scores well. Scoring
coverage against the original's own grey levels — where a hard edge is
penalised for sitting anywhere but the 50% point of the blur — showed it
immediately.

Each arc is now fitted individually so its residual can be inspected
rather than averaged away:

  outer sweep   (29.2009, 29.2009) r 29.2009   rms 0.079
  tail-outer    (51.5937, 16.1418) r 55.1234   rms 0.075
  throat        (44.8724, 20.0286) r 17.7232   rms 0.051
  elbow         (29.2867, 33.5044) r  2.8805   rms 0.139
  tail-inner    (65.6136, 70.4548) r 48.9362   rms 0.087

Head cusp (41.3675, 2.6554), tail cusp (17.8645, 59.7414). The outer
sweep again lands centred on its own radius, tangent to the top and left
of the stroke's box — this time it fell out of the fit rather than being
imposed.

Against the original by area, intersection over union goes from 0.848 to
0.944. The second stroke's enlargement refines from 1.06 to 1.07. A
further 3.5 degree rotation of it scores 0.948; it is left out, because
an arbitrary tilt is not something a logo specification should carry.

The small-size cut follows, stepping the second stroke out 3 units to
widen the 4.4-unit channel to 8.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The gap between the two strokes was drawn from two separate circles that
curved in opposite directions. Two arcs bowing apart open a lens: the channel
measured 5.4 units at its ends and 8.6 in the middle, with a hard corner at
each end of the swell. That dip is what the owner flagged.

Measured across the original, its channel is 4.75 units wide with a standard
deviation of 0.25 — constant. Both of its edges are arcs of one circle, one
inside the other.

The mark is now built that way. A single circle at (89.7175, 83.5939) carries
the upper stroke's facing edge at r 74.8165 and the lower stroke's at r 70.0627,
so the gap is 4.7537 units along its whole length and both edges turn the same
way. Each stroke reaches its facing edge through a tangent blend arc — 7.5 units
on the upper, 12 on the lower, against the original's 2.88, which was tight
enough to read as a corner.

The outer silhouette is untouched. Measured on the rebuilt file the channel is
4.75 wide with a standard deviation of 0.10, and area agreement with the
original rises from 94.1% to 94.7%.

The small-size cut now widens the channel to 7.75 units by moving only the two
facing edges, instead of displacing the whole second stroke, so the favicon and
the primary mark share one silhouette.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The middle of the mark has been wrong in two different ways, and both times
the cause was the same: the two facing edges were separate curves, so they
could drift apart. Drawing them from two circles opened a lens (5.4 units at
the ends, 8.6 in the middle). Drawing them as two arcs of one circle fixed the
width but left each stroke turning onto its edge through a 7.5-unit blend that
reads as a knuckle on the spine of the S.

The two strokes are now divided by a single straight line, and each stroke's
facing edge is that line offset by half the gap. The edges are parallel by
construction, so the gap cannot open and neither edge can curve against the
other. Each stroke joins its edge with one 13-unit blend under the head, and
both blends bend away from the other stroke, so nothing on either facing edge
turns over.

Measured across the finished mark the gap is 4.35 units with a standard
deviation of 0.28, against 4.75 ± 0.25 in the original, which also bows 1.25
units along its length. This is a deliberate improvement on the source rather
than a copy of it.

The outer silhouette, both head cusps and the point are untouched. The
small-size cut widens the gap to 7.2 units by moving the two lines apart, so it
now shares the primary file's silhouette exactly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
… exact

Three findings from a measured review of the mark.

The point was misplaced. Refitting the original's dot at the 50% level of its
edge puts it at (60.4716, 17.3581) with radius 10.4586, against the
(58.9234, 16.5279) radius 10.2165 these files carried — 1.8 units in and 2.3%
small. That was a measurement error rather than a decision, and it crowded the
S's shoulder while leaving the point looking like a stray. Restored.

The mark sat left in its tile. The placement weighted the anchor 46% of the way
from the S's own centre toward the glyph's right edge, to stop the light point
dragging the heavy S leftward. It over-corrected: 65 px of margin on the left
against 164 px on the right at 512. The ink's bounding box is now centred,
which gives 112 px each side.

The symmetry was approximate. The cut has moved 0.31 units so that the point
reflection which makes the second stroke carries the first stroke's facing edge
exactly onto the second's. The whole mark is now invariant under that single
transform, and the second stroke is written in the files as a transform of the
first rather than as its own path.

Also: the maskable icon put ink 176 px from the centre of a 512 px icon, outside
the 171 px Android allows inside its safe circle. Re-centring and a scale of
62% brings it to 168.

The straight cut, both outer silhouettes and both head cusps are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
CI has been red on this branch since its first commit: `check:repo-awareness-snapshot`
reports "documentation differs from the repository" because the two new brand
documents were added without regenerating data/repo-awareness-snapshot.json.

Regenerated with `npm run snapshot:repo-awareness`. Verified locally: the
snapshot check now passes, along with brand:check, check:assets,
docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links,
sitemap:check, check:branch-review-ledger, check:outstanding-issues,
check:ledger-write-discipline, check:knip, check:maintainability-budgets,
check:type-scale, check:icon-scale, check:design-system-contract,
format:changed and lint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The preview covered how the mark is built but not how to use it. Three sections
added, so the page carries everything a person needs without opening the spec:

- Clear space and misuse: the quarter-height margin drawn to scale, the five
  rules as a table, and four rendered "do not" tiles — stretched, shadowed,
  re-spaced, and dropped on a mid-tone — so each failure is shown rather than
  described.
- The files: all fifteen with what each is for, plus the screen-reader note.
- Still open: the two taglines on the brand sheet, Inter against the running
  application's Geist, and the tail tips left as a preference rather than a
  defect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The tail tips were the last open question on the drawing. Both versions were
rendered and compared side by side; the owner chose the clean angled cut on
2026-08-28.

Written down in both the spec and the preview, with the reasoning, so it is a
settled decision rather than an open one: fine points thin both strokes, they
belong with a curved middle line rather than a straight one, and they are the
first thing to disappear at 16 px.

Two questions remain open, and neither is about the drawing: which of the brand
sheet's two taglines survives, and whether the wordmark's Inter or the running
application's Geist wins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The finished PsychSift S now draws every brand surface, not just the
files under public/brand: the in-app <BrandMark>, the browser-tab
icon, the multi-size favicon, the Apple touch icon, the PWA and
maskable icons, and the Open Graph image all derive from the same
geometry in src/lib/brand-mark.ts.

The browser-tab icon and favicon use the wider optical cut, so the
channel between the two strokes stays open at 16-32 px instead of
closing into a solid shape.

Also fixes the monochrome PWA icon, which asked for a white tile and
so filled its whole alpha channel with a solid square. It is now
transparent, leaving only the glyph, which is what a monochrome icon
is for.

The tile colour stays bound to --clinical-accent, so the mark adapts
to light, dark and forced-colors exactly as the old one did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The stacked lockup sized its own height from a guessed fraction of the
cap height (26%) rather than from the wordmark's real ink bottom. The
descenders of the "p" and the "y" reach 2.1 units further down than
that, so a renderer cut them off at the bottom edge.

The height now comes from the wordmark's measured bounding box, rounded
up to the two decimal places the path coordinates are written at, so the
letterforms sit fully inside the frame. The layout is otherwise
unchanged: the tile, the glyph and the wordmark keep their positions,
and only the frame's bottom edge moves, from 461.824 to 463.93.

The three horizontal lockups and the standalone wordmark were measured
too and none of them clips.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
Two changes that the pre-commit documentation hook requires in one
commit, because it refuses to regenerate the generated docs while any
of their inputs is still dirty.

THE MARK

The mark was drawn as a white S inside a filled accent-blue tile. On a
white page that reads as an app-store icon pasted into the chrome
rather than as a logo. The roles are now the other way round: the
symbol carries the accent colour and the ground behind it is simply
the surface it sits on.

In the app the tile is gone entirely. BrandMark draws the glyph alone,
filled --clinical-accent, so it sits directly on the page in light and
dark alike. It uses a new BRAND_GLYPH_TRANSFORM_BARE that scales the
glyph to fill its box, so the mark occupies exactly the slot the tiled
version used to rather than shrinking by the tile's old margin.

The tile survives only where the format cannot be transparent and
something has to be painted: the .ico, the Apple touch icon and the
PWA raster icons. Those now render as the blue symbol on white.

The design-token contract test gets stricter rather than looser: it
pinned only the tile to --clinical-accent, and now pins the ink to
--clinical-accent and the tile to --surface-raised, in both themes.

The favicon is written in RGBA. Saved as RGB, Next.js refuses to decode
the embedded PNG and every page 500s.

THE NAME

The app now calls itself PsychSift everywhere a person can see it: the
browser tab and page titles, the installed-app name and its shortcuts,
the sidebar and header, the guide, the privacy pages, the safety-plan
tool, the offline page, and the messages the local tooling prints.

Three things are deliberately left alone. The Supabase project is still
named "Clinical KB Database" — that is the live database's name, pinned
by AGENTS.md and checked by check:supabase-project, not a product name.
The lowercase identifiers stay: the clinical-kb plugin directory, the
package name, cache keys and paths; renaming those changes nothing a
person reads and breaks things that resolve by string. And docs/ keeps
the old name where it is a dated record — plans, specs, archives, audit
reports, and the frozen review and issue ledgers — because those
describe what the app was called when they were written, and several
are immutable by repository rule. Generated current-state docs are
regenerated.

The live domain monitor greps the served page for its title, so it is
updated here too; leaving it would fail the moment this deploys. The
service-worker cache version is bumped because the precached offline
document changed, and an edit that ships without that bump strands
installed clients on the old copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
PR #2452 squash-merged while this branch was still open, so the branch
carries the same content under different commits. Merging main in
brings the histories together; the resulting diff against main is only
the rename and the untiled mark.

# Conflicts:
#	docs/design-system.md
#	src/app/favicon.ico
#	src/app/icon.svg
#	src/components/clinical-dashboard/brand.tsx
#	src/lib/brand-mark.ts
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ce92ff4-3b8b-4995-9d9f-4fa452d774ad


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@supabase

supabase Bot commented Aug 28, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

claude added 3 commits August 28, 2026 22:38
The point sat level with the upper stroke's sharp tip, and the nearest
thing to it anywhere on the S was that tip, aimed straight at it from
13.65 units away. At a 16 px icon that is 2.2 px, which antialiasing
closes: a sharp point aimed at a circle reads as contact even when the
numbers say it is clear.

Dropping the point 7 units opens that approach to 18.46 units, a 35%
increase, while the lower stroke — a broad flank rather than a point —
still keeps 14.95. It also moves the point from 17% to 24% of the
glyph's height, which is where the bowl of a P closes back onto its
stem, so the mark now carries a hint of the P in PsychSift alongside
the S rather than reading as an S with a stray dot beside it.

The move is purely vertical on purpose. The point defines the glyph's
right edge, so any horizontal move would change the ink bounding box
and with it every placement, lockup layout and maskable safe-zone
derived from it. The bounding box is unchanged to four decimal places,
verified against both the ordinary and small-size cuts, so the lockups
and icon placements are regenerated identically.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
Replaces "Source-backed clinical search" under the wordmark in the
header. Temporary, pending a final choice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
The point is moved into the concave bay on the S's right face, and its
centre is placed at exactly the centre of the throat arc — the 17.7232
circle at (44.8724, 20.0286) whose arc forms that face.

That placement is not a judgement call. Because the point shares its
centre with the arc that cradles it, the crescent of white between them
is a constant 7.2646 units all the way round, variation 0.000. Anywhere
else in the bay the crescent tapers: the position first chosen by eye,
2.26 units further in, ran 5.00 at its narrowest and 6.93 at its widest.
It is the same principle as the straight cut between the two strokes —
negative space of one measured width rather than a gap that happens to
look about right — and it also gives the largest clearance of any
position in the bay, 7.26 to the upper stroke and 8.18 to the lower.

Cradling it makes the glyph 22% narrower, 55.33 wide against 70.93,
because the point no longer defines the right edge. Every placement
derived from the ink box is regenerated: the tile transform, the
untiled in-app transform, and the lockups. The maskable icon still fits
Android's safe circle with room to spare, 160 px of ink against the
171 px allowed.

Small sizes get their own point. The crescent is 0.93 px at a 16 px
icon, so BRAND_POINT_SMALL slides it 10 units back out of the cradle,
opening the crescent to 11.55 units. That widens its ink box too, so
the small variant carries its own centring transform, and
brandMarkInner picks the cut, the point and the placement together from
one flag — they are a set, and mixing one with another variant's
placement puts the glyph off-centre in its tile. Below about 20 px the
point still fuses into the S; that is the size, not the placement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
@BigSimmo
BigSimmo marked this pull request as ready for review August 29, 2026 00:35
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T00:43:41.895642Z 42b1c39 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cursor

cursor Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_b1c508f5-b7f6-495c-befd-e123d5c07bee)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42b1c39212

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/list-database-skills.mjs
@BigSimmo
BigSimmo enabled auto-merge August 29, 2026 00:47
claude added 2 commits August 29, 2026 01:09
…trapline

THE SHEET

docs/brand/preview.html is regenerated from the current geometry. It was
badly stale: every embedded image still drew the retired mark, and four
of them — the misuse tiles — were stale for a reason worth fixing rather
than patching. Their generator hardcoded the tile placement as a literal
transform instead of deriving it, so they kept drawing a retired mark
through two geometry changes without anything going red. The generator
now takes that placement from the same function that emits it for every
other file.

The prose is brought in line too: the construction table gains the
small-size point, section 03 explains that the small-size variant opens
two gaps rather than one, and the colours section is rewritten around
the untiled in-app mark on the accent token rather than white ink on a
navy tile.

THE HUB LINK

The Developer Hub gains a "Brand and design" card in its reference
group. It is the one panel that leaves the app for a static file, so it
carries an `external` flag: PanelCard renders it as a real anchor rather
than a Link, because the client router has no entry for a file, and the
route-existence test skips it rather than looking for it in the route
manifest.

The file it points at is public/brand/preview.html, a copy of the
documented sheet. A test holds the two byte-identical by hash — a stale
copy would show a retired mark to the one reader most likely to trust
it, which is exactly the failure the generator fix above was about.

THE STRAPLINE

"From question to source" now gets a considered setting rather than the
one it inherited. The wordmark takes the display tracking the rest of
the interface's headings use; at 18px/800 the untracked default reads
loose. The strapline drops from 600 to 500, where it supports the name
instead of competing with it at almost the same weight.

Two things were tried and rejected on measurement rather than taste.
--text-soft composites to #8894a6 on this surface and gives 3.07:1
against the header, under the 4.5:1 floor, so the colour stays
--text-muted at 6.15:1 light and 8.62:1 dark. And 11px made the block
bottom-light for no gain in hierarchy. An accent-coloured strapline and
an uppercase eyebrow were both drawn and rejected: the first puts a
second blue beside the mark, the second turns a sentence into a
category label.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
MERGE

Main's Caring Contacts Phase 2B landed while this branch was open and
conflicted on one file: src/lib/caring-contacts-routes.ts, where main
added a paragraph to the module note and this branch had renamed the
product inside it. Resolved by keeping main's fuller paragraph and
applying the rename to it, so neither side loses anything. Main also
brought in seven fresh occurrences of the retired name in the
caring-contacts page comments; those are renamed too.

THE PLUGIN'S USER-FACING NAME

Codex was right, and this is a gap in the original rename rather than a
nit. That change renamed the catalogue's bookkeeping label but left the
name a person actually sees: the marketplace card, the plugin's whole
interface block — display name, both descriptions, developer name and
its three suggested prompts — and the routed skill's own frontmatter
description. So the marketplace still advertised a retired product, and
because skill selection matches on description, a request phrased with
the current name was less likely to route to this plugin at all.

Renamed in the user-facing fields only. The lowercase identifiers are
untouched on purpose: the `clinical-kb` plugin name, its directory, its
marketplace id, its keywords and the `clinical-kb-workflow` skill folder
are addresses, and moving them breaks resolution for no reader's gain.

A guard now holds that split, because nothing did before and that is why
it drifted. `check:skills` fails if any of the five user-facing files
carries the retired name, with the Supabase project `Clinical KB
Database` excluded by a negative lookahead — that is the live database's
real name, not a product name. Two tests cover it: one that the surfaces
are clean, and one that the guard still fails when a surface reverts,
because a check that cannot fail is not a check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018udjLhnir8SEbNjGFjCJzm
@BigSimmo
BigSimmo merged commit 438d1d0 into main Aug 29, 2026
29 checks passed
@BigSimmo
BigSimmo deleted the claude/psychiatry-sift-logo-vector-nd3615 branch August 29, 2026 01:39
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.

2 participants