Visitar URL original
Let the Prose Gate Choose a Commit's Diff Base, Pair Code Spans as Markdown Does, and Re-Raise Hook Interrupts by ptr727 · Pull Request #4145 · ptr727/ProjectTemplate · GitHub
Skip to content

Let the Prose Gate Choose a Commit's Diff Base, Pair Code Spans as Markdown Does, and Re-Raise Hook Interrupts - #4145

Merged
ptr727 merged 12 commits into
developfrom
burndown/hook-chain-gate
Nov 13, 2026
Merged

ptr727 merged 12 commits into
developfrom
burndown/hook-chain-gate

Conversation

@ptr727

@ptr727 ptr727 commented Nov 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • The prose gate chooses a commit's diff base itself (Diff a Merge Commit Against MERGE_HEAD in the pre-commit Framework Snippet's Prose Gate #4131). prose_lint.py --diff-commit diffs against HEAD, against both parents while a merge is in progress, and against the empty tree before a first commit. On a merge it keeps the lines both the MERGE_HEAD and the HEAD diff name, the lines new against both parents, and a move one parent's diff records only where the other parent lacks the new path. A moved file reports only what no recorded source held. The empty tree is hashed in the format extensions.objectFormat names, SHA-1 where unset, which a git before 2.29 can read. The pre-commit framework snippet passes it in its entry, which stays one command line, so a merge commit no longer reads the merged-in parent's lines as added on any host. Both Husky.Net hooks drop their own copy of that choice. hub_fetch_run.py drops its unborn-HEAD rewrite, which the gate now owns, and which hard-coded the SHA-1 empty tree. --diff beside --diff-commit is refused.
  • Code spans pair as Markdown pairs them (Pair Code Spans as Markdown Does in sentence-length and dead-path #4135). mask_code_and_quotes (sentence-length) blanks spans through blank_code_spans, so an escaped backtick opens no span. dead-path reads a new masked unit, each inline token's spans spaced out as Markdown pairs them, so a span wrapped across a line hides no later link or span, and a link inside a wrapped span is read as code.
  • The Husky hooks re-raise an interrupt (The Husky Pre-Commit Snippet Sets No INT or TERM Trap That CODESTYLE.md Interrupts Requires #4123). The snippet and the hub's .husky/pre-commit trap INT and TERM, stop the step running in the background, remove the list file, print one line, and re-raise the signal. .husky/pre-push gains the traps it lacked, with the review engine run in the background. A launcher (uvx, uv run, dotnet, the xargs call) stays in the foreground, since the trap's kill reaches only $! and a backgrounded launcher's tool would ignore Ctrl-C.
  • hub_fetch_run.py handles SIGINT and SIGTERM (Handle SIGINT and SIGTERM in hub_fetch_run.py #4108). One KeyboardInterrupt path terminates and waits for the uv child, the temporary tree is removed as it unwinds, one line is printed, and the signal is re-raised at the __main__ call site (exit 130 on Windows). prose_lint.py, edited here, takes the same path. Both take SIGINT and SIGTERM through one handler and pass over a later signal, such as the SIGTERM uv run forwards after a Ctrl-C reached its process group.

Tests

  • tests/test_prose_lint.py: --diff-commit on a merge, a merge where both parents changed one file, a move only one parent made, a move the resolution makes of a file either parent added or moved, a plain commit, a first commit in a SHA-1 and a SHA-256 repository, and beside --diff; an escaped backtick for sentence-length; wrapped and escaped spans for dead-path.
  • tests/test_pre_commit_hook.py: the interrupt cases now assert the hook died by the signal, a signal to the hook alone stops its background step, and the pre-push hook stops its engine on either signal, to its group or to it alone.
  • tests/test_prose_lint.py: the gate, its first git call held open, is signalled mid-run and asserted dead by the signal with no traceback.
  • tests/test_hub_fetch_run.py: the helper, run under its interpreter with the network stubbed, is signalled mid-run and asserted dead by the signal, with its child and fetched tree gone.
  • Each new interrupt case was run against the develop copies of the hooks and the helper and fails there.

Local review

local-strict-review passes before each push. Before the opening push, the first raised five findings, disposed as:

  • Backgrounded launchers left their tools ignoring Ctrl-C: fixed, launchers stay in the foreground.
  • hub_fetch_run.py duplicated first-commit handling: fixed, removed.
  • Duplicated test process-group helpers: fixed, test_hub_fetch_run.py imports them.
  • A redundant symbolic-ref probe in commit_base: fixed, removed.
  • Husky.Net's generated _/husky.sh re-runs the hook in an inner sh, so a signal sent to the outer shell alone does not reach the snippet's traps: declined. That outer shell is Husky.Net's generated file rather than anything the hub carries, and Ctrl-C reaches both shells as one process group, where both end by the signal (probed with dash).

The second raised two, both fixed: prose_lint.py lacked the interrupt path its edit owed, and the hooks' comment misnamed why a launcher stays in the foreground.

The third raised two, after the edit budget was spent:

  • introduced, declined as ownership elsewhere: CODESTYLE.md "Interrupts in Shell" names neither a POSIX sh script nor a launcher. It does not say that a launcher stays in the foreground, that dash runs no EXIT trap on a re-raised signal, or that sh has no array for pids. The hooks follow the rule's own reason, that the trap's kill reaches only $!, so a function, a group, a subshell, a pipeline, or sh -c runs in the foreground. CODESTYLE.md belongs to another group this round, so the wording gap is reported to the orchestrator rather than edited here.
  • Disproved: .husky/pre-push suppresses SC2317 and SC2329 for its trap-only function while the two sh hooks need none. The pinned koalaman/shellcheck:stable run passes all three, and refused pre-push with SC2329 before the suppression.

After the opening push, the pull request's review raised a git-before-2.29 first commit (fixed) and a wrapped span hiding a path (declined in its thread). The passes over those fixes raised:

  • A merge read the branch's own lines in a file both parents changed: fixed, the both-parents scope above.
  • A move only the branch made leaked into that scope, and the scope line still named MERGE_HEAD: fixed, the move filter, and the line now names MERGE_HEAD and HEAD.
  • The move filter had no test, merge test names still said one parent, a repository git cannot read refused naming the empty tree, and a SIGTERM uv run forwards during a SIGINT could escape as a traceback or decide the reported signal: each fixed, the last by one handler for both signals, with tests sending the pair.
  • A resolution moving a file only one parent added was read by neither diff's move list: fixed, each diff's moves count where the other parent lacks the path.
  • Where both diffs recorded a move to one path, one source was kept and the other's backlog read as new, and the mirror move had no test: fixed, every recorded source is subtracted, with tests.
  • The other-parent probe started one git process per move a merge brought in, staged or not: fixed, only a path left in the merge's both-parents scope is probed, which a clean merged-in rename is not.
  • introduced, declined as ownership elsewhere: CODESTYLE.md "Interrupts in Python" describes Python's own SIGINT handling and a SIGTERM handler alone, while both scripts route SIGINT through their handler to close the forwarded-SIGTERM race. Like the shell gap above, it is reported to the orchestrator, since CODESTYLE.md belongs to another group this round.

Closes on promotion: #4131, #4135, #4123, #4108

🤖 Generated with Claude Code

ptr727 and others added 3 commits November 12, 2026 23:24
…rkdown Does, and Re-Raise Hook Interrupts

- prose_lint.py gains --diff-commit: MERGE_HEAD during a merge, HEAD
  otherwise, the empty tree before a first commit. The pre-commit
  framework config takes it, so a merge commit no longer reads the
  merged-in parent's lines as added, and both Husky.Net hooks drop
  their own copy of that choice (#4131).
- mask_code_and_quotes and dead-path pair code spans through
  blank_code_spans, so an escaped backtick opens no span and a span
  wrapped across a line break hides no later link or span (#4135).
- The husky snippet and the hub's .husky hooks run their tools in the
  background, stop them from the INT and TERM traps, and re-raise the
  signal. pre-push gains the traps it lacked (#4123).
- hub_fetch_run.py stops its uv child, removes its fetched tree, prints
  one line, and re-raises SIGINT or SIGTERM, with a test that signals
  it mid-run (#4108).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the Gate

- A launcher (uvx, uv run, dotnet) runs in the foreground, since the
  trap's kill would reach it and not the tool it starts. Ctrl-C reaches
  the tool directly again, and a background step is one that stops its
  own children.
- hub_fetch_run.py drops its unborn-HEAD rewrite, which --diff-commit now
  owns, hashing the empty tree in the repository's own object format.
- The interrupt tests share one set of process-group helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ys in the Foreground

- prose_lint.py, edited here, takes CODESTYLE.md "Interrupts": one
  KeyboardInterrupt path, one line, the signal re-raised, with a test
  that signals it mid-run. It and hub_fetch_run.py ignore a second
  SIGTERM, which uv run forwards after its process group took one.
- The hooks' comment names the real reason a launcher stays in the
  foreground: in the background its tool ignores SIGINT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings November 13, 2026 07:57
@ptr727 ptr727 added the comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses label Nov 13, 2026
@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • 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

@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head a93bba5fa6a67c1f8e792e8aefaa02a71f092e64, 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.

🟡 Changes recommended

Two moderate active issues remain: first-commit diffs fail on older Git versions, and wrapped code spans can silently omit deleted paths.

2 open issues
What changed in this PR

This PR centralizes commit diff-base selection in the prose gate, aligns code-span masking with Markdown behavior, and improves interrupt cleanup across hooks and helper scripts.

Changes:

  • Adds --diff-commit support for merge, ordinary, and first commits.
  • Updates prose checks to pair escaped and wrapped Markdown code spans.
  • Adds signal handling, child cleanup, and signal re-raising for hooks and hub_fetch_run.py.
  • Expands regression coverage for diff bases, span masking, and interrupt behavior.
File Description
tests/​test_prose_lint.py Tests commit-base selection, Markdown span handling, and prose-gate interruption.
tests/​test_pre_commit_hook.py Tests hook cleanup, signal termination, and pre-push engine handling.
tests/​test_hub_fetch_run.py Tests helper subprocess cleanup and signal termination.
scripts/​README.md Documents the commit-aware prose-gate invocation.
GOVERNANCE.md Updates the hook diff-scope policy.
catalog/​snippets/​pre-commit/​README.md Documents the framework hook's commit-aware diff behavior.
catalog/​snippets/​pre-commit/​.pre-commit-config.yaml Passes --diff-commit to the fetched prose gate.
catalog/​snippets/​husky/​pre-commit Adds interrupt handling and commit-base selection to the Husky.Net hook snippet.
catalog/​snippets/​hub_fetch_run.py Adds signal-aware child-process and temporary-directory cleanup.
.husky/​pre-push Adds interrupt handling around the local review engine.
.husky/​pre-commit Adds interrupt handling and commit-aware prose-gate invocation.
.github/​actions/​prose-gate/​prose-gate.json Defines the new CLI option and conflicting-option error.
.github/​actions/​prose-gate/​prose_lint.py Implements commit-base selection, Markdown span masking, and signal handling.

Review effort: Lite

@codecov

codecov Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.70%. Comparing base (b38e084) to head (3e45ba0).
⚠️ Report is 184 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #4145      +/-   ##
===========================================
- Coverage    81.60%   76.70%   -4.91%     
===========================================
  Files           26       40      +14     
  Lines         9070    14148    +5078     
===========================================
+ Hits          7402    10852    +3450     
- Misses        1668     3296    +1628     
Flag Coverage Δ
python-3.13 76.70% <ø> (-4.91%) ⬇️

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 Nov 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

/review

@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

ptr727 and others added 3 commits November 13, 2026 00:08
…nswer

rev-parse --show-object-format arrived in git 2.29. An older git made
--diff-commit return HEAD on a first commit, which the gate then
refused. Such a git cannot open a SHA-256 repository, so an unset
extensions.objectFormat is SHA-1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Against MERGE_HEAD alone, a file both parents changed read the
branch's own committed lines as added by the merge. --diff-commit now
keeps a merge to the lines that also differ from HEAD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A merge commit's scope kept the MERGE_HEAD diff's moves, so a move the
branch alone made reported its path-dependent findings on the merge. A
move now counts only where the HEAD diff records it too, and a file in
both diffs stays in scope with no line, so such a move is still read.
The scope line names both bases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

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

ptr727 and others added 2 commits November 13, 2026 00:30
… a Broken Repository Refuses

- A merge keeps a move where HEAD's diff records it too or HEAD lacks the
  new path, so a move the resolution makes is still read, with a test
  each way.
- commit_base returns HEAD where git cannot read the repository, so the
  refusal names the base a commit would use.
- Once an interrupt is unwinding, a forwarded SIGTERM is ignored.
- Merge test names say both parents.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d an Unreadable Tree

- prose_lint.py and hub_fetch_run.py take SIGINT and SIGTERM through
  one handler, where SIGINT was not inherited as ignored. A later
  signal, the SIGTERM uv run forwards after a Ctrl-C, is passed over
  rather than cutting the unwinding short. Tests send that pair.
- The move filter is the HEAD-lacks-the-path test alone, which a
  rename in HEAD's diff already satisfies.
- Tests cover a resolution moving a file only the merged-in parent
  added, and a tree no repository holds refusing against HEAD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

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

ptr727 and others added 2 commits November 13, 2026 00:41
… the Path

A resolution moving a file only the branch added is recorded by the
HEAD diff alone, so a merge took no move from it and left the move's
findings unread. Each diff's moves now count where the other parent
lacks the new path. The interrupt comment names the one handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Where both parents' diffs record a move to one new path, the union kept
one source, so a finding the other parent's source already held read
as added by the merge. A moved file now reports only what no recorded
source held. Tests cover that collision and a move only the merged-in
parent made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head f749a637b4de815d66ff3df85cc3e3d020e48997, the content this pull request carries at that commit against develop, and it recorded 1 finding.

ptr727 and others added 2 commits November 13, 2026 00:50
A merge bringing in many renames started one git process per rename to
test the other parent, though the hook reads only the staged paths.
Only a moved path the run reads is probed now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A merge stages every rename the merged-in side made, so filtering on
the paths the run reads still probed each one. A clean merged-in
rename is unchanged against MERGE_HEAD and so out of the both-parents
scope, which is the filter now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 13, 2026

Copy link
Copy Markdown
Owner Author

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

@ptr727
ptr727 merged commit a878d9d into develop Nov 13, 2026
13 checks passed
@ptr727
ptr727 deleted the burndown/hook-chain-gate branch November 13, 2026 09:10
ptr727 added a commit that referenced this pull request Nov 13, 2026
…ct Four Carried Rules (#4149)

## Summary

- **The shell interrupt rule describes the hooks it governs (a
disagreement merged #4145 left).** `CODESTYLE.md` "Interrupts in Shell"
told a reviewer to background every long-running external command. The
hub hooks #4145 changed keep a launcher (`uvx`, `uv run`, `dotnet`,
`xargs`) in the foreground instead. A background child starts with
SIGINT ignored, and the tool a launcher starts inherits that, so a
backgrounded launcher's tool survives Ctrl-C. The rule now says a
launcher may run in the foreground, and must where it does not stop its
tool on SIGTERM. `hub_fetch_run.py`, which terminates the gate it
starts, stays a legitimate background child. A new bullet covers a
deliberately POSIX `#!/bin/sh` script such as a git hook: dash runs no
`EXIT` trap when the re-sent signal ends it, so the `INT` and `TERM`
traps release paths and locks themselves. The child's process ID is a
scalar such as `child`, since sh has no arrays, and every variable a
trap reads is set before the traps are. "Interrupts" now applies to
every shell script rather than every Bash one. "Interrupts in Python" is
untouched, since #4146 holds it.
- **The sh exception gives a reason that holds (#4140).** Measured
rather than taken from the issue: dash accepts `set -E`, reading it as
its emacs editing option, and rejects `trap ... ERR`. What aborts a
bash-form `#!/bin/sh` hook is `set -o pipefail` on a dash that predates
the option, which Ubuntu 24.04's does (`Illegal option -o pipefail`,
measured in an `ubuntu:24.04` container). The `GOVERNANCE.md` "Shells"
bullet and `shell-codestyle` both stated a reason that does not hold on
that dash, and both now state this one. No version number appears, since
the spec validator refuses a version literal in an instruction document.
- **The review engines are named as the hub's (#3916).** Both mentions
in "Verification Discipline" read "the hub-hosted `scripts/...`", which
"Hub-Hosted Tooling" requires of a tool a carried rule names.
- **The secret naming examples carry the owner field (#4114).** The
"Repo-Scoped Secrets" examples use a constructed short name, `widget`,
so none contradicts the `<shortName>_<purpose>` bullet beside them.
`widget` rather than the issue's `example` keeps a name such as
`widget_docker.env.example` from reading as two `.example` suffixes.
- **The Python profiles say a mypy section names its target (#3787).**
One paragraph in `python-codestyle`'s `references/profiles.md` covers
both profiles, since CI's type-check step passes mypy no path in either.
It covers a `mypy.ini`, `.mypy.ini`, or `setup.cfg` `[mypy]` section as
well as `[tool.mypy]`. The skill's description does not change.

Generated includes and the skill trees are rebuilt with
`scripts/build_dist.py`, and `--check` is clean.

Closes on promotion: #4140, #3916, #4114, #3787

## Local review dispositions

- Declined: the local pass asked to drop the `widget_` prefix from the
repo-scoped `.secrets/` examples, since only host `~/.secrets/` files
carry the owner rule. #4114 asks for every example in the section to
carry the owner field. A prefixed name is still lowercase fields joined
by `_`, so it satisfies `CODESTYLE.md` "Script and Utility File Names"
as well.

- Declined (`introduced`, design): the third local pass read the new
`references/profiles.md` paragraph as restating `python-codestyle`
`SKILL.md`'s build clean-compile note that mypy with no target exits
with an error. The `SKILL.md` sentence explains what the build-profile
clean-compile does in that layout. The new paragraph states the
requirement for both profiles and names the keys. Neither contradicts
the other, and the procedure keeps its own context rather than a bare
pointer.

- Disproved (`introduced`): the fourth local pass suspected `uv` resets
SIGINT before starting its tool, which would make "the tool a launcher
starts inherits that" false for `uvx` and `uv run`. Measured under a
backgrounded `dash -c`: a Python tool started by `uv run`, `uvx`, and
`xargs` each reports SIGINT as ignored (`1`, `SIG_IGN`).

## Pre-existing findings, not filed

- `docs/reusable-workflows.md` "Adopting the Gates", the mypy target
bullet: it names only a `[tool.mypy]` section, while the type-check step
also runs mypy with no path for a directory configured by `mypy.ini`,
`.mypy.ini`, or `setup.cfg` `[mypy]`. Class: incomplete instruction.
Outside this branch's file set.

## Verification

- `scripts/build_dist.py --check`: current.
- Prose gate, diff-scoped against `develop`: clean.
- `tests/test_spec_validate.py`, `tests/test_audit.py`,
`tests/test_audit_helpers.py`, `tests/test_build_dist.py`: pass.
`spec/validate.py`: OK.
- Shell claims measured with constructed probes on dash and bash, and on
`ubuntu:24.04`'s dash in a container.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Nov 13, 2026
… Rules (#4189)

## Summary

Promotes the backlog-burndown rounds and changes from other hub sessions
from `develop` to `main`.

- Hooks and the prose gate: #4132, #4134, #4136, #4145, #4152, #4184.
The Husky hook reads its path list once and diffs a merge against
`MERGE_HEAD`. Interrupts re-raise their signal, a Markdown code span
reads as quoted data, and the gate picks a commit's diff base and
recognizes a conflicted promotion's branch cut from `main`.
- Procedures and carried rules: #4133, #4139, #4141, #4149, #4166,
#4177, #4179, #4183, #4185. Resync, audit and check-this-repo procedure
gaps, code style and shell interrupt rules, review-loop gaps across four
skills, the context and delegation section of `AGENTS.md`, question
rules in governance, the promotion line in pull request bodies,
closing-keyword behavior on promotion, and the history-rewrite premise.
- Review and cleanup tooling: #4138, #4148, #4154, #4156, #4157, #4163,
#4164, #4168, #4174, #4180. Cleanliness reads, parked handoffs, the
backlog report's JSON output, exact inline script pins, trusted inputs,
env-file includes, the bounded review wait, side-reviewer matching, and
a Copilot billing-failure notice read as a refusal.
- Workflow and runbook contract: #4153, #4155, #4169, #4171, #4178,
#4182. The runtime-secrets check, a registry entry and spec references,
the Copilot runbook pointers, credential-free checkout steps, and the
deploy-key and runner wording.
- From other hub sessions: #4159 (a repository's own .NET line under a
fleet default), #4161 (the 1Password CLI as an optional host tool),
#4162 (Codex's Windows installer and one managed opencode copy). These
carry no promotion line.

#4182 carries no promotion line by design, and #4175 holds the split-out
part of #4057's scope. Both #1448 and #4175 stay open.

Fixes #1071
Fixes #1154
Fixes #1391
Fixes #1471
Fixes #1594
Fixes #1620
Fixes #1627
Fixes #1650
Fixes #1801
Fixes #2853
Fixes #3620
Fixes #3668
Fixes #3697
Fixes #3766
Fixes #3787
Fixes #3837
Fixes #3840
Fixes #3842
Fixes #3844
Fixes #3865
Fixes #3882
Fixes #3890
Fixes #3894
Fixes #3912
Fixes #3916
Fixes #3954
Fixes #4014
Fixes #4015
Fixes #4016
Fixes #4043
Fixes #4050
Fixes #4057
Fixes #4058
Fixes #4062
Fixes #4084
Fixes #4097
Fixes #4098
Fixes #4099
Fixes #4104
Fixes #4108
Fixes #4114
Fixes #4115
Fixes #4117
Fixes #4118
Fixes #4119
Fixes #4121
Fixes #4122
Fixes #4123
Fixes #4131
Fixes #4135
Fixes #4140
Fixes #4142
Fixes #4143
Fixes #4144
Fixes #4151

🤖 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

comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants