Repository navigation
Keep a project's agent from restoring notes into another project - #254
Merged
Merged
Conversation
Before: a note trashed in project A whose parent folder was later dragged into project B could still be restored by A's agent. Its trashed path still pointed into A, so the scope check passed, but the restore put the note under its parent in B and wrote a "Restored page" version to that page. After: the Pages restore tool checks the note's parent and every ancestor above it, as revert already checks the old parent, and refuses when any of them is outside the project's notes. Nothing is written and no version is added. Restores inside the project, including ones that bring back trashed ancestors, work as before. Coven-Harness: Claude Code / claude-opus-5-5
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
# Conflicts: # docs/status.md
Code coverage overviewLanguages: TypeScript TypeScript / code-coverage-agent
View coverage of the 8 most impacted files.
ℹ️ Calculations represent line coverage. Results may change as calculations are updated. |
BunsDev
added a commit
that referenced
this pull request
Oct 16, 2026
) The paired iPhone flow failed three times on 2026-10-15/16 (CI runs 38707861067, 38747016392 and 38832248437, attempt 1 each) timing out on the fixture's /resume. The simulator's unified log in each xcresult (simctl_diagnostics/<device>/system.logarchive) shows two causes. The UI-test runner makes no other request, so URLSession's first use in that process came at this step, minutes after the simulator booted. Its setup (cfprefsd, nsurlsessiond's storage container, trustd) decided most of the outcome: run call to send reply 38747016392 a1 (red) never in 44 s - 38707861067 a1 (red) 20 s none in 8.4 s 38832248437 a1 (red) 1.3 s none in 10 s 38832248437 a2 (green) 0.16 s 204 in 72 ms 38836144274 a1 (green) 0.08 s 204 in 62 ms resumeMac now POSTs over a plain BSD socket to 127.0.0.1, which needs none of those daemons, within the suite's scaled budget. The old 10 s request timeout was the one wait UITestBudget did not scale. In 38707861067 and 38832248437 the POST did reach the fixture, which neither answered nor brought the companion back (the phone kept getting connection refused), yet exited at once on SIGTERM at the end of the job. 38848571338 (PR #254) failed the same way at the first reply: the fixture left a snapshot and then a TLS ClientHello unanswered for 5 s and 8 s, the app marked the Mac disconnected, and the create-thread tap landed on the disabled button 0.2 s later. Locally the fixture answers /resume in 3 ms after 8-80 s outages, and dispose() returns at once with a phone connection in any state. The fixture writes no log, so that cause stays open. It now logs the phone's calls, the pause and the resume, and each event-loop stall of 1 s or more with the CPU time, major faults and context switches during it. Overall XCTest load did not separate red from green: green 38832248437 attempt 2 had the slowest app launches (54 s) of the five runs. Coven-Harness: Claude Code / claude-opus-5-5
This was referenced Oct 16, 2026
BunsDev
added a commit
that referenced
this pull request
Oct 19, 2026
… and the routines spec (#310) v0.2.0 was published on 2026-10-18 (23:14Z) from the signed tag on 01b1b8a. This follows Val's status layout (#290): - Shipped gains a v0.2.0 row linking its release and its review. - The 13 "On main, unreleased" items move unchanged to a new "Status summary" at the end of the v0.2.0 review, along with the old In flight entry. Each one was introduced by a commit in the tag (#248, #253, #254, #257 to #261, #263, #264, #266, #267, #269). The CF slices and #283's Markdown parser came after the tag, so they stay. - In flight keeps a short follow-ups entry for the gates no receipt records yet: the independent download checks, the banner upgrade on the release Mac, and the Companion 0.2.0 (7) TestFlight upload. - The routines spec and the README now say Phase 1, and most of Phase 0, ship from v0.2.0. Unchanged: the website's static fallback (apps/site/release.json) and the release evidence, which stay with the release owner. Claimed on #290. Coven-Harness: Claude Code / claude-opus-5-5
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #241 (finding 2: scoped restore can write into another project).
What was wrong
Probe: project A has a page Plans with a child Old plan. The child is trashed, then the Plans folder is dragged into project B. A's agent calls the Pages
restoretool on Old plan.On
mainthe restore succeeded. The trashed note's recorded path still pointed into A, soinScopepassed. ButNotesStore.trash(id, false)restores every ancestor of the note andrestoreFileputs the note under its live parent. The note came back atPersonal/theirs/Plans/Old plan.md(B), and Plans in B got a third version, "Restored page", attributed to A's agent.What changed
apps/desktop/src/main/engine/pages-agents.ts: before a restore, the tool walks the note's parent and every ancestor above it (the same chaintrash(id, false)restores) and refuses with "This note is outside this project's notes." if any of them is out of scope. This applies the existing revert check (which checks the historical parent) to every page the restore would touch. A note without a parent lands at its own trashed path, which the existinginScope(page.id)check already covers. Nothing innotes-store.tschanges, so this stays clear of the other #241 findings there (finding 3, stale trashed paths after moves, is a separate PR).Regression test
apps/desktop/test/pages-agents.test.ts, "scoped Pages restore refuses a note whose parent folder moved to another project":On unmodified
mainthe test failed at the refusal assertion (isErrorwasundefined: the restore went through). A standalone probe against the built code showed the note landing underPersonal/theirs/Plans/and the parent page going from 2 to 3 versions. With the fix the probe gets the refusal and the parent page stays at 2 versions.Verification
node --test dist/test/pages-agents.test.js: 17/17 passpnpm build && pnpm testfrom the worktree root: exit 0, no failures. Worktree scripts 107/107, core 16/16, desktop 1,437 tests (1,421 pass, 16 skipped, 0 fail) plus 21/21 native and update checks, site 10/10, store-desktop 16/16. The new test passed in the full run.docs/status.mdlist),build:mainand the pages-agents, notes-* and workspace-analytics test files: 95/95 pass.Coven-Harness: Claude Code / claude-opus-5-5