Skip to content

docs(readme): document built-in references for cycles, drop legacy (ref X)#28

Merged
konard merged 2 commits intomainfrom
issue-27-eb86cc75f92a
May 3, 2026
Merged

docs(readme): document built-in references for cycles, drop legacy (ref X)#28
konard merged 2 commits intomainfrom
issue-27-eb86cc75f92a

Conversation

@konard
Copy link
Copy Markdown
Member

@konard konard commented May 3, 2026

Summary

Closes #27.

The encoder in both JS and Python already emits circular references using
the built-in links-notation self-reference form
(self-ref: first-ref second-ref ...) rather than a (ref obj_N) marker.
For example, { self: obj } encodes as
(obj_0: object ((str c2VsZg==) obj_0)) (JS) or
(obj_0: dict ((str c2VsZg==) obj_0)) (Python). Decoders in both languages
already reject (ref X) as an unknown type marker.

The per-language READMEs still documented the legacy (ref obj_0) syntax
in their "How It Works" sections, which contradicted both the emitted
format and the main README.md (which already documented the new style).
This PR makes the per-language docs match reality and adds regression
tests that lock in the format invariant.

Changes

  • js/README.md, python/README.md: replace the stale
    (ref obj_0) / (list obj_0 ...) description with the actual
    (obj_0: dict ...) / (obj_0: list ...) self-reference form, and
    link to All our packages should be published, and if that didn't happen, we need clear visible feedback as badges for each package #27 for context.
  • js/tests/test_circular_references.test.js,
    python/tests/test_circular_references.py: two new regression tests
    per language asserting:
    1. cycles encode as bare obj_N links inside an (obj_N: type ...)
      self-reference definition (the encoded string contains no
      (ref substring);
    2. the legacy (ref X) form fails to decode with
      Unknown type marker: ref, so it cannot silently masquerade as a
      real type marker.
  • js/.changeset/issue-27-builtin-references.md: patch changeset
    (docs + tests, no source changes).
  • python/changelog.d/20260503_issue_27_builtin_references.md:
    matching scriv fragment.
  • .gitkeep: removed (placeholder from PR-init now superseded by real
    changes).

Test plan

  • cd js && npm test — 146 passed (was 144; +2 new regression tests)
  • cd js && npm run lint && npm run format:check — clean (only
    pre-existing complexity warnings in src/codec.js and
    src/format.js)
  • cd python && pytest tests/ --no-cov — 73 passed (was 71;
    +2 new regression tests)
  • cd python && ruff check src tests && ruff format --check src tests && mypy src — all clean
  • Manually verified encoder output for self-references, mutual
    references, and shared sub-objects in both JS and Python — all
    use obj_N direct references, none use (ref ...).

Issue reproduction

The example from the issue:

const obj = { self: obj, other: { '1': 1, '2': 2 } };

now produces (and is documented to produce):

(obj_0: object ((str c2VsZg==) obj_0) ((str b3RoZXI=) (object ((str MQ==) (int 1)) ((str Mg==) (int 2)))))

— exactly the built-in self-reference form requested in the issue, with
no ref keyword.

Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: #27
@konard konard self-assigned this May 3, 2026
…ef X)

The encoder in both JS and Python already emits cycles using the built-in
links-notation `(self-ref: first-ref second-ref ...)` form — a self-
referencing dict is `(obj_0: dict ((str c2VsZg==) obj_0))`, with bare
`obj_N` back-references rather than a `(ref obj_N)` marker. Decoders in
both languages reject `(ref X)` as an unknown type marker.

The per-language READMEs (`js/README.md`, `python/README.md`) still
documented the legacy `(ref obj_0)` syntax in their "How It Works" sections,
which contradicted the actual emitted format and the main README. This
commit makes the per-language docs match reality and links to issue #27.

Regression tests in both languages now assert two invariants:
1. cycles encode as bare `obj_N` links inside an `(obj_N: type ...)`
   self-reference definition (no `(ref ` substring in the output);
2. the legacy `(ref X)` form must fail to decode with "Unknown type marker:
   ref", so it cannot silently masquerade as a real type.

Closes #27.
@konard konard changed the title [WIP] All our packages should be published, and if that didn't happen, we need clear visible feedback as badges for each package docs(readme): document built-in references for cycles, drop legacy (ref X) May 3, 2026
@konard konard marked this pull request as ready for review May 3, 2026 13:10
@konard
Copy link
Copy Markdown
Member Author

konard commented May 3, 2026

Working session summary

Done. The investigation revealed the encoders in JS and Python already produce the built-in self-reference form requested in issue #27(obj_0: dict ((str c2VsZg==) obj_0)) rather than (ref obj_0). The bug was that js/README.md and python/README.md still documented the legacy (ref obj_0) syntax, contradicting both the actual emitted format and the (already-correct) main README.md.

PR #28 is updated and marked ready for review: #28

Changes:

  • Per-language READMEs (js/README.md, python/README.md) now document the actual (obj_N: type ...) self-reference form with bare obj_N back-references.
  • Two regression tests per language assert (1) cycles encode without any (ref substring and (2) the legacy (ref X) form is rejected with Unknown type marker: ref.
  • Patch changeset for JS and matching scriv fragment for Python.
  • Removed leftover .gitkeep placeholder.

All checks pass: JS 146 tests, Python 73 tests, ruff/mypy/prettier clean.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Member Author

konard commented May 3, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $5.112691

📊 Context and tokens usage:

Claude Opus 4.7: (2 sub-sessions)

  1. 114.7K / 1M (11%) input tokens, 7.7K / 128K (6%) output tokens
  2. 108.4K / 1M (11%) input tokens, 21.3K / 128K (17%) output tokens

Total: (21.1K new + 204.7K cache writes + 5.7M cache reads) input tokens, 36.1K output tokens, $5.112691 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Model: Claude Opus 4.7 (claude-opus-4-7)

📎 Log file uploaded as Gist (2484KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Member Author

konard commented May 3, 2026

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@konard konard merged commit 3806da8 into main May 3, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

All our packages should be published, and if that didn't happen, we need clear visible feedback as badges for each package

1 participant