Skip to content

Add a negative-control scenario: legal status transitions #173

Description

@sepehr-safari

Good First Issue

Add a scenario status-transitions-legal. It is a negative control: a connector
walking a completely legal status path must produce no failures at all.

This is the highest-value gap in the corpus. STATUS_TRANSITION_VIOLATION has been
wrong twice, in #128 and again in #155, and #155 found the rule was flagging 22
transitions that the OCPP 1.6 table actually permits. Nothing in the corpus would
have caught that. This scenario is that guard.

What to do

  1. Create
    packages/toolkit/src/scenarios/__scenarios__/status-transitions-legal.ts
  2. Build a synthetic trace that walks a legal path and nothing else:
    • BootNotification at 2026-02-01T10:00:00.000Z, and its CallResult with
      interval: 300
    • StatusNotification on connector 1 with errorCode: 'NoError' at each of
      these times and statuses, each with its own CallResult:
      10:00:30.000Z Available, 10:01:00.000Z Preparing,
      10:02:00.000Z Charging, 10:03:00.000Z Finishing,
      10:04:00.000Z Available
    • Heartbeat at 10:05:00.000Z, and its CallResult
  3. Set expectedFailures: []
  4. Add { type: 'no_failures', params: {} } as the assertion
  5. Import and register in packages/toolkit/src/scenarios/index.ts
  6. Update the scenario count in every place that states it, see "Files to modify"
  7. Run ocpp-debugkit ci, then the full local check from
    Verify Locally.
    ocpp-debugkit ci covers neither formatting nor lint nor types, and CI stops at
    the first failure.
  8. Add a changeset with pnpm changeset, and pick patch. See
    How to Add a Scenario.

Why those statuses

Every step is a transition the section 4.9 table permits:
Available -> Preparing -> Charging -> Finishing -> Available. The trailing
Heartbeat keeps the heartbeat rules quiet, and the whole trace finishes inside
twice the 300 second interval so TIMEOUT_NO_HEARTBEAT stays silent too. This
trace was run against the detection engine and reports no failures.

Files to modify

  • packages/toolkit/src/scenarios/__scenarios__/status-transitions-legal.ts (new)
  • packages/toolkit/src/scenarios/index.ts (register, and add to scenarioNames)
  • packages/toolkit/src/scenarios/index.test.ts (count, name order, getScenario)
  • tests/external-fixture/test.mjs (count)
  • README.md (count)
  • packages/toolkit/README.md (count)
  • .changeset/ (new changeset file)

Only the first two of the count sites fail the suite when they drift, so the two
READMEs are easy to miss. Do not touch the detection-rule count, which is a
different number and stays at 16.

Guidelines

  • All data must be synthetic. This scenario reserves station ID
    CS-SYNTHETIC-022, so please use that one, and number the idTag to match if
    you add one.
  • meter-value-zero.ts is the closest existing negative control to copy the shape
    from.
  • Verify with ocpp-debugkit scenario run status-transitions-legal that no
    failures are reported. If a rule does fire, fix the trace rather than adding the
    code to expectedFailures. Staying clean is the entire point of this scenario.
  • The scenario count depends on what has merged ahead of you. Run the suite and use
    the number it reports rather than assuming.
  • Branch off current main, not off another scenario branch.

How to claim

Comment "I'd like to work on this" and it will be assigned to you.

Please hold one open claim at a time. Once the pull request for it is merged, say
which issue you want next and it will be assigned.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions