Skip to content

ts(B-0086): port 1 git script (.sh→.ts) — slice 13 of TS/Bun migration#892

Merged
AceHack merged 2 commits intomainfrom
lane-b/ts-bun-slice-13-push-with-retry-2026-04-30
Apr 30, 2026
Merged

ts(B-0086): port 1 git script (.sh→.ts) — slice 13 of TS/Bun migration#892
AceHack merged 2 commits intomainfrom
lane-b/ts-bun-slice-13-push-with-retry-2026-04-30

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented Apr 30, 2026

Summary

Slice 13 of the TS/Bun migration trajectory — one port:

  • tools/git/push-with-retry.{sh→ts} (git push retry wrapper for transient GitHub 5xx; thin-wrapper-over-existing-CLI exemption per docs/POST-SETUP-SCRIPT-STACK.md)

DST classification preserved

ACCEPTED_BOUNDARY (external network I/O + retry-on-failure) per docs/research/dst-accepted-boundaries.md §3 and Otto-168. Header comment carries the full registration context.

Audit substrate

See docs/trajectories/typescript-bun-migration/slice-audits.md Slice 13 entry.

Mechanical port notes

  • Bash [[ =~ $int_re ]] regex → POSITIVE_INT_RE.test().
  • Bash mktemp + tee + grep on tmp file → spawnSync with stderr captured in-memory; TRANSIENT_5XX_RE.test() against captured string.
  • Bash set +e; git push; exit_code=$?; set -e → straightforward result.status ?? 1.
  • Bash sleep $backoffAtomics.wait(view, 0, 0, seconds * 1000) synchronous-busy-wait (preserves the script's synchronous flow; async setTimeout would change exit-code semantics).
  • Exponential backoff doubling preserved (backoff *= 2).

Behavioural note vs bash

Bash uses tee for live-stream-AND-capture; TS uses spawnSync for capture-then-replay. UX difference invisible for typical git-push runtimes (seconds); for long pushes stderr appears in batches per attempt rather than streaming live. Documented in port header.

Test plan

  • bun --bun tsc --noEmit -p tsconfig.json clean (the new lint (tsc tools) gate from ci(B-0106): add lint-tsc-tools gate job — tsc --noEmit on tsconfig.json #890 will validate this in CI).
  • eslint clean on the new file.
  • Side-by-side equivalence on env-validation paths (GIT_PUSH_MAX_ATTEMPTS=foo and GIT_PUSH_BACKOFF_S=-1 both produce identical messages and exit code 2).
  • CI gate (gate.yml + CodeQL + new lint-tsc-tools).

Trajectory

🤖 Generated with Claude Code

* ts(slice-13, wip 1/N): port git/push-with-retry (.sh→.ts)

First script of slice 13. Thin retry wrapper over `git push` for
transient GitHub 5xx errors. DST-ACCEPTED-BOUNDARY classification
preserved (Otto-168, network I/O + retry-on-failure).

Byte-equivalent on env-validation paths. Network-dependent retry
path tested locally only (success-path requires real push; 5xx-
retry-path requires real 5xx).

Mechanical changes:
- bash `[[ =~ $int_re ]]` regex → POSITIVE_INT_RE.test()
- bash mktemp + tee + grep tmp file → spawnSync stderr-capture +
  TRANSIENT_5XX_RE.test() against captured string
- bash `set +e; git push; exit_code=$?; set -e` → result.status ?? 1
- bash `sleep $backoff` → Atomics.wait(view, 0, 0, seconds * 1000)
  synchronous-busy-wait (preserves the script's synchronous flow
  that the bash original assumes; async setTimeout would change
  exit-code semantics)
- Exponential backoff doubling preserved (`backoff *= 2`)

Behavioural note: bash uses `tee` for live + capture; TS uses
spawnSync for capture-then-replay. UX difference invisible for
typical git-push runtimes (seconds). Documented in port header.

Lint-clean: bun --bun tsc --noEmit + eslint strictTypeChecked +
sonarjs all pass on the new file.

* trajectory(ts-bun): slice 13 audit substrate + RESUME tracker

- slice-audits.md: append slice-13 audit (1 port — git/push-with-retry).
- RESUME.md: bump slice-11-merged → slice-12-merged (#885, commit cfb5964).
  Milestone 33 → 34 (33 ported + 1 in-flight in slice-13). Bucket B 10 → 9.
  Bucket D ported list grew to 33 entries.
Copilot AI review requested due to automatic review settings April 30, 2026 05:21
@AceHack AceHack enabled auto-merge (squash) April 30, 2026 05:21
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d73405f937

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/git/push-with-retry.ts
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Ports one Git helper script from Bash to TypeScript/Bun as part of the ongoing TS/Bun migration trajectory, and updates the migration audit/trajectory docs to record slice 13.

Changes:

  • Add tools/git/push-with-retry.ts, a Bun/TS port of the existing git push transient-5xx retry wrapper.
  • Record Slice 13 audit details in slice-audits.md.
  • Update the trajectory dashboard (RESUME.md) milestone/bucket counts to reflect the new in-flight port.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
tools/git/push-with-retry.ts New TS/Bun implementation of the git push retry wrapper (transient 5xx handling + env validation).
docs/trajectories/typescript-bun-migration/slice-audits.md Adds Slice 13 audit entry describing the port and equivalence notes.
docs/trajectories/typescript-bun-migration/RESUME.md Updates trajectory status/milestones and Bucket B inventory to reflect slice 13.

Comment thread tools/git/push-with-retry.ts
Comment thread docs/trajectories/typescript-bun-migration/slice-audits.md Outdated
Comment thread tools/git/push-with-retry.ts Outdated
Comment thread tools/git/push-with-retry.ts
Five real findings from automated reviewers:

Codex P2 — Guard null stderr from failed spawnSync:
  When spawnSync cannot start git (ENOENT etc.), result.stderr is
  null at runtime even though @types/node claims `string`. Added
  `?? ""` guard with eslint-disable + rationale comment so the
  downstream regex match is safe.

Copilot P1 — spawnSync failure modes weren't being classified:
  Added classifySpawnFailure helper handling 4 cases:
  - status !== null: passthrough
  - error.code === ENOENT: return 127 (matches bash command-not-found)
  - other error.code: return 1 with error message
  - signal !== null: return 1 with signal name
  - otherwise: return 1 with "no exit code" note
  Each case writes a contextual message to stderr.

Copilot P1 — sleepSeconds comment claimed nonexistent fallback:
  Comment claimed "falls back to a tight loop if not available" but
  no fallback was implemented. Reframed comment to state the actual
  Bun-vs-Node main-thread Atomics.wait behavior. No fallback needed:
  the shebang pins Bun, which supports main-thread Atomics.wait.

Copilot P2 — eslint-disable lacked justification:
  Added rationale comment ABOVE the disable directive (not below —
  eslint-disable-next-line applies to the literal next line, so the
  rationale must precede the directive, not split it from the code).
  Same security posture as bash `git push "$@"`.

Copilot P1 — line-count drift in audit:
  Audit said "129 → 138 lines" but the new TS file is now 184 lines
  after the spawn-failure classification. Updated the audit.
@AceHack AceHack merged commit e9dc894 into main Apr 30, 2026
24 checks passed
@AceHack AceHack deleted the lane-b/ts-bun-slice-13-push-with-retry-2026-04-30 branch April 30, 2026 05:31
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d48e2d651

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const result = spawnSync("git", ["push", ...args], {
stdio: ["inherit", "inherit", "pipe"],
encoding: "utf8",
maxBuffer: 64 * 1024 * 1024,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid aborting pushes on stderr buffer overflow

Using spawnSync with maxBuffer: 64 * 1024 * 1024 introduces a hard cap that the previous shell implementation did not have (tee wrote to a temp file). git push writes progress to stderr, so large/verbose pushes can exceed 64 MiB; when that happens spawnSync returns with a spawn error (for example ENOBUFS) and the wrapper reports a generic failure instead of propagating the real git push outcome or retrying based on the remote error. This turns valid long-running pushes into deterministic wrapper failures.

Useful? React with 👍 / 👎.

AceHack added a commit that referenced this pull request Apr 30, 2026
…tion (#894)

* ts(slice-14, wip 1/N): port budget/snapshot-burn (.sh→.ts)

First script of slice 14. Captures point-in-time LFG cost/burn
snapshot via gh API + appends one JSON line to
`docs/budget-history/snapshots.jsonl`. Composes with project-runway +
daily-cost-report (Aaron's #287 visibility deadline).

Byte-equivalent on argument-validation paths (--note, --help).
Live --dry-run verified against GitHub API: produces snapshot with
all the same fields as bash original.

Mechanical changes:
- bash `gh api ... | jq` pipelines → ghJson helper wrapping spawnSync
- bash `mapfile` workaround (while-read for macOS bash 3.2 compat)
  → straightforward TS for-loop
- bash heredoc `jq -n` snapshot composition → typed Snapshot interface
  + JSON.stringify
- bash JSONL append (`printf '%s\n' >> "$out"`) → appendFileSync
- Per-repo aggregation extracted into aggregateTimings + summarizePulls
  helpers under cognitive-complexity threshold
- Optional fields elided via spread+conditional for
  exactOptionalPropertyTypes compliance

Lint-clean: bun --bun tsc --noEmit + eslint strictTypeChecked +
sonarjs all pass. The new lint (tsc tools) gate from #890 will
validate this in CI.

* trajectory(ts-bun): slice 14 audit substrate + RESUME tracker

- slice-audits.md: append slice-14 audit (1 port — budget/snapshot-burn).
  Also flip slice-13 from PR-pending to merged-with-PR-number.
- RESUME.md: bump slice-12-merged → slice-13-merged (#892, commit e9dc894).
  Milestone 34 → 35 (34 ported + 1 in-flight in slice-14). Bucket B 9 → 8.
  Bucket D ported list grew to 34 entries.
AceHack added a commit that referenced this pull request Apr 30, 2026
…gration (#896)

* ts(slice-15, wip 1/N): port peer-call/grok (.sh→.ts)

First script of slice 15. Otto's harness-side caller for invoking
Grok via cursor-agent as a peer reviewer. Opens the peer-call
cluster — sibling ports (gemini + codex) follow the same shape.

Byte-equivalent on argument-validation paths. LLM-response
equivalence is non-deterministic; only structural/UX equivalence
verified.

Mechanical changes:
- bash arg-parse loop → classifyFlag helper + MutableArgState
  (main parseArgs stays under cognitive-complexity 15)
- bash 'eval "$context_cmd" 2>&1 | head -c 20000' →
  spawnSync('/bin/sh', ['-c', contextCmd]) + slice to CTX_HEAD_BYTES
- bash file-head read → readFileSync + Buffer.subarray
- bash 'cursor-agent --print ...' → spawnSync with stdio:'inherit'
  (preserves live LLM-streaming UX)
- PREAMBLE preserved verbatim (Otto's contribution to the
  four-ferry consensus protocol convention)
- eslint-disable for no-os-command-from-path placed on the literal
  next line per directive-placement pattern from #892 review

Lint-clean: bun --bun tsc --noEmit + eslint strictTypeChecked +
sonarjs all pass. The lint (tsc tools) gate from #890 will validate
this in CI.

* trajectory(ts-bun): slice 15 audit substrate + RESUME tracker

EOF
AceHack added a commit that referenced this pull request Apr 30, 2026
#907)

Last git-cluster port: tools/git/batch-resolve-pr-threads.{sh→ts}.
Slice 13 (push-with-retry) + slice 20 (batch-resolve-pr-threads)
together complete the git-cluster.

Behavioural improvements over bash original (deliberate, not drift):

- jq pipelines replaced with native JSON parse + array operations;
  drops jq from runtime deps (only `gh` required now).
- Pattern classification via TypeScript pattern arrays + `.some()`
  rather than bash `for pat in ; do [[ ]]; done` — same semantics,
  more type-safe with `Classification = "dangling-ref" |
  "name-attribution" | "unknown"` discriminated union.
- ResolveError discriminated record with `stage: "reply" | "resolve"`
  so failure mode is visible in error messages.

Byte-equivalence verified on this repo state:
- Three argument-validation paths byte-equivalent (no args / bad
  pr-number / unknown second arg) — same exit code + same message.
- Live dry-run on PR #902 (4 unresolved threads) byte-equivalent —
  empty diff against bash original.
- Apply mode not exercised (would mutate live PR state); code path
  verified by inspection.

All bash safety rails from PR #199 (Copilot/Codex) preserved:
positive-integer validation, exact-`--apply` second-arg check,
GraphQL errors array inspection, null-pullRequest detection,
paginated thread fetch (50 per page) + paginated per-thread comments
(50 per thread with truncation warning), positional -F args
(avoids parameter-expansion-quote pitfall), printf-not-echo for
review-comment bodies (handled via TypeScript string operations).

Bucket B 2 → 1 (only tools/pr-preservation/archive-pr.sh 674L
remains; bash+Python mix — slice 21).

Composes with:
- tools/git/push-with-retry.ts (slice 13, #892) — git-cluster siblings
- docs/trajectories/typescript-bun-migration/RESUME.md updated
- docs/trajectories/typescript-bun-migration/slice-audits.md slice 20 audit

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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