# Changelog

All notable changes to vSEAL will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

**Versioning:** Pre-release milestones use `0.x.y`. First production release will adopt
[Calendar Versioning](https://calver.org/) (`YYYY.MM.PATCH`).

## [Unreleased]

---

## [0.1.20] - 2026-02-24

CLI Support Bundle - Diagnostic file collection, ZIP archiving, and upload to Cloudflare Worker + R2 backend.

### Added

**Support Bundle Command**
- `vseal support-bundle` collects diagnostic files into a ZIP with embedded manifest
- 5-category file discovery: status.json, logs, baselines, custom plugins, config
- Config path overrides from `[logging].seal_path` and `[baseline].path` in TOML
- Graceful degradation: missing files reported in summary, never fatal
- ZIP archiver with timestamped naming, top-level directory prefix, and UUID tracking
- Embedded `manifest.json` with bundleVersion, bundleId, created, hostname, vsealVersion, file inventory
- Upload HTTP client with single POST to Cloudflare Worker, progress tracking via `atomic.Int64`
- `[support]` TOML config section with `upload_url` and `token` fields
- `--no-upload` flag to create bundle locally without upload attempt
- `--note` flag for free-text context included in manifest and upload metadata
- `--output` flag for specifying output directory (default: current directory)
- Branded collection summary showing found/missing items with counts
- Upload progress bar with scramble animation
- TUI spinners for collect and archive phases
- Verbose output for skipped log files (age/count limits)
- Actionable message when upload not configured ("add [support] section")
- Local bundle preserved on upload failure with manual send guidance

**Support Bundle Worker**
- Cloudflare Worker backend at `tools/support-worker/` with R2 storage
- POST `/v1/support/upload` with `X-Auth-Token` auth and `application/zip` body
- Custom metadata on R2 objects: bundle-id, original-filename, tool-version, platform, hostname, note
- GET `/health` endpoint returning JSON status (unauthenticated)
- 404 for missing/wrong auth tokens (no information leakage)
- Validation: wrong Content-Type (400), empty body (400), oversized uploads (413)
- 11 Vitest integration tests via `@cloudflare/vitest-pool-workers`

**Baselines Cleanup Command**
- `vseal baselines cleanup` for batch deletion with filter criteria
- `--invalid` flag selects baselines that failed validation
- `--older-than` flag with human-readable duration (`7d`, `4w`) selects stale baselines
- `--keep N` protects the N newest valid baselines from deletion
- Filters combine as OR; `--keep` overrides other filters for protected baselines
- Interactive confirmation prompt with `--yes` for scripted use and `--dry-run` for preview
- `--force` includes protected baselines in cleanup candidates
- Full `--json` output with candidates, skipped, deleted, and summary fields
- Go-native batch deletion (`os.RemoveAll`) replaces per-item PowerShell calls (~5ms vs ~2s each)
- Single PowerShell call resolves baselines path; all deletions use native Go I/O
- Retry with 200ms delay handles Windows file locks (AV scanners, indexers)
- Live progress counter on spinner during batch operations (e.g., "12/408")

**Scramble Spinner & Manifest View**
- Gradient scramble animation component with five-tier color degradation (TrueColor → TextOnly)
- Manifest-style plugin list: all plugins shown as a live-filling checklist during seal/engage
- `plugin.summary` event parsing populates execution order from PowerShell module
- Active plugin line highlighted with bold text and `›` brand-colored prefix
- Pending plugins rendered dimmed; completed plugins show checkmark/X with duration
- Loading spinners for `vseal doctor`, `vseal plugins`, and `vseal status` commands
- Scramble animation on baselines spinner (prefix-only, with animated dots)
- Legacy fallback preserved when no `plugin.summary` event is received

### Changed

**CLI Code Simplification**
- Extract shared `operation.go` from duplicated seal.go/engage.go (~370 lines eliminated)
- Consolidate rollback execution into `operation.go` via `operationExtra` struct (~150 lines eliminated)
- Extract shared `dateutil.go` with `parseDate()` for RFC3339 and bare ISO 8601 date handling
- Remove 17 dead functions across render, cmd, and internal packages
- Fix data race: remove unsynchronized `cancelled` bool in rollback, use `result.Cancelled` exclusively
- Add `dateutil_test.go` with table-driven tests for date parsing edge cases
- Net reduction: ~850 lines eliminated, tests increased from 444 to 637

**PowerShell Module Simplification**
- Unify output suppression to `$null =` pattern across 12 files (~20 instances)
- Remove dead identical-branch conditionals in `Invoke-vSEALCoreRollback`, `Invoke-vSEAL`, and `example-hybrid` plugin (~18 instances)
- Consolidate baseline merge logic for success/failure paths in `Invoke-vSEAL` (~30 lines saved)
- Replace switch dispatchers with hashtable dispatch tables in `Import-vSEALTemplate`
- Extract repeated error/warning merge pattern into reusable scriptblock
- Remove unused `-PassThru` flag, redundant file-path comments, trailing blank lines, and duplicate variable declarations
- Add integration test verifying `baselineId` presence in status after Seal phase
- Net reduction: ~130 lines eliminated, tests increased from 1750 to 1751

### Fixed

- `Add-vSEALBaselineEntry` no longer rejects Command entries without `RollbackCommand` — rollback commands are optional for one-way operations
- Config auto-discovery wired for `support-bundle` (compensates for SkipPreflight bypassing preflight config block)
- `ParseUploadConfig` surfaces TOML parse errors instead of silently returning unconfigured
- Log collection capped to 14 days and 100 files to prevent oversized bundles

---

## [0.1.19] - 2026-02-23

Docusaurus Website - Product landing page, documentation suite, dual doc generation pipelines, and blog infrastructure.

### Added

**Documentation Suite**
- [Architecture Overview](docs/architecture.md) covering two-component model, CLI layer, module bootstrap, phase model, plugin lifecycle, baseline system, and event streaming
- [Configuration Reference](docs/configuration.md) with all TOML keys, 6 built-in plugin configs, environment variables, and full annotated example
- [API Reference](docs/api-reference.md) documenting all 39 exported PowerShell functions with parameters, return types, and examples
- [Plugin Authoring Guide](docs/plugin-authoring.md) with quick start, decision flowchart, and complete guides for declarative, hybrid, and imperative patterns
- Cross-references between all documentation pages

**Docusaurus Website**
- Docusaurus 3.9 scaffold with vSEAL brand theming and custom Prism syntax theme
- Product landing page with animated terminal demo, feature cards, interactive architecture diagram
- PowerShell doc generation pipeline producing 39 .mdx function references
- Go CLI doc generation pipeline producing 15 command references
- Content migration from 6 existing docs into reader-journey structure
- 8 new documentation pages: intro, quickstart guide, contributing, plugin testing
- 4 custom React components: TerminalMockup, ConfigExample, PluginCard, ArchitectureDiagram
- Blog infrastructure with inaugural post, author config, RSS feed

### Changed

**Documentation**
- Update quickstart UAT guide for current CLI output formatting (branded header, Unicode symbols, lipgloss tables, styled status output)
- Update version references from 0.1.16 to 0.1.19 across all example output blocks
- README documentation section updated with links to new architecture, configuration, API, and plugin authoring docs

---

## [0.1.18] - 2026-02-21

CLI & Log Quality Polish - Flag declutter, verbose standardization, JSON wiring, log output cleanup, and animated brand header.

### Added

**Error Rendering Consistency**
- Branded header before pre-flight error exits
- Rollback timeout context wired through baseline listing
- Idle timeout converted to structured `RenderError` format

**Flag Declutter**
- Flag-hiding map removes deprecated/internal flags from help output
- Tests for flag hiding behavior

**Verbose Standardization**
- Shared verbose helper and verbose preamble on all human-facing commands
- Doctor verbose diagnostics with un-hidden verbose flag
- `BuildCommand` export for verbose pwsh display
- Renamed plugins `--verbose` to `--paths` (semantic clarity)

**JSON & Timeout Wiring**
- `--json` flag for `config validate` and `version` commands
- `--timeout` wired for `status` and `doctor` commands
- `--detail` flag for `plugins` command in JSON and text modes

**Log Output Quality**
- Remove decorators, duplicate messages, and jargon from log output
- `plugin.summary` NDJSON event replaces verbose table output
- Eliminate duplicate completion messages from `Close-vSEALLogger`

**Animated Brand Header**
- `AnimatedLogo` spotlight component with sweep animation
- `AnimatedHeader` with golden shimmer on copyright text
- Redesigned header layout with copyright, license, and dev warning
- Integrated into interactive operation commands and static commands

**CIM Health Prerequisite**
- CIM operation timeout and health prerequisite check

### Fixed

- Project URLs updated to GoldenImageLabs org
- Repo URL in animated header uses ldflags-injected value instead of hardcoded constant
- Progress bar width matches header separator line
- Double-space removed after spinner in baselines and rollback views
- Active plugin spinner aligned with completion line symbols
- Completion lines reprinted after bubbletea exit for scrollback persistence
- Plugin detail `Dependencies` enumeration and `Critical` truthiness corrected
- Duplicate baseline-created log message removed

### Changed

- Progress bar widened to fill terminal width
- TUI View() redesigned with inline completions and minimal progress line
- Completion lines moved from `tea.Printf` into model state

---

## [0.1.17] - 2026-02-20

Baseline & Rollback Improvement - Fix correctness bugs, harden robustness, and improve UX across the baseline capture, storage, and rollback pipeline.

### Added

**Baseline Data Pipeline Fix**
- ThreadJob baseline context extraction via `__vSEALBaseline` marker preserves fine-grained entry types (Registry, Service, Task, Command) across runspace boundary
- Conditional Custom wrapper creation: only used as fallback when no fine-grained entries exist
- `baseline.merge` NDJSON event emitted with type breakdown for observability
- 7 new baseline context merging tests

**Entry Validation**
- Type-specific field validation in `Add-vSEALBaselineEntry`: Service requires StartMode, Command requires RollbackCommand, Task requires State, Registry requires hashtable OriginalValue
- Collect-then-throw validation pattern reports all missing fields in single error message
- 15 new entry validation tests covering all 5 entry types

**Manifest Schema Validation**
- `Test-vSEALBaselineIntegrity` validates required manifest fields (id, created, status, phase, plugins) with type checking
- Missing or wrong-type plugins field caught at integrity check time
- 11 new manifest field validation tests

**Rollback Pre-flight and Forward Baseline**
- Rollback command inherits full pre-flight pipeline (elevation, pwsh, module, config validation)
- `--backup-current` CLI flag creates forward baseline (`pre-rollback-{id}`) capturing current system state before rollback execution
- Forward baseline capture failure aborts rollback entirely (safety-first semantics)
- `-Id`, `-Phase`, `-SourceBaseline` parameters on `Save-vSEALBaseline` for forward baseline support
- Conflict detection prevents overwriting existing baselines
- 17 new forward baseline tests

**Rollback Transaction Semantics**
- Per-plugin transaction summary in rollback output: OK with entry count on success, FAILED with error detail on failure
- Custom entry type handling with `CustomSkipped` counter and `CustomEntries` array
- Custom skip warnings listing each skipped entry by name and plugin
- All-Custom baseline guard refuses no-op rollbacks with clear error message
- 11 new transaction semantics tests

**CLI Loading Indicators**
- Bubbletea spinner for `vseal baselines list/show/delete` with action-specific messages
- `runWithSpinner` helper centralizes TTY detection, `--json` bypass, and Ctrl+C handling
- Non-TTY and `--json` modes bypass spinner entirely

**CLI Process Timeout**
- Global `--timeout` flag (default 30s) on root command
- Wall-clock timeout via `context.WithTimeout` for baselines commands
- Idle-based timeout via `IdleTimeoutContext` for streaming operations (seal/engage/rollback)
- `idleResetReader` wrapper resets idle timer on each stdout read with data
- `IdleTimedOut` field on `RunResult` distinguishes timeout from Ctrl+C
- Timeout error includes actionable hint: "use --timeout \<seconds\> to increase the limit"

**Structured Error Rendering**
- `render.RenderError` helper with symbol + summary + detail + hint format
- `render.RenderErrorJSON` for `--json` mode structured error output
- `render.RenderVerboseStderr` for verbose mode stderr framing
- 6 new error rendering tests

**Testing**
- 2,142 total tests (1,750 PowerShell + 392 Go), up from 2,083

### Fixed

- ThreadJob plugins now produce fine-grained baseline entries instead of opaque Custom wrappers (rollback was silently broken for all ThreadJob plugins)
- Rollback command no longer skips pre-flight validation (config, elevation, module checks)
- Custom-type baseline entries no longer silently skipped during rollback (explicit warning per entry)
- All-Custom baselines no longer run to completion doing nothing (refused upfront with clear error)
- Rollback no longer short-circuits when plugin registry is empty (rollback processes baseline entries, not registry)
- Config init error output directed to stderr instead of stdout
- Error interface to string conversion in preflight error display

### Changed

- Baselines package functions accept context parameter (`ListWithContext`, `ShowWithContext`, `DeleteWithContext`)
- 23 error-and-exit paths across 5 command files migrated to consistent structured format via `render.RenderError`
- All CLI error output consistently routed to stderr

---

## [0.1.16] - 2026-02-18

CLI Branding & Charm Stack Migration - Charm ecosystem migration with gradient branding and bubbletea TUI.

### Added

- Comment-based help for Invoke-vSEAL with full parameter documentation and usage examples
- Comment-based help for 8 private functions (10 functions total including PluginContext stack)

### Fixed

- CLI event timestamps now display in local time instead of raw UTC
- Portable mode preserves system PSModulePath as fallback for Windows OS cmdlets (Get-ScheduledTask, Get-Service, etc.)
- Plugin analysis uses Test-vSEALTaskExists for task existence checks with safe error defaults
- Bubbletea TUI race condition: operation.end no longer triggers premature quit, ProcessDoneMsg is sole quit trigger
- Bubbletea TUI visual overlay: two-line layout separates spinner info from progress bar
- Verbose mode conflicts: `--verbose` bypasses bubbletea entirely, forces static renderer
- CLI version compatibility: dev prerelease builds (e.g. `0.1.16-dev.abc123`) pass module semver constraint check

### Changed

- Minimum PowerShell version bumped from 7.1 to 7.4 LTS across module, CLI, and documentation
- Baseline context functions extracted to individual files (Clear/Get/Initialize-vSEALBaselineContext)
- Seal/engage/rollback commands use `fm.Result()` from bubbletea model instead of goroutine-local variable

---

## [0.1.15] - 2026-02-14

Make vSEAL Truly Portable - Hermetically sealed portable distribution where CLI and PowerShell module use ONLY bundled artifacts at runtime.

### Added

- Disk-based portable mode detection via `os.Stat` of bundled `vSEAL.psd1` manifest
- `IsPortableMode()` API replacing string-prefix-based `IsPortable()` detection
- `BuildEnv()` portable isolation: PSModulePath contains only bundled module + deps paths in portable mode
- `ValidatePortableLayout()` catches corrupt portable bundles (missing manifest or meta.json)
- `Test-PortableDepsMode` helper detects portable mode from PSModulePath shape (2 entries, deps leaf)
- Portable-aware `Test-ModuleDependenciesPrerequisite` validates bundled PSToml directly
- Portable-aware `Get-vSEALDependencyStatus` returns portable-appropriate install commands
- Hard error with actionable message when bundled module is missing in portable mode
- Hard error with actionable message when bundled PSToml is missing in portable mode
- Exe-relative module version lookup for portable distribution layout
- Source-level regression test guarding against Pre-flight OK message reintroduction
- 29 new tests (14 Go + 15 Pester) covering portable/dev mode branching

### Changed

- `getModuleVersion()` checks exe-relative path first, then falls back to system paths
- `ModuleInstalledCheck` branches on portable/override/dev mode for correct module discovery
- `GetDetails()` reports module source as "portable", "override", or "system"
- Dev mode behavior completely unchanged across both CLI and module

### Removed

- `Pre-flight: OK` success message from CLI (redundant with startup banner, contaminated `--json` output)

---

## [0.1.14] - 2026-02-13

Quality & Release Polish - Bug fixes, UX improvements, and CI/CD readiness.

### Added

- CLI startup banner showing version, hostname, config path, and preflight context on seal/engage/rollback
- `--json` output for `vseal plugins`, `vseal baselines list`, `vseal baselines show`, and `vseal status` commands
- SymbolSet abstraction with Unicode/ASCII fallback for terminals without Unicode support (cmd.exe, SSH, piped output)
- `VSEAL_ASCII` environment variable to force ASCII mode explicitly
- `BuildStatusCommand` and `InvokeStatusJSON` for Pattern B status capture
- JSON round-trip tests for plugins, baselines, and status commands
- AST-based function detection in bloatware tests for test isolation

### Changed

- Engage skip gate now shows yellow em-dash with skip reason instead of misleading green checkmark
- Engage `operation.end` event carries `reason` field through Go pipeline to summary display
- `vseal engage --analyze` bypasses status gate on master machine (runs analyze pipeline instead of blocking)
- `vseal rollback` works without `--config` flag when default config exists (matches baselines behavior)
- `vseal plugins` output sorted alphabetically by plugin ID
- Bloatware plugin version aligned from 2.0.0 to 1.0.0 (consistent with pre-release versioning)
- example-hybrid README updated to reflect switch-based parameter model (--analyze, --rollback)
- `vSEAL.psd1` updated with LicenseUri, ProjectUri, and release-ready metadata
- `vSEAL.psd1` is now single source of truth for all metadata including CLI version bounds
- `just generate-meta` and version-bump recipes use `Import-PowerShellDataFile` instead of InvokeBuild
- PowerShell module emits only ASCII or structured data (no Unicode formatting characters)

### Removed

- `vseal analyze` command (deprecated; use `vseal seal --analyze` or `vseal engage --analyze`)
- `build/` folder and `vSEAL.build.ps1` (InvokeBuild script)
- InvokeBuild module dependency

---

## [0.1.13] - 2026-02-09

CLI-PowerShell Protocol Alignment - Every CLI command has a documented protocol, correct STREAM_MODE, and proper event lifecycle.

### Added

- `docs/cli-ps-protocol.md` protocol contract document mapping 12 CLI commands to 4 communication patterns
- Protocol contract tests (`protocol_contract_test.go`) with 13 subtests covering all CLI-to-PowerShell command paths
- Analyze mode NDJSON event lifecycle: `operation.start` (mode=analyze), `analyze.plugin` per plugin, `operation.end` with result
- Progressive per-plugin analyze rendering with change counts and rollback status
- Verbose mode (`--verbose`) shows group/action breakdown for analyze operations
- `ExitChanges=2` exit code constant for analyze mode (terraform convention)
- 7 exported `BuildXxxCommand` builders for Pattern B commands (testability)

### Changed

- `baselines list/show/delete` and `doctor` commands set `VSEAL_STREAM_MODE=stdout` before PowerShell delegation (prevents Write-Host corruption of JSON output)
- Exit codes unified to terraform convention: 0=success, 1=error, 2=changes (analyze)
- `buildCommand()` simplified: removed `Invoke()`, `mapExitCode()`, and status-check tail
- Summary rendering replaced with Style A+ single-line format (symbol prefix, inline metrics) for seal, engage, and rollback commands
- Analyze summary shows correct result instead of "Failed" box-drawing

### Removed

- `Invoke()` and `mapExitCode()` dead code from `pwsh/invoke.go`
- `ExitPartialSuccess` and `ExitCancelled` constants from pwsh package (only used by removed functions)
- Box-drawing summary rendering (`RenderSummary`, `stripANSI`, `go-runewidth` import)

---

## [0.1.12] - 2026-02-07

CLI v2 Plugin Alignment - Go CLI and build system speak v2 exclusively.

### Changed

- CLI elevation check uses native Windows API (`windows.GetCurrentProcessToken`) instead of spawning pwsh subprocess (~300ms faster)
- `vseal version` now requires elevation (removed from preflight skip list)
- Elevation check runs before module-path override in preflight chain
- `vseal plugins` delegates to PowerShell `Get-vSEALPlugin` for validated v2 discovery
- `vseal plugins` output includes STATUS column and summary line (valid/skipped/errors)
- `vseal plugins --detail` shows Status, SkipReason, ErrorMessage, and PluginPath
- `just package` depends on build (always packages fresh artifacts, no stale dist/)
- `plugins-custom/` in package is flat directory with v2 plugin guide (no v1 category subdirectories)
- Plugin stats counting delegates to `Get-vSEALPlugin` instead of counting .ps1 files
- All v1 plugin format comments removed from Go and PowerShell source files
- All example plugin READMEs updated to v2 format
- All 6 PowerShell test files migrated from v1 to v2 plugin fixtures

### Added

- `vseal doctor --json` structured JSON output for CI/CD consumption
- DoctorReport envelope with summary, categories, checks, and lowercase status strings
- `just test-package` validates v2 structure and doctor --json output
- `templates/plugins-custom-README.md` v2 plugin authoring guide

**Prerelease Distribution**
- `just prerelease` - build, package, and publish to internal R2 bucket in one command
- `just publish-prerelease` - upload existing ZIP to vseal-builds.kowal.one
- `just list-prereleases` - show current builds in bucket
- `just delete-prerelease <file>` - remove specific build
- `just clear-prereleases` - clear all builds (with confirmation)
- Uses rclone with project-local config (`.rclone.conf.example` template provided)

### Removed

- Go-native TOML parsing in plugin scanner (replaced by PowerShell delegation)
- Hardcoded `categoryIndex` and `categoryOrder` maps from detail.go and scan.go
- `dummy`/`mock` prefix-based plugin filtering from scanner
- `.ps1` suffix-based plugin identification
- v1 `PluginToml`, `PluginMeta`, `PluginDetail`, `SchemaField` Go types
- v1 category subdirectory creation (`edr`, `agents`, `system`, etc.) from build system
- `Get-PluginMetadata` references from test helpers and plugin READMEs

---

## [0.1.11] - 2026-02-06

Plugin Architecture v2 - Self-contained folder-based plugins with TOML metadata.

### Added

**Plugin TOML Schema**
- `Import-vSEALPluginMetadata` - Parse `plugin.toml` metadata files from plugin folders
- `test-schema` reference plugin with complete TOML metadata example
- Metadata fields: name, version, description, author, phases, priority, critical, timeout

**Requirements Evaluation**
- `Test-vSEALPluginRequirements` - Evaluate plugin requirements against system context
- `Get-vSEALRequirementsContext` - Collect OS, platform, and module context for evaluation
- Plugins declare requirements in `plugin.toml`; incompatible plugins skipped gracefully

**Plugin Discovery and Configuration**
- Rewrote plugin registry for folder-based discovery (`Plugins/{id}/plugin.toml`)
- `Get-vSEALPlugin` updated with `-Status` filter parameter (Valid, Skipped, Error)
- Flat plugin IDs replace category-based naming (`defender` instead of `mock/defender`)
- Config format changed to `[plugins.{id}]` (npm/Cargo-style pattern)
- `Test-vSEALConfiguration` updated for new `[plugins.{id}]` format

**Plugin Validation and Health**
- `Test-vSEALPluginHealth` - Validate plugin structure, metadata, and script integrity
- `Invoke-vSEALLintPlugins` developer command for batch plugin validation
- `vseal doctor` includes plugin health check section
- Lifecycle integration tests for plugin load, execute, teardown

**Testing**
- 16 UAT scenarios passed
- Discovery, API, requirements, health, and lifecycle test coverage
- Integration tests migrated from mock plugins to v2 folder-based plugins

### Changed

**Plugin Migration**
- All plugins migrated from `Plugins/mock/` to self-contained `Plugins/{id}/` folders
- Each plugin folder contains `plugin.toml` (metadata) and `plugin.ps1` (script)
- `mock/` directory deleted; plugins renamed to `example-*` prefix
- Bloatware plugin migrated to v2 metadata structure
- Orchestrator updated for v2 registry (flat IDs, folder-based resolution)
- `Get-PluginAnalysis` updated for v2 plugin entries
- Example configs and CLI skeleton template updated to v2 plugin IDs

**Analyze/Rollback Parameter Model**
- Analyze and Rollback converted from `-Phase` values to `-Analyze` / `-Rollback` switch parameters
- Removed Analyze and Rollback from plugin `Phases` ValidateSet
- Go CLI command builder updated for switch parameter model
- All Pester and Go tests updated for new parameter model

### Fixed

- Baseline capture guarded to Seal phase only (previously ran in all phases)
- `Test-Applicable` guarded for scriptless (pure-TOML declarative) plugins
- Integration tests for status, seal, and engage migrated from deleted mock plugins to v2

---

## [0.1.9] - 2026-02-01

Portable Distribution, Manifests & Dependency Cleanup - Self-contained distribution with bundled dependencies.

### Added

**Reference Cleanup**
- Removed PwshSpectreConsole from dependency checking (was never actually used)
- Removed legacy PSADT and BIS-F references from comments and documentation
- README now describes vSEAL as "modern VDI sealing framework" without competitor references

**Config Auto-Discovery**
- CLI auto-discovers config at `$env:ProgramData\vSEAL\vseal.toml` when `--config` not specified
- Doctor shows config source: "Explicit (--config flag)" or "Auto-discovered at default location"
- Clear actionable error when no config found with `vseal config init` remediation hint
- `Flags().Changed()` pattern distinguishes explicit flag from default value

**Extended Baseline Manifest**
- Baseline manifest includes OS info: name, edition, version, buildNumber, releaseId, architecture, isWorkstation/isServer
- Baseline manifest includes platform info: hypervisor, isVMware, isHyperV, isNutanixAHV, isXenServer, isAzure, azureMetadata
- `vseal baselines list` shows OS column with OS name (truncated to 15 chars)
- Rollback with OS mismatch now logs WARNING and proceeds (previously blocked with error)
- Backward compatibility: old manifests with `osBuild` field still work

**Go CLI Module Discovery**
- CLI discovers bundled module at `<exe-dir>/module/vSEAL/vSEAL.psd1`
- CLI discovers bundled PSToml at `<exe-dir>/deps/PSToml/`
- `--module-path` flag for explicit module location override
- Doctor shows "(portable)" indicator when using bundled module
- Doctor shows "Bundled deps" line when deps directory exists
- All 12 Go files using `Import-Module vSEAL` converted to absolute path
- `modulepath` package with sync.Once singleton for efficient path discovery
- Clear error message when module not found: "Module not found at: <path>"

**Plugin Discovery Order**
- Plugin discovery searches `<vseal>/plugins-custom/{category}/` first (Source='local')
- Plugin discovery searches `$env:ProgramData\vSEAL\plugins/{category}/` second (Source='shared')
- Built-in plugins in `Plugins/{category}/` discovered with Source='built-in'
- Duplicate plugin detection across all locations with descriptive error listing all conflicts
- `vseal plugins` shows SOURCE column (local/shared/built-in)
- `vseal plugins --verbose` shows full PATH for each plugin
- Doctor shows Plugin Discovery section with paths and plugin counts

**Build System & Packaging**
- `just package` creates `vseal-{version}-windows-amd64.zip` portable distribution
- `just test-package` extracts ZIP to temp and validates with `vseal doctor`
- `just package-clean` provides clean-slate build workflow (clean → build → package)
- Distribution includes: vseal.exe, module/vSEAL/, deps/PSToml/, plugins-custom/ (6 categories)
- Bundled PSToml dependency copied from installed module location

**Testing**
- 1357 PowerShell tests (was 1332)
- 222 Go tests (was 357, reorganized)
- 1579 total tests

### Changed

- `Get-vSEALDependencyStatus` returns only PSToml (removed PwshSpectreConsole)
- `just setup` installs only required dependencies (PSToml, Pester, InvokeBuild)
- Module prepends deps folder to `$env:PSModulePath` at load time for bundled dependencies
- Build-release creates portable structure: `dist/module/vSEAL/` and `dist/deps/PSToml/`

### Removed

- PwshSpectreConsole dependency (never actually used)
- PSADT references in code comments
- BIS-F references in README and source comments
- Addressed backlog items from BACKLOG.md

---

## [0.1.8] - 2026-01-30

Structured Event Streaming - Go CLI as sole user-facing interface with NDJSON event communication.

### Added

**PowerShell Event Streaming**
- NDJSON event emission via `$env:VSEAL_STREAM_MODE=stdout` or `stderr`
- Event schema: ts (ISO 8601), level, msg, source, opId, phase
- Extended event fields: type, data, step.current/total/name, durationMs
- Operation context: unique 8-char hex opId per operation
- Secret redaction with 10 pattern categories (passwords, tokens, keys, etc.)
- `[Console]::Out.WriteLine` for clean JSON output (bypasses PowerShell streams)

**Orchestrator Lifecycle Events**
- `operation.start` event at phase beginning with computerName, pluginCount
- `operation.end` event at phase completion with result, counts, durationMs
- `plugin.start/success/failed/timeout/skipped` events with timing
- `rollback.start/end` events with baselineId and result
- `baseline.create` event for baseline operations
- Stopwatch-based precise timing (System.Diagnostics.Stopwatch)

**Go CLI Event Parser**
- `internal/events` package with Event struct and NDJSON parser
- `OperationState` with RWMutex-protected fields and deep-copy `Snapshot()`
- `bufio.Scanner` with 64KB buffer and 1MB max token for large events
- `RunOperation` with io.Pipe, WaitGroup coordination, context cancellation
- `InvokeWithEvents` replaces pass-through Invoke for seal/engage/rollback
- Graceful degradation: non-JSON lines logged as RAW events
- Events-primary exit code derivation (never downgrade from events)

**Terminal Rendering**
- `internal/render` package with TTY detection via `golang.org/x/term`
- `briandowns/spinner` with "[X/Y] plugin-name" suffix format
- Unicode progress bar: `[████████░░] 75% (3/7)`
- Completion lines with checkmark/x-mark and duration
- Summary box with Unicode box-drawing characters and color-coded headers
- `--json` global flag for raw NDJSON passthrough (CI/CD mode)
- NO_COLOR and TERM=dumb environment variable support
- Slow plugin warning at 120s with color change

**Interactive Prompt Migration**
- `PluginNames` field in baseline list results (sorted array)
- `vseal rollback` displays baseline list with plugin names in Go CLI
- `--baseline <id>` flag for non-interactive baseline selection
- `--force` flag skips confirmation prompt
- `--non-interactive` flag fails with guidance when interaction required
- Auto non-interactive mode when stdin is not a terminal
- Max 10 baselines in selection list with overflow hint

**Contract and Stress Testing**
- `EventContract.Tests.ps1` with 28 schema validation tests
- Event ordering tests: operation.start first, operation.end last
- Go concurrency stress tests: 1000 events in 11.5ms
- Go parser tests: malformed input, empty lines, oversized tokens
- Integration tests with real PowerShell subprocess

**Testing**
- 1332 PowerShell tests (was 1218)
- 357 Go tests (was 176)
- 1689 total tests

### Changed

- Go CLI is now sole user-facing interface for seal/engage/rollback
- PowerShell module is pure execution engine (no interactive prompts)
- Exit codes derived from events, not just process exit code

---

## [0.1.7] - 2026-01-27

vARC Implementation - Action execution infrastructure with rollback capability.

### Added

**Action Executors**
- `Invoke-vSEALRegistryAction` - Registry modifications (Set, Delete, DeleteKey) with HKCU rejection
- `Invoke-vSEALServiceAction` - Service start mode changes with optional stop
- `Invoke-vSEALTaskAction` - Scheduled task enable/disable by path
- `Invoke-vSEALCommandAction` - Shell commands with timeout and exit code capture
- COLLECT-EXECUTE-VERIFY-CAPTURE pattern for all executors
- Consistent result structure: Action, Target, Status, Message, Baseline, Duration

**Condition System**
- `Test-vSEALCondition` - Evaluate conditions against globals, registry, services, tasks
- `Test-vSEALTaskExists` - Task existence check with wildcard support (* and ?)
- 9 operators: `=`, `!=`, `>`, `>=`, `<`, `<=`, `in`, `not_in`, `contains`
- Globals conditions for `$Globals.OS.*` and `$Globals.Platform.*`
- Multiple conditions implicit AND logic

**Baseline Manager**
- `Save-vSEALBaseline` - Persist baseline with timestamped folder (YYYYMMDD_HHMMSS)
- `Get-vSEALBaseline` - Retrieve baseline by ID with integrity validation
- `Get-vSEALBaselineList` - List all baselines sorted newest-first
- `Remove-vSEALBaseline` - Delete baseline with retry for locked files
- `Add-vSEALBaselineEntry` - Accumulate entries during execution
- `Initialize-vSEALBaselineContext`, `Get-vSEALBaselineContext`, `Clear-vSEALBaselineContext` - Lifecycle management
- Storage at `C:\ProgramData\vSEAL\baselines\` with manifest and per-plugin JSON files
- Protected baseline flag prevents accidental deletion

**Group Processor**
- `Invoke-vSEALActionGroup` - Execute action groups with phase context
- Group and per-action condition evaluation with short-circuit
- Error handling strategies: continue, stop, rollback
- LIFO rollback order for group-level recovery
- Baseline capture after successful actions

**Template System**
- `Import-vSEALTemplate` - Parse TOML template files for declarative plugins
- Template validation: required fields, action types, condition types
- Metadata support: name, version, description, min_build
- Forward compatibility: unknown fields generate warnings

**Orchestrator Integration**
- `-Phase Analyze` - Dry-run showing planned changes (terraform-plan style)
- `-Phase Rollback` - Restore system from baseline
- `Invoke-vSEALCoreRollback` - LIFO rollback engine for declarative actions
- Seal phase automatically saves baseline after plugin execution
- BaselineId persistence in status.json
- Exit codes: 0=no changes, 1=changes pending, 2=errors (Analyze phase)

**Mock Plugin Migration**
- Migrated 7 existing plugins to `Plugins/mock/` category (defender, sccm, office, pagefile, eventlogs, engine, test)
- Category metadata for baseline file naming
- `example-declarative` plugin - Pure TOML template (no PowerShell)
- `example-hybrid` plugin - TOML template with custom Analyze/Rollback
- `example-imperative` plugin - Direct vARC executor calls

**CLI Integration**
- `vseal rollback` command with interactive baseline selection
- `vseal baselines` command lists available baselines
- `vseal baselines show <id>` displays baseline details
- `vseal baselines delete <id>` removes a baseline
- `--baseline` flag for non-interactive rollback
- `--force` flag skips CLI confirmation prompts

**Testing**
- 1218 total tests passing (was 691)
- Action executor tests: 131 tests
- Condition system tests: 71 tests
- Baseline manager tests: 143 tests
- Group processor tests: 84 tests
- Template system tests: 62 tests
- Orchestrator tests: 49 tests

### Changed

- Module exports increased from 17 to 37 functions
- Plugin metadata now requires `Category` field

---

## [0.1.6] - 2026-01-24

vSEAL CLI Implementation - Go-based CLI wrapper for streamlined command invocation.

### Added

**vSEAL CLI**
- `vseal seal` command invokes Invoke-vSEAL -Phase Seal via PowerShell subprocess
- `vseal engage` command invokes Invoke-vSEAL -Phase Engage via PowerShell subprocess
- `vseal status` command invokes Get-vSEALStatus for last run status
- `--analyze` flag on seal/engage commands for dry-run mode
- `--plugin` flag on seal/engage commands for single plugin execution
- Exit code mapping: 0 (success), 2 (failure), 3 (partial success)
- PowerShell output streams to terminal in real-time
- Bookend messages with timing ("Starting seal...", "Seal completed successfully (Xs)")

**vSEAL CLI**
- Pre-flight check infrastructure with Checker interface and RunChecks orchestrator
- 6 preflight checks: pwsh exists, pwsh version, module installed, version compat, config exists, config syntax
- Meta package for parsing vSEAL.meta.json version compatibility data
- PersistentPreRunE integration runs preflight automatically before commands
- `--skip-preflight` global flag bypasses all checks with warning
- SkipPreflightAnnotation allows version/doctor commands to bypass preflight
- Fail-fast behavior stops on first error, verbose mode shows check timing
- Color output for check results (green OK, red FAILED, yellow warnings)
- Version command shows "(unavailable)" gracefully when components missing

**vSEAL CLI**
- Go CLI project scaffold with Cobra framework
- Command stubs: seal, engage, analyze, status, doctor, config, plugins, version
- Version embedding via ldflags (version, commit, build date)
- `just build-cli` task for building vseal.exe to dist/

**Build System**
- Smart versioning with git tag detection (`is_tagged`, `display_version`)
- `just set-version X.Y.Z` task for explicit version control
- BuildCommit and BuildDate embedded in built module PrivateData for traceability

### Fixed

**Tests**
- Initialize-vSEALLogger tests now use metadata inspection instead of invocation to prevent interactive prompts
- Build.Tests.ps1 uses dynamic manifest version instead of hardcoded value

### Changed

**vSEAL CLI**
- `vseal analyze` now shows deprecation warning (use `--analyze` flag instead)
- Default config path set to C:\ProgramData\vSEAL\vseal.toml

---

## [0.1.5] - 2026-01-24

ThreadJob Plugin Isolation Fix - Plugins can now access exported vSEAL functions.

### Fixed

**ThreadJob Module Access**
- Plugins running in ThreadJob can now call `Write-vSEALLog` and other exported vSEAL functions
- Added `-InitializationScript` parameter to `Start-ThreadJob` in `Invoke-vSEAL.ps1`
- InitializationScript imports vSEAL module into ThreadJob runspace before plugin execution
- Design contract (`plugin-isolation-design.md`) now fully compliant
- `just smoke` passes with all 5 real plugins (defender, sccm, pagefile, dummy, engine)

### Added

**Testing**
- Integration test verifying plugins can call `Write-vSEALLog` in ThreadJob
- Integration test verifying ephemeral modules can access exported vSEAL functions
- 642 total tests passing (was 640)

---

## [0.1.4] - 2026-01-23

CLI Parity milestone - Module functions for vSEAL CLI wrapper integration.

### Added

**Plugin Metadata API**
- `Get-vSEALPlugin` - Returns plugin metadata for CLI discovery and documentation
- Returns PSCustomObject array with Name, Description, Category, Path, Phases, Priority, Critical, Schema
- `-Name` parameter with wildcard support for filtering
- Schema extraction via ephemeral module from plugin ScriptContent
- JSON serializable output for CLI consumption

**Dependency Status API**
- `Get-vSEALDependencyStatus` - Returns dependency status for CLI doctor command
- Checks PSToml >= 0.4.0 and PwshSpectreConsole >= 2.3.0
- Returns PSCustomObject array with Name, MinimumVersion, InstalledVersion, Status, InstallCommand, ErrorMessage
- Status values: Installed, Outdated, Missing, Error
- Prerelease versions treated as Outdated (strict stable-only)
- JSON serializable output for CLI consumption

**Build Integration**
- `build/vSEAL.build.ps1` - InvokeBuild script with GenerateMetadata task
- `vSEAL.meta.json` - CLI compatibility metadata (moduleVersion, minPwshVersion, minCliVersion, maxCliVersion)
- Build task reads manifest and generates metadata file with validation
- UTF-8 without BOM encoding for cross-platform compatibility

**Testing**
- Unit tests for Get-vSEALPlugin (20 tests)
- Unit tests for Get-vSEALDependencyStatus (23 tests)
- Unit tests for Build.Tests.ps1 (13 tests)
- 640 total tests passing (was 584)

---

## [0.1.3] - 2026-01-23

Status Persistence milestone - vSEAL tracks image state and makes intelligent Engage decisions.

### Added

**Core Status Infrastructure**
- `Write-vSEALStatus` - Persists execution status to `$env:ProgramData\vSEAL\status.json`
- Atomic write pattern (temp file + rename) for durability against abrupt termination
- Filesystem flush before function returns (BIS-F #390 scenario prevention)
- Status includes: computerName, timestamp, result, pluginsRun, pluginsFailed, errors, version
- Result values: Success, PartialSuccess, Failed
- `Read-vSEALStatus` - Reads execution status (returns $null if not found)
- `-PersistentDisk` parameter for write-cache VDI support
- Merges seal from C:\ProgramData with engage from persistent disk

**Phase Integration**
- `Resolve-vSEALStatusPath` - Determines status file path based on config and write-cache detection
- `Invoke-vSEAL` writes status after each phase (in finally block for durability)
- Seal phase clears engage section, Engage phase preserves seal section
- Error collection from failed plugins captured in status.json

**Decision Logic and API**
- `Test-vSEALShouldSkipEngage` - Returns Skip/Reason hashtable for intelligent decisions
- Skip Engage if no seal record exists (virgin machine)
- Skip Engage if running on seal machine (computerName match)
- Skip Engage if already engaged successfully on this clone
- `Get-vSEALStatus` - Public API for status queries (thin wrapper over Read-vSEALStatus)

**Testing**
- Unit tests for Write-vSEALStatus, Read-vSEALStatus, Resolve-vSEALStatusPath
- Unit tests for Test-vSEALShouldSkipEngage, Get-vSEALStatus
- Integration tests for status recording in Invoke-vSEAL
- 584 total tests passing (was 455)

---

## [0.1.2] - 2026-01-21

Framework Stabilization milestone - Fixed all 4 critical bugs.

### Added

**Configuration Validation**
- `Test-FrameworkSchema` - Validates [vseal], [logging], [storage] config sections
- `Test-PluginSchema` - Validates plugin config against declared schema
- `Test-vSEALConfiguration` - Orchestrates full config validation at startup
- Validation integrated into `Invoke-vSEAL` execution flow (fail-fast before plugins)
- Clear error messages with field path, expected type, and actual value
- Plugin schema support via `Get-PluginConfigSchema` function in plugins

**Plugin Timeout**
- ThreadJob-based timeout wrapper for plugin execution
- Configurable default timeout via `[vseal] default_plugin_timeout` (default: 300s)
- Per-plugin timeout override via `timeout` field in plugin config
- `timeout = 0` for infinite execution (no timeout)
- Graceful abort with WARNING log on timeout
- Critical plugin timeout aborts entire operation

**Integration Tests**
- `-PluginPath` parameter for test isolation
- Integration tests for full Seal flow with dummy plugins
- Integration tests for full Engage flow with dummy plugins
- Tests for critical plugin failure abort behavior
- Tests for timeout behavior (non-critical warning, critical abort)

**Testing**
- Unit tests for timeout behavior (12 tests)
- Unit tests for configuration validation (20 tests)
- Integration tests for Seal/Engage orchestration (8 tests)
- 455 total tests passing

### Changed

**Version Requirements**
- PowerShell minimum version updated from 7.0 to 7.1
- Required for null-conditional (`?.`) and null-coalescing (`??`) operators
- Module manifest, prerequisite checks, and all 51 source/test files updated

### Fixed

- PowerShell version mismatch between manifest (7.0) and operator usage (7.1)
- Plugin execution could hang indefinitely with no timeout
- Config values not validated against plugin schemas
- No integration tests for end-to-end flow
- `ContainsKey()` replaced with `Contains()` for OrderedDictionary/Hashtable compatibility
- Verbosity tests updated to include required plugin config fields

---

## [0.1.0] - 2026-01-01

### Added
- Initial module structure with prerequisite checking system
- Modular prerequisite validation (PS version, OS version, elevation, Windows environment, module dependencies)
- `Get-vSEALOperatingSystemInfo` - Native PowerShell 7 OS detection using P/Invoke
- `Get-vSEALAzurePlatformData` - Azure IMDS metadata retrieval with fail-fast TCP check
- `Test-InternetConnectivity` - Private function for network availability testing
- Repository structure following design specification
