Three-stage scan pipeline + expression-as-authored-contract#68
Merged
nahiyankhan merged 27 commits intomainfrom May 5, 2026
Merged
Three-stage scan pipeline + expression-as-authored-contract#68nahiyankhan merged 27 commits intomainfrom
nahiyankhan merged 27 commits intomainfrom
Conversation
…st-map Land the bucket pipeline and consolidate to a four-tool topology. A scan now runs in three stages — topology (map.md) → objective (bucket.json) → subjective (expression.md) — all owned by ghost-expression. ghost.bucket/v1: new artifact catalogues every concrete design value with structured specs, occurrence counts, and deterministic content-hashed IDs. Schema, lint, merge, and fix-ids primitives live in @ghost/core. New ghost-expression verbs: - inventory [path] — raw repo signals JSON (migrated from ghost-map). - lint [file] — auto-detects expression.md / map.md / bucket.json. - bucket merge — deterministic concat with id-based dedup, idempotent. - bucket fix-ids — recompute row IDs from content; lets surveyor agents author rows with empty id fields and finalize in one pass. - scan-status [dir] — report per-stage state and recommended next stage. New skill recipes (ghost-expression bundle): - map.md — topology stage (migrated from ghost-map skill recipe). - survey.md — objective stage. LLM-driven extraction with dialect-specific grep strategies, exhaustiveness discipline, saturation predicate. - scan.md — meta-recipe orchestrating topology → survey → profile. Refactored: profile.md is now strictly the subjective interpretation stage (reads bucket.json as ground truth; cannot fabricate values). ghost-map package deleted. ghost.map/v1 schema/types moved to @ghost/core; inventory + lint moved to ghost-expression. ghost-fleet now imports map types from @ghost/core. CLAUDE.md, README.md, and docs IA updated to reflect the four-tool topology. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…veness Self-distance reported 17.5% on freshly authored expressions because loadExpression never backfilled `oklch` on hex-only palette colors. comparePalette then treated every color as fully unmatched and contributed distance 1.0 per color even when comparing an expression to itself. Two-layer fix: - loadExpression now backfills oklch deterministically (parseColorToOklch is pure: same hex → same oklch), so re-parsing produces identical in-memory shapes. - comparePalette resolves oklch on-the-fly when missing and falls back to hex-string equality for non-parseable values (CSS vars, opaque refs). Defensive against third-party producers that emit hex-only. Survey recipe tightened with a load-bearing exhaustiveness rule. Triggered by a dogfood scan that produced ~10% recall on components (6 rows for a 97-component package). The rule is repo-agnostic: the agent identifies the canonical signal in this repo, enumerates exhaustively, and cross-checks counts. Recipe explicitly forbids sampling and placeholder/glob library names. Coverage check (step 8) is now a real gate — exhaustiveness must match independent counts before declaring saturation. Pinned attempt-1 artifacts under dogfood/ghost-ui/attempt-1/ with a structured NOTES.md documenting the failure modes. Future attempts go alongside so we can track improvement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recall delta vs attempt 1: - values: 22 → 190 (10x) - tokens: 11 → 238 (22x, ~99% of 240 declared in main.css) - components: 6 → 97 (16x, 100% of registry:ui items) - libraries: 6 → 42 (7x, every design-surface dep enumerated) Decision count: 7 → 11. New decisions added — chart-strategy, surface-hierarchy, font-sourcing, density, interactive-patterns — and renames adjusted toward pattern-naming (token-architecture → theming-architecture, shadow-hierarchy → elevation, with the count corrected from 4 tiers to 7). Self-distance: 0.0% (was 17.5%). Confirms the oklch backfill fix. Agent followed the recipe by writing build-bucket.mjs (pinned alongside artifacts) — walks main.css for tokens, registry.json for components, package.json for libraries. Reproducible. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
External libraries (icon sets, primitive collections, motion libs, charting) no longer have a top-level bucket section. Whether a system uses Radix or hand-rolls primitives doesn't change what its design language *is*; what matters surfaces elsewhere — font families show up as typography tokens, and load-bearing library choices (icon family, font sourcing) belong in interpreter prose under the relevant decision dimension. Bucket sections are now: values, tokens, components. Removed from @ghost/core exports: LibraryRow, LibraryRowSchema, libraryRowId. Lint, merge, and fix-ids no longer touch a libraries section. Skill recipes (survey.md, profile.md) updated — survey.md no longer instructs the agent to enumerate libraries; profile.md tells the agent that load-bearing library choices land in prose, not as structured rows. zod schema stays non-strict, so historical buckets that still carry a libraries field continue to lint clean (the field is simply ignored). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pology Six documentation files were carrying stale framing from the five-tool era or hadn't been updated for the bucket pipeline / libraries-cut. - packages/ghost-expression/README.md: full rewrite. Was framed around "four verbs" (lint/describe/diff/emit) with no mention of the scan pipeline. Now leads with the three-stage table (topology → objective → subjective), enumerates all seven verbs (inventory, scan-status, lint, describe, diff, bucket, emit), and points at all four skill recipes (scan, map, survey, profile). - packages/ghost-drift/README.md: dropped "five-tool decomposition" and the ghost-map reference. The "Authoring expression.md?" sidebar now surfaces inventory + scan-status + bucket merge alongside the existing lint/describe/diff/emit verbs. - CLAUDE.md / AGENTS.md (symlinked): bucket description no longer mentions "and libraries", scan-status added to the verbs table, scan recipe added to the workflows list. - apps/docs/src/content/docs/cli-reference.mdx: added scan-status and bucket sections under ghost-expression. Updated overview to seventeen verbs and added the scan recipe to the skill-recipes table. - apps/docs/src/content/docs/getting-started.mdx: tools table grew to include scan-status, added a three-stage diagram, replaced the single-step "Profile Your First System" with a stage-aware "Scan Your First System" walkthrough. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nents Slot → token bindings either fall out of decisions[] (pattern consequences) or live in bucket.json components[] (exhaustive catalog). The hybrid roles[] slot was filling neither cleanly, didn't scale to systems with many components, and the schema never committed on whether it was exemplary or exhaustive. Removes roles[] from the zod schema (.strict() now rejects it), Expression type, lint (broken-role-reference rule, slug-binding propagation, and the references.ts token resolver), profile/scan/schema/verify/review recipes, expression.template.md, the docs site, and every fixture (arcade, market, ghost-ui, fleet members, .scratch). unused-palette is simplified to check decision evidence/prose only. Also: ignore .scratch/ for dogfood scans, and ship the ghost-ui expression-fidelity test bundles (arcade + market) as new fixtures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Free-form `decisions[].dimension` slugs fragment fleet aggregation — ghost-ui's `color-strategy` and a Cash app's `color-system` describe the same axis under different names, and N-way overlap on incidentally shared labels is not a basis for cross-system distance. Add a 12-slug controlled list in `@ghost/core` (color-strategy, surface-hierarchy, shape-language, typography-voice, spatial-system, density, motion, elevation, theming-architecture, interactive-patterns, token-architecture, font-sourcing) plus `closestCanonical()` and `resolveDecisionKind()` helpers. The frontmatter schema accepts an optional `dimension_kind` on `decisions[]` as the escape hatch for genuinely novel decisions, which fleet-aggregation primitives use to roll up by canonical bucket. New soft `non-canonical-dimension` lint warning suggests the closest match without rejecting authoring freedom. Validated against every expression.md in the repo: the ghost-ui reference is 11/11 canonical with zero warnings; across 9 expressions, 47 of 64 decisions land canonical, and the matcher resolves 4 of the remaining 17 to a clear suggestion (`theming` → `theming-architecture`, `shadow-hierarchy` → `elevation`, `semantic-density` → `density`, `product-area-color-coding` → `color-strategy`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces the perceptual prior — Ghost's opinionated stance that drift severity should track how loudly a change registers visually, not just whether it deviates from a recorded value. Three perceptual tiers fix membership for each canonical dimension: loud (color-strategy, font-sourcing → critical), structural (shape, elevation, surface, interactive, typography-voice → serious), and rhythmic (spatial-system, density, motion, theming, token → nit). Match shape is per-RuleKind: color is exact, spacing is band (±2px), type-size is percent (±10%), radius and shadow are structural. Presence/absence escalation lifts a rule one tier when bucket count for its dimension is at or below presence_floor — sparsity is a design decision, and adding to a silent dimension is the loudest possible change. Adds Rule, RuleKind, RuleMatchShape, DriftSeverity types alongside existing Decision (additive — nothing removed). Expression.rules is optional. Exports computeRuleSeverity, resolveMatchShape, resolveTolerance, escalateForPresence as the helpers a v0 emitter threads the prior through. 35 new tests cover tier coverage, severity mapping, escalation boundaries, match defaults, and tolerance defaults. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds install/install.sh + install/manifest.json so the Ghost design-
language scan + emit recipes can be installed without npm or a build
step:
curl -fsSL https://raw.githubusercontent.com/block/ghost/main/install/install.sh | sh
The installer detects the host agent (claude / cursor / codex /
opencode), validates input up-front, fetches the manifest-listed files
under packages/ghost-expression/src/skill-bundle/, and lays them down
under the agent's skills directory (e.g. ~/.claude/skills/ghost/).
Idempotent — refuses to overwrite without --force. Supports
--source <url> for testing against a local mirror or a release fork.
~200 lines of POSIX sh; no Node, no jq dependency. Smoke-tested for
auto-detect, explicit agent, force-reinstall, bad-agent rejection,
and --help.
Pairs with the prose fallbacks already added to scan.md / map.md /
profile.md — the no-CLI install path is real, not degraded.
Also includes the v0 changeset (rules[] + perceptual prior +
curl-install) describing this branch's user-facing impact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trim the unreleased Rule type before it ships. The field added churn without earning its keep — re-scan verification can be done by re-grepping the bucket against the rule's pattern, no per-rule citation list required. Also keeps the YAML lighter for hand-authors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pair packages/ghost-ui/expression.md with its bucket.json so the reference design system carries both stage-2 and stage-3 artifacts side-by-side, like a real consumer would. Earlier dogfood/* attempts remain as the rough drafts; this is the keeper, scanned at 16f0ab5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
INVARIANTS.md §3 named Character, Signature, and decision rationale as the body's prose layer. Signature is no longer load-bearing — every claim it carried is covered better by rules[] (with presence_floor for absences), decision evidence, or palette/spacing/typography/surfaces frontmatter — and the section had collapsed into restating other parts of the artifact. This is the invariant amendment per INVARIANTS.md's own preamble. The schema, parser, writer, recipe, template, and existing artifact changes ship as the next commit (major bump on ghost-expression). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Major bump on ghost-expression. The `# Signature` body section and `observation.distinctiveTraits` field are removed from the canonical expression.md schema: - DesignObservation.distinctiveTraits removed from @ghost/core - writer no longer emits `# Signature`; lint no longer expects it - parser silently ignores legacy `# Signature` blocks in older expression.md files (graceful migration for downstream consumers) - profile.md recipe: absences are now codified as rules with presence_floor instead of Signature prose - schema.md / expression-format.md / template / docs site / SKILL.md files all updated - 9 in-repo expression.md files (ghost-ui, fleet fixtures, fidelity bundles, dogfood/ghost-ui) rewritten via scripts/strip-signature.mjs - context-bundle emit uses observation.personality for the trait-phrase hooks where it previously used distinctiveTraits INVARIANTS.md §3 amended in the prior commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
End-to-end ghost-expression scan against an external target — Square's managerbot app inside the square-web Nx monorepo. Validates the recipe chain on a real shadcn-flavored design system with AI elements wired in. map.md — topology card (the libs/managerbot-ui design-system home) bucket.json — 459 tokens / 384 distinct values / 103 components expression.md — 7 rules, 9 decisions, lint clean, self-distance 0.0% bucket-gen.mjs is the survey-stage generator the recipe authored — kept inline for reproducibility (run from this directory to regenerate the bucket against the live target). Surfaced a few recipe gaps worth noting: - componentRowId hashes only (source, name) — two components named "Message" (ai-elements vs. conversation) collided at fix-ids time. Disambiguated via group-prefix in the generator; survey.md should document the convention. - lineHeightPattern enum is tight | normal | loose; managerbot's display ramp is genuinely mixed (1.0 on display, ~1.4 on body). Picked normal as the closest honest value. - lint cite-matching is literal — citing var(--neutral-900) doesn't satisfy the palette-citation gate; have to inline the resolved oklch literal in evidence prose. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Re-scan packages/ghost-ui end-to-end with the current recipes after the recent expression schema changes (drop signature section, drop distinctiveTraits, drop based_on rule provenance). Validates that ghost-ui's reference design language still profiles cleanly under the trimmed schema, alongside the managerbot run from b397451. map.md — topology card (refreshed mapped_at, language counts) bucket.json — 169 tokens / 101 distinct values / 97 components expression.md — 7 rules, 11 decisions, lint clean, self-distance 0.0% bucket-gen.mjs is the survey-stage generator the recipe authored — kept inline for reproducibility (rerun from this directory to regenerate the bucket against the live target). Component count = 97 = registry:ui count exactly (49 ui/ + 48 ai-elements/), enumerated from registry.json as the canonical signal. Cross-group name collisions disambiguated via the same group-prefix convention introduced in the managerbot run. Surfaced recipe gaps worth folding into survey.md / profile.md: - `--text-*` namespace is dual-purpose in Tailwind v4: `--text-xxs` (typography size) and `--text-default` (foreground color role) share the same prefix. Classifier must inspect the resolved literal, not just the name. survey.md's Tailwind-v4 entry should call this out. - `@theme inline` re-exports of the form `--color-X: var(--X)` are a mechanical Tailwind class-atom layer with no design information. Filtered them out as noise; survey.md should document the filter. - clamp()-bounded font sizes can't reduce to a single px; honest reading is to extract min/max as separate sizeRamp entries. profile.md's typography step should mention this. - Tailwind class-atom spacing (`p-2`, `gap-6`) consumes the Tailwind default scale, which `--spacing-*` declarations don't surface. The bucket honestly captures only declared `--spacing-*` tokens, leaving the spacing scale sparse vs. the actual rendered scale. profile.md should note the gap (or survey.md should add a class-atom pass). - Spacing-scale honesty surfaced a real semantic shift: baseUnit went from 4 to null and regularity from 0.8 to 0.5 once the scale was bucket-only. Worth re-examining whether the canonical packages/ghost-ui/expression.md should track the bucket strictly or reflect the rendered (Tailwind-default-augmented) scale. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tailwind targets render most of their design language from class atoms
(`p-2`, `bg-orange-500`, `text-sm`) that consume framework defaults —
the spacing scale is `N * --spacing` (4px-base) by default, with most
N values never declared as `--spacing-N` tokens in `@theme {}`. A
bucket built from declarations alone undercounts the rendered scale
systematically and produces an irregular `expression.spacing.scale`
even when the live UI sits on a clean modular grid.
Surfaced by the ghost-ui dogfood at edc0913: declarations-only pass
produced spacing scale [20, 32, 44, 52, 75, 100], baseUnit null,
regularity 0.5 — vs. the canonical (curated) [2, 4, 6, 8, 12, 16, 20,
24, 32, 36, 40, 52, 75, 100], baseUnit 4. Resolving the actually-used
class atoms (`rg -oN '\bp[lrtbxy]?-N\b' | resolve to N*4px`) recovers
13 of the 14 canonical values at occurrence floor 2.
Adds a `## Tailwind class-atom pass` section between extraction step 2
and step 3 spelling out:
- the v4 atom-to-literal resolver (calculated from `--spacing`,
overrideable per N via `--spacing-N` declarations)
- the v3 fallback (read `theme.*` from `tailwind.config.{ts,js}`)
- the procedure: grep atoms, resolve to literals, record as
`values[]` rows with `usage.className`, plus tokens[] rows for the
Tailwind defaults consumed
- merge-on-collision behavior when a literal comes from both a
declared token and class-atom usage
Existing `bucket-gen.mjs` generators in dogfood/* don't implement the
pass yet — they still produce declarations-only buckets. A follow-up
attempt-4 would re-validate end-to-end.
Make expression.md the generation and drift root with references, signature, and checks, and add a fresh ghost-ui dogfood scan.
Reframe references as local provenance (not the primary contract), add guidance that Character/Signature/Decisions describe the language directly instead of introducing the repo by name, and steer evidence toward portable survey-grounded patterns with file paths only as optional provenance. Updates the profile/scan/schema recipes, the SKILL/template, the writer-emitted prompt.md, and the home-page thesis. Renames the orphan-prose lint code to orphan-dimension. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures map.md, survey.json, and expression.md for the dsgn-playground target as a fresh dogfood run against the portability-tightened recipes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both scan schemas bump to /v2. `map.md` adds `surface_sources` (renderable include/exclude paths, render strategy, coverage gaps) so the survey stage knows where actual implemented UI lives. `survey.json` adds a top-level `ui_surfaces[]` section catalogueing routes, stories, screens, fixtures, docs examples, screenshots, and source-only surfaces, each with kind, locator, renderability, optional classification (intent / surface_type / density / layout_shape / confidence) and signals (dominant components, layout patterns, breakpoint behaviour, value refs, notes). Library: zod schemas, types, lint, merge, fix-ids, and id helpers updated across `@ghost/core`. Recipes: map/survey/profile and the SKILL get revised guidance for the new sections; profile uses ui_surfaces to ground Character/Signature/Decisions. CLI: `lint-map` and `scan-status` track the new surface stage. Tests + fixtures upgraded to v2; new surface-profile fixture covers the profile-from-surfaces path. Breaking: existing v1 maps and surveys no longer validate. Re-run map and survey stages to upgrade. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures map.md, survey.json, and expression.md against schema v2 with implemented-surface evidence, plus the build-survey.mjs script used to generate the survey from the iOS source tree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New survey op that distills a `ghost.survey/v2` file into a compact profile digest — Markdown by default, JSON with `--format json`, with `compact` / `standard` / `full` budgets. Output covers source provenance, top-N values per kind with count summaries, token families with theme breakdowns, component inventory highlights, UI-surface groups, and resolution status, while preserving row IDs so the agent can fall back to targeted raw lookups for exact provenance. Profile and scan recipes now make summary-first the default working context for stage 3 — agents read the bounded digest end-to-end and only open `survey.json` when a specific row needs verification. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Re-runs the ghost-ui scan using `ghost-expression survey summarize` as the profile context (compact budget) instead of the full raw survey. Compact digest is ~5% the size of survey.json and produced a zero-distance expression vs attempt-6 with no semantic diff, confirming the summary-first profile path preserves the design-language contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop fragment-era embedding and on-disk decision fragments — embeddings are recomputed at load time from the authored body, and INVARIANTS.md / its references are folded into CLAUDE.md. Add `ghost-expression verify-profile` to check palette provenance and promoted-check calibration against survey.json, plus a `survey catalog` op for derived value enum/spec views. Refresh ghost-ui by removing the stale package-root expression/map/survey artifacts and expression-fidelity bundles, replaced with attempt-8 dogfood and new profile-verifier fixtures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch reshapes Ghost from a single-package fingerprint tool into a four-tool topology around a three-stage scan pipeline, then iterates the
expression.mdcontract until it's an authored-only artifact agents can write, lint, and govern without parallel binary state.Topology
ghost-driftinto@ghost/core(workspace-only library: embedding math, target resolver, skill loader, shared schemas) plus four tools:ghost-expression(scan + authoring),ghost-drift(drift detection + governance),ghost-fleet(cross-project elevation), andghost-ui(reference design system to dogfood against).lint,describe,diff,emit review-command,emit context-bundle) move fromghost-drifttoghost-expression. Stub commands stay registered inghost-driftfor one major-version cycle.ghost-mapis folded back intoghost-expression; its inventory verb and topology recipe live there now.Three-stage scan pipeline
A scan is now
map.md(topology, stage 1) →survey.json(observed evidence, stage 2) →expression.md(authored interpretation, stage 3). All three stages and their skill recipes (map.md,survey.md,profile.md, plus thescan.mdorchestrator) ship inghost-expression. The bucket → survey rename happens partway through the branch — search forsurveyin the resulting tree.Schemas:
ghost.map/v2+ghost.survey/v2ghost.map/v2requiresimplemented_surfaces[]evidence so the profiler is grounded in real screens, not hypothetical ones. Source-graph scans let one primary subject supply usage/salience while resolver sources supply concrete values.ghost.survey/v2catalogues every concrete design value (palette, spacing, typography, radii, shadows, breakpoints, motion, layout primitives) plus tokens, components, and UI surfaces — each row content-hashed for deterministic ID.survey.libraries[]is gone (icon/primitive choices aren't part of the design language; load-bearing library calls surface as prose evidence in the profile stage). Survey recipe now requires a Tailwind class-atom pass so utility-driven repos don't undercount their scale.expression.mdschema iterations on this branchThe contract gets simpler over the course of the branch. End state: YAML frontmatter (machine layer —
references, palette/spacing/typography/surfaces,checks[]) + a three-section prose body (# Character→# Signature→# Decisions).# Signatureas the final-picture guidance section and added directreferencesfor living specs/components/examples.checks[]as the v0 authoring surface for drift review — human-promoted, grep-friendly review gates withpattern,paths,contexts,observed_count, andpresence_floorfor codifying absences.@ghost/core) that calibrates emitted check severity — color and font-family are loud, shape and elevation structural, spacing and motion-detail rhythmic. Promoted checks render as a Rams-shaped review slash command grouped by Critical / Serious / Nit.color-strategy,surface-hierarchy,shape-language,typography-voice,spatial-system,density,motion,elevation,theming-architecture,interactive-patterns,token-architecture,font-sourcing) so cross-project aggregation can group decisions. Novel slugs may pair with an optionaldimension_kindmapping to a canonical survey.roles[]— slot bindings either fall out of decisions or live insurvey.jsoncomponents[].based_onrule provenance,distinctiveTraits, and thesignaturebody section (then a different# Signaturewas reintroduced — see above; not the original distinctive-traits-laden section).embeddingand the decision-fragment surface. Embeddings are recomputed at load time from the authored body.expression.mdis now an authored-only contract — no parallel binary state, nothing to keep in sync.New CLI surface
ghost-expression verify-profile <expression> <survey>— fidelity gate after profiling. Palette values must be survey-backed; promoted checks must be calibrated against survey/root.ghost-expression survey summarize— bounded profile digest (compact / standard / full budgets) so the profiler can ground itself without loading the full survey into context.ghost-expression survey catalog— derived value enum/spec view of a survey.ghost-expression scan-status [dir]— report which stages have produced artifacts and what to run next.ghost-expression inventory [path]— emit raw repo signals for the topology recipe (migrated fromghost-map).ghost-expression lintauto-detects file kind by extension/content (expression.md,map.md,survey.json).Other
install/install.sh) so the skill bundle installs without npm or a build step; recipes carry prose fallbacks for the most-called CLI verbs.INVARIANTS.mdfolded intoCLAUDE.mdand.github/workflows/ghost-ci.ymlremoved (CI lives in lefthook + per-package).Breaking changes
ghost-drift:fingerprint→expression. Default readsexpression.md.adopt/parent renamed totrack/tracks.lint,describe,diff,emit review-command,emit context-bundle) moved toghost-expression. Library re-exports stay for one major; CLI verbs print a migration message.ghost-expression:expression.mdis an authored-only contract — frontmatterembedding,decisions[].embedding, and the on-disk decision-fragments directory are gone. Existing files must drop those fields.roles[]removed from the schema. Migrate by deleting the section.ghost.map/v2andghost.survey/v2.map.mdmust declareimplemented_surfaces[];survey.jsonno longer acceptslibraries[].# Signaturebody section anddistinctiveTraitsfield were dropped, then a different# Signaturewas reintroduced as final-picture guidance — files carrying the old distinctive-traits-laden shape need to be re-authored.surfaces.shadowComplexity: nonerenamed todeliberate-none.based_onrule provenance field removed.ghost-map:@ghost/core; verbs and recipe live inghost-expression.Test plan
pnpm buildcleanpnpm checkclean (biome + typecheck + file-size + cli-manifest)pnpm test— 407 tests across 34 files, all passing locallyexpression.md(fleet members, profile-verifier fixtures, expression-fidelity arcade/market bundles) against the current schemamap → survey → profileend-to-end on at least one dogfood target and confirmverify-profilepassesghost-drift compareself-distance is 0 on every fixture🤖 Generated with Claude Code