diff --git a/docs/backlog/P2/B-0106-tsc-noemit-gate-job-for-ts-tools-2026-04-30.md b/docs/backlog/P2/B-0106-tsc-noemit-gate-job-for-ts-tools-2026-04-30.md index 46dd22d43..eb56265b3 100644 --- a/docs/backlog/P2/B-0106-tsc-noemit-gate-job-for-ts-tools-2026-04-30.md +++ b/docs/backlog/P2/B-0106-tsc-noemit-gate-job-for-ts-tools-2026-04-30.md @@ -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) composes_with: [B-0086] tags: [ci-lint, factory-hygiene, ts-bun-migration, mechanical-guard, missing-gate] --- diff --git a/docs/hygiene-history/loop-tick-history.md b/docs/hygiene-history/loop-tick-history.md index b662414eb..2259a573e 100644 --- a/docs/hygiene-history/loop-tick-history.md +++ b/docs/hygiene-history/loop-tick-history.md @@ -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`, 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` catch is a substrate rule**: when narrowing `keyof T` to exclude one or two members, prefer `Exclude` 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). |