Skip to content

Commit 9695cb4

Browse files
committed
docs: update max_depth guidance and 1.4.1-wip changelog
Updates README/docs and internal guidance files to reflect max_depth semantics and adds 1.4.1-wip changelog entries for iterative hardening/performance work.
1 parent 2e4f3bc commit 9695cb4

5 files changed

Lines changed: 16 additions & 7 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Concise, project-specific guidance for AI coding agents working on this repo. Fo
1313
## 2. Key Behavioral Invariants
1414
- DO NOT mutate caller inputs—copy/normalize (shallow copy for mappings; deep-copy only when a callable filter may mutate; index-projection for sequences) before traversal.
1515
- Cycle detection in `encode._encode` must raise `ValueError("Circular reference detected")`—preserve side-channel algorithm.
16-
- Depth, list, and parameter limits are security/safety features: respect `depth`, `max_depth`, `list_limit`, `parameter_limit`, and `strict_depth` / `raise_on_limit_exceeded` exactly as tests assert. `max_depth` is capped to the current recursion limit.
16+
- Depth, list, and parameter limits are security/safety features: respect `depth`, `max_depth`, `list_limit`, `parameter_limit`, and `strict_depth` / `raise_on_limit_exceeded` exactly as tests assert. For encoding, `max_depth=None` means unbounded traversal (`sys.maxsize`); explicit values are enforced directly without recursion-limit capping, and exceeding an explicit `max_depth` raises `ValueError("Maximum encoding depth exceeded")`.
1717
- Duplicate key handling delegated to `Duplicates` enum: COMBINE → list accumulation; FIRST/LAST semantics enforced during merge.
1818
- List format semantics (`ListFormat` enum) change how prefixes are generated; COMMA + `comma_round_trip=True` must emit single-element marker for round-trip fidelity.
1919
- Charset sentinel logic: when `charset_sentinel=True`, prepend sentinel *before* payload; obey override rules when both charset and sentinel present.

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
- Preserve or raise the coverage level tracked in `coverage.xml`; CI flags regressions.
2323
- Name tests `test_{feature}_{scenario}` and refresh fixtures whenever query-string semantics shift.
2424
- When touching cross-language behavior, run `tests/comparison/compare_outputs.sh` to confirm parity with the Node reference.
25-
- For encoding depth changes, cover `EncodeOptions.max_depth` (positive int/None) and cap-to-recursion behavior.
25+
- For encoding depth changes, cover `EncodeOptions.max_depth` (positive int/None): `None` means unbounded traversal
26+
(`sys.maxsize`) and explicit values are enforced directly (no recursion-limit capping).
2627

2728
## Commit & Pull Request Guidelines
2829
- Follow the emoji-prefixed summaries visible in `git log` (e.g., `:arrow_up: Bump actions/setup-python from 5 to 6 (#26)`), using the imperative mood.

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 1.4.1-wip
2+
3+
* [FIX] harden encoder traversal to an iterative implementation to avoid recursion-based crashes on very deep nested input
4+
* [FIX] harden decode merge path (`Utils.merge`) with iterative traversal to prevent `RecursionError` on deep conflicting merges
5+
* [FIX] update `EncodeOptions.max_depth` semantics: `None` is unbounded by this option; explicit limits are enforced directly
6+
* [FIX] preserve legacy map-merge key collision semantics for mixed key types (`'1'` vs `1`) in iterative merge
7+
* [CHORE] optimize deep encode performance by replacing per-frame side-channel chain scans with O(1) ancestry cycle state lookups
8+
* [CHORE] add deep stack-safety regressions (depth 12_000) and cycle-state compatibility tests
9+
* [CHORE] update encoding depth documentation
10+
111
## 1.4.0
212

313
* [FEAT] add `EncodeOptions.max_depth` to cap encoding traversal depth (capped to the current recursion limit)

README.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,7 @@ Maximum encoding depth
463463

464464
You can cap how deep the encoder will traverse by setting the
465465
`max_depth <https://techouse.github.io/qs_codec/qs_codec.models.html#qs_codec.models.encode_options.EncodeOptions.max_depth>`__
466-
option. If unset, the encoder derives a safe limit from the interpreter recursion limit; when set, the effective
467-
limit is capped to the current recursion limit to avoid ``RecursionError``.
466+
option. If unset, traversal is unbounded by this option. When set, the provided limit is enforced directly.
468467

469468
.. code:: python
470469

docs/README.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,8 @@ Maximum encoding depth
413413
^^^^^^^^^^^^^^^^^^^^^^
414414

415415
You can cap how deep the encoder will traverse by setting the
416-
:py:attr:`max_depth <qs_codec.models.encode_options.EncodeOptions.max_depth>` option. If unset, the encoder derives a
417-
safe limit from the interpreter recursion limit; when set, the effective limit is capped to the current recursion
418-
limit to avoid ``RecursionError``.
416+
:py:attr:`max_depth <qs_codec.models.encode_options.EncodeOptions.max_depth>` option.
417+
If unset, traversal is unbounded by this option. When set, the provided limit is enforced directly.
419418

420419
.. code:: python
421420

0 commit comments

Comments
 (0)