Skip to content

feat: Adds typescript domain - /tsc-blindspots, /derive-types, /avoid-any, /decompose-large-files, /migration-context-cost skills - #69

Open
MajorLift wants to merge 16 commits into
MetaMask:mainfrom
MajorLift:add/typescript-typing-skill
Open

feat: Adds typescript domain - /tsc-blindspots, /derive-types, /avoid-any, /decompose-large-files, /migration-context-cost skills#69
MajorLift wants to merge 16 commits into
MetaMask:mainfrom
MajorLift:add/typescript-typing-skill

Conversation

@MajorLift

@MajorLift MajorLift commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Overview

Adds a typescript domain — five experimental skills for TypeScript authoring and JS→TS migration, the layer coding-guidelines only gestures at. Grounded in MetaMask/contributor-docs docs/typescript.md.

  • avoid-anyany disables type checking rather than widening a type. Substitute by position: assignee → unknown, assigned → never.
  • derive-types — derive from authoritative sources (indexed access, typeof) instead of ad-hoc types that duplicate and drift (#42583).
  • decompose-large-files — split by coherent, independently-mergeable units, unblocking incremental migration. Modeled on the MetamaskController decomposition (#41735).
  • migration-context-cost — the fan-in/fan-out cost of a conversion: cheap first migration, or one pulling half the repo.
  • tsc-blindspots — the defects tsc is structurally unable to report; a green build is not evidence the types are correct. Lands here rather than in testing, superseding Add typescript-compiler-blindspots skill #85: derive-types' question, one step later.

Motivation

All three repos author new TypeScript and re-enable @typescript-eslint/no-explicit-any to error over a shared config that turns it off — extension .eslintrc.js:162, mobile .eslintrc.js:170, core eslint.config.mjs:152.

With checkJs off, unconverted neighbors are unchecked, so a green build does not establish well-formedness across the boundary.

Two are proposed always-loaded, spending shared description budget: tsc-blindspots, because a green build reads as proof, so nobody searches for what tsc cannot report; derive-types, because an author hand-writing a type does not know an authoritative source exists.

Showcase

Trial runs against merged PRs nobody flagged. Gap: the run surfaced something the PR had not.

PR Skill Verdict Finding
#41333 tsc-blindspots Gap local type restates upstream Log.topics; naive probe reports false clean

The evidence showcase carries the derive-types example: #44397 (derived-type substitution) — 12 hand-written types, 9 with an authoritative source, 5 of those disagreeing, 1 dropped guard traced to inert, 2 unnecessary runtime changes; one arm silent at exit 0.

MajorLift added a commit to MajorLift/metamask-skills that referenced this pull request Jul 16, 2026
…d by the `typescript-typing` skill

Their content now ships as the `typescript-typing` skill in MetaMask#69,
where it distributes via the CLI — knowledge/ files are never synced.
@MajorLift MajorLift changed the title Add typescript-typing skill (any-handling + type derivation) Add typescript domain: avoid-any, derive-types, decompose-large-files Jul 16, 2026
…ary-identification is step one of any migration
…und unit conversion, swap in the stronger derive-types example, slim CHANGELOG

- migration-context-cost: line count is a factor not a non-factor; fan-in is a reading cost (not a change/review surface), fan-out is the change surface; drop the wrong "upstream types land first" and off-topic barrel bullet
- decompose-large-files: the point is converting to TS in small self-contained units, not extraction
- derive-types: replace the NetworkState restatement with the reinvented-messenger + hand-copied-return example (derive via `ReturnType<Action['handler']>`)
- CHANGELOG: list the domain, not each skill
@MajorLift
MajorLift force-pushed the add/typescript-typing-skill branch from 5e7bc67 to 801758f Compare July 22, 2026 16:31
CHANGELOG.md tracks consumer-facing changes to the `@metamask/skills` package,
per CONTRIBUTING's "CLI / tooling changes" section. No merged skill-only PR adds
an entry (MetaMask#80, MetaMask#78, MetaMask#70, MetaMask#62, MetaMask#61 all touch zero changelog lines).

It was also the sole source of this branch's conflict with `main`, since every
skill PR edits the same `[Unreleased]` block.
@MajorLift MajorLift changed the title Add typescript domain: avoid-any, derive-types, decompose-large-files feat(typescript): add authoring and JS→TS migration skills Jul 30, 2026
@MajorLift
MajorLift marked this pull request as draft July 30, 2026 14:03
…main

Was a separate PR against `domains/testing`. It belongs here: its subject is
whether a hand-written type agrees with its authoritative source, which is the
question `derive-types` answers from the authoring side, and it shares this
domain's premise that a green `tsc` is not evidence the types are correct.

Directory name and frontmatter `name` already agree; only the domain moved.
@MajorLift MajorLift changed the title feat(typescript): add authoring and JS→TS migration skills feat(typescript): add authoring, migration, and compiler-blindspot skills Jul 30, 2026
@MajorLift MajorLift changed the title feat(typescript): add authoring, migration, and compiler-blindspot skills feat(typescript): add typescript-compiler-blindspot and authoring, migration skills Jul 30, 2026
@MajorLift MajorLift changed the title feat(typescript): add typescript-compiler-blindspot and authoring, migration skills feat(typescript): add typescript-compiler-blindspots and type-safe authoring, JS->TS migration skills Jul 30, 2026
@MajorLift
MajorLift marked this pull request as ready for review July 30, 2026 18:15
@MajorLift

MajorLift commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Context budget

What this PR costs an agent, measured from an install rather than read from the diff. Three tiers, and only the first is unavoidable.

Skill Frontmatter Selected + refs & knowledge
avoid-any 359 chars ~1,605 tok ~1,605 tok
decompose-large-files 266 chars ~1,612 tok ~1,612 tok
derive-types 210 chars ~1,168 tok ~1,168 tok
migration-context-cost 243 chars ~781 tok ~781 tok
tsc-blindspots 1,244 chars ~3,406 tok ~8,327 tok

Frontmatter is the only tier paid unconditionally — every agent loads it on every run once the skill is installed, used or not, because it is what the agent reads to decide relevance. The 28 skills across the eleven open skill PRs sit at a median of ~1,716 tokens selected and ~1,860 with references followed. All are within the 1,536-character description budget.

Selected is paid only when the agent picks the skill. + refs & knowledge is the ceiling if every bundled reference is then read; it is a worst case, not an expectation.

Method

tools/install --repo metamask-extension --maturity experimental against this branch at e170b394c, measured per installed skill directory. Repo overlays are merged into the emitted SKILL.md, so they land in the selected tier rather than being missed by a source-byte count. Token figures are bytes/4 — a proxy for scale, not accounting.

These figures are pinned to the commit above and drift on every push; #96 tracks automating them.

The skill lives in the `typescript` domain, so the prefix repeated information
already carried by the path and by every discovery surface that shows it.
Installed as `mms-compiler-blindspots`.
@MajorLift MajorLift changed the title feat(typescript): add typescript-compiler-blindspots and type-safe authoring, JS->TS migration skills feat(typescript): add compiler-blindspots and type-safe authoring, JS->TS migration skills Jul 31, 2026
@MajorLift MajorLift changed the title feat(typescript): add compiler-blindspots and type-safe authoring, JS->TS migration skills feat(typescript): add tsc-blindspots and type-safe authoring, JS->TS migration skills Jul 31, 2026
Skills install flat as `mms-<name>`, so `domains/typescript/` does not
disambiguate the name at the callsite — and "compiler" reads as React Compiler in
a repo where that is a live subject. The skill is about `tsc` specifically: its
own first clause is "the type defects `tsc` is structurally unable to report".

Also adds the slash trigger to the description, which listed only prose phrases.
Four additions, each of which found something the existing sections did not
point at, while reviewing a JS->TS conversion.

`any` absorption gains its complement: the existing bullet traces where a
confidently-typed value entered, which finds nothing when the value is a module's
own return. Tracing where an `any` *exits* — assigning the return to two
impossible types with a known-typed sibling as control — found `any` escaping a
resolver into its caller. The control line is load-bearing: without it a silent
probe is indistinguishable from one that cannot fail, and running outside the
project tsconfig produces errors that are the harness rather than the finding.

Ethers `Contract` dynamic methods are named as a source, since the ABI is runtime
data and the call reads as an ordinary typed await. It is already tracked at
#31973, where one consumer declares `Promise<any>` with a disable comment and
another lets it infer; the second is the dangerous form.

Ambient `declare module` verification moves from reading package source to
requiring the package and checking exports, return `typeof`, and whether a
default export is legitimate under esModuleInterop.

Inventory now begins by checking the module is referenced at all — a dead
module's types are unfalsifiable, and its conversion is a deletion candidate
rather than a typing exercise.
MajorLift added a commit that referenced this pull request Aug 4, 2026
Adds #44 (platform), #69 (typescript), #90 (privacy-egress-diligence),
#91 (agent-run-cost) and #98 (mms-debug). The first nine were taken from an
earlier sync list rather than an enumeration of open PRs, which is how these
were missed.
…finds it

A precise annotation fed `any` at every call site is reportable by neither
`tsc` nor `no-explicit-any`, and an ambient `declare module` in the path
re-mints the `any` as a confident `string`. Both arms of the probe verified
against `metamask-extension`.

Also fixes `avoid-any`'s frontmatter, which did not parse as YAML.
The installer emits `mms-tsc-blindspots`; the description advertised `/tsc-blindspots`.
`tsc-blindspots`, `derive-types` and `avoid-any` shipped without a
`repos/` directory, so they installed into every repo by default rather
than by decision, carrying content written against no repo in particular.

A blind spot only exists where the setting that would catch it is off,
so the overlays genuinely differ. Extension and mobile set `allowJs`,
making the JS boundary a live unchecked surface; core does not, and its
overlay says so rather than omitting the class. Core instead has
`composite: true`, where a type can go stale across a project reference.
Extension's `strict` is inherited from `@tsconfig/node22` rather than
local, which is itself a blind spot for anyone auditing tsconfig.json.

`@metamask/eslint-config-typescript` sets `no-explicit-any` and all five
`no-unsafe-*` rules to 'off' in every resolved major (13.0.0 mobile,
14.1.1 extension, 15.0.0 core), so each repo's local 'error' is a
deliberate re-enable rather than a default.

Extension's lint block carrying `no-explicit-any` takes its file list
from the parsed tsconfig program, so the ~300 `*.stories.ts(x)` excluded
from `tsconfig.json` lose the rule and `tsc` together.

Every line citation verified against `origin/main` rather than a working
tree; none resolves to a blank line. Installs verified into all three
repos with the correct overlay merged.
@MajorLift MajorLift changed the title feat(typescript): add tsc-blindspots and type-safe authoring, JS->TS migration skills feat: Adds typescript domain - tsc blindspots, derive types, avoid any, decompose large files, migration context cost skills Aug 31, 2026
Every count and line number in the three overlays was read from a local
checkout that was behind `origin/main`, so the figures were stale: core
reported 75 packages and 1,380 `.ts` files against an actual 98 and 2,052.

Adds the two findings the re-read surfaced: `tsconfig.lint.json` declares
its own 14 `references` rather than inheriting the root config's 98, so
`lint:tsc` covers 14 of 98 packages; and extension's `no-explicit-any`
block scopes to the parsed tsconfig program, so the 300 `.stories.ts(x)`
excluded from `tsconfig.json` lose the lint rule and `tsc` together.

Drops the note in `references/metamask-extension.md` explaining that the
notes live outside `repos/` to avoid skipping mobile and core installs —
the skill now ships all three overlays, so the reason is spent.
@MajorLift MajorLift changed the title feat: Adds typescript domain - tsc blindspots, derive types, avoid any, decompose large files, migration context cost skills feat: Adds typescript domain - /tsc-blindspots, /derive-types, /avoid-any, /decompose-large-files, /migration-context-cost skills Aug 31, 2026
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