act names a job's container from the workflow and job names alone (createContainerName("act", "<workflow>/<job>"), act v0.2.89), and removes any existing container of that name before creating its own. So when two embedded-act jobs with the same workflow and job names run at once, the second deletes the first's container mid-run, and the first job dies with exit code 137 ("RWLayer of container ... is unexpectedly nil"). That needs only two repositories with a `Release` workflow and a `release` job pushing tags around the same time, or two pushes of one workflow. Seen in production: armada-stack's v0.4.1 release was killed four seconds after npanel's v0.3.0 release started. Both used act-Release-release-3b54765c..., which is sha256("act-Release-release"), and npanel's container was then left behind. The names can't be made unique from outside act without changing what jobs see (the workflow name is also `github.workflow`), so the runner now claims the names a workflow's jobs will use before starting act, and a job whose names are held waits, holding its slot, until the job holding them has finished. Names that can't be known in advance (job names with expressions, matrix `-<n>` suffixes, reusable workflows) are claimed as a prefix covering all they could become; an unreadable workflow claims everything. Claims are compared with act's sanitising (non-alphanumerics to `-`) applied, so names act would treat as one, like `Release-x`/`y` and `Release`/`x-y`, conflict too. Only the embedded-act runner shares one daemon between jobs, so the socket-adapter backend is unchanged.
↑