Skip to content

Release v4.3.1 - #25

Merged
countzero merged 14 commits into
mainfrom
develop
Sep 23, 2026
Merged

countzero merged 14 commits into
mainfrom
develop

Conversation

@countzero

Copy link
Copy Markdown
Owner

A patch release that keeps sca usage and sca monitor readable when a network's IPv6 route silently drops packets. The trigger was a network where IPv6 stopped working: .NET connects IPv6 first and falls back to IPv4 only after Windows abandons the attempt (measured 21.1 s), so every request hit the old 12/15/10 s budgets and every row showed error, while curl and Claude Code kept working. Upgrading is replacing the file; no interface changed.

v4.3.1

  • Raised the usage, token and profile HTTP budgets to 30 s, above the Windows connect fallback, so a broken IPv6 route costs about 21 s per new connection instead of an error.
  • Replaced .NET's 101-character, localized HttpClient.Timeout sentence with request timed out after Ns, chosen by exception type.
  • Word-wrapped footer lines to the render width with a hanging indent under the [Tag] prefix; terminal-wrapped continuation rows used to start at column 0, outside the frame inset.
  • Ported the version-number and changelog rules from ai_comfyui into docs/conventions.md (a MAJOR/MINOR/PATCH table for this script, one entry per change, the four prose cases, an optional bold component prefix in Common Changelog's own form).
  • Added the trim-prose skill, adapted to PowerShell and this repository's scratch and branch rules, and the rule that multi-step work keeps the todo tool current.
  • Ran two whole-repository trim-prose passes over every comment, document and skill (about 3,460 fewer words), then corrected four comments the pass found to be wrong and padded eight tables that predated the padding rule.

Shortcomings

  • The 30 s budget only rescues Windows. Linux gives up on a dead connect after about 127 s, so the same network still times out there.
  • While IPv6 is broken, a poll of three slots can outlast the 60 s watch interval, and the frame stays frozen until it finishes. It shows real numbers, just slowly.
  • A genuinely unreachable endpoint now takes up to 30 s per slot to report, instead of 12 s.
  • The comment pass is large (about 1,800 changed lines). A token-stream comparison proves no code token, test name or -Because string changed, and that every markdown heading and fenced block is byte-identical, but the judgment calls on wording are only as good as a read.

Feedback wanted

  • Whether 30 s is the right trade, or whether a real IPv4-first connect is worth pursuing. It was tried: a SocketsHttpHandler.ConnectCallback written as a PowerShell class hung every request, and one variant crashed the host, because the hook runs on a pool thread in the caller's runspace. An Add-Type C# connector works (0.4 s instead of 21 s) but was ruled out to keep the script pure PowerShell.
  • A skim of the script's comment diff for anything a pass cut that you would have kept.

Not done

  • No automatic IPv4 fallback; the budget increase is the whole fix.
  • The 30 s path has been verified live only on a healthy network. The broken-IPv6 case was measured with standalone probes, not with sca itself, since IPv6 recovered before the change landed.

Steps 1 and 2 of cutting a release had homes, in conventions.md for the
version-and-changelog commit and in pull_requests.md for the release pull
request. Everything after the merge had none: where the tag goes, what the
release body contains, that the asset is attached by a workflow, and what to
check afterwards were carried by whoever last did it.

Its own document rather than a section of pull_requests.md, because the task
is distinct. A reader writing a pull request description and a reader cutting
a tag arrive with different questions, and documentation.md routes by the
task the reader is doing.

The two traps recorded are the ones already paid for. v4.2.0 shipped a
compare link reading v4.1.0...v4.3.0 against a repository name three renames
stale, which stayed merely broken until v4.3.0 existed and then began
resolving to a superset of what v4.2.0 contained. And publishing as a
prerelease or a draft leaves a release with no asset, because the workflow
that uploads it either skips the event or never sees it.

The digest check earns its place for the same reason: the workflow uploads
the file at the tag, so a release published against the wrong target ships a
plausible file for the wrong commit and every other check still passes.
The document described the tag placement and the shape of the body but never
showed the invocation that produces them, which documentation.md requires of
a procedure. Its absence is not cosmetic: with no command to run, the way to
publish is to open the previous release, copy its body and edit the version
numbers, and that copy is how v4.2.0 shipped a compare link reading
v4.1.0...v4.3.0 with only one of the two versions updated, carrying a
repository name three renames stale along with it.

Considered and rejected: generating the body from CHANGELOG.md in a workflow.
It would make both mistakes unrepresentable, but at 326 lines of script, tests
and YAML guarding a two-line body that has been wrong once in seventeen
releases, and it would add a failure path that can leave a release with no
notes at all. The command below costs six lines and removes the copy that
caused the defect.
Ported from a sibling repository and rewritten for this one: PowerShell instead of bash, scratch under .tmp/sessions/<session-id>/ as the Scratch files rule requires, develop/main as the comparison bases, and the Pester suite plus the byte budgets as its Verify step. The console output encoding is forced to UTF-8 because the Windows default code page decodes git's output so that a search for an arrow or an umlaut matches nothing.
…he frame

A timed-out request left .NET's 101-character HttpClient.Timeout sentence on the row, and every footer line longer than the terminal was wrapped by the terminal itself. A terminal-wrapped row starts at column 0, outside the frame inset that is added per logical line, so the watch footer broke out of its margin.

The timeout reason is now 'request timed out after Ns', chosen by exception type because the .NET message is localized. Format-UsageFooter word-wraps each line to the render width with a hanging indent under the '[Tag] ' prefix, and wraps nothing when the width is unknown.
.NET connects to the addresses DNS returns one after another, IPv6 first, and moves to IPv4 only when Windows abandons the attempt, measured at 21.1 s. On a network whose IPv6 route silently drops packets, the 12/15/10 s budgets therefore failed every request that IPv4 would have answered, while curl and Claude Code kept working.

All three budgets are now 30 s. A healthy network is unaffected; a broken IPv6 route costs about 21 s per new connection instead of an error. An in-process IPv4-first connect hook was tried and dropped: PowerShell code in a SocketsHttpHandler.ConnectCallback runs on a pool thread and hung or crashed the host.
A trim-prose pass over the comments the timeout and footer fixes added: the budget rationale states the current behavior rather than the past, a sentence restating the line of code beneath it goes, and a paragraph left over-long by an edit is re-wrapped to the file's width.
This repository followed Semantic Versioning without saying what counts as its interface, so every release decided the bump afresh. The new Version numbers section names the interface (actions, parameters, environment variables, themes, -Json output, the files an earlier version wrote, the PowerShell minimum) and maps it to MAJOR, MINOR and PATCH.

The Changelog section gains three rules from the same source: one entry per change rather than per commit, prose earning an entry in four cases only, and an optional bold component prefix, written in Common Changelog's own section 2.4.4 form rather than ai_comfyui's bracket tags so the file stays inside the spec it claims.
Ported from fertilizer_management (DUN-370). A multi-step task run without a visible task list leaves the human unable to tell what is done, what is in flight and what was dropped until the final summary; one item in progress at a time, ticked off as it finishes, makes the session followable while it runs.
Two trim-prose passes over every document and skill, the second auditing the first. Cut history lessons, narrated routes to a decision, meta-commentary, restated rationale (now a pointer to its home) and inventories that rot; kept every measured number, platform fact and failure mode. Headings and fenced code blocks are byte-identical to before, so no pointer into these files moves. Lines -82 +58, words -1462 +1099.
Two trim-prose passes over every comment in the script, tools/ and the CI workflow, the second auditing the first. A token-stream comparison against the previous commit confirms no code token changed, only comment text. The suite passes unchanged at 98.7% coverage. Lines -405 +268, words -4141 +2679.
Two trim-prose passes over every comment in tests/, the second auditing the first. Test names, -Because strings and code are untouched (verified by token-stream comparison); comments naming the regression a test pins were tightened, not cut, and history phrasing now states the current contract. Lines -570 +396, words -5485 +3851.
Get-Slots' docblock said it fingerprints slots against .credentials.json; it reads the active slot from the state file and hashes nothing. Invoke-Tests.ps1 described Pester's coverage target as the gate, contradicting the paragraph below it that explains why Pester 5.7.1 does not enforce it, and its rounding example still used the old 90% threshold. A list test's comment had its sidecar condition inverted. The pr-code-review skill called this a Windows project; CI runs on all three platforms.
Eight tables predated the padding rule in docs/conventions.md -> Punctuation. Cell text is unchanged; only the padding moved.
A patch release: the HTTP budgets, the timeout reason and the footer wrapping change no interface (docs/conventions.md -> Version numbers). The documentation and comment passes shipped alongside earn no entry under the four prose cases.
@countzero
countzero merged commit ed9ac6e into main Sep 23, 2026
3 checks passed
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.

1 participant