Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 18 additions & 0 deletions .claude/skills/drift/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ origin = "github:your-org/your-repo"
sig = "a1b2c3d4e5f6a7b8"
```

A consumer repo with a local checkout of the origin repo can map it and have those anchors actually checked instead of skipped — against the sibling checkout's files, with blame from its history:

```bash
drift check --repo github:your-org/your-repo=../your-repo
```

Or persistently in `.drift/config.toml` (flag wins over config for the same origin):

```toml
version = 1

[[repos]]
origin = "github:your-org/your-repo"
path = "../your-repo"
```

If a mapped path doesn't exist on disk, the anchor is skipped with reason `mapped repo missing` rather than failing the check.

## Staleness

`drift check` reads bindings from `drift.lock` and exits 1 if any anchor is stale or markdown link is broken. Use `drift check --changed <path>` to scope checking to affected docs — useful in CI when you know which files changed. For supported languages (TypeScript-family files including TS/TSX/JS/JSX, Python, Rust, Go, Zig, Java), comparison is syntax-aware — formatting-only changes won’t trigger staleness. For changed anchors, stale reports include best-effort git context for the target file (author, commit, committer date, subject) so you can see what changed.
Expand Down
20 changes: 19 additions & 1 deletion docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Check all docs for staleness. The primary command. Exits 1 if any anchor is stale or any link is broken. `drift lint` is an alias. Markdown files under directories with their own `drift.lock` are skipped — they belong to a nested scope.

```
drift check [--format text|json] [--changed <path>] [--silent]
drift check [--format text|json] [--changed <path>] [--silent] [--repo <origin>=<path>]...
```

Reads bindings from `drift.lock`, recomputes content signatures for each target, and compares against the stored `sig` values. Reports stale anchors with reasons.
Expand Down Expand Up @@ -47,6 +47,24 @@ vendor/shared-skill.md

Anchors with an `origin` field that doesn't match the current repo are skipped — they reference files in a different repository.

The `--repo <origin>=<path>` flag (repeatable) maps a foreign origin to a local checkout so those anchors are checked instead of skipped. The origin must be in the normalized `github:owner/repo` form; the path is the checkout's root directory, resolved relative to the current working directory. Fingerprints and blame for mapped anchors compute against the mapped checkout. If the mapped directory does not exist on disk the anchors are skipped with reason `mapped_repo_missing` rather than reported stale, so a teammate without the sibling checkout is not broken.

```
$ drift check --repo github:acme/server=../server
```

The same mappings can live in `.drift/config.toml` as `[[repos]]` tables, so they don't have to be repeated on every invocation:

```toml
version = 1

[[repos]]
origin = "github:acme/server"
path = "../server"
```

Config paths resolve against the lockfile root (checkout-location-independent), while `--repo` paths resolve against the current working directory. When a flag and a config entry map the same origin, the flag wins.

## drift status

Show all docs and their anchors without checking staleness. Reads bindings from `drift.lock`.
Expand Down
6 changes: 6 additions & 0 deletions docs/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,9 @@ We use tree-sitter for link extraction rather than regex because:
- Tree-sitter markdown's `section` node provides heading-to-body grouping, which regex cannot reliably determine

The two-parser architecture requires two passes per file: block grammar first (producing `inline` node ranges), then inline grammar on those ranges. This adds build complexity (two grammar C sources, two `ts.Language` instances) but is how the grammar is designed — block and inline are separate grammars with separate node types.

## 15. Repo mappings merge with CLI-wins precedence

Foreign-origin checkout mappings come from two sources: repeated `--repo <origin>=<path>` flags and `[[repos]]` tables in `.drift/config.toml`. Both feed one merged map; when both define the same origin, the flag entry wins. This follows the usual configuration layering rule — the most explicit, most recent instruction (typed on the command line for this run) overrides the persistent default (checked into config) — and makes one-off experiments cheap: point an origin at a scratch checkout without editing shared config.

Path resolution differs by source on purpose. Config paths resolve against the lockfile root so a committed mapping like `path = "../server"` works for every teammate regardless of where the repo is cloned or which subdirectory `drift check` runs from. Flag paths resolve against the cwd, matching how every other command-line path argument behaves.
25 changes: 14 additions & 11 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,20 +249,23 @@ Format rules:
- Lines starting with `#` are comments, blank lines ignored; inline comments and general TOML tables are outside the lockfile subset
- Discovery: walk up from cwd until `drift.lock` is found

### .drift/config.yaml
### .drift/config.toml

Optional project-level settings. The `.drift/` directory exists only for configuration (scan globs, VCS backend override, etc.).

```yaml
# .drift/config.yaml (optional)
scan:
include:
- "docs/**/*.md"
- "*.md"
exclude:
- "node_modules/**"
- "vendor/**"
vcs: auto # auto | git | jj
The config reuses the lockfile's TOML subset: a mandatory `version = 1` header, `[[array-of-tables]]` blocks, bare keys, and single-line basic strings with the same escapes. Blank lines and full-line `#` comments are ignored; unknown keys or tables are hard errors with a line number, matching lockfile strictness.

```toml
# .drift/config.toml (optional)
version = 1

[[repos]]
origin = "github:acme/server"
path = "../server"
```

Each `[[repos]]` table maps a foreign binding origin to a local checkout, with exactly two keys: `origin` (normalized `github:owner/repo` form, same validation as `--repo` flag specs) and `path` (the checkout's root directory). Relative paths resolve against the lockfile root — not the cwd — so the mapping works no matter where in the checkout `drift check` runs. Unknown keys inside `[[repos]]` are hard errors.

`--repo` flags and `[[repos]]` entries feed the same origin map; when both define the same origin, the CLI flag wins. Flag paths resolve against the cwd, as usual for command-line paths.

If no config exists, drift scans all `*.md` and `**/*.md` files and auto-detects the VCS.
3 changes: 2 additions & 1 deletion docs/check-json-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ Each entry represents a relative markdown link extracted from the doc via tree-s
| `symbol_not_found` | A `file#Symbol` anchor's symbol is no longer present. |
| `fingerprint_unavailable` | A `@sig:` anchor could not be re-fingerprinted (e.g. unknown language). |
| `baseline_unavailable` | Reserved — historical baseline could not be retrieved. (Not currently emitted; held for forward compatibility.) |
| `origin_mismatch` | The doc's `origin:` does not match the current repo identity. Anchors are skipped. |
| `origin_mismatch` | The doc's `origin:` does not match the current repo identity and no `--repo` mapping covers it. Anchors are skipped. |
| `mapped_repo_missing` | A `--repo` mapping covers the origin but the mapped directory does not exist on disk. Anchors are skipped. |
| `link_target_not_found` | A plain markdown link in the doc points to a file that doesn't exist. |

`reason.message` strings are stable in `v1` and asserted by tests. Changing one is a
Expand Down
10 changes: 5 additions & 5 deletions drift.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = 1
doc = ".claude/skills/drift/SKILL.md"
target = "src/main.zig"
origin = "github:fiberplane/drift"
sig = "3faa73e2bb344a79"
sig = "94225f5ed5a3ca5b"

[[bindings]]
doc = ".claude/skills/drift/SKILL.md"
Expand All @@ -20,7 +20,7 @@ sig = "2dccb33f6b790afa"
[[bindings]]
doc = "CLAUDE.md"
target = "src/main.zig"
sig = "3faa73e2bb344a79"
sig = "94225f5ed5a3ca5b"

[[bindings]]
doc = "docs/CLI.md"
Expand All @@ -30,7 +30,7 @@ sig = "3ae8f4ee2c85d8d8"
[[bindings]]
doc = "docs/CLI.md"
target = "src/commands/lint.zig"
sig = "fe7bd5a687f3e917"
sig = "3afc7404179936ee"

[[bindings]]
doc = "docs/CLI.md"
Expand All @@ -55,12 +55,12 @@ sig = "82d9da38ea486f36"
[[bindings]]
doc = "docs/DESIGN.md"
target = "src/lockfile.zig"
sig = "55bc77a2853cb654"
sig = "851c526f05362849"

[[bindings]]
doc = "docs/DESIGN.md"
target = "src/main.zig"
sig = "3faa73e2bb344a79"
sig = "94225f5ed5a3ca5b"

[[bindings]]
doc = "docs/DESIGN.md"
Expand Down
Loading
Loading