feat: announce reused lockfile-verification verdicts#12326
Conversation
When the lockfile-verification gate short-circuits on a cached verdict, it used to stay completely silent, which made it look like the supply-chain policy gate never ran (#12324). Emit a new `cached` status on the pnpm:lockfile-verification channel carrying the reused record's verifiedAt timestamp, and render it in the default reporter as "Lockfile passes supply-chain policies (verified 2h ago)" (falling back to "previously verified" for records that predate the timestamp). The event fires only when policy verifiers are active, so the shape-only check every install performs stays quiet. Ported to pacquet in the same change: a `Cached` variant on the reporter's LockfileVerificationMessage with the matching camelCase wire shape, emitted from the same cache-hit point in verify_lockfile_resolutions.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (13)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🧰 Additional context used📓 Path-based instructions (2)pacquet/**/*.rs📄 CodeRabbit inference engine (pacquet/AGENTS.md)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (8)📚 Learning: 2026-05-26T21:01:06.666ZApplied to files:
📚 Learning: 2026-05-20T19:40:55.051ZApplied to files:
📚 Learning: 2026-05-22T00:08:44.646ZApplied to files:
📚 Learning: 2026-05-20T23:07:58.444ZApplied to files:
📚 Learning: 2026-06-06T18:58:37.156ZApplied to files:
📚 Learning: 2026-05-14T09:04:00.133ZApplied to files:
📚 Learning: 2026-06-05T13:47:26.046ZApplied to files:
📚 Learning: 2026-06-05T13:47:05.929ZApplied to files:
🔇 Additional comments (14)
📝 WalkthroughWalkthroughThis PR extends lockfile verification to expose cached verdicts instead of silently reusing them. When verification is short-circuited by the cache, a "cached" message is now emitted with an optional timestamp of when the lockfile was previously verified, displayed to users with human-readable durations. ChangesLockfile Verification Cached Status and Messages
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install timed out. The project may have too many dependencies for the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Micro-Benchmark ResultsLinux |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #12326 +/- ##
=======================================
Coverage 87.73% 87.73%
=======================================
Files 291 291
Lines 36034 36044 +10
=======================================
+ Hits 31613 31622 +9
- Misses 4421 4422 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Integrated-Benchmark Report (Linux)Each scenario reports direct installs and pnpr installs. Bencher consumes pacquet@HEAD and pnpr@HEAD. Scenario: Isolated linker: fresh restore, cold cache + cold store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 10.321633290640001,
"stddev": 0.09246384135628427,
"median": 10.31884307294,
"user": 3.8106472599999988,
"system": 2.14301474,
"min": 10.20515459894,
"max": 10.51674737394,
"times": [
10.36494973594,
10.51674737394,
10.38262087594,
10.36157075394,
10.26109133994,
10.31651105294,
10.32117509294,
10.27597227494,
10.20515459894,
10.21053980694
]
},
{
"command": "pacquet@main",
"mean": 10.284321675940001,
"stddev": 0.056187172603647195,
"median": 10.26641675944,
"user": 3.7601576599999995,
"system": 2.16284774,
"min": 10.21516078894,
"max": 10.39436375894,
"times": [
10.39436375894,
10.26670376494,
10.26612975394,
10.36444559094,
10.21516078894,
10.25758276594,
10.30652411594,
10.23704197394,
10.25248372094,
10.28278052494
]
},
{
"command": "pnpr@HEAD",
"mean": 5.220947227840001,
"stddev": 0.1491757767313957,
"median": 5.18054783194,
"user": 2.7528888599999997,
"system": 1.8440864399999999,
"min": 5.10388374494,
"max": 5.62123384494,
"times": [
5.13713560894,
5.18719618194,
5.10388374494,
5.62123384494,
5.18692151994,
5.13663381694,
5.2294232139400005,
5.17417414394,
5.15472135294,
5.27814884994
]
},
{
"command": "pnpr@main",
"mean": 5.18492499984,
"stddev": 0.08334373162516463,
"median": 5.14727614244,
"user": 2.73596446,
"system": 1.8318604399999994,
"min": 5.12588020094,
"max": 5.3719712279400005,
"times": [
5.3719712279400005,
5.13943564394,
5.15511664094,
5.22978724994,
5.13004840794,
5.12814643794,
5.2798607229400005,
5.12588020094,
5.12782151294,
5.16118195294
]
}
]
}Scenario: Isolated linker: fresh restore, hot cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 0.4754310596,
"stddev": 0.011658042717783822,
"median": 0.47068201640000007,
"user": 0.3777297,
"system": 0.7703764,
"min": 0.46037816240000007,
"max": 0.49169700940000005,
"times": [
0.46370402540000005,
0.46762096740000003,
0.48704259340000006,
0.4702470174,
0.46794887240000005,
0.47111701540000006,
0.49015210640000006,
0.48440282640000004,
0.49169700940000005,
0.46037816240000007
]
},
{
"command": "pacquet@main",
"mean": 0.47478433100000006,
"stddev": 0.0077098531229636506,
"median": 0.47274151490000005,
"user": 0.37218819999999997,
"system": 0.7839913999999999,
"min": 0.46160519740000006,
"max": 0.4907853394,
"times": [
0.47638395340000006,
0.4758207494,
0.47210535140000004,
0.46160519740000006,
0.47129852940000005,
0.47190050540000006,
0.47337767840000006,
0.48273791540000005,
0.47182809040000007,
0.4907853394
]
},
{
"command": "pnpr@HEAD",
"mean": 0.5854582467,
"stddev": 0.01734355359663726,
"median": 0.5809292129000001,
"user": 0.3848217,
"system": 0.7942684999999999,
"min": 0.5634538274,
"max": 0.6185002754000001,
"times": [
0.6185002754000001,
0.6035775874,
0.5973911454,
0.5932235844,
0.5709727784,
0.5723854314000001,
0.5771428024,
0.5847156234,
0.5732194114000001,
0.5634538274
]
},
{
"command": "pnpr@main",
"mean": 0.5801106596000001,
"stddev": 0.02723103229750047,
"median": 0.5717542054,
"user": 0.3905674,
"system": 0.7806403999999999,
"min": 0.5555244864000001,
"max": 0.6481742874,
"times": [
0.5766116304000001,
0.6481742874,
0.5774737714,
0.6033380064,
0.5781361644,
0.5620934154,
0.5659717284000001,
0.5668967804,
0.5668863254000001,
0.5555244864000001
]
}
]
}Scenario: Isolated linker: fresh install, cold cache + cold store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 8.44257299212,
"stddev": 0.04548567258544682,
"median": 8.44347679002,
"user": 3.76306602,
"system": 2.0749866000000003,
"min": 8.37585149552,
"max": 8.52807351252,
"times": [
8.37585149552,
8.44153750652,
8.44261323752,
8.44434034252,
8.38033836852,
8.45632867852,
8.48280505252,
8.52807351252,
8.41336938652,
8.460472340519999
]
},
{
"command": "pacquet@main",
"mean": 8.47002705562,
"stddev": 0.0439457518500649,
"median": 8.48042834852,
"user": 3.7628470199999997,
"system": 2.0683372,
"min": 8.368825296519999,
"max": 8.51228067552,
"times": [
8.50109150252,
8.45514532152,
8.368825296519999,
8.51228067552,
8.432426272519999,
8.51220514552,
8.49247773252,
8.49111851052,
8.469738186519999,
8.46496191252
]
},
{
"command": "pnpr@HEAD",
"mean": 4.99716597702,
"stddev": 0.13508784946113978,
"median": 4.932009692519999,
"user": 2.5459312199999995,
"system": 1.7719706000000002,
"min": 4.862251512519999,
"max": 5.236142549519999,
"times": [
5.236142549519999,
4.91398035552,
4.90830146352,
4.90848627552,
5.20798817652,
4.96440003552,
4.91838519352,
4.94563419152,
4.862251512519999,
5.10609001652
]
},
{
"command": "pnpr@main",
"mean": 4.965971531719999,
"stddev": 0.1542564087815126,
"median": 4.89999903802,
"user": 2.56940422,
"system": 1.7683042999999998,
"min": 4.8600676395199995,
"max": 5.37438342552,
"times": [
4.94669727452,
4.89973300452,
5.06699912852,
5.37438342552,
4.89312230852,
4.897974340519999,
4.92911899752,
4.90026507152,
4.89135412652,
4.8600676395199995
]
}
]
}Scenario: Isolated linker: fresh install, hot cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 0.9402329691600002,
"stddev": 0.013660156299153639,
"median": 0.9345915342600001,
"user": 1.1209460799999997,
"system": 1.0010175,
"min": 0.9230298017600002,
"max": 0.9663624557600001,
"times": [
0.9336982697600001,
0.9336017847600001,
0.9354513227600001,
0.9615601307600001,
0.9230298017600002,
0.9387241827600001,
0.9337317457600001,
0.9316607077600001,
0.9445092897600001,
0.9663624557600001
]
},
{
"command": "pacquet@main",
"mean": 0.9547978451600001,
"stddev": 0.022000419902687397,
"median": 0.9490964202600001,
"user": 1.13677868,
"system": 1.0014173999999998,
"min": 0.9358182247600001,
"max": 1.00360855076,
"times": [
0.9531810757600001,
0.9413393597600002,
0.9559011287600001,
0.9829940767600001,
0.9530744147600001,
0.9398338957600001,
0.9371092987600002,
1.00360855076,
0.9358182247600001,
0.9451184257600002
]
},
{
"command": "pnpr@HEAD",
"mean": 0.5183191953600002,
"stddev": 0.050296205196286074,
"median": 0.50014782276,
"user": 0.34068358,
"system": 0.7567370999999998,
"min": 0.48702047276000004,
"max": 0.6551543657600001,
"times": [
0.5407601247600001,
0.49467326676,
0.49844459776000005,
0.48702047276000004,
0.5018510477600001,
0.49255285176,
0.6551543657600001,
0.5069042717600001,
0.50866967776,
0.49716127676000005
]
},
{
"command": "pnpr@main",
"mean": 0.5002288044600001,
"stddev": 0.007198036011321011,
"median": 0.49930343326000004,
"user": 0.33890748,
"system": 0.751375,
"min": 0.48722304676,
"max": 0.5111264097600001,
"times": [
0.5111264097600001,
0.49649218376000004,
0.49345848776,
0.5082663697600001,
0.48722304676,
0.5060538497600001,
0.49767147676,
0.5002582147600001,
0.49834865176000004,
0.50338935376
]
}
]
}Scenario: Isolated linker: fresh install, cold cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 4.699605027980001,
"stddev": 0.015344482929571699,
"median": 4.701206429380001,
"user": 1.6220023600000002,
"system": 1.19980618,
"min": 4.672187360880001,
"max": 4.7180461108800005,
"times": [
4.7180461108800005,
4.695075177880001,
4.69991721488,
4.672187360880001,
4.714963277880001,
4.67571800388,
4.708996931880001,
4.698890732880001,
4.702495643880001,
4.709759824880001
]
},
{
"command": "pacquet@main",
"mean": 4.695332178180001,
"stddev": 0.011713476546600163,
"median": 4.6922056883800005,
"user": 1.60349596,
"system": 1.2045819800000002,
"min": 4.68069381088,
"max": 4.71939497788,
"times": [
4.688368119880001,
4.71939497788,
4.69558186588,
4.688991375880001,
4.709860007880001,
4.686612360880001,
4.69981734188,
4.688581919880001,
4.69542000088,
4.68069381088
]
},
{
"command": "pnpr@HEAD",
"mean": 0.50119142768,
"stddev": 0.008286558507852712,
"median": 0.49797917988000007,
"user": 0.33949156,
"system": 0.7657788799999999,
"min": 0.49694215188,
"max": 0.5241977238800001,
"times": [
0.5241977238800001,
0.49786497488000003,
0.49809338488000005,
0.49729440488000004,
0.5002654118800001,
0.49694215188,
0.49965981787999997,
0.50281498288,
0.49758739288000003,
0.49719403088
]
},
{
"command": "pnpr@main",
"mean": 0.50216709938,
"stddev": 0.014238655522782417,
"median": 0.49808956688,
"user": 0.3433136600000001,
"system": 0.74918478,
"min": 0.48897060088,
"max": 0.53963284988,
"times": [
0.53963284988,
0.49367693088000003,
0.49827266488,
0.49790646888,
0.49536156688000005,
0.49563586788,
0.5049579408800001,
0.48897060088,
0.49913408888,
0.5081220138800001
]
}
]
} |
|
| Branch | pr/12326 |
| Testbed | pacquet |
Click to view all benchmark results
| Benchmark | Latency | Benchmark Result milliseconds (ms) (Result Δ%) | Upper Boundary milliseconds (ms) (Limit %) |
|---|---|---|---|
| isolated-linker.fresh-install.cold-cache.cold-store | 📈 view plot 🚷 view threshold | 8,442.57 ms(-8.39%)Baseline: 9,215.58 ms | 11,058.69 ms (76.34%) |
| isolated-linker.fresh-install.cold-cache.hot-store | 📈 view plot 🚷 view threshold | 4,699.61 ms(-6.06%)Baseline: 5,002.55 ms | 6,003.06 ms (78.29%) |
| isolated-linker.fresh-install.hot-cache.hot-store | 📈 view plot 🚷 view threshold | 940.23 ms(-33.59%)Baseline: 1,415.73 ms | 1,698.88 ms (55.34%) |
| isolated-linker.fresh-restore.cold-cache.cold-store | 📈 view plot 🚷 view threshold | 10,321.63 ms(+2.25%)Baseline: 10,094.88 ms | 12,113.86 ms (85.21%) |
| isolated-linker.fresh-restore.hot-cache.hot-store | 📈 view plot 🚷 view threshold | 475.43 ms(-27.28%)Baseline: 653.80 ms | 784.56 ms (60.60%) |
|
| Branch | pr/12326 |
| Testbed | pnpr |
⚠️ WARNING: No Threshold found!Without a Threshold, no Alerts will ever be generated.
Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the--ci-only-thresholdsflag.
Click to view all benchmark results
| Benchmark | Latency | milliseconds (ms) |
|---|---|---|
| isolated-linker.fresh-install.cold-cache.cold-store | 📈 view plot | 4,997.17 ms |
| isolated-linker.fresh-install.cold-cache.hot-store | 📈 view plot | 501.19 ms |
| isolated-linker.fresh-install.hot-cache.hot-store | 📈 view plot | 518.32 ms |
| isolated-linker.fresh-restore.cold-cache.cold-store | 📈 view plot | 5,220.95 ms |
| isolated-linker.fresh-restore.hot-cache.hot-store | 📈 view plot | 585.46 ms |
Code Review by Qodo
Context used✅ Tickets:
🎫 pnpm update should test trustPolicy 1. Legacy cache records skipped
|
PR Summary by QodoAnnounce reused lockfile-verification verdicts with a new WalkthroughsDescription• Emit a cached lockfile-verification event when a passing verdict is reused. • Render a user-visible "verified 2h ago" line in the default reporter. • Add TS + Rust tests for cache-hit emission, silence rules, and NDJSON shape. Diagramgraph TD
A["pnpm: verifyLockfileResolutions"] --> B[("lockfile-verified cache")] --> C["LockfileVerificationMessage: cached"] --> D["pnpm default reporter"]
E["pacquet: verify_lockfile_resolutions"] --> F[("lockfile-verified cache")] --> C --> G["pacquet reporter (NDJSON)"]
High-Level AssessmentThe following are alternative approaches to this PR: 1. Reuse `done` event shape with a new `cached: true` flag
2. Always emit cached events (even with no policy verifiers) and let reporters decide
3. Log cached reuse at `info` level instead of `debug`
Recommendation: Current approach is the best tradeoff: introduce an explicit File ChangesEnhancement (7)
Tests (5)
Other (1)
|
Summary
Closes #12324
When the lockfile-verification gate short-circuits on a cached verdict, it stayed completely silent — with
trustLockfile/trustPolicy/minimumReleaseAgeactive, a repeatpnpm updateorpnpm installlooked like the supply-chain policy gate never ran. This PR makes the reused verdict visible:Changes
pnpm (TypeScript)
@pnpm/core-loggers: newcachedstatus onLockfileVerificationMessage, carrying the reused record'sverifiedAt(ISO-8601) andlockfilePath. Noentriescount — the short-circuit happens before candidates are collected, keeping the fast path stat-only.@pnpm/installing.deps-installer: the cache-hit return inverifyLockfileResolutionsemits the event, but only when policy verifiers are active — the offline shape-only check every install performs stays quiet.tryLockfileVerificationCachenow surfacesverifiedAtfrom both the stat-shortcut and content-hash hit paths.@pnpm/cli.default-reporter: renders the relative age viapretty-ms(clamped at zero against clock skew), falling back to(previously verified)for cache records that predate the timestamp field.pacquet (Rust port, same change)
Cachedvariant on the reporter'sLockfileVerificationMessagewith the matching camelCase wire shape (status: "cached",verifiedAt,lockfilePath; absent fields omitted), emitted from the same cache-hit point inverify_lockfile_resolutions.CacheLookupResultgainedverified_at.Behavior notes
? Verifying lockfile…/✓ … (N entries in Xms).fresh_install_records_lockfile_verification_for_mtime_bypassed_noop) asserted the cache hit emits no verification events; it now pins "exactly oneCached, no fan-out events".Testing
verifiedAt).pnpm updatewithminimumReleaseAgeset prints the cached line on repeat runs; after wiping<cacheDir>/lockfile-verified.jsonlthe started/done pair still renders.Written by an agent (Claude Code, claude-fable-5).
Summary by CodeRabbit