flagrm 0.1.1 → 0.2.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 +92 -0
- package/README.md +62 -21
- package/dist/adapters/dotnet/flow.js +429 -0
- package/dist/adapters/dotnet/index.js +2 -0
- package/dist/adapters/dotnet/setup.js +163 -0
- package/dist/cli.js +97 -19
- package/dist/core/baseline.js +140 -20
- package/dist/core/config-snapshot.js +183 -0
- package/dist/core/config.js +22 -1
- package/dist/core/doctor.js +37 -17
- package/dist/core/environment.js +79 -0
- package/dist/core/flag-words.js +36 -0
- package/dist/core/git.js +8 -0
- package/dist/core/hook.js +18 -8
- package/dist/core/install.js +128 -22
- package/dist/core/inventory.js +39 -0
- package/dist/core/markdown.js +16 -5
- package/dist/core/report.js +54 -11
- package/dist/core/scope.js +192 -0
- package/dist/core/tools.js +108 -0
- package/dist/core/types.js +7 -1
- package/dist/core/util.js +10 -0
- package/dist/core/verify/commands.js +127 -19
- package/dist/core/verify/context.js +9 -0
- package/dist/core/verify/deleted-text.js +180 -0
- package/dist/core/verify/index.js +3 -1
- package/dist/core/verify/leftovers.js +19 -2
- package/dist/core/verify/removed-tests.js +141 -0
- package/dist/core/verify/test-results.js +31 -6
- package/package.json +1 -1
- package/skills/flagrm-remove/SKILL.md +14 -14
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,97 @@ All notable changes to this project are documented here. The format follows
|
|
|
5
5
|
[Semantic Versioning](https://semver.org/). Before 1.0, a minor version may
|
|
6
6
|
contain breaking changes.
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-10-04
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Breaking:** JSON schema version 7. `baseline --json` prints a summary of
|
|
13
|
+
`baseline.json` instead of the whole file: each test run's results as
|
|
14
|
+
counts with at most 20 short failed test names (`failedTests`,
|
|
15
|
+
`moreFailedTests`), and no `config` snapshot. On a large suite the full
|
|
16
|
+
output was megabytes. `baseline.json` is unchanged, and version 6 files are
|
|
17
|
+
still read.
|
|
18
|
+
- The Stop hook only blocks once the removal has edited a file git tracks
|
|
19
|
+
(other than `flagrm.config.yaml`), or the last verify used `--skip`. A
|
|
20
|
+
removal paused on a question to the user, a config fix or an untracked
|
|
21
|
+
file such as a stray test result no longer blocks.
|
|
22
|
+
- `verify`'s `tests[]` reports `failed` and the short names of `newFailures`
|
|
23
|
+
and `knownFailures` per project.
|
|
24
|
+
- `verify` no longer fails the `tests` check when every failing test already
|
|
25
|
+
failed at the baseline: those are reported as known failures and only warn.
|
|
26
|
+
Only new failures fail it, and they are listed. Test names are compared
|
|
27
|
+
without xUnit data-row arguments. Needs `testResults`.
|
|
28
|
+
- `baseline --force` refuses to replace a baseline once the code has changed
|
|
29
|
+
since its commit (`.flagrm/`, `flagrm.config.yaml` and files matching
|
|
30
|
+
`testResults` don't count), so a
|
|
31
|
+
rerun after fixing the setup can't record a half-done removal. The error
|
|
32
|
+
says how to set uncommitted edits aside with `git stash`.
|
|
33
|
+
- Tests that no longer run are sorted by why (`tests[]` in `verify --json`):
|
|
34
|
+
`deleted` (gone from a changed test file, or a data row dropped from one),
|
|
35
|
+
`renamed` (the same test without the flag's words in its name, matched to
|
|
36
|
+
the new test), `excludedByConfig` (the test command or its files changed
|
|
37
|
+
since the baseline) and `unexplained`. Only `unexplained` tests warn; the
|
|
38
|
+
summary counts the others, and `--md` lists each group.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- `flagrm init` asks which AI coding tools to set up (Claude Code, GitHub
|
|
43
|
+
Copilot, Codex), pre-selecting the ones the repository already uses
|
|
44
|
+
(`.claude/`, `.github/copilot-instructions.md` or skills, `AGENTS.md`), and
|
|
45
|
+
installs only their files. `--tool claude-code,codex` chooses without
|
|
46
|
+
asking; without a terminal, the detected tools (all when none) are set up.
|
|
47
|
+
The choice is saved as `tools:` in `flagrm.config.yaml`, which a later
|
|
48
|
+
`init` and `update` follow; files of a tool dropped from it are left in
|
|
49
|
+
place and named. Copilot also gets `/flagrm-remove` and `/flagrm-verify`
|
|
50
|
+
prompt files in `.github/prompts/`. `doctor` checks only those tools.
|
|
51
|
+
- `flagrm scope`: for each .NET project, checks the machine (the SDK
|
|
52
|
+
`global.json` asks for, with `rollForward`; `cargo` where a project's build
|
|
53
|
+
runs it; Docker where a test project uses Testcontainers) and shows which
|
|
54
|
+
projects a solution filter would leave out: those and every project that
|
|
55
|
+
references them. `--write` creates `flagrm.slnf`, adds it to
|
|
56
|
+
`.git/info/exclude` and points the project's build and test at it, editing
|
|
57
|
+
`flagrm.config.yaml` in place. When the commands already name a solution
|
|
58
|
+
filter, `flagrm.slnf` keeps only its projects; a command that names a
|
|
59
|
+
project file is left alone. `doctor` (and so `init`) reports the same
|
|
60
|
+
problems: a missing SDK fails, a missing `cargo` or Docker warns.
|
|
61
|
+
- README: leave a locale-dependent test out with `--filter` rather than
|
|
62
|
+
forcing `LC_ALL` for the whole run.
|
|
63
|
+
- `verify` warns in `leftovers` about tests of the OFF path that never name
|
|
64
|
+
the flag: a test that still checks a string literal the removal deleted
|
|
65
|
+
from the code (and that no other code still has). When a test checked the
|
|
66
|
+
deleted text but none checks the text kept on the same line, it warns
|
|
67
|
+
that the ON path lost its test coverage.
|
|
68
|
+
- .NET discovery follows a flag's value: bool locals, fields and properties
|
|
69
|
+
assigned `IsEnabled(<flag>)`, methods that only return it (or a ternary on
|
|
70
|
+
it; static ones as `Class.Method`), and the bool parameters it is passed
|
|
71
|
+
to. `flagrm list` shows them as `flow`; `baseline` records as wrappers the
|
|
72
|
+
ones that clearly name the flag and lists the rest as `suggestedNames`. A
|
|
73
|
+
local, parameter or field (recorded with `file`) is only checked in its own
|
|
74
|
+
file; a method or property must contain the flag's whole name, or a flag
|
|
75
|
+
word with a digit. A parameter of one of several same-named methods, or a
|
|
76
|
+
method whose name another method shares, is only suggested. Test calls
|
|
77
|
+
passing `true`/`false` for such a parameter are listed as
|
|
78
|
+
`parameterizedTests`.
|
|
79
|
+
- `baseline --name X --file <path>` records `X` as a wrapper checked only in
|
|
80
|
+
that file.
|
|
81
|
+
- The baseline records its configuration (`config` in `baseline.json`): each
|
|
82
|
+
project's resolved build and test commands with a hash of the files they
|
|
83
|
+
name (`.slnf`, `.runsettings`, filter lists; not `.sln`/`.csproj`),
|
|
84
|
+
`testResults`, and the text of `flagrm.config.yaml`. `verify` warns when
|
|
85
|
+
they changed since: a command or named file in `build`/`tests`, any other
|
|
86
|
+
config change in `leftovers` with the changed lines.
|
|
87
|
+
- A failed build or test run whose log shows a machine setup problem gets
|
|
88
|
+
`failure: { kind: "environment", message }` in `baseline.json` and the
|
|
89
|
+
`verify`/`doctor` output: a .NET SDK that doesn't match `global.json`
|
|
90
|
+
(requested vs installed versions), a command a build step couldn't find
|
|
91
|
+
(and the project that runs it), or Docker not running for Testcontainers.
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
- Two projects whose `testResults` patterns overlap (`./**/TestResults/*.trx`)
|
|
96
|
+
no longer count each other's result files when their test runs follow each
|
|
97
|
+
other. Result files from earlier runs were already ignored.
|
|
98
|
+
|
|
8
99
|
## [0.1.1] - 2026-10-01
|
|
9
100
|
|
|
10
101
|
### Changed
|
|
@@ -44,5 +135,6 @@ removes the flag through the `flagrm-remove` skill, and flagrm checks the result
|
|
|
44
135
|
`doctor` warns about an incremental `dotnet build`, which hides existing
|
|
45
136
|
warnings from the dead-code comparison.
|
|
46
137
|
|
|
138
|
+
[0.2.0]: https://github.com/dino-cosic/flagrm/releases/tag/v0.2.0
|
|
47
139
|
[0.1.1]: https://github.com/dino-cosic/flagrm/releases/tag/v0.1.1
|
|
48
140
|
[0.1.0]: https://github.com/dino-cosic/flagrm/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ hook fails and does not guard the removal. `flagrm verify` still works.
|
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
39
|
npm install -D flagrm # or run everything with npx flagrm
|
|
40
|
-
npx flagrm init # config, skills, Stop hook, .gitignore entry
|
|
40
|
+
npx flagrm init # asks which AI tools; config, skills, Stop hook, .gitignore entry
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Fill in the project paths and the build and test commands in
|
|
@@ -54,7 +54,7 @@ When the agent reports back, review the result:
|
|
|
54
54
|
/flagrm-verify NewCheckout
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
You get a short overview (checks, changed files, tests
|
|
57
|
+
You get a short overview (checks, changed files, tests deleted or renamed) and
|
|
58
58
|
a proposed commit message. The agent never commits for you. The overview looks
|
|
59
59
|
like this (abridged):
|
|
60
60
|
|
|
@@ -66,31 +66,43 @@ like this (abridged):
|
|
|
66
66
|
| leftovers | ✅ pass | no recorded name left in code or config |
|
|
67
67
|
| dead-code | ✅ pass | no new unused-code diagnostics |
|
|
68
68
|
| build | ✅ pass | web, api built successfully |
|
|
69
|
-
| tests |
|
|
69
|
+
| tests | ✅ pass | tests passed (web 24 → 22: 2 deleted, 1 renamed; api 18 → 16: 2 deleted) |
|
|
70
70
|
|
|
71
71
|
**Files changed since baseline (26):** `backend/src/Shop.Api/Services/CheckoutService.cs`, ...
|
|
72
72
|
|
|
73
|
-
**Tests
|
|
73
|
+
**Tests deleted (4):** `LegacyPricingCalculatorTests.AppliesBulkDiscount`, ...
|
|
74
|
+
|
|
75
|
+
**Tests renamed (1):** `CheckoutComponent › places the order when NewCheckout is on` → `CheckoutComponent › places the order`
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
the
|
|
78
|
+
Tests that no longer run are sorted by why: deleted in the diff (the OFF
|
|
79
|
+
path's tests), renamed without the flag in the name, or left out by a test
|
|
80
|
+
command changed since the baseline. Only a test that no longer runs for none
|
|
81
|
+
of these reasons is a warning, for the agent to explain in its notes.
|
|
78
82
|
|
|
79
83
|
## How it works
|
|
80
84
|
|
|
81
|
-
1. **`flagrm init`**
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
a
|
|
85
|
-
|
|
85
|
+
1. **`flagrm init`** asks which AI coding tools to set up (Claude Code,
|
|
86
|
+
GitHub Copilot, Codex), with the ones the repository already uses
|
|
87
|
+
pre-selected; `--tool claude-code,codex` answers without asking, and
|
|
88
|
+
without a terminal it takes the detected tools (all three when none is).
|
|
89
|
+
It writes `flagrm.config.yaml` for the Angular and .NET projects it finds,
|
|
90
|
+
with the choice as `tools:`, and adds `.flagrm/` to `.gitignore`. Then per
|
|
91
|
+
tool: for Claude Code the `flagrm-remove` and `flagrm-verify` skills in
|
|
92
|
+
`.claude/skills/` and a Stop hook in `.claude/settings.json`; for Copilot
|
|
93
|
+
the skills in `.github/skills/` and `/flagrm-remove` and `/flagrm-verify`
|
|
94
|
+
prompt files in `.github/prompts/`; for Codex the skills in
|
|
95
|
+
`.agents/skills/` and a pointer in `AGENTS.md`.
|
|
86
96
|
2. **`/flagrm-remove <flag>`**: the agent checks that the tree is clean and runs
|
|
87
97
|
`flagrm baseline <flag>`, which records the git commit, the build and test
|
|
88
98
|
results, and the flag's names. It finds every usage with its own search,
|
|
89
99
|
records wrappers and aliases with `flagrm baseline <flag> --name`, removes
|
|
90
100
|
the flag, and repeats `flagrm verify <flag>` until it passes.
|
|
91
101
|
3. **The Stop hook** (Claude Code) keeps the agent from finishing while a
|
|
92
|
-
removal is in progress
|
|
93
|
-
|
|
102
|
+
removal is in progress and not verified. In progress means a file git
|
|
103
|
+
tracks changed on top of the baseline commit (changes to
|
|
104
|
+
`flagrm.config.yaml` and untracked files don't count, so a removal paused
|
|
105
|
+
on a question to the user doesn't block), or the last verify used `--skip`.
|
|
94
106
|
4. **`/flagrm-verify <flag>`** runs `flagrm verify <flag> --md` and adds notes
|
|
95
107
|
and a commit message.
|
|
96
108
|
|
|
@@ -98,11 +110,12 @@ the OFF path, on purpose, and explains that in its notes.
|
|
|
98
110
|
|
|
99
111
|
| Command | What it does | Exit codes |
|
|
100
112
|
|---|---|---|
|
|
101
|
-
| `init` | Set up the config,
|
|
102
|
-
| `doctor` | Check the config, build and test commands (`--run` runs them), git, `.gitignore`, installed skills and hook, and abandoned baselines | 0 ok, 1 problems |
|
|
103
|
-
| `
|
|
113
|
+
| `init` | Set up the config and `.gitignore` entry, and each chosen AI tool's files (asks, or `--tool claude-code,copilot,codex`; saved as `tools:`). Never overwrites or deletes | 0, 2 usage error |
|
|
114
|
+
| `doctor` | Check the config, build and test commands (`--run` runs them), the .NET SDK `global.json` asks for, `cargo` and Docker where projects need them, git, `.gitignore`, installed skills and hook, and abandoned baselines | 0 ok, 1 problems |
|
|
115
|
+
| `scope` | For each .NET project, show what the machine lacks and which projects a solution filter would leave out; `--write` creates `flagrm.slnf`, adds it to `.git/info/exclude` and points the project's build and test at it | 0 nothing missing, 1 something missing |
|
|
116
|
+
| `update` | Refresh the installed skills, prompt files, `AGENTS.md` block and hook from this flagrm version, for the config's `tools:` | 0 |
|
|
104
117
|
| `list` | List every feature flag in the project: definitions, configured state per environment, reference counts | 0 |
|
|
105
|
-
| `baseline <flag>` | Before any edit, record the git commit, build and test results and the flag's names in `.flagrm/<flag>/baseline.json`. `--name X --kind alias\|wrapper` adds names to an existing baseline; `--force` starts over; `--no-checks` skips build and tests | 0, 2 usage error |
|
|
118
|
+
| `baseline <flag>` | Before any edit, record the git commit, build and test results and the flag's names in `.flagrm/<flag>/baseline.json`. In .NET code the names include the locals, fields, parameters and methods the flag's value travels through when they name the flag (a local, parameter or field is checked only in its own file); generic or ambiguous ones are listed as `suggestedNames`, with `parameterizedTests` that pass the value as a literal. `--file` limits `--name` entries to one file (and records them as wrappers). `--name X --kind alias\|wrapper` adds names to an existing baseline; `--json` prints a summary (test counts, at most 20 failed test names; the file keeps everything); `--force` starts over, but only while the code is unedited since the baseline commit (changes to `flagrm.config.yaml` and `testResults` files are fine); `--no-checks` skips build and tests | 0, 2 usage error |
|
|
106
119
|
| `verify <flag>` | Gate the removal with `leftovers`, `dead-code`, `build` and `tests`. Writes `.flagrm/<flag>/verify.json`. `--md` prints the overview, `--json` the full result, `--skip` skips checks, `--strict` fails on warnings | 0 pass, 1 fail, 2 usage error |
|
|
107
120
|
| `hook stop` | The Claude Code Stop hook installed by `init` | always 0 |
|
|
108
121
|
|
|
@@ -113,10 +126,16 @@ the OFF path, on purpose, and explains that in its notes.
|
|
|
113
126
|
|
|
114
127
|
| Check | Fails when |
|
|
115
128
|
|---|---|
|
|
116
|
-
| `leftovers` | A recorded name (the flag literal, its constants, wrappers the agent recorded) is still in code or config. A mention in a comment is a warning |
|
|
129
|
+
| `leftovers` | A recorded name (the flag literal, its constants, wrappers the agent recorded) is still in code or config. A mention in a comment is a warning, and so is a test that checks text the removal deleted from the code (a test of the OFF path that never names the flag), or deleted text whose replacement on the same line no test checks (lost ON coverage) |
|
|
117
130
|
| `dead-code` | The compiler reports new unused code (locals, imports, private members) in changed files |
|
|
118
131
|
| `build` | A project's build command fails |
|
|
119
|
-
| `tests` | A test that passed at the baseline fails.
|
|
132
|
+
| `tests` | A test that passed at the baseline fails. With `testResults`, tests that already failed at the baseline are known failures and only warn. A test that no longer runs though the diff neither deletes nor renames it and the test config is unchanged, and a changed test file none of whose tests ran, are warnings for the agent to account for |
|
|
133
|
+
|
|
134
|
+
The baseline also records the configuration it was taken with: each project's
|
|
135
|
+
resolved build and test commands, the files they name (a `.slnf`, a
|
|
136
|
+
`.runsettings`, a filter list) and the text of `flagrm.config.yaml`. When any
|
|
137
|
+
of it changed since, the check it affects warns and shows the difference: a
|
|
138
|
+
narrower test command makes "no new failures" mean less.
|
|
120
139
|
|
|
121
140
|
In typed code, deleting the flag's definition turns every missed reference into
|
|
122
141
|
a compile error, so the build does most of the work. `leftovers` covers what the
|
|
@@ -125,6 +144,7 @@ compiler cannot see: config files, templates, comments and wrappers.
|
|
|
125
144
|
## Configuration
|
|
126
145
|
|
|
127
146
|
```yaml
|
|
147
|
+
tools: [claude-code, codex] # the AI tools init and update set up
|
|
128
148
|
projects:
|
|
129
149
|
- name: web
|
|
130
150
|
adapter: angular
|
|
@@ -150,9 +170,30 @@ exclude: ['**/Migrations/**']
|
|
|
150
170
|
Paths are relative to the config file, and commands run inside each project's
|
|
151
171
|
path. Without `build` or `test`, the adapter's defaults are used (`dotnet build
|
|
152
172
|
--no-incremental`, `npx ng build`, and so on). `testResults` (JUnit XML or TRX)
|
|
153
|
-
lets `verify` compare individual tests against the baseline. `timeout`
|
|
173
|
+
lets `verify` compare individual tests against the baseline. Only files written during the run are read, so result files left by earlier runs don't count, and projects whose patterns overlap don't count each other's files. `timeout`
|
|
154
174
|
(seconds) fails a project's build or test command that runs longer, for example
|
|
155
|
-
a test runner left in watch mode.
|
|
175
|
+
a test runner left in watch mode. `tools` lists the AI coding tools whose files
|
|
176
|
+
`init` and `update` manage (`claude-code`, `copilot`, `codex`); dropping one
|
|
177
|
+
leaves its files in place, and `init` names them so you can delete them.
|
|
178
|
+
|
|
179
|
+
### When the machine can't build everything
|
|
180
|
+
|
|
181
|
+
`flagrm init` and `flagrm doctor` check that the .NET SDK `global.json` asks
|
|
182
|
+
for is installed (honoring `rollForward`), that `cargo` is on PATH when a
|
|
183
|
+
project's build runs it, and that Docker is running when a test project uses
|
|
184
|
+
Testcontainers. A missing SDK has to be installed. For `cargo` or Docker,
|
|
185
|
+
`flagrm scope` shows which projects a solution filter would leave out: those
|
|
186
|
+
projects and everything that references them. `flagrm scope --write` creates
|
|
187
|
+
`flagrm.slnf` next to the solution, keeps it out of git, and points the
|
|
188
|
+
project's `build` and `test` at it. The baseline and verify then run on what
|
|
189
|
+
the machine can build; edits to the left-out projects aren't checked by
|
|
190
|
+
build or tests, so mention them in the PR.
|
|
191
|
+
|
|
192
|
+
A test that fails only because of the machine's locale (a decimal comma, a
|
|
193
|
+
date format) is best left out by name, for example `dotnet test --filter
|
|
194
|
+
"FullyQualifiedName!=Ns.PriceTests.FormatsTotal"`, rather than by forcing
|
|
195
|
+
`LC_ALL=en_US.UTF-8` for the whole run: changing the locale for every test
|
|
196
|
+
can break others that pass today.
|
|
156
197
|
|
|
157
198
|
For .NET, keep `--no-incremental` in `build`. An incremental build skips
|
|
158
199
|
up-to-date projects and prints none of their warnings, so the dead-code check
|