Files
opcda-diagnozer/TODO.md
T
2026-10-08 06:30:54 +02:00

4.8 KiB
Raw Blame History

TODO — implementation status

Companion to docs/IMPLEMENTATION_PLAN.md (the authoritative plan) and CHANGELOG.md (what shipped). One row per plan task; updated as work lands. Legend: [done] complete & verified · [partial] some of it landed · [todo] not started · [skip] dropped by decision.

Phase 0 — Feasibility & environment [done]

  • [done] Wrapper backend decision: OPC DA Automation Wrapper (OPC.Automation) → 32-bit interpreter mandatory (spec §11).
  • [done] Test server: Matrikon OPC Simulation Server, local ProgID Matrikon.OPC.Simulation.1; baseline read RTT + wrapper error shapes recorded (repo memory).
  • [done] Dependencies chosen for a 32-bit, no-compiler install: ruamel.yaml (PyYAML has no cp314 win32 wheels), pywin32.

Phase 1 — Core engine

  • [done] 1. config.py — typed YAML config + strict validation; D16 devices: indicators with configurable ok_values; check-config prints them.
  • [done] 2. quality.py — decode tables (spec §7).
    • [todo] status_text(raw) -> "NAME (0xNN)" clear-text helper (spec §7 closing rule; used by every reporter).
  • [done] 3. opc/base.py — client/browser protocols, ReadResult, OpcError with decoded HRESULT.
  • [done] 4. opc/automation.py — connect / browse / read (per-item Item.Read; SyncRead is unmarshallable from pywin32 — verified), per-tag errors, safe COM teardown.
    • [skip] Single persistent group + static items (poller will create its own per client; the throwaway-group read pattern is verified).
  • [todo] 5. monitor/state.py — connection state machine, exponential backoff (1 s → 60 s cap), reconnect accounting (only the enum exists).
  • [todo] 6. monitor/detectors.py — D1–D15 pure detectors + rolling window (only the PollOutcome dataclass exists).
    • [todo] D16 device-link detector (ok_values semantics, edge-level, DEVICE_LINK_DOWN/DEVICE_LINK_UP).
  • [todo] 7. monitor/poller.py — the COM thread poll loop + hang watchdog (abandon & rebuild past hard_hang_s).
    • [todo] Startup tag validation: probe every configured tag (incl. device indicators) before entering the loop; fail fast on invalid ItemIDs.
    • [open] Poll source default (CACHE vs DEVICE) — needs a spec decision: Matrikon shows BAD qualities on some tags only via CACHE.
  • [todo] 8. run verb — foreground monitoring loop, event pipeline to reporters, heartbeat (D15).
  • [done] 9. opc/fake.py — scriptable fake client (reads already scriptable via read_results; hang/error sequences land with the poller).

Phase 2 — Reporters

  • [todo] 1. report/jsonl.py — rotating JSONL (size + backups), config-digest header, atomic-ish append.
  • [todo] 2. report/textlog.py — plain-text anomaly log (spec §9.1): anomalies-YYYYMMDD.log, one line per detected anomaly, clear-text status NAME (0xNN), recoveries logged so it reads as an incident narrative.
  • [todo] 3. report/eventlog.py — Windows Event Log (WARN+), source registration via install.
  • [todo] 4. report/http.py — optional webhook, bounded queue, never blocks polling.
  • [todo] 5. Heartbeat assembly (D15) + reporter fan-out dispatcher.

Phase 3 — Windows service

  • [todo] 1. service.py — ServiceFramework host; clean stop (STOP_PENDING, join-with-timeout, abandon hung COM thread).
  • [todo] 2. CLI verbs install/uninstall/start/stop (sc.exe semantics).
  • [todo] 3. SCM recovery (sc failure ... restart), auto-start, service account docs.
  • [todo] 4. %ProgramData%\OPCDA-Diagnozer\ config/log dir conventions (frozen exe already defaults there).
  • [open] Frozen-exe SCM hosting: console exe must expose ServiceMain — one careful build pass (pywin32 ServiceControlDispatcher).

Phase 4 — Integration & chaos testing

  • [todo] Scenario matrix vs the sim server: server kill / service stop / firewall silent drop / latency injection / device comm failure / quality oscillation / stale+frozen / mass bad / config errors / D16: flip a device indicator (e.g. a P500x.Connected alias).
  • [todo] 24 h soak (AC10): no leaks, reconnect accounting correct, heartbeats every 5 min, ≤ ~50 MB RAM, ~0 % CPU idle.

Phase 5 — Packaging & docs

  • [done] PyInstaller exe build (scripts/build_exe.ps1, onedir + onefile, read canary) — live-verified.
  • [done] README (install, config, DCOM checklist, HRESULT table).
  • [todo] Ops runbook: reading events, kind meanings (spec §12 matrix), threshold tuning, evidence locations.
  • [todo] 1.0.0 tag once AC1–AC10 pass.

Housekeeping

  • [todo] Wire status_text into read/probe output once it exists (currently shows raw_hex + decoded name separately).
  • [todo] Record the CACHE-vs-DEVICE poll-source decision in the spec once made; add fake-client scripted reads for both sources to the poller tests.