Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
08ed7f0
Add expression.md format as canonical fingerprint artifact
nahiyankhan Apr 18, 2026
03ff3cc
Add generation loop: context, generate, verify commands
nahiyankhan Apr 18, 2026
ee3bf3b
Sync docs and CLI reference with current architecture
nahiyankhan Apr 18, 2026
07480d9
Rewrite expression.md as frontmatter-authoritative (schema 2)
nahiyankhan Apr 19, 2026
1524f8d
Bump expression format to schema 4: fragment the embedding, add metad…
nahiyankhan Apr 19, 2026
1232b6e
Add semantic roles: slot → token bindings
nahiyankhan Apr 19, 2026
079dc1e
Add emit-review: generate drift-review command from expression
nahiyankhan Apr 19, 2026
c7bfe0a
Consolidate CLI surface: 18 verbs → 11
nahiyankhan Apr 19, 2026
7043632
Refresh ghost-ui drift docs for consolidated CLI surface
nahiyankhan Apr 19, 2026
2b3bca2
Extract + unit-test consolidated verb dispatch
nahiyankhan Apr 19, 2026
a8b65dd
Add library build for @ghost/ui
nahiyankhan Apr 19, 2026
d8c1c02
Split apps/catalogue out of packages/ghost-ui
nahiyankhan Apr 19, 2026
33b41cb
Split drift docs into apps/docs (VitePress)
nahiyankhan Apr 19, 2026
65a6058
Fix DocsRedirect base for Pages sub-path
nahiyankhan Apr 19, 2026
0bd34c2
Revert apps/docs split — catalogue is the one site
nahiyankhan Apr 19, 2026
1da0f30
Rename apps/catalogue → apps/docs
nahiyankhan Apr 19, 2026
2e2b506
Scrub "fingerprint" naming; delete legacy JSON reader
nahiyankhan Apr 19, 2026
00ee046
Untrack local Claude Code harness files
nahiyankhan Apr 19, 2026
28cf94c
Finish fingerprint→expression rename; schema 5; split drift/verify
nahiyankhan Apr 19, 2026
d938314
Trim surface: drop Values/Director/--ai, unify compare()
nahiyankhan Apr 20, 2026
4245274
Cut surface: one agent, flat modules, six verbs
nahiyankhan Apr 20, 2026
9c35ca7
Alias @ghost/core to source in vitest
nahiyankhan Apr 20, 2026
de3e1cc
BYOA refactor: fingerprint.md + deterministic primitives
nahiyankhan Apr 20, 2026
6ccca5a
regenerated pnpm lock
nahiyankhan Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 20 additions & 8 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
name: Deploy Ghost UI to GitHub Pages
name: Deploy to GitHub Pages

# Builds apps/docs with DEPLOY_BASE=/ghost/ and uploads the dist as the
# Pages artifact. apps/docs is the one deployed site — it owns the home,
# the design language catalogue (/ui/*), and the drift tooling docs
# (/tools/drift/*) under a single aesthetic.

on:
push:
Expand Down Expand Up @@ -26,17 +31,24 @@ jobs:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build registry

- name: Build @ghost/ui library
run: pnpm --filter @ghost/ui build:lib

- name: Build shadcn registry
run: pnpm --filter @ghost/ui build:registry
- name: Build Ghost UI
run: pnpm --filter @ghost/ui build

- name: Build docs site (base=/ghost/)
env:
VITE_BASE_PATH: /ghost/
- name: Copy index.html to 404.html for SPA routing
run: cp packages/ghost-ui/dist/index.html packages/ghost-ui/dist/404.html
DEPLOY_BASE: /ghost/
run: pnpm --filter @ghost/docs build

- name: SPA fallback
run: cp apps/docs/dist/index.html apps/docs/dist/404.html

- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
with:
path: packages/ghost-ui/dist
path: apps/docs/dist

deploy:
needs: build
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
node_modules
dist
dist-lib
*.tsbuildinfo
.DS_Store
.claude/settings.local.json
packages/ghost-ui/public/r/
.env
.env.local
packages/ghost-ui/.ghost/

# Claude Code local harness state
.claude/scheduled_tasks.lock
.claude/worktrees/

# Emitted skill bundle — re-generate with `ghost emit skill`
.claude/skills/
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
registry=https://registry.npmjs.org/
shamefully-hoist=false
strict-peer-dependencies=true
@anthropic-ai:registry=https://registry.npmjs.org
87 changes: 43 additions & 44 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ pnpm --filter ghost-cli exec ghost <command>

## Environment Variables

- `ANTHROPIC_API_KEY` — required for AI-powered profiling (`--ai` flag) and LLM agents
- `OPENAI_API_KEY` — alternative LLM provider
- `GITHUB_TOKEN` — optional, for GitHub target resolution and discovery (avoids rate limits)
Ghost's CLI is deterministic — no API key required for any verb.

- `OPENAI_API_KEY` / `VOYAGE_API_KEY` — optional, consumed only by `computeSemanticEmbedding` (library function; used when a host writes a fingerprint.md and wants an enriched 49-dim vector for paraphrase-robust comparison).
- `GITHUB_TOKEN` — optional, for `resolveParent` fetching a parent fingerprint from GitHub (avoids rate limits).

The CLI auto-loads `.env` and `.env.local` from the working directory.

Expand All @@ -38,43 +39,52 @@ Pre-push hook: `just check`, `just test`, `just build` (parallel).

## Justfile

Run `just` to list all recipes. Key ones: `setup`, `build`, `check`, `fmt`, `test`, `dev` (ghost-ui catalogue), `build-ui`, `build-registry`, `clean`, `ci`.
Run `just` to list all recipes. Key ones: `setup`, `build`, `check`, `fmt`, `test`, `dev` (docs site at apps/docs), `build-ui` (docs build), `build-lib` (@ghost/ui library), `build-registry`, `build-pages`, `clean`, `ci`.

## Architecture

**Director** (`packages/ghost-core/src/agents/director.ts`) orchestrates the pipeline:
Ghost is **BYOA (bring-your-own-agent)**. The CLI is a set of **deterministic primitives**. It never calls an LLM. Judgement work (profile, review, verify, generate, discover) belongs to the host agent harness (Claude Code, Codex, Cursor, Goose, etc.), which drives the primitives via an [agentskills.io](https://agentskills.io)-compatible skill bundle. Ghost ships that bundle via `ghost emit skill`.

Core library layout:

- **Stages** (`packages/ghost-core/src/stages/`) — deterministic async functions: `extract`, `compare`, `comply`
- **Agents** (`packages/ghost-core/src/agents/`) — LLM-powered steps: `FingerprintAgent`, `DiscoveryAgent`, `ComparisonAgent`, `ComplianceAgent`, `ExtractionAgent`
- `packages/ghost-core/src/compare.ts` — embedding-based comparison (pairwise + fleet)
- `packages/ghost-core/src/embedding/` — 49-dim vector computation, optional semantic embedding via OpenAI/Voyage
- `packages/ghost-core/src/fingerprint/` — parse/compose/diff/lint `fingerprint.md`
- `packages/ghost-core/src/evolution/` — history, ack manifest, fleet analysis, parent resolution
- `packages/ghost-core/src/context/` — artifact generators (review-command, context-bundle, tokens.css)
- `packages/ghost-core/src/reporters/` — output formatters for compare/fleet/temporal/fingerprint

Typical pipeline: `target → extract (stage) → fingerprint (agent) → compare/comply (stage)`
What was removed in the BYOA migration: the Claude Agent SDK profiling loop (`src/agents/`), the LLM-driven review pipeline (`src/review/`), the LLM generate/verify loops (`src/generate/`, `src/verify/`), the Anthropic/OpenAI provider plumbing (`src/llm/`), and the GitHub Action that wrapped them. Profile, review, verify, generate, and discover are now skill recipes the host agent executes.

## Packages

| Package | Description |
|---------|-------------|
| `packages/ghost-core` | Core library: agents, stages, fingerprinting, scanners, extractors, evolution, LLM providers, reporters |
| `packages/ghost-cli` | CLI (citty-based), 12 subcommands |
| `packages/ghost-ui` | Reference design language97 shadcn-compatible components, design tokens, live catalogue |
| `packages/ghost-mcp` | MCP server exposing Ghost UI registry to AI assistants (6 tools, 2 resources) |
| `action/` | GitHub Action for automated PR design review |
| `packages/ghost-core` | Core library: deterministic primitives — compare, embedding, fingerprint parse/lint, evolution, reporters |
| `packages/ghost-cli` | CLI (cac-based) + the shipped `ghost-drift` agentskills.io skill bundle under `src/skill-bundle/` |
| `packages/ghost-ui` | Reference component library49 UI primitives + 48 AI elements + theme + hooks, shipped via `dist-lib/` + shadcn `registry.json` |
| `packages/ghost-mcp` | MCP server exposing the Ghost UI component registry to AI assistants (5 tools, 2 resources) — registry lookups only |
| `apps/docs` | The deployed docs site (`@ghost/docs`) — home, drift tooling docs, design language foundations, live component catalogue. Consumes `@ghost/ui`. |

## CLI Commands

Six deterministic primitives. Everything else (profile, review, verify, generate, discover) is a skill recipe the host agent executes.

| Command | Description |
|---------|-------------|
| `ghost review [files]` | Review files for visual language drift against a fingerprint (zero-config) |
| `ghost scan` | Scan for design drift (requires `ghost.config.ts`) |
| `ghost profile [target]` | Generate a fingerprint — accepts paths, `github:owner/repo`, `npm:package`, URLs |
| `ghost compare <a.json> <b.json>` | Compare two fingerprint JSON files |
| `ghost diff [component]` | Compare local components against registry |
| `ghost comply [target]` | Check compliance; `--against parent.json` for drift checking |
| `ghost discover [query]` | Find public design systems |
| `ghost fleet <a.json> <b.json> ...` | Ecosystem-level comparison (2+ fingerprint files) |
| `ghost ack` | Acknowledge drift, record stance (aligned/accepted/diverging) |
| `ghost adopt <fingerprint.json>` | Adopt a new parent baseline |
| `ghost diverge <dimension>` | Declare intentional divergence with reasoning |
| `ghost viz <a.json> <b.json> ...` | 3D fingerprint visualization (Three.js) |
| `ghost compare [...fingerprints]` | Pairwise (N=2) or fleet (N≥3) comparison over fingerprint embeddings. `--semantic`, `--temporal`. |
| `ghost lint [fingerprint.md]` | Validate schema + body/frontmatter coherence |
| `ghost ack` | Acknowledge drift; records stance in `.ghost-sync.json` (reads local `fingerprint.md`) |
| `ghost adopt <fingerprint.md>` | Adopt a new parent baseline |
| `ghost diverge <dimension>` | Declare intentional divergence on a dimension |
| `ghost emit <kind>` | Derive artifacts from `fingerprint.md` — `review-command`, `context-bundle`, or `skill` (the agentskills.io bundle). Run `ghost emit skill` to install the `ghost-drift` skill into your host agent. |

**Workflows the CLI does not do** — these are recipes the host agent follows:
- **Profile** (write `fingerprint.md` from a project) — `src/skill-bundle/references/profile.md`
- **Review** (flag drift in PR changes) — `src/skill-bundle/references/review.md`
- **Verify** (generate → review loop) — `src/skill-bundle/references/verify.md`
- **Generate** (produce UI from fingerprint) — `src/skill-bundle/references/generate.md`
- **Discover** (find public design systems) — `src/skill-bundle/references/discover.md`

## Target Types

Expand All @@ -85,28 +95,17 @@ The `resolveTarget()` function in `packages/ghost-core/src/config.ts` accepts:
- `figma:file-url` — Figma file
- `./path` or `/absolute/path` — local directory
- `https://...` — URL
- `.` — current directory (default for `profile` and `comply`)

Use explicit prefixes when the input is ambiguous.

## Review Pipeline
- `.` — current directory

The `review` module (`packages/ghost-core/src/review/`) provides fingerprint-informed design review:
Used by `resolveParent` (parent fingerprint resolution) and legacy library consumers. The profile flow itself no longer consumes targets — the host agent explores whatever directory is relevant.

- **matcher.ts** — deterministic scan: match hardcoded values against fingerprint palette/spacing/typography/surfaces
- **deep-review.ts** — LLM-powered nuanced drift detection (optional, `--deep` flag)
- **file-collector.ts** — git diff parsing to resolve changed files and line numbers
- **pipeline.ts** — orchestrates: resolve fingerprint → collect files → match → (optional) deep review → report
## Fingerprint format

Zero-config: `ghost review` looks for `.ghost-fingerprint.json` in cwd. Generate with `ghost profile . --emit`.
The canonical fingerprint artifact is **`fingerprint.md`** — a human-readable, LLM-editable Markdown file with YAML frontmatter (machine layer) and a three-layer prose body (Character → Signature → Decisions → Values). See `docs/fingerprint-format.md` for the full spec; a condensed reference ships inside the skill bundle at `packages/ghost-cli/src/skill-bundle/references/schema.md`.

## Key Conventions

- Fingerprints are 64-dimensional vectors stored as JSON (`DesignFingerprint` type)
- `compare`, `fleet`, and `viz` commands take **file paths** to fingerprint JSON, not target strings
- `profile` outputs fingerprints; pipe to `--output <file>` to save for later comparison
- `--against` on `comply` takes a **file path** to a parent fingerprint JSON
- `--ai` enables LLM-powered enrichment on `profile`; `--verbose` shows agent reasoning
- `review` reads `.ghost-fingerprint.json` by default; `--fingerprint <path>` overrides
- `review --deep` requires `ANTHROPIC_API_KEY` for LLM-powered nuanced analysis
- `review --staged` checks only staged changes; `--base main` diffs against a branch
- Each fingerprint carries a 49-dimensional embedding vector (palette [0–20], spacing [21–30], typography [31–40], surfaces [41–48]; see `packages/ghost-core/src/embedding/embedding.ts`). The canonical on-disk form is `fingerprint.md`.
- `compare` takes **file paths** to `fingerprint.md`, not target strings. Mode auto-detects from N and flags: `--semantic` / `--temporal` require N=2; N≥3 runs fleet.
- `ack` / `adopt` / `diverge` read the local `fingerprint.md`. The host agent is responsible for regenerating `fingerprint.md` (via the profile recipe) before acknowledging drift.
- `lint` takes a single fingerprint.md and reports schema/partition violations. Use as the success gate when writing a fingerprint.
Loading
Loading