feat: namespace-drift CI check for contracts package (#77)#82
Conversation
The @mento-protocol/contracts package is generated from .treb/deployments.json one namespace at a time, so any published namespace nobody remembers to regenerate silently drifts — its live on-chain addresses never reach the package and nothing notices (issue #77: ~88 addresses sat unpublished for two months). Add `pnpm contracts:check-drift` (scripts/check-namespace-drift.ts): it regenerates every already-published namespace into a temp copy using the real generator and fails if the result adds or re-points any address vs the committed contracts.json. Reusing the generator makes it authoritative — it can't disagree with the generator's own filtering rules. The published namespace set is derived from the committed contracts.json, so ephemeral namespaces (virtual/throwaway/test/old RCs) are excluded by construction and a new namespace is guarded the moment it first lands in the package. Drift is additive-only (treb ahead of package); the generator never removes keys, so package-ahead-of-treb is out of scope. - gen-contracts-package.ts: honor CONTRACTS_OUT_DIR to redirect all output to a temp dir and skip the formatter in that mode (the check compares parsed JSON, so formatting is irrelevant). Normal runs are unchanged. - Wired into the existing `check` job in test.yml, reusing the out/ artifacts already built there (no second forge build). - Unit tests for the pure diff/namespace helpers; README documents the guard and local command. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fi9YQqbETy2YubqdeXxSq5
|
Claude finished @chapati23's task in 1m 50s —— View job ✅ Review complete — verdict: LGTM
This is a re-review triggered by the fix commit Cross-cutting checks
Roll-up of all findings
No new issues found in the fix commit itself. The unit tests ( |
Addresses two P2 findings from Claude's review of PR #82: - process.exit(1) inside the try block skipped the finally { rmSync } cleanup (Node does not unwind finally on process.exit), leaking the temp regen dir on every drift-detected or regen-failure run. Now the drift path sets process.exitCode and regenerateInto throws, so the finally always runs; a top-level catch keeps the clean exit-1 + message. - Running the check locally before `forge build` would feed the child generator's interactive "Run forge build now?" prompt an EOF stdin under spawnSync, hanging forever. Now main() fails fast with a clear message when out/ is missing or empty. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fi9YQqbETy2YubqdeXxSq5
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e96810cb7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Thanks for the reviews. Both findings addressed in
30 unit tests pass; the drift check is green on the current tree and correctly red on simulated drift. (Note: the earlier |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74101a2420
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Re: Codex's ABI-drift suggestion on |
Closes #77.
Problem
@mento-protocol/contractsis generated from.treb/deployments.jsonbyscripts/gen-contracts-package.ts, run manually one namespace at a time. Any published namespace nobody remembers to regenerate silently drifts: its live on-chain addresses never reachcontracts.json, with no error anywhere. PR #76 revealed ~88 addresses that had been sitting unpublished since v0.8.1 — including Celo mainnet Chainlink relayers consumers may have needed for two months.What this adds
A
pnpm contracts:check-driftguard (scripts/check-namespace-drift.ts) that:contracts.jsonitself — currentlymainnet,monad-mainnet,testnet-v2-rc5. Ephemeral namespaces (virtual,throwaway,test, superseded RCs) are excluded by construction, and a newly-published namespace is guarded the moment it first lands in the package.Design decisions (the issue's open questions)
trunkneeded in CI, runnable locally), not a shellgit diff.checkjob intest.yml, reusing theout/artifacts already built there (no secondforge build).Generator change
gen-contracts-package.tshonors a newCONTRACTS_OUT_DIRenv var to redirect all output to a temp dir and skip the formatter in that mode. Normalcontracts:updateruns are unchanged.Verification
pnpm test— 30 pass (5 new unit tests for the pure diff/namespace helpers).pnpm contracts:check-drift— passes onmain(package is in sync).137/mainnet/EUROPfrom the committed package): the check correctly flagged the missing key, mapped it tomainnet, printed the exactcontracts:updateremediation command, and exited 1.trunk checkclean on all changed files.Ship Checklist
🤖 Generated with Claude Code
Note
Low Risk
CI and local tooling only; generator behavior for normal
contracts:updateis unchanged aside from optionalCONTRACTS_OUT_DIR.Overview
Adds
pnpm contracts:check-driftso CI can catch when.treb/deployments.jsonhas moved ahead of the committed@mento-protocol/contractspackage without a regen.The check discovers published namespaces from committed
contracts.json, regenerates each namespace with the realgen-contracts-package.tsinto a temp tree (via newCONTRACTS_OUT_DIR), and fails on additive drift—new contract keys or changed addresses (case-insensitive). It printscontracts:updateremediation commands.gen-contracts-package.tsskipstrunk fmtwhen writing to that temp dir.The Foundry
checkjob runs the drift step afterforge buildso ABIs come from existingout/artifacts. Docs and Vitest cover the pure diff/namespace helpers.Reviewed by Cursor Bugbot for commit e96810c. Configure here.