Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/skills/agent-conduct/SKILL.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions .agents/skills/comment-and-doc-style/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,10 @@ gate. It reports a prose comment that opens its own line, in the diff's scope. A
modified line as an added one, so rewording one and re-indenting one each report it. That is the
rule's cost and the label is its answer, since a comment worth keeping takes the same label as a
comment worth writing. A trailing comment is out of scope. That is because which mid-line marker
opens a comment differs by language in ways a gate cannot settle from the marker alone. A docstring is not
a comment line, an instruction to a tool is not a comment the rule reads, and Markdown is out of
scope.
opens a comment differs by language in ways a gate cannot settle from the marker alone. A line
holding code after a block comment's closer is out of scope too, since deleting it deletes that
code. A docstring is not a comment line, an instruction to a tool is not a comment the rule reads,
and Markdown is out of scope.

Deleting the comment is the ordinary answer, since the bullets above already say what one has to
earn. Where a comment is genuinely owed, and a rule requiring one is the clearest case of that, the
Expand Down
8 changes: 4 additions & 4 deletions .agents/skills/local-strict-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ In the hub, `.husky/pre-push` checks the receipt at the push itself. So the mome
| The refusal says | What it means | What clears it |
| --- | --- | --- |
| No local review covers this branch's current content | The ordinary missing pass: no recorded receipt covers what this push delivers, either because none was recorded or because the content moved after one was | One pass over the branch's whole diff, recorded per "Recording the Pass" above |
| Tracked content differs from HEAD | A push delivers HEAD while a receipt covers the index and working tree, so the receipt does not describe this push. The hook prints the same headline for an unresolved merge and for a `git update-index --refresh` that exited above 1, naming each on its own line | Commit what is being pushed, then the pass, then the record. Where the change also carries the canonical ledger, record those passes before that commit, per "The Carried-Content Sweep" above, since a ledger written after it leaves the tree differing from HEAD again. Resolve the merge first where the hook names one, and run `git status` first where it names the refresh, since the content may not differ at all |
| The commit is not this worktree's HEAD | Any pushed branch ref carrying an object id that is neither this worktree's HEAD nor the all-zero id of a delete, which a push from a checkout sitting elsewhere reaches and so does a multi-ref push such as `git push --all` | Push one branch, the one this worktree holds. Where another branch is the one wanted, check it out in its own worktree first, per `repo-worktree` |
| Any wording saying the gate did not or could not run | An execution boundary rather than a verdict, which blocks because a gate that waves a push through when it could not run has stopped gating. The cause is named in that same message or in the engine error printed above it, and it is a missing Python interpreter, an unresolvable target, an unreadable receipt, a git command that failed, or any unexpected failure | Whatever the message names, most often installing an interpreter per `docs/host-setup.md` or fetching the target branch. Never another pass |
| The recorded pass was run against X and this check measured Y, printed under the missing-pass headline | The hook reads `develop` and nothing else, so a branch based elsewhere is measured against `develop` whatever the pass targeted, and the engine deliberately prints no record command, since the one it would print records a pass over a diff nobody read | One more pass against the branch this work actually targets, where it does target the measured one. Where it does not, the gate cannot judge the branch at all and the bypass is its answer |
| Tracked content differs from HEAD | A push delivers HEAD while a receipt covers the index and working tree, so the receipt does not describe this push. The hook prints the same headline for an unresolved merge and for a `git update-index --refresh` that exited above 1. It names each on its own line | Commit what is being pushed, then the pass, then the record. Where the change also carries the canonical ledger, record those passes before that commit, per "The Carried-Content Sweep" above. That is because a ledger written after the commit leaves the tree differing from HEAD again. Resolve the merge first where the hook names one. Run `git status` first where it names the refresh, since the content may not differ at all |
| The commit is not this worktree's HEAD | Any pushed branch ref carrying an object id that is neither this worktree's HEAD nor the all-zero id of a delete. A push from a checkout sitting elsewhere reaches such a ref, and so does a multi-ref push such as `git push --all` | Push one branch, the one this worktree holds. Where another branch is the one wanted, check it out in its own worktree first, per `repo-worktree` |
| Any wording saying the gate did not or could not run | An execution boundary rather than a verdict, which blocks because a gate that waves a push through when it could not run has stopped gating. The cause is named in that same message or in the engine error printed above it. The cause is a missing Python interpreter, an unresolvable target, an unreadable receipt, a git command that failed, or any unexpected failure | Whatever the message names, most often installing an interpreter per `docs/host-setup.md` or fetching the target branch. Never another pass |
| The recorded pass was run against X and this check measured Y, printed under the missing-pass headline | The hook reads `develop` and nothing else, so a branch based elsewhere is measured against `develop` whatever the pass targeted. The engine deliberately prints no record command, since the one it would print records a pass over a diff nobody read | One more pass against the branch this work actually targets, where it does target the measured one. Where it does not, the gate cannot judge the branch at all and the bypass is its answer |

This table is the fleet's one enumeration of these, and every other surface states the principle and routes here rather than listing the shapes. That is deliberate. Every review round that added a shape also left a restatement of it somewhere else. Keeping one table is what stops the next round doing the same.

Expand Down
17 changes: 10 additions & 7 deletions .agents/skills/pr-review-conduct/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,23 @@ visible comments, routinely still carries a finding nobody has answered. Treatin
A Copilot round states its own count of open findings, which the digest reads as
`overview=T/M` beside the number of review threads that round opened. The digest's
`FINDINGS WITH NO THREAD` block counts the findings the round names that no open entry links
to a thread on the pull request. The round can name them in that count or in its findings
list. What the block counts is usually
to a thread on the pull request. The round can name them in that count, in its findings
list, or in its file table's findings column. What the block counts is usually
findings the round withheld, the same blind spot under a different name, and sometimes the
digest undercounting instead. Reading the review body is what tells the two apart, and nothing
else does. So read it and dispose of what it holds as this section's outcomes require. `T`
reads `?` where no count was found, which is a round stating none and equally one the digest
could not locate. So a `?` leaves this item unsatisfied and sends you to the body exactly as a
shortfall does. A round with a verdict other than the
clean one that counts no finding prints its headline under `VERDICT WITH NO COUNTED FINDING`,
and `status` and `wait` exit `50`. The
headline is the one place that round names what it flags, so answer it as a suppressed finding.
shortfall does. A round with a verdict other than the clean one stating no open finding
prints its headline under `VERDICT WITH NO COUNTED FINDING`, and `status` and `wait` exit
`50`. The headline is where that round names what it
flags, beside any findings list or file table it carries. So answer each as a suppressed
finding.
The exit code repeats on that head after the answer. A clean verdict on the same terms prints
its headline under `CLEAN VERDICT HEADLINE`, which changes no exit code. Read that headline,
since it can name a nit no thread carries, and answer any such nit with `comment`.
since it can name a nit no thread carries, and answer any such nit with `comment`. A clean
round whose findings list or file table names a finding prints none, since `FINDINGS WITH NO
THREAD` names those.
A finding `suppressed=` counts may be counted in the shortfall too. So answer what the body
holds rather than what the two numbers add up to.
What closing a finding owes turns on whether it is `pre-existing`, under the classes
Expand Down
8 changes: 5 additions & 3 deletions .agents/skills/python-codestyle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ form that the fleet baseline expects. Its header names the pip-form and lint-onl
`dependsOn`-only. Neither chains with `&&`, so the mirror runs the same on any task shell.

CI runs these same commands as the authoritative backstop in every directory the hub validator's
`python-directories` input declares. A repo declaring none has its root gated only where it tracks
`python-directories` input declares. Its `uvx` ruff runs at the version the hub's `python-tool-pins`
action pins rather than at `@latest`. So a ruff release can make a local run and CI disagree until
the caller's hub pin moves to a release carrying the new version. A repo declaring none has its root gated only where it tracks
a root `pyproject.toml`, per `WORKFLOW.md` D1.2. That undeclared root is gated more loosely. CI
reads its type-checker configuration only from the `[tool.mypy]` or `[tool.pyright]` section of its
`pyproject.toml`. It skips the type check where neither is there,
Expand Down Expand Up @@ -285,8 +287,8 @@ Before pushing or opening a PR:

A command-line script is one a person or an agent runs by name. A hook its host runs, taking its input from that host rather than from a command line, is not one.

- **Every command-line script answers `--help` and `-h`** with the same text on stdout, then exits 0, changing nothing. That text opens on a usage line naming the script. An agent learns a script's interface by asking it, so a script that reads `--help` as an input acts in a way nobody predicted.
- **An argument the script does not recognize is refused**, with a non-zero exit before any read or write. The refusal names it as an unknown or unrecognized option, argument, flag, or parameter, and PowerShell's own refusal of a parameter it cannot bind counts. An unrecognized first argument is never taken as a default mode or as a target.
- **Every command-line script answers `--help` and `-h`** with the same text on stdout, then exits 0, changing nothing. That text opens on a usage line naming the script. An agent learns a script's interface by asking it, so a script that reads `--help` as an input acts in a way nobody predicted. A PowerShell script declaring its own parameters answers `-Help` and `-h` instead, from a `-Help` switch carrying an `h` alias. That form follows PowerShell's own parameter convention, so such a script owes no answer to a literal `--help`. A wrapper that forwards its arguments to another script answers whatever that script answers.
- **An argument the script does not recognize is refused**, with a non-zero exit before any read or write. The refusal names it as an unknown or unrecognized option, argument, flag, or parameter, and PowerShell's own refusal of a parameter it cannot bind counts. So a PowerShell script declaring its own parameters refuses a literal `--help` like any other unrecognized argument. Where no parameter takes the remaining arguments, the binder's refusal does that. A script with such a parameter refuses a dash-prefixed leftover itself. An unrecognized first argument is never taken as a default mode or as a target.

<!-- /include -->

Expand Down
22 changes: 13 additions & 9 deletions .agents/skills/python-codestyle/references/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,25 @@ Tool configuration alone marks the lint-only one:
pytest from it as `.venv/bin/python -m pytest`. A directory declared in the hub validator's
`python-directories` input runs ruff and the type checker from that environment where it
installs them. It otherwise runs them through `uvx`, with the checker pointed at that
environment. The undeclared default root runs `uvx ruff@latest` and a bare
`uvx <checker>@latest`, with nothing installed.
environment. The undeclared default root runs ruff through `uvx` at the pinned version the
lint-only profile below names, and a bare `uvx <checker>@latest`, with nothing installed.
- **Scripts** (the `lint-only` profile): stdlib-only utility scripts (e.g. a
Python tooling subtree of a `csharp` app). Run the tools with `uvx` (no project install,
no lockfile). The `pyproject.toml` carries only tool config (`[tool.ruff]`, `[tool.mypy]`, and
an optional `[tool.pyright]` editor block). There is no `[project]`, no `[build-system]`, and no
`uv.lock` (that metadata would misrepresent it as a shippable package). mypy is the type-check
gate (there is no first-party package for pyright strict to anchor on). A `[tool.pyright]`
block in standard mode keeps Pylance quiet in the editor, the same mypy-gate/pyright-editor
split the build profile uses. There is no lockfile, and a `uvx <tool>@<ver>` pin in a `run:`
step is not something Dependabot tracks. So CI runs `uvx ruff@latest` / `uvx mypy@latest` rather
than a manual pin that would silently go stale. The fleet rule is to pin only what Dependabot
auto-updates (SHA-pinned actions, package deps) and otherwise run latest. So the VS Code tasks,
README, and CI all run the unpinned latest here. `.py` files follow the repo's LF line-ending
default (per GOVERNANCE.md's "Line Endings" section). There is no pytest suite, and `unittest` is
split the build profile uses. There is no lockfile, and a `uvx <tool>@<ver>` literal in a `run:`
step is not something Dependabot tracks. The fleet rule is to pin only what Dependabot
auto-updates (SHA-pinned actions, package deps) and otherwise run latest. A manual pin would
silently go stale. So CI runs ruff at the version the hub validator's
`python-tool-pins` action reads from the `requirements.txt` beside it, which the hub's
Dependabot pip ecosystem bumps. A caller reaches that version at the hub commit its workflow
pins, so a ruff release reaches its lint only through a hub release. CI runs `uvx mypy@latest`,
and a carrier's VS Code tasks and README run the unpinned latest of every tool. The hub's own
tasks and hook take that `requirements.txt` as a requirement instead. `.py` files follow the
repo's LF line-ending default (per GOVERNANCE.md's "Line Endings" section). There is no pytest suite, and `unittest` is
the runner instead. The directory still owes tests, written with the standard
library's `unittest` so they need no test runner installed. Each is a `test_<script>.py`
under a `tests/` directory beside the scripts it exercises and their `pyproject.toml`
Expand All @@ -72,7 +76,7 @@ Tool configuration alone marks the lint-only one:
owes the same gates whatever its profile: lint, format, a type check, a test suite, and a
coverage report to Codecov. The hub validator runs them in each directory the caller declares
in its `python-directories` input, which the registry's `pythonDirectories` mirrors. From inside
a lint-only directory it runs `uvx ruff@latest check`, `uvx ruff@latest format --check`,
a lint-only directory it runs `uvx ruff@<pin> check`, `uvx ruff@<pin> format --check`,
`uvx mypy@latest`, and `uvx coverage@latest run -m unittest discover -s tests`. It adds
`--with-requirements tests/requirements.txt` to that last where the directory carries one. It then
writes `coverage.xml` and uploads it best-effort per `WORKFLOW.md` D1.6, with no threshold
Expand Down
Loading
Loading