# Slice 6 — ssh_tasks content tabs: Files + Actions (worker output) ## Files changed | File | Status | Lines | |------|--------|-------| | `frontend/src/pages/service-tabs/FilesTab.tsx` | new | 528 | | `frontend/src/pages/service-tabs/ActionsTab.tsx` | new | 308 | | `frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx` | new | 63 | | `frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx` | new | 49 | | `frontend/src/pages/service-tabs/index.ts` | modified | +4/-4 (import real FilesTab/ActionsTab) | | `frontend/src/pages/service-tabs/stubs.tsx` | modified | -8 (removed FilesTab/ActionsTab stubs) | | `frontend/src/pages/service-tabs/MediaTab.tsx` | modified | +10/-1 (row-click nav fix) | | `frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx` | modified | +4 (mock useServiceInstances) | **Total: ~967 lines** (948 new + 27 modified diff). Over the 400-line budget; dominated by the verbatim lift of the FileBrowser content (~528 lines) and Actions content (~308 lines). The genuine new-logic delta is ~30 lines (instance wiring + row-click fix + tests). ## How instance.id is wired into hooks **FilesTab**: `instance.id` replaces the old `machine_id` from search params. All hooks (`useDirectoryListing`, `useFfprobe`, `useRunJob`) receive `instance.id` directly as the machineId parameter. The machine-tab selector (`TabbedCard` + `useMonitoringSettings`), the machine_id search-param logic, and the "no file machines" fallback are all removed. The initial path is read from `?path=` search param for deep-link support. **ActionsTab**: `instance.id` is used as the fixed `runServiceId` — the old `useServiceInstances("ssh_tasks")` call and the service selector dropdown are removed. Tasks run on this instance by default. The task editor dialog no longer has a "Default SSH task service" dropdown (the instance is implicit). The `services` prop on `TaskEditor`/`TaskDialog` is removed entirely since the instance is fixed. ## MediaTab row-click resolution (cross-slice fix from slice 5) The old row-click navigated to `/files?path=...` (legacy route, now 404s). Fixed: ```tsx const { data: sshServices = [] } = useServiceInstances("ssh_tasks"); const handleRowClick = (row: MediaItem) => { const sshInstance = sshServices.find((s) => s.enabled); const base = sshInstance ? `/services/ssh_tasks/${sshInstance.id}` : "/services/ssh_tasks"; navigate(`${base}?path=${encodeURIComponent(row.path)}`); }; ``` If an enabled ssh_tasks instance exists, the link opens its service page with the path query param (FilesTab reads `?path=`). If none exists, the link goes to `/services/ssh_tasks` (ServiceTypePage empty state / resolver). ## Validation ``` npm run lint → 0 errors, 2 pre-existing warnings (UsersPage.impl.tsx, unrelated) npm run build → ✓ built (tsc -b + vite) npm run test → 29 files / 94 tests passed (was 90; +4 new) ``` ## Deviations from design 1. **Over 400-line budget.** The FilesTab lift is ~528 lines because it includes all the ffprobe rendering helpers + component logic verbatim from FileBrowser.impl.tsx. ActionsTab is ~308 lines. Could not shrink without dropping features. The task explicitly acknowledged this: "FileBrowser.impl.tsx is large; the lift is mostly mechanical." 2. **ActionsTab simplified: no service-selector dropdown.** The old Actions page had a "Default SSH task service" dropdown in both the editor and the run pane, using `useServiceInstances("ssh_tasks")`. Since the tab is already on a specific instance, the run service is always `instance.id`. The dropdown and the `services` prop on TaskEditor/TaskDialog are removed. The `NONE` sentinel constant is also removed. 3. **No mobile layout.** This branch is based on main, NOT on mobile-responsive-parity. FilesTab lifts main's DataTable + column-visibility pattern (no MobileCardRow). 4. **Old page files kept.** FileBrowser.impl.tsx and Actions.tsx stay in the repo (cleanup is Slice 11). Their test files still pass since they render the page components directly. ## skill_resolution `none` — no project/user SKILL.md paths were injected; no `.atl/skill-registry.md` found. ## Residual risks - **FilesTab and ActionsTab duplicate code** from their old top-level pages. The duplicates are temporary (Slice 11 deletes the old pages). - **ActionsTab removed the service-selector dropdown.** If users need to run a task on a DIFFERENT ssh_tasks instance (not the current one), they'd need to switch instances via the service page's instance switcher. This is consistent with the new IA (each instance has its own page). - **MediaTab now depends on `useServiceInstances("ssh_tasks")`.** This adds a TanStack Query call but it's cache-shared with other ssh_tasks queries. ```acceptance-report { "criteriaSatisfied": [ { "id": "criterion-1", "status": "satisfied", "evidence": "Slice 6 implements FilesTab (lift from FileBrowser.impl.tsx, instance-scoped hooks, ?path= deep-link), ActionsTab (lift from Actions.tsx, instance as default run service), resolves the MediaTab row-click cross-slice dependency (navigate to /services/ssh_tasks/?path=...), and adds tests for both tabs. No scope widening: only service-tab files + MediaTab row-click + test mock touched. Old page files preserved for Slice 11. 94 tests pass; lint/build green." } ], "changedFiles": [ "frontend/src/pages/service-tabs/FilesTab.tsx", "frontend/src/pages/service-tabs/ActionsTab.tsx", "frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx", "frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx", "frontend/src/pages/service-tabs/index.ts", "frontend/src/pages/service-tabs/stubs.tsx", "frontend/src/pages/service-tabs/MediaTab.tsx", "frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx" ], "testsAddedOrUpdated": [ "frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx", "frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx", "frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx" ], "commandsRun": [ { "command": "cd frontend && npm run lint", "result": "passed", "summary": "0 errors, 2 pre-existing warnings" }, { "command": "cd frontend && npm run build", "result": "passed", "summary": "tsc -b + vite build clean" }, { "command": "cd frontend && npm run test", "result": "passed", "summary": "29 files / 94 tests passed (was 90; +4 new)" } ], "validationOutput": [ "FilesTab: instance.id wired into useDirectoryListing/useFfprobe/useRunJob; ?path= read from useSearchParams; machine selector removed.", "ActionsTab: instance.id used as fixed runServiceId; service-selector dropdown removed; TaskEditor/TaskDialog simplified.", "MediaTab row-click: navigates to /services/ssh_tasks/?path=... (resolves slice 5 cross-slice flag).", "stubs.tsx: FilesTab/ActionsTab stubs removed; index.ts imports real components.", "MediaTab.test.tsx: useServiceInstances mock added to fix QueryClient error." ], "residualRisks": [ "FilesTab/ActionsTab duplicate code from old pages (temporary; Slice 11 deletes old files).", "ActionsTab no longer has a service-selector dropdown (run is always on current instance; switch via instance switcher).", "No mobile layout (branch is on main, not mobile-responsive-parity)." ], "noStagedFiles": true, "diffSummary": "~967 lines: FilesTab.tsx (528, verbatim lift from FileBrowser.impl.tsx with instance wiring + ?path= deep-link), ActionsTab.tsx (308, lift from Actions.tsx with instance as fixed run service), 4 test files (112 lines), index.ts/stubs.tsx wiring (12 lines), MediaTab.tsx row-click fix (10 lines). Over 400-line budget due to mechanical lift of two large pages.", "reviewFindings": [ "no blockers" ], "manualNotes": "git status confirms nothing is staged; all changes are unstaged/untracked. The old FileBrowser.impl.tsx and Actions.tsx are kept (Slice 11 deletes them). Their existing tests still pass." } ```