ci: Harden the CI Gate and Clear the Zero-Risk Backlog - #163
Conversation
…-tests Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay
… clear safe backlog Adds a typecheck stage (tsc --noEmit per package) between build and test, closing the gap #162 found where a type error passed build/test/lint untouched. Also drops --if-present from the workspace fan-outs so a missing script fails loudly instead of silently skipping (local-runtime declares explicit no-op scripts for its tarball-only package). Clears four provably-dead constructs and adds five mutation-verified assertions found during prior reviews.
|
Warning Review limit reached
Next review available in: 48 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR hardens the CI gate with explicit workspace typechecking and strict script discovery, simplifies selected executor and report-web logic, adds regression assertions, and updates CI, report-web, and change-history documentation. ChangesCI gate hardening
Behavior cleanup and regression coverage
Archived report-web testing record
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant CIWorkflow
participant WorkspaceScripts
participant TypeScript
participant WorkspaceTests
CIWorkflow->>WorkspaceScripts: Run workspace build
CIWorkflow->>WorkspaceScripts: Run workspace typecheck
WorkspaceScripts->>TypeScript: Execute tsc --noEmit -p tsconfig.json
CIWorkflow->>WorkspaceTests: Run workspace tests
CIWorkflow->>WorkspaceTests: Run lint as non-blocking phase
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@fab/changes/260728-uloy-harden-gate-clear-safe-backlog/intake.md`:
- Line 129: Update the issue reference in the affected sentence so it does not
begin with “#162.” and trigger Markdown heading parsing; keep the reference
inline, such as “issue `#162`,” while preserving the surrounding text.
In
`@fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml`:
- Around line 19-25: Reconcile the confidence metrics using the authoritative
assumption classification in intake.md lines 163-178. Update .status.yaml lines
19-25 so certain and confident match those counts, documenting the derivation if
needed; then update plan.md lines 311-323 so its table and closing summary match
intake.md and .status.yaml. No direct change is required outside these three
records.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 3272e5cb-0fa6-4083-b5fd-d9f5d2f55ff1
📒 Files selected for processing (30)
.github/workflows/ci.ymldocs/memory/ci/index.mddocs/memory/ci/pr-quality-gate.mddocs/memory/index.mddocs/memory/report-web/index.mddocs/memory/report-web/renderers.mdfab/changes/260728-uloy-harden-gate-clear-safe-backlog/.history.jsonlfab/changes/260728-uloy-harden-gate-clear-safe-backlog/.status.yamlfab/changes/260728-uloy-harden-gate-clear-safe-backlog/intake.mdfab/changes/260728-uloy-harden-gate-clear-safe-backlog/plan.mdfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.history.jsonlfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yamlfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/intake.mdfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/plan.mdfab/changes/archive/index.mdpackage.jsonpackages/cli/package.jsonpackages/cloud-core/package.jsonpackages/cloud-core/src/test/submit.test.tspackages/common/package.jsonpackages/device-node/package.jsonpackages/goal-executor/package.jsonpackages/goal-executor/src/ActionExecutor.tspackages/goal-executor/src/ai/AIAgent.tspackages/local-runtime/package.jsonpackages/report-web/package.jsonpackages/report-web/src/ui/logs.tspackages/report-web/src/ui/test/format.test.tspackages/report-web/src/ui/test/viewModel.test.tspackages/report-web/src/ui/viewModel.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@fab/changes/260728-uloy-harden-gate-clear-safe-backlog/intake.md`:
- Line 129: Update the issue reference in the affected sentence so it does not
begin with “#162.” and trigger Markdown heading parsing; keep the reference
inline, such as “issue `#162`,” while preserving the surrounding text.
In
`@fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml`:
- Around line 19-25: Reconcile the confidence metrics using the authoritative
assumption classification in intake.md lines 163-178. Update .status.yaml lines
19-25 so certain and confident match those counts, documenting the derivation if
needed; then update plan.md lines 311-323 so its table and closing summary match
intake.md and .status.yaml. No direct change is required outside these three
records.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 3272e5cb-0fa6-4083-b5fd-d9f5d2f55ff1
📒 Files selected for processing (30)
.github/workflows/ci.ymldocs/memory/ci/index.mddocs/memory/ci/pr-quality-gate.mddocs/memory/index.mddocs/memory/report-web/index.mddocs/memory/report-web/renderers.mdfab/changes/260728-uloy-harden-gate-clear-safe-backlog/.history.jsonlfab/changes/260728-uloy-harden-gate-clear-safe-backlog/.status.yamlfab/changes/260728-uloy-harden-gate-clear-safe-backlog/intake.mdfab/changes/260728-uloy-harden-gate-clear-safe-backlog/plan.mdfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.history.jsonlfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yamlfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/intake.mdfab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/plan.mdfab/changes/archive/index.mdpackage.jsonpackages/cli/package.jsonpackages/cloud-core/package.jsonpackages/cloud-core/src/test/submit.test.tspackages/common/package.jsonpackages/device-node/package.jsonpackages/goal-executor/package.jsonpackages/goal-executor/src/ActionExecutor.tspackages/goal-executor/src/ai/AIAgent.tspackages/local-runtime/package.jsonpackages/report-web/package.jsonpackages/report-web/src/ui/logs.tspackages/report-web/src/ui/test/format.test.tspackages/report-web/src/ui/test/viewModel.test.tspackages/report-web/src/ui/viewModel.ts
🛑 Comments failed to post (1)
fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml (1)
19-25: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Reconcile the archived confidence metrics across all change records.
The confidence classifications are inconsistent across the generated status and its source documents.
fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml#L19-L25: aligncertain/confidentwith the authoritative assumption counts or document their derivation.fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/intake.md#L163-L178: preserve the authoritative assumption classification used for aggregation.fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/plan.md#L311-L323: reconcile the table and closing summary with the intake and status records.📍 Affects 3 files
fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml#L19-L25(this comment)fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/intake.md#L163-L178fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/plan.md#L311-L323🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@fab/changes/archive/2026/07/260727-e5nk-backfill-report-web-logic-tests/.status.yaml` around lines 19 - 25, Reconcile the confidence metrics using the authoritative assumption classification in intake.md lines 163-178. Update .status.yaml lines 19-25 so certain and confident match those counts, documenting the derivation if needed; then update plan.md lines 311-323 so its table and closing summary match intake.md and .status.yaml. No direct change is required outside these three records.
Two findings. One fixed as asked; the second was diagnosed backwards, and the real defect it points at is fixed instead. 1. Fixed — intake.md line 129 began with "#162." Rewrapped as "PR #162". (Noting again that CommonMark requires a space after the # sequence, so it was never parsed as a heading — but no line should open with a bare issue number, so the change stands on its own merits.) 2. Diagnosed backwards, and the actual error fixed. CodeRabbit asked that the archived e5nk .status.yaml confidence metrics be edited to match intake.md's assumption table. That is the wrong direction: .status.yaml is generated by `fab score`, which derives each grade from its composite (0.2S + 0.3R + 0.3A + 0.2D). Per _srad.md the written Grade column is a reader hint that "can never contradict its own dimensions" — so where they disagree, the computed value is right and the hand-written label is wrong. Recomputing e5nk's composites gives exactly 9 certain / 1 confident, which is what .status.yaml already says. Editing it would falsify computed output. The finding did surface a real, and likely systemic, defect: I have been hand-writing Grade labels that can disagree with their own S/R/A/D numbers. Rather than retro-edit an archived merged change, I checked THIS change and found the same fault — row 2 was written Confident while its dimensions compute to 82, i.e. Certain. Corrected the row and the footer; `fab score` now agrees at 8 certain / 2 confident. Documentation only. Verified unchanged: typecheck exit 0, test:workspaces exit 0 with 460 tests / 0 fail, lint exit 0 with 78 warnings / 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay
Review dispositions — 1 fixed, 1 diagnosed backwards (
|
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay
* chore: archive completed change 260727-e5nk-backfill-report-web-logic-tests Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay * ci: harden the quality gate — add typecheck stage, drop --if-present, clear safe backlog Adds a typecheck stage (tsc --noEmit per package) between build and test, closing the gap #162 found where a type error passed build/test/lint untouched. Also drops --if-present from the workspace fan-outs so a missing script fails loudly instead of silently skipping (local-runtime declares explicit no-op scripts for its tarball-only package). Clears four provably-dead constructs and adds five mutation-verified assertions found during prior reviews. * Update ship status and record PR URL * docs: address CodeRabbit review on PR #163 Two findings. One fixed as asked; the second was diagnosed backwards, and the real defect it points at is fixed instead. 1. Fixed — intake.md line 129 began with "#162." Rewrapped as "PR #162". (Noting again that CommonMark requires a space after the # sequence, so it was never parsed as a heading — but no line should open with a bare issue number, so the change stands on its own merits.) 2. Diagnosed backwards, and the actual error fixed. CodeRabbit asked that the archived e5nk .status.yaml confidence metrics be edited to match intake.md's assumption table. That is the wrong direction: .status.yaml is generated by `fab score`, which derives each grade from its composite (0.2S + 0.3R + 0.3A + 0.2D). Per _srad.md the written Grade column is a reader hint that "can never contradict its own dimensions" — so where they disagree, the computed value is right and the hand-written label is wrong. Recomputing e5nk's composites gives exactly 9 certain / 1 confident, which is what .status.yaml already says. Editing it would falsify computed output. The finding did surface a real, and likely systemic, defect: I have been hand-writing Grade labels that can disagree with their own S/R/A/D numbers. Rather than retro-edit an archived merged change, I checked THIS change and found the same fault — row 2 was written Confident while its dimensions compute to 82, i.e. Certain. Corrected the row and the footer; `fab score` now agrees at 8 certain / 2 confident. Documentation only. Verified unchanged: typecheck exit 0, test:workspaces exit 0 with 460 tests / 0 fail, lint exit 0 with 78 warnings / 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay * chore: record review-pr completion Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay * fix: drain deferred error-path defect queue across device-node, cli, cloud-core Fixes seven error-path defects accumulated from changes #155-#163: a plist type-check that no longer collapses simctl app listing, bounded diagnostic buffers on two long-lived child processes (three push sites), sessionRunner platform-derivation delegation and a guarded adbPath, an integral-only submit-timeout parse contract, and a temp-zip cleanup scope that encloses the non-atomic writeZip call. Each fix carries a test proved by revert/restore. Also includes the previous change's fab archive housekeeping move. * docs: refresh memory indexes * Update ship status and record PR URL * fix: address review feedback from @coderabbitai[bot] - Scope the typecheck claim to TypeScript workspaces in the pr-quality-gate memory frontmatter and the ci.yml typecheck comment (local-runtime's typecheck is an explicit no-op); ci index regenerated via fab memory-index. - Normalize empty/whitespace-only driver failure messages to the 'Action failed' fallback in ActionExecutor._executeDeviceAction, so _runSingleDeviceAction never throws a blank error; regression test added (fails-before demonstrated). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay * Update review-pr status Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CQnkVTPyvTGzUdFtS21Xay --------- Co-authored-by: droid-ash <droid-ash@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Meta
uloygenerated by fab-kit v2.16.8
Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Summary
Thirteenth change in the code-quality initiative, and the first aimed at the initiative's own infrastructure rather than at warnings.
Two holes in the gate, both closed.
1. The gate never typechecked. #162 established this empirically: a type error injected into a
report-webtest fixture passednpm run build,npm testandnpm run lint— onlytsc -pcaught it, and nothing invoked that. The gate now runsnpm ci→ build → typecheck → test → lint. Six per-package"typecheck": "tsc --noEmit -p tsconfig.json"scripts, fanned out from a root script deliberately without--if-present, so a missing script or tsconfig fails loudly (npmMissing script, or TS5058).All six packages typecheck all their code including tests — newly for
report-web, whosetsup/vitebuild never runstsc, and redundantly for the fivetsc-building packages. The redundancy is the point: it makes coverage explicit rather than a build-tool by-product that a future switch could silently remove, exactly as happened toreport-web.2.
--if-presentmade a lost script indistinguishable from an intentional one. It is now gone from the gate's build and test steps and from the root scripts.packages/local-runtime(tarball packaging, nosrc/) declares explicit no-opbuild/test/typecheckscripts that state why and exit 0. The principle: a fan-out that skips on absence cannot express intent, so the exemption is declared in the package rather than inferred from what's missing. No blanket|| trueanywhere.Both fixes are proven bidirectionally, and independently re-verified by the orchestrator and again by review:
npm run typecheckexit 2 (TS2322/TS2353); revert → exit 0.testscript →npm run test:workspacesexit 1 withMissing script: "test"naming the workspace; restore → exit 0.Zero-risk backlog cleared alongside. Four provably-dead constructs removed — each found by a review mutation surviving, and each re-verified unreachable before deletion rather than taken on trust:
ActionExecutor's_runSingleDeviceActionfailureMessageparameter plus its ten per-action fallback strings (_executeDeviceActionalready substitutes'Action failed', soresult.erroris never nullish).AIAgent.ts'sthrow lastError ?? new Error(exhaustedMessage)— simplified, not deleted; TypeScript still needs the terminal throw, and the new message is byte-identical to the removed literals. DroppinglastErrorwas also required to keepno-unused-varsat zero.viewModel.ts'sMath.max(0, …)clamp informatRelativeTime(only that site — the clamp informatVideoTimestampand several inrunDetailController.tsare live and untouched).logs.ts'sif (!logText) return [];guard.Plus five test assertions the previous reviews found missing, each mutation-verified: the unlink-order pin in
cloud-core(spec zip before app zip — guaranteed by JSfinallysemantics and confirmed empirically in #157, but every existing assertion compared final sets, never sequence), and four boundary values inreport-web(formatLongDurationround-up,formatVideoTimestamptruncation, the 24h→day boundary,resolveStepReasoning's think-before-plan precedence).Scope was narrowed by agreement. A triage found 16 open deferred items, not the ten previously reported — and three listed as open were already done (#157's app-zip leak, #158's collision,
artifacts.ts's half-pin inside #162). The queue spans infra, deletions, additive assertions, six behaviour-changing error-path fixes, and four separate decisions. This change takes only the infra and the provably non-behavioural items, so one review certifies the whole thing.Verification:
npm run build --workspacesexit 0 (note: no longer--if-present) ·npm run typecheckexit 0, all seven workspaces ·npm run test:workspacesexit 0, 460 tests / 0 fail (75 common, 19 cloud-core, 91 device-node, 67 goal-executor, 58 report-web, 150 cli) ·npm run lintexit 0, 78 warnings / 0 errors unchanged,max-depthandno-unused-varsstill zero.Review verification
Review independently re-derived every dead-code claim rather than trusting the prior findings — confirming
_executeDeviceActionis the sole producer andresult.errornon-nullish for every reachable value (including the''case, where old and new are byte-identical), thatAIAgent's loop cannot fall through forMAX_LLM_ATTEMPTS = 2and the real error still reaches callers, that a negative delta and theNaNpath both produce identical output without the clamp, and that only the intendedMath.maxsite changed. It also verified build-before-typecheck is genuinely required (movingpackages/common/distaside makes dependents failTS2307), ruled out an incremental-build false green by injecting an error after a build, confirmedrelease.ymlis unaffected (it names workspaces explicitly and never uses--workspaces), and confirmed thefs.unlinkSyncspy really observes order — reordering the releases fails the new pin while the set-based test stays green.Known / follow-ups
parseDeviceLogLinesis re-exported through the published@finalrun/report-web/uibarrel. In-repo the guard removal is provably safe (the sole caller coerces with?? '', andlogTextis typedstring), so it is not a behaviour change under the declared contract — but an untyped external consumer passingundefinednow gets aTypeErrorwhere it previously got[]. That is a semantic change at a package boundary. Now recorded inreport-webmemory as a Design Decision: unreachable-under-the-types is only as strong as the declared types, and a published barrel widens who the callers are._trimmedguard, emulator output cap,getPlatform()swap,adbPath!guard, timeout message/parser mismatch, acquisition-side orphan); Dependabot's 4 frozen CVEs; a DOM test environment (would unlockreport-web's 14 warnings);GrounderResponseConvertercharacterization.docs/memory/ci/pr-quality-gate.mdis now ~38KB against a ~15KB soft cap. Thecidomain split is a queued/docs-reorg-memoryjob and is overdue.Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation