authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-26 08:47:29-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-26 13:20:36-08:00
log6cf03d987c28af7fdc7867d63f791720a0464a27
tree1bad2b8dd6cfbf97e189ff517fca695eadcb8ac5
parent9b8184df7e1a5fd1837b21eaa225d06f614b574b

cleanup


2 files changed, 9 insertions(+), 11 deletions(-)

.plans/16c-pr89-remediation-checklist.md+2-11
...@@ -333,15 +333,6 @@ Counts: active `51` (`valid=33`, `partially-valid=18`), closed-invalid `6`...@@ -333,15 +333,6 @@ Counts: active `51` (`valid=33`, `partially-valid=18`), closed-invalid `6`
333333
334### Phase 6334### Phase 6
335335
336- [ ] `C024` In `executeUnprepared`, preparing outside an effect and not closing the statement can cause uncaught errors and leaks. Suggest wrapping with `Effect.acquireUseRelease`: prepare in acquire (error-safe) and `finalize` in release.
337 - Status: `TODO`
338 - Verdict: `partially-valid`
339 - Severity: `Medium`
340 - Area: `Other`
341 - File: `apps/server/src/persistence/NodeSqliteClient.ts:145`
342 - Threads: PRRT_kwDORLtfbc5whxX9
343 - Audit note: prepare() still outside managed effect boundary; failure handling risk remains.
344
345- [ ] `C028` Branch sync dispatches both server and stale local update336- [ ] `C028` Branch sync dispatches both server and stale local update
346 - Status: `TODO`337 - Status: `TODO`
347 - Verdict: `partially-valid`338 - Verdict: `partially-valid`
...@@ -351,8 +342,8 @@ Counts: active `51` (`valid=33`, `partially-valid=18`), closed-invalid `6`...@@ -351,8 +342,8 @@ Counts: active `51` (`valid=33`, `partially-valid=18`), closed-invalid `6`
351 - Threads: PRRT_kwDORLtfbc5v-XCu342 - Threads: PRRT_kwDORLtfbc5v-XCu
352 - Audit note: Optimistic local+server dual update is intentional but can temporarily diverge.343 - Audit note: Optimistic local+server dual update is intentional but can temporarily diverge.
353344
354- [ ] `C037` `Effect.callback` should return a cleanup function to close the server(s) on fiber interruption. Without it, the `Net.Server` handles keep the process alive and leak the port if the effect is cancelled. <details> <summary>🚀 Reply "<strong>fix it for me</strong>" or copy this <strong>AI Prompt</strong> for your agent:</summary>345- [x] `C037` `Effect.callback` should return a cleanup function to close the server(s) on fiber interruption. Without it, the `Net.Server` handles keep the process alive and leak the port if the effect is cancelled. <details> <summary>🚀 Reply "<strong>fix it for me</strong>" or copy this <strong>AI Prompt</strong> for your agent:</summary>
355 - Status: `TODO`346 - Status: `DONE`
356 - Verdict: `partially-valid`347 - Verdict: `partially-valid`
357 - Severity: `Low`348 - Severity: `Low`
358 - Area: `Other`349 - Area: `Other`
apps/server/src/config.ts+7
...@@ -66,6 +66,7 @@ export class NetService extends ServiceMap.Service<NetService, NetServiceShape>(...@@ -66,6 +66,7 @@ export class NetService extends ServiceMap.Service<NetService, NetServiceShape>(
66 static readonly layer = Layer.succeed(NetService, {66 static readonly layer = Layer.succeed(NetService, {
67 findAvailablePort: (preferred) =>67 findAvailablePort: (preferred) =>
68 Effect.callback<number, NetError>((resume) => {68 Effect.callback<number, NetError>((resume) => {
69 let fallbackServer: Net.Server | null = null;
69 const server = Net.createServer();70 const server = Net.createServer();
70 server.listen(preferred, () => {71 server.listen(preferred, () => {
71 server.close(() => resume(Effect.succeed(preferred)));72 server.close(() => resume(Effect.succeed(preferred)));
...@@ -88,6 +89,12 @@ export class NetService extends ServiceMap.Service<NetService, NetServiceShape>(...@@ -88,6 +89,12 @@ export class NetService extends ServiceMap.Service<NetService, NetServiceShape>(
88 Effect.fail(new NetError({ message: "Failed to find an available port", cause })),89 Effect.fail(new NetError({ message: "Failed to find an available port", cause })),
89 );90 );
90 });91 });
92 fallbackServer = fallback;
93 });
94
95 return Effect.sync(() => {
96 server.close();
97 fallbackServer?.close();
91 });98 });
92 }),99 }),
93 });100 });