Repository navigation
Conversation
## Summary Implements #3616 as the maintainer decided on it: a Dependabot-managed ruff pin with no fleet canary. - **The manifest.** A new `python-tool-pins` composite action carries `requirements.txt` with `ruff==0.17.3`, the current PyPI release and the version the hub's own code already passes. Its one step reads that pin from `$GITHUB_ACTION_PATH` and fails, naming the file, unless exactly one `ruff==<version>` line is there. It does so without `mapfile`, so the test also runs under macOS's stock bash 3.2. - **The validator.** `validate-task.yml` reaches the action as `$/.github/actions/python-tool-pins`, so it resolves at the reusable workflow's own commit. A carrier calling the workflow at a hub pin therefore runs that pin's ruff rather than anything in its own tree. Both lint-only `uvx` calls, `ruff check` and `ruff format --check`, now run `uvx "ruff@$RUFF_VERSION"`. A declared pip directory whose venv installs ruff, and a uv directory, keep their own versions as before. - **Dependabot.** The hub's `.github/dependabot.yml` gains a `pip` pair, main and develop, on `/.github/actions/python-tool-pins`, so the next ruff release opens a hub pull request. The hub's own CI calls the workflow locally, so that bump is linted against the hub's code before it merges. It then reaches carriers at a named hub release. - **Hub-local runs.** The hub's `.husky/pre-commit`, the `OPERATIONS.md` local block, and its own `.vscode/tasks.json` ruff tasks run `uvx --with-requirements .github/actions/python-tool-pins/requirements.txt ruff ...`. That constrains ruff to the pin, so a local run here still matches CI. A probe with a manifest pinning `ruff==0.15.22` resolved 0.15.22 that way. - **Docs and spec.** `spec/project-types.json` `python.scripts.uvx`, the python-codestyle skill (`SKILL.md` and `references/profiles.md`), and `docs/reusable-workflows.md` now say CI's uvx ruff runs the hub's pin. mypy, pyright, and coverage still run `@latest`. A carrier's local tools (the catalog's VS Code and pre-commit snippets, the skill's local commands) still run ruff `@latest`, since #3616 covers the validator only. The skill now names the skew that leaves, and says it ends when the caller's hub pin moves to a release carrying the new version. The change adds comment lines, so it carries the `comments` label. Closes on promotion: #3616 ## Verification - `tests/test_release_guards.py` gains `test_tool_pins_read_exactly_one_ruff_pin`. It runs the action's step against the hub's own manifest and against constructed manifests: one with a comment, no pin, a range, and two pins. It also gains `test_tool_pins_manifest_is_dependabot_tracked_on_both_branches`. The existing `test_ruff_prefers_a_declared_pip_directory_venv` now expects `uvx ruff@<pin>`. - The full unittest suite ran 3105 tests, OK (skipped=7). - `uvx ruff@0.17.3 check .` and `format --check .` are clean on the hub. mypy, `repo_gate.py` (composite-actions included), `spec/validate.py`, `build_dist.py --check`, actionlint, and the prose gate with `--allow-comments` are clean too. - The full unittest suite ran again on the final head: 3105 tests, OK (skipped=7). The hub's own pre-commit hook ran the pinned ruff on each commit. - Recorded `local-strict-review` passes ran before each push. - The first raised two `introduced` findings: `docs/reusable-workflows.md` and the python-codestyle `SKILL.md` still described the fallback as `ruff@latest`. Both are fixed in ee4ed5b. - The second raised four, all fixed in 7180e2f. They were the `mapfile` read under bash 3.2, a hand-rolled `step_script`, the hub's hook and `OPERATIONS.md` claiming to match CI while running `@latest`, and the skill naming the wrong release as the end of the skew. - The third raised the redundant `skipUnless(shutil.which("bash"))` decorator, which Copilot raised too. It is fixed in 853ba38. - The passes on the fix push raised two more, both fixed. One was the hub's own VS Code ruff tasks still running `@latest`, fixed in b248df8. The other was the spec and profile text then misdescribing the hub, plus the hook's and `OPERATIONS.md`'s separate sed readers, fixed in 633642c. - The last pass raised one design finding, declined below on evidence. ## Declined findings - `.github/actions/python-tool-pins/action.yml` read step, `introduced`, design: the finding says the multi-line half of the one-pin check guards a failure that is already loud, since a second unkeyed line in `$GITHUB_OUTPUT` fails the step. Declined. It is one more condition in the `if` the empty-pin check needs anyway, and the finding itself says that check stays. Its error names the manifest and the expected `ruff==<version>` shape, which a runner refusal of a malformed output line does not. The `two pins` subtest of `test_tool_pins_read_exactly_one_ruff_pin` pins that message. The finding's alternative, `uvx --with-requirements` in the validator, would float silently to latest if the manifest lost its ruff line. So it would need the same presence check. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) ## Summary A Copilot `ccr-overview-v2` round can open on "Approval recommended" and state "No open issues". Its narrative can still name findings in a nested "Review findings remain unresolved:" list and in the file table's Findings column. The reader counted none of them. So the digest printed `CLEAN VERDICT HEADLINE` for a round it said counts no finding, and `wait` exited 0 with nothing pointing at the findings. - The nested label is now a findings-list spelling in `scripts/reviewers/copilot.json`. - The file table's Findings column is read through a new `table_findings` vocabulary key. One `table_cells` reader replaces `table_paths`, so the paths and the column come from a single walk. - A new `Reading.listed` field holds the larger of the list count and the filled Findings cells, since both name the same findings. `unthreaded` takes it into account, so `FINDINGS WITH NO THREAD (2)` prints for the body in #3610. - `Reading.open` stays the count the round states. So `overview=T/M` and its `?` reading keep their meaning for the Merge Gate. - A clean round whose list or table names a finding no longer prints `CLEAN VERDICT HEADLINE`. A flagging round in the same shape still exits 50 as it did on `develop`. - No exit code changes. The documented contract keeps `FINDINGS WITH NO THREAD` advisory. Closes on promotion: #3610 ## Verification - `tests/test_pr_review_copilot.py` and `tests/test_pr_review.py` gain constructed cases for the #3610 shape, the list alone, the column alone, a stated count beside the lists, and a flagging verdict that still exits 50. Each new case fails against the base reader. - The whole suite passes (`python -m unittest discover -s tests`), `tests/test_pr_review_size.py` included. - ruff format, ruff check, mypy, the prose gate, `build_dist.py --check`, and the eol gate pass. ## Local pass findings The first push's spent edit budget left four `introduced` findings open. The next push fixed each: - `scripts/pr_review_digest.py` dropped the headline under a flagging verdict carrying a findings list. Fixed in 872b4ed, which also added the test assertion for it. - `scripts/pr_review.py` `--help` said the headline alone names what the round flags. Fixed in 872b4ed. - Lines this change edited ran past the wrap width. Rewrapped in 872b4ed. - The flagging wording named only the findings list, while `listed` can come from the file table alone. The pr-review-conduct skill still called the headline the one place. Fixed in dd213c6. A later pass raised one more `introduced` finding, also fixed: - `scripts/pr_review_copilot.py` the `Reading` docstring said `listed` is the findings the Findings column names, while a cell counts once however many it names. Fixed in fc8eb49, which states the possible undercount. The pass over fc8eb49 raised no finding. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Closes on promotion: #3622 Aligns the comment copies the two parallel sentence-length slices split differently, drops the stale counts, and puts the Scripts README rollout wording in the present tense. - Parameter-scope, native-command, and WSL_UTF8 comments read one wording across host-setup. - Removed "four functions", "four scripts", "four lines", and "fourth script" counts that did not match the code. - Rewrote past-tense rollout wording in scripts/README.md. docs/fleet-map.md is untouched. The change edits comment lines, so it carries the `comments` label. The local strict review pass raised three findings, all fixed in the second commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
… Prompt (#3646) ## Summary Splits the `GOVERNANCE.md` "Communicating with the User" command bullet by where the command runs. - The bullet opens with a placement test. A command runs outside this session where this session's input line cannot run it or cannot hold its effect, such as one waiting on typed input, one meant for another host, or one setting a variable the session reads at launch. Every other one runs at the session's input line, where that line can run a command. - A command run outside the session stays in the question's own text, as before. - A command run at the session's input line, a `!` line on Claude Code, never goes in an interactive prompt, since an open prompt blocks the place it runs. It opens a plain message as a fenced block holding the `!` line. Any question the turn owes follows as a numbered list, then any report. The message asks the user to reply once it has run, the turn ends with no prompt open, and the agent reads back the state or output on the next message. - The "Ask every question", "Raise work blocked on the user", and parked-queue handoff bullets each name such a turn as an exception that carries its questions in that message. The `session-handoff` skill's own steps 4 and 5 and "The Parked Decision Queue" say the same. - The `agent-conduct` and `session-handoff` include copies are regenerated with `scripts/build_dist.py`. Closes on promotion: #3638 ## Local review findings Every finding the earlier local passes raised was fixed in a later push. The last pass, over the current head, raised one `introduced` finding, declined with evidence below. 1. `introduced`, declined: the pass asked for a fourth example, a command that never exits such as a foreground server, among the outside-session cases. The test sentence already states the property, "where this session's input line cannot run it or cannot hold its effect", and a process that outlives the line's run is one the line cannot hold. The examples after it illustrate that property rather than closing it. A fourth example adds length without changing what the rule decides. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary - `session-handoff` "The Attended Session" gains a step 0: clone the hub's `main` into a new directory under the fleet worktree directory as the session's first command, with the command in the step. That clone is the checkout `$handoff` runs from, and it is pulled fast-forward before step 6 writes. - Step 0 says that wherever the skill was loaded from is never the session's hub checkout, and leaves task worktrees off a base clone to `repo-worktree`. - "Running the Chain" now says `<hub-checkout>` is a hub checkout of the session's own, never the maintainer's, and drops the in-hub relative-path exception. - `unattended-handoff` "The Seats" stops citing that removed exception, and says a seat clones its own hub checkout on `main` the way step 0 does. - Distributions regenerated with `scripts/build_dist.py`. Where a private checkout lives long-term and who removes it stays #3330's subject, closed under the decision on #3391. This change is about when the clone is made. Closes on promotion: #3604 ## Local pass findings The two `introduced` findings the first push listed, the orchestrator being named as a cloning seat and Picker step 6 forbidding the picker's own clone, are fixed in 9e0a7de. A further pass over that commit raised none. Each unattended round now leaves a picker clone and a worker clone under the fleet worktree directory. Removing them is the subject #3330 named, closed under the decision on #3391, so this change sets none. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary
`host-setup/linux/install-tools.sh`'s `package_installed` matched dpkg's
whole `${Status}` against `install ok installed`. A held package, whose
status is `hold ok installed`, therefore read as missing and was planned
for install again. `setup-github.sh` already read a hold as installed,
so the two hub copies of the check disagreed.
- **One definition.** Both scripts now carry the same
`package_installed`, which compares `${db:Status-Status}` to
`installed`. Each Linux script stays independently fetchable, per
`host-setup/README.md` "Three Rules This Directory Follows", so the
definition is an identical copy rather than a sourced file. A new test
in `tests/test_setup_github.py` holds the two copies equal, and the
README's list of duplicated helpers now names it.
- **Held Docker conflicts.** With a hold now counted, the Docker
conflict removal would hand a held conflict to `apt-get remove -y`,
which refuses it with exit 100, while a `-s` simulation passes.
`docker_install` now reads `${db:Status-Want}` first. Where any name on
Docker's uninstall list is held, it warns with the `apt-mark unhold`
remedy and returns before removing anything, so `docker` lands in the
failed set. That covers every name on the list, `docker-doc` included,
on purpose. A held `runc` or `containerd` beside an unheld `docker.io`
would otherwise remove the distro engine and then fail the `docker-ce`
install, leaving the host with no engine.
## Verification
- `python3 -m unittest tests.test_install_tools
tests.test_setup_github`: 78 tests pass, with 1 skipped. The new tests
fail against the base branch's `install-tools.sh`.
- Run in a throwaway `debian:13` container with `less` and `runc`
installed and held. Both scripts read the held `less` as installed.
`apt_missing` does not plan either held package. `docker_install`
reports the held `runc`, returns 1, and leaves it installed. In the same
container, `apt-get remove -y` on the held `runc` exits 100 and `apt-get
remove -s` exits 0, which is why a dry run is not the evidence.
- `docker_lint.py` passes shellcheck, shfmt, editorconfig-checker,
markdownlint, and cspell. The pre-commit hook passes ruff, mypy, and the
prose gate.
- The local strict review ran three passes. The first raised a reuse
finding, fixed by moving the equality test onto the existing
`function_body` helper. The second found that leaving a held conflict
installed while still removing the others could remove the engine, fixed
by restoring refuse-before-removing. The third raised nothing.
Closes on promotion: #3511
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary `CODESTYLE.md` "Command-Line Arguments" required every command-line script to answer `--help` and `-h`. A PowerShell script declaring its own parameters takes the `-Help` switch with an `h` alias instead, as the hub's own `host-setup` scripts do, so a literal `--help` reached the unknown-argument path. Read literally, the rule put every such script in breach. The maintainer already chose to keep the PowerShell form, so this changes the rule text only. - **Bullet 1** now says a PowerShell script declaring its own parameters answers `-Help` and `-h` and owes no answer to a literal `--help`. A wrapper forwarding its arguments to another script answers whatever that script answers. - **Bullet 2** now says such a script refuses a literal `--help` like any other unrecognized argument. The binder does that where no parameter takes the remaining arguments. A script with such a parameter refuses a dash-prefixed leftover itself, as `install-agents.ps1`, `install-tools.ps1`, and `setup-wsl.ps1` already do. - The `python-codestyle` and `shell-codestyle` Skills carry the section as a generated include, regenerated with `scripts/build_dist.py`. ## Verification - `uv run --no-project --script scripts/build_dist.py --check` reports the generated distributions current. - The `.husky/pre-commit` gate passes, prose lint included. - Three `local-strict-review` passes ran. The first two found claims the hub's own scripts contradicted: the remaining-arguments scripts and the two forwarding wrappers. Both were fixed. The third found nothing. Closes on promotion: #3602 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…#3654) ## Summary The prose gate's `sentence-length` rule read only paragraph inline units. So a sentence in a Markdown table cell was never counted. A table cell holds prose as a paragraph does. So each header and body cell is now its own sentence block, held to the same cap. Two short cells on one row never join into one sentence. A blockquoted table stays unread, as a blockquoted paragraph already is. - `.github/actions/prose-gate/prose_lint.py`: `extract_markdown` builds a `paragraph` unit for each inline token under `th_open` or `td_open`, as it already did under `paragraph_open`. `sentence-length` is the only rule reading `paragraph` units, so no other rule starts reading cells. - `tests/test_prose_lint.py`: new cases cover a body cell, a header cell, and two cells on one row judged apart. The structure test drops its table-row case, the exemption this issue ends. - The table cells the stricter check reported in hub-authored content are reworded under the cap. Those cells are in `AGENTS.md`, `WORKFLOW.md` section 5, the `local-strict-review` skill, `catalog/snippets/workflows/README.md`, `docs/host-setup.md`, `host-setup/windows/README.md`, and `scripts/README.md`. The skill distributions are regenerated with `scripts/build_dist.py`. **Downstream effect.** Carriers fetch the prose gate from the hub's `main`. Once this is promoted, a change touching a table row whose cell holds an over-cap sentence fails the gate there. The composite action runs diff-scoped, so only touched rows are read. That is the intended effect of the fix. Closes on promotion: #3456 ## Verification - The issue's repro now reports both `probe.md:5` (the cell) and `probe.md:7` (the paragraph). - `python3 scripts/prose_lint.py .` over the whole tree reports no violations. - `python -m unittest discover -s tests` passes on the final head. Its one failure on the first commit was the old table-row exemption this change ends. - `scripts/build_dist.py --check` reports the generated distributions current. Docker markdownlint, cspell, and editorconfig-checker pass, and so do ruff check and ruff format. - Six `local-strict-review` passes ran over the whole diff. Each of the first five found meaning drift or an ambiguous pronoun in a reworded cell, fixed in the commit after it. The sixth found no defect in this change. ## Pre-existing findings, filed - `.github/actions/prose-gate/prose_lint.py:1103`, `pre-existing`: `rule_semicolon` splits a table row on raw `|`, so an escaped `\|` splits a cell and raises a false semicolon finding. Filed as #3655. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) ## Summary The semicolon rule split a Markdown table row on every pipe, so an escaped `\|` cut its cell in two. A comma before the escaped pipe then no longer excused the semicolon list after it, and the rule reported semicolons the whole cell allows. A cell now ends only at a pipe no backslash escapes, the same escape markdown-it-py honors when it splits a row. ## Why Not the Parser's Cell Tokens The issue proposed reading the `th_open` and `td_open` inline tokens the `sentence-length` rule reads. A local review pass found that loses text the row split reads today. - A table inside a blockquote yields no cell units, since the extractor skips blockquotes, so its rows would be read whole. - markdown-it-py drops any body cell past the header's column count, so a semicolon there would never be read. Keeping the row split and fixing only where it ends a cell closes the issue's case and keeps both of those. ## Changes - `.github/actions/prose-gate/prose_lint.py`: `rule_semicolon` splits a row with `CELL_BREAK`, a pipe no backslash precedes. - `tests/test_prose_lint.py`: an escaped pipe stays inside its cell, at top level and inside a blockquote. The row-per-cell test now uses a real table. - `scripts/README.md`: states the escape rule. ## Verification - The issue's repro now reports no `semicolon` violation, and reported two before. - The prose gate suite passes, and both new tests fail against the old split. - A whole-tree `semicolon` and `sentence-length` run is unchanged. ## Local Review Three recorded `local-strict-review` passes. The first raised the two regressions above, which moved the fix off the parser tokens. The second raised one `introduced` overstatement in the docstring and README, which was narrowed. The third raised nothing. The pre-existing finding that the split runs after code spans and quotations are blanked is filed as #3657. Closes on promotion: #3655 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…3660) ## Summary The prose gate's Markdown rules blanked code spans and quotations across a whole table row before any cell split. So a cell boundary inside either one was lost. - markdown-it-py ends a cell at an unescaped pipe inside a code span. Blanking the span first merged those two cells, and a comma in the first then excused a semicolon list in the second. - An unpaired `"` in one cell, such as an inch mark, paired with a quote in a later cell. Every cell between them was blanked, so no rule read them. The semicolon rule is the one the issue names. A local review pass found the same defect class in the `dash`, `dupword`, `spelling`, and `dead-path` rules, all in the same file, so every site moves onto one helper here. ## Changes - `.github/actions/prose-gate/prose_lint.py`: - `TABLE_ROW` and `row_cells` split a row opening with a pipe, blockquoted or not, at each pipe no backslash escapes. - `by_cell` applies a blanker one cell at a time and rejoins the cells, so every pipe that ends a cell stays where it was. - `prose_lines`, `unit_texts`, and the `dead-path` code-span and link scans each go through it. `rule_semicolon` reads the blanked row from `prose_lines` as before. - `tests/test_prose_lint.py`: both of the issue's cases for the semicolon rule, a quotation inside one cell still blanked, the unpaired-quote case for `dash`, `dupword`, and `spelling`, a code span across cells for `dash`, and two `dead-path` cases. - `scripts/README.md`: states that a row opening with a pipe is blanked a cell at a time, and why. ## Verification - The issue's repro now reports four `semicolon` violations, two on each body row, and reported none before. The issue says five. Counting the cells it names gives four: `e; f; g` holds two semicolons and `a; b; c` holds two. - The prose gate suite passes, 640 tests. Every new test fails against the base `rule_semicolon` and blanking code. - A whole-tree prose gate run is unchanged, with no violations before or after. ## Local Review Three recorded `local-strict-review` passes. - The first raised that the fix covered only the semicolon rule while the other rules shared the defect. Fixed by the shared helper. - The second raised a second row check in `rule_semicolon`, a code-span token scan in `dead-path` still reading the whole row, and docs wider than the code for rows with no leading pipe. All three were fixed. - The third raised one finding, that `rule_semicolon` still split a row itself beside `row_cells`. That push's edit budget was spent, so it went out listed as open and was fixed on the next push, which now calls `row_cells`. - The fourth, over that push, raised nothing. Closes on promotion: #3657 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## Summary A job record can stay `IN_PROGRESS` after its workflow run has completed. `pr_review.py status` and `wait` read it as a check still running, so a driver waits on a record no run will update. This change names that shape and says how to clear it. - `check_nodes` marks a check run that is still `IN_PROGRESS` while its suite has completed as `stale`. It also carries the run's id on every check run. - `check_shape` judges a stale node `STALE_RECORD` at any age. The digest prints `CHECK RECORD STALE` with the run id and both remedies, a re-run of that job or a new head. - A required stale record on a `BLOCKED` merge takes exit `44`. It is not settling, so it holds no poll. - A stale record in an older run counts as finished for superseding. So while a newer run of the same workflow is still going on the head, the poll holds instead of exiting `44` on a record that run will replace. ## Changes - `scripts/pr_review_checks.py` was at 447 lines against its 450 ceiling. So `STUCK_LINES` and `check_lines` move first into a new reader, `scripts/pr_review_check_lines.py`, which gets its own size ceiling and its own place in the reader import guards. Their inline comments move into docstrings. - The new shape is added to the `--help` text, the `CHECKS_NOT_MERGEABLE` line, and `scripts/README.md`. - The test fixture `check()` now gives a running job an in-progress suite unless a case names the suite's status, since a running job in a completed suite is the shape this change reads as stale. - New tests cover the shape at two ages, the digest line, the `44` exit, the poll that no longer holds, and the newer-run supersede. Each one fails with the reader change reverted. ## Verification - `python -m unittest discover -s tests`: 3128 tests OK (7 skipped), run before the two review-fix commits. After them, the `test_pr_review*` suites pass (565 tests). - The pre-commit hook (ruff, mypy, prose gate, eol) passes on every commit. - A local strict review ran three rounds. Round 1 found the older-run supersede gap and a docstring inaccuracy. Round 2 found a dangling `/` in the superseded line. Both were fixed, and round 3 found nothing. Closes on promotion: #3362 🤖 Generated with [Claude Code](https://claude.com/claude-code)
#3665) This closes the one #1664 shape that the lexer-based prose gate still reads as a comment and that a fix can remove without trading a visible false positive for a silent false negative. - **A line holding code after a block comment's closer is not a `comment-added` line.** A new `Line.trailed` flag marks it, and a later comment on that line does not count as code. Deleting such a line, as `comment-added` asks, would delete that code and leave the comment unterminated. The case is covered for CSS, TypeScript, C#, JSONC, HTML, XML and csproj. - **A heredoc body in a workflow `run:` block stays code, as develop reads it.** This is the answer on decision #3666. Eight recorded `local-strict-review` passes over a hand-built reading of shell each found new shapes it read as data where bash runs the body as code. Each such error silently drops a real comment from `comment-added`, `comment-wrap` and `comment-case`. Develop's reading errs only toward a visible false positive, which the `comments` label clears. So this shape from #1664 is recorded as accepted rather than fixed, and the heredoc commits on this branch are withdrawn by the latest commits rather than rewritten out of its history. - **Measured but not reproduced, so not changed:** at develop `b09f957c`, the TOML `"""` string, the Terraform heredoc, the extensionless `.husky/pre-push`, and a multi-line double-quoted YAML scalar under an ordinary key all read clean. - `scripts/README.md` and the `comment-and-doc-style` skill state the closer exclusion. The skill's distributions are regenerated. ## Verification - The full suite passes, with 3123 tests run and 7 skipped. - The closer test fails against develop, and a variant of `code_follows` that stops at the second comment on a line fails it in all seven languages. - ruff, mypy, the diff-scoped and whole-tree prose gate, `build_dist.py --check`, and the eol gate are clean. Closes on promotion: #1664 🤖 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.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3667 +/- ##
==========================================
+ Coverage 81.69% 81.72% +0.03%
==========================================
Files 26 27 +1
Lines 9111 9128 +17
==========================================
+ Hits 7443 7460 +17
Misses 1668 1668
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.
🟡 Changes recommended
Two active P1 issues remain: Markdown table parsing mishandles even backslash parity, and review triage can undercount multiple findings in one cell.
2 open issues
What changed in this PR
This pull request promotes the changes merged into develop since promotion #3636 to main, improving validator pinning, Markdown prose checks, review-finding accounting, host setup behavior, session guidance, and synchronized documentation and skills.
Changes:
- Pins validator Ruff execution through a Dependabot-managed requirements manifest.
- Extends prose checks to Markdown table cells and handles block-comment closers.
- Improves Copilot finding parsing, stale-check detection, held-package handling, and session prompt guidance.
- Updates related tests, documentation, generated skills, and tooling configuration.
- Three review findings remain concerning Markdown table boundaries, pipe-leading paragraph classification, and multiple findings in one Copilot table cell.
| File | Description |
|---|---|
WORKFLOW.md |
Rewords workflow test scenarios into shorter sentences. |
tests/test_setup_github.py |
Tests held-package detection and identical Linux helper definitions. |
tests/test_release_guards.py |
Tests pinned Ruff resolution and Dependabot tracking. |
tests/test_prose_lint.py |
Adds table-cell and block-comment parsing coverage. |
tests/test_pr_review_size.py |
Adds the new check-lines module ceiling. |
tests/test_pr_review_copilot.py |
Tests findings-list and table-based Copilot findings. |
tests/test_install_tools.py |
Tests held packages and Docker conflict handling. |
tests/test_bootstrap.py |
Removes stale script-count wording. |
spec/project-types.json |
Updates the lint-only Ruff versioning contract. |
scripts/reviewers/qodo.json |
Adds the optional table-findings vocabulary field. |
scripts/reviewers/copilot.json |
Adds unresolved-list and findings-column parsing. |
scripts/reviewers/coderabbit.json |
Adds the optional table-findings vocabulary field. |
scripts/pr_review.py |
Updates review and stale-check guidance. |
scripts/pr_review_rounds.py |
Accounts for listed findings in verdict handling. |
scripts/pr_review_digest.py |
Reports findings from lists and file tables. |
scripts/pr_review_copilot.py |
Parses Copilot finding lists and file tables. |
scripts/pr_review_checks.py |
Detects stale jobs in completed workflow runs. |
scripts/pr_review_check_lines.py |
Centralizes digest text for check states. |
OPERATIONS.md |
Uses the pinned Ruff requirements manifest locally. |
host-setup/windows/upgrade-host.ps1 |
Aligns the WSL encoding comment copy. |
host-setup/windows/setup-wsl.ps1 |
Aligns script and output-stream comments. |
host-setup/windows/README.md |
Updates host-tool comparison wording. |
host-setup/windows/install-tools.ps1 |
Removes stale function-count wording. |
host-setup/windows/install-agents.ps1 |
Clarifies the nested-scope parameter comment. |
host-setup/README.md |
Documents the duplicated installed-package helper. |
host-setup/menu.ps1 |
Clarifies parameter and compatibility comments. |
host-setup/linux/setup-github.sh |
Reads dpkg's normalized installed status. |
host-setup/linux/install-tools.sh |
Handles held packages before Docker conflict removal. |
host-setup/bootstrap.ps1 |
Removes stale script and function counts. |
GOVERNANCE.md |
Defines where session-input commands and questions belong. |
docs/reusable-workflows.md |
Documents the hub-pinned Ruff fallback. |
docs/host-setup.md |
Updates the uv tool role description. |
CODESTYLE.md |
Documents PowerShell help and unknown-argument behavior. |
catalog/snippets/workflows/README.md |
Splits long workflow table-cell sentences. |
AGENTS.md |
Clarifies routed procedure and skill descriptions. |
.vscode/tasks.json |
Runs local Ruff through the pinned requirements manifest. |
.husky/pre-commit |
Aligns the hook with CI's pinned Ruff version. |
.github/workflows/validate-task.yml |
Reads and applies the validator's Ruff pin. |
.github/skills/workflow-ci-contract/references/test-methodology.md |
Regenerates workflow test-methodology prose. |
.github/skills/unattended-handoff/SKILL.md |
Regenerates unattended handoff instructions. |
.github/skills/shell-codestyle/SKILL.md |
Regenerates shell command-line rules. |
.github/skills/python-codestyle/SKILL.md |
Regenerates Python toolchain and command-line rules. |
.github/skills/python-codestyle/references/profiles.md |
Regenerates Python profile guidance. |
.github/skills/pr-review-conduct/SKILL.md |
Regenerates review-finding handling guidance. |
.github/skills/local-strict-review/SKILL.md |
Regenerates local review guidance. |
.github/skills/comment-and-doc-style/SKILL.md |
Regenerates comment and prose rules. |
.github/skills/agent-conduct/SKILL.md |
Regenerates session communication rules. |
.github/dependabot.yml |
Adds daily pip updates for the Ruff manifest on both branches. |
.github/actions/python-tool-pins/requirements.txt |
Pins Ruff for validator execution. |
.github/actions/python-tool-pins/action.yml |
Reads and validates the Ruff pin. |
.github/actions/prose-gate/prose_lint.py |
Adds table-cell processing and block-comment closer handling. |
.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/test-methodology.md |
Regenerates the Claude workflow reference. |
.claude-plugin/fleet-skills/skills/unattended-handoff/SKILL.md |
Regenerates the Claude unattended handoff skill. |
.claude-plugin/fleet-skills/skills/shell-codestyle/SKILL.md |
Regenerates the Claude shell skill. |
.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md |
Regenerates the Claude Python skill. |
.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md |
Regenerates the Claude Python profile reference. |
.claude-plugin/fleet-skills/skills/pr-review-conduct/SKILL.md |
Regenerates the Claude review-conduct skill. |
.claude-plugin/fleet-skills/skills/local-strict-review/SKILL.md |
Regenerates the Claude local-review skill. |
.claude-plugin/fleet-skills/skills/comment-and-doc-style/SKILL.md |
Regenerates the Claude documentation skill. |
.claude-plugin/fleet-skills/skills/agent-conduct/SKILL.md |
Regenerates the Claude agent-conduct skill. |
.claude-plugin/fleet-skills/.source-digests/workflow-ci-contract |
Updates the workflow skill digest. |
.claude-plugin/fleet-skills/.source-digests/unattended-handoff |
Updates the unattended handoff digest. |
.claude-plugin/fleet-skills/.source-digests/shell-codestyle |
Updates the shell skill digest. |
.claude-plugin/fleet-skills/.source-digests/session-handoff |
Updates the session handoff digest. |
.claude-plugin/fleet-skills/.source-digests/python-codestyle |
Updates the Python skill digest. |
.claude-plugin/fleet-skills/.source-digests/pr-review-conduct |
Updates the review-conduct digest. |
.claude-plugin/fleet-skills/.source-digests/local-strict-review |
Updates the local-review digest. |
.claude-plugin/fleet-skills/.source-digests/comment-and-doc-style |
Updates the documentation digest. |
.claude-plugin/fleet-skills/.source-digests/agent-conduct |
Updates the agent-conduct digest. |
.agents/skills/workflow-ci-contract/references/test-methodology.md |
Updates the canonical workflow reference. |
.agents/skills/unattended-handoff/SKILL.md |
Updates the canonical unattended handoff skill. |
.agents/skills/shell-codestyle/SKILL.md |
Updates the canonical shell skill. |
.agents/skills/python-codestyle/SKILL.md |
Updates the canonical Python skill. |
.agents/skills/python-codestyle/references/profiles.md |
Updates the canonical Python profile reference. |
.agents/skills/pr-review-conduct/SKILL.md |
Updates the canonical review-conduct skill. |
.agents/skills/local-strict-review/SKILL.md |
Updates the canonical local-review skill. |
.agents/skills/comment-and-doc-style/SKILL.md |
Updates the canonical documentation skill. |
.agents/skills/agent-conduct/SKILL.md |
Updates the canonical agent-conduct skill. |
Review effort: Lite
Answers the Copilot finding raised on promotion #3667 against `scripts/pr_review_copilot.py`, which #3642 introduced. - **A Copilot Findings cell now counts each finding it names.** The file table's Findings column counted one finding per filled cell, so a second finding in the same cell went uncounted. On a clean-verdict round that leaves it out of triage. A new per-reviewer vocabulary pattern, `table_finding_marker`, is `\[P\d\]` for Copilot and empty for CodeRabbit and Qodo. A filled cell counts each marker it carries, and once where it carries none, so no count drops below what it was before. - The `Reading` docstring states the new counting. ## Verification - The full suite passes, with 3123 tests run and 7 skipped. - The new subtest, a cell carrying two markers beside a cell carrying none, counts 3. It fails against develop's adapter, which counts 2. - ruff, mypy, the diff-scoped prose gate, and the eol gate are clean. ## Dropped findings - `scripts/pr_review_copilot.py`: a `[Pn]` written inside a code span or in prose about another finding also counts. The only effect is a higher count in the digest's no-thread line, a loud failure rather than a silent one, so it is left as is under "Trust Boundaries and Hardening Effort". Closes on promotion: none. The finding was raised on #3667 and has no issue of its own. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…mment Rules (#3675) Promotes the changes merged into `develop` since promotion #3667 to `main`. - [#3674](#3674) Exempts a Python script's PEP 723 metadata block from every comment rule. The block's lines leave the comment run before any rule reads it, and only a closed `# /// script` block qualifies. Closes #3634 🤖 Generated with [Claude Code](https://claude.com/claude-code)


Promotes the changes merged into
developsince promotion #3636 tomain.uvx ruffto a Dependabot-managed manifest.-Helpand-hform in the command-line argument rules.pr_review.py.comment-added. Its squash commit ondevelopcarries the pull request's original title, which names a heredoc reading. That reading was withdrawn before the merge on decision Decide How the Prose Gate's Heredoc Half of #1664 Proceeds #3666, so a workflowrun:heredoc body still reads as code.[Pn]marker in a Copilot Findings cell, so a second finding in one cell is no longer dropped from triage. It answers one of the two findings Copilot raised on this promotion. The other is declined with a parser probe in its thread.Closes #3616
Closes #3610
Closes #3622
Closes #3638
Closes #3604
Closes #3511
Closes #3602
Closes #3456
Closes #3655
Closes #3657
Closes #3362
Closes #1664
🤖 Generated with Claude Code