Commit graph

11 commits

Author SHA1 Message Date
Claude
942e771319
fix(deep-learning-book): reject overlapping capacity regime bands
Ninth review on PR #994 found that --underparameterized-max and
--overparameterized-min, added two commits earlier, were never checked against each
other. Reproduced, and the consequence is sharper than a silent misclassification:
with --underparameterized-max 20 --overparameterized-min 5 and a ratio of 10, the
tool reported a model ten times overparameterized as "underparameterized" and exited
0. That verdict ranks "shrink the model" FIRST rather than last, inverting the exact
double-descent correction this tool exists to apply.

Added an argparse guard rejecting under-max >= over-min with a message naming both
values (exit 2, the documented usage-error code). Equal bands are rejected too,
since they leave the near-interpolation regime unreachable.

Verified: inverted and equal bands both exit 2; a valid override still moves the
regime (--overparameterized-min 500 gives near-interpolation); defaults unchanged at
overparameterized / OVERFIT / 240.0 with smaller-model last; the other exit codes
still 1 for an action, 0 for balanced, 4 for a leaky split.

Worth noting for the two flags' own history: they were added to close a consistency
nit, and introduced this defect in doing so. A new option is new surface, and its
interaction with existing options is part of it.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 20:06:05 +00:00
Claude
35f5b3b6d3
fix(deep-learning-book): narrow plural matching to -s, ending a false-refusal collision
Eighth review on PR #994 found that _matches()'s (?:s|es)? suffix reintroduced a
smaller version of the substring bug it was written to fix: "rag" + "es" matches the
standalone word "rages", so --goal "why overfitting still rages in large models"
exited 3, refused as out-of-scope retrieval-augmented-generation work.

Reproduced before fixing, then checked whether the -es branch earns its keep at all.
It does not: every keyword in the table ending in s, x, z, ch or sh is already plural
or non-count (basics, features, foundations, prerequisites, statistics, speech,
mlops, fairness, mathematics, time series), so no token needs -es appended. Narrowed
the auto-plural to plain -s and documented that irregular forms belong in
SURFACE_FORMS, spelled out, the way fine-tuning, prompting and agentic already are.

Verified: "rages" no longer matches while standalone "rag" still does; transformers,
embeddings, autoencoders and agentic still match; the goal above is now correctly
unroutable (exit 4) rather than confidently misrouted. RLHF, LoRA fine-tuning, RAG
pipelines and prompt/agent goals still exit 3; sequence, vision, generative and
practitioner routing unchanged.

That makes two rounds of false out-of-scope refusals from the same root cause —
approximate string matching standing in for a word list. The refusal path is the
part of this tool users are least able to second-guess, so it is the wrong place to
approximate.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:56:56 +00:00
Claude
5f5d84f469
feat(deep-learning-book): expose capacity_planner's regime bands as CLI flags
Seventh review on PR #994 noted that capacity_planner.py exposes --overfit-rel-gap
but hardcodes the two params-per-example regime bands, unlike its sibling scripts
where every threshold is overridable. The reviewer called it fine as shipped; the
inconsistency is small enough to close rather than carry.

The band matters more than a typical default: it decides whether "shrink the model"
is ranked last, which is the double-descent correction this tool exists to apply.
The interpolation point depends on task, architecture and label noise, so a user
whose model sits elsewhere had no way to say so.

Adds --underparameterized-max and --overparameterized-min, threaded through plan()
and classify_regime() as keyword arguments defaulting to the existing constants, and
reports all three thresholds in --output json the way training_diagnostics.py already
does. The help text repeats that these are heuristic bands, not a threshold theorem.

Defaults preserve behaviour exactly: the --sample fixture still reports
overparameterized / OVERFIT / 240.0 params-per-example with smaller-model ranked
last, identical to before the change. An override demonstrably moves the regime
(--overparameterized-min 500 reclassifies the same model as near-interpolation).
Exit codes unchanged: 1 for an action, 0 for balanced, 4 for a leaky split.

Not fixed here: CHANGELOG.md's duplicate [Unreleased] header, also noted in that
review. Verified pre-existing rather than introduced by this branch — the count is
2 at the merge-base with main and 2 at HEAD. Left for a separate changelog cleanup.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:49:51 +00:00
Claude
98019ac169
fix(deep-learning-book): make --include-intro actually do something
Sixth review on PR #994 noted that --include-intro appeared to have an observable
effect only on the complete lane. Checked it, and it was worse than reported: the
flag was inert on every lane, complete included.

Two reasons compounded. ch01 is not a prerequisite of any chapter, so it never
arrived through prerequisite closure; and the only lane that targets it, complete,
skipped the ch01 filter entirely. The filter therefore removed a chapter that was
never present, and the flag that controlled it could not change any output.

This also means my own verification of the parameter rename in c75500f was
inconclusive: it compared the complete lane with the flag against the vision lane
without it, and those differ for reasons unrelated to the flag. A test that cannot
fail proves nothing.

Inverted the logic so the flag adds ch01 rather than un-removing it, which gives it
a real effect on every lane while leaving complete unchanged (ch01 is already among
its targets). Help text now states what it does and that no lane pulls ch01 in on
its own.

Verified per lane: complete unchanged; vision, generative and foundations each gain
ch01 with the flag and are untouched without it; ch01 sorts first and never precedes
a chapter it would violate. Routing and both refusal paths are unchanged — sequence,
vision, generative and practitioner all route as before, out-of-scope still exits 3,
unroutable still exits 4.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:44:24 +00:00
Claude
8f833d22dd
fix(deep-learning-book): validate embedding seq_len like every other numeric field
Fifth review on PR #994 found the one numeric spec field I missed when adding typed
validation in the previous commit: embedding's seq_len still went through a bare
int(), so it bypassed the checks every sibling field had just been given.

Both failure modes reproduced before fixing:
  seq_len "ten"  -> uncaught ValueError, traceback, exit 1 (documented: exit 4)
  seq_len 0      -> no error at all; reported a plausible "0x8" layer with zero
                    activation elements and exited 0, presenting a degenerate model
                    as a valid one

Routed through _positive_int with the existing default (the incoming sequence
length, or 1), so both now exit 4 naming the layer and field. Verified the default
fallback still resolves to the input shape (16x8) and an explicit valid seq_len is
still honoured (32x8).

Swept the file afterwards rather than fixing only the reported instance: all 13
numeric spec fields now go through _positive_int, and no raw int() on a spec field
remains. The reference specs are unchanged — convnet 545,098 parameters, transformer
asset 7,087,872.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:38:58 +00:00
Claude
e923237360
fix(deep-learning-book): word-boundary keyword matching and typed input validation
Fourth review on PR #994 raised two findings against this plugin's scripts. Both
reproduced before fixing; the review's other findings are against marketing/linkedin,
which this branch carries from main but does not touch (see the PR comment).

1. reading_path_planner.py matched keywords by bare substring, so "rag" matched
   inside "storage", "lora" inside "exploratory", "conv" inside "converge" and
   "text" inside "context". Confirmed: --goal "train models for image storage and
   retrieval" exited 3, confidently refused as out-of-scope RAG work, and
   "an exploratory look at optimization" exited 3 citing LoRA. A tool whose stated
   design is to refuse rather than guess was guessing, and doing it with certainty.

   Matching is now word-boundary anchored with an optional plural, plus an explicit
   surface-form table for the few tokens whose inflections a word-boundary match
   would otherwise miss (fine-tuning, prompting, agentic). Verified: both goals above
   now route correctly (exit 0 / the optimization lane), "converge" reaches the
   optimization lane rather than vision, and the real refusals still refuse — RLHF,
   LoRA fine-tuning, RAG pipelines and prompt/agent goals all still exit 3.

2. model_arithmetic.py documented exit 4 for a spec it cannot parse but only caught
   SpecError and ShapeError, so malformed input escaped as a traceback with exit 1.
   Confirmed across five cases: a non-dict top-level JSON, a non-dict layer entry,
   stride 0, groups 0, and a non-numeric filters value. Numeric fields now go through
   a checked accessor that rejects non-integer and non-positive values, the input
   layer's shape is validated, and the top-level spec and every layer entry are
   type-checked. All five now exit 4 with a message naming the layer and field.

Regression battery over eight goals routes exactly as before; the convnet sample
still reports 545,098 parameters and the transformer asset 7,087,872.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:33:25 +00:00
Claude
eeb3cb9ad6
fix(deep-learning-book): position-wise linear, correcting a 512x parameter error in the example asset
Third review on PR #994 found a real bug in the flagship example asset. Verified
before fixing: assets/example_layer_spec.json reported 1,207,962,624 parameters
for the feedforward up-projection instead of 2,362,368 — off by exactly 512x, the
sequence length — putting the block's total at ~1.21B instead of ~7.09M.

Root cause was in the tool, not only the asset. model_arithmetic.py's mha layer
emits (seq, d_model) but linear refused any 2-D input, so the only way to attach a
feedforward block was to flatten first. Flattening collapses all 512 positions into
one 393,216-element vector, which models a dense layer over the whole sequence — a
different layer, with seq_len times the parameters. A transformer FFN was therefore
not expressible at all, and the shipped example walked straight into it. Clean exit
is not correct numbers, which is why --sample exit-code testing never caught it.

Fixed the cause: linear on a 2-D (seq, features) input is now position-wise — one
weight matrix shared across positions, parameters independent of sequence length,
compute linear in it. Documented in the module docstring; the 3-D path still refuses
with an updated message pointing at flatten. Removed the flatten from the example
asset and recorded in its comment why it must not come back.

Verified: the corrected block reports 7,087,872 parameters, matching a hand-check of
2*(2*768) + (4*768^2+4*768) + (768*3072+3072) + (3072*768+768) exactly, and the size
of a BERT-base encoder layer. The convnet --sample is unchanged at 545,098, and
linear on 3-D input still exits 5.

Also adds the missing CHANGELOG.md [Unreleased] entry, which the same review noted:
CLAUDE.md, README.md and marketplace.json carried the new skill and its counter
deltas but CHANGELOG.md did not.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:17:50 +00:00
Claude
1366714fdc
fix(deep-learning-book): break lane-scoring ties by keyword specificity
Second independent review on PR #994 observed that reading_path_planner.py's
score_lanes() broke equal-hit ties alphabetically by lane key, so SKILL.md's own
documented example "train a transformer" resolved to the practitioner lane rather
than sequence.

Reproduced: the goal hits practitioner on "train" and sequence on "transformer",
one keyword each, and alphabetical ordering picked practitioner.

Fixed the cause rather than the example. Ties now break on keyword specificity —
the lane whose longest matched keyword is longest wins — because an equal hit
count between a generic term and a discriminating one should not be settled by
luck. Lane key remains the final tie-break so ordering stays deterministic.

Regression battery over eight goals: "train a transformer" now routes to sequence;
vision, generative, foundations, practitioner, complete, representation and
sequence goals all route exactly as before. Refusal paths unchanged (out-of-scope
exit 3, unroutable exit 4, sample exit 0).

Gates green after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, book_skill_validator,
and --help + --sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:07:14 +00:00
Claude
c75500f804
fix(deep-learning-book): address review nits — internal naming and SAME-padding disclosure
Two small findings from the automated review on PR #994, both verified against the
source before fixing.

1. reading_path_planner.py: the plan() parameter was named include_optional while
   the CLI flag and call site both use include_intro, and it only ever gates ch01.
   Renamed the parameter and its use for consistency. Behavior unchanged, confirmed
   both ways: --include-intro keeps ch01 first, the default drops it.

2. model_arithmetic.py: conv2d "same" padding computes ceil(H / stride), which is
   the TensorFlow/Keras SAME convention, and the tool did not disclose which
   framework it matches. Documented it in the module docstring — including that
   PyTorch's padding='same' is symmetric-only and rejects a stride other than 1, so
   a strided PyTorch layer will not match, with "valid" named as the exact-case
   workaround — plus a pointer comment at the computation itself. No arithmetic
   change; the sample stack reports identical parameters and FLOPs.

The reviewer's third point was that it could not execute the gates in a sandboxed
environment. No code change: those gates were run locally and are green.

Verified after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, the book-skill
validator, and --sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:02:25 +00:00
Claude
cf572c83b6
fix(deep-learning-book): qualify reference and asset links from the plugin root
CI gate G1 (scripts/check_paths.py) failed on the previous commit: the agent and
command files live at engineering/deep-learning-book/{agents,commands}/, so bare
references/*.md and assets/*.md tokens resolved against neither the plugin root,
the file's own directory, nor the repo root — the three bases the linter accepts.
The files they point at live under skills/deep-learning-book/.

Prefix the nine offending links with skills/deep-learning-book/ so they resolve
from the plugin root. Content unchanged otherwise; SKILL.md's own relative links
were already correct and were not touched.

Reproduced the failure locally (9 unresolvable references across 4 files), then
confirmed the same check clean, plus every other blocking gate: compileall,
check_plugin_json, check_skill_names, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:00:23 +00:00
Claude
1a8d782872
feat(engineering): add deep-learning-book — companion skill for the free Goodfellow/Bengio/Courville textbook
Requested as "convert deeplearningbook.org into a skill". Built as a companion
rather than a compilation, because the repo's own rights gate forbids the latter
for a public plugin.

Why not book-to-skill: its emitter refuses a shareable package without
public-domain / open-license / internal-docs / author-permission, none of which
applies to an MIT Press title whose site states its HTML-only format exists as a
friction against copying under the authors' contract. Its rights reference lists
publishing a compiled skill of a copyrighted book to a public marketplace under
"Do not", and its hard rule 1 forbids scraping a book from the web, so the
pipeline could not have run against a URL either.

What shipped instead: the compiled-skill shape (master SKILL.md ~2.0k tokens with
chapter and topic indexes, chapters/ch01..ch20, glossary, patterns, cheatsheet)
filled with original synthesis and linking to the official free chapters. No
passages, figures, or per-paragraph paraphrase. Passes book-to-skill's own
book_skill_validator.py clean, with every file inside token_budget_estimator's caps.

The differentiator is the delta layer. A compilation freezes a source at its
publication date; this one dates it. Every chapter carries "What changed after
2016", and references/book_to_2026_delta.md gives five corrections with primary
citations and per-claim confidence levels: double descent qualifying Ch 5's
U-curve, AdamW splitting weight decay from L2, transformers displacing Ch 10's
recurrence, diffusion growing out of Ch 18's score matching, and self-supervised
learning vindicating Ch 15 while replacing its methods. Two claims are marked
contested rather than propagated, two named as folklore.

Four stdlib-only tools, each with a real refusal:
- reading_path_planner.py — prerequisite closure over the book's actual dependency
  graph; exit 3 for a goal the book does not cover, exit 4 with forcing questions
- training_diagnostics.py — Ch 11's rules in priority order, so a NaN is never
  reported as overfitting; exit 4 rather than diagnosing with no instruments
- capacity_planner.py — regularization ladder in cost order, "shrink the model"
  ranked last in the overparameterized regime; exit 4 on a val-below-train split
- model_arithmetic.py — params/FLOPs/activation memory for conv, linear, MHA and
  LSTM/GRU stacks; exit 5 naming the layer whose shapes do not connect

Also: 4 references citing 7-8 sources each, 3 assets, cs-deep-learning-tutor
agent, /cs:deep-learning + /cs:dl-reading-path + /cs:dl-diagnose.

Counters: skills 386 to 387, tools 723 to 727, refs 838 to 842, agents 116 to 117,
commands 146 to 149, plugins 97 to 98 (verified by derive_counters.py --check).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 18:56:57 +00:00