Repository navigation
Conversation
## Summary `pr_review.py` filtered open review threads by a set of known reviewer logins before counting them. A thread opened under a login outside that set dropped out of `unresolved=`, so `status` and `wait` printed a digest that read clean while a finding sat open. This implements the disposition recorded on #1404, direction 1: count every unresolved thread whoever opened it, and use the known logins only to attribute a thread in the breakdown. - `open_reviewer_threads` becomes `open_threads`, which keeps every unresolved thread regardless of author. - The breakdown beside `unresolved=` names any author outside the known set as `other`. It prints whenever more than one group contributes, or whenever `other` contributes at all, since that is the count a reader cannot assume. - `unresolved_threads()`, the `reply` command's paginated walk, now reuses `open_threads` instead of repeating the same filter. - The module docstring, the `threads_truncated` docstring, and the test summary in `scripts/README.md` now describe the new rule. ## Callers re-checked - `digest()` counts and lists every open thread. Both of its callers, `status` and `wait`, throw away the count it returns, so no `wait` exit code changes. Exit 0 still means a review covers the head, not that the merge gate passed. - `uncounted_verdict()` (exit 50) now holds off while any thread is open, whoever opened it. Before, it held off only for a known reviewer's thread. It reports again once the thread is resolved, as it already did. ## Tests - A thread from an unknown login is counted and shows as `unresolved=1 (other=1)`. The digest that `status` and `wait` print carries it. - A thread from a deleted account is counted as `other`. - A maintainer's own open thread is counted and listed. The old test asserted the opposite and has been turned around. - `uncounted_verdict` holds off for an unknown login's open thread. - With the old filter put back, all six affected cases fail. Closes on promotion: #1404 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Review digests now count all open review threads, including those from unknown or missing authors, and attribute them to the appropriate reviewer category. * Verdict checks now use the same all-thread counting rules, preventing uncounted-verdict alerts when a thread’s author is unknown. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary
The `--branch` paragraph in `AUDIT.md` named two outcomes of a
`--branch` value: a ref that resolves, and a ref that does not resolve.
It did not name the third, a value off the `groundTruthBranch` grammar,
which `spec/audit.py` refuses before any read with exit `2` and one
stderr line. This adds one sentence naming that outcome and where the
grammar lives, `GROUND_TRUTH_BRANCH_PATTERN` in `spec/validate.py`.
The issue places the paragraph in section 1. It sits in section 8
("Report"), and the edit is made where the paragraph actually is.
## Verification
- `python3 spec/audit.py --branch 'a/../zen' ProjectTemplate` printed
one stderr line and exited `2`, before any read.
- `scripts/prose_lint.py --diff origin/develop`, `scripts/repo_gate.py
--check eol`, `spec/validate.py`, and `scripts/docker_lint.py`
(markdownlint, cspell) all pass.
- Two `local-strict-review` passes ran over the branch diff and are
recorded. The first found the new sentence over the 25-word cap, so it
is split in two. The second found nothing.
Closes on promotion: #1509
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Three assertions in `tests/test_pr_review.py` pinned a needle against the raw source of `scripts/pr_review.py`, so a rewrap broke them and one failed with a message claiming the comment was deleted. - A `comment_flowed_text` reader strips each line's leading `#` marker before collapsing whitespace, and the vetted-list-size assertion reads through it. - The backoff `delays` read uses a regex tolerant of an annotation or a rewrap, and fails with a named message when the assignment is gone. - The `n in blob` pin reads through `flowed_text`. Verified by mutating `scripts/pr_review.py`: a rewrap of each pinned line passes, an annotated `delays` passes, and removing each subject fails with a message naming it. The full `python3 -m unittest discover -s tests` suite passes. A local strict review pass found nothing. Closes on promotion: #1732 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…e Live Channel (#2701) `skills_install.py --report` now carries `live.plugin` with `installed` and `enabled`, read from `claude plugin list --json` for the user-scope `fleet-skills@projecttemplate-fleet` entry (null where the listing cannot be read), only when the marketplace is registered. A shared `claude_json` helper backs both listings. The `check-this-repo` skill and `scripts/README.md` name the field. Closes on promotion: #1757 Remaining local-review findings after the two-round edit budget (class introduced): - `enabled` is read from the directory `--report` runs in, so a project-level `enabledPlugins` override in that directory changes it. The skill and README present it as machine-wide. - A project- or local-scope-only install reads `installed: false`, which the skill and README word as "serves nothing". - No test asserts `claude_json` passes `timeout=SUBPROCESS_TIMEOUT` (small). Not changed: Windows `claude.cmd` resolution via bare `claude` (pre-existing in `marketplace_entry`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…ell-codestyle Claim (#2703) Removes the five `# shellcheck disable=SC2016` directives in `repo-config/configure.sh` that suppress nothing, then makes the `shell-codestyle` "Rules" sentence citing that file true of every directive that remains. ## Measurement Replacing every SC2016 directive in a copy of the file with `:` (line numbers kept) and running shellcheck flags only the commands behind the remaining directives, under both 0.10.0 and the CI image `koalaman/shellcheck:stable` (0.11.0). None of the removed sites is flagged: - Three pass a single-quoted program straight to `jq`, which shellcheck already exempts. - Two are double-quoted with an escaped `\$t`, where SC2016 never fires. Every remaining directive guards a single-quoted `jq` program handed to the `jqr` or `jq_has` wrappers or held in a variable, or a single-quoted GraphQL query passed to `gh api graphql`. Each carries its reason on the same line, and the file stays shellcheck clean. ## Skill The worked-example sentence now says the disables sit only where shellcheck flags a single-quoted `jq` program or GraphQL query that must stay unexpanded. Generated copies rebuilt with `scripts/build_dist.py`. Closes on promotion: #1156 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Drops the one remaining `driftNotes` entry on the `Utilities` registry entry. It says the repository has no `get-version-task` and relies on `validate-task`. Both release-bearing stubs on `Utilities` `main` call the hub's `build-release-task.yml`, which reaches `get-version-task.yml`, so the note describes finished work, which `RESYNC.md` section 3 deletes rather than leaves standing. The `configLayout` half of the issue was already done. Verified: `spec/validate.py` passes, `spec/audit.py Utilities` raises nothing from this edit, and the spec validator, configure model, and configure archived tests pass. A local strict review pass raised no findings. Closes on promotion: #1115 Related: #1145. The `LanguageTags` entry carries the identical stale note and is left for its own change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…d Wording (#2707) Brings the two remaining surfaces #1237 names into line with the wording `GOVERNANCE.md` "Verification Discipline" now carries. The third surface, `agent-conduct`, already matched on develop. - The `comment-and-doc-style` line-endings reference said `write_text()` writes `\n` back and offered `newline=''` on `Path.read_text()`. It now says `write_text()` translates each `\n` to `os.linesep`, and the fix is bytes or `open()` with `newline=''` on both the read and the write, since `Path.read_text()` accepts `newline` only on Python 3.13 and newer. The two generated copies are regenerated by `scripts/build_dist.py`. - The `tests/test_repo_gate.py` docstring blamed a shell heredoc, which a quoted heredoc disproves. It now names `printf`, `echo -e`, and `$'...'`. The local review pass also found that the pattern loop only compiled each pattern, which a control character survives, so the loop now also asserts each pattern is printable ASCII. A mutant pattern carrying a backspace fails the test, and the real patterns pass. Verified: ruff format and check, mypy, `prose_lint.py` with and without `--check sentence-length`, `build_dist.py --check`, `spec/validate.py`, and `tests.test_repo_gate` (144 tests) all pass. Two local strict review passes ran, the first raising three findings that the second commit fixes, the second raising none. Closes on promotion: #1237 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified guidance for preserving line endings during text edits, including how newline handling varies across Python versions. * **Tests** * Expanded checks to verify that key patterns compile and contain only printable ASCII characters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…kill Description (#2709) Brings the `workflow-ci-contract` entry's Trigger line in line with the skill's frontmatter description, and drops the false "largest law doc" superlative from the G9 Gap. Closes on promotion: #1243 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
## Summary `python-codestyle` described the build profile's CI type check in ways the hub validator's "Type check Python step" does not match. This states what the validator actually runs. - **One checker per directory.** The validator runs at most one checker in each Python directory, mypy where both are configured. The skill said CI may run pyright, mypy, or both. It now says that, and that a repo enforcing pyright beside mypy runs pyright from its own `.github/actions/validate/action.yml` hook, which starts from a bare checkout. Mirrored in `references/profiles.md`. - **No path target.** The skill gave `uv run mypy src` as the command CI runs. CI passes the checker no path where the config sits in the project directory, so a mypy config with no target setting passed locally and failed in CI. The skill now gives `uv run mypy`, says the config's own target settings decide what is checked, and gives the root-config fallback CI uses for a declared subdirectory with no config of its own, `uv run --project <dir> <checker> <dir>` from the root. - **CI-gate bullet.** "Linter cleanliness" no longer says every command runs from the project directory, since the root-config case runs from the root. - Generated copies rebuilt with `scripts/build_dist.py`. ## Verification - `uvx mypy@latest` with `[tool.mypy] strict = true` and no target exits 2 with "Missing target module, package, files, or command.", and with `files = ["src"]` it checks `src`. Constructed probe, run in scratch. - `scripts/build_dist.py --check`, `scripts/prose_lint.py --diff`, `scripts/repo_gate.py --check eol`, `spec/validate.py`, and `scripts/docker_lint.py` all clean. - Three `local-strict-review` passes, the last raising no finding. A pre-existing gap the passes found in the pip-form paragraph is filed as #2711. Closes on promotion: #2025 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…le (#2714) ## Summary The pip-form paragraph under `python-codestyle` "Local development loop" gave its type-check commands with no path argument and no word on where to run them. The hub validator's "Type check Python step" falls a declared subdirectory with no checker config of its own back to the repository root's config, then runs the checker from the root with the directory as its path and that directory's `.venv` interpreter. A pip-form subdirectory relying on the root config, following the skill, ran its checker inside the subdirectory and checked a different file set than CI, or none. - The paragraph now states that CI runs the checker in the project directory with no path where the config sits there, and from the root with `<dir>` as its path and `<dir>/.venv/bin/python` as the interpreter where the config is the root's, with `<dir>/.venv/bin/python -m mypy <dir>` as the example. The uv-form paragraph already states the same fallback. - The Windows sentence now covers every interpreter path the paragraph names rather than only `.venv\Scripts\python.exe` at the directory. - Generated copies rebuilt with `scripts/build_dist.py`. ## Verification - Each stated command checked against `.github/workflows/validate-task.yml` "Type check Python step": `targets` is empty when the config sits in the directory, `find_checker . true` supplies the root fallback, and the interpreter is the directory's own `.venv/bin/python`, for the venv mypy, `uvx mypy --python-executable`, and `uvx pyright --pythonpath` forms alike. - `scripts/build_dist.py --check`, `scripts/prose_lint.py --diff` with and without `--check sentence-length`, `scripts/repo_gate.py --check eol`, `spec/validate.py`, and `scripts/docker_lint.py` all clean. - Two `local-strict-review` passes. The first raised one over-long sentence, fixed in the second commit, and the second raised no finding. Closes on promotion: #2711 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated Python type-checking instructions to distinguish project-level configurations from subdirectories that inherit the repository configuration. For inherited configurations, the documented CI and local commands run the checker from the repository root, target the subdirectory, and use its interpreter. Windows interpreter paths are documented separately. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Two test harnesses built a child's PATH from an empty fallback, so with
PATH unset the child lost the default search path that the parent's
lookup used.
- `tests/test_skills_install.py`: both child environments now use
`os.environ.get("PATH", os.defpath)`.
- `tests/test_local_review.py` `fake_cli`: the stub directory is
prepended to `os.defpath` when PATH is unset, and the cleanup now
restores the true previous state (unset is popped, not set to empty).
- `tests/test_local_review.py`
`test_a_missing_binary_is_a_boundary_through_main`: judged correct as
is. It deliberately replaces PATH with an empty directory, so no
fallback applies.
Verification with `env -u PATH /usr/bin/python3 -m unittest
test_skills_install`: before, 1 failure and 4 errors; after, OK.
`test_local_review` under unset PATH still errors in setUp where it runs
bare `git` (outside the three sites; 105 failing before, 102 after).
With PATH set both modules pass.
Closes on promotion: #1862
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
## Summary The skills refresh cadence was stated on several surfaces that disagreed on the flag. This applies the decision recorded on #2191: `docs/host-setup.md` "Fleet Skills Install" owns the cadence and keeps the full install, and the other surfaces point to it. - `skill-lifecycle` step 8 drops its `--snapshot-only` restatement and points to "Fleet Skills Install". - `check-this-repo` "Refresh cadence" keeps `--snapshot-only` for its own freshly fetched checkout and no longer claims host-setup states the same cadence. It now names the symptom it triggers on rather than one "below" that the file does not hold. - `docs/fleet-map.md` G6 (item 3 and the resolution) now says the cadence has one home that `check-this-repo` points to. - Generated copies rebuilt with `scripts/build_dist.py`. The declined alternative, `--snapshot-only` everywhere with a full-install exception, is not reopened. `merge-and-release` step 7's own `--snapshot-only` refresh from a detached worktree is unchanged, since it is not the host cadence. ## Verification - `scripts/build_dist.py --check`: current. - `scripts/prose_lint.py --diff <merge-base>`, with and without `--check sentence-length`: clean. - `spec/validate.py`, `scripts/repo_gate.py --check eol`, markdownlint: clean. - `local-strict-review`: two recorded passes. Round 1 found the fleet-map item 3 contradiction and a sentence-length overrun, both fixed. Round 2 found nothing. Closes on promotion: #2191 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…g-burndown (#2720) ## Summary `backlog-burndown` "Grouping and File Claims", in the "Verify the prediction before dispatching" bullet, named `gh pr diff <number> --name-only` per open pull request but no command that enumerates the open set. This adds the listing command, a `gh pr list` with an explicit `--limit` (gh lists 30 by default) and a jq filter that drops only this repository's own `develop -> main` promotion pull request. The filter checks `isCrossRepository` too, so a fork's `develop -> main` pull request stays in the listing. The clause points at the bullet's existing "Exclude the open promotion pull request" sentence rather than stating the exclusion a second time. - Generated copies rebuilt with `scripts/build_dist.py`. - #1275's other defects in the same bullet are out of scope and untouched. Closes on promotion: #1308 ## Verification - The jq filter, run on constructed input (same-repo develop -> main, fork develop -> main, feature -> develop, hotfix -> main), drops only the first. - The full command runs cleanly against this repository on gh 2.102.0 (no open pull requests at the time, so empty output). - `scripts/build_dist.py --check`: current. - `scripts/prose_lint.py --diff <merge-base>`: clean. With `--check sentence-length`, the two sentences it reports both predate this change (the opening sentence shortened from 50 to 45 words, the `git worktree list` sentence unchanged and only moved). - `spec/validate.py`: OK. - `local-strict-review`: three recorded passes. The first found the exclusion restated (fixed), the second found a fork's `develop` would be dropped (fixed), the third found nothing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary On a pull request into a branch other than the default, a fix push covered by an attested local pass took the held branch of `pr_review.py wait`. That branch returned exit `0` at once with no `status=` line while checks were still running, which a caller reading only the exit code took as ready. The held branch now polls the head's checks (the full query, since the liveness query carries none) while `held_checks_open` reads that they can still move the merge: - `Q_FULL` reads each rollup member's `isRequired(pullRequestNumber:)` and the pull request's `state`. A missing key reads as required or open. - The poll ends once the merge reads `CLEAN`, `UNSTABLE`, or `HAS_HOOKS`, or the pull request is no longer open. A `BLOCKED` merge carrying a stuck required check ends it too, its `44` already decided. - It holds on a required check still settling (one running long included), on any settling check while no required one has posted (a required aggregator behind `needs:` enters the rollup only once its dependencies finish), on an empty readable rollup under `BLOCKED`, `BEHIND`, or `DRAFT`, and on a merge still `UNKNOWN`. An unrecognized review shape ends it, its `43` already decided. - `checks_settling` is the complement of `checks_stuck`, leaving the state taxonomy to `check_shape`. A covered head still open at the timeout exits `30` with `status=CHECKS_PENDING`, ranked ahead of the `44` arm. The poll stops at once where the head is no longer covered: a push exits `49`, and a requested round exits `30` with `status=PENDING` unless a `46` or `47` quota reading outranks it. The `wait` help text and `scripts/README.md` state the new readings. The Copilot (non-held) path is unchanged. Closes on promotion: #2685 ## Remaining Local-Review Findings Each finding still open after the local passes, with its class and outcome: - `introduced`, design: the held poll loop is a second inline copy of the Copilot loop's backoff shape. Deferred to #2723. - `introduced`: the 44 arm still fires on any stuck check under `BLOCKED`, and its README and code-comment rationale cites a ruleset read this change now makes for free. Deferred to #2724. - `introduced`: the seconds-long gap after a `needs:` dependency finishes, or before a slower workflow's jobs register, can end the poll early if a read lands in it. Every fleet ruleset measured requires a single aggregator, and the measured gap is one to three seconds against a poll interval of fifteen or more. - `introduced`: a `BEHIND` merge with a failed required check ends the poll with exit `0`, since the `44` arm requires `BLOCKED`. That arm's scope is #2724's. - `introduced`: the held poll reads the full `Q_FULL` document each iteration where a narrower one would do. Deferred to #2723. - `introduced`: `scripts/README.md`'s `30` paragraph does not name the immediate `44` a stuck required check gives, and `check_nodes`'s docstring does not name the `required` key. Deferred to #2725. ## Verification - `python3 -m unittest discover -s tests`: 2445 tests OK on the head. - Each guard in `held_checks_open` and the loop was mutation-tested: removing it fails a named test. The first tests fail against the unfixed script. - `isRequired` and `state` were read live on this pull request and on merged ones. - `ruff format --check`, `ruff check`, `mypy`, `prose_lint.py --diff`, `repo_gate.py --check eol`, `spec/validate.py`: clean. `--check sentence-length` reports only sentences older than this change. - `local-strict-review`: a recorded pass before every push, seventeen in all, each push's findings fixed within its edit budget or listed above. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * The `wait` command now continues polling checks that could affect a held pull request, even when a local pass has been attested. * If checks remain unsettled at timeout, `wait` reports `CHECKS_PENDING` with exit code 30. Closed pull requests and terminal merge states end polling. * Long-running checks are no longer treated as stuck. Exit code 44 is reserved for stuck required checks when the merge state is `BLOCKED`. * **Documentation** * Clarified polling outcomes and the distinction between pending checks, pending reviews, and other results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary `scripts/pr_review.py wait` took exit `44` (`status=CHECKS_NOT_MERGEABLE`) on any stuck check while the merge read `BLOCKED`. A merge blocked by an unresolved thread or a missing approval, carrying a failed check nothing requires, therefore still exited `44`. The full query already reads `isRequired` on every rollup member, so the `44` arm now counts only a stuck check marked required, and still requires `BLOCKED`. - The `44` line names each required stuck check, since the digest block above it prints optional stuck checks too. - The module docstring, the code comment above the arm, and the `scripts/README.md` paragraphs state the `isRequired` reading instead of the call-cost rationale. - A test pins that a stuck optional check on a `BLOCKED` merge exits `0` and a stuck required one exits `44`. Another pins that the `44` line names only the required check. The CLEAN-merge test is renamed to the `BLOCKED` half of the condition it pins. The change rewrites the code comment above the `44` arm, which the issue asks for, so it carries the `comments` label. Closes on promotion: #2724 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#2729) Documents the immediate `44` beside the held `30` conditions in `scripts/README.md`, and names every key a `check_nodes` node can carry (`required`, `unreadable`) in its docstring. Closes on promotion: #2725 Remaining local-review finding after the two-round edit budget (class: introduced, wording): in the README sentence the clause "either one past `--check-grace`" follows a list of three states and could be read as also applying to a failed check, which gets no grace in `check_shape`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…2732) ## Summary - `scripts/pr_review.py wait` now runs both of its polls through one `backoff` helper on the `POLL_DELAYS` schedule, so a fix to the timeout check or the delay schedule lands once. The Copilot poll passes in its initial `(done, answer, drift)` tuple, so the `--ignore-quota-signal` path that forces `done` false still holds for the first evaluation, and re-reads through `live_state`, now extended to return those three readings rather than left as an unused sibling. - The held-head check poll re-reads a narrower `Q_HELD` document, the fields its readers use, sharing one `HELD_FIELDS` fragment with `Q_FULL`. A `Q_HELD` read that would end the poll is re-read as `Q_FULL` first, so the poll stops only on the full payload the verdict then grades, and a poll that never sleeps grades its first read with no extra call. On the timeout the verdict takes a fresh `Q_FULL`. - Tests: two new `backoff` cases pin the delay schedule and the timeout bound, a case pins `Q_HELD` leaving out the threads and files, and two `wait` cases pin the query sequence and the full-read confirmation. The existing `wait` tests pass unchanged. Two other existing tests changed: the contract test that scraped a local `delays` list now reads `POLL_DELAYS`, and the two `live_state` tests take its new return shape. Closes on promotion: #2723 ## Local review Three `local-strict-review` passes ran, and the edit budget is spent. Disposed of so far: - PEP 695 `def backoff[Polled]` needs Python 3.12. Declined: `spec/host-tools.json` sets the interpreter floor at 3.13, and ruff's default rules under `target-version = "py313"` (UP047) refuse the `TypeVar` form. - Two duplications that predate this change, the liveness triple computed both inline and per iteration and a held wait's back-to-back `Q_FULL` reads, are filed as #2731. Still open, each `introduced`: - **Test gap.** The `answer` fake ignores the query, so every `Q_HELD` read in the suite carries `reviewThreads` and `files`. Replacing `final = polled if any(polled is f for f in fulls) else None` with `final = polled` passes the suite, although on a held timeout ending on a `Q_HELD` read the digest would raise a `KeyError` on `reviewThreads`. - **Design.** The `fulls` list and its identity scan do more than the job needs, since only the last full read can be the returned value. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… Its Snapshot (#2734) ## Summary Two duplications in `scripts/pr_review.py wait` are removed. - **One helper computes the liveness readings.** `liveness(pr, min_rounds)` returns the three stop readings (`head_review_done`, `answered_outside_review`, `reviewer_login_drift`). `main`'s first `Q_LIVE` evaluation and every `live_state` re-read both call it, so a reading added to one site cannot be missing from the other. The drift rationale that sat as a comment in `main` now lives in the helper's docstring. - **A held wait opens its poll on `snapshot`.** It no longer makes a second, back-to-back `Q_FULL` read, which saves one GraphQL call per held wait. An `assert` narrows `snapshot` for the type checker. `held` already requires a non-None snapshot. ## Tests - The held-wait tests that count reads or queue responses now expect one `Q_FULL` read fewer. - The test that modeled a push between the two `Q_FULL` reads now models a push before the snapshot read, and is renamed to match. Once only one read is left, that is the window that remains. - Two tests are new. The first checks that the first stop evaluation and every poll go through the same helper. Mutating `main` back to computing the readings inline makes it fail. The second checks that `live_state` returns `liveness` of the same payload. ## Verification - `python3 -m unittest discover -s tests`: 2455 tests, OK (6 skipped). - `ruff format --check`, `ruff check`, `mypy`, `prose_lint.py --diff`, `repo_gate.py --check eol`, and `spec/validate.py` all pass. - `local-strict-review` ran twice, with each pass recorded. The first raised one introduced finding, a stale test name and docstring, which is fixed in a170f96. The second raised none. Closes on promotion: #2731 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Pull request review waiting now applies the same checks at startup and during polling, including review completion, answers outside a formal review, and reviewer login changes. * When the pull request’s head has changed, the hold decision uses the current head’s review status. Rechecking a completed review with `--ignore-quota-signal` continues to honor the existing refusal check. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…2737) ## Summary The prose gate's semicolon check exempted any sentence holding a colon before its first semicolon and a comma, so a colon that explains rather than labels let a clause-joining semicolon through (#1396). Per the decision on #2736 (option 1), a lone semicolon now counts as a list separator only between two labeled items, as in `Inputs: a, b; outputs: c`. Two or more semicolons plus a comma stay exempt. - `prose_lint.py`: `LABELED_ITEM` (built from `LABEL_WORD`) must match both the first item, past any list marker, and the item after a single semicolon. A label is up to three words, emphasis or a code span allowed, with `.`, `/`, `-` only between word characters, so `D1.2:` labels while `e.g.`, `/tmp`, and a quotation do not. - Tests: the old colon-arm exemptions now assert a report, the abbreviation test is rebuilt as a series, and new tests cover labeled items, both halves of the condition, and the three non-label shapes. Each new negative fails with the previous pattern restored. - Tree recasts for the six lines the narrower exemption reports: `WORKFLOW.md` lines 54, 181, 247, 294 (plus generated skill-reference copies) and `catalog/snippets/vscode/README.md` lines 17-18. - Rule text: the maintainer chose to narrow the stated exception in this PR, so `comment-and-doc-style` and `scripts/README.md` now say a single semicolon separates a list only between two labeled items. Closes on promotion: #1396 ## Known Residual A short labeled first clause followed by a short labeled tail still passes (`It fails: it reads x, y; it stops: the run halts.`), since shape cannot tell a three-word clause from a label. Requiring a label on both sides, per Copilot's finding, narrowed this from any colon-bearing first clause. ## Local-Review Findings The four findings the first push listed here were fixed in 91a438e and a4d38d6, the same ones Copilot raised. The rule text's opening-label clause was narrowed to a bold label in b58540b. The last pass found that the gate strips only the `**` bold spellings, so `__Label__:` and `***Label***:` openers still count as a first label. That is the gate falling short of the rule rather than the rule being wrong, so it is deferred to #2738 with the pre-existing `+`/`N)` marker gap. Carries the `comments` label for the added code comments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2740 +/- ##
==========================================
+ Coverage 59.58% 59.83% +0.25%
==========================================
Files 16 16
Lines 8316 8368 +52
==========================================
+ Hits 4955 5007 +52
Misses 3361 3361
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🔵 Needs a closer look
Merge-gate control flow and required-check decisions have changed alongside fleet-wide guidance, warranting final human validation.
0 open findings
What changed in this PR
This PR promotes a set of develop changes to main, updating the fleet’s review tooling, prose gate, audit reporting, and guidance.
Changes:
- Reworks
pr_review.py waitto poll checks on attested heads and distinguish pending from blocked checks. - Narrows the prose gate’s single-semicolon exemption and updates its tests.
- Corrects audit and development guidance, then refreshes distributed skill copies.
| File | Description |
|---|---|
WORKFLOW.md |
Corrects CI contract prose. |
tests/test_skills_install.py |
Tests plugin state and PATH fallbacks. |
tests/test_repo_gate.py |
Strengthens pattern assertions. |
tests/test_prose_lint.py |
Tests semicolon exemptions. |
tests/test_pr_review.py |
Tests wait behavior and thread counts. |
tests/test_local_review.py |
Adds a default PATH fallback. |
scripts/skills_install.py |
Reports installed and enabled plugin state. |
scripts/README.md |
Documents wait and installer behavior. |
scripts/pr_review.py |
Reworks polling, check verdicts, and thread counts. |
reports/_template.md |
Aligns audit dimensions and verdict guidance. |
repo-config/configure.sh |
Removes inert ShellCheck directives. |
registry/repos.json |
Removes a stale drift note. |
docs/fleet-map.md |
Updates skill scope and cadence descriptions. |
catalog/snippets/vscode/README.md |
Clarifies extension descriptions. |
AUDIT.md |
Documents invalid --branch handling. |
.github/skills/workflow-ci-contract/references/test-methodology.md |
Refreshes generated CI prose. |
.github/skills/workflow-ci-contract/references/d-guarantees.md |
Refreshes generated retention prose. |
.github/skills/workflow-ci-contract/references/architecture.md |
Refreshes generated architecture prose. |
.github/skills/skill-lifecycle/SKILL.md |
Refreshes generated cadence guidance. |
.github/skills/shell-codestyle/SKILL.md |
Refreshes generated ShellCheck guidance. |
.github/skills/python-codestyle/SKILL.md |
Refreshes generated type-check guidance. |
.github/skills/python-codestyle/references/profiles.md |
Refreshes generated profile guidance. |
.github/skills/comment-and-doc-style/SKILL.md |
Refreshes generated semicolon guidance. |
.github/skills/comment-and-doc-style/references/line-endings.md |
Refreshes generated line-ending guidance. |
.github/skills/check-this-repo/SKILL.md |
Refreshes generated install guidance. |
.github/skills/backlog-burndown/SKILL.md |
Refreshes generated PR enumeration guidance. |
.github/actions/prose-gate/prose_lint.py |
Narrows the semicolon exemption. |
.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/test-methodology.md |
Mirrors CI prose. |
.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/d-guarantees.md |
Mirrors retention prose. |
.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/architecture.md |
Mirrors architecture prose. |
.claude-plugin/fleet-skills/skills/skill-lifecycle/SKILL.md |
Mirrors cadence guidance. |
.claude-plugin/fleet-skills/skills/shell-codestyle/SKILL.md |
Mirrors ShellCheck guidance. |
.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md |
Mirrors type-check guidance. |
.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md |
Mirrors profile guidance. |
.claude-plugin/fleet-skills/skills/comment-and-doc-style/SKILL.md |
Mirrors semicolon guidance. |
.claude-plugin/fleet-skills/skills/comment-and-doc-style/references/line-endings.md |
Mirrors line-ending guidance. |
.claude-plugin/fleet-skills/skills/check-this-repo/SKILL.md |
Mirrors install guidance. |
.claude-plugin/fleet-skills/skills/backlog-burndown/SKILL.md |
Mirrors PR enumeration guidance. |
.claude-plugin/fleet-skills/.source-digests/workflow-ci-contract |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/skill-lifecycle |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/shell-codestyle |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/python-codestyle |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/comment-and-doc-style |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/check-this-repo |
Updates the skill digest. |
.claude-plugin/fleet-skills/.source-digests/backlog-burndown |
Updates the skill digest. |
.agents/skills/workflow-ci-contract/references/test-methodology.md |
Corrects CI prose at its source. |
.agents/skills/workflow-ci-contract/references/d-guarantees.md |
Corrects retention prose at its source. |
.agents/skills/workflow-ci-contract/references/architecture.md |
Corrects architecture prose at its source. |
.agents/skills/skill-lifecycle/SKILL.md |
Points refresh guidance to its source. |
.agents/skills/shell-codestyle/SKILL.md |
Corrects ShellCheck guidance. |
.agents/skills/python-codestyle/SKILL.md |
Clarifies CI type-check commands. |
.agents/skills/python-codestyle/references/profiles.md |
Clarifies the two-checker profile. |
.agents/skills/comment-and-doc-style/SKILL.md |
Clarifies the semicolon exception. |
.agents/skills/comment-and-doc-style/references/line-endings.md |
Corrects Python line-ending advice. |
.agents/skills/check-this-repo/SKILL.md |
Clarifies its refresh scope. |
.agents/skills/backlog-burndown/SKILL.md |
Names the open-PR enumeration command. |
🧠 Review effort: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This is a caution rather than a finding. It names no defect, opens no thread, and counts no finding. The changes it points at are the |
Summary
Promotes 20 changes from
developtomain:Closes #1396
Closes #2731
Closes #2723
Closes #2725
Closes #2724
Closes #2685
Closes #1308
Closes #2191
Closes #1862
Closes #2711
Closes #2025
Closes #1243
Closes #1237
Closes #1115
Closes #1156
Closes #1757
Closes #1593
Closes #1732
Closes #1509
Closes #1404
🤖 Generated with Claude Code