Skip to content

Pin the Prose Gate and Its Data to One Commit via git ls-remote - #3420

Merged
ptr727 merged 3 commits into
developfrom
fix/hub-fetch-run-pin-companion-sha
Oct 24, 2026
Merged

ptr727 merged 3 commits into
developfrom
fix/hub-fetch-run-pin-companion-sha

Conversation

@ptr727

@ptr727 ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the finding the third Copilot round on the develop -> main promotion #3417 raised against catalog/snippets/hub_fetch_run.py, under the maintainer's ruling on it.

Where the API lookup of main's commit failed, the snippet fetched prose-gate.json and prose_lint.py from the moving main ref in separate requests. The two could then come from different commits, pairing a new vocabulary with an old parser. That happens when a commit lands between the requests or when the raw CDN serves one file from cache.

  • A second lookup. lookup_via_git() runs git ls-remote https://github.com/ptr727/ProjectTemplate refs/heads/main under LOOKUP_TIMEOUT, with GIT_TERMINAL_PROMPT=0. resolve_main_commit() calls it only after the API lookup fails. It accepts exactly one <sha>\trefs/heads/main line, and every other shape returns a named cause.
  • One commit for every file. Either resolved commit names the ref both files are fetched at, so the script and its data always pair. The provenance label names that commit.
  • The documented fail-open stays. Where neither lookup resolves, one stderr line names both causes and the gate runs against main. The docstring says why: a hook with no network cannot fetch the gate at all, and the CI gate is the enforcement.
  • Prose. GOVERNANCE.md "Running the Linters Locally (Known-Working Invocations)" and the husky and pre-commit snippet READMEs name the git ls-remote call beside the API lookup.

Tests

Constructed in tests/test_hub_fetch_run.py, with the network and git stubbed:

  • test_git_fallback_pins_the_script_and_its_data_to_one_commit: a rate-limited API lookup with a resolving git ls-remote fetches both files at the git commit, in order, and prints nothing.
  • test_git_fallback_is_not_run_when_the_api_resolves, and test_lookup_only_for_the_prose_gate asserting no git call for another script.
  • test_fallback_causes_print_a_line_and_the_gate_still_runs asserts the git cause in the one line, and both files fetched at main.
  • GitLookupTests covers the accepted line, the command, timeout, and prompt setting, and each failure shape. Those are a non-zero exit, a missing git, a timeout, and unexpected output (empty, a short hash, two lines, upper case).

Local review

Three recorded passes at the frontier tier, the edit budget spent on the second round.

  • The first pass found four, and 03665d5 fixes three. Those are a mypy redefinition of sha, and a Windows wait on a remote helper's stderr pipe after a timeout. The third is a GOVERNANCE.md sentence whose "those" bound only to uv. The fourth is declined below.
  • The second pass found two, both fixed in 9b49229: the network-calls sentence left out the script fetches, and one docstring line ran past 100 columns.
  • The third pass covers the head and found two introduced findings, open under the spent budget:
    • tests/test_hub_fetch_run.py:196, introduced: DATA_PATH repeats a path the test at line 370 spells locally and hub.COMPANIONS holds. Declined. A test pins the literal path rather than reading the module's own constant. A rename in the snippet then fails the test instead of passing with it.
    • tests/test_hub_fetch_run.py:2, introduced: the module docstring's subject list does not name the git ls-remote fallback. Declined as style. The list stays true, since the fallback feeds the provenance path it names.

Declined from the first pass: a host's global url.insteadOf can rewrite https://github.com/ to SSH. There ls-remote can prompt for a key or a host key on the terminal. That host configuration is the maintainer's own, the prompt is visible rather than silent, and it is reached only after the API lookup fails. GOVERNANCE.md "Trust Boundaries and Hardening Effort" rules out hardening for it.

Verification

  • uv run --no-project --with-requirements tests/requirements.txt python -m unittest discover -s tests -> Ran 2860 tests, OK (skipped=7).
  • uvx ruff@latest format --check ., uvx ruff@latest check, and uvx mypy@latest -> clean.
  • python3 scripts/build_dist.py --check -> Generated skill distributions are current.

🤖 Generated with Claude Code

Where the API lookup of main's commit fails, hub_fetch_run.py resolves it
through git ls-remote, so prose_lint.py and prose-gate.json are fetched at
one commit and always pair. Where neither lookup resolves, the gate still
runs against main, since a hook with no network cannot fetch the gate at all
and the CI gate is the enforcement.
Copilot AI lite review requested due to automatic review settings October 24, 2026 14:20
@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 9b4922901f2887e29cff3b9fcff368a9ef37d009, the content this pull request carries at that commit against develop, and it recorded 2 findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The reviewed changes have no approval-blocking issues; one minor documentation nit remains.

No open issues 🎉

What changed in this PR

This pull request ensures the prose gate script and companion data are fetched from the same resolved commit, using a validated git ls-remote fallback when the GitHub API lookup fails.

Changes:

  • Adds bounded, non-interactive Git commit resolution with strict output validation.
  • Pins both prose-gate files and their provenance to one commit.
  • Preserves fail-open behavior when neither lookup resolves.
  • Expands fallback, failure, timeout, and environment tests.
  • Updates governance and hook documentation.
File Summary
tests/​test_hub_fetch_run.py Adds coverage for fallback resolution, commit pinning, validation, failures, timeouts, and subprocess configuration.
GOVERNANCE.md Documents API and Git lookup behavior for downstream hooks.
catalog/​snippets/​pre-commit/​README.md Documents the Git fallback for pre-commit users.
catalog/​snippets/​husky/​README.md Documents the Git fallback for Husky users.
catalog/​snippets/​hub_fetch_run.py Adds Git-based commit resolution and commit-pinned fetching for the prose gate files.

Review effort: Lite

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.78%. Comparing base (20e8270) to head (9b49229).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3420   +/-   ##
========================================
  Coverage    80.78%   80.78%           
========================================
  Files           23       23           
  Lines         8848     8848           
========================================
  Hits          7148     7148           
  Misses        1700     1700           
Flag Coverage Δ
python-3.13 80.78% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ptr727

ptr727 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

Answer to the headline of the Copilot round on 9b492290, "one minor documentation nit remains". The round names no nit in a thread or in its body, so nothing locates it. The documentation nit on record for this head is the module docstring of tests/test_hub_fetch_run.py not naming the git ls-remote fallback. It is Listed in the body under "Local review", declined as style because the list stays true.

@ptr727
ptr727 merged commit a19ed7f into develop Oct 24, 2026
14 checks passed
@ptr727
ptr727 deleted the fix/hub-fetch-run-pin-companion-sha branch October 24, 2026 14:33
ptr727 added a commit that referenced this pull request Oct 24, 2026
…#3417)

## Summary

Promotes the pull requests merged into develop since release 2.0.1148.
Each carries a maintainer decision of 2026-10-23 recorded on #3391.

- [#3407](#3407): rewrites
the write guard as a small lexer of 1,653 lines. It fails open under its
stated threat model and fails closed only on requirement 4. A test holds
it at 2,500 lines or fewer (item 1).
- [#3409](#3409): adds
CODESTYLE rules. Tests live in `tests/`, and a maintained parser
replaces a hand-written one. A script declares its dependencies in PEP
723 metadata and runs as `uv run --no-project --script`. It switches the
callers to that spelling and adds a managed allow rule to the
agent-safety installer (item 1 follow-ups).
- [#3410](#3410): splits
`pr_review.py` into the gate, a Copilot adapter reading its vocabulary
from JSON, and `pr_cleanup.py`. It collapses the exit codes and adds
`tests/requirements.txt` and the CI runners.
- [#3411](#3411): rebuilds
the prose gate on Pygments and markdown-it-py, with its vocabulary and
exemptions in `prose-gate.json` and a repo-local override.
- [#3415](#3415): holds
the Merge Gate on a part of a Copilot review body the tooling cannot
place. The hold lasts until an owner acknowledges it with outcomes (item
4 follow-up).
- [#3416](#3416): moves
the audit self-test to `tests/` and reads YAML and Markdown with PyYAML
and markdown-it-py. It adds the check registry `spec/checks.json` and
splits out `spec/audit_markdown.py`. It shares `spec/carried_text.py`
with carry, `build_dist`, and `canonical_review`.
- [#3418](#3418): fixes
the findings this promotion's first review round raised on the content
above. It aligns the drive-pr escalation line with pr-review-conduct and
names `tests/requirements.txt` where the prose said the tests need
nothing installed. It also restores the `uvx` launcher in a
release-guard assertion.
- [#3419](#3419): fixes
the finding the second review round raised. The Copilot adapter's prose
path reads a coverage count longer than `COUNT_DIGITS` as `unknown`,
sharing `count_state` with the marker path.
- [#3420](#3420): fixes
the finding the third review round raised, under the maintainer's
ruling. `hub_fetch_run.py` falls back to `git ls-remote` where the API
lookup of `main` fails, so the prose gate and its data are fetched at
one commit. Where neither lookup resolves, the documented fail-open
against `main` stays.
- [#3421](#3421): fixes
the findings the fourth review round raised. The Copilot adapter reads a
finding count longer than `COUNT_DIGITS` as unknown rather than zero,
through one length check and one None-aware sum. The host-setup
gates-and-tests row says `uv` installs the test requirements.

Closes #3408

## Constituent coverage

The Copilot rounds on this promotion ran at Lite effort and state no
full coverage, so Merge Gate item 2 rests on the promotion case. Each
change this promotion carries had full coverage on its own pull request
into develop, at its merged head:

| Pull request | Merged head | Coverage |
| --- | --- | --- |
| [#3407](#3407) |
`9efc1002` | attested local pass, `coverage=local` |
| [#3409](#3409) |
`bcc7a9e1` | attested local pass, `coverage=local` |
| [#3410](#3410) |
`00cec726` | attested local pass, `coverage=local` |
| [#3411](#3411) |
`bd128136` | attested local pass, `coverage=local` |
| [#3415](#3415) |
`5be9db87` | attested local pass, `coverage=local` |
| [#3416](#3416) |
`b914f083` | attested local pass, `coverage=local` |
| [#3418](#3418) |
`3a86cb51` | attested local pass, and a Copilot table naming exactly the
changed files, `coverage=table` |
| [#3419](#3419) |
`6e7b868d` | attested local pass, and a Copilot table naming exactly the
changed files, `coverage=table` |
| [#3420](#3420) |
`9b492290` | attested local pass, and a Copilot table naming exactly the
changed files, `coverage=table` |
| [#3421](#3421) |
`743010e6` | attested local pass, and a Copilot table naming exactly the
changed files, `coverage=table` |

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants