Add REST endpoints and frontend wiring for per-language project actions:
- POST /api/workspace/{project}/translation/{lang}/queue — queue translation
- POST /api/workspace/{project}/audio/{lang}/queue — queue audio generation
- GET/POST /api/workspace/{project}/format/{lang} — format metadata (EPUB/PDF)
- GET /api/workspace/{project}/review/{lang}/chapters/{chapter} — utterance review
- GET/POST /api/workspace/{project}/front-matter/{lang} — front matter editor
- GET /api/workspace/{project}/chapters/{lang} — chapter list
- GET /api/workspace/{project}/chapter-content/{lang}/{chapter} — chapter text
Frontend fixes:
- Review page shows per-language text (English source, Chinese translation, etc.)
- Non-translated languages show 'Queue translation' button only
- Speaker data from English source matched by paragraph ID
- UmbraAudio column layout: Speaker, Variation, Text, Actions
- Chapter tree in left sidebar: Front matter, Back matter, Body
- Audio Format label at top of sidebar
- Pandoc formatting toolbar for front matter text editing
3.5 KiB
Status — Umbra Tools UI and project-status backend
Updated: 2026-10-22 Plan: Docs/Plan_Umbra_Tools_UI.md Tasks: Docs/TaskList_Umbra_Tools_UI.md
What was wrong (from the review)
The first shell did not meet the requirement. All four failures were front-end:
- Login defaulted to Project, not Control Panel.
- Control Panel navigated away (workaround for the DENY framing policy), leaving the shell empty.
- The activity dropdown did not repaint the rail or the main panel.
- Projects showed language lanes but never the list of projects in scope.
Decisions (2026-10-22)
- D1 Control panel: refactor admin into an embeddable module (not framed).
- D2 Default: administrators → Control Panel; members → Project.
- D3 Projects: list projects in scope, click for detail.
- D4 Per-language rows: build a real project-status endpoint.
- D5 Format page: full §32 metadata matrix.
Done
- Plan written (Docs/Plan_Umbra_Tools_UI.md)
- Task list written (Docs/TaskList_Umbra_Tools_UI.md)
- F1 shell routing — rewritten
assets/umbra-app.js: - default control for admins, project for members - activity change repaints rail AND main reliably - hash routing (#control/<section>,#project/<id>,#edit,#audio) - Back/forward works (hashchange listener) - banner: logo + activity dropdown / project name / user + role + menu - F2 embeddable admin module —
assets/admin-view.js: -UmbraAdminView.mount(container, {section})renders dashboard, accounts, organizations, projects, audit inline - reads the real API (getSummary,listAccounts,listOrganizations,listProjects,listAudit), envelopedata.items- shell loads it; framing policy on the standalone page untouched - F3 projects list — main panel lists projects in scope from
/api/workspace, with the project-card styling and honest empty state - Both new JS files parse cleanly (pyjsparser) and are brace-balanced
- All files serve 200 and match the repo (restarted
umbratrans-web)
In progress / next
- B1 project-status endpoint —
GET /api/projects/{id}and/api/projects/{id}/status, backed by the production directory with a store seam; needed before F4 language rows show real progress. - F4 project detail language rows on real status data
- B2 + F5 edition metadata endpoints and the §32 matrix
- F6 Edit and Audio activities
Verified
SERVICE_VERSIONbumped 0.1.0 → 0.2.0;/api/healthreports 0.2.0.umbra-app.html,assets/umbra-app.js,assets/admin-view.js,assets/styles.cssall return 200 and match the repo.umbratrans-webrestarted; 24 auth tests pass.
Not yet verified (needs a signed-in browser session)
- The shell end-to-end with a real session. Static checks pass, but the authenticated rendering path has not been exercised live.
Side note
Translation of Deal Hunter zh-CN resumed: ch-20…ch-32 relaunched
(/tmp/translate_rest6.log). 19 chapters had translation.json before this run.
Root cause of the recurring stall fixed: pipeline.py analyse() raised
analyst returned list, expected object when the small analyst model answered
with a non-object. Analysis is guidance for the drafter, not a requirement for a
valid translation, so it now logs the degraded answer and continues with a
minimal analysis instead of aborting the chunk. Confirmed past the previous
crash point (ch-20-c010) and progressing. No manual cache-clearing should be
needed for this failure mode again.