Conversation
Task cleanup closed only its own task pane and relied on Herdr removing a workspace whose last tab went with it. A workspace that also held a pane firstmate does not own, such as a plugin sidebar or a tab the captain opened by hand, therefore survived every cleanup, and projected one-task workspaces accumulated without bound. Spawn now records herdr_workspace_created=1 for a workspace it created, taken from the create response rather than inferred from a label, title, or tab count, and teardown closes that workspace once the task pane is confirmed gone. The new adapter helper refuses rather than closing when that proof is absent, when the workspace is the focused one, when a remaining tab is the captain's active tab, when a remaining pane still has a live or unreadable agent, or while any other recorded task in this home names that workspace or still has a pane in it. That recorded-task scan, not a pane label, is the "no firstmate task pane remains" test, so a renamed plugin, a second plugin, and a hand-added pane all read the same way. The workspace is what closes; a pane firstmate does not own is never closed to force Herdr's last-tab behaviour. The exact prior tab is restored after the close, because Herdr 0.7.5 moves focus when an explicit close empties a non-focused workspace and the retirement does not assume 0.8.0. Coverage: adapter regressions for every refusal and for the confirmed close, teardown regressions for the foreign-pane case, the lone-task-pane case, focus restoration, an adopted workspace, and a registered agent, plus a real-Herdr guard in a guarded named lab that reproduces the leak live and proves the removal preserves exact focus. Dated evidence is recorded in docs/verification/runtime-backends.md.
…refuse ambiguous records
… proof unconditional
a90715f to
abb8c63
Compare
|
Ready for a maintainer when you have a moment. This one is complete on our side with all checks green. Nothing further is pending from this fork. |
|
Speaking as Kun's firstmate: Corrective — teardown now closes a firstmate-CREATED Herdr workspace once the task pane is gone, so a foreign pane (plugin sidebar, hand-added tab) cannot leak it. Adopted workspaces stay refused before any Herdr call; focus is never stolen; leftover panes firstmate does not own are never closed. I reviewed the full diff on HEAD |
Intent
Stop firstmate leaking herdr workspaces. When a plugin keeps a pane in a workspace, firstmate's task teardown no longer removes that workspace, and they accumulate without bound.
The diagnosis was done and confirmed before this work started, and was not to be redone. Firstmate never closed a workspace explicitly; it closed only its task tab and relied on herdr's behaviour that closing a workspace's last tab deletes the workspace itself. The captain installed the herdr-sidebar plugin (https://github.com/alexarthurs/herdr-sidebar), which keeps a permanent pane in every workspace, so the task tab is never the last tab. Confirmed by controlled comparison on 2026-08-19, not just by reading: across eight workspaces, the only one WITHOUT a sidebar pane was removed on teardown, and every one WITH a sidebar pane survived. Same code path, same host, minutes apart.
What to build: make firstmate remove a workspace IT CREATED once no firstmate task pane remains in it, without ever stealing the captain's focus. Most of the machinery already existed (fm_backend_herdr_emptying_close_plan, fm_backend_herdr_workspace_prune_seeded_default_tab, fm_backend_herdr_workspace_presence_state, docs/herdr-backend.md), so the task was to study it first and reuse it rather than build something new.
Five constraints were stated as load-bearing, all deliberate captain decisions rather than incidental preferences:
Required regression coverage: a firstmate-created workspace containing a task pane PLUS one extra non-task pane must be gone after teardown, and the same workspace with only the task pane must also be gone. Both cases, and neither may move focus. tests/fm-backend-herdr-focus-flash-e2e.test.sh already reproduces the focus-steal and was named as the model to follow.
A herdr lab contract was mandatory for this task and was followed for every live check: every create, close, focus or move went through bin/fm-herdr-lab.sh in a named non-default lab, never against the default session where the captain's own session and a live worker are running. Direct herdr server or session lifecycle commands and any call scoped only by ambient HERDR_SESSION were forbidden, including for read-only probes and cleanup after failure. The helper's before/after default-session tripwire stayed armed.
The repo is firstmate's own shared tracked material, so .claude/skills/firstmate-coding-guidelines was read first and applied: knowledge-placement decision tree, one-owner rule, one sentence per line in tracked Markdown, plain dash and never an em dash anywhere including the commit message and PR body, no agent co-author trailer, tests that exercise behaviour through an executable interface and never assert implementation-source bytes, colocated tests extending existing runners, and the harness-dependent-checks rule requiring a portable regression plus a live guard plus dated evidence in docs/verification/runtime-backends.md.
Implementation decisions made while doing the work, which a reviewer reading only the diff would not know:
Verification performed: tests/fm-teardown.test.sh and tests/fm-backend-herdr.test.sh both green, tests/fm-test-run.test.sh green, shellcheck 0.11.0 clean, bin/fm-doc-audience-check.sh clean, and the live guard run against real herdr 0.8.0 protocol 19 through the guarded lab producing leak_live=1 (the leak reproduced live before the fix ran) with exact focus preserved in every sample and the default session verified byte-identical afterward. actionlint is not installed on this host, so bin/fm-lint.sh exits nonzero on that step alone; no workflow files were changed.
Delivery: firstmate ships through the full validation pipeline. Do not touch the default herdr session, the captain's workspace w1Q, or the live research workspace w1Z.
What Changed
fm_backend_herdr_workspace_retire_createdtobin/backends/herdr.sh, which closes the workspace itself only under a literalcreatedproof argument and only after every gate passes: structured workspace presence, an unambiguous focus snapshot, the target not being the focused workspace or holding the captain's active tab, a positively dead or unregistered agent state on every remaining pane, and no other still-recorded task in this home naming that session and workspace or holding a live recorded pane there. It restores the exact prior tab behind the close and confirms removal, and it never closes a tab or pane firstmate does not own.bin/fm-spawn.shrecords the durable created-versus-adopted proofherdr_workspace_created=1from the create response (projected create, validated version 2 reclaim binding, and a non-empty seeded tab id on the flat container-ensure path), and adds the key topreserve_relaunch_metaso a relaunch recomputes it instead of carrying a stale value.bin/fm-teardown.shcalls the retirement after the exact task pane is confirmed gone, requires the session presentation lock, and treats a refusal or failure as a warning rather than a teardown blocker; its journal-quarantine warning now states why the journal was not retired.tests/fm-backend-herdr-workspace-retire-e2e.test.sh(leak measurement, foreign-pane close, lone-task-pane no-op, adopted-workspace refusal) and registers it in the real-herdr-gated family inbin/fm-test-run.sh, plus portable coverage of the retirement refusals and the teardown call site intests/fm-backend-herdr.test.shandtests/fm-teardown.test.shand of the proof surviving relaunch intests/fm-control-relaunch.test.sh.docs/herdr-backend.mddocuments the retirement, the metadata key, and the flat-layout limit;docs/verification/runtime-backends.mdrecords the dated 0.8.0 protocol 19 run.Risk Assessment
✅ Low: The change introduces a genuinely destructive operation teardown never performed before, but it is narrowly scoped to a durable created-versus-adopted proof recorded at spawn, guarded by seven independent refusals that all fail toward leaving the workspace in place, non-blocking on refusal, and covered by portable adapter, teardown and relaunch regressions plus an unconditional live guard, with only one informational hardening nit remaining.
Testing
Ran the targeted regression set (fm-teardown, fm-backend-herdr, fm-control-relaunch, fm-test-run) all green, then proved the intent live: the registered guard against real herdr 0.8.0 protocol 19 reproduced the leak before the fix path ran (leak_live=1), drove a real workspace close (live_close=1), and kept exact focus in every sample, and a hand-driven lab transcript shows the captain's workspace strip with the task workspace surviving its pane close while a plugin sidebar pane remains and then being removed, the foreign pane never closed, focus unchanged, and an adopted workspace refused before any Herdr call. Non-vacuity was confirmed by restoring the baseline teardown call site in an out-of-tree copy, where the required foreign-pane regression fails with the reported symptom. No visual artifact was captured because the change has no rendered surface of its own: the user-visible surface is herdr's workspace list, captured here as real CLI output, and attaching to a herdr session to screenshot the workspace strip would itself move the captain's focus, which this change exists to prevent. One modified real-Herdr test (presentation e2e) cannot complete on this host due to a pre-existing treehouse logical-versus-physical $HOME path mismatch that aborts teardown before the new code; CI's herdr lane owns that coverage. All Herdr work went through the guarded lab helper, every lab teardown verified the default session byte-identical, and the treehouse pool residue my run created was removed, leaving the worktree clean.
Evidence: Live herdr 0.8.0 transcript: the captain's workspace strip before the leak, at the leak, and after the retirement
CASE 1 firstmate-created task workspace + one extra pane firstmate does not own (plugin sidebar) -- BEFORE teardown -- workspace focused label w1 yes captains-own-workspace w2 no fm-task-leak-demo w3 no bystander-workspace focus: workspace w1 tab w1:t1 -- teardown step 1: close the exact task pane w2:p1 (production path) -- task pane now: pane_not_found -- state after the pane close: THIS IS THE LEAK (pre-fix teardown stopped here) -- workspace focused label w1 yes captains-own-workspace w2 no fm-task-leak-demo w3 no bystander-workspace foreign pane w2:p2: present -- teardown step 2 (the fix): retire the workspace firstmate CREATED -- exit=0 output='' herdr calls the retirement made: herdr workspace list / tab list / pane list / pane get w2:p2 / agent get w2:p2 herdr workspace close w2 herdr workspace list / tab list --workspace w1 -- AFTER teardown -- workspace focused label w1 yes captains-own-workspace w3 no bystander-workspace focus: workspace w1 tab w1:t1 foreign pane w2:p2: gone with its workspace: pane_not_found CASE 2 same workspace with ONLY the task pane -- AFTER teardown (retirement is a silent no-op: exit=0 output='') -- w4 fm-task-lone-demo is gone; focus still workspace w1 tab w1:t1 herdr calls the retirement made (a presence probe only, no close): workspace list CASE 3 an ADOPTED workspace the captain owns retirement without the created proof: exit=2 output='' herdr calls made: 0 (refused before talking to Herdr at all) w6 captains-adopted-workspace still present, its foreign pane w6:p2 present == lab teardown == lab fm-lab-fm-leak-evidence-... torn down; default session verified byte-identicalEvidence: Live guard against real herdr: leak reproduced live, workspace close driven, focus preserved
ok - leak reproduced: closing the task pane left the whole workspace behind because a foreign pane remained ok - cleanup: the surviving created workspace was closed with exact focus preserved in every sample ok - lone task pane: the workspace goes with it and cleanup stays a silent no-op ok - adopted workspace: cleanup refuses before any Herdr call and leaves it exactly as it was evidence: herdr=0.8.0 protocol=19 leak_live=1 live_close=1 default-session-tripwire=armedEvidence: Negative control: the required regression fails with the baseline teardown call site restored
# out-of-tree copy of HEAD with only bin/fm-teardown.sh reverted to 03bb1d8 ok - herdr projection teardown surfaces failed focus restoration without turning confirmed cleanup into a hard failure not ok - herdr-retire-foreign-pane: the workspace a foreign pane kept alive survived teardown # exit=1 ; the same case passes with the fix in placeEvidence: Evidence harness used for the live transcript (all Herdr calls routed through bin/fm-herdr-lab.sh)
Evidence: Targeted regression runs (teardown, adapter, relaunch, runner registration)
tests/fm-teardown.test.sh: ok - herdr teardown closes a created workspace a foreign pane would otherwise keep alive ok - herdr teardown leaves no workspace behind when the task pane was the last one in it ok - herdr teardown restores the captain's exact tab when closing a created workspace moves focus ok - herdr teardown warns and still restores the captain's exact tab when the workspace close fails ok - herdr teardown never closes a workspace it cannot prove firstmate created ok - herdr teardown leaves a created workspace in place while an agent is still registered in it tests/fm-backend-herdr.test.sh: twelve created-workspace retirement gates green tests/fm-control-relaunch.test.sh: created proof carried on relaunch, never invented for an adopted workspaceEvidence: Unrelated host blocker for the modified presentation e2e
ok - real Herdr lab: an opted-out spawn retains the Stage 1 Herdr command sequence with zero ordering calls not ok - opted-out teardown failed: ... worktree /local/home/inthuson/.treehouse/project-70889f/2/project is not managed by treehouse error: treehouse return failed for worktree ...; teardown aborted # treehouse-state.json recorded the same worktree as /home/inthuson/.treehouse/project-70889f/2/project # /home/inthuson -> /local/home/inthuson ; abort is at bin/fm-teardown.sh:2453, before the new retirement blockPipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:2681- HERDR_WORKSPACE_CREATED is only initialized at bin/fm-spawn.sh:1906, inside thecase "$BACKEND"block that is skipped entirely when RELAUNCH=1 (theif [ "$RELAUNCH" -eq 1 ]; then ... else case ... esac fispanning lines 1849-2106). Line 2681 dereferences it unconditionally for BACKEND=herdr, so underset -eu(line 197) everyfm-spawn.sh --relaunchof a herdr task dies with "HERDR_WORKSPACE_CREATED: unbound variable" while writing the replacement meta. This is reachable in the product through bin/fm-control.sh:814, and no test covers --relaunch with backend=herdr (tests/fm-control-relaunch.test.sh has no herdr fixture), so nothing catches it. The same omission is also a semantic defect: relaunch re-reads herdr_session/herdr_workspace_id/herdr_tab_id/herdr_pane_id from RELAUNCH_META at lines 1031-1034 but never reads herdr_workspace_created, while preserve_relaunch_meta now strips it as an owned key, so a relaunched task would permanently lose the created proof and leak its workspace. That contradicts the new docs/herdr-backend.md line "it survives a relaunch that rewrites the endpoint". Fix both by reading it from RELAUNCH_META in the herdr block at lines 1030-1035 (normalizing to 0/1); relaunch cannot change the workspace, since a structurally gone pane already refuses the relaunch, so carrying the recorded value forward is never stale.tests/fm-backend-herdr-presentation-e2e.test.sh:741- The new herdr_workspace_created=1 meta line breaks this existing test's byte comparison. Theshapetask is spawned once with presentation off (flat path: it ADOPTS the workspaceanchorcreated at line 501, so fm_backend_herdr_workspace_ensure returns an empty seeded tab id and no key is written) and once projected (line 601: fm_backend_herdr_projection_create_task sets HERDR_WORKSPACE_CREATED=1, so the key IS written). normalize_meta at line 424 masks only window/herdr_workspace_id/herdr_tab_id/herdr_pane_id/spawn_gen, so the ON meta now carries one extra line andcmp -sat line 741 fails with "metadata changed beyond Herdr container IDs between opted-out and projected paths". This file is registered in the real-herdr-gated family at bin/fm-test-run.sh:162, which is the family the CI herdr lane runs. Fix by adding the new key to normalize_meta (for example-e '/^herdr_workspace_created=/d') and, if the created-versus-adopted difference is worth pinning there, asserting it explicitly rather than through the byte compare.bin/backends/herdr.sh:1952- The recorded-task scan reads other tasks' herdr_session, herdr_workspace_id, and herdr_pane_id withsed -n 's/^key=//p' | head -n 1, i.e. first-occurrence-wins. Every other reader of this same meta format uses different semantics: fm_meta_get (bin/fm-backend.sh:338) is documented as last-value-wins, and fm_backend_meta_exact_value (bin/fm-backend.sh:371) refuses outright unless the key appears exactly once, precisely because destructive teardown must treat ambiguity as a refusal. If another task's record ever carries a duplicated herdr_workspace_id or herdr_pane_id, this gate reads a value the rest of the system does not, skips the match at lines 1955 and 1961, and licenses aworkspace closeon a workspace a live task still holds. Make this scan refuse on a duplicated or ambiguous key (or at minimum match fm_meta_get's last-wins) so the destructive gate fails toward refusal like the endpoint validator does.tests/fm-teardown.test.sh:2104- The fixture defines FM_FAKE_HERDR_WS_CLOSE_FAIL but no test ever sets it, so the adapter's workspace-close failure branch at bin/backends/herdr.sh:1968-1972 (warn, run the prior-tab restore, return 1) is uncovered in both the portable teardown suite and the adapter suite - the adapter suite covers the unconfirmed-removal branch but not the failed-close branch. Either exercise the knob with a case that asserts the warning plus the restore, or drop the dead knob.🔧 Fix: carry created-workspace proof through relaunch, refuse ambiguous records
4 issues (1 warning, 3 infos) still open:
bin/fm-teardown.sh:2513- The quarantined-journal warning is now factually wrong because of this change. It prints "herdr presentation journal for $ID remains quarantined; no workspace cleanup was attempted", but the new created-workspace retirement block at bin/fm-teardown.sh:2532 runs unconditionally after it and can issue a realworkspace close. Concrete path: a projected task (so its meta carries herdr_workspace_created=1 from bin/fm-spawn.sh:2008) whose journal no longer correlates at teardown, so fm_backend_herdr_projection_endpoint_matches_journal fails and HERDR_PRESENTATION_RETIRE_CANDIDATE stays 0; theelif [ "$BACKEND" = herdr ]branch closes the pane through fm_backend_herdr_kill_serialized, line 2513 prints the warning, fm_backend_herdr_endpoint_confirmed_gone at line 2523 passes, and the retirement then closes the workspace. The behavior itself is correct - the retirement's authority is the task's own validated metadata, not the non-authoritative journal - but the operator is told the opposite in exactly the ambiguity path where the docs tell them to inspect manually. Scope the sentence to the journal-authorized cleanup it actually describes (for example "no journal-authorized workspace cleanup was attempted"), leaving the unrelated line 2509 message alone since the endpoint gate below it does still stop the retirement.bin/backends/herdr.sh:2323- Sibling path note for the durable-fix question, not a demand to widen scope. fm_backend_herdr_projection_cleanup_exact (the same-process abort cleanup invoked from bin/fm-spawn.sh:728) closes the task pane and the seeded pane but never the workspace, and on that path no task meta is written at all, so no herdr_workspace_created proof ever exists. A workspace a plugin pane keeps alive there is therefore permanently outside the new retirement's reach, and bin/fm-herdr-session-cleanup.sh cannot reclaim it either because its candidate test requires tab_count == 1 and pane_count == 1 (bin/fm-herdr-session-cleanup.sh:134). This is bounded by how often a projected create aborts mid-sequence, and docs/herdr-backend.md already routes "crashes, lost responses, failed exact-pane cleanup" to manual cleanup, so the authorized teardown leak this change targets is genuinely closed. Recording it so the remaining shape is known rather than assumed fixed.tests/fm-backend-herdr-workspace-retire-e2e.test.sh:216- The live guard's entire fix proof is gated on LEAK_LIVE. Part A closes the task pane and sets LEAK_LIVE=1 only if ws_alive (line 97,workspace get) still reports the doomed workspace; if that probe fails for any reason other than a genuinely removed workspace, the script prints "leak note: ..." and skips all of Part B, so fm_backend_herdr_workspace_retire_created is never once driven to an actualworkspace closelive - Part C only exercises the already-absent no-op and Part D only the proof refusal - and the run still exits 0 with everyokline. That silently defeats the point of registering the file in the real-herdr-gated family that CI runs with --fail-on-gate-skip. The model test at tests/fm-backend-herdr-focus-flash-e2e.test.sh keeps its mitigation assertions unconditional and gates only the extra defective-release checks. Either create a fresh doomed workspace for Part B so the close is always exercised, or distinguish "workspace absent" from "probe unreadable" and fail on the latter.tests/fm-teardown.test.sh:2034- configure_herdr_workspace_retire_case exports FM_FAKE_HERDR_EXTRA_PANE into the whole test process, unlike every other knob in this fixture family (FM_FAKE_HERDR_WS_CLOSE_FAIL, FM_FAKE_HERDR_STEAL_FOCUS, FM_FAKE_HERDR_LIVE_AGENT) which callers pass as leading assignments, and unlike run_workspace_retire_teardown's own marker variables. It is the onlyexport FM_FAKE_*in the file, and it stays set at whatever the last retire case chose for every test that runs after it. Nothing downstream reads it today, so this is hygiene rather than a live defect, but a future case that forgets to call configure_herdr_workspace_retire_case would silently inherit a stale foreign-pane setting. Pass it through run_workspace_retire_teardown from a case-scoped variable instead.🔧 Fix: correct quarantine warning, make live retirement proof unconditional
1 info still open:
bin/fm-teardown.sh:2542- herdr_workspace_created is the single key that authorizes the new destructiveworkspace close, but it is the one endpoint field on that path still read with last-value-wins semantics:meta_valuedelegates to fm_meta_get (bin/fm-backend.sh:337-342, documented as last-wins). Every other field that reaches the same close is exact-value validated - fm_backend_validate_task_endpoint runs fm_backend_meta_exact_value over herdr_session, herdr_workspace_id, herdr_tab_id and herdr_pane_id (bin/fm-backend.sh:459-462), which refuses outright unless the key appears exactly once, and the previous round extended that same refuse-on-duplicate contract to other tasks' records inside the adapter (bin/backends/herdr.sh:1957-1964). A record carrying two herdr_workspace_created lines therefore licenses the close on a value the rest of the destructive path would have refused to resolve. This is hardening consistency, not a live defect: spawn writes the key at most once (bin/fm-spawn.sh:2691) and preserve_relaunch_meta owns it, so the only way to produce a duplicate is a partial write or a hand edit - which is exactly the class fm_backend_meta_exact_value exists to refuse before destruction. Reading it through fm_backend_meta_exact_value (or an equivalent exactly-once check) would close the gap.tests/fm-backend-herdr-presentation-e2e.test.sh:421- tests/fm-backend-herdr-presentation-e2e.test.sh (modified by this change) cannot complete on this host and is not a product defect: treehouse 2.1.1 stores pool paths as /home/inthuson/... while firstmate records the physical /local/home/inthuson/... (because /home/inthuson is a symlink), sotreehouse returnrefuses with "is not managed by treehouse" and teardown aborts at bin/fm-teardown.sh:2453 - 77 lines before the new created-workspace retirement block, on the opted-out flat path that carries no created proof. I cannot fix this from the test phase (it needs host/treehouse path handling, not a repo change), so the required CI herdr lane owns verifying this file's meta-shape adjustment. The change's own behaviour is covered locally by the live retire guard and the fake-herdr teardown cases.bin/fm-test-run.sh tests/fm-teardown.test.sh- all cases green, including the six new created-workspace cleanup cases (foreign-pane leak, lone task pane, focus-move restore, failed-close restore, adopted refusal, registered-agent refusal)bin/fm-test-run.sh tests/fm-backend-herdr.test.sh tests/fm-control-relaunch.test.sh- green, covering the twelve adapter retirement gates and the relaunch created-proof carry/no-carry pairbin/fm-test-run.sh --fail-on-gate-skip 'herdr not found' tests/fm-backend-herdr-workspace-retire-e2e.test.sh- live guard against real herdr 0.8.0 protocol 19, reporting leak_live=1 live_close=1 and exact focus preserved in every samplebin/fm-test-run.sh tests/fm-test-run.test.sh- green, covering the new live guard's real-herdr-gated family registrationNegative control:git archive HEADinto an out-of-tree copy, restored baselinebin/fm-teardown.sh(03bb1d8) with the new tests kept, thenbash tests/fm-teardown.test.sh- fails atherdr-retire-foreign-pane: the workspace a foreign pane kept alive survived teardownManual live evidence harness/tmp/no-mistakes-evidence/01M0DCEPAT5QNVW8DYKFJPRMEW/live-workspace-leak-transcript.sh- drivesfm_backend_herdr_projection_close_pane_focus_preservingthenfm_backend_herdr_workspace_retire_createdagainst real herdr throughbin/fm-herdr-lab.shin a named non-default lab, printing the captain's workspace strip and focus before/leak/after for the foreign-pane, lone-pane, and adopted casesbin/fm-test-run.sh --fail-on-gate-skip 'herdr not found' tests/fm-backend-herdr-presentation-e2e.test.sh- fails on this host from a pre-existing treehouse path mismatch, isolated tobin/fm-teardown.sh:2453(before the new retirement block) by reading~/.treehouse/project-*/treehouse-state.jsonagainst the refused pathdocs/verification/runtime-backends.md:505- docs/verification/runtime-backends.md:505 records the dated 2026-08-05 whole-lane evidence asfamily=real-herdr-gated count=11 failed=0. This change adds tests/fm-backend-herdr-workspace-retire-e2e.test.sh to that family, so the lane now selects 13 scripts (it already selected 12 before this change, so the record was one short already). The line is explicitly scoped to that dated run against Herdr 0.7.4 and 0.8.0, so it is not a false current claim, and refreshing it needs a full live real-herdr lane re-run through the guarded lab, which is outside this documentation phase. Suggested follow-up: refresh that count the next time the whole lane is run.✅ **Push** - passed
✅ No issues found.