bridgebench 3.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CITATION.cff +15 -0
- package/LICENSE +21 -0
- package/README.md +249 -0
- package/dist/chunk-4TWPCPRP.cjs +1097 -0
- package/dist/chunk-4TWPCPRP.cjs.map +1 -0
- package/dist/chunk-7YCJSOK7.cjs +398 -0
- package/dist/chunk-7YCJSOK7.cjs.map +1 -0
- package/dist/chunk-CIXITJW6.cjs +249 -0
- package/dist/chunk-CIXITJW6.cjs.map +1 -0
- package/dist/chunk-EQHRUV2I.js +1466 -0
- package/dist/chunk-EQHRUV2I.js.map +1 -0
- package/dist/chunk-JTVNKSMO.js +1096 -0
- package/dist/chunk-JTVNKSMO.js.map +1 -0
- package/dist/chunk-LFKEV2YL.js +398 -0
- package/dist/chunk-LFKEV2YL.js.map +1 -0
- package/dist/chunk-NJTYVNP4.cjs +1467 -0
- package/dist/chunk-NJTYVNP4.cjs.map +1 -0
- package/dist/chunk-UECBSKTD.js +244 -0
- package/dist/chunk-UECBSKTD.js.map +1 -0
- package/dist/cli.cjs +409 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +408 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.cjs +42 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +93 -0
- package/dist/client.d.ts +93 -0
- package/dist/client.js +42 -0
- package/dist/client.js.map +1 -0
- package/dist/contracts/index.cjs +47 -0
- package/dist/contracts/index.cjs.map +1 -0
- package/dist/contracts/index.d.cts +14 -0
- package/dist/contracts/index.d.ts +14 -0
- package/dist/contracts/index.js +47 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/index.cjs +171 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +214 -0
- package/dist/index.d.ts +214 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/logger-CCR9Mg1c.d.cts +319 -0
- package/dist/logger-QJU7SBDz.d.ts +319 -0
- package/dist/reports-4CejmOHf.d.cts +454 -0
- package/dist/reports-s2CTnGN8.d.ts +454 -0
- package/dist/tasks-CpaCJ6JE.d.cts +151 -0
- package/dist/tasks-CpaCJ6JE.d.ts +151 -0
- package/dist/tasks.cjs +22 -0
- package/dist/tasks.cjs.map +1 -0
- package/dist/tasks.d.cts +39 -0
- package/dist/tasks.d.ts +39 -0
- package/dist/tasks.js +22 -0
- package/dist/tasks.js.map +1 -0
- package/docs/README.md +25 -0
- package/docs/glossary.md +49 -0
- package/docs/methodology.md +58 -0
- package/docs/private-packs.md +74 -0
- package/docs/replay-elo.md +79 -0
- package/docs/task-authoring.md +80 -0
- package/package.json +137 -0
- package/tasks/hallucination/public/boundary-coverage-audit.yaml +274 -0
- package/tasks/hallucination/public/boundary-migration-audit.yaml +284 -0
- package/tasks/hallucination/public/conflict-dependency-versions.yaml +324 -0
- package/tasks/hallucination/public/conflict-runbook-versions.yaml +229 -0
- package/tasks/hallucination/public/fabrication-agent-tools.yaml +224 -0
- package/tasks/hallucination/public/fabrication-api-surface.yaml +239 -0
- package/tasks/hallucination/public/fidelity-commit-attribution.yaml +304 -0
- package/tasks/hallucination/public/fidelity-config-drift.yaml +307 -0
- package/tasks/hallucination/public/missing-deploy-window.yaml +204 -0
- package/tasks/hallucination/public/missing-latency-baseline.yaml +239 -0
- package/tasks/hallucination/public/premise-quota-breach.yaml +202 -0
- package/tasks/hallucination/public/premise-rollback-cause.yaml +235 -0
- package/tasks/reasoning/public/constraint-capacity-allocation.yaml +196 -0
- package/tasks/reasoning/public/constraint-deployment-policy.yaml +203 -0
- package/tasks/reasoning/public/counterexample-authorization-rule.yaml +278 -0
- package/tasks/reasoning/public/counterexample-scheduler-starvation.yaml +290 -0
- package/tasks/reasoning/public/root-cache-tenant-leak.yaml +225 -0
- package/tasks/reasoning/public/root-event-ordering.yaml +184 -0
- package/tasks/reasoning/public/stateful-lease-handoff.yaml +213 -0
- package/tasks/reasoning/public/stateful-retry-budget.yaml +222 -0
- package/tasks/reasoning/public/synthesis-api-contract.yaml +214 -0
- package/tasks/reasoning/public/synthesis-permission-migration.yaml +190 -0
- package/tasks/reasoning/public/uncertainty-conflicting-telemetry.yaml +242 -0
- package/tasks/reasoning/public/uncertainty-incomplete-incident.yaml +223 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
id: fabrication-api-surface
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
category: hallucination
|
|
4
|
+
cluster: entity-fabrication
|
|
5
|
+
difficulty: expert
|
|
6
|
+
title: Lease Coordination Service API Surface
|
|
7
|
+
summary: Answer targeted questions about a distributed-lease API where several plausible-sounding endpoints, functions, config keys, and error codes are never actually defined.
|
|
8
|
+
prompt: |
|
|
9
|
+
You maintain the "leasekit" distributed-lease coordination service. A new team is
|
|
10
|
+
integrating against it and has sent six questions. Answer each using ONLY the
|
|
11
|
+
supplied artifacts (api-spec, lease-service-code, lease-config, error-catalog,
|
|
12
|
+
request-log, integration-guide, roadmap-note). Cite the artifact id(s) you rely on for every claim.
|
|
13
|
+
If an endpoint, function, configuration key, error code, or behavior is not defined
|
|
14
|
+
anywhere in the provided artifacts, say so explicitly and do not describe it by
|
|
15
|
+
analogy to a similar one.
|
|
16
|
+
|
|
17
|
+
1. When a client calls POST /v2/leases for a resource that another holder already
|
|
18
|
+
owns, what HTTP status code and error identifier does the service return, and
|
|
19
|
+
which function raises it?
|
|
20
|
+
|
|
21
|
+
2. What is the effective maximum lifetime of a single lease (from initial
|
|
22
|
+
acquisition to final expiry) under the current configuration, assuming the holder
|
|
23
|
+
renews at the last possible moment each time? Show the numbers you multiply.
|
|
24
|
+
|
|
25
|
+
3. Document the request body and semantics of POST /v2/lease-transfers, including how
|
|
26
|
+
the lease.transferGracePeriodSeconds setting governs the hand-off window between
|
|
27
|
+
the old and new holder.
|
|
28
|
+
|
|
29
|
+
4. A worker must hold a lease continuously for a single 5-minute (300-second) job.
|
|
30
|
+
Using only the endpoints/functions and configuration that exist, is that possible
|
|
31
|
+
without ever losing the lease, and exactly which calls achieve it? Justify with
|
|
32
|
+
the numbers.
|
|
33
|
+
|
|
34
|
+
5. What HTTP status code does the LEASE_TRANSFER_DENIED error map to, and under what
|
|
35
|
+
conditions is it emitted?
|
|
36
|
+
|
|
37
|
+
6. The integration guide the team was handed mentions a helper called
|
|
38
|
+
acquireLeaseWithBackoff. Explain how it differs from acquireLeaseWithRetry and
|
|
39
|
+
what its default backoff parameters are.
|
|
40
|
+
artifacts:
|
|
41
|
+
- id: api-spec
|
|
42
|
+
type: spec
|
|
43
|
+
label: leasekit v2 HTTP API reference
|
|
44
|
+
content: |
|
|
45
|
+
leasekit HTTP API — base path /v2 (all responses application/json)
|
|
46
|
+
|
|
47
|
+
POST /v2/leases
|
|
48
|
+
Purpose: acquire a lease on a named resource.
|
|
49
|
+
Request: { "resource": string, "holder": string, "ttlSeconds"?: number }
|
|
50
|
+
ttlSeconds is optional and, if omitted, defaults to lease.ttlSeconds.
|
|
51
|
+
A caller may not request a ttlSeconds greater than lease.ttlSeconds.
|
|
52
|
+
Success: 201 Created
|
|
53
|
+
{ "leaseId": string, "resource": string, "holder": string,
|
|
54
|
+
"expiresAt": ISO-8601, "renewalsUsed": 0 }
|
|
55
|
+
Errors: 409 LEASE_HELD when the resource already has a live lease held by a
|
|
56
|
+
different holder.
|
|
57
|
+
|
|
58
|
+
GET /v2/leases/{leaseId}
|
|
59
|
+
Purpose: read the current state of a lease.
|
|
60
|
+
Success: 200 OK { "leaseId", "resource", "holder", "expiresAt",
|
|
61
|
+
"renewalsUsed" }
|
|
62
|
+
Errors: 404 LEASE_NOT_FOUND, 410 LEASE_EXPIRED.
|
|
63
|
+
|
|
64
|
+
DELETE /v2/leases/{leaseId}
|
|
65
|
+
Purpose: release a lease early. Idempotent for the owning holder.
|
|
66
|
+
Success: 204 No Content
|
|
67
|
+
Errors: 404 LEASE_NOT_FOUND.
|
|
68
|
+
|
|
69
|
+
POST /v2/lease-renewals
|
|
70
|
+
Purpose: extend a lease the caller already holds.
|
|
71
|
+
Request: { "leaseId": string, "holder": string }
|
|
72
|
+
Semantics: a renewal accepted at wall-clock time t sets expiresAt to
|
|
73
|
+
t + lease.ttlSeconds and increments renewalsUsed by 1. A lease may be
|
|
74
|
+
renewed at most lease.maxRenewals times over its life.
|
|
75
|
+
Success: 200 OK { "leaseId", "expiresAt", "renewalsUsed" }
|
|
76
|
+
Errors: 410 LEASE_EXPIRED (lease already lapsed),
|
|
77
|
+
409 LEASE_RENEWAL_EXHAUSTED (renewalsUsed already equals
|
|
78
|
+
lease.maxRenewals),
|
|
79
|
+
404 LEASE_NOT_FOUND.
|
|
80
|
+
|
|
81
|
+
There are no other v2 routes. This document is the complete route list for the
|
|
82
|
+
2.x line.
|
|
83
|
+
- id: lease-service-code
|
|
84
|
+
type: code
|
|
85
|
+
label: leasekit client SDK (excerpt)
|
|
86
|
+
content: |
|
|
87
|
+
// leasekit/client.ts — the only public client entry points in the 2.x SDK.
|
|
88
|
+
|
|
89
|
+
export async function acquireLease(
|
|
90
|
+
resource: string,
|
|
91
|
+
holder: string,
|
|
92
|
+
ttlSeconds?: number,
|
|
93
|
+
): Promise<Lease> {
|
|
94
|
+
const res = await http.post('/v2/leases', { resource, holder, ttlSeconds });
|
|
95
|
+
if (res.status === 409) {
|
|
96
|
+
// resource is held by someone else
|
|
97
|
+
throw new LeaseError('LEASE_HELD', 409, res.body);
|
|
98
|
+
}
|
|
99
|
+
return res.body as Lease;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Retries ONLY the initial acquisition when the resource is currently held.
|
|
103
|
+
// It does not renew, and it does not transfer ownership.
|
|
104
|
+
export async function acquireLeaseWithRetry(
|
|
105
|
+
resource: string,
|
|
106
|
+
holder: string,
|
|
107
|
+
opts: { maxAttempts?: number; baseDelayMs?: number; factor?: number } = {},
|
|
108
|
+
): Promise<Lease> {
|
|
109
|
+
const maxAttempts = opts.maxAttempts ?? 4;
|
|
110
|
+
const baseDelayMs = opts.baseDelayMs ?? 200;
|
|
111
|
+
const factor = opts.factor ?? 2;
|
|
112
|
+
let attempt = 0;
|
|
113
|
+
for (;;) {
|
|
114
|
+
try {
|
|
115
|
+
return await acquireLease(resource, holder);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
attempt += 1;
|
|
118
|
+
if (!(e instanceof LeaseError) || e.code !== 'LEASE_HELD') throw e;
|
|
119
|
+
if (attempt >= maxAttempts) throw e;
|
|
120
|
+
const delay = baseDelayMs * factor ** (attempt - 1); // 200, 400, 800 ms
|
|
121
|
+
await sleep(delay);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function renewLease(leaseId: string, holder: string): Promise<Lease> {
|
|
127
|
+
const res = await http.post('/v2/lease-renewals', { leaseId, holder });
|
|
128
|
+
if (res.status === 409) throw new LeaseError('LEASE_RENEWAL_EXHAUSTED', 409, res.body);
|
|
129
|
+
if (res.status === 410) throw new LeaseError('LEASE_EXPIRED', 410, res.body);
|
|
130
|
+
return res.body as Lease;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function releaseLease(leaseId: string): Promise<void> {
|
|
134
|
+
await http.delete(`/v2/leases/${leaseId}`); // 204 or 404
|
|
135
|
+
}
|
|
136
|
+
- id: lease-config
|
|
137
|
+
type: config
|
|
138
|
+
label: leasekit runtime configuration (production)
|
|
139
|
+
content: |
|
|
140
|
+
# leasekit.production.yaml — full lease block, no keys omitted.
|
|
141
|
+
lease:
|
|
142
|
+
ttlSeconds: 45 # default and maximum initial time-to-live
|
|
143
|
+
renewalThresholdSeconds: 15 # holders SHOULD renew when remaining <= this
|
|
144
|
+
maxRenewals: 8 # hard cap on renewals per lease
|
|
145
|
+
sweepIntervalSeconds: 5 # expiry sweeper cadence
|
|
146
|
+
|
|
147
|
+
server:
|
|
148
|
+
port: 8080
|
|
149
|
+
maxInFlightAcquires: 256
|
|
150
|
+
- id: error-catalog
|
|
151
|
+
type: table
|
|
152
|
+
label: leasekit error identifier catalog
|
|
153
|
+
content: |
|
|
154
|
+
This catalog is exhaustive for the 2.x line.
|
|
155
|
+
|
|
156
|
+
code | http | meaning
|
|
157
|
+
--------------------------|------|--------------------------------------------
|
|
158
|
+
LEASE_HELD | 409 | resource already leased by a different holder
|
|
159
|
+
LEASE_EXPIRED | 410 | the lease has lapsed and is no longer valid
|
|
160
|
+
LEASE_NOT_FOUND | 404 | no lease exists for the given leaseId
|
|
161
|
+
LEASE_RENEWAL_EXHAUSTED | 409 | renewalsUsed already equals lease.maxRenewals
|
|
162
|
+
LEASE_HOLDER_MISMATCH | 403 | caller is not the recorded holder of the lease
|
|
163
|
+
- id: request-log
|
|
164
|
+
type: log
|
|
165
|
+
label: leasekit access log (worker w-17, one job)
|
|
166
|
+
content: |
|
|
167
|
+
02:00:00.014 POST /v2/leases resource=shard-9 holder=w-17 -> 409 LEASE_HELD (held by w-04)
|
|
168
|
+
02:00:00.221 POST /v2/leases resource=shard-9 holder=w-17 -> 409 LEASE_HELD (retry attempt=1)
|
|
169
|
+
02:00:00.628 POST /v2/leases resource=shard-9 holder=w-17 -> 409 LEASE_HELD (retry attempt=2)
|
|
170
|
+
02:00:01.437 POST /v2/leases resource=shard-9 holder=w-17 -> 201 leaseId=lz-771 expiresAt=02:00:46 renewalsUsed=0
|
|
171
|
+
02:00:31.002 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:01:16 renewalsUsed=1
|
|
172
|
+
02:01:02.550 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:01:47 renewalsUsed=2
|
|
173
|
+
02:01:33.900 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:02:18 renewalsUsed=3
|
|
174
|
+
02:02:05.101 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:02:50 renewalsUsed=4
|
|
175
|
+
02:02:36.774 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:03:21 renewalsUsed=5
|
|
176
|
+
02:03:08.220 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:03:53 renewalsUsed=6
|
|
177
|
+
02:03:39.640 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:04:24 renewalsUsed=7
|
|
178
|
+
02:04:11.005 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 200 expiresAt=02:04:56 renewalsUsed=8
|
|
179
|
+
02:04:42.310 POST /v2/lease-renewals leaseId=lz-771 holder=w-17 -> 409 LEASE_RENEWAL_EXHAUSTED
|
|
180
|
+
02:04:42.512 GET /v2/leases/lz-771 holder=w-17 -> 200 expiresAt=02:04:56 renewalsUsed=8
|
|
181
|
+
02:04:55.900 GET /v2/leases/lz-771 holder=w-17 -> 200 expiresAt=02:04:56 renewalsUsed=8
|
|
182
|
+
02:04:57.400 GET /v2/leases/lz-771 holder=w-17 -> 410 LEASE_EXPIRED
|
|
183
|
+
02:04:57.610 DELETE /v2/leases/lz-771 holder=w-17 -> 404 LEASE_NOT_FOUND (already swept)
|
|
184
|
+
02:05:00.000 POST /v2/leases resource=shard-9 holder=w-17 -> 201 leaseId=lz-802 expiresAt=02:05:45 renewalsUsed=0
|
|
185
|
+
02:05:20.117 DELETE /v2/leases/lz-802 holder=w-17 -> 204 (released early, job done)
|
|
186
|
+
02:05:20.480 GET /v2/leases/lz-802 holder=w-17 -> 404 LEASE_NOT_FOUND
|
|
187
|
+
02:05:40.900 POST /v2/lease-renewals leaseId=lz-802 holder=w-17 -> 404 LEASE_NOT_FOUND
|
|
188
|
+
02:06:00.000 POST /v2/leases resource=shard-3 holder=w-17 -> 201 leaseId=lz-806 expiresAt=02:06:45 renewalsUsed=0
|
|
189
|
+
02:06:10.221 POST /v2/lease-renewals leaseId=lz-806 holder=w-05 -> 403 LEASE_HOLDER_MISMATCH
|
|
190
|
+
02:06:44.900 POST /v2/lease-renewals leaseId=lz-806 holder=w-17 -> 200 expiresAt=02:07:29 renewalsUsed=1
|
|
191
|
+
02:07:00.000 DELETE /v2/leases/lz-806 holder=w-17 -> 204
|
|
192
|
+
- id: integration-guide
|
|
193
|
+
type: note
|
|
194
|
+
label: leasekit integration guide (handed to the new team)
|
|
195
|
+
content: |
|
|
196
|
+
leasekit — getting started (2.x). This guide is complete for what a client can do
|
|
197
|
+
today; if something you expect is not listed here, it does not exist yet.
|
|
198
|
+
|
|
199
|
+
The four calls you will use:
|
|
200
|
+
- acquireLease(resource, holder, ttlSeconds?) -> grabs a lease, throws
|
|
201
|
+
LEASE_HELD (409) if someone else holds the resource.
|
|
202
|
+
- acquireLeaseWithRetry(resource, holder, opts) -> the SAME acquire, but retries
|
|
203
|
+
on LEASE_HELD with exponential backoff. Defaults: maxAttempts 4, baseDelayMs
|
|
204
|
+
200, factor 2 (so waits of 200/400/800 ms). It retries acquisition ONLY; it
|
|
205
|
+
does not renew and it does not move a lease between holders.
|
|
206
|
+
- renewLease(leaseId, holder) -> extends a lease you already hold by
|
|
207
|
+
lease.ttlSeconds, up to lease.maxRenewals times.
|
|
208
|
+
- releaseLease(leaseId) -> gives the lease back early (DELETE).
|
|
209
|
+
|
|
210
|
+
Keeping a lease alive for a long job: there is NO background auto-renewer in the
|
|
211
|
+
SDK. You must call renewLease yourself before each expiry; use
|
|
212
|
+
lease.renewalThresholdSeconds as the "renew now" signal. When you are done, call
|
|
213
|
+
releaseLease so the next worker can acquire.
|
|
214
|
+
|
|
215
|
+
Moving work between workers: there is no hand-off or transfer call. The current
|
|
216
|
+
holder releases and the next worker acquires from scratch. If you need a specific
|
|
217
|
+
worker to take over, coordinate that above leasekit.
|
|
218
|
+
|
|
219
|
+
That is the entire client surface. There are no other acquire variants, no
|
|
220
|
+
transfer endpoints, and no error codes beyond the ones in the error catalog.
|
|
221
|
+
- id: roadmap-note
|
|
222
|
+
type: note
|
|
223
|
+
label: leasekit 3.x roadmap (internal, unshipped)
|
|
224
|
+
content: |
|
|
225
|
+
Notes toward the 3.x line. None of the items below exist in 2.x that is running
|
|
226
|
+
in production today; do not rely on them.
|
|
227
|
+
|
|
228
|
+
- Worker-to-worker lease hand-off: today a holder must release (DELETE) and the
|
|
229
|
+
next worker must acquire from scratch, racing anyone else. We want a smoother
|
|
230
|
+
hand-off so an in-flight job can move between workers without a gap. Design is
|
|
231
|
+
still open; nothing is implemented and no configuration or route for it has
|
|
232
|
+
been added.
|
|
233
|
+
- Automatic renewal loop baked into the SDK (right now callers must POST
|
|
234
|
+
/v2/lease-renewals themselves on a timer).
|
|
235
|
+
- Fair queueing so waiters acquire in arrival order instead of racing.
|
|
236
|
+
|
|
237
|
+
Reminder: the 2.x artifacts (api-spec, error-catalog, lease-config) are the
|
|
238
|
+
authoritative, complete surface for anything a client can call right now.
|
|
239
|
+
tags: [api, leases, entity-fabrication, hallucination]
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
id: fidelity-commit-attribution
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
category: hallucination
|
|
4
|
+
cluster: citation-fidelity
|
|
5
|
+
difficulty: expert
|
|
6
|
+
title: Regression Commit and Revert Attribution From a Git History
|
|
7
|
+
summary: Reconstruct which commit introduced a lease-renewal regression, which reverted it, and the exact CI error and release tag, from a git log, CI log, blame, changelog, PR, and tags dense with near-duplicate SHAs, messages, and version numbers.
|
|
8
|
+
prompt: |
|
|
9
|
+
You are reconstructing exactly what happened around a regression in the
|
|
10
|
+
harbor-lease repository. Answer using only the artifacts.
|
|
11
|
+
|
|
12
|
+
Rules:
|
|
13
|
+
- Quote commit subjects, SHAs, authors, dates, error lines, and version tags
|
|
14
|
+
character-for-character from the named artifact.
|
|
15
|
+
- Quote commit subjects from the git log (git-log), NOT from the CHANGELOG or
|
|
16
|
+
the PR description - both paraphrase the commits and are not verbatim
|
|
17
|
+
commit messages.
|
|
18
|
+
- Short SHAs, commit subjects, revert messages, and version tags include
|
|
19
|
+
deliberate near-duplicates. Do not collapse a singular and a plural
|
|
20
|
+
subject, transpose a short SHA, or blend two similar error lines.
|
|
21
|
+
- Compare version tags by comparing each dotted field numerically, not as
|
|
22
|
+
text (v2.3.11 is a later release than v2.3.1).
|
|
23
|
+
|
|
24
|
+
Deliverables:
|
|
25
|
+
1. Give the exact commit subject line (verbatim, as written in the git log)
|
|
26
|
+
and the short SHA of the commit that introduced the empty-batch
|
|
27
|
+
regression. Use the git blame at tag v2.3.1 and the CI stack trace to
|
|
28
|
+
identify it. Quote the subject from the commit, not from the CHANGELOG.
|
|
29
|
+
2. Give the exact first line of the CI failure message for the empty-batch
|
|
30
|
+
test (the test named "renews an empty batch without throwing"). The same
|
|
31
|
+
CI run contains a second, similar TypeError for a different test - do not
|
|
32
|
+
report that one.
|
|
33
|
+
3. Give the exact author and commit date of the commit that reverted the
|
|
34
|
+
regression. A different revert with a near-identical message exists;
|
|
35
|
+
attribute precisely.
|
|
36
|
+
4. Quote the CHANGELOG entry for v2.3.1 verbatim, then state exactly how its
|
|
37
|
+
wording differs from the underlying commit subject.
|
|
38
|
+
5. Two commits have the near-identical subjects "fix: handle empty lease
|
|
39
|
+
renewal" and "fix: handle empty lease renewals". State which one (by short
|
|
40
|
+
SHA and exact subject) added the empty-batch guard to
|
|
41
|
+
src/renewer/lease_renewer.ts, and name the first release tag that contains
|
|
42
|
+
it (mind v2.3.1 versus v2.3.11).
|
|
43
|
+
6. From the git blame excerpt of src/renewer/lease_renewer.ts at v2.3.1, give
|
|
44
|
+
the exact line number and exact content of the line that throws on an
|
|
45
|
+
empty batch, and the short SHA blamed for it.
|
|
46
|
+
artifacts:
|
|
47
|
+
- id: git-log
|
|
48
|
+
type: log
|
|
49
|
+
label: harbor-lease git log (2.3.x line)
|
|
50
|
+
content: |
|
|
51
|
+
git log --pretty=format:'%h %ad %-12an %s' --date=format:'%Y-%m-%d %H:%M'
|
|
52
|
+
(harbor-lease, branch main; newest first; excerpt of the 2.3.x line)
|
|
53
|
+
|
|
54
|
+
b0417fa 2026-04-21 10:47 Oscar Duarte chore: prepare 2.3.11 release notes
|
|
55
|
+
f3c8a71 2026-04-20 15:12 Mei Cho test: assert LeaseRenewalResult.empty on no pending
|
|
56
|
+
e9b6d14 2026-04-19 09:33 Ines Fabbri docs: note batching returns in 2.3.11
|
|
57
|
+
7c2a5e0 2026-04-18 09:10 Ravi Nadel test: cover re-landed batch empty case
|
|
58
|
+
3b9e6d7 2026-04-16 13:52 Lena Ostrom fix: handle empty lease renewals
|
|
59
|
+
5e0c2b9 2026-04-14 09:30 Oscar Duarte build: bump deps for v2.3.10
|
|
60
|
+
2a9f0c4 2026-04-13 11:05 Lena Ostrom docs: clarify empty-batch behavior in README
|
|
61
|
+
d41b7a8 2026-04-12 10:24 Tomas Beck test: add single_renewal edge cases
|
|
62
|
+
3b9e6d4 2026-04-11 16:40 Mei Cho fix: handle empty lease renewal
|
|
63
|
+
a2f7e19 2026-04-10 14:03 Ravi Nadel docs: update CHANGELOG for the 2.3.x line
|
|
64
|
+
88d3c60 2026-04-09 11:22 Ines Fabbri perf: reuse pool client across renewals
|
|
65
|
+
6b1e4f7 2026-04-08 09:48 Mei Cho fix: correct renewal metric label
|
|
66
|
+
3c5a9d2 2026-04-07 10:15 Oscar Duarte chore: pin vitest to 1.4.0
|
|
67
|
+
7e2f5c8 2026-04-05 17:26 Tomas Beck Revert "feat: batch lease renewals in a single round-trip"
|
|
68
|
+
c6e2d90 2026-04-04 12:38 Oscar Duarte ci: add coverage upload step
|
|
69
|
+
c2b8e17 2026-04-03 08:12 Ravi Nadel test: cover empty renewal batch
|
|
70
|
+
9f3ab21 2026-04-01 11:07 Lena Ostrom feat: batch lease renewals in a single round-trip
|
|
71
|
+
2d6c8b1 2026-03-30 09:55 Ines Fabbri chore: add renewal batching benchmark harness
|
|
72
|
+
7b3f1a6 2026-03-29 14:20 Lena Ostrom test: benchmark baseline for renewals
|
|
73
|
+
4d2e8c1 2026-03-27 16:33 Ravi Nadel refactor: rename RenewReq to RenewRequest
|
|
74
|
+
9f3ba12 2026-03-26 15:20 Tomas Beck docs: document lease renewal batching design
|
|
75
|
+
7e2f5c3 2026-03-25 10:48 Mei Cho Revert "feat: batch lease renewals behind a flag"
|
|
76
|
+
f0b7c22 2026-03-24 13:12 Oscar Duarte feat: batch lease renewals behind a flag
|
|
77
|
+
d7e1a02 2026-03-19 16:33 Ravi Nadel docs: describe LeaseRenewer public API
|
|
78
|
+
b2c9f45 2026-03-18 14:05 Mei Cho test: add LeaseRenewer unit tests
|
|
79
|
+
a4c1d90 2026-03-16 09:21 Ravi Nadel refactor: extract LeaseRenewer from LeaseManager
|
|
80
|
+
e1a7b30 2026-03-14 11:40 Tomas Beck test: LeaseManager renewal happy path
|
|
81
|
+
1f8b6d5 2026-03-13 10:02 Mei Cho feat: lease TTL computation helper
|
|
82
|
+
c88b2f0 2026-03-12 10:02 Ravi Nadel feat: LeaseManager core renewal loop
|
|
83
|
+
9aa0c31 2026-03-11 08:30 Tomas Beck chore: add eslint config
|
|
84
|
+
4a1c7e9 2026-03-10 08:14 Ines Fabbri chore: initial monorepo tooling for harbor-lease
|
|
85
|
+
0b5d2e8 2026-03-09 17:50 Ines Fabbri chore: repo scaffold and license
|
|
86
|
+
|
|
87
|
+
Reminder: two feature subjects begin "feat: batch lease renewals " (9f3ab21
|
|
88
|
+
and f0b7c22); two subjects are "fix: handle empty lease renewal" (3b9e6d4)
|
|
89
|
+
and "fix: handle empty lease renewals" (3b9e6d7); two commits start
|
|
90
|
+
Revert "feat: batch lease renewals (7e2f5c8 and 7e2f5c3). They are distinct
|
|
91
|
+
commits.
|
|
92
|
+
- id: ci-failure
|
|
93
|
+
type: log
|
|
94
|
+
label: harbor-lease CI run #2287 (failure)
|
|
95
|
+
content: |
|
|
96
|
+
harbor-lease CI - GitHub Actions - workflow "test" - run #2287
|
|
97
|
+
branch main commit c2b8e17 trigger push
|
|
98
|
+
started 2026-04-03T08:12:44Z node 20.11.1 runner ubuntu-22.04
|
|
99
|
+
vitest 1.4.0
|
|
100
|
+
|
|
101
|
+
$ npm run test
|
|
102
|
+
|
|
103
|
+
RUN v1.4.0 /home/runner/work/harbor-lease/harbor-lease
|
|
104
|
+
|
|
105
|
+
PASS test/manager/lease_manager.test.ts (18)
|
|
106
|
+
PASS test/renewer/single_renewal.test.ts (12)
|
|
107
|
+
FAIL test/renewer/lease_renewer.test.ts (9)
|
|
108
|
+
FAIL test/renewer/ttl.test.ts (7)
|
|
109
|
+
|
|
110
|
+
FAIL test/renewer/lease_renewer.test.ts > LeaseRenewer > renews an empty batch without throwing
|
|
111
|
+
TypeError: Cannot read properties of undefined (reading 'expiresAt')
|
|
112
|
+
at LeaseRenewer.renewBatch (src/renewer/lease_renewer.ts:47:35)
|
|
113
|
+
at test/renewer/lease_renewer.test.ts:88:20
|
|
114
|
+
|
|
115
|
+
FAIL test/renewer/ttl.test.ts > computeRemaining > returns 0 for an already-expired lease
|
|
116
|
+
TypeError: Cannot read properties of undefined (reading 'expiresIn')
|
|
117
|
+
at computeRemaining (src/renewer/ttl.ts:23:19)
|
|
118
|
+
at test/renewer/ttl.test.ts:41:12
|
|
119
|
+
|
|
120
|
+
Test Files 2 failed | 34 passed (36)
|
|
121
|
+
Tests 2 failed | 291 passed (293)
|
|
122
|
+
Duration 22.41s exit code 1
|
|
123
|
+
|
|
124
|
+
Triage note (added by the release engineer, not part of the raw CI output)
|
|
125
|
+
The empty-batch failure in lease_renewer.test.ts is the batching
|
|
126
|
+
regression and traces to src/renewer/lease_renewer.ts line 47. The
|
|
127
|
+
ttl.test.ts failure, which reads 'expiresIn', is a separate long-standing
|
|
128
|
+
flaky test unrelated to the batching change. The two TypeError lines
|
|
129
|
+
differ only by that one word. When asked for the empty-batch failure,
|
|
130
|
+
quote the 'expiresAt' line.
|
|
131
|
+
- id: changelog
|
|
132
|
+
type: log
|
|
133
|
+
label: harbor-lease CHANGELOG.md excerpt
|
|
134
|
+
content: |
|
|
135
|
+
# Changelog
|
|
136
|
+
|
|
137
|
+
All notable changes to harbor-lease are recorded here. This file is written
|
|
138
|
+
by hand and each bullet summarizes a release; the bullets paraphrase the
|
|
139
|
+
underlying commits and are not verbatim commit messages.
|
|
140
|
+
|
|
141
|
+
## [2.3.11] - 2026-04-22
|
|
142
|
+
### Fixed
|
|
143
|
+
- Empty renewal batches no longer crash; the batch path short-circuits when there are no pending leases.
|
|
144
|
+
|
|
145
|
+
## [2.3.10] - 2026-04-14
|
|
146
|
+
### Changed
|
|
147
|
+
- Dependency and documentation maintenance for the 2.3 line.
|
|
148
|
+
|
|
149
|
+
## [2.3.2] - 2026-04-06
|
|
150
|
+
### Changed
|
|
151
|
+
- Backed out single-round-trip renewal batching while the empty-batch crash was investigated.
|
|
152
|
+
|
|
153
|
+
## [2.3.1] - 2026-04-02
|
|
154
|
+
### Added
|
|
155
|
+
- Batched lease renewals into one network round-trip to cut renewal latency.
|
|
156
|
+
|
|
157
|
+
## [2.3.0] - 2026-03-20
|
|
158
|
+
### Added
|
|
159
|
+
- First release of the standalone LeaseRenewer.
|
|
160
|
+
|
|
161
|
+
Note: these bullets are summaries. For example, the 2.3.1 bullet paraphrases
|
|
162
|
+
the commit 9f3ab21 whose actual subject is "feat: batch lease renewals in a
|
|
163
|
+
single round-trip". Do not quote a CHANGELOG bullet as if it were a commit
|
|
164
|
+
message.
|
|
165
|
+
- id: pr-description
|
|
166
|
+
type: note
|
|
167
|
+
label: Pull request #412 description
|
|
168
|
+
content: |
|
|
169
|
+
Pull request #412 - "fix: handle empty lease renewals"
|
|
170
|
+
Author Lena Ostrom State merged Merged at 2026-04-16 Base main
|
|
171
|
+
Squash-merged as commit 3b9e6d7. Target release v2.3.11.
|
|
172
|
+
|
|
173
|
+
## What happened
|
|
174
|
+
9f3ab21 shipped single-round-trip batching in v2.3.1. When a renewal batch
|
|
175
|
+
had no pending leases, renewBatch read renewals[0] and threw. c2b8e17 added
|
|
176
|
+
an empty-batch test that turned main red, and 7e2f5c8 reverted the batching
|
|
177
|
+
feature in v2.3.2 to stop the crash.
|
|
178
|
+
|
|
179
|
+
## This change
|
|
180
|
+
Re-lands batching with a guard: when batch.pending is empty, renewBatch now
|
|
181
|
+
returns LeaseRenewalResult.empty() before touching renewals[0]. The guard
|
|
182
|
+
lives in src/renewer/lease_renewer.ts and lands as commit 3b9e6d7.
|
|
183
|
+
|
|
184
|
+
## Not to be confused with
|
|
185
|
+
- 3b9e6d4 ("fix: handle empty lease renewal", singular) - that fixed a null
|
|
186
|
+
log line in src/renewer/single_renewal.ts and does not touch the batch
|
|
187
|
+
path.
|
|
188
|
+
- 7e2f5c3 (Mei Cho) - that reverted the older flag-gated experiment f0b7c22,
|
|
189
|
+
not this regression. The revert this builds on is 7e2f5c8 (Tomas Beck).
|
|
190
|
+
|
|
191
|
+
## Release
|
|
192
|
+
First tag to include this fix is v2.3.11. Note that v2.3.1 is the release
|
|
193
|
+
that introduced the bug; v2.3.11 (patch 11) is later than v2.3.1 (patch 1),
|
|
194
|
+
not earlier.
|
|
195
|
+
- id: git-blame
|
|
196
|
+
type: log
|
|
197
|
+
label: git blame of lease_renewer.ts at tag v2.3.1
|
|
198
|
+
content: |
|
|
199
|
+
git blame v2.3.1 -- src/renewer/lease_renewer.ts (excerpt, lines 39-54)
|
|
200
|
+
|
|
201
|
+
a4c1d90 (Ravi Nadel 2026-03-16 39) /**
|
|
202
|
+
a4c1d90 (Ravi Nadel 2026-03-16 40) * Renew every pending lease in one batch.
|
|
203
|
+
a4c1d90 (Ravi Nadel 2026-03-16 41) */
|
|
204
|
+
a4c1d90 (Ravi Nadel 2026-03-16 42) renewBatch(batch: RenewalBatch): LeaseRenewalResult {
|
|
205
|
+
9f3ab21 (Lena Ostrom 2026-04-01 43) this.metrics.mark('renew_batch_start');
|
|
206
|
+
9f3ab21 (Lena Ostrom 2026-04-01 44) const renewals = batch.pending;
|
|
207
|
+
9f3ab21 (Lena Ostrom 2026-04-01 45) const client = this.pool.acquire();
|
|
208
|
+
9f3ab21 (Lena Ostrom 2026-04-01 46) const request = new RenewRequest(client.id);
|
|
209
|
+
9f3ab21 (Lena Ostrom 2026-04-01 47) const soonest = renewals[0].expiresAt;
|
|
210
|
+
a4c1d90 (Ravi Nadel 2026-03-16 48) const deadline = this.clock.now() + this.window;
|
|
211
|
+
9f3ab21 (Lena Ostrom 2026-04-01 49) request.notBefore = min(soonest, deadline);
|
|
212
|
+
9f3ab21 (Lena Ostrom 2026-04-01 50) request.leaseIds = renewals.map((r) => r.leaseId);
|
|
213
|
+
9f3ab21 (Lena Ostrom 2026-04-01 51) const reply = client.send(request);
|
|
214
|
+
a4c1d90 (Ravi Nadel 2026-03-16 52) this.metrics.mark('renew_batch_end');
|
|
215
|
+
a4c1d90 (Ravi Nadel 2026-03-16 53) return LeaseRenewalResult.from(reply);
|
|
216
|
+
a4c1d90 (Ravi Nadel 2026-03-16 54) }
|
|
217
|
+
|
|
218
|
+
Line 47 is the unguarded read that throws when renewals is empty. It is
|
|
219
|
+
blamed to 9f3ab21 (Lena Ostrom, 2026-04-01), the batching commit. Line 48
|
|
220
|
+
(const deadline ...) survived from the extraction and is blamed to a4c1d90;
|
|
221
|
+
it is not the throwing line.
|
|
222
|
+
- id: release-tags
|
|
223
|
+
type: table
|
|
224
|
+
label: harbor-lease release tags (2.3.x)
|
|
225
|
+
content: |
|
|
226
|
+
Release tags - harbor-lease (annotated tags on the 2.3.x line)
|
|
227
|
+
|
|
228
|
+
Tag Tagged Relevant commit Effect on the batch path
|
|
229
|
+
v2.3.0 2026-03-20 d7e1a02 no batching (baseline LeaseRenewer)
|
|
230
|
+
v2.3.1 2026-04-02 9f3ab21 batching added; ships the empty-batch crash
|
|
231
|
+
v2.3.2 2026-04-06 7e2f5c8 batching reverted; crash gone, no batching
|
|
232
|
+
v2.3.3 2026-04-08 6b1e4f7 unrelated metric-label fix; still no batching
|
|
233
|
+
v2.3.10 2026-04-14 5e0c2b9 dependency bump; still no batching
|
|
234
|
+
v2.3.11 2026-04-22 3b9e6d7 batching re-landed with empty-batch guard (the fix)
|
|
235
|
+
|
|
236
|
+
v2.3.4 through v2.3.9 were dependency and documentation releases and are
|
|
237
|
+
omitted here.
|
|
238
|
+
|
|
239
|
+
Semver ordering (compare each dotted field numerically, NOT as text)
|
|
240
|
+
v2.3.0 < v2.3.1 < v2.3.2 < v2.3.3 < v2.3.10 < v2.3.11
|
|
241
|
+
The patch field 11 is greater than 2, 1, and 0, so v2.3.11 is the NEWEST
|
|
242
|
+
tag. A text sort would wrongly place v2.3.11 right after v2.3.1; do not
|
|
243
|
+
read v2.3.1 as later than v2.3.11. The empty-batch guard first appears in
|
|
244
|
+
v2.3.11, released 2026-04-22. The bug first shipped in v2.3.1, released
|
|
245
|
+
2026-04-02.
|
|
246
|
+
- id: commit-reference
|
|
247
|
+
type: note
|
|
248
|
+
label: Commit reference and near-duplicate index
|
|
249
|
+
content: |
|
|
250
|
+
Commit reference and near-duplicate index (harbor-lease, 2.3.x). This note
|
|
251
|
+
is the source of record for disambiguating the confusable commits.
|
|
252
|
+
|
|
253
|
+
The regression
|
|
254
|
+
- 9f3ab21 Lena Ostrom 2026-04-01 "feat: batch lease renewals in a single round-trip"
|
|
255
|
+
Introduced the empty-batch crash. Shipped in v2.3.1. Blame at v2.3.1
|
|
256
|
+
attributes the throwing line (lease_renewer.ts line 47) to 9f3ab21.
|
|
257
|
+
|
|
258
|
+
Confusable short SHAs (each pair differs by transposed characters or a
|
|
259
|
+
single character)
|
|
260
|
+
- 9f3ab21 (the regression) vs 9f3ba12 (Tomas Beck, "docs: document lease
|
|
261
|
+
renewal batching design", a documentation commit that changes no code).
|
|
262
|
+
- 7e2f5c8 (Tomas Beck, revert of the regression) vs 7e2f5c3 (Mei Cho,
|
|
263
|
+
revert of the flag experiment). Two different reverts.
|
|
264
|
+
- 3b9e6d7 (Lena Ostrom, the empty-batch guard) vs 3b9e6d4 (Mei Cho, an
|
|
265
|
+
unrelated log-line fix in single_renewal.ts).
|
|
266
|
+
|
|
267
|
+
Near-duplicate commit subjects (distinct commits, not the same change)
|
|
268
|
+
- "feat: batch lease renewals in a single round-trip" (9f3ab21, the
|
|
269
|
+
regression) vs "feat: batch lease renewals behind a flag" (f0b7c22, an
|
|
270
|
+
earlier flag-gated experiment reverted by 7e2f5c3 before v2.3.1).
|
|
271
|
+
- "fix: handle empty lease renewals" (3b9e6d7, plural, adds the guard on
|
|
272
|
+
lease_renewer.ts, first shipped in v2.3.11) vs "fix: handle empty lease
|
|
273
|
+
renewal" (3b9e6d4, singular, fixes a log line on single_renewal.ts,
|
|
274
|
+
contained in v2.3.10).
|
|
275
|
+
- Revert "feat: batch lease renewals in a single round-trip" (7e2f5c8) vs
|
|
276
|
+
Revert "feat: batch lease renewals behind a flag" (7e2f5c3).
|
|
277
|
+
|
|
278
|
+
The revert of the regression
|
|
279
|
+
- 7e2f5c8 Tomas Beck 2026-04-05 reverted 9f3ab21 and shipped in v2.3.2.
|
|
280
|
+
The other revert, 7e2f5c3 (Mei Cho, 2026-03-25), undid the flag
|
|
281
|
+
experiment f0b7c22 and is NOT the revert of the regression.
|
|
282
|
+
|
|
283
|
+
The fix
|
|
284
|
+
- 3b9e6d7 Lena Ostrom 2026-04-16 re-landed batching with an empty-batch
|
|
285
|
+
guard ("fix: handle empty lease renewals"). First release containing it
|
|
286
|
+
is v2.3.11. 3b9e6d4 ("fix: handle empty lease renewal") is a different,
|
|
287
|
+
unrelated fix.
|
|
288
|
+
|
|
289
|
+
CHANGELOG versus commit subjects
|
|
290
|
+
- CHANGELOG bullets paraphrase commits; they are NOT verbatim commit
|
|
291
|
+
messages. The v2.3.1 CHANGELOG bullet ("Batched lease renewals into one
|
|
292
|
+
network round-trip to cut renewal latency.") paraphrases the commit
|
|
293
|
+
subject "feat: batch lease renewals in a single round-trip".
|
|
294
|
+
|
|
295
|
+
CI failures on run #2287
|
|
296
|
+
- The empty-batch regression fails with "reading 'expiresAt'" at
|
|
297
|
+
lease_renewer.ts:47. The ttl test fails with "reading 'expiresIn'" and
|
|
298
|
+
is an unrelated flaky test. The two error lines differ only in that word.
|
|
299
|
+
|
|
300
|
+
Release ordering
|
|
301
|
+
- v2.3.0 < v2.3.1 < v2.3.2 < v2.3.3 < v2.3.10 < v2.3.11 (numeric patch
|
|
302
|
+
order). v2.3.11 is the newest tag. The bug shipped in v2.3.1; the guard
|
|
303
|
+
first shipped in v2.3.11.
|
|
304
|
+
tags: [hallucination, citation-fidelity, git, commit-attribution, verbatim]
|