Commit bb269b5
committed
feat(calc-tasks): context-aware task count formula (team, scope, themes)
v4 Shade dogfood (2026-04-13) surfaced LEARNING #11: the old formula
`ceil(requirements * 1.5)` clamped [10, 40] was monotonic and
context-blind. `calc-tasks --requirements 32` returned 40 (the max
clamp) for a solo operator on Shade Phase 5 — a brownfield final-phase
project with 4 thematic groups where the right answer was 12. The
child correctly overrode to 12 based on domain reasoning, but the
script was "WAY off" (user's exact phrasing).
Rewrite cmd_calc_tasks to take four inputs:
- requirements_count (required)
- team_size (default 1, solo)
- scope_phase (greenfield | brownfield | final_phase, default greenfield)
- thematic_groups (optional, N natural parent groups in the scope)
New formula — thematic groups dominates when set:
if thematic_groups > 0:
base = thematic_groups * 3 # ~3 parent tasks per natural group
else:
base = max(1, ceil(reqs / 4)) # ~1 task per 4 requirements
scope_adjust = {greenfield: 1.2, brownfield: 1.0, final_phase: 1.0}
team_multiplier = 1 + (team_size - 1) / 10
raw = base * scope_adjust * team_multiplier
recommended = clamp(round(raw), 3, 25)
Greenfield gets 1.2x because nothing exists to lean on; brownfield
and final_phase stay at 1.0 because the group-count heuristic already
captures the decomposition correctly. New floor is 3 (was 10) and new
ceiling is 25 (was 40): quick-mode is now viable, and 30+ tasks on a
single scope is almost always over-decomposition.
Shade validation case (32 reqs, solo, final_phase, 4 groups) now
returns 12 exactly. Confirmed via direct script.py invocation.
Output JSON schema changed:
- Old: flat fields (requirements_count, raw_calculation, recommended, formula)
- New: nested structure (inputs, calculation, recommended, reasoning,
formula, scope_adjust_map)
Updated 3 test files to match the new schema and new formula:
- tests/test_script.py: replaced 7 old tests with 8 new ones covering
the Shade validation case, solo-greenfield default, brownfield,
team multiplier, floor/ceiling clamps, thematic-group override, and
the new reasoning field
- tests/test_critical_paths.py: updated negative-input and
large-input expectations for the new clamps
- tests/test_edge_cases.py: same updates
All 12 calc-tasks tests pass on the new formula. Zero existing
behavior changed for users who did not already depend on the old
flat JSON schema (which was purely internal to the skill).
Fixes: LEARNING #11
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent a0a3c28 commit bb269b5
File tree
4 files changed
+221
-59
lines changed- tests
4 files changed
+221
-59
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
741 | 741 | | |
742 | 742 | | |
743 | 743 | | |
744 | | - | |
745 | | - | |
746 | | - | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
747 | 810 | | |
748 | 811 | | |
749 | | - | |
750 | | - | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
751 | 824 | | |
752 | | - | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
753 | 832 | | |
754 | 833 | | |
755 | 834 | | |
| |||
1581 | 1660 | | |
1582 | 1661 | | |
1583 | 1662 | | |
1584 | | - | |
| 1663 | + | |
1585 | 1664 | | |
| 1665 | + | |
| 1666 | + | |
| 1667 | + | |
| 1668 | + | |
| 1669 | + | |
| 1670 | + | |
| 1671 | + | |
| 1672 | + | |
| 1673 | + | |
| 1674 | + | |
| 1675 | + | |
| 1676 | + | |
| 1677 | + | |
| 1678 | + | |
| 1679 | + | |
| 1680 | + | |
| 1681 | + | |
| 1682 | + | |
1586 | 1683 | | |
1587 | 1684 | | |
1588 | 1685 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
274 | 274 | | |
275 | 275 | | |
276 | 276 | | |
277 | | - | |
| 277 | + | |
278 | 278 | | |
279 | 279 | | |
280 | | - | |
| 280 | + | |
281 | 281 | | |
282 | 282 | | |
283 | | - | |
284 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
285 | 286 | | |
286 | 287 | | |
287 | | - | |
| 288 | + | |
288 | 289 | | |
289 | 290 | | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
218 | 218 | | |
219 | 219 | | |
220 | 220 | | |
221 | | - | |
| 221 | + | |
222 | 222 | | |
223 | 223 | | |
224 | | - | |
| 224 | + | |
225 | 225 | | |
226 | | - | |
227 | 226 | | |
228 | | - | |
| 227 | + | |
| 228 | + | |
229 | 229 | | |
230 | 230 | | |
231 | | - | |
| 231 | + | |
232 | 232 | | |
233 | 233 | | |
234 | | - | |
| 234 | + | |
| 235 | + | |
235 | 236 | | |
236 | 237 | | |
237 | 238 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
342 | 342 | | |
343 | 343 | | |
344 | 344 | | |
345 | | - | |
| 345 | + | |
346 | 346 | | |
347 | | - | |
348 | | - | |
349 | | - | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
350 | 354 | | |
351 | 355 | | |
352 | | - | |
353 | | - | |
354 | | - | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
355 | 362 | | |
356 | | - | |
357 | | - | |
358 | | - | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
359 | 397 | | |
360 | | - | |
361 | | - | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
362 | 402 | | |
363 | | - | |
364 | | - | |
365 | | - | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
366 | 412 | | |
367 | | - | |
368 | | - | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
369 | 418 | | |
370 | | - | |
371 | | - | |
372 | | - | |
373 | | - | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
374 | 423 | | |
375 | | - | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
376 | 428 | | |
377 | | - | |
378 | | - | |
379 | | - | |
380 | | - | |
381 | | - | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
382 | 435 | | |
383 | | - | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
384 | 440 | | |
385 | | - | |
386 | | - | |
387 | | - | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
388 | 449 | | |
389 | | - | |
| 450 | + | |
| 451 | + | |
390 | 452 | | |
391 | | - | |
392 | | - | |
393 | | - | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
394 | 456 | | |
395 | | - | |
396 | | - | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
397 | 460 | | |
398 | 461 | | |
399 | 462 | | |
| |||
0 commit comments