17 Commits
Author SHA1 Message Date
Youssef 52aa127d60 The harness that scored the old skill had a third instance of the same bug
The runs archive copied a fixed filename list, index.html, tokens.css,
styles.css, and stampPresent scans that archive. A swept build whose stamp
lives in page.css scored skillLoaded=false with a correct stamp on disk,
which is the same stale assumption already fixed in stampPresent and in the
reference budget, one function lower. The archive now takes every top-level
html and css the build produced.

The three affected run.json files are rescored from the real artifacts:
only the buggy cell changed (inspo false to true); the bare control stays
false, which is the leak check holding. Also archives the second three-arm
run: bare 56 FAIL with the same six numbered eyebrows, both Hallmark arms
clean, and the control now provably offered zero MCP tools.
2026-08-06 15:17:36 +01:00
Youssef 7425c415c3 Two live builds prove the flip, and the harness that scored them was measuring the old skill
b1 names no theme, so it must derive, and it did: direction.md was the first
reference read, the stamp carries a real seed and a five-line direction
contract, and the derived world (the IPA vowel quadrilateral, plotted, on a
speech-lab plate) reaches the actual hero rather than stopping at the stamp.
Twelve reference reads, zero waste, in the right order. R.1's rejection is
legible in the genre note: it refused the radial blooms the atmospheric genre
would have allowed, because the reflex check had already spent that move.

b7 passes --fast and must not derive, and did not. It read two theme files and
never opened direction.md. No seed, no contract, no slate, no draw line. The
posture line still emits, which is the color.md repair working: posture is
universal now, not a derived-run field.

Both artifacts lint clean at 0 FAIL, 0 REFLEX, 0 WARN.

Three harness bugs, all of them the flip's doing. stampPresent scanned a fixed
filename list of index.html, styles.css and tokens.css, and a build that named
its stylesheet page.css scored skillLoaded=false with a correct stamp sitting in
it; its regex also demanded Hallmark immediately after the comment open, so
"/* Formant Studio · Hallmark derived system" missed too. It now scans every
emitted css and html and matches the marker anywhere in a leading comment.

The reference-read budget was ten, set when a run read one theme file. A derived
run reads direction.md and theme-axes.md in its place, so the floor moved up by
one, and a clean derived build measures twelve. Fourteen leaves room for two
conditionals and still catches the thing the check is for, which is defensive
pre-loading of a forty-file tree.

The cost cap was three dollars, hardcoded. A derived build on Opus lands near
three and stopped mid Step-7, which scored a complete artifact as
error_max_budget_usd and never exercised the gate sweep at all. It is --budget-usd
now, defaulting to five.

b7 also joins the brief set: the suite had no coverage of the catalog fast path
after that path stopped being the default.
2026-08-06 11:59:50 +01:00
Youssef 37081e89a1 Comp before build, and a reviewer that did not watch the build
Two mechanisms Phase 1 could not supply, both conditional, neither able to block.

Step 5.5 renders the first viewport before composing it in CSS. It fires only
when TOGETHER_API_KEY is present (signal 9); with no key the step does not exist
and nothing else changes. Two comps at 1280x800 built from the direction
contract rather than the brief, varied on one compositional axis so the
comparison means something, one approval point, then build. The prompt carries
the scene sentence, the paper and accent as plain colour words, the display
class rather than a face name, and one negative clause pushing off the category
default, because a prompt that reads like the brief returns the category default
in pixels and that is what R.1 already spent its budget refusing.

The comp gets no vote on the Floor. An image generator will hand back eyebrows,
a gradient ramp and a fake browser window because it has read none of the gates.
Same rule as an archive exemplar: take the composition, not the compliance.

Reproduction is the part that makes the step worth having. A model reliably
believes its recreation succeeded when it did not, and the belief is what stops
it looking, so the built hero is screenshot at the comp's own dimensions and
answered in writing on mass, interval and entry before anything below the fold
exists. Diverging from the comp deliberately is fine. Diverging without noticing
is the failure.

The medium inventory sits under it: every region gets a written implementation
medium before any of it is built, and the gate is that a CSS gradient is not a
texture. Writing CSS against woven cloth or printed grain is how a committed
comp silently becomes a flat page with the same section order.

Step 7 gains a reviewer with no inherited transcript. The thread that walks the
gates is the thread that formed every opinion it is grading and reads the page
as the thing it meant rather than the thing it made, which is the weakest
reviewer available and the one every build has used. The new one gets the
artifact, the screenshots, the contract and the Floor list, and nothing about
why. It answers the question no gate can reach: does the direction contract
describe the page in front of it. Every gate is local, so a page can pass all
fifty-eight while quietly not being what its own stamp claims.

Findings are then scored resolved, partial or unresolved rather than
re-reviewed, unresolved is a legitimate outcome, and two rounds is the ceiling.
Off Claude Code the review runs in-thread and says so, because the user is
entitled to know which one they got.

Read-set cost for a run with no key and no subagents: zero. comp.md loads on
signal 9 only, and the reviewer brief lives in slop-test.md, which already
loaded at Step 7.
2026-08-06 11:22:13 +01:00
Youssef 1695c9defb Trim the branch to what the README and the site actually show
The eval run outputs, the internal design proposals, and a scratch QC
page for the imagery kit were all riding along in the PR while being
linked from nothing. They come out of tracking: eval/runs (the four A/B
cells from this session plus the older model-comparison artifacts, all
of it evidence rather than product), site/_proposals (44 files of
before/after and theme-exploration pages, preserved outside the repo),
and site/imagery/_qc.html (a scratch grid I used to eyeball the
generated assets). The eval harness itself stays so the tests are
re-runnable, and .gitignore now covers the pycache and the QC pages that
slipped past it.

The four theme examples added this round stay: arcade-01, field-01,
grid-01, and ledger-01 are the worked examples their own theme docs link
to, not stray test output.
2026-07-31 14:25:25 +01:00
Youssef 509ec0662b A/B evidence: four live Sonnet cells, with and without the skill
Two briefs (voice-cloning studio, pre-traction B2B SaaS) built twice
each, once with no skill and once running the Hallmark flow, same model
and same subscription. Artifacts, run records, and the skill's own state
files land under eval/runs so the comparison is auditable rather than
asserted: the two control pages carry 95 sloplint failures between them
(off-scale spacing, unowned colour literals, pure #fff surfaces,
layout-property transitions, no provenance stamp), the two skill pages
carry none, at roughly a third more tokens and a tenth more wall-clock.
Both arms respected the pre-traction brief's honesty constraint, so that
half of the test was a wash and each run.json records it that way, along
with the runner substitution and the effort setting actually used.
2026-07-31 14:04:33 +01:00
Youssef 5262882305 gen-cli sheds host-session env so child auth works in a logged-in terminal
Running the harness from inside a Claude Code session leaks
ANTHROPIC_BASE_URL and the CLAUDE_CODE_* host vars into the spawned
claude, which then reports not-logged-in even in an authenticated
terminal. The child env now drops them alongside the API key. Also
removes the six dead cells that run recorded: headless subscription auth
needs a terminal login this environment cannot perform, so the A/B
results were produced with in-session subagents instead (disclosed in
the PR).
2026-07-31 12:42:03 +01:00
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 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 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 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 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 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