Commit Graph
179 Commits
Author SHA1 Message Date
Youssef 6febf4f86e Tier A gains the A/B controls: a bare arm, model and effort passthrough, usage capture
gen-cli.mjs learns --model and --effort (forwarded to the claude call),
a bare no-skill control arm (plain brief prompt, no skill copy), a $3
per-cell budget guard, and --setting-sources project on BOTH arms so the
user-scope hallmark install can neither leak into the control nor
version-skew the skill arm; stampPresent on a bare cell doubles as the
leak detector. The result event's usage lands in run.json (tokens
in/out/cacheRead, turns, stop subtype) with the camelCase modelUsage
fallback, and cells are named arm-effort-cli so effort variants coexist.
2026-07-31 12:37:52 +01:00
Youssef 94ae30e680 The imagery kit is real: 39 committed assets, a filled manifest, no more fake people
site/imagery/ now ships (serving at usehallmark.com/imagery/ on deploy):
16 photoreal placeholder avatars (768px, varied ages/skin/hair on neutral
studio grounds, natural texture, no smooth-mesh AI look; provenance JSON
sidecars committed; each paired deterministically with a unisex name so
gate 19 never meets another Jane Doe), 4 watercolor washes and 4 single-
colour brush gestures on white ground (composited via multiply - no faked
alpha; the category skips dark themes), 4 hand-built tileable texture
SVGs, 12 hand-built currentColor marks in four geometric families (inline
them - img cannot inherit currentColor; wordmarks are a composition of
mark + display-token text, since baked-text SVGs cannot use page fonts),
and 3 app-screen frames built on Hallmark tokens with their HTML sources
committed beside them for one-command re-render. Total 1.7MB, ~$1.06 of
Together spend, every generated file QC'd in the browser (two off-brief
brushes were regenerated single-colour and pixel-verified).

imagery-kit.md's manifest is now the real allowlist with provenance
columns; the categories table gains avatar/mark/screens rows and the
white-ground multiply contract; the placeholder ladder's tier 1 points at
the real kit and tier 4 loses person keywords (F9's territory); the
portrait row of the image-need table routes to kit avatars.
2026-07-31 12:35:47 +01:00
Youssef 6dedaceef2 The finish tier: nine mechanical polish checks, none of them a gate
sloplint gains F1-F9, a tier that reports beside the gates without ever
counting in the 58: straight quotes and three-period ellipses caught on a
new position-preserving masked-prose view (code blocks, comments, and
tags space-padded so line numbers stay exact; entity-encoded quotes match
too, and doc.text now decodes quot/apos/hellip/mdash for future text
checks), missing text-wrap balance on display heads, more than one
filled-primary button, icon-in-coloured-circle coins, display-size
numerics without tabular figures, one container recipe stamped across
six-plus selectors, a second scroll-choreography pattern, and fake-human
avatar hotlinks (the tier's one FAIL) with person-keyword stock URLs as
the WARN half. gateSortKey groups F ids after the numbered gates;
component scope inherits F4/F5/F6/F9.

Verified: a fixture trips all nine with correct grades and lines; the
canonical examples stay 0-FAIL (their handful of new F-WARNs is the tier
working); the legacy sweep holds at exactly the 190-FAIL baseline.
2026-07-31 12:24:52 +01:00
Youssef 7a126456f2 The surface escalation ladder: cards are the top rung, not the first move
layout-and-space.md gains § Surfaces directly above Depth: whitespace,
then a hairline seam, then a tinted well (paper-2/3, no border - the tint
IS the boundary), then a card, reserved for independently interactive or
fundamentally different content. Never straight to cards, never white
cards on a tinted page, and Depth now reads as the ladder's dressed top
rung. Gate 9 names the ladder as its fix vocabulary: different regions
climb different rungs. The F7 monotony check lands with the F-tier.
2026-07-31 12:22:21 +01:00
Youssef d90fd6960c The finish layer: the last 2% that separates set from generated
references/finish.md joins the every-build list: heading measure by size
(ch caps ON the element, from ~20ch at display down to ~45ch at xl, body
envelope untouched), typeset punctuation (curly quotes, true ellipsis,
non-breaking unit pairs, tabular-nums on comparing numbers), text-wrap
balance/pretty, hanging punctuation on pull-quotes, one filled primary
per page, the button height budget threaded through the existing 44px
floor and 48px coarse-pointer rules via the hit-target expansion recipe,
icon discipline (one set, natural grid, no coloured coins, first-line
alignment), concentric radii (inner = outer - padding), the mobile-runs-
larger idiom (body-adjacent UI steps DOWN at 60rem; display clamps
exempt; 16px mobile floor), and motion finish (exits 60-75% of enters,
stagger bands 30-50/60-100ms).

Companions: typography.md gains the measure table at its sizing section,
motion.md's exit ratio widens from ~75% to the 60-75% band so it stops
disagreeing with microinteractions.md, responsive.md points at the
mobile-larger idiom. The F-tier checks land separately.
2026-07-31 12:21:53 +01:00
Youssef 0bc5d53511 Brand truth: fetch a real brand's values or ask; never recall them
references/brand-truth.md: when a brief names a real company, the brand's
colours and fonts are captured mechanically (homepage + same-origin CSS
under study.md's remote-safety rules, meta theme-color, names-only font
CSS) into .hallmark/brand-spec.md with provenance and a derived-not-
guessed attestation, and theming anchors on the spec. Memory hex is a
named failure. The spec caches like preflight.json (90-day staleness,
design.md still outranks it), the no-fetch path asks once and otherwise
builds free of brand claims, and real logos are never redrawn or
hotlinked from strangers. Wired as pre-flight signal source 0.5, into the
Step 1 brand-colour signal, the conditional load list, and custom B.1's
anchor derivation.
2026-07-31 12:21:03 +01:00
Youssef dea57c4cbb Data viz: the chart rules Ledger and Almanac practiced become house law
references/data-viz.md: form heuristic first (one value = stat tile never
a one-bar chart, > 7 categories = a table, parts-of-whole = stacked bar
never pie/donut/gauge), hand-built SVG construction specs (bars <= 24px
baseline-zero, 2px lines, 1px solid gridlines never dashed, ONE y-axis
never dual), colour adapted to the one-accent discipline (lightness ramp
on the accent for multi-series, fixed order never cycled; labels never
wear the data colour), honesty riding gate 46 (zero baselines, annotated
zooms, internally consistent sample data), the dark note, and the
dashboard bar: one figure, one chart, one table - the six-gauge KPI wall
is the tell this file kills. Stat-Led, Ledger, Sport, and Almanac point
at it; SKILL.md loads it conditionally.
2026-07-31 12:20:15 +01:00
Youssef e071b5572f Dark mode grows from an 8-line recipe into a parity protocol
references/dark-mode.md: per-token re-derivation table (elevation gets
LIGHTER, accent chroma drops as lightness rises, hue never moves, body
weight -50), the exact dual-block emission shape ([data-mode=dark] plus a
prefers-color-scheme auto block guarded by :root:not([data-mode]), with
the no-flash toggle note and color-scheme), and the dark discipline:
shadows become lightness or inset rings (glow stays a THEME carve-out,
named), cards sit lighter than canvas, one heading colour, never CSS
invert on raster, kit multiply assets skip dark. Both modes run the full
gate sweep and the stamp records modes: light+dark.

color.md's recipe shrinks to a pointer and its 12-16 vs 12-18 paper
disagreement unifies at 12-18. Dual-mode stays strictly opt-in: a dark
theme is not a dual-mode page. SKILL.md gains the Step 6 bullet and the
conditional load entry.
2026-07-31 12:19:25 +01:00
Youssef 0de213db0a Scroll choreography: four earned patterns replace a blanket ban
motion.md banned scroll-scrubbed animation 'unless there is a specific
reason' while tier-c sanctioned animation-timeline outright - a live
contradiction with no vocabulary between them. references/
scroll-choreography.md now IS the specific reason: four named patterns
(pinned chapter, scrub-linked headline, progress spine, sticky diptych)
with Baseline-2025 recipes, each inside @supports + reduced-motion +
min-width guards so the base page is always the finished page. Two
correctness rules are baked in: the animation shorthand resets
animation-timeline (declare after), and pinned-pane children cannot drive
their own view() (steps ride a named timeline on the tall track).

Budget: one pattern per page (sloplint F8 will count), never on body
text, linear easing for scrub, hero orchestration untouched, JS fallback
is the IO reveal-once only. motion.md reroutes to the vocabulary, tier-c's
decision row defers to it, macros 14/16 and f2 point at it, and SKILL.md
loads it conditionally.
2026-07-31 12:18:22 +01:00
Youssef 64f84b4f12 Texture becomes a system: five artifacts, one budget, earned by lineage
The grain/halftone/misregistration/scanline recipes scattered across the
riso, carnival, and arcade specs (plus the assets.md feTurbulence recipe)
generalize into references/texture.md: five named artifacts with tokened
budgets (--texture-opacity caps, one artifact family per page, never
animated, pointer-events none), an affinity table (Riso/Carnival/Arcade/
faint-Newsprint earn it; Specimen/Atelier/modern-minimal stay banned), and
a custom-ritual hook (B.6b: print-lineage draws may take ONE artifact).

Rides along: e7's knob drops its scroll-linked-parallax option (it
contradicted the page-wide parallax ban), hero-discipline's grain note
stops claiming Specimen/Atelier carry texture (they ban it) and now names
the real carriers, and the starfield ban line gains the scoped Arcade
carve-out cross-reference so the two files stop arguing. Specs point at
the shared recipes; SKILL.md Step 3 loads texture.md conditionally.
2026-07-31 12:17:05 +01:00
Youssef 834dfebb6a Harness adapters learn each model family's tics
The round-1 plan included per-model tic bans for the harness adapters but
the item fell out of the execution order; landing it now. codex.md gains a
Model-tics-to-refuse section (ghost cards, sketchy SVG filler, feTurbulence
grain washes as filler, diagonal-stripe wallpaper, emoji bullets), and
opencode.md gets the symptom-keyed version since it runs many models, with
the standing line that the Critical floor and gates outrank any model's
taste. Refuse-by-default framing: the brief's own words can earn a pattern
back, the model's taste cannot. The grain line points at the forthcoming
texture.md so budgeted texture stays sanctioned while filler grain stays
refused.
2026-07-31 12:15:35 +01:00
Youssef 4184722d4f Verification fixups: Riso reclassed grotesk-heavy, known close pairs documented
The consistency sweep caught one twin the mid-band move created (Riso and
Almanac both landed on mid/grotesk-sans/cool): Riso's display is set at
800/900, so its honest class is grotesk-heavy, which separates them. The
two pre-existing near-twins (Specimen/Atelier, Sport/Editorial) are now
named in theme-axes' closing note so the two-of-three rotation rule knows
to arbitrate them. Step 2's opening Do-line catches up with the hero and
mirror-test additions.
2026-07-30 16:39:33 +01:00
Youssef de3a01dd84 Gate 23 gets teeth: one accent number, measured two ways
color.md's 3%-vs-5% contradiction resolves to 5% everywhere. The gate
moves from judged-only to M/R:

- static half (sloplint.mjs check23, WARN-grade): flags accent tokens
  painting viewport-scale rules (body/section/hero-class selectors, or
  rules sized >= 40dvh / 320px / inset 0) and display-size accent text.
  Posture-aware via the stamp comment (Drenched skips; Committed and
  dark papers are structurally exempt because fields and papers are
  never accent tokens); alpha-thinned washes and atmospheric radial
  blooms pass
- render half (sloplint-render.mjs, 1280x800 only, undeclared-posture
  pages): resolves the accent tokens to sRGB and sums painted area on a
  16px union grid (no double-counting of nested rects); > 8% FAIL,
  > 5% WARN, atmospheric thresholds 30/20. Along the way the render
  tier gains a real colour parser: modern Chrome serializes computed
  values and canvas fillStyle in their authored space, so oklch is now
  converted with the same math sloplint uses (the old rgb-only regex
  would have silently skipped every oklch page)

Verified in the browser: a full-bleed accent fixture measures 94.2%
painted (FAIL) and the live coral landing measures 0% (pass); the static
half flags the fixture's three sites and stays quiet on all canonical
examples. Also: garden-01's pre-existing zero-chroma mask-matte token
gains 0.005 chroma so the full example sweep is 0-FAIL again.
2026-07-30 16:35:35 +01:00
Youssef b34d96b722 Cookbook restructure: knobs and mobile collapse live with the archetype
The 259-line cookbook forced a full read for any pick because the knob
table and the mobile-collapse table sat inside the index file. Both tables
now ride inside the 50 archetype files themselves (## Knobs with the
gate-32 vary-one rule, ## Mobile collapse with the two breakpoints),
migrated by an asserted script; the previously missing rows are authored:
knobs for S1-S5 and N10, collapse for S1-S5, N1b, and N10-N13 (exactly
the navs the skill steers toward, whose collapse was undefined).

The cookbook drops to 173 lines: index, routing tables (the nav/footer
authority), picking rules, and the two breakpoint definitions with
pointers. The truncated H7/H9 index one-liners are completed, and
SKILL.md's token-waste warning now points at per-category archetype
pre-loading rather than the (now cheap) index read.
2026-07-30 16:28:45 +01:00
Youssef 10e7c9ff2b Critique with teeth, the mirror test, and a verification budget
- Pre-emit critique: the axis letters now match the stamp (P/H/E/S/R/V),
  every axis carries a what-a-3-looks-like-vs-a-5 anchor, the V axis
  scores against the log's fingerprint entries instead of memory, and at
  least one axis must score <= 4 with its reason and fix named in a new
  weakest: clause - a straight-5s stamp is called what it is, unexamined
- The mirror test lands in Step 2 (would these picks have come out for a
  neighbouring brief? then change one and name it) and as the reflex
  check's third altitude in the custom ritual (a slate that fits the
  category's other products unchanged is category gravity)
- Step 7 and the gate-classes section both carry the verification budget:
  one batched desktop+mobile inspection round, one fix batch, at most one
  confirm round, stop polishing. Step 7 finally names --render
2026-07-30 16:26:14 +01:00
Youssef dad9fe0f8c Rotation gets memory, the log gets axes, nav routing gets one truth
- Nav/footer no-repeat deepens from consecutive-runs-only to the last
  three runs, matching macro depth (N5/N1b ping-pong was legal before)
- The log schema grows axes and fingerprint fields (plus hero from the
  posture change) in all three write sites (SKILL.md, variants winner
  entry, custom § F), so structure.md's anti-repetition rule and gate 32
  now compare against the log instead of memory; older entries without
  the fields are treated as unconstrained
- The Picks block example gains the deck cell from the section-deck change
- component-cookbook routing tables become the single nav/footer authority:
  playful's default returns to N7 (its genre file had banned N5 while the
  cookbook listed N5 acceptable - resolved in the genre file's favour),
  modern-minimal's default settles on N1b with N5 explicitly acceptable,
  and every genre file's default line points at the authoritative table.
  A cross-check script confirms zero contradictions
- SKILL.md's nav range reads N1/N1b through N13 (no n1a file exists;
  N1a stays documented as the older alias)
2026-07-30 16:25:12 +01:00
Youssef 1428d2bde0 SaaS sections become a deck that must deviate, not a sequence to stamp
macrostructures.md's fixed hero-logos-features-testimonials-pricing-FAQ-CTA
run becomes a deck of eight core cards with roles. Every deal deviates
twice: drop at least one named card (hero and footer never drop), and
either promote a wildcard (spec-sheet, changelog, manifesto-inset,
worked-example, comparison-anatomy, index) or reorder one adjacent pair
meaningfully; both moves are stated in the Picks block as a deck: cell.
The completeness floor moves from 'skip at most two' (which contradicted
mandatory drops) to 'at least five core cards'. Voice rules survive intact.
The four theme specs that hard-coded section chains (cobalt, coral, field,
ledger) now name deck ingredients instead.
2026-07-30 16:23:33 +01:00
Youssef 886e1669db Catalog de-duplication: axis twins broken, mid paper band opened, fingerprints complete
- Coral: General Sans becomes the display/body family (Geist falls back);
  axis moves to grotesk-sans, breaking the Bloom/Coral twin
- Aurora: the teal-green (172) is promoted to the one UI signal at
  oklch(68% .145 172) (7.7:1 on paper) and cyan demotes to the first bloom;
  display becomes Sora 600. Breaks the Midnight/Aurora twin and cuts the
  Geist display collision from four themes to two
- Almanac 94% -> 84% cool slate stock and Riso 91% -> 84% pink stock: the
  previously empty mid paper band gets its first two occupants. Muted greys
  darkened to hold 4.5:1+, Riso's spot blue deepened to oklch(46% .14 220)
  so focus rings stay >= 3:1 on the deeper stock (the old cyan was already
  under 3:1), both accent-ink slots fixed to = paper (were unreadable)
- structure.md fingerprint table now covers all 24 themes; Aurora's row no
  longer duplicates Bloom's, the Brutal/Manifesto identical-row twin and
  the Sport/Coral/Bloom/Studio/Terminal near-twins are re-grounded, and a
  mechanical pairwise check passes: no two rows share more than three of
  the six structural axes (noted in the table preamble)
- theme-axes rows + closing note (Aurora 172 vs Ledger 185 arbitration),
  four spec files rewritten to the new values, main.js theme copy synced
  (plus the stale riso proofA and coral three-percent lines), site font
  links gain Sora + a Fontshare link (also fixes Sentient never loading),
  theme dots updated. Verified in the browser: riso/almanac render on the
  new stocks, Sora/Sentient/General Sans all load
2026-07-30 16:22:45 +01:00
Youssef c4a7b837d5 Hero postures: six named fold geometries replace the single silhouette
Every Hallmark hero shared one geometry (70-90% viewport, bottom-heavy 1.3x
padding). hero-discipline.md now opens with a posture table - Settled (the
old geometry, still the default), Banner, Poster, Ledge, Corridor, Stage -
each with its own min-height envelope, padding rule, alignment allowance,
H1-H9 pairings, and genre affinity. Mobile collapses to content height.

- hero-discipline.md loads on EVERY page hero now, not only enriched ones
  (SKILL.md Step 3 Always list), and the posture is picked at Step 2 with
  nav/footer, rotated (no non-Settled repeat back-to-back, Settled never
  three in a row), logged (hero: Stage/H2), stamped, and in the Picks block
- gate 6: the 100vh/100dvh ban is scoped outside a stamped Poster; the
  centred-element ceiling binds unchanged on all postures
- gate 44a: the padding check reads the stamped posture (Ledge inverts to
  top-heavy with base-anchored content, an anchored Poster waives it);
  44b fold-fit at 1280x800 stays posture-independent
- typography.md: define --text-display-s (referenced by the headline
  brackets but never declared): clamp(2.2rem, 4vw + 0.75rem, 4.2rem)

No script changes; absent stamp field = Settled, so every existing build
stays legal (canonical example dirs verified 0-FAIL).
2026-07-30 16:13:46 +01:00
Youssef c3553f7da7 Specs teach register, never composition; the imagery kit stops emitting dead links
- Seven theme specs (arcade, cobalt, field, garden, grid, ledger, riso) drop
  'canonical build to mirror' for 'reference build: match its register (tokens,
  voice, motion feel), never its composition; reusing its section order, hero
  geometry, or grid is a gate-32-grade repeat'
- Hum's .btn block becomes a recipe: press mechanics mandatory, skin free;
  the verbatim-copy mandate is gone. Spring easing scoped to micro press/pop
  only, and hero-discipline's bounce ban now says exactly that
- imagery-kit.md reframed: composition playbook today, hosted assets later;
  hard rule that no URL outside the (currently empty) manifest is ever emitted;
  the wash example now shows the constructed gradient equivalent
- hero-enrichment's Kit-led route renamed Composed-abstract (built in-page)
2026-07-30 16:11:29 +01:00
Youssef de6d5a4903 One release: everything on this branch is v1.2
Unify every version string: skill frontmatter and preview block, package.json,
the four preview-examples samples, the eval direction note, the ROADMAP opener,
and the site badges/captions (which were still stamped v1.1/v1.3). The PR is
retitled to match and sits as a draft on the renamed v1.2 branch.
2026-07-30 16:08:57 +01:00
Youssef 30c55128b2 v1.4.0: the harness pivot - one core, three first-class harnesses
Hallmark stops targeting open-weight models and goes deep on the three
terminals where design work happens: Claude Code, Codex CLI, and OpenCode.
Same core everywhere (SKILL.md standard), plus a per-harness adapter each
harness loads before Step 0.

- references/harnesses/codex.md: $hallmark invocation, workspace-write
  sandbox + network-off reality (picker server asks first, --static
  fallback), no hooks/subagents (sequential variants + progressive reveal),
  AGENTS.md as a Step 0 signal, batch-per-direction patches
- references/harnesses/opencode.md: /hallmark + skill-tool invocation,
  allow/ask/deny permission model, parallel variants via its subagents,
  formatter/LSP interplay, compatibility-path discovery
- references/models.md deleted; its harness-agnostic rules live on in both
  adapters. SKILL.md dispatch now routes by harness, not by model family
- agents/openai.yaml: Codex interface + implicit-invocation policy
- scripts/install.mjs: detects installed harnesses and installs a lean
  1.5MB payload (SKILL.md, references, scripts, agents, LICENSE - never
  site/ or eval/) to ~/.claude/skills, ~/.agents/skills (+ refreshes the
  stale legacy ~/.codex/skills copy), and leaves OpenCode to its
  compatibility discovery; --dry-run / --remove / idempotent
- README: 'Open models' section replaced by 'One skill, three harnesses'
  with the install matrix; ROADMAP and eval/README reframed (Tier B kept
  as archive only); version 1.4.0

Ran the installer live: all three locations now serve 1.4.0 with the
adapters in place (the Codex location previously held a 27MB v1.0.0 copy).
2026-07-30 12:08:56 +01:00
Youssef 746e812d90 Variants corner dock: full-bleed pages, one control surface bottom-right
The picker's single view, the on-page chip, the injection overlay, and the
static compare page all wrapped or barred the page they were showing. Replace
all four chromes with one shared HmDock factory in core.mjs: a compact glass
bar pinned to the bottom-right corner (grid glyph, chevrons, direct number
jump with a dimmed pulse for still-generating directions, small-caps title,
Pick, and an expandable tray with tuple meta, Riff, Graft, and key hints).
The page itself now fills the viewport everywhere.

- chip/inject mount the dock in a shadow root so page CSS cannot touch it,
  and read /api/state to learn titles, meta, and the live direction count,
  so a riffed direction 4 is reachable even with a stale data-of (serve.mjs
  gains CORS on /api/state for the routes-mode cross-origin read)
- chip gains Graft parity and an optional data-title attribute
- single view cycles ready directions only; compare page swaps the fake Pick
  for an honest 'pick N' chip that copies the chat reply to the clipboard
- variants.md updated to the dock (chip contract, picker walkthrough, riff
  note, static-compare shape, poll-ladder wording); site demo mirrors it

Verified in the browser on a scratch run: grid, full-bleed single view,
tray, ready-only arrow cycling, pick queued and drained through await.mjs,
chip on a direct page, live count refresh, static compare, mobile.
2026-07-30 12:08:33 +01:00
Youssef 3093e9e2f8 Fix grid-01 example: zero-chroma neutrals violated gate 22
The example was ported from the proposal mockup with oklch(x% 0 0) neutrals;
the shipped Grid theme tokens carry a faint cool cast (0.003-0.010 at hue 255).
Bring the example's palette in line: 7 FAILs -> sloplint clean.
2026-07-30 12:08:20 +01:00
Youssef 3968b6264c Coherence pass: fix the five defects the v1.3 review surfaced
- main.js: 4 stray '57 gates' marketing strings -> 58
- all-themes.html: visible H1 '20 themes' -> '24 themes'
- gen-cli.mjs header: correct arm ids (claude/glm/kimi) + token env names
  (ZAI_AUTH_TOKEN / MOONSHOT_AUTH_TOKEN)
- ledger spec: radius claim '8px tight' -> '12px card / 8px controls'
- arcade spec: note the starfield/scanline vars are page-local decorative
  tokens (define in :root per arcade-01), not catalog tokens
- tier-e stamp example uses the real imagegen default; hyphens
2026-07-24 15:08:01 +01:00
Youssef 2dc9974414 v1.3.0: version bump, README variants-v2 + edit-time-linting sections, roadmap refresh
Skill and package to 1.3.0; preview-example version strings to v1.3.0;
README variants section rewritten for v2 (progressive reveal, parallel +
sketch-default, thumbnails, compositional grafts, section-zoom, scoped
injection); ROADMAP marks the five v1.3 items shipped.
2026-07-24 14:55:42 +01:00
Youssef cc06e7f23c Variants v2: speed (progressive, sketch-default, parallel, analysis-once) + smoothness (grafts, section-zoom, decisions) + thumbnails + scoped injection
- scripts: core.mjs picker gains PNG-thumbnail grid (falls back to the
  scaled iframe), a Graft button + G key; serve.mjs adds /thumb + /inject
  routes and a graft action on /api/pick; new thumbs.mjs (dual-engine,
  zero-install); buildInjectJs for dev-only Vite/Astro/SvelteKit preview
  injection. All v1 behavior preserved (smoke-tested end to end + browser).
- verbs/variants.md v2 (280->423): progressive-first flow, parallel default
  + analysis-once + shared head, sketch-depth drafts by default (--full),
  optional --fast-drafts, compositional grafts, section-zoom after the pick,
  decisions.md log, thumbnail step, Vite/Astro/SvelteKit injection recipes.
- eval/variants-bench.{md,mjs}: speed-bench doc + a mechanical timing harness.
- site/_proposals/variants-demo.html: client-only progressive-picker demo
  (gradient text removed to stay on-brand); variants-vs.md head-to-head.

Verified in the browser: progressive fill (building -> thumbnail), labeled
counter, guarded arrows, Pick/Riff/Graft, live single-view iframe.
2026-07-24 14:53:59 +01:00
Youssef 272a55062a Tier A harness: gen-cli.mjs drives the real Claude Code binary
Runs 'claude -p "/hallmark <brief>"' with the skill copied into a scratch
project, parses the stream-json transcript for conformance (skill loaded via
stamp, files written, reference-read count + load-order, cost), writes into
runs/<brief>/<arm>-cli/. Skills do not auto-trigger headless (measured), so
it invokes by name: a conformance harness, not an auto-trigger test. Claude
arm uses the subscription (no key); GLM/Kimi arms Anthropic-shaped and
disabled until their auth tokens exist. Plumbing validated against the real
binary here (spawn, stream-json parse both event shapes, run.json); a real
run needs a logged-in terminal.
2026-07-24 14:42:13 +01:00
Youssef 50ed78f69b Spec files for the 4 new themes (Grid, Field, Ledger, Arcade)
Lean specs (131-150 lines) grounded in each new [data-theme] block and its
mockup: signature moves, anti-patterns, voice fixtures, and honest
neighbour-differentiation (Ledger vs Cobalt/Midnight; Arcade vs
Terminal/Hum). Arcade spec states the gate-47 carve-out inline (scanlines,
starfield, pixel type, cursor are the sanctioned retro signal; fake OS
chrome stays banned) and keeps body copy in the readable sans. Catalog
token names throughout; page-decorative tokens noted as page-added.
2026-07-24 14:36:11 +01:00
Youssef f760298ca9 Image hook (Together) + canonical examples for the 4 new themes
- scripts/imagegen.mjs: opt-in generated-still hook via Together's images
  endpoint (FLUX.1.1-pro default, gemini-3-pro-image optional), cache by
  prompt hash, provenance sidecar. No key -> graceful exit 3, falls back
  to CSS-art / placeholder (verified). Wired into tier-e-generated.md +
  SKILL Step 4 as opt-in, never auto-fires.
- site/examples/{grid,field,ledger,arcade}-01: canonical builds from the
  proposal mockups, all sloplint 0-FAIL, referenced by each theme spec.
2026-07-24 14:33:25 +01:00
Youssef 5426348836 Wire 4 new themes into the catalog: Grid, Field, Ledger, Arcade (20 -> 24)
- tokens.css: 4 [data-theme] blocks (full token set; Grid neutrals tinted
  to pass gate 22; Ledger/Arcade color-scheme dark; Arcade second accent)
- main.js: THEMES / ARCHETYPES / THEME_GENRES / COPY entries for all 4
- theme-axes.md: 4 rotation rows; SKILL.md Step 2.6 cluster list; genre
  files (Grid->editorial, Ledger->modern-minimal, Field+Arcade->playful)
- count strings bumped 20 -> 24 across skill, site, README; stale 57->58
  gate counts fixed in marketing copy
- Arcade gate-47 carve-out in slop-test + anti-patterns (pixel/scanline
  allowed; fake OS chrome still banned)
- site loads the 4 new themes' fonts; all 24 render in the live picker
2026-07-24 14:29:47 +01:00
Youssef 123599dd1c Theme specs for the 16 spec-less catalog themes
Lean specs (126-145 lines each, from the cobalt.md template) for specimen,
midnight, brutal, garden, atelier, newsprint, terminal, manifesto, almanac,
sport, studio, riso, bloom, coral, aurora, editorial. Each grounded in its
real [data-theme] tokens block and theme-axes row: signature moves,
anti-patterns, voice fixtures, macrostructure affinity, and honest
neighbour-differentiation. Loaded eagerly by Step 3 only when that theme is
picked, so zero cost to any build that picks a different theme. Also cleaned
em/en dashes from the 4 pre-existing specs.
2026-07-24 14:19:28 +01:00
Youssef 087dc859fd Edit-time lint hook: sloplint on write via PostToolUse, advisory only
- scripts/lint-hook.mjs: reads the PostToolUse payload, lints .html/.css
  Hallmark artifacts on write, feeds FAILs back via additionalContext,
  never blocks (exit 0 always), no-ops on non-artifacts
- scripts/install-hook.mjs: idempotent settings merge (--global/--print/
  --remove), preserves other hooks and permissions
- SKILL.md Step 7 note + README section; Claude-Code-only, degrades to
  the Step 7 sweep everywhere else
2026-07-24 14:06:27 +01:00
Youssef 75bafe3188 Strip em/en dashes from theme demo files 2026-07-24 10:38:05 +01:00
Youssef 054a860224 Seven full-page theme mockups: Plate, Grid, Bench, Maison, Field, Ledger, Arcade
Each is a complete self-contained landing page for a fictional brand in
the candidate theme's tokens, grounded in the reference sites (Aesop,
Vitra, Teenage Engineering, The Row, Notion, Mercury, Panic). All seven
pass sloplint clean (0 FAIL, 0 WARN). Linked from the theme cards via the
Open-full-page overlay.
2026-07-24 10:37:32 +01:00
Youssef 3e6fe26e73 Proposal pages: clickable full-page views + generated-page browser
- five-themes cards open a complete full-page mockup per theme
- before/after cards open the actual generated pages (before from
  hallmark-lab, after from the eval runs), copied into _proposals/pages
- eval judge defaults to operator mode: no Anthropic key spend, the
  Claude Code operator scores from the screenshots; --provider together
  or anthropic for an automated pass
2026-07-24 10:17:20 +01:00
Youssef 01386239f3 Eval run 2026-07-23: findings, judge fallback chain, output-ceiling fix
Full-pack matrix on Claude, GLM (Together), and the Kimi stand-in:
zero mechanical FAILs everywhere after at most one repair round; the
floor-only pack collapses on open models (96 FAILs on GLM), so the full
skill is load-bearing, not bloat. No-vision probe: every model declined
cleanly. Zero invented metrics. Rotation held per arm.

judge.py: Together vision fallback chain + User-Agent fix; vision judge
itself pending API credit or an OpenRouter key. gen-direct: 64K output
ceiling (Claude needed 37K on one brief).
2026-07-23 14:41:11 +01:00
Youssef 49b2724b7d Ignore eval caches and run artifacts 2026-07-23 13:28:33 +01:00
Youssef 6d52d29c50 Coherence pass: fix every contradiction the five-walkthrough review surfaced
- one canonical top-of-file order: stamp, critique line, direction contract
- theme-axes.md: the 20-row Rotation lookup now ships inside the skill
- tier taxonomies unified by name; craft tiers keep construction letters
- S1 reworked to stacked-numbered (the old side-column head was gate 54's
  own auto-fail); carnival + lumen examples brought up to gates 54/55/24;
  sloplint: mask/filter exemption on gate 22, precision fix + FAIL grade
  on gate 54, 15-line stamp window
- variants playbook matches the scripts byte for byte (request ids, riff
  shape, fallback wording, flow order); draft-sweep exceptions written
  into slop-test, custom-theme, and SKILL
- study.md: italic roles diagnosed as-is, built roman; preview-examples
  regenerated for v1.2
2026-07-23 13:28:26 +01:00
Youssef 71e88046f8 Docs for 1.2: five verbs, Variants and Open models sections, roadmap refresh 2026-07-23 13:08:45 +01:00
Youssef faf7d56233 Eval harness: direct-API bench matrix, screenshots, sloplint + vision-judge scoring, compare gallery
Arms: Anthropic baseline, GLM on Together, Kimi on OpenRouter (DeepSeek
and Qwen staged, disabled). Six briefs incl. metric-temptation,
component-scope, and vision-probe probes. Floor-only vs full skill packs
to measure prompt bloat. run-matrix orchestrates gen, shots, score,
judge, report; the repair loop feeds sloplint FAILs back to the model.
2026-07-23 13:08:45 +01:00
Youssef 04a9873633 The variants verb: three live directions, a local picker, pick-and-continue
- scripts/variants/{core,serve,start,await}.mjs: zero-dep picker server
  (loopback only, port walk-up, polling, atomic request queue, idle
  self-shutdown), scaled-iframe grid + single view + keyboard flow,
  chip.js overlay for generated routes, static compare fallback
- references/verbs/variants.md: context detection, per-framework route
  recipes, shared ceremony + direction-plan table, divergence rules,
  the poll ladder, pick-and-continue, riff
2026-07-23 13:08:45 +01:00
Youssef 75c577fd1d Custom art-direction ritual: the slate, the draw, postures, the direction contract
- custom-theme.md: reflex check at two altitudes, spent defaults, a
  seven-entry slate, the deterministic draw with wildcards, the scene
  sentence, four colour postures, a five-block direction contract with
  a promise-by-promise finish review; loosened triggers; reworked
  worked examples
- scripts/seed.mjs: reproducible draw (FNV-1a over brief + date + reroll)
- references/direction-atlas.json: 41 design-history lineages dealt as
  wildcards
2026-07-23 13:08:45 +01:00
Youssef b901563ac3 Open-model hardening: sloplint mechanical checker, gate classes, models.md, no-vision study path
- scripts/sloplint.mjs: zero-dep checker for the M-class gates, optional
  render tier, fixtures; calibrated to 0 FAIL on shipped examples
- slop-test.md: every gate tagged M / M-R / R-J / J, numeric fallbacks
  for gates 35 and 44, posture clause on gate 23
- SKILL.md: critical floor, flow skeleton, script-first Step 7,
  harness-neutral phrasing, models.md dispatch, v1.2.0
- references/models.md: per-family quirks, loaded only off-Claude
- study.md: capability check before image mode, fetch-tool neutral wording
- color.md: Colour postures; responsive.md: mechanical-equivalent pointers
2026-07-23 13:08:45 +01:00
Youssef 80701e3cc5 Speed pass: consolidate SKILL.md, slim anti-patterns, split enrichment and craft into index-then-pick files
- SKILL.md 559 to 331 lines: critical floor, flow skeleton, one Rotation
  block, one Picks block, fast mode, per-step Do lines
- anti-patterns.md becomes a 120-line pre-emit list; audit reporting
  moves to verbs/audit.md
- hero-enrichment.md and custom-craft.md become slim indexes over new
  references/enrichment/ and references/craft/ per-pick files
- Core-15 sweep named in slop-test.md for component scope
- pointer cleanup in macrostructures.md and component-cookbook.md;
  tokens.css header count fixed
2026-07-23 12:40:42 +01:00
Youssef 0c4f5ef8d3 Theme research: proposal page with five candidates and two alternates 2026-07-23 12:40:42 +01:00
Hassan El MghariandGitHub aeb42fb354 Merge pull request #18 from Nutlope/fix/existing-stylesheet-merge
Append to an existing global stylesheet instead of overwriting it
2026-06-04 16:42:42 -04:00
Hassan El MghariandGitHub 2cd53ce4d3 Merge pull request #17 from Nutlope/fix-v1.1-count-consistency
fix: reconcile slop-test gate count (58) and stale N1 nav refs
2026-06-04 16:42:02 -04:00
Youssef 58517f0f18 Append to an existing global stylesheet instead of overwriting it
When Hallmark builds into a project that already has an entry stylesheet
(e.g. app/globals.css, src/index.css), treat it as append-only: keep the
existing @tailwind / @import "tailwindcss" directives and the project's own
tokens, add the Hallmark layer below them, and keep any new @import at the
top. Overwriting it was silently dropping the framework's CSS entry
directives and the user's tokens, which left the whole app unstyled.
2026-06-04 15:35:14 +01:00
Youssef df5498f7f6 README: show Mend Assembly in the Custom section, move Ferns & Fathom to the gallery 2026-06-03 19:06:34 +01:00