Skip to content

Commit 8ba101d

Browse files
pavel-kirienkoclaudeCopilot
authored
PyCyphal v2 (#379)
This is the new implementation that was first announced in #351 almost a year ago. While Cyphal/CAN is wire-compatible between the two versions, the API is completely different, and so is the design philosophy. PyCyphal v2 does not attempt to be a one-stop shop for Cyphal, rather it focuses on connectivity only, intentionally omitting application-level concerns. As a result, the new API is a tiny fraction of the old. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: pavel-kirienko <3298404+pavel-kirienko@users.noreply.github.com>
1 parent 572cb45 commit 8ba101d

317 files changed

Lines changed: 19684 additions & 39422 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
name: cyphal-parity-guard
3+
description: Keep the Python Cyphal rewrite in wire-visible behavioral parity with the C reference at `reference/cy`. Use when auditing/reviewing parity drift, identifying wire/state-machine discrepancies, updating `src/pycyphal2/` to match reference behavior, replacing conflicting Python tests with C-parity expectations, and adding regression tests for every discovered divergence. API-level discrepancies are by design and are to be ignored; this skill focuses on wire-visible and state-machine behavior only.
4+
---
5+
6+
# Cyphal Parity Guard
7+
8+
## Overview
9+
10+
Run a deterministic parity workflow for `pycyphal2` against `reference/cy` in two modes:
11+
- `sync` mode: identify divergences, patch Python implementation, and add/adjust regression tests.
12+
- `review` mode: report parity findings only, no edits.
13+
14+
Apply the following defaults unless the user overrides them:
15+
- Target wire+state parity with `cy.c`.
16+
- Treat `cy.c` behavior as source of truth when Python tests conflict.
17+
- Add Python regression coverage for each confirmed divergence.
18+
- Ignore API-level discrepancies that do not affect wire/state behavior (e.g., differences in API design, error handling style, etc).
19+
20+
## Mode Selection
21+
22+
Select mode from user intent:
23+
- Use `review` mode when asked to "review", "audit", or "find discrepancies".
24+
- Use `sync` mode when asked to "fix", "update", "bring in sync", or "correct divergences".
25+
- If intent is ambiguous, start in `review` mode and then switch to `sync` when requested.
26+
27+
## Source-of-Truth Order
28+
29+
Use this precedence:
30+
1. `reference/cy/cy/cy.h` for constants/API semantics.
31+
2. `reference/cy/cy/cy.c` for wire-visible and state-machine behavior.
32+
3. `reference/cy/model/` when C code intent is ambiguous.
33+
4. `src/pycyphal2/` and existing tests as implementation artifacts, not normative authority.
34+
35+
## Workflow
36+
37+
1. Prepare context.
38+
- Confirm repository root.
39+
- Inspect touched files and current test baseline.
40+
- Load `references/parity-checklist.md` and use it as the audit checklist.
41+
42+
2. Build a discrepancy matrix.
43+
- Compare `reference/cy` behavior with `src/pycyphal2/_node.py`, `_wire.py`, and related modules.
44+
- Ignore differences that are not visible on the wire or in state machines (e.g., differences in API design, error handling style, etc).
45+
- Keep in mind that error handling differs significantly between C and Python; therefore, certain error-path-related
46+
discrepancies may be expected and should be noted as such in the matrix (e.g., where C would clamp invalid
47+
arguments, Python should raise ValueError, etc).
48+
Error handling must be Pythonic first of all.
49+
- For each discrepancy, record:
50+
- C anchor (`file:line` + behavior statement).
51+
- Python anchor (`file:line` + divergent behavior).
52+
- Impact and severity.
53+
- Needed test coverage.
54+
55+
3. Execute mode-specific actions.
56+
- In `review` mode:
57+
- Produce findings ordered by severity.
58+
- Include exact file/line anchors and missing regression tests.
59+
- Do not edit code.
60+
- In `sync` mode:
61+
- Implement fixes in `src/pycyphal2/`.
62+
- Update/remove conflicting test expectations when they contradict `cy.c`.
63+
- Add at least one regression test per divergence under `tests/`.
64+
65+
4. Validate.
66+
- Run targeted tests first for changed behavior.
67+
- Run full quality gates when feasible:
68+
- `nox -s test-3.12`
69+
- `nox -s mypy`
70+
- `nox -s format`
71+
- If full matrix is requested or practical, also run `test-3.11` and `test-3.13`.
72+
73+
5. Report.
74+
- Always return the discrepancy matrix (resolved or unresolved).
75+
- For `sync` mode, map every fixed divergence to specific tests.
76+
- Call out residual risks if any discrepancy remains untested.
77+
78+
## Repository Constraints
79+
80+
Enforce project constraints while implementing parity fixes:
81+
- Preserve behavior across GNU/Linux, Windows, and macOS.
82+
- Keep support for all declared Python versions in `pyproject.toml` (currently `>=3.11`).
83+
- Keep async I/O in `async`/`await` style and maintain strict typing.
84+
- Keep formatting Black-compatible with line length 120.
85+
- Keep logging rich and appropriately leveled for unusual/error paths.
86+
87+
## Output Contract
88+
89+
For parity reviews, return:
90+
- Findings first, ordered high to low severity.
91+
- File/line references for C and Python anchors.
92+
- Explicit statement when no discrepancies are found.
93+
- Testing gaps and confidence level.
94+
95+
For parity sync work, return:
96+
- What changed in implementation.
97+
- What changed in tests and which divergences they cover.
98+
- Commands executed and notable pass/fail outcomes.
99+
100+
## Reference Map
101+
102+
- `references/parity-checklist.md`: hotspot checklist, anchor patterns, and discrepancy matrix template.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Cyphal parity guard"
3+
short_description: "Keep pycyphal aligned with reference behavior"
4+
default_prompt: "Use $cyphal-parity-guard to review parity against the reference and either report divergences or fix them with regression tests."
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Parity Checklist
2+
3+
Use this file to drive fast, repeatable parity analysis between `reference/cy` and `src/pycyphal2/`.
4+
5+
## High-Risk Areas
6+
7+
1. CRDT allocation and collision arbitration.
8+
2. Gossip propagation, validation, scope handling, and unknown-topic behavior.
9+
3. Implicit topic lifecycle and retirement timing.
10+
4. Reliable publish ACK/NACK acceptance and association slack updates.
11+
5. Deduplication and reordering interaction with reliability.
12+
6. Response ACK/NACK and future retention semantics.
13+
7. Header packing/unpacking and wire constants.
14+
8. Consult with the reference implementation and formal models to identify additional high-risk areas.
15+
16+
## Discrepancy Matrix Template
17+
18+
Use one row per confirmed divergence.
19+
20+
| ID | Area | C Anchor | Python Anchor | Divergence | Severity | Fix Plan / Action | Regression Test |
21+
|---|---|---|---|---|---|---|---|
22+
| P-001 | ACK acceptance | `reference/cy/cy/cy.c:4448` | `src/pycyphal2/_node.py:...` | Describe exact behavioral mismatch | High | Adjust ACK acceptance rules and slack handling | `tests/test_pubsub.py::...` |
23+
24+
## Review Quality Bar
25+
26+
Before declaring parity, ensure:
27+
1. Every listed high-risk area was inspected or explicitly marked not applicable.
28+
2. Every confirmed divergence has at least one mapped regression test (existing or new).
29+
3. Any changed expectation that conflicts with previous Python tests is resolved in favor of `cy.c`.

.github/workflows/docs.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Docs
2+
3+
on:
4+
push:
5+
branches: [master]
6+
7+
permissions:
8+
contents: read
9+
pages: write
10+
id-token: write
11+
12+
concurrency:
13+
group: pages
14+
cancel-in-progress: true
15+
16+
jobs:
17+
docs:
18+
runs-on: ubuntu-latest
19+
environment:
20+
name: github-pages
21+
url: ${{ steps.deploy.outputs.page_url }}
22+
steps:
23+
- uses: actions/checkout@v6
24+
with:
25+
submodules: recursive
26+
- uses: actions/setup-python@v6
27+
with:
28+
python-version: "3.11"
29+
- run: pip install nox
30+
- run: nox -s docs
31+
- uses: actions/upload-pages-artifact@v4
32+
with:
33+
path: html_docs/
34+
- uses: actions/deploy-pages@v5
35+
id: deploy

.github/workflows/release.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [master]
6+
paths:
7+
- "src/pycyphal2/__init__.py"
8+
9+
jobs:
10+
release:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: write # for creating tags
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- name: Extract version
18+
id: version
19+
run: |
20+
VERSION=$(python -c "import re, pathlib; print(re.search(r'__version__\s*=\s*\"(.+?)\"', pathlib.Path('src/pycyphal2/__init__.py').read_text()).group(1))")
21+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
22+
23+
- name: Check if tag exists
24+
id: tag_check
25+
run: |
26+
if git ls-remote --tags origin "refs/tags/${{ steps.version.outputs.version }}" | grep -q .; then
27+
echo "exists=true" >> "$GITHUB_OUTPUT"
28+
else
29+
echo "exists=false" >> "$GITHUB_OUTPUT"
30+
fi
31+
32+
- name: Create tag
33+
if: steps.tag_check.outputs.exists == 'false'
34+
run: |
35+
git tag "${{ steps.version.outputs.version }}"
36+
git push origin "${{ steps.version.outputs.version }}"
37+
38+
- name: Check if version is on PyPI
39+
id: pypi_check
40+
run: |
41+
if pip index versions pycyphal2 2>/dev/null | grep -qF "${{ steps.version.outputs.version }}"; then
42+
echo "exists=true" >> "$GITHUB_OUTPUT"
43+
else
44+
echo "exists=false" >> "$GITHUB_OUTPUT"
45+
fi
46+
47+
- name: Build package
48+
if: steps.pypi_check.outputs.exists == 'false'
49+
run: |
50+
pip install build
51+
python -m build
52+
53+
- name: Publish to PyPI
54+
if: steps.pypi_check.outputs.exists == 'false'
55+
uses: pypa/gh-action-pypi-publish@release/v1
56+
with:
57+
password: ${{ secrets.PYPI_API_TOKEN }}

.github/workflows/test-and-release.yml

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)