diff --git a/CHANGELOG.md b/CHANGELOG.md index b568e109..40635e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (4×429 → 5 min pause, RPM tracking), which shipped without a Help entry. Added to the AI Studio help category, deep-linking to Settings; translated into the five Production locales, English fallback for the other 14 (per the tag-dense-HTML help-body policy). +- **DeepSource static-analysis integration (token-free).** Added [`.deepsource.toml`](.deepsource.toml) + (analysis-only — no autofix transformers, so it never fights Biome and needs no repo token; activates + once the free DeepSource OSS app is installed). Auto-detects JavaScript/Rust/Docker/CSS analyzers. + Complements the existing CI gate as a second review layer while CodeAnt's free-tier quota is + exhausted. Process: [`docs/DEEPSOURCE-REVIEW-LOOP.md`](docs/DEEPSOURCE-REVIEW-LOOP.md) (living runbook, + complements the CodeAnt one); backlog tracking: [`docs/DEEPSOURCE-REMEDIATION-PLAN.md`](docs/DEEPSOURCE-REMEDIATION-PLAN.md) + (prioritised P0-security→P5-docs, with the triage principle: rule-ignore findings already governed by + Biome/strict-TS/test convention, fix DeepSource-unique real issues). ### Changed @@ -67,6 +75,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 audit. WebNN execution-provider selection remains available internally in `packages/ai-core/src/webnnBridge.ts` (always attempted when the browser exposes WebNN); only the no-op user toggle is gone. +- **Dead Settings toggles removed (19 no-op toggles across 6 sections).** A full audit found settings + that persisted a value **no service or hook ever read**. Removed the whole **Notifications**, + **Performance**, and **Backup** sections (all no-ops; the real one-click encrypted backup lives in + Settings → Data, untouched), the dead sync/import card in **Integrations** (Notion/Evernote/Google + Docs/Scrivener — the **LanguageTool** integration is real and kept), the 4 dead **Collaboration** + toggles (the **WebRTC signaling URLs** field is real and kept), and Privacy's `crashReporting` / + `shareUsageData` (analytics/encryption/data-residency stay). Also cleaned `settingsSearchHints.ts` + (stale hints for the removed categories; retargeted Integrations hints to grammar/spell). Each was a + stacked PR with its own tests + i18n removal across 19 locales. ## [1.24.0] — 2026-06-21 diff --git a/README.md b/README.md index 41947cc7..3126fc0d 100644 --- a/README.md +++ b/README.md @@ -719,6 +719,8 @@ See **[`CONTRIBUTING.md`](CONTRIBUTING.md)** for the full dev setup, Biome / Vit | [`AUDIT.md`](AUDIT.md) | Security & quality audit trail + scorecard | | [`docs/AUDIT-PERFECTION-PLAN-v1.23.md`](docs/AUDIT-PERFECTION-PLAN-v1.23.md) | Living master plan for the v1.23 audit/perfection engagement (phase status + batch log) | | [`docs/CI.md`](docs/CI.md) | GitHub Actions jobs, Node/pnpm parity, Act examples | +| [`docs/DEEPSOURCE-REVIEW-LOOP.md`](docs/DEEPSOURCE-REVIEW-LOOP.md) | DeepSource static-analysis correction loop (living runbook; complements the CodeAnt loop) | +| [`docs/DEEPSOURCE-REMEDIATION-PLAN.md`](docs/DEEPSOURCE-REMEDIATION-PLAN.md) | Prioritised DeepSource backlog tracker (P0-security→P5-docs) with triage decisions | | [`docs/adr/`](docs/adr/README.md) | Architecture Decision Records — state-management boundaries, local-AI stack layering, WorkerBus v2 hybrid routing | | [`docs/ACCESSIBILITY.md`](docs/ACCESSIBILITY.md) | A11y architecture (live regions, focus, WCAG 2.2, Lighthouse 0.95 gate) | | [`docs/BEST-PRACTICES.md`](docs/BEST-PRACTICES.md) | Engineering + content guidelines, glossary, CI parity checklist | diff --git a/docs/CODEANT-LOOP-RUNBOOK.md b/docs/CODEANT-LOOP-RUNBOOK.md index fafe9c71..a7bc4988 100644 --- a/docs/CODEANT-LOOP-RUNBOOK.md +++ b/docs/CODEANT-LOOP-RUNBOOK.md @@ -1,166 +1,33 @@ -# CodeAnt Correction-Loop Runbook (executable) - -> Operational, command-level companion to the policy doc -> [`CODEANT-REVIEW-LOOP.md`](CODEANT-REVIEW-LOOP.md). Use this to **run** the loop across one or -> more open PRs in a single combined pass. Captures the live state of the architecture-refactor PRs -> so a later session can resume without re-deriving context. - -Repo: `qnbs/WorldScript-Studio` · default branch: `main`. - ---- - -## 0. When to run - -Run **after** all planned feature/refactor work for a batch is shipped as open PRs (this is the -deferred final step). The intent for the current effort: a **second plan** will be authored and -executed the same way (more PRs); then run this loop over **every** open PR — this plan's *and* the -next plan's — together. - -## 1. The iron rule - -Loop until **quiescent**: a fresh CodeAnt review yields **0 new comments** AND **0 unresolved -threads**. Each push triggers a new review wave that often raises new findings; never stop while -comments are still arriving. **Never add a new `biome-ignore`/eslint-disable** to silence a finding — -the suppression ratchet (`scripts/check-suppressions.mjs`) fails the quality gate; refactor instead. - -## 2. Per-PR procedure - -For each open PR `` (process one PR fully, then the next): - -### 2a. Fetch unresolved threads (thread id + comment db id + anchor + body) - -```bash -gh api graphql -f query='query { repository(owner:"qnbs",name:"WorldScript-Studio"){ - pullRequest(number:){ reviewThreads(first:100){ nodes { - id isResolved isOutdated path line - comments(first:1){ nodes { databaseId author{login} body } } } } } } }' \ - --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false) | - "\(.id) | \(.comments.nodes[0].databaseId) | \(.path):\(.line) | \(.comments.nodes[0].author.login)"' -``` - -### 2b. For each thread — validate against the CURRENT code (anchors may be stale) - -Then either: -- **Fix the root cause fully** — code **+ tests + i18n + docs** in lockstep. Prefer - behavior-preserving fixes; if a fix changes behavior, make sure that's intended and tested. -- **Or justify** with evidence why it's a false positive / out-of-scope (e.g. pre-existing behavior - moved verbatim by a pure refactor → track as a follow-up, don't change behavior in that PR). - -### 2c. Reply to the thread (cite the resolving commit or the justification) - -```bash -gh api repos/qnbs/WorldScript-Studio/pulls//comments \ - -f body='Fixed in : .' \ - -F in_reply_to= -``` - -### 2d. Resolve the thread - -```bash -gh api graphql -f query='mutation { resolveReviewThread(input:{threadId:""}){ thread { isResolved } } }' -``` - -### 2e. After addressing the batch: verify locally (low-end hardware → one at a time) - -```bash -find . -name '*.tsbuildinfo' -not -path './node_modules/*' -delete && pnpm run typecheck -pnpm run lint -pnpm exec vitest run -``` - -### 2f. Commit, push, re-trigger - -```bash -git commit -m "fix(): address CodeAnt review — " -git push -gh pr comment --body "@codeant-ai review" -``` - -### 2g. Loop - -Wait for the new review wave, re-run **2a**. Repeat until **0 unresolved AND 0 new**. - -## 3. Merge criteria (per PR) - -Only when **both**: full CI green (every job — security/quality/build/e2e/lighthouse/storybook, not -just required checks) **AND** the loop is quiescent. Then squash-merge (admin-squash only after CI is -green + loop quiescent). These refactor PRs are independent (mostly disjoint files); P4 adds -`xstate`/`@xstate/react` deps. Merge order doesn't matter except rebase any that drift. - ---- - -## 4. Live state — architecture-refactor batch (snapshot 2026-06-17) - -Six open PRs off `main`, all opened CI-green; CodeAnt reviews arriving. The Tauri SW hotfix already -merged to `main` + released as `v1.23.1` (not part of this loop). - -| PR | Branch | Scope | Loop status | -|----|--------|-------|-------------| -| #177 | `refactor/project-slice-reducer-modules` | P1 — projectSlice → 12 reducer modules | **In progress** — see §4a | -| #178 | `refactor/command-palette-hook-virtualization` | P2 — `useCommandPalette` + virtualization | Not started (fetch threads) | -| #179 | `refactor/view-layout-extraction` | P3 — ManuscriptView/WriterViewUI layout extraction | Not started | -| #180 | `refactor/proforge-xstate-machine` | P4 — ProForge XState machine (additive core) | Not started | -| #181 | `docs/xstate-hybrid-adr` | P5 — ADR-0009 + machine catalogue (docs) | Not started | -| #182 | `docs/security-drift-housekeeping` | SEC-6/7/8 drift reconciliation (docs) | Not started | - -> Plus the **next plan's** PRs (to be created) — include them in the same combined pass. - -### 4a. PR #177 — in-progress detail - -CI green. CodeAnt posted **5 inline findings**. Commit **`c7638f15`** (pushed) already fixed **3**: -- `storyObjectReducers.updateStoryObject` — id kept immutable (assign then restore) → referential - integrity for `objectGroups[*].objectIds`. -- `storyObjectReducers.updateObjectGroup` — same, for `storyObjects[*].groupIds`. -- `binderReducers.deleteBinderNode` — visited guard on the recursive subtree collector (cyclic - parentId chains no longer recurse forever). Tests added in `projectSlice.objects.test.ts` + - `projectSlice.test.ts`. - -**Still TODO for #177** (re-fetch thread ids via 2a — they rotate on re-trigger; these are the -2026-06-17 ids): - -1. **Reply + resolve the 3 fixed threads**, citing `c7638f15`: - - `PRRT_kwDOQOeAgc6KWFoJ` (comment `3431202507`) — storyObjectReducers updateStoryObject id. - - `PRRT_kwDOQOeAgc6KWFoU` (comment `3431202520`) — storyObjectReducers updateObjectGroup id. - - `PRRT_kwDOQOeAgc6KWG9O` (comment `3431209957`) — binderReducers cycle guard. -2. **Justify + resolve the 2 remaining** (pre-existing behavior moved verbatim by a zero-behavior - -change decomposition; track as follow-ups, do not change behavior in this PR): - - `PRRT_kwDOQOeAgc6KWFoZ` (comment `3431202527`) — `writingAnalyticsReducers.updateWritingGoal`: - `WritingGoal.id` is optional in the type but the reducer targets by a required id. Reply: - *in-app goals always carry an id; the optionality is import/type tolerance. Targeting by - required id is the intended contract and is unchanged from the pre-split reducer — not a - regression. Tracked as a type-model nuance.* - - `PRRT_kwDOQOeAgc6KWG9W` (comment `3431209969`) — `plotReducers.removePlotConnectionsForSection`: - deleting a section's connections leaves stale `subplot.sectionIds`. Reply: *this action's single - responsibility is connections; cascading section removal into subplot `sectionIds` belongs in - `deleteManuscriptSection` (a separate, behavior-changing enhancement), out of scope for this - pure decomposition. Tracked as follow-up FU.* — **Optional upgrade:** if a real fix is wanted, - add subplot-membership cleanup in `manuscriptReducers.deleteManuscriptSection` (+ test) and the - plot action, then mark this a true fix instead of a justification. -3. Then push (if any code changed), **re-trigger** (`gh pr comment 177 --body "@codeant-ai review"`), - and loop until quiescent. - -### 4b. PRs #178–#182 — start fresh - -For each: run §2a to fetch threads, then §2b–2g. Expected hotspots: -- **#178**: virtualization ↔ ARIA listbox/`aria-activedescendant`; ensure no a11y regression. Custom - scorer kept intentionally (no fuse.js) — justify if CodeAnt suggests a library. -- **#179**: pure layout extraction; verify no DOM-order/responsive regressions. -- **#180**: additive XState core (not imported by app yet). Watch for "dead code" flags — answer: - intentionally additive, wired in P4b behind `enableProForgeXState`. -- **#181 / #182**: docs only; mostly link/markdown nits. - ---- - -## 5. One-shot helpers - -Count unresolved threads on a PR: -```bash -gh api graphql -f query='query { repository(owner:"qnbs",name:"WorldScript-Studio"){ - pullRequest(number:){ reviewThreads(first:100){ nodes { isResolved } } } } }' \ - --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved==false)] | length' -``` - -Check all CI checks on a PR (look for any non-success): -```bash -gh pr checks -``` +# CodeAnt Correction-Loop Runbook — SUPERSEDED (tombstone) + +> **This file is a tombstone.** Its content (an "executable companion" that also captured the live +> state of long-merged architecture-refactor PRs) is **superseded** by the single canonical runbook: +> +> ### → [`CODEANT-REVIEW-LOOP.md`](CODEANT-REVIEW-LOOP.md) +> +> The canonical doc carries the full command-level recipes (GraphQL thread fetch, REST reply, resolve, +> re-trigger, merge) **and** the policy. Use it for every PR. + +## Why this was retired (read if you arrived here from an old link) + +This file contained the line **"Each push triggers a new review wave"**, which is **misleading** and +once led an external analysis astray. The reality, documented correctly in the canonical runbook: + +- CodeAnt's GitHub App **auto-reviews on PR open**, but **re-reviews after a push are NOT reliably + automatic** — you **manually re-trigger** with a PR comment: `@codeant-ai review`. +- A PR is review-quiescent only when a fresh review yields **0 new comments** AND **0 unresolved + threads**, with green CI. + +## Current operational context (2026-06-24) + +- **CodeAnt was unresponsive** (no check-run / status / comment on PRs even after manual triggers) — + an **outage / exhausted free-tier quota**, not a trigger-name problem. The free-tier **CI Action** + token cannot be issued. Procedure while it is down: proceed under the standing + hung/unresponsive-check rule (all required CI green + 0 unresolved → admin squash-merge), exactly as + the canonical runbook §8 describes. +- A **token-free second review layer** was added — DeepSource — with its own living runbook: + **[`DEEPSOURCE-REVIEW-LOOP.md`](DEEPSOURCE-REVIEW-LOOP.md)**. When both tools are live, a PR is + review-quiescent only when **both** loops are satisfied. + +_(File kept at this path so existing links resolve; do not add new content here — update the canonical +runbook instead.)_