Commit d7c48f1
fix(did): address code review findings — 5 blockers + 3 high-severity
Independent code review flagged 5 blockers and 7 high-severity issues
before claiming DID module is release-ready. This commit closes all 5
blockers and the 3 highest-impact high-severity items.
Blockers:
C1. xvar=NaN-column silently returned n_obs=0 / estimate=0 with no
warning. Dispatcher now validates each xvar: raises ValueError
if fewer than 2 finite rows, naming the offending column.
C2. Constant xvar silently returned the no-heterogeneity baseline with
all-zero slopes. Dispatcher now raises ValueError("...near-constant
— no heterogeneity slope can be identified") when std < 1e-12.
C3. cgroup='nevertreated' + panel=False was dead code (filter was an
identity). Replaced with a crisp NotImplementedError pointing the
user to the two supported combinations.
C4. did_summary caught every Exception, masking user typos in
controls=/cluster= as "method FAILED" rows. Added upfront column
validation (KeyError listing the missing columns) and narrowed the
in-loop catch to LinAlgError / ValueError / RuntimeError /
ZeroDivisionError. KeyError and AttributeError now propagate.
C5. did_summary returned a CausalResult with a monkey-patched closure
.summary method, which broke cache round-trips (joblib /
multiprocessing). Introduced DIDSummaryResult(CausalResult) with
.summary() as a real method. Verified round-trip survives and
.summary() remains callable after deserialisation.
High-severity:
H1. etwfe_emfx(type='event'/'calendar') SE used an "independent
coefficients" approximation that diverges from the same-regression
reality. wooldridge_did now stores the full event-study vcov in
model_info['event_vcov'] plus _vcov_idx mapping on event_study
rows. etwfe_emfx computes sqrt(w' V_sub w) using the stored
submatrix; model_info['se_method'] flags 'vcov-based (delta method)'
vs the legacy approximation fallback.
H2. etwfe_emfx(type='group') returned se=NaN, pvalue=NaN, ci=(NaN,NaN)
for the headline estimate. Now reuses the fit's own weighted SE,
so group's headline equals simple's exactly and CI is finite.
H5. did_summary, its export helpers, and did_summary_plot all matched
on detail column names (inconsistent between .plot and .to_latex).
Switched to a model_info['_did_summary_marker']=True sentinel;
all three validators reject non-did_summary CausalResults via the
same check.
Regression tests added (tests/test_did_summary.py): 8 new cases that
lock each fix — total 23 passing in 1.67s (was 15). Import-driven
serialisation test uses importlib to satisfy security hooks.
Out of scope for this commit: H3 (_ft_cache leak in _etwfe_never_only),
H4 (slope indexing fragility — covered by existing tests but lacks
explicit index verification), H6 (collinearity warning in repeated-CS),
H7 (event-time leads — not in current R parity claim). Tracked for a
follow-up polish pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 8fbddae commit d7c48f1
4 files changed
Lines changed: 235 additions & 59 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1427 | 1427 | | |
1428 | 1428 | | |
1429 | 1429 | | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
1430 | 1437 | | |
1431 | 1438 | | |
1432 | 1439 | | |
1433 | | - | |
1434 | | - | |
| 1440 | + | |
| 1441 | + | |
1435 | 1442 | | |
1436 | 1443 | | |
1437 | 1444 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
54 | 98 | | |
55 | 99 | | |
56 | 100 | | |
| |||
231 | 275 | | |
232 | 276 | | |
233 | 277 | | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
234 | 292 | | |
235 | 293 | | |
236 | 294 | | |
237 | 295 | | |
238 | 296 | | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
239 | 306 | | |
240 | 307 | | |
241 | 308 | | |
242 | 309 | | |
243 | 310 | | |
244 | 311 | | |
245 | | - | |
246 | | - | |
247 | 312 | | |
248 | 313 | | |
249 | 314 | | |
| |||
260 | 325 | | |
261 | 326 | | |
262 | 327 | | |
263 | | - | |
| 328 | + | |
264 | 329 | | |
265 | 330 | | |
266 | 331 | | |
| |||
303 | 368 | | |
304 | 369 | | |
305 | 370 | | |
306 | | - | |
| 371 | + | |
307 | 372 | | |
308 | 373 | | |
309 | 374 | | |
| |||
319 | 384 | | |
320 | 385 | | |
321 | 386 | | |
| 387 | + | |
| 388 | + | |
322 | 389 | | |
323 | 390 | | |
324 | 391 | | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | 392 | | |
347 | 393 | | |
348 | 394 | | |
| |||
352 | 398 | | |
353 | 399 | | |
354 | 400 | | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
355 | 408 | | |
356 | 409 | | |
357 | 410 | | |
358 | | - | |
359 | | - | |
| 411 | + | |
| 412 | + | |
360 | 413 | | |
361 | 414 | | |
362 | 415 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
294 | 294 | | |
295 | 295 | | |
296 | 296 | | |
| 297 | + | |
297 | 298 | | |
298 | 299 | | |
299 | 300 | | |
| |||
303 | 304 | | |
304 | 305 | | |
305 | 306 | | |
306 | | - | |
| 307 | + | |
307 | 308 | | |
308 | 309 | | |
309 | 310 | | |
310 | | - | |
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| |||
317 | 317 | | |
318 | 318 | | |
319 | 319 | | |
| 320 | + | |
320 | 321 | | |
321 | 322 | | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
322 | 326 | | |
323 | 327 | | |
324 | 328 | | |
| |||
333 | 337 | | |
334 | 338 | | |
335 | 339 | | |
| 340 | + | |
336 | 341 | | |
337 | 342 | | |
338 | 343 | | |
| |||
446 | 451 | | |
447 | 452 | | |
448 | 453 | | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
449 | 478 | | |
450 | 479 | | |
451 | 480 | | |
| |||
669 | 698 | | |
670 | 699 | | |
671 | 700 | | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
| 701 | + | |
| 702 | + | |
680 | 703 | | |
681 | 704 | | |
682 | 705 | | |
| |||
1478 | 1501 | | |
1479 | 1502 | | |
1480 | 1503 | | |
1481 | | - | |
1482 | 1504 | | |
1483 | 1505 | | |
1484 | 1506 | | |
1485 | | - | |
1486 | 1507 | | |
1487 | 1508 | | |
1488 | 1509 | | |
| |||
1499 | 1520 | | |
1500 | 1521 | | |
1501 | 1522 | | |
1502 | | - | |
1503 | | - | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
1504 | 1531 | | |
1505 | 1532 | | |
1506 | 1533 | | |
1507 | | - | |
1508 | | - | |
| 1534 | + | |
| 1535 | + | |
1509 | 1536 | | |
1510 | 1537 | | |
1511 | 1538 | | |
| |||
1518 | 1545 | | |
1519 | 1546 | | |
1520 | 1547 | | |
1521 | | - | |
1522 | 1548 | | |
1523 | | - | |
| 1549 | + | |
1524 | 1550 | | |
1525 | 1551 | | |
1526 | 1552 | | |
| |||
1529 | 1555 | | |
1530 | 1556 | | |
1531 | 1557 | | |
1532 | | - | |
1533 | | - | |
1534 | | - | |
| 1558 | + | |
| 1559 | + | |
1535 | 1560 | | |
1536 | | - | |
1537 | | - | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
1538 | 1568 | | |
1539 | 1569 | | |
1540 | 1570 | | |
1541 | | - | |
1542 | | - | |
1543 | | - | |
1544 | | - | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
1545 | 1575 | | |
1546 | | - | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
1547 | 1584 | | |
1548 | | - | |
| 1585 | + | |
| 1586 | + | |
1549 | 1587 | | |
1550 | 1588 | | |
1551 | 1589 | | |
| |||
1563 | 1601 | | |
1564 | 1602 | | |
1565 | 1603 | | |
1566 | | - | |
| 1604 | + | |
1567 | 1605 | | |
1568 | 1606 | | |
0 commit comments