Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
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"
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
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
20 changes: 17 additions & 3 deletions AUDIT.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
# WorldScript Studio — Codebase Audit Report

**Date:** 2026-04-17 (baseline); **follow-up chain:** … → 2026-05-28 (v1.19.0 — Security/Voice/RTL/Logger B-1..B-8) → **2026-05-30 (B-1 passphrase UX + CI unblock)** → **2026-05-31 (i18n audit + settings features + CI stabilization)** → **2026-05-31 (Edge-AI Perfection Cycle — Phases 0-7 complete)** → **2026-06-01 (Post-crash session: CI stabilisation + 14 CodeAnt AI fixes + E2E hardening)** → **2026-06-02 (Perf Phase 2.3 — pipeline-LRU unification + PR #69 CodeAnt fixes)** → **2026-06-03 (WorkerBus v2 Phase 3 — Rust TaskSupervisor + Tauri-build unblock)** → **2026-06-06 (Phase 3 i18n Expansion — ja/zh/pt/el + Intl APIs)** → **2026-06-09 (v1.21 Deep Audit Correction — Whisper WASM download UI + 3 CodeAnt fixes + CloudSync LWW)** → **2026-06-09 (feat/deep-audit-v1.21 — CSP hardening, zh locale ≤5% EN, coverage Batches A/B/C, VoiceActivityCoordinator B-2 bridge)** → **2026-06-11 (Ultimate Copilot v2 Phase 2+3 — markdown, sidebar, Apply-to-chapter, InlineAnnotation, ProForge chip; PR #110+#111)** → **2026-06-11 (v1.22.0 release — OpenRouter Cloud 5 provider, AI Execution Modes hybrid/cloud/local/eco, AiModeIndicator, SW cache-invalidation fix)**
**Date:** 2026-04-17 (baseline); **follow-up chain:** … → 2026-05-28 (v1.19.0 — Security/Voice/RTL/Logger B-1..B-8) → **2026-05-30 (B-1 passphrase UX + CI unblock)** → **2026-05-31 (i18n audit + settings features + CI stabilization)** → **2026-05-31 (Edge-AI Perfection Cycle — Phases 0-7 complete)** → **2026-06-01 (Post-crash session: CI stabilisation + 14 CodeAnt AI fixes + E2E hardening)** → **2026-06-02 (Perf Phase 2.3 — pipeline-LRU unification + PR #69 CodeAnt fixes)** → **2026-06-03 (WorkerBus v2 Phase 3 — Rust TaskSupervisor + Tauri-build unblock)** → **2026-06-06 (Phase 3 i18n Expansion — ja/zh/pt/el + Intl APIs)** → **2026-06-09 (v1.21 Deep Audit Correction — Whisper WASM download UI + 3 CodeAnt fixes + CloudSync LWW)** → **2026-06-09 (feat/deep-audit-v1.21 — CSP hardening, zh locale ≤5% EN, coverage Batches A/B/C, VoiceActivityCoordinator B-2 bridge)** → **2026-06-11 (Ultimate Copilot v2 Phase 2+3 — markdown, sidebar, Apply-to-chapter, InlineAnnotation, ProForge chip; PR #110+#111)** → **2026-06-11 (v1.22.0 release — OpenRouter Cloud 5 provider, AI Execution Modes hybrid/cloud/local/eco, AiModeIndicator, SW cache-invalidation fix)** → **2026-06-13/14 (v1.23 perfection batch — OpenRouter + AI-Execution-Mode settings sections localized/modernized, i18n single-brace interpolation bug-class fix + `i18nPlaceholders` regression guard, bundle split + budget tightening PR #130)** → **2026-06-16 (v1.23.0 release — rebrand StoryCraft → WorldScript Studio, local-first data foundation ADR-0008, Tauri blank-screen + asset-URL fixes, AI error taxonomy + retry hardening, command-palette & local-AI settings localization, WorldScript W monogram icons)** → **2026-06-16 (post-release documentation perfection pass — corpus sync, metric reconciliation, history archival, dependabot hardening)**
**Scope:** Full application, repository configuration, CI/CD, documentation, release validation
**Current version:** **v1.22.0** — 2026-06-11 (OpenRouter Cloud 5 provider; AI Execution Modes hybrid/cloud/local/eco; AiModeIndicator; Ultimate Copilot AI v2 Phases 1-3; HeuristicEngine 8 rules; InsightGenerator debounce+LRU; sidebar mode; Apply-to-chapter; InlineAnnotationLayer; ProForge Ask-Copilot chip; PWA SW cache fix; **2594 keys × 11 locales**; docs/COPILOT.md + docs/HEURISTIC-RULES.md)
**Current version:** **v1.23.0** — 2026-06-16 (Rebrand StoryCraft → WorldScript Studio; local-first data foundation behind `enableLocalFirstSync` (ADR-0008); Tauri blank-screen + updater asset-URL fixes; AI error taxonomy + retry hardening; OpenRouter reactive cloud-policy; command-palette & local-AI settings localization; WorldScript W monogram icons; **2709 keys × 11 locales**; v1.23 perfection engagement — docs/AUDIT-PERFECTION-PLAN-v1.23.md)

**Quality gate (2026-06-11 — v1.22.0):** lint ✅ · typecheck ✅ · i18n:check ✅ (**2594 keys × 11 locales**) · unit tests ✅ (5 475+ / 449 files) · coverage thresholds L74/B60/F67/S72 ✅. Toolchain: Node 22/24, **pnpm 11**, Vite 8, TypeScript 7 (tsgo).
**Quality gate (2026-06-16 — v1.23.0):** lint ✅ · typecheck ✅ · i18n:check ✅ (**2709 keys × 11 locales**) · placeholder guard ✅ · unit tests ✅ (5807+ / 485 files) · coverage thresholds L74/B60/F67/S72 ✅. Toolchain: Node 22/24, **pnpm 11**, Vite 8, TypeScript 7 (tsgo).

## v1.23.0 Post-Release Documentation Perfection Pass (2026-06-16)

**Scope:** Bring the entire doc corpus into lockstep with the shipped v1.23.0 code, curate/restructure historical material, clear the Dependabot queue, and complete the GitHub release/package rebrand.

- **Metric reconciliation:** `scripts/sync-readme-metrics.mjs` re-run → README now reads **2709 keys / 485 test files** (was 2706 / 481). AUDIT header (version, quality-gate, follow-up chain) advanced from the stale **v1.22.0** label to **v1.23.0** with current numbers.
- **Feature-flag truth-up:** docs claimed **21** flags; the slice has **23**. `CLAUDE.md` rewritten — the default model had inverted (new installs get the **full set**; only 5 default off: `enableRtlLayout`, `enableVoiceSupport`, `enableVoiceWasm`, `enableGlobalCopilot`, `enableLocalFirstSync`). Retired/promoted flags (`enableCodexAutoTracking`, `enableCrossProjectSearch`, `enablePlotBoardV2`, `enableCloudSync`) removed from the live list. Three slice JSDoc `(default: true)` annotations that contradicted the runtime defaults corrected to `(default: false)`.
- **Bundle budget:** current help/docs aligned to **6200 / 2500** (`AGENTS.md`); `docs/CODE_QUALITY.md` confirmed not to hardcode the figure.
Comment thread
qnbs marked this conversation as resolved.
Comment thread
qnbs marked this conversation as resolved.
- **Roadmap/TODO:** v1.23 section flipped from "ACTIVE / target 2026-06-20" to **RELEASED 2026-06-16** with the real deliverables; forward P1/P2 work consolidated into a single **Upcoming — v1.24 / v2.0 Foundation** block.
- **Corpus restructure:** archived finished plans into `docs/history/` via `git mv` — `EDGE_AI_PERFECT_PLAN.md`, `EDGE_AI_ZWISCHENSTAND.md`, `CHECKPOINT-2026-05-24.md`, `CHECKPOINT-2026-06-06.md`, `WIEDERAUFNAHME.md`; inbound links repaired (0 broken relative links).
- **Rebrand residue:** ADR-0008 present-tense "StoryCraft is offline-first" → "WorldScript Studio". Remaining `storycraft*` hits are intentional historical records (CHANGELOG version entries, archived sprints) or technical identifiers that were genuine at their version — left intact.
- **GitHub releases:** 6 historical release titles renamed StoryCraft → WorldScript (v1.3.0, v1.5.0, v1.7.0, v1.17.0, v1.20.0, v1.21.0); v1.23.0 release/tag verified correct (latest, full changelog, tag → `fbaa33c3`).
- **GitHub Packages:** orphaned `storycraft-studio` GHCR container image to be deleted so only `worldscript-studio` remains (requires `delete:packages` token scope — pending maintainer auth refresh).
- **Dependabot hardening:** added `cooldown: default-days: 3` to all three `.github/dependabot.yml` ecosystems so newly released versions age 3 days before a PR is opened (the dependabot.yml equivalent of the `.npmrc` `minimum-release-age` already set for pnpm install-time). Open queue (#150/#151 Rust candle green; #152 dev-tooling + #154/#155 npm failing) handled per the CodeAnt Correction Loop.
Comment thread
qnbs marked this conversation as resolved.
Outdated

## v1.23 i18n Interpolation Bug-Class Fix + Regression Guard (2026-06-14)

Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ Production uses **rolldown** (not esbuild/rollup); CI E2E runs `vite dev` — pr

### Feature Flags

Experimental features are gated behind `features/featureFlags/featureFlagsSlice.ts` (21 flags). Default **on**: `enableCodexAutoTracking`, `enableCrossProjectSearch`, `enablePlotBoardV2` (@deprecated — v1 board removed in v1.6; retained in slice for localStorage compat; hidden from Settings UI). All others default **off**. UI: Settings → Experimental flags (`FeatureFlagsSection.tsx`). Do not use scattered `if (true)` hacks.
Experimental features are gated behind `features/featureFlags/featureFlagsSlice.ts` (**23 flags**). New installs get the **full feature set**: all flags default **on** except five user-opt-in flags. `enableCodexAutoTracking` + `enableCrossProjectSearch` were promoted to permanent core behaviour (v1.20 / v1.8); `enablePlotBoardV2` and `enableCloudSync` were retired — none of those four remain in the slice. UI: Settings → Experimental flags (`FeatureFlagsSection.tsx`). Do not use scattered `if (true)` hacks.

Key flags (on by default): `enableDuckDbAnalytics`, `enableProForge`, `enableStoryBibleAdvanced`, `enableBinderResearch`, `enableCompileWizard`, `enableProjectHealthScore`, `enableAppHealthPanel`. **User opt-in (off by default):** `enableVoiceSupport` (requires browser mic permission), `enableVoiceWasm` (B-2, ~57 MB Whisper download), `enableGlobalCopilot` (ambient AI), `enableRtlLayout` (B-5, ar/he stubs only), `enableIdbAtRestEncryption` (B-1, passphrase UX complete — enable via Settings › Privacy). **Edge-AI (all off):** `enableAdaptiveAiEngine`, `enableWebnnInference`, `enableComputeShaders`, `enableWorkerBusV2`, `enableRustCompute`. **Stub/future (all off):** `enableLoraAdapters`, `enablePluginSystem`, `enableObjectsGroups`, `enableMindMaps`, `enableCharacterInterviews`. Note: `enableCloudSync` was **retired** in v1.20 (no UI shipped; `CloudSyncBackend.create()` requires explicit-consent boolean instead).
**Default on (18):** `enableStoryBibleAdvanced`, `enableBinderResearch`, `enableCompileWizard`, `enableProjectHealthScore`, `enableAppHealthPanel`, `enableDuckDbAnalytics`, `enableObjectsGroups`, `enableMindMaps`, `enableCharacterInterviews`, `enableLoraAdapters`, `enablePluginSystem`, `enableProForge`, `enableIdbAtRestEncryption` (B-1, passphrase UX complete — Settings › Privacy), `enableAdaptiveAiEngine`, `enableWebnnInference`, `enableComputeShaders`, `enableWorkerBusV2`, `enableRustCompute`. **User opt-in — default off (5):** `enableVoiceSupport` (requires browser mic permission), `enableVoiceWasm` (B-2, ~57 MB Whisper download), `enableGlobalCopilot` (ambient AI), `enableRtlLayout` (B-5, ar/he stubs only), `enableLocalFirstSync` (shadow Yjs projection, ADR-0008; Redux stays SoT). Note: `enableCloudSync` was **retired** in v1.20 (no UI shipped; `CloudSyncBackend.create()` requires explicit-consent boolean instead).

### Command Center & shortcuts

Expand Down Expand Up @@ -329,7 +329,7 @@ All `.md` guides listed in **[`README.md`](README.md#-documentation-hub) § Docu

**useAppSelectorShallow with plotBoard:** Include `plotBoard: { activeMode: 'swimlane', snapToGrid: false, selectedConnectionId: null, isDrawingConnection: false, drawFromSectionId: null, activeSubplotFilter: null, zoom: 1, panX: 0, panY: 0 }` in mock state. Connections/subplots/tensionOverrides are in `project.present.data`. Add `// biome-ignore lint/suspicious/noExplicitAny: test mock` before `(selector: (s: any) => unknown)` lines.

**FeatureFlagsState mocks:** Always include ALL 21 flags (TypeScript strict rejects partial). Flags that are **off** by default: `enableRtlLayout`, `enableVoiceSupport`, `enableVoiceWasm`, `enableGlobalCopilot`, `enableIdbAtRestEncryption`, and all edge-AI flags (`enableAdaptiveAiEngine`, `enableWebnnInference`, `enableComputeShaders`, `enableWorkerBusV2`, `enableRustCompute`). When a test needs a flag that is off by default, set it explicitly in the mock — don't assume the default.
**FeatureFlagsState mocks:** Always include ALL 23 flags (TypeScript strict rejects partial). Only **five** default **off**: `enableRtlLayout`, `enableVoiceSupport`, `enableVoiceWasm`, `enableGlobalCopilot`, `enableLocalFirstSync` — every other flag (including all edge-AI flags and `enableIdbAtRestEncryption`) defaults **on**. When a test needs a non-default flag state, set it explicitly in the mock — don't assume the default.

**ConnectionLayer test IDs:** `data-testid="connection-group"` — query by testid, not role.

Expand Down
Loading
Loading