Skip to content

refactor: drop the last four suppressions under the type-guard parser exemption - #162

Open
Upd4ting wants to merge 2 commits into
mainfrom
refactor/parser-exemption
Open

Upd4ting wants to merge 2 commits into
mainfrom
refactor/parser-exemption

Conversation

@Upd4ting

@Upd4ting Upd4ting commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Why

Antony wants this repo held by its lint with no escape hatches: every suppression guardrails.suppressions.json allows goes to 0 with the code fixed (ANT-1098). The last four were anti-slop/no-unknown-parameters directives on functions that parse an untyped stored cell or query answer. tooling-configs now exempts a parameter a function reads only through type guards (ANT-2363). This PR pins that tooling-configs, drops the four directives and lowers the ceiling to 0. Every ceiling in the file is now 0.

Temporary deps: wait for release of @antelopejs/tooling-configs

What changed

  • package.json, lockfiles, .tgz-deps/. @antelopejs/tooling-configs is pinned to a tarball of its main at faf4580, which carries the exemption, until it is released. pnpm-workspace.yaml takes the allowBuilds: lefthook: false entry that pack's sync now writes.
  • src/utils/query.ts (cellToText), src/service/browse.ts (jsTypeOf), src/service/introspect.ts (inferFieldType). Each one already reads its parameter only through type guards, so the exemption covers it. The directive line is removed and nothing else changes.
  • src/routes/query.ts (normaliseRows). It stored the answer it couldn't classify as { value: raw }, a value no guard had narrowed, so the exemption didn't cover it. It now narrows the answer through isRow, a local isList and isScalarAnswer (string, number, boolean or null), and answers an empty row for anything else. Each entry of a list goes through rowOf the same way.
  • src/test/query-rows.test.ts. A new test drives DatabaseQueryController.execute with chosen store answers and checks the rows it returns.

Attention

One output changes. A query answer, or a list entry, that has no JSON form now gives an empty row {}. That means a bigint, a symbol, a function, or an undefined list entry. Before:

  • A bigint was stored as { value: 1n }. The route then failed to send it, because JSON.stringify throws on a bigint.
  • A symbol, a function or an undefined list entry was stored as { value: … }, and JSON.stringify dropped the key, so the client already received {}.

For those three the wire answer is unchanged. For a bigint the answer goes from a failed response to {}. No store this module runs on answers these values. Every other answer gives the same rows as before.

Proof

The new test, on origin/main and on this branch. Before, it failed only on the answers with no JSON form:

  [integration] query console rows
    ✔ shows an object as a row, a scalar or a list as its value (56ms)
    1) shows an answer with no JSON form as an empty row

  1 passing (84ms)
  1 failing

  1) [integration] query console rows
       shows an answer with no JSON form as an empty row:

      AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

  [
+   {
+     value: 1n
+   }
-   {}
  ]

      + expected - actual

       [
      -  {
      -    "value": "1"
      -  }
      +  {}
       ]
      

After:

  [integration] query console rows
    ✔ shows an object as a row, a scalar or a list as its value (86ms)
    ✔ shows an answer with no JSON form as an empty row

  2 passing (157ms)

pnpm run checks on the committed head:

Checks: 12 passed, 0 failed.
flowchart TD
  A[query answer] --> L{isList} -->|yes| M["each entry through rowOf"]
  L -->|no| R{isRow} -->|yes| O["[answer]"]
  R -->|no| S{isScalarAnswer} -->|yes| V["[{ value: answer }]"]
  S -->|no| U{undefined} -->|yes| N["no row"]
  U -->|no| E["[{}], no JSON form"]
Loading

No SAFETY: comment is added.

API: 1 packages, 3 entries unchanged against origin/main (committed HEAD).
API: skipped .agents/skills/verify-dms-database, not a workspace package.
API: skipped frontend-vue, private.
API: skipped playground, not a workspace package.
Runtime API: 1 packages, 2 entries unchanged against origin/main (committed HEAD).
Auto-imports: 1 packages, 0 entries unchanged against origin/main (committed HEAD).
No behavioural probe ran.

Suppressions in authored code files (origin/main and committed HEAD). A lint directive counts once per rule it names; * is a directive naming none.

Suppressions base HEAD
Lint suppressions, all rules 4 0
Lint suppressions, anti-slop/no-unknown-parameters 4 0
@ts-expect-error 0 0
@ts-ignore 0 0
SAFETY: comments 0 0
Lint config rule-offs, all rules 0 0

@Upd4ting Upd4ting added the tgz-pending Waits for a release; holds a .tgz-deps tarball label Nov 13, 2026
Upd4ting added a commit that referenced this pull request Nov 13, 2026
…163)

## Why

interface-database 0.4.0 was published on 2026-11-13. It drops
`Schema.get`'s type arguments and types a looked-up schema's definition
as `unknown` (ANT-2383). The `frontend` CI job builds this layer in a
fresh Inertia app, which now installs 0.4.0, so it fails on `main` and
on every open branch. The failure is in
`frontend-vue/app/build/composables/useQueryRuntime.ts`, which called
`Schema.get<unknown, SchemaDefLike>`. This PR makes the layer compile on
0.3 and 0.4 alike, so the open PRs can go green before the module's full
0.4.0 move lands.

## What changed

- `frontend-vue/app/build/composables/useQueryRuntime.ts`. The console's
schema map is typed `Schema<unknown, unknown>` and is filled with
`Schema.get(summary.id)`, without type arguments. Nothing reads a
binding's `definition`: the map is only handed to the user's query code.
A `new Schema(id, definition)` built for a schema the registry lacks
fits the same type. Type arguments are erased, so the emitted JavaScript
is the same.

## Attention

- `antelopejs-api-diff` exits 1 on base and head alike: the released
tooling-configs still tries to compare `playground`, which has no
emitted declaration (ANT-2239, fixed on tooling-configs main and pinned
in #162). The packages it does compare report no change.
- The `ubuntu` check is the aggregate gate and fails whenever `frontend`
does.

## Proof

`pnpm test:frontend` is the `frontend` CI job: it builds and type-checks
the layer in a generated Inertia app, which installs interface-database
0.4.0.

Before (`origin/main`):

```
✖ Type check failed · 2 errors 45.7s
✖ 2 type errors
  ./frontend-vue/app/build/composables/useQueryRuntime.ts:68:3  TS2322
  ./frontend-vue/app/build/composables/useQueryRuntime.ts:69:15  TS2558
```

After (this branch):

```
✔ Type check passed 1m 14s
Verified 2 modules · 1m 33s
```

`pnpm test:layer` on the layer's own lockfile, which still resolves
interface-database 0.3.1:

```
 Test Files  19 passed (19)
      Tests  166 passed (166)
```

`pnpm run checks` on the committed head:

```
Checks: 12 passed, 0 failed.
```

API: comparison incomplete due to execution errors.
API: skipped .agents/skills/verify-dms-database, no exports, main or
types.
API: skipped frontend-vue, private.
Execution error: playground (playground):
/home/debian/.tmp/antelope-proof-vU7Y8y/worktrees/base/playground:
published target dist/index.d.ts has no emitted declaration.
Execution error: playground (playground):
/home/debian/.tmp/antelope-proof-vU7Y8y/worktrees/head/playground:
published target dist/index.d.ts has no emitted declaration.
Runtime API: 2 packages, 3 entries unchanged against origin/main
(committed HEAD).
Auto-imports: 1 packages, 0 entries unchanged against origin/main
(committed HEAD).
No behavioural probe ran.

Suppressions in authored code files (origin/main and committed HEAD). A
lint directive counts once per rule it names; `*` is a directive naming
none.
| Suppressions | base | HEAD |
| --- | ---: | ---: |
| Lint suppressions, all rules | 4 | 4 |
| Lint suppressions, `anti-slop/no-unknown-parameters` | 4 | 4 |
| `@ts-expect-error` | 0 | 0 |
| `@ts-ignore` | 0 | 0 |
| `SAFETY:` comments | 0 | 0 |
| Lint config rule-offs, all rules | 0 | 0 |
<!-- antelopejs-proof base=d571521db3dfdb977246a7111bb95132da0fd805
head=91ec99a047636f99155636495fa8f5a004a12132 lines=17
digest=a8d9577e2f00bfd3 command: antelopejs-api-diff origin/main -->
… exemption

tooling-configs main (faf4580, pinned as a tarball until its release)
exempts a parameter a function only reads through type guards.
cellToText, jsTypeOf and inferFieldType already do. normaliseRows
stored its fallback un-narrowed: it now keeps an object as a row, a
scalar or a list as { value }, and answers an empty row for a value with
no JSON form.
…ist entry

A count answers a bare number; the rows test only read numbers inside a
list and never a boolean. An undefined list entry now gives an empty row,
which JSON already sent.
@Upd4ting
Upd4ting force-pushed the refactor/parser-exemption branch from 635c94a to 7766bb9 Compare November 13, 2026 13:40

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tgz-pending Waits for a release; holds a .tgz-deps tarball

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant