Skip to content

fix(desktop): pin electron to ^41.7.1 for better-sqlite3 prebuild compat (Phase 0 A1)#290

Merged
github-actions[bot] merged 1 commit into
developfrom
fix/electron-41-pin-for-better-sqlite3
Jun 9, 2026
Merged

fix(desktop): pin electron to ^41.7.1 for better-sqlite3 prebuild compat (Phase 0 A1)#290
github-actions[bot] merged 1 commit into
developfrom
fix/electron-41-pin-for-better-sqlite3

Conversation

@tomymaritano

@tomymaritano tomymaritano commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Phase 0 A1 of the post-audit devops roadmap. Unblocks v0.15.x Build.

The v0.15.0 Build workflow failed on all 3 platforms (run 27184736470) because better-sqlite3 12.10.0 explicitly removed Electron v42 prebuilds (WiseLibs/better-sqlite3#1470). Without a prebuild, `electron-builder install-app-deps` falls through to a source build via `@electron/rebuild`, which then hits V8 13.x API breakages:

  • `SetNativeDataProperty` ambiguity (3 candidate overloads)
  • `External::Value()` requires `ExternalPointerTypeTag` argument
  • `External::New()` signature change

Same root cause on Linux/macOS (GCC/clang) and Windows (MSVC).

Fix

Pin Electron to `^41.7.1` (latest 41.x as of 2026-05-26). better-sqlite3 has prebuilts for it.

Local validation

```
apps/desktop postinstall: electronVersion=41.7.1 arch=arm64
apps/desktop postinstall: buildFromSource=false
apps/desktop postinstall: preparing moduleName=better-sqlite3
apps/desktop postinstall: finished moduleName=better-sqlite3
apps/desktop postinstall: completed installing native dependencies
```

`buildFromSource=false` = the prebuilt was found and consumed; no V8 errors.

  • ✅ `pnpm install` (with scripts) — succeeds
  • ✅ `pnpm -r typecheck` — green
  • ✅ `pnpm test` — 17/17 packages

When to bump back to 42

Watch WiseLibs/better-sqlite3 releases for v42 prebuild restoration. As of 2026-06-09 there's no public ETA. When it lands: bump electron to `^42.x` + better-sqlite3 to the version that re-includes v42 prebuilds, in a single PR.

Stack context

This is A1 of Phase 0 (devops stabilization). A2-A4, B1-B5, C1-C2, D follow in subsequent PRs against develop.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated the runtime dependency for the desktop application.

@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 Ready Ready Preview, Comment Jun 9, 2026 1:55pm

@github-actions github-actions Bot enabled auto-merge (squash) June 9, 2026 12:59
@github-actions github-actions Bot added dependencies Pull requests that update a dependency file app:desktop labels Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@tomymaritano, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 6 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c5bc877-27dd-44ed-9e29-bd127d835caa

📥 Commits

Reviewing files that changed from the base of the PR and between d5aea6d and 7c8a18e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • apps/desktop/package.json
📝 Walkthrough

Walkthrough

The electron development dependency in the desktop application package is downgraded from version ^42.3.3 to ^41.7.1. This is a single-line version constraint change in the package.json configuration file.

Changes

Electron Dependency Version

Layer / File(s) Summary
Electron dependency downgrade
apps/desktop/package.json
Electron devDependency is updated from ^42.3.3 to ^41.7.1.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Suggested labels

dependencies, size/S

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: pinning Electron to ^41.7.1 for better-sqlite3 prebuild compatibility, which directly addresses the build failure problem documented in the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/electron-41-pin-for-better-sqlite3

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.

@github-actions github-actions Bot added the size/S label Jun 9, 2026
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>

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/package.json`:
- Line 78: Add an inline comment next to the "electron": "^41.7.1" dependency in
apps/desktop/package.json explaining that the Electron version is intentionally
pinned to 41.x as a temporary workaround for better-sqlite3 prebuild
compatibility (reference WiseLibs/better-sqlite3#1470), include the date or
PR/issue that motivated the pin and a note to revisit/unpin when the upstream
fix is available; update the comment when you later remove the pin.
- Line 78: Update the package.json electron dependency entry ("electron":
"^41.7.1") to include a short follow-up: add a comment or project note (e.g., in
package.json's "comments" field or repo docs/changelog) documenting the
downgrade rationale and the prebuild workaround for better-sqlite3, and consider
tightening the version specifier (remove caret or pin to "41.7.1") if prebuilds
only support specific 41.x releases; modify the "electron" dependency line and
add the tracking note in the repository docs or package metadata accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b6f7260f-c58a-4c89-8463-36fe4ea7cc06

📥 Commits

Reviewing files that changed from the base of the PR and between b54541a and d5aea6d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • apps/desktop/package.json

Comment thread apps/desktop/package.json
"@playwright/test": "^1.49.1",
"@vitejs/plugin-react": "^6.0.2",
"electron": "^42.3.3",
"electron": "^41.7.1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding an inline comment documenting the version constraint.

To help future maintainers understand why Electron is pinned to 41.x, consider adding a comment explaining that this is a temporary workaround for better-sqlite3 prebuild compatibility (WiseLibs/better-sqlite3#1470).

📝 Suggested documentation addition
+    // TODO: Upgrade to ^42.x when better-sqlite3 restores Electron 42 prebuilds
+    // See: https://github.com/WiseLibs/better-sqlite3/issues/1470
     "electron": "^41.7.1",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/package.json` at line 78, Add an inline comment next to the
"electron": "^41.7.1" dependency in apps/desktop/package.json explaining that
the Electron version is intentionally pinned to 41.x as a temporary workaround
for better-sqlite3 prebuild compatibility (reference
WiseLibs/better-sqlite3#1470), include the date or PR/issue that motivated the
pin and a note to revisit/unpin when the upstream fix is available; update the
comment when you later remove the pin.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify Electron 41.7.1 exists and check for security advisories

echo "=== Checking Electron 41.7.1 availability on npm ==="
npm view electron@41.7.1 version 2>/dev/null || echo "Version 41.7.1 not found"

echo -e "\n=== Checking latest Electron 41.x version ==="
npm view electron@^41.0.0 version

echo -e "\n=== Checking for Electron security advisories ==="
gh api graphql -f query='
{
  securityVulnerabilities(first: 10, ecosystem: NPM, package: "electron") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Repository: tomymaritano/readide

Length of output: 3359


🌐 Web query:

better-sqlite3 12.10.0 Electron 41 prebuild support compatibility

💡 Result:

Better-sqlite3 version 12.10.0 provides full support and prebuilt binaries for Electron 41 [1][2]. Compatibility for Electron 41 was introduced in the 12.x release cycle to address V8 API breaking changes, specifically the removal of PropertyCallbackInfo::This in newer V8 versions used by Electron 41 [3]. The library was updated to use Holder instead, and further adjustments were made to ensure compatibility with V8 API evolutions [3][4]. As of June 9, 2026, the CI build configuration in version 12.10.0 explicitly includes prebuild targets for Electron 41.0.0 [2]. While recent efforts have also explored support for Electron 42, that support has been temporarily rolled back due to unresolved build issues, leaving Electron 41 as a supported, stable target in the current version [5][6].

Citations:


Electron 41.7.1 downgrade rationale is supported; consider small follow-ups

  • electron@41.7.1 is a published version, and the available Electron advisory data shown affects 41.x only up to <41.1.0 (patched at 41.1.0), so 41.7.1 doesn’t fall into those ranges.
  • better-sqlite3@12.10.0 includes prebuild support for Electron 41 (workaround for the Electron 42 prebuild gap is reasonable given the downgrade intent).
  • Optional: add a brief tracking/upgrading note (and consider whether ^41.7.1 should be tightened if prebuilds only cover certain Electron 41.x versions).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/package.json` at line 78, Update the package.json electron
dependency entry ("electron": "^41.7.1") to include a short follow-up: add a
comment or project note (e.g., in package.json's "comments" field or repo
docs/changelog) documenting the downgrade rationale and the prebuild workaround
for better-sqlite3, and consider tightening the version specifier (remove caret
or pin to "41.7.1") if prebuilds only support specific 41.x releases; modify the
"electron" dependency line and add the tracking note in the repository docs or
package metadata accordingly.

github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
…se 0 A4) (#293)

## Summary

Phase 0 A4. Two guardrails on \`release.yml\` to make a silent or
partial release impossible.

## Why

The v0.15.0 release pipeline failed silently twice:

1. **Silent no-op**: PR #245's squash-merge title (\`release: audit +
Ed25519 signed envelopes + lefthook (v0.15.0) (#245)\`) didn't match a
conventional commit type in \`releaseRules\`. semantic-release exited
cleanly with \"no release\" and the workflow ended green; the operator
only noticed because no tag appeared. We patched this with #289 by
adding a forcing \`feat:\` commit, but the trap will fire again on the
next big squash unless the workflow refuses to silently no-op.
2. **Stale version**: even when the release finally cut, both
\`package.json\` files still read \`0.14.0\` because the deleted
\`scripts/bump-version.js\` was never re-introduced (fixed in PR #291).
Tag points at one version, file content reads another — visible by
anyone running \`jq .version package.json\` against the tag.

## Guardrails

### Pre-flight (dry-run)

\`\`\`yaml
- name: Pre-flight (dry-run) check
  run: |
    npx semantic-release --dry-run 2>&1 | tee /tmp/sr-dry.log
    if grep -qE \"There are no relevant changes\" /tmp/sr-dry.log; then
echo \"::error::semantic-release dry-run: no release will be cut.\"
      exit 1
    fi
    if ! grep -qE \"next release version is\" /tmp/sr-dry.log; then
echo \"::error::semantic-release dry-run did not announce a next release
version.\"
      exit 1
    fi
\`\`\`

Stops the workflow loud and clear before \`--ci\` if commit-analyzer
would have returned \"no release\". Actionable error messages point at
\`release.config.js > releaseRules\` and the commit log.

### Post-flight (version assertion)

\`\`\`yaml
- name: Verify version bump applied
  run: |
expected=$(grep -oE \"next release version is [0-9]+\\.[0-9]+\\.[0-9]+\"
/tmp/sr-dry.log | tail -n 1 | awk '{print $NF}')
    root_v=$(jq -r .version package.json)
    desk_v=$(jq -r .version apps/desktop/package.json)
if [ \"$root_v\" != \"$expected\" ] || [ \"$desk_v\" != \"$expected\" ];
then
      echo \"::error::Version mismatch after semantic-release.\"
      exit 1
    fi
\`\`\`

Re-uses the captured dry-run log to know what version SHOULD have been
written. Catches a misconfigured or skipped \`scripts/bump-version.mjs\`
(PR #291) BEFORE the tag-triggered build downloads the stale
package.json.

## What gets caught

| Trap | Caught by |
|---|---|
| Non-conventional PR title (#245 trap) | Pre-flight: \"no relevant
changes\" |
| Wrong releaseRules / type filter | Pre-flight: \"did not announce next
release\" |
| \`prepareCmd\` missing or wrong path | Post-flight: version mismatch |
| \`bump-version.mjs\` only updated one file | Post-flight: per-file
diff |
| semantic-release crashed mid-cycle | Native exit code from \`Run
semantic-release\` step |

## Verification

I dry-ran the gate logic locally against the current main commit log;
the dry-run output contains the expected lines for both happy-path and
no-op cases. No way to test end-to-end without actually invoking the
workflow.

## Stack context

Phase 0 A4. Independent from A1 (#290), A2 (#291), B-bundle (#292).
Different files / steps; no overlapping changes.

🤖 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
## Why

develop's lint job has been failing since **2026-04-24** (over a month).
Until this lands, **every Phase 0 PR (#290#294) is structurally
unmergeable** because branch protection requires \`lint\` to pass and
\`strict: true\` requires PRs to match develop's tip.

This is the unblock for the whole post-audit release stack.

## What

Two orthogonal fixes that together get \`pnpm lint\` to **0 errors**.

### 1. \`preserve-caught-error\` × 4 in \`encryptionService.ts\`

Four \`try/catch\` blocks re-throw a wrapped error without attaching the
caught one:

\`\`\`ts
} catch (error) {
  throw new Error(
\`Failed to encrypt content: \${error instanceof Error ? error.message :
'Unknown error'}\`,
+    { cause: error }  // ← lints clean and preserves the stack
  );
}
\`\`\`

Affected throw sites: \`initialize\` (114), \`encrypt\` (261),
\`decrypt\` (292), \`importKey\` (351). The \`{ cause }\` payload is the
standard ES2022 way to chain errors; runtime semantics unchanged.

### 2. mcp-server tsconfig refactor for ESLint projectService

\`packages/mcp-server/tsconfig.json\` was excluding \`src/__tests__\`.
ESLint uses \`@typescript-eslint/parser\` with \`projectService: true\`,
which delegates project discovery to the TypeScript LSP. The LSP walked
up from the test file, found mcp-server/tsconfig.json with the explicit
exclude, and rejected the test → **parsing error: \"was not found by the
project service\"**.

Fix: split build vs editor configs.

- **tsconfig.json** — single source of truth for editors/lint/test.
Includes everything under \`src\`. Adds \`vitest/globals\` to \`types\`.
- **tsconfig.build.json** — extends tsconfig.json, re-adds \`exclude:
[\"src/__tests__\"]\`. Used by the build script.
- **package.json** — \`\"build\": \"tsc\"\` → \`\"build\": \"tsc -p
tsconfig.build.json\"\`.

Confirmed locally:
- \`pnpm lint\` → 0 errors (39 warnings unchanged, all pre-existing
import-x/order).
- \`pnpm --filter @readied/mcp-server build\` succeeds;
\`dist/__tests__/\` does not exist.
- \`pnpm --filter @readied/mcp-server test\` → 5/5 pass.
- \`pnpm -r typecheck\` succeeds.

## Why a separate PR (not bundled with #290 / A1)

A1 is the Electron-pin commit. Mixing in a multi-file lint fix would
muddy what's a release-pipeline change vs a code-hygiene change. Keeping
this separate also means: this PR can go in first, then #290#294 can
rebase one by one and pass CI cleanly.

## Roadmap status

- [ ] **this PR** — lint baseline unblock
- [ ] #290 A1 (electron 41.7.1)
- [ ] #291 A2 (bump-version.mjs)
- [ ] #292 B (workflow surface)
- [ ] #293 A4 (release guardrails)
- [ ] #294 C1 (pr-title commitlint)
- [ ] C2 follow-up — add \`commitlint\` to required checks after #294
lands
- [ ] D — cut v0.15.1
@tomymaritano tomymaritano force-pushed the fix/electron-41-pin-for-better-sqlite3 branch from d5aea6d to 693a6c8 Compare June 9, 2026 13:41
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
## Why

Phase 0 **C1** of the DevOps cleanup roadmap. After v0.15.0 traced back
to PR #245's squash-merge producing a non-conventional commit message
(`release: audit...`) which semantic-release silently rejected, the
merge gate needs to block non-conventional PR titles **upstream of
merge** — not just whine in CI.

The check already existed as a step inside `ci.yml`'s `lint` job, but it
shipped as a sub-step of a multi-purpose job. Branch protection can only
require whole status checks, so requiring \`lint\` would also block on
ESLint/Prettier failures. Pulling commitlint into its own workflow gives
branch protection a clean, single-responsibility check name to require:
\`PR title / commitlint\`.

## What changes

- **New: \`.github/workflows/pr-title.yml\`** — runs commitlint against
\`github.event.pull_request.title\` on pull_request \`opened\`,
\`edited\`, \`reopened\`, \`synchronize\`.
- **\`ci.yml\`** — drops the duplicated step from the \`lint\` job and
leaves a one-line breadcrumb pointing at the new workflow.

## Security shape

The workflow follows the [GitHub command-injection
guidance](https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/):

- \`github.event.pull_request.title\` is **never** interpolated directly
into a \`run:\` script. It passes through \`env:\` as \`PR_TITLE\` and
the shell reads \`\$PR_TITLE\` from the process environment.
- The script uses \`printf '%s' "\$PR_TITLE" | pnpm commitlint\` instead
of \`echo\` — a PR title beginning with \`-e\` or \`-n\` would otherwise
be treated as an echo flag in bash/sh.

## Verification

- \`pnpm commitlint --config commitlint.config.js\` on the local
checkout exits non-zero for \`release: foo\`, \`hotfix: foo\`, \`Add
feature\`; zero for \`feat: foo\`, \`fix(scope): foo\`, \`chore!: foo\`.
- Type enum used: \`feat | fix | refactor | docs | test | chore | style
| perf | ci | build | revert\` (sourced from \`commitlint.config.js\`).

## Follow-ups (Phase 0 C2)

Once this merges, **C2** sets \`PR title / commitlint\` as a required
status check on \`develop\` and \`main\` via \`gh api\` — that's the
step that actually blocks #245-style merges. C1 is the pre-req: required
checks must exist on the default branch before they can be required.

## Roadmap status

- [x] A1 #290 — electron 41.7.1 pin
- [x] A2 #291 — \`scripts/bump-version.mjs\` + release.config.js wire
- [x] B   #292 — workflow surface cleanup
- [x] A4 #293 — release dry-run + version-assertion guardrails
- [x] **C1 (this PR)** — PR-title commitlint standalone
- [ ] C2 — branch protection \`gh api\` (next)
- [ ] D  — cut v0.15.1
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
…postinstall in setup (#296)

## Why

Two distinct CI issues, both blocking every Phase 0 PR (#290, #292,
#294). Bundling them is OK because they're orthogonal-but-related: both
clear a "lint-or-setup says no, so I can't merge" path on develop.

### Issue 1: Prettier fails on \`CHANGELOG.md\`

semantic-release writes CHANGELOG entries without prettier formatting.
The root \`format:check\` script uses \`--ignore-path .gitignore\`,
which **overrides** Prettier's default \`.prettierignore\` lookup.
CHANGELOG.md correctly isn't gitignored (it's tracked), so it gets
linted, fails, kills lint.

### Issue 2: \`setup\` job fails when native deps don't match the host
Electron

\`setup\` runs \`pnpm install --frozen-lockfile\` (no
\`--ignore-scripts\`). That triggers apps/desktop's \`electron-builder
install-app-deps\` postinstall, which **rebuilds better-sqlite3 from
source against Electron's bundled Node headers**. When better-sqlite3
lags an Electron major (the v0.15.0 incident: Electron 42 +
better-sqlite3 12.10.0, V8 \`External::Value\` signature mismatch), the
rebuild fails and setup dies — taking lint/test/typecheck/build down
with it.

The same shape took down deploy-api.yml (#287) and release.yml (#288).
This brings ci.yml in line.

## What changes

- **\`.prettierignore\`** (new) — CHANGELOG.md + local build artefacts
(.next/, .source/, .astro/, .wrangler/, dist/, out/, release/,
coverage/, pnpm-lock.yaml).
- **\`package.json\`** — \`format\` and \`format:check\` now pass
\`--ignore-path .gitignore --ignore-path .prettierignore\` (Prettier 3.x
supports repeated \`--ignore-path\`).
- **\`.github/workflows/ci.yml\`** — \`setup\` job install:
\`--ignore-scripts\` added with explanatory comment.

## Verification

- \`pnpm format:check\` locally → "All matched files use Prettier code
style!"
- CI doesn't need a runtime-functional better-sqlite3: lint and
typecheck don't load native modules, and \`pnpm test\` excludes
storage-sqlite per CLAUDE.md.

## Order of operations

After this lands → rebase #290 / #292 / #294 → CI green → merge them in
order → cut v0.15.1.
The v0.15.0 Build workflow failed on all three platforms (mac/win/linux,
run 27184736470) because better-sqlite3 12.10.0 explicitly removed
Electron v42 prebuilds in release notes:

> Temporarily rollback support for Electron v42 prebuilds
> (WiseLibs/better-sqlite3#1470)

Without a prebuild for Electron 42, electron-builder install-app-deps
falls through to a source build via @electron/rebuild. That build then
hits V8 API breakages introduced in Electron 42's V8 (V8 13.x):
- SetNativeDataProperty ambiguity (3 candidate overloads)
- External::Value() now requires an ExternalPointerTypeTag argument
- External::New() signature change

Until better-sqlite3 ships v42 prebuilds again (no public ETA), pin
Electron to its previous major. v41.7.1 is the latest 41.x as of
2026-05-26 and has a complete prebuild matrix.

After this change, `pnpm install` locally:

  apps/desktop postinstall: electronVersion=41.7.1 arch=arm64
  apps/desktop postinstall: buildFromSource=false
  apps/desktop postinstall: preparing       moduleName=better-sqlite3
  apps/desktop postinstall: finished        moduleName=better-sqlite3
  apps/desktop postinstall: completed installing native dependencies

`buildFromSource=false` = we used the prebuilt binary; no V8 compile
errors. CI Build for v0.15.1 should now succeed on all platforms
without further changes to electron-builder, codesign, or notarize
config.

This is Phase 0 A1 in the post-audit roadmap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tomymaritano tomymaritano force-pushed the fix/electron-41-pin-for-better-sqlite3 branch from 693a6c8 to 7c8a18e Compare June 9, 2026 13:53
@github-actions github-actions Bot merged commit f5adb62 into develop Jun 9, 2026
16 of 17 checks passed
github-actions Bot pushed a commit that referenced this pull request Jun 9, 2026
## Summary

Phase 0 B-bundle of the post-audit roadmap. Six independent fixes
batched into one PR because they all touch the workflow YAML surface and
reviewing them together is faster than three ping-pong PRs that all
conflict on the same files.

## docs.yml

| Change | Why |
|---|---|
| \`pnpm install\` → \`pnpm install --filter '@readied/web...'
--ignore-scripts\` | Marketing-site install was the last workflow still
firing apps/desktop's \`electron-builder install-app-deps\` step that
fails on Linux + Node 22. Same shape as #287 (deploy-api) and #288
(release). |
| Added \`permissions: contents: read\` | Cloudflare Pages deploy
doesn't need anything beyond checkout |
| Build step moved into \`working-directory: apps/web\` | Was inline
\`cd apps/web && ...\` — explicit working-directory reads better |

## build.yml

| Change | Why |
|---|---|
| \`windows-latest\` → \`windows-2025-vs2026\` | GitHub announced
\`windows-latest\` migration to that image on **2026-06-15** (6 days
from this commit). Pinning ahead avoids a surprise toolchain swap
mid-release. |
| Removed \`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true\` env | This was
the migration toggle for the Node 20→24 actions rollout. With all
actions now on @v5 (Node 24-native) it's no-op. |
| Artifact upload \`if-no-files-found: ignore\` → \`error\` | Silent
zero-asset releases are worse than a failed upload. If electron-builder
swallowed an error, signing failed, working-directory drifted, etc., we
want loud failure here, not a release un-drafted with no installers. |

## release.yml

| Change | Why |
|---|---|
| Removed \`HUSKY: '0'\` env | Leftover from the husky → lefthook
migration in #267. Lefthook only reads .git/hooks if those files exist;
on fresh CI clones they don't. |

## deploy-api.yml

| Change | Why |
|---|---|
| Added \`permissions: contents: read\` | Cloudflare deploy doesn't push
commits or create issues; minimum-privilege default. |

## Action versions sweep (all 8 workflows)

| From | To |
|---|---|
| \`actions/checkout@v4\` | \`@v5\` |
| \`actions/setup-node@v4\` | \`@v5\` |
| \`actions/cache@v4\` | \`@v5\` |
| \`actions/cache/save@v4\` | \`@v5\` |
| \`actions/cache/restore@v4\` | \`@v5\` |
| \`actions/upload-artifact@v4\` | \`@v5\` |

GitHub announced Node 20-based actions deprecation on **2026-06-16** (7
days from this commit). The \`@v5\` family runs on Node 24.

## Verification

- ✅ \`pnpm -r typecheck\` — green
- ✅ \`pnpm test\` — 17/17 (untouched)
- ✅ YAML parsed locally; no syntax errors

## Stack context

Phase 0 B-bundle. Pairs with #290 (A1 electron pin) and #291 (A2
bump-version). 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>
tomymaritano added a commit that referenced this pull request Jun 9, 2026
## Release v0.15.1 — Phase 0 DevOps stabilization

Brings the 7-PR DevOps cleanup chain to main and cuts a clean release.
This is the verification gate for the whole Phase 0 effort — if anything
breaks at tag, build, or publish, Phase 0 isn't done.

### What landed since v0.15.0

| PR | Phase | Summary |
|----|-------|---------|
| #290 | **A1** | \`fix(desktop)\`: pin Electron to ^41.7.1 so
better-sqlite3 prebuilts apply (closes the v0.15.0 V8 ABI failure on all
3 build platforms) |
| #291 | **A2** | \`fix(release)\`: restore version bumping via
\`scripts/bump-version.mjs\` + \`@semantic-release/exec\` (closes the
"tag at 0.14.0" trap) |
| #292 | **B** | \`chore(ci)\`: workflow surface cleanup — actions
@v4@v5 sweep, \`windows-latest\` → \`windows-2025-vs2026\` pin, drop
\`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24\`, \`if-no-files-found: error\`,
\`permissions:\` blocks, HUSKY: '0' removal |
| #293 | **A4** | \`chore(ci)\`: \`release.yml\` pre-flight dry-run gate
+ post-flight version assertion (closes the "silent no-release" trap) |
| #294 | **C1** | \`ci\`: PR-title commitlint as a standalone workflow →
required check on develop + main |
| #295 | | \`fix(lint)\`: develop lint baseline (preserve-caught-error ×
4 in encryptionService + mcp-server tsconfig split for ESLint
projectService) |
| #296 | | \`chore(ci)\`: unblock CI on develop — ignore CHANGELOG.md in
Prettier (semantic-release writes it), \`pnpm install --ignore-scripts\`
in setup job (same shape as release.yml + deploy-api.yml) |

### C2 — branch protection updates (already applied via gh api)

Both \`develop\` and \`main\`:
- **Required status checks**: \`lint\`, \`test\`, \`typecheck\`,
\`CodeRabbit\`, \`commitlint\`
- Force-pushes blocked
- \`strict: true\` (PRs must be up to date)

### Release pipeline guardrails now in place

- **Pre-merge**: PR-title commitlint blocks \`release:\`-style
non-conventional squash titles upstream.
- **Mid-release**: \`release.yml\` dry-run check fails loud if no
release would be cut. \`scripts/bump-version.mjs\` mutates both
\`package.json\` files. Post-flight assertion verifies both match the
dry-run-announced version.
- **Post-release**: \`build.yml\` artifact upload uses
\`if-no-files-found: error\` (silent zero-asset releases die at upload).
- **Native deps**: \`apps/desktop\` pinned to Electron 41.7.1 with
prebuilt better-sqlite3. CI \`setup\` skips postinstall so workflow-side
install never rebuilds native modules.

### Expected behavior of the Release pipeline after merge

1. Merge this PR → main tip advances.
2. Manually dispatch the **Release** workflow.
3. \`release.yml\` runs:
- \`pnpm install --ignore-scripts\` (no native rebuild needed for
semantic-release).
- **Pre-flight dry-run** → "next release version is 0.15.1" (single
\`fix(release):\` commit since v0.15.0).
   - \`npx semantic-release\`:
- \`@semantic-release/exec\` runs \`node scripts/bump-version.mjs
0.15.1\` → both package.json files updated.
     - \`@semantic-release/git\` commits + pushes tag \`v0.15.1\`.
     - \`@semantic-release/github\` creates draft Release.
   - **Post-flight assertion** → both package.jsons read \`0.15.1\`.
4. Tag push triggers \`build.yml\` on macOS-14, windows-2025-vs2026,
ubuntu-latest.
5. All 3 platforms succeed → publish job un-drafts the GitHub Release.
6. Auto-sync PR opens to merge main → develop.

### What still needs verification (post-release)

- [ ] Tag push actually triggers Build (needs GH_TOKEN with workflow
scope — A3 deferred, may need PAT regen)
- [ ] Build completes on all 3 platforms with prebuilt better-sqlite3
(smoke-test desktop bundle after publish)
- [ ] Auto-sync PR back to develop is created

🤖 This is the Phase 0 verification gate. Mobile + Plugin Marketplace UI
remain deferred.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added PR title validation workflow for automated commit message
compliance checks.

* **Bug Fixes**
  * Enhanced error diagnostics in encryption operations.
* Added pre-flight checks to release process to prevent failed
deployments.
  * Stricter artifact validation in builds.

* **Chores**
  * Updated GitHub Actions to latest stable versions.
  * Improved code formatting configuration and build scripts.
  * Adjusted Electron dependency version.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:desktop dependencies Pull requests that update a dependency file size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant