From e2f7469f8a6e168055eb432c48487b97d4db5a38 Mon Sep 17 00:00:00 2001 From: imkp1 Date: Mon, 3 Aug 2026 00:22:32 +0530 Subject: [PATCH] docs: count the empty-queue reasons correctly, and say what CI actually enforces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four corrections, no behaviour. Two comments still describe four empty-queue reasons. There have been six since stage 4 landed and added `unverified`: the CI packaging step's note and the terminal path's explanation of why one shared line will not do. Both are the same drift `install.py` already documents as the reason `doctor` checks a skill for staleness — "a skill that lists five reason codes is a skill inviting the model to flatten the sixth into one it recognises." That sentence stays as written; it is history, and it was right. The one that costs someone time: CI now runs pytest under coverage against an 84% floor, and CONTRIBUTING said "the three checks" and listed pytest, ruff, mypy. A contributor whose change drops the number fails on a rule documented nowhere they would look. It is written down now, with the command to see it locally and the note that nothing is excluded from the measurement. And `reprobe` is in the corpus tools list, where it has been missing since it shipped. It was findable only in design.md, which is not where anyone goes for a command to run. Co-Authored-By: Claude Opus 5 --- .github/workflows/ci.yml | 2 +- CONTRIBUTING.md | 21 +++++++++++++++++++++ src/grask/cli.py | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3cabfb..cca5e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,7 @@ jobs: run: | grask --help # A GRASK_HOME this run just created has never captured anything, and - # an empty queue has to say which of the four kinds of empty it is. + # an empty queue has to say which of the six kinds of empty it is. grask serve --json | grep -q '"pending": null' grask serve --json | grep -q '"reason": "never"' # `stats` is the one command a developer runs against a database that diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 362803b..2e5898b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,6 +54,17 @@ uv run ruff check . uv run mypy ``` +CI adds one thing these three do not: it runs `pytest` under coverage against a floor, and a +change that drops total coverage below **84%** fails there whatever the tests say. The floor +is set at the level already reached rather than an aspiration, so it ratchets — if you raise +the real number, raise the floor with it. Nothing is excluded from the measurement to flatter +it (`survey.py` and `triage_run.py` are operator scripts with no tests, and they are the bulk +of the remaining gap). To see the number locally: + +```bash +uv run pytest --cov=grask --cov-report=term-missing +``` + `mypy` is `strict` against `src/grask`, because the package ships `py.typed` and that is a promise to anyone importing it. The two relaxations (`disallow_untyped_defs`, `disallow_incomplete_defs`) exist so injected test doubles are not pinned to production @@ -69,11 +80,21 @@ range first and refuse to run without `--go`. uv run python -m grask.survey # what's in the local transcript corpus (free) uv run python -m grask.triage_run # run stage 1 over the corpus; costs money uv run python -m grask.capture_run # run the full pipeline over past sessions; --go to spend +uv run python -m grask.reprobe # re-ask seeds whose question never landed; --go to spend ``` `capture_run` skips grask's own project by default. The sessions that end from now on are overwhelmingly grask's own, and waiting for the queue to fill measures grask on grask. +`reprobe` is the recovery path for the two places capture stores a seed and no probe — stage 4 +discarding the question, and stage 3 giving up. It re-runs both stages rather than taking a +cheaper shortcut: re-asking without verifying would reintroduce the defect stage 4 exists to +catch, on the population most likely to carry it. A seed that fails twice is worth reading as +a fact about the seed rather than a bad roll. + +The developer-facing counterpart is `grask stats`, which is free, consumes nothing, and is the +only one of these built for someone who is not working on grask. + ## Where things live | Path | What | diff --git a/src/grask/cli.py b/src/grask/cli.py index d8115ee..ca5147b 100644 --- a/src/grask/cli.py +++ b/src/grask/cli.py @@ -484,7 +484,7 @@ def main( if pending is None: # A command you typed that prints nothing looks broken. Silence is # for the tools that push; this one was asked for — and one line for - # four different states would misdescribe three of them. + # six different states would misdescribe five of them. print(TERMINAL_EMPTY_NOTES[store.empty_reason()]) return 0