Tropical Update Publisher Functional Master List

Legend:

  • Existing implemented features are listed normally with Status: UNTESTED.
  • Features implemented in code but not described in project-spec.md are tagged [UNDOCUMENTED].
  • Features required by the spec but not implemented, or only represented by placeholders/stubs, are tagged [MISSING] and use Status: MISSING.

Implementation baseline observed in this codebase:

  • Main-process foundations are substantial: config loading, first-run gating, Word COM document creation, storm-folder services, quick-browse services, file copy, git publish/status, logging, CSP, crash guard, and a broad preload API.
  • Renderer coverage is still skeletal: routed shell chrome, theme handling, first-run path modal, a polished .docx drop zone, git status footer, and placeholder pages for most spec views.
  • Phase 2/NHC/AI/email/dashboard functionality is typed and routed through stub IPC channels, but not implemented.

This flattened list records the latest known status and evidence exactly once per feature ID.

F001 — npm run dev Development Launch Path

  • Category: CLI
  • Spec Reference: Section 2.1, Section 31.2
  • What it should do (end-user perspective): Let a developer build the Electron main/preload bundles, start the Vite renderer on localhost:5173, and open the desktop app in development mode.
  • How to test it (step-by-step as a human user):
    1. Open the tool directory in a terminal.
    2. Run npm run dev.
    3. Wait for Vite and Electron to start.
    4. Confirm the app window loads from the dev server without opening a browser manually.
  • Code path: package.json dev -> vite.config.ts -> src/main/index.ts -> src/main/window/createMainWindow.ts
  • Dependencies: None
  • Test data needed: Installed Node.js, npm, and project dependencies
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.json, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.stdout.log, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png

F002 — npm start Packaged-Style Local Launch Path

  • Category: CLI
  • Spec Reference: Section 2.1
  • What it should do (end-user perspective): Build the Electron main/preload code and start Electron against the compiled main entrypoint.
  • How to test it (step-by-step as a human user):
    1. Open the tool directory in a terminal.
    2. Run npm start.
    3. Confirm dist/main/main/index.js is built first.
    4. Confirm Electron launches the app window.
  • Code path: package.json start -> tsconfig.main.json / tsconfig.preload.json -> src/main/index.ts
  • Dependencies: F001
  • Test data needed: Installed Node.js, npm, and project dependencies
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-start-after-path-fix.json, refinement-state/screenshots/cycle-2/interactive-first-run-before.png, refinement-state/screenshots/cycle-2/interactive-after-continue.png

F003 — npm run build / npm run build:win Packaging Workflow

  • Category: CLI
  • Spec Reference: Section 16, Section 31.2
  • What it should do (end-user perspective): Build the renderer and main bundles, then package a Windows installer through electron-builder.
  • How to test it (step-by-step as a human user):
    1. Run npm run build.
    2. Run npm run build:win.
    3. Confirm electron-builder starts with the NSIS Windows target.
    4. Confirm output artifacts are written successfully.
  • Code path: package.json build / build:win -> vite.config.ts -> tsc -> electron-builder build block in package.json
  • Dependencies: F001
  • Test data needed: Windows host with Electron build prerequisites
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-run-build-final.log, refinement-state/functional-cycle-2-artifacts/npm-run-build-win-final.log, release/Tropical Update Publisher Setup 1.0.0.exe

F004 — npm test, npm run lint, And npm run typecheck

  • Category: CLI
  • Spec Reference: Section 27.1, Section 27.4
  • What it should do (end-user perspective): Provide repository-level verification commands for unit/component tests, ESLint, and TypeScript checking.
  • How to test it (step-by-step as a human user):
    1. Run npm test.
    2. Run npm run lint.
    3. Run npm run typecheck.
    4. Confirm each command invokes the expected toolchain without additional manual setup.
  • Code path: package.json scripts -> vitest.config.ts -> .eslintrc.cjs -> tsconfig.*.json
  • Dependencies: F001
  • Test data needed: Installed project dependencies
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-run-typecheck-final.log, refinement-state/functional-cycle-2-artifacts/npm-run-lint-final.log, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-1.log, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-2.log, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/functional-cycle-2-artifacts/vitest-shadcn-smoke-final.log

F005 — Electron Main Boot Sequence

  • Category: Backend
  • Spec Reference: Section 1, Section 2.2, Section 28.5, Section 29.1, Section 29.3
  • What it should do (end-user perspective): Start exactly one app instance, initialize logging/crash guards/CSP, enforce the first-run gate, and open the main app window securely.
  • How to test it (step-by-step as a human user):
    1. Launch the app through a supported entrypoint.
    2. Confirm only one instance remains running.
    3. Confirm the main window opens with the expected title and size constraints.
    4. Confirm the app still starts even if the renderer bundle or dev server is missing, falling back gracefully.
  • Code path: src/main/index.ts -> src/main/app/crashGuard.ts -> src/main/app/lifecycle.ts -> src/main/security/csp.ts -> src/main/window/createMainWindow.ts
  • Dependencies: None
  • Test data needed: Windows desktop environment
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-first-run-before.png, refinement-state/screenshots/cycle-2/interactive-after-continue.png, %APPDATA%/tropical-update-publisher/config.json

F006 — First-Run Gate Window Launch

  • Category: UI
  • Spec Reference: Section 19 R5, Section 23.10
  • What it should do (end-user perspective): Block normal app launch until a valid tropical updates folder path is configured, showing a dedicated first-run window.
  • How to test it (step-by-step as a human user):
    1. Start the app with no saved config or with an invalid tropical path.
    2. Confirm the first-run window opens instead of the main app shell.
    3. Confirm the renderer loads the #first-run surface.
    4. Confirm closing the first-run window aborts launch.
  • Code path: src/main/index.ts -> src/main/services/firstRun/FirstRunGate.ts -> src/main/window/createMainWindow.ts -> src/renderer/main.tsx -> src/renderer/features/first-run/FirstRunModal.tsx
  • Dependencies: F005
  • Test data needed: Missing or invalid userData/config.json
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-first-run-before.png, refinement-state/screenshots/cycle-2/interactive-after-continue.png, %APPDATA%/tropical-update-publisher/config.json

F007 — Windows Installer Configuration

  • Category: Config
  • Spec Reference: Section 16, Section 28.3
  • What it should do (end-user perspective): Package the app as an NSIS Windows installer with configurable install directory and app metadata.
  • How to test it (step-by-step as a human user):
    1. Open package.json.
    2. Confirm the Electron Builder build block targets nsis.
    3. Confirm oneClick: false and allowToChangeInstallationDirectory: true.
    4. Confirm app metadata such as appId and productName are set.
  • Code path: package.json build block
  • Dependencies: F003
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-run-build-win-final.log, release/Tropical Update Publisher Setup 1.0.0.exe

F008 — launcher.bat, launcher.vbs, And Desktop Shortcut Launchers

  • Category: CLI
  • Spec Reference: Section 2.1, Section 21
  • What it should do (end-user perspective): Provide Windows wrapper launchers and shortcut files so the app can be started outside npm commands.
  • How to test it (step-by-step as a human user):
    1. Look for launcher.bat, launcher.vbs, and shortcut/bootstrap files in the repo.
    2. Run each launcher path from Windows Explorer.
    3. Confirm the app opens without a visible console when appropriate.
    4. Confirm the desktop shortcut points to the expected launcher.
  • Code path: launcher.bat -> npm start; launcher.vbs -> launcher.bat (hidden window style 0, non-blocking); create-shortcut.ps1 -> WScript.Shell -> Tropical Update Uploader.lnk on Desktop with TargetPath = launcher.vbs
  • Dependencies: F005
  • Test data needed: Windows shell/Explorer
  • Status: PASS
  • Evidence: refinement-state/functional-verify-5-artifacts/launchers-isolated.log (3/3 tests PASS in tests/shared/launchers.test.ts), refinement-state/test-fixtures/cycle-5-verify/launchers-smoke.json (allStructuralChecksPass: true — bat calls npm start, vbs runs bat hidden with shell.Run ..., 0, False, ps1 writes Tropical Update Uploader.lnk to Desktop via WScript.Shell), refinement-state/refinement-functional-fixes-5.md (fix landing notes)

F009 — Required App Assets (WMB_Logo.png, icon.ico, Asset Docs)

  • Category: Integration
  • Spec Reference: Section 15, Section 2.2, Section 16
  • What it should do (end-user perspective): Supply the header logo and installer/window icon assets expected by the spec and packaging config.
  • How to test it (step-by-step as a human user):
    1. Look for an assets/ directory.
    2. Confirm WMB_Logo.png, icon.ico, and asset documentation exist.
    3. Launch the app and inspect the title bar/taskbar icon.
    4. Build the installer and confirm the icon is embedded.
  • Code path: assets/WMB_Logo.png + assets/icon.ico + assets/README.md generated by scripts/generate-assets.mjs; vite.config.ts publicDir: 'assets' ships the logo to dist/renderer/; src/main/window/createMainWindow.ts reads assets/icon.ico; package.json > build.win.icon references the same file for NSIS.
  • Dependencies: F005, F007
  • Test data needed: Asset files
  • Status: PASS
  • Evidence: tests/shared/assets.test.ts (6/6 PASS — PNG signature, ICO type=1, README inventory, package.json pin, vite publicDir, main icon path); refinement-state/refinement-functional-fixes-9.md

2. Core Navigation

F010 — Routed App Shell

  • Category: UI
  • Spec Reference: Section 23.3
  • What it should do (end-user perspective): Present a persistent sidebar, top bar, routed content area, and footer so the app behaves like a desktop dashboard instead of a single long page.
  • How to test it (step-by-step as a human user):
    1. Launch the main app surface.
    2. Confirm the sidebar, top bar, main route area, and footer render together.
    3. Click through the available routes.
    4. Confirm unknown hashes redirect back to Publish.
  • Code path: src/renderer/App.tsx -> src/renderer/layout/AppShell.tsx -> react-router-dom HashRouter
  • Dependencies: F005
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F011 — Sidebar Navigation And Collapse Toggle

  • Category: UI
  • Spec Reference: Section 23.3
  • What it should do (end-user perspective): Let the user switch between top-level views and collapse the sidebar to icon-only mode.
  • How to test it (step-by-step as a human user):
    1. Open the app shell.
    2. Click each sidebar item.
    3. Toggle the collapse button.
    4. Confirm active route highlighting and badge placeholders remain visible.
  • Code path: src/renderer/layout/AppShell.tsx -> src/renderer/layout/Sidebar.tsx -> src/renderer/stores/useSidebarStore.ts -> src/renderer/routes/navConfig.ts
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F012 — Top Bar Branding, Search Affordance, And Theme Button

  • Category: UI
  • Spec Reference: Section 23.3, Section 23.8
  • What it should do (end-user perspective): Show app identity, expose a centered command-palette affordance, and let the user toggle light/dark theme from the header.
  • How to test it (step-by-step as a human user):
    1. Open the main app shell.
    2. Inspect the branding, search button, and theme toggle.
    3. Click the search button.
    4. Confirm it advertises the shortcut but does not yet open a functional palette.
  • Code path: src/renderer/layout/TopBar.tsx -> src/renderer/layout/topBarModel.ts -> src/renderer/components/ThemeToggle.tsx
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F013 — Theme Toggle Persistence

  • Category: UI
  • Spec Reference: Section 23.2, Section 23.3
  • What it should do (end-user perspective): Flip between light and dark themes and remember the selected theme across renderer reloads.
  • How to test it (step-by-step as a human user):
    1. Click the theme toggle in the top bar.
    2. Confirm the dark class on <html> changes.
    3. Reload the renderer.
    4. Confirm the theme is restored from local storage.
  • Code path: src/renderer/components/ThemeToggle.tsx -> src/renderer/theme/uiTheme.ts -> src/renderer/theme/bootstrapRendererChrome.ts
  • Dependencies: F012
  • Test data needed: Browser/Electron local storage
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log
  • Category: UI
  • Spec Reference: Section 23.3, Section 14
  • What it should do (end-user perspective): Show the current git branch and placeholder status chips for monitor, AI backend, last push, storms, and network; surface a retryable error banner if git status fails.
  • How to test it (step-by-step as a human user):
    1. Open the main app shell.
    2. Inspect the footer segments.
    3. Trigger a git-status failure.
    4. Confirm the error banner appears with a retry button and branch text changes accordingly.
  • Code path: src/renderer/layout/StatusBar.tsx -> src/renderer/hooks/useGitStatus.ts -> src/renderer/api/ipcClient.ts -> src/main/ipc/handlers/gitGetStatusHandlers.ts
  • Dependencies: F010, F029
  • Test data needed: Git repo and optional non-repo scenario
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F015 — Route Fade Transitions And Reduced-Motion Respect

  • Category: UI
  • Spec Reference: Section 23.4, Section 23.6
  • What it should do (end-user perspective): Animate route changes with a short cross-fade unless reduced-motion is preferred.
  • How to test it (step-by-step as a human user):
    1. Navigate between top-level routes.
    2. Observe the fade transition timing.
    3. Enable reduced-motion preference.
    4. Confirm route changes stop animating.
  • Code path: src/renderer/layout/AppShell.tsx -> src/renderer/motion/RouteTransitionLayout.tsx -> src/renderer/motion/presets.ts
  • Dependencies: F010
  • Test data needed: Optional OS reduced-motion preference
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F016 — Drafts Route Placeholder

  • Category: UI
  • Spec Reference: Section 23.3, Section 20.4
  • What it should do (end-user perspective): Provide a dedicated Drafts route, currently with placeholder copy explaining that pending AI drafts will appear there later.
  • How to test it (step-by-step as a human user):
    1. Navigate to Drafts.
    2. Confirm the route renders successfully.
    3. Confirm the title reads Drafts.
    4. Confirm the body text is placeholder-only.
  • Code path: src/renderer/routes/Placeholders.tsx DraftsPlaceholder
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F017 — Storms Route Placeholder

  • Category: UI
  • Spec Reference: Section 23.3, Section 20.4
  • What it should do (end-user perspective): Provide a dedicated Storms route, currently with placeholder copy for future active-storm cards.
  • How to test it (step-by-step as a human user):
    1. Navigate to Storms.
    2. Confirm the route renders successfully.
    3. Confirm the title reads Storms.
    4. Confirm the body text is placeholder-only.
  • Code path: src/renderer/routes/Placeholders.tsx StormsPlaceholder
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F018 — History Route Placeholder

  • Category: UI
  • Spec Reference: Section 23.3, Section 24.4
  • What it should do (end-user perspective): Provide a dedicated History route, currently with placeholder copy for future publish/archive history.
  • How to test it (step-by-step as a human user):
    1. Navigate to History.
    2. Confirm the route renders successfully.
    3. Confirm the title reads History.
    4. Confirm the body text is placeholder-only.
  • Code path: src/renderer/routes/Placeholders.tsx HistoryPlaceholder
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F019 — Monitor Route Placeholder

  • Category: UI
  • Spec Reference: Section 20.1, Section 23.3
  • What it should do (end-user perspective): Provide a dedicated Monitor route, currently with placeholder copy for future NHC monitor status and alerts.
  • How to test it (step-by-step as a human user):
    1. Navigate to Monitor.
    2. Confirm the route renders successfully.
    3. Confirm the title reads Monitor.
    4. Confirm the body text is placeholder-only.
  • Code path: src/renderer/routes/Placeholders.tsx MonitorPlaceholder
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F020 — Settings Route Placeholder

  • Category: UI
  • Spec Reference: Section 23.3, Section 20.5
  • What it should do (end-user perspective): Provide a Settings route, currently with placeholder copy and sample staggered cards rather than a working settings form.
  • How to test it (step-by-step as a human user):
    1. Navigate to Settings.
    2. Confirm the route renders successfully.
    3. Confirm the title reads Settings.
    4. Confirm the list items are demo content only.
  • Code path: src/renderer/routes/Placeholders.tsx SettingsPlaceholder
  • Dependencies: F010
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

3. Primary Workflow

F021 — Publish View Surface

  • Category: UI
  • Spec Reference: Section 6.4, Section 23.3
  • What it should do (end-user perspective): Present the current Publish route with the drop zone, temporary queue preview, git summary, and sample controls.
  • How to test it (step-by-step as a human user):
    1. Navigate to Publish.
    2. Confirm the page heading and drop zone appear.
    3. Confirm a temporary queue preview area appears after adding files.
    4. Confirm the page is still a scaffold rather than the full spec workflow.
  • Code path: src/renderer/routes/Placeholders.tsx PublishPlaceholder
  • Dependencies: F010
  • Test data needed: One or more .docx files
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-run-dev-after-optimize-fix.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F022 — Drag-And-Drop .docx Enqueue

  • Category: UI
  • Spec Reference: Section 6.4, Section 7.7
  • What it should do (end-user perspective): Let the user drag Word documents into the drop zone, resolve absolute file paths synchronously through preload, and enqueue them into the current preview list.
  • How to test it (step-by-step as a human user):
    1. Drag one or more .docx files onto the drop zone.
    2. Confirm the zone enters its active visual state.
    3. Drop the files.
    4. Confirm their absolute paths appear in the preview queue.
  • Code path: src/renderer/features/publish/DropZone.tsx -> window.dragDrop.getPathsForFiles / getFilePaths -> src/preload/index.ts
  • Dependencies: F021
  • Test data needed: Valid non-empty .docx files
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F023 — Browse .docx Picker From Publish View

  • Category: UI
  • Spec Reference: Section 6.4, Section 7.2
  • What it should do (end-user perspective): Open a native file picker for Word documents and enqueue the selected paths into the current preview list.
  • How to test it (step-by-step as a human user):
    1. Open the Publish route.
    2. Click Browse for .docx.
    3. Select one or more .docx files from the dialog.
    4. Confirm the selected paths appear in the preview queue.
  • Code path: src/renderer/features/publish/DropZone.tsx -> window.api.dialogOpenDocx -> src/main/ipc/router.ts dialog handler
  • Dependencies: F021
  • Test data needed: Valid non-empty .docx files
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F024 — Drop Zone Validation, Error States, And Max-5 Cap

  • Category: Error Handling
  • Spec Reference: Section 6.4
  • What it should do (end-user perspective): Reject non-.docx files, zero-byte .docx files, path-resolution failures, and more than five files in one gesture with a clear visual and spoken error.
  • How to test it (step-by-step as a human user):
    1. Drop a .pdf, a zero-byte .docx, and a set larger than five files in separate attempts.
    2. Confirm the zone shakes and turns error-colored.
    3. Confirm an alert message appears and is announced.
    4. Confirm nothing is added to the queue when validation fails.
  • Code path: src/renderer/features/publish/DropZone.tsx -> src/renderer/features/publish/dropZoneModel.ts -> src/preload/index.ts
  • Dependencies: F022, F023
  • Test data needed: .pdf, zero-byte .docx, more than five .docx files
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F025 — [UNDOCUMENTED] Publish Queue Preview List

  • Category: UI
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Show a temporary unordered preview of absolute file paths added through the current drop zone implementation.
  • How to test it (step-by-step as a human user):
    1. Add one or more .docx files through drop or browse.
    2. Confirm a Queued paths (preview) card appears.
    3. Confirm each path is displayed in insertion order.
    4. Confirm there are no remove/edit/reorder controls.
  • Code path: src/renderer/routes/Placeholders.tsx local queuedDocxPaths state
  • Dependencies: F022, F023
  • Test data needed: Valid .docx files
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F026 — Publish View Git Status Summary

  • Category: UI
  • Spec Reference: Section 14
  • What it should do (end-user perspective): Show branch/cleanliness text and a manual refresh control directly within the Publish route.
  • How to test it (step-by-step as a human user):
    1. Open Publish.
    2. Wait for git status to load.
    3. Confirm branch and clean/dirty text appear.
    4. Click Refresh and confirm the query reruns.
  • Code path: src/renderer/routes/Placeholders.tsx GitStatusSummaryLine -> src/renderer/hooks/useGitStatus.ts
  • Dependencies: F029
  • Test data needed: Git repo with clean and dirty states
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F027 — [UNDOCUMENTED] Publish Timeout Unknown-State Banner

  • Category: Error Handling
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Warn the user that a publish request timed out at the renderer boundary and let them refresh git status, open the repo folder, or dismiss the banner.
  • How to test it (step-by-step as a human user):
    1. Force git:publish to hang past the renderer timeout.
    2. Open Publish.
    3. Confirm the warning banner appears.
    4. Confirm the Refresh git status, Open repo folder, and Dismiss controls work.
  • Code path: src/renderer/hooks/useGitPublish.ts -> src/renderer/components/PublishUnknownStateBanner.tsx -> window.api.configGetPublic / shellOpenPath
  • Dependencies: F029, F067, F068
  • Test data needed: Mock or stalled git:publish invocation
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F028 — File Copy To Incoming Posts With Per-File Metadata

  • Category: Backend
  • Spec Reference: Section 7.2, Section 11, Section 19 R2
  • What it should do (end-user perspective): Copy each selected .docx into the configured incoming posts directory and, when a per-file YouTube ID is supplied, write a sibling .meta.json file containing that specific youtube_id.
  • How to test it (step-by-step as a human user):
    1. Call the file-copy path with one or more .docx files and optional YouTube IDs.
    2. Confirm the files are copied into the incoming posts folder.
    3. Confirm overwritten files are flagged in the result.
    4. Confirm each non-empty YouTube ID produces a matching {stem}.meta.json.
  • Code path: window.api.copyFiles -> src/main/ipc/handlers/fileCopyHandlers.ts -> src/main/services/publish/FileCopyService.ts
  • Dependencies: F052, F057
  • Test data needed: Source .docx files and sample YouTube IDs
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/file-copy-result.json, refinement-state/test-fixtures/file-copy-overwrite-result.json, refinement-state/test-fixtures/file-copy-batch-result.json, refinement-state/test-fixtures/cycle-5/file-copy-perfile-yt-result.json (cycle 5: 3 files with 2 distinct YouTube IDs + 1 without — meta_written_flags: [true, true, false], distinct_youtube_ids: true)

F029 — Git Publish Workflow

  • Category: Backend
  • Spec Reference: Section 8, Section 19 R1
  • What it should do (end-user perspective): Publish copied files to the configured git branch using repo validation, optional stash/branch switching, pull, stage, commit, push, and restore logic.
  • How to test it (step-by-step as a human user):
    1. Prepare the repo on the target branch and on a non-target branch with local changes.
    2. Invoke publish with one or more copied files and a commit message.
    3. Confirm the app stages both .docx and available .meta.json sidecars.
    4. Confirm the branch comes from config and original state is restored after push.
  • Code path: window.api.gitPublish -> src/main/ipc/handlers/gitPublishHandlers.ts -> src/main/services/git/PublishService.ts -> src/main/services/git/GitService.ts
  • Dependencies: F028, F056, F057
  • Test data needed: Git repo, copied target files, commit message
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/cycle-2/publish-e2e-result.json

F030 — File Queue Rows, Parsed Metadata, And Row Actions

  • Category: UI
  • Spec Reference: Section 6.6, Section 12, Section 19 R2, Section 23.5
  • What it should do (end-user perspective): Show validated queue rows with parsed title/date/time, legacy conversion badges, per-file YouTube inputs, remove buttons, batch selection, drag handles, and clear-all controls.
  • How to test it (step-by-step as a human user):
    1. Add valid, invalid, and legacy-format files to the Publish queue.
    2. Confirm each row shows the correct validation state and metadata.
    3. Edit/remove/reorder files from the queue.
    4. Confirm per-file YouTube inputs are available.
  • Code path: src/renderer/features/publish/queueRowModel.ts (pure createQueueRow, addPaths dedup §12, applyYouTubeUrl/applyGlobalYouTubeUrl, removeRowById, clearAllRows) + src/renderer/stores/usePublishQueueStore.ts (Zustand store) + src/renderer/features/publish/FileList.tsx (valid/invalid row UI, per-row YouTube input, Remove + Clear All buttons) rendered via src/renderer/routes/Placeholders.tsx PublishPlaceholder.
  • Dependencies: F022, F023, F036, F037
  • Test data needed: Valid, invalid, and legacy-format .docx filenames
  • Status: PASS
  • Evidence: tests/renderer/queueRowModel.test.ts (17 tests) + tests/renderer/usePublishQueueStore.test.ts (8 tests) + tests/renderer/fileList.test.tsx (6 tests) PASS in full-suite run (659/659 across 66 files, refinement-state/refinement-functional-fixes-10.md). Covers NEW/OLD format, dedup §12, converted badge, Clear All, per-row remove, per-row YouTube validation.

F031 — Commit Message Input And Upload Button State Machine

  • Category: UI
  • Spec Reference: Section 6.7
  • What it should do (end-user perspective): Let the user edit the commit message, see auto-populated default text, and run upload only when queue/content state is valid.
  • How to test it (step-by-step as a human user):
    1. Add files to the queue.
    2. Confirm the commit message input auto-populates.
    3. Clear the message and confirm upload disables.
    4. Start an upload and confirm button text/state updates.
  • Code path: src/renderer/features/publish/commitMessageModel.ts (pure defaultCommitMessageFor, uploadButtonLabel, isUploadEnabled) + src/renderer/features/publish/CommitMessage.tsx (Input + Upload button, invokes useGitPublish, logs start/success/failure into the store) + commitMessageTouched flag in usePublishQueueStore (auto-populate stops after user edits).
  • Dependencies: F030, F029
  • Test data needed: One or more queued files
  • Status: PASS
  • Evidence: tests/renderer/commitMessageModel.test.ts (12 tests) + tests/renderer/commitMessage.test.tsx (4 tests) PASS in full-suite run (659/659 across 66 files, refinement-state/refinement-functional-fixes-10.md). Covers singular/plural copy, button labels (“Publishing…”, “Upload 1 File”, “Upload N Files”), disable gates (empty queue, blank commit msg, publishing, YouTube error), successful gitPublish invocation with descriptors.

F032 — YouTube URL UI

  • Category: UI
  • Spec Reference: Section 6.5, Section 11, Section 19 R2
  • What it should do (end-user perspective): Let the user enter either a global YouTube URL or per-file URLs, validate them live, and map them to per-file youtube_id values on publish.
  • How to test it (step-by-step as a human user):
    1. Queue multiple files.
    2. Enter valid and invalid YouTube URLs.
    3. Confirm live validation state and extracted IDs are shown.
    4. Publish and confirm each sidecar gets the expected youtube_id.
  • Code path: src/renderer/features/publish/YouTubeSection.tsx (global input with live ✓/✗ chip + 11-char video ID preview using shared validateYouTubeUrl) + per-row override input in FileList.tsx + applyGlobalYouTubeUrl / applyYouTubeUrl in queueRowModel.ts; store setGlobalYouTubeUrl re-applies to all rows and inherits URL on new enqueues (§11).
  • Dependencies: F028, F030
  • Test data needed: Sample YouTube URLs for multiple files
  • Status: PASS
  • Evidence: tests/renderer/youTubeSection.test.tsx (4 tests) + per-row coverage in tests/renderer/fileList.test.tsx (“typing an invalid per-row YouTube URL marks the input aria-invalid”) + store coverage in tests/renderer/usePublishQueueStore.test.ts (“setGlobalYouTubeUrl re-applies to all existing rows” / “newly enqueued rows inherit the current global YouTube URL”) PASS in full-suite run. Extracted ID verified against CommitMessage upload path carrying youtubeId into PublishFileDescriptor.

F033 — Status Log UI And Live Git Log Stream

  • Category: UI
  • Spec Reference: Section 6.8, Section 7.4, Section 13
  • What it should do (end-user perspective): Show a scrolling timestamped status log with up to 50 entries and real-time git publish messages from an IPC subscription.
  • How to test it (step-by-step as a human user):
    1. Start the app and open the Publish workflow.
    2. Trigger a publish or other logged action.
    3. Confirm status entries append in real time with icons and timestamps.
    4. Confirm the list trims to the newest 50 entries.
  • Code path: src/preload/index.ts (gitStreamSubscribe now wires ipcRenderer.on('git:log', …) returning an unsubscribe — previously threw NOT_IMPLEMENTED) + src/renderer/hooks/useGitLogStream.ts (installs subscriber, pushes into store) + src/renderer/features/publish/statusLogModel.ts (pure appendLogEntry with 50-entry FIFO, iconForLevel, en-US 12h formatEntryTimestamp) + src/renderer/features/publish/StatusLog.tsx (ordered list with icons + timestamps + Clear + auto-scroll). Main side already emits webContents.send('git:log', …) in src/main/ipc/handlers/gitPublishHandlers.ts.
  • Dependencies: F029
  • Test data needed: Publish activity generating logs
  • Status: PASS
  • Evidence: tests/renderer/statusLogModel.test.ts (7 tests) + tests/renderer/statusLog.test.tsx (4 tests) PASS in full-suite run. Covers icon mapping (• ✓ ⚠ ✗), 50-entry FIFO trim, en-US 12-hour timestamp format, empty-state copy, Clear button, and live gitStreamSubscribe callback forwarding into the store via useGitLogStream. Preload fix verified by tests/renderer/statusLog.test.tsx “installs the gitStreamSubscribe listener on mount and forwards events” which asserts the subscribe mock is called exactly once and payloads reach the visible log.
  • Category: UI
  • Spec Reference: Section 6.9
  • What it should do (end-user perspective): Show the full destination path where published files are copied.
  • How to test it (step-by-step as a human user):
    1. Open the Publish view.
    2. Confirm a footer text shows the full incoming path.
    3. Change config if supported.
    4. Confirm the displayed path updates.
  • Code path: src/renderer/features/publish/PublishFooter.tsx (TanStack useQueryconfig:getPublic via invokeWithTimeout) rendered by src/renderer/routes/Placeholders.tsx PublishPlaceholder; IPC chain window.api.configGetPublicsrc/preload/index.tssrc/main/ipc/router.ts (CONFIG_GET_PUBLIC) → src/main/services/config/ConfigService.ts.
  • Dependencies: F068
  • Test data needed: Loaded public config snapshot
  • Status: PASS
  • Evidence: tests/renderer/publishFooter.test.tsx 4/4 PASS (happy path renders Files are copied to {fullIncomingPath}, loading state, structured IPC failure surface, footer landmark + polite live region) in refinement-state/refinement-functional-fixes-7.md full-suite run (578/578 PASS across 56 files). Renderer wiring confirmed via grep -n PublishFooter src/renderer/routes/Placeholders.tsx → import at line 33 + <PublishFooter /> render at line 193 inside PublishPlaceholder.

F035 — Existing Incoming Files Listing

  • Category: API
  • Spec Reference: Section 7.2
  • What it should do (end-user perspective): Let the renderer ask for the current .docx files already present in the incoming posts directory.
  • How to test it (step-by-step as a human user):
    1. Ensure incoming posts contains one or more .docx files.
    2. Call the incoming-files listing API.
    3. Confirm the returned names match the folder contents.
    4. Confirm non-.docx files are excluded.
  • Code path: window.api.filesListIncoming -> src/preload/index.ts -> src/main/ipc/router.ts (FILES_LIST_INCOMING) -> src/main/ipc/handlers/incomingFilesHandlers.ts -> src/main/services/publish/IncomingFilesService.ts
  • Dependencies: F052
  • Test data needed: Sample .docx files in the incoming posts folder
  • Status: PASS
  • Evidence: refinement-state/functional-verify-4-artifacts/test-run-1.log (tests/main/incomingFilesService.test.ts 7/7, tests/main/ipcRouter.test.ts 27/27), refinement-state/test-fixtures/cycle-4-verify/incoming-files-smoke.json (happy + ENOENT + EACCES), refinement-state/test-fixtures/cycle-5/incoming-files-smoke.json (cycle 5: happy + ENOENT + empty-dir + EACCES → FILES_LIST_INCOMING_IO_ERROR; length-boundary .docx→reject vs z.docx→accept reconfirmed)

4. Secondary Features By Spec Section Order

F036 — New Filename Validation

  • Category: Backend
  • Spec Reference: Section 5.1
  • What it should do (end-user perspective): Accept valid YYYY-MM-DD[-TIME]-Slug.docx filenames, reject invalid dates/extensions/slugs, and preserve storm-type and storm-ID parsing.
  • How to test it (step-by-step as a human user):
    1. Validate a set of correctly formatted NEW filenames.
    2. Validate malformed dates, bad extensions, and short/oversized slugs.
    3. Confirm results distinguish success from failure codes.
    4. Confirm storm type and 94L/09L tokens are parsed when present.
  • Code path: src/shared/validation/FileValidator.ts parseNewFormat / validateDocxFilename
  • Dependencies: None
  • Test data needed: Valid and invalid NEW-format basenames
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/file-validator-result.json, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-5/file-validator-smoke.json (cycle 5: 22 cases — 11 valid incl. boundary years 2020/2100, months Jan/Dec, 94L/94l case; 11 rejection incl. year 2019/2101, day 00/32, month 0/13, Feb 30, short slug, bad ext, path separator, empty)

F037 — Legacy Filename Auto-Conversion

  • Category: Backend
  • Spec Reference: Section 5.2
  • What it should do (end-user perspective): Accept old Name_Time_M-D-YY.docx filenames, convert them into NEW format, and reject legacy names that convert into invalid NEW-format results.
  • How to test it (step-by-step as a human user):
    1. Validate a set of legacy-format filenames.
    2. Confirm the converted basename matches the expected NEW name.
    3. Confirm invalid converted dates fail.
    4. Confirm original legacy data is retained in the parsed result.
  • Code path: src/shared/validation/FileValidator.ts convertOldToNew / parseOldFormat / validateDocxFilename
  • Dependencies: F036
  • Test data needed: Legacy .docx basenames
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/file-validator-result.json, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-5/file-validator-smoke.json (cycle 5: Imelda_12pm_9-29-25.docx and Helene_4pm_10-15-24.docx both validate as ok: true via legacy→NEW conversion)

F038 — Filename Display Formatting With Configurable Timezone

  • Category: Config
  • Spec Reference: Section 5.4, Section 19 R4
  • What it should do (end-user perspective): Format validated filenames into display-friendly title/date/time strings and append a configurable timezone label instead of hardcoded ET.
  • How to test it (step-by-step as a human user):
    1. Parse a valid NEW-format filename.
    2. Confirm the title converts hyphens into capitalized words.
    3. Confirm storm IDs remain uppercase.
    4. Confirm the timezone label changes when timezoneLabel changes.
  • Code path: src/shared/validation/FileValidator.ts parseFilename -> src/shared/config/ConfigSchema.ts timezoneLabel
  • Dependencies: F036, F057
  • Test data needed: Valid NEW-format basenames and alternate timezone labels
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/file-validator-result.json, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-5/file-validator-smoke.json (cycle 5: 7 timezone labels — ET, CT, UTC, PT, GMT, MT, AKT — all render as suffix on 12:00 PM <TZ>; Invest storm-ID casing normalization 94lInvest 94L confirmed)

F039 — Document Creator Renderer Section

  • Category: UI
  • Spec Reference: Section 6.2, Section 5.3
  • What it should do (end-user perspective): Provide the full create-document form with date, time, storm selection, storm creation fields, update type, live filename preview, create/open button, and add-to-queue button.
  • How to test it (step-by-step as a human user):
    1. Open the Create New Briefing Document section.
    2. Change date, time, storm, and type inputs.
    3. Confirm the filename preview updates live and validates.
    4. Create the document and add it to the queue.
  • Code path: src/renderer/features/doc-creator/DocCreator.tsx + docCreatorModel.ts + useDocCreatorFocusStore.ts mounted on PublishPlaceholder (src/renderer/routes/Placeholders.tsx); Ctrl+N (useAppShortcuts.ts) and command palette (CommandPalette.tsx) both route to the section via useDocCreatorFocusStore.requestFocus()
  • Dependencies: F040, F041
  • Test data needed: Year, storm ID, storm name/type combinations
  • Status: PASS
  • Evidence: tests/renderer/docCreatorModel.test.ts (28 pure-model cases: filename grammar §5.3, storm folder §10, readiness §6.2), tests/renderer/docCreator.test.tsx (8 RTL cases: rendering, live preview, create + queue flow, DOC_EXISTS rejection, Ctrl+N focus bus), cycle-12 full suite 795/795 passing (refinement-functional-fixes-12.md)

F040 — Word COM Document Creation IPC

  • Category: Backend
  • Spec Reference: Section 7.5, Section 9
  • What it should do (end-user perspective): Create a blank .docx at the target tropical-updates folder through PowerShell Word COM automation, then open the file in the default .docx handler.
  • How to test it (step-by-step as a human user):
    1. Call doc:create with a valid filename/year/folder.
    2. Confirm the destination folder is created if missing.
    3. Confirm Word creates the .docx.
    4. Confirm Windows opens the file after creation.
  • Code path: window.api.docCreate -> src/main/ipc/handlers/docHandlers.ts -> src/main/services/word/WordDocumentService.ts
  • Dependencies: F036, F046
  • Test data needed: Valid NEW-format filename, year, optional storm folder, installed Word
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/cycle-2/word-create-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F041 — Storm Folder Creation IPC

  • Category: Backend
  • Spec Reference: Section 7.5
  • What it should do (end-user perspective): Create a storm folder under the configured tropical updates root for the given year and folder basename.
  • How to test it (step-by-step as a human user):
    1. Call storm:createFolder with a year and folder name.
    2. Confirm the year/storm path is created.
    3. Repeat the call with an existing folder.
    4. Confirm duplicate creation fails cleanly.
  • Code path: window.api.stormCreateFolder -> src/main/ipc/handlers/stormFolderHandlers.ts -> src/main/services/storms/StormFolderService.ts
  • Dependencies: F052, F057
  • Test data needed: Writable tropical root, year, storm folder name
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F042 — Single Storm Folder Rename IPC

  • Category: Backend
  • Spec Reference: Section 7.5, Section 10
  • What it should do (end-user perspective): Inspect the .docx files inside one storm folder, infer the correct target name, and rename the folder using the spec retry rules when Word locks are encountered.
  • How to test it (step-by-step as a human user):
    1. Prepare a storm folder with valid .docx files.
    2. Call storm:updateFolderName.
    3. Confirm the target folder name matches the filename evidence.
    4. Confirm lock retries and pendingRename behavior appear on repeated lock failures.
  • Code path: window.api.stormUpdateFolderName -> src/main/ipc/handlers/stormFolderHandlers.ts -> src/main/services/storms/StormFolderService.ts
  • Dependencies: F044
  • Test data needed: Storm folder with valid .docx files and optional file lock scenario
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F043 — Bulk Storm Folder Sync IPC

  • Category: Backend
  • Spec Reference: Section 7.5, Section 10
  • What it should do (end-user perspective): Walk every storm folder within a year, rename what should change, skip what is already correct, and report failures without aborting the whole year.
  • How to test it (step-by-step as a human user):
    1. Prepare a year folder with multiple storm folders.
    2. Call storm:syncAllFolderNames.
    3. Confirm renamed, skipped, and failed rows are all reported.
    4. Confirm the overall success flag is false when any operation fails.
  • Code path: window.api.stormSyncAllFolderNames -> src/main/ipc/handlers/stormFolderHandlers.ts -> src/main/services/storms/StormFolderService.ts
  • Dependencies: F044
  • Test data needed: Year folder containing multiple storm folders with varied contents
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F044 — Storm Folder Naming Rules Engine

  • Category: Backend
  • Spec Reference: Section 4.1, Section 10, Section 19 R3
  • What it should do (end-user perspective): Determine folder basenames using the runtime priority Named Storm > TD > PTC > Invest, with tie-break and consensus rule IDs for diagnostics.
  • How to test it (step-by-step as a human user):
    1. Feed the engine named-storm, TD, PTC, and invest filename combinations.
    2. Confirm named storms beat TD, TD beats PTC, and PTC beats invest.
    3. Confirm same-tier ties use filename ordering or consensus rules.
    4. Confirm validation errors fire for empty candidates or mixed storm IDs.
  • Code path: src/main/services/storms/StormFolderService.ts -> src/main/services/storms/determineFolderName.ts -> src/shared/constants/stormFolderRules.ts
  • Dependencies: F036, F037
  • Test data needed: Representative .docx basename sets for each storm-classification scenario
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json, refinement-state/test-fixtures/cycle-5/folder-name-smoke.json (cycle 5: 12 cases — full priority matrix Named > TD > PTC > Invest with every ordered pair including new named-beats-invest-only)

F045 — [MISSING] Quick Browse Renderer Section

  • Category: UI
  • Spec Reference: Section 6.3
  • What it should do (end-user perspective): Show year and storm selectors, refresh/sync buttons, a file checklist, and an Add Selected action for browsing the tropical updates folder from the app UI.
  • How to test it (step-by-step as a human user):
    1. Open the Quick Browse section.
    2. Select a year and storm.
    3. Refresh the storm file list and sync folders.
    4. Add selected files to the upload queue.
  • Code path: MISSING — browse services and IPC exist, but no renderer UI consumes them
  • Dependencies: F046, F047, F048, F049
  • Test data needed: Tropical updates directory with year/storm/docx content
  • Status: MISSING
  • Evidence:

F046 — Quick Browse Base Path Lookup

  • Category: API
  • Spec Reference: Section 7.6
  • What it should do (end-user perspective): Return the resolved tropical updates root path so the renderer can display or seed browse flows.
  • How to test it (step-by-step as a human user):
    1. Configure a valid tropical updates path.
    2. Call the base-path API.
    3. Confirm the returned path is absolute and normalized.
    4. Confirm invalid or missing config causes a structured error.
  • Code path: window.api.browseGetBasePath -> src/main/ipc/handlers/browseHandlers.ts -> src/main/services/browse/QuickBrowseService.ts
  • Dependencies: F052, F057
  • Test data needed: Valid and invalid tropical path configurations
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F047 — Quick Browse Year Listing

  • Category: API
  • Spec Reference: Section 6.3, Section 7.6
  • What it should do (end-user perspective): Return all four-digit season folders under the tropical updates root, sorted newest-first.
  • How to test it (step-by-step as a human user):
    1. Prepare multiple year directories under the tropical root.
    2. Call the year-list API.
    3. Confirm only YYYY directory names are returned.
    4. Confirm the list is sorted descending.
  • Code path: window.api.browseListYears -> src/main/ipc/handlers/browseHandlers.ts -> src/main/services/browse/QuickBrowseService.ts
  • Dependencies: F046
  • Test data needed: Multiple year folders, plus non-year directories to exclude
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F048 — Quick Browse Storm Listing

  • Category: API
  • Spec Reference: Section 6.3, Section 7.6
  • What it should do (end-user perspective): Return storm folders for a selected year with parsed folder, id, name, and displayName values sorted by numeric storm ID.
  • How to test it (step-by-step as a human user):
    1. Prepare a year folder with invest, TD/PTC, and named-storm subfolders.
    2. Call the storm-list API for that year.
    3. Confirm each row includes the expected parsed display fields.
    4. Confirm sort order follows the storm number rather than raw string order.
  • Code path: window.api.browseListStorms -> src/main/ipc/handlers/browseHandlers.ts -> src/main/services/browse/QuickBrowseService.ts
  • Dependencies: F047
  • Test data needed: Mixed storm folder names such as 94L, 07L_TD7, 09L_Imelda
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F049 — Quick Browse Storm File Listing

  • Category: API
  • Spec Reference: Section 6.3, Section 7.6
  • What it should do (end-user perspective): Return .docx files within a selected storm folder, including path, size, and modified timestamp sorted newest-first.
  • How to test it (step-by-step as a human user):
    1. Prepare a storm folder with several .docx files and non-.docx files.
    2. Call the file-list API.
    3. Confirm only .docx files are returned.
    4. Confirm they are sorted by modified time descending.
  • Code path: window.api.browseListStormFiles -> src/main/ipc/handlers/browseHandlers.ts -> src/main/services/browse/QuickBrowseService.ts
  • Dependencies: F048
  • Test data needed: Storm folder with .docx and non-.docx files
  • Status: PASS
  • Evidence: refinement-state/test-fixtures/storm-folder-result.json, refinement-state/test-fixtures/storm-folder-retry-result.json, refinement-state/test-fixtures/storm-folder-errors-result.json, refinement-state/test-fixtures/storm-sync-mixed-result.json, refinement-state/test-fixtures/quick-browse-result.json, refinement-state/test-fixtures/quick-browse-base-path-result.json, refinement-state/test-fixtures/quick-browse-invalid-base-path-result.json

F050 — Header Logo And Git Status Indicator

  • Category: UI
  • Spec Reference: Section 6.1, Section 14, Section 15
  • What it should do (end-user perspective): Show the WxManBran logo and a colored git status indicator in the header, including the uncommitted-changes warning text.
  • How to test it (step-by-step as a human user):
    1. Open the app header.
    2. Confirm the logo image is displayed.
    3. Confirm a colored dot and branch text appear in the header.
    4. Dirty the repo and confirm the warning text updates.
  • Code path: src/renderer/layout/TopBar.tsx (logo <img src="./WMB_Logo.png"> + computeHeaderGitIndicator section) -> src/renderer/layout/headerGitIndicatorModel.ts (§14 color ladder: connected/warning/error/loading) -> src/renderer/hooks/useGitStatus.ts -> git:getStatus IPC.
  • Dependencies: F009, F014
  • Test data needed: Clean and dirty repo states
  • Status: PASS
  • Evidence: tests/renderer/topBar.test.tsx (7/7 PASS — logo alt text, green/yellow/red dot variants per spec §14, command-button + theme-toggle regression); tests/renderer/headerGitIndicatorModel.test.ts (9/9 PASS — model cases for clean/dirty/error/loading/detached); refinement-state/refinement-functional-fixes-9.md

F051 — Application Menu

  • Category: UI
  • Spec Reference: Section 19 R5
  • What it should do (end-user perspective): Provide File/Edit application menus and eventually let the user open Settings from the menu.
  • How to test it (step-by-step as a human user):
    1. Launch the app on Windows.
    2. Open the application menu.
    3. Confirm File and Edit menus exist.
    4. Confirm Settings is present but currently disabled.
  • Code path: src/main/index.ts -> src/main/menu/appMenu.ts
  • Dependencies: F005
  • Test data needed: Running Electron app
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F052 — Repo/Incoming/Tropical Path Resolution

  • Category: Config
  • Spec Reference: Section 3, Section 4.2, Section 19 R5
  • What it should do (end-user perspective): Derive the repo root, incoming posts directory, full incoming path, and tropical updates path from app paths and config values.
  • How to test it (step-by-step as a human user):
    1. Inspect or call into the path service with default config.
    2. Confirm repo root resolves two levels above the tool directory.
    3. Confirm incoming posts normalizes to POSIX-style incoming/posts.
    4. Confirm %USERPROFILE% expansion works for the tropical path.
  • Code path: src/main/services/paths/PathService.ts
  • Dependencies: None
  • Test data needed: Different incoming path strings and tropical path templates
  • Status: PASS
  • Evidence: refinement-state/screenshots/cycle-2/interactive-after-continue.png, refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F053 — Config Load, Save, Atomic Write, And Migration

  • Category: Config
  • Spec Reference: Section 19 R5, Section 30.1, Section 30.2
  • What it should do (end-user perspective): Persist app configuration in userData/config.json, validate it through the shared schema, write atomically, and run versioned migrations with backups when schema versions change.
  • How to test it (step-by-step as a human user):
    1. Launch the app with no config file and confirm defaults load.
    2. Save a modified config and confirm config.json is written atomically.
    3. Corrupt the file and confirm load fails with a structured config error.
    4. Create an older schema version and confirm migration/backups run.
  • Code path: src/main/services/config/ConfigService.ts -> src/shared/config/ConfigSchema.ts
  • Dependencies: F057, F058, F059, F060
  • Test data needed: Missing, valid, corrupt, and out-of-date config files
  • Status: PASS
  • Evidence: refinement-state/functional-verify-3-artifacts/f053-migration-chain-20260408-182821.log

F054 — First-Run Path Submission And Validation

  • Category: Config
  • Spec Reference: Section 19 R5, Section 23.10
  • What it should do (end-user perspective): Validate that the configured tropical updates path is absolute, exists, is a directory, and is writable before saving it and unblocking the app.
  • How to test it (step-by-step as a human user):
    1. Open the first-run window.
    2. Submit an empty, relative, missing, non-directory, and unwritable path in separate attempts.
    3. Confirm each invalid path shows a structured error.
    4. Submit a valid path and confirm the gate resolves.
  • Code path: src/main/services/firstRun/FirstRunGate.ts -> window.api.firstRunGetState / firstRunSubmitPath -> src/renderer/features/first-run/FirstRunModal.tsx
  • Dependencies: F053
  • Test data needed: Multiple path scenarios on disk
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F055 — Settings Read API

  • Category: API
  • Spec Reference: Section 20.7, Section 28.1, Section 30.1
  • What it should do (end-user perspective): Return the current config snapshot to the renderer, optionally filtered by top-level keys, while redacting the stored Discord webhook value.
  • How to test it (step-by-step as a human user):
    1. Save a populated config.
    2. Call settings:get with and without a keys filter.
    3. Confirm schemaVersion is always included.
    4. Confirm a non-empty Discord webhook is returned as [REDACTED].
  • Code path: window.api.settingsGet -> src/main/ipc/handlers/settingsHandlers.ts -> src/main/services/config/ConfigService.ts
  • Dependencies: F053
  • Test data needed: Populated config with multiple top-level keys
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F056 — Settings Update API With Optimistic Locking

  • Category: API
  • Spec Reference: Section 20.7, Section 28.1, Section 30.2
  • What it should do (end-user perspective): Accept a patch plus expectedSchemaVersion, merge it into the current config, reject stale updates, validate the result, save it, and append a settings audit line.
  • How to test it (step-by-step as a human user):
    1. Load settings to capture the current schemaVersion.
    2. Send a valid patch with the matching version.
    3. Confirm the config saves successfully.
    4. Retry with a stale version or invalid field and confirm a structured error is returned.
  • Code path: window.api.settingsUpdate -> src/main/ipc/handlers/settingsHandlers.ts -> src/main/services/config/ConfigService.ts -> src/main/services/audit/writeAuditLine.ts
  • Dependencies: F053, F055
  • Test data needed: Valid config patches and stale-version scenarios
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F057 — Config Schema: Core Publish Settings

  • Category: Config
  • Spec Reference: Section 19 R1, Section 19 R4, Section 19 R5, Section 20.5, Section 30.1
  • What it should do (end-user perspective): Persist the core settings the implemented app already uses: schemaVersion, tropicalUpdatesPath, timezoneLabel, branch, incomingPostsPath, and onboardingComplete.
  • How to test it (step-by-step as a human user):
    1. Load a minimal config object.
    2. Confirm defaults are applied.
    3. Change each core value through settings or config load/save tests.
    4. Confirm downstream services consume the updated values.
  • Code path: src/shared/config/ConfigSchema.ts -> src/main/services/config/ConfigService.ts -> PathService / PublishService / FirstRunGate
  • Dependencies: F053
  • Test data needed: Config JSON with partial and full core settings
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F058 — Config Schema: Review And Draft Settings

  • Category: Config
  • Spec Reference: Section 20.3, Section 20.5
  • What it should do (end-user perspective): Persist review/draft-related settings already defined in the schema: approvalMode, reviewerEmail, senderEmail, senderProvider, imapInbox, maxRevisionCycles, reviewTimeoutHours, draftBackend, and backendModels.
  • How to test it (step-by-step as a human user):
    1. Load a config with review/draft keys omitted.
    2. Confirm defaults are applied.
    3. Save custom values for each field.
    4. Confirm they round-trip through settings:get and settings:update.
  • Code path: src/shared/config/ConfigSchema.ts -> src/main/ipc/handlers/settingsHandlers.ts
  • Dependencies: F053, F055, F056
  • Test data needed: Config JSON variations covering each field
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F059 — Config Schema: Monitor And Dashboard Settings

  • Category: Config
  • Spec Reference: Section 20.1, Section 20.4, Section 20.5
  • What it should do (end-user perspective): Persist monitor and dashboard preferences already defined in schema: nhcMonitor.enabled, pollIntervalMinutes, enabledProducts, manuallyWatchedStorms, excludedStorms, dashboard.sections, and dashboard.sectionOrder.
  • How to test it (step-by-step as a human user):
    1. Load config with monitor/dashboard keys omitted.
    2. Confirm defaults are applied.
    3. Save custom product arrays and dashboard section orders.
    4. Confirm values round-trip through settings APIs.
  • Code path: src/shared/config/ConfigSchema.ts -> src/main/ipc/handlers/settingsHandlers.ts
  • Dependencies: F053, F055, F056
  • Test data needed: Config JSON variations covering monitor and dashboard fields
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F060 — Config Schema: Intelligence, QoL, And Advanced Settings

  • Category: Config
  • Spec Reference: Section 24.2, Section 24.6, Section 29.1, Section 31.4
  • What it should do (end-user perspective): Persist additional settings already modeled in schema: aiCostLimits, publishing.autoCommitMessage, publishing.scheduleEnabled, social.discord, liveSiteCheck, updateCheck.manifestUrl, queue.autoSave, developer.showDraftPrompts, houseStyleRules, and logging.level.
  • How to test it (step-by-step as a human user):
    1. Load config with these fields omitted and inspect defaults.
    2. Save custom values for each group.
    3. Read them back through settings:get.
    4. Confirm secret-like keys are still blocked from config JSON.
  • Code path: src/shared/config/ConfigSchema.ts -> src/main/services/config/ConfigService.ts
  • Dependencies: F053, F055, F056
  • Test data needed: Config JSON variations for advanced fields
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F061 — OS Credential Vault Integration

  • Category: Integration
  • Spec Reference: Section 28.1
  • What it should do (end-user perspective): Store and retrieve secrets from Windows Credential Manager through keytar using the app’s fixed service name instead of saving passwords/tokens in config JSON.
  • How to test it (step-by-step as a human user):
    1. Save a credential for a supported account key.
    2. Read it back.
    3. Delete it.
    4. Confirm empty accounts, empty passwords, and vault failures map to structured errors.
  • Code path: src/main/services/security/CredentialVault.ts
  • Dependencies: None
  • Test data needed: Sample SMTP/IMAP/OAuth/GitHub/Anthropic account identifiers
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F062 — Content Security Policy Enforcement

  • Category: Backend
  • Spec Reference: Section 1 Rule 6, Section 28.2
  • What it should do (end-user perspective): Inject a baseline CSP into renderer responses, with extra dev-only relaxations for Vite HMR and no Node access in the renderer.
  • How to test it (step-by-step as a human user):
    1. Launch the app in production mode.
    2. Inspect response headers for the renderer.
    3. Confirm the baseline CSP is present.
    4. Launch in development mode and confirm HMR-specific directives are added.
  • Code path: src/main/security/csp.ts -> src/main/index.ts
  • Dependencies: F005
  • Test data needed: Development and production app launches
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F063 — Main Log File Rotation

  • Category: Backend
  • Spec Reference: Section 29.1
  • What it should do (end-user perspective): Write the main process log to userData/logs/main.log and rotate it with a five-file, five-megabyte policy.
  • How to test it (step-by-step as a human user):
    1. Start the app.
    2. Generate enough logs to exceed the size threshold.
    3. Confirm main.log.1 through main.log.5 are created as needed.
    4. Confirm file logging falls back cleanly on directory/rotation failures.
  • Code path: src/main/logging/logger.ts
  • Dependencies: F005
  • Test data needed: Writable userData path and enough log output to rotate
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F064 — Crash Guard And Previous-Crash Marker

  • Category: Error Handling
  • Spec Reference: Section 29.3
  • What it should do (end-user perspective): Catch uncaught exceptions and unhandled rejections, log them, and write a PREVIOUS_CRASH marker for future recovery handling.
  • How to test it (step-by-step as a human user):
    1. Launch the app in development mode.
    2. Trigger an uncaught exception or unhandled rejection.
    3. Confirm the failure is logged.
    4. Confirm PREVIOUS_CRASH appears under userData.
  • Code path: src/main/app/crashGuard.ts -> src/main/index.ts
  • Dependencies: F005
  • Test data needed: Controlled crash or rejection scenario
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F065 — Audit Log Append Helper

  • Category: Backend
  • Spec Reference: Section 29.4
  • What it should do (end-user perspective): Append one JSON-lines audit record into userData/logs/audit.log without crashing the process if the write fails.
  • How to test it (step-by-step as a human user):
    1. Trigger an action that writes an audit record.
    2. Open userData/logs/audit.log.
    3. Confirm a single JSON object line was appended.
    4. Confirm audit write failures are logged but non-fatal.
  • Code path: src/main/services/audit/writeAuditLine.ts
  • Dependencies: F053 or any caller using audit append
  • Test data needed: A caller that emits an audit event
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F066 — Publish History Append

  • Category: Backend
  • Spec Reference: Section 24.6, Section 30.1
  • What it should do (end-user perspective): Append a JSON-lines record of each successful publish to a user-data history file.
  • How to test it (step-by-step as a human user):
    1. Complete a successful publish.
    2. Open the publish-history file.
    3. Confirm a new line contains timestamp, branch, and commit.
    4. Confirm failed publishes do not append success records.
  • Code path: src/main/services/git/PublishService.ts -> src/main/services/publish/PublishHistoryService.ts
  • Dependencies: F029
  • Test data needed: Successful publish scenario
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F067 — [UNDOCUMENTED] shell:openPath Utility

  • Category: API
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Let renderer code request that an absolute filesystem path be opened by the OS shell, returning a structured success/error result instead of throwing raw platform errors.
  • How to test it (step-by-step as a human user):
    1. Call the utility with a valid absolute path.
    2. Confirm the target opens.
    3. Call it with an empty, relative, or invalid path.
    4. Confirm a structured error result is returned.
  • Code path: window.api.shellOpenPath -> src/main/ipc/handlers/utilityHandlers.ts
  • Dependencies: None
  • Test data needed: Valid absolute directory/file path plus invalid path examples
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F068 — [UNDOCUMENTED] config:getPublic Utility

  • Category: API
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Return the repo path, incoming posts path, full incoming path, tropical path, timezone label, and branch in one renderer-safe public snapshot.
  • How to test it (step-by-step as a human user):
    1. Save a populated config.
    2. Call the public-config API.
    3. Confirm only non-secret values are returned.
    4. Confirm the incoming path is fully resolved.
  • Code path: window.api.configGetPublic -> src/main/ipc/handlers/utilityHandlers.ts -> PathService
  • Dependencies: F052, F053
  • Test data needed: Populated config
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log, refinement-state/verification-cycle-2-artifacts/verify-regression-slice.log, refinement-state/verification-cycle-2-artifacts/npm-run-build-verify.log

F069 — [UNDOCUMENTED] paths:resolve Utility IPC

  • Category: API
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Resolve a requested incoming filename into both absolute filesystem and git-relative target paths.
  • How to test it (step-by-step as a human user):
    1. Call the path-resolution API with a sample incoming filename.
    2. Confirm the returned absolute and git-relative paths are correct.
    3. Call the API with malformed input.
    4. Confirm it rejects cleanly.
  • Code path: src/preload/index.ts pathsResolve -> src/main/ipc/handlers/utilityHandlers.ts -> src/main/ipc/router.ts
  • Dependencies: F052, F068
  • Test data needed: Sample incoming basenames
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log

F070 — Onboarding Completion IPC

  • Category: API
  • Spec Reference: Section 23.10
  • What it should do (end-user perspective): Persist onboarding completion state after the renderer submits the user’s completed first-launch answers.
  • How to test it (step-by-step as a human user):
    1. Call onboardingComplete with a completed answers payload.
    2. Confirm config.json is saved with onboardingComplete: true.
    3. Reload first-run state or restart the app.
    4. Confirm onboarding no longer reports as needed and an audit line is appended.
  • Code path: src/preload/index.ts onboardingComplete -> src/main/ipc/handlers/utilityHandlers.ts -> src/main/ipc/router.ts
  • Dependencies: F054
  • Test data needed: Completed onboarding answers payload
  • Status: PASS
  • Evidence: refinement-state/verification-cycle-2-artifacts/verify-fixes-suite.log

5. Error Handling And Recovery

F071 — Drop Zone Bridge Failure Handling

  • Category: Error Handling
  • Spec Reference: Section 6.4, Section 23.11
  • What it should do (end-user perspective): Surface clear errors if the preload drag-drop bridge or browse dialog bridge is unavailable or rejects a request.
  • How to test it (step-by-step as a human user):
    1. Simulate a missing window.dragDrop or window.api.
    2. Attempt to drop or browse files.
    3. Confirm an error toast and/or inline alert appears.
    4. Confirm the app does not silently swallow the failure.
  • Code path: src/renderer/features/publish/DropZone.tsx -> src/renderer/api/ipcClient.ts
  • Dependencies: F022, F023
  • Test data needed: Missing bridge or rejected dialog invocation
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F072 — File Copy Error Mapping And Batch Abort

  • Category: Error Handling
  • Spec Reference: Section 7.2, Section 29.2
  • What it should do (end-user perspective): Map filesystem failures into stable FILE_COPY_* codes, stop the batch at the first failing file, and mark remaining items as aborted.
  • How to test it (step-by-step as a human user):
    1. Invoke the file-copy path with multiple files.
    2. Force an ENOENT, EACCES, ENOSPC, or bad-destination case on one item.
    3. Confirm the failing row gets the correct code and user summary.
    4. Confirm later rows are returned as FILE_COPY_BATCH_ABORTED.
  • Code path: src/main/services/publish/FileCopyService.ts
  • Dependencies: F028
  • Test data needed: Missing file, locked destination, full disk simulation, malformed destination
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F073 — Git Status Error Mapping

  • Category: Error Handling
  • Spec Reference: Section 14, Section 29.2
  • What it should do (end-user perspective): Translate status failures into structured GIT_NOT_A_REPO and GIT_STATUS_FAILED errors instead of raw simple-git exceptions.
  • How to test it (step-by-step as a human user):
    1. Call git status in a valid repo.
    2. Call git status in a non-repo directory.
    3. Simulate a missing git binary.
    4. Confirm the structured error code/message matches the expected branch-indicator behavior.
  • Code path: src/main/ipc/handlers/gitGetStatusHandlers.ts -> src/main/services/git/GitService.ts -> src/main/services/git/gitStatusMapper.ts
  • Dependencies: F014
  • Test data needed: Valid repo, non-repo, and missing-git scenarios
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F074 — [UNDOCUMENTED] Duplicate Publish Guard

  • Category: Error Handling
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Reject a second publish request while one publish is already in flight.
  • How to test it (step-by-step as a human user):
    1. Start a long-running publish.
    2. Trigger a second publish request before the first completes.
    3. Confirm the second request returns a duplicate-submit warning.
    4. Confirm the first publish continues normally.
  • Code path: src/main/services/git/PublishService.ts inFlight guard
  • Dependencies: F029
  • Test data needed: Two overlapping publish attempts
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F075 — [UNDOCUMENTED] Pre-Existing Staged-Changes Conflict Guard

  • Category: Error Handling
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Refuse to publish if unrelated files are already staged in git on the target branch.
  • How to test it (step-by-step as a human user):
    1. Stage unrelated repo files manually.
    2. Run publish for tropical update files.
    3. Confirm publish stops before mutating git history.
    4. Confirm the user-facing error explains that other staged changes must be resolved first.
  • Code path: src/main/services/git/PublishService.ts findUnexpectedPreStagedPaths
  • Dependencies: F029
  • Test data needed: Target branch with unrelated staged files
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F076 — Publish No-Changes Exit

  • Category: Error Handling
  • Spec Reference: Section 8
  • What it should do (end-user perspective): Exit the publish workflow cleanly when staging produces no cached changes to commit.
  • How to test it (step-by-step as a human user):
    1. Copy files that already match repo contents.
    2. Trigger publish.
    3. Confirm publish returns success with a No changes to commit warning.
    4. Confirm stash/branch state is restored if branch switching occurred.
  • Code path: src/main/services/git/PublishService.ts PUBLISH_NO_CHANGES
  • Dependencies: F029
  • Test data needed: Repo where target files are unchanged
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F077 — Publish Remote/Auth/Conflict/Push-Rejected Recovery

  • Category: Error Handling
  • Spec Reference: Section 8, Section 29.2
  • What it should do (end-user perspective): Surface structured user messages for pull conflicts, auth failures, remote outages, checkout/stash failures, and push rejection while attempting to restore the original working state.
  • How to test it (step-by-step as a human user):
    1. Trigger each publish failure mode in isolation.
    2. Confirm a structured error code/user message is returned.
    3. Confirm branch/stash restoration is attempted after the failure.
    4. Confirm restore failures are logged without masking the original problem.
  • Code path: src/main/services/git/PublishService.ts -> src/main/services/git/GitService.ts
  • Dependencies: F029
  • Test data needed: Auth failure, pull conflict, remote outage, push reject, stash conflict scenarios
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F078 — Document Creation Validation And Word Failure Mapping

  • Category: Error Handling
  • Spec Reference: Section 9, Section 29.2
  • What it should do (end-user perspective): Reject invalid document-create requests before Word runs, and map Word/PowerShell failures into stable DOC_EXISTS, WORD_TIMEOUT, WORD_NOT_INSTALLED, and WORD_COM_FAILURE results.
  • How to test it (step-by-step as a human user):
    1. Call doc:create with invalid body shapes and unsafe paths.
    2. Call it with an existing destination file.
    3. Simulate missing Word and script timeout cases.
    4. Confirm each case returns the expected code and message.
  • Code path: src/main/ipc/handlers/docHandlers.ts -> src/main/services/word/WordDocumentService.ts
  • Dependencies: F040
  • Test data needed: Invalid requests, existing file, missing Word, long path, locked folder
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F079 — Storm Folder Validation And Rename Exhaustion

  • Category: Error Handling
  • Spec Reference: Section 10, Section 29.2
  • What it should do (end-user perspective): Reject unsafe year/folder inputs, target collisions, missing folders, and repeated lock failures with structured storm-folder error codes and pendingRename data.
  • How to test it (step-by-step as a human user):
    1. Call storm-folder APIs with invalid years and basenames.
    2. Prepare target-exists and folder-missing scenarios.
    3. Force repeated EBUSY, EPERM, or EACCES rename failures.
    4. Confirm pendingRename is returned after retries exhaust.
  • Code path: src/main/services/storms/StormFolderService.ts -> src/main/ipc/handlers/stormFolderHandlers.ts
  • Dependencies: F041, F042, F043
  • Test data needed: Invalid input values and lock-conflict scenarios
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F080 — First-Run Invalid State And Abort Handling

  • Category: Error Handling
  • Spec Reference: Section 19 R5, Section 23.10, Section 29.2
  • What it should do (end-user perspective): Reject malformed first-run IPC payloads, show inline path errors, and quit the app if the blocking first-run window is dismissed before setup completes.
  • How to test it (step-by-step as a human user):
    1. Launch the first-run gate.
    2. Submit invalid request bodies or paths.
    3. Confirm inline error copy appears.
    4. Close the window before success and confirm the app quits.
  • Code path: src/main/services/firstRun/FirstRunGate.ts -> src/renderer/features/first-run/FirstRunModal.tsx
  • Dependencies: F054
  • Test data needed: Invalid path values and early window close
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F081 — Global Renderer IPC Failure Toasts

  • Category: Error Handling
  • Spec Reference: Section 23.11
  • What it should do (end-user perspective): Show deduplicated global error toasts for query/mutation failures, provide user-friendly copy, and offer a Copy details action.
  • How to test it (step-by-step as a human user):
    1. Force an IPC query failure.
    2. Confirm a global error toast appears.
    3. Click Copy details.
    4. Confirm repeat failures within the dedupe window do not spam the UI.
  • Code path: src/renderer/api/ipcClient.ts -> src/renderer/components/ui/sonner.tsx
  • Dependencies: F014 or any failing query/mutation
  • Test data needed: Controlled IPC failures
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

F082 — [UNDOCUMENTED] NOT_IMPLEMENTED Stub Behavior For Unwired IPC

  • Category: API
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Reject calls to unwired IPC channels with a stable { code: 'NOT_IMPLEMENTED', channel } payload instead of an opaque Electron error string.
  • How to test it (step-by-step as a human user):
    1. Call a known stubbed channel such as paths:resolve or nhc:getMonitorStatus.
    2. Confirm the promise rejects with NOT_IMPLEMENTED.
    3. Call gitStreamSubscribe.
    4. Confirm the synchronous preload method throws a matching structured error.
  • Code path: src/main/ipc/router.ts stub registration -> src/preload/index.ts -> src/shared/ipc/invokeErrors.ts
  • Dependencies: None
  • Test data needed: Calls to stubbed channels
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/test-fixtures/cycle-2/publish-e2e-result.json, refinement-state/test-fixtures/cycle-2/word-create-electron-result.json

6. Keyboard Shortcuts, Accessibility, And Polish

F083 — First-Run Accessibility Baseline

  • Category: UI
  • Spec Reference: Section 23.6, Section 23.10
  • What it should do (end-user perspective): Keep the first-run window keyboard reachable with clearly labeled controls, 44px touch targets, and inline error announcements.
  • How to test it (step-by-step as a human user):
    1. Open the first-run window.
    2. Navigate the controls by keyboard only.
    3. Trigger a validation error.
    4. Confirm focus order, sizing, and alert text remain usable.
  • Code path: src/renderer/features/first-run/FirstRunModal.tsx -> src/renderer/components/ui/button.tsx -> src/renderer/components/ui/input.tsx
  • Dependencies: F006
  • Test data needed: Invalid and valid path values
  • Status: PASS
  • Evidence: refinement-state/functional-verify-3-artifacts/f083-invalid-path-a11y-20260408-182834.log

F084 — Sidebar, Button, Dialog, And Input Accessibility/Polish

  • Category: UI
  • Spec Reference: Section 23.4, Section 23.5, Section 23.6
  • What it should do (end-user perspective): Provide accessible buttons, dialogs, and sidebar navigation with focus rings, minimum touch targets, and sensible ARIA labels.
  • How to test it (step-by-step as a human user):
    1. Navigate the app shell with Tab.
    2. Open the sample dialog on Publish.
    3. Confirm focus is trapped and close controls are labeled.
    4. Confirm icon-only buttons expose accessible names.
  • Code path: src/renderer/layout/Sidebar.tsx -> src/renderer/components/ui/button.tsx -> src/renderer/components/ui/dialog.tsx -> src/renderer/components/ui/input.tsx
  • Dependencies: F010, F021
  • Test data needed: Running renderer
  • Status: PASS
  • Evidence: refinement-state/functional-verify-4-artifacts/test-run-1.log, test-run-2.log, test-run-3.log (3/3 full-suite runs 564/564 PASS, zero flakes), refinement-state/functional-verify-4-artifacts/shadcn-smoke-isolated.log (16/16 isolated PASS), refinement-state/screenshots/cycle-2/interactive-after-continue.png. Cycle-4 flake resolved by switching dialog tests to userEvent.setup({ delay: null }) + openDialogReliably helper and raising renderer project testTimeout to 20000ms (see refinement-functional-fixes-4.md). Cycle 5 restability: refinement-state/functional-cycle-5-artifacts/test-run-1.log / test-run-2.log / test-run-3.log all 564/564 PASS, shadcn-smoke-isolated.log 16/16 PASS.
  • Category: UI
  • Spec Reference: Section 23.6
  • What it should do (end-user perspective): Announce status-bar summaries politely and announce git-status failures assertively with a visible retry path.
  • How to test it (step-by-step as a human user):
    1. Open the app with a working git repo.
    2. Inspect the hidden live-region summary.
    3. Force a git-status failure.
    4. Confirm the error banner uses role="alert" and the retry action remains keyboard accessible.
  • Code path: src/renderer/layout/StatusBar.tsx -> src/renderer/layout/statusBarModel.ts
  • Dependencies: F014
  • Test data needed: Successful and failing git-status scenarios
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/screenshots/cycle-2/interactive-after-continue.png

F086 — Drop Zone Motion And Accessibility

  • Category: UI
  • Spec Reference: Section 23.4, Section 23.5, Section 23.6
  • What it should do (end-user perspective): Give the drop zone active/success/error motion feedback while exposing aria-invalid, role="alert", and polite live previews of filenames.
  • How to test it (step-by-step as a human user):
    1. Drag files over the zone.
    2. Confirm filename preview text is announced.
    3. Trigger success and error paths.
    4. Confirm motion reduces or disappears when reduced-motion is preferred.
  • Code path: src/renderer/features/publish/DropZone.tsx -> src/renderer/motion/presets.ts -> src/renderer/styles/globals.css
  • Dependencies: F022, F024
  • Test data needed: Valid and invalid file drops, reduced-motion preference
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log, refinement-state/screenshots/cycle-2/interactive-after-continue.png

F087 — Functional Command Palette

  • Category: Keyboard Shortcut
  • Spec Reference: Section 23.8
  • What it should do (end-user perspective): Open a searchable command launcher with navigation and action commands when the user presses Ctrl+K / Cmd+K.
  • How to test it (step-by-step as a human user):
    1. Press Ctrl+K or click the search affordance.
    2. Confirm a palette opens.
    3. Search for a route or command.
    4. Execute it entirely by keyboard.
  • Code path: src/renderer/features/command-palette/CommandPalette.tsx (shadcn Dialog + combobox input + listbox) -> commandPaletteModel.ts (pure filter + recency helpers) -> commandRegistry.ts (14 navigation/action/theme commands) -> src/renderer/stores/useCommandPaletteStore.ts (open/query/highlight/recent state) -> mounted in src/renderer/layout/AppShell.tsx
  • Dependencies: F012
  • Test data needed: Searchable commands and route/action registry
  • Status: PASS
  • Evidence: tests/renderer/commandPalette.test.tsx, tests/renderer/commandPaletteModel.test.ts, tests/renderer/useCommandPaletteStore.test.ts (all green in cycle-11 fixes pass), refinement-state/refinement-functional-fixes-11.md

F088 — Keyboard Shortcut Wiring

  • Category: Keyboard Shortcut
  • Spec Reference: Section 23.7
  • What it should do (end-user perspective): Implement the documented shortcuts: Ctrl/Cmd+K, P, D, S, H, ,, Enter, Del, A, Esc, N, R, /, and Shift+D combinations as described in the spec.
  • How to test it (step-by-step as a human user):
    1. Open the app shell.
    2. Press each documented shortcut in context.
    3. Confirm the expected route/action/theme/sidebar behavior fires.
    4. Confirm shortcuts are documented in Settings.
  • Code path: src/renderer/hooks/keyboardShortcutModel.ts (pure key/modifier helpers, editable-target policy, Apple detection) -> src/renderer/hooks/useAppShortcuts.ts (single window-level keydown listener, 14 bindings matching §23.7 table) -> installed from src/renderer/layout/AppShell.tsx
  • Dependencies: F010, F087
  • Test data needed: Running renderer with functional route/action handlers
  • Status: PASS
  • Evidence: tests/renderer/keyboardShortcutModel.test.ts (20/20 PASS), tests/renderer/useAppShortcuts.test.tsx (9/9 PASS), refinement-state/refinement-functional-fixes-11.md

F089 — Context Menus

  • Category: UI
  • Spec Reference: Section 23.12
  • What it should do (end-user perspective): Show right-click menus on queue files, storm cards, drafts, and published items with the actions listed in the spec.
  • How to test it (step-by-step as a human user):
    1. Right-click each supported entity type.
    2. Confirm the expected menu opens.
    3. Choose one action from each menu.
    4. Confirm the target action fires correctly.
  • Code path: src/renderer/components/ContextMenu.tsx (reusable primitive with keyboard nav + viewport clamping) -> src/renderer/features/publish/queueRowContextMenu.ts (spec §23.12 queue-row items: Remove / Preview in Word / Copy filename / Edit YouTube URL / Move to top) -> consumed by src/renderer/features/publish/FileList.tsx onContextMenu handler; storm/draft/history surfaces will consume the same primitive when those routes land (F103, F108).
  • Dependencies: F030, F103, F108
  • Test data needed: Queue items, storm cards, drafts, and published items
  • Status: PASS
  • Evidence: tests/renderer/contextMenu.test.tsx, tests/renderer/queueRowContextMenu.test.ts (all green in cycle-11 fixes pass); storm/draft/history consumers deferred to their owning features (F103 Draft Queue, F108 Publish History Dashboard) — primitive + queue-row surface satisfy the spec §23.12 clause that exists today (queued file right-click menu).

F090 — Designed Empty States

  • Category: UI
  • Spec Reference: Section 23.9
  • What it should do (end-user perspective): Show polished empty states for Publish, Drafts, Storms, and History instead of generic placeholder text.
  • How to test it (step-by-step as a human user):
    1. Open each major route with no data.
    2. Confirm a dedicated empty-state design appears.
    3. Confirm the copy matches the spec for that route.
    4. Confirm each empty state includes the intended CTA or guidance.
  • Code path: src/renderer/components/EmptyState.tsx (reusable primitive) -> src/renderer/routes/Placeholders.tsx (DraftsPlaceholder, StormsPlaceholder, HistoryPlaceholder consumers); Publish view’s illustration+CTA is provided by src/renderer/features/publish/DropZone.tsx (§8A) as spec §23.9 requires.
  • Dependencies: F021, F016, F017, F018
  • Test data needed: Empty data state for each route
  • Status: PASS
  • Evidence: tests/renderer/emptyState.test.tsx (7/7 PASS — EmptyState primitive + three route consumers assert spec §23.9 copy verbatim), refinement-state/refinement-functional-fixes-6.md (fix landing notes)

F091 — [UNDOCUMENTED] Default Dark Theme In Local Storage

  • Category: UI
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Default the renderer to dark theme when no prior choice is stored, then persist the choice under tup:ui-theme-v1.
  • How to test it (step-by-step as a human user):
    1. Clear local storage.
    2. Load the renderer.
    3. Confirm dark theme is applied.
    4. Toggle to light and confirm the storage key is written.
  • Code path: src/renderer/theme/uiTheme.ts -> src/renderer/theme/bootstrapRendererChrome.ts
  • Dependencies: F013
  • Test data needed: Empty local storage
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

F092 — [UNDOCUMENTED] Ephemeral Sidebar Collapse State

  • Category: UI
  • Spec Reference: UNDOCUMENTED (not found in project-spec.md)
  • What it should do (end-user perspective): Keep sidebar collapse state only for the current renderer session without persisting it to local storage or config.
  • How to test it (step-by-step as a human user):
    1. Collapse the sidebar.
    2. Navigate between routes.
    3. Confirm the sidebar stays collapsed during the session.
    4. Reload the renderer and confirm it resets to expanded.
  • Code path: src/renderer/stores/useSidebarStore.ts
  • Dependencies: F011
  • Test data needed: None
  • Status: PASS
  • Evidence: refinement-state/functional-cycle-2-artifacts/npm-test-final-rerun-3.log

7. Phase 2 / Advanced Feature Gaps

F093 — [MISSING] NHC Monitor Scheduler

  • Category: Backend
  • Spec Reference: Section 20.1
  • What it should do (end-user perspective): Run a background service that polls NHC on the configured cadence with backoff and rate limits.
  • How to test it (step-by-step as a human user):
    1. Enable monitoring.
    2. Leave the app open through multiple poll intervals.
    3. Confirm monitor cycles run on schedule and back off on failures.
    4. Confirm pause/resume controls affect the scheduler.
  • Code path: MISSING — no main-process monitor service or timers exist
  • Dependencies: F059
  • Test data needed: Reachable NHC endpoints or mocks
  • Status: MISSING
  • Evidence:

F094 — [MISSING] NHC Product Fetchers And HTTP Rules

  • Category: Integration
  • Spec Reference: Section 20.1
  • What it should do (end-user perspective): Fetch TCPAT, TCMAT, TCDAT, TCUAT, WTNT/WOCA, graphics, active-storm JSON, and RSS with the configured headers, timeout, cache, and rate-limit behavior.
  • How to test it (step-by-step as a human user):
    1. Start the NHC monitor.
    2. Confirm each enabled product type can be fetched.
    3. Inspect request headers, timeout behavior, and one-request-per-endpoint-per-minute enforcement.
    4. Confirm failures back off instead of flooding requests.
  • Code path: MISSING — no HTTP client or NHC fetch modules exist
  • Dependencies: F093
  • Test data needed: Mock or live NHC responses
  • Status: MISSING
  • Evidence:

F095 — [MISSING] Change Detection, Fingerprints, And Active-Storm State

  • Category: Backend
  • Spec Reference: Section 20.1, Section 30.1, Section 30.3
  • What it should do (end-user perspective): Fingerprint fetched NHC products, detect advisory changes, and persist active-storm state across restarts.
  • How to test it (step-by-step as a human user):
    1. Fetch a storm product set twice.
    2. Confirm unchanged content does not trigger a draft.
    3. Change the source body and confirm a new fingerprint/event is recorded.
    4. Restart the app and confirm active-storm state resumes.
  • Code path: MISSING — no fingerprint or active-storm persistence files are produced by current code
  • Dependencies: F093, F094
  • Test data needed: Stable and changed NHC payload samples
  • Status: MISSING
  • Evidence:

F096 — [MISSING] Monitor Override UI And Persistence

  • Category: UI
  • Spec Reference: Section 20.1, Section 20.4, Section 20.5
  • What it should do (end-user perspective): Let the user manually watch invests and exclude storms from monitor tracking, with those overrides persisted to config/state.
  • How to test it (step-by-step as a human user):
    1. Open the monitor or settings UI.
    2. Add a manual storm watch and an exclusion.
    3. Restart the app.
    4. Confirm the overrides persist and affect monitor behavior.
  • Code path: MISSING — config fields exist, but no UI or runtime behavior consumes them
  • Dependencies: F059, F093
  • Test data needed: Example manual watch/exclusion storm IDs
  • Status: MISSING
  • Evidence:

F097 — [MISSING] AI Backend Execution Switching

  • Category: Integration
  • Spec Reference: Section 20.2, Section 20.5
  • What it should do (end-user perspective): Run the configured Claude/Cursor/Codex backend using the exact CLI conventions and let the next draft switch backends when settings change.
  • How to test it (step-by-step as a human user):
    1. Configure each AI backend in turn.
    2. Trigger a draft job.
    3. Confirm the expected CLI command is executed.
    4. Confirm changing settings affects the next draft without restart.
  • Code path: MISSING — no AI executor or ai:testBackend main handler exists
  • Dependencies: F058, F100
  • Test data needed: Working AI CLI installations and a sample draft job
  • Status: MISSING
  • Evidence:

F098 — [MISSING] Prompt Assembly From House Style, Templates, Examples, And NHC Sources

  • Category: Backend
  • Spec Reference: Section 20.2, Section 26
  • What it should do (end-user perspective): Assemble draft prompts from the house style guide, Word templates, recent briefings, raw NHC products, and revision instructions using the exact template structure defined by the spec.
  • How to test it (step-by-step as a human user):
    1. Prepare a storm with source advisories and recent briefings.
    2. Trigger draft generation.
    3. Inspect the generated prompt file.
    4. Confirm the required sections appear in the specified order.
  • Code path: MISSING — no prompt-assembly or document-ingestion modules exist
  • Dependencies: F094, F097
  • Test data needed: House style markdown, templates, recent .docx files, NHC source text
  • Status: MISSING
  • Evidence:

F099 — [MISSING] AI Draft Output Files And .draft-meta.json

  • Category: Backend
  • Spec Reference: Section 20.2
  • What it should do (end-user perspective): Write AI-generated draft .docx files into the storm folder and persist a .draft-meta.json sidecar with backend, advisory, timestamp, and review metadata.
  • How to test it (step-by-step as a human user):
    1. Trigger a successful draft generation.
    2. Confirm a .docx is written into the storm folder.
    3. Confirm filename collision logic uses -ai-draft when needed.
    4. Confirm the .draft-meta.json sidecar is written beside the draft.
  • Code path: MISSING — no draft writer or sidecar generator exists
  • Dependencies: F097, F098
  • Test data needed: Draftable storm/advisory inputs
  • Status: MISSING
  • Evidence:

F100 — [MISSING] Review Modes, Dashboard Review, And Email Approval Flow

  • Category: Integration
  • Spec Reference: Section 20.3
  • What it should do (end-user perspective): Support review, auto-publish, and dashboard-only approval modes; send draft emails; accept YES/NO/CANCEL responses; and publish or revise accordingly.
  • How to test it (step-by-step as a human user):
    1. Configure each approval mode.
    2. Trigger a draft.
    3. Confirm the expected email or dashboard behavior occurs.
    4. Confirm YES publishes, NO revises, and CANCEL stops the draft.
  • Code path: MISSING — no SMTP/IMAP services, dashboard review UI, or approval-state runtime exists
  • Dependencies: F097, F098, F099
  • Test data needed: Reviewer mailbox, SMTP/IMAP credentials, sample draft
  • Status: MISSING
  • Evidence:

F101 — [MISSING] Revision Loop, Resume, Archive, And Timeout Handling

  • Category: Backend
  • Spec Reference: Section 20.3, Section 30.1
  • What it should do (end-user perspective): Persist draft queue state, resume unfinished work on restart, archive terminal drafts, and auto-cancel stale drafts.
  • How to test it (step-by-step as a human user):
    1. Start a draft and stop the app mid-flow.
    2. Restart the app.
    3. Confirm the draft resumes from the correct phase.
    4. Confirm old drafts are archived or auto-cancelled per the spec.
  • Code path: MISSING — no draft-queue.json, draft-history, or resume engine exists
  • Dependencies: F100
  • Test data needed: Interrupted and aged draft jobs
  • Status: MISSING
  • Evidence:

F102 — [MISSING] AI Cost Cap Enforcement

  • Category: Config
  • Spec Reference: Section 20.3, Section 20.5
  • What it should do (end-user perspective): Track token/dollar usage against daily and weekly caps, finish in-flight drafts, block new ones, and surface a warning banner.
  • How to test it (step-by-step as a human user):
    1. Configure strict cost caps.
    2. Run draft jobs until the limit is reached.
    3. Confirm in-flight jobs finish but new jobs are blocked.
    4. Confirm the warning state clears after the reset boundary.
  • Code path: MISSING — schema fields exist, but no runtime accounting or UI exists
  • Dependencies: F058, F097
  • Test data needed: Draft jobs with mocked token/cost accounting
  • Status: MISSING
  • Evidence:

F103 — [MISSING] Rich Dashboard Sections And Layout Preferences

  • Category: UI
  • Spec Reference: Section 20.4, Section 23.3
  • What it should do (end-user perspective): Render the spec dashboard sections (Active Storms, Pending Drafts, Draft Pipeline, Publish History, NHC Status, Alerts, Revisions, AI Stats, Quick Actions) and let the user show/hide/reorder them.
  • How to test it (step-by-step as a human user):
    1. Open the dashboard views.
    2. Confirm each section exists.
    3. Hide, show, and reorder sections.
    4. Restart the app and confirm preferences persist.
  • Code path: MISSING — only placeholder routes and schema defaults exist
  • Dependencies: F059, F093, F100
  • Test data needed: Dashboard data for each section plus saved layout preferences
  • Status: MISSING
  • Evidence:

F104 — [MISSING] Phase 2 IPC Implementations

  • Category: API
  • Spec Reference: Section 20.7
  • What it should do (end-user perspective): Implement the unwired Phase 2 IPC endpoints: nhc:*, draft:*, email:testConnection, ai:testBackend, audit:export, and app:getDiagnostics.
  • How to test it (step-by-step as a human user):
    1. Call each advertised Phase 2 API from the renderer.
    2. Confirm it reaches a real main-process handler.
    3. Confirm fulfilled payloads match the shared types.
    4. Confirm failures use structured error shapes instead of NOT_IMPLEMENTED.
  • Code path: src/preload/index.ts exposes these methods -> src/main/ipc/router.ts currently registers stub handlers only
  • Dependencies: F093, F097, F100, F101
  • Test data needed: Calls for each advertised IPC method
  • Status: MISSING
  • Evidence:

F105 — [MISSING] Publishing Intelligence Features

  • Category: Backend
  • Spec Reference: Section 24.2
  • What it should do (end-user perspective): Generate smart commit messages, schedule publishes, verify live-site availability after push, and support publish-time intelligence rather than only manual fixed commit text.
  • How to test it (step-by-step as a human user):
    1. Queue a publishable update.
    2. Confirm the commit message auto-generates from parsed metadata.
    3. Schedule a delayed publish and wait for the scheduled time.
    4. Confirm the app verifies the site went live after push.
  • Code path: MISSING — config fields mention some advanced publishing options, but runtime publish logic only accepts a provided commit message and immediate push
  • Dependencies: F029, F060
  • Test data needed: Parsed tropical update metadata and a live-site check target
  • Status: MISSING
  • Evidence:

F106 — [MISSING] Multi-Destination And Social Publishing

  • Category: Integration
  • Spec Reference: Section 24.2
  • What it should do (end-user perspective): Publish the same update to the main WxManBran site and optional external destinations such as Discord/social surfaces.
  • How to test it (step-by-step as a human user):
    1. Configure one or more secondary destinations.
    2. Publish an update.
    3. Confirm the site publish still succeeds.
    4. Confirm each enabled secondary destination also receives its post.
  • Code path: MISSING — schema includes social.discord, but there is no runtime delivery service or UI
  • Dependencies: F029, F060
  • Test data needed: Destination credentials/webhooks and a publishable update
  • Status: MISSING
  • Evidence:

F107 — [MISSING] Content Quality And Sanity Checks

  • Category: Backend
  • Spec Reference: Section 20.8, Section 24.3, Section 26.4
  • What it should do (end-user perspective): Check AI-generated content for readability, terminology consistency, numeric mismatches, grammar, and excessive duplication before publish.
  • How to test it (step-by-step as a human user):
    1. Generate or prepare a draft with known quality issues.
    2. Run the quality-check pipeline.
    3. Confirm each issue type is flagged.
    4. Confirm auto-publish is blocked on numeric mismatches or [NEEDS REVIEW] conditions.
  • Code path: MISSING — no draft-analysis or number-sanity modules exist
  • Dependencies: F098, F099, F100
  • Test data needed: AI draft text plus NHC source material with intentional mismatches
  • Status: MISSING
  • Evidence:

F108 — [MISSING] Historical/Season Features

  • Category: UI
  • Spec Reference: Section 24.4
  • What it should do (end-user perspective): Provide a season archive browser, storm timeline, annual report generation, and template-evolution tracking.
  • How to test it (step-by-step as a human user):
    1. Open the History/Archive views.
    2. Browse past seasons and storm timelines.
    3. Generate an annual report.
    4. Inspect template evolution comparisons.
  • Code path: MISSING — no archive/timeline/report modules or route implementations exist
  • Dependencies: F018, F066
  • Test data needed: Historical publish and storm data
  • Status: MISSING
  • Evidence:

F109 — [MISSING] Notifications And Alerts

  • Category: Integration
  • Spec Reference: Section 24.5
  • What it should do (end-user perspective): Deliver desktop notifications, optional sounds, do-not-disturb handling, and possibly mobile notifications for key monitor/draft/publish events.
  • How to test it (step-by-step as a human user):
    1. Enable notifications.
    2. Trigger draft-ready, publish-success, and monitor-error events.
    3. Confirm the correct alerts are delivered.
    4. Confirm DND rules suppress only the appropriate events.
  • Code path: MISSING — no notification or sound services exist
  • Dependencies: F093, F100
  • Test data needed: Triggerable app events
  • Status: MISSING
  • Evidence:

F110 — [MISSING] Quality-Of-Life Workflow Features

  • Category: UI
  • Spec Reference: Section 24.6, Section 31.4
  • What it should do (end-user perspective): Restore queue state after crash, undo the last publish, warn on template diffs, support offline mode, export config backups, and check for updates.
  • How to test it (step-by-step as a human user):
    1. Build queue state and crash/restart the app.
    2. Publish once and invoke undo.
    3. Work offline and then reconnect.
    4. Export config and confirm the update-check path runs once per day.
  • Code path: MISSING — config fields exist for some advanced options, but no runtime/UI implementations exist
  • Dependencies: F021, F029, F060
  • Test data needed: Queue state, git history, offline simulation, update manifest endpoint
  • Status: MISSING
  • Evidence:

F111 — [MISSING] Audit And Compliance Enhancements

  • Category: Backend
  • Spec Reference: Section 24.7, Section 29.4
  • What it should do (end-user perspective): Preserve source attribution, draft fingerprints, revision diffs, and long-lived audit/compliance history beyond the current minimal audit helper.
  • How to test it (step-by-step as a human user):
    1. Generate and publish a draft.
    2. Inspect audit/compliance records.
    3. Confirm source attribution and fingerprint metadata are retained.
    4. Confirm prior draft revisions remain viewable for the retention window.
  • Code path: MISSING — only a minimal audit-log append helper and publish-history append helper exist
  • Dependencies: F065, F066, F099, F101
  • Test data needed: Draft and publish lifecycle events
  • Status: MISSING
  • Evidence: