fairlead 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +129 -25
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 (2026-09-26)
|
|
4
|
+
|
|
5
|
+
### New
|
|
6
|
+
|
|
7
|
+
- Edges the imports don't show: `[[graph.edges]]` makes each file matching `from` depend on the files its `to` globs match, and the planner follows the edge like an import. It fits a test that reaches its code over HTTP instead of importing it. A `{name}` is read from the side where it's a whole path segment, so `{area}{,-*}.test.ts` still picks up `orders-refunds.test.ts`, and `config check` refuses a rule that would silently match the wrong files. See [Import graph](https://mahkassem.github.io/fairlead/docs/graph.html#edges-the-imports-dont-show).
|
|
8
|
+
- A walk barrier: `graph.barrier` names files the planner reaches but doesn't go past, such as a server module that every area imports and that imports every area. A changed barrier file is left to `tests.unreached` unless `plan.run_all` covers it. `graph why` and `test --explain` say where a barrier stopped the walk, and `graph stats` counts rule edges and barrier files. See [Barriers](https://mahkassem.github.io/fairlead/docs/graph.html#barriers).
|
|
9
|
+
- Replay reads `bun test` output: `extractor = "bun"` attributes each `(fail)` line to the file header above it, including bun's interleaved parallel output and several bun runs in one job, and never takes a failure from bun's closing summary. The dataset keeps those lines. See [Replay](https://mahkassem.github.io/fairlead/docs/replay.html).
|
|
10
|
+
|
|
11
|
+
### Known gaps
|
|
12
|
+
|
|
13
|
+
- A bun test file that fails to load prints no `(fail)` line, so replay can't attribute it yet ([#68](https://github.com/mahkassem/fairlead/issues/68)).
|
|
14
|
+
- A captured path segment that looks like glob syntax, such as `[slug]`, is re-read as a glob when filled into another pattern ([#69](https://github.com/mahkassem/fairlead/issues/69)).
|
|
15
|
+
|
|
16
|
+
## 0.2.0 (2026-09-26)
|
|
17
|
+
|
|
18
|
+
### New
|
|
19
|
+
|
|
20
|
+
- `fairlead plan` lists the tests and checks the changes since a base commit can reach, and why each one is in. It builds an import graph of JavaScript and TypeScript from source, with no install, following tsconfig paths and workspace packages, and caches parsed files by git blob. It adds owner rules, test classes (`unit`, `own`, `demand`, `canary`), checks, and a run-everything fallback for anything it can't read with certainty. The plan is JSON with a published schema. See [Test plan](https://mahkassem.github.io/fairlead/docs/plan.html).
|
|
21
|
+
- `fairlead test --explain` says why a test or check is in the plan, or why it isn't.
|
|
22
|
+
- `fairlead ci plan` plans the checked-out commit and, with `--format github`, sets step outputs. `fairlead ci run --plan` runs the plan's invocations. The GitHub Action installs Fairlead and runs any command. See [Plans in CI](https://mahkassem.github.io/fairlead/docs/ci.html).
|
|
23
|
+
- `fairlead graph stats`, `why` and `importers` inspect the import graph.
|
|
24
|
+
- `fairlead replay fetch` records a repository's pull request and merge queue runs from GitHub. `fairlead replay run` re-plans every recorded failure and reports recall: each failure is a hit, a miss, flaky, unconfirmed, or quarantined. `[[replay.quarantine]]` declares a test flaky in named jobs, with evidence and an expiry, and applies only while the data bears it out. See [Replay](https://mahkassem.github.io/fairlead/docs/replay.html).
|
|
25
|
+
- Opt-in lockfile scoping (`plan.lockfile = "scope"`): a pnpm lockfile change runs only the packages whose resolved dependencies changed.
|
|
26
|
+
- An owner rule can take a run-all path it covers (`overrides_run_all`), such as a fixture project's runner config.
|
|
27
|
+
- Weekly public benchmarks on Effect, pnpm and vitest, published on the [benchmarks page](https://mahkassem.github.io/fairlead/docs/benchmarks.html).
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- The minimum Rust version for building from source is 1.90.
|
|
32
|
+
- The site has a front page, and the documentation moved to [/docs/](https://mahkassem.github.io/fairlead/docs/). Old page addresses redirect.
|
|
33
|
+
- Fairlead has a brand: the logo and its colors are in `assets/brand`.
|
|
34
|
+
|
|
35
|
+
### Recall
|
|
36
|
+
|
|
37
|
+
Replayed from each project's CI history (run 5 of the weekly benchmarks, planned at `8c1b179d44cc`). Adjusted recall leaves out tests quarantined with evidence; raw counts them.
|
|
38
|
+
|
|
39
|
+
| Repository | Window | Adjusted recall | Raw recall | Misses |
|
|
40
|
+
| --- | --- | --- | --- | --- |
|
|
41
|
+
| Effect-TS/effect | 2026-05-09 to 2026-08-06 | 98.8% (n=853) | 98.0% (n=890) | 10 |
|
|
42
|
+
| pnpm/pnpm | 2026-04-25 to 2026-07-23 | 99.4% (n=312) | 99.4% (n=312) | 2 |
|
|
43
|
+
| vitest-dev/vitest | 2026-06-13 to 2026-09-10 | 95.6% (n=528) | 93.6% (n=627) | 23 |
|
|
44
|
+
|
|
45
|
+
Selection is recorded, not yet a gate: the median plan still selects most test files (Effect 98.6%, pnpm 100.0%, vitest 98.7%), and 31.7%, 84.8% and 34.9% of plans ran everything, mostly for CI config, lockfile and `package.json` changes. Narrowing that is the next milestone's work.
|
|
46
|
+
|
|
47
|
+
A full graph build without the parse cache takes 1.19 s on Effect, 1.02 s on pnpm and 0.41 s on vitest on 4 cores, under the 1.5 s budget, which CI checks on every pull request ([Import graph](https://mahkassem.github.io/fairlead/docs/graph.html#speed)). That's with the files already in the operating system's cache; a first read from a cold disk takes longer.
|
|
48
|
+
|
|
49
|
+
Quarantined, each until 2026-12-31 and applied only while the data bears it out:
|
|
50
|
+
|
|
51
|
+
- Effect `packages/sql/mysql2/test/Persistence.test.ts` in the first test shard: times out after 30 s waiting on MySQL on changes that touch neither; 21 failures across 19 pull requests.
|
|
52
|
+
- Effect `packages/sql/mysql2/test/KeyValueStore.test.ts` in the second test shard: its setup hook times out waiting on MySQL; 9 failures across 9 pull requests.
|
|
53
|
+
- Effect `packages/sql/d1/test/Resolver.test.ts` in the second Node shard: times out after 5 s against the local D1 engine; 7 failures across 7 pull requests.
|
|
54
|
+
- vitest `test/typescript/test/typechecker.test.ts` in the Windows unit job only: out-of-memory crashes and missing-command cases. It was declared on 60 failures across 36 pull requests, while the same job passed 356 times, and has absorbed 100 failures across 54 pull requests.
|
|
55
|
+
|
|
56
|
+
Every miss, with its cause:
|
|
57
|
+
|
|
58
|
+
- Effect, 10: database and service tests failing together on unrelated changes (`sql-libsql` Client 3, `platform-node` NodeRedis 1, SqlRunnerStorage 1, `sql-pg` Client 1 on a LISTEN notification timeout, `sql-libsql` Resolver 1 on a 5 s timeout); `toArbitrary.test.ts` 1, a property test that failed after 8 random cases; `openapi-generator` 2, a native module error (`Failed to recover TsconfigCache type from napi value`) under Deno on a change to `platform-deno`.
|
|
59
|
+
- pnpm, 2: `releasing/commands/test/change/index.test.ts` on Linux and Windows, a missing `CHANGELOG.md` fixture, on a pull request that only edited a test helper in another package.
|
|
60
|
+
- vitest, 23: headless browser specs 14 (`runner.test.ts` 9, fixtures failing inside it: a 249 ms locator click timeout in 5, a CDP events test in 3 (both recurring across unrelated pull requests) and a WebKit clipboard test on Windows in 1; `trace.test.ts`, `bail-out.test.ts`, `locators.test.ts`, `server-url.test.ts` and `to-match-screenshot.test.ts` 1 each, timing and Windows snapshot mismatches); `detect-async-leaks.test.ts` 6, the same leak assertion across unrelated pull requests and bases; `list.test.ts` and `open-telemetry.test.ts` 2, a browser that didn't close within 10 s; `coverage-test/reporters.test.ts` 1, a 15 s timeout on Windows.
|
|
61
|
+
|
|
62
|
+
The bar we set for this release was 100% recall on failures a change could have caused. By our reading of the logs, none of these misses is one, but that's a judgement, not a measurement: literal 100% recall wasn't reached on any repository, and the misses above are the whole list.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- Replay waits out GitHub's secondary rate limit instead of stopping, and asks once per lookup.
|
|
67
|
+
|
|
3
68
|
## 0.1.1 (2026-09-26)
|
|
4
69
|
|
|
5
70
|
### New
|
package/README.md
CHANGED
|
@@ -1,36 +1,123 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/mahkassem/fairlead/main/assets/brand/fairlead-reversed-horizontal-dark.svg">
|
|
4
|
+
<img alt="Fairlead" src="https://raw.githubusercontent.com/mahkassem/fairlead/main/assets/brand/fairlead-primary-horizontal-light.svg" width="360">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
2
7
|
|
|
3
|
-
Guardrails and a guided path for coding agents
|
|
8
|
+
<p align="center"><strong>Guardrails and a guided path for coding agents.</strong></p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://github.com/mahkassem/fairlead/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/mahkassem/fairlead/actions/workflows/ci.yml/badge.svg"></a>
|
|
12
|
+
<a href="https://github.com/mahkassem/fairlead/releases/latest"><img alt="Latest release" src="https://img.shields.io/github/v/release/mahkassem/fairlead?color=008F67"></a>
|
|
13
|
+
<a href="https://mahkassem.github.io/fairlead/docs/"><img alt="Docs" src="https://img.shields.io/badge/docs-book-0B1618"></a>
|
|
14
|
+
</p>
|
|
4
15
|
|
|
5
16
|
A fairlead is the fitting on a boat that keeps a line running true, so it
|
|
6
17
|
doesn't chafe, tangle or pull off course. Fairlead does that for an agent
|
|
7
|
-
working in your repository
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
working in your repository. It is one Rust binary with no project-specific
|
|
19
|
+
logic: everything about your repository lives in your own `fairlead.toml`.
|
|
20
|
+
|
|
21
|
+
## Why Fairlead
|
|
22
|
+
|
|
23
|
+
Join a good team and you don't start from zero. Someone tells you which module
|
|
24
|
+
never to touch without running the migration check first, which test lies on
|
|
25
|
+
Windows, and which "quick fix" broke production last spring. That knowledge is
|
|
26
|
+
why a new engineer is useful in week two instead of month six.
|
|
27
|
+
|
|
28
|
+
A coding agent gets none of it. It opens your repository cold every time,
|
|
29
|
+
reads the same code again, makes the mistake your team already paid for, and
|
|
30
|
+
finds out in CI that it was an old lesson nobody told it. Fairlead gives every
|
|
31
|
+
repository its own memory, so your agent starts where your team left off instead
|
|
32
|
+
of trying things like a stranger.
|
|
33
|
+
|
|
34
|
+
- **A memory for every repository.** The hard lessons from past work live with
|
|
35
|
+
the code, per module, where the agent meets them before it acts. A lesson is
|
|
36
|
+
kept short, reviewed on a date, and turned into a check when it can be, so
|
|
37
|
+
the memory stays true instead of growing into noise.
|
|
38
|
+
*Today:* owner rules record which tests guard which code, and a quarantined
|
|
39
|
+
test applies only while the evidence holds and until its date.
|
|
40
|
+
- **Set up once, never start cold.** The agent's first job is to learn
|
|
41
|
+
the repository: its modules, test runners, rules, and the commands that prove
|
|
42
|
+
a change is right. That goes into one checked config, so every session starts
|
|
43
|
+
where the last one left off.
|
|
44
|
+
*Today:* `fairlead config check` validates every layer, and `show --origin`
|
|
45
|
+
says where each value came from.
|
|
46
|
+
- **The right tool, not the nearest one.** The agent asks what applies to the
|
|
47
|
+
files in front of it and gets the rule, the command and the next step for
|
|
48
|
+
exactly those files.
|
|
49
|
+
*Today:* `fairlead plan` names the tests and checks a change can reach, and
|
|
50
|
+
`test --explain` says why each one is in or out.
|
|
51
|
+
- **Plans the change, not just the tests.** Before an edit, the agent sees
|
|
52
|
+
what it's about to touch, everything that depends on it, the rules and
|
|
53
|
+
lessons recorded there, and what has to pass before it's done. Afterwards,
|
|
54
|
+
what actually changed is checked against that brief.
|
|
55
|
+
*Coming in K3* ([#45](https://github.com/mahkassem/fairlead/issues/45)).
|
|
56
|
+
- **The right skills for the code in front of it.** A frontend change
|
|
57
|
+
shouldn't come with database advice. Fairlead picks the skills that apply to
|
|
58
|
+
what a change reaches, just as it picks tests, and checks the agent used them.
|
|
59
|
+
*Coming in K4* ([#43](https://github.com/mahkassem/fairlead/issues/43)).
|
|
60
|
+
- **Measured, not guessed.** Good and bad are numbers: whether the plan would
|
|
61
|
+
have caught real CI failures, rework, escaped defects, tokens and cost.
|
|
62
|
+
*Today:* `fairlead replay` re-plans real failures from a repository's CI
|
|
63
|
+
history, and the [benchmarks](https://mahkassem.github.io/fairlead/docs/benchmarks.html)
|
|
64
|
+
measure that recall every week.
|
|
65
|
+
- **Fast because it remembers.** No rereading the codebase to rediscover what
|
|
66
|
+
was learned last week. The graph, the plan and the lessons are already there.
|
|
67
|
+
*Today:* the import graph is built without installing dependencies and
|
|
68
|
+
cached between runs.
|
|
69
|
+
- **It learns where it's blind.** When a change reaches no test, Fairlead says
|
|
70
|
+
so and points at the rule that's missing, so the team's knowledge grows
|
|
71
|
+
exactly where it was thin.
|
|
72
|
+
*Today:* `fairlead plan` lists every file no test depends on, and replay
|
|
73
|
+
suggests the owner rule or check path that would have caught a miss.
|
|
74
|
+
- **Stopped before the mistake, not after.** Your rules run as the agent
|
|
75
|
+
works, catching a wrong move in seconds instead of minutes later in CI.
|
|
76
|
+
*Coming in K2.*
|
|
77
|
+
|
|
78
|
+
## Works with
|
|
79
|
+
|
|
80
|
+
- **Any test runner.** Vitest, Jest, Playwright, `node --test`, Bun: a runner is
|
|
81
|
+
one command in your config, so Fairlead never needs a plugin for your stack.
|
|
82
|
+
- **Monorepos, precisely.** pnpm, npm, yarn and bun workspaces. A pnpm lockfile
|
|
83
|
+
change runs only the packages whose dependencies actually changed.
|
|
84
|
+
- **No install needed to read your code.** The JavaScript and TypeScript import
|
|
85
|
+
graph comes from source alone, with tsconfig paths resolved and parsed files
|
|
86
|
+
cached, so a plan takes a fraction of a second.
|
|
87
|
+
- **Your CI, not a new one.** A GitHub Action and `ci plan --format github` for
|
|
88
|
+
Actions, and a JSON plan with a published schema for any other CI.
|
|
89
|
+
- **Proven on real projects.** Recall is replayed from the CI history of Effect,
|
|
90
|
+
pnpm and vitest every week, and published.
|
|
91
|
+
- **Private by default.** The CLI sends nothing you didn't ask for: no
|
|
92
|
+
telemetry, and it never phones home.
|
|
93
|
+
- **One binary, everywhere.** Linux, macOS and Windows, installed with a shell
|
|
94
|
+
script, PowerShell or npm.
|
|
95
|
+
|
|
96
|
+
*It reads JavaScript and TypeScript today. More languages, framework packs and
|
|
97
|
+
folders of several repositories are on the way
|
|
98
|
+
([#47](https://github.com/mahkassem/fairlead/issues/47)); Vue, Svelte and Astro
|
|
99
|
+
files fall back to broader test selection until then.*
|
|
100
|
+
|
|
101
|
+
## What it does today
|
|
102
|
+
|
|
103
|
+
The test plan (`plan`, `test --explain`), plans in CI (`ci plan`, `ci run` and
|
|
104
|
+
the GitHub Action), `replay`, the import graph (`graph`), and the config
|
|
105
|
+
commands. The [quick start](#quick-start) shows them, and the
|
|
106
|
+
[book](https://mahkassem.github.io/fairlead/docs/) covers each one.
|
|
23
107
|
|
|
24
108
|
## Status
|
|
25
109
|
|
|
26
|
-
Pre-alpha.
|
|
27
|
-
|
|
28
|
-
|
|
110
|
+
Pre-alpha. The latest release, v0.3.0, adds edges the imports don't show, a
|
|
111
|
+
walk barrier, and replay of bun test output to v0.2.0's test plan, CI commands
|
|
112
|
+
and action, replay, and config commands. Recall on real CI failures, with every
|
|
113
|
+
miss and its cause, is in the [changelog](CHANGELOG.md) and on the
|
|
114
|
+
[benchmarks page](https://mahkassem.github.io/fairlead/docs/benchmarks.html).
|
|
115
|
+
Claude Code comes first, then Codex. The [roadmap](https://mahkassem.github.io/fairlead/docs/roadmap.html)
|
|
116
|
+
has milestones K0 to K6, each an [issue](https://github.com/mahkassem/fairlead/issues)
|
|
117
|
+
with its exit criteria.
|
|
29
118
|
|
|
30
119
|
## Install
|
|
31
120
|
|
|
32
|
-
Once the first release is published:
|
|
33
|
-
|
|
34
121
|
```sh
|
|
35
122
|
# macOS and Linux
|
|
36
123
|
curl -fsSL https://github.com/mahkassem/fairlead/releases/latest/download/fairlead-installer.sh | sh
|
|
@@ -38,13 +125,30 @@ curl -fsSL https://github.com/mahkassem/fairlead/releases/latest/download/fairle
|
|
|
38
125
|
# Windows (PowerShell)
|
|
39
126
|
powershell -c "irm https://github.com/mahkassem/fairlead/releases/latest/download/fairlead-installer.ps1 | iex"
|
|
40
127
|
|
|
41
|
-
# In a JavaScript or TypeScript project
|
|
128
|
+
# In a JavaScript or TypeScript project, as a dev dependency
|
|
42
129
|
bun add -d fairlead # or: npm i -D fairlead
|
|
43
130
|
```
|
|
44
131
|
|
|
132
|
+
Then `fairlead doctor` says which binary, platform and config it would use.
|
|
133
|
+
|
|
134
|
+
## Quick start
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
fairlead config check # validate fairlead.toml
|
|
138
|
+
fairlead plan --base main # the tests and checks this branch can affect
|
|
139
|
+
fairlead test --explain src/a.test.ts # why that test is in the plan, or isn't
|
|
140
|
+
fairlead graph why src/a.test.ts src/util.ts # how one file depends on another
|
|
141
|
+
```
|
|
142
|
+
|
|
45
143
|
## Documentation
|
|
46
144
|
|
|
47
|
-
The
|
|
145
|
+
The site is [mahkassem.github.io/fairlead](https://mahkassem.github.io/fairlead/), and [the book](https://mahkassem.github.io/fairlead/docs/) covers
|
|
146
|
+
install, configuration, the import graph, the test plan, plans in CI, replay
|
|
147
|
+
and the benchmarks. Its source is in `docs/`.
|
|
148
|
+
|
|
149
|
+
## Brand
|
|
150
|
+
|
|
151
|
+
The logo, its colors and how to use them are in [`assets/brand`](assets/brand).
|
|
48
152
|
|
|
49
153
|
## License
|
|
50
154
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"hasInstallScript": true,
|
|
20
20
|
"license": "MIT OR Apache-2.0",
|
|
21
21
|
"name": "fairlead",
|
|
22
|
-
"version": "0.
|
|
22
|
+
"version": "0.3.0"
|
|
23
23
|
},
|
|
24
24
|
"node_modules/detect-libc": {
|
|
25
25
|
"engines": {
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"requires": true,
|
|
51
|
-
"version": "0.
|
|
51
|
+
"version": "0.3.0"
|
|
52
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"artifactDownloadUrls": [
|
|
3
|
-
"https://github.com/mahkassem/fairlead/releases/download/v0.
|
|
3
|
+
"https://github.com/mahkassem/fairlead/releases/download/v0.3.0"
|
|
4
4
|
],
|
|
5
5
|
"bin": {
|
|
6
6
|
"fairlead": "run-fairlead.js"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"zipExt": ".tar.xz"
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
|
-
"version": "0.
|
|
93
|
+
"version": "0.3.0",
|
|
94
94
|
"volta": {
|
|
95
95
|
"node": "18.14.1",
|
|
96
96
|
"npm": "9.5.0"
|