Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openspec/changes/consolidate-specs/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-04
62 changes: 62 additions & 0 deletions openspec/changes/consolidate-specs/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## Context

This change stacks on top of PR #258 (`migrate-specs-to-v4`), which made all 35 specs pass `openspec validate --specs --strict`. That left the *organization* problem untouched: 35 flat spec directories of inconsistent scope. The forcing function is scale — SBMD device drivers are expected to grow to 50–100+, and OpenSpec discovery is flat (one directory deep), so neither per-driver specs nor subdirectories are viable.

Key facts grounding the design:
- Each `.sbmd.js` driver declares exactly one `deviceClass`; the device-class set is bounded (~8: light, doorLock, thermostat, sensor, environmentalSensor, airQualitySensor, + planned windowCovering, presence, lightController).
- Concrete drivers are already validated by `scripts/ci/validate_sbmd_v4_specs.py` against a JSON schema at build time — a mechanism independent of OpenSpec.

```
drivers │ 10 ───────────────▶ 100+ (scales freely)
.sbmd.js files │ core/deviceDrivers/matter/sbmd/specs/*.sbmd.js
governed by │ validate_sbmd_v4_specs.py + JSON schema ← not OpenSpec
───────────────┼───────────────────────────────
device classes │ ~8 ───────────────▶ ~10-15 (bounded)
OpenSpec specs │ per capability + per device class (bounded ~15-25)
```

## Goals / Non-Goals

**Goals:**
- Bound OpenSpec spec count by capabilities and device classes, not drivers.
- Consolidate the existing 35 specs into coherent, consistently-scoped capabilities.
- Encode the organizing principle so future changes cannot regress into per-driver sprawl.
- Keep `openspec validate --specs --strict` green throughout.

**Non-Goals:**
- Net-new capability documentation for undocumented device classes (doorLock, sensor, airQualitySensor).
- Any requirement-meaning change; any code/driver/API change.

## Decisions

**D1. A spec is a capability or a device class — never a driver.**
The driver *is* its `.sbmd.js` file, governed by the schema validator. Encoding this in `openspec/config.yaml` (context + `rules.proposal` + `rules.specs`) makes it a standing constraint the propose/apply skills inject. *Alternative:* rely on reviewer discipline — rejected; it does not scale and is what produced the current sprawl.

**D2. Merge fine-grained framework/cross-cutting specs by concatenating requirements.**
`sbmd-runtime`, `sbmd-mappers`, `sbmd-endpoint-resolution`, `sbmd-claiming`, `agent-skills`, `release-process`, and `matter-testing` are lossless concatenations of their sources' `## Requirements` under one new title + purpose. Requirement bodies are byte-preserved.

**D3. Reframe per-driver specs to device-class specs at the class-contract level.**
`device-class-light`, `device-class-thermostat`, and `device-class-environmental-sensor` describe what the *class* guarantees (endpoint profile, resources, Matter cluster/attribute bindings). Requirements that asserted a driver *file* exists, or that integration tests pass, are dropped — those are owned by the `.sbmd.js` files, the schema validator, and the `matter-testing` spec respectively. The `environmentalSensor` spec is rewritten (its source was driver- and test-centric); light and thermostat retain their accurate resource/binding requirements verbatim.

**D4. Do not fabricate specs for undocumented classes.**
`doorLock`, `sensor`, and `airQualitySensor` had no prior OpenSpec coverage. Rather than author rushed normative specs from driver files, they remain governed by their drivers + tooling; class-contract specs can be added later per D1 when warranted.

## Risks / Trade-offs

- **Reframing environmental-sensor could alter a stated fact.** → Requirements were rewritten directly from the source spec's technical content (clusters 0x0402/0x0405, int16/uint16, null sentinels 0x8000/0xFFFF); scenarios preserve the exact values.
- **Partial device-class coverage (3 of ~6 classes) looks inconsistent.** → Acceptable: the model and governance are established; the other classes were never documented as specs, so nothing is lost, and D1 makes completing them a routine follow-up.
- **Merged specs are larger.** → Still coherent (one capability each) and far more navigable than 35 fragments; strict validation keeps them well-formed.

## Migration Plan

1. Add the governance rule to `openspec/config.yaml`.
2. Concatenate the framework/cross-cutting merges (scripted, lossless).
3. Reframe the three device-class specs; delete consumed source directories.
4. Run `openspec validate --specs --strict` — must be green (20/20).
5. Commit and submit as PR #2 stacked on #258 via `gh stack`.

Rollback is trivial — documentation/organization only; reverting the branch restores the prior layout with no runtime effect.

## Open Questions

- Do we want class-contract specs for `doorLock`, `sensor`, and `airQualitySensor` now, or as follow-ups? (This change defers them.)
32 changes: 32 additions & 0 deletions openspec/changes/consolidate-specs/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Why

The flat `openspec/specs/` list had grown to 35 specs of wildly inconsistent granularity — some describe an entire subsystem, others a single device driver. With spec-based Matter drivers (SBMD) expected to scale to 50–100+, a per-driver spec model would explode the flat namespace: OpenSpec spec discovery is exactly one directory deep, so subfolders are not an option (nested `spec.md` files are silently ignored). We need an organization whose spec count is bounded by capabilities and device classes, not by the driver catalog.

## What Changes

- **Governance rule (the durable fix):** encode in `openspec/config.yaml` that OpenSpec specs are authored per capability or per device class — never per concrete driver. A new supported device is added as a `.sbmd.js` driver file governed by the SBMD schema validator (`scripts/ci/validate_sbmd_v4_specs.py`), not as a new spec. This keeps the spec count bounded (~15–25) as drivers scale to 100+.
- **Consolidate 35 → 20 specs** (requirement meaning preserved):
- **SBMD framework**: `sbmd-runtime` (←`sbmd-system` + `sbmd-v4-runtime` + `sbmd-script-execution-limits`), `sbmd-mappers` (←`sbmd-resource-prerequisites` + `sbmd-seed-from-attribute`), `sbmd-endpoint-resolution` (←`device-type-endpoint-resolution` + `endpoint-cluster-fallback`), `sbmd-claiming` (←`vendor-product-claiming`).
- **Device classes**: `device-class-light` (←`sbmd-v4-light-driver`), `device-class-thermostat` (←`matter-thermostat-sbmd`), `device-class-environmental-sensor` (←`temperature-humidity-sbmd-drivers`) — reframed from per-driver to class-contract level.
- **Cross-cutting**: `agent-skills` (←7 `agent-skill-*`), `release-process` (←`changelog-generation` + `release-workflow`), `matter-testing` (←`matter-test-infrastructure` + `matterjs-virtual-device-framework` + `matterjs-door-lock-device` + `matter-thermostat-testing` + `python-sideband-client`).
- The device-class reframes **drop** requirements that were about a driver *file* existing or about integration tests passing; those concerns are now owned by the `.sbmd.js` files + the SBMD schema validator + the `matter-testing` spec.

## Capabilities

### New Capabilities
<!-- This change reorganizes existing capabilities into consolidated/renamed specs; it does not introduce new system behavior. The consolidated spec files (sbmd-runtime, device-class-*, agent-skills, etc.) carry forward existing requirements verbatim (or, for device-class reframes, at the class-contract level). No delta specs are authored because no requirement's meaning changes. -->

### Modified Capabilities
<!-- None. Requirement semantics are unchanged; only spec file organization and (for device classes) framing change. -->

## Impact

- **Specs**: `openspec/specs/` goes 35 → 20 directories (18 consumed by merges, 3 reframed/renamed, 12 unchanged).
- **Config**: `openspec/config.yaml` gains the spec-organization governance rule (context + proposal/specs rules) that the propose/apply skills inject.
- **No** code, build, CI, API, or runtime impact — documentation/organization only. The `spec-validation` CI gate from the base change (PR #258) keeps all 20 specs strictly valid.

## Non-goals

- Authoring brand-new device-class specs for classes that had no prior OpenSpec coverage (`doorLock`, `sensor`, `airQualitySensor`). Their drivers exist as `.sbmd.js` files under the SBMD validator; a class-contract spec can be added later per the governance rule when warranted.
- Changing any requirement's meaning, or altering drivers, tooling, or the public API.
- Subdirectory organization of specs — proven unsupported by OpenSpec discovery.
28 changes: 28 additions & 0 deletions openspec/changes/consolidate-specs/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## 1. Governance

- [x] 1.1 Add the spec-organization governance rule to `openspec/config.yaml` (context section + `rules.proposal` + `rules.specs`): specs are per capability or per device class, never per driver

## 2. SBMD framework consolidation

- [x] 2.1 Create `sbmd-runtime` from `sbmd-system` + `sbmd-v4-runtime` + `sbmd-script-execution-limits`
- [x] 2.2 Create `sbmd-mappers` from `sbmd-resource-prerequisites` + `sbmd-seed-from-attribute`
- [x] 2.3 Create `sbmd-endpoint-resolution` from `device-type-endpoint-resolution` + `endpoint-cluster-fallback`
- [x] 2.4 Rename `vendor-product-claiming` to `sbmd-claiming`

## 3. Device-class reframe

- [x] 3.1 Reframe `sbmd-v4-light-driver` → `device-class-light` (class contract; drop driver-file and integration-test requirements)
- [x] 3.2 Reframe `matter-thermostat-sbmd` → `device-class-thermostat` (retitle + repurpose; preserve resource/binding requirements)
- [x] 3.3 Reframe `temperature-humidity-sbmd-drivers` → `device-class-environmental-sensor` (rewrite to class-contract level; drop per-driver-file and test requirements)

## 4. Cross-cutting consolidation

- [x] 4.1 Create `agent-skills` from the 7 `agent-skill-*` specs
- [x] 4.2 Create `release-process` from `changelog-generation` + `release-workflow`
- [x] 4.3 Create `matter-testing` from `matter-test-infrastructure` + `matterjs-virtual-device-framework` + `matterjs-door-lock-device` + `matter-thermostat-testing` + `python-sideband-client`

## 5. Verify

- [x] 5.1 Delete all consumed source spec directories
- [x] 5.2 Run `openspec validate --specs --strict` — all specs valid, exit 0 (35 → 20)
- [ ] 5.3 Submit PR #2 stacked on #258 via `gh stack`
13 changes: 13 additions & 0 deletions openspec/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,23 @@ context: |
- C++ naming: PascalCase classes, camelCase methods
- Test naming: test files prefixed with test or suffixed with Test/test

## Spec Organization
OpenSpec specs are authored per capability or per device class — never per concrete
device driver. A new supported device is added as a `.sbmd.js` driver file under
core/deviceDrivers/matter/sbmd/specs/ (governed by the SBMD schema validator,
scripts/ci/validate_sbmd_specs.py), not as a new OpenSpec spec. This keeps the
spec count bounded by the number of framework capabilities and device classes
(~8-15) even as the driver catalog scales to 100+. A new OpenSpec spec is justified
only by a new framework capability or a new device class. Specs live in a flat
layout (openspec/specs/<id>/spec.md — discovery is one directory deep); group
related specs with name prefixes (e.g. sbmd-*, device-class-*), not subdirectories.

rules:
proposal:
- Always include a "Non-goals" section to clarify scope boundaries
- Reference affected layers explicitly (API, core, drivers, subsystems, etc.)
- Note which CMake feature flags are relevant
- Do not introduce a new spec per device driver; new device support is a `.sbmd.js` file, and new specs are justified only by a new framework capability or device class
design:
- Include ASCII architecture diagrams showing how changes fit into existing layers
- Call out thread safety considerations (GLib main loop, Matter event loop, pthread mutexes)
Expand All @@ -97,6 +109,7 @@ rules:
- For Matter features, specify cluster IDs, attribute IDs, and TLV types
- For SBMD specs, include the complete mapper scripts
- Define expected GObject signals/events for new functionality
- Scope device support by device class (device-class-*), not by concrete driver; the per-driver detail lives in the `.sbmd.js` file and its schema
tasks:
- Break tasks into chunks of max 4 hours
- Separate API changes from implementation changes
Expand Down
53 changes: 0 additions & 53 deletions openspec/specs/agent-skill-build/spec.md

This file was deleted.

Loading
Loading