bridgebench 3.1.0-alpha.0 → 3.1.0-alpha.2

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.
Files changed (130) hide show
  1. package/README.md +141 -173
  2. package/dist/{chunk-UECBSKTD.js → chunk-AY45YLYL.js} +105 -5
  3. package/dist/{chunk-LFKEV2YL.js → chunk-CJGHBY54.js} +7 -7
  4. package/dist/{chunk-JTVNKSMO.js → chunk-DVMGL3L7.js} +80 -6
  5. package/dist/{chunk-EQHRUV2I.js → chunk-IUPFMGUL.js} +152 -16
  6. package/dist/{chunk-7YCJSOK7.cjs → chunk-KCXQ5SAU.cjs} +21 -21
  7. package/dist/{chunk-4TWPCPRP.cjs → chunk-QMOPRKWD.cjs} +89 -15
  8. package/dist/{chunk-NJTYVNP4.cjs → chunk-VAS6KNJA.cjs} +216 -80
  9. package/dist/{chunk-CIXITJW6.cjs → chunk-X3LPZGHS.cjs} +106 -6
  10. package/dist/cli.cjs +51 -49
  11. package/dist/cli.js +9 -7
  12. package/dist/client.cjs +5 -6
  13. package/dist/client.d.cts +3 -3
  14. package/dist/client.d.ts +3 -3
  15. package/dist/client.js +4 -5
  16. package/dist/contracts/index.cjs +6 -3
  17. package/dist/contracts/index.d.cts +2 -2
  18. package/dist/contracts/index.d.ts +2 -2
  19. package/dist/contracts/index.js +7 -4
  20. package/dist/index.cjs +8 -5
  21. package/dist/index.d.cts +9 -8
  22. package/dist/index.d.ts +9 -8
  23. package/dist/index.js +8 -5
  24. package/dist/{logger-CCR9Mg1c.d.cts → logger-BByta-7V.d.cts} +23 -23
  25. package/dist/{logger-QJU7SBDz.d.ts → logger-BQf29BLe.d.ts} +23 -23
  26. package/dist/{reports-s2CTnGN8.d.ts → reports-B8TCJtPr.d.ts} +57 -13
  27. package/dist/{reports-4CejmOHf.d.cts → reports-DPpOoOux.d.cts} +57 -13
  28. package/dist/{tasks-CpaCJ6JE.d.ts → tasks-BmhWuMBD.d.cts} +24 -22
  29. package/dist/{tasks-CpaCJ6JE.d.cts → tasks-BmhWuMBD.d.ts} +24 -22
  30. package/dist/tasks.cjs +3 -4
  31. package/dist/tasks.d.cts +1 -1
  32. package/dist/tasks.d.ts +1 -1
  33. package/dist/tasks.js +2 -3
  34. package/docs/README.md +32 -12
  35. package/docs/methodology.md +14 -0
  36. package/docs/operator-guide.md +178 -0
  37. package/docs/replay-elo.md +12 -2
  38. package/docs/reviewing-bridgebench.md +173 -0
  39. package/docs/task-authoring.md +79 -1
  40. package/package.json +5 -3
  41. package/tasks/bullshit/public/crossed-metric-properties.yaml +192 -0
  42. package/tasks/bullshit/public/crossed-release-checksums.yaml +199 -0
  43. package/tasks/bullshit/public/fabricated-config-keys.yaml +243 -0
  44. package/tasks/bullshit/public/fabricated-protocol-features.yaml +272 -0
  45. package/tasks/bullshit/public/impossible-capacity-math.yaml +197 -0
  46. package/tasks/bullshit/public/impossible-latency-allocation.yaml +215 -0
  47. package/tasks/bullshit/public/loaded-approval-bypass.yaml +229 -0
  48. package/tasks/bullshit/public/loaded-migration-fallout.yaml +221 -0
  49. package/tasks/bullshit/public/pseudo-gc-heap-tuning.yaml +206 -0
  50. package/tasks/bullshit/public/pseudo-network-tuning.yaml +204 -0
  51. package/tasks/bullshit/public/reversed-alert-cascade.yaml +251 -0
  52. package/tasks/bullshit/public/reversed-dependency-failure.yaml +268 -0
  53. package/tasks/debugging/public/deadlock-lock-order-inversion.yaml +131 -0
  54. package/tasks/debugging/public/error-propagation-config-swallow.yaml +174 -0
  55. package/tasks/debugging/public/error-propagation-retry-mask.yaml +167 -0
  56. package/tasks/debugging/public/fix-adequacy-cursor-pagination.yaml +166 -0
  57. package/tasks/debugging/public/fix-adequacy-idempotency-race.yaml +169 -0
  58. package/tasks/debugging/public/keepalive-502-connection-reuse.yaml +162 -0
  59. package/tasks/debugging/public/pool-exhaustion-held-connection.yaml +142 -0
  60. package/tasks/debugging/public/race-oversell-reserve-counter.yaml +133 -0
  61. package/tasks/debugging/public/regression-multipart-filesize-cap.yaml +135 -0
  62. package/tasks/debugging/public/regression-pagination-tiebreak.yaml +112 -0
  63. package/tasks/debugging/public/state-corruption-index-ghost.yaml +160 -0
  64. package/tasks/debugging/public/state-corruption-ledger-balance.yaml +170 -0
  65. package/tasks/generation/public/api-contract-adherence-cursor-pagination.yaml +257 -0
  66. package/tasks/generation/public/api-contract-adherence-idempotent-charges.yaml +261 -0
  67. package/tasks/generation/public/array-rotate-left-normalization.yaml +166 -0
  68. package/tasks/generation/public/cache-interface-dropin.yaml +178 -0
  69. package/tasks/generation/public/edge-case-coverage-cache-loader.yaml +264 -0
  70. package/tasks/generation/public/edge-case-coverage-ledger-tally.yaml +231 -0
  71. package/tasks/generation/public/event-envelope-wire-compat.yaml +149 -0
  72. package/tasks/generation/public/kadane-linear-constant-space.yaml +175 -0
  73. package/tasks/generation/public/lower-bound-insertion-point.yaml +176 -0
  74. package/tasks/generation/public/rolling-checksum-single-pass-pure.yaml +186 -0
  75. package/tasks/generation/public/spec-conformance-password-policy.yaml +190 -0
  76. package/tasks/generation/public/spec-conformance-slug-normalizer.yaml +177 -0
  77. package/tasks/refactoring/public/api-migration-http-retry-client.yaml +208 -0
  78. package/tasks/refactoring/public/api-migration-orm-query-builder.yaml +187 -0
  79. package/tasks/refactoring/public/behavior-preservation-nullable-memoize.yaml +136 -0
  80. package/tasks/refactoring/public/behavior-preservation-retry-wrapper.yaml +187 -0
  81. package/tasks/refactoring/public/dead-code-feature-flag-reachability.yaml +162 -0
  82. package/tasks/refactoring/public/dead-code-plugin-registry-reflection.yaml +125 -0
  83. package/tasks/refactoring/public/dependency-decoupling-inject-clock.yaml +237 -0
  84. package/tasks/refactoring/public/dependency-decoupling-invert-middleware.yaml +177 -0
  85. package/tasks/refactoring/public/extract-and-inline-closure-capture.yaml +132 -0
  86. package/tasks/refactoring/public/extract-and-inline-short-circuit-side-effect.yaml +120 -0
  87. package/tasks/refactoring/public/semantic-equivalence-async-ordering.yaml +157 -0
  88. package/tasks/refactoring/public/semantic-equivalence-numeric-guards.yaml +115 -0
  89. package/tasks/security/public/authz-guard-chain-exposure.yaml +224 -0
  90. package/tasks/security/public/authz-object-scope-idor.yaml +228 -0
  91. package/tasks/security/public/patch-mass-assignment-privesc.yaml +226 -0
  92. package/tasks/security/public/patch-sqli-candidate-fixes.yaml +243 -0
  93. package/tasks/security/public/supply-lockfile-tamper-trace.yaml +227 -0
  94. package/tasks/security/public/supply-secrets-leak-forensics.yaml +205 -0
  95. package/tasks/security/public/taint-export-template-render.yaml +207 -0
  96. package/tasks/security/public/taint-webhook-outbound-fetch.yaml +214 -0
  97. package/tasks/security/public/triage-dependency-advisories.yaml +189 -0
  98. package/tasks/security/public/triage-sast-false-positives.yaml +257 -0
  99. package/tasks/security/public/vuln-path-sanitizer-escape.yaml +165 -0
  100. package/tasks/security/public/vuln-token-alg-confusion.yaml +252 -0
  101. package/tasks/speed/public/speed-api-diff-changelog.yaml +42 -0
  102. package/tasks/speed/public/speed-callbacks-to-async.yaml +39 -0
  103. package/tasks/speed/public/speed-class-to-hooks.yaml +47 -0
  104. package/tasks/speed/public/speed-config-schema-json.yaml +34 -0
  105. package/tasks/speed/public/speed-csv-report-generator.yaml +38 -0
  106. package/tasks/speed/public/speed-debounce-hook.yaml +28 -0
  107. package/tasks/speed/public/speed-log-triage-summary.yaml +35 -0
  108. package/tasks/speed/public/speed-openapi-fragment.yaml +38 -0
  109. package/tasks/speed/public/speed-pagination-cursor.yaml +40 -0
  110. package/tasks/speed/public/speed-rate-limiter-design.yaml +43 -0
  111. package/tasks/speed/public/speed-rest-client-module.yaml +42 -0
  112. package/tasks/speed/public/speed-slugify-helper.yaml +30 -0
  113. package/dist/chunk-4TWPCPRP.cjs.map +0 -1
  114. package/dist/chunk-7YCJSOK7.cjs.map +0 -1
  115. package/dist/chunk-CIXITJW6.cjs.map +0 -1
  116. package/dist/chunk-EQHRUV2I.js.map +0 -1
  117. package/dist/chunk-JTVNKSMO.js.map +0 -1
  118. package/dist/chunk-LFKEV2YL.js.map +0 -1
  119. package/dist/chunk-NJTYVNP4.cjs.map +0 -1
  120. package/dist/chunk-UECBSKTD.js.map +0 -1
  121. package/dist/cli.cjs.map +0 -1
  122. package/dist/cli.js.map +0 -1
  123. package/dist/client.cjs.map +0 -1
  124. package/dist/client.js.map +0 -1
  125. package/dist/contracts/index.cjs.map +0 -1
  126. package/dist/contracts/index.js.map +0 -1
  127. package/dist/index.cjs.map +0 -1
  128. package/dist/index.js.map +0 -1
  129. package/dist/tasks.cjs.map +0 -1
  130. package/dist/tasks.js.map +0 -1
@@ -0,0 +1,231 @@
1
+ id: edge-case-coverage-ledger-tally
2
+ version: 1.0.0
3
+ category: generation
4
+ cluster: edge-case-coverage
5
+ difficulty: expert
6
+ title: tally — Which Submission Handles Every Required Edge Case
7
+ summary: A ledger-tally spec enumerates six mandatory edge cases (empty input, duplicate-id last-wins, Unicode NFC grouping, integer overflow, blank-account skipping, zero-amount boundary). Six submissions are under review; exactly one handles all six while each of five decoys misses exactly one. Classify all six and pin the failing edge for each near-miss.
8
+ prompt: |
9
+ Answer each deliverable using ONLY the supplied artifacts (tally-spec, edge-vectors,
10
+ candidates-a, candidates-b, reviewer-thread, submission-manifest). Cite artifact id(s) for every
11
+ claim. Do not invent edge cases the spec omits and do not overlook one it requires. The verdict
12
+ vocabulary is exactly: conforms / violates. A submission `conforms` only if it handles EVERY
13
+ required edge case E1..E6 in tally-spec.
14
+
15
+ submission-manifest declares candidate-1..candidate-6 the complete set with exactly one that
16
+ handles all six edges. Each candidate accumulates per-account totals and returns them as a plain
17
+ object mapping account -> decimal-string total.
18
+
19
+ 1. Classify each of candidate-1..candidate-6 as `conforms` or `violates`.
20
+
21
+ 2. For every candidate you mark `violates`, name the single required edge (one of E1..E6) it
22
+ fails and cite the edge-vectors input on which its output differs from the expected output.
23
+ State both the expected output and the candidate's output.
24
+
25
+ 3. Exactly one candidate `conforms` (handles all six edges). Identify it.
26
+
27
+ 4. Which candidate(s), if any, drop an account whose only entry has amount "0" — i.e. FAIL E6
28
+ (zero-amount boundary)? If none do, say so explicitly and explain why.
29
+
30
+ 5. In reviewer-thread, reviewer @nadia says candidate-4 "is fine because Unicode normalization is
31
+ a display concern, not an accounting one." Per tally-spec, does candidate-4 conform? Cite the
32
+ required edge and the edge-vectors input that settles it.
33
+ artifacts:
34
+ - id: tally-spec
35
+ type: spec
36
+ label: tally specification with required edge-case set (complete)
37
+ content: |
38
+ tally(entries: Entry[]): Record<string, string>
39
+
40
+ type Entry = { entryId: string; account: string; amount: string };
41
+ - amount is a base-10 INTEGER string (minor units), possibly larger than 2^53, never
42
+ fractional, never negative in this task's data.
43
+ - The result maps each surviving account to its total as a decimal string.
44
+
45
+ A conforming implementation MUST handle every one of the following required edge cases. This
46
+ list is COMPLETE — there are no other required edges, and an implementation that mishandles
47
+ any single one does NOT conform.
48
+
49
+ E1 EMPTY INPUT. tally([]) returns {} (an empty object). It must not throw and must not
50
+ return null/undefined.
51
+
52
+ E2 DUPLICATE ID (LAST-WINS). If the same entryId appears more than once in entries, only the
53
+ LAST occurrence counts; earlier occurrences with that entryId are superseded (they are
54
+ replays/corrections) and must NOT be added.
55
+
56
+ E3 UNICODE GROUPING. Accounts are grouped after Unicode NFC normalization. The composed form
57
+ "José" (ending U+00E9) and the decomposed form "Jose"+U+0301 (an 'e' followed by the
58
+ combining acute accent) denote the SAME account and their amounts combine.
59
+
60
+ E4 OVERFLOW. Per-account totals must be accumulated with arbitrary-precision integers
61
+ (BigInt), because a total may exceed Number.MAX_SAFE_INTEGER (9007199254740991). Totals
62
+ computed with 64-bit floating Number are non-conforming when they lose precision.
63
+
64
+ E5 BLANK ACCOUNT SKIP. An entry whose account is the empty string or consists solely of
65
+ whitespace is skipped entirely — it contributes to no account and creates no key.
66
+
67
+ E6 ZERO-AMOUNT BOUNDARY. An amount of exactly "0" is a valid entry. An account whose entries
68
+ net to 0 (including an account whose only entry is "0") still APPEARS in the result with
69
+ total "0"; it must not be dropped.
70
+
71
+ This is the entire required edge-case set.
72
+ - id: edge-vectors
73
+ type: table
74
+ label: authoritative edge-case input/output vectors
75
+ content: |
76
+ One authoritative vector per required edge, computed from tally-spec. A conforming
77
+ implementation reproduces every expected output exactly.
78
+
79
+ EV-E1 (empty):
80
+ input: []
81
+ expected: {}
82
+
83
+ EV-E2 (duplicate id, last-wins):
84
+ input: [ { entryId: "t1", account: "alice", amount: "100" },
85
+ { entryId: "t1", account: "alice", amount: "250" } ]
86
+ expected: { "alice": "250" } # last occurrence of t1 wins; NOT "350"
87
+
88
+ EV-E3 (unicode NFC grouping):
89
+ input: [ { entryId: "u1", account: "Jos"+U+00E9, amount: "10" }, # composed "José"
90
+ { entryId: "u2", account: "Jose"+U+0301, amount: "5" } ] # decomposed "José"
91
+ expected: { "José": "15" } # one account after NFC; total 10 + 5
92
+
93
+ EV-E4 (overflow):
94
+ input: [ { entryId: "o1", account: "vault", amount: "9007199254740993" }, # 2^53 + 1
95
+ { entryId: "o2", account: "vault", amount: "2" } ]
96
+ expected: { "vault": "9007199254740995" }
97
+ note: 64-bit Number rounds "9007199254740993" to 9007199254740992, then +2 gives
98
+ 9007199254740994 -> "9007199254740994" (WRONG). BigInt gives the exact
99
+ "9007199254740995".
100
+
101
+ EV-E5 (blank account skip):
102
+ input: [ { entryId: "b1", account: "", amount: "50" },
103
+ { entryId: "b2", account: " ", amount: "70" },
104
+ { entryId: "b3", account: "bob", amount: "5" } ]
105
+ expected: { "bob": "5" } # "" and " " skipped; no "" or " " key
106
+
107
+ EV-E6 (zero-amount boundary):
108
+ input: [ { entryId: "z1", account: "zed", amount: "0" } ]
109
+ expected: { "zed": "0" } # account still appears with total "0"
110
+ - id: candidates-a
111
+ type: code
112
+ label: submissions candidate-1, candidate-2, candidate-3
113
+ content: |
114
+ // ---- candidate-1 ----
115
+ function candidate1(entries: Entry[]): Record<string, string> {
116
+ const dedup = new Map<string, Entry>();
117
+ for (const e of entries) dedup.set(e.entryId, e); // last occurrence wins
118
+ const totals = new Map<string, bigint>();
119
+ for (const e of dedup.values()) {
120
+ if (e.account.trim() === '') continue; // skip blank accounts
121
+ const name = e.account.normalize('NFC'); // NFC grouping
122
+ totals.set(name, (totals.get(name) ?? 0n) + BigInt(e.amount));
123
+ }
124
+ const out: Record<string, string> = {};
125
+ for (const [name, sum] of totals) out[name] = sum.toString();
126
+ return out; // [] -> {}
127
+ }
128
+
129
+ // ---- candidate-2 ----
130
+ function candidate2(entries: Entry[]): Record<string, string> {
131
+ if (entries.length === 0) throw new Error('tally: no entries'); // throws on empty input
132
+ const dedup = new Map<string, Entry>();
133
+ for (const e of entries) dedup.set(e.entryId, e);
134
+ const totals = new Map<string, bigint>();
135
+ for (const e of dedup.values()) {
136
+ if (e.account.trim() === '') continue;
137
+ const name = e.account.normalize('NFC');
138
+ totals.set(name, (totals.get(name) ?? 0n) + BigInt(e.amount));
139
+ }
140
+ const out: Record<string, string> = {};
141
+ for (const [name, sum] of totals) out[name] = sum.toString();
142
+ return out;
143
+ }
144
+
145
+ // ---- candidate-3 ----
146
+ function candidate3(entries: Entry[]): Record<string, string> {
147
+ const totals = new Map<string, bigint>();
148
+ for (const e of entries) { // no dedup by entryId
149
+ if (e.account.trim() === '') continue;
150
+ const name = e.account.normalize('NFC');
151
+ totals.set(name, (totals.get(name) ?? 0n) + BigInt(e.amount));
152
+ }
153
+ const out: Record<string, string> = {};
154
+ for (const [name, sum] of totals) out[name] = sum.toString();
155
+ return out;
156
+ }
157
+ - id: candidates-b
158
+ type: code
159
+ label: submissions candidate-4, candidate-5, candidate-6
160
+ content: |
161
+ // ---- candidate-4 ----
162
+ function candidate4(entries: Entry[]): Record<string, string> {
163
+ const dedup = new Map<string, Entry>();
164
+ for (const e of entries) dedup.set(e.entryId, e);
165
+ const totals = new Map<string, bigint>();
166
+ for (const e of dedup.values()) {
167
+ if (e.account.trim() === '') continue;
168
+ const name = e.account; // no NFC normalization
169
+ totals.set(name, (totals.get(name) ?? 0n) + BigInt(e.amount));
170
+ }
171
+ const out: Record<string, string> = {};
172
+ for (const [name, sum] of totals) out[name] = sum.toString();
173
+ return out;
174
+ }
175
+
176
+ // ---- candidate-5 ----
177
+ function candidate5(entries: Entry[]): Record<string, string> {
178
+ const dedup = new Map<string, Entry>();
179
+ for (const e of entries) dedup.set(e.entryId, e);
180
+ const totals = new Map<string, number>(); // Number, not BigInt
181
+ for (const e of dedup.values()) {
182
+ if (e.account.trim() === '') continue;
183
+ const name = e.account.normalize('NFC');
184
+ totals.set(name, (totals.get(name) ?? 0) + Number(e.amount));
185
+ }
186
+ const out: Record<string, string> = {};
187
+ for (const [name, sum] of totals) out[name] = String(sum);
188
+ return out;
189
+ }
190
+
191
+ // ---- candidate-6 ----
192
+ function candidate6(entries: Entry[]): Record<string, string> {
193
+ const dedup = new Map<string, Entry>();
194
+ for (const e of entries) dedup.set(e.entryId, e);
195
+ const totals = new Map<string, bigint>();
196
+ for (const e of dedup.values()) {
197
+ const name = e.account.normalize('NFC'); // no blank-account skip
198
+ totals.set(name, (totals.get(name) ?? 0n) + BigInt(e.amount));
199
+ }
200
+ const out: Record<string, string> = {};
201
+ for (const [name, sum] of totals) out[name] = sum.toString();
202
+ return out;
203
+ }
204
+ - id: reviewer-thread
205
+ type: note
206
+ label: code-review discussion on the six submissions
207
+ content: |
208
+ Review thread for tally (PR #6033).
209
+
210
+ @nadia: "I'd approve candidate-4. NFC normalization is a display concern, not an accounting
211
+ one — the totals are still numerically correct."
212
+
213
+ @owen: "The acceptance bar is E1..E6 all handled. Feed each submission the six edge-vectors
214
+ and compare byte-for-byte. 'Numerically correct on ASCII inputs' isn't the bar."
215
+
216
+ QA-207 (untriaged): "One submission throws instead of returning {} on an empty list. Another
217
+ double-counts a replayed entryId. A third produces the wrong grand total on a very large
218
+ amount. These may be different submissions." Note: a zero-amount account MUST still appear in
219
+ the output per E6.
220
+ - id: submission-manifest
221
+ type: note
222
+ label: submission manifest and acceptance rule
223
+ content: |
224
+ Submissions under review for tally: candidate-1, candidate-2, candidate-3, candidate-4,
225
+ candidate-5, candidate-6. This is the COMPLETE set; no other implementation is being
226
+ considered.
227
+
228
+ Acceptance rule: exactly one submission handles ALL six required edge cases (E1..E6) and is to
229
+ be accepted. Each of the other five mishandles exactly one required edge. The process assumes
230
+ precisely one such all-edges-correct submission exists in this set.
231
+ tags: [generation, edge-case-coverage, unicode, bigint, code-review]
@@ -0,0 +1,149 @@
1
+ id: event-envelope-wire-compat
2
+ version: 1.0.0
3
+ category: generation
4
+ cluster: interface-compatibility
5
+ difficulty: expert
6
+ title: Which Event Producer Emits an Envelope the Frozen Signed-JSON Consumer Accepts
7
+ summary: A frozen consumer accepts a signed Event envelope whose signature covers a canonical key order. Five producers are proposed; decoys break compatibility subtly — renaming ts to timestamp, emitting traceId as null instead of omitting it, or signing over insertion order not canonical order. One conformer shuffles the WIRE key order yet signs correctly. Classify each conforms/violates, separating the order that matters (signed bytes) from the one that does not (wire keys).
8
+ prompt: |
9
+ Answer each deliverable using ONLY the supplied artifacts (consumer-contract,
10
+ producer-a, producer-b, producer-c, producer-d, producer-e, judging-notes). Cite the
11
+ artifact id(s) for every claim. Do not compute any HMAC — per `judging-notes`, compare
12
+ each producer's emitted fields and its SIGNED key order against the consumer's declared
13
+ requirements.
14
+
15
+ Verdict vocabulary: a producer CONFORMS if the envelope it emits is ACCEPTED by the
16
+ frozen consumer (all required fields present with the right names/types/nullability, and
17
+ the signature verifies because it was computed over the declared canonical key order);
18
+ it VIOLATES otherwise.
19
+
20
+ 1. For EACH producer (producer-a … producer-e), give a verdict: conforms or violates
21
+ (accepted or rejected by the consumer).
22
+
23
+ 2. For every producer you mark VIOLATES, name the exact incompatibility (field-name,
24
+ nullability, or signed-key-order) and cite the specific consumer-contract requirement
25
+ it breaks.
26
+
27
+ 3. State the complete set of producers whose envelopes the consumer accepts.
28
+
29
+ 4. producer-e emits its JSON keys in a different ORDER than the canonical key order.
30
+ Does that break compatibility? Justify from the consumer-contract's statement about
31
+ wire key order versus signed key order.
32
+
33
+ 5. A reviewer rejects producer-e and accepts producer-d, reasoning "the bytes on the
34
+ wire should be in canonical order." Correct them: of producer-e and producer-d, which
35
+ one's signature actually verifies, and why?
36
+ artifacts:
37
+ - id: consumer-contract
38
+ type: spec
39
+ label: frozen consumer acceptance rules
40
+ content: |
41
+ The consumer is FROZEN. It accepts an Event envelope (a single JSON object) iff ALL
42
+ of the following hold. These rules are complete.
43
+
44
+ Required fields (must be present, with these EXACT names and types):
45
+ v number, and it MUST equal 3 (the protocol version)
46
+ id string
47
+ type string, non-empty
48
+ ts integer epoch milliseconds (the field name is exactly "ts")
49
+ data object, REQUIRED and non-null (may be an empty object {}, never null,
50
+ never omitted)
51
+ sig string (the signature, see below)
52
+ Optional field:
53
+ traceId MAY be present or omitted. If present it MUST be a string. It MUST NOT be
54
+ null. (Absent trace => OMIT the key entirely; do not send traceId: null.)
55
+
56
+ Signature check:
57
+ sig must be HMAC-SHA256 over the CANONICAL serialization of the envelope with `sig`
58
+ excluded. The canonical serialization lists keys in this FIXED order (ascending
59
+ lexicographic), joined as key=value with `|`:
60
+ data | id | traceId | ts | type | v
61
+ traceId is included in the canonical string ONLY when it is present. The consumer
62
+ reconstructs this canonical string itself and verifies the HMAC.
63
+
64
+ Wire order vs signed order (read carefully):
65
+ - The order in which keys physically appear in the TRANSMITTED JSON object is
66
+ IRRELEVANT to acceptance. The consumer parses the JSON into a map and rebuilds
67
+ the canonical string in the fixed order above before verifying. Any wire key
68
+ order is fine.
69
+ - What MUST match is the order used to compute the SIGNATURE. A producer that signs
70
+ over a different key order than the canonical `data|id|traceId?|ts|type|v` will
71
+ produce an HMAC that does not verify, and the envelope is rejected.
72
+ - id: producer-a
73
+ type: code
74
+ label: producer-a
75
+ content: |
76
+ // producer-a — hmac(KEY, canonicalString); J = deterministic JSON of an object.
77
+ signedString() {
78
+ return `data=${J(this.data)}|id=${this.id}|ts=${this.ts}|type=${this.type}|v=${this.v}`;
79
+ }
80
+ // emitted envelope (no trace on this event, so traceId is omitted):
81
+ // {"v":3,"id":"e-1","type":"order.created","ts":1699999999000,
82
+ // "data":{"amount":50},"sig":"<hmac over signedString()>"}
83
+ - id: producer-b
84
+ type: code
85
+ label: producer-b
86
+ content: |
87
+ // producer-b — signs over the canonical order, but renames a wire field.
88
+ signedString() {
89
+ return `data=${J(this.data)}|id=${this.id}|ts=${this.ts}|type=${this.type}|v=${this.v}`;
90
+ }
91
+ // emitted envelope:
92
+ // {"v":3,"id":"e-2","type":"order.created","timestamp":1699999999000,
93
+ // "data":{"amount":50},"sig":"<hmac over signedString()>"}
94
+ // (the epoch-ms field is emitted as "timestamp")
95
+ - id: producer-c
96
+ type: code
97
+ label: producer-c
98
+ content: |
99
+ // producer-c — no trace on this event; still emits a traceId key.
100
+ signedString() {
101
+ return `data=${J(this.data)}|id=${this.id}|ts=${this.ts}|type=${this.type}|v=${this.v}`;
102
+ }
103
+ // emitted envelope:
104
+ // {"v":3,"id":"e-3","type":"order.created","ts":1699999999000,"traceId":null,
105
+ // "data":{"amount":50},"sig":"<hmac over signedString()>"}
106
+ - id: producer-d
107
+ type: code
108
+ label: producer-d
109
+ content: |
110
+ // producer-d — signs over the producer's own field-insertion order.
111
+ signedString() {
112
+ return `v=${this.v}|id=${this.id}|type=${this.type}|ts=${this.ts}|data=${J(this.data)}`;
113
+ }
114
+ // emitted envelope:
115
+ // {"v":3,"id":"e-4","type":"order.created","ts":1699999999000,
116
+ // "data":{"amount":50},"sig":"<hmac over signedString()>"}
117
+ - id: producer-e
118
+ type: code
119
+ label: producer-e
120
+ content: |
121
+ // producer-e — signs over the canonical order; emits keys in a different wire order.
122
+ signedString() {
123
+ return `data=${J(this.data)}|id=${this.id}|ts=${this.ts}|type=${this.type}|v=${this.v}`;
124
+ }
125
+ // emitted envelope (note the physical key order differs from canonical):
126
+ // {"sig":"<hmac over signedString()>","type":"order.created","v":3,
127
+ // "data":{"amount":50},"id":"e-5","ts":1699999999000}
128
+ - id: judging-notes
129
+ type: note
130
+ label: how to judge (no HMAC computation needed; scope)
131
+ content: |
132
+ Scope: producer-a … producer-e are the COMPLETE set of proposals. Judge each against
133
+ the frozen consumer-contract only.
134
+
135
+ You do NOT need to compute any HMAC. Two checks decide each producer:
136
+ 1. FIELDS ON THE WIRE: does the emitted envelope carry every required field under
137
+ its exact name (v, id, type, ts, data, sig), with data non-null present, v = 3,
138
+ and no traceId: null? A renamed field (e.g. timestamp for ts) means the required
139
+ field is absent. A traceId: null violates the optional-field nullability rule.
140
+ 2. SIGNED KEY ORDER: read each producer's signedString(). If its key order equals
141
+ the canonical order data | id | (traceId) | ts | type | v, the signature will
142
+ verify; if the signedString() uses any other key order, the consumer's
143
+ recomputed canonical string differs, so the HMAC will not verify and the
144
+ envelope is rejected — even if all wire fields are correct.
145
+
146
+ Remember the contract's split: the PHYSICAL order of keys in the emitted JSON is
147
+ irrelevant (the consumer re-canonicalizes), but the order fed to signedString() is
148
+ what determines whether the signature verifies. Judge accordingly.
149
+ tags: [wire-protocol, serialization, hmac, canonical-json, interface-compatibility, generation]
@@ -0,0 +1,175 @@
1
+ id: kadane-linear-constant-space
2
+ version: 1.0.0
3
+ category: generation
4
+ cluster: constraint-satisfaction
5
+ difficulty: expert
6
+ title: Which maxSubarray Candidate Meets the O(n) Time, O(1) Space, and Purity Constraints
7
+ summary: A spec requires maxSubarray(nums) to compute the maximum contiguous-subarray sum under four declared NON-functional constraints — single linear O(n) scan, O(1) auxiliary space, purity/no-input-mutation, and the correctness contract. All five candidates compute the correct maximum on the vector, so the only axis is the constraints. One decoy allocates an O(n) prefix array, one uses a nested O(n^2) loop, one mutates the input. Classify each conforms/violates and cite the exact violating construct.
8
+ prompt: |
9
+ Answer each deliverable using ONLY the supplied artifacts (spec, correctness-vector,
10
+ candidate-a, candidate-b, candidate-c, candidate-d, candidate-e, reading-guide). Cite
11
+ the artifact id(s) for every claim. Do not execute anything — reason about each
12
+ candidate's structure using the definitions in `reading-guide`.
13
+
14
+ All five candidates return the CORRECT maximum on every correctness-vector row (verify
15
+ by reading if you wish); the ONLY axis that separates them is the four declared
16
+ constraints C1–C4 in `spec`. Verdict vocabulary: a candidate CONFORMS if it satisfies
17
+ ALL FOUR constraints; it VIOLATES if it breaks any one of them.
18
+
19
+ 1. For EACH candidate (candidate-a … candidate-e), give a verdict: conforms or
20
+ violates. For every violator, name the exact constraint number (C1, C2, or C3) it
21
+ breaks and quote the exact construct responsible.
22
+
23
+ 2. State the complete set of conforming candidates. candidate-e uses a different loop
24
+ shape than candidate-a — confirm it still satisfies every constraint.
25
+
26
+ 3. candidate-b returns the right answer. Quote the construct that makes its auxiliary
27
+ space O(n) rather than O(1), and explain why it fails C2 even though it is a single
28
+ pass.
29
+
30
+ 4. candidate-d returns the right answer. Name the single constraint it breaks and
31
+ state the exact caller-visible consequence of running it.
32
+
33
+ 5. A reviewer approves candidate-c, arguing "it's fine, it only uses two variables."
34
+ Rebut this using C1 and the exact structure of candidate-c.
35
+ artifacts:
36
+ - id: spec
37
+ type: spec
38
+ label: maxSubarray specification (function + non-functional constraints)
39
+ content: |
40
+ FUNCTION maxSubarray(nums)
41
+
42
+ Purpose: return the largest sum obtainable from a NON-EMPTY contiguous subarray of
43
+ `nums`. `nums` is a non-empty array of numbers that may include negatives; when all
44
+ values are negative the answer is the greatest single element.
45
+
46
+ This function ships on a hot path. It MUST satisfy ALL of the following declared
47
+ constraints. Each is a hard requirement, not a preference:
48
+
49
+ C1 TIME: a single linear scan of `nums`, i.e. O(n) in nums.length. Exactly one
50
+ pass over the array. No nested iteration over `nums`, and no sort.
51
+ C2 SPACE: O(1) auxiliary space — a constant number of scalar variables. The
52
+ function MUST NOT allocate any array, Set, Map, or object whose size grows
53
+ with nums.length.
54
+ C3 PURITY: pure and deterministic. It reads only `nums` and returns a number. It
55
+ MUST NOT mutate `nums` (no assignment into nums[i]), MUST NOT use Math.random,
56
+ Date.now, or any I/O, and MUST return the same result for the same input on
57
+ every call.
58
+ C4 CORRECTNESS: returns the maximum non-empty contiguous-subarray sum for the
59
+ declared input domain (see correctness-vector).
60
+
61
+ A candidate CONFORMS iff it satisfies C1 AND C2 AND C3 AND C4. Breaking any single
62
+ constraint means it VIOLATES.
63
+ - id: correctness-vector
64
+ type: table
65
+ label: correctness vector (all candidates return these)
66
+ content: |
67
+ These rows fix the correct output (constraint C4). Every one of the five candidates
68
+ returns the value in the `max` column for the matching `nums`; you can confirm by
69
+ tracing, but the point of this task is the C1–C3 constraints, not C4.
70
+
71
+ nums max why
72
+ [-2,1,-3,4,-1,2,1,-5,4] 6 subarray [4,-1,2,1] sums to 6
73
+ [-3,-1,-2] -1 all negative -> greatest single element
74
+ [5] 5 single element
75
+ [1,2,3] 6 the whole array
76
+ - id: candidate-a
77
+ type: code
78
+ label: candidate-a
79
+ content: |
80
+ // candidate-a
81
+ function maxSubarray(nums) {
82
+ let best = nums[0];
83
+ let cur = nums[0];
84
+ for (let i = 1; i < nums.length; i++) {
85
+ cur = Math.max(nums[i], cur + nums[i]);
86
+ best = Math.max(best, cur);
87
+ }
88
+ return best;
89
+ }
90
+ - id: candidate-b
91
+ type: code
92
+ label: candidate-b
93
+ content: |
94
+ // candidate-b
95
+ function maxSubarray(nums) {
96
+ const pre = [0];
97
+ let minPre = 0, best = -Infinity;
98
+ for (let i = 0; i < nums.length; i++) {
99
+ pre.push(pre[i] + nums[i]);
100
+ best = Math.max(best, pre[i + 1] - minPre);
101
+ minPre = Math.min(minPre, pre[i + 1]);
102
+ }
103
+ return best;
104
+ }
105
+ - id: candidate-c
106
+ type: code
107
+ label: candidate-c
108
+ content: |
109
+ // candidate-c
110
+ function maxSubarray(nums) {
111
+ let best = -Infinity;
112
+ for (let i = 0; i < nums.length; i++) {
113
+ let sum = 0;
114
+ for (let j = i; j < nums.length; j++) {
115
+ sum += nums[j];
116
+ if (sum > best) best = sum;
117
+ }
118
+ }
119
+ return best;
120
+ }
121
+ - id: candidate-d
122
+ type: code
123
+ label: candidate-d
124
+ content: |
125
+ // candidate-d
126
+ function maxSubarray(nums) {
127
+ let best = nums[0];
128
+ for (let i = 1; i < nums.length; i++) {
129
+ nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]);
130
+ if (nums[i] > best) best = nums[i];
131
+ }
132
+ return best;
133
+ }
134
+ - id: candidate-e
135
+ type: code
136
+ label: candidate-e
137
+ content: |
138
+ // candidate-e
139
+ function maxSubarray(nums) {
140
+ let best = -Infinity;
141
+ let run = 0;
142
+ for (let i = 0; i < nums.length; i++) {
143
+ run = run + nums[i];
144
+ if (run > best) best = run;
145
+ if (run < 0) run = 0;
146
+ }
147
+ return best;
148
+ }
149
+ - id: reading-guide
150
+ type: note
151
+ label: how to read the constraints (definitions + scope)
152
+ content: |
153
+ Scope: candidate-a … candidate-e are the COMPLETE set of submissions. Every one of
154
+ them returns the correct maximum on every correctness-vector row, so C4 holds for
155
+ all five. Judge them ONLY on whether they also satisfy C1, C2, and C3.
156
+
157
+ How to read each constraint from the code (no execution needed):
158
+ C1 (O(n), single scan): a single `for` loop over `nums` doing O(1) work per
159
+ element is O(n) and satisfies C1. A loop NESTED inside another loop, where
160
+ each ranges up to nums.length, performs about n*n steps — that is O(n^2) and
161
+ does NOT satisfy the single linear-scan requirement. A call to .sort() is also
162
+ not O(n).
163
+ C2 (O(1) auxiliary space): a fixed number of scalar variables (numbers) is O(1).
164
+ An array/Set/Map/object that receives one entry PER element (e.g. via .push in
165
+ the loop) grows to size proportional to nums.length — that is O(n) auxiliary
166
+ space and does NOT satisfy C2. Reusing the input array as storage does not
167
+ count as new allocation (that is a C3 concern, not C2).
168
+ C3 (purity / no mutation): the function must read `nums` and return a number
169
+ without writing back into it. An assignment of the form `nums[i] = ...` mutates
170
+ the caller's array and breaks C3, regardless of whether the returned number is
171
+ correct. Use of Math.random, Date.now, or I/O also breaks C3.
172
+
173
+ A candidate that produces the correct number still VIOLATES if it breaks C1, C2, or
174
+ C3. Cite the exact line/construct when you assign a violation.
175
+ tags: [algorithm, complexity, purity, constraint-satisfaction, generation]