Skip to content

fix(webui-v2): enforce TypeScript source conventions - #6057

Merged
BenKurrek merged 3 commits into
mainfrom
codex/frontend-source-conventions
Jul 13, 2026
Merged

BenKurrek merged 3 commits into
mainfrom
codex/frontend-source-conventions

Conversation

@BenKurrek

Copy link
Copy Markdown
Collaborator

Summary

  • finish the WebUI v2 TypeScript migration by converting the remaining authored .js, .mjs, and .mts modules to .ts/.tsx
  • make relative code-module imports extensionless and replace the remaining HTM html\...`` test helper with JSX
  • restore previously undiscovered test suites and preserve the legacy Button loading/idle/link coverage in typed tests
  • add a TypeScript-AST source-convention checker and wire it into pnpm lint together with typechecking
  • remove the stale ESLint configuration and dependencies that only inspected JavaScript files after the source had moved to TypeScript

Root cause

The large frontend TypeScript/TSX conversion missed nine existing JavaScript-family files, and two more were added afterward. Vitest only discovers .test.ts and .test.tsx, so the leftover .mjs/.mts suites were silently skipped. The existing ESLint configuration also targeted only .js/.mjs, which meant it no longer inspected the TypeScript source while still returning success.

Enforcement

The new convention gate scans authored modules under frontend/src and rejects:

  • JavaScript-family source modules other than .ts/.tsx
  • explicit .js/.jsx/.mjs/.cjs/.ts/.tsx/.mts/.cts suffixes on relative imports, re-exports, and dynamic imports
  • legacy html\...`` tagged templates

Non-code assets, generated JavaScript bundle names, package imports such as highlight.js, and explicit filenames passed to file APIs such as new URL(...) remain allowed.

Validation

  • pnpm --dir crates/ironclaw_webui_v2/frontend lint
  • pnpm --dir crates/ironclaw_webui_v2/frontend test — 88 files, 708 tests
  • pnpm --dir crates/ironclaw_webui_v2/frontend build
  • cargo test -p ironclaw_webui_v2 --features webui-v2-beta — 170 tests
  • cargo clippy -p ironclaw_webui_v2 --all-features --tests -- -D warnings

Focused red/green tests cover missing checker implementation, attributed dynamic imports, restored SSE dependencies, Button coverage migration, and JSX conversion.

Compatibility and rollback

This changes authored frontend source and development checks only. Browser bundle filenames, HTTP/static paths, persistence, configuration, and runtime schemas are unchanged. Rollback is a normal revert of this PR; there are no data migrations or hidden runtime side effects.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fc3cee77-f083-4f8e-a6da-5e54e4683caa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

WebUI v2 adds a TypeScript AST-based source-convention checker, replaces ESLint linting, removes extensionful frontend imports, updates VM-based tests and JSX test harnesses, and documents the resulting lint and migration workflow.

Changes

Frontend source conventions

Layer / File(s) Summary
Convention checker and validation
crates/ironclaw_webui_v2/frontend/scripts/check-source-conventions.ts, crates/ironclaw_webui_v2/frontend/src/test/source-conventions.test.ts, crates/ironclaw_webui_v2/frontend/tsconfig.json, docs/superpowers/specs/...
Adds AST-based checks for JavaScript-family modules, explicit relative extensions, and html tagged templates, with deterministic reporting and Vitest coverage.
Lint wiring and module migration
crates/ironclaw_webui_v2/frontend/package.json, crates/ironclaw_webui_v2/frontend/README.md, crates/ironclaw_webui_v2/frontend/src/**, docs/superpowers/plans/...
Runs convention checks before typechecking, removes ESLint configuration and packages, updates frontend imports to extensionless paths, and refreshes TypeScript source references.
Test harness and regression updates
crates/ironclaw_webui_v2/frontend/src/**/*.test.*
Aligns VM harnesses with TypeScript modules, replaces the Slack picker test template with native JSX-compatible rendering, and expands Button loading and accessibility assertions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant pnpmLint
  participant ConventionChecker
  participant TypeScript
  Developer->>pnpmLint: run lint
  pnpmLint->>ConventionChecker: scan frontend/src
  ConventionChecker-->>pnpmLint: report violations or pass
  pnpmLint->>TypeScript: run typecheck
  TypeScript-->>pnpmLint: report type errors or pass
  pnpmLint-->>Developer: lint result
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title uses Conventional Commits style and accurately summarizes the main change: enforcing WebUI v2 TypeScript source conventions.
Description check ✅ Passed The description covers summary, root cause, enforcement, validation, and rollback, but omits several template sections like Change Type and Linked Issue.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6057 July 13, 2026 18:43 Destroyed
@github-actions github-actions Bot added scope: docs Documentation size: XL 500+ changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jul 13, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request completes the TypeScript migration for the WebUI v2 frontend and introduces a custom source convention checker to enforce extensionless relative imports, JSX usage, and TypeScript-only modules. Stale ESLint configurations and dependencies are removed, and existing tests are updated to comply with these rules. The review feedback recommends refactoring a highly coupled assertion in button.test.tsx to use the includesElementType helper, making the test more resilient to future component DOM changes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +126 to +129
const children = rendered.props.children as ReactElement[];
const content = children[1] as ReactElement<{ children: [unknown, unknown] }>;
assert.equal(content.props.children[0], false, "disabled without loading renders no spinner");
assert.equal(content.props.children[1], "Save");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The assertion here is highly coupled to the internal JSX structure of the Button component (e.g., expecting the children to be at index 1 and the conditional spinner to be at index 0 of its children). If the component's internal DOM structure is refactored (such as removing or adding wrapper elements), this test will break even if the behavior remains correct.

Using the existing includesElementType helper is much more robust and maintainable, as it recursively checks for the presence of the Spinner element without relying on exact array indices.

Suggested change
const children = rendered.props.children as ReactElement[];
const content = children[1] as ReactElement<{ children: [unknown, unknown] }>;
assert.equal(content.props.children[0], false, "disabled without loading renders no spinner");
assert.equal(content.props.children[1], "Save");
assert.equal(includesElementType(rendered.props.children, Spinner), false, "disabled without loading renders no spinner");

@github-actions

Copy link
Copy Markdown
Contributor

Coverage ratchet

Ratchet mode: ENFORCING

RATCHET PASS: global
  observed: 85.38% (296980 / 347853 lines)
  floor:    85.3% (tolerance 0.5pp -> effective floor 84.8%)
  denominator: 347853 lines now vs 320188 at floor capture (+27665 lines, +8.64%) — material change (>5%)

⚠️ 2 Reborn crate(s) have 0 int-tier coverage (target: 0) — ironclaw_prompt_envelope, ironclaw_scripts

Reborn integration-tier coverage

Line coverage (Reborn crates): 85.38% — 296980 / 347853 lines

Per-crate breakdown (63 crates, lowest-covered first)
Crate Line % Covered / Total
ironclaw_prompt_envelope 0% 0 / 88
ironclaw_scripts 0% 0 / 345
ironclaw_runtime_policy 31.75% 80 / 252
ironclaw_event_projections 43.31% 673 / 1554
ironclaw_run_state 53.07% 225 / 424
ironclaw_authorization 53.89% 464 / 861
ironclaw_triggers 59.89% 1792 / 2992
ironclaw_observability 61.54% 16 / 26
ironclaw_webui_v2 62.93% 2679 / 4257
ironclaw_mcp 63.03% 578 / 917
ironclaw_reborn_cli 66.2% 4492 / 6785
ironclaw_reborn_migration 67.09% 1215 / 1811
ironclaw_filesystem 67.1% 3833 / 5712
ironclaw_dispatcher 67.15% 92 / 137
ironclaw_memory 69.2% 773 / 1117
ironclaw_trust 72.88% 661 / 907
ironclaw_capabilities 74.39% 1685 / 2265
ironclaw_wasm_limiter 74.6% 47 / 63
ironclaw_reborn_event_store 74.67% 958 / 1283
ironclaw_extractors 74.72% 538 / 720
ironclaw_first_party_extensions 78.23% 5439 / 6953
ironclaw_llm 78.36% 20328 / 25941
ironclaw_product_context 78.57% 11 / 14
ironclaw_process_sandbox 80.65% 671 / 832
ironclaw_wasm_product_adapters 80.71% 1448 / 1794
ironclaw_memory_native 81.22% 3205 / 3946
ironclaw_secrets 82.7% 2791 / 3375
ironclaw_wasm 82.72% 996 / 1204
ironclaw_events 82.86% 1765 / 2130
ironclaw_reborn_identity 83.59% 433 / 518
ironclaw_auth 83.87% 3078 / 3670
ironclaw_reborn_config 84.06% 1814 / 2158
ironclaw_processes 84.44% 993 / 1176
ironclaw_common 84.85% 1490 / 1756
ironclaw_turns 84.94% 13575 / 15982
ironclaw_host_api 85.17% 2664 / 3128
ironclaw_product_workflow 85.56% 10836 / 12665
ironclaw_projects 85.92% 659 / 767
ironclaw_threads 86.07% 4404 / 5117
ironclaw_network 86.12% 670 / 778
ironclaw_slack_v2_adapter 86.79% 1806 / 2081
ironclaw_product_adapters 86.98% 3207 / 3687
ironclaw_skills 87.58% 4470 / 5104
ironclaw_hooks 87.75% 9917 / 11302
ironclaw_product_adapter_registry 88.06% 531 / 603
ironclaw_reborn_traces 88.19% 11946 / 13546
ironclaw_host_runtime 88.53% 17271 / 19509
ironclaw_reborn_composition 89.02% 76510 / 85949
ironclaw_extensions 89.03% 2864 / 3217
ironclaw_runner 89.28% 16695 / 18700
ironclaw_approvals 89.41% 1587 / 1775
ironclaw_reborn_openai_compat 89.46% 3768 / 4212
ironclaw_conversations 90.33% 3120 / 3454
ironclaw_event_streams 90.82% 1009 / 1111
ironclaw_loop_host 92.51% 14755 / 15950
ironclaw_resources 92.83% 4736 / 5102
ironclaw_attachments 93.06% 630 / 677
ironclaw_reborn_webui_ingress 93.19% 2217 / 2379
ironclaw_telegram_v2_adapter 93.62% 2511 / 2682
ironclaw_agent_loop 94.57% 8789 / 9294
ironclaw_safety 94.88% 3671 / 3869
ironclaw_first_party_extension_ports 95.24% 3343 / 3510
ironclaw_outbound 95.59% 3556 / 3720

This table itself is informational and never gates the PR on its own — not the percentage, not the per-crate holes, not the 0-coverage callout. A separate coverage ratchet (dry-run until enforce=true; see tests/integration/coverage-floor.toml) can fail the build on specific configured floors.

Exemptions (3 entry/entries excluded from the accounting above)
Module / Crate Reason Issue
crate: ironclaw_embeddings v1-only: consumed only by root ironclaw (src/app.rs, src/tools/builtin/memory.rs, src/workspace/mod.rs, src/config/{mod,embeddings}.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_gateway v1-only: consumed only by root ironclaw (src/channels/web/platform/static_files.rs, src/channels/web/handlers/frontend.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_tui v1-only: consumed only by root ironclaw (src/main.rs, src/channels/tui.rs); no crates/* dependents. Crate's own doc comment confirms it bridges INTO v1, not Reborn. Covered by "Tests (Legacy)". #5657

@BenKurrek
BenKurrek marked this pull request as ready for review July 13, 2026 18:58

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@BenKurrek
BenKurrek merged commit 25f8c12 into main Jul 13, 2026
62 checks passed
@BenKurrek
BenKurrek deleted the codex/frontend-source-conventions branch July 13, 2026 19:09
BenKurrek added a commit that referenced this pull request Jul 13, 2026
…#5850)

Atomic roll-up of the 8-PR NEA-25 taxonomy stack onto current main. Extension is
the only installable product object; tool/channel/auth are derived capability
surfaces; runtime kind controls loading only; manifest projection (v2, host_api
contracts) is the sole surface-discovery source of truth. The connectable-channels
rail and the parallel `kind` taxonomy are removed and pinned by a zero-legacy gate.
slack_bot and slack_personal are retired into one `slack` extension with bounded
forward migrations. Extensions wire carries runtime + surfaces, not a conflated kind.

Supersedes #5833, #5839, #5842, #5845, #5847, #5848, #5849, #5850. Conflicts with
main since the train forked were reconciled preserving main's newer behavior
(#5851 unified slack cleanup, #6054 get_conversation_info DM resolution, #5499
extension import, #6057 TS source conventions). provider_identity domain
duplication removed; the residual is a legitimate up-layer port adapter. See the PR
description for the per-PR crosswalk, resolutions, placement audit, and verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-6057 — a8957fd6 Deployed Jul 13, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: low Changes to docs, tests, or low-risk modules scope: docs Documentation size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant