Migrating to Dotdog 1.0

This guide covers the 1.0 npm/Bun release. Homebrew and Spec Kit extension assets are separately maintained distributions; verify their published versions before installing.

Distribution

npm and Bun continue to install the same JavaScript package. Homebrew remains a separately maintained distribution. The Rust port in PR #330 is not part of this npm cutover. Node.js minimum is now explicitly 22.12.0; Bun 1.3+ remains supported.

Rebuild generated identities

Run dotdog refresh after upgrading. Generated IDs now include a digest of the original identity components, preserving distinctions such as A.ts versus a.ts. Old compiled graph formats remain readable; regenerating them changes their generated IDs. Update any external references to generated IDs, or use graph labels for interactive queries.

Human-owned .doghouse/semantic and .doghouse/overlays inputs are preserved. Observed graph data, caches and refresh state belong under ignored .doghouse output paths. Decide explicitly which human-owned inputs your repository should track.

Compact spec graphs retain schemas, defaults, lifecycle and descriptions rather than discarding them to maximize a compression score. Different source files with incompatible declarations for the same entity use Name@source-file labels. Relationships resolve in their source file; an unresolved ambiguous relationship is an error, not an arbitrary link.

Skills, hooks and CI

dotdog skills install --agent both installs repository-local Codex and Claude skills. It does not change global configuration or enable hooks. Edited skills are not overwritten; review them before updating.

dotdog hooks install --agent git installs a staged-index check. Existing hooks and custom hook-manager configuration are preserved by refusing replacement. A shared Git worktree hook outside the current repository boundary must be configured through the existing hook manager instead.

dotdog hooks install --agent claude adds a PostToolUse edit hook while retaining unrelated settings. This hook does not observe all shell or external-editor writes. Task-boundary refresh and independent CI checks are still necessary.

Use dotdog hooks status to inspect registration, and dotdog hooks remove --agent git or claude to remove Dotdog’s hook contribution. Git hooks do not auto-stage generated graphs or human files.

Run a pinned Dotdog version and dotdog check in CI alongside application-specific tests. check --staged uses an isolated index snapshot; an unstaged edit does not change what it checks. These checks validate graph generation/integrity, not application behavior.

Changed error behavior

trace --depth was removed because the old command ignored it. Use context --depth for an actually bounded multi-hop neighborhood.

MCP and imports

MCP offers structured output plus text fallback, bounded context/impact queries, input validation, paging and standard protocol errors. Use an explicit project when several are available. listProjects reports invalid projects separately rather than serving their corrupt contents. Deleted graphs are evicted from the current server view.

Legacy initialization revisions and modern 2026-07-28 discovery/per-request metadata are supported. Modern clients must supply protocol version and client capabilities in _meta; unsupported versions are rejected. Local stdio remains the only server transport. Live infrastructure verification remains an explicit operation.

graph import --format rea-callgraph accepts a saved REA NativeCallGraph body. Supply --rea-direction forward or --rea-direction backward matching the original producer request: the bare export omits direction, so guessing could reverse call edges. Regenerate earlier imports whose direction was not recorded. This is not a general-purpose Ghidra loader or REA Evidence-envelope parser. Evidence addresses, coverage and limitations are retained. A supplied binary SHA-256 scopes identities to that binary; otherwise the export digest scopes them and binary identity is unknown. Dotdog never invokes or reconfigures REA/Ghidra.

Path/context/impact/traverse results retain supplied graph coverage and limitations; absent coverage is reported as unknown. A bounded no_path is not proof that two procedures are independent. Inspect maxHops and truncated. MCP traverse keeps legacy node name/edges fields and adds full node identity/provenance. Token-budget failures report budget_too_small rather than returning an oversized or scope-free successful result.

Workspace manifests now validate nested shape before registry construction. Optional properties must be omitted or have their declared type; explicit null/undefined is not omission. Invalid manifests report validation errors instead of TypeError. The internal parser exposes typed data only on success; the existing validation JSON shape is unchanged.

Ambiguous MCP context candidates now contain exact node IDs rather than repeated display labels. Context/impact/traverse report truncated: true when candidate IDs are omitted. Claude hook installation refuses malformed settings/hook collections before changing settings or registering ownership; repair the existing file rather than replacing unrelated configuration.

Interpretation limits

Repository extraction covers inventory plus JS/TS top-level declarations and static relative imports/re-exports. Alias resolution, dynamic calls, whole-program behavior and non-JS/TS symbol extraction remain unverified. Git ignore rules are honored when a Git root is present. Scan/read errors fail rather than justify deleting an unseen suffix.

analyze remains a heuristic helper. staleness, simulate, and verify are deprecated aliases for read-only status, scenario-check, and reference-check. status detects stale or absent outputs; scenario/reference diagnostics do not independently establish graph freshness. Invalid or unmatched diagnostics return nonzero. Reference mappings prefer an exact entity ID and reject ambiguous labels; both diagnostics use the shared 32 MiB graph input limit. verify --init is retired; author explicit mappings instead. These commands do not prove application correctness. Search is lexical TF-IDF, not an embedding model. Compile-time token figures use a byte-based estimate; context token budgets use the declared tokenizer/encoding and exclude host framing. Savings vary and can be negative when retained metadata exceeds the source size.

Security and provider changes

Path endpoint matching no longer treats an empty ASCII-word query as a match for every node. Exact IDs/labels and genuine substring matches remain usable, including Unicode. Ambiguous path results now return at most 100 exact candidate IDs rather than labels; truncated reports a cut candidate list as well as a bounded search. Absolute origin file paths are omitted using both POSIX and Windows path rules, independent of the current host. This is not general redaction of arbitrary graph properties or evidence.

Generated destinations reject symlinks; Git inventory cannot follow redirected directories outside the repository. Hook ownership metadata must match the expected installation, not arbitrary file/hash claims. MCP lines are capped at 1 MiB and graph inputs at 32 MiB. Regenerate graphs after upgrading.

Provider verification no longer launches guessed MCP tools or unauthenticated remote MCP sessions. Cloudflare requires both CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID; D1/KV mappings use IDs. Railway uses service:<service-id>, RAILWAY_API_TOKEN for account/workspace tokens or RAILWAY_TOKEN for project tokens. Supabase project checks do not claim table validation. Strict live --exit-code fails for skipped/warning infrastructure checks. Endpoint JSON contracts now compare nested values/types, not merely field presence; redirects are rejected and response bodies/timeouts are bounded.

graph audit adds recorded-evidence identity/freshness checks and an optional advisory embodied coverage profile. See security audit and embodied evidence. Legacy @spec/* packages, the unwired keyword scanner, duplicate version script, scratch parser dumps and invalid historical-log benchmark harness were removed; none was in the published npm package.

Generated writes now replace complete files atomically and preserve existing file permissions. Refresh, map and compile serialize cooperating writers with .doghouse/refresh.lock. A killed process can be recovered on the next invocation; malformed/foreign-host locks and interrupted acquisition guards require inspection rather than automatic deletion. Contention returns nonzero with a retry message.