Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Phase 0 and Phase 2 hardening complete as of v1.19.0. Remaining open items:
| --- | --- | --- | --- |
| SEC-1 | Collaboration | Mandatory password enforcement — `CollabEncryptionRequiredError` thrown in `collaborationService.ts` when no password is provided in production | ✅ Complete (Phase 0) |
| SEC-2 | Documentation | Updated security policy, version table, scope, and active-item tracking | ✅ Complete (Phase 0) |
| SEC-3 | Storage | IDB at-rest encryption — `services/storage/storageEncryptionService.ts`, AES-256-GCM, PBKDF2 600k iter; `enableIdbAtRestEncryption` flag (off by default) | ✅ Implemented (Phase 2 / B-1) |
| SEC-3 | Storage | IDB at-rest encryption — `services/storage/storageEncryptionService.ts`, AES-256-GCM, PBKDF2 600k iter; `enableIdbAtRestEncryption` flag (on by default since v1.23) | ✅ Implemented (Phase 2 / B-1) |
| SEC-4 | Voice | Web Speech API consent gate — GDPR Art. 13 disclosure and explicit opt-in before audio is routed to cloud STT providers | ✅ Complete (Phase 0) |
| SEC-5 | Storage | IDB at-rest encryption UX — passphrase unlock modal, forgot-passphrase export flow, key rotation UI | ✅ Complete (2026-06-02) |
| SEC-6 | Storage | DuckDB OPFS at-rest encryption — WAL and data files outside IDB; requires separate encryption layer | ⬜ Phase 3 (P0-4) |
Expand Down
6 changes: 3 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ types.ts → Core shared interfaces and types

7. **Command Center:** Palette commands live in **`services/commands/`** (i18n keys, fuzzy search, recent/pinned). **`CommandExecutorProvider`** exposes execution for Help „Try it” (`tryActionId`) and toasts with **`commandId`**. **`useGlobalKeyboardShortcuts`** reads Redux shortcut bindings; **`app/transientUiStore`** toggles palette visibility.

8. **ProForge Pipeline:** 8-stage agentic manuscript editing pipeline gated behind `featureFlags.enableProForge` (off by default). Stage sequence: `intake` → `structural` → `lineProse` → `copyEdit` → `proof` → `production` → `publishing` → `analytics`. Manuscripts are **never auto-modified** — each stage pauses at `awaitingReview`. Orchestrator: `services/proForge/proForgeOrchestrator.ts`; Redux slice: `features/proForge/proForgeSlice.ts`; UI: `components/proForge/` (ProForgeDashboard, PipelineProgressPanel, PipelineReviewPanel); docs: `docs/PROFORGE-PIPELINE.md`.
8. **ProForge Pipeline:** 8-stage agentic manuscript editing pipeline gated behind `featureFlags.enableProForge` (on by default). Stage sequence: `intake` → `structural` → `lineProse` → `copyEdit` → `proof` → `production` → `publishing` → `analytics`. Manuscripts are **never auto-modified** — each stage pauses at `awaitingReview`. Orchestrator: `services/proForge/proForgeOrchestrator.ts`; Redux slice: `features/proForge/proForgeSlice.ts`; UI: `components/proForge/` (ProForgeDashboard, PipelineProgressPanel, PipelineReviewPanel); docs: `docs/PROFORGE-PIPELINE.md`.

9. **Voice Full Support:** Gated behind `featureFlags.enableVoiceSupport` + `settings.voice.enabled`. Abstract engine pattern in `services/voice/voiceTypes.ts` (SttEngine, TtsEngine, VadEngine, WakeWordEngine, IntentEngine). `VoiceCommandService` singleton manages state machine (idle → listening → processing → speaking). Web Speech API fallbacks require zero downloads. Hooks: `useVoice`, `usePushToTalk` (Ctrl+Shift+V), `useVoiceDictation`.

10. **Feature Flags:** 21 flags in `features/featureFlags/featureFlagsSlice.ts`. Default **on**: `enableCodexAutoTracking`, `enableCrossProjectSearch`, `enablePlotBoardV2` (deprecated UI, retained for localStorage compat). All others default off. Key flags: `enableProForge`, `enableGlobalCopilot`, `enableVoiceSupport`, `enableDuckDbAnalytics`, `enableWorkerBusV2`. Do not use scattered `if (true)` hacks — all experimental features must go through a flag.
10. **Feature Flags:** **23 flags** in `features/featureFlags/featureFlagsSlice.ts`. New installs get the **full feature set** — all default **on** except five opt-in flags that default **off**: `enableRtlLayout`, `enableVoiceSupport`, `enableVoiceWasm`, `enableGlobalCopilot`, `enableLocalFirstSync`. (`enableCodexAutoTracking` + `enableCrossProjectSearch` were promoted to permanent core; `enablePlotBoardV2` + `enableCloudSync` were retired — none remain in the slice.) See `docs/FEATURE-PARITY.md`. Do not use scattered `if (true)` hacks — all experimental features must go through a flag.

11. **Global AI Copilot (v2):** `enableGlobalCopilot` flag. `CopilotPanel` (dialog/sidebar mode), `CopilotMessageList` (markdown rendering via DOMPurify), `InlineAnnotationLayer` (badge in ManuscriptEditor). Heuristic rules: `services/copilot/heuristicEngine.ts` (8 rules). Apply-to-chapter: `services/copilot/actionApplier.ts` (offset-safe edit, redux-undo, ≥70% length gate). ProForge integration: Ask-Copilot chip on each `ReviewItemCard`. Docs: `docs/COPILOT.md`, `docs/HEURISTIC-RULES.md`.

Expand Down Expand Up @@ -175,7 +175,7 @@ See `AUDIT.md` and `TODO.md`. Key items:
- `app/listenerMiddleware.ts` — occasional TypeScript friction with redux-undo `StateWithHistory`
- `workers/inference.worker.ts:50` — `@ts-expect-error` on `@xenova/transformers` dynamic import (Vite resolves at build, `tsc` cannot)
- **DS-5:** Delete legacy bridge block from `index.css` — deferred until DS-1 token migration verified in production
- **v2.0 stubs behind feature flags:** RTL layout (`enableRtlLayout`), Cloud-Sync R2 adapter (`enableCloudSync`), LoRA adapter inference (`enableLoraAdapters`), Plugin system loader (`enablePluginSystem`)
- **v2.0 stubs behind feature flags:** RTL layout (`enableRtlLayout`), LoRA adapter inference (`enableLoraAdapters`), Plugin system loader (`enablePluginSystem`). (The Cloud-Sync R2 adapter's `enableCloudSync` flag was **retired** in v1.20 — activation is now `CloudSyncBackend.create(..., explicitConsent)`.)
- RTCDataChannel in-flight E2E encryption is **shipped** (y-webrtc patch v1.17.0) — no longer open

## Commands
Expand Down
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ updates:
schedule:
interval: weekly
day: monday
# QNBS-v3: cooldown delays Dependabot PRs until a release has aged 7 days — matched to the
# .npmrc `minimum-release-age=10080` (7-day) supply-chain policy, so a freshly-published
# version is never PR'd before `pnpm install --frozen-lockfile` would accept it (avoids
# ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION CI failures like #154/#155). The .npmrc gate is
# install-time only; this cooldown is the PR-creation-time counterpart.
cooldown:
default-days: 7
open-pull-requests-limit: 10
groups:
# QNBS-v3: react and react-dom must stay in lockstep; split bumps cause version-mismatch errors at test time.
Expand Down Expand Up @@ -35,6 +42,8 @@ updates:
schedule:
interval: weekly
day: monday
cooldown:
default-days: 7
open-pull-requests-limit: 5
groups:
tauri-deps:
Expand All @@ -50,4 +59,6 @@ updates:
schedule:
interval: weekly
day: monday
cooldown:
default-days: 7
open-pull-requests-limit: 5
20 changes: 13 additions & 7 deletions .github/workflows/tauri-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,30 @@ jobs:
[ -f "$SIG_FILE" ] || continue
BASE="${SIG_FILE%.sig}"
FNAME="$(basename "$BASE")"
# QNBS-v3: GitHub normalizes spaces in uploaded asset names to dots (e.g.
# "WorldScript Studio_*.AppImage" → "WorldScript.Studio_*.AppImage"). The bundle file on
# disk still has the space, so the updater URL MUST use the normalized name or it 404s.
URLNAME="${FNAME// /.}"
SIG_CONTENT="$(cat "$SIG_FILE")"
case "$FNAME" in
*.AppImage)
LINUX_URL="${REPO_URL}/${FNAME}"; LINUX_SIG="$SIG_CONTENT" ;;
LINUX_URL="${REPO_URL}/${URLNAME}"; LINUX_SIG="$SIG_CONTENT" ;;
*-setup.exe)
# NSIS installer — preferred Windows updater format
WIN_URL="${REPO_URL}/${FNAME}"; WIN_SIG="$SIG_CONTENT" ;;
WIN_URL="${REPO_URL}/${URLNAME}"; WIN_SIG="$SIG_CONTENT" ;;
*.msi)
# MSI fallback if no NSIS sig collected yet
[ -z "$WIN_SIG" ] && { WIN_URL="${REPO_URL}/${FNAME}"; WIN_SIG="$SIG_CONTENT"; } ;;
[ -z "$WIN_SIG" ] && { WIN_URL="${REPO_URL}/${URLNAME}"; WIN_SIG="$SIG_CONTENT"; } ;;
*_aarch64.app.tar.gz)
# QNBS-v3: macOS updater bundle is .app.tar.gz (not .dmg).
# .dmg is the user-facing installer; .app.tar.gz is what Tauri downloads for in-app updates.
# aarch64 = macos-latest ARM runner. x64 runner not yet in matrix.
MAC_AARCH64_URL="${REPO_URL}/${FNAME}"; MAC_AARCH64_SIG="$SIG_CONTENT" ;;
MAC_AARCH64_URL="${REPO_URL}/${URLNAME}"; MAC_AARCH64_SIG="$SIG_CONTENT" ;;
*_x64.app.tar.gz)
MAC_X64_URL="${REPO_URL}/${FNAME}"; MAC_X64_SIG="$SIG_CONTENT" ;;
MAC_X64_URL="${REPO_URL}/${URLNAME}"; MAC_X64_SIG="$SIG_CONTENT" ;;
*.app.tar.gz)
# Fallback for generic .app.tar.gz (older Tauri versions)
MAC_AARCH64_URL="${REPO_URL}/${FNAME}"; MAC_AARCH64_SIG="$SIG_CONTENT" ;;
MAC_AARCH64_URL="${REPO_URL}/${URLNAME}"; MAC_AARCH64_SIG="$SIG_CONTENT" ;;
esac
done

Expand All @@ -213,4 +217,6 @@ jobs:

echo "Generated latest.json:"
cat latest.json
gh release upload "$TAG" latest.json --clobber
# QNBS-v3: this job has no actions/checkout, so gh has no local git context — pass --repo
# explicitly or `gh release upload` aborts with "fatal: not a git repository" (v1.23.0 fix).
gh release upload "$TAG" latest.json --clobber --repo "$GITHUB_REPOSITORY"
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ WorldScript-Studio/
│ ├── status/ # App-wide status / loading flags
│ ├── writer/ # Writer view state
│ ├── versionControl/ # Snapshots and branches
│ ├── featureFlags/ # ~20 experimental flags (mostly off by default)
│ ├── featureFlags/ # 23 flags — full set on by default; 5 opt-in (default-off)
│ ├── plotBoard/ # Ephemeral viewport/draw state (NOT undo-able; localStorage)
│ ├── progressTracker/ # Writing sessions, streaks, goals
│ ├── sceneComments/ # Per-scene comments (EntityAdapter)
Expand Down Expand Up @@ -181,7 +181,7 @@ pnpm run mutation # Stryker mutation testing (CI-only; manual workflow

# Analysis / budgets
pnpm run analyze # Rollup visualizer → dist/bundle-analysis.html
pnpm run bundle:budget # Chunk size guard (default max 6500 KB total, 4000 KB entry)
pnpm run bundle:budget # Chunk size guard (default max 6200 KB total, 2500 KB entry)
pnpm run storybook # Storybook dev server on :6006
pnpm run build-storybook # Static Storybook build
pnpm run test:storybook # Test-runner against served Storybook
Expand Down Expand Up @@ -387,7 +387,7 @@ Edge builds run `scripts/build-edge.mjs` which sets `DEPLOY_TARGET=edge` and pat

### Feature Flags

- `features/featureFlags/featureFlagsSlice.ts` gates ~20 experimental flags + `enableVoiceSupport` (mostly off by default; a few like `enableCodexAutoTracking` and `enableCrossProjectSearch` are on).
- `features/featureFlags/featureFlagsSlice.ts` gates **23 flags**. New installs get the **full feature set**: all default **on** except five opt-in flags that default **off** — `enableRtlLayout`, `enableVoiceSupport`, `enableVoiceWasm`, `enableGlobalCopilot`, `enableLocalFirstSync`. (`enableCodexAutoTracking` + `enableCrossProjectSearch` were promoted to permanent core; `enablePlotBoardV2` + `enableCloudSync` were retired — none remain in the slice.) See `docs/FEATURE-PARITY.md` for the per-flag matrix.
- UI: Settings → Experimental flags.
- Do not use scattered `if (true)` hacks.

Expand Down Expand Up @@ -455,15 +455,15 @@ Central orchestration layer for all background worker tasks. Messages use short
- `services/hybridRouter.ts` — routes to Web Worker pool or Rust TaskSupervisor (Tauri only) when `enableRustCompute` is on.
- `services/legacyWorkerBusAdapter.ts` — shims old `@domain/ai-core` WorkerBus API onto v2.
- `services/tauriTaskBridge.ts` — `invokeRustTask()`, `isRustComputeAvailable()` (60s TTL ping cache).
- Feature flags: `enableWorkerBusV2` (off by default), `enableRustCompute` (off by default; Tauri desktop only).
- Feature flags: `enableWorkerBusV2` (on by default), `enableRustCompute` (on by default; effective on Tauri desktop only).
- v2 workers: `workers/v2/inference.worker.ts` (text + embed via Hugging Face transformers), `workers/v2/duckdb.worker.ts` (init/query/exec/shutdown).

### DuckDB Analytics

- `workers/duckdbWorker.ts` runs DuckDB-WASM off main thread (OPFS persistence → in-memory fallback).
- `services/duckdb/duckdbClient.ts` is a singleton proxy with AbortSignal and init retry.
- Schema (`duckdbSchema.ts`): 10 tables + 5 views including `rag_chunks` (FLOAT[384]), `cross_project_index`, `codex_*`.
- Gated behind `featureFlagsSlice.enableDuckDbAnalytics` (off by default).
- Gated behind `featureFlagsSlice.enableDuckDbAnalytics` (on by default).
- Dual-write (IDB + DuckDB) goes through `duckdbListenerLoader.ts` in the listener middleware.

---
Expand Down
Loading
Loading