Skip to content

web: review types are hand-mirrored instead of imported from @codesema/contract, and have already diverged #90

Description

@naashw

Intent

packages/contract exists to be the shared review contract, and its description says so: "Shared review contract (types + sanitizers) between the codesema CLI and codesema.com." The CLI consumes it (packages/cli/src/contract.ts is a one-line re-export).

The web UI does not. packages/web/package.json declares no dependency on @codesema/contract at all; instead packages/web/src/types.ts:43 redeclares ReviewRecord by hand, with the mirroring stated as a comment at :74:

// Mirrors packages/cli/src/serve.ts and partial.ts.

That mirror has already drifted. files_reviewed?: ReviewedFile[] exists in the contract (packages/contract/src/index.ts:98), is produced by the CLI (packages/cli/src/dual.ts:404) and is recomputed by the contract's own remapping logic (:731-744), but no such field exists in the web type. The typechecker cannot see the divergence, because there is no dependency edge for it to check.

The result is a contract that constrains the external consumer (codesema.com) while leaving the in-repo consumer free to drift — which is the reverse of what a shared contract is for, since the web UI is the one shipped inside the CLI tarball.

Scope

In scope:

  • Review-shaped types in packages/web/src/types.ts that mirror contract types.
  • The missing dependency edge from packages/web to @codesema/contract.

Out of scope:

  • Web-only view types with no contract counterpart (component props, board state).
  • The SSE frame types, unless they turn out to mirror contract types too.
  • Any change to the contract's own shape.

Approach

Add @codesema/contract as a workspace dependency of packages/web, then delete the hand-mirrored declarations in favour of imports, one type at a time. Where the web genuinely needs a narrower view, derive it from the contract type (Pick/Omit) so the typechecker still fails when the source moves.

MODIFIED Requirements

Requirement: Review types MUST have a single source

The system SHALL define review-shaped types once, in @codesema/contract, and both the CLI and the web UI SHALL derive their types from it rather than restate them.

Scenario: a contract field is added

  • GIVEN a new optional field added to the review type in @codesema/contract
  • WHEN the web package is typechecked
  • THEN the web sees the new field without any manual edit to packages/web/src/types.ts

Scenario: a contract field is renamed

  • GIVEN a field renamed in @codesema/contract
  • WHEN the web package is typechecked
  • THEN the build fails at every web site that referenced the old name

Tasks

1. Wire the edge

  • 1.1 Add @codesema/contract as a workspace:* dependency of packages/web
  • 1.2 Confirm the Vite build resolves it and the published tarball is unaffected

2. Remove the mirror

  • 2.1 Inventory the types in packages/web/src/types.ts that mirror contract types
  • 2.2 Replace each with an import, or a Pick/Omit derived from it
  • 2.3 Delete the // Mirrors ... comment once nothing mirrors

3. Close the known drift

  • 3.1 Decide whether the web should render files_reviewed, or explicitly omit it via a derived type

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingseverity:minorMinor severity review finding

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions