Skip to content

Update links-notation to 0.23.0, use its binary links notation, and fail CI on outdated dependencies unless an open issue holds them back - #107

Merged
konard merged 8 commits into
mainfrom
issue-104-5bb1e3bae0ff
Oct 7, 2026
Merged

konard merged 8 commits into
mainfrom
issue-104-5bb1e3bae0ff

Conversation

@konard

@konard konard commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Closes #104.

Every dependency in the repository is now on its latest release. Both ports take binary links notation from links-notation 0.23.0 instead of carrying their own copy, as the issue comment asked. The Dependencies workflow now checks every manifest git tracks, and it holds a dependency back only while a linked issue is open.

Dependency updates

Package Where Before After
links-notation rust/Cargo.toml, rust/wasm (lock) 0.22.0 0.23.0
Link.Foundation.Links.Notation csharp/…Library.csproj, examples/lino-structure-probe 0.22.0 0.23.0
vite js/package.json 8.3.2 8.3.3
@vitejs/plugin-react js/package.json 6.1.1 6.1.2
bitflags, cfg-if, libc, rustix, syn, thiserror, thiserror-impl, unicode-ident docs/case-studies/issue-100/evidence/external-range/rust/Cargo.lock stale latest compatible

The issue was opened at 0.16.1 → 0.22.0. main reached 0.22.0 in #106, and 0.23.0 has been released since. The case-study lock file was stale because the old check read only the three project directories. Its reproduction still prints Reproduced after the update.

After cargo update, cargo update --dry-run prints no Updating lines in rust/, rust/wasm/ or the case-study crate.

minicov stays at 0.3.8 because wasm-bindgen-test pins it with =0.3.8. cargo update --dry-run reports it as Unchanged, not Updating.

Binary links notation from links-notation (issue comment)

links-notation 0.23.0 ships the binary links notation that #105 introduced here: links_notation::binary in Rust and Link.Foundation.Links.Notation.Binary in C#. Upstream provides everything link-cli needs, so the copies are deleted:

  • Rust: rust/src/protocol/{packet,mapping,format}.rs.
  • C#: Protocol/{ArityRange,LinksPacket,LinoMapping,LinoFormat,SectionPlanner,LinoStreamReader}.cs.

Together that is about 1 700 lines in C# and the matching Rust modules.

link-cli keeps only the transport around the notation. The text framing, protocol detection, LinksServer/LinksClient, RemoteLinks and the store archive (--export-binary/--import-binary) all use the upstream codec.

Evidence that nothing was lost:

  • The shared golden vectors in docs/protocol/binary-links-notation-vectors.txt still pass byte for byte in both ports (84 documents × 12 option sets, plus raw packets).
  • examples/tcp/run-interop.sh, examples/tcp/run-interop.sh csharp and examples/archive/run-interop.sh pass. Rust and C# servers, clients and archives still interoperate.

Breaking changes

These are released as major in both ports.

Before After
Rust codec errors encode_document, decode_document, parse_document, LinksPacket::from_bytes/read_from return ProtocolError They return upstream BinaryError. Every protocol, server, client and archive function still returns ProtocolError, and From<BinaryError> keeps the kind and message
C# codec types Foundation.Data.Doublets.Cli.Protocol.{LinksPacket, ArityRange, DecodeLimits, LinoMapping, LinoFormat, …} Link.Foundation.Links.Notation.Binary.*. LinoStreamReader becomes PacketReader. The protocols still throw only LinoProtocolException, with the codec exception as InnerException
Text size limit DecodeLimits::max_text_bytes / DecodeLimits.MaxTextBytes TextLinoProtocol::max_text_bytes / TextLinoProtocol.MaxTextBytes (64 MiB). Framing text is transport, not notation
Limits for both protocols DecodeLimits in ServerOptions::limits, read_any_document, MessageFormat::protocol (and the C# equivalents) New ProtocolLimits { binary, max_text_bytes } (Default, Unlimited)
Default nesting depth 1024 64, the depth the upstream text parser accepts
String limit none max_string_bytes, 64 MiB of strings a packet may expand to
Encoding unchecked BinaryLinoProtocol checks its limits when writing, so it refuses (Unencodable) a packet its peer would reject
Decoding Stricter upstream validation: link and reference counts are checked before any link is decoded

Release notes: rust/changelog.d/20261007_120000_issue_104_links_notation_binary.md and csharp/.changeset/issue-104-links-notation-binary.md.

Dependency freshness in CI

.github/scripts/check-latest-dependencies.mjs, run by .github/workflows/dependencies.yml on pull requests and daily, now checks the following:

  • Every manifest git tracks (git ls-files): projects, examples and case-study reproductions alike. That covers every Cargo.toml, .csproj, package.json (plus its package-lock.json) and workflow (actions, Node.js/.NET versions, installed tools).

  • Every tracked Cargo.lock: the check fails if cargo update --dry-run prints any Updating line.

  • Blockers: a dependency that cannot be updated yet is held back only by a comment on its manifest line that links the issue explaining the blocker:

    foo = "1.2.0" # held back: https://github.com/owner/repo/issues/12
    <PackageReference Include="Foo" Version="1.2.0" /> <!-- https://github.com/owner/repo/issues/12 -->
    - uses: owner/action@v3 # https://github.com/owner/repo/issues/12

    The check looks the issue up through the GitHub API, using the workflow's GITHUB_TOKEN with issues: read:

    • While the issue is open, the dependency is listed as held back and does not fail the job.
    • Once the issue is closed, the dependency fails the job again, listed under "held back by closed issues".
    • A plain comment, or a link to a pull request instead of an issue, holds nothing back.
  • Dependabot watches the same directories (/rust, /rust/wasm, the case-study crate, /csharp, /examples/lino-structure-probe and both case-study C# projects). A new policy test fails if a directory the check reads is missing from .github/dependabot.yml.

Limitation: JSON has no comments, so an npm dependency cannot be held back this way. An outdated npm dependency always fails the check.

Tests

  • Rust: the codec tests now exercise upstream through link-cli (rust/tests/protocol_packet_tests.rs). The transport tests move to rust/tests/protocol_transport_tests.rs, which adds:
    • error kinds and messages survive the BinaryError → ProtocolError conversion;
    • ProtocolLimits keeps the binary and text budgets separate;
    • a 70-deep document is refused when encoding with the default limits and round-trips with ProtocolLimits::unlimited().
  • C#: the protocol test suites are ported, including the limit tests. That covers an overflow in the text budget with unlimited limits, which is fixed.
  • Dependency check: five new tests:
    • blocker URL extraction;
    • Cargo, csproj and workflow comments hold back only their own line, even with # inside quotes;
    • only an open issue holds an outdated dependency back.
  • Workflow policy: Dependabot covers every directory the check reads.

Local results:

  • cargo fmt --check, and cargo clippy --all-targets --all-features -D warnings (rust/ and rust/wasm/).
  • cargo test: 38 test binaries, all passing.
  • dotnet build: 0 warnings. dotnet test: 447/447.
  • node --test .github/scripts/: 70/70.
  • The dependency check against the live registries: exit 0.
  • The three interop scripts.

Release

The release workflows publish once this is merged:

  • Rust: a major changelog fragment, published to crates.io.
  • C#: a major changeset, published to NuGet.

There is no npm publishing workflow in this repository. The WebAssembly workbench is built by WebAssembly CI and deployed to Pages, so there is nothing to publish to npm.

Changes

  • 51 file(s) modified
  • 841 line(s) added
  • 3246 line(s) removed
  • Files:
    • .github/dependabot.yml
    • .github/scripts/check-latest-dependencies.mjs
    • .github/scripts/check-latest-dependencies.test.mjs
    • .github/scripts/workflow-policy.test.mjs
    • .github/workflows/dependencies.yml
    • csharp/.changeset/issue-104-links-notation-binary.md
    • csharp/Foundation.Data.Doublets.Cli.Library/Foundation.Data.Doublets.Cli.Library.csproj
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/ArityRange.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinksClient.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinksOperation.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinksPacket.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinksServer.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinoFormat.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinoMapping.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinoProtocolException.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinoProtocols.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/LinoStreamReader.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/SectionPlanner.cs
    • csharp/Foundation.Data.Doublets.Cli.Library/Protocol/StoreArchive.cs
    • csharp/Foundation.Data.Doublets.Cli.Tests/Protocol/BinaryLinksNotationTests.cs
    • csharp/Foundation.Data.Doublets.Cli.Tests/Protocol/LinksServerTests.cs
    • csharp/Foundation.Data.Doublets.Cli.Tests/Protocol/LinoProtocolCodecTests.cs
    • csharp/Foundation.Data.Doublets.Cli.Tests/Protocol/RemoteLinksTests.cs
    • csharp/Foundation.Data.Doublets.Cli.Tests/Protocol/StoreArchiveTests.cs
    • csharp/Foundation.Data.Doublets.Cli/Program.cs
    • csharp/README.md
    • docs/ARCHITECTURE.md
    • docs/REQUIREMENTS.md
    • docs/case-studies/issue-100/evidence/external-range/rust/Cargo.lock
    • docs/protocol/binary-links-notation.md
    • examples/lino-structure-probe/LinoStructureProbe.csproj
    • js/package-lock.json
    • js/package.json
    • rust/Cargo.lock
    • rust/Cargo.toml
    • rust/README.md
    • rust/changelog.d/20261007_120000_issue_104_links_notation_binary.md
    • rust/src/protocol/archive.rs
    • rust/src/protocol/client.rs
    • rust/src/protocol/error.rs
    • rust/src/protocol/format.rs
    • rust/src/protocol/links_operations.rs
    • rust/src/protocol/mapping.rs
    • rust/src/protocol/mod.rs
    • rust/src/protocol/packet.rs
    • rust/src/protocol/protocols.rs
    • rust/src/protocol/remote_links.rs
    • rust/src/protocol/server.rs
    • rust/tests/protocol_packet_tests.rs
    • rust/tests/protocol_transport_tests.rs
    • …and 1 more

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

Issue: #104
@konard konard self-assigned this Oct 7, 2026
konard added 6 commits October 7, 2026 00:29
…gin-react to 6.1.2

Rust (rust/ and rust/wasm lock files) and C# (the library and the
lino-structure-probe example) move to links-notation 0.23.0. The only
dependency cargo update leaves behind is minicov 0.3.8, which
wasm-bindgen-test 0.3.79 pins with =0.3.8.
…y links notation

links-notation 0.23.0 ships the binary links notation (packets, the LiNo
mapping and the canonical text form) that link-cli carried as
src/protocol/{packet,mapping,format}.rs. The protocol module now re-exports
links_notation::binary (including the packet module, so
link_cli::protocol::packet keeps working) and keeps only the transport:
framing, detection, server, client and the store archive.

- BinaryError converts into the ProtocolError variant of the same name.
- The text size limit left DecodeLimits upstream; TextLinoProtocol has its own
  max_text_bytes and the new ProtocolLimits pairs it with the binary limits
  for read_any_document, MessageFormat::protocol and ServerOptions.
- BinaryLinoProtocol::encode checks its limits too, as upstream does.
- Transport tests moved to protocol_transport_tests.rs.
…anifest

The dependency check now reads every manifest git tracks (examples and
case-study reproductions included), which found the external-range
reproduction's Cargo.lock eight updates behind; it is updated and still
reproduces. Dependabot watches the same directories, and a policy test keeps
the two in sync.

A dependency that cannot be updated yet is held back by a comment on its
manifest line linking the issue that blocks it (Cargo.toml '#', .csproj
'<!-- -->', workflow '#'). The check reads the issue: open means held back
(listed, not a failure), closed means outdated again.
…f a copy of binary links notation

links-notation 0.23.0 ships the binary links notation that link-cli carried
its own copy of (ArityRange, LinksPacket, LinoMapping, LinoFormat,
SectionPlanner, LinoStreamReader). The copy is removed; the protocols,
server, client and store archive use the upstream codec and PacketReader.

Text framing stays link-cli's own, so its size limit moves from
DecodeLimits.MaxTextBytes to TextLinoProtocol.MaxTextBytes, and the new
ProtocolLimits record carries both budgets. The binary protocol now checks
its limits when writing too, so it refuses what its peer would reject.
Codec errors still surface as LinoProtocolException with the same kind.
Point the protocol spec, architecture notes and READMEs at the upstream
codec instead of the removed copies, document the new defaults (depth 64,
string bytes, text limit on the transport) and the dependency hold-back rule,
and add the Rust changelog fragment listing the breaking changes.
Comment thread .github/scripts/check-latest-dependencies.mjs Fixed
@konard konard changed the title [WIP] Update links-notation to the latest release (0.16.1->0.22.0) and enforce dependency freshness in CI Update links-notation to 0.23.0, use its binary links notation, and fail CI on outdated dependencies unless an open issue holds them back Oct 7, 2026
@konard
konard marked this pull request as ready for review October 7, 2026 00:49
…comment regexp

CodeQL flagged /<!--.*?-->/ (js/bad-tag-filter). Only the text up to the
end of the PackageReference line is searched, so the issue URL is taken
from it directly.
@konard

konard commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Working session summary

I've updated PR #107 and marked it ready for review: #107. All CI workflows pass on the latest commit, 6623b0e.

Dependencies (R1, R2):

  • links-notation and Link.Foundation.Links.Notation go from 0.22.0 to 0.23.0. Main had already reached 0.22.0 in LiNo over TCP: text and binary links notation protocols, remote links store and binary store archive in Rust and C# #106, and 0.23.0 came out since the issue was opened.
  • vite goes to 8.3.3 and @vitejs/plugin-react to 6.1.2.
  • A case-study Cargo.lock was eight packages behind; I updated it. The old check only read three directories, so it never saw that file.
  • cargo update --dry-run now prints no Updating lines in any of the repo's Cargo.lock files.
  • minicov stays at 0.3.8 because wasm-bindgen-test pins that exact version. Cargo lists it as Unchanged, so the check doesn't fail on it.

Binary links notation from the upstream package (issue comment):

  • Both ports now use the codec that ships in links-notation: links_notation::binary in Rust and Link.Foundation.Links.Notation.Binary in C#. I deleted the local copies, about 1,700 lines in C# plus the matching Rust modules. link-cli keeps only the transport around it: text framing, protocol detection, server, client, rem
Rest of the working session summary (2 KB)
ote links and the store archive.
- The shared golden vectors still match byte for byte, and Rust and C# servers, clients and archives still work with each other.
- Breaking changes, listed in the PR and released as major in both ports:
```text
  - The default maximum nesting depth drops from 1024 to 64.
  - The text-message size limit moves to `TextLinoProtocol`.
  - A new `ProtocolLimits` type carries both the binary and the text limits.
  - The encoder now refuses packets the other side would reject.
  - In Rust, the re-exported encode/decode functions return the upstream `BinaryError`.
  - In C#, the codec types move to the upstream namespace.
```

**CI freshness check (R3):**
- The check now reads every manifest git tracks, including examples and case studies, plus every `Cargo.lock`. Dependabot watches the same directories, and a new test fails if the two lists drift apart.
- To hold a dependency back, put a link to the blocking issue in a comment on its manifest line, for example `foo = "1.2.0" # https://github.com/owner/repo/issues/12`. While that issue is open the dependency is listed but doesn't fail the job; once it closes, it fails again. If the issue can't be looked up, the check fails.
- npm dependencies can't be held back this way, because `package.json` has no comments.
- After I marked the PR ready, the repo's security scanner (CodeQL) flagged one regex in the check script. I replaced it, and the alert no longer shows as open on the PR.

**Release (R4):** crates.io and NuGet publish when the PR is merged; I added a major release note for each. This repo has no npm publishing workflow, so there was nothing to release to npm.

Locally, the Rust tests, clippy, the 447 C# tests, the 70 script tests and the three Rust–C# compatibility scripts all pass. I couldn't run the WebAssembly browser tests locally because `wasm-pack` isn't installed; they pass in CI. I also removed the placeholder `.gitkeep` that was committed to open the PR.

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

@konard

konard commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

🤖 Solution Draft Log

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

💰 Cost: $8.474493

📊 Context and tokens usage:

Claude Opus 5.5: (3 sub-sessions)

  1. 115.6K / 1M (12%) input tokens, 20.5K / 128K (16%) output tokens
  2. 117.1K / 1M (12%) input tokens, 32.4K / 128K (25%) output tokens
  3. 111.4K / 1M (11%) input tokens, 26.7K / 128K (21%) output tokens

Total: (14.6K new + 448.4K cache writes + 13.3M cache reads) input tokens, 128.8K output tokens, $8.474493 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus (claude-opus-5)
  • Thinking level: high (~23999 tokens)
  • Model: Claude Opus 5.5 (claude-opus-5-5)

📎 Log file uploaded as Gist (5406KB)


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

@konard
konard merged commit 458c223 into main Oct 7, 2026
37 checks passed
@konard

konard commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

🎉 Auto-merged

This pull request has been automatically merged by hive-mind.

  • All CI checks have passed

Auto-merged by hive-mind with --auto-merge flag

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.

Update links-notation to the latest release (0.16.1->0.22.0) and enforce dependency freshness in CI

2 participants