Repository navigation
Four issues reported against 1.4.0rc2 - #144
Merged
Merged
Conversation
The quoted diagnosis was capped at twenty lines and no bytes at all, and `eslint -f json` is one line however many megabytes it holds — so a sensor that died mid-report put the whole report into a notice habit-hooks writes into a coding agent's context. Measured at two million characters. Both ends of a long line survive, by the same economy the line budget already used: cut only when the cut is shorter, which is also what keeps the elision from ever reading `1 characters omitted`. The lines that survive are chosen before any of them is cut, so bounding megabytes no longer costs a second copy of them.
Routing a smell to an executable guide and naming a command that is not there printed a Python stack trace: `cli.run_console` catches `ToolError` and this spawn raised `FileNotFoundError`. It is the same first-contact mistake #114 answered for a missing sensor tool, a mistyped config and a bare `--help`, in the one place that sweep did not reach. The guide is named beside the command, because a project routes a smell to a runner by the guide's extension — so which file asked for this is the reader's next question.
…aller's Node caps a captured stream at 1 MB unless told otherwise. `project_tool.run` never told it otherwise, so a bigger report came back with no exit status, a truncated stdout and an empty stderr — and `eslint.cjs` forwarded the empty stderr. The whole notice was a command line with nothing under it (#142). Around a hundred files with findings is enough, on any platform. knip carried both guards at its own call site and eslint carried neither, which is the actual defect: two callers, one question, no shared answer. The seam now owns all of it — no output ceiling, one predicate for "this run produced nothing worth reading", and a complaint that cannot be empty. What a tool half-wrote to stdout is never the complaint: it is a report cut off mid-write, not a diagnosis.
It asks a project to install eslint, knip, ts-morph, jscpd and the two @typescript-eslint packages, and then reported every one of them as declared and imported nowhere (#143). It was complaining about its own footprint. The shipped knip config overlooks them; a project with its own knip config is untouched, as it is for every other setting. The list is derived from each plugin's declared detectors and from what the shipped eslint config resolves, so a plugin that grows a Node tool cannot quietly bring the bug back. knip spells a column `col`; the sensor contract spells it `column`, and a field name is vocabulary like any other.
Two sensors can mean one smell — eslint's `max-lines` and the line counter both mean `oversized-file` — and one sensor can report a smell many times over, as jscpd does per clone. The mapper printed a block per finding, so each of those was another copy of the same two hundred words (#140). Findings that resolve to the same guide are one finding. The guide, not the smell name: a repo holding Python and TypeScript has two `high-complexity` guides, and collapsing them would coach a .ts file in Python. Severity is per smell, so the smell stays in the key too — keyed on the guide alone a suggested finding could absorb an enforced one and lower the exit code. A sensor's own issue list is never thinned. Two variables declared on one line are two things to fix, and pmd, phpmd and the comment sensor all name a line without a column, so only the sensor can tell them apart.
Every git-derived mode asked git and so had never seen a build artifact; `--all` walked the tree and measured whatever it found. One project, two universes: the monorepo in #142 held 321 tracked .ts/.tsx and 843 on disk, and its owner had to write `!**/dist/**` into `[files]` before a run was usable. A default somebody has to patch is the wrong default. A project git cannot answer for still measures the disk — outside a repository, with no git installed, on any failure, and when the project is itself ignored by the repository around it. Git saying nothing is never read as nothing to scan. A submodule leaves the scope, as it always did from every git mode, and now says so rather than shrinking the scan in silence.
Both found the hard way today. Two suites keep working state inside the checkout rather than in a temp directory, so a second concurrent pytest walks into the middle of the first one's run and both go red for no reason. And `GIT_CEILING_DIRECTORIES` is not the guard a scratch fixture needs: it stops git walking up to find a repository, which a script already standing in this one never needs it to. A multi-line command whose first line is `&&`- guarded and whose third is not put 45 files of four agents' work into a commit titled `init`.
Four issues reported against rc2, none of them a Windows bug: a sensor that died without a word when its tool printed more than a megabyte (#142), a smell coached once per sensor that saw it (#140), habit-hooks reporting its own tools as unused dependencies (#143), and a whole-project scan that measured build artifacts every git-derived mode had never seen (#142 again). A release candidate does not move the minor, so only the six version lines move; the plugin floors are minor-grained and already satisfied.
Windows has no signals: `process.kill(pid, "SIGKILL")` there is `TerminateProcess(handle, 1)`, so a tool killed halfway through writing its report exits 1 — which is exactly what eslint and knip exit when they found something to report. Nothing upstream can tell the two apart, so the half- written array reached `JSON.parse` and both sensors answered a reader with a `SyntaxError` and four frames of Node. Reading a tool's report is the seam's question for the same reason running it and describing its failure already were: both callers need the same answer, and the last time one of them was left to decide for itself was #142. A run that printed plenty and left nothing usable says so, rather than borrowing the words for one that said nothing at all. The test that found this now asserts both platforms rather than the one the author's machine could produce.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft, opened to run CI on the Windows leg before tagging
v1.4.0rc3.Fixes #142, #140, #143, plus a
[runners]traceback and two false cleans found on the way.Local: 956 passed, 2 skipped, ruff clean,
uv run habit-hooks --allexit 0.Opened by Claude on Ivett's behalf, while she is away.