Release 0.7.0 - #85
Merged
Merged
Conversation
The README status line was missed in the 0.6.0 release; a test now ties it to hndl.__version__. HNDL is a base library, so release notes, SPEC, and test docstrings no longer name a particular downstream consumer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adding equalized= to linear, attention and feed_forward without a version bump made every 0.6.0 plan holding those operators fail to load with E_INTEGRITY and changed their semantic digests. Arg gains since="<release>" for arguments added to a released operator. A resolved node that holds such an argument's default omits it from its args and argument origins; construct() fills it back in. Plans that do not use the new argument keep their 0.6.0 bytes and digests, and 0.6.0 plans load. equalized is declared since="0.7.0". Adds plan fixtures generated by the 0.6.0 release and a regression test that loads, builds and re-resolves them, and documents the rule in docs/ADDING_OPERATORS.md. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Parse configs in process instead of in a subprocess worker The AST allowlist is unchanged and source is still never compiled or executed. hndl/_parser.py replaces the python -I -S worker, its JSON wire protocol, response validation and resource limits. Before ast.parse, a token-stream screen bounds bracket nesting (50) and Python operators or keywords (32; valid configs use none): on CPython 3.11-3.13 a few thousand chained operators otherwise crash ast.parse with SIGSEGV on a small thread stack. Parser MemoryError/RecursionError become E_RESOURCE. Statement handling is one dispatch table on each side: Validator.STATEMENTS in _parser.py and _Interpreter.STATEMENTS in config.py. The concat timing test now counts solver shape updates instead of racing a 5 s subprocess timeout. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Explain plan mismatches and fill values a saved plan determines Revalidation lists every differing port shape and argument per node instead of a one-line E_INTEGRITY. A plan missing only an operator default or an argument bound to a verified port dimension loads completed, with a warning naming the filled values and the new semantic digest. Missing values only a policy or relation search would choose are still refused. Digest mismatches say the file is corrupted or was hand-edited. Raise the default max_state_bytes from 1 GiB to 64 GiB (a 405M-parameter network failed to build by default), drop from_json's 16 MiB cap and its duplicate max_nodes check, and have capture read max_nodes from the shared limits. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Document in-process parsing, plan completion and limit defaults Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adding a constant to the whole relative-position bias table shifts every logit equally, which softmax cancels, so the assertion passed or failed on rounding noise (flaky on CI 3.14). Independent normal perturbations change the output for every input tried (0 of 500 indistinguishable). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#83) * Validate each input signature once instead of every port on every call GraphModule._execute() checked the shape, dtype and device of every port of every node, and replayed the registered-state walk, on every forward call: a fixed ~10 us per node that made a five-node MLP at batch 32 run ~1.7x hand-written PyTorch. The first call for a given input signature (every external input's shape, dtype and device, plus training mode and autocast state) now runs the full checked program and the state check, as before. The signature is then remembered, and later calls with it compare the signature and run the modules back to back from a slot-indexed program. What was validated is invalidated on the events that can break it: - .to()/.cuda()/.double()/... (_apply) drops every signature and forces a full state re-check; - registering a parameter, buffer or submodule on any module in the graph (register_* or attribute assignment) advances a watch generation through torch's global registration hooks, filtered to modules of built graphs, so the next call re-checks state and revalidates every port; a registration during a fast call is checked at the end of that call, as before. Errors are readable: port mismatches name the node, operation and source line and show the contract in HNDL notation ("[B=32, 64]:float32 on cpu") beside the tensor that arrived; torch errors raised inside a node are wrapped as E_RUNTIME with the node's inputs and any state change that explains them; OOM errors pass through unwrapped. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Document validation once per input signature CHANGELOG, README, IMPLEMENTATION and SPEC describe when contracts are checked, what invalidates a validated signature, the new error wording, and the registered-state edits PyTorch runs no hook for. The parity benchmark's docstring now describes the cheap path it actually times. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Keep exceptions raised inside a node as their own type, with a note Wrapping a torch error raised inside a node in HNDLError (a ValueError) broke callers that catch RuntimeError around a forward call. The original exception now propagates unchanged --- type, message and traceback --- and gains one add_note() naming the node, its operation and source line, its inputs against their contract, any registered-state change that explains the failure, the upstream port that drifted after validation, and a hint when the error came from torch.compile. An exception passing out through nested graphs keeps only the innermost node's note. HNDLError (E_RUNTIME) is kept for what HNDL's own checks find: first-call validation and state mismatches. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`for _ in range(N):` with a positive int literal N repeats its body, which may hold any top-level statement including nested loops. The interpreter unrolls it before resolution, so a loop yields the same node IDs, plan, semantic digest and state_dict keys as the statements written out by hand. Explicit names gain the per-level iteration suffix (block3, res1_3), node source metadata records the iterations, and configuration, resolution and runtime errors report them. The multiplied-out node count is checked against max_nodes before the first node is emitted, loops nest at most 8 levels, and every other loop, conditional and comprehension form is rejected by name. The ViT and GPT example networks now use loops for their blocks. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bump version, README status, and rename the Unreleased changelog heading for bounded config loops, once-per-signature contract checks, in-process config parsing, forward-compatible saved plans, and the equalized and coordinate rendering primitives. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 0.7.0: brings develop to master and bumps the version.
Included (all merged into develop):
Arg(since=...))for _ in range(N):loops in configsbroadcast_mul,coordinate_grid,fourier_features,grid_sample__version__by a testLocal: 3645 passed, 80 skipped (
-m "not network and not benchmark"); benchmark suite 28 passed, 1 skipped (inductor toolchain);hndl.docs --checkcurrent. See CHANGELOG.md for details.🤖 Generated with Claude Code