]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/log
e-mobility-charging-stations-simulator.git
3 weeks agochore: release main (#1851) cli@v4.7.3 ocpp-server@v4.7.3 simulator@v4.7.3 ui-common@v4.7.3 v4.7 web@v4.7.3
Jérôme Benoit [Wed, 13 May 2026 17:03:51 +0000 (19:03 +0200)] 
chore: release main (#1851)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks agochore(deps): lock file maintenance (#1853)
renovate[bot] [Wed, 13 May 2026 12:30:06 +0000 (14:30 +0200)] 
chore(deps): lock file maintenance (#1853)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agofix(deps): update all non-major dependencies (#1855)
renovate[bot] [Wed, 13 May 2026 12:14:59 +0000 (14:14 +0200)] 
fix(deps): update all non-major dependencies (#1855)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore(deps): update all non-major dependencies (#1854)
renovate[bot] [Tue, 12 May 2026 12:08:05 +0000 (14:08 +0200)] 
chore(deps): update all non-major dependencies (#1854)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agobuild: add --interpreted-frames-native-stack to profiling scripts
Jérôme Benoit [Mon, 11 May 2026 23:41:47 +0000 (01:41 +0200)] 
build: add --interpreted-frames-native-stack to profiling scripts

3 weeks agobuild: add dev profiling script and fix prod profiling
Jérôme Benoit [Mon, 11 May 2026 23:32:27 +0000 (01:32 +0200)] 
build: add dev profiling script and fix prod profiling

3 weeks agochore(deps): update all non-major dependencies (#1852)
renovate[bot] [Mon, 11 May 2026 21:42:15 +0000 (23:42 +0200)] 
chore(deps): update all non-major dependencies (#1852)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agofix(test): mock router.push in all remaining test files
Jérôme Benoit [Mon, 11 May 2026 21:37:20 +0000 (23:37 +0200)] 
fix(test): mock router.push in all remaining test files

3 weeks agofix(test): mock router.push to return Promise in all test files
Jérôme Benoit [Mon, 11 May 2026 21:30:32 +0000 (23:30 +0200)] 
fix(test): mock router.push to return Promise in all test files

3 weeks agofix(test): mock router.push to return Promise
Jérôme Benoit [Mon, 11 May 2026 21:23:55 +0000 (23:23 +0200)] 
fix(test): mock router.push to return Promise

3 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Mon, 11 May 2026 21:13:13 +0000 (21:13 +0000)] 
[autofix.ci] apply automated fixes

3 weeks agofix(lint): enable Vue strictTypeChecked and fix config
Jérôme Benoit [Mon, 11 May 2026 21:09:48 +0000 (23:09 +0200)] 
fix(lint): enable Vue strictTypeChecked and fix config

3 weeks agorefactor: consolidate object-check utilities to eliminate duplication
Jérôme Benoit [Mon, 11 May 2026 19:20:30 +0000 (21:20 +0200)] 
refactor: consolidate object-check utilities to eliminate duplication

Replace type() + isObject with a single isPlainObject helper.
Make isJsonObject and assertIsJsonObject delegate through it
instead of duplicating the check logic independently.

3 weeks agorefactor: remove unnecessary type assertions across monorepo
Jérôme Benoit [Mon, 11 May 2026 18:43:22 +0000 (20:43 +0200)] 
refactor: remove unnecessary type assertions across monorepo

- Remove all @typescript-eslint/no-unnecessary-type-assertion violations
- Add assertIsJsonObject/isJsonObject utilities for runtime-safe narrowing
- Restructure OCPP16RequestService.buildRequestPayload with proper
  runtime validation (assertIsJsonObject + OCPPError) replacing unsafe cast
- Use _syncResult assignment pattern in OCPPResponseService for
  no-floating-promises compliance while preserving isAsyncFunction pattern
- Refine AsyncLock.runExclusive fn parameter as union of function types
  for proper isAsyncFunction type guard narrowing
- Configure varsIgnorePattern: '^_' for @typescript-eslint/no-unused-vars
- Remove unused type imports in test files

3 weeks agochore: remove unnecessary overrides and minimumReleaseAgeExclude
Jérôme Benoit [Mon, 11 May 2026 16:42:31 +0000 (18:42 +0200)] 
chore: remove unnecessary overrides and minimumReleaseAgeExclude

3 weeks agofix: regenerate lockfile matching overrides configuration
Jérôme Benoit [Mon, 11 May 2026 16:38:27 +0000 (18:38 +0200)] 
fix: regenerate lockfile matching overrides configuration

3 weeks agochore: regenerate lockfile with pnpm 11
Jérôme Benoit [Mon, 11 May 2026 16:31:58 +0000 (18:31 +0200)] 
chore: regenerate lockfile with pnpm 11

3 weeks agofix: set allowBuilds placeholders to false
Jérôme Benoit [Mon, 11 May 2026 13:18:23 +0000 (15:18 +0200)] 
fix: set allowBuilds placeholders to false

3 weeks agochore(deps): update pnpm to v11 (#1850)
renovate[bot] [Mon, 11 May 2026 13:14:03 +0000 (15:14 +0200)] 
chore(deps): update pnpm to v11 (#1850)

* chore(deps): update pnpm to v11

* fix: migrate pnpm settings from package.json to pnpm-workspace.yaml

pnpm 11 no longer reads the 'pnpm' field from package.json.
Move patchedDependencies and allowBuilds to pnpm-workspace.yaml.
Remove dead pnpm field from package.json.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com>
3 weeks agofix(ci): lowercase badge label for consistency
Jérôme Benoit [Mon, 11 May 2026 00:51:24 +0000 (02:51 +0200)] 
fix(ci): lowercase badge label for consistency

3 weeks agofix(ci): use stable v1.4.2 release of github-repo-stats
Jérôme Benoit [Mon, 11 May 2026 00:32:39 +0000 (02:32 +0200)] 
fix(ci): use stable v1.4.2 release of github-repo-stats

HEAD (b1ef746a) has a first-run bug where ghrs-data/ directory is not
created before write. Fall back to the stable v1.4.2 release.

3 weeks agoci: replace clone-count with jgehrcke/github-repo-stats
Jérôme Benoit [Mon, 11 May 2026 00:28:57 +0000 (02:28 +0200)] 
ci: replace clone-count with jgehrcke/github-repo-stats

- Replace fragile MShawon/github-clone-count-badge (unversioned curl)
  with jgehrcke/github-repo-stats (SHA-pinned, proper deduplication)
- Add schneegans/dynamic-badges-action for shields.io endpoint badge
- Pin all actions to full commit SHA (supply chain hardening)
- Add permissions, concurrency, and timeout-minutes
- Remove obsolete CLONE.md
- Rename workflow file to repo-stats.yml

3 weeks agochore(deps): update commitlint monorepo to v21 (#1848)
renovate[bot] [Sun, 10 May 2026 11:38:18 +0000 (13:38 +0200)] 
chore(deps): update commitlint monorepo to v21 (#1848)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore(deps): update dependency lint-staged to ^17.0.4 (#1847)
renovate[bot] [Sun, 10 May 2026 11:37:54 +0000 (13:37 +0200)] 
chore(deps): update dependency lint-staged to ^17.0.4 (#1847)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore: release main (#1846) cli@v4.7.2 ocpp-server@v4.7.2 simulator@v4.7.2 ui-common@v4.7.2 web@v4.7.2
Jérôme Benoit [Sat, 9 May 2026 18:15:07 +0000 (20:15 +0200)] 
chore: release main (#1846)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Sat, 9 May 2026 17:19:04 +0000 (17:19 +0000)] 
[autofix.ci] apply automated fixes

3 weeks agofix: resolve #1244 — add per-connector maximum power support (#1843)
github-actions[bot] [Sat, 9 May 2026 17:15:55 +0000 (19:15 +0200)] 
fix: resolve #1244 — add per-connector maximum power support (#1843)

* feat(charging-station): add per-connector maximum power support

Add maximumPower field to ConnectorStatus representing the physical
limitation of each connector cable/plug (thermal current rating).

Per OCPP Device Model, AvailablePowerMaxLimit is defined at the
Connector component level. The connector maximumPower acts as a
hardware cap in the power computation pipeline alongside the station-
level powerDivider sharing mechanism.

- Add ConnectorStatus.maximumPower?: number (in W)
- Initialize at boot via initializeConnectorsMaximumPower(): default
  is stationPower / staticConnectorCount (using static count, not
  dynamic powerDivider which can be 0 in shared mode at init)
- Clamp in getConnectorMaximumAvailablePower as additional min() term
- Use in getConnectorChargingProfilesLimit as primary cap (falls back
  to stationPower/powerDivider for backward compat)
- Update 6 shared-mode templates with explicit maximumPower per
  connector (= station power for DC shared-bus stations)

Resolves #1244

* chore(sandcastle): update validation and main scripts

* chore: sync release-please manifests and sandcastle prompt

* fix(charging-station): exclude index 0 from staticCount in getDefaultConnectorMaximumPower

The staticCount calculation included EVSE 0 and connector 0, while runtime
getPowerDivider excludes them. This caused connector hardware caps to be
more restrictive than intended (e.g., stationPower/3 instead of
stationPower/2 on a 2-EVSE station with EVSE 0 defined).

* [autofix.ci] apply automated fixes

* refactor(charging-station): add NaN guard to connectorHardwareMaximumPower in min()

Align the connectorHardwareMaximumPower entry with the same null/NaN guard
pattern used by all other entries in the min() call for consistency and
defensive robustness.

* docs: document per-connector maximumPower in template examples

Add maximumPower field to Connectors and Evses section examples.
Clarify powerSharedByConnectors behavior description.

---------

Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com>
Co-authored-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks agochore(deps): update actions/dependency-review-action action to v5 (#1845)
renovate[bot] [Sat, 9 May 2026 17:07:44 +0000 (19:07 +0200)] 
chore(deps): update actions/dependency-review-action action to v5 (#1845)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore(deps): update all non-major dependencies (#1844)
renovate[bot] [Sat, 9 May 2026 13:47:27 +0000 (15:47 +0200)] 
chore(deps): update all non-major dependencies (#1844)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore: release main (#1842) cli@v4.7.1 ocpp-server@v4.7.1 simulator@v4.7.1 ui-common@v4.7.1 web@v4.7.1
Jérôme Benoit [Fri, 8 May 2026 18:55:37 +0000 (20:55 +0200)] 
chore: release main (#1842)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks agofix(ui/web): smooth icon-btn danger hover shadow and remove dead token
Jérôme Benoit [Fri, 8 May 2026 18:45:44 +0000 (20:45 +0200)] 
fix(ui/web): smooth icon-btn danger hover shadow and remove dead token

- Add box-shadow to .modern-icon-btn transition shorthand so the danger
  variant hover glow animates instead of snapping
- Remove --skin-shadow-color (declared line 61 but never consumed)

3 weeks agofix(ui/web): fix editable pill hover visibility in light themes
Jérôme Benoit [Fri, 8 May 2026 18:30:30 +0000 (20:30 +0200)] 
fix(ui/web): fix editable pill hover visibility in light themes

Refactor pill background to use scoped --_pill-bg and --_pill-bg-hover
custom properties (MD3 pattern). Each variant co-locates its base and
hover background values, and light-mode overrides reassign both.

The hover rule simply consumes var(--_pill-bg-hover), eliminating the
specificity battle that prevented the hover effect from appearing in
light themes.

3 weeks agorefactor(ui/web): remove redundant connector status column from classic skin
Jérôme Benoit [Fri, 8 May 2026 18:00:49 +0000 (20:00 +0200)] 
refactor(ui/web): remove redundant connector status column from classic skin

The connector status is now accessible via the Set Status dropdown in
the Actions column, making the dedicated read-only Status column
redundant. Move status/error-code selects to the top of Actions and
style them to fill the column width consistently with buttons.

3 weeks agofix(sandcastle): patch pi thinking option and replace type indirections
Jérôme Benoit [Fri, 8 May 2026 15:08:22 +0000 (17:08 +0200)] 
fix(sandcastle): patch pi thinking option and replace type indirections

Apply pnpm patch for @ai-hero/sandcastle porting PR #584 (pi --thinking
flag). Wire the thinking option through agentProvider() and replace
Awaited<ReturnType<...>> indirections with direct type imports (Sandbox,
SandboxRunResult, RunResult, PiOptions).

3 weeks agofix(sandcastle): wire reasoning effort through to agent providers
Jérôme Benoit [Fri, 8 May 2026 14:09:44 +0000 (16:09 +0200)] 
fix(sandcastle): wire reasoning effort through to agent providers

Pass AGENT_*_EFFORT constants through agentProvider() to the opencode
provider's variant flag. LoopStrategy gains actorEffort/criticEffort
optional overrides following the same pattern as actorModel/criticModel.

- opencode: effort mapped to --variant CLI flag
- pi: no effort support (provider limitation, param silently ignored)

3 weeks agofix(deps): update all non-major dependencies (#1840)
renovate[bot] [Fri, 8 May 2026 13:49:01 +0000 (15:49 +0200)] 
fix(deps): update all non-major dependencies (#1840)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore(deps): update dependency mypy to v2 (#1841)
renovate[bot] [Fri, 8 May 2026 13:42:44 +0000 (15:42 +0200)] 
chore(deps): update dependency mypy to v2 (#1841)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agofix(sandcastle): update pi package to @earendil-works/pi-coding-agent
Jérôme Benoit [Fri, 8 May 2026 12:43:21 +0000 (14:43 +0200)] 
fix(sandcastle): update pi package to @earendil-works/pi-coding-agent

The pi coding agent npm package migrated from @mariozechner/pi-coding-agent
to @earendil-works/pi-coding-agent (repo moved to earendil-works/pi-mono).

3 weeks agochore: release main (#1833) cli@v4.7.0 ocpp-server@v4.7.0 simulator@v4.7.0 ui-common@v4.7.0 web@v4.7.0
Jérôme Benoit [Fri, 8 May 2026 00:04:29 +0000 (02:04 +0200)] 
chore: release main (#1833)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks agofix(sandcastle): add missing JSDoc descriptions to satisfy lint rules
Jérôme Benoit [Thu, 7 May 2026 23:54:12 +0000 (01:54 +0200)] 
fix(sandcastle): add missing JSDoc descriptions to satisfy lint rules

3 weeks agorefactor(sandcastle): remove plannerOutput from TaskSpec
Jérôme Benoit [Thu, 7 May 2026 23:48:28 +0000 (01:48 +0200)] 
refactor(sandcastle): remove plannerOutput from TaskSpec

Raw agent stdout will be handled by sandcastle's own debug/logging
mechanism rather than stored in-memory on TaskSpec. Structured fields
(acceptanceCriteria, rootCauseHypothesis, confidence, issueType) remain
as the sole inter-agent communication channel.

3 weeks agorefactor(sandcastle): remove redundant lastFindings from LoopResult
Jérôme Benoit [Thu, 7 May 2026 23:33:21 +0000 (01:33 +0200)] 
refactor(sandcastle): remove redundant lastFindings from LoopResult

Derive last-round findings from roundHistory.at(-1)?.findings in
finalizer.ts instead of maintaining a separate field. The PR body
now shows all critic findings from the final round (including LOW
confidence) for full transparency.

3 weeks agofix(sandcastle): assign opus to actor, sonnet to planner, increase planner iterations
Jérôme Benoit [Thu, 7 May 2026 23:20:58 +0000 (01:20 +0200)] 
fix(sandcastle): assign opus to actor, sonnet to planner, increase planner iterations

Swap model assignments: claude-opus-4.6 (high effort) for the actor,
claude-sonnet-4.6 (medium effort) for the planner. Increase planner
maxIterations from 1 to 5 so it can actually read AGENTS.md and
project context before producing its analysis.

3 weeks agofeat(sandcastle): enrich planner with acceptance criteria and root cause hypothesis
Jérôme Benoit [Thu, 7 May 2026 23:04:27 +0000 (01:04 +0200)] 
feat(sandcastle): enrich planner with acceptance criteria and root cause hypothesis

The planner now produces structured analysis per issue: issueType,
confidence, rootCauseHypothesis, and acceptanceCriteria. These flow
into the actor prompt (confidence-gated hypothesis + criteria) and the
critic prompt (criteria as verification checklist).

- Confidence controls plan specificity: high → full context, medium/low → criteria only
- All planner-generated fields are sanitized and length-bounded
- Critic evaluates observable outcomes, never plan adherence
- Backward-compatible: missing fields result in empty template variables

3 weeks agofeat(sandcastle): add roundHistory to LoopResult and plannerOutput to TaskSpec
Jérôme Benoit [Thu, 7 May 2026 22:36:27 +0000 (00:36 +0200)] 
feat(sandcastle): add roundHistory to LoopResult and plannerOutput to TaskSpec

Replace the unused onRoundComplete callback with a structured
roundHistory array that accumulates RoundSnapshot per round
(including post-loop validation retry). Attach raw planner stdout
to TaskSpec.plannerOutput for downstream verification use.

This enables a future planner-verification step to receive the full
findings history alongside the original plan context.

3 weeks agofix(ui): allow changing status of individual connectors (#1834)
github-actions[bot] [Thu, 7 May 2026 21:56:02 +0000 (23:56 +0200)] 
fix(ui): allow changing status of individual connectors (#1834)

* feat(ui/web): allow changing status of individual connectors

Add a 'Set Status' action to the connector UI in both modern and classic
skins. Users can simulate OCPP connector statuses (e.g. Faulted, Unavailable)
directly from the dashboard.

- UIClient.setConnectorStatus sends STATUS_NOTIFICATION via existing ProcedureName
- useConnectorActions exposes setConnectorStatus with pending.setStatus guard
- Modern skin: SetConnectorStatusDialog presents a status picker in a modal
- Classic skin: inline <select> triggers status change on change event
- Test helpers and composable tests updated accordingly

* fix: correct OCPP version handling for connector status changes

- Add OCPP20ConnectorStatusEnumType enum to ui-common
- Fix UIClient.setConnectorStatus to send version-aware payload:
  connectorStatus field for OCPP 2.0.x, status field for OCPP 1.6
- Update useConnectorActions to accept ocppVersion and pass it through;
  widen status parameter type to union of 1.6 and 2.0.x enums;
  accept optional onSuccess callback per action invocation
- Fix SetConnectorStatusDialog to close only after action resolves
  (pass close as onSuccess instead of calling it immediately)
- Show version-appropriate status options in SetConnectorStatusDialog
- Forward ocppVersion and onRefresh from ConnectorRow to dialog
- Propagate need-refresh event through ConnectorRow → StationCard → ModernLayout
- Add tests for new OCPP 2.0.x paths and dialog behaviour

* [autofix.ci] apply automated fixes

* feat(ui): complete connector status change with error simulation and local state update

- Fix classic skin to show version-appropriate status options (OCPP 1.6/2.0.x)
- Pass ocppVersion to useConnectorActions in classic skin
- Replace passthrough STATUS_NOTIFICATION handler with sendAndSetConnectorStatus
  to update in-memory connector state and emit connectorStatusChanged event
- Add OCPP 1.6 errorCode support (issue requests error simulation capability)
- Add OCPP16ChargePointErrorCode enum to ui-common
- Add error code selector in both skins (OCPP 1.6 only, hidden for 2.0.x)
- Remove unnecessary re-exports from useConnectorActions composable
- Update tests for new errorCode parameter and passthrough behavior change

Resolves the outstanding HIGH findings from automated review.

* fix(ui): polish connector status — reactivity consistency, JSDoc, tests, init from current status

- Wrap props in computed() in SetConnectorStatusDialog for consistency
- Fix JSDoc on mountDialog test helper to satisfy jsdoc/require-jsdoc
- Initialize selectedStatus from connector.status for OCPP 2.0.x too
- Add 5 unit tests for classic skin CSConnector status change behavior

* refactor(ui): remove redundant onRefresh from connector actions

The server already pushes a REFRESH notification via WebSocket when
connector state changes (connectorStatusChanged → buildUpdatedMessage →
workerEventUpdated → scheduleClientNotification → REFRESH broadcast).

The onRefresh callback in useConnectorActions duplicated this by manually
calling getChargingStations() after each action. Remove it along with
the need-refresh event bubbling chain in the modern skin.

The useAsyncAction onRefresh mechanism remains available for composables
where the server does NOT push updates (e.g., useStationActions).

* [autofix.ci] apply automated fixes

* refactor(ui-common): extract buildStatusNotificationPayload shared builder

Factor version-aware StatusNotification payload construction into
ui-common alongside existing buildAuthorize/Start/StopTransactionPayload
builders. Both CLI and Web UI now use the shared builder, eliminating
duplicated OCPP 1.6 vs 2.0.x branching logic.

* [autofix.ci] apply automated fixes

* fix(ui-common): keep buildStatusNotificationPayload strongly typed

Remove string fallback from status/errorCode parameters — the builder
accepts only the OCPP enum types. The CLI casts user input at the call
site, keeping the shared API type-safe.

* [autofix.ci] apply automated fixes

* fix(ui-common): remove invalid Occupied from OCPP16ChargePointStatus enum

Occupied is an OCPP 2.0.x-only connector status. It was erroneously
included in the OCPP 1.6 enum, causing the UI dropdown to offer an
invalid status option for OCPP 1.6 stations. Tests referencing it are
updated to use OCPP20ConnectorStatusEnumType.OCCUPIED or a valid 1.6
status as appropriate.

* fix(ui-common): make ChargePointStatus a union of OCPP 1.6 and 2.0.x enums

ChargePointStatus was aliased to OCPP16ChargePointStatus only, which
made ConnectorStatus.status unable to represent OCPP 2.0.x values like
Occupied. Now it is OCPP16ChargePointStatus | OCPP20ConnectorStatusEnumType,
matching the src/ canonical ConnectorStatusEnum pattern.

* refactor(ui-common): use ChargePointStatus type alias instead of inline union

Replace all occurrences of the verbose
'OCPP16ChargePointStatus | OCPP20ConnectorStatusEnumType' inline union
with the existing ChargePointStatus type alias across ui-common, web UI,
and CLI.

* [autofix.ci] apply automated fixes

* fix: add connectorId guard to handleStatusNotification for consistency

Other broadcast channel handlers (handleMeterValues, UNLOCK_CONNECTOR,
LOCK_CONNECTOR) throw BaseError when connectorId is missing. Without
this guard, a malformed request would silently succeed.

* fix(ui): address review feedback — clickable status pill, stale state sync, error-code apply

Modern skin:
- Replace 'Set Status' button with clickable status pill (edit icon on
  hover, tooltip with status, aria-haspopup=dialog). More compact UX per
  reviewer request (DerGenaue).
- Add .modern-pill--editable CSS with hover border, focus ring, and
  fade-in edit icon.

Classic skin:
- Add watch on props.connector.status to sync selectedStatus ref when
  server pushes new state (fixes stale dropdown after external changes).
- Add @change handler on error-code select so changing errorCode alone
  also triggers a StatusNotification (previously only status change did).

Addresses review feedback from hyperspace-insights, copilot, and
DerGenaue.

* fix: persist errorCode on ConnectorStatus, remove Partial<> cast, add tooltip

Backend:
- Add errorCode field to ConnectorStatus (src/ and ui-common)
- Persist errorCode in sendAndSetConnectorStatus alongside status
- Move errorCode defaulting from buildStatusNotificationRequest to
  OCPP16RequestService.buildRequestPayload via spread default pattern:
  { errorCode: NO_ERROR, ...commandParams }
- Remove Partial<> cast and ?? fallback from the builder — it now
  simply passes through commandParams.errorCode (always defined by
  the time it reaches the builder)

UI:
- Status pill tooltip shows errorCode when present and not NoError
  (e.g., 'Faulted (ConnectorLockFailure)'), per DerGenaue's request
- ConnectorStatus.errorCode propagates automatically through existing
  buildUpdatedMessage → spread serialization chain

* fix(ui): address DerGenaue feedback — always-visible icon, preserve pill height

- Edit icon always visible (no hover-only opacity transition)
- Smaller icon (8px) + reduced gap (3px) to preserve original pill height
- Simpler pencil SVG (single path, thicker stroke for clarity at small size)
- Removed opacity animation rules

* fix(ui): editable status pill design (#1838)

* fix: validate status field in handleStatusNotification

Prevents connectorStatus.status corruption when ocppStrictCompliance is
disabled and the payload arrives without a status value.

---------

Co-authored-by: OpenCode Agent <agent@opencode.ai>
Co-authored-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com>
Co-authored-by: Daniel <7558512+DerGenaue@users.noreply.github.com>
3 weeks agofix(web): fetch templates on dialog open via layout composable (#1837) (#1839)
github-actions[bot] [Thu, 7 May 2026 21:33:27 +0000 (23:33 +0200)] 
fix(web): fetch templates on dialog open via layout composable (#1837) (#1839)

Expose getTemplates from useLayoutData instead of duplicating the fetch
in useAddStationsForm. Each layout triggers the refresh at the right
moment:

- Modern skin: watch showAddDialog → getTemplates() on open
- Classic skin: watch route → getTemplates() on ADD_CHARGING_STATIONS

The templatesEqual guard in useAddStationsForm prevents resetting the
user's selection when the refetch returns an identical list.

Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com>
3 weeks agofix(sandcastle): run validation across all workspace packages
Jérôme Benoit [Thu, 7 May 2026 20:43:24 +0000 (22:43 +0200)] 
fix(sandcastle): run validation across all workspace packages

3 weeks agofix(sandcastle): increase validation timeout to 600s
Jérôme Benoit [Thu, 7 May 2026 20:40:15 +0000 (22:40 +0200)] 
fix(sandcastle): increase validation timeout to 600s

4 weeks agofix(sandcastle): add configurable agent provider (pi/opencode)
Jérôme Benoit [Thu, 7 May 2026 19:33:28 +0000 (21:33 +0200)] 
fix(sandcastle): add configurable agent provider (pi/opencode)

Introduce AGENT_PROVIDER constant to switch between pi and opencode backends.
pi streams JSON output immediately, avoiding the opencode idle timeout bug
where git check-ignore indexing produces zero stdout.

Also removes redundant copyToWorktree since onSandboxReady pnpm install
handles node_modules via the mounted pnpm store.

4 weeks agofix(sandcastle): revert idle timeout to 300s and remove redundant copyToWorktree
Jérôme Benoit [Thu, 7 May 2026 18:26:40 +0000 (20:26 +0200)] 
fix(sandcastle): revert idle timeout to 300s and remove redundant copyToWorktree

The 600s timeout was a misguided workaround for serena MCP init. The actual
root cause is an opencode bug: zero stdout during its git check-ignore
indexing phase. Removing copyToWorktree since pnpm install in onSandboxReady
already handles node_modules via the mounted pnpm store.

4 weeks agochore(sandcastle): increase idle timeout to 600s for MCP init
Jérôme Benoit [Thu, 7 May 2026 17:00:49 +0000 (19:00 +0200)] 
chore(sandcastle): increase idle timeout to 600s for MCP init

4 weeks agoci(sandcastle): schedule daily run at midnight Europe/Paris
Jérôme Benoit [Thu, 7 May 2026 16:46:03 +0000 (18:46 +0200)] 
ci(sandcastle): schedule daily run at midnight Europe/Paris

4 weeks agochore(deps): update dependency lint-staged to v17 (#1836)
renovate[bot] [Thu, 7 May 2026 16:23:11 +0000 (18:23 +0200)] 
chore(deps): update dependency lint-staged to v17 (#1836)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agochore(sandcastle): set planner effort to high
Jérôme Benoit [Thu, 7 May 2026 10:40:16 +0000 (12:40 +0200)] 
chore(sandcastle): set planner effort to high

4 weeks agochore(sandcastle): add agent effort constants (future use)
Jérôme Benoit [Thu, 7 May 2026 10:39:27 +0000 (12:39 +0200)] 
chore(sandcastle): add agent effort constants (future use)

4 weeks agochore(deps): update all non-major dependencies (#1835)
renovate[bot] [Thu, 7 May 2026 09:24:47 +0000 (11:24 +0200)] 
chore(deps): update all non-major dependencies (#1835)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agochore(sandcastle): clarify prompt headings with role taxonomy
Jérôme Benoit [Thu, 7 May 2026 09:20:30 +0000 (11:20 +0200)] 
chore(sandcastle): clarify prompt headings with role taxonomy

4 weeks agorefactor(sandcastle): rename implement-prompt.md to actor-prompt.md
Jérôme Benoit [Thu, 7 May 2026 09:17:22 +0000 (11:17 +0200)] 
refactor(sandcastle): rename implement-prompt.md to actor-prompt.md

4 weeks agodocs(sandcastle): fix stale JSDoc referencing empty string sentinel
Jérôme Benoit [Thu, 7 May 2026 08:57:20 +0000 (10:57 +0200)] 
docs(sandcastle): fix stale JSDoc referencing empty string sentinel

4 weeks agorefactor(sandcastle): add error observability and type-safe sentinels
Jérôme Benoit [Thu, 7 May 2026 08:53:45 +0000 (10:53 +0200)] 
refactor(sandcastle): add error observability and type-safe sentinels

- Add failureReason to LoopResult for post-mortem debugging
- Replace captureHeadSha sentinel '' with null (type-safe)
- discover() throws on planner failure (no hidden process.exitCode)
- Add console.debug in hashContextLines for dedup diagnostics

4 weeks agorefactor(sandcastle): improve separation of concerns and API clarity
Jérôme Benoit [Thu, 7 May 2026 08:43:02 +0000 (10:43 +0200)] 
refactor(sandcastle): improve separation of concerns and API clarity

- Extract runValidation into validation.ts
- Encapsulate nonce in loop (remove from strategy interface)
- Delete dead GRACE_TIMEOUT_MS constant
- Reorganize constants into proper domain groups
- Un-export FindingSchema and extractStderr

4 weeks agorefactor(sandcastle): generalize actor/critic loop with LoopContext and coherent API
Jérôme Benoit [Thu, 7 May 2026 08:25:26 +0000 (10:25 +0200)] 
refactor(sandcastle): generalize actor/critic loop with LoopContext and coherent API

- Introduce LoopContext to group invariant params (spec, sandbox, strategy, baseBranch, signal)
- Extract GIT_BASE_BRANCH constant, thread through loop + finalization + prompts
- Rename 'implementer' to 'actor' in generic loop code
- Add extensibility: validate?, actorModel?, criticModel? on LoopStrategy
- Add baseBranch to RefinementLoopOptions and LoopResult
- Make Finding.category extensible (z.string())
- Make TaskSpec.labels optional
- Fix param ordering: pushBranch(spec, cwd, ...), deduplicateFindings(findings, cwd, ...)
- Simplify root lint-staged to cover all TS files

4 weeks agochore: simplify root lint-staged config to cover all TS files
Jérôme Benoit [Thu, 7 May 2026 07:24:19 +0000 (09:24 +0200)] 
chore: simplify root lint-staged config to cover all TS files

4 weeks agorefactor(sandcastle): remove StrategyConfig type alias, inline intersection
Jérôme Benoit [Thu, 7 May 2026 07:13:10 +0000 (09:13 +0200)] 
refactor(sandcastle): remove StrategyConfig type alias, inline intersection

4 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Thu, 7 May 2026 06:57:35 +0000 (06:57 +0000)] 
[autofix.ci] apply automated fixes

4 weeks agorefactor(sandcastle): organize constants by domain with coherent naming
Jérôme Benoit [Thu, 7 May 2026 06:49:45 +0000 (08:49 +0200)] 
refactor(sandcastle): organize constants by domain with coherent naming

4 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Thu, 7 May 2026 06:45:27 +0000 (06:45 +0000)] 
[autofix.ci] apply automated fixes

4 weeks agochore(sandcastle): use gpt-5.4 as critic model
Jérôme Benoit [Thu, 7 May 2026 06:42:17 +0000 (08:42 +0200)] 
chore(sandcastle): use gpt-5.4 as critic model

4 weeks agorefactor(sandcastle): split AGENT_MODEL into per-role constants
Jérôme Benoit [Thu, 7 May 2026 06:40:37 +0000 (08:40 +0200)] 
refactor(sandcastle): split AGENT_MODEL into per-role constants

4 weeks agofix(sandcastle): improve PR metadata accuracy
Jérôme Benoit [Wed, 6 May 2026 23:57:51 +0000 (01:57 +0200)] 
fix(sandcastle): improve PR metadata accuracy

4 weeks agochore(sandcastle): install uv, harden APT setup, add memories to prompts
Jérôme Benoit [Wed, 6 May 2026 23:18:06 +0000 (01:18 +0200)] 
chore(sandcastle): install uv, harden APT setup, add memories to prompts

4 weeks agochore(sandcastle): install uv, harden APT repo setup
Jérôme Benoit [Wed, 6 May 2026 22:44:33 +0000 (00:44 +0200)] 
chore(sandcastle): install uv, harden APT repo setup

- Add uv via griffo.io APT (provides uvx for MCP servers in sandbox)
- Eliminate pipe patterns to prevent silent download failures
- Migrate GitHub CLI key to /etc/apt/keyrings/
- Remove gpg from base deps (no longer needed)

4 weeks agochore(sandcastle): install uv via griffo.io APT for MCP server support
Jérôme Benoit [Wed, 6 May 2026 22:35:32 +0000 (00:35 +0200)] 
chore(sandcastle): install uv via griffo.io APT for MCP server support

4 weeks agochore(sandcastle): increase MAX_PARALLEL to 5
Jérôme Benoit [Wed, 6 May 2026 22:24:47 +0000 (00:24 +0200)] 
chore(sandcastle): increase MAX_PARALLEL to 5

4 weeks agochore(sandcastle): increase MAX_CRITIC_ROUNDS to 10
Jérôme Benoit [Wed, 6 May 2026 21:56:49 +0000 (23:56 +0200)] 
chore(sandcastle): increase MAX_CRITIC_ROUNDS to 10

4 weeks agochore(sandcastle): remove requirements doc from repo (kept externally)
Jérôme Benoit [Wed, 6 May 2026 19:54:04 +0000 (21:54 +0200)] 
chore(sandcastle): remove requirements doc from repo (kept externally)

4 weeks agochore(sandcastle): increase timeouts for large repo tasks
Jérôme Benoit [Wed, 6 May 2026 19:30:24 +0000 (21:30 +0200)] 
chore(sandcastle): increase timeouts for large repo tasks

CI job timeout: 60min → 120min
Task timeout: 15min → 100min (allows 5 full critic rounds)
Also adds parallel decomposition requirements doc and logs planner errors.

4 weeks agofix(sandcastle): pre-create .local/share dirs in Dockerfile
Jérôme Benoit [Wed, 6 May 2026 18:47:38 +0000 (20:47 +0200)] 
fix(sandcastle): pre-create .local/share dirs in Dockerfile

Docker creates intermediate directories as root:root for bind mounts.
Pre-creating /home/agent/.local/share/pnpm/store and opencode with
correct ownership prevents EACCES when opencode writes to its data dir.

4 weeks agofix(sandcastle): remove corepack prepare from Dockerfile
Jérôme Benoit [Wed, 6 May 2026 18:32:12 +0000 (20:32 +0200)] 
fix(sandcastle): remove corepack prepare from Dockerfile

Align with the working Dockerfile from sap-ai-provider. The container
does not need explicit pnpm setup — corepack in node:24 handles it
on demand when pnpm is invoked.

4 weeks agofix(sandcastle): log planner error details instead of swallowing
Jérôme Benoit [Wed, 6 May 2026 18:13:14 +0000 (20:13 +0200)] 
fix(sandcastle): log planner error details instead of swallowing

4 weeks agochore: remove temporary release-as overrides
Jérôme Benoit [Wed, 6 May 2026 17:36:57 +0000 (19:36 +0200)] 
chore: remove temporary release-as overrides

4 weeks agochore: release main (#1832) cli@v4.6.1 ocpp-server@v4.6.1 simulator@v4.6.1 ui-common@v4.6.1 v4.6 web@v4.6.1
Jérôme Benoit [Wed, 6 May 2026 17:32:34 +0000 (19:32 +0200)] 
chore: release main (#1832)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
4 weeks agofix(deps): override ip-address vulnerability
Jérôme Benoit [Wed, 6 May 2026 17:21:54 +0000 (19:21 +0200)] 
fix(deps): override ip-address vulnerability

4 weeks agochore: force release-as 4.6.1 (temporary, remove after release)
Jérôme Benoit [Wed, 6 May 2026 17:13:04 +0000 (19:13 +0200)] 
chore: force release-as 4.6.1 (temporary, remove after release)

4 weeks agochore: trigger release-please recalculation
Jérôme Benoit [Wed, 6 May 2026 17:05:55 +0000 (19:05 +0200)] 
chore: trigger release-please recalculation

4 weeks agoci: add sandcastle autonomous agent pipeline
Jérôme Benoit [Wed, 6 May 2026 15:53:58 +0000 (17:53 +0200)] 
ci: add sandcastle autonomous agent pipeline

Automated issue→PR workflow using Docker-sandboxed AI agents with an
implement↔critic refinement loop. Includes:

- GitHub issue discovery with planner agent
- Concurrent task execution with AbortSignal-based cooperative timeout
- Quality ratchet with content-addressed dedup and rollback
- Configurable strategy (prompts, validation, finalization)

Also simplifies clone-count workflow to use vars.GIST_ID instead of
auto-provisioned secret, and adds cspell words for sandcastle domain.

4 weeks agochore: update serena project configuration
Jérôme Benoit [Wed, 6 May 2026 13:21:23 +0000 (15:21 +0200)] 
chore: update serena project configuration

4 weeks agofix(deps): update all non-major dependencies (#1830)
renovate[bot] [Wed, 6 May 2026 12:46:23 +0000 (14:46 +0200)] 
fix(deps): update all non-major dependencies (#1830)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agofix(deps): update all non-major dependencies (#1825)
renovate[bot] [Tue, 5 May 2026 21:32:59 +0000 (23:32 +0200)] 
fix(deps): update all non-major dependencies (#1825)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agofix: restore comments lost during rebase conflict resolution
Jérôme Benoit [Sun, 3 May 2026 22:20:13 +0000 (00:20 +0200)] 
fix: restore comments lost during rebase conflict resolution

4 weeks agochore: rename webui component to web for naming consistency
Jérôme Benoit [Sun, 3 May 2026 22:16:34 +0000 (00:16 +0200)] 
chore: rename webui component to web for naming consistency

Align the web UI package name and identifiers with the directory
structure (ui/web) and the CLI convention (ui/cli → cli). Renames
package.json name, release-please component, Dockerfile pnpm filter,
SonarCloud project key, and screenshot asset filename.

4 weeks agochore: release main (#1819) cli@v4.6.0 ocpp-server@v4.6.0 simulator@v4.6.0 ui-common@v4.6.0 web@v4.6.0
Jérôme Benoit [Sun, 3 May 2026 15:43:51 +0000 (17:43 +0200)] 
chore: release main (#1819)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
4 weeks agofix: stop nullifying wsConnection prematurely in close/terminate
Jérôme Benoit [Sat, 2 May 2026 21:41:49 +0000 (23:41 +0200)] 
fix: stop nullifying wsConnection prematurely in close/terminate

closeWSConnection() and terminateWSConnection() set wsConnection to null
immediately after calling close()/terminate(), but the 'close' event
fires asynchronously afterward. The onClose handler then emitted an
'updated' event with wsState undefined (since wsConnection was null),
causing the UI to display 'ws unknown' instead of 'ws closed'.

Remove the null assignments — the stale WebSocket reference is harmless
(overwritten by the next openWSConnection call) and allows onClose to
read the correct readyState (CLOSED=3) when emitting state updates.

4 weeks agofix: do not nullify wsConnection in onError handler
Jérôme Benoit [Sat, 2 May 2026 21:21:24 +0000 (23:21 +0200)] 
fix: do not nullify wsConnection in onError handler

The ws library guarantees that a 'close' event always follows an 'error'
event. Eagerly setting wsConnection to null in onError caused the
subsequent onClose handler to emit an 'updated' event with wsState
undefined, making the UI display 'unknown' instead of 'closed'.

4 weeks agorefactor(webui): remove redundant optimistic fetch from modern skin
Jérôme Benoit [Sat, 2 May 2026 21:08:50 +0000 (23:08 +0200)] 
refactor(webui): remove redundant optimistic fetch from modern skin

Rely solely on server push (ServerNotification.REFRESH) for data refresh
after user actions, eliminating the duplicate getChargingStations() call
that was triggered via the need-refresh event chain.

4 weeks agofix(deps): update dependency zod to ^4.4.2 (#1823)
renovate[bot] [Sat, 2 May 2026 12:42:07 +0000 (14:42 +0200)] 
fix(deps): update dependency zod to ^4.4.2 (#1823)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agofix(deps): update dependency basic-ftp to v6 (#1822)
renovate[bot] [Fri, 1 May 2026 22:43:36 +0000 (00:43 +0200)] 
fix(deps): update dependency basic-ftp to v6 (#1822)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agochore(deps): update sonarsource/sonarqube-scan-action action to v8 (#1821)
renovate[bot] [Fri, 1 May 2026 22:31:10 +0000 (00:31 +0200)] 
chore(deps): update sonarsource/sonarqube-scan-action action to v8 (#1821)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5 weeks agochore: remove stale opencode agent config
Jérôme Benoit [Thu, 30 Apr 2026 18:02:48 +0000 (20:02 +0200)] 
chore: remove stale opencode agent config