Skip to content

fix(session-context): report a read failure instead of throwing it - #577

Merged
rhuanbarreto merged 1 commit into
mainfrom
claude/session-context-read-failures
Aug 21, 2026
Merged

rhuanbarreto merged 1 commit into
mainfrom
claude/session-context-read-failures

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Picks up the findings deferred out of #576. That review ran against the branch before it was rebased, so it covered files belonging to #574 — already merged — and they were out of scope there.

The bug

sessionReadFailure exists, by its own docstring, for "a session file that is discovered but then unreadable, which a session removed between discovery and the read produces".

It could not be reached for that case. readTextIfExists checks existence and then reads, returning null only for absence — its own comment says so: "Only absence is absorbed — a file that exists but cannot be read still throws." So the exact scenario the helper is named for produced a rejection, which escaped readClaudeCodeSession, readCursorSession and readCopilotSession rather than becoming a result.

In practice: a transcript that is permission-denied, or deleted between discovery and the read, crashed the command instead of reporting which session failed.

What makes this more than a hypothetical is that two sibling readers already guard it — session-context-antigravity.ts and session-context-pi.ts both write readTextIfExists(...).catch(() => null). Three readers in the same module family did not. This makes them consistent.

Fire-tested per site, both directions

reader without fix with fix
readClaudeCodeSession fail pass
readCursorSession fail pass
readCopilotSession fail pass

An unreadable-but-present file can only be built as a non-root POSIX user — chmod is a no-op on Windows and root bypasses the mode bits — so these cases carry skipIf and were verified under WSL. On a Windows dev machine they report as passing without ever executing, which is precisely how this class of gap survives.

Also

Switches the three transcript parses to safeParse, the convention CLAUDE.md states. Behaviour is unchanged — the surrounding try/catch already caught the throw, and still guards Bun.JSONL.parse.

Verification

bun run validate green: 2576 pass, 0 fail, 21/21 ADR rules, build check clean. Independent of #576 and based on main; the two can land in either order.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@rhuanbarreto, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 652db9ec-4e26-4c78-9c0f-68d6afed06c5

📥 Commits

Reviewing files that changed from the base of the PR and between 22715ee and edd0794.

📒 Files selected for processing (5)
  • src/helpers/session-context-copilot.ts
  • src/helpers/session-context.ts
  • tests/helpers/session-context-copilot.test.ts
  • tests/helpers/session-context-cursor.test.ts
  • tests/helpers/session-context.test.ts

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 21, 2026 •

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: edd0794
Status: ✅  Deploy successful!
Preview URL: https://6bbe5d00.archgate-cli.pages.dev
Branch Preview URL: https://claude-session-context-read.archgate-cli.pages.dev

View logs

@github-actions

github-actions Bot commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 99.9% (10632 / 10643)
Threshold 99.9% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 100.0% 2194 / 2194
src/engine/ 100.0% 2620 / 2621
src/formats/ 100.0% 151 / 151
src/helpers/ 99.8% 5667 / 5677

@rhuanbarreto

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 21, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

`sessionReadFailure` exists, by its own docstring, for "a session file
that is discovered but then unreadable, which a session removed between
discovery and the read produces". It could not be reached for that case:
`readTextIfExists` checks existence and then reads, and returns null only
for absence — a file that exists but cannot be read rejects, and the
rejection escaped `readClaudeCodeSession`, `readCursorSession` and
`readCopilotSession` instead of becoming a result.

The antigravity and pi readers already spell this `.catch(() => null)`;
these three did not. A permission-denied transcript, or one deleted
between discovery and the read, therefore crashed the command rather than
reporting which session failed.

Fire-tested per site, both directions, under WSL — chmod is a no-op on
Windows and root ignores the mode bits, so these cases are non-root POSIX
only and report as passing without ever running anywhere else.

Also switches the three transcript parses to `safeParse`, the convention
CLAUDE.md states. Behaviour is unchanged: the surrounding try/catch
already caught the throw, and still guards `Bun.JSONL.parse`.

Found by CodeRabbit on #576 and deferred out of it: the review ran against
that branch before it was rebased, so it covered files belonging to #574,
already merged.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto
rhuanbarreto force-pushed the claude/session-context-read-failures branch from 709659f to edd0794 Compare August 21, 2026 17:27
@rhuanbarreto

Copy link
Copy Markdown
Contributor Author

@coderabbitai approve

@rhuanbarreto
rhuanbarreto enabled auto-merge (squash) August 21, 2026 17:30
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@rhuanbarreto
rhuanbarreto merged commit 94ffdcd into main Aug 21, 2026
24 checks passed
@rhuanbarreto
rhuanbarreto deleted the claude/session-context-read-failures branch August 21, 2026 17:32
@archgatebot archgatebot Bot mentioned this pull request Aug 21, 2026
rhuanbarreto pushed a commit that referenced this pull request Aug 22, 2026
# archgate

## [0.55.0](v0.54.0...v0.55.0)
(2026-08-22)

### Features

* **bun:** adopt Bun 1.4 archive, test parallelism, and terminal APIs
([#576](#576))
([22715ee](22715ee))

### Bug Fixes

* **ci:** stop comment runs from evicting the release push run
([#585](#585))
([9a3c881](9a3c881)),
references [#581](#581)
[#575](#575)
* **fs:** survive Bun 1.4's rejecting-read regression, and upgrade to
1.4.0 ([#574](#574))
([51f7ffc](51f7ffc))
* **session-context:** report a read failure instead of throwing it
([#577](#577))
([94ffdcd](94ffdcd)),
references [#576](#576)
[#574](#574)
[#576](#576)
* **session-context:** truncate previews on grapheme boundaries
([#581](#581))
([cc8d93c](cc8d93c))

---
This PR was generated with
[simple-release](https://github.com/TrigenSoftware/simple-release).

<details>
<summary>📄 Cheatsheet</summary>
<br>



You can configure the bot's behavior through a pull request comment
using the `!simple-release/set-options` command.

### Command Format

````md
!simple-release/set-options

```json
{
  "bump": {},
  "publish": {}
}
```
````

### Useful Parameters

#### Bump

| Parameter | Type | Description |
|-----------|------|-------------|
| `version` | `string` | Force set specific version |
| `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type
|
| `prerelease` | `string` | Pre-release identifier (e.g., "alpha",
"beta") |
| `firstRelease` | `boolean` | Whether this is the first release |
| `skip` | `boolean` | Skip version bump |
| `byProject` | `Record<string, object>` | Per-project bump options for
monorepos |

#### Publish

| Parameter | Type | Description |
|-----------|------|-------------|
| `skip` | `boolean` | Skip publishing |
| `access` | `'public' \| 'restricted'` | Package access level |
| `tag` | `string` | Tag for npm publication |

### Usage Examples

#### Force specific version

````md
!simple-release/set-options

```json
{
  "bump": {
    "version": "2.0.0"
  }
}
```
````

#### Force major bump

````md
!simple-release/set-options

```json
{
  "bump": {
    "as": "major"
  }
}
```
````

#### Create alpha pre-release

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "alpha"
  }
}
```
````

#### Publish with specific access and tag

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "beta"
  },
  "publish": {
    "access": "public",
    "tag": "beta"
  }
}
```
````

### Custom Changelog Preamble

You can add custom markdown to the top of the changelog (right after the
version header) using the `!simple-release/set-preamble` command. The
markdown after the command line becomes the preamble.

```md
!simple-release/set-preamble

## What's new?

- The website was completely redesigned
- The new API gives you awesome possibilities
```

In a monorepo, pass the full package name after the command to target a
single package's changelog. Wrap the name in backticks so GitHub keeps
it as text instead of a mention:

```md
!simple-release/set-preamble `@your-org/core`

## Core changes

- New plugin system
```

Use one comment per package, plus one without a name for the whole
release.

### Access Restrictions

The commands can only be used by users with permissions:
- repository owner
- organization member
- collaborator

### Notes

- The last comment with `!simple-release/set-options` command takes
priority
- The last `!simple-release/set-preamble` comment per package takes
priority
- JSON must be valid, otherwise the `set-options` command will be
ignored
- Parameters apply only to the current release execution
- The commands can be updated by editing the comment or adding a new one


</details>

<!--
  Please do not edit this comment.
  simple-release-pull-request: true
  simple-release-branch-from: release
  simple-release-branch-to: main
-->

Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

1 participant