Skip to content

Read-only mode#450

Merged
cb1kenobi merged 17 commits intomainfrom
readonly-mode
May 6, 2026
Merged

Read-only mode#450
cb1kenobi merged 17 commits intomainfrom
readonly-mode

Conversation

@cb1kenobi
Copy link
Copy Markdown
Member

@cb1kenobi cb1kenobi commented May 1, 2026

Adding support for a HARPER_READONLY environment variable and --readonly CLI flag to open RocksDB databases in read-only mode and avoids the dreaded Error: IO error: While lock file: /Users/chris/harper/database/data/LOCK: Resource temporarily unavailable opening database /Users/chris/harper/database/data.

Also exports a new flushDatabases() function on the public API.

Fixes #404. Also addresses HarperFast/nextjs#41.

heskew

This comment was marked as outdated.

@heskew
Copy link
Copy Markdown
Member

heskew commented May 1, 2026

AI Review: Read-only mode implementation

....

🤖 Generated by Gemini CLI

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 1, 2026

Reviewed; no blockers found.

Copy link
Copy Markdown
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

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

Cool, this is great!

Data Integrity (Crash Recovery):

I believe this is actually a really important thing here. RocksDB often has much/most of its data just in memory. Using read-only mode successfully will actually usually require that you flush data and then start the new harper process. I suppose this is actually executed in the nextjs plugin, but noting here. But maybe this might drive a need for having a public flush() method (and I guess maybe it kind of a top-level piece of functionality, ideally you want to flush everything before a new process because it is difficult to guess what the new process might access).

Comment thread resources/databases.ts Outdated
export function isReadOnlyMode(): boolean {
if (_isReadOnlyMode !== undefined) return _isReadOnlyMode;
// Check environment variable
if (process.env.READONLY && process.env.READONLY !== '0' && process.env.READONLY !== 'false') {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I mentioned this in another PR but I would love if we can have this prefixed. Like HARPER_READONLY or something like that.

heskew and others added 7 commits May 4, 2026 17:15
Symptom: every PR was failing `Auth gate invariants / validate`
with `authorize job has no step setting USERS_TO_CHECK env var`,
even on workflows that clearly set it. Reported on PR #452 and
others.

Cause: the check `USERS_TO_CHECK presence` (added in #417 review-
fixup) was using a jq-flavored expression — `// empty` in
particular — but yq on ubuntu-latest is `mikefarah/yq` (Go), not
jq. yq's lexer rejects `empty`. The script had `2>/dev/null` on
the yq invocation, so the lexer error was eaten and the variable
came back as the empty string, tripping the existence check on
every workflow.

Fix: rewrite the expression in idiomatic yq:
- `.jobs.authorize.steps[].env.USERS_TO_CHECK | select(. != null)`
  — emits a stream of one value per step that sets the env var,
  skipping steps that don't.
- `head -1` collapses the stream to a single value (or empty)
  for the `[ -n ]` check.

Verified locally with mikefarah/yq v4.53.2 against all three
harper claude-*.yml workflows — all pass.

Out of scope but worth following up:
- The `2>/dev/null` swallowed a real yq error. Worth either
  removing the suppression or capturing stderr for diagnostics
  when the expression returns empty.
- oauth's mirror (#68) carries the same bug; a copy of this
  fix needs to land there too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runner deprecation warning on the validate job:

> Node.js 20 actions are deprecated. The following actions are
> running on Node.js 20 and may not work as expected:
> actions/checkout@34e1148.
> Actions will be forced to run with Node.js 24 by default starting
> June 2nd, 2026. Node.js 20 will be removed from the runner on
> September 16th, 2026.

`actions/checkout` v5.0.0 was the Node 20 → Node 24 jump. v6.0.2
(2026-01-09) is the latest stable, ~4 months baked, and is already
in use elsewhere in this repo (`format-check.yml`,
`integration-tests.yml`, `unit-test.yml`) — same SHA, no new
trust surface.

11 instances bumped across:
- auth-gate-invariants.yml          (1)
- claude-issue-to-pr.yml            (3)
- claude-mention.yml                (3)
- claude-review.yml                 (4)

v6.0.0's notable change was "persist creds to a separate file"
(security improvement). v6.0.2 adds tag-handling fixes. We don't
configure custom credential persistence in our checkouts, so the
upgrade is transparent.

Other actions in claude-*.yml were NOT flagged by the runner —
`actions/setup-node@v6.2.0`, `actions/create-github-app-token@v3.1.1`,
`anthropics/claude-code-action@v1.0.99` are presumed Node-24-clean.
If/when their warnings appear, that's a separate sweep.

oauth needs the same change — will mirror after this lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sweep of currently-pinned third-party action SHAs to latest stable
releases past the 3-day buffer (per pin-bump trust model — internal
repos can ship same-day, third-party waits for bake time).

Bumps applied:

- **actions/setup-node**: v6.2.0/v6.3.0 → v6.4.0 (2026-04-20, 14
  days old). Minor version, no breaking changes. Aligns
  claude-*.yml with format-check.yml / integration-tests.yml /
  unit-test.yml at a single version.
  - claude-issue-to-pr.yml, claude-mention.yml: v6.2.0 → v6.4.0
  - format-check.yml, integration-tests.yml, unit-test.yml: v6.3.0 → v6.4.0

- **actions/upload-artifact**: v7.0.0 → v7.0.1 (2026-04-10, 24
  days old). Patch version. integration-tests.yml only.

- **anthropics/claude-code-action**: v1.0.99 → v1.0.110 (2026-04-29,
  5 days old). Patch range, no breaking changes from v1
  migration. v1.0.111 (2026-05-01) is at the buffer edge so
  conservatively held back. claude-issue-to-pr.yml,
  claude-mention.yml, claude-review.yml.

Skipped (already current past buffer):
- actions/checkout v6.0.2 (2026-01-09)
- actions/create-github-app-token v3.1.1 (2026-04-11)
- actions/download-artifact v8.0.1 (2026-03-11)

Verified locally:
- All affected workflows parse as valid YAML.
- `validate-auth-gate-invariants.sh` passes against all three
  claude-*.yml workflows.

oauth needs a parallel sweep — will follow once this lands. oauth's
sweep also picks up:
- The actions/checkout v4.3.1 → v6.0.2 mirror (the change shipped
  in harper #461 hasn't been mirrored to oauth yet).
- pr-checks.yml's three tag-pinned refs (`actions/checkout@v4`,
  `actions/setup-node@v4`, `oven-sh/setup-bun@v2`) need SHA pins.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cb1kenobi cb1kenobi requested a review from a team as a code owner May 4, 2026 22:15
Comment thread index.ts
Copy link
Copy Markdown
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

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

Great!

kriszyp pushed a commit that referenced this pull request May 5, 2026
Diagnosis from harper PR #450 review failure (run 25234303343):
agent burned ~20 turns on `Bash(grep -rn …)` searches across the
whole repo before hitting `--max-turns 24`, posted no review
comment, and the log step skipped (no marker'd comment to log).
Diff was small (5 files, +83/−8) — exploration pattern, not diff
size, was the cost driver.

Two changes:

1. **--max-turns 24 → 48.** Cheap band-aid that ends the immediate
   dropouts on PRs with non-trivial cross-symbol exploration. Per
   the existing comment, this is the real cost ceiling — bumping
   doubles the worst-case budget and moves us out of the 'one
   exploratory grep too many = no review at all' regime.

2. **Tools section: explicit turn-budget hint + sharpened
   anti-pattern.** Names "repo-wide search" as THE biggest
   turn-burner, points at the `Grep` tool with `path` scoping, and
   cites the failure mode ("recent run that timed out before
   posting anything") so the agent has concrete signal that
   matches its observed behavior.

Out of scope: investigating whether `Bash(grep …)` is supposed to
be denied by the existing `--allowedTools` list (current entries
scope to `Bash(git diff:*)`, `Bash(git log:*)`, `Bash(git blame:*)`,
`Bash(git show:*)`, `Bash(gh ...:*)` — `Bash(grep …)` shouldn't
match any pattern but ran cleanly in #450's failed run, with
`is_error: false` on every grep tool call). Either claude-code-
action permits any `Bash(...)` once the tool is enabled, or there's
a matching gotcha. Tracked as a follow-up; this PR addresses the
immediate symptom.

oauth needs the same change — will mirror after this lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@heskew
Copy link
Copy Markdown
Member

heskew commented May 5, 2026

Filed two follow-ups for read-only-mode gaps surfaced in an earlier Gemini review (intentionally out of scope for this PR):

@cb1kenobi cb1kenobi merged commit cd8d567 into main May 6, 2026
26 of 27 checks passed
@cb1kenobi cb1kenobi deleted the readonly-mode branch May 6, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read-only mode

5 participants