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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
199 changes: 33 additions & 166 deletions docs/CODEANT-LOOP-RUNBOOK.md
Original file line number Diff line number Diff line change
@@ -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 `<N>` (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:<N>){ 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/<N>/comments \
-f body='Fixed in <commit-sha>: <one-line what changed>.' \
-F in_reply_to=<comment-databaseId>
```

### 2d. Resolve the thread

```bash
gh api graphql -f query='mutation { resolveReviewThread(input:{threadId:"<THREAD_ID>"}){ 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 <changed test files>
```

### 2f. Commit, push, re-trigger

```bash
git commit -m "fix(<area>): address CodeAnt review — <summary>"
git push
gh pr comment <N> --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:<N>){ 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 <N>
```
# 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.)_
Loading