Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b78e47f
Fix RX-path crash on crafted gossip names; guard CAN reader ingest
pavel-kirienko Jul 18, 2026
ac84d05
Wrap the subject-ID hash+evictions² sum mod 2^64 to match the reference
pavel-kirienko Jul 18, 2026
d2102a6
Make the UDP fragment-tree right-neighbor lookup inclusive per the re…
pavel-kirienko Jul 18, 2026
feef062
Seed the UDP transfer-ID history with the unmasked 64-bit sentinel
pavel-kirienko Jul 18, 2026
43e57de
Destroy idle slot-free CAN RX sessions at the transfer-ID timeout
pavel-kirienko Jul 18, 2026
af3af85
Fix CAN FD framing: the frame format follows the interface, never BRS
pavel-kirienko Jul 18, 2026
d5e3e5f
Classify wildcards by whole segment, not by character containment
pavel-kirienko Jul 18, 2026
03f278e
Allow CAN unicast to remote node-ID 0
pavel-kirienko Jul 18, 2026
deee162
Drop SLCAN standard-ID data frames instead of aliasing them as extended
pavel-kirienko Jul 18, 2026
fa40030
Restrict Linux multicast RX sockets to their own group membership
pavel-kirienko Jul 18, 2026
7aaae71
Validate subject_id_modulus with the reference predicate
pavel-kirienko Jul 18, 2026
bbab7ab
Wake a parked SocketCAN reader on close/fail
pavel-kirienko Jul 18, 2026
a5c4ef1
Send UDP redundant interfaces concurrently with per-socket serialization
pavel-kirienko Jul 18, 2026
b56395e
Use conforming subject-ID moduli in tests after the modulus validation
pavel-kirienko Jul 18, 2026
93833db
Bound subject_id_modulus validation against oversized values
pavel-kirienko Jul 18, 2026
8993ad0
Harden the UDP concurrent send path
pavel-kirienko Jul 18, 2026
7d015c1
Refine SocketCAN close/fail RX semantics
pavel-kirienko Jul 18, 2026
e414d6b
Make node and transport setup paths transactional
pavel-kirienko Jul 18, 2026
4bcbf69
Keep response streams alive across node close and implicit GC
pavel-kirienko Jul 18, 2026
6c20570
Bound per-remote state under untrusted traffic
pavel-kirienko Jul 18, 2026
b5b3551
Update docs and changelog for the correctness fixes
pavel-kirienko Jul 18, 2026
7d4b57e
Address review round 1: doc gaps, TX-socket rollback, comment cleanup
pavel-kirienko Jul 18, 2026
af9f4c0
Simplify per review consensus: dedicated node housekeeping task
pavel-kirienko Jul 18, 2026
a0439dc
Fix Windows CI: avoid a real loopback multicast send in the lock test
pavel-kirienko Jul 18, 2026
cf148b0
Bump version and clean the changelog
pavel-kirienko Jul 18, 2026
15daf8a
Update the review-loop skill
pavel-kirienko Jul 18, 2026
f5761e3
Set FDF and BRS on every CAN FD frame
pavel-kirienko Jul 18, 2026
01e8c23
Stop acting on a closed node; guard the last constructor acquisition
pavel-kirienko Jul 18, 2026
a1fbcd5
Count a cancelled interface as a failed send, not a delivery
pavel-kirienko Jul 18, 2026
4b3bbb9
Keep the periodic housekeeping loops alive across a faulty sweep
pavel-kirienko Jul 18, 2026
7970964
Fix media teardown: deregister before close, and don't misreport a cl…
pavel-kirienko Jul 18, 2026
51c01ba
Record why three unbounded-looking structures are correct as written
pavel-kirienko Jul 18, 2026
ba5316a
Run ruff in CI, test on Python 3.14, and tidy loose ends
pavel-kirienko Jul 18, 2026
aca2eec
Tolerate event loops without reader/writer registration
pavel-kirienko Jul 18, 2026
6e3b369
Downsize the comments and docs added by this branch
pavel-kirienko Jul 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 27 additions & 22 deletions .claude/skills/review-loop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,56 @@
name: review-loop
description: >-
Multi-agent review/refine loop. Use after a change or milestone, or when asked to review work:
fan out fresh-context, single-focus reviewers across distinct tools, consolidate and fix, add a
regression test for every defect, and repeat until reviews stay clean for three consecutive turns.
dispatch a fresh-context full-spectrum reviewer plus a dissimilar correctness reviewer,
consolidate and fix, add a regression test for every defect, and repeat until a round is clean.
---

# Adversarial review/refine loop

After a change or milestone, or when prompted, dispatch a fan-out of fresh-context review agents at
After a change or milestone, or when prompted, dispatch fresh-context review agents at
MAXIMUM THINKING EFFORT, then consolidate, fix, and repeat.
The goal is broad coverage from adversarial, diverse, independent perspectives.
The goal is adversarial, diverse, independent coverage.

## Fan out — one focus per agent
The prompts given to the agents shall be extremely terse, at most a few sentences.
Giving excessive detail may constrain their thinking causing the tunnel vision syndrome.
They must be given the opportunity to look at the work without bias or prejudice.

Spawn one agent per concern and run them in parallel. Never give an agent multiple jobs: it dilutes attention
and degrades every answer. Cover at least these angles, one agent each:
## The reviewer pair

- Opportunities for SIMPLIFICATION.
- Functional CORRECTNESS and ROBUSTNESS.
- ARCHITECTURAL CLEANLINESS, DESIGN PRACTICES, CODE QUALITY.
- POLICY and STYLE compliance with the project's own docs.
Run two reviewers in parallel per round:

### Dissimilar agents
- An *ultrathink* Claude agent with the FULL-SPECTRUM remit, in priority order: functional CORRECTNESS and
ROBUSTNESS first, then SIMPLIFICATION opportunities, ARCHITECTURAL CLEANLINESS and CODE QUALITY,
and POLICY/STYLE compliance with the project's own docs.

In addition to the subagents above, dispatch distinct tools focusing on CORRECTNESS only to maximize the diversity
of perspectives and minimize blind spots. Check which tools are available (Codex etc.) and use all of them.

Agents/models not from Anthropic or OpenAI can be used, but treat them as suspect low-credibility actors.
Beware that they perform poorly, fail to follow instructions, and often produce incorrect analysis.
- Codex running the *most advanced model* in *ultra* effort focusing on CORRECTNESS only, to maximize perspective
diversity and minimize blind spots.

## Reviewers are read-only

Review agents must not modify the worktree or run mutating commands. If one needs a mutable environment,
it copies the worktree elsewhere.

## Reviewers do not re-run the project test suites

The tests normally should already be green when the review loop is invoked; re-running them
duplicates work and, for the broad sessions, wastes minutes of compute per round. State this in the
reviewer prompts. Reviewer effort goes instead into adversarial counterexamples for behaviors the
existing tests do NOT cover, executed in a scratch clone. Probes must run under the repo's own test
interpreter (e.g. `.nox/tests/bin/python`, which mutates nothing) rather than whatever is on PATH:
a version-skewed interpreter or dependency set can produce findings that do not apply to the project
or miss ones that do. Reproducing their own findings before reporting remains mandatory.

## Consolidate and act

When all reviewers return, merge their findings, discard the noise, and fix what is real.
For every correctness defect, add a regression test verified to fail before the fix and pass after.

## When to stop

Repeat until the reviewers surface only minor feedback (or none) for THREE consecutive turns — this is
non-negotiable, however many iterations it takes.
A round is clean when the reviewers surface only trivial feedback or none; the first clean round ends the loop.
Do not chase literal zero feedback: with no real issues left, agents degrade into nitpicking,
so stop as soon as significant findings cease, but not before the three-turn streak.
A blank turn followed by one that digs up a real defect is exactly why the streak must be consecutive;
expect dozens (sometimes over a hundred) of agent sessions per full pass.
so a round is clean as soon as significant findings cease.

## Operational notes

Expand All @@ -58,3 +62,4 @@ is a common cause of stream-idle timeouts.
Some headless agents hang waiting on stdin (like Codex) — redirect from `/dev/null`.

Retry agents that fail on a transient or connection error until they succeed.
If an agent gets stuck or hits a security guardrail, try resuming it first instead of restarting its work from scratch.
14 changes: 13 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python: ["3.11", "3.12", "3.13"]
python: ["3.11", "3.12", "3.13", "3.14"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -61,6 +61,18 @@ jobs:
- run: pip install nox
- run: nox -s mypy

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_OLDEST }}
- run: pip install nox
- run: nox -s lint

format:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Source is in `src/pycyphal2/`, tests in `tests/`. The package is extremely compa

Concrete transports are in top-level submodules:
- `pycyphal2.udp` — Cyphal/UDP transport implementation.
- `pycyphal2.can` (coming soon, not yet in the codebase) — Cyphal/CAN transport implementation.
- `pycyphal2.can` — Cyphal/CAN transport implementation.

The core must be dependency-free.
Transports may introduce (optional) dependencies that MUST be kept to the bare minimum.
Expand Down
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

nox.options.sessions = ["test", "mypy", "lint", "format"]

PYTHONS = ["3.11", "3.12", "3.13"]
PYTHONS = ["3.11", "3.12", "3.13", "3.14"]


@nox.session(python=False, default=False)
Expand Down
2 changes: 1 addition & 1 deletion src/pycyphal2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ async def main():
from ._transport import Transport as Transport
from ._transport import TransportArrival as TransportArrival

__version__ = "2.0.0.dev8"
__version__ = "2.0.0.dev9"

# pdoc needs __all__ to display re-exported members.
__all__ = [
Expand Down
7 changes: 6 additions & 1 deletion src/pycyphal2/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ async def request(
from any subscriber that chooses to answer.

``response_timeout`` is the maximum idle gap (liveness timeout) between accepted responses,
so it applies both to one-off RPC and to streaming.
so it applies both to one-off RPC and to streaming. Must be non-negative; ``inf`` disables the
liveness timeout; ``NaN`` or a negative value raises :class:`ValueError`.
"""
raise NotImplementedError

Expand Down Expand Up @@ -552,6 +553,10 @@ def new(transport: Transport, home: str = "", namespace: str = "") -> Node:

If the namespace is not set, it is read from the CYPHAL_NAMESPACE environment variable,
which is the main intended use case. Direct assignment might be considered an anti-pattern in most cases.

Raises :class:`ValueError` if ``transport.subject_id_modulus`` does not satisfy the reference
predicate (at least 57203, prime, congruent to 3 modulo 4); only custom transports are affected.
See :meth:`Transport.subject_id_modulus`.
"""
from ._node import NodeImpl

Expand Down
Loading