Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1db6ae1
Wait for managed-worktree terminals before deletion
sambitcreate Oct 15, 2026
b97df80
Keep CLI worktree adapter aligned with async terminal drain
sambitcreate Oct 15, 2026
4d9cf10
Observe terminal exit before synchronous invalidation
sambitcreate Oct 15, 2026
37d0e7d
Block deletion while PTY session jobs survive
sambitcreate Oct 15, 2026
3e74e67
Fail closed on filtered Linux process inventory
sambitcreate Oct 15, 2026
6cad950
Guard terminal signals for invalid PTY identities
sambitcreate Oct 15, 2026
7250288
Refresh managed worktree remover prebuilts
sambitcreate Oct 15, 2026
8375442
Merge origin/main into managed worktree process cleanup
sambitcreate Oct 15, 2026
060f3b7
Align first-message worktree fixture with terminal drain
sambitcreate Oct 15, 2026
2d984f0
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
0ebd2c9
docs: note Android JDK setup for worktree verification
sambitcreate Oct 16, 2026
11097e4
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
6accb40
docs: record latest main integration and validation
sambitcreate Oct 16, 2026
1f8d6c1
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
0201076
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
e55d71a
docs: record latest main integration and validation
sambitcreate Oct 16, 2026
ac9fa79
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
b2d9504
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
0c0a495
docs: record latest main integrations and local validation
sambitcreate Oct 16, 2026
3082154
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
60e30da
docs: record revision 33 integration and validation
sambitcreate Oct 16, 2026
5485ee2
Merge remote-tracking branch 'origin/main' into feature/managed-workt…
sambitcreate Oct 16, 2026
31da26c
docs: record latest main validation for process cleanup
sambitcreate Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .memory/managed-worktree-process-cleanup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Managed worktree process cleanup

Started 2026-10-15, pending PR #500. Started from `origin/main` `11b58367`;
as of 2026-10-16, merged latest `origin/main` `6c2b44bb0` into the PR branch
without rebasing. The integrations include #498, #503, #506, #501, #504,
the 0.57.0 release merge, #508, #509, #510, #511, #512, #496, #505, #494,
and #499. The merged root
`package.json` test chain matches main. The #512 integration supplies Aiden
Remote revision 33 with synchronized iOS and fixture contracts; this PR
changes neither that revision nor its wire shape.

Explicit managed-worktree removal now awaits exit of Aiden-owned PTY sessions
after signalling them. The terminal service retains pending exits across retries;
a five-second timeout returns an actionable message and preserves the checkout.
`workspace-worktree-application-service` awaits this before dirty-state capture,
snapshot, or Git deletion. Generation, operation and schedule cancellation and
Git's ownership/identity/journal gates continue to apply.
The Remote Git adapter maps this retryable refusal to its existing
`git_capability_denied` response with the specific terminal message; iOS and
Android already surface Remote errors without a wire-shape change.
The standalone CLI has no owned PTYs; its shared-service adapter implements an
async no-op to satisfy the drain contract. Root typecheck does not compile this
package, so its separate build/typecheck is required.
Review found that synchronous renderer invalidation during terminal creation
could terminate the session before PTY exit observation was installed. Exit is
now observed before owner subscription and any post-spawn invalidation teardown.
A behavioral test covers rejection, pending exit, then successful drain.
The process boundary audits actual POSIX session membership with the packaged
native remover after shell exit. Job-control background groups can survive the
shell and lose their controlling PTY while retaining its session ID; they block
deletion until gone. Missing or invalid inventory fails closed. The Remote idempotency
ledger forgets this pre-Git refusal, allowing a same-key retry after the job
exits. The scoped unit test covers a surviving background member and replay.
On Linux, procfs may hide other users' PIDs with `hidepid`; the native audit
checks the proc mount policy and its PID-namespace view before and after
enumeration. Filtered or malformed inventory returns unavailable rather than
`empty`. The Linux fixture test and a private-mount-namespace probe cover this.
Parsing numeric PID directory names with the existing digit parser avoids
the `strtol` C23 symbol that raised the Linux package's glibc floor.
The worktree-remover prebuilts for macOS universal, Linux x64, and Linux arm64
were rebuilt from this native source, with matching binary and source hashes
in each checked-in manifest. The renderer-other CI lane checks these manifests;
updating only the source leaves that lane red even when native tests pass.
An invalid node-pty PID must never reach either the process-group signal or
node-pty's own `kill()` (which also signals its reported PID on Unix). Since
there is no session ID to audit, Aiden retains a hard removal hold for that
workspace for the service lifetime; blindly clearing it on retry would allow
deletion without a liveness proof. The error directs manual inspection.
The existing iOS and Android clients surface the Remote error message without
a protocol revision. Focused iOS simulator XCTest (12 tests) and Android JVM
tests (934 tests) passed on the prior head; the Linux-only inventory follow-up
did not change either client or the Remote contract.

The `b1e6054a` merge conflicted only on the three native manifest `builtAt`
fields. Their helper records combined automatically, preserving both this PR's
worktree remover and #501's file mutator binaries. Local validation on the
merge commit passed root typecheck, 36 native remover tests, 160 focused
desktop/Remote tests, 6 prebuilt manifest tests, terminal coverage, 99 CLI
tests, Android JVM tests, focused iOS simulator XCTest, and the sidebar E2E
case repaired by #506. The root tool-output chain passed 214 tests with CI's
Node 22.22.3; local Node 26 has different `fs.glob` symlink results. New
exact-head CI and review gates remain pending. PR #504 has merge priority, so
this branch may require one more `main` integration before eligibility.

The subsequent `ee218d1f` merge again conflicted only on the manifest
`builtAt` fields; retaining the newer timestamps preserved both the remover
and file mutator records. Local checks on the merge commit passed root
typecheck, 6 prebuilt manifest tests, 36 native remover tests, 160 focused
desktop/Remote tests, the native file mutator suite (31 passed, 3 platform
skips), terminal coverage, 218 tool-output tests under CI Node 22.22.3, and
99 CLI tests. The prior-head hosted CI run `38847791193` was green, but its
Hermes review failed twice in the engine before a verdict. Fresh exact-head
CI and a successful bot review are required after this merge.

The subsequent `515de6738` merge brought in release version and plan-index
changes without conflicts. The root `package.json` test chain still matches
main and the in-review lifecycle plan row remains present. The native helper
manifest test passed on this head. Root typecheck, 36 native remover tests,
160 focused desktop/Remote tests, the native file mutator suite (31 passed,
3 platform skips), terminal coverage, 218 tool-output tests under CI Node
22.22.3, and 99 CLI tests passed before the next push.

This is one bounded phase. No automatic retention sweep or new owner metadata is
enabled. Future eligibility must default old worktrees to manual, keep manual
worktrees out of sweeps, skip uncertain/dirty/unpushed/unknown-ignored/open-PR-
head-or-base candidates, report the reason, and revalidate before deletion.

The `e55d71a61` exact-head CI run `38854074444` was green across desktop,
mobile, E2E, CLI, and Linux packaging, with Pullfrog passing. Hermes did not
produce a verdict: service logs showed AGY quota exhaustion (429), with a
reported reset near 15:34 UTC on October 16. After main advanced to
`716636cf9`, that main was merged without conflicts. The #509 Remote Bot Files
authority fix and #508 E2E adjustment did not change this PR's process cleanup
path, package test chain, or Remote revision 32. Post-merge local root typecheck,
36 native remover tests, 6 manifest tests, 31 lifecycle tests, 99 CLI tests,
Android JVM gate and 109 focused iOS Remote client tests passed. A combined
desktop/Remote run hit an existing four-second Git timeout under concurrent
CLI build load; the isolated lifecycle suite passed. Fresh exact-head CI and
Hermes review remain required after this merge.

Main advanced again to `9deb63f52` (#510 Bot Web Search and #511 focus
modality); the merge had no conflicts. The package test chain matches main
and Remote revision remains 32. A combined local desktop/Remote run on the
earlier `716636cf9` integration passed 218 of 221 cases, but wall-clock
delays under extreme host load (load average above 250) expired a Bot Files
handle and a Remote Git snapshot and caused a first-message Git timeout.
The focused Bot Files case had passed in the first combined run; the isolated
lifecycle suite and CLI rerun also passed. Preserve these failures in the PR
record and use fresh exact-head hosted CI to judge the new head.
Root typecheck and 119 focused Bot access, Web Search, renderer, and input
modality tests passed after the `9deb63f52` merge.
The subsequent #512 merge had no conflicts. Root typecheck, 215 focused
Remote protocol/router/Bot-session/operation tests, and Android JVM tests
passed. Focused iOS Remote client, Bot session, and phase-0 simulator suites
returned exit 0 with 175 passing cases; Xcode then spent ten minutes trying
to collect simulator diagnostics and reported a diagnostic timeout. The
actual test gate passed, but hosted iOS CI remains the clean-run evidence.

The `60e30da04` exact-head CI run `38951048254` completed green across all
desktop, E2E, mobile, CLI, and Linux packaging jobs. Pullfrog passed, Hermes
reviewed that head with no findings, and no review threads remained open.
The coordinator then assigned #500 a delivery slot after #499 merged to
`6c2b44bb0`; that main merged without conflicts. The root test chain matches
main, the Remote contract remains revision 33 with no PR wire-shape change,
and all three native manifests contain both the remover and lease-flock
helpers with valid hashes. After refreshing root and CLI dependencies for
Pi 1.3.0, local root typecheck, full lint and build, 36 native remover tests,
6 native manifest tests, 160 focused desktop/Remote tests, 122 focused tests
for new main Bot lease, coding tools and device paths, 106 CLI tests, terminal
coverage, and 220 tool-output tests under CI Node 22.22.3 passed. Fresh
exact-head hosted CI, Pullfrog and Hermes are required on the post-merge head.
27 changes: 27 additions & 0 deletions .papercuts/managed-worktree-cleanup-2026-10-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Managed worktree cleanup friction

- The project history pointer in `.memory/PROJECT-CONTEXT.md` names `.memory/PROJECT-HISTORY.md`, which is absent from this checkout. The active lifecycle plan and stack disposition supplied the relevant status.
- A shell glob for `main/services/shell*.ts` failed under zsh's `nomatch`; use `rg --files` for optional paths.
- A fresh worktree has no root `node_modules` or built native helpers. Typecheck and focused worktree tests fail with missing `tsc`, `node-pty`, and `aiden-worktree-file-io` until the standard dependencies and helpers are installed/built.
- Root `npm run type-check` did not compile the self-contained `packages/cli`; the Linux container gate caught its stale synchronous terminal adapter. Run CLI build/typecheck locally whenever a shared application-service dependency changes.
- Review exposed a synchronous callback gap: `owner.onInvalidated()` can call back before returning, so a PTY exit listener installed after that subscription leaves a retained exit promise unresolved. Register exit observation before subscribing.
- A PTY shell exit is weaker than a worktree-safe process drain: interactive job control moves background jobs to another process group. On macOS, `ps -o sess` yielded `0` for a `forkpty` session leader; after shell exit, a surviving job lost its controlling TTY as well. Both `ps` fields missed the member. Audit POSIX session membership with `getsid` through the packaged native helper and fail closed if inventory is unavailable.
- A pre-Git Remote refusal must clear its idempotency admission; otherwise the client cannot retry the same deletion key after the terminal job stops.
- The Android Gradle wrapper could not find a default Java runtime or SDK in this fresh worktree; set `JAVA_HOME` to Android Studio's bundled JBR and `ANDROID_HOME` to the installed user SDK for the focused unit suite.
- Linux `hidepid=2` can hide a cross-UID PTY-session member from `/proc` enumeration while `getsid` could identify it by PID. Check procfs mount visibility before accepting an empty audit; the private mount namespace probe reproduced the hidden survivor.
- On Ubuntu's newer glibc, adding `strtol` to the native remover pulled in a GLIBC_2.38 C23 symbol and broke Aiden's GLIBC_2.34 package floor. Reuse the remover's manual unsigned parser for PID directory names and verify symbols from a newer Linux compiler.
- An invalid node-pty PID of `0` makes both `process.kill(-pid)` and node-pty's Unix `pty.kill()` target the host process group. Guard both signals. With no PID, there is no session to audit, so clearing the workspace's unknown-process hold on retry would be unsafe; report manual inspection instead.
- The legacy subagent phase-3 contract expected the exact text `if (ownerInvalidated())` after spawning a PTY; exit-observation ordering moved that check into a different expression. Remove this source-spelling assertion and rely on terminal behavioral tests for synchronous invalidation.
- Renderer-other CI failed deterministically after the native remover source changed because all three checked-in prebuilts and their manifests still carried the old source hash. Rebuild the macOS universal, Linux x64, and Linux arm64 binaries with the project toolchain, update only the remover entries in the manifests, and run `scripts/native-helpers.test.mjs` before pushing.
- After merging #491, root typecheck caught its new first-message worktree test fixture returning `void` for the terminal close dependency that this PR made async. Update the fixture to return a promise and rerun both typecheck and the focused test.
- Android's Gradle wrapper could not find a Java runtime in the shell after merging #497. Set `JAVA_HOME` to Android Studio's bundled JDK and `ANDROID_HOME` to the installed SDK before running `:app:testDebugUnitTest`.
- Merging #501 conflicted on `builtAt` in all three native prebuilt manifests. The helper records had merged automatically; retain the later timestamp and verify both helper source/binary hashes with `scripts/native-helpers.test.mjs`.
- The #501 `coding-tools` glob oracle fails locally with Node 26 because native `fs.glob("**/*")` handles symlink traversal differently. The identical test passes in the full tool-output chain under CI's pinned Node 22.22.3; use that runtime to check CI parity.
- Merging #504 repeated the three manifest `builtAt` conflicts. Its timestamps are newer; retain them while preserving both helper records, then verify the checked-in hashes.
- Running `scripts/subagent-file-mutator.test.mjs` directly skips its test-helper build and fails with `ENOENT`. Use `npm run test:subagent-file-mutator:native` for its build-first gate.
- Hermes failed twice in its engine on `6accb4035`, without a review verdict. Record the service failure separately from code findings and require a successful review on the next head.
- On `e55d71a61`, Hermes retries continued to fail because AGY exhausted its individual quota (429); the public bot comment showed only `agy failed (3)`. Respect the bot's backoff and the reported quota reset before a further manual request.
- Running the combined desktop/Remote suite concurrently with the CLI build caused a four-second Git lifecycle timeout; the standalone lifecycle suite passed 31/31. The CLI run also timed out one bundled codemode child (exit 143) under that load, then passed 99/99 in isolation. Record both symptoms and avoid parallelizing resource-heavy local gates.
- A later combined desktop/Remote run without another local test still took 27 minutes while the Mac load average exceeded 250: 218/221 passed, with a Bot Files link expiry, Remote Git snapshot expiry, and first-message Git 4-second timeout. These are time-sensitive failures; preserve the exact results and use an uncontended hosted runner for the new head.
- The focused iOS revision-33 simulator run returned exit 0 with 175 passing tests, but Xcode spent ten additional minutes collecting diagnostics and reported a diagnostic collection timeout. Keep the local test result separate from the simulator diagnostic delay; use hosted iOS CI for the clean gate.
- After #499 merged, directly invoking its harness/profile suites failed because the new `build/native/aiden-lease-flock` had not been built; use the build-first `build:lease-flock` script. The updated coding-tools glob case still differs under local Node 26; run it with CI's Node 22.22.3.
Loading
Loading