[GH-ISSUE #1173] [Bug] Cancelled macOS ownership helper compilation leaves Swift object files #415

Closed
opened 2026-10-15 18:24:53 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 9, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1173

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Process capture or runtime observation

Observed behavior

Cancelling macOS REA process-ownership helper preparation leaves Swift compiler object files after the CLI reports complete cleanup. The behavior is independently reproducible without Ghidra on the release and main. It also occurs when the real reader is closed directly during compilation. The defect is bounded leftover helper compilation storage, not a surviving process or a Ghidra project leak.

The CLI cancellation attempt left two helper object files on each tested build, 2/2 cancellation attempts per build, including a second run of the exact reproduction script below. All four invocations exited 143 and returned cancelled with details.operation: trace_web_source_location and details.cleanup: complete. Each fresh TMPDIR retained TemporaryDirectory.<suffix>/.keep-directory, ProcessRunTokenReader-1.o at 174,592 bytes, and ProcessRunTokenReaderMain-1.o at 50,584 bytes. REA's own helper root was absent, and no sampled descendant PID survived after the invocation exited.

An additional direct real-reader check on each build called reader.close() after the first compiler object appeared. Both close calls resolved, preparation rejected with AbortError, and the same temporary object directory remained. This corroborates the documented close contract directly; it is an internal-boundary check, not a separate user-facing defect.

The uncancelled CLI control succeeded on each build, 1/1 attempts per build, returned the expected original source-map content, and left its supplied TMPDIR empty. The supplied earlier Ghidra observations saw residue at 600/700/800 ms deadlines and after MCP cancellation, but two 1000 ms controls were clean. Cancellation timing matters; these sample counts are not a population frequency estimate.

Reproduction

Use a fresh scratch directory, Node 24 on PATH, Python 3, and Apple Swift via xcrun. No Ghidra, JDK, browser, or native target is required. Set REA_CHECKOUT to a scratch clone of the tested main revision after npm ci && npm run build:cached. Save the following as $SCRATCH/repro.py and run python3 "$SCRATCH/repro.py" main cancel and python3 "$SCRATCH/repro.py" release cancel. Use a fresh $SCRATCH for each repetition because the script creates new per-run directories. main success and release success run the same fixture without cancellation.

The script starts the real CLI, waits for a helper object file rather than guessing a deadline, and sends SIGTERM to the actual REA entry point. It records the result, post-exit files, and observed surviving child PIDs. The source-map input is an inert authored fixture with exact script digest and contents.

import os,pathlib,json,hashlib,subprocess,time,signal,sys
root=pathlib.Path(os.environ['SCRATCH'])
f=root/'fixture';(f/'files/modules').mkdir(parents=True,exist_ok=True)
s='generated'; (f/'files/modules/main.js').write_text(s)
manifest={'capture_path':'/capture.json','capture_sha256':'a'*64,'capture_kind':'browser-scenario','source_evidence_id':None,'capture_completeness':{'status':'complete','equality_eligible':True,'missing_sections':[],'truncated_sections':[]},'output_directory':'/analysis','analysis_input':{'input_path':'/analysis','format':'directory'},'limitations':[],'scripts':[{'url':'https://app.test/main.js?build=1#entry','source':{'kind':'scenario-response','transaction_id':'fixture','request_sequence':1,'response_sequence':2,'status':200},'content':{'state':'exported','relative_path':'modules/main.js','layout':'isolated','layout_reason':'fixture','sha256':hashlib.sha256(s.encode()).hexdigest(),'bytes':len(s),'media_type':'text/javascript','redacted':False,'representation':'browser-decoded-response-bytes'}}]}
(f/'manifest.json').write_text(json.dumps(manifest));(f/'app.js.map').write_text(json.dumps({'version':3,'sources':['original.ts'],'sourcesContent':['original'],'names':[],'mappings':'AAAA'}))
build=sys.argv[1]; mode=sys.argv[2]
t=root/(build+'-'+mode);t.mkdir()
env=os.environ.copy();env.update({'TMPDIR':str(t),'NODE_COMPILE_CACHE':str(root/'node-cache'),'npm_config_cache':str(root/'npm-cache'),'REA_LOG_LEVEL':'silent','REA_BROWSER_EXECUTABLE':'relative-unconfigured-browser'})
cmd=['node',str(pathlib.Path(os.environ['REA_CHECKOUT'])/'scripts/rea.mjs')] if build=='main' else ['npx','-y','rea-agents@6.1.0']
cmd+=['trace-web-source-location',str(f/'manifest.json'),'0',str(f/'app.js.map'),'https://app.test/app.js.map','1','0','--json']
p=subprocess.Popen(cmd,env=env,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True);start=time.monotonic();sent=False;target=None;seen=[];owned=set()
while p.poll() is None and time.monotonic()-start<40:
    table=subprocess.check_output(['/bin/ps','-axo','pid=,ppid=,command='],text=True)
    records=[line.strip().split(None,2) for line in table.splitlines() if line.strip()]
    descendants={p.pid};change=True
    while change:
        old=len(descendants)
        for r in records:
            if int(r[1]) in descendants:descendants.add(int(r[0]))
        change=old!=len(descendants)
    owned|=descendants
    objects=list(t.glob('TemporaryDirectory.*/*-1.o'))
    if mode=='cancel' and not sent and objects:
        # Signal the actual REA Node entry point, not npm's launcher.
        candidates=[r for r in records if int(r[0]) in descendants and ('scripts/rea.mjs' in r[2] or '/dist/main.js' in r[2]) and 'swift' not in r[2]]
        target=int(candidates[-1][0]) if candidates else p.pid
        seen=[{'file':str(x.relative_to(t)),'bytes':x.stat().st_size} for x in objects]
        os.kill(target,signal.SIGTERM);sent=True
    time.sleep(.01)
if p.poll() is None:
    p.kill()
out,err=p.communicate(timeout=10)
time.sleep(.2)
files=[{'file':str(x.relative_to(t)),'bytes':x.stat().st_size} for x in t.rglob('*') if x.is_file()]
alive=[]
for pid in owned:
    try:os.kill(pid,0);alive.append(pid)
    except ProcessLookupError:pass
result={'build':build,'mode':mode,'exit':p.returncode,'signal_sent':sent,'elapsed_s':round(time.monotonic()-start,3),'objects_at_signal':seen,'remaining_files':files,'surviving_observed_descendants':alive,'stdout':out,'stderr':err}
(root/(build+'-'+mode+'.json')).write_text(json.dumps(result,indent=2))
print(json.dumps({k:v for k,v in result.items() if k not in ('stdout','stderr')},indent=2));print(out[:3000]);print(err[:1000])

These are real cancellation cases. A short Ghidra startup deadline is a supplied earlier variant, not a Ghidra rerun in this investigation.

Expected behavior

ProcessOwnershipHost.close() is documented in src/process/ProcessOwnership.ts:89 to "Release owned native inspection helpers and their temporary files." The remaining object files contain only REA's packaged helper compilation output and are attributable to its owned preparation operation. Closing or cancelling that preparation should release these transient files as well as the tracked helper root. If an owned transient cannot be removed, the cleanup outcome should preserve that failure rather than claim complete cleanup.

The public Ghidra guarantee is narrower: docs/provider-evaluation.md:68-81 promises removal of the Ghidra runtime root, and that root was removed in the supplied report. docs/process-capture.md:33-38 likewise names the helper's private directory. This report relies on the shared process-host's broader helper-temporary-files contract; it does not claim that either directory-specific promise alone covers arbitrary compiler storage. docs/mcp-contracts.md:83-84 defines cleanup_incomplete once an owned cleanup failure is established.

Impact and scope

The observed residue totals 225,176 bytes of object files per cancelled CLI attempt. It recurs across fresh macOS processes when cancellation intersects compilation. No surviving owned process, Ghidra runtime-root residue, corrupted source-map result, or core workflow blockage was observed. Linux and Windows are not covered by these Darwin-specific probes. A dedicated per-run TMPDIR permits safe manual removal after all processes exit; shared temporary directories must not be glob-cleaned.

REA version

Latest npm release rea-agents@6.1.0; main b34bdcdb2877be394c59c9cbf70269dc1841ff78, built with npm ci && npm run build:cached. The release CLI ran through npx -y rea-agents@6.1.0; main ran through node scripts/rea.mjs.

Runtime and platform

Node.js v24.21.0; macOS 27.0.1, build 26A434; arm64; Apple Swift 6.4, swiftlang-6.4.0.34.1 clang-2100.3.34.1; swift-driver 1.168.6. Ghidra and Java were not used in the new reproduction.

Target and artifact context

Authored inert source-map fixture, generated script text generated, original content original, and mappings AAAA. No private target, application execution, browser, Ghidra project, or native binary is required.

Interface

CLI

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

  • Expected source: src/process/ProcessOwnership.ts:89, the shared native-inspection helper close contract; narrower public root guarantees are distinguished under Expected behavior.
  • Failure source: Real source-map CLI cancellation and real-reader close runs on both tested builds; sizes and typed CLI result appear under Actual behavior.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

The earlier Ghidra deadline/cancellation observations are supplied evidence; the provider-free CLI and direct-close observations are new local execution evidence.

{"code":"cancelled","category":"cancelled","details":{"operation":"trace_web_source_location","cleanup":"complete"}}

The excerpt omits the unchanged message/remediation fields. The process returned exit 143, not a successful analysis result.

Typed outcome or recovery expected

Release owned helper compilation transients when preparation is cancelled or closed. If owned transient cleanup cannot complete, preserve that failure in the cleanup outcome. The requested restoration is:

Repeat the real CLI cancellation at the first object-file boundary and the direct reader-close check under a dedicated empty TMPDIR. Passing cleanup leaves no helper-specific TemporaryDirectory.* object files, or reports incomplete owned cleanup instead of complete cleanup if removal fails. Keep the uncancelled source-map control successful with the same original content and digest. Preserve unrelated files and Swift's intended reusable module cache. A larger timeout alone does not test restoration because it can avoid the cancellation boundary.

Analysis or suspected cause

Source-derived explanation: src/process/DarwinProcessRunTokenReader.ts:146-164 creates a tracked rea-process-token-* root and sends a copied environment, including TMPDIR, to xcrun swiftc. Abort, close, and exit cleanup remove that tracked root at lines 131-140, 182-186, and 340-354. The leftover directories are siblings under TMPDIR rather than children of that root. These facts explain the tracking gap without prescribing a fix.

The final executable is reused within one reader and REA process; concurrent preparation shares compilation and the last cancelling waiter aborts it. Fresh CLI invocations compile again. Swift's reusable module cache is intentionally retained and is outside this report. The .o transients are not that cache.

The supported public path is CLI trace-web-source-location, through src/javascript/sourceMaps/SourceMapCommand.ts:59 into prepareProcessOwnershipInspection() and the system Darwin reader. The same shared prerequisite is reached by Ghidra startup through src/process/ProviderProcess.ts:144.

The strongest competing interpretation is that "their temporary files" means only files explicitly tracked inside REA's private helper directory. That is consistent with the narrower public directory wording. The observed files are nevertheless specific to REA's owned helper compilation, and a direct close leaves them behind. Please treat this as one bounded helper-cleanup report, not a claim that REA must delete arbitrary ambient TMPDIR files.

Additional context

Open and closed issues and pull requests were searched for ProcessRunTokenReader, TemporaryDirectory, Swift cleanup, and swiftc temp. No report of this residue was found. The nearest issue is #1137; its merged PR #1139 addresses cold module-cache cost and ownership-preparation deadline placement, not these post-cancellation object files. The current main still reproduces after that change.

No additional REA defect was discovered in this bounded investigation. No security impact is claimed.

Triage assessment

  • Impact level: P3
  • Assessment status: supported
  • Impact basis: Cancelled helper preparation leaves 225,176 bytes of compiler object files per observed CLI attempt. This is bounded cleanup residue; no surviving owned process, corrupted result, or workflow blockage was observed.
  • Workaround status: available
  • Workaround basis: The observed files can be removed safely from the caller's dedicated per-run TMPDIR after the CLI and its compiler have exited. Do not glob-delete shared system temporary directories.
Originally created by @coygeek on GitHub (Oct 9, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1173 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Process capture or runtime observation ### Observed behavior Cancelling macOS REA process-ownership helper preparation leaves Swift compiler object files after the CLI reports complete cleanup. The behavior is independently reproducible without Ghidra on the release and main. It also occurs when the real reader is closed directly during compilation. The defect is bounded leftover helper compilation storage, not a surviving process or a Ghidra project leak. The CLI cancellation attempt left two helper object files on each tested build, 2/2 cancellation attempts per build, including a second run of the exact reproduction script below. All four invocations exited 143 and returned `cancelled` with `details.operation: trace_web_source_location` and `details.cleanup: complete`. Each fresh TMPDIR retained `TemporaryDirectory.<suffix>/.keep-directory`, `ProcessRunTokenReader-1.o` at 174,592 bytes, and `ProcessRunTokenReaderMain-1.o` at 50,584 bytes. REA's own helper root was absent, and no sampled descendant PID survived after the invocation exited. An additional direct real-reader check on each build called `reader.close()` after the first compiler object appeared. Both close calls resolved, preparation rejected with `AbortError`, and the same temporary object directory remained. This corroborates the documented close contract directly; it is an internal-boundary check, not a separate user-facing defect. The uncancelled CLI control succeeded on each build, 1/1 attempts per build, returned the expected original source-map content, and left its supplied TMPDIR empty. The supplied earlier Ghidra observations saw residue at 600/700/800 ms deadlines and after MCP cancellation, but two 1000 ms controls were clean. Cancellation timing matters; these sample counts are not a population frequency estimate. ### Reproduction Use a fresh scratch directory, Node 24 on PATH, Python 3, and Apple Swift via `xcrun`. No Ghidra, JDK, browser, or native target is required. Set `REA_CHECKOUT` to a scratch clone of the tested main revision after `npm ci && npm run build:cached`. Save the following as `$SCRATCH/repro.py` and run `python3 "$SCRATCH/repro.py" main cancel` and `python3 "$SCRATCH/repro.py" release cancel`. Use a fresh `$SCRATCH` for each repetition because the script creates new per-run directories. `main success` and `release success` run the same fixture without cancellation. The script starts the real CLI, waits for a helper object file rather than guessing a deadline, and sends SIGTERM to the actual REA entry point. It records the result, post-exit files, and observed surviving child PIDs. The source-map input is an inert authored fixture with exact script digest and contents. ```python import os,pathlib,json,hashlib,subprocess,time,signal,sys root=pathlib.Path(os.environ['SCRATCH']) f=root/'fixture';(f/'files/modules').mkdir(parents=True,exist_ok=True) s='generated'; (f/'files/modules/main.js').write_text(s) manifest={'capture_path':'/capture.json','capture_sha256':'a'*64,'capture_kind':'browser-scenario','source_evidence_id':None,'capture_completeness':{'status':'complete','equality_eligible':True,'missing_sections':[],'truncated_sections':[]},'output_directory':'/analysis','analysis_input':{'input_path':'/analysis','format':'directory'},'limitations':[],'scripts':[{'url':'https://app.test/main.js?build=1#entry','source':{'kind':'scenario-response','transaction_id':'fixture','request_sequence':1,'response_sequence':2,'status':200},'content':{'state':'exported','relative_path':'modules/main.js','layout':'isolated','layout_reason':'fixture','sha256':hashlib.sha256(s.encode()).hexdigest(),'bytes':len(s),'media_type':'text/javascript','redacted':False,'representation':'browser-decoded-response-bytes'}}]} (f/'manifest.json').write_text(json.dumps(manifest));(f/'app.js.map').write_text(json.dumps({'version':3,'sources':['original.ts'],'sourcesContent':['original'],'names':[],'mappings':'AAAA'})) build=sys.argv[1]; mode=sys.argv[2] t=root/(build+'-'+mode);t.mkdir() env=os.environ.copy();env.update({'TMPDIR':str(t),'NODE_COMPILE_CACHE':str(root/'node-cache'),'npm_config_cache':str(root/'npm-cache'),'REA_LOG_LEVEL':'silent','REA_BROWSER_EXECUTABLE':'relative-unconfigured-browser'}) cmd=['node',str(pathlib.Path(os.environ['REA_CHECKOUT'])/'scripts/rea.mjs')] if build=='main' else ['npx','-y','rea-agents@6.1.0'] cmd+=['trace-web-source-location',str(f/'manifest.json'),'0',str(f/'app.js.map'),'https://app.test/app.js.map','1','0','--json'] p=subprocess.Popen(cmd,env=env,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True);start=time.monotonic();sent=False;target=None;seen=[];owned=set() while p.poll() is None and time.monotonic()-start<40: table=subprocess.check_output(['/bin/ps','-axo','pid=,ppid=,command='],text=True) records=[line.strip().split(None,2) for line in table.splitlines() if line.strip()] descendants={p.pid};change=True while change: old=len(descendants) for r in records: if int(r[1]) in descendants:descendants.add(int(r[0])) change=old!=len(descendants) owned|=descendants objects=list(t.glob('TemporaryDirectory.*/*-1.o')) if mode=='cancel' and not sent and objects: # Signal the actual REA Node entry point, not npm's launcher. candidates=[r for r in records if int(r[0]) in descendants and ('scripts/rea.mjs' in r[2] or '/dist/main.js' in r[2]) and 'swift' not in r[2]] target=int(candidates[-1][0]) if candidates else p.pid seen=[{'file':str(x.relative_to(t)),'bytes':x.stat().st_size} for x in objects] os.kill(target,signal.SIGTERM);sent=True time.sleep(.01) if p.poll() is None: p.kill() out,err=p.communicate(timeout=10) time.sleep(.2) files=[{'file':str(x.relative_to(t)),'bytes':x.stat().st_size} for x in t.rglob('*') if x.is_file()] alive=[] for pid in owned: try:os.kill(pid,0);alive.append(pid) except ProcessLookupError:pass result={'build':build,'mode':mode,'exit':p.returncode,'signal_sent':sent,'elapsed_s':round(time.monotonic()-start,3),'objects_at_signal':seen,'remaining_files':files,'surviving_observed_descendants':alive,'stdout':out,'stderr':err} (root/(build+'-'+mode+'.json')).write_text(json.dumps(result,indent=2)) print(json.dumps({k:v for k,v in result.items() if k not in ('stdout','stderr')},indent=2));print(out[:3000]);print(err[:1000]) ``` These are real cancellation cases. A short Ghidra startup deadline is a supplied earlier variant, not a Ghidra rerun in this investigation. ### Expected behavior `ProcessOwnershipHost.close()` is documented in `src/process/ProcessOwnership.ts:89` to "Release owned native inspection helpers and their temporary files." The remaining object files contain only REA's packaged helper compilation output and are attributable to its owned preparation operation. Closing or cancelling that preparation should release these transient files as well as the tracked helper root. If an owned transient cannot be removed, the cleanup outcome should preserve that failure rather than claim complete cleanup. The public Ghidra guarantee is narrower: `docs/provider-evaluation.md:68-81` promises removal of the Ghidra runtime root, and that root was removed in the supplied report. `docs/process-capture.md:33-38` likewise names the helper's private directory. This report relies on the shared process-host's broader helper-temporary-files contract; it does not claim that either directory-specific promise alone covers arbitrary compiler storage. `docs/mcp-contracts.md:83-84` defines `cleanup_incomplete` once an owned cleanup failure is established. ### Impact and scope The observed residue totals 225,176 bytes of object files per cancelled CLI attempt. It recurs across fresh macOS processes when cancellation intersects compilation. No surviving owned process, Ghidra runtime-root residue, corrupted source-map result, or core workflow blockage was observed. Linux and Windows are not covered by these Darwin-specific probes. A dedicated per-run TMPDIR permits safe manual removal after all processes exit; shared temporary directories must not be glob-cleaned. ### REA version Latest npm release `rea-agents@6.1.0`; main `b34bdcdb2877be394c59c9cbf70269dc1841ff78`, built with `npm ci && npm run build:cached`. The release CLI ran through `npx -y rea-agents@6.1.0`; main ran through `node scripts/rea.mjs`. ### Runtime and platform Node.js v24.21.0; macOS 27.0.1, build 26A434; arm64; Apple Swift 6.4, swiftlang-6.4.0.34.1 clang-2100.3.34.1; swift-driver 1.168.6. Ghidra and Java were not used in the new reproduction. ### Target and artifact context Authored inert source-map fixture, generated script text `generated`, original content `original`, and mappings `AAAA`. No private target, application execution, browser, Ghidra project, or native binary is required. ### Interface CLI ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence - Expected source: `src/process/ProcessOwnership.ts:89`, the shared native-inspection helper close contract; narrower public root guarantees are distinguished under Expected behavior. - Failure source: Real source-map CLI cancellation and real-reader close runs on both tested builds; sizes and typed CLI result appear under Actual behavior. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete The earlier Ghidra deadline/cancellation observations are supplied evidence; the provider-free CLI and direct-close observations are new local execution evidence. ```json {"code":"cancelled","category":"cancelled","details":{"operation":"trace_web_source_location","cleanup":"complete"}} ``` The excerpt omits the unchanged message/remediation fields. The process returned exit 143, not a successful analysis result. ### Typed outcome or recovery expected Release owned helper compilation transients when preparation is cancelled or closed. If owned transient cleanup cannot complete, preserve that failure in the cleanup outcome. The requested restoration is: Repeat the real CLI cancellation at the first object-file boundary and the direct reader-close check under a dedicated empty TMPDIR. Passing cleanup leaves no helper-specific `TemporaryDirectory.*` object files, or reports incomplete owned cleanup instead of complete cleanup if removal fails. Keep the uncancelled source-map control successful with the same original content and digest. Preserve unrelated files and Swift's intended reusable module cache. A larger timeout alone does not test restoration because it can avoid the cancellation boundary. ### Analysis or suspected cause Source-derived explanation: `src/process/DarwinProcessRunTokenReader.ts:146-164` creates a tracked `rea-process-token-*` root and sends a copied environment, including TMPDIR, to `xcrun swiftc`. Abort, close, and exit cleanup remove that tracked root at lines 131-140, 182-186, and 340-354. The leftover directories are siblings under TMPDIR rather than children of that root. These facts explain the tracking gap without prescribing a fix. The final executable is reused within one reader and REA process; concurrent preparation shares compilation and the last cancelling waiter aborts it. Fresh CLI invocations compile again. Swift's reusable module cache is intentionally retained and is outside this report. The `.o` transients are not that cache. The supported public path is CLI `trace-web-source-location`, through `src/javascript/sourceMaps/SourceMapCommand.ts:59` into `prepareProcessOwnershipInspection()` and the system Darwin reader. The same shared prerequisite is reached by Ghidra startup through `src/process/ProviderProcess.ts:144`. The strongest competing interpretation is that "their temporary files" means only files explicitly tracked inside REA's private helper directory. That is consistent with the narrower public directory wording. The observed files are nevertheless specific to REA's owned helper compilation, and a direct close leaves them behind. Please treat this as one bounded helper-cleanup report, not a claim that REA must delete arbitrary ambient TMPDIR files. ### Additional context Open and closed issues and pull requests were searched for `ProcessRunTokenReader`, `TemporaryDirectory`, `Swift cleanup`, and `swiftc temp`. No report of this residue was found. The nearest issue is [#1137](https://github.com/morluto/rea/issues/1137); its merged [PR #1139](https://github.com/morluto/rea/pull/1139) addresses cold module-cache cost and ownership-preparation deadline placement, not these post-cancellation object files. The current main still reproduces after that change. No additional REA defect was discovered in this bounded investigation. No security impact is claimed. ## Triage assessment - Impact level: P3 - Assessment status: supported - Impact basis: Cancelled helper preparation leaves 225,176 bytes of compiler object files per observed CLI attempt. This is bounded cleanup residue; no surviving owned process, corrupted result, or workflow blockage was observed. - Workaround status: available - Workaround basis: The observed files can be removed safely from the caller's dedicated per-run TMPDIR after the CLI and its compiler have exited. Do not glob-delete shared system temporary directories.
bsakaguchi 2026-10-15 18:24:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#415
No description provided.