Reincarnation: flat-corpus fingerprint, core checks, @design-intelligence#205
Merged
Conversation
Stop circling. Three notes (purposes, ghost-layers, contract-and-binding) shared one diagnosis: the descriptive core is clean; selection/routing/merge leaked into the artifact's shape. reset.md fixes purpose, goals, layers, and separation of concerns, and schedules a single first cut. coordinate-space.md is the clean-room Layer 2 design: a surface is an author-named group with an optional description; topology is a strict containment tree plus cascade-from-ancestors plus rare explicit shared-edges; resolution is BYOA (Ghost emits a described menu, the agent matches); delete list covers inventory.topology, smeared applies_to, and ghost.map/v1. Focus pass: delete pre-redesign docs (fingerprint-format, generation-loop, host-adapters, ghost-fleet, language-fingerprints, relay-configs-and-context, prompt-first-relay-prd) that described the dead Relay-routing and topology/applies_to model. Port the one durable thesis (language maps onto the four facets) inline into the voice skill reference and fix its stale coordinate guidance. Update README and ideas/README to the reset arc.
A real non-UI composition case showed the topology conflated two axes. Containment (where a node lives, who owns it) is a Layer 2 strict tree with cascade-from-ancestors. Composition (what combines to serve a request) is a Layer 3 typed reference graph laid over the tree. The explicit edges are not a rare exception; in composition-heavy, pathless cases they are the primary structure. The original 'tree + rare edges' framing over-fit the in-repo UI case and under-served the no-repo composition case. Amends the topology section, the layer-asks, decision 3, the surface shape, read-back, and the ideas README.
First concrete cut from coordinate-space.md. Proposes a new surfaces.yml facet (ghost.surfaces/v1) anchored by the existing manifest, expressing both axes: parent (the containment tree) and typed edges over edge_kinds (the composition graph). Specifies a field-by-field migration off inventory.topology, smeared applies_to, and exemplar surface_type/scope to a single surface: placement pointer, keeping Layer 1 prose constant and the flat facet files intact for the first cut. Includes a worked example from this repo's own dogfood .ghost/, lint obligations, and open forks (closed vs open edge_kinds, dotted ids, default placement, where path->surface mapping lives). Additive and backward compatible: absent surfaces.yml keeps single-core behavior.
Resolve two open forks into decisions. edge_kinds is a fixed, Ghost-owned, closed set referenced (never defined) per package: opening it would make Ghost a general-purpose graph database and lose the interface-composition focus; richer consumers extend edges consumer-side, not by opening Ghost's set. IDs are flat, unique slugs with no structural meaning; dotted-id-as-hierarchy is banned (lint error) so the tree lives only in parent, one source of truth (kills Leak C). Updates the example, field rules, lint obligations, and forks list; two forks remain (surface default, path->surface binding).
…coped ownership Resolve the remaining forks. Placement is explicit: defaulting un-placed nodes to core would rebuild global-fallback (the brand-mixing failure the redesign cures), so authoring drafts placement, lint warns-and-teaches on the gap, and un-placed never silently means core (warning not error, matching the derivation- ref convention). Reframe the path->surface fork as scoped ownership: in a repo, surfaces are owned by location (the checkout surface is realized under apps/checkout), which is ordinary nested-package/CODEOWNERS-shaped binding, not a new subsystem. The portable contract (surfaces.yml) carries no paths; paths live on the binding. One sub-fork remains for its own note: nested-package-as-binding vs explicit path declaration vs both.
Second concrete extraction. The contract (surfaces.yml) carries no paths; the binding owns all path matching. Directory location is the default binding (a scoped .ghost/ binds surfaces to its subtree, reframing nested-package resolution from data-merge to binding); an explicit .ghost.bind.yml is the escape hatch when ownership does not match the tree, and is the real home for the deleted topology.scopes[].paths. One resolver serves prompt, path, and diff roads, meeting at a surface id; no-repo cases need no binding. Reframes nesting-as-ownership to retire Leak E (no silent merge override, no silently disabled inherited critical check). Records open forks (external contract references, core fallback, bind-vs-redeclare) and the honest caution that this is the least proof-validated layer, so it ships smallest-first.
Plan the breaking change as eight dependency-ordered phases, each a green, committed cut: (0) freeze/baseline, (1) ghost.surfaces/v1 schema, (2) surfaces lint, (3) placement on nodes — the breaking line, removing topology/applies_to/ surface_type/scope, (4) delete ghost.map/v1, (5) slice resolver + menu (prompt road), (6) one-shot migration command + migrate this repo's .ghost/, (7) ghost.binding/v1 path/diff roads + retire child-wins-by-id (Leak E), (8) command/ skill/docs reconciliation. Measured blast radius (~38 src, ~16 map, ~20 test files). Additive phases 1-2 land first to de-risk; least-validated binding lands last. Records open planning decisions (relay survival, migrator permanence, delete-list commands).
…s test A command's desire survives if the new model serves it; its implementation survives only if it already is that. Relay's desire (right narrow context, right time, traceable) is realized by the Phase 5 resolver; relay's implementation (relay-config, request_resolvers, sources, ghost.relay-request/v1) is the second routing system on the delete list. So relay/stack/survey/diff/describe are deleted: relay and stack absorbed into a new gather/select command shipped in Phase 5, the rest dead. Phase 5 ships the new context command on the resolver (not old relay plumbing); Phase 8 deletes the dead commands as execution, not decision. Collapses three open planning decisions into one.
…odule First implementation cut, purely additive. Specs a new ghost-core/surfaces/ module mirroring fingerprint/ (types, schema, index) plus a schema test and one re-export in ghost-core/index.ts. Schema bans dotted ids via a dot-excluding slug regex (the tree lives only in parent); single parent falls out of parent being scalar; edge kinds restricted to the fixed Ghost-owned set. Draws an explicit schema/lint boundary: graph-level checks (cycles, dangling parent/edge refs, near-miss, reserved core) are deferred to Phase 2 lint, documented in a test case so they are not fixed in the wrong layer. Out-of-scope and acceptance criteria are enumerated; one commit, no changeset (no user-visible behavior).
Two regressions from the earlier docs focus pass, surfaced by running the full test suite (the pre-commit hook runs pnpm check, not pnpm test). Remove Ghost's own dogfood .ghost/ package and its verify test: the package cited deleted docs as evidence (fingerprint-evidence-unreachable), and a self-referential fingerprint has been more confusing than useful. Scope terminology-public to genuinely shipped text (README, docs site content, skill bundle, changesets), excluding docs/: the design notes and purposes.md now use 'layers' and 'cascade' as the canonical vocabulary of the surface-model redesign, which the old guard forbade.
Phase 1 of the surface-model cutover (docs/ideas/phase-1-plan.md). Purely additive: a new ghost-core/surfaces/ module mirroring fingerprint/, changing no existing behavior. - schema.ts: Zod for surfaces.yml. Flat-slug ids with the dot excluded, so dotted-id hierarchy is rejected at the schema layer (the tree lives only in parent). Single scalar parent; edge kinds restricted to the fixed Ghost-owned set (composes, governed-by). - types.ts: constants, interfaces, and lint report types reusing the fingerprint facet shape for uniformity. - index.ts + ghost-core/index.ts: re-export under @anarchitecture/ghost/core. - tests: schema accepts a minimal doc and a realistic tree with typed edges; rejects dotted ids, array parents, unknown edge kinds, unknown keys. One case documents that dangling edge refs pass the schema on purpose (a Phase 2 lint concern), so the schema/lint boundary is not crossed in the wrong layer. Graph validation (cycles, dangling refs, reserved core) is Phase 2. No changeset: no user-visible behavior yet.
Add the Phase 2 execution spec (lintGhostSurfaces graph validation + ghost lint dispatch for surfaces.yml; edge cycles allowed, only parent tree-constrained). Also adopt the pre-commit test gate: lefthook.yml now runs just test alongside just check, closing the gap Phase 1 exposed (the check-only hook let two regressions through). Implementation-plan and phase-2-plan process notes updated to reflect that both gates now run automatically.
Phase 2 of the surface-model cutover (docs/ideas/phase-2-plan.md). Additive: adds document-level graph validation and recognizes surfaces.yml in ghost lint. - lint.ts: lintGhostSurfaces validates what the schema cannot see in isolation — parent references exist (with core as the implicit-root exemption), the parent graph is a tree (cycles and self-parent error), edge targets exist (no core exemption), core may not declare a parent, duplicate ids error, and near-miss parent/edge ids warn via a local Levenshtein. Edge cycles are allowed; only parent is tree-constrained. - types.ts: add errors/warnings/info counts to the lint report so it matches the other facet linters and the CLI dispatch return shape. - scan/file-kind.ts: detect surfaces.yml / surfaces.yaml and the ghost.surfaces/v1 literal, dispatch to lintSurfacesFile, mirroring the patterns/resources path. - exports + tests: 12 lint cases covering every rule plus the allowed edge cycle and the schema-failure-as-issues path.
Specs Phase 3, the breaking line: remove topology/applies_to/surface_type/scope from the canonical fingerprint (delete the Scope and Topology schemas) and add a single optional surface: placement per node, validated against surfaces.yml. Maps every removed field to its replacement against the live schema, and scopes the cut to the description facets only — check.applies_to is left for Phase 4/7 because it is coupled to map routing, and pulling it into Phase 3 would leave a half-migrated routing layer. Enumerates the lint rework (placement validation with cross-facet surface input, unplaced warns, near-miss reuse), the consumer ripple (context/graph the largest, kept minimal pending Phase 5), type removals, test migration, the major changeset stub, and explicit out-of-scope.
… test fallout A full read of context/graph.ts shows it is two subsystems: a structure/content graph built from refs (keep, mechanical coordinate-string swap) and an applicability/scope selection machinery that IS the old coordinate model (buildScopes/matchScopes/nodeMatchesTargets/applicabilityFrom*). The original 'map applicability to home surface' instruction would reimplement the selection machinery against placement in the breaking phase only for Phase 5 to discard it — doing the work twice. Revise to make Job 2 compile-dormant and rewrite selection once in Phase 5/7. Also name the expected consequence: path-based selection tests (relay/context) break, and must be migrated or marked pending rather than propped up.
…ase 3) BREAKING: remove topology, applies_to, surface_type, and scope from the canonical fingerprint; coordinates are now a single optional surface: placement per node, validated against surfaces.yml. Schema/types: delete GhostFingerprintScope/Topology/TopologyScope and the topology subtree; add surface: to situations, principles, experience_contracts, patterns, exemplars. Lint: replace topology-ref checking with checkPlacement — unplaced nodes warn (fingerprint-node-unplaced), unknown placements error (fingerprint-surface- unknown) with near-miss suggestions; surface ids are passed in via a new GhostFingerprintLintOptions.surfaceIds (cross-facet, mirroring validate lint). graph.ts: keep the structure/content graph (Job 1, mechanical surface swap); make the path/scope selection machinery (Job 2) compile-dormant — rebuilt against surfaces in Phase 5/7 rather than reimplemented against placement now. Consumers: comparable-fingerprint, package-context, package-review-command, fingerprint-contribution, fingerprint-package-layers, fingerprint-stack updated; map-derived check routing (mapFromFingerprint) and check scope/surface_type grounding made dormant pending Phase 4/7. ghost-ui: migrate the reference bundle to surfaces.yml; drop topology. Tests: migrate fixtures to surface:; rewrite topology/grounding assertions to the dormant behavior; skip path-selection suites (relay, context-entrypoint) and two cli relay cases pending Phase 5/7. Full suite green (410 passed, 31 skipped).
Specs Phase 4: delete the map.md coordinate/routing layer made dormant in Phase 3. Key finding from a full read — the map module is two tangled concerns: the routing layer (MapFrontmatter, getEffectiveMapScopes, MAP_FILENAME, the map.md schema/lint) to delete, and inventory-output types (GitInfo, InventoryOutput, LanguageHistogramEntry, TopLevelEntry) that merely live in map/types.ts and must be relocated, not deleted, since scan/inventory.ts needs them. Plan: relocate the types first as a safe sub-commit, then delete routing and rewire consumers (fingerprint-stack, checks/lint+routing+types, core/check, scope-resolver, file-kind, lint-map, scan-status, fingerprint-package). check routes on applies_to.paths alone; surface-based routing is deferred to Phase 7. Flags reachability checks for scope-resolver and routeGhostValidateForPath before delete-vs-reduce.
…(Phase 4) BREAKING: remove the map.md / ghost.map/v1 coordinate-and-routing system made dormant in Phase 3. - Delete ghost-core/map/ (schema, scopes, the map half of types) and scan/ lint-map.ts. Relocate the inventory-output types (GitInfo, InventoryOutput, LanguageHistogramEntry, TopLevelEntry) that merely lived in map/types.ts to ghost-core/scan-types.ts; scan/inventory.ts is unaffected. - routeGhostValidateForPath now routes on applies_to.paths alone (no map scope resolution); drop routeGhostPathToScopes, matched_scopes, and the options.map check-scope grounding. Surface-based routing is rebuilt in Phase 7. - core/check.ts routes by paths; remove mapFromFingerprint, parseMap, map.md reading, and the map field on the check package/stack types. - Delete dead legacy: core/scope-resolver.ts and scan/fingerprint-set.ts (both unreachable map-scope fingerprint loaders) and their re-exports. - scan-status: drop --include-scopes / scope reporting (map-driven). file-kind: drop the map DetectedFileKind and dispatch. Pull ghost-fleet out of the workspace: a private, map-native relic of a past idea, to be reintroduced later on the surface model. Removed from the root tsconfig references and the cli-manifest dump; package deleted (recoverable from history). Tests: delete map-scopes and scope-resolver tests; retarget checks routing tests to path-only. Full suite green (383 passed, 31 skipped).
…olver Specs Phase 5, the first additive phase: rebuild the dormant selection road on the surface model and ship it as a new gather command (relay's desire done right). Four pieces: a surfaces loader (reads surfaces.yml into the package model — never built; Phases 1-2 did schema+lint only), a deterministic slice resolver (own placed nodes + cascaded ancestors + one-hop typed-edge contributions with provenance, no LLM), a menu emitter (surfaces + descriptions for the host agent to match against), and the gather command (surface to slice, no/unknown surface to menu). Ambiguity returns the menu, never a whole-tree dump. Replaces entrypoint.ts Job 2 (matchScopes/globalFallbackRefs/CAPS). Scoped to the prompt road; path/diff routing is Phase 7. Re-expresses the Phase 3 selection skips against gather. Minor changeset (additive).
Phase 5 — the first additive phase. Rebuilds the dormant selection road on the surface model and ships it as a new gather command (relay's desire done right). - Surfaces loader: read surfaces.yml into the package model (the disk-read step deferred since Phase 1). loadFingerprintPackage now parses it onto LoadedFingerprintPackage.surfaces; FingerprintPackagePaths gains surfaces. - resolveSurfaceSlice (ghost-core/surfaces/resolve.ts): deterministic, no I/O, no LLM. Composes own placed nodes + cascaded ancestors (down-tree only) + one-hop typed-edge contributions, each tagged with provenance (own / ancestor:<id> / edge:<kind>:<id>). Unplaced nodes resolve as core. Checks are excluded — they route by paths (Phase 7), not surface placement. - buildSurfaceMenu (surfaces/menu.ts): deterministic id+description+parent+edges list, always including the implicit core, for the host agent to match against. - gather command: ghost gather <surface> emits the slice (markdown or json); no surface emits the menu (exit 0); unknown surface emits the menu (exit 2). Net-new, not built on relay-config/request-resolution. Tests: resolver (own/cascade/edge/unplaced/empty/no-doc), menu shape, and gather CLI (slice + menu + unknown). Full suite green (397 passed, 31 skipped). Minor changeset (additive).
Specs Phase 6: a one-shot ghost migrate command that moves a legacy .ghost/ onto the surface model. Scope correction — the plan's 'migrate this repo's dogfood .ghost/' no longer applies (deleted in the reset; ghost-ui was hand-migrated in Phase 3), so Phase 6 is only the command + tests, for external users. Key constraint: the current schema rejects legacy fields, so the migrator operates on raw parsed YAML, not the package loader. Derives surfaces.yml from topology.scopes; places single-scope nodes via surface:; drops surface_type (no placement concept) and reports applies_to.paths (Phase 7 binding concern). Core discipline: report-don't-guess — ambiguous/multi-scope nodes are surfaced for human review, never auto-placed. Additive, minor changeset.
Phase 6 — additive. A one-shot migration of a legacy .ghost/ onto the surface model. - migrateLegacyPackage (scan/migrate-legacy.ts): pure transform over raw parsed YAML (the schema rejects legacy fields, so the loader cannot read a legacy package). Derives surfaces.yml from inventory.topology.scopes; places nodes via surface: from a single scope (explicit exemplar scope, or a lone applies_to.scopes entry); strips applies_to/surface_type/scope. Report, don't guess: multi-scope, surface_type-only, and bare nodes are left unplaced and recorded in a MigrationReport, never auto-placed. paths are reported, not converted (binding is Phase 7). Does not mutate input. - looksLegacy: detect a legacy package by topology / node coordinate fields. - ghost migrate [dir] command: --dry-run (print plan + report, write nothing), --force (rewrite in place), --format cli|json. Refuses non-legacy packages. Tests: 11 transform unit tests (surface derivation, single-scope placement, exemplar placement, multi-scope/type-only/bare reporting, topology drop, no-mutation, migrated package passes lint) + 2 CLI round-trip tests (migrate → lint clean → gather places correctly; refuses non-legacy). Full suite green (410 passed, 31 skipped). Minor changeset.
…roads) Specs Phase 7, the largest and least proof-validated cut. Surfaces the core structural tension from reading fingerprint-stack.ts: the current model is merge-centric (loadFingerprintStackForPath walks root-to-leaf, mergeFingerprints unions facets child-wins-by-id, consumers read stack.merged.*). Binding replaces 'merge layers into one fingerprint' with 'resolve path to binding to surface to composed slice' (the Phase 5 resolver output, not a facet union) — the load-bearing reframe to get right before touching consumers. Four steps: binding schema+loader (ghost.binding/v1, .ghost.bind.yml), the path-to-surface resolver (nearest binding wins, explicit beats directory-implied, multi-surface directory requires explicit — report don't guess), wiring the path road (gather --path) and diff road (check/review union of surfaces), and retiring the merge (delete mergeFingerprints/mergeChecks/mergeById and child-wins-by-id, keeping layer discovery as binding discovery). Consumers measured: check (biggest), review-packet, scan-stack, scan-emit; relay left for Phase 8 deletion. Scoped to in-repo contract: . only; external references and relay rewire deferred.
The additive, format-neutral half of Phase 7: turn a filesystem path into a surface, the substrate any check routing needs underneath. - ghost.binding/v1 (ghost-core/binding/): schema, lint, types for .ghost.bind.yml. contract is in-repo '.' only (external refs deferred); paths live on the binding, never the surface. Lint enforces the supported contract and rejects double-bound surfaces. - resolvePathToSurface: pure path-to-surface resolver. Nearest binding wins; explicit beats directory-implied at the same level; a single directory-implied entry binds unconditionally; a multi-entry binding requires a path match (report, don't guess); unbound resolves to core when a root contract exists, else returns null (caller emits the menu). - discoverBindingsForPath (scan/): walk root-to-leaf, collect directory-implied (scoped surfaces.yml) and explicit (.ghost.bind.yml) candidates. - .ghost.bind.yml file-kind detection + lint dispatch. - gather --path <file>: resolve a repo path to its surface via binding, then compose the slice. Verified end-to-end. 14 new tests (7 resolver, 7 schema/lint). Full suite green (424 passed). Minor changeset. Diff road + merge retirement deferred (see phase-7b note).
…unded checks After reading how checks are actually authored (markdown + frontmatter, agent-evaluated, LLM-filtered for relevance), the 'add surface: to Ghost's deterministic detector' sketch is wrong. Settles three decisions: Ghost does not run checks; mimic the established markdown check format rather than compete with it; the differentiator is grounding — when a check flags something, Ghost supplies the why (principles/contracts) and what-to-change (patterns/exemplars) from the surface's gather slice. Ghost owns deterministic path-to-surface routing (the relevance filter, better than an LLM guess) and fingerprint grounding; it never owns the check engine. ghost.validate/v1's regex detector becomes legacy. Leaves four open questions for the 7b build (check placement, grounding emit shape, validate/v1 deprecation, and the still-owed merge retirement), explicitly not improvised here.
Sequences the governance build into four independent cuts: (1) retire the child-wins-by-id merge (Leak E) — the one piece with no dependency on the check-format question, riskiest and most independent, done first and alone; (2) ghost.check/v1 as markdown + frontmatter (name/description/severity/tools/ turn-limit + surface:), mirroring the established agent-check format, parsed and linted but never executed; (3) surface-routed relevance — a diff resolves paths to surfaces (Phase 7a) and selects checks governing those surfaces and ancestors, reusing the Phase 5 cascade and replacing path-glob routing; (4) fingerprint grounding built on review — each flagged surface emits why (principles/contracts) + what (patterns/exemplars). ghost.validate/v1 detector kept parseable but demoted from the governance path; full removal and check migration deferred. Cut 1 first and alone; 2-4 in order.
…tract (7b Cut 1) Retires the fingerprint merge (Leak E). A nested .ghost/ no longer carries its own fingerprint merged into the parent by id — instead a path resolves to the single root contract, used as-is, and nesting binds paths to that contract's surfaces (ghost.binding/v1). One contract, many bindings. - buildFingerprintStack: the root-most layer is the contract; no mergeFingerprints / mergeChecks. stack.merged → stack.contract (the root's fingerprint + checks). - Deleted mergeFingerprints/mergeIntent/mergeInventory/mergeComposition/ mergeBuildingBlocks/mergeSummary/mergeChecks/mergeById/mergeByKey/mergeStrings and the child-wins-by-id provenance. - Consumers rewired: core/check.ts, review-packet.ts, scan-stack-command.ts, fingerprintStackToPackageContext. relay left for Phase 8 deletion (minimal compile fix only). - Public check-report/v1, review, and stack JSON expose (not ) and drop . Fixes Leak E directly: the prior nested fixture had a child disabling an inherited critical check via merge — now the root contract's active check governs and the diff correctly fails. Tests rewritten to the bind-only model. Full suite green (424 passed).
Adds the Ghost check format: markdown + frontmatter, agent-evaluated, never run by Ghost. Mirrors the established .agents/checks format plus a Ghost surface: placement that routes the check. - ghost-core/check/: types, parse (frontmatter splitter), lint, and a typed loader. Frontmatter: name, description, severity (high|medium|low), optional tools / turn-limit, optional surface (flat slug; absent governs core). - lintGhostCheck validates required frontmatter, known severity, flat-slug surface, and a non-empty body; warns when unplaced. No detector, no execution. - file-kind: a markdown file under a checks/ directory lints as a check (detected by location, since the format has no schema: field). 9 tests (parse, lint paths, typed load). Full suite green (433 passed). Minor changeset. Surface-routed relevance (Cut 3) and grounding (Cut 4) next.
Specs Cut 3: the deterministic relevance filter where 7a binding, the Phase 5 cascade, and Cut 2 markdown checks compose. selectChecksForSurfaces (pure) selects checks governing a diff's touched surfaces and their ancestors, reusing ancestorChain from the slice resolver (one cascade for context and governance). Diff road: changed paths to surfaces (binding) to relevant checks. Surfaces the key decision — markdown checks route by surface, legacy validate/v1 detectors keep their path-glob router; add surface routing beside it, do not rip out the legacy path (deprecate by addition). Recommends a checks/ dir loader and a new additive command rather than disturbing check. No grounding (Cut 4), no execution, no validate/v1 removal.
…7b Cut 3) The deterministic relevance filter — where 7a binding, the Phase 5 inheritance, and Cut 2 markdown checks compose. - Extracted ancestorChain/buildParentMap into surfaces/cascade.ts; the slice resolver and check routing now share one inheritance definition (context and governance resolve the same way). - selectChecksForSurfaces (ghost-core/check/route.ts): pure, no LLM. Selects checks governing a diff's touched surfaces and their ancestors; unplaced checks govern core (apply everywhere); provenance tags own vs. ancestor. - loadChecksDir (scan/): reads <package>/checks/*.md, lints each, skips invalid with a reason. - ghost checks --diff: resolve changed paths to surfaces (binding), union, select; prints relevant checks per surface (markdown + json). Additive; the legacy validate/v1 detector path and its router are untouched. 13 tests. Full suite green (440 passed). Minor changeset. Grounding (Cut 4) next.
The audit tense of the same substrate review uses (plan: notes/haunt-integrity.md). Review grades a change; integrity grades the whole inventory: does what we own still cohere with what we said, and with itself? - haunt integrity [--package --ghost-dir --json]: no diff input; partitions git-tracked files by inventory paths and emits a deterministic per-material packet. Fingerprint required (shared exit-2 on-ramp, now also used by review). - The packet is a map, not a payload: authored prose only; paths are glob pointers with verified match counts, no embedded file lists. Siblings are pointers (id + description + paths) so the agent grades each material relationally, pulling code depth itself (BYOA). - Two baselines in the preamble: the fingerprint's stated truths, and the inventory's own latent pattern - on-pattern vs outlier, with outlier findings required to name the pattern they break. Five sprawl axes ship as orientation, not grading instructions. - Gaps: dead-paths (globs matching zero tracked files - rot) and unreferenced-material (no check references it - unguarded). - Shared baseline resolver extracted from review-packet (verbatim, review behavior pinned by existing tests); init's example check is now sprawl-flavored; skill bundle and README teach the two tenses. 10 test files, 39 haunt tests (+12).
CLAUDE.md and docs/purposes.md still taught the retired directory-tree-is-the-graph model (path inheritance, relates edges, checks inside .ghost/). Rewrite both against what the code implements: a flat corpus of <kind>.<slug>.md nodes plus a glossary, menu-driven selection, checks living in Haunt and binding via references. Strip the fossil embedding-API env vars and delete the dead context-sandbox test suite (skipped, referencing a removed relay CLI).
…nse seam The review packet rendered 'Offered via:' for fingerprint-only checks, implying a mechanical diff->inventory match that never happened. Add offered: "matched" | "always" to OfferedCheck and render the two honestly. Document the mixed-check semantics the code already had: a local reference scopes a check to its material at review (trigger + baseline); whole-system drift outside a material's paths is haunt integrity's job, on a cadence the consumer chooses (manual, cron, signal-driven). One truth, two tenses — review stays strict and quiet, integrity carries the advisory 'fyi' net.
One front door: `ghost` stays the primary bin and grows git-style external-subcommand dispatch — `ghost haunt <command>` execs the `ghost-haunt` binary when installed (PATH first, node_modules/.bin fallback), with a friendly install hint and exit 2 when absent. Haunt's bin renames haunt -> ghost-haunt, making the family visible in every invocation. `ghost-haunt init` now scaffolds a missing .ghost/ fingerprint first (reusing the fingerprint package's own scaffold) with a loud notice that an unauthored fingerprint grades nothing. Following yarn/yarnpkg, the public package also ships a `ghost-fingerprint` alias bin for machines where another tool owns the `ghost` name (notably the Ghost blog CLI).
…unt/ One dotdir, one anchor. Haunt's on-disk package moves from a standalone .haunt/ to the reserved haunt/ subtree inside .ghost/ — a plugin that piggybacks on the fingerprint completely. The fingerprint's manifest is the only package anchor: haunt's own manifest.yml, schema, --package and --id flags are deleted, and its location is derived (<ghost-dir>/haunt), never configured. Packets drop packageId (it would always equal fingerprintId). Fingerprint side: 'haunt' joins the reserved root entries; the retired checks/ reservation and loadChecksDir export are removed. The reserved list is now closed by constitution (docs/purposes.md): new entries must pass the leak test and ship with a schema version; reserved subtrees never travel with a fingerprint export. A legacy top-level .haunt/ next to .ghost/ gets a migration warning from ghost-haunt validate rather than silent breakage.
Three curation-pass findings from authoring the docs-site fingerprint, folded into one schema pass: - manifest.yml gains an optional plugins key declaring which reserved plugin subtrees the package uses; ghost-haunt init declares plugins: [haunt], and validate warns on present-but-undeclared or unknown plugins. Reservation stays unconditional — the key is hygiene, not gating. - ghost gather serves the haunt plugin's inventory as a Materials section after the node menu: generation may lean on the repo's building blocks, while checks remain feed-back only and are never gathered. - The index.md → core id mapping is gone: one uniform rule, id = path minus .md. The entrypoint node's documented job is the human-curated front door; the glossary is taught as a dictionary of every term with defined meaning, including bare-node terms like voice.
…index front door Three amendments tracking the schema pass: - gather's projection now includes the haunt inventory as a materials section — the feed-forward/feed-back seam runs through the plugin itself (inventory grounds building, checks grade output, checks are never gathered). - the manifest's plugins list is the declared register of reserved subtrees in use; validate warns on present-but-undeclared. - the entrypoint node is index.md with id index (uniform id rule), and its job is named: the human-curated front door, never a generated listing. The glossary is defined as the author's dictionary — every term with defined meaning, including bare-node terms.
Delete docs/ideas/ and ideas/ (superseded graph-era models and removed commands — code and git history are the record; docs/purposes.md remains the sole internal model doc). Rewrite both READMEs from the skill-bundle canon in plain language: flat corpus, glossary kinds, condition-in-prose, real CLI commands only. Patch Haunt README (pointer example, gitignored notes/ links) and getting-started (haunt/ in the reserved list, front-door phrasing). Clean stale code comments pointing at deleted idea docs.
…local history tape Add `ghost pull <id> [<id>…]`: emit the named nodes' full prose bodies (markdown or json) and append each selection as one line to .ghost/.pulls — a gitignored, disposable history tape. The point is the iterating loop: tune a node's description, re-run the task, tail the tape to see whether the agent reached for the truth. Ghost never reads the tape back; it is scratch, never canonical state. Unknown ids exit 2 with a closest-id hint and append nothing; --no-history skips the append. ghost init now seeds .ghost/.gitignore covering the tape. The skill bundle (SKILL.md, recall, brief) teaches agents to pull instead of reading node files directly. Also commits the two pending changesets from the previous docs/skill commit.
…ocal pulse Retire the separate packages/haunt package and its second binary. Capabilities now attach as haunts under .ghost/haunts/<id>/ (managed by ghost haunt add|remove|list or ghost init --with), with checks as the first haunt. Nodes carry optional materials locators; ghost review assembles advisory diff packets from material-backed nodes and checks. Add local gather/pull event tracing (.ghost/.events) and a ghost pulse report. Vessel picks up stack, surface, and text primitives plus an agent-safety audit script.
- New Checks And Review guide: haunts, check authoring, review packets, coverage gaps as tuning signal - CLI reference: haunt and review commands, exit codes, validate scope, init --with checks, haunts/ in the package shape - Getting started / authoring: feed-forward vs feed-back framing, materials frontmatter, haunts/ reserved name, cross-links - Homepage thesis and hero: retire the node-graph/inheritance model for the flat corpus, gather-as-menu, and haunts - Tools pages and command palette: ghost scan -> ghost gather, real review framing, dead anchors removed - install.sh: describe the actual skill bundle and loop, not the retired intent.yml/lint/verify era - Source: validate help text and stale comments describe current validation scope; no ghost migrate pointer; changeset for the user-visible help text fix
Replace the legacy intent/inventory/surfaces yml package (and its extraction-era history.jsonl) with a current-format fingerprint distilled from the Phase 0 invariants doc: - index + principle.reference-not-brand: the reference-body seam - principle.named-decisions: agent-safety discipline - asset.tokens / asset.registry: material-backed contracts - condition.escape-hatches / condition.upstream-sync: situational truths - checks haunt: four review assertions wired to ghost review Validates clean; gather/pull/review smoke-tested with zero coverage gaps on token+component diffs. Vessel's .ghost now doubles as a living exemplar of the format. README updated to point at it.
- Rename the public scope to @decentralized-design across packages, docs, workflows, and release scripts - Order ghost pull packets for steering and extract Skeletons last; add probe execution to ghost review and concreteness to pulse - Move steering starter templates into scan/steering-template.ts - Add node prose stances and a scored drafting gate to the capture recipe, wired into both authoring recipes - Refresh skill bundle prose, README, CLAUDE.md, and docs content
- @decentralized-design/* -> @design-intelligence/* across packages, lockfile, workflows, release tag/tarball prefix, and guard scripts - Replace the scope-name manifesto with a Thesis section: agents changed the unit of design work; the work that compounds is architectural - check-packed-package: strip inherited npm_config_* env and pin packageManager in the temp consumer so the check passes under pnpm run
…I scores Intent / inventory / composition stop being a named Ghost concept. Authoring surfaces now teach three drafting questions — why (stance), with what (materials), how it is assembled (patterns) — each mapped to the dimension the machinery already scores: stance prose reads first and steers weakest alone, materials drive concreteness/pull ordering/review matching, Skeleton fences are extracted and emitted dead last. - Rename references/inventory.md to references/blocks.md; declare "block node" as recipe shorthand up front and show the glossary declaration the block.* worked examples require, so copying them cannot fail ghost validate. - Rewrite the lens sections in capture.md, authoring-scenarios.md, SKILL.md, docs/purposes.md, CLAUDE.md, both docs-site .mdx pages, two nav cards, and the ghost-core types.ts comment onto the same vocabulary. - Counterweight "weakest steering" so authors do not under-invest in stance. - Update install/manifest.json and cli.test.ts for the rename.
Maps each claim in agent-readable-brand-steering.md to verified literature with honest evidence tiers (Established / Adjacent / Prior), a list of claims we deliberately do not cite, and open experiments for untested priors.
* main: chore: version packages (#188) fix: honor GHOST_PACKAGE_DIR in drift, ack, history, and review-command paths # Conflicts: # packages/ghost/package.json # packages/ghost/src/context/package-review-command.ts # packages/ghost/src/core/evolution/history.ts # packages/ghost/src/drift-command.ts # packages/ghost/src/evolution-commands.ts
The one-plugin plugin system (ghost haunt add|remove|list, haunt.yml, ghost.haunt/v1, KNOWN_HAUNTS) is gone. Checks are a core capability in a flat .ghost/checks/ directory: scaffold with ghost checks init or ghost init --with checks; export --no-checks replaces --no-haunts. validate flags stale haunts/ trees with a migration hint. The word is purged from all public prose and added to the terminology guard. The repo's own nested fingerprints (apps/docs, vessel) are migrated and their glossaries fixed to the current kinds: schema.
@design-intelligence/ghost has never been published; the first release under the new name has no consumers to break, and the retired @anarchitecture/ghost name never receives this code. Majors here would only force an accidental 1.0.0 — that milestone should be declared deliberately.
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.
Category: improvement
User Impact: Ghost becomes one package (
@design-intelligence/ghost) with one CLI, and a fingerprint is now a flat folder of plain-prose brand truths any agent can read before it generates.Problem: The previous model — a graph-shaped fingerprint with inheritance, cross-package refs, a separate adherence binary (Haunt), and a cross-medium projection axis — shipped surface area nobody used and made authoring a fingerprint feel like configuring a system instead of writing down brand truths.
Solution: Collapse everything onto the flat-corpus model:
.ghost/ismanifest.yml+glossary.md+ prose nodes withmaterialslocators. Haunt folds into the fingerprint, then the plugin abstraction is removed entirely: checks are a core opt-in capability at.ghost/checks/.ghost pullbecomes the read chokepoint with a local events tape andghost pulse. The npm scope renames to@design-intelligence,ghost-uibecomes the privatevesselregistry, andghost-fleetis deleted.The major shifts
@anarchitecture/ghost→@design-intelligence/ghost. Tarball/tag prefixes, install script, release workflows, and the npm publish secret (DESIGN_INTELLIGENCE_NPM_PUBLISH_TOKEN) all follow.extends, no colon refs, no JSON fingerprint schema. A node is a markdown file; its kind is a filename prefix declared in the glossary. Removed unused surface:incarnation/--as, scan/signals/inventory, standalonesearch(folded intogather's no-match path).ghost haunt,haunt.yml,ghost.haunt/v1). Checks live flat at.ghost/checks/, scaffolded byghost checks initorghost init --with checks;ghost reviewemits advisory diff packets from material-backed nodes and checks;export --no-checksexcludes them.validateflags stalehaunts/trees with a migration hint, and the retired word is enforced-absent from public prose by the terminology guard.ghost pull <id>…emits selected node bodies and appends to a local.ghost/.eventstape;ghost pulsesummarizes it.ghost-ui→vessel(private shadcn registry + MCP server);ghost-fleetdeleted; docs site and README rewritten around the new thesis; research references doc added.Blast radius
@design-intelligence/ghosthas never been published, so this branch has no released consumers to break; 1.0 stays a deliberate milestone)packages/vessel(266 files, mostly renames from ghost-ui),packages/ghost(239),apps/docs(197),.changeset(69)check:release-workflows,check:release-tarball, andcheck:packed-packageall pass, but the live publish is unverified until the version PR merges..ghost/is re-authored under the flat-corpus model (index, glossary, voice + BYOA-boundary principles, surface-sprawl guard, flat-corpus decision trace);ghost validatepasses clean.Validation:
pnpm build: passpnpm test: 130 passed, 1 skipped (12 files)pnpm check: pass (biome, typecheck, package-bin, packed-package, file-sizes, terminology, docs, install-bundle, release-tarball, release-workflows, cli-manifest)Changeset: 69 changesets accumulated on the branch (48 minor, 21 patch); Changesets will open the version PR after merge, bumping to 0.20.0 under the new scope.
Ghost Review:
ghost validate: 0 errors, 0 warnings on the re-authored root fingerprint.ghost reviewnot run: no checks directory on this fingerprint yet.File changes (grouped — 850 files)
packages/ghost/ (239 files)
The public package rebuilt around the flat corpus: node schema, glossary kind-prefix validation, gather menu + closest-id suggestions, pull chokepoint + events tape, pulse, core checks management, review packet assembly, unified skill bundle, CLI exit-code contract,
ghost manifest.packages/vessel/ (266 files, mostly
R100renames frompackages/ghost-ui/)Rename to
vessel: private shadcn component registry +vessel-mcpserver. Removed from public docs/exports.packages/ghost-fleet/ (25 files, deleted)
Fleet package removed; the concept survives only as the
ghost-fleetskill outside this repo.apps/docs/ (197 files)
Docs rewritten for the flat-corpus + core-checks model: new quickstart, verb-led onboarding, constitution amendments, generated CLI manifest, removal of graph/incarnation/extends pages.
.changeset/ (69 files)
One changeset per user-visible change across the branch.
docs/, ideas/, README.md, CONTRIBUTING.md, CLAUDE.md
Thesis rewrite, research references doc, retired three-lenses vocabulary, stop-slop passes.
.github/workflows/, install/, scripts/
Release workflows and install script moved to the
design-intelligenceprefix and new publish secret; check scripts updated for the single-public-package shape;emit-fingerprint-schemaandstrip-signatureremoved.schemas/fingerprint.schema.json (deleted)
The JSON schema era ends; validation is CLI-native.
.ghost/ (re-authored)
Old-model facets (intent/inventory/composition/validate YAML) replaced with a flat-corpus fingerprint: manifest, glossary, index, two principles, one guard, one decision trace. Ghost dogfooding Ghost.
Root config (
package.json,pnpm-lock.yaml,tsconfig.json,biome.json,lefthook.yml,justfile,.gitignore,.agents)Workspace bookkeeping for the renamed/removed packages.
Screenshots/Demos: N/A