# Drive — Spec Delta (drive-port) ## ADDED Requirements ### DRIVE-01 — Drive consumes `AbstractStorage` directly `Drive` MUST accept any concrete `AbstractStorage` from `@suaveplan/storage` as its storage substrate. There MUST NOT be a separate `StorageAdapter` shim. Drive MUST narrow capabilities through a `DriveStorage` view that extends `AbstractStorage` with `id: string` and optional `capabilities?: { partialReads?, nativeStreams?, atomicWrites?, contentAddressable?, partialWrites?, requiresLifecycle? }` plus optional `connect?()`, `dispose?()`, `isConnected?()` lifecycle hooks. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-01`). ### DRIVE-02 — `initialize()` is idempotent and ownership-tracking `Drive.initialize()` MUST be idempotent. For each registered storage, drive MUST call `storage.connect?.()` ONLY when `storage.isConnected?.() !== true`, and MUST record those storages in an internal `connectedByMe: WeakSet`. Connection failures MUST surface as `DriveError(DRIVE.STORAGE_CONNECT_FAILED, { cause })`. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-02`). ### DRIVE-03 — `dispose()` is idempotent and ownership-respecting `Drive.dispose()` MUST be idempotent. Drive MUST only close storages in `connectedByMe`; storages pre-connected by the caller MUST be left open. After `dispose()`, the drive transitions to a terminal disposed state. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-03`). ### DRIVE-04 — Operations after `dispose()` throw Any file operation invoked on a disposed drive (`read`, `write`, `delete`, `stat`, `list`, `createReadStream`, `createWriteStream`) MUST throw `DriveError(DRIVE.DISPOSED)`. Operations invoked before `initialize()` MUST throw `DriveError(DRIVE.NOT_INITIALIZED)`. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-04`). ### DRIVE-05 — Error-code registry is namespaced and frozen `DRIVE_CODES` MUST be declared via `defineCodes("DRIVE", [...])` from `@suaveplan/error`. `Object.isFrozen(DRIVE_CODES)` MUST be `true`. Every code value MUST start with `DRIVE.`. `DriveError` MUST extend `SuaveplanError`. **Verified by:** `src/error-codes.spec-conformance.test.ts` (`DRIVE-05`). ### DRIVE-06 — Plugin middleware order `drive.use(plugin)` and `drive.useMiddleware(mw)` MUST install in registration order. Middleware chains for `read`, `write`, `delete`, `stat`, `list` MUST execute outer-first on the request path and outer-last on the response path. `plugin.dispose()` MUST be called in reverse-registration order on `Drive.dispose()`. Plugin install/dispose throws MUST surface as `DriveError(DRIVE.PLUGIN_FAILED, { cause })`. **Verified by:** `src/plugins/registry.spec-conformance.test.ts` (`DRIVE-06`). ### DRIVE-07 — Capability fallbacks for streams `drive.createReadStream(path)` MUST use `storage.createReadStream` when `storage.capabilities?.nativeStreams === true`, otherwise MUST fall back to the inherited `AbstractStorage.defaultCreateReadStream`. Same rule for `createWriteStream`. **Verified by:** `src/file-operations/streams.spec-conformance.test.ts` (`DRIVE-07`). ### DRIVE-08 — Generic storage typing `Drive` MUST narrow `TStorageMap` through `drive.use(id, storage)` so that `drive.getStorage(id)` returns `TStorageMap[K]` exactly (no widening to the base `DriveStorage`). Calls with an unknown id MUST be a TypeScript error. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-08`, type-level via `expectTypeOf`). ### DRIVE-09 — Constructor overloads `new Drive()`, `new Drive(storage)`, `new Drive(storage, options)`, and `new Drive({ defaultStorage, plugins, ... })` MUST all be valid. The bare-storage form MUST be observably equivalent to passing `{ defaultStorage: storage }` and MUST register the storage under id `"default"`. **Verified by:** `src/drive/drive.spec-conformance.test.ts` (`DRIVE-09`).