Commit Graph
5 Commits
Author SHA1 Message Date
e99286813e fix(ci): preserve Maven suite results across cache write-back failures (#15274)
* fix(ci): scope the sdk-java test lock to the cache write-back (#15262)

The Managed Agent fast tier can fail without reporting a test result after waiting out the per-host SDK Java lock. #15128 scoped the MariaDB lane's lock to its cache write-back, but the test job still held the same lock across the SDK and Managed Agent Maven suites, so a long full-tier suite could starve the fast tier on that host.

Seed the test job's Maven repository from the host cache, run both suites unlocked from that job-local copy, and take the ticketed host lock only for the cache write-back. The write-back children close fd 9 so a cancelled job's survivor cannot retain the lock. Pin the new order and the write-back fd closures in the workflow tests, and update the fair-lock design docs and the workflow size baseline.

Fixes #15262

Co-authored-by: Qwen-Coder <[email protected]>

* fix(ci): keep sdk-java cache write-back best-effort (#15262)

* fix(ci): keep the sdk-java gate result across the cache write-back (#15262)

The write-back runs after the suite, so the step's exit code must come from
the suite: both lanes now track the Maven status, demote only a lock-wait
timeout with a step-summary record, and redden when the queue itself is
unusable. The wait drops to 1800 s because it guards only the bounded copy;
the seed stops hiding cp's diagnosis while staying quiet on a fresh host;
the design docs record the head-of-queue stall the shorter hold does not
bound.

* fix(ci): revert the sdk-java lock helper to the PR footprint (#15262)

The previous round changed .github/scripts/sdk-java-lock.sh, which this PR never touched; the deterministic gate rejects that expansion. Restore the helper and keep both call sites on the pre-round `if !` shape, retaining the 1800 s wait and the step-summary record. Drop the status-2 pins and tests that only existed for the reverted helper, and record the unusable-queue gap as a follow-up in the design docs. The timeout-returns test stays.

Co-authored-by: Qwen-Coder <[email protected]>

* fix(ci): de-alias every resolver tracking file and guard an unusable lock queue (#15262)

* fix(ci): de-alias Maven install metadata in the sdk-java seed (#15262)

Co-authored-by: Qwen-Coder <[email protected]>

* test(ci): restore the per-job Maven seed binding (#15262)

* fix(ci): keep sdk-java resolution metadata out of the host cache (#15262)

The seed drops maven-metadata-*.xml hardlinks, but the write-back still
published job-local metadata with cp -n, where the first publisher's copy
could never be refreshed. Exclude it at both write-back sites and pin the
seed and write-back name sets to each other.

Also witness each suite-status exit with an exit-1 case, restore the lock
test's combined-stream assertion, and bring the design docs' acceptance
criteria and fault arms up to date.

* test(ci): carry the deferred-status helper into the sdk-java slices

The tolerated-skip arms now call mvn_report_failed_suite, which the step
defines above the lock block. Every slice that starts at lock_setup_fault()
or at the write-back therefore ran bash -e without the definition and died
with 127, which read as a code failure rather than a missing prelude.

* docs(ci): clarify remaining sdk-java cache hardening scope

* fix(ci): bound failed MySQL cache waits and exclude resolver residue

Co-authored-by: Qwen-Coder <[email protected]>

* fix(ci): clear inherited resolver state in the Maven cache seed prune

The seed de-alias prunes carried -links +1, which restricted deletion to
the hardlinks cp -aln created in this job. RUNNER_TEMP survives across
jobs on the pool, so a previous job's mutable resolver state (nlink 1
*.lastUpdated, _remote.repositories, resolver-status.properties) survived
in the job-local repository and could redden an otherwise green Maven
lane. Drop -links +1 from all four seed prunes so inherited state is
cleared again; the write-back's -links 1 delta filter is unchanged and
the seed stays best-effort (2>/dev/null || true).

Move the deAlias test pin with the fix and add a regression witness that
plants single-link markers in the job-local repository before the seed
body runs and asserts they are gone (red with -links +1 restored, exit 1;
green with the fix, on macOS and Linux). Re-record the sdk-java.yml
.size-baseline entry (153970 bytes) and synchronize both design-doc
languages, including the nine-coordinate set the main merge brought in.

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Qwen Autofix <[email protected]>
Co-authored-by: qwen-code-dev-bot <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
Co-authored-by: yiliang114 <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
2026-11-07 08:51:30 +08:00
aaec411379 fix(web-shell): show actionable skill installation errors (#15013)
* fix(web-shell): show actionable skill installation errors

* test(cli): synchronize hosted monitor shutdown requests

* test(ci): seed Java lock queue fixture

---------

Co-authored-by: Ethan Ye <[email protected]>
Co-authored-by: claudeethan <[email protected]>
2026-10-22 17:36:15 +08:00
jinyeandQwen-Coder 605fd5ee17 feat(managed-agent): Add session lifecycle UI and reading exports (#15100)
* feat(managed-agent): Add session lifecycle UI and reading exports

Expose durable lifecycle actions and archive navigation in Managed Web Shell, with identity-scoped browser recovery and immutable HTML/Markdown reading exports.

Co-authored-by: Qwen-Coder <[email protected]>

* fix(managed-agent): Resolve lifecycle review and smoke regressions

Use the host React DOM server renderer, announce global errors once, and advance the OpenAPI version. Keep smoke selectors specific to session navigation and align the Workspace expectation with its existing Managed label.

Co-authored-by: Qwen-Coder <[email protected]>

* test(managed-agent): Preserve schema bindings in channel race fixture

Reuse the production schema-aware JDBC template so repeated H2 queries keep binary identity parameters. Preserve the existing ownership race and its assertions.

Co-authored-by: Qwen-Coder <[email protected]>

* fix(managed-agent): Correct lifecycle retry and export handling

Keep failed unadmitted archive intents idle until explicit retry, scope approval capability to each session profile, and preserve public export semantics and embedded downloads.

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: Qwen-Coder <[email protected]>
2026-10-22 16:37:26 +08:00
438bcb2a8f fix(ci): let the fast Java tier overtake waiting full-tier lock tickets (#15035)
* fix(ci): serve the fast Java tier before full-tier lock holds (#15032)

Co-authored-by: Qwen-Coder <[email protected]>

* fix(ci): keep a parked lock head's ticket alive under fast priority

A head blocked in `flock --wait` could not touch its ticket, so once a
hold outlasted the 1800s mtime arm another waiter reaped a live head and
the next ticket, whatever its class, parked in the kernel too. With two
classes that lets normal tickets take kernel positions ahead of fast
tickets that arrive later during a long hold. A keepalive now refreshes
the parked head's ticket at the waiters' two-second cadence; it closes
the lock fd and uses `touch -c`, so it can neither hold the lock nor
recreate a removed ticket.

The ordering and promotion cases used a stub whose `--wait` returned
every 200 ms, so they exercised a head that loops, which production never
does. They now park `--wait` until release and assert the reachable
paths: a fast ticket overtaking a normal ticket that is still waiting,
and a promoted waiting normal ticket preceding a later fast ticket.

The comments and design docs no longer claim a fast job waits at most
the hold already running (a parked head still goes first) or cite
#14962/#15032 as fast-behind-full evidence; they state what priority
removes and that a single hold longer than the budget is outside it.

---------

Co-authored-by: Qwen Autofix <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: wenshao <[email protected]>
2026-10-22 03:54:27 +00:00
976425cdb9 fix(ci): queue the sdk-java host lock first-come-first-serve (#14743) (#14912)
* fix(ci): queue the sdk-java host lock first-come-first-serve (#14743)

flock(2) does not order its wakeups, so under continuous arrivals one waiter can lose every release and die at the wait budget — repeatedly burning 40, then 60, then 90 minutes per starved lane across at least three hosts. Replace the inline flock --wait at all three acquisition sites with a ticketed queue: every acquirer takes the next sequence number atomically, only the head of line retries the lock, dead owners are reaped, and the lock still releases at the step boundary. The pinned infrastructure-signature error text is preserved.

The .size-baseline records the workflow's new size (smaller than main's, but main itself already exceeds its recorded baseline).

* fix(ci): block the queue head instead of polling the lock

The first live run starved its full 5400 s budget as queue ticket 1: the head polled flock --nonblock while main and older branches still run blocking flock --wait, so every release went to a legacy waiter's kernel wakeup. The head now blocks in five-second slices, re-entering the same wake race on even terms; tickets still order every run that uses this helper.

* fix(ci): serve the fast tier before full-tier holds

The queue bounded the wait by position but a fast-tier PR job still queued behind every full-tier hold ahead of it. Give the fast tier its own class: the head is the first sorted ticket and fast tickets sort first, so a PR job waits at most the hold already running. A normal ticket ages into the fast class after 20 minutes, so continuous PR traffic cannot starve the full tier.

* refactor(ci): keep the lock queue plain FIFO.

Drops the priority/aging classes: a single first-come-first-serve line is simpler to review and reason about. The head still blocks in five-second slices so it re-enters the kernel wake race on even terms with legacy waiters, and dead owners are still reaped. The tradeoff is explicit: a fast-tier job waits its turn behind full-tier holds instead of jumping them.

* fix(ci): stop leaking the host-lock ticket and reap stale orphans

Three bounded defects in the fair-lock helper, all confirmed by executing
it rather than by reading alone:

- The EXIT/TERM/INT traps quoted `${ticket}`, a `local` that is already out
  of scope once the sourcing step's shell exits, so every trap ran
  `rm -f ''` and each successful acquisition left its head ticket behind.
  Drop the traps and leave the queue at acquisition instead: a holder needs
  no place in line once the kernel holds the lock, and SIGKILL runs no trap.
- The ticket was published after `exec 8>&-` released the counter lock, so
  a later arrival could take seq+1, see an empty queue, name itself head and
  win the lock out of arrival order. Publish inside the critical section.
- Orphan liveness was decided solely by `kill -0`, so a ticket whose PID had
  been recycled to a live process was never aged out and, being head, made
  an idle lock unreachable for every job on the host. Age a ticket out on
  mtime alone above 1800s; a live waiter re-touches every ~7s.

Measured on a free lock with a live-PID, 2h-old orphan head ticket:
base burns its full 6023ms budget and exits 1 with the orphan intact;
this commit acquires in 19ms and reaps it.

Co-authored-by: Qwen-Coder <[email protected]>
Patrol-Run: qwen-pr-closeout/jmvhb9cysmc

* style(ci): keep only the load-bearing why in the lock helper comments

Co-authored-by: Qwen-Coder <[email protected]>
Patrol-Run: qwen-pr-closeout/jmvhb9cysmc

* fix(ci): keep the lock queue head in one blocking wait

The head re-entered the kernel wait queue every five seconds, so a release
reached waiters that stayed blocked first; the head could lose every
release and starve to its budget. Run 39472038337 still burned the full
5400 s as queue ticket 2. Wait once for the remaining budget and log the
remaining time at most once a minute.

A resumed release tag can predate the helper, so both acquisition sites
fall back to the bare lock instead of dying before Maven and wedging the
release. Pin the emitted ::error:: annotation prefix rather than a file
substring a comment can satisfy, and observe the real acquisition order in
the stub.

* fix(ci): name the blocking ticket in the sdk-java lock timeout

The timeout line reported only the dying waiter's own ticket, so a deep
queue and a wedged one produced the same message and neither could be
acted on from the log. Name the head of line, which separates a real
sibling hold from an orphan ticket.

Bring both design docs back to the shipped mechanism: two acquisition
sites, the flock'd counter with no aging path, the 1800 s mtime arm and
the ticket removed at acquisition, plus the operator recovery command.
Refresh the stale .size-baseline entry for sdk-java.yml.

* test(ci): wait for the first ticket instead of a fixed sleep

The FIFO case started the second acquirer 800 ms after the first and relied
on that being enough for A to take sequence 1. On a loaded runner it is not,
and B wins sequence 1, so the case fails on timing rather than behavior.
Poll for A's published ticket instead.

* fix(ci): print the lock wait line before blocking

The wait line was emitted only after `flock` returned, so a head parked
behind a sibling hold printed nothing for its whole budget: run
39528681869's step sat in flock for 40 minutes and was cancelled with an
empty log, which is the opposite of the attribution this change exists to
add. Probe with --nonblock, print the ticket line, then block.

The observability bullet in both design docs now states what the code does.

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
2026-10-21 12:21:44 +08:00