Skip to content

chore(knip): delete verified-unused files (PR-Knip-1)#279

Merged
github-actions[bot] merged 1 commit into
refactor/extract-from-main-indexfrom
chore/knip-unused-files
Jun 9, 2026
Merged

chore(knip): delete verified-unused files (PR-Knip-1)#279
github-actions[bot] merged 1 commit into
refactor/extract-from-main-indexfrom
chore/knip-unused-files

Conversation

@tomymaritano

@tomymaritano tomymaritano commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

First slice of the knip cleanup. Knip surfaced 28 unused files in #267. After per-file verification (greps, import tracing, barrel resolution), 12 were genuinely orphaned — those are deleted here. The rest stay for reasons documented below.

Deleted (12 files, 659 lines)

`apps/desktop`

File Why safe
`src/renderer/analytics.ts` No imports anywhere
`src/renderer/hooks/useTheme.ts` No imports anywhere
`src/renderer/settings.tsx` No imports anywhere (the real settings entry is `pages/settings/SettingsApp.tsx`, loaded via dynamic import in `main.tsx`)
`src/renderer/ui/patterns/Modal.tsx` + `index.ts` + `Modal.module.css` + `.gitkeep` Only the barrel imported `Modal`, and the barrel itself was unused — both go together

`packages`

File Why safe
`plugin-api/src/editor/types.ts` Not re-exported by `plugin-api/src/index.ts`
`storage-core/src/{interfaces,migrations,repositories,types}/index.ts` Main package index imports directly from concrete files, not these barrels
`storage-sqlite/src/repositories/index.ts` Same — concrete imports, no barrel use

`scripts`

File Why safe
`scripts/bump-version.js` Not referenced by any `package.json` script or CI workflow

Kept (Knip false positives)

Auto-discovered files Knip can't see

File Why kept
`apps/desktop/src/renderer/vite-env.d.ts` `/// ` — required by Vite
`apps/desktop/src/renderer/css-modules.d.ts` TypeScript module shim for CSS module imports
`apps/desktop/src/renderer/turndown-plugin-gfm.d.ts` TypeScript module shim for an untyped npm dep
`apps/web/mdx-components.tsx` Next.js convention — auto-discovered, never imported

Knip wrong about being unused

File Reality
`renderer/pages/settings/components/controls/{NumberInput,Select,TextInput,Toggle}.tsx` Imported by EditorSection / AiSection / UpdatesSection through the `controls/index.ts` barrel. Knip flagged both the components and the barrel as unused because it doesn't follow the chain.

Skipped (out of audit scope)

apps/web cleanup: `magicui/*`, `NavDropdown`, `ui/separator`. The audit excluded apps/web; leaving them for a separate marketing-site pass.

Test plan

  • `pnpm -r typecheck` — green
  • `pnpm test` — 17/17 packages
  • Manual smoke after merge

What's next in this cleanup track

  • PR-Knip-2: remove unused production + dev dependencies (the `Unused dependencies (9)` block from knip)
  • PR-Knip-3: remove unused exports (the `Unused exports (~100)` block) — much more careful, since some exports may be public API contracts for plugins or external consumers

Stack context

Stacked on top of #278 (PR-G) → #277 (PR-E) → #276 (PR-F3) → #275 (PR-F2) → #274 (PR-F5) → #273 (PR-F4) → #272 (PR-F1) → #271 (PR-I) → #270 (PR-J) → #269 (PR-D) → #268 (PR-H) → #267 (PR-C) → #266 (PR-A) → #265 (PR-B). 15 PRs deep.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Removals
    • Removed settings page functionality from the desktop application
    • Removed modal dialog components and related styling
    • Removed theme customization and appearance settings
    • Disabled analytics and event tracking

Knip surfaced 28 unused files in #267. After per-file verification,
12 were genuinely orphaned. Deleting them:

apps/desktop:
- src/renderer/analytics.ts          — no imports anywhere
- src/renderer/hooks/useTheme.ts     — no imports anywhere
- src/renderer/settings.tsx          — no imports anywhere
- src/renderer/ui/patterns/Modal.tsx — only its sibling index.ts
- src/renderer/ui/patterns/index.ts  — barrel that nothing imports
- src/renderer/ui/patterns/Modal.module.css + .gitkeep — left over

packages:
- plugin-api/src/editor/types.ts     — not re-exported by index.ts
- storage-core/src/interfaces/index.ts \
- storage-core/src/migrations/index.ts  \
- storage-core/src/repositories/index.ts \  — main package index imports
- storage-core/src/types/index.ts        /   directly from concrete files,
- storage-sqlite/src/repositories/index.ts/   not these barrels

scripts:
- scripts/bump-version.js            — not in any package.json script
                                       and not referenced by any CI workflow

Kept (Knip false positives — auto-discovered files Knip can't see):
- vite-env.d.ts                      (vite reference declaration)
- css-modules.d.ts                   (TypeScript module shim)
- turndown-plugin-gfm.d.ts           (TypeScript module shim)
- apps/web/mdx-components.tsx        (Next.js MDX convention, no import)

Kept (Knip wrong — barrel that IS used):
- renderer/pages/settings/components/controls/{NumberInput,Select,TextInput,Toggle}.tsx
  All four are imported by EditorSection / AiSection / UpdatesSection
  through the controls/index.ts barrel.

Skipped (out of audit scope):
- apps/web/components/magicui/*, NavDropdown, ui/separator

Validates:
- pnpm -r typecheck — green
- pnpm test — 17/17 packages, all cached except plugin-api which ran
  fresh after the editor/types.ts deletion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
readide Building Building Preview, Comment Jun 9, 2026 1:22am

@github-actions github-actions Bot merged commit 0ad51bb into refactor/extract-from-main-index Jun 9, 2026
4 of 6 checks passed
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d28a4da-235a-40fb-9dca-92d93e7a4f27

📥 Commits

Reviewing files that changed from the base of the PR and between 2bd1396 and fd9b809.

📒 Files selected for processing (14)
  • apps/desktop/src/renderer/analytics.ts
  • apps/desktop/src/renderer/hooks/useTheme.ts
  • apps/desktop/src/renderer/settings.tsx
  • apps/desktop/src/renderer/ui/patterns/.gitkeep
  • apps/desktop/src/renderer/ui/patterns/Modal.module.css
  • apps/desktop/src/renderer/ui/patterns/Modal.tsx
  • apps/desktop/src/renderer/ui/patterns/index.ts
  • packages/plugin-api/src/editor/types.ts
  • packages/storage-core/src/interfaces/index.ts
  • packages/storage-core/src/migrations/index.ts
  • packages/storage-core/src/repositories/index.ts
  • packages/storage-core/src/types/index.ts
  • packages/storage-sqlite/src/repositories/index.ts
  • scripts/bump-version.js

📝 Walkthrough

Walkthrough

This PR removes desktop UI components (Modal, analytics, theme hook, settings page), eliminates re-exports from plugin-api and storage packages (interfaces, types, migrations, repositories), and deletes the version bumping build script. The changes represent a significant API surface reduction and UI component consolidation across desktop and package layers.

Changes

Cohort / File(s) Summary
Modal Component Suite
apps/desktop/src/renderer/ui/patterns/Modal.tsx, apps/desktop/src/renderer/ui/patterns/Modal.module.css, apps/desktop/src/renderer/ui/patterns/index.ts
Removes Modal component with ARIA semantics, ModalProps interface, CSS module with fade-in/scale-in animations and size variants, and barrel export.
Analytics & Theme Hooks
apps/desktop/src/renderer/analytics.ts, apps/desktop/src/renderer/hooks/useTheme.ts
Removes offline-first analytics module with localStorage queue, PostHog/custom endpoint integration, and periodic flush logic. Removes useTheme hook with dark/light theme resolution, accent color parsing, and CSS variable application.
Settings Entrypoint
apps/desktop/src/renderer/settings.tsx
Removes React entrypoint that instantiated QueryClient, wrapped SettingsApp with QueryClientProvider, LicenseProvider, and error boundary.
Storage-Core Re-exports
packages/storage-core/src/interfaces/index.ts, packages/storage-core/src/migrations/index.ts, packages/storage-core/src/repositories/index.ts, packages/storage-core/src/types/index.ts
Removes re-exports for DatabaseAdapter, PreparedStatement, StatementResult, Migration, MigrationRecord, ExtendedNoteRepository, runMigrations, getPendingMigrations, getCurrentVersion, InMemoryNoteRepository, ArchivedFilter, ListNotesOptions, and NoteSnapshot.
Plugin API & Storage-SQLite Re-exports
packages/plugin-api/src/editor/types.ts, packages/storage-sqlite/src/repositories/index.ts
Removes EditorAPI type re-export from plugin-api; removes SQLiteNoteRepository and BacklinkInfo type re-export from storage-sqlite.
Build Scripts
scripts/bump-version.js
Removes version bumping utility that updated semver versions in package.json files with validation and formatting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • tomymaritano/readide#157: PR #157 introduced scripts/bump-version.js as part of semantic-release automation; this PR removes that script.

Suggested labels

size/XL, app:desktop

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/knip-unused-files

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd9b809cd7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/bump-version.js
@@ -1,33 +0,0 @@
#!/usr/bin/env node

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore the release bump script

When the manual release workflow runs npx semantic-release (.github/workflows/release.yml), semantic-release's documented default config lookup includes release.config.js, and @semantic-release/exec documents prepareCmd as the shell command executed in the prepare step; this repo's config still has prepareCmd: 'node scripts/bump-version.js ${nextRelease.version}'. Deleting this file means any release that reaches the prepare step will fail with a missing module instead of bumping package.json/apps/desktop/package.json; the existing scripts/bump-version.test.js also still invokes the same path.

Useful? React with 👍 / 👎.

github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
## Summary

Phase 2 of knip cleanup. Knip flagged 11 unused dependencies in #267;
per-dep verification confirmed **6 are genuinely unused** in our scope.
Removing them shrinks the lockfile by ~120 lines.

## Removed

### \`apps/desktop\` production

| Dep | Why safe |
|---|---|
| \`highlight.js\` | We use \`rehype-highlight\`, which depends on
\`lowlight\` (NOT \`highlight.js\` directly). \`lowlight\` ships its own
grammars. |
| \`pino-roll\` | \`logger.ts\` writes directly via
\`createWriteStream\` — no pino transport / no rolling pipeline |
| \`react-resizable-panels\` | No imports anywhere |
| \`unist-util-visit\` | No imports anywhere (the only consumer is
\`@readied/wikilinks\`, which declares it itself) |

### \`apps/desktop\` dev

| Dep | Why safe |
|---|---|
| \`@types/mdast\` | No imports anywhere |
| \`pino-pretty\` | \`logger.ts\` doesn't pipe through a transport; dev
output is raw JSON via the synchronous pino factory |

### \`packages\`

| Package | Dep removed | Why |
|---|---|---|
| \`@readied/sync-core\` | \`@readied/core\` | No imports of
\`@readied/core\` in \`src/*\` — workspace link was stale |
| \`@readied/wikilinks\` | \`unified\` | \`src/*\` uses
\`unist-util-visit\` directly (kept) but never \`unified\` |

## Skipped (out of audit scope)

\`apps/web\`: \`@radix-ui/react-separator\`, \`next-themes\`,
\`tailwindcss-animate\` — marketing site, separate pass.

## Test plan

- [x] \`pnpm install --ignore-scripts\` — succeeds. Pre-existing peer
warnings about electron-builder / electron-vite are unrelated.
- [x] \`pnpm -r typecheck\` — green.
- [x] \`pnpm test\` — 17/17 packages.
- [ ] Manual smoke on the desktop app after merge — verify nothing
transitively depended on highlight.js / pino-roll / etc. that grep
missed.

## Stack context

Stacked on **PR-Knip-1** (#279) → PR-G (#278) → PR-E (#277) → ... down
to PR-B (#265). 16 PRs deep.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
…ge layer (PR-F3-Wiring) (#281)

## Summary

Wires the verification primitive from #276 into the desktop's
\`FileLicenseStorage\`. The path from server → disk → in-memory now has
a real Ed25519 verification step at read time, with **lenient
fallthrough** during the migration window.

## Changes

### \`packages/licensing/src/types.ts\`

\`StoredSubscriptionData\` now allows an optional \`signedEnvelope\`:

\`\`\`ts
interface StoredSubscriptionData {
  readonly subscription: SubscriptionInfo;
  readonly lastVerified: string;
  readonly cacheExpiresAt: string;
  readonly signedEnvelope?: SignedSubscriptionEnvelope; // NEW
}
\`\`\`

Both can coexist during migration. Long-term, the unsigned
\`subscription\` field becomes a derived view of the envelope payload.

### \`apps/desktop/src/main/services/fileLicenseStorage.ts\`

\`readSubscriptionData\` now branches on envelope presence:

| State on disk | Behavior |
|---|---|
| **Envelope present + signature valid** | Return cache as-is |
| **Envelope present + signature invalid** | Log error, **refuse the
cache** (return null). Next caller fetches fresh from the API |
| **Envelope absent** | Log warning, accept the cache (lenient migration
mode) |

Plus a \`SUBSCRIPTION_PUBLIC_KEY\` constant at the top of the file with
a **REPLACE BEFORE SHIPPING** note. The all-zeros placeholder means any
real envelope will fail verification — that's the *correct* failure mode
while the placeholder is in place. The lenient "no envelope" branch is
what runs today.

## What's NOT in this PR (still pending the server team)

- \`ApiClient.getSubscriptionStatus\` does not yet return an envelope.
When it does, \`mapApiToSubscriptionData\` in \`licenseHandlers.ts\`
grows one more field (\`signedEnvelope\`) and \`writeSubscriptionData\`
persists it. That change is one-liner plumbing, blocked only on the API
contract being updated.
- The placeholder public key gets swapped for the real server key in the
release that first ships signed envelopes.

## Behavior matrix

| Disk state | Today (placeholder key) | After server rollout (real key)
|
|---|---|---|
| Empty | null returned, no log | null returned, no log |
| Old shape (no envelope) | Warning logged, accepted | Warning logged,
accepted (until strict mode) |
| Real envelope, valid sig | Cannot occur (server isn't signing yet) |
Silently accepted |
| Real envelope, invalid sig | Will fail (placeholder key) → refused →
refetch | Refused → refetch |
| Tampered envelope | Refused → refetch | Refused → refetch |

## Test plan

- [x] \`pnpm -r typecheck\` — green
- [x] \`pnpm test\` — 17/17 packages (the 18 signature tests from #276
cover the verify path; this PR just calls into them)
- [ ] Manual: edit \`subscription.json\` to flip a single byte in the
cached \`subscription.subscriptionId\` field. Reopen the app. Once
server signs envelopes: expect error log + refetch. Today: warning log +
cache accepted (no envelope to verify).

## Stack context

Stacked on **PR-Knip-2** (#280) → PR-Knip-1 (#279) → PR-G (#278) → PR-E
(#277) → ... down to PR-B (#265). **17 PRs deep.**

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
…Repository (#282)

## Summary

**Phase 1 of the SQLiteNoteRepository split.** Pure helpers come out to
their own file so future sub-repositories (sync, tag, archive) can reuse
them without inheriting from the 1000-line class.

| Metric | Before | After |
|---|---|---|
| \`SQLiteNoteRepository.ts\` | 1121 lines | **1038 lines** (-7%) |
| \`noteMapping.ts\` | — | 133 lines (new) |

## Extracted

| Symbol | Kind | Notes |
|---|---|---|
| \`NoteRow\`, \`TagRow\`, \`TagWithColorRow\`, \`BacklinkInfo\` | Row
types | Re-exported by SQLiteNoteRepository so external imports keep
working |
| \`rowToNote(row, tags) -> Note\` | Pure mapper | Reconstructs a domain
Note from a SQLite row + its tags |
| \`prepareFtsQuery(input) -> string\` | Pure helper | FTS5 query
escaper + tokenizer |
| \`archivedConditionSql(filter, alias) -> string\` | Pure helper | SQL
fragment for archived filtering |

Call sites swapped from \`this.<helper>()\` to plain function imports.
**The public class signature is unchanged** — \`BacklinkInfo\` is
re-exported so external consumers (e.g.
\`apps/desktop/src/main/handlers/types.ts\`) keep working without edits.

## What this PR DELIBERATELY does NOT do

- **Extract sync methods** (\`getPendingChanges\` through
\`getSyncHistory\` ~430 lines) into a \`SQLiteNoteSyncRepository\`.
Those share state — tag queries, transactions, FTS sync triggers — with
the main class in ways that need real-DB integration coverage to
refactor safely. The helpers extracted here are the foundation: a
follow-up PR can build the sync sub-repo on top of them without touching
the helpers again.
- **Extract tag methods** (\`setManualTags\`, \`renameTag\`,
\`getAllTagsWithColors\`, etc.) for the same reason.

The audit aspired to a 4-way split (NoteCrudRepository +
NoteTagRepository + NoteArchiveRepository + NoteSyncRepository). That
remains the destination. This PR ships the **foundation** that makes
those splits low-risk; each can ride its own PR with focused review.

## Test plan

- [x] \`pnpm -r typecheck\` — green
- [x] \`pnpm test\` — 17/17 packages
- [ ] Manual: launch the desktop, exercise notes CRUD + search + tag
operations. Behavior should be identical (no observable change).

## Stack context

Stacked on **PR-F3 wiring** (#281) → PR-Knip-2 (#280) → PR-Knip-1 (#279)
→ PR-G (#278) → PR-E (#277) → ... down to PR-B (#265). **18 PRs deep.**

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
## Summary

**Phase 1 of the MarkdownEditor split.** Pure theme + markdown
HighlightStyle move to their own file so further extractions (extensions
array, keymap bindings) can ride on top without merging against a
churn-prone component shell.

| Metric | Before | After |
|---|---|---|
| \`MarkdownEditor.tsx\` | 737 lines | **612 lines** (-17%) |
| \`editorTheme.ts\` | — | 139 lines (new) |

## Extracted

| Symbol | Kind |
|---|---|
| \`SCROLL_PAST_END_PADDING\` | constant |
| \`createEditorTheme(fontSize, fontFamily, lineHeight)\` | factory
returning \`EditorView.theme({...})\` |
| \`markdownHighlighting\` | \`HighlightStyle.define([...])\` with all
tag styles for markdown |

## Imports cleaned up

- Drop \`HighlightStyle\` from \`@codemirror/language\` import (no
longer referenced in this file)
- Drop \`tags\` from \`@lezer/highlight\` (moved into editorTheme.ts)

## What this PR DELIBERATELY does NOT do

- **Extract the extensions array** (~96 lines of \`createExtensions\`).
It closes over user settings (\`lineNumbersCompartment\` etc.) and mixes
context-coupled values like \`wikilinkAutocomplete\` from a hook. Safely
pulling that out requires either passing the closure context via a
builder, or moving the whole \`useMemo\` into its own hook. **Better
done under Playwright coverage (PR-E #277) so renderer regressions
surface.**
- **Extract the keymap.** Same reason — bindings reference
view-imperatives + the command-registry which are constructed inside the
React tree.

## Test plan

- [x] \`pnpm -r typecheck\` — green (renderer + e2e tsconfigs)
- [x] \`pnpm test\` — 17/17 packages
- [ ] Manual: open the editor, type in a markdown note with headings,
emphasis, lists, code blocks. The look must be identical (theme is
byte-for-byte the same; just moved).

## Stack context

Stacked on **note repo split** (#282) → PR-F3 wiring (#281) → PR-Knip-2
(#280) → PR-Knip-1 (#279) → PR-G (#278) → PR-E (#277) → ... down to PR-B
(#265). **19 PRs deep.**

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
## Summary

Promotes `develop` to `main` for **v0.15.0**. Originally opened
2026-04-24; now refreshed with the 19-PR tech-debt audit shipped via
#285 plus the accumulated dependabot bumps reconciled.

`semantic-release` will pick the version bump. Expected: **minor
(v0.14.x → v0.15.0)** because of multiple \`feat:\` commits.

## What ships (audit highlights, from #285)

### Runtime fixes (user-facing)
- **Editor no longer crashes on table-containing notes** (#266) —
\`Decoration.replace\` over multi-line ranges moved from a ViewPlugin to
a StateField, plus an EditorView.exceptionSink so any future plugin
error no longer tears down the EditorView.
- **AI keys survive sleep/wake** (#275) — \`aiKeyStorage\` stopped
silently deleting the encrypted store when the keychain was temporarily
locked after macOS sleep.
- **Backup restore is now safe** (#271) — restored DBs go through
\`PRAGMA integrity_check\` before being swapped in; corrupt backups roll
back to the safety copy.
- **MCP server runs without electron-builder rebuilds** (#264#270) —
migrated from native \`better-sqlite3\` to built-in \`node:sqlite\`
(Node 22.5+), updated to the new \`registerTool\` MCP SDK API.

### Security
- **Typed IPC boundary** (#272 + #273 + #274) — 130+ IPC channels now
validated with Zod tuples at the main↔renderer boundary. Garbage in
fails fast with \`IpcValidationError\` instead of corrupting downstream
code.
- **Ed25519 license verification scaffolding** (#276 + #281 + #284) —
\`signSubscriptionPayload\` / \`verifySubscriptionSignature\` helpers
ship in \`@readied/licensing\`, wired into
\`FileLicenseStorage.readSubscriptionData\` with lenient fallthrough
during migration. Real public key embedded (\`d04901…\`). Server-side
\`LICENSE_SIGNING_PRIVATE_KEY\` already set in Cloudflare staging +
production.

### Developer experience
- **Husky → Lefthook** (#267) plus lint-staged that now runs ESLint, not
just Prettier.
- **\`knip\` added** (#267) + 12 unused files deleted (#279) + 6 unused
deps dropped (#280).
- **Playwright Electron E2E scaffold** (#277) with smoke + notes-IPC
specs and a Linux+xvfb CI job (\`continue-on-error: true\` while it
stabilises).
- **Vitest coverage baseline** (#269) — 12 packages share a coverage
config; smoke tests added for \`@readied/commands\`.

### Refactor (no behavior change)
- **Zustand selectors migration** (#268) — 3 components stopped
destructuring entire stores.
- **God-file extractions**:
- \`main/index.ts\` 1065 → 950 lines (#278) — \`FileLicenseStorage\`,
\`windowState\` extracted to services
- \`SQLiteNoteRepository.ts\` 1121 → 1038 lines (#282) — pure helpers
extracted to \`noteMapping.ts\`
- \`MarkdownEditor.tsx\` 737 → 612 lines (#283) — theme +
markdownHighlighting extracted to \`editorTheme.ts\`

## Deploys triggered

| Workflow | Trigger | What happens |
|---|---|---|
| \`deploy-api.yml\` | Auto on \`push\` to main affecting
\`packages/api/**\` | Tests + deploys \`@readied/api\` to Cloudflare
Workers (\`readied-api-production\`). This stack only touched
\`wrangler.toml\` + \`.dev.vars\` docs, no production code change. |
| \`release.yml\` | Manual \`workflow_dispatch\` post-merge |
\`semantic-release\` analyses conventional commits, bumps version,
creates GitHub Release draft + tag |
| \`build.yml\` | Auto on tag push from release.yml | mac / windows /
linux parallel builds, artefacts attached to the GitHub Release |

## Pre-merge verification (local, this branch)

- ✅ \`pnpm -r typecheck\` — green across 18 workspace projects
- ✅ \`pnpm test\` — 17/17 packages
- ✅ Merge resolved: take develop versions for 19 conflicted
package.jsons (develop has equal or newer deps than main's dependabot
bumps)

## Post-merge action items (operator)

1. **Deploy API to staging first** (smoke test):
   \`\`\`
   gh workflow run deploy-api.yml -f environment=staging
   \`\`\`
2. Confirm staging API responds correctly (subscription endpoint with
new \`LICENSE_SIGNING_PRIVATE_KEY\` secret already set in CF).
3. Merge this PR → auto-deploys API to production.
4. Trigger Release workflow: GitHub → Actions → Release → "Run workflow"
→ main.
5. Watch Build workflow for mac/win/linux completion.
6. Confirm the release un-drafts itself.

## Known risks / follow-ups

- **Pre-existing Vercel preview failure for \`apps/web\`** — marketing
site, scheduled to be extracted to its own repo (P3 in the roadmap).
- **\`SUBSCRIPTION_PUBLIC_KEY\` is dev-grade** — generated in a Claude
session. Before the licensing server emits envelopes for real paid
users, rotate the keypair from a trusted machine and ship a follow-up
release.
- **Branch protection should require CodeRabbit completion before
automerge** — added to the roadmap as a process item; this very PR was
BLOCKED correctly because of that policy gap being closed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
tomymaritano added a commit that referenced this pull request Jun 9, 2026
## Why this PR

PR #245 squash-merged 19 individual PRs (#266-#284) into a single commit
on main: \`release: audit + Ed25519 signed envelopes + lefthook
(v0.15.0) (#245)\`. That message **isn't a conventional commit type that
semantic-release recognises**, so the analyser saw 11 commits since the
last tag and concluded *"no release"*. The actual feat:/fix:/refactor:
messages from the 19 underlying PRs were lost in the squash.

Concretely, run
[27184456847](https://github.com/tomymaritano/readide/actions/runs/27184456847)
finished cleanly but logged:

\`\`\`
[semantic-release] [@semantic-release/commit-analyzer] › ℹ Analysis of
11 commits complete: no release
[semantic-release] › ℹ There are no relevant changes, so no new version
is released.
\`\`\`

## What this PR does

### 1. Provides the release signal

This commit's title is \`feat(release): cut v0.15.0 audit release\` — a
recognised conventional type. semantic-release will analyse it as a
**minor bump** (v0.14.x → v0.15.0).

### 2. Drops the broken \`@semantic-release/exec\` step

\`release.config.js\` referenced \`node scripts/bump-version.js
\${nextRelease.version}\` in a prepareCmd, but that script was deleted
in the knip cleanup (#279) and the config wasn't updated. Any release
triggered now would fail at the prepare step with \`ENOENT\`.

The remaining \`@semantic-release/git\` plugin already commits root
\`package.json\` + \`apps/desktop/package.json\` + \`CHANGELOG.md\` via
its \`assets\` list — that's everything the desktop release needs
bumped. Workspace packages stay at \`workspace:*\` and their numeric
versions aren't user-visible.

## Side effect

\`@semantic-release/exec\` is still listed in \`package.json\` devDeps
but unused after this PR. Not removing it here to keep this PR surgical;
can be dropped in the next knip pass.

## After this merges

1. Manually re-trigger Release workflow on main
2. semantic-release picks up this commit + the existing release notes
generator → cuts **v0.15.0**
3. Creates GitHub Release draft + tag
4. Tag push fires Build workflow → mac/win/linux artefacts
5. Builds complete → release un-drafts → electron-updater serves it

## Related

- #287 (deploy-api workflow fix)
- #288 (release workflow install fix)
- #279 (knip cleanup that deleted bump-version.js without updating
release.config.js)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
…hase 0 A2) (#291)

## Summary

Phase 0 A2. Restores the version-bump step semantic-release needs to
actually write the new version into the package.json files BEFORE the
git plugin commits them.

## What was broken

The v0.15.0 tag points at a commit where both \`package.json\` and
\`apps/desktop/package.json\` still read \`0.14.0\`:

\`\`\`
$ git show v0.15.0:package.json | jq -r .version
0.14.0
$ git show v0.15.0:apps/desktop/package.json | jq -r .version
0.14.0
\`\`\`

Symptom: electron-updater sees mismatched versions; any consumer reading
from package.json drifts from the tag; ship-it-and-forget-it release
becomes "wait, what version is this?".

### Why

semantic-release pipeline is a chain. Each plugin has a contract.

| Plugin | Contract |
|---|---|
| \`commit-analyzer\` | decides next version |
| \`release-notes-generator\` | writes release notes |
| \`changelog\` | mutates CHANGELOG.md |
| \`exec.prepareCmd\` | **mutates package.json (this step was missing)**
|
| \`git\` | commits the mutated files via \`assets:\` list |
| \`github\` | creates draft release |

The \`assets:\` list in \`@semantic-release/git\` ONLY commits files; it
doesn't create the diff. Without an explicit mutation step, the git
plugin sees no changes to package.json and commits an effectively empty
diff (just the CHANGELOG update).

The original \`scripts/bump-version.js\` performed that mutation, wired
via \`@semantic-release/exec\`. It was deleted in the knip cleanup
(#279) under the false assumption nothing referenced it — knip didn't
scan \`release.config.js\` as an entry point.

PR #289 patched \`release.config.js\` to remove the dangling
\`prepareCmd\`, which made the workflow stop crashing but left versions
stale.

## Fix

1. **\`scripts/bump-version.mjs\`** (new) — pure-ESM, zero dependencies,
updates ONLY the \`version\` field of exactly two files
(\`package.json\` and \`apps/desktop/package.json\`). Preserves existing
trailing-newline. Fails non-zero on missing version arg, unparseable
JSON, or absent version field.

2. **\`release.config.js\`** — re-wires the \`@semantic-release/exec\`
plugin (already a devDep) with \`prepareCmd: 'node
scripts/bump-version.mjs \${nextRelease.version}'\`. Comment block in
the file documents the history so the next maintainer doesn't repeat the
mistake.

Packages with independent release cycles (notably \`packages/api\` on
Cloudflare Workers, \`packages/mcp-server\`) are deliberately NOT in the
target list. If we ever need to bump them, that's a separate concern
with a separate script.

## Verification

\`\`\`
$ node scripts/bump-version.mjs 0.15.1
bump-version: package.json 0.14.0 -> 0.15.1
bump-version: apps/desktop/package.json 0.14.0 -> 0.15.1
bump-version: updated 2 of 2 target(s)
\`\`\`

Edge cases:
- \`node scripts/bump-version.mjs\` (no arg) → \`missing version
argument\`, exit 1
- \`node scripts/bump-version.mjs 0.14.0\` (already at version) →
\`already at 0.14.0, skipped\`, exit 0
- Same version on already-bumped files → idempotent, no diff

- ✅ \`pnpm -r typecheck\` — green
- ✅ \`pnpm test\` — 17/17 packages

## Stack context

Phase 0 A2 of the post-audit devops roadmap. Pairs with #290 (A1,
electron pin). Independent files, can land in any order.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant