Skip to content

chore(lint): estende no-loose-number, no-raw-cents, no-double-cast e knip a scripts/** - #262

Merged
fm1randa merged 3 commits into
mainfrom
chore/259-scripts-lint-scope
Nov 6, 2026
Merged

fm1randa merged 3 commits into
mainfrom
chore/259-scripts-lint-scope

Conversation

@fm1randa

@fm1randa fm1randa commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

Problema

no-loose-number, no-raw-cents e no-double-cast só rodavam em src/** e test/**, e o knip só olhava bin/** e src/**. Por isso scripts/** acumulou Number() frouxo e centavos crus (Math.round(x * 100)) nos mocks e nos scripts do guard, além de exports mortos que ninguém via.

Mudança

  • eslint.config.js: as três regras passam a cobrir scripts/**/*.ts. Nenhuma isenção foi necessária.
  • knip.json: scripts/**/*.ts entra no project; scripts/mock-api.ts e scripts/private-terms-cli.ts entram como entry, porque o verify.sh os roda direto e o knip não lê shell.
  • Mocks (mock-api, mock-entries, mock-cards, mock-balances):
    • IDs capturados por regex passam por parseId. IDs do corpo da requisição passam por idOf, que aceita número JSON ou string de dígitos, porque o conta do create é string (src/types/entry.ts).
    • Somas usam roundToCents. Campos que já são number no tipo (Entry.conta, Entry.valor) deixam de ser convertidos.
    • Campos numéricos do payload passam por requiredNumber/requiredId. Um campo que não é número agora derruba a requisição em vez de ser coerçido em silêncio. Assim uma regressão da CLI que mande "12" no lugar de 12 aparece no e2e.
  • check-eslint-disables.ts, private-terms.ts e private-terms-history.ts: os números do cabeçalho do diff e do git cat-file passam por parseInteger. No private-terms.ts, um tamanho ilegível agora cai no erro unexpected git cat-file header que já existia, em vez de virar NaN.
  • Knip: 14 exports sem uso em scripts/** perdem o export. O código continua lá, só deixa de ser exportado.

Escopo

Closes #259

Checklist

  • Se a mudança introduz ou altera um termo do domínio, o GLOSSARY.md foi atualizado neste PR. (Não altera termos.)

Risco

bun scripts/risk.ts classifica o PR como arriscado (exit 2) porque ele toca scripts/private-terms.ts, scripts/private-terms-history.ts e scripts/private-terms-corpus.ts. Análise de impacto feita à mão (não há skill /blast-radius nesta sessão):

  • private-terms.ts: só muda o parse do tamanho do blob em blobContents. Um cabeçalho válido produz o mesmo número de antes. Um inválido agora falha alto em vez de gerar NaN.
  • private-terms-history.ts: só muda o parse do número de linha do hunk em deletedLines. Mesmo resultado para qualquer cabeçalho @@ -N.
  • src/utils/parse.ts (achado do blast radius): o guard passou a ler a saída do git com parseInteger, mas o risk.ts não marcava esse arquivo como superfície de segurança. Um PR futuro que mexesse em parseInteger mudaria o guard sem ganhar o label risco. Corrigido: src/utils/parse.ts entrou em SECURITY_SURFACES. O novo teste test/risk-guard-imports.test.ts percorre os imports em tempo de execução de private-terms-cli.ts, private-terms-corpus.ts e check-private-messages.ts e falha quando algum módulo carregado não é superfície. A única exceção é scripts/private-terms-excused.ts, que o AGENTS.md já deixa de fora. O AGENTS.md foi atualizado com a nova superfície e a nova linha da tabela de cobertura.
  • private-terms-corpus.ts: só perde o export de hasPhrase, uncoveredRemovedTerms e o re-export de tipos sem uso. Nenhuma lógica muda.
  • Prova do fato de segurança: test/private-terms.test.ts e test/private-terms-corpus.test.ts (com o replay da migração chore: remove referências pessoais do código e dos fixtures #177) passam sem alteração, e os passos private terms e private-terms corpus do verify.sh passam.

Aguarda a decisão do mantenedor antes do merge.

Verificação

  • scripts/verify.sh: VERIFICAÇÃO OK (Bun 1.4.2, o fixado em packageManager), após o merge da main atual.
  • Reprodução antes: o config desta branch aplicado ao código da main falha (ver Prova).
  • Reprodução depois: bun run lint e bun run knip passam na branch.

Prova

Fails-on-main: isento — PR chore sem mudança em src/ ou bin/; a prova é a regra falhando no código da main.

Web: sem equivalente na web

Antes (main)

Worktree em origin/main com o eslint.config.js e o knip.json desta branch:

$ bunx eslint scripts   # config da main
exit=0
$ bunx eslint scripts   # config da branch
exit=1
     37 local/no-loose-number
      5 local/no-raw-cents
$ bunx knip
exit=1
Unused exports (6)
Unused exported types (8)

Depois (branch)

$ bun run lint
exit=0
$ bun run knip
exit=0
$ env -u TERM -u COLORTERM -u TERM_PROGRAM scripts/verify.sh
✓ private-terms corpus
✓ typecheck
✓ lint
✓ knip
✓ test
✓ private terms
VERIFICAÇÃO OK

Superfície src/utils/parse.ts no risk.ts

test/risk-guard-imports.test.ts rodado contra o risk.ts de antes da correção (só com securityDetail exportado):

(fail) private-data guard imports > every module the guard loads is a security surface
+ [
+   "src/utils/parse.ts",
+ ]
(fail) private-data guard imports > flags a behavior change in src/utils/parse.ts as security
+   "reasons": [],
+   "risky": false,

Na branch: bun test test/risk-guard-imports.test.ts test/risk.test.ts test/risk-label.test.ts: 31 pass, 0 fail.

O gate risk mudou, então segue o replay (bun scripts/replay-gates.ts --gate risk). Nenhum dos 10 commits mexe em src/utils/parse.ts, por isso os disparos são os mesmos de antes:

replay-gates: 10 commits from origin/main
1045a83 docs: align README, GLOSSARY and api-filters with the CLI (#261)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
d1530d3 refactor(api): lê a MDCLI_API_URL na hora da chamada (#257)
  risk: FIRED (src/lib/api.ts (auth): unclassified change in a sensitive file; src/lib/api.ts (write): unclassified change in a sensitive file)
c6a404c refactor(browser-session): type the page global as MdWindow instead of any (#256)
  risk: FIRED (src/lib/browser-session/index.ts (auth): unclassified change in a sensitive file)
1c801d4 refactor(dates): stamp importId through nowMs() instead of Date.now() (#255)
  risk: FIRED (src/commands/entries/import/commit.ts (write): unclassified change in a sensitive file)
d3c672f chore(release): v2026.11.5 (#254)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
0a96f92 test(ci): run browser tests outside the parallel pool (#253)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
7b4a5e8 docs(agents): report a CI failure from its log, not a passing rerun (#252)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
bf8f6d3 docs(agents): merge main before opening or pushing an implementation PR (#251)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
4c0332a refactor(ci): dono único para "este diff muda comportamento" (#245)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
602a86a test(ci): declare the Bun runtime premise of the stdout guard (#247)
  risk: skipped (safe: no authentication, session, credential, data write or security surface change)
replay-gates: 3 fired, 7 skipped
  • Modelo: claude-opus-5-5
  • Harness: t3/claude code

Agent and others added 2 commits November 6, 2026 17:29
Scope no-loose-number, no-raw-cents and no-double-cast to scripts/**, add
scripts/** to the knip project, and replace the flagged Number() calls and
raw cents in the mocks and guard scripts with the src helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the risco PR arriscado: exige /blast-radius e decisão do mantenedor label Nov 6, 2026
The guard now parses git output with parseInteger, so a change to
src/utils/parse.ts changes what the guard reads without any guard file
moving. Add it to SECURITY_SURFACES, and add a test that walks the
runtime imports of the guard entry points and fails on any module
risk.ts does not flag, so the next shared helper cannot slip past.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@datadog-official

Copy link
Copy Markdown

Pipelines

❌ Errors

Your PR has failed checks. Please review the issues below and take necessary action before merging.

🚦 1 Pipeline job failed

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: ad7575c | Docs | View more details | Give us feedback!

@fm1randa
fm1randa merged commit ec8ae54 into main Nov 6, 2026
7 of 8 checks passed
@fm1randa
fm1randa deleted the chore/259-scripts-lint-scope branch November 6, 2026 16:48
fm1randa pushed a commit that referenced this pull request Nov 6, 2026
Resolve the conflicts with #262: check-eslint-disables, private-terms-history
and replay-gates keep the scripts/git.ts helpers and the shared parseDiff,
which now reads hunk numbers through parseInteger as #262 required of the old
parsers. scripts/git.ts and scripts/behavior-change.ts join the security
surfaces, since the private-data guard now loads both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risco PR arriscado: exige /blast-radius e decisão do mantenedor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(lint): estende no-loose-number/no-raw-cents/no-double-cast (+ knip) a scripts/**

1 participant