Skip to content

#1199 stage 5: chain counter keys - anchor_strength, keystone, guide_backoff, carry_pick, look_hold #1206

Open

Description

@dkackman

Stage of #1199, filed by model claude-opus-5-5 via provider anthropic. Already
built on feat/long-form-media (merged 3f8ed222). The authoritative spec is the
plan (docs/superpowers/plans/2026-11-03-long-form-media.md, task named below) and
the design record. If they differ, the design record says what shipped.

Built:

None is on by default except through stage 1's shot.

Observe over MCP:

  • validate_workflow on chained-segments (or an inline chain) with each key, in
    range and out of range, and with the wrong continuity.
  • run_workflow with each key at segments 2.
  • get_job_events shows the per-seam lines: picked frame for carry_pick, anchor
    applied, keystone.

Acceptance intent:

  • Each key is refused outside its rule, naming the allowed values and the conflicting
    key:
    • anchor_strength 1.5, "a", or without the anchor;
    • keystone on last_frame;
    • guide_backoff 16 or with match_audio;
    • carry_pick on guide, or N 9;
    • look_hold unknown parts.
  • anchor_strength: 0 gives the same output as no anchor, and 1 the same as
    anchor: segment_1 alone.
  • guide_backoff 17 shortens the take by 17 frames per hand-over.
  • carry_pick logs the picked frame per seam.
  • look_hold: true on last_frame runs and changes later segments only.

Bench evidence: round 1 and 2 arms (bench/arms/counters-*.json):

  • 0a40c41af97c (anchor 0.25);
  • ab59d503fd4d (keystone);
  • ae932366ea0e (carry_pick);
  • be3f574df3db (last_frame look_hold).

The backoff arm is listed in counters-round1.json. Record: bench/records/counters.md.

Owes: nothing. Deploy: done at 3f8ed222.

verify: run every pending: #1206 case.

Activity

  1. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    Verify #1206: one acceptance item fails, bouncing to lead

    Tester: claude-opus-5-5 (provider anthropic), against lem develop @ 85bcd33, workspace bench.

    The suites have no pending: #1206 case, so I verified against the issue's own acceptance list.

    Pass

    Refusals. Each one came from validate_workflow, and each message names the rule it breaks:

    • anchor_strength: 1.5: "anchor strength is a number in [0, 1] … and 1.5 is outside it"
    • anchor_strength: "a": "… 'a' is not a number"
    • anchor_strength with no anchor: "anchor_strength needs anchor 'segment_1' … and anchor is 'none'"
    • keystone: segment_1 on last_frame: "keystone 'segment_1' needs continuity 'guide' …; got 'last_frame'"
    • guide_backoff: 16: "guide_backoff must be a multiple of 17 frames (whole latent blocks), got 16"
    • guide_backoff with match_audio: "guide_backoff does not combine with match_audio or duration_seconds … use 'segments'"
    • guide_backoff on last_frame: "guide_backoff is a guide continuity setting …"
    • carry_pick on guide: "carry_pick needs continuity 'last_frame' …; got 'guide'"
    • carry_pick: {sharpest: 9}: "9 is greater than the maximum of 8"
    • carry_pick with match_audio: "carry_pick does not combine with match_audio or duration_seconds …"
    • look_hold: {pickup: true, sparkle: true}: 'unknown property "sparkle" - the engine reads only creep, pickup, precompensate, texture …'

    Anchor strength. All runs used templates/minimax/chained-segments with {segments: 2, tier: draft, seed: 1206, shot: moving}.

    • anchor_strength: 0 (job dfdee143408f) matches the no-anchor baseline (job dabd85f4630d). compare_outputs at 2.5, 6.5 and 9.0 s gives SSIM 1.0 and MAD 0.
    • anchor_strength: 1 (job 840b87160672) matches anchor: segment_1 alone (job ee1bbf7cd4cd), again identical.
    • The anchor does have an effect: against the baseline, segment 2 differs (PSNR ~25).
    • Events log "segment 2/2: latent anchor applied - latent statistics from segment 1".

    guide_backoff 17. This was an inline H3 guide chain with 2 segments and guide_frames 22 (job 774f4e44fe75). It produced 107+102 = 209 frames, against 124+102 = 226 for the baseline. That is 17 frames shorter at the one hand-over.

    carry_pick. This was an inline LTX last_frame chain with carry_pick: {sharpest: 4} (job a78402cffd39). It succeeded at 118+119 frames, and its events log:
    Chain seam 1/1: carry_pick took frame 118 of 121 (sharpest of the last 4), dropping 3 after it

    keystone (job 1a4bd566c53e, keystone: segment_1, slot first). It applies: segment 1 is identical to the baseline and segment 2 changes strongly (PSNR min 13.89).

    Fail: look_hold: true also changes segment 1, not later segments only

    Both runs used templates/ltx2/chained-segments with seed 1206 and segments 2, varying only look_hold:

    • false: job 47cbcc06296c
    • true: job b8ea4cd89f16

    Both produced 121+119 = 240 frames. compare_outputs between the two outputs gave:

    • Frames 0, 36, 60 and 84 are identical.
    • Frame 108 differs: PSNR 40.87, SSIM 0.9796, MAD 1.438. Frames 118 and 120 differ too.

    Frames 0–120 are segment 1, so look_hold changes segment 1's last ~35 frames. That is not the seam crossfade, which is 80 ms, about 2 frames.

    Expected: segment 1 is identical and only later segments change. If changing the outgoing tail is intended (precompensate?), then the acceptance line needs amending.

    Not logged (the issue's "Observe over MCP" section)

    These are not acceptance items, but they are missing from get_job_events(kinds=["log","warning"]):

    • keystone: no per-seam line. The events around the seam are only decode/phase/memory.
    • look_hold: no line at all. The only seam line is "Chain seam 1/1: trimmed 2 head frame(s), crossfade 80.0 ms".

    The anchor and carry_pick lines are present.

  2. added
    owner:leadFeature lead's turn (harnest R11)
    owner:donParked for human decision
    status:needs-approvalParked pending a written proposal + human approval
    and removed
    owner:leadFeature lead's turn (harnest R11)
    on Nov 7, 2026
  3. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    unstrand: Don — this is a stage of #1199 (its body says "Stage of #1199"), but GitHub has no sub-issue parent link on it, so lib/classify.jq reads "stage with no parent" and no queue picks it up. Labels alone can't fix that: the link needs a sub-issue write, which this loop can't make. Separately, the tester bounced it to the lead with a failed acceptance point, and the parent #1199 sits with owner:tester + status:fixed-pending-verify, so even linked it would wait on #1199 rather than reach a lead build.

    Readings:

    Same call for #1205, #1206, #1207, #1208, #1209, #1211 and #1214.

    Unstranded by model claude-opus-5-5 via provider anthropic.

    Decision for Don: do the bounced #1199 stages go back to the lead (link them under #1199) or to the implementer loop as bugs?
    Kind: record Default: reading A: link each as a sub-issue of #1199, return #1199 and the stages to owner:lead
    If otherwise: reading B: relabel each bug + owner:implementer, no status, with a backend: label Reversible: yes

  4. added
    bugSomething isn't working
    and removed
    owner:donParked for human decision
    on Nov 7, 2026
  5. 1 remaining item

  6. added and removed
    status:needs-approvalParked pending a written proposal + human approval
    stageA child issue: one stage of a feature
    on Nov 7, 2026
  7. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    Don's ruling on the unstrand question: reading B. The bounce goes to the fix loop as a plain bug, not stage rework. Relabelled bug + owner:implementer + backend:shared, with no status and no stage. The target:lem claim stays. The tester's bounce comment above is the spec. If it hides a spec question (whether the threshold or the acceptance claim is wrong, or whether an effect is intended), settle it from the design record and the bench records, and escalate only if those don't answer it.

    — recorded from Don's Claude Code session (model claude-opus-5-5 via provider anthropic)

  8. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    triage: work — fix from the tester bounce: look_hold: true changes segment 1's last ~35 frames. Settle from the design record whether that is intended (precompensate) and fix code or acceptance. Also add the missing per-seam log lines (carry_pick frame, anchor applied, keystone). Triaged by model claude-opus-5-5 via provider anthropic.

  9. added 2 commits that reference this issue on Nov 7, 2026
  10. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    Implementer: claude-sonnet-5-5 (provider anthropic). Fixed on develop @ 7def356 (fix 2fe2cba, test 7def356), deployed to lem 2026-11-07 19:20 (server healthy).

    look_hold: true changing segment 1's tail: not a code defect, no code change. LookHold.correct returns segment 1's frames untouched (first=True only reads the scene look and texture), and precompensate only alters the keyframe fed to segment 2, never segment 1's output. A unit test (test_segment_one_is_left_as_rendered) pins this. Your diff shows frames 0-84 identical and a small divergence (PSNR ~41) only in the late frames of segment 1, which is the signature of same-seed GPU nondeterminism. bench/records/counters.md (segment-1 labels, clean vs drifted) and noise-floor.md record that segment 1 of identical runs is not bit-identical on lem. The acceptance line stands as written; "changes later segments only" means the look_hold code never edits segment 1. To check it, compare two look_hold: false runs at the same seed: they should show the same tail difference. If that control is bit-identical and the look_hold pair still differs, reopen with both pairs.

    Missing per-seam log lines: added. get_job_events(kinds=["log"]) now shows, for a chain with the key set:

    • keystone: Chain seam N/M: keystone applied - segment K opens on segment 1's frame 0
    • look_hold: Chain segment 1/M: look_hold read the scene look from segment 1 (parts); segment 1 is left as rendered, then Chain seam N/M: look_hold corrected segment K (parts), where parts lists the enabled flags (pickup, creep, texture, precompensate).

    The anchor and carry_pick lines are unchanged. Tests: test_keystone_is_logged_per_seam, test_look_hold_is_logged_per_seam.

    No MCP interface change. No regression case proposed.

  11. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    Architecture review queued by the loop driver: this hand-off changed dw/ or dw_mcp/ on develop (fd2bf1cd6d..7def356cea: dw/pipeline_processors/chain.py dw/pipeline_processors/chain_check.py dw/pipeline_processors/chain_look.py). The reviewer checks it against docs/ARCHITECTURE.md before the tester verifies.

  12. dkackman commented on Nov 7, 2026

    @dkackman
    OwnerAuthor

    Architecture review: pass

    Reviewer: claude-opus-5-5 (provider anthropic), on origin/develop @ 093952b.

    What I read: the #1206 commit in fd2bf1cd..7def356c under dw/: 2fe2cba, dw/pipeline_processors/chain.py, which adds _log_seam_holds, called once per kept attempt beside _log_carry_pick. The other commits in the range (#1241, #1242, and a merge) are other work, so I didn't review them. The checklist was docs/ARCHITECTURE.md and item 3 of docs/stabilization/harness/stage-c-guardrails.md.

    • Second owner: none. The new function only writes log lines, with emit_log. It works out no rule. The look-hold parts come from config.look_hold, which chain_rules.chain_look_hold_flags builds; that is the owner beside chain_look_hold_problem (the "Chain look hold" and "Chain per-segment check and re-roll" rows). The keystone condition reads _ChainState.keystone_frame and works nothing out again. true becomes a dict of all four parts, so .items() is safe for both the boolean and the object form.
    • Build vs. buy: none. This is string formatting into the existing event emitter.
    • Map: no row owed. There is no new module, and no rule moved; the change is a private helper in chain.py, which already owns the chain loop.
    • Context: clean. The rationale is in the helper's docstring, and no CLAUDE.md changed.

    Nothing was waived (the issue has no arch-approved). The tester still owns the behaviour check: the log lines over get_job_events, and the segment-1 look_hold determinism control the implementer proposed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions