--- kanban-plugin: table --- # C# Backend Parity Acceptance Criteria (Python Twin) ## Goal Create a C# backend that is behaviorally equivalent to the current Python backend for core journaling workflows, with zero data-loss regressions and compatible vault handling. ## Parity Rule Behavior parity is required. Internal implementation can differ. ## Architecture Lock (Decision Record) 1. Non-AI backend remains C# system-of-record for migration scope: - entry I/O, vault crypto/load/save, search, fragments, config surface, and transport layers. 2. AI inference/execution remains Python: - C# AI code is bridge-only (`IAiService` + Python sidecar adapter), with timeout/error envelope handling. - No model inference logic or model runtime will be introduced in C# during this migration plan. 3. Speech remains intentionally Python-side delegated during hybrid and cutover phases. 4. Any change to this lock requires a written RFC, benchmark evidence, and explicit maintainer approval. ## Source of Truth (Current Python) - `journal/core/storage.py` - `journal/core/encryption.py` - `journal/core/parser.py` - `journal/core/models.py` - `journal/core/database.py` - `journal/cli/main.py` - `journal/ai/analysis.py` - `journal/ai/chat.py` - `journal/core/speech.py` ## Definition of Done (Release Gate) 1. All `P0` criteria below are marked `Pass`. 2. Existing Python-created vault files load successfully in C# backend. 3. Side-by-side output comparison on shared fixture corpus shows no functional mismatch for `P0` flows. 4. No plaintext journal data remains after graceful shutdown flow. ## Shared Fixture Corpus (Required) 1. `fixtures/vaults/` - Multiple months (`YYYY-MM.vault`) generated by Python app. - Includes at least one wrong-password test case. 2. `fixtures/entries/` - Daily, deep, recovery, fragment-heavy entries. - Includes multiline fragments, tags, checkboxes, unusual spacing. 3. `fixtures/search/` - Queries for text, section, tag, type, checked, unchecked, date ranges. 4. `fixtures/ai/` - Stubbed LLM/embedding responses for deterministic comparison. ## Acceptance Matrix Use status values: `Not Started`, `In Progress`, `Blocked`, `Pass`, `Fail`. | ID | Priority | Feature | Acceptance Criteria | Status | Owner | Evidence | | ------- | -------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | DOM-001 | P0 | Fragment model parity | Fragment has `type`, `description`, `time`, `tags`; rejects empty `type`/`description`; trims values. | Pass | Stan44/Codex/J. Schmidt | `Journal.Core/Models/Fragment.cs`, `Journal.Core/Services/FragmentService.cs`, smoke test `CreateAsync trims fields` + `UpdateAsync rejects whitespace type` | | DOM-002 | P0 | Journal entry domain parity | Entry model supports `date`, `raw_content`, `sections`, `fragments` equivalent to Python semantics. | Pass | Stan44/Gemini | `Journal.Core/Models/JournalEntry.cs`, `Journal.Core/Models/ParsedSection.cs`, `Journal.Core/Entry.cs`, smoke tests `JournalEntry model stores parity fields` + `Entry entries.save writes and merges content` + `Entry entries.load returns raw content payload` | | PAR-001 | P0 | Date extraction parity | Parser reads `**Date:**` or `Date:`; falls back to filename stem when missing. | Pass | Stan44/Gemini | `Journal.Core/Services/JournalParser.cs`, smoke tests `Parser extracts date from **Date:** marker` + `Parser falls back to file stem when date missing` | | PAR-002 | P0 | Section parsing parity | Recognizes canonical section titles and captures section content lines. | Pass | Stan44/Codex | `Journal.Core/Services/JournalParser.cs`, smoke tests `Parser captures canonical sections and content` + `Parser ignores non-canonical section headers` | | PAR-003 | P0 | Checkbox parsing parity | Parses markdown checkboxes (`- [ ]`, `- [x]`) and preserves checked state by checkbox text. | Pass | Stan44/Codex | `Journal.Core/Services/JournalParser.cs`, smoke test `Parser captures checkbox states per section` | | PAR-004 | P0 | Fragment parsing parity | Parses `!TYPE @time #tags` plus multiline description blocks with same boundary behavior as Python regex parser. | Pass | Stan44 | `Journal.Core/Services/JournalParser.cs`, smoke tests `Parser captures multiline fragment blocks` + `Parser fragment boundary follows header lines` | | MRG-001 | P0 | Merge behavior parity | Saving existing entry merges non-empty section updates and appends only non-duplicate fragments by description. | Pass | Stan44/Codex | `Journal.Core/Models/JournalEntry.cs`, smoke tests `MergeWith overwrites section when new content is meaningful` + `MergeWith appends non-duplicate fragments by description` | | MRG-002 | P0 | Markdown reconstruction parity | Entry serialization writes canonical section order and fragment block formatting equivalent to Python `to_markdown()`. | Pass | Stan44 | `Journal.Core/Models/JournalEntry.cs`, smoke tests `ToMarkdown writes canonical section order` + `ToMarkdown writes fragment blocks` | | VLT-001 | P0 | Vault crypto format compatibility | Uses AES-256-GCM with payload layout compatible with Python (`salt + nonce + tag + ciphertext`). | Pass | Stan44/Codex | `Journal.Core/Services/VaultCryptoService.cs`, smoke tests `Vault crypto roundtrip preserves data and layout` + `Vault crypto decrypts Python payload fixture` | | VLT-002 | P0 | KDF compatibility | Uses PBKDF2-HMAC-SHA256 with matching salt/key sizes and iteration count for Python vault compatibility. | Pass | Stan44/Codex | `Journal.Core/Services/VaultCryptoService.cs`, smoke test `Vault key derivation matches Python fixture` | | VLT-003 | P0 | Monthly vault naming parity | Vault filename format exactly `YYYY-MM.vault`. | Pass | Stan44/Codex | `Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault monthly filename matches parity format` | | VLT-004 | P0 | Load workflow parity | `load all vaults` clears decrypted workspace first, then decrypts/extracts monthly vaults. | Pass | Stan44/Codex | `Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault load clears workspace and extracts decrypted files` | | VLT-005 | P0 | Wrong password behavior | Wrong password returns explicit failure and does not corrupt existing vault files. | Pass | Stan44/Codex | `Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault load wrong password does not modify vault files` | | VLT-006 | P1 | Legacy vault handling | Legacy `_init_vault.vault` handling behavior is preserved or intentionally migrated with backward-compat note. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault load ignores and removes legacy _init_vault.vault`; migration note: file is ignored+deleted on load | | VLT-007 | P0 | Current-month optimized save | Supports current-month save path equivalent to Python optimization. | Pass | Stan44 | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault current-month save writes only current month and skips unchanged state` | | VLT-008 | P0 | Full rebuild save | Supports full monthly regroup/rebuild save flow from decrypted `.md` files. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault rebuild saves grouped monthly archives from decrypted files` | | DAT-001 | P0 | Decrypted data cleanup | Graceful shutdown removes decrypted workspace artifacts. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, smoke test `Vault clear data directory removes decrypted workspace artifacts` | | DB-001 | P1 | SQLCipher compatibility | Database key derivation and SQLCipher connection behavior are compatible with Python expectations. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/JournalDatabaseService.cs`, `journal-master/journal/Journal.Core/Services/IJournalDatabaseService.cs`, smoke tests `Database key derivation matches Python fixture` + `Entry db.status returns database compatibility payload` + `Entry db.hydrate_workspace returns hydration metadata` | | DB-002 | P1 | Schema parity | `entries`, `sections`, `fragments`, `tags`, `fragment_tags` schema exists with compatible constraints. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/JournalDatabaseService.cs`, smoke tests `Database schema parity tables are created` + `Entry db.initialize_schema creates schema in data directory` + `Entry db.hydrate_workspace returns hydration metadata` | | SCH-001 | P0 | Search parity (content) | Search supports text query over full entry content. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/EntrySearchService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, smoke tests `Entry search.entries matches query against full raw content` + `Entry search.entries without query returns all markdown entries` | | SCH-002 | P0 | Search parity (filters) | Search supports date range, section filter, tag filter, fragment type filter, checked/unchecked filters. | Pass | Stan44 | `journal-master/journal/Journal.Core/Services/EntrySearchService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, smoke tests for date/section/tag+type/checked+unchecked filters + invalid date handling | | CLI-001 | P0 | Vault CLI parity | CLI supports vault load/save with password prompt semantics matching Python UX. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/SidecarCli.cs`, `journal-master/journal/Journal.Sidecar/App.cs`, smoke tests `Sidecar vault CLI load succeeds with --password` + `Sidecar vault CLI save writes monthly vault with --password` | | CLI-002 | P0 | Search CLI parity | CLI options match existing Python capabilities sufficiently for drop-in replacement. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/SidecarCli.cs`, smoke tests `Sidecar search CLI returns matching entries with filters` + `Sidecar search CLI warns when no decrypted entries exist` | | API-001 | P0 | Sidecar protocol stability | Stdin/stdout contract is line-delimited JSON with `{ok,data}` or `{ok:false,error}` and strict action routing. | Pass | Stan44/Codex | `Journal.Core/Entry.cs`, `Journal.SmokeTests/Program.cs`, `Journal.SmokeTests/Fixtures/transport_cases.json` | | API-002 | P1 | HTTP API parity | API exposes endpoints equivalent to supported sidecar actions; no template-only endpoints in parity mode. | Pass | Stan44/Codex | `journal-master/journal/Journal.Api/Program.cs`, `journal-master/journal/Journal.Api/Journal.Api.http`, `tests/test_api_contract.py`, `scripts/migration-gate.ps1` | | AI-001 | P1 | LLM summarize parity | Entry/all-entry summarize workflow callable with equivalent behavior and timeout controls. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal-master/journal/Journal.Core/Entry.cs`, smoke tests for `ai.health` + summarize bridge/error handling | | AI-002 | P2 | Embedding parity | Embedding endpoint integration available with equivalent request/response contract. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal-master/journal/Journal.Core/Entry.cs`, smoke tests for `ai.embed` bridge/disabled parsing | | AI-003 | P1 | Cloud chat parity | Cloud chat request/response flow available and configurable. | Pass | Stan44 | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal/ai/chat.py`, `journal-master/journal/Journal.Core/Entry.cs`, smoke tests for `ai.chat` bridge/disabled/error handling | | SPC-001 | P2 | Speech parity | Engine-selectable speech flow (whisper/google/sphinx-like modes) retained or intentionally delegated. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Services/ISpeechBridgeService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarSpeechService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal/ai/sidecar.py`, smoke tests for speech bridge empty-device/error/timeout paths | | CFG-001 | P0 | Config parity | Equivalent configuration keys exist for paths, vault format, AI endpoints, and speech settings. | Pass | Stan44 | `journal-master/journal/Journal.Core/Services/JournalConfigService.cs`, `journal-master/journal/Journal.Core/Models/JournalConfig.cs`, smoke tests `Config service exposes parity path, vault, AI, and speech settings` + `Entry config.get returns config payload` | | OBS-001 | P1 | Logging/error parity | Failures return actionable messages without leaking secrets or plaintext journal data. | Pass | Stan44/Codex | `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.Core/Services/LogRedactor.cs`, smoke tests `Log redactor scrubs sensitive payload fields` + `Log redactor preserves non-sensitive payload fields` | ## Mandatory Gate Tests (P0) 1. `Vault Compatibility` - Given existing Python vault fixtures, C# load succeeds with correct password. - Wrong password consistently fails without partial corruption. 2. `Parser + Merge` - Given fixture entries, C# parser output matches Python parser output for sections/fragments/checkboxes. - Saving edited entry preserves merge semantics. 3. `Search` - For shared corpus, C# and Python return the same entry set for all P0 search filters. 4. `Transport` - Sidecar commands for core actions produce stable JSON success/error envelopes. 5. `Cleanup` - After graceful shutdown sequence, decrypted workspace is empty. ## Migration Phases (Recommended) 1. `Phase 1: Fragment Vertical Slice` - Complete `DOM-001`, `API-001`, persistence beyond in-memory. 2. `Phase 2: Entry/Parser/Merge Twin` - Complete `DOM-002`, `PAR-*`, `MRG-*`. 3. `Phase 3: Vault/Crypto Twin` - Complete `VLT-*`, `DAT-001`. 4. `Phase 4: Search + CLI Twin` - Complete `SCH-*`, `CLI-*`, `CFG-001`. 5. `Phase 5: AI/Speech` - Complete `AI-*` as Python-bridge parity (not C# model parity), plus `SPC-001`. 6. `Phase 6: Frontend Cutover` - Tauri frontend switches to C# backend only after all P0 criteria pass. ## Rules for Change Requests 1. Any intentional divergence from Python behavior requires: - Written rationale. - New acceptance criterion replacing old one. - Migration note describing user-visible impact. 2. No removal of a `P0` criterion without both maintainers approving in writing. ## Status Snapshot (2026-02-24, Phase 5 Complete / Phase 6 Ready) This section is a proposed status/evidence snapshot based on current code in: - Python source: `Project_Journal/` - C# migration: `Project_Journal/journal-master/journal/` It does not change release gates or acceptance definitions. ### Phase Summary | Phase | Current State | Evidence | | -------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Phase 1: Fragment Vertical Slice | Pass (complete) | Fragment model/service/sidecar + persisted repository + fixture-backed transport smoke tests: `journal-master/journal/Journal.Core/Models/Fragment.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.Core/Repositories/FileFragmentRepository.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs`, `journal-master/journal/Journal.SmokeTests/Fixtures/transport_cases.json` | | Phase 2: Entry/Parser/Merge Twin | Pass | C# `JournalEntry` domain, parser slices (`PAR-001..004`), and merge/reconstruction slices (`MRG-001..002`) are implemented with smoke evidence. | | Phase 3: Vault/Crypto Twin | Pass | Vault parity slices (`VLT-001..008`) and decrypted cleanup (`DAT-001`) are implemented with smoke evidence. | | Phase 4: Search + CLI Twin | Pass | Search parity (`SCH-001`, `SCH-002`), CLI parity (`CLI-001`, `CLI-002`), and config parity (`CFG-001`) are implemented with smoke evidence. | | Phase 5: AI/Speech | Pass | `AI-001`/`AI-002`/`AI-003` bridge parity implemented and `SPC-001` completed with Python-side speech execution + C# orchestration contract (`speech.devices.list`, `speech.transcribe`). | | Phase 6: Frontend Cutover | Ready | Release-gate fixture corpus, parity harness, and API contract tests are implemented and callable through `scripts/migration-gate.ps1`. | ### Acceptance Status Snapshot | ID | Proposed Status | Evidence | Notes | | ------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | DOM-001 | Pass | `journal-master/journal/Journal.Core/Models/Fragment.cs`, `journal-master/journal/Journal.Core/Services/FragmentService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Fields/validation/trim behavior implemented and smoke-tested. | | DOM-002 | Pass | `journal-master/journal/Journal.Core/Models/JournalEntry.cs`, `journal-master/journal/Journal.Core/Models/ParsedSection.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Entry parity is implemented for model and runtime save/load/list flows with smoke coverage (`entries.save`/`entries.load`/`entries.list`). | | PAR-001 | Pass | `journal-master/journal/Journal.Core/Services/JournalParser.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Date extraction supports `**Date:**` and `Date:` with file-stem fallback and smoke coverage. | | PAR-002 | Pass | `journal-master/journal/Journal.Core/Services/JournalParser.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Canonical section headers are recognized and section content lines are captured with smoke coverage. | | PAR-003 | Pass | `journal-master/journal/Journal.Core/Services/JournalParser.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Checkbox state extraction for `- [ ]`/`- [x]` is implemented with per-section lookup coverage. | | PAR-004 | Pass | `journal-master/journal/Journal.Core/Services/JournalParser.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Fragment header metadata and multiline description boundaries are parsed with smoke coverage. | | MRG-001 | Pass | `journal-master/journal/Journal.Core/Models/JournalEntry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Merge overwrites only meaningful section updates and appends non-duplicate fragments by description. | | MRG-002 | Pass | `journal-master/journal/Journal.Core/Models/JournalEntry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Markdown reconstruction emits canonical section order and fragment blocks with smoke coverage. | | VLT-001 | Pass | `journal-master/journal/Journal.Core/Services/VaultCryptoService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Payload layout (`salt+nonce+tag+ciphertext`) is validated and can decrypt Python-generated fixture data. | | VLT-002 | Pass | `journal-master/journal/Journal.Core/Services/VaultCryptoService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | PBKDF2-HMAC-SHA256 derivation matches Python fixture output and parameterization. | | VLT-003 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Monthly vault filename format is emitted as `YYYY-MM.vault`. | | VLT-004 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Load workflow clears decrypted workspace before decrypting and extracting vault files. | | VLT-005 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Wrong password returns failure and leaves existing vault bytes unchanged. | | VLT-006 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Legacy `_init_vault.vault` is treated as obsolete, ignored for decryption, and deleted during load for compatibility. | | VLT-007 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Current-month optimized save path is implemented with fingerprint-based skip behavior and smoke coverage. | | VLT-008 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Full monthly rebuild flow from decrypted `.md` files is implemented with smoke coverage. | | DAT-001 | Pass | `journal-master/journal/Journal.Core/Services/VaultStorageService.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Decrypted workspace cleanup path removes artifacts and recreates an empty data directory with smoke coverage. | | DB-001 | Pass | `journal-master/journal/Journal.Core/Services/JournalDatabaseService.cs`, `journal-master/journal/Journal.Core/Services/IJournalDatabaseService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | PBKDF2-HMAC-SHA256 key derivation parity plus runtime SQLCipher connection/key validation are implemented and surfaced by `db.status` (`RuntimeReady=true`) and `db.hydrate_workspace`. | | DB-002 | Pass | `journal-master/journal/Journal.Core/Services/JournalDatabaseService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Schema parity DDL for `entries/sections/fragments/tags/fragment_tags` is implemented and validated through runtime schema creation and table checks in `db.hydrate_workspace`. | | SCH-001 | Pass | `journal-master/journal/Journal.Core/Services/EntrySearchService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | `search.entries` performs case-insensitive full raw-content query across decrypted `.md` entries with smoke coverage. | | SCH-002 | Pass | `journal-master/journal/Journal.Core/Services/EntrySearchService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Date range, section-scoped query, tag/type, and checked/unchecked filters are implemented for `search.entries`. | | CLI-001 | Pass | `journal-master/journal/Journal.Core/Services/SidecarCli.cs`, `journal-master/journal/Journal.Sidecar/App.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Sidecar supports `vault load/save` CLI mode with password prompt semantics and non-interactive `--password` support. | | CLI-002 | Pass | `journal-master/journal/Journal.Core/Services/SidecarCli.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Sidecar supports search CLI flags (query/date/section/tag/type/checked/unchecked) and parity-style output messaging. | | API-001 | Pass | `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs`, `journal-master/journal/Journal.SmokeTests/Fixtures/transport_cases.json` | Line-delimited JSON envelope behavior and strict action routing are covered by smoke tests and transport fixtures. | | API-002 | Pass | `journal-master/journal/Journal.Api/Program.cs`, `journal-master/journal/Journal.Api/Journal.Api.http`, `tests/test_api_contract.py`, `scripts/migration-gate.ps1` | HTTP parity contract is locked (`POST /api/command`, `GET /health`, `GET /healthz`) with malformed/missing/unknown action coverage. | | AI-001 | Pass | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | `ai.health` + summarize bridge parity implemented with provider modes (`none`, `python-sidecar`) and timeout/error envelopes. | | AI-002 | Pass | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | `ai.embed` bridge parity is implemented with provider-mode fallback (`none`/`python-sidecar`) and smoke coverage. | | AI-003 | Pass | `journal-master/journal/Journal.Core/Services/IAiService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarAiService.cs`, `journal/ai/sidecar.py`, `journal/ai/chat.py`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | `ai.chat` bridge parity is implemented with provider-mode fallback (`none`/`python-sidecar`) and smoke coverage. | | SPC-001 | Pass | `journal-master/journal/Journal.Core/Services/ISpeechBridgeService.cs`, `journal-master/journal/Journal.Core/Services/PythonSidecarSpeechService.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal/ai/sidecar.py`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Speech delegation is locked as Python execution + C# orchestration (`speech.devices.list`, `speech.transcribe`) with timeout/error/empty-device coverage. | | CFG-001 | Pass | `journal-master/journal/Journal.Core/Services/JournalConfigService.cs`, `journal-master/journal/Journal.Core/Models/JournalConfig.cs`, `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | C# config surface now includes parity keys for paths, vault format, AI endpoints, and speech settings via `config.get`. | | OBS-001 | Pass | `journal-master/journal/Journal.Core/Entry.cs`, `journal-master/journal/Journal.Core/Services/LogRedactor.cs`, `journal-master/journal/Journal.SmokeTests/Program.cs` | Structured logging envelope and secret redaction are implemented and covered by smoke tests. | ### Snapshot Risks/Blockers 1. Remaining migration risk is operational only: maintain parity by running `scripts/migration-gate.ps1` before cutover merges. 2. DB runtime parity is active in C# with SQLCipher via NuGet packages (`Microsoft.Data.Sqlite.Core` + `SQLitePCLRaw.bundle_e_sqlcipher`) and smoke validation. 3. Hybrid DB hydration handoff remains routed through C# sidecar (`db.hydrate_workspace`) from `journal/core/storage.py`; Python-side post-load DB hydration remains disabled in hybrid mode. %% kanban:settings ``` {"kanban-plugin":"board","list-collapse":[false]} ``` %%