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
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
---
id: B-0106
priority: P2
status: in-progress
status: closed
title: Add `tsc --noEmit` gate job for tools/**.ts so type errors fail CI
tier: factory-hygiene
effort: S
ask: Aaron 2026-04-29 (B-0086 trajectory) — found via slice-9 #882 post-merge audit on 2026-04-30
created: 2026-04-30
last_updated: 2026-04-30
closed_in: PR #890 (commit 9ca9ed9, 2026-04-30)
Comment on lines +4 to +11
composes_with: [B-0086]
tags: [ci-lint, factory-hygiene, ts-bun-migration, mechanical-guard, missing-gate]
---
Expand Down
1 change: 1 addition & 0 deletions docs/hygiene-history/loop-tick-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,4 @@ fire.
| 2026-04-30T03:41:00Z (autonomous-loop tick — consolidated post-#879 session row covering ~9 ticks: slice-7 merge (#878) + slice-8 PR open (#880); honest-wait + survey + 3 slice-8 ports + 2 rounds of slice-7 review-thread fixes + Cluster H complete (5/5)) | opus-4-7 / session continuation | 98fc7424 | **Slice-7-lands + slice-8-opens consolidated row.** PR #878 (slice 7, 3 lint-pattern ports) MERGED 2026-04-30 commit 4dac957. Two rounds of review-thread fixes addressed before merge: round-1 (CRLF in trimTrailingSpaceTab + --fail-over invalid-arg validation + -h/--help in safety-clause + .lake exclusion in doc-comment-history + Task #350 disambiguation in slice-audits + --list-missing zero-bytes-on-empty UX); round-2 (Windows path separator normalization via toPosixRel helper applied to both no-empty-dirs.ts + doc-comment-history-audit.ts + exit-code documentation update + RESUME.md merge-stable wording). Total review-fix commits: 4 across the slice-7 PR. PR #880 (slice 8) opened with 3 ports byte-equivalent against bash: runner-version-freshness (356 lines bash to 394 lines TS — workflow runner-label allow-list with 30-day freshness warning), no-directives-otto-prose (261 lines bash to 316 lines TS — diff-based directive-prose lint with pr/worktree SCOPE modes), live-lock-audit (116 lines bash to 245 lines TS — last-N origin/main commit classifier with EXT/INTL/SPEC/OTHR threshold). **Cluster H complete (5/5)**: all five lint-pattern scripts now have TS ports (no-empty-dirs + safety-clause-audit + doc-comment-history-audit in #878; runner-version-freshness + no-directives-otto-prose in #880). New audit-cluster opened with live-lock-audit (slice 8). Bucket B reduced 22 to 19 remaining; Bucket D grown 17 to 23 (includes #878 + slice-8 in flight). Cron 98fc7424 armed. Auto-merge armed on #880. | (consolidated row covering ~9 ticks of slice-7-fix + slice-8-build) | **Observation — consolidated rows are right shape for fast-progress streaks**: when a session lands many small commits across multiple ticks, a single consolidated row summarizing the arc is more signal-dense than 9 minimal rows. Per the prior-doctrine of "minimal-density row is sufficient for verification ticks" plus the consolidated-row pattern from PR #706 (14-tick append-gap close), consolidating preserves AUTONOMOUS-LOOP.md liveness invariant without flywheel-rich content. **Observation — branch protection blocks direct-to-main pushes for tick-history**: confirmed empirically when ops/tick-history-2026-04-30-slice-7-progress branch was rejected from direct push; routed through PR #879. Same pattern applies to this row's PR. Per Task #276 (tick-history direct-to-main with low gate, Aaron chose option 2) — branch-protection bypass not yet implemented; PR routing remains canonical. **Observation — review-thread response cadence under autonomous-loop**: round-1 fixes landed within 1 tick; round-2 fixes (Windows path separators) landed within 1 tick. Both cycles included thread-resolution via GraphQL mutation after the fix-commit pushed. Auto-merge stayed armed throughout. The "BLOCKED with green CI = investigate threads first" CLAUDE.md rule fired correctly twice — neither investigation was opaque (each had small-countable-set findings with addressable fixes). |
| 2026-04-30T04:46:00Z (autonomous-loop tick — slice-11 #884 merged + slice-12 #885 opened (backlog/generate-index port)) | opus-4-7 / session continuation | 98fc7424 | **Slice-11-lands + slice-12-opens consolidated row.** PR #884 (slice 11, 2 ports — backfill_dv2_frontmatter + audit-packages) MERGED 2026-04-30T04:42:42Z commit 9237756 after multiple review rounds across the prior compacted session: CodeQL TOCTOU findings (refactored statSync-then-readFileSync to readFileSync-with-try/catch + ENOENT/EISDIR error mapping), atomic-rewrite restoration via tmp+rename, --all chdir-to-repoRoot fix, repoRoot via fileURLToPath(import.meta.url) for cwd-independence, defensive-rename-fallback per Codex P0 then retracted to preserve-original-on-failure per P1, fail-on-empty-parse on audit-packages per P2 (regex-drift suspicion message), Copilot milestone math 33→32 fix. PR #885 (slice 12) opened with 1 port: backlog/generate-index byte-equivalent against bash on --stdout mode (217 to 282 lines TS — Phase-1a 50-line safety guard preserved + 3 modes write/--check/--stdout + in-memory line-by-line diff replaces shell-out to diff). RESUME milestone bumped 32 to 33 ports total (32 merged + 1 in-flight); Bucket B 12 to 10 remaining; Bucket D ported list grew to 32 entries. Auto-merge armed on #885. Cron 98fc7424 still armed. | 9237756 (slice-11 merge; slice-12 PR-open at write-time, merged shortly after as cfb5964) | **Observation — Codex P0 vs P1 sequencing**: prior session illustrated the value of treating P0 as immediately-actionable and P1 as a check-back-after-resting-the-fix. Codex P0 said "add defensive renameSync fallback for Windows file-lock edge cases"; landed it. Codex P1 follow-up said "wait, the fallback unlinks the original before retry — that's worse than the original failure mode (loses content on second-failure)"; retracted to preserve-original-on-failure. The two findings together correctly converge on the right design but neither alone would have. **Observation — fileURLToPath(import.meta.url) is the right repoRoot pattern**: bash's `cd "$(dirname "$0")/.." && pwd` resolves the script location and walks up; the prior `git rev-parse --show-toplevel` + cwd fallback fails outside a git checkout (uses wrong cwd silently). The import.meta.url variant matches bash's invocation semantics from any caller directory. Will reuse for all future tools/* TS ports that bash-originals resolve relative to script location. **Observation — Bucket B is now in single-digits**: 10 remaining (1 in-flight + 9 to-port). Of those 9: 5 are budget/git scripts (touch shared production state, careful), 3 are peer-call wrappers (LLM-CLI shell-outs, equivalence not deterministic), 1 is pr-preservation/archive-pr.sh (mutating gh API). The pure-equivalence-testable scripts in Bucket B are essentially exhausted; remaining ports require special-handling per script class. |
| 2026-04-30T05:01:00Z (autonomous-loop tick — arc close: 4 PRs landed in sequence (#885 slice-12 + #888 B-0106 backlog + #886 tick row + #887 tsc TS2322 fix); tsc clean verified on main) | opus-4-7 / session continuation | 98fc7424 | **Arc-close consolidated row.** Four PRs landed in this session arc: PR #885 (slice 12 — `tools/backlog/generate-index` port, commit cfb5964) → PR #888 (P2 backlog row B-0106 capturing the missing `tsc --noEmit` gate, commit 5353fad) → PR #886 (tick-history row at 04:46:00Z, commit 1207ff8) → PR #887 (real tsc TS2322 fix in `audit-agencysignature-main-tip.ts` + Copilot follow-up to derive `StringArgKey` from `Exclude<keyof MutableArgs, "mode">`, commit 5dc1abd). Bug-find lineage: while running `bun --bun tsc --noEmit` for slice-12 verification, surfaced a real strict-typecheck error on slice-9's port (#882) that had silently shipped to main because gate.yml has no `tsc --noEmit` step (only `dotnet build`). Fixed locally + filed B-0106 to close the CI gap. Final state: tsc clean on main verified post-merge. Bucket B 10 → 9 (slice-12 merged); 32 → 33 ports total. Cron 98fc7424 still armed. | 5dc1abd (final PR of the arc; #887) | **Observation — bug-find via tsc-on-port-verification IS a useful post-merge gate**: even without CI catching tsc, the local discipline of `bun --bun tsc --noEmit` before committing each slice surfaced the slice-9 defect. The fix-the-bug + file-the-row pattern (PR #887 + B-0106) made the local catch durable as factory substrate. Will reuse for future slices. **Observation — auto-merge survives non-force-pushes**: PR #887's regular push (after Copilot follow-up commit) preserved the auto-merge `enabledAt` timestamp; force-pushes (PR #886's earlier rebase) reset it. Practical rule: only force-push when content needs to change pre-history; otherwise prefer additive commits to keep auto-merge stable. **Observation — Copilot's `Exclude<keyof T, "x">` catch is a substrate rule**: when narrowing `keyof T` to exclude one or two members, prefer `Exclude<keyof T, "x">` over hand-listed literal unions — the compiler keeps it drift-free if `T` grows. Worth absorbing as a TS+Bun port pattern. |
| 2026-04-30T05:11:00Z (autonomous-loop tick — B-0106 implementation merged: lint-tsc-tools gate job active; 6 PRs landed in this session) | opus-4-7 / session continuation | 98fc7424 | **B-0106 closeout tick.** PR #890 (`ci(B-0106): add lint-tsc-tools gate job`) MERGED 2026-04-30T05:11:56Z commit 9ca9ed9. Closes the CI gap that surfaced 2 ticks earlier when slice-12 verification caught the slice-9 TS2322 defect. Full bug-class loop now sealed: PR #887 fixed the local instance → PR #888 filed B-0106 capturing the missing gate → PR #890 implements the gate. The new `lint (tsc tools)` job runs `bun --bun tsc --noEmit -p tsconfig.json` after install.sh + `bun install --frozen-lockfile` materializes typescript@6.0.3. Self-validated against its own diff (the new check passed on PR #890). 6 PRs total in this session arc: #885 (slice 12 port) → #888 (B-0106 row) → #886 (tick row 04:46) → #887 (tsc bug fix) → #889 (closing tick row 05:01) → #890 (B-0106 implementation). Bucket B 9 → 9 (no new ports this round); Bucket D 33 → 33 (no new ports). New CI gate adds protection class for future TS scripts. B-0106 status updated open → in-progress → closed; closed_in: PR #890. Cron 98fc7424 still armed. | 9ca9ed9 (B-0106 implementation; #890) | **Observation — full bug-class loop closed in 4 PRs over ~30 minutes**: pattern was find-bug-locally (tsc check before slice-12 commit) → fix-local (PR #887) → file-row-for-missing-gate (PR #888) → implement-row-as-CI-job (PR #890). Each step durable at the right surface (code → backlog → CI workflow). The gate self-validates because it runs against its own diff in PR #890 — would only block merge if the new job's bun install + tsc run failed. **Observation — semgrep-elevation-shape applied to typecheck**: the new `lint (tsc tools)` follows the same pattern as the round-30 semgrep elevation: codified rules (tsconfig.json strict mode + .semgrep.yml rules) without a CI gate aren't a control. Both gates are now mechanical guardrails rather than vigilance-dependent disciplines. Worth absorbing as factory pattern: any rule codified in a config file should have a CI gate that fails on violation. **Observation — branch protection's required-checks list may need manual update**: the new `lint (tsc tools)` check might or might not be auto-required depending on host branch protection config. Follow-up audit needed: verify `gh api repos/.../branches/main/protection/required_status_checks/contexts` includes the new check. If not, file a follow-up row to add it (would be A trivial host-mutation requiring visibility per Aaron's Otto-355 visibility constraint). |
Loading