Files
suaveplan/openspec/changes/complete-network-plugins/specs/network-plugin-state/spec.md
2026-05-27 23:29:53 +01:00

5.5 KiB

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"