Repository navigation
#601 stage 5 (fix-forward): join_windows static count check misses output: sources #666
Description
Activity
- addedfeatureWork bigger than a fix: designed with Don, built in stages (harnest R11)Work bigger than a fix: designed with Don, built in stages (harnest R11)owner:leadFeature lead's turn (harnest R11)Feature lead's turn (harnest R11)stageA child issue: one stage of a featureA child issue: one stage of a feature
on Oct 7, 2026 - added a commit that references this issue
on Oct 7, 2026 - addedowner:testerTester's turn to actTester's turn to actstatus:fixed-pending-verifyImplementer fixed, awaiting tester verificationImplementer fixed, awaiting tester verificationand removedowner:leadFeature lead's turn (harnest R11)Feature lead's turn (harnest R11)
on Oct 7, 2026 Built by the lead agent, model
claude-opus-5-5viaanthropic.Shipped:
53225a9e(merge offeat/601-E-output-source-probe, fix commit on that branch). Deploy line:[deploy 08:10:12] deployed develop @ 53225a9e, healthy.Cause: none of the issue's hypotheses about
fetch_outputitself.dw/server/admission.pyadmit()makes the request workspace's assets the active library for every validate-time check (activate_asset_dir), but it left the output root at its default, which is the default workspace's outputs. The reference check passesroot=workspace.outputsexplicitly, sooutput:resolved there, butresolve_probe_path→fetch_outputused the default root, missed, and the probe returnedNone, so the check stayed silent. The tester'scc/…output lives in their session workspace.Fix:
admit()now also activatesworkspace.outputsas the output root (activate_output_root) for the same scope, which covers validate, submit and rerun. Because the fix is at the shared scope, it covers every probe that reads anoutput:source:window_count_errors,dissolve_frame_errors, slice preflight and the warnings.Plan items covered: plan v3, stage 3's static window-count check, "fires when
sourcenames a knowable file (asset:/output:…)". Theoutput:arm now fires. Acceptance is C-F233 step 2, as the stage says.Tests (
tests/test_admission.py, throughPOST /api/validatein a named non-default workspace whose outputs alone hold the source):join_windowswith anoutput:source and a 50-frame clip, 17/4: 3 windows refused atsteps[1]("needs 4 windows"), 4 clean, 5 refused.dissolve_videosoveroutput:members shorter thandissolve_framesis refused.- All three refusal cases fail without the fix and pass with it. Full pytest: the same 17 failures as
developbefore the change (Kandinsky-6 template catalog checks, local env), none new.ruffis clean.
Deviations: the fix sits in admission's scope, not in
resolve_probe_pathas the issue guessed. The resolver was correct; it was being called with the wrong ambient root. No MCP shape changed.Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(447f0a6e5f..53225a9e3f: dw/server/admission.py). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.Architecture review: pass. Reviewer agent, model
claude-opus-5-5viaanthropic.What I read:
bdb4ae53(the only #666 commit in447f0a6e..53225a9e; underdw//dw_mcp/it touches onlydw/server/admission.py), againstdocs/ARCHITECTURE.mdand item 3 ofstage-c-guardrails.md.- Second owner: none. The fix doesn't re-derive the output root. It calls the owner's own
dw/runs.pyactivate_output_root/deactivate_output_root, the same ContextVar pair thatdw/workflow.pyanddw/workflow_run.pyalready use.output:resolution and confinement stay indw/runs.py/dw/security.py(map row "Reference confinement"). - Build vs. buy: nothing hand-rolled.
- The map: no new owner and no rule moved. The "Admission" row (
dw/server/admission.py:admit, which checks a request once) still describes it, so no row update is needed. - Context: the reasoning is in the code comment in
admit(), next to the existing asset-dir rationale. NoCLAUDE.mdchanged.
Nothing was waived (the issue has no
arch-approvedlabel). It goes to the tester for C-F233 step 2.- Second owner: none. The fix doesn't re-derive the output root. It calls the owner's own
Verified. Tester agent, model
claude-opus-5-5viaanthropic, against lem on develop @ 7f524c4.Acceptance is C-F233 step 2. No suite case carries
pending: #666, so there were no pending lines to remove.Default workspace (session workspace):
run_workflow{"id":"cc", concat_videos(["asset:qa-cast/ep6-cold-open.mp4"]) → video/mp4 @24}ran as job06523207f2e4. It wrotecc/20261007-082336-1221c529/cc-cat.0-0.0.mp4(124 frames).validate_workflowon C-F229's RT (33/8, cosine) withsource_video: "output:cc/20261007-082336-1221c529/cc-cat.0-0.0.mp4":- 4 windows:
valid: false, error atsteps[1]: "join_windows needs 5 windows for a 124-frame source with num_frames 33 and overlap 8 (stride 25), got 4 - add 1 entry (index 4)". - 5 windows (exact):
valid: true, no errors,list_entries.windows: 5. - 6 windows (
w5repeating index 4):valid: falseatsteps[1]: "… got 6 - drop 1 entry (index 5)".
- 4 windows:
Non-default workspace (
qa-ep115, the case the fix targeted):- The same concat ran with
workspace: "qa-ep115"as jobe5d8a4888f19and wrotecc/20261007-082404-43c1a703/cc-cat.0-0.0.mp4. validate_workflow(workspace="qa-ep115")with thatoutput:source:- 4 windows: refused at
steps[1], naming 5 (same message as above). - 5 windows:
valid: true,plan.workspace: qa-ep115,output_dir …/qa-ep115/outputs.
- 4 windows: refused at
Nothing was queued by any validate. Both concat runs were removed with
delete_output(job_id=…).I did not exercise the
dissolve_videosoutput:arm the hand-off also mentions. The stage's acceptance is thejoin_windowscheck alone.Side note for the suite, not this fix: C-F229's RT as written has no top-level
id, andvalidate_workflowrefuses it with "'id' is a required property". I added"id": "rt"to run it. I'm filing that as a suite amendment on the harness repo.- addedstatus:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP calland removedstatus:fixed-pending-verifyImplementer fixed, awaiting tester verificationImplementer fixed, awaiting tester verification
on Oct 7, 2026
Fix-forward for #601, filed by the lead agent (
claude-opus-5-5viaanthropic) from the tester's failed final check of the parent. It concerns stage 3 (#630):join_windows' static window-count check. Plan v3 says the check fires whensourcenames a knowable file, "asset:/output:, or a literal path the run may read". Theoutput:arm doesn't fire. This is a build miss, not a plan gap.Acceptance
C-F233 step 2, which already exists, so this stage needs no new spec. A wrong window count with an
output:source must be refused atvalidate_workflow, at thejoinstep's path, naming the needed count.The failure, from the bounce (lem, develop @ b8aef18)
run_workflow{"id":"cc","steps":[{"name":"cat","task":{"command":"concat_videos","arguments":{"videos":["asset:qa-cast/ep6-cold-open.mp4"]}},"result":{"content_type":"video/mp4","fps":24}}]}. Job 1b73865a4a47 wrotecc/20261007-030343-8f1db730/cc-cat.0-0.0.mp4.validate_workflowon C-F229's RT (num_frames 33, overlap 8, cosine) withsource_video: "output:cc/20261007-030343-8f1db730/cc-cat.0-0.0.mp4"and 4 windows (w0–w3).valid: true, no errors, no warnings,plan.list_entries.windows: 4.steps[1]naming 5 windows, as the same RT gives withasset:qa-cast/ep6-cold-open.mp4.output:…/nope.mp4is refused atvariables.source_videowith "Output '…/nope.mp4' not found under …/outputs".run_workflowon the step 2 workflow (job 17b72f533155) ran all 4 windows on the GPU and then failed atjoin: "join_windows needs 5 windows for a 124-frame source with num_frames 33 and overlap 8 (stride 25), got 4 - add 1 entry (index 4)". The run-time rule works. The static check misses theoutput:source, which costs a full GPU run that validate should have stopped.Where to look (lead's reading, not verified)
dw/window_count_errors.py:96callsresolve_probe_path(arguments.get("source"), base_dir, …).dw/probe_paths.py:41-51resolvesoutput:throughfetch_output(value), with nobase_diror workspace, and any exception there returnsNone, so the check stays silent.fetch_outputresolves against a different outputs root at validate than the reference check does (the session workspace's), or it raises, or it returns a non-str. Then_frame_countgets nothing.dissolve_frame_errorssharesresolve_probe_path. If the cause is there, itsoutput:arm is likely silent too. Fix it at the shared resolver and test both.Tests
window_count_errorswith anoutput:source under a non-default workspace's outputs: short, exact and long lists.dissolve_frame_errorsif the fix is inresolve_probe_path.Deploy: server restart. Estimate: ~$2.