Repository navigation
Fix six follow-ups: xdist ids, decision table graphs, gate output, Studio replay identity, human-task races, platform user viewer scope - #57
Merged
Conversation
added 10 commits
October 19, 2026 21:25
Two parametrized tests built their ids from uuid4(), so each xdist worker collected different ids and 'pytest -n 4' aborted at collection. Use fixed ids instead.
weave workflow graph raised KeyError: 'decisionTable' on any workflow with a decision table step because the graph labels had no entry for that node kind. Label it, and pin that every compiled node kind has a label.
scripts/check.py printed only 'Checks failed; inspect private evidence.', and CI keeps no evidence, so a failing unit test could not be identified. On failure it now prints the stage name and the FAILED/ERROR node ids from pytest's short summary. The ' - message' part, tracebacks and captured output stay in the private stage log.
After a capacity refusal, Studio paused and sent the same keyed change again without rechecking who was signed in. If another person signed in during the pause, the host sent the replay as them. The replay now waits for any sign-in check still out, as the Workers and Runs bulk loops do, and is sent only when the person and workspace are unchanged; otherwise the refusal stands and nothing more is sent.
test_due_expiry_wins_concurrent_completion and test_completion_races_cancellation_under_run_lock failed with 429 WV-OPERATION-CAPACITY instead of 409 whenever one side held the project's operation lock longer than the other's 250 ms lock wait, which a cold or loaded database does. That depended on timing, not on which module ran first. A capacity refusal runs nothing, so the tests now send it again, as a client does, and assert the real outcome. A variant whose deadline tick holds the lock for 600 ms reproduces the 429 every time.
weave platform user granted viewer on the demo environment, but the catalog is a project resource and an environment grant never contains a project-level read (tenant > project > environment). A person created with operator or deployment_approver plus viewer could not see published workflows in Studio, although the guide says viewer reads the catalog. viewer is now granted on the demo project, as developer is.
The concurrent claim, concurrent completion and keyed run start tests race two changes in one project the same way, and the completion race failed with 429 WV-OPERATION-CAPACITY in a tasks-before-files run.
From the independent review: a canceled request no longer waits for a slow sign-in check before it stops, the gate reads node ids only up to pytest's closing summary line, and the browser test of the capacity replay leaves a slow runner more time inside the pause.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Six small, independent fixes. Each fix has a test that fails without it.
Stable parametrized test ids under pytest-xdist (F56)
tests/unit/operations/test_run_views.pyandtests/unit/test_ai_endpoints.pybuilt parametrized ids fromuuid4(), so each xdist worker collected different ids andpytest tests/unit -n 4stopped at collection ("Different tests were collected between gw0 and gw1"). Both now use fixed ids. A double--collect-onlydiff overtests/unit tests/contractsfinds no other nondeterministic id.pytest tests/unit tests/contracts -n 4now collects and runs: 7,761 passed.weave workflow graphdraws decision tables (F48)The graph labels had no entry for the
decisionTablenode kind, so text, Mermaid and SVG exports raisedKeyError: 'decisionTable'. Decision table steps are labeled Apply a decision table. The tests compile a workflow with a decision table and export it in all three formats. A second test checks that every node kind inIRNodehas a label.Failing stage and test ids when the gate fails (F60)
scripts/check.pyprinted onlyChecks failed; inspect private evidence., and CI keeps no evidence, so the failing test could not be identified. On failure it now printsStage <name> failed.and, from the stage log's last pytest short summary, theFAILED/ERRORnode ids. The- messagepart, tracebacks, captured output and lines printed before the summary are never shown. The output is capped at 50 lines of 300 characters, and ANSI color codes are removed. Stage logs stay in the private evidence directory. CONTRIBUTING.md describes the new output.Studio replays a capacity-refused change only for the same person (F57)
StudioApi.requestpaused forRetry-Afterand then sent a keyed change again without rechecking who was signed in. If another person signed in during the pause, the host sent the replay as that person. The shell now gives the API a replay guard: before sending a keyed change again, the API waits foridentitySettled()and comparesscopeKeyOf(shell)with its value at the first send. This is the same check the Workers and Runs bulk loops have used since #47. If the person or workspace changed, the original 429 stands and nothing more is sent. Reads are unchanged, so identity checks, which are reads, cannot wait on themselves.worker-operations.spec.ts): a bulk Drain whose first send gets 429 withRetry-After: 2, while John signs in during the pause. Without the fix, the replay went out as John.Human-task race tests and capacity refusals (F45)
Running
test_human_tasks.pybeforetest_human_files.pywas not what caused the failures. These tests race two changes in one project, and a change waits at most 250 ms (lock_timeout) for the project's operation lock. When the other side holds the lock longer, which happens on a cold or loaded database, the request gets429 WV-OPERATION-CAPACITYinstead of its real outcome. The failures came and went with the database's speed, in either order. Refusing in this case is correct product behavior: nothing ran. So the tests now send a capacity refusal again, as a client does, before checking the outcome. This applies to the expiry-versus-completion, completion-versus-cancellation, concurrent claim, concurrent completion and keyed run-start races. A new variant makes the deadline tick hold the lock for 600 ms, and it reproduced the 429 on every run before the fix.weave platform usergrants viewer on the demo project (F63)viewerwas granted on the demo environment. The catalog is a project resource, and under tenant ⊃ project ⊃ environment an environment grant never covers a project-level read. So a person created with, for example,--role operator --role vieweror--role deployment_approver --role viewercould not see published workflows, although the guides sayviewerreads the catalog.vieweris now granted on the demo project, asdeveloperalready is, and as the X1 fixture does. The CLI help, CLI reference, local-platform, people-and-access and roles guides are updated. Roles that never includecatalog.read, such asdeployment_approveralone, still get no catalog read. Adding one automatically would be an implicit grant, and that is left for a product decision.Checks
make check: all 17 stages passed. Unit and contract tests ran serially: 7,761 passed. Agentic worker 222 passed, files worker 42.pytest tests/unit tests/contracts -n 4: 7,761 passed.npm run check,format:check, vitest 2,393 passed. Playwright: shell, studio-bootstrap, operate-releases, deployment-operations, operate-overview, layout-fixes, operate-runs, run-actions and worker-operations, 260 passed.test_human_tasks.pyandtest_human_files.py(27 tests) passed in both orders, four runs in total. The container and its network were removed using the recorded IDs. No other suites ran against real services.Independent review
A fresh reviewer read the diff and found nothing Critical or Important; the verdict was ready. It reverted each fix and confirmed its test then fails, for F56, F48, F60, F63 and the F57 vitest cases. For the F57 Playwright test and F45 it reasoned from the code instead. Three Minor findings are fixed in d98f192:
Retry-After: 5).Two Minor findings remain open as follow-ups:
scopeKeyOfcompares the whole identity, so a refresh for the same person whose grants changed refuses the replay. This fails safe.