Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/median-headings-vessel-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@design-intelligence/ghost": patch
---

Reframe the median as Ghost-stamped model truth and align Vessel's median check with heading anchors.
5 changes: 5 additions & 0 deletions .changeset/median-one-home.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@design-intelligence/ghost": minor
---

The median floor gets one authored home: `anti-goal.median` rules become markdown headings with per-rule check references, so `ghost validate` warns on every flag orphaned by pruning. All init templates (`skeleton`, `minimal`, `composition`) now stamp the median node; `ghost checks init` copies the paired check from the packaged payload and skips it when the node is absent.
2 changes: 1 addition & 1 deletion apps/docs/src/content/docs/cli-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ a finding (exit `1`).

### Initialize: `init`

Scaffold a `.ghost/` package with the skeleton starter: a manifest, a `glossary.md` declaring the grammar/signature/register/anti-goal kinds, a core `index.md`, six grammar nodes of value-free decision logic, four signature nodes as unanswered dials awaiting your brand's values, and `anti-goal.median` — the model's measured defaults as reject→replace rules, pruned per brand. Nothing in the skeleton is fiction: grammar and the median floor are safe to consume verbatim; the dials tell the agent to ask or flag, never freehand. Use `--template minimal` when you only want the small manifest/glossary/index starter. Add truths by adding files (`principle.density.md`). Use
Scaffold a `.ghost/` package. Every template and body includes `anti-goal.median`; the skeleton starter also includes a manifest, a `glossary.md` declaring the grammar/signature/register/anti-goal kinds, a core `index.md`, six grammar nodes of value-free decision logic, and four signature nodes as unanswered dials awaiting your brand's values. The median node is Ghost's measured knowledge of unsteered model behavior — model truth, not brand truth — stamped at init and owned (pruned, adapted) by you thereafter. Nothing in the skeleton is fiction: grammar and the median floor are safe to consume verbatim; the dials tell the agent to ask or flag, never freehand. Use `--template minimal` when you only want the small manifest/glossary/index starter. Add truths by adding files (`principle.density.md`). Use
`--package <dir>` for an exact directory, or set `GHOST_PACKAGE_DIR` when a host
wrapper stores Ghost files outside the default `.ghost`. Core `init` scaffolds
the fingerprint only; pass `--with checks` to also add the checks directory in
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ by decision. One high-confidence truth beats an empty catalog.

The CLI handles the deterministic package work. Your agent handles the authoring:
interviewing you, working with the material you show it, drafting node prose,
and asking you to curate the claims. `ghost init` scaffolds the skeleton starter: `manifest.yml`, a `glossary.md` declaring the grammar/signature/register/anti-goal kinds, a core `index.md`, six grammar nodes of value-free decision logic, four signature nodes as unanswered dials, and `anti-goal.median` — the model's measured defaults as reject→replace rules headed by a prune instruction. Nothing in the skeleton is fiction: grammar and the median floor hold for any brand, and each dial tells the agent to ask you or flag the gap rather than freehand a value. Answering the dials is how the skeleton becomes your brand. Use `ghost init --template minimal` when you only want the small manifest/glossary/index starter.
and asking you to curate the claims. `ghost init` stamps `anti-goal.median` into every template and body; the median node is Ghost's measured knowledge of unsteered model behavior — model truth, not brand truth — owned (pruned, adapted) by you after init. The skeleton starter also includes `manifest.yml`, a `glossary.md` declaring the grammar/signature/register/anti-goal kinds, a core `index.md`, six grammar nodes of value-free decision logic, and four signature nodes as unanswered dials. Nothing in the skeleton is fiction: grammar and the median floor hold for any brand, and each dial tells the agent to ask you or flag the gap rather than freehand a value. Answering the dials is how the skeleton becomes your brand. Use `ghost init --template minimal` when you only want the small manifest/glossary/index starter.

```bash
ghost init
Expand Down
9 changes: 8 additions & 1 deletion packages/ghost/src/commands/checks-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ export function registerChecksCommand(cli: CAC): void {
if (opts.format === "json") {
process.stdout.write(
`${JSON.stringify(
{ dir: result.dir, written: result.written },
{
dir: result.dir,
written: result.written,
skipped: result.skipped,
},
null,
2,
)}\n`,
Expand All @@ -45,6 +49,9 @@ export function registerChecksCommand(cli: CAC): void {
for (const file of result.written) {
process.stdout.write(` ${file}\n`);
}
for (const file of result.skipped) {
process.stdout.write(` skipped ${file}\n`);
}
}
process.exit(0);
} catch (err) {
Expand Down
10 changes: 9 additions & 1 deletion packages/ghost/src/commands/init-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ export function registerInitCommand(cli: CAC): void {
dir: result.paths.dir,
written: result.written,
...(addedChecks !== undefined
? { checks: { written: addedChecks.written } }
? {
checks: {
written: addedChecks.written,
skipped: addedChecks.skipped,
},
}
: {}),
},
null,
Expand All @@ -97,6 +102,9 @@ export function registerInitCommand(cli: CAC): void {
for (const file of addedChecks.written) {
process.stdout.write(` checks/${file}\n`);
}
for (const file of addedChecks.skipped) {
process.stdout.write(` skipped checks/${file}\n`);
}
}
}
process.exit(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,82 @@ description: "The model's median defaults this fingerprint refuses — gather fo

This is the model's median, not your brand. Each rule is reject→replace.
Delete every line your brand legitimately violates — `ghost validate` will
surface any check the deletion orphans.
warn on any check reference the deletion orphans — delete the paired flag too.

These are not aesthetic opinions. Where a count is given, it is the measured
convergence of 300 unsteered generations across three frontier models (the
antimedian experiment): the defaults a model reaches for when nobody hands it
a brand. An output showing several of these tells reads as generated,
whatever else it does right. A deterministic floor rides alongside these
rules in checks — contrast, reduced motion, sane z-index, no overshoot
easing — verified at review, never steered in prose.
rules in the paired check — mechanical tells like gradient-filled text,
emoji as interface icons, em-dash pileups, and aphoristic cadence —
verified at review, never steered in prose.

<!-- rule:median-hover-lift -->
### Hover-lift
Reject hover-lift (`translateY` + growing shadow) as the default interaction
→ confirm with color and background change at the fingerprint's fast
duration. (measured: 341)

<!-- rule:median-indigo-accent -->
### Indigo accent
Reject the indigo/blue/purple default accent (`#4f46e5`, `#2563eb`,
`#8b5cf6` family; purple/violet hue 260–310) → the fingerprint's declared
palette; absent one, monochrome plus a single functional accent.

<!-- rule:median-dark-theme -->
### Dark theme
Reject unprompted dark theme → the fingerprint's declared surface.
Dark-to-look-cool and light-to-be-safe are the same retreat from a decision.
(measured: 271)

<!-- rule:median-gradients -->
### Gradients
Reject gradient page and section backgrounds and gradient-filled CTAs → flat
surfaces in semantic roles.

<!-- rule:median-side-stripe -->
### Side-stripe
Reject side-stripe borders (a thick colored border on one side of a rounded
card) — the single most recognizable tell of AI-generated UI → a full
hairline border, a 4–8% surface tint, or a leading glyph.

<!-- rule:median-cream-surface -->
### Cream surface
Reject the cream/sand/beige default surface (warm off-white; token names
like `--cream`, `--sand`, `--parchment` are the tell) → a true off-white,
the brand's own hue, or a committed color; warmth via accent and type, not
the ground.

<!-- rule:median-glassmorphism -->
### Glassmorphism
Reject glassmorphism (decorative backdrop blur) → flat surfaces with real
borders and the fingerprint's elevation tiers.

<!-- rule:median-chat-bubbles -->
### Chat bubbles
Reject chat bubbles with initials-circle avatars for assistant turns →
assistant text plain on the page surface; user turns marked compactly.

<!-- rule:median-stock-copy -->
### Stock copy
Reject stock template copy ("Simple, transparent pricing") → headings that
state what this product specifically does.

<!-- rule:median-celebration -->
### Celebration
Reject celebration copy and UI (exclamation success, confetti language) →
quiet factual confirmation.

<!-- rule:median-nested-cards -->
### Nested cards
Reject nested cards and everything-in-cards → one surface level per region;
interior hierarchy from spacing and type; spacing and alignment group
without card overhead.

<!-- rule:median-hero-metric -->
### Hero metric
Reject the hero-metric template (big number + small label + supporting stats
as default proof) → evidence specific to the product, or nothing. A
prominent metric showing real user data is fine.

<!-- rule:median-every-button-primary -->
### Every button primary
Reject every button a primary button → one primary per view; the rest step
down the fingerprint's emphasis ladder.

<!-- rule:median-eyebrow-kicker -->
### Eyebrow kicker
Reject an eyebrow kicker on every section → at most one, where the register
sanctions it; one named kicker is voice, every-section is AI grammar.

<!-- rule:median-decorative-motion -->
### Decorative motion
Reject decorative looping animation (pulse/float/shimmer) and uniform
fade-and-rise on every scrolled section → motion as evidence of state
change; loops only for genuine loading; decoration never compensates for
Expand Down
117 changes: 117 additions & 0 deletions packages/ghost/src/init-payloads/median/median-tells.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
name: Median tells
description: Flags the measured defaults of unsteered generation, the deterministic floor, and current model-signature tells — hover-lift, default accents, unprompted dark theme, gradient text, contrast, frequency tells, and per-model signatures.
severity: high
references:
- anti-goal.median > Hover-lift
- anti-goal.median > Indigo accent
- anti-goal.median > Dark theme
- anti-goal.median > Gradients
- anti-goal.median > Glassmorphism
- anti-goal.median > Side-stripe
- anti-goal.median > Cream surface
- anti-goal.median > Chat bubbles
- anti-goal.median > Stock copy
- anti-goal.median > Celebration
- anti-goal.median > Hero metric
- anti-goal.median > Eyebrow kicker
---

These flags target the measured convergence patterns of unsteered model
generation, the deterministic floor the median node licenses, and tells
specific to individual models. Each is mechanically detectable in a diff.
Pruning a rule from `anti-goal.median` orphans its paired reference here —
`ghost validate` warns; delete the flag and its reference together.

Flag `transform` with `translateY` inside a `:hover` rule on cards,
buttons, or list items, especially paired with a shadow increase. Hover
confirmation in this fingerprint is color and background change, not lift.
(`anti-goal.median > Hover-lift`)

Flag accent values in the indigo/blue/purple default family (`#4f46e5`,
`#6366f1`, `#2563eb`, `#3b82f6`, `#8b5cf6`, and close neighbors)
unless the diff shows the user asked for them. They are model defaults, not
palette members. (`anti-goal.median > Indigo accent`)

Flag whole-page dark backgrounds when the ask did not request dark mode.
Dark surfaces are a declared brand choice or an explicit theme, never an
unprompted default. (`anti-goal.median > Dark theme`)

Flag `linear-gradient` or `radial-gradient` as page or section
backgrounds, and gradient-filled buttons. (`anti-goal.median > Gradients`)

Flag `backdrop-filter: blur` used for glassmorphism cards.
(`anti-goal.median > Glassmorphism`)

Flag `background-clip: text` (with or without the `-webkit-` prefix)
paired with a gradient. Emphasis comes from weight or size in a single
solid color.

Flag a thick colored border on one side of an element (`border-left` or a
`border-l-*` utility at 2px or more in a non-neutral color) while the
other sides stay thin. (`anti-goal.median > Side-stripe`)

Flag warm off-white page backgrounds in the cream/sand/beige band, and token
names like `--cream`, `--sand`, `--parchment`, `--linen` introduced
by the diff. (`anti-goal.median > Cream surface`)

Flag assistant messages rendered as bubbles with initials-circle avatars.
(`anti-goal.median > Chat bubbles`)

Flag emoji used as icons or imagery in interface chrome. Text labels carry
meaning.

Flag stock template copy in headings: "Simple, transparent pricing",
"Welcome back", and interchangeable-with-a-competitor phrasing. Recommend
copy that states what this product specifically does.
(`anti-goal.median > Stock copy`)

Flag exclamation-marked success copy, confetti language, and celebratory UI
("You did it!", "Awesome!"). Confirmation is quiet and factual.
(`anti-goal.median > Celebration`)

Flag the hero-metric template — a big number, small label, and supporting
stats as default proof — unless the metric shows real user data. Recommend
evidence specific to the product, or nothing.
(`anti-goal.median > Hero metric`)

Deterministic floor — licensed by the median node, verified here, never
steered in prose:

Flag text/background pairs below WCAG AA contrast: 4.5:1 for body text,
3:1 for large text (24px and up, or 18.7px bold and up). Check the worst
stop when the background is a gradient.

Flag animation or transition without a `prefers-reduced-motion: reduce`
alternative — a crossfade or instant state change.

Flag ad-hoc z-index values (`999`, `9999`, or any value outside a
declared scale). Layering wants a semantic scale, not an arms race.

Flag `cubic-bezier` easings whose control points overshoot the 0–1 range,
and keyframe names matching bounce, elastic, wobble, or jiggle.

Frequency tells — the crime is repetition, not the move (advisory):

Flag three or more uppercase, tracked eyebrow kickers above section headings
in one page. One named kicker is voice; a kicker on every section is model
grammar. (`anti-goal.median > Eyebrow kicker`)

Flag five or more em-dashes in body copy in one view.

Flag three or more instances of the aphoristic rebuttal cadence ("Not X. Y."
/ "Sentence. No qualifiers.") in one page's copy.

Model-signature tells — skip any block whose model did not produce the diff
(advisory):

Codex: flag a 1px border paired with a box-shadow of 16px blur or more on
the same element — pick a solid border or a tight shadow, not both. Flag
border-radius of 32px or more on cards, sections, or inputs unless an
answered shape dial (`signature.shape`) sanctions large radii — then it is
fidelity, not a tell. Flag 1px linear-gradient grid or repeating-stripe
backgrounds used as decoration.

Gemini: flag `transform` (scale, rotate, translate) on `img` inside a
`:hover` rule, including group-hover utilities targeting a child image.
Animate the card's background, border, or shadow instead.
4 changes: 2 additions & 2 deletions packages/ghost/src/init-payloads/skeleton/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ kinds:
# grammar

The brand's decision logic: closed sets, role vocabularies, and assembly
rules, stated in token roles and never in literal values. Grammar survives a
rebrand unchanged — swap every value and these nodes still hold. Gather
rules, stated in token roles and never in literal values. Grammar survives an
adaptation unchanged — swap every value and these nodes still hold. Gather
grammar before inventing structure.

# signature
Expand Down
4 changes: 2 additions & 2 deletions packages/ghost/src/init-payloads/skeleton/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
description: "Always read first — the trust tiers of this starter fingerprint, the unanswered dials, and how to work before they are answered."
---

This is a skeleton fingerprint: the rebrand-safe law of good interface work,
This is a skeleton fingerprint: the adaptation-safe law of good interface work,
with every brand decision left explicitly open. It steers an agent away from
the model's median from the first generation, without pretending to be a
brand it is not.

The corpus carries two trust tiers. Grammar and the median floor are law:
safe to consume verbatim, unchanged by any future rebrand — they speak in
safe to consume verbatim, unchanged by any adaptation — they speak in
token roles and closed sets, never in literal values. Signature nodes are
dials, and in this starter every dial is unanswered: each states the fixed
relationship worth keeping and the question only a human can answer. Do not
Expand Down
Loading