diff --git a/.changeset/fingerprint-metadata.md b/.changeset/fingerprint-metadata.md new file mode 100644 index 00000000..14fbbad7 --- /dev/null +++ b/.changeset/fingerprint-metadata.md @@ -0,0 +1,5 @@ +--- +"@anarchitecture/ghost": minor +--- + +Align package metadata around portable product-experience fingerprints. diff --git a/apps/docs/src/App.tsx b/apps/docs/src/App.tsx index cb3515a5..89fcac45 100644 --- a/apps/docs/src/App.tsx +++ b/apps/docs/src/App.tsx @@ -3,9 +3,10 @@ import { useEffect } from "react"; import { Navigate, Route, Routes, useLocation, useParams } from "react-router"; import DocsIndex from "@/app/docs/page"; import HomePage from "@/app/page"; -import GhostDriftLanding from "@/app/tools/drift/page"; +import GhostEmitLanding from "@/app/tools/emit/page"; import GhostFleetLanding from "@/app/tools/fleet/page"; import ToolsIndex from "@/app/tools/page"; +import GhostReviewLanding from "@/app/tools/review/page"; import GhostScanLanding from "@/app/tools/scan/page"; import GhostUiLanding from "@/app/tools/ui/page"; import ComponentPage from "@/app/ui/components/[name]/page"; @@ -51,14 +52,19 @@ export function App() { } /> - {/* Tools — four-card index plus per-tool landings */} + {/* Tools - command-specific references */} } /> } /> } /> - } /> + } /> + } /> + } + /> } /> } /> @@ -66,9 +72,7 @@ export function App() { } /> - } + element={} /> {/* MDX-authored doc pages under /docs/* */} @@ -96,15 +100,15 @@ export function App() { /> - } + element={} /> - } + element={} + /> + } /> {/* Redirects from legacy root /foundations and /components URLs */} diff --git a/apps/docs/src/app/docs/page.tsx b/apps/docs/src/app/docs/page.tsx index 2bf96ca0..81a334a3 100644 --- a/apps/docs/src/app/docs/page.tsx +++ b/apps/docs/src/app/docs/page.tsx @@ -1,7 +1,16 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { BookOpen, Rocket } from "lucide-react"; +import { + BookOpen, + Boxes, + GitCompare, + PenLine, + RadioTower, + Rocket, + ShieldCheck, + Sparkles, +} from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -16,54 +25,95 @@ const sections: { { name: "Getting Started", href: "/docs/getting-started", - description: - "Install Ghost, set up the repo fingerprint, and learn the loop around .ghost.", + description: "Install Ghost and run the first fingerprint lifecycle loop.", icon: , }, + { + name: "Fingerprint Package", + href: "/docs/fingerprint-package", + description: + "Understand the portable contract: prose, inventory, composition, checks, memory, and cache.", + icon: , + }, + { + name: "Authoring", + href: "/docs/authoring", + description: + "Create, inspect, gather source material, and validate fingerprint layers.", + icon: , + }, + { + name: "Generation", + href: "/docs/generation", + description: + "Use `ghost emit context-bundle` before an agent writes or revises UI.", + icon: , + }, + { + name: "Governance", + href: "/docs/governance", + description: + "Run checks and advisory review after generated or changed surfaces land.", + icon: , + }, + { + name: "Comparison", + href: "/docs/comparison", + description: + "Compare packages, inspect stacks, and reason across many systems.", + icon: , + }, + { + name: "Host Adapters", + href: "/docs/adapters", + description: + "Connect Ghost to agents, CI, and review surfaces without changing the package contract.", + icon: , + }, { name: "CLI Reference", href: "/docs/cli", description: - "Commands for checks and comparison, plus the skill recipes your agent runs.", + "Find exact command flags and generated help for the full lifecycle.", icon: , }, ]; export default function DocsIndex() { const ref = useStaggerReveal(".doc-card", { - stagger: 0.06, - y: 30, - duration: 0.7, + stagger: 0.05, + y: 24, + duration: 0.65, }); return (
{sections.map((item) => ( -
+
{item.icon}
- + {item.name} - + -

+

{item.description}

diff --git a/apps/docs/src/app/tools/emit/page.tsx b/apps/docs/src/app/tools/emit/page.tsx new file mode 100644 index 00000000..bad9a9f2 --- /dev/null +++ b/apps/docs/src/app/tools/emit/page.tsx @@ -0,0 +1,80 @@ +"use client"; + +import { useStaggerReveal } from "ghost-ui"; +import { BookOpen, Send, Sparkles } from "lucide-react"; +import type { ReactNode } from "react"; +import { Link } from "react-router"; +import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; +import { SectionWrapper } from "@/components/docs/wrappers"; + +const cards: { + name: string; + href: string; + description: string; + icon: ReactNode; +}[] = [ + { + name: "Generation workflow", + href: "/docs/generation", + description: + "Use the context bundle before a host agent writes or revises UI.", + icon: , + }, + { + name: "CLI reference", + href: "/docs/cli#ghost---generate", + description: + "See exact flags for `ghost emit review-command` and `ghost emit context-bundle`.", + icon: , + }, + { + name: "Host adapters", + href: "/docs/adapters", + description: "Connect emitted packets to agents, CI, and review surfaces.", + icon: , + }, +]; + +export default function GhostEmitLanding() { + const ref = useStaggerReveal(".tool-card", { + stagger: 0.06, + y: 30, + duration: 0.7, + }); + + return ( + + + +
+ {cards.map((item) => ( + +
+ {item.icon} +
+ + + {item.name} + + + +

+ {item.description} +

+ + ))} +
+
+ ); +} diff --git a/apps/docs/src/app/tools/fleet/page.tsx b/apps/docs/src/app/tools/fleet/page.tsx index d95bde99..bc1f0bbe 100644 --- a/apps/docs/src/app/tools/fleet/page.tsx +++ b/apps/docs/src/app/tools/fleet/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { BookOpen, Network, Rocket } from "lucide-react"; +import { BookOpen, GitCompare, Network } from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -14,14 +14,14 @@ const cards: { icon: ReactNode; }[] = [ { - name: "Get started", - href: "/docs/getting-started", + name: "Comparison workflow", + href: "/docs/comparison", description: "Compare many projects after each has a fingerprint.", - icon: , + icon: , }, { name: "CLI reference", - href: "/docs/cli#ghost-fleet--view-across-projects", + href: "/docs/cli#ghost---compare-and-adapt", description: "List members, compute a view, and emit fleet reports.", icon: , }, diff --git a/apps/docs/src/app/tools/page.tsx b/apps/docs/src/app/tools/page.tsx index 1725fb4a..02b4dd94 100644 --- a/apps/docs/src/app/tools/page.tsx +++ b/apps/docs/src/app/tools/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { FileText, Network, Orbit, Palette } from "lucide-react"; +import { FileText, Network, Palette, Send, ShieldCheck } from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -19,11 +19,17 @@ const tools: { blurb: "Check fingerprint readiness", icon: , }, + { + name: "ghost emit", + href: "/tools/emit", + blurb: "Create generation packets", + icon: , + }, { name: "ghost review", - href: "/tools/drift", - blurb: "Review UI drift", - icon: , + href: "/tools/review", + blurb: "Govern changed UI", + icon: , }, { name: "ghost-fleet", @@ -49,7 +55,7 @@ function ToolStrip() { return (
{tools.map((tool) => ( diff --git a/apps/docs/src/app/tools/drift/page.tsx b/apps/docs/src/app/tools/review/page.tsx similarity index 66% rename from apps/docs/src/app/tools/drift/page.tsx rename to apps/docs/src/app/tools/review/page.tsx index 93e22a78..7b78cb51 100644 --- a/apps/docs/src/app/tools/drift/page.tsx +++ b/apps/docs/src/app/tools/review/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { BookOpen, Orbit, Rocket } from "lucide-react"; +import { BookOpen, ShieldCheck, Sparkles } from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -14,29 +14,29 @@ const cards: { icon: ReactNode; }[] = [ { - name: "Ghost loop", - href: "/docs/getting-started#the-simple-model", + name: "Governance workflow", + href: "/docs/governance", description: - "See how memory, checks, review, comparison, and intent fit together.", - icon: , + "See how checks, advisory review, divergence, and fingerprint updates fit together.", + icon: , }, { - name: "Get started", - href: "/docs/getting-started", + name: "Generation workflow", + href: "/docs/generation", description: - "Install the skill bundle and review changed UI against the .ghost bundle.", - icon: , + "Start changed UI from the fingerprint before governance catches issues afterward.", + icon: , }, { name: "CLI reference", - href: "/docs/cli#ghost--review-and-compare", + href: "/docs/cli#ghost---govern", description: - "Run checks, emit exemplar-guided advisory review, compare fingerprints, and record intent.", + "Run deterministic checks, advisory review packets, and stance commands.", icon: , }, ]; -export default function GhostDriftLanding() { +export default function GhostReviewLanding() { const ref = useStaggerReveal(".tool-card", { stagger: 0.06, y: 30, @@ -47,8 +47,8 @@ export default function GhostDriftLanding() {
, }, { - name: "Format spec", - href: "https://github.com/block/ghost/blob/main/docs/fingerprint-format.md", + name: "Package format", + href: "/docs/fingerprint-package", description: "The full package format for fingerprint prose, inventory, composition, and checks.", icon: , diff --git a/apps/docs/src/components/docs/dock.tsx b/apps/docs/src/components/docs/dock.tsx index a6cae6ee..57da0981 100644 --- a/apps/docs/src/components/docs/dock.tsx +++ b/apps/docs/src/components/docs/dock.tsx @@ -16,11 +16,19 @@ import { import type { LucideIcon } from "lucide-react"; import { BookOpen, + Boxes, + FileText, + GitCompare, Home, Monitor, Moon, + PenLine, + RadioTower, Rocket, Search, + Send, + ShieldCheck, + Sparkles, Sun, Wrench, } from "lucide-react"; @@ -36,10 +44,10 @@ const nav: { }[] = [ { name: "Home", path: "/", icon: Home }, { - name: "Start", - path: "/docs/getting-started", + name: "Docs", + path: "/docs", activePath: "/docs", - icon: Rocket, + icon: BookOpen, }, { name: "Tools", path: "/tools", icon: Wrench }, ]; @@ -196,12 +204,12 @@ export function Dock() { { - navigate("/docs/getting-started"); + navigate("/docs"); setSearchOpen(false); }} > - - Start + + Docs { @@ -214,7 +222,70 @@ export function Dock() { - + + { + navigate("/docs/getting-started"); + setSearchOpen(false); + }} + > + + Getting Started + + { + navigate("/docs/fingerprint-package"); + setSearchOpen(false); + }} + > + + Fingerprint Package + + { + navigate("/docs/authoring"); + setSearchOpen(false); + }} + > + + Authoring + + { + navigate("/docs/generation"); + setSearchOpen(false); + }} + > + + Generation + + { + navigate("/docs/governance"); + setSearchOpen(false); + }} + > + + Governance + + { + navigate("/docs/comparison"); + setSearchOpen(false); + }} + > + + Comparison + + { + navigate("/docs/adapters"); + setSearchOpen(false); + }} + > + + Host Adapters + { navigate("/docs/cli"); @@ -233,16 +304,25 @@ export function Dock() { setSearchOpen(false); }} > - + ghost scan { - navigate("/tools/drift"); + navigate("/tools/emit"); setSearchOpen(false); }} > - + + ghost emit + + { + navigate("/tools/review"); + setSearchOpen(false); + }} + > + ghost review - + ghost-fleet ; export function routeFor(fm: DocsFrontmatter): string { if (fm.route) return fm.route; - const prefix = - fm.section === "guide" - ? "/docs" - : fm.section === "drift" - ? "/tools/drift" - : "/ui"; - return `${prefix}/${fm.slug}`; + return `/docs/${fm.slug}`; } diff --git a/apps/docs/src/content/docs/adapters.mdx b/apps/docs/src/content/docs/adapters.mdx new file mode 100644 index 00000000..753cf8cc --- /dev/null +++ b/apps/docs/src/content/docs/adapters.mdx @@ -0,0 +1,63 @@ +--- +title: Host Adapters +description: Integrate Ghost with agents, CI, and review surfaces without changing the portable fingerprint contract. +kicker: Docs +section: reference +order: 70 +slug: adapters +--- + + + +Ghost is bring-your-own-agent. Ghost owns the portable fingerprint package, +deterministic validation, stack resolution, and machine-readable packets. Host +tools own display, severity mapping, review comments, and repo-specific +workflow. + + + + + +Ghost provides: + +- `.ghost/fingerprint/` loading and stack merging +- core layers as generation context +- optional checks, intent, decisions, and source cache +- `ghost check --format json` for `ghost.check-report/v1` +- `ghost review --format json` for advisory governance packets +- `ghost emit context-bundle` for generation handoff +- `--memory-dir ` for custom package roots + + + + + +Host adapters provide: + +- repo-specific installation and invocation +- native review/check file formats +- severity mapping from `critical | serious | nit` +- policy for blocking, commenting, or staying advisory +- normal Git review for fingerprint edits + +Adapters should not treat generated cache as canonical inventory. Checked-in +core layer files remain the authority. + + + + + +Wrappers can use a safe relative package root when `.ghost` is not the right +location: + +```bash +ghost init --scope apps/checkout --memory-dir .design/memory +ghost stack apps/checkout/review/page.tsx --memory-dir .design/memory --format json +ghost check --base main --memory-dir .design/memory --format json +ghost review --base main --memory-dir .design/memory --format json +``` + +Use `--package ` when the caller already knows the exact package root and +wants to bypass stack discovery. + + diff --git a/apps/docs/src/content/docs/authoring.mdx b/apps/docs/src/content/docs/authoring.mdx new file mode 100644 index 00000000..aff37d78 --- /dev/null +++ b/apps/docs/src/content/docs/authoring.mdx @@ -0,0 +1,79 @@ +--- +title: Authoring +description: Create, inspect, and validate fingerprint layers before agents depend on them. +kicker: Docs +section: workflow +order: 30 +slug: authoring +--- + + + +Start with the smallest checked-in package: + +```bash +ghost init +ghost init --with-intent +ghost init --scope apps/checkout --with-intent +ghost init --scope apps/checkout --memory-dir .design/memory +``` + +Use scoped packages when a product area needs local product-experience memory. +Use `--memory-dir` only when a host adapter stores Ghost package roots outside +`.ghost`. + + + + + +`ghost scan` reports layer readiness without calling an LLM: + +```bash +ghost scan +ghost scan --format json +ghost scan --include-nested --format json +``` + +A package is ready only when prose, inventory, and composition all contain +useful content. Optional cache does not satisfy inventory readiness. + + + + + +Generated cache is useful when an agent needs observed repo facts: + +```bash +mkdir -p .ghost/fingerprint/sources/cache +ghost inventory > .ghost/fingerprint/sources/cache/inventory.json +``` + +Treat generated cache as provisional source material. Promote durable +conclusions into the core layer files through normal edits and review. + + + + + +Validate syntax, refs, evidence paths, exemplars, decisions, and config +references: + +```bash +ghost lint .ghost +ghost verify .ghost --root . +ghost lint --all +ghost verify --all +``` + +Run these before declaring a fingerprint complete. The checks keep the portable +contract coherent before generation or governance workflows depend on it. + + + + + +Ghost does not need a separate draft lifecycle. Fingerprint edits are ordinary +repo edits. Uncommitted work is draft work; checked-in package files are +canonical for Ghost. + + diff --git a/apps/docs/src/content/docs/cli-reference.mdx b/apps/docs/src/content/docs/cli-reference.mdx index 0af2ea63..b157c101 100644 --- a/apps/docs/src/content/docs/cli-reference.mdx +++ b/apps/docs/src/content/docs/cli-reference.mdx @@ -2,8 +2,8 @@ title: CLI Reference description: Commands around the portable fingerprint lifecycle. Your agent handles the judgment work. kicker: Docs -section: guide -order: 30 +section: reference +order: 90 slug: cli --- @@ -11,8 +11,8 @@ slug: cli The CLI does the repeatable parts around the fingerprint lifecycle: author packages, report readiness, validate files, emit handoff packets, govern diffs, -compare and adapt packages, and gather optional source material. Your agent -does the reading, writing, and reviewing. +compare packages, inspect stacks, adapt host workflows, and gather optional +source material. Your agent does the reading, writing, and reviewing. `ghost --help` intentionally shows the grouped lifecycle workflow for new adopters. Run `ghost --help --all` for the complete lifecycle command index; @@ -30,8 +30,10 @@ product areas: apps/checkout/.ghost/fingerprint/manifest.yml ``` -The tables below are generated from the CLI source. Run `pnpm dump:cli-help` -after command or flag changes. +Start with [Authoring](/docs/authoring), [Generation](/docs/generation), and +[Governance](/docs/governance) when you want the workflow. Use this page when +you need exact command flags. The tables below are generated from the CLI +source. Run `pnpm dump:cli-help` after command or flag changes. diff --git a/apps/docs/src/content/docs/comparison.mdx b/apps/docs/src/content/docs/comparison.mdx new file mode 100644 index 00000000..b29158a6 --- /dev/null +++ b/apps/docs/src/content/docs/comparison.mdx @@ -0,0 +1,51 @@ +--- +title: Comparison +description: Compare fingerprint packages, inspect stacks, and reason across many systems. +kicker: Docs +section: workflow +order: 60 +slug: comparison +--- + + + +Use comparison when you need to understand how two or more product-experience +contracts relate: + +```bash +ghost compare market/.ghost dashboard/.ghost +ghost compare */.ghost +``` + +Package comparison uses canonical `.ghost/fingerprint/` packages when +available. Direct fingerprint markdown files still work for legacy semantic +comparison: + +```bash +ghost compare a.fingerprint.md b.fingerprint.md --semantic +``` + + + + + +For scoped packages, inspect the resolved stack for a path: + +```bash +ghost stack apps/checkout/review/page.tsx --format json +``` + +Stack output shows which broad and local fingerprint layers apply before +generation, checks, review, or comparison. + + + + + +`ghost-fleet` is the view across many fingerprint packages. It helps teams see +clusters, reference relationships, and differences across a group of projects. + +Use the fleet tool when the question is about the shape of many systems, not +whether one changed surface still follows its local contract. + + diff --git a/apps/docs/src/content/docs/fingerprint-package.mdx b/apps/docs/src/content/docs/fingerprint-package.mdx new file mode 100644 index 00000000..c5e0bb3b --- /dev/null +++ b/apps/docs/src/content/docs/fingerprint-package.mdx @@ -0,0 +1,104 @@ +--- +title: Fingerprint Package +description: The portable product-experience contract that Ghost tools and host agents read. +kicker: Docs +section: fingerprint +order: 20 +slug: fingerprint-package +--- + + + +A Ghost fingerprint is the checked-in product-experience contract for a repo. +It is portable because the package lives under `.ghost/fingerprint/`, separate +from local adapter config. + +```text +.ghost/ + config.yml + fingerprint/ + manifest.yml + prose.yml + inventory.yml + composition.yml + enforcement/checks.yml + memory/intent.md + memory/decisions/ + sources/cache/ +``` + +Git is the approval boundary. Uncommitted or unmerged edits are drafts; +checked-in fingerprint files are the source of truth for Ghost. + + + + + +Generation starts from three core files: + +- `prose.yml` explains what matters and why. +- `inventory.yml` points to curated material, building blocks, source links, + and exemplars an agent can inspect. +- `composition.yml` explains how those materials become product experience. + +The package manifest anchors the on-disk shape: + +```yaml +schema: ghost.fingerprint-package/v1 +id: local +``` + +Raw layer files may be sparse. Ghost normalizes missing files or sections into +the assembled shape used by checks, review packets, context bundles, compare, +and stack resolution. + + + + + +Support files extend the contract without changing the core generation model: + +- `enforcement/checks.yml` stores deterministic gates grounded in fingerprint + refs. +- `memory/intent.md` stores optional human-authored or human-approved intent. +- `memory/decisions/` stores accepted or rejected rationale. +- `sources/cache/` stores refreshable generated observations. + +Generated cache can help author `inventory.yml`, but cache never counts as +fingerprint readiness by itself. + + + + + +Use layer-qualified refs so checks and review can cite product memory: + +```text +prose.situation: +prose.principle: +prose.experience_contract: +inventory.exemplar: +composition.pattern: +check: +``` + +Ref-backed checks are preferred. Inventory refs can support checks, but +inventory-only grounding does not establish product judgment on its own. + + + + + +Large repos can add scoped packages: + +```text +.ghost/fingerprint/... +apps/checkout/.ghost/fingerprint/... +apps/checkout/review/page.tsx +``` + +For a changed path, Ghost resolves matching packages root-to-leaf. Child +entries with the same id replace parent entries, arrays merge with de-dupe, and +child-relative paths normalize to repo-root paths in reports. + + diff --git a/apps/docs/src/content/docs/generation.mdx b/apps/docs/src/content/docs/generation.mdx new file mode 100644 index 00000000..0375ebd0 --- /dev/null +++ b/apps/docs/src/content/docs/generation.mdx @@ -0,0 +1,84 @@ +--- +title: Generation +description: Use the fingerprint as upstream context before an agent writes or revises UI. +kicker: Docs +section: workflow +order: 40 +slug: generation +--- + + + +Ghost is most useful before the diff exists. The fingerprint gives the host +agent the product-experience contract it should extend: + +```text +prose.yml + inventory.yml + composition.yml + | + v +host agent or generator + | + v +HTML / JSX / app code +``` + +Checks and review validate output afterward. They do not replace the upstream +fingerprint inputs. + + + + + +Emit the generation packet before work begins: + +```bash +ghost emit context-bundle +``` + +The packet organizes: + +- prose: product judgment and experience contracts +- inventory: building blocks, exemplars, and optional source cache +- composition: patterns for assembling product experience +- active checks: validation expectations, not generation input + +Give the packet to Codex, Cursor, Claude, Goose, or another host agent so the +work starts from the same portable contract. + + + + + +A good pre-generation brief asks the agent to: + +1. Read the relevant fingerprint layers. +2. Select the matching situations, principles, contracts, and patterns. +3. Inspect inventory exemplars as concrete anchors. +4. Use building blocks and local implementation conventions. +5. Keep active checks in view so avoidable failures do not land. + +If a layer is silent, the agent may use nearby product surfaces and ordinary UX +judgment, but it should label that reasoning as provisional and not +Ghost-backed. + + + + + +Inventory is strongest when it points to material an agent can inspect or use: +component paths, token files, route examples, copy in context, motion specs, +and shipped flows. Screenshots and PDFs can still help, but buildable evidence +usually gives agents better leverage. + + + + + +Once the surface exists, move to [Governance](/docs/governance): + +```bash +ghost check --base main +ghost review --base main --include-memory +``` + + diff --git a/apps/docs/src/content/docs/getting-started.mdx b/apps/docs/src/content/docs/getting-started.mdx index 6276e5c1..b3205d4c 100644 --- a/apps/docs/src/content/docs/getting-started.mdx +++ b/apps/docs/src/content/docs/getting-started.mdx @@ -1,162 +1,118 @@ --- title: Getting Started -description: Install Ghost, author a portable product-experience fingerprint, and use it to generate, validate, compare, and govern product surfaces. +description: Install Ghost, create a repo-local fingerprint package, and run the first lifecycle loop. kicker: Docs -section: guide +section: start order: 10 slug: getting-started --- - + -Ghost keeps a project's portable product-experience fingerprint in the repo, -where your agent can use it. The public package is `@anarchitecture/ghost`, -and it installs one CLI: `ghost`. - -The canonical portable fingerprint is a folder: +Ghost keeps a portable product-experience fingerprint in the repo. Agents use +that fingerprint before generation, and Ghost tooling validates or governs the +result afterward. ```text -.ghost/ - config.yml - fingerprint/ - manifest.yml - prose.yml - inventory.yml - composition.yml - enforcement/checks.yml - memory/intent.md - memory/decisions/ - sources/cache/ +.ghost/fingerprint/ + manifest.yml + prose.yml + inventory.yml + composition.yml + enforcement/checks.yml + memory/intent.md + memory/decisions/ + sources/cache/ ``` -Generation starts from prose, inventory, and composition. Checks validate the -result afterward; they are not generation input. `.ghost/config.yml` stays -outside the portable package because it is local routing config. +The smallest useful loop is: + +1. Author the fingerprint. +2. Generate or revise from the fingerprint. +3. Validate and govern the changed surface. +4. Update code, explain divergence, or evolve the fingerprint through Git. -Nested product areas can add child package roots such as -`apps/checkout/.ghost/fingerprint/`. Ghost resolves fingerprint stacks -root-to-leaf for the file or diff being reviewed. +Read [Fingerprint Package](/docs/fingerprint-package) when you need the file +model, then move through [Authoring](/docs/authoring), +[Generation](/docs/generation), and [Governance](/docs/governance). - + ```bash npm install -D @anarchitecture/ghost npx ghost --help -npx ghost --help --all npx ghost skill install ``` -`ghost --help` shows the grouped lifecycle workflow for new adopters. Use -`ghost --help --all` when you want the complete lifecycle command index. - -Once the skill is installed, ask your agent in plain English: "Set up the Ghost -fingerprint for this repo" or "review this PR against the Ghost fingerprint". -The recipe tells the agent what to read, what to write, and which CLI checks to -run. - - +The public package is `@anarchitecture/ghost`; it installs one CLI, `ghost`. +The skill bundle teaches the host agent how to capture, apply, validate, +govern, and compare fingerprints. - +Once installed, ask your agent: ```text Set up the Ghost fingerprint for this repo. +Brief this work from the Ghost fingerprint. +Review this PR against the Ghost fingerprint. ``` -The fingerprint records durable product-experience guidance: + + + -1. **Prose** - what product this is, who it serves, which situations matter, - and which principles or contracts govern the experience. -2. **Inventory** - topology, building blocks, files, routes, assets, libraries, - exemplars, and source links agents may inspect or use. -3. **Composition** - patterns, rules, layouts, structures, flows, states, - content, behavior, and visual arrangements. +Create the package, inspect readiness, and validate the result: ```bash ghost init --with-intent -ghost init --scope apps/checkout --with-intent -ghost init --scope apps/checkout --memory-dir .design/memory ghost scan --format json -ghost scan --include-nested --format json -mkdir -p .ghost/fingerprint/sources/cache -ghost inventory > .ghost/fingerprint/sources/cache/inventory.json ghost lint .ghost ghost verify .ghost --root . -ghost lint --all -ghost verify --all ``` -Generated cache is optional source material. Curate durable prose, inventory, -and composition into the core layer files, then use normal Git review for -approval. - -For generation, emit the upstream handoff packet: +Generated cache can help orient the first pass, but it is source material, +not canonical product memory: ```bash -ghost emit context-bundle +mkdir -p .ghost/fingerprint/sources/cache +ghost inventory > .ghost/fingerprint/sources/cache/inventory.json ``` - +Curate durable conclusions into `prose.yml`, `inventory.yml`, and +`composition.yml`. - + -```bash -ghost compare market/.ghost dashboard/.ghost -ghost compare */.ghost -``` + -Package comparison uses canonical `.ghost/fingerprint/` packages when -available. Direct fingerprint markdown files still work for legacy semantic -comparison: +Before the agent writes UI, emit a context bundle: ```bash -ghost compare a.fingerprint.md b.fingerprint.md --semantic -``` - - - - - -```text -Review this PR against the Ghost fingerprint +ghost emit context-bundle ``` -`ghost check` applies active deterministic gates from the resolved fingerprint -stack for each changed file. `ghost review` emits advisory context grounded in -merged split fingerprint layers, optional memory, checks, and the diff. +The packet is organized around the core fingerprint layers and active checks. +It gives the host agent a compact handoff before code changes begin. -Wrappers should consume `ghost check --format json` and map Ghost severities -outside Ghost. Ghost severities remain `critical`, `serious`, and `nit`. +See [Generation](/docs/generation) for the full pre-generation workflow. - + -Use the installed `ghost` skill when work reveals durable product-experience -judgment Ghost should add to the fingerprint: +After code changes, run deterministic checks and advisory review: -```text -Brief this work from the Ghost fingerprint -Update the fingerprint with this product-experience decision +```bash +ghost check --base main +ghost review --base main --include-memory ``` -Fingerprint edits are ordinary edits to the split fingerprint package and -optional rationale files. Uncommitted or unmerged edits are drafts; checked-in -`fingerprint/` core files are canonical. - - - - - -Drift is a governance signal over a fingerprint, not Ghost's center. `ack`, -`track`, and `diverge` still operate on tracked direct fingerprint markdown -files for compatibility with older workflows: +Checks can block when they are active deterministic gates. Review is advisory: +it helps decide whether to fix code, record intentional divergence, or update +the fingerprint. -```bash -ghost ack --stance aligned --reason "Initial baseline" -ghost track new-tracked.fingerprint.md -ghost diverge typography --reason "Editorial product uses a different type scale" -``` +See [Governance](/docs/governance) for the full post-generation workflow and +[CLI Reference](/docs/cli) for exact flags. diff --git a/apps/docs/src/content/docs/governance.mdx b/apps/docs/src/content/docs/governance.mdx new file mode 100644 index 00000000..f0c430b0 --- /dev/null +++ b/apps/docs/src/content/docs/governance.mdx @@ -0,0 +1,86 @@ +--- +title: Governance +description: Validate generated or changed surfaces against the checked-in fingerprint. +kicker: Docs +section: workflow +order: 50 +slug: governance +--- + + + +Governance starts after a surface changes. Ghost compares the diff against the +resolved fingerprint stack for the files being touched. + +```text +changed UI + | + v +ghost check + ghost review + | + v +deterministic gates + advisory findings +``` + +Drift is a governance signal inside this loop. It is not the center of Ghost. + + + + + +`ghost check` runs active deterministic gates: + +```bash +ghost check --base main +ghost check --base main --format json +``` + +Without `--package`, Ghost groups changed files by resolved fingerprint stack +and runs merged checks for each group. Only active checks can block. + + + + + +`ghost review` emits an advisory governance packet: + +```bash +ghost review --base main --include-memory +ghost review --base main --format markdown +``` + +Review packets include the diff, split fingerprint layers, relevant inventory +exemplars, active checks, optional accepted decisions, and finding categories +for fixes, intentional divergence, missing memory, experience gaps, and eval +uncertainty. + + + + + +When review finds a mismatch, choose the smallest useful response: + +- fix the changed code +- explain why the divergence is intentional +- update the fingerprint when the product contract has changed +- add missing rationale or intent when the fingerprint was under-specified + +Advisory review should not fail CI unless the finding is backed by an active +deterministic check. + + + + + +Compatibility verbs record stance toward tracked direct fingerprint workflows: + +```bash +ghost ack --stance aligned --reason "Initial baseline" +ghost track new-tracked.fingerprint.md +ghost diverge typography --reason "Editorial product uses a different type scale" +``` + +Use them when a workflow needs explicit acknowledgement, tracking, or declared +divergence. + + diff --git a/package.json b/package.json index f82500f6..0245ec0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ghost", "private": true, - "description": "Product-experience world model tooling for AI agents", + "description": "Portable product-experience fingerprint tooling for AI agents", "license": "Apache-2.0", "packageManager": "pnpm@10.33.0", "engines": { diff --git a/packages/ghost/package.json b/packages/ghost/package.json index 070272e0..0f4af339 100644 --- a/packages/ghost/package.json +++ b/packages/ghost/package.json @@ -1,7 +1,7 @@ { "name": "@anarchitecture/ghost", "version": "0.4.0", - "description": "Unified Ghost CLI for repo-local product fingerprints, deterministic checks, advisory review, and drift tracking", + "description": "Unified Ghost CLI for portable product-experience fingerprints, generation packets, validation, governance, and comparison", "license": "Apache-2.0", "author": "Block, Inc.", "repository": { @@ -13,12 +13,13 @@ "url": "https://github.com/block/ghost/issues" }, "keywords": [ - "design-system", - "drift-detection", "fingerprint", - "design-tokens", - "shadcn", + "product-experience", + "ai-agents", + "design-system", "design-language", + "design-tokens", + "drift-detection", "cli" ], "type": "module", diff --git a/scripts/check-docs-frontmatter.mjs b/scripts/check-docs-frontmatter.mjs index 3d143c3f..be805a58 100644 --- a/scripts/check-docs-frontmatter.mjs +++ b/scripts/check-docs-frontmatter.mjs @@ -11,7 +11,7 @@ const Schema = z.object({ title: z.string().min(1), description: z.string().min(1), kicker: z.string().optional(), - section: z.enum(["guide", "drift", "ui"]).optional(), + section: z.enum(["start", "fingerprint", "workflow", "reference"]).optional(), order: z.number(), slug: z.string().min(1), route: z.string().optional(), @@ -32,14 +32,7 @@ function walk(dir) { function routeFor(fm) { if (fm.route) return fm.route; - const section = fm.section ?? "guide"; - const prefix = - section === "guide" - ? "/docs" - : section === "drift" - ? "/tools/drift" - : "/ui"; - return `${prefix}/${fm.slug}`; + return `/docs/${fm.slug}`; } const files = walk(DOCS_DIR); @@ -77,6 +70,8 @@ for (const { file, fm: _fm } of parsed) { "/tools", "/tools/map", "/tools/scan", + "/tools/emit", + "/tools/review", "/tools/drift", "/tools/drift/workflow", "/tools/fleet",