flagrm 0.1.1 → 0.2.1

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 CHANGED
@@ -5,6 +5,106 @@ 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.1] - 2026-10-04
9
+
10
+ ### Fixed
11
+
12
+ - `flagrm scope` on Windows: `--json` printed the solution path with forward
13
+ slashes, and `--write` showed a wrong `.git/info/exclude` path (and could
14
+ write a wrong line to it) when the path held a short name such as
15
+ `RUNNER~1`.
16
+
17
+ ## [0.2.0] - 2026-10-04
18
+
19
+ ### Changed
20
+
21
+ - **Breaking:** JSON schema version 7. `baseline --json` prints a summary of
22
+ `baseline.json` instead of the whole file: each test run's results as
23
+ counts with at most 20 short failed test names (`failedTests`,
24
+ `moreFailedTests`), and no `config` snapshot. On a large suite the full
25
+ output was megabytes. `baseline.json` is unchanged, and version 6 files are
26
+ still read.
27
+ - The Stop hook only blocks once the removal has edited a file git tracks
28
+ (other than `flagrm.config.yaml`), or the last verify used `--skip`. A
29
+ removal paused on a question to the user, a config fix or an untracked
30
+ file such as a stray test result no longer blocks.
31
+ - `verify`'s `tests[]` reports `failed` and the short names of `newFailures`
32
+ and `knownFailures` per project.
33
+ - `verify` no longer fails the `tests` check when every failing test already
34
+ failed at the baseline: those are reported as known failures and only warn.
35
+ Only new failures fail it, and they are listed. Test names are compared
36
+ without xUnit data-row arguments. Needs `testResults`.
37
+ - `baseline --force` refuses to replace a baseline once the code has changed
38
+ since its commit (`.flagrm/`, `flagrm.config.yaml` and files matching
39
+ `testResults` don't count), so a
40
+ rerun after fixing the setup can't record a half-done removal. The error
41
+ says how to set uncommitted edits aside with `git stash`.
42
+ - Tests that no longer run are sorted by why (`tests[]` in `verify --json`):
43
+ `deleted` (gone from a changed test file, or a data row dropped from one),
44
+ `renamed` (the same test without the flag's words in its name, matched to
45
+ the new test), `excludedByConfig` (the test command or its files changed
46
+ since the baseline) and `unexplained`. Only `unexplained` tests warn; the
47
+ summary counts the others, and `--md` lists each group.
48
+
49
+ ### Added
50
+
51
+ - `flagrm init` asks which AI coding tools to set up (Claude Code, GitHub
52
+ Copilot, Codex), pre-selecting the ones the repository already uses
53
+ (`.claude/`, `.github/copilot-instructions.md` or skills, `AGENTS.md`), and
54
+ installs only their files. `--tool claude-code,codex` chooses without
55
+ asking; without a terminal, the detected tools (all when none) are set up.
56
+ The choice is saved as `tools:` in `flagrm.config.yaml`, which a later
57
+ `init` and `update` follow; files of a tool dropped from it are left in
58
+ place and named. Copilot also gets `/flagrm-remove` and `/flagrm-verify`
59
+ prompt files in `.github/prompts/`. `doctor` checks only those tools.
60
+ - `flagrm scope`: for each .NET project, checks the machine (the SDK
61
+ `global.json` asks for, with `rollForward`; `cargo` where a project's build
62
+ runs it; Docker where a test project uses Testcontainers) and shows which
63
+ projects a solution filter would leave out: those and every project that
64
+ references them. `--write` creates `flagrm.slnf`, adds it to
65
+ `.git/info/exclude` and points the project's build and test at it, editing
66
+ `flagrm.config.yaml` in place. When the commands already name a solution
67
+ filter, `flagrm.slnf` keeps only its projects; a command that names a
68
+ project file is left alone. `doctor` (and so `init`) reports the same
69
+ problems: a missing SDK fails, a missing `cargo` or Docker warns.
70
+ - README: leave a locale-dependent test out with `--filter` rather than
71
+ forcing `LC_ALL` for the whole run.
72
+ - `verify` warns in `leftovers` about tests of the OFF path that never name
73
+ the flag: a test that still checks a string literal the removal deleted
74
+ from the code (and that no other code still has). When a test checked the
75
+ deleted text but none checks the text kept on the same line, it warns
76
+ that the ON path lost its test coverage.
77
+ - .NET discovery follows a flag's value: bool locals, fields and properties
78
+ assigned `IsEnabled(<flag>)`, methods that only return it (or a ternary on
79
+ it; static ones as `Class.Method`), and the bool parameters it is passed
80
+ to. `flagrm list` shows them as `flow`; `baseline` records as wrappers the
81
+ ones that clearly name the flag and lists the rest as `suggestedNames`. A
82
+ local, parameter or field (recorded with `file`) is only checked in its own
83
+ file; a method or property must contain the flag's whole name, or a flag
84
+ word with a digit. A parameter of one of several same-named methods, or a
85
+ method whose name another method shares, is only suggested. Test calls
86
+ passing `true`/`false` for such a parameter are listed as
87
+ `parameterizedTests`.
88
+ - `baseline --name X --file <path>` records `X` as a wrapper checked only in
89
+ that file.
90
+ - The baseline records its configuration (`config` in `baseline.json`): each
91
+ project's resolved build and test commands with a hash of the files they
92
+ name (`.slnf`, `.runsettings`, filter lists; not `.sln`/`.csproj`),
93
+ `testResults`, and the text of `flagrm.config.yaml`. `verify` warns when
94
+ they changed since: a command or named file in `build`/`tests`, any other
95
+ config change in `leftovers` with the changed lines.
96
+ - A failed build or test run whose log shows a machine setup problem gets
97
+ `failure: { kind: "environment", message }` in `baseline.json` and the
98
+ `verify`/`doctor` output: a .NET SDK that doesn't match `global.json`
99
+ (requested vs installed versions), a command a build step couldn't find
100
+ (and the project that runs it), or Docker not running for Testcontainers.
101
+
102
+ ### Fixed
103
+
104
+ - Two projects whose `testResults` patterns overlap (`./**/TestResults/*.trx`)
105
+ no longer count each other's result files when their test runs follow each
106
+ other. Result files from earlier runs were already ignored.
107
+
8
108
  ## [0.1.1] - 2026-10-01
9
109
 
10
110
  ### Changed
@@ -44,5 +144,7 @@ removes the flag through the `flagrm-remove` skill, and flagrm checks the result
44
144
  `doctor` warns about an incremental `dotnet build`, which hides existing
45
145
  warnings from the dead-code comparison.
46
146
 
147
+ [0.2.1]: https://github.com/dino-cosic/flagrm/releases/tag/v0.2.1
148
+ [0.2.0]: https://github.com/dino-cosic/flagrm/releases/tag/v0.2.0
47
149
  [0.1.1]: https://github.com/dino-cosic/flagrm/releases/tag/v0.1.1
48
150
  [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 that no longer run) and
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 | ⚠️ warn | tests passed (web 24 → 21, api 18 → 16) |
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 that no longer run (5):** `LegacyPricingCalculatorTests.AppliesBulkDiscount`, ...
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
- A warning is not a failure. Here the agent deleted the tests that covered only
77
- the OFF path, on purpose, and explains that in its notes.
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`** writes `flagrm.config.yaml` for the Angular and .NET
82
- projects it finds. It installs the `flagrm-remove` and `flagrm-verify`
83
- skills into `.claude/skills/`, `.github/skills/` and `.agents/skills/`, adds
84
- a pointer to `AGENTS.md` for Codex, adds a Claude Code Stop hook to
85
- `.claude/settings.json`, and adds `.flagrm/` to `.gitignore`.
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 (uncommitted changes on top of its baseline commit)
93
- and not verified.
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, skills, `AGENTS.md` block, Stop hook and `.gitignore` entry. Never overwrites | 0 |
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
- | `update` | Refresh the installed skills, the `AGENTS.md` block and the hook from this flagrm version | 0 |
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. Tests that no longer run, and changed test files none of whose tests ran, are warnings for the agent to account for |
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