Skip to content

feat: add portable rule-owned migration dashboard - #29

Draft
devagrawal09 wants to merge 16 commits into
masterfrom
agent/rule-dashboard
Draft

feat: add portable rule-owned migration dashboard#29
devagrawal09 wants to merge 16 commits into
masterfrom
agent/rule-dashboard

Conversation

@devagrawal09

@devagrawal09 devagrawal09 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an opt-in, portable Solid 2 migration dashboard while preserving the analyzer's existing default terminal behavior.

  • adds --report FILE, explicit --force, and explicit --open
  • emits one self-contained HTML file with inert escaped JSON and file:// hash routing
  • adds four complete rule-owned pilot slices:
    • web renderer imports
    • component renames
    • createEffect review sites
    • legacy subpath relocation proposals
  • keeps the host payload-opaque; each rule owns its report contract, empty/merge behavior, summary, and detail renderer
  • previews transformation edits without applying them
  • renders rule-owned structured summaries, reasons, steps, cautions, validation, and official links from the same data that formats terminal guidance

Settled behavior

  • one immutable run per report; no report history
  • all four pilot rules remain visible, including clear zero states and stable routes
  • bounded snippets contain the complete matched range plus one complete line before and after
  • detail pages support filename filtering in the rule hash URL, local expansion state, direct one-click VS Code actions with copy-location overflow menus, and 100-result pagination after filtering the full dataset
  • findings sort by normalized relative filename, line, and column
  • the index groups by static domain metadata and alphabetizes groups and rules
  • the header shows the full fixed absolute analyzed target root in a wrapping utility row with a Copy root action
  • complete light/dark themes start from prefers-color-scheme; manual changes are session-only and reset on reload
  • existing report destinations are refused unless --force; browser launch happens only with --open

Source disclosure

Generated HTML embeds bounded project source snippets and the absolute analyzed target path. Treat and share the report as project source and local machine metadata. The CLI and README disclose this, including the limitation that editor links retain the fixed generation-time path.

Validation

pnpm verify passes in full:

  • 9 architecture tests
  • 10 report tests
  • 13 package/CLI tests
  • 28 analysis adapters / 48 fixtures
  • 1 transformation adapter / 11 fixtures
  • workflow and transform end-to-end tests
  • source and dashboard typechecks
  • both workflow schema validations

Additional native/browser checks:

  • repeated native report runs produced byte-identical HTML
  • tests/fixture SHA-256 hashes were unchanged after report generation
  • Chrome verified file://...report.html#/rules/... clicks, back/forward, reload, unknown routes, and hash-contained filename filters
  • Chrome verified forced light and dark system preferences, manual theme toggles, reset-on-reload, persistent target-root display, structured sections, VS Code URIs, and copy fallbacks
  • Chrome keyboard checks verified direct editor focus, overflow-menu activation, and Tab focus into Copy location; a 360 px viewport had no horizontal document overflow and preserved the full wrapped root

Local-only review artifacts

.reports/rule-dashboard-plan.html and .reports/sample-dashboard.html remain local and untracked; they are not part of this PR.

- Organize read-only analysis rules under rules/analysis/ (imports, jsx,
  lifecycle, props, reactivity, store)
- Add transform workflow: deterministic relocation of the five pure legacy
  Solid subpaths (h, html, universal, jsx-runtime, jsx-dev-runtime) with
  per-edit reports and end-to-end fixture/expected trees
- Consolidate emit steps into one shared scripts/emit-report.ts used by both
  the analyze and transform workflows (guidance vs relocation report)
- Extend architecture, packaging, rule, and workflow tests for the two
  workflow layout and the new transform rule adapter
- Fix prototype-chain module lookup: bare specifiers such as constructor,
  toString, hasOwnProperty, valueOf, and __proto__ resolved through
  Object.prototype and were rewritten into inherited-member garbage; use
  Object.hasOwn for the relocation map lookup
- Fix `export default "solid-js/h"` being treated as a re-export source:
  only a string that follows the `from` keyword is a re-export's module
  source, so exported string values stay byte-identical
- Fix locally shadowed `require` false positives: files declaring their own
  require binding (function, const, parameter, import, catch) now leave
  every bare require() call in the file untouched; ambient `declare const
  require` remains a valid CommonJS require
- Split transform rule coverage into 10 focused fixtures (static imports,
  single quotes, re-exports, runtime forms, negative forms, shadowed
  require, prototype names, escaped specifiers, no matches, broad
  integration), each asserting exact relocations and exact transformed text
- Extend end-to-end transform fixtures with src/negative.ts (0 relocations),
  src/plain.js (CommonJS require), and src/nested/deep.jsx (nested JSX)
- Update the rule adapter, transform-rules harness invariant (1 adapter /
  10 fixtures), architecture fixture list, and e2e report regex/count
Rule folders stay lean: legacy-subpath-relocation now contains only the
rule and its test adapter, with all 10 focused fixtures under
fixtures/. Update the transform-rules harness to scan the subfolder and
generalize assertRuleLayout to allow an optional fixtures subdirectory
(analysis rule folders remain flat).
The syntactic shadow scan for bare require() calls matched any identifier
named require next to a binding construct, which was wrong in both
directions:

- false positives (safe, missed relocations): `import { require as r }`,
  `function f(a = require)`, and `const alias = require` counted as local
  require bindings even though the local binding is r, a, and alias
- false negatives (unsafe, wrong edits): `const [require] = arr`,
  `function f([require])`, and `const { require = 1 } = obj` were not
  detected as bindings, so bare require("solid-js/...") calls that resolve
  to those local functions were rewritten

The scan now matches the exact binding slot via tree-sitter fields
(import_specifier.alias, parameter.pattern/value, assignment left,
pair_pattern value, declarator name), so references next to bindings never
count and destructuring bindings always do. `declare const/function
require` remains exempt as the ambient CommonJS require.

Regression coverage: new destructured-require fixture (array and
object-pattern-default shadows stay byte-identical) and extended
runtime-forms fixture (import alias, parameter default value, and
declarator alias references no longer suppress the require relocation).
Harness counts updated to 11 fixtures; verified with 12 independent
workflow probes (6 relocate / 6 untouched, all correct).
@socket-security

socket-security Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​solidjs/​vite-plugin@​3.0.0-next.287610010090100
Added@​types/​node@​24.10.11001008195100
Addedvite@​8.2.1991008296100
Addedvite-plugin-singlefile@​2.3.310010010082100
Added@​solidjs/​web@​2.0.0-rc.0961008397100
Addedsolid-js@​2.0.0-rc.01001009596100
Added@​solidjs/​router@​2.0.0-next.1610010010097100

View full report

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.

1 participant