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
6 changes: 6 additions & 0 deletions .changeset/clarify-agent-guidance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"ghost-drift": patch
"ghost-expression": patch
---

Clarifies agent-facing scan and drift guidance across docs and skill bundles.
70 changes: 35 additions & 35 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions apps/docs/src/app/tools/expression/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const cards: {
name: "Format spec",
href: "https://github.com/block/ghost/blob/main/docs/expression-format.md",
description:
"The full expression.md spec — frontmatter schema, three-layer body, 49-dim machine vector.",
"The full expression.md spec — authored frontmatter, portable prose, and derived runtime views.",
icon: <FileText className="size-8" strokeWidth={1.5} />,
},
];
Expand All @@ -48,7 +48,7 @@ export default function GhostExpressionLanding() {
<AnimatedPageHeader
kicker="ghost-expression"
title="Authoring"
description="The package that owns expression.md — Ghost's canonical design-language artifact. YAML frontmatter for machines, prose body (Character / Decisions) for humans and LLMs. Validated, described, diffed, and emitted into per-project review commands and grounding bundles for any generator."
description="The package that owns expression.md — Ghost's authored design-language contract. YAML frontmatter stores compact value digests, while the prose body (Character / Signature / Decisions) explains the design choices for humans and LLMs. Validated, described, diffed, and emitted into per-project review commands and context bundles for any generator."
/>

<div
Expand Down
46 changes: 18 additions & 28 deletions apps/docs/src/content/docs/cli-reference.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: CLI Reference
description: Eighteen verbs across three tools. Everything interpretive lives in the skill bundles your host agent runs.
description: Eighteen verbs across three tools. Judgment work lives in the skill bundles your host agent runs.
kicker: Docs
section: guide
order: 20
Expand All @@ -9,17 +9,16 @@ slug: cli

<DocSection title="Overview">

The CLIs are the calculator your host agent reaches for when it needs a
reproducible answer. A scan produces three artifacts in sequence — **`map.md`**
The CLIs give your host agent reproducible answers. A scan produces three artifacts in sequence — **`map.md`**
(map the system) → **`survey.json`** (survey what exists) → **`expression.md`** (express what it means) —
all owned by `ghost-expression`. Most commands accept a path; they default to
`./expression.md` for kind-aware verbs. No API key required.
`./expression.md` for kind-aware verbs. No API key required.

Verbs are scoped to the tool that owns the artifact:

- **`ghost-expression`** — the scan pipeline: `inventory`, `scan-status`, `lint`, `verify-profile`, `describe`, `diff`, `survey <op>`, `emit`
- **`ghost-drift`** — drift detection + governance: `compare`, `ack`, `track`, `diverge`, `emit skill`
- **`ghost-fleet`** — elevation across many members: `members`, `view`, `emit skill`
- **`ghost-drift`** — drift detection + stance: `compare`, `ack`, `track`, `diverge`, `emit skill`
- **`ghost-fleet`** — view across many members: `members`, `view`, `emit skill`

Workflows like _scan_, _map_, _survey_, _profile_, _review_, _verify_, and
_remediate_ are skill recipes your host agent runs — not CLI verbs. Install
Expand Down Expand Up @@ -82,18 +81,11 @@ recommended next stage (or "scan complete" when every artifact is present).

Operate on `ghost.survey/v2` files:

- **`merge`** — concat with id-based dedup, deterministic and idempotent.
The composition primitive: modular rollups (one repo, N feature modules)
and fleet cohort views (N members merged into one cohort survey) both
reduce to survey merge.
- **`fix-ids`** — recompute every row's `id` from its content. The survey
recipe instructs the agent to author rows with `"id": ""` and finalize
with this verb in one pass — agents don't compute SHA-256 hashes by hand.
- **`summarize`** — emit a bounded Markdown or JSON digest for broad
profiling context.
- **`catalog`** — emit a deterministic compact value enum/spec view derived
from survey rows. Markdown is the default; JSON uses
`ghost.survey.catalog/v1`. Use `--kind <kind>` to focus one value family.
- **`merge`** — combine surveys with id-based dedup.
- **`fix-ids`** — recompute every row's `id` from its content.
- **`summarize`** — print a short Markdown or JSON digest for profiling.
- **`catalog`** — print exact value enums/specs derived from survey rows.
Markdown is the default; JSON uses `ghost.survey.catalog/v1`.

<CliHelp tool="ghost-expression" command="survey" hideDescription />

Expand Down Expand Up @@ -144,13 +136,11 @@ ghost-expression lint path/to/expression.md --format json

### Profile fidelity — `verify-profile`

Validate that an `expression.md` stayed faithful to the `survey.json` that
produced it. This is stricter than `lint`: palette, spacing, typography,
radii, and shadow posture must be backed by survey evidence; high-salience
new survey values are surfaced as drift warnings; and promoted `checks[]`
entries must carry calibration metadata. With `--root`, promoted check
patterns are counted under their `paths` scopes and mismatched
`observed_count` values fail the gate. `contexts` are guidance only.
Validate that an `expression.md` matches its `survey.json`. This is stricter
than `lint`: palette, spacing, typography, radii, and shadow posture must be
survey-backed. High-salience survey values omitted from the expression become
warnings. With `--root`, promoted check patterns are counted under their
`paths` scopes; `contexts` are guidance only.

<CliHelp tool="ghost-expression" command="verify-profile" hideDescription />

Expand Down Expand Up @@ -239,7 +229,7 @@ ghost-expression emit skill
# Emit a per-project design-review slash command
ghost-expression emit review-command

# Emit a grounding bundle any generator can consume
# Emit a context bundle any generator can consume
ghost-expression emit context-bundle

# Single prompt.md for plain-text LLM context
Expand All @@ -251,7 +241,7 @@ ghost-expression emit context-bundle --out dist/context

</DocSection>

<DocSection title="ghost-drift — drift detection & governance">
<DocSection title="ghost-drift — drift detection & stance">

### Comparison — `compare`

Expand Down Expand Up @@ -333,7 +323,7 @@ ghost-drift emit skill --out ~/.my-agent/skills/ghost-drift

</DocSection>

<DocSection title="ghost-fleet — elevation across members">
<DocSection title="ghost-fleet — view across members">

A fleet is a directory containing many `(map.md, expression.md)` members.
`ghost-fleet` reads the fleet, emits per-fleet outputs (`fleet.md` +
Expand Down
70 changes: 30 additions & 40 deletions apps/docs/src/content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,28 @@ slug: getting-started
<DocSection title="The Shape of Ghost">

Ghost is split into **four small tools**, each with one responsibility, plus a
shared library (`@ghost/core`) underneath. Your host agent (Claude Code, Cursor,
Goose, Codex, …) does the interpretive work — profile, review, verify, remediate —
using [agentskills.io](https://agentskills.io)-compatible recipe bundles that
each tool ships. The CLIs are the calculator the agent reaches for when it
needs a reproducible answer.
shared library (`@ghost/core`). Your host agent (Claude Code, Cursor, Goose,
Codex, …) does the judgment work: profile, review, verify, remediate. The CLIs
handle deterministic checks such as linting, profile verification, diffs, and
distance.

A scan runs in three stages, all owned by `ghost-expression`:

```
map → survey → expression
map.md survey.json expression.md
ghost.map/v2 ghost.survey/v2 (the canonical artifact)
ghost.map/v2 ghost.survey/v2 design contract
```

| Tool | Owns | Verbs |
| --- | --- | --- |
| `ghost-expression` | the three-stage scan pipeline | `inventory`, `scan-status`, `lint`, `verify-profile`, `describe`, `diff`, `survey <op>`, `emit` |
| `ghost-drift` | drift detection + governance | `compare`, `ack`, `track`, `diverge`, `emit skill` |
| `ghost-fleet` | `fleet.md` (elevation across members) | `members`, `view`, `emit skill` |
| `ghost-drift` | drift detection + stance | `compare`, `ack`, `track`, `diverge`, `emit skill` |
| `ghost-fleet` | `fleet.md` (view across members) | `members`, `view`, `emit skill` |
| `ghost-ui` | reference design system (97 shadcn components) | — |

You install Ghost in two steps: add whichever CLI(s) you need, then emit the
matching skill bundle into your agent.
Install the CLI(s) you need, then emit the matching skill bundle into your
agent.

</DocSection>

Expand Down Expand Up @@ -64,8 +63,7 @@ embeddings, `GITHUB_TOKEN` for fetching tracked expressions).

<DocSection title="Install the Skill Bundles">

Each tool ships its own bundle. Install whichever capability you want
your agent to gain:
Each tool ships its own recipe bundle:

```bash
ghost-drift emit skill # → .claude/skills/ghost-drift
Expand All @@ -79,19 +77,16 @@ Each bundle ships its own `SKILL.md` plus recipes under `references/`:
- **`ghost-drift`** — `compare.md` (interpretation), `review.md` (PR review), `verify.md` (generation→review loop), `remediate.md` (suggest minimal fixes).
- **`ghost-fleet`** — `target.md` (synthesize fleet narrative from `view` output).

Each recipe declares `handoffs` in its frontmatter so hosts can surface the
next step inline — e.g. after `profile`, a prompt to `compare` against
another expression, or to run `ghost-expression emit review-command`. Once
installed, ask your agent in plain English ("profile this design language",
"review this PR for drift") and it'll follow the recipe, calling the right
CLI whenever it needs a reproducible answer.
Once installed, ask your agent in plain English: "profile this design language"
or "review this PR for drift". The recipe tells the agent what to read, what to
write, and which CLI checks to run.

</DocSection>

<DocSection title="Scan Your First System">

Scanning is the host-agent loop, not a single CLI verb. Open your host
agent in the project you want to profile and ask it something like:
Scanning is a recipe your agent runs, not one CLI command. Open your agent in
the project you want to profile and ask:

```text
Scan this design language end-to-end
Expand All @@ -105,12 +100,11 @@ dispatches into the per-stage recipes:
describing where the design system lives. Validated by
`ghost-expression lint map.md`.
2. **Survey (`survey.json`)** — the `survey` recipe walks the source
exhaustively (writing dialect-specific greps; the recipe forbids
sampling) and writes a `survey.json` cataloguing every concrete value,
token, component, and implemented UI surface. Validated by
exhaustively and writes a `survey.json` cataloguing concrete values,
tokens, components, and implemented UI surfaces. Validated by
`ghost-expression lint survey.json`.
3. **Expression (`expression.md`)** — the `profile` recipe interprets the
survey as ground truth: reads `survey summarize` for broad context and
survey as evidence: reads `survey summarize` for broad context and
`survey catalog` for exact value enums/specs, assigns roles to values,
emits direct references, names design decisions, writes Character and
Signature, and produces the `expression.md`. Cannot fabricate values not
Expand All @@ -122,12 +116,10 @@ If you only want one stage, ask for it directly: "map this repo", "survey
the design values", "profile this expression from the survey". The recipes
chain via `handoffs`, so the agent surfaces the next stage when ready.

An **expression** is a two-layer Markdown file: YAML frontmatter is the
machine layer (palette, spacing, typography, surfaces, direct references,
checks), and the body is prose organized into Character, Signature, and
Decisions. Runtime comparison derives embeddings from the authored file;
there is no sibling embedding artifact to edit. Humans can read it. LLMs can
consume it. Ghost's CLIs diff it.
An **expression** is one Markdown file. YAML frontmatter stores compact values
such as palette, spacing, typography, surfaces, references, and checks. The
body stores prose: Character, Signature, and Decisions. Runtime comparison
derives embeddings from the file; there is no sibling embedding file to edit.
See the expression fixture at
[`packages/ghost-expression/test/fixtures/ghost-ui-expression/expression.md`](https://github.com/block/ghost/blob/main/packages/ghost-expression/test/fixtures/ghost-ui-expression/expression.md)
for a full example.
Expand All @@ -148,9 +140,8 @@ ghost-expression verify-profile expression.md survey.json --root .

<DocSection title="Compare Two Systems">

Once you have two expressions, `ghost-drift compare` returns a scalar
distance, per-dimension deltas, and (optionally) qualitative or temporal
enrichment:
Once you have two expressions, `ghost-drift compare` returns distance and
per-dimension deltas:

```bash
# Pairwise (N=2) — distance + per-dimension delta
Expand All @@ -166,9 +157,8 @@ ghost-drift compare before.expression.md after.expression.md --temporal
ghost-drift compare *.expression.md
```

`compare` weights palette, spacing, typography, surfaces, and runtime
decision embeddings. Decisions are matched semantically above a
cosine-similarity threshold so wording doesn't have to line up.
`compare` uses palette, spacing, typography, surfaces, and runtime decision
embeddings. Decisions can match semantically even when the wording differs.

For a structural prose-level diff (what decisions and palette roles
changed, ignoring vector distance), use `ghost-expression diff` instead.
Expand Down Expand Up @@ -224,10 +214,10 @@ ghost-drift diverge typography --reason "Editorial product uses a different type

<DocSection title="The Generation Loop">

Ghost doubles as pipeline infrastructure for AI-generated UI. The
expression grounds the generator; the `review` recipe gates the output.
Ghost can sit inside an AI-generated UI pipeline. The expression gives the
generator design-language context; the `review` recipe checks the output.

1. `ghost-expression emit context-bundle` — emit a grounding bundle from an
1. `ghost-expression emit context-bundle` — emit a context bundle from an
expression (SKILL.md + expression.md + prompt.md + tokens.css) that any
generator can consume.
2. Run any generator — your host agent, Cursor, v0, or an in-house tool —
Expand All @@ -237,7 +227,7 @@ expression grounds the generator; the `review` recipe gates the output.
classifying each dimension as _tight_, _leaky_, or _uncaptured_.

```bash
# Emit a grounding bundle — default output: ./ghost-context/
# Emit a context bundle — default output: ./ghost-context/
ghost-expression emit context-bundle

# Single prompt.md for plain-text LLM context
Expand Down
20 changes: 10 additions & 10 deletions docs/expression-format.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# The `expression.md` Format

A Ghost expression is the authored design-language contract agents read for generation and drift review. It is a Markdown file with YAML frontmatter plus a prose body: compact enough to travel, grounded enough to verify against `survey.json`.
A Ghost expression is the design-language contract agents read for generation and drift review. It is one Markdown file: YAML frontmatter for compact values, plus prose for the parts that need judgment.

`survey.json` remains the durable evidence ledger. `survey catalog` and runtime embeddings are derived views, not manually edited source of truth.
`survey.json` stores the scan evidence. `survey catalog` and runtime embeddings are derived from existing files; regenerate them instead of editing them by hand.

## Shape

Frontmatter is the machine layer: identity, references, personality tags, decision slugs, promoted checks, and compact value digests.
Frontmatter stores the compact data: identity, references, personality tags, decision slugs, promoted checks, and value digests.

Body is the prose layer: `# Character`, `# Signature`, and `# Decisions` with `### <dimension>` rationale blocks and `**Evidence:**` bullets.
The body stores the prose: `# Character`, `# Signature`, and `# Decisions` with `### <dimension>` blocks and `**Evidence:**` bullets.

There are no canonical sibling fragments. Readers do not auto-load `embedding.md`, `# Fragments`, or `decisions/*.md`. Embeddings are computed at runtime from the parsed expression structure when comparison needs them.
Everything authored lives in `expression.md`. Readers do not auto-load `embedding.md`, `# Fragments`, or `decisions/*.md`. Comparisons compute embeddings at runtime from the parsed expression.

## Frontmatter

Expand Down Expand Up @@ -68,7 +68,7 @@ Required: `id`, `source`, `timestamp`, `palette`, `spacing`, `typography`, `surf

Forbidden: root `embedding`, `decisions[].embedding`, `observation.summary`, `decisions[].decision`, `decisions[].evidence`, `checks[].enforce_at`, `checks[].rationale`, and unknown root keys such as `schema`.

`checks[].paths` are filesystem scopes for verifier counts. `checks[].contexts` are reviewer/generator hints. Check rationale belongs in the matching Decision body; `summary` is only the short reviewer label.
`checks[].paths` are filesystem scopes used by `verify-profile` for counts. `checks[].contexts` are hints for reviewers and generators. Put the reason for a check in the matching Decision body; keep `summary` short.

## Body

Expand All @@ -92,13 +92,13 @@ Every gray carries a warm undertone; hue appears only when it clarifies state or
- Survey color evidence: 31 of 33 color observations fall on the documented palette
```

The body should travel. Local paths may appear as provenance, but Character, Signature, and Decisions should still make sense to a downstream project that cannot open the original repo.
Write the body so it still makes sense outside the original repo. Local paths are fine as provenance, but Character, Signature, and Decisions should not depend on opening those files.

## Derived Views

- `ghost-expression survey summarize survey.json` gives bounded profiling context.
- `ghost-expression survey catalog survey.json [--kind <kind>]` gives compact value enums/specs for exact frontmatter values.
- `ghost-drift compare` computes runtime embeddings from `expression.md`; no embedding file is authored.
- `ghost-expression survey summarize survey.json` gives a short profiling digest.
- `ghost-expression survey catalog survey.json [--kind <kind>]` lists exact values/specs from the survey.
- `ghost-drift compare` computes runtime embeddings from `expression.md`; there is no authored embedding file.

## Validation States

Expand Down
Loading
Loading