Initial Commit
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: network-plugin-state (complete-network-plugins)
|
||||
|
||||
**Package**: `@suaveplan/network-plugin-state`
|
||||
**Status**: PROPOSED
|
||||
|
||||
> Every requirement below carries a `**Verified by:**` line at authoring time.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: StatePlugin conforms to NetworkPlugin lifecycle
|
||||
|
||||
The package SHALL export `StatePlugin implements NetworkPlugin` and `StatePluginConfig`. The plugin SHALL manage state synchronization, delta compression, history pruning, and reconciliation against peer states.
|
||||
|
||||
#### Scenario: install / uninstall lifecycle
|
||||
|
||||
- **WHEN** a host installs then uninstalls the plugin
|
||||
- **THEN** the plugin reaches `INSTALLED` then `UNINSTALLED` cleanly
|
||||
|
||||
**Verified by:** `src/plugin/state-plugin.spec-conformance.test.ts::"install / uninstall lifecycle is clean"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: BloomFilter and BloomFilterComparator detect divergence
|
||||
|
||||
The package SHALL export `BloomFilter`, `BloomFilterComparator`, and `BloomFilterConfig`. The comparator SHALL diff two bit-vectors of equal byte-length and return the set of suspected divergent slots.
|
||||
|
||||
#### Scenario: comparator finds divergent slots
|
||||
|
||||
- **WHEN** two filters of the same configuration are compared
|
||||
- **THEN** the result identifies slots set in one and unset in the other
|
||||
|
||||
**Verified by:** `src/bloom/bloom-filter-comparator.spec-conformance.test.ts::"diff identifies divergent slots"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: BloomFilterComparator rejects length-mismatch with typed error
|
||||
|
||||
`BloomFilterComparator` SHALL throw `NetworkStateError` with `code === "NET_STATE.BLOOM_LENGTH_MISMATCH"` and a `context` payload carrying both byte lengths whenever the two filters' byte arrays have different sizes. The class SHALL NOT throw bare `Error`.
|
||||
|
||||
#### Scenario: byte-length mismatch
|
||||
|
||||
- **WHEN** two bloom filters of byte lengths 8 and 16 are compared
|
||||
- **THEN** the call throws `NetworkStateError` with `code === "NET_STATE.BLOOM_LENGTH_MISMATCH"` and `context === { left: 8, right: 16 }`
|
||||
|
||||
**Verified by:** `src/bloom/bloom-filter-comparator.spec-conformance.test.ts::"throws BLOOM_LENGTH_MISMATCH on byte-length mismatch"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: DeltaCompressor produces and applies state diffs
|
||||
|
||||
The package SHALL export `DeltaCompressor` that takes prior and next state snapshots and produces a compact delta that, when applied to the prior, reconstructs the next.
|
||||
|
||||
#### Scenario: delta round-trip reconstructs next state
|
||||
|
||||
- **WHEN** `apply(prev, compress(prev, next))` is computed
|
||||
- **THEN** the result is structurally equal to `next`
|
||||
|
||||
**Verified by:** `src/delta/delta-compressor.spec-conformance.test.ts::"compress / apply round-trip"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Reconciler deepMerge merges peer-state branches
|
||||
|
||||
The package SHALL export `deepMerge` and a reconciler abstraction that merges two state branches under a configurable strategy. Missing strategy keys SHALL raise `NetworkStateError(STRATEGY_MISSING_MERGE)`.
|
||||
|
||||
#### Scenario: missing strategy raises typed error
|
||||
|
||||
- **WHEN** a reconciler is run with no strategy registered for the key in conflict
|
||||
- **THEN** the call throws `NetworkStateError` with `code === "NET_STATE.STRATEGY_MISSING_MERGE"`
|
||||
|
||||
**Verified by:** `src/reconciler/reconciler.spec-conformance.test.ts::"throws STRATEGY_MISSING_MERGE when no strategy registered"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: StateHistoryPruner enforces retention policy
|
||||
|
||||
The package SHALL export `StateHistoryPruner` and `StateHistoryPrunerConfig`. The pruner SHALL drop history entries older than the configured retention window and SHALL raise `NetworkStateError(PRUNE_INVALID_RETENTION)` on invalid retention configuration.
|
||||
|
||||
#### Scenario: invalid retention raises typed error
|
||||
|
||||
- **WHEN** `new StateHistoryPruner({ retentionMs: -1 })` is called
|
||||
- **THEN** the call throws `NetworkStateError` with `code === "NET_STATE.PRUNE_INVALID_RETENTION"`
|
||||
|
||||
**Verified by:** `src/pruner/state-history-pruner.spec-conformance.test.ts::"throws PRUNE_INVALID_RETENTION on negative window"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Error-code registry is frozen and namespaced NET_STATE
|
||||
|
||||
`NETWORK_STATE_CODES` SHALL be frozen under the `NET_STATE` namespace and SHALL include at minimum: `PATH_INVALID`, `STRATEGY_MISSING_MERGE`, `DELTA_OUT_OF_ORDER`, `RESOURCE_PROFILE_UNKNOWN`, `PRUNE_INVALID_RETENTION`, and the new `BLOOM_LENGTH_MISMATCH`.
|
||||
|
||||
#### Scenario: registry contains BLOOM_LENGTH_MISMATCH
|
||||
|
||||
- **WHEN** `NETWORK_STATE_CODES` is inspected
|
||||
- **THEN** `BLOOM_LENGTH_MISMATCH` maps to `"NET_STATE.BLOOM_LENGTH_MISMATCH"`
|
||||
|
||||
**Verified by:** `src/error-codes.spec-conformance.test.ts::"NETWORK_STATE_CODES includes BLOOM_LENGTH_MISMATCH"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: No bare-Error throws in production code
|
||||
|
||||
`src/` SHALL contain zero bare `throw new (Error|TypeError|RangeError|SyntaxError)\(` sites outside test files.
|
||||
|
||||
#### Scenario: source grep returns zero hits
|
||||
|
||||
- **WHEN** `grep -rnE "throw new (Error|TypeError|RangeError|SyntaxError)\(" packages/network/network-plugin-state/src/ --include="*.ts"` excluding tests
|
||||
- **THEN** the output is empty
|
||||
|
||||
**Verified by:** `tests/no-bare-throws.test.ts::"network-plugin-state src/ has no bare Error throws"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: README is auto-docs idempotent
|
||||
|
||||
The package `README.md` SHALL contain exactly one balanced auto-docs block; the generator SHALL produce a byte-identical file on a second run.
|
||||
|
||||
#### Scenario: marker count is exactly one
|
||||
|
||||
- **WHEN** `grep -c "begin:auto-docs" packages/network/network-plugin-state/README.md`
|
||||
- **THEN** output is `1`
|
||||
|
||||
**Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-state"`
|
||||
Reference in New Issue
Block a user