Qwen3-TTS as modified on the audio node, kept. Quality over time is the principle that
settles it, and the engine already in use is the one worth keeping.
The modifications are on the audio node and unknown here, so the speak work function
cannot be written blind. Listed what is needed: what changed and why, whether it is a fork
or a carryable patch, the input contract, and whether it loads a model and how large -
which decides whether node 238 can run it at all.
Parallel synthesis is a requirement, not an optimisation. The mechanism exists already
(submit_children and the decompose route), which means the work-function protocol has to
be designed for decomposition rather than have parallelism retrofitted into it.
`claim_job` took an `organization_id` and matched it against the job's. Read plainly
that says: a machine may only do work for the tenant that owns it. Both paired nodes
belong to BDMurphy and The Last Dwarf belongs to WorstAuthor, so a node could never do a
word of the audio node's work however idle it was. The only way to have found that out
was to queue the job and watch it sit there.
`place()` had the same fault - it listed candidate nodes by organization - so the
scheduler could not use the fleet across tenants either. Both are fixed.
A node is a machine. It belongs to whoever administers it, not to a tenant, and a
tenant's data reaches it inside one job's payload for the duration of that job, never by
widening what the node itself can see. `kind` and the placement requirements decide what
a node may do; ownership decides who may switch it off. What did not change: a node still
returns one job's payload and nothing else, so it still cannot enumerate another tenant's
work.
test_node_tenancy.py asserts the behaviour, and was confirmed to detect the old one: five
of its seven tests fail when the tenant filter is restored.
Also adds docs/plan-translation-pipeline.md, which separates the critical path - the
work-function protocol, TTS, assembly, lineage, and one finished episode of The Last
Dwarf - from the work that can proceed beside it.
Writing those tests cost more time than it should have and the reason is worth recording:
four of them failed for reasons that had nothing to do with tenancy. A job left behind by
one test is claimed by the next, which reads as the rule breaking. `TRUNCATE ... CASCADE`
on a table shared with other fixtures destroyed `project_publishers` and surfaced two
files away as "relation does not exist". The queue is now left alone and the claims filter
on a job kind only this file creates, so a neighbour's leftovers cannot be returned and
the assertions can be exact.
547 passed, 29 skipped.