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
b51f3af
docs(ideas): plan five-tool decomposition
nahiyankhan Apr 27, 2026
e8f034a
docs(ideas): settle Phase 0 decisions (skill bundles, package layout)
nahiyankhan Apr 27, 2026
0907da2
feat(ui): canonical map.md + registry meta.expression extensions
nahiyankhan Apr 27, 2026
bbf9112
refactor(core): extract @ghost/core package from ghost-drift
nahiyankhan Apr 27, 2026
e6002e2
feat(map): bootstrap ghost-map package with inventory + lint
nahiyankhan Apr 27, 2026
990413e
Merge @ghost/core extraction (Phase 1)
nahiyankhan Apr 27, 2026
49652ad
Merge ghost-ui canonical conventions (Phase 1)
nahiyankhan Apr 27, 2026
bd2dd4a
Merge ghost-map greenfield (Phase 1)
nahiyankhan Apr 27, 2026
7f8ee9e
feat(expression): extract ghost-expression package from ghost-drift
nahiyankhan Apr 27, 2026
66b47c9
refactor(drift): trim ghost-drift to drift-only verbs; add remediate.md
nahiyankhan Apr 27, 2026
33c3407
Merge Phase 2: ghost-expression extraction + drift refactor
nahiyankhan Apr 27, 2026
b10d337
feat(fleet): bootstrap ghost-fleet package with members + view
nahiyankhan Apr 27, 2026
5aca199
fix(ui): align map.md with ghost.map/v1 schema
nahiyankhan Apr 27, 2026
5f682d5
fix(map,expression): Phase 4a — Tier 1 hard blockers + Tier 2 detecti…
nahiyankhan Apr 27, 2026
e7e2de7
Merge Phase 4a: Tier 1 + Tier 2 detection fixes
nahiyankhan Apr 27, 2026
aeb2281
feat(map,expression): Phase 4b — schema arrays + token_source + deriv…
nahiyankhan Apr 27, 2026
25ad774
Merge Phase 4b: schema arrays + token_source + derived_files
nahiyankhan Apr 27, 2026
2758723
docs(expression): Phase 4c — branch profile recipe by repo kind
nahiyankhan Apr 27, 2026
7515e69
Merge Phase 4c: profile recipe branching
nahiyankhan Apr 27, 2026
c0601b4
fix(expression,map): Phase 5a — Tier A bugs from re-validation
nahiyankhan Apr 27, 2026
89babaa
feat(map,expression): Phase 5b — schema gaps for real-world variety
nahiyankhan Apr 27, 2026
fb41ae7
docs(expression,map): polish recipe-branch + token-pipeline compositi…
nahiyankhan Apr 27, 2026
4e957d5
docs(map): token-pipeline composition.styling note
nahiyankhan Apr 27, 2026
1278460
ci: build before running unit tests
nahiyankhan Apr 27, 2026
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
8 changes: 7 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["ghost-ui", "ghost-docs"]
"ignore": [
"ghost-ui",
"ghost-docs",
"@ghost/core",
"ghost-fleet",
"ghost-map"
]
}
5 changes: 5 additions & 0 deletions .changeset/extract-ghost-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ghost-drift": patch
---

Extract embedding math, target resolution, skill-bundle loader, and shared types into the new internal `@ghost/core` workspace package. No user-facing CLI or library API changes.
5 changes: 5 additions & 0 deletions .changeset/extract-ghost-expression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ghost-drift": major
---

Move expression authoring (lint, describe, diff, emit review-command, emit context-bundle) into the new sibling `ghost-expression` package. `ghost-drift emit` now only handles `skill`; the moved verbs print a migration message pointing at `ghost-expression`. Library consumers can keep importing `loadExpression`, `lintExpression`, `diffExpressions`, `emitReviewCommand`, `writeContextBundle`, etc. from `ghost-drift` — those re-export from `ghost-expression` for one major-version cycle, then will be removed. Drift's skill bundle drops `profile.md`, `discover.md`, `generate.md`, and adds the new `remediate.md` recipe.
5 changes: 5 additions & 0 deletions .changeset/fix-profile-recipe-paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ghost-expression": patch
---

Fix the profile recipe — it now reads `design_system.paths` (the actual map.md frontmatter field) instead of the nonexistent `design_system.location`. The skill bundle ships under ghost-expression, so the broken recipe shipped to host agents.
5 changes: 5 additions & 0 deletions .changeset/initial-ghost-expression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ghost-expression": minor
---

Bootstrap `ghost-expression` — Ghost's expression.md authoring package. CLI verbs: `lint`, `describe`, `diff` (new — structural prose-level diff), and `emit <kind>` (kinds: review-command, context-bundle, skill). The skill bundle ships the map-aware `profile.md` recipe alongside the condensed schema reference. All four verbs are deterministic; profile is a recipe the host agent executes. Mirrors the BYOA contract that the rest of Ghost follows.
7 changes: 7 additions & 0 deletions .changeset/phase-4b-schema-enrichment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"ghost-expression": minor
---

`expression.md`: `surfaces.shadowComplexity` enum value `none` is renamed to `deliberate-none` so the choice reads as a positive design stance rather than as "we forgot." The `unused-palette` lint now also counts hex citations in `roles[]` (palette field bindings + inline references in `evidence` strings), so role-bound colors no longer require name-dropping in decision prose.

The `none` → `deliberate-none` change is breaking for any `expression.md` setting `shadowComplexity: none`. `ghost-expression` is pre-1.0 and not yet published, so no major bump; existing files should update their value.
5 changes: 5 additions & 0 deletions .changeset/phase-4c-recipe-branching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ghost-expression": patch
---

Branch the profile recipe by detected repo kind. The recipe now reads `design_system.token_source`, `composition.frameworks`, `registry`, and `platform` from `map.md` and chooses one of three sampling strategies — ui-library (default), token-pipeline (sample at layer level through YAML graph), or consumer-of-external-DS (record upstream slugs and override patterns instead of resolving to hex). Library-mode `feature_areas` guidance now distinguishes component categories from token-architecture layers. No schema changes.
15 changes: 15 additions & 0 deletions .changeset/phase-5-bugs-and-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"ghost-expression": minor
---

Phase 5 fixes and schema widening for real-world repo variety.

Bug fixes (5a):

- Skill-bundle `schema.md` and `profile.md`: `decisions[].evidence` belongs in the body under `**Evidence:**` bullets, not as a frontmatter array. The condensed reference the LLM loads still showed the old shape; agents following the profile recipe were hitting 10 schema errors on first lint.
- `unused-palette` now propagates slug-bindings: `roles[].tokens.palette.<slot>` referencing `{palette.dominant.X}` marks the underlying hex as cited. Phase 4b claimed this; the code only matched literal hexes.

Schema widenings (5b):

- `roles[].tokens.palette` is now an open record (`Record<string, string>`) instead of a fixed three-key object. Conventional vocabulary (`background`, `foreground`, `surface`, `border`, `accent`, `muted`, `link`) is documented in the schema reference and `expression-format.md`; richer slot names (`ring`, `popover`, `separator`, …) no longer hard-error.
- `broken-role-reference` accepts opaque external token refs (`{base.color.brand.x}`, `{semantic.text.on-brand}`, …) without trying to resolve them. Style-Dictionary-style consumer expressions can now bind role slots to upstream tokens without the linter rejecting them.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ jobs:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm test
87 changes: 87 additions & 0 deletions .github/workflows/ghost-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Ghost CI (ghost-ui canonical loop)

# DRAFT — captured for review per docs/ideas/ghost-ui.md ("CI loop — the demo").
# Gated off (`if: false`) so this never runs on PRs until reviewed and the
# verbs it relies on (`ghost map lint`, `ghost expression lint`,
# `ghost drift compare --by-component`, `ghost drift emit review-command`)
# all exist. Today's CLI is `ghost-drift lint`; the verbs in this draft
# correspond to the post-decomposition `ghost <tool>` dispatcher.
#
# Intended shape:
# - `ghost map lint` — block PR. Topology must be valid.
# - `ghost expression lint` — block PR. Expression must be valid.
# - `ghost drift compare` — advisory. Reports drift on PR comment, never fails.
# - `ghost drift emit review-command` — advisory artifact for reviewers.

on:
pull_request:
branches: [main]
paths:
- "packages/ghost-ui/**"

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
ghost:
name: Ghost (map + expression + drift)
if: false # DRAFT — do not enable until verbs exist and the loop is reviewed.
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: packages/ghost-ui
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # need main:expression.md for the drift comparison

- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: pnpm

- name: Install
working-directory: .
run: pnpm install --frozen-lockfile

- name: Build CLIs
working-directory: .
run: pnpm build

# ----- Block: map.md must lint clean -----
- name: ghost map lint
run: pnpm exec ghost map lint map.md

# ----- Block: expression.md must lint clean -----
- name: ghost expression lint
run: pnpm exec ghost expression lint expression.md

# ----- Advisory: report drift against main, never fail -----
- name: ghost drift compare (advisory)
id: drift
continue-on-error: true
run: |
git show "origin/${{ github.base_ref }}:packages/ghost-ui/expression.md" > /tmp/expression.main.md
pnpm exec ghost drift compare expression.md /tmp/expression.main.md --by-component | tee drift-report.txt

- name: ghost drift emit review-command (advisory)
if: always()
continue-on-error: true
run: pnpm exec ghost drift emit review-command

- name: Post drift report on PR
if: always() && steps.drift.outcome == 'success'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('packages/ghost-ui/drift-report.txt', 'utf8');
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## Ghost drift report\n\n```\n' + body + '\n```'
});
96 changes: 15 additions & 81 deletions apps/docs/src/generated/cli-manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"generatedAt": "2026-04-25T02:58:04.127Z",
"generatedAt": "2026-04-27T12:04:59.221Z",
"commands": [
{
"name": "compare",
Expand Down Expand Up @@ -40,36 +40,6 @@
}
]
},
{
"name": "lint",
"rawName": "lint [expression]",
"description": "Validate expression.md schema and body/frontmatter coherence",
"options": [
{
"rawName": "--format <fmt>",
"name": "format",
"description": "Output format: cli or json",
"default": "cli",
"takesValue": true,
"negated": false
}
]
},
{
"name": "describe",
"rawName": "describe [expression]",
"description": "Print a section map of expression.md (line ranges + token estimates) so agents can selectively load only the sections they need.",
"options": [
{
"rawName": "--format <fmt>",
"name": "format",
"description": "Output format: cli or json",
"default": "cli",
"takesValue": true,
"negated": false
}
]
},
{
"name": "ack",
"rawName": "ack",
Expand Down Expand Up @@ -174,65 +144,29 @@
{
"name": "emit",
"rawName": "emit <kind>",
"description": "Emit a derived artifact from expression.md (kinds: review-command, context-bundle, skill)",
"description": "Emit the ghost-drift agentskills.io bundle (kind: skill). For review-command and context-bundle, use `ghost-expression emit`.",
"options": [
{
"rawName": "-e, --expression <path>",
"name": "expression",
"description": "Source expression file (default: expression.md)",
"default": null,
"takesValue": true,
"negated": false
},
{
"rawName": "-o, --out <path>",
"name": "out",
"description": "Output path (review-command → .claude/commands/design-review.md; context-bundle → ghost-context/; skill → .claude/skills/ghost-drift/)",
"default": null,
"takesValue": true,
"negated": false
},
{
"rawName": "--stdout",
"name": "stdout",
"description": "Write to stdout instead of a file (review-command only)",
"default": null,
"takesValue": false,
"negated": false
},
{
"rawName": "--no-tokens",
"name": "tokens",
"description": "Skip tokens.css output (context-bundle)",
"default": true,
"takesValue": false,
"negated": true
},
{
"rawName": "--readme",
"name": "readme",
"description": "Include README.md (context-bundle)",
"default": null,
"takesValue": false,
"negated": false
},
{
"rawName": "--prompt-only",
"name": "promptOnly",
"description": "Emit only prompt.md — skips SKILL.md / expression.md / tokens.css (context-bundle)",
"default": null,
"takesValue": false,
"negated": false
},
{
"rawName": "--name <name>",
"name": "name",
"description": "Override the skill name (default: expression id) (context-bundle)",
"description": "Output directory (default: .claude/skills/ghost-drift)",
"default": null,
"takesValue": true,
"negated": false
}
]
},
{
"name": "lint",
"rawName": "lint [...args]",
"description": "Moved to `ghost-expression lint`. Install ghost-expression and re-run.",
"options": []
},
{
"name": "describe",
"rawName": "describe [...args]",
"description": "Moved to `ghost-expression describe`. Install ghost-expression and re-run.",
"options": []
}
],
"globalOptions": [
Expand Down
Loading
Loading