mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
* feat(verify-pr): add a watch mode backed by the PR probe gate A maintainer round ends with the report; noticing the next push and starting the next round is manual. The two halves of an automatic trigger already ship (the PR probe that prints only transitions, and a scheduled task whose gate runs a shell command outside the model), but nothing connects them, so each maintainer rebuilds the same cron and re-learns its failure modes. --watch composes them: a recurring gated task whose gate is `autofix-pr snapshot <n> --gate`, so a fire costs one shell command and the round runs only when the head actually moves. The contract adds the guardrails the pieces do not enforce for each other — an absolute CLI path that carries the probe, gh auth before scheduling, a state file written before the round so a dead round does not replay the same head, and cron_delete on stop. * fix(verify-pr): filter gate events and refuse a shared probe cursor Two review findings on the watch mode, both composition defects rather than wording. The gate's output is what starts a turn: the scheduler hands any non-empty output to the model, so a probe line for a new comment or a failed check (`action: "fix"`) woke the watch while the head stood still — the prompt cannot un-start a turn that already began. scripts/verify-pr-watch-gate.mjs now wraps the probe and forwards only `resync` and `stop`; unparseable output is forwarded rather than swallowed, and a failing probe still surfaces as a gate failure. The probe keeps one cursor per PR, so a second `snapshot --gate` watcher on the same PR takes the head moves and `stop` the first one needs, and a prepared `autofix-pr` watch suppresses heads through `knownHeads`. Verification-owned state would need a probe flag that does not exist, so the wrapper's `--check` refuses to install when the PR's gate cursor or prepared state already exists, and the skill says coexistence is unsupported instead of letting two watchers starve each other. * fix(verify-pr): run the watch gate on encoded paths and reserve the PR atomically Two review findings on the wrapper. The entry-point check compared `import.meta.url` against `file://` + a raw path. `import.meta.url` is percent-encoded, so a checkout containing a space or non-ASCII characters never ran `main()` — the gate exited 0 with empty output, which the scheduler reads as a quiet tick, for head moves, stops and probe errors alike. Both sides are now resolved through `realpath`, which also covers a symlinked checkout because Node resolves the entry module's symlinks while `argv[1]` keeps the shell's path. The setup check only read files. Two sessions sharing a clone could both pass it before either probe created its cursor, and both install a watch on one cursor. Setup now takes an atomic claim (`wx`) on `.qwen/tmp/verify-pr-watch-<n>.owner.json`; a read-only check reports an existing claim too, and a claim is never taken over from a timestamp — deciding staleness that way is the same race — so a dead setup's claim is released with `--release`, which the skill also runs when the task stops or creation fails.