Skip to content

Adopt the CLI-scaffold-parity component baseline (#8) - #9

Merged
mbreissi merged 8 commits into
mainfrom
feat/baseline-adoption
Jul 20, 2026
Merged

Adopt the CLI-scaffold-parity component baseline (#8)#9
mbreissi merged 8 commits into
mainfrom
feat/baseline-adoption

Conversation

@mbreissi

@mbreissi mbreissi commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Brings camera-adapter to the CLI-scaffold-parity component baseline (PR edgecommons/edgecommons#57, design core/docs/platform/DESIGN-cli-scaffold-parity.md; contract core/docs/SOUTHBOUND.md §2.2/§5). camera-adapter is a camera, not a signal adapter — sb/read/sb/write/sb/signals/sb/browse are N/A; the focus is the lifecycle verbs, the metric-family pattern, panels, and hygiene.

Per-item checklist

P1 — adapter parity (SOUTHBOUND §2.2 / §5)

  • P1-1 sb/pause / sb/resume — suspend a camera's new capture work (scheduled + commanded); in-flight captures run to completion; new work refused with the stable INSTANCE_PAUSED code; idempotent { paused, changed }; instance-routed; surfaced in sb/status. Pause is process-local (a restart begins unpaused) and scoped to capture workload (sb/reconnect/PTZ/read-only verbs unaffected). (D-CAM-24)
  • P1-2 repoll applicabilityrecorded N/A: this adapter is capture-on-demand and schedule-driven, not poll-based; sb/capture/sb/capture-submit are the on-demand trigger. Recorded in DESIGN.md (D-CAM-24) and docs/reference/messaging-interface.md.
  • P1-3 error-code reconciliationhard rename, no aliases: INVALID_REQUEST/INSTANCE_REQUIREDBAD_ARGS, UNKNOWN_INSTANCENO_SUCH_INSTANCE, CAMERA_UNAVAILABLEDEVICE_UNAVAILABLE. Domain codes (CAPTURE_*, PTZ_*, STORAGE_PRESSURE, …) kept. (D-CAM-23) — see Breaking change below.
  • P1-4 operational-metric family patterncamera_captures converted to (Total, Interval) counter pairs (accumulate → drain on the sampler tick; the interval preserves the every-event guarantee); new CameraCommand family (instance×verb×result, request/error pairs + latency, cells defined lazily). Existing measure semantics kept. camera_queue stays sampled gauges. Recorded cardinality decision (D-CAM-25): camera_captures/camera_queue stay fleet-scoped (no per-camera dim) to avoid 256-streams-per-measure; only the lower-frequency CameraCommand carries instance.
  • P1-5 edge-console panel triooverview/signals/diagnostics via register_panel, order 10/20/30, scope:"instance", bound to the verbs served (overview → sb/status/sb/reconnect/sb/pause/sb/resume). (D-CAM-26)

P2 — hygiene

  • P2-6 governanceAGENTS.md + CLAUDE.md (@AGENTS.md import + local-dev notes). DESIGN.md register extended (D-CAM-23…28).
  • P2-7 config.schema.json — Draft 2020-12 schema whose root models component.global (with $defs/camera for instances + $defs for every backend/profile/schedule/enum), derived field-for-field from src/config.rs; strict where the parser is, permissive only where it is (featureOverrides, resourceGroups). edgecommons component validate reports no findings. (D-CAM-28)
  • P2-8 deploy-docs.yml — hook-guarded docs-rebuild workflow, verbatim from modbus-adapter.
  • P2-9 data-types.md decision — added docs/reference/data-types.md recording the signal value-mapping page is N/A for an image adapter, pointing to messaging-interface.md for the published shapes. (D-CAM-27)
  • P2-10 lockfile policy (SD-B)Cargo.lock committed (git-sourced), /Cargo.lock gitignore + rationale dropped; Dockerfile/dockerignore/MSRV build --locked; RTSP harness keeps its writable-overlay lock. Resolution recorded in DESIGN.md (D-CAM-27).
  • P2-11 license — manifest + README reconciled to BUSL-1.1 (matches LICENSE). Fixes #7.

Breaking change (SD-E) + consumer grep

The error-code rename is wire-visible for any consumer keying on the old strings (INVALID_REQUEST/INSTANCE_REQUIRED/UNKNOWN_INSTANCE/CAMERA_UNAVAILABLE). The component is pre-1.0/experimental; a documented breaking change is acceptable. Consumer grep found no matches for the old strings in edge-console (ui/protocol/gateway source) or bottling-company-test, so no out-of-tree consumer breaks. Called out in docs/reference/messaging-interface.md (current codes) and DESIGN.md (D-CAM-23, migration record).

Validation

  • cargo test --lib: 631 passed, 0 failed, 1 ignored (self-skipping live suite).
  • cargo clippy --all-targets -- -D warnings: clean.
  • cargo llvm-cov --lib: line ~92.9% (≥90 gate); diff coverage 96% (≥95 gate, diff-cover vs origin/main).
  • config.schema.json: validated with a Draft 2020-12 validator (shipped simulator-config.json + DESIGN §10.1 example ACCEPT; five malformed cases REJECT) and with edgecommons component validateOK, no findings (lockfile warning resolved).
  • Fresh-clone build proof: cargo check --locked with the .cargo [patch] inactive resolves the pinned git dep from the committed lock.
  • Linux-gated rtsp/genicam suites and the Docker image build run in CI (the live proxy for this sim-backed adapter).

Fixes #8
Fixes #7

🤖 Generated with Claude Code

https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL

mbreissi and others added 8 commits July 19, 2026 22:20
Bring camera-adapter to the CLI-scaffold-parity southbound contract:

- Error codes (C-2): hard-rename the routing/availability codes to the
  standardized family — INVALID_REQUEST/INSTANCE_REQUIRED -> BAD_ARGS,
  UNKNOWN_INSTANCE -> NO_SUCH_INSTANCE, CAMERA_UNAVAILABLE -> DEVICE_UNAVAILABLE.
  Domain codes (CAPTURE_*, PTZ_*, STORAGE_PRESSURE, ...) are unchanged. No
  aliases. Wire-visible breaking change (D-CAM-23).
- sb/pause / sb/resume (C-1): suspend a camera's new capture work (scheduled and
  commanded); in-flight captures run to completion; new work is refused with the
  stable INSTANCE_PAUSED code; idempotent {paused, changed}; surfaced in
  sb/status. repoll recorded N/A (capture-on-demand adapter). (D-CAM-24)
- Operational metric families (C-3): camera_captures becomes (Total, Interval)
  counter pairs drained on the sampler tick; new CameraCommand family
  (instance x verb x result); camera_captures/camera_queue stay fleet-scoped by
  the recorded cardinality decision. (D-CAM-25)
- Edge-console panel trio (C-4): overview/signals/diagnostics via register_panel,
  order 10/20/30, scope instance, bound to the verbs actually served. (D-CAM-26)

Docs (messaging-interface, metrics, DESIGN register) updated in the same change.
Coverage stays above the 90 line gate; new logic is unit- and integration-tested.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
WS-2/WS-3: add AGENTS.md (component shape, backend seam, config location,
validation expectations, inherited org conventions) and CLAUDE.md (short header +
@AGENTS.md import + local-dev notes), and .github/workflows/deploy-docs.yml so a
doc-only push refreshes the aggregated EdgeCommons docs site for this registered
component.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
WS-7: the Cargo.toml `license` field and the README license line declared
Apache-2.0 while the LICENSE file is Business Source License 1.1. Align both to
BUSL-1.1.

Fixes #7

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
WS-5 (org lockfile policy, SD-B): drop the /Cargo.lock gitignore rule and its
three-way-constraint rationale, and commit Cargo.lock regenerated with the local
.cargo [patch] override inactive so it records the pinned git source and is valid
on a fresh clone / in CI (proved: `cargo check --locked` with the patch inactive
resolves the pin). The Dockerfile now copies the lock and builds `--locked`; the
image dockerignore admits it; the MSRV check runs `--locked`; and the RTSP
native-coverage harness keeps its writable-overlay lock (the read-only source
mount plus the local patch mean cargo must not rewrite the committed lock).
Resolution recorded in DESIGN.md (D-CAM-27).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
Add a failing-target test so both operational drains (camera_captures and
CameraCommand) exercise their emit-error branches — a briefly-unavailable metric
backend must never take a timer-driven drain down with it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
WS-1: author a Draft 2020-12 config.schema.json so `edgecommons component
validate` can check camera-adapter configs and stops warning on the missing
schema. The root models `component.global` (the CLI validates `/component/global`
against it) with `$defs/camera` for one `component.instances[]` entry and `$defs`
for every backend/profile/schedule/enum — derived field-for-field from
`src/config.rs`, strict where the parser is (`deny_unknown_fields`) and permissive
only where it is (`featureOverrides`, `resourceGroups`).

Validated with a Draft 2020-12 validator (shipped simulator-config.json and the
DESIGN §10.1 full example ACCEPT; a malformed global key, an ONVIF backend missing
`mediaProfile`, a bad enum, an unknown backend field, and a camera missing
`backend` REJECT) and with `edgecommons component validate` — no findings.
Recorded in DESIGN.md (D-CAM-28).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
…rce)

The baseline-adoption worktree is nested inside the main camera-adapter checkout, whose gitignored
.cargo/config.toml [patch] override is discovered by Cargo's ancestor walk — so the initial
generate-lockfile resolved edgecommons as a LOCAL PATH source, producing a Cargo.lock that would not
resolve on a fresh clone or in CI (the "fresh-clone proof" false-passed only because the sibling path
still existed). Regenerated in an isolated clone outside the ancestry; the sole change is the git
source line on the edgecommons entry (validated with `cargo metadata --locked`). All other pins
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
Review M3: DESIGN.md §12/§13 normative sections still documented the OLD error
codes as the live set, contradicting the hard rename in the code and
messaging-interface.md. Rewrite them to the standardized codes:

- §13.13 error catalog: INSTANCE_REQUIRED/INVALID_REQUEST collapse to BAD_ARGS,
  UNKNOWN_INSTANCE -> NO_SUCH_INSTANCE, CAMERA_UNAVAILABLE -> DEVICE_UNAVAILABLE,
  and add INSTANCE_PAUSED. Domain codes (CAPTURE_*, PTZ_*, ...) unchanged.
- §12 error example and §13.1 instance-selection / group-validation spec lines
  renamed to match.
- Also add the missing sb/pause / sb/resume rows to the §13 verb table (stale
  vs the shipped 16-verb surface).

The D-CAM-23 decision-register entry keeps the old->new mapping intact as the
migration record. Docs-only; no code or coverage impact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxV5wFi7LCratBERVT6aiL
@mbreissi
mbreissi marked this pull request as ready for review July 20, 2026 15:31
@mbreissi
mbreissi merged commit 2002302 into main Jul 20, 2026
5 checks passed
@mbreissi
mbreissi deleted the feat/baseline-adoption branch July 20, 2026 15:59
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