Repository navigation
feat(slm): Data hygiene page — list, preview and confirm cleanup of orphaned data; host #16927's unreachable-resource repair (#17038) #17040
Description
Activity
- added 7 commits that reference this issue
on Sep 20, 2026 Chunking triage — a proposal, not an assignment
- Proposed priority:
priority: medium— not applied. - triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639 criterion met: none of the five. Placed as scoped and small: one PR, no open question, not blocking.
- triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639 bucket: 2 — scoped and small (one PR, no open question, not blocking)
- Umbrella / container: no.
- Pre-filter: ⚠ a merged commit references this issue —
a248a04900 fix(slm): address review nits on the Data hygiene page. A reference is not a delivery: verify AC coverage before putting it in a chunk, and consider a closure pass first. - Basis: triage(v0.9.0): release criticality of the 123 open issues — 26 blocking, 36 small, 18 umbrellas, 41 misfiled, 2 undetermined #17639's per-issue row, reused rather than re-derived — "No code left. prior row cites criterion-level evidence on origin/main for all five ACs (routes, preview/cancel + per-row failure tests, 11 locales, admin guard + admin-only routers); close with that evidence"
Nothing was relabelled, moved or closed by this pass.
- Proposed priority:
Closure pass — 4 of 5 criteria met from merged code. Not closed, on one wording. Evidence at
origin/main7adaca8c29; landed viaa248a04900.AC1 — both sections listed from the real APIs, with a frontend test over the table and totals — MET.
autobot-slm-frontend/src/views/settings/admin/DataHygieneView.vue, tested atDataHygieneView.test.ts:138— "renders the storage and resources tables with their totals from the mocked APIs".AC2 — preview then confirm, nothing deletes without confirmation, with a cancel test — MET.
:154"cancelling the preview issues no POST /approval-gates request" — an assertion about the request never being made, which is the right shape: it fails if the component deletes eagerly, and it cannot pass by mocking the outcome.AC3 — a backend failure is shown per row, not hidden — MET, on both sections.
:171(a proposed candidate) and:202(a repaired resource), each asserting the failure lands "against that row only, not swallowed".:225additionally covers the success confirmation surviving the auto-refresh, which is the regression the obvious implementation of AC3 would introduce.AC5 — admin only in the route guard and on the backend — MET. Route:
autobot-slm-frontend/src/router/index.ts:305meta: { title: 'Data Hygiene', parent: 'settings', admin: true }. Backend: the endpoints it calls arerequire_roleadmin/superadmin (autobot-backend/api/admin_orphan_storage.py:11), and deletion is not exposed as a bare admin route at all — it goes through the approval chain, which the router's own comment at:300records: "cleanup via POST /approval-gates, never deletes directly".AC4 — half verified, and I am not ticking the other half
"All strings are i18n'd in 11 locales, and the page is in the admin navigation."
- Locale coverage: 11 of 11. Every locale file under
autobot-slm-frontend/src/locales/—ar, de, en, es, fa, fr, he, lv, pl, pt, ur— carries the page's keys. No locale is missing. - Admin navigation: present, via the route's
admin: truemeta under the settings parent. - "All strings", though, is a claim about absence — that no literal remains in the component — and the only thing that settles it is the repository's own hardcoded-UI-string guard, which I cannot run here (running repo code is reserved to hooks and CI under the current ruling). A green run of that guard over
DataHygieneView.vuecloses this criterion; my grep over locale files cannot, because a component can be fully keyed in 11 locales and still hold one literal.
Not closed on that single unverified half. Four criteria verified with tests that assert the right things.
- Locale coverage: 11 of 11. Every locale file under
v0.9-hostreview — this issue is not waiting on a host. Its remaining criterion is a CI run.Part of a review of all ten
v0.9-hostissues: for each, is host evidence genuinely the only thing missing, or is something else hiding behind "waiting for a deployment"?This one is in the wrong place. Its open criterion needs a run, not a deployed host — the distinction matters because the deployment call is an event nobody controls, while a CI run is available today. Parked here, it waits for the wrong thing.
Detail is in my earlier per-AC audit on this issue. The short form:
- bug(test): 3 multimodal performance/scalability tests fail — metadata Mock lacks __setitem__ since #15234 #16990 — AC1 is
pytest -m "slow or integration or distributed or performance"oversystem_benchmarks_performance_test.pywith the output pasted. A CI invocation. (AC2 and AC3 are already verified in code.) - feat(slm): Data hygiene page — list, preview and confirm cleanup of orphaned data; host #16927's unreachable-resource repair (#17038) #17040 — AC4's "all strings are i18n'd" is an absence claim, and the only thing that settles it is the repository's own hardcoded-UI-string guard. A guard run. (Locale coverage is already 11 of 11; the other four criteria are met.)
- ci(docker): an unreachable Ubuntu mirror surfaces as a misleading 'held broken packages' error; apt steps neither retry nor fail on index errors #16291 — AC4 wants a build log showing the retry or the explicit
apt-get updatefailure under a simulated unreachable mirror. That is a build with a manipulated network, not a deployment — harder than a plain CI job, and still not the deployment call. (The other three are verified in code.)
Recommendation: move these three out of
v0.9-host. They belong wherever a "needs a run" bucket lives, or back in their topic chunk with the criterion marked needs a CI run. Leaving them here means the deployment call arrives, nobody looks at them because they are not host work, and they stay parked for the next reason.- bug(test): 3 multimodal performance/scalability tests fail — metadata Mock lacks __setitem__ since #15234 #16990 — AC1 is
Verdict: the last AC is already satisfied by merged code — this was never host-blocked
The unticked AC is "All strings are i18n'd in 11 locales, and the page is in the admin navigation." Both halves are delivered on
main.In the admin navigation —
autobot-slm-frontend/src/views/SettingsView.vue:62:{ id: 'data-hygiene', name: t('dataHygiene.tabName'), path: '/settings/admin/data-hygiene', icon: ... }The comment at
:59-61records why that placement is load-bearing: it is "reachable through this same tab bar so the router's existing admin-route guard covers it automatically" — which is also what backs the already-ticked admin-only AC. Route:autobot-slm-frontend/src/router/index.ts:302-304(admin/data-hygiene→DataHygieneView.vue).:22-24notes this tab is the only entry in that array added through i18n; the siblings hardcode their names, a pre-existing gap explicitly scoped out.i18n in 11 locales —
dataHygienekeys are present and uniform across every shipped locale:ar=3 de=3 en=3 es=3 fa=3 fr=3 he=3 lv=3 pl=3 pt=3 ur=3The guards that hold this, and they do cover the SLM-frontend paths (checked by what each receives, not by its filename):
Guard Root it receives What it settles repo_tests/slm_frontend_i18n_parity_test.py:41_APP = Path("autobot-slm-frontend"),:42_LOCALES = _APP/src/locales:49_EXPECTED_LOCALESis exactly the 11;:129-130asserts each{locale}.jsonexists, failing with "the SLM console is back to fewer than 11 locales". DeclaresREACHat:77.repo_tests/slm_frontend_bare_ui_literals_test.py:83_SRC = Path("autobot-slm-frontend")/"src",:190/:203rglob("*.vue")Any bare visible string in any .vueunder that tree fails, across_VISIBLE_ATTRS(:86). DeclaresREACHat:215.Together they are a real enforcement pair for this page: a string left hardcoded in
DataHygieneView.vuetrips the literals guard, and a key added toen.jsonalone trips parity. Both are Python guards underrepo_tests/, so the pre-push hook runs them.With this, all five ACs are met. I am not ticking or closing — this issue hosts #17038/#16927's repair flow, so whether it closes now is the owner's call, not a measurement. Flagging it as closable on the evidence above.
All five criteria met — flagged closable, not closed, because the closure is an owner call. This issue hosts #17038/#16927's repair flow, so whether it closes is a scope decision rather than a measurement. Evidence for the last one (AC4, all strings are i18n'd): nav entry
autobot-slm-frontend/src/views/SettingsView.vue:62{ id: 'data-hygiene', name: t('dataHygiene.tabName'), … }, route atsrc/router/index.ts:302-304, anddataHygienekeys uniform across all 11 locales (3 each: ar de en es fa fr he lv pl pt ur).The absence claim is settled by two guards, both genuinely rooted in the SLM frontend — checked by what each receives, not by its filename:
repo_tests/slm_frontend_i18n_parity_test.py(:41_APP = Path("autobot-slm-frontend"),:49the 11 locales,:129-130asserts each{locale}.jsonexists, REACH at:77) andrepo_tests/slm_frontend_bare_ui_literals_test.py(:83_SRC = autobot-slm-frontend/src,:190/:203rglob("*.vue"), REACH at:215). They are a real pair for this page: a hardcoded string trips the literals guard, a key added toen.jsonalone trips parity. Both underrepo_tests/, so the pre-push hook runs them.This issue was never host-blocked — moved out of
v0.9-hosttoday.Closed — the last unticked criterion is delivered, verified at
2a6c281760Four of five were already ticked. The fifth — "All strings are i18n'd in 11 locales, and
the page is in the admin navigation" — has both halves:i18n: 11 of 11. Every
autobot-slm-frontend/src/locales/*.jsoncarriesdataHygiene
keys; counted across the whole locale set, not sampled.Navigation: a real entry, not merely a route. I checked these separately because a
registered route is not a navigation item, and the criterion asks for the second:src/router/index.ts:302-304— the routeadmin/data-hygiene→
settings-admin-data-hygiene→DataHygieneView.vue.src/views/SettingsView.vue:62— the nav entry itself:
{ id: 'data-hygiene', name: t('dataHygiene.tabName'), path: '/settings/admin/data-hygiene', icon: … }.
Had only the route existed, the page would be reachable by URL and invisible in the UI —
which is the half the criterion is actually about, and the half a route grep would have
scored as satisfied.No remainder. The other four cover the page listing both sections from the real APIs
with a mocked-API frontend test, preview-then-confirm with a cancel test, and per-row
backend failures shown rather than hidden.
Owner rules (2026-09-18), binding on this feature and on any data or credential cleanup
Mechanism: consolidate, don't fork. AutoBot already has approval gates:
services/approval_gate_service.py,api/approval_gates.py, and the frontendllc/ApprovalsInbox.vue. A cleanup proposal becomes an approval-gate request, and approving it triggers the owning service's removal. The Approvals inbox and the SLM Data hygiene page both show pending cleanup requests. The approval record plus an audit entry are the paper trail. No second approval system.What
An SLM Data hygiene page, in the admin or maintenance area:
/api/admin/orphanscandidates (facts and secrets with no live owner) and uses its existing repair flow. It is linked, not re-implemented.Acceptance criteria