543 Commits

Author SHA1 Message Date
c1089201b1 fix(shell): accent Rescan (not Quit) in NoCableDialog; minor cleanups
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:26:42 -04:00
494ba2b00b feat(shell): add NoCableDialog for the no-cable case
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:23:03 -04:00
1a80ea85cf test(shell): cover CablePanel rescan-to-zero; clarify emit comment
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:21:16 -04:00
2972c4e264 feat(shell): add CablePanel for dashboard cable selection
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:16:40 -04:00
f3f60d21b8 refactor(core): narrow port_scan import guard and dedupe cable check
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:13:06 -04:00
5436866bc6 feat(core): add port_scan helper for service-cable discovery
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:09:13 -04:00
7a2cb30987 docs(plan): dashboard service-cable detection implementation plan
Ten TDD tasks: pure port_scan helper, CablePanel widget, NoCableDialog, launcher
gating, SuiteWindow source handoff + dashboard scan, source-driven DA-12 module,
app.py wiring, COM-dialog DRY, and full verification + docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 13:05:26 -04:00
12d647c347 docs(spec): dashboard service-cable detection design
On the suite dashboard, scan COM ports, surface detected service cables in an
inline panel, and gate module entry until one is selected (modal warning + Rescan
/ Quit when none). Records the live finding that both cables are FTDI 0403:6001
and indistinguishable from each other by USB descriptor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:57:54 -04:00
df59c2a710 modules: add DA-07 and IOModbus VB6 baselines + coming-soon cards
Drop the full VB6 source for two more service tools into their module
legacy/ baselines and register them as ComingSoonModule cards in the shell:
- cim_suite/modules/da07/legacy/      (DA-07 Service Tool Software)
- cim_suite/modules/iomodbus/legacy/  (IOModbus RS-485 service utility)

Both appear as "coming soon" launcher cards; rebuilding each into a live
module is its own spec → plan → implement cycle (see docs/BACKLOG.md).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:34:21 -04:00
53742d2b03 docs(backlog): retitle to the suite; fix BL-1 to target the shell (app.py removed) 2026-06-02 12:26:47 -04:00
5d01008e84 docs: fix stale test path in CLAUDE.md commands (tests/core/test_codecs.py) 2026-06-02 12:22:50 -04:00
2ce4e0a5ef docs: add recipe for adding modules #2 and #3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:16:50 -04:00
f32dd81d88 docs: point RUNNING/HARDWARE-VERIFICATION/DESIGN-SYSTEM at the suite shell entry 2026-06-02 12:15:06 -04:00
20cb87c9f2 docs: update CLAUDE.md, suite architecture, status, backlog for the monorepo
Update all five named files to reflect the completed suite-monorepo reshape:
run/entry commands point at cim_suite.shell.app; architecture tables and paths
updated to cim_suite/core + cim_suite/modules/da12 + cim_suite/shell; SUITE-
ARCHITECTURE.md status changed from "not yet built" to done with actual layout
and updated Module contract; REBUILD-STATUS.md records 88 tests and Phase 5;
BACKLOG.md marks reshape done and adds BL-S1/S2/S3 follow-ups including the
config/data-path migration caveat; transport __init__ docstring points to
cim_suite.core.transport.serial_transport for the real transport.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:12:19 -04:00
603d12c52b repackage as CIMTechniques Service Suite (shell entry, fonts path, installer)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:03:28 -04:00
589551cdfe clear Da12Module refs on shutdown; test module re-switch + card construction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:58:32 -04:00
cd6d3fc621 add suite shell: registry, card launcher, window, entry point
Implements Task 8: LauncherView card grid, SuiteWindow stacked host,
build_registry, shell app.py entry point, launcher CSS tokens appended
to stylesheet; repoints packaging launcher; deletes obsolete da12/app.py.
84 tests pass, ruff clean, headless self-test exits 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:52:46 -04:00
4c331f6e3a polish Da12Module shutdown/guard; add ComingSoonModule test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:48:48 -04:00
0e4324a0f3 add Module contract and Da12Module wrapper
Introduces the `Module` Protocol in `cim_suite/core/module.py` (with
`ComingSoonModule` placeholder) and `Da12Module` in
`cim_suite/modules/da12/module.py` that wraps controller + MainWindow
behind the contract. Adds 2 tests (79 total passing).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:42:35 -04:00
595b860532 harden config.load_json against non-dict JSON; restore wrapper docstring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:39:24 -04:00
ef77be593c split config into generic core engine + DA-12 wrapper
Introduces cim_suite/core/config.py with app-scoped path helpers and JSON
load/save utilities that are independent of QApplication name.  The DA-12
module config.py becomes a thin wrapper that binds APP_NAME and filenames
while keeping the same public API (load_config, save_config, data_dir,
cal_csv_path) so no call sites change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:33:04 -04:00
8fc33616da extract theme + TableTab into cim_suite/core/ui
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:28:02 -04:00
cdacb6d80a extract transport base + serial reader into cim_suite/core/transport 2026-06-02 11:24:00 -04:00
eddb464b1d extract codecs primitives into cim_suite/core/protocol
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:20:28 -04:00
49ab67b5f9 relocate DA-12 python package into cim_suite/modules/da12
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:14:37 -04:00
f5147234aa move DA-12 VB6 baseline into modules/da12/legacy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 11:05:17 -04:00
d207b7c05e scaffold cim_suite core/modules/shell package skeleton 2026-06-02 11:00:49 -04:00
2ff64ce7ad docs: add suite monorepo reshape implementation plan
Task-by-task, test-guarded plan implementing the approved reshape spec:
branch + scaffold, move VB6 baseline per-module, relocate the DA-12 package,
extract core (codecs/transport/theme+TableTab/config), Module contract +
Da12Module, the card-launcher shell, suite repackaging, docs, and the
drop-in recipe for apps #2/#3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 10:57:24 -04:00
9aac4ceef9 docs: add suite monorepo reshape design spec
Concrete, approved design for turning the standalone DA-12 repo into the
CIMTechniques Service Suite monorepo: cim_suite/ import root, conservative
core extraction, a card-launcher shell, the Module contract, and a
test-guarded migration order. Legacy VB6 source moves per-module into
modules/<app>/legacy/. Supersedes the sketch in SUITE-ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 10:49:43 -04:00
e54e8dee67 Add frontend design system (SmartScan azure, Lato)
Establish the suite-wide visual design system as a self-contained theme
layer and apply it across the DA-12 module.

- theme package (da12_service/ui/theme): tokens -> fonts -> stylesheet ->
  apply_theme; no app dependencies, shaped to move into core/ui/theme.
- Palette/fonts derived from the SmartScan brand: azure #0096FF accent on
  cool-slate surfaces, Lato bundled (OFL) and loaded at runtime.
- Applied app-wide: branded toolbar header + primary Connect action,
  underline tab bar, banded gridless tables, themed inputs/buttons/dialogs,
  status-bar connection pill, primary-button variants.
- Alarm row colors now come from SEVERITY tokens (alarms red / warnings
  amber) instead of hardcoded pastels.
- Packaging ships fonts in both the PyInstaller spec and the wheel.

Documented as the binding suite standard in docs/DESIGN-SYSTEM.md (rules +
per-module adoption checklist), cross-linked from SUITE-ARCHITECTURE.md and
CLAUDE.md. Backlog: BL-3 DONE, BL-4 (dark variant) and BL-5 logged.

ruff clean; 73 tests pass; app boots with --simulate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 09:37:51 -04:00
48f59aa02e docs: cross-link BACKLOG.md <-> REBUILD-STATUS.md
Reciprocal pointers so the live to-do list (backlog) and the point-in-time status
stay in sync regardless of which is opened first; status 'Known gaps' now flagged as
candidates to promote into the backlog.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 08:56:31 -04:00
4da383d6d7 docs: start BACKLOG.md with two robustness cleanup items
- BL-1: graceful shutdown on app close (close port / join reader via closeEvent).
- BL-2: connection status goes stale on unexpected disconnect (emit
  connectionChanged(False) from the reader error path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 08:42:25 -04:00
d3d2925e90 fix(packaging): correct PyInstaller entry point (relative-import crash)
The bundled exe died at startup with 'attempted relative import with no known
parent package' because the spec ran da12_service/app.py as __main__ (no package
context). Dev was unaffected (python -m sets the context).

- packaging/da12_launcher.py: thin entry that imports the package absolutely so
  app.py loads as a submodule and its relative imports resolve.
- spec: target the launcher; robust pathex via SPECPATH.
- app.py: DA12_SELFTEST hook (boot then auto-quit) for reliable build verification.
- tests/test_packaging_entry.py: runs the entry as PyInstaller does; asserts clean
  boot — regression guard (73 tests total).
- RUNNING.md: correct verification method (a lingering window != a clean boot).

Rebuilt exe verified: boots and self-exits with code 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 08:26:16 -04:00
cf813cd8dd docs: record unified service-suite direction (DA-12 as module #1)
- SUITE-ARCHITECTURE.md: agreed direction (unified modular app on a shared core),
  rationale, target monorepo structure, thin module contract, rule-of-three caution,
  and sequencing (awaiting source for apps #2/#3). Not yet built.
- REBUILD-STATUS.md: 'Next direction' pointer to the suite plan.
- VB6-MIGRATION-PLAYBOOK.md: new section on consolidating multiple apps into one
  suite (when to unify vs separate shells; don't over-build core from one app).

No code changes — documentation only, per request, ahead of receiving the other apps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 08:21:20 -04:00
1c523a371b docs: reusable VB6 -> modern migration playbook
Portable guide distilled from the DA-12 rebuild: why VB6 apps break, stack choice
(Python+PySide6 vs .NET), the phased process, how to read VB6 source, a VB6-quirk
-> Python reference (signed-16/32 hex, Int() floor, fixed-point/sentinels, OCX
replacements, serial specifics), the layered/simulator architecture, dropped-feature
discipline, testing, packaging/AV/signing, and a per-app reuse checklist.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 07:56:58 -04:00
6bb511da98 fix(protocol): address code-review findings (scale/offset sentinel + Int floor)
- decode_float(): scale/offset use VB AddFloat semantics with NO 8000 sentinel
  (8000 is a real negative value there, not no-value). decoder 'A' branch updated.
- encode_scaled(): use math.floor to match VB Int() (floors toward -inf), correct
  for negative calibration offsets.
- Simulator F-frame: comment that its layout is not verified ground truth.
- REBUILD-STATUS: record the review + the deferred F-counter display.
- +3 regression tests (72 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:30:54 -04:00
88b101da69 build+docs: PyInstaller spec (built & verified), Inno Setup installer, guides
Phase 4:
- packaging/da12_service.spec: one-folder PyInstaller build (AV-friendly), trims
  unused PySide6 modules. Built successfully; DA12-Service.exe launches standalone.
- packaging/installer.iss: Inno Setup script -> per-machine install, Start-menu
  shortcut, no runtime/OCX deps (signing hook noted).
- docs/RUNNING.md: dev setup, run (--simulate/--port), tests, build, data locations.
- docs/HARDWARE-VERIFICATION.md: checklist for the 5 hardware-only unknowns,
  each mapped to its fix-up location.
- docs/REBUILD-STATUS.md: overnight session summary / handoff.
- .gitattributes: normalize line endings (legacy VB6 kept CRLF).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:22:30 -04:00
5777545d7e feat(ui): PySide6 app — 5 tabs, dialogs, toolbar, status bar
Phase 3:
- TableTab base (signal-safe repaint), Sensors/Alarm Limits/Statistics/Station/
  Calibration tabs wired to controller signals with inline editing dispatch.
- CalibrationDialog (2-point + offset-only, live preview, writes scale/offset and
  appends DACal.csv history); CalibrationTab history grid with copy/delete/erase.
- ComSetupDialog (station port only), JSON config (config.py) replacing DAService.tab.
- MainWindow shell: Connect/Refresh/Set-Clock/Reset/Log toolbar + status bar.
- app.py entry with --simulate and --port; live tick loop in simulate mode.
- 69 passing tests (offscreen Qt); app boots cleanly under simulation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:19:18 -04:00
6ed18183dc fix(simulator): drop unused imports/vars (ruff clean) 2026-06-01 17:14:28 -04:00
e9b8285900 feat(transport+domain): serial/simulator transports, models, calibration, logging, controller
Phase 2:
- transport: BaseTransport interface, pyserial SerialTransport (19200-8-N-1 reader
  thread), and a deterministic in-memory SimulatedStation speaking the wire protocol.
- domain: SensorTable/LimitsTable/StatsTable/StationSettings with partial updates;
  two-point + offset-only calibration math with DACal.csv-compatible history;
  per-sensor MeasurementLogger matching the legacy format.
- StationController (QObject) routes transport->framer->decoder->models->signals,
  using AutoConnection so the simulator runs synchronously and the serial reader
  thread is marshaled to the GUI thread. Full outbound command surface.
- 62 passing tests (protocol + transport + domain).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:13:44 -04:00
ae159c1e80 feat(protocol): pure framing/codecs/decoder/encoder + tests
Phase 1: hardware-free protocol core for the DA-12 station serial format.
- codecs: hex widths, signed-16/32 parsing, fixed-point scaling, alarm bitmask,
  duration/clock helpers, FieldReader (tab-delimited, type-letter-adjacent).
- framing: StreamFramer extracts {...} bodies with overflow protection.
- messages/decoder: A/B/C/I/D/E/F/G/H message types.
- encoder: refresh/reset/clock/clear/remove/add + SendSetting (scaled/string/IP).
- 33 passing tests with vectors derived from the VB6 source.
- Station clock epoch + sensor type/calc codes FLAGGED for hardware verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:08:38 -04:00
df8646a74b docs: implementation plan for Python/PySide6 rebuild
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:02:40 -04:00
f7e43d6b87 Baseline: legacy VB6 DA-12 Service Tool + rebuild design spec
Imports the original Visual Basic 6 source (Main.frm, Support.bas, Calib.frm,
NewSensors.frm, ComSetup.frm, Error.frm, project files) and reference data
(DACal.csv, DAService.tab, Exceptions.txt) as the starting point, plus the
approved modernization design spec under docs/superpowers/specs/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 16:58:47 -04:00