Skip to content

feat: Ladder CLI and GUI for Click rung import/export#67

Merged
ssweber merged 179 commits intomainfrom
paste
Apr 2, 2026
Merged

feat: Ladder CLI and GUI for Click rung import/export#67
ssweber merged 179 commits intomainfrom
paste

Conversation

@ssweber
Copy link
Copy Markdown
Owner

@ssweber ssweber commented Mar 18, 2026

  • clicknick-rung CLI — load/save rungs to clipboard, decode full programs to CSV, and guided batch verify with
    progress tracking
  • Ladder menu (beta) — GUI access to load CSV to clipboard, save clipboard to CSV, export program from Click, guided
    paste for multi-file folders, and convert to pyrung
  • Guided Paste panel — step-through UI for pasting a folder of ladder CSVs into Click, with nickname import and
    show-nicknames toggle
  • Dataview Editor — reconnect support and improved timeout defaults

ssweber and others added 30 commits March 2, 2026 13:27
Extract working prototype from clickplc-tools/exploring/runggrid_construct.py
into self-contained clicknick.ladder module (model/codec/clipboard layers).
Template-based encoding confirmed working for 4-char operands (X###, Y###).

Includes HANDOFF.md (v7) with stream-based format discovery: operand strings
are variable-length UTF-16LE and all downstream offsets shift accordingly.
Fixed coil func code offset (+0x2E not +0x30).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add devtools/capture.py — scans clipboard for type IDs (0x27XX) and
probes stream-relative offsets for operands (+16) and func codes (+42/+60).
Saves captures to scratchpad/captures/ (gitignored).

Update HANDOFF.md (v7 -> stream-based):
- Findings 10-12 rewritten around stream-relative offsets
- New instruction table: NO/NC/rise/fall/immediate func codes (4097-4102)
- Patch map updated with stream-relative offset table
- Phase 3 captures added (rise, fall, NO/NC immediate)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eam codec

**Description**
Adds next-step Click ladder model/codec support for reverse-engineered contact/coil variants and dynamic operand lengths.

- Extend ladder model:
  - Contact immediate: `X1.immediate`, `~X1.immediate`
  - Coil types: `out`, `latch`, `reset`
  - Coil range/immediate: `out(Y1..Y2)`, `out(immediate(Y1..Y2))`
  - Enforce inner-wrapper immediate syntax (reject `immediate(out(...))`)
  - Strict operand regex: `^[A-Z]{1,3}\d{1,5}$`
  - Preserve existing shorthand rung CSV compatibility

- Rework ladder codec:
  - Remove fixed 4-char operand assumptions
  - Encode/decode with dynamic stream offsets from type byte
  - Support mapped func codes for out/latch/reset normal/immediate/range/range+immediate
  - Decode by scanning stream type markers and dynamic func-code positions

- Test coverage:
  - Model parsing/serialization for new forms and ambiguity decisions
  - Codec round-trip coverage for all variants
  - Capture-backed decode tests for provided binaries
  - Short/long range address scenarios (`C1..C2`, `C1..C2000`, `C1901..C2000`)

- Docs:
  - Minimal factual `HANDOFF.md` status updates for completed captures and remaining items only.
…alizer, and AST adapter

**Description**
- Add a new contract-aligned CSV consumer stack under `clicknick.ladder`:
  - strict canonical v1 parsing (`marker + A..AF`, exact header, exact 33 columns)
  - strict shorthand row normalization (`marker,<conditions>,:,<AF>`)
  - bundle parsing for `main.csv` + lexically ordered `sub_*.csv`
- Introduce typed AST model for parsed ladder CSV:
  - bundle/file/rung/row structure
  - typed condition nodes
  - typed AF call nodes with forward-compatible unknown handling (`known=False`)
- Add strict shorthand macro rules:
  - only one of `->` or `...` in `A..AE`
  - macro must be last explicit condition token
  - macros forbidden in marker/AF
- Add `RungGrid` compatibility adapter:
  - converts only simple single-row, 1–2 contact, coil-only rungs
  - raises `UnsupportedComplexRungError` with reason codes for complex shapes
- Export new parser/normalizer/bundle/adapter APIs from `clicknick.ladder`
- Add full test coverage for contract, shorthand, parser, bundle, and adapter
- Preserve existing `RungGrid` and `ClickCodec` APIs/behavior (legacy ladder tests remain green)
…cument header metadata findings

**Description**
Adds robust support for 2-contact series rung encoding/decoding across immediate variants using native Click capture templates, and documents newly confirmed header/pointer metadata behavior.

- Ladder codec:
  - Add template-backed encode paths for:
    - `X001,X002,->,:out(Y001)`
    - `X001.immediate,X002,->,:out(Y001)`
    - `X001,X002.immediate,->,:out(Y001)`
    - `X001.immediate,X002.immediate,->,:out(Y001)`
  - Keep 2-series mode constrained to validated 4-char contacts.
- Tests:
  - Extend round-trip and capture-backed decode coverage for all 2-series immediate combinations.
- Resources:
  - Add new `.bin` templates captured from native Click output for the three immediate 2-series variants.
- Handoff:
  - Add findings on the repeating header structural table (`0x0254 + n*0x40`) and variant-dependent pointer/rendering bytes (`0x00B8-0x00CF`).
  - Update series-contact status, capture inventory, and remaining capture targets.

Validation:
- `uv run pytest tests/ladder -q` passes (`90 passed`).
…scaping

- Updates AF token parsing to v1.1 string escaping semantics.
- Quoted AF string args now decode CSV-style doubled quotes (`"" -> "`).
- Removes backslash escape handling (`\"`, `\\`) from AF token parsing.
- `parse_af_token()` now raises `ValueError` for malformed quoted AF strings.
- Keeps non-string AF args unchanged.
- Adds focused parser tests for:
  - normal/empty strings
  - embedded doubled quotes
  - quoted commas
  - literal backslashes
  - malformed quote errors
- Adds CSV integration coverage to verify CSV-reader-unquoted AF cells are correctly token-decoded.
- Non-goals preserved: no subroutine-name quote validation and no string rendering helper/API changes.
Updated `RungGrid` shorthand to use a standalone colon delimiter between condition columns and output, matching CSV v1.1 canonical format.

- `RungGrid.to_csv()` now emits `...,->,:,<coil>` (e.g. `X001,->,:,out(Y001)`).
- `RungGrid.from_csv()` now parses `:` as its own token.
- Backward compatibility NOT kept.
- Updated ladder tests and `HANDOFF.md` examples to the new shorthand.
- Verified round-trip behavior and full test suite pass.
…ion AST names

- Added deterministic regen tool: `devtools/update_ladder_capture_manifest.py`.
- Upgraded `tests/fixtures/ladder_captures/manifest.json` schema from `version: 1` to `version: 2`.
- Enriched each manifest entry with:
  - `description`
  - `rung_rows`
  - `verified`
  - `codec_generatable`
  - `metadata_todo`
- Implemented checklist/matrix-driven metadata hydration, canonical row normalization, and explicit column-placement overrides for ambiguous shorthand rows.
- Added TODO handling for: `nc_a_immediate_only`, `no_a_immediate_only`, `no_c_immediate_only`, `pasteback_vert_b_with_horiz`.
- Implemented `codec_generatable` computation using decode/encode plus structural header + topology equivalence checks.
- Updated token policy in `parse_condition_token`:
  - `|` -> structured vertical token
  - `+` -> generic/unsupported token (no structured vertical semantics)
- Refactored wire condition AST naming for clarity:
  - `WireCondition` -> `HorizontalWire`
  - `VerticalTopCondition` -> `JunctionDownWire`
  - `VerticalMidCondition` -> `VerticalPassThroughWire`
  - `ConditionNode` -> `ConditionCellNode`
- Updated parser/adapter/tests accordingly.
- Updated shorthand normalization to treat AF `...` as blank AF for canonical manifest row storage.
- Expanded tests for schema v2 contracts, token behavior, row normalization/marker rules, and regression cases.
…crash-aware verify, and drop scratchpad manifest v1

- add shared ladder capture backend:
  - `src/clicknick/ladder/capture_registry.py`
  - `src/clicknick/ladder/capture_workflow.py`
- add direct CLI frontend + entrypoint:
  - `src/clicknick/ladder/capture_cli.py`
  - `clicknick-ladder-capture` script in `pyproject.toml`
- add TUI wrapper using the same workflow backend:
  - `devtools/ladder_capture_tui.py`
- add scratchpad working manifest seed:
  - `scratchpad/ladder_capture_manifest.json`
- implement crash-aware verification events in shared logic:
  - `copied`, `crash`, `cancelled`
  - crash path does not force clipboard reads
- enforce promotion gate policy:
  - native entries promotable
  - non-native entries require `verify_status=verified_pass`
  - promotion payload selection: `verify_result_file` then `payload_file`
- upsert fixture manifest v2 entries and recompute `codec_generatable` via decode/re-encode + structural/topology checks
- remove deprecated overlapping tools:
  - `devtools/capture.py`
  - `devtools/clipboard_load.py`
  - `devtools/update_ladder_capture_manifest.py`
  - `scratchpad/pasteback_smoke.py`
- update docs/checklists to new unified commands:
  - `scratchpad/capture-checklist.md`
  - `scratchpad/instruction-capture-checklist.md`
  - `RE-notes.md`
- drop scratchpad manifest v1 support; standardize scratchpad manifest on v2 and add rejection test for v1

**Tests**
- added:
  - `tests/ladder/test_capture_registry_workflow.py`
  - `tests/ladder/test_capture_cli.py`
- verified:
  - ruff checks pass on new/changed capture modules
  - targeted pytest suite passes for capture registry/workflow/cli and fixture compatibility
…d new scratchpad cases

- Seeded scratchpad ladder capture manifest with 13 new native cases for NC/immediate/C/rise-fall series variants.
- Updated `clicknick-ladder-capture tui` option 2 to run a guided pending-native queue:
  - auto-selects native entries with no `payload_file`
  - walks entries one-by-one
  - supports capture / skip / quit per entry
  - removes need to type labels for each capture
- Added regression test for queue behavior in `tests/ladder/test_capture_cli.py`.

Validation:
- `uv run pytest tests/ladder/test_capture_cli.py` (5 passed)
…e CLI

Adds a new read-only reporting command to the unified ladder capture CLI:

- New command: `clicknick-ladder-capture report profile`
- Supports single-entry and bulk modes:
  - `--label <label>` for one manifest entry
  - `--all` for all entries with `payload_file`
- Supports output formats:
  - default human-readable summary
  - `--json` machine-readable output
  - `--csv` tabular export
- Extracts key RE bytes from captured payloads:
  - cell bytes (`cell_05`, `cell_11`, `cell_1a`, `cell_1b`) at row0/col4
  - header bytes (`header_05`, `header_11`, `header_17`, `header_18`) at entry 0
  - trailer byte (`trailer_0a59`)
- Adds CLI tests for:
  - single-label JSON reporting
  - `--all` CSV reporting

This replaces ad-hoc extraction snippets with a first-class workflow command.
…d TUI

Added a new internal doc at [scratchpad/llm-capture-checklist-guide.md for LLM operators.

This doc now defines:
- The required programmatic flow to add checklist items via `clicknick-ladder-capture` commands (no direct JSON edits).
- Non-negotiable operational rules, including forbidden retired tools.
- A minimal copy/paste workflow for add/show/capture/verify/promote.
- Programmatic gotchas and enum constraints.
- A complete CLI + guided TUI command/flag inventory.
- A JSON response envelope example and quick validation commands.

Validation was also run to confirm:
- Command surface parity with current `--help`.
- Happy path (`manifest init` -> `entry add` -> `entry show`).
- Duplicate-label failure behavior.
- Enum rejection for invalid `--status` / `--clipboard-event`.
- TUI menu options match runtime behavior.
ssweber and others added 26 commits March 27, 2026 13:16
…commands

`program save FOLDER` decodes Scr*.tmp files into a CSV bundle
(main.csv + subroutines/{slug}.csv). `program load FOLDER` is the
existing guided clipboard paste workflow for loading bundles into Click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows writing the CSV bundle to a separate directory instead of
alongside the source Scr*.tmp files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move pure logic (encode, decode, MDB provisioning, program save/load)
into program.py so both CLI and GUI can share it. Slim cli.py to
argparse + interactive flows. Remove --split-rungs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Decodes Scr*.tmp files from the connected Click project into a
portable CSV bundle (main.csv + subroutines/) via program_save().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Non-modal tksheet panel (File > Load Ladder Folder) that walks the user
through pasting a folder of ladder CSVs into Click one at a time.

- Service helpers: list_csv_folder, read_csv_comment, count_csv_rungs
- Row states (done/current/pending) with color highlighting
- Next/Skip/Restart/Re-copy buttons
- MDB path and Click HWND resolved live at paste time

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thread show_nicknames through prepare_csv_load → encode so math
instructions display tag names instead of raw addresses in Click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pyrung as editable dependency and wire up ladder_to_pyrung_project
behind a new "Convert Ladder to pyrung..." File menu item. Export Ladder
CSV now also writes nicknames.csv from the MDB alongside the ladder CSVs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add nicknames.csv as the first step when loading a ladder folder so
nicknames are imported into the MDB before pasting rungs.  Change the
workflow from auto-copy-on-select to an explicit Copy → Next flow for
clarity.  Enable "show nicknames in math" by default and let the window
size itself dynamically so the button row is never clipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clipboard and restart icons to buttons, remove Re-copy button since
clicking a row resets to Copy state, fix column widths by using
set_column_widths after data load, and widen window to 820px so File
and Description columns have room.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move ladder operations (Export from Click, Convert to pyrung, Open in
Guided Paste) out of File into a dedicated Ladder menu. Rename labels,
dialog titles, and internal methods to match. Update checkbox label to
"Show nicknames in math instructions".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds (beta) label to the menu item and a one-time info dialog
explaining decoder limitations and encouraging bug reports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows a Retry/Cancel dialog when output files are locked by another
program, and a warning for nicknames.csv write failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove funlog/rich/codespell from lint pipeline, simplify lint.py to
plain subprocess calls with --check CI mode, and re-resolve lockfile.

Fix ruff F821 by moving Path import to module level so the return type
annotation on _get_export_popup_flag resolves.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single-file alternative to Guided Paste — pick a CSV, encode it,
and copy to Click's clipboard format ready for pasting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9d5289e added timeout=3 to the real connect call but the test fake
only accepted positional (host, port), causing a silent TypeError.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Group menu items by direction (in/out), add Save Clipboard to CSV
option, and move beta label to the menu cascade.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ssweber ssweber marked this pull request as ready for review April 2, 2026 14:50
@ssweber ssweber changed the title feat: add clicknick-rung CLI for ladder rung clipboard bridge feat: Ladder CLI and GUI for Click rung import/export Apr 2, 2026
@ssweber ssweber merged commit 03cd923 into main Apr 2, 2026
3 checks passed
@ssweber ssweber deleted the paste branch April 2, 2026 14:51
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.

1 participant