mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
main
1281
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6c8d1e0f70 |
test(managed-agent): pin the queue_one reachability (FG11d) (#15187)
* test(managed-agent): pin the queue_one reachability (FG11d) The design record claims the queued-input arm is reachable under queue_one; this cell is the witness. A second manual fire is admitted at one active run, its run commits, and no prompt for its occurrence ever appears. The cancel half stays open: measured here, a task cancel on that queued run is accepted and the run stays running, because the queue is settled by the turn. * test(managed-agent): align the queue_one assertions and mark the cancel half ungated (FG11d) The active-run half of the reachability cell excluded one settled state fewer than the queued half, so a run that had failed would still read as untouched. Both halves now exclude the same three settled states. The design record called the un-gated cancel half "(measured)", which reads as if a witness exists in the tree. It now says "measured locally, not gated", the same claim the PR body makes. * test(managed-agent): observe the queue_one dwell and scope the record to what it proves (FG11d) The negative rested on a single `isEmpty()` sampled one poll after the run row committed, so an asynchronous dispatch of the queued input would land after the assertion had already returned green. It now runs as a bounded dwell through `waiting()`, keeping the failFast and lock-exception guard. Both records cited the cell as pinning that no prompt appears, which attributes the absence to the overlap arm. The first turn is parked, so the wake pump cannot start the queued input under any policy; the records now say the cell pins admission (its own run id and a `fired` occurrence) and only observes the absence over a dwell. |
||
|
|
480b4d341a |
feat(managed-agent): read the Harness credentials from one file (#15063)
* feat(managed-agent): read the Harness credentials from one file The Hosted Harness and the control plane share a bearer token and a capability digest, which the reference distribution stored twice, in harness.env and server.env, so every rotation or hand edit had to change both files identically. QWEN_MANAGED_AGENT_HARNESS_CREDENTIALS_FILE now names the Harness's own environment file. The control plane reads QWEN_SERVER_TOKEN and QWEN_HOSTED_HARNESS_CAPABILITY_DIGEST from it into its configuration, never into its process environment, and refuses to start when the file is combined with a direct token or digest, or lacks either key. Preflight reports the file's permissions and points credential fixes at it. The bootstrap, templates, systemd instructions and guide store the credentials once. * fix(managed-agent): refuse credential lines the Harness reads differently The credentials parser accepted a subset of the environment-file grammar and silently mis-read the rest. A continuation, an escape, an unterminated quote, text after a closing quote or a `$` expansion gave the control plane a different value than systemd or a shell gave the Harness, while preflight passed. Such lines now fail startup, naming the file and line but never the content. The file is now read once and only while the Harness is enabled, and an unreadable file reports its exception type in the validation row. Preflight shares one secret-file permission policy between the config and credentials rows. The credentials row also fails an unreadable file and reports an unusable path instead of aborting, and the harness row fails the shipped placeholder token. Tests now pin the run order, values containing `=`, world-readable files, the file-aware 401 fix and the shipped harness.env.example keys. The systemd READMEs describe the warning as a warning. * fix(managed-agent): accept only credential lines both readers take literally Credential values in the Harness credentials file may now contain only letters, digits and ._:/+=-, and whitespace around `=` or a carriage return is refused: a shell runs `KEY = value` as a command and keeps a trailing \r, so the control plane and the Harness could hold different digests while every preflight row passed. When startup refuses the file, the harness row now skips its probe instead of sending whatever credentials are left bound, and the file is applied atomically. run() delegates to checks(args) so a test can pin the credentials row after the harness row. |
||
|
|
cfd95f6abb |
fix(ci): scope the sdk-java host lock to the cache write-back (#15128)
* fix(ci): scope the sdk-java host lock to the cache write-back (#15117) Run 39627609266's fast-tier job arrived at 17:38, stayed head of the sdk-java host-lock queue, and failed at 19:15 without starting Maven. The MariaDB integration lane held the same lock across its install and full MySQL clean verify; under pool contention that hold ran from 15:54 to 18:57 (run 39628985638), past the fast tier's 90-minute budget. Both MariaDB Maven runs already resolve from a job-local repository, so they touch no host-shared state. Seed that repository before the lock, run both Maven commands unlocked, and take the host lock only for the cache write-back, the sole remaining host-shared mutation. Drop fd 9 on the write-back children so a cancelled job's survivor cannot retain the lock. Raise the lane ceiling to 300 minutes for the ~3-hour verify plus one lock wait and setup, and pin the new order and fd closes. Fixes #15117 * test(ci): exempt the OpenTUI parity suites from the no-AK gate (#15117) The main merge brought three interactive suites from #14964. The no-AK gate requires every runnable integration test to be selected or explicitly exempted, so the Test job fails until they are listed. Co-authored-by: Qwen-Coder <[email protected]> --------- Co-authored-by: Qwen Autofix <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: jinjing.zzj <[email protected]> Co-authored-by: 易良 <[email protected]> |
||
|
|
06e59666df |
fix(ci): skip the duplicate prepare build in the daemon E2E lane (#14884)
* fix(ci): skip the duplicate prepare build in the daemon E2E lane (#14870) Co-authored-by: Qwen-Coder <[email protected]> * test(ci): pin the daemon E2E prepare-skip premises (Refs #14870) * test(ci): keep the daemon E2E step commands pinned (Refs #14870) * test(ci): pin the daemon E2E step and its install warning (#14870) --------- Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: Qwen Autofix <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> |
||
|
|
288e4c481d |
perf(ci): Optimize MySQL integration verification (#15200)
Close Spring contexts before fixture database cleanup, run integration classes in isolated reusable forks, and remove redundant fixture validation and duplicate load-test execution. Document bounded local validation and preserve full CI gates. Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
0b3c2f816a |
feat(ci): restore a MariaDB leg for the non-Hosted IT family (#15003)
* fix(ci): align Java integration database and lock lifetime * test(ci): re-pin the sdk-java lock and MySQL probe after the single-step merge The merge commit staged the conflict resolution before these two re-pins were written, so they land as a follow-up in the same push: - `keeps the host lock out of every Maven child` counted three lock-bearing steps; #14903 collapsed the MariaDB lane's two Maven steps into one, so the count is now two (test job + mysql-integration). - The MySQL startup probe took the step's first `mvn` line, which is now the `-DskipTests install` staging command; select the `-Pmysql-integration` command instead so the probe still exercises the consumer. Verified: vitest sdk-java-workflow.test.js 96 passed; prettier --check clean. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmvgz448zlp * fix(ci): skip the MySQL binlog, drop the unused database, correct the reaper bound Three independent corrections to the mysql-integration lane this PR reworks. 1. MySQL 8 enables the binary log by default (MariaDB 10.11 did not in the configuration this lane replaced), and the datadir is an uncapped tmpfs. Nothing in packages/managed-agent-server/src or packages/sdk-java reads a binlog (0 hits for binlog|log_bin|GTID|SHOW MASTER STATUS), and the container is disposable with no replica, so `--skip-log-bin` is appended after the image name beside --innodb-use-native-aio=0. Without it the ~67 MiB hex-encoded LONGBLOB query this lane already raises max_allowed_packet for is serialized a second time into host RAM. 2. `--env MYSQL_DATABASE='runtime_broker_test'` had no consumer: the lane's only connection is -Dmysql.url=.../managed_agent_test?createDatabaseIfNotExist=true. The declaration invited a cleanup that drops createDatabaseIfNotExist and dies at first connect with Unknown database. Dropping it lets the JDBC URL own the schema and shrinks the diff. 3. The cleanup comment and removal-failure warning said the host reaper reclaims a stranded container "after a 24h age gate" / "up to a day". The real bound is ~48h: qwen-docker-cleanup.sh:31 gates on a strict `now - created_at > 86400` (exactly 24h is SKIPPED) and qwen-docker-cleanup.timer fires once a day, so a container created just after a fire is skipped at the next one and reaped at the one after. Test pins updated in the same change: the start-step assertion, the exact docker-run trace literal, and the cleanup warning literal. All three were mutant-verified red (drop --skip-log-bin / re-add MYSQL_DATABASE / restore "after 24h") and restored byte-identical. Only this PR's own copy of the reaper wording is corrected; the two pre-existing copies (sdk-java.yml's event-transport-multi-node job and release-managed-agent-reference.yml) are untouched to keep this diff scoped. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmvhb9cysmc * feat(ci): restore a MariaDB leg for the non-Hosted IT family #14936 moved the mysql-integration lane onto MySQL 8.4 and removed the last real MariaDB server, leaving the published MariaDB-only V12 repair (RTRIM, error 1901) and the schema catalog's MariaDB branches without a falsifier. Both engines now run the same non-Hosted *IT family as two matrix legs of one job: the container image, its startup arguments, its client, and its readiness signal come from the leg, and the container name carries the engine so two legs on one pool host cannot collide. --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
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]> |
||
|
|
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]> |
||
|
|
ec82cac361 |
test(managed-agent): keep a sibling run alive past a cancel (FG11d) (#14999)
* test(managed-agent): keep a settled run's outcome (FG11d)
* test(managed-agent): reuse a same-key cancel (FG11d)
* test(managed-agent): refuse a second fire while the turn runs (FG11d)
* revert: move the second-fire cell onto its own branch
The cell belongs to the next PR in the chain, which bases on this branch, so
it cannot also live here: the next PR's diff would be empty. Content of this
branch is unchanged from
|
||
|
|
240eecf617 |
feat(web-shell): allow hosts to inject disabled catalog models (#15015)
* feat(web-shell): allow hosts to inject disabled catalog models Hosts can show product models that are not currently usable in the composer picker, with a framework-neutral hover slot for text or authorize actions. Co-authored-by: Cursor <[email protected]> * docs(web-shell): add unavailable-model picker screenshots Co-authored-by: Cursor <[email protected]> * fix(web-shell): polish unavailable-model tooltip card Co-authored-by: Cursor <[email protected]> * fix(web-shell): make unavailable models look disabled Co-authored-by: Cursor <[email protected]> * fix(ci): isolate script fixtures and reuse runtime archives * test(cli): bound command budget fixture work and drain timed-out writes --------- Co-authored-by: Ethan Ye <[email protected]> Co-authored-by: Cursor <[email protected]> |
||
|
|
54a56f30ce |
fix(ci): write back only the MariaDB lane's Maven delta and size its ceiling (#15000) (#15064)
* fix(ci): bound the MariaDB lane's cache write-back and size its ceiling (#15000) Run 39563394993's mysql-integration job was cancelled at the 200-minute ceiling: 54 minutes queued for the host lock, 75 minutes of Maven work, then a 60-minute unbounded tar of the host-shared ~/.m2. The cache is an optimization, so skip it after five minutes; the ceiling now covers the 90-minute wait, the measured Maven pass, the bounded write-back and setup headroom. * fix(ci): write back only the MariaDB lane's Maven delta by hardlink The bounded tar pipeline extracted straight into the host-shared ~/.m2, so a timeout mid-member left a truncated artifact that --skip-old-files never repaired and the next seed hardlinked into its job. Its 300 s cap was also below the measured 26-61 minute whole-tree cost, so it would have tripped on every run. Publish only the files Maven fetched in this job (nlink == 1 after the hardlink seed) with per-file cp -ln, keeping the two in-house excludes. Each link is atomic and never replaces a host file, so the 300 s backstop can only leave artifacts missing. Distinguish the timeout from other failures, and fold the backstop into the derived ceiling floor instead of a second hardcoded one. * ci: record sdk-java.yml's real size in the workflow ratchet This PR grows .github/workflows/sdk-java.yml from 113473 to 114180 bytes: the MariaDB lane's timeout ceiling moves 200 -> 280 with the arithmetic that justifies it, and the Maven write-back is rewritten to publish only this job's own downloads (nlink == 1) under a 300 s backstop instead of taring the whole tree. The growth is the change, so record it rather than move the step out. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmvj37bcsp8 --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
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]> |
||
|
|
7091697f00 | fix(ci): enroll the OpenTUI parity tests in the no-AK lane (#15142) | ||
|
|
f773580e13 |
test(managed-agent): refuse a second fire while the turn runs (FG11d) (#14998)
* test(managed-agent): keep a settled run's outcome (FG11d)
* test(managed-agent): reuse a same-key cancel (FG11d)
* test(managed-agent): refuse a second fire while the turn runs (FG11d)
* revert: move the second-fire cell onto its own branch
The cell belongs to the next PR in the chain, which bases on this branch, so
it cannot also live here: the next PR's diff would be empty. Content of this
branch is unchanged from
|
||
|
|
0ac1fcca91 |
feat(cli): align OpenTUI input, editing and status lines with Ink (#14964)
* fix(cli): restore bounded OpenTUI dialogs and add migration gates * fix(cli): preserve OpenTUI input and attachment ownership * feat(cli): align OpenTUI status lines with Ink * fix(cli): align OpenTUI editor and cancellation transactions * fix(tui): harden migration cleanup and evidence after review * test(tui): fail acceptance on unhandled errors * docs(cli): clarify consolidated OpenTUI delivery status * test(cli): isolate system settings in TUI parity fixtures * fix(cli): settle OpenTUI cancellation when replay resets a session * style(cli): format merged OpenTUI test callbacks * test(cli): preserve visible input across session rotation * test(cli): await cancellation before releasing held response * fix(cli): preserve completion and escape precedence and validate status colors * fix(cli): preserve attachment navigation with one completion * fix(cli): display session titles in the OpenTUI composer border * fix(cli): discard generated command work after cancellation |
||
|
|
79242671bb |
test(ci): guard no-AK membership and filter resolution (#14989)
* test(ci): guard no-AK membership and filter resolution * test(ci): require non-blank no-AK exemption reasons --------- Co-authored-by: 易良 <[email protected]> |
||
|
|
fbeb188b16 |
test(managed-agent): reuse a same-key cancel (FG11d) (#14997)
* test(managed-agent): keep a settled run's outcome (FG11d)
* test(managed-agent): reuse a same-key cancel (FG11d)
* test(managed-agent): refuse a second fire while the turn runs (FG11d)
* revert: move the second-fire cell onto its own branch
The cell belongs to the next PR in the chain, which bases on this branch, so
it cannot also live here: the next PR's diff would be empty. Content of this
branch is unchanged from
|
||
|
|
21337f0e51 |
fix(release): cover every spawned vendored binary in the tarball exec-bit gate (#15008)
* fix(release): cover every spawned vendored binary in the tarball exec-bit gate The gate matched only vendor/ripgrep/*/rg, but the tarball spawns a second vendored executable: vendor/landlock-run/<arch>-linux/qwen-landlock-run. Its own runtime heal shares the ripgrep heal's hard limit — it can only chmod an install the running user owns, so a root-owned sudo install degrades the same silent way. Widen the expected set with a small spec list keyed on the leaf binary's presence (the landlock-run/src source directory falls out structurally), parse every regular-file tar entry instead of a single ripgrep regex, and extend the fixture tests to cover both trees with pass/reject cases. Also correct the stale comment above the landlock heal: it claimed npm archives strip non-bin exec bits, which is the inverse of what #12668 established — pnpm's packer wrote 0644 for every non-bin entry from 0.24.4 to 0.25.3; npm keeps working-tree modes. Refs #12668 * fix(release): keep missing-binary strictness in the widened exec-bit gate Deriving the expected set from the leaf binary's presence meant a platform directory whose binary was dropped during staging silently shrank the expected set: a dist without vendor/ripgrep/x64-linux/rg but with the directory would pass with five entries. Platform membership now comes from the directory name alone — ripgrep skips '-win32', landlock-run skips the 'src' source directory — so a missing binary fails as 'missing from the packed tarball' again, matching the pre-widening strictness. Also update the function doc block, which still claimed the gate covered ripgrep only. Regression test: an empty ripgrep platform directory fails with the missing-entry diagnostic even when every other binary passes. |
||
|
|
a4562edb67 |
fix(ci): align Java integration database and lock lifetime (#14936)
* fix(ci): align Java integration database and lock lifetime * test(ci): re-pin the sdk-java lock and MySQL probe after the single-step merge The merge commit staged the conflict resolution before these two re-pins were written, so they land as a follow-up in the same push: - `keeps the host lock out of every Maven child` counted three lock-bearing steps; #14903 collapsed the MariaDB lane's two Maven steps into one, so the count is now two (test job + mysql-integration). - The MySQL startup probe took the step's first `mvn` line, which is now the `-DskipTests install` staging command; select the `-Pmysql-integration` command instead so the probe still exercises the consumer. Verified: vitest sdk-java-workflow.test.js 96 passed; prettier --check clean. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmvgz448zlp * fix(ci): skip the MySQL binlog, drop the unused database, correct the reaper bound Three independent corrections to the mysql-integration lane this PR reworks. 1. MySQL 8 enables the binary log by default (MariaDB 10.11 did not in the configuration this lane replaced), and the datadir is an uncapped tmpfs. Nothing in packages/managed-agent-server/src or packages/sdk-java reads a binlog (0 hits for binlog|log_bin|GTID|SHOW MASTER STATUS), and the container is disposable with no replica, so `--skip-log-bin` is appended after the image name beside --innodb-use-native-aio=0. Without it the ~67 MiB hex-encoded LONGBLOB query this lane already raises max_allowed_packet for is serialized a second time into host RAM. 2. `--env MYSQL_DATABASE='runtime_broker_test'` had no consumer: the lane's only connection is -Dmysql.url=.../managed_agent_test?createDatabaseIfNotExist=true. The declaration invited a cleanup that drops createDatabaseIfNotExist and dies at first connect with Unknown database. Dropping it lets the JDBC URL own the schema and shrinks the diff. 3. The cleanup comment and removal-failure warning said the host reaper reclaims a stranded container "after a 24h age gate" / "up to a day". The real bound is ~48h: qwen-docker-cleanup.sh:31 gates on a strict `now - created_at > 86400` (exactly 24h is SKIPPED) and qwen-docker-cleanup.timer fires once a day, so a container created just after a fire is skipped at the next one and reaped at the one after. Test pins updated in the same change: the start-step assertion, the exact docker-run trace literal, and the cleanup warning literal. All three were mutant-verified red (drop --skip-log-bin / re-add MYSQL_DATABASE / restore "after 24h") and restored byte-identical. Only this PR's own copy of the reaper wording is corrected; the two pre-existing copies (sdk-java.yml's event-transport-multi-node job and release-managed-agent-reference.yml) are untouched to keep this diff scoped. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmvhb9cysmc --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
96953853fd |
test(managed-agent): resume the automation streams across a settle (FG11e) (#15017)
* test(managed-agent): resume the automation streams across a settle (FG11e) Gate the FG11e row of #14446 with two cells in the FG11 automation class. One cuts a run's task event feed and a public Session stream while the wake Turn is held between its fire and its settle, and resumes both from their last positions; the other pages the run list across an insert. The Session arm asserts today's precondition that a run adds no event to the Session stream, so it gates the resume across that window rather than automation content. The cells book 39 s on the shared Hosted fork (healthy 10272 s, fork 10872 s, so the Verify step moves to 192 minutes and the job ceiling to 295), and the FG11e design record moves to partly delivered in both languages. * test(managed-agent): decode the FG11e task cursor independently The stream cell built each expected task cursor with the store's own encoder, so the cursor format was never witnessed apart from the code that writes it. The served cursor is now decoded in the test and must name its row's sequence. The Session comparison trims the ledger with a limit instead of subList, so a stream that served more frames than the journal holds fails as an assertion rather than an IndexOutOfBounds. * test(managed-agent): count each run's settle in the FG11e list cell The run-list cell counted model Turns for the automation but never read the settle commands, so a run settled twice without a second model call would pass it, while both design records say each cell checks one settle per occurrence. It now asserts the journal holds exactly one settleRun per run, in the order the runs settled. * test(managed-agent): fail an FG11e task cursor outside its format The independent cursor check fell back to the decoded text when it did not match the cursor format, so a cursor that decodes to a bare number became a valid-looking sequence and matched the ledger. A cursor outside the format now fails the check outright. * test(managed-agent): rebook the FG11e cells at their slower samples Two later runs measured the stream cell at 14.1 s and the run-list cell at 5.6 s, above the 13.8 s and 5.2 s the ledger was booked against. At 2x the slower samples the cells take 41 s: healthy 10424 s, fork 11024 s, which the 194-minute Verify step still wraps with 16 s of margin. |
||
|
|
9efdca76d3 |
feat(managed-agent): derive Session Store wiring on a single host (#15005)
* feat(managed-agent): derive Session Store wiring on a single host An enabled Hosted Harness requires the Managed Session Store, yet the store's switch, base URL and workspace ID all had to be configured by hand, and the shipped templates set a workspace ID that the documented local-process tool path then rejects. The store now follows the Harness switch, takes its base URL from this server's loopback or wildcard listener, and shares the Runtime Broker's workspace identity, derived from the Workspace directory when no ID is set. Explicit values keep precedence. Preflight reports the effective store wiring, and the templates, bootstrap and deployment guide name the Workspace directory instead of a conflicting ID. * fix(managed-agent): derive no plaintext Store URL for a TLS listener When the public listener serves TLS through server.ssl and no dedicated internal listener exists, the derived http:// loopback URL reached the TLS connector, so every Store call failed while preflight reported PASS. Such a listener now derives nothing and the existing refusal asks for an explicit URL. The internal listener is always plaintext, so it still derives behind a TLS public listener. * test(managed-agent): pin the dual-path entry to the derived Store wiring The dual-path README contract still required the explicit store switch that the entry no longer exports, and its ordering check would pass vacuously once the name was gone. It now checks that the store follows the Harness by default, that Prerequisites exports the workspace ID, and that the Harness base-url export precedes the restart cue, with both positions required. |
||
|
|
86875ee18b |
test(managed-agent): reuse the pinned registration after a lost ack (FG13a) (#14993)
* test(managed-agent): lose the store ack after the result commit (FG13a) StoreFaultGate's existing seam rejects a commit before it applies, so the whole commit rolls back. This layer adds the opposite failure: the commit lands and the caller never sees its acknowledgement. The faulting store calls afterApply only after super.apply succeeds; the new cell proves one physical Hook call, a durable settled result, and a status read that returns it without a second call. Adds the bilingual design note. One cell adds 150 s to the shared fork: healthy 10189 s, fork 10789 s, Verify 190 minutes, job 293 minutes. * test(managed-agent): keep the durable dispatch after a lost ack (FG13a) * test(managed-agent): reuse the pinned registration after a lost ack (FG13a) * test(managed-agent): report the lost ack after the commit lands (FG13a) * test(managed-agent): let the dispatch ack-loss cell call its Hook (FG13a) * docs(managed-agent): describe the ack seam without overclaiming (FG13a) * test(managed-agent): bound the dispatch recovery instead of guessing (FG13a) * docs(managed-agent): carry the audit fixes into the registration slice (FG13a) * docs(managed-agent): align the Chinese dispatch slice with its cell (FG13a) * docs(managed-agent): drop the model-request claim from the Chinese slice (FG13a) * docs(managed-agent): align the Chinese registration slice budget (FG13a) * test(managed-agent): witness the replay instead of a transient phase (FG13a) * test(managed-agent): witness the replay on the registration ack loss (FG13a) |
||
|
|
644dfcf68b |
test(managed-agent): keep the durable dispatch after a lost ack (FG13a) (#14992)
* test(managed-agent): lose the store ack after the result commit (FG13a) StoreFaultGate's existing seam rejects a commit before it applies, so the whole commit rolls back. This layer adds the opposite failure: the commit lands and the caller never sees its acknowledgement. The faulting store calls afterApply only after super.apply succeeds; the new cell proves one physical Hook call, a durable settled result, and a status read that returns it without a second call. Adds the bilingual design note. One cell adds 150 s to the shared fork: healthy 10189 s, fork 10789 s, Verify 190 minutes, job 293 minutes. * test(managed-agent): keep the durable dispatch after a lost ack (FG13a) * test(managed-agent): report the lost ack after the commit lands (FG13a) * test(managed-agent): let the dispatch ack-loss cell call its Hook (FG13a) * docs(managed-agent): describe the ack seam without overclaiming (FG13a) * test(managed-agent): bound the dispatch recovery instead of guessing (FG13a) * docs(managed-agent): align the Chinese dispatch slice with its cell (FG13a) * docs(managed-agent): drop the model-request claim from the Chinese slice (FG13a) * test(managed-agent): witness the replay instead of a transient phase (FG13a) |
||
|
|
021dc1fdd6 |
test(managed-agent): lose the store ack after the result commit (FG13a) (#14991)
* test(managed-agent): lose the store ack after the result commit (FG13a) StoreFaultGate's existing seam rejects a commit before it applies, so the whole commit rolls back. This layer adds the opposite failure: the commit lands and the caller never sees its acknowledgement. The faulting store calls afterApply only after super.apply succeeds; the new cell proves one physical Hook call, a durable settled result, and a status read that returns it without a second call. Adds the bilingual design note. One cell adds 150 s to the shared fork: healthy 10189 s, fork 10789 s, Verify 190 minutes, job 293 minutes. * test(managed-agent): report the lost ack after the commit lands (FG13a) * docs(managed-agent): describe the ack seam without overclaiming (FG13a) * docs(managed-agent): drop the model-request claim from the Chinese slice (FG13a) |
||
|
|
8545558a25 |
test(managed-agent): keep a settled run's outcome (FG11d) (#14996)
* test(managed-agent): keep a settled run's outcome (FG11d) * docs(managed-agent): name the settled run's real refusal code The cell's own comment still said task_already_settled while the assertions and both design docs record 409 task_action_unavailable, which is the code the measured behaviour actually answers. |
||
|
|
97567d5dd7 |
feat(core): add a real PTY backend for the Bun runtime (#14046)
* feat(core): separate app launcher and JS interpreter runtime boundary
Establishes the runtime boundary the Bun migration (MYWO-8 S1) needs
before workers, hooks, sandbox helpers and the code-mode host spawn
JavaScript children under a future compiled-app flavor: arbitrary-JS
child processes resolve their interpreter through one accessor (package
manifest first, process.execPath fallback) instead of reading
process.execPath directly, Bun detection has a single seam, and the
app-launcher contract is documented alongside the full call-site
inventory in a bilingual design doc. Adds the same-fixture Node/Bun
regression matrix (stdio framing, exit codes, SIGTERM, IPC channel,
--expose-gc, --input-type=commonjs --eval).
* fix(core): anchor interpreter resolution to the trusted install root
Arbitrary-JS child resolution no longer walks upward looking for a
manifest: the only trusted location is the standalone package root —
the parent of the caller's bundle directory, which must hold both a
manifest.json and the standalone entry marker lib/cli-entry.js — so an
unrelated ancestor manifest in npm, source or SDK layouts can never be
read. Declarations are validated before use: runtime must be exactly
'bun' or 'node', and the interpreter must be an existing executable
regular file; any invalid or missing declaration falls back to
process.execPath without throwing (non-string interpreter, directory,
non-executable file, unknown runtime, absent binary, missing marker).
Adds the regression matrix for unrelated ancestor manifests (npm
bundle and deep SDK layouts), object/number/directory interpreters,
unknown runtime, missing and non-executable interpreters, and the
trust anchor; syncs both design-doc language versions with the
validated contract.
* docs(design): complete the migration inventory handoff
Adds the three interpreter-identity call sites the re-review found
missing from the call-site inventory (hook-command-cgroup launcher,
bwrap-execution and landlock-execution allowlist staging), marks the
unwired rows as owned by the S3 migration sweep, and notes platform
applicability: the cgroup/bwrap/landlock rows are Linux-only
mechanisms validated against the Linux targets of the platform
matrix, while the mem0 and pem rows apply on every platform. Both
design-doc language versions are updated; no product or test code
changes.
* feat(core): add a real PTY backend for the Bun runtime
Under Bun, @lydell/node-pty's wrapper pumps the PTY master fd through a
tty.ReadStream, and Bun surfaces the nonblocking fd's EAGAIN as an error
event instead of "no data yet", destroying the stream and closing the
master: onData never fires, resize fails with EBADF, and the shell tool
and web terminal hang. Reproduced on Bun 1.3.14 and 1.4.0.
getPty() now loads a qwen-bun-pty backend under Bun (non-Windows) that
drives the same native addon directly with a main-thread async fs.read
pump: EAGAIN retries on a short timer instead of erroring, EIO/EBADF end
the pump and close the fd, writes queue through an async fs.write with
EAGAIN retries, and exit waits briefly for the drained fd so data is
never truncated behind onExit. The wrapper's observable contract (env
sanitizing, flow-control bytes, encoding, resize validation, IPty
lifecycle) is mirrored, and the pump starts in the constructor so an
unpumped fd can never hold the event loop open.
Packaging stages the node-pty addon for both runtime flavors, since Bun
installs now load it through this backend. The Windows-under-Bun gate
stays honest (explicit load error), and the runtime-boundary design docs
point at the new backend doc for the mechanism and evidence.
Tests: unit coverage for the backend lifecycle (output, write, resize,
kill, pause/resume, flow control, raw encoding), getPty selection under
Bun/Windows, and a cross-runtime regression that runs the same fixture
through the real getPty() seam under both Node and Bun when a bun binary
is present.
* fix(core): keep PTY exit detection alive while paused
The pinned node-pty addon fires its native exit callback only around
master-fd read activity (isolated-probe evidence, identical on Node and
Bun), so the old pause() that stopped the pump lost onExit entirely:
pause then child exit left the master fd open and the host unable to
drain — the same mechanism behind the XOFF-then-cancel FD residue under
handleFlowControl.
pause() now buffers output into a bounded hold (1 MiB) that resume()
flushes, while reads continue so exit detection rides on the pump.
On end of life the hold is discarded for wrapper parity: onExit arrives
exactly once and the fd is released, but resume-after-exit replays
nothing, matching the wrapper's destroyed paused socket. Docs are
synced to the actual main-thread async fs.read pump (the earlier
worker-threads/blocking-read sketch is documented as abandoned), and
regressions cover pause-at-exit, hold overflow, and XOFF-cancel on both
runtimes.
* fix(core): make the Bun PTY pause hold lossless and exits leak-free
Serializes master-fd reads behind an in-flight guard (a resume chaining
into a read that is still outstanding would cross-observe the shared
64 KiB buffer), holds paused output without a cap so nothing is ever
silently dropped, and routes every end-of-life path through one cleanup
that flushes the decoder, stops the retry timer, closes the master fd
and fires onExit exactly once — including the 500 ms fallback, which is
now ref'd so exit delivery cannot depend on a droppable timer. Pins all
of it with byte/line-exact regressions: no-gap pause/resume storms and
a ~1.9 MB flood resumed byte-for-byte, cross-runtime.
* fix(core): cap the Bun PTY pause hold and terminate on overflow
The lossless pause hold could grow without bound while a consumer
stays paused. The hold now copies chunks into fixed 64 KiB blocks
under a per-pty byte ledger (4 MiB default) inside a process-wide
budget (32 MiB total hold, 8 active ptys, 1 MiB write queue), so the
bound holds for any producer chunk pattern.
Reaching a cap terminates that pty (SIGTERM then SIGKILL) and emits
one structured PtyLimitError — never a success result and never a
fabricated native exit; the real signal death lands only in
stats.nativeExitRecord. Shell executions converge the error into
{error, exitCode: null, signal: null}; web terminals mark the session
failed and the /terminal route sends an error control frame followed
by close 4001. Node behavior is unchanged.
Design docs corrected per review: the drip "kernel corruption" claim
is withdrawn, and exit detection wording no longer overstates when
exits are observed.
* fix(core): harden post-termination pty edges per review
Dual-review follow-ups on the bounded hold: resize() joins write() in
treating a terminated/closed pty as a no-op instead of throwing EBADF
from the addon; a read that was in flight when the limit termination
closed the fd no longer delivers or re-charges its late bytes; and a
resume() replay stops at the first data listener that terminates the
pty, so no held bytes flow after the structured error.
* fix(core): detach pty error subscriptions by observed shape, not assumed Disposable
node-pty's Terminal.prototype.on proxies the listener to its master socket
and returns undefined, while an EventEmitter-based pty (the Bun backend)
returns the emitter itself. The registry stored that return value as a
Disposable and called dispose() on release, so every Bun release, natural
exit, or backend failure path threw TypeError from the route/registry and
could take the whole serve process down (server exit 1, client saw 1006
instead of the explicit close).
Store the subscription return as unknown and detach by observed shape: a
real { dispose } is used as-is, otherwise off/removeListener removes the
listener, and undefined (node-pty's actual return) keeps the previous
no-dispose behavior unchanged.
Covered by two registry unit tests on the mocked shapes plus a real-serve
lifecycle probe (release 4004 / exit 4000 / backend over-limit 4001 with
failed-session reconnect replay, server alive throughout) run under Bun
1.3.14, Bun 1.4.0, and Node.
* fix(core): close Bun PTY fds only after in-flight ops settle
Review round on #14046:
- bun-pty closeFd() ran closeSync() while libuv fs.read/fs.write ops could
still own the master fd, so the recycled descriptor number could take a
queued write into an unrelated session. fdClosed now flips and the
process-wide admission slot is released immediately, but the real close
is deferred until the last outstanding op settles, with witnesses for
both the read-held and write-held arms.
- A write-side EIO/EBADF (child already gone) is the expected teardown
race and is no longer reported, matching the wrapper's swallowed EIO;
other write errors keep their errno code so the entry classifier and
getPtyLimitMessage can recognize them instead of escaping as an
uncaught exception. The pump's emit dispatch runs under try/finally so
a throwing error listener can never strand the pump.
- The web-terminal registry's pty error subscription no longer re-throws:
a throw there leaves the backend's fs callback as an uncaught exception
and kills the serve daemon. EIO/EAGAIN races are swallowed and other
non-limit errors go to the diagnostic sink.
- Failed sessions no longer count against the web-terminal admission cap,
and release() no longer fabricates a 143/15 exit frame for them.
- processPtyBudget.maxActivePtys is 64 (headroom over the eight-slot
web-terminal cap so a full house cannot starve the shell tool), with
the per-pty vs process-wide cap relationship documented.
- ShellExecutionResult.executionMethod declares 'qwen-bun-pty', its
error-field contract documents resource-limit termination, and the two
casts that hid the Bun backend name are dropped.
- getPty tests that assert the Bun arm loads now pin a POSIX platform so
they pass on Windows hosts; docs and the packaging help text are
aligned (correct smoke-runtime.js path, boundary-doc PTY row now cites
the bun-pty fixture, node-pty staging applies to both runtimes).
* chore: re-verify S1 boundary test-file merge resolution with recorded evidence
Empty commit: no code change is warranted by the deterministic gate's
test-weakening rejection. The merge
|
||
|
|
b51ce2c305 |
feat(workflow): add per-turn human-origin workflow hints (#14876)
* feat(workflow): add per-turn human-origin workflow hints * fix(workflow): preserve intent across recall and cached submissions --------- Co-authored-by: qqqys <[email protected]> |
||
|
|
15ab745f1e |
test(managed-agent): gate R1-1 owner-release recovery across a Spring restart (FG12d) (#14990)
Cover #14880 item 3. During a lifecycle v2 close the Broker proxy refuses the owner release after every configuration is drained, then the test replaces Spring and its embedded Broker. Detach must recover with exactly one forwarded owner release (no acquire, no MCP control), clear the storage holder, and leave the Runtime Session RELEASED. The recorded blocker was the rig, not WorkspaceStorageGuard: startSpring() registered the storage and inserted the Workspace rows on every boot, and the guard refuses a second registration while the holder is booked. Production never re-registers on start, so seed only on the first boot and restart in the JVM; the Broker's close writes nothing and the durable provisioner keeps the worker alive, which is the state R1-1 needs. R1-1 does not reproduce on main: the replaced Broker reaches the persisted-Session release path, and #13673's managed-context branch releases the saved Session while the Harness drains. Disabling that branch turns the case red 3 of 3 times with the original symptom (every retry answers 503 and the holder stays booked). Budget the cell at 24 s (2x its measured 11.9 s): healthy 10039 -> 10063, fork 10639 -> 10663, Verify stays 188 minutes. |
||
|
|
a791e47a54 |
feat(cua): streamline computer use and port native reliability fixes (#14846)
* feat(cua): preload the JavaScript computer use runtime * refactor(cua): remove the native Wayland backend * feat(cua): move app computer use into the driver * feat(cua): preserve background delivery and port platform fixes * feat(cua): add explicit desktop input and browser runtime facade * feat(cua): package the unified 0.26.0 computer use runtime * fix(cua): finalize cross-platform native reliability * fix(cua): isolate runtime releases from CLI versioning * fix(cua): keep Electron out of root workspace installs * fix(cua): synchronize consumers and async cleanup tests * fix(browser): migrate smoke to preloaded cua runtime * docs(cua): document MCP setup for Qwen Code Claude Code and Codex |
||
|
|
e17380e6ef | test(managed-agent): reuse the run on a same-key retry (FG11d) (#14981) | ||
|
|
8f3c7e15e4 |
fix(cli): preserve runtime boundaries during standalone updates (#14934)
* fix(cli): preserve runtime boundaries during standalone updates
Preserve Node/Bun archive flavor and validate actual CLI loading, package
identity, version and prepared installation identity before activation.
Keep Node npm transport and restrict Bun registry lookup to trusted config.
Integrates chiga0's update stack through
|
||
|
|
7d27f475be |
test(managed-agent): keep a suppressed reply suppressed across a reload (FG13f) (#14978)
A MessageDisplay command Hook suppresses the streamed reply; the public
ledger must not carry its text, and after a Harness restart the next model
request's history must not carry it either. The fixture gains a
hook-suppress mode that records the Hook input and answers
{suppressOutput:true}.
Adds the bilingual design note. One cell adds 150 s to the shared fork:
healthy 10012 s, fork 10612 s, Verify 187 minutes, job 290 minutes.
|
||
|
|
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]> |
||
|
|
ee332fe5b2 |
test(managed-agent): gate a pre-dispatch MCP operation cancel (FG12d) (#14963)
Cover #14880 item 2 without seeding a row. invoke() commits the mcp_operation at intent, acquires the owner and only then commits dispatch_started, and the cancel route is not gated by an in-flight invoke. The Broker proxy parks the first tool-session acquire that arrives while the durable record is still intent, and the case cancels through the supported Harness route inside that window. The cancel settles managed_mcp_cancelled with the record at cancelled/not_started_proven; the resumed invoke, a same-id retry and a status read answer the same view, and no MCP control reaches the Broker after the parked acquire. Three bundle mutants (cancel skips its intent branch, invoke skips the post-acquire re-read, invoke ignores the local proof) each turn the case red; the last only through the wire assertion. Budget the cell at 18 s (2x its measured 9.1 s): healthy 9518 -> 9536, fork 10118 -> 10136, Verify stays 179 minutes. |
||
|
|
5f638ae436 |
feat(generated-ui): bundle Generated UI behind an experimental flag (#14888)
* feat(generated-ui): bundle behind an experimental flag * fix(generated-ui): preserve runtime admission and settings aliases * fix(generated-ui): invalidate owning cards after MCP refresh --------- Co-authored-by: 衍星 <[email protected]> |
||
|
|
bb2eb88a23 |
test(managed-agent): pin the close refusal while a turn is active (FG11d) (#14974)
* test(managed-agent): pin the close refusal while a turn is active (FG11d) * ci(managed-agent): budget the close-in-flight refusal cell |
||
|
|
6e6598e35c |
fix(cli): restore bounded OpenTUI dialogs and add migration gates (#14933)
* fix(cli): restore bounded OpenTUI dialogs and add migration gates * fix(tui): harden migration cleanup and evidence after review * test(tui): fail acceptance on unhandled errors |
||
|
|
f8c3388470 |
test(managed-agent): resume both Session streams across a held Hook (FG13e) (#14917)
* test(managed-agent): resume both Session streams across a held Hook (FG13e)
A PreToolUse command Hook holds inside the Runtime worker while the public
and WebShell clients read the Session stream. Both clients are then cut,
the deny lands while neither is connected, and each resumes with its own
cursor (Last-Event-ID on the public route, afterSequence on the WebShell
route). Each resumed view must equal the committed ledger byte for byte
with no gap and no duplicate, carry exactly one completion, and the model
must see exactly one tool result carrying the denial reason while the tool
never runs.
The tool-call start frame is only emitted after the call leaves the Hook,
so the cut deliberately happens before it: the frames written during the
hold are exactly the ones a cut client misses. Adds the bilingual design
note. One cell adds 150 s to the shared fork: healthy 9630 s, fork
10230 s, Verify 181 minutes.
* test(managed-agent): read the cut cursors after the readers stop
The resume cursor was sampled before abort(), so a frame the reader
thread appended in that window would be served again on resume and redden
the union as a duplicate. Take the cursors after abort(), matching the
FG12f class.
* test(managed-agent): release the held Hook after both streams are cut
The fixture now offers a hook-release mode that waits for <evidence>.release
instead of sleeping for a fixed 20 s, and the test writes that file only
after both readers abort. The deny therefore cannot land before the cut, so
the gap the cell claims to test is the one it actually creates.
assertResumedView now names what the Hook-held turn put on the ledger: one
failed terminal for call_FG13E_HOLD, past the cut cursor, and one
completion. Transport fidelity to a ledger that lost or duplicated the deny
no longer passes.
fg13-cases joins the Hosted artifact upload and the meta test pins it. Both
design docs correct the CI trigger: pull_request selects the fast tier, and
the full suite runs on the first maintainer approval of the head.
* test(managed-agent): correct the FG13e witness and raise the stall bound
Mutation witness #2 said a live-only resume reddens on the gap assertion.
continueFrom runs after the turn completed, so that client never reaches the
ledger tail: its 90 s wait exhausts and the case reddens on that timeout.
Both design docs now say so, and the Non-goals point the duplicated-helper
extraction at #14921.
The method's stall bound is raised to 480 s, above the 420 s of inner await
budgets, so a hung wait reports its own description instead of the outer
timeout. The Hosted lane trigger sentence was already corrected in
|
||
|
|
8cb67de793 |
test(managed-agent): skip a closed Session's automation slots (FG11d) (#14931)
* test(managed-agent): skip a closed Session's automation slots (FG11d) * test(managed-agent): park the scanner until the Session closes * test(managed-agent): keep the broker-directory comment on its wider arm * test(managed-agent): pin the closed-Session skip at one slot, with the helper --------- Co-authored-by: 易良 <[email protected]> |
||
|
|
e206b5ee8f |
fix(ci): isolate hosted MySQL integration test classes (#14875)
* fix(ci): isolate hosted MySQL integration test classes * codex: address PR review feedback (#14875) * codex: address PR review feedback (#14875) |
||
|
|
82bd240ad0 |
test(ci): pin the heap caps that failed the Managed Agent fast tier (#14862) (#14874)
* test(ci): pin the heap caps that failed the Managed Agent fast tier (#14862) Co-authored-by: Qwen-Coder <[email protected]> * test(ci): pin prepare heap cap to root build cap (#14862) Co-authored-by: Qwen-Coder <[email protected]> * test(ci): fold the heap-cap relation into its sibling guard (#14862) Co-authored-by: Qwen-Coder <[email protected]> --------- Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: 易良 <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: jinjing.zzj <[email protected]> |
||
|
|
596b7b2c5e |
fix(release): publish the generated CLI with npm so vendored ripgrep keeps its exec bit (#14907)
* fix(release): publish the generated CLI with npm so vendored ripgrep keeps its exec bit `pnpm pack` writes 0755 for the entries named in the manifest's `bin` map and 0644 for every other entry, so ever since #12400 moved publishing to `corepack pnpm publish` the released tarball has shipped `vendor/ripgrep/*/rg` without an exec bit: 0.24.2 carries `-rwxr-xr-x`, 0.24.4 onward `-rw-r--r--`, while only `cli-entry.js` (the single `bin` entry) keeps 0755. A fresh install then cannot spawn the bundled ripgrep at all, and on a machine without a system rg search silently degrades to the built-in grep. The #12673 / #12892 runtime heals cannot chmod a root-owned or read-only install, so they do not cover it. The tar writer is the only place the bit is lost: `copy_bundle_assets.js` restores it on the staged binaries and every other copy path preserves it. So publish the generated CLI with npm, which keeps the working-tree mode, exactly as it was before #12400. The recursive workspace publish stays on pnpm; `publish_package` is only ever called for `dist`, the one package that carries vendored binaries. A pre-publish gate now packs the prepared CLI the same way the publish step does and reads the archive's recorded entry modes, failing when any unix vendored ripgrep lacks all three exec bits. It runs in the arm that produces `dist`, before the publish step consumes it, and refuses to pass vacuously when the vendored tree is missing. Unit coverage pins npm as the CLI's publisher, keeps the gate in that arm, and exercises both the npm-keeps-0111 and gate-rejects-0644 directions. Fixes #12668 Co-authored-by: Qwen-Coder <[email protected]> * fix(release): run the tarball exec-bit gate from the workflow-pinned scripts The gate was invoked through the selected release ref's own `scripts/` path. The publish job's trusted checkout only materializes the paths named in its sparse-checkout list, and a manual release may select any branch or full SHA — so releasing a ref that predates the gate (v0.25.3, or any commit before this change) died in `build-package` with MODULE_NOT_FOUND, dry runs included. Ship the gate with the workflow-pinned scripts — add its path to the release workflow checkout's sparse list — and run it from `.release-workflow/`, the same way the version guard rides that checkout. The working directory stays the selected release ref, so the `dist` argument still resolves to that ref's prepared package. The sparse-checkout list and the invocation are both pinned in the release workflow and package script tests. Fixes the blocking review finding on #12668. --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
3820924bc2 |
fix(ci): hold chosen RocketMQ ports until the JVMs bind them (#14860)
* fix(ci): hold chosen RocketMQ ports until the JVMs bind them The chooser released its sockets as soon as it printed them, so between the choose step and the JVM bind (download, namesrv boot) any sibling job on the pool host could take the port: #14545's full lane died twice this way, on the broker HA listener and on the NameServer listener. Park each chosen port behind a detached holder process instead, and let rocketmq-lite-broker.sh kill only the holder of the port it is about to hand to a JVM, shrinking the pick-to-bind race to the sub-second kill-to-bind window. The pid files live in RMQ_HOLDER_DIR and are cleaned up on start success, rollback and stop; local runs without RMQ_HOLDER_DIR behave as before. * fix(ci): keep the broker companion arithmetic readable by macOS Bash 3.2 The inner quotes around the numeric operand make macOS's system Bash 3.2 raise "operand expected", so every start and stop failed there after the NameServer had already booted. The script supports macOS, so the operands stay unquoted. * fix(ci): terminate holder pid records and reject overlapping companions A pid file without a trailing newline makes bash read the last line and return 1, so unhold_port and release_holders aborted start and stop under set -e once the workflow consumed RMQ_HOLDER_DIR. Terminate the record and require the file to name the child this chooser just spawned. A broker companion (listenPort - 2 / + 1) can repeat a port an earlier role already parked, and the new holder then died on bind while the live holder's pid file faked success, leaving the fast channel or HA listener colliding with that role. Reject those companions and release only the holders the rejected candidate parked. The script tests now drive the real chooser, then start and stop against stand-in components with its ports and RMQ_HOLDER_DIR. * test(ci): cover the holder records on the stop path too unhold_port and release_holders read the chooser's holder records through separate code paths, and only the start side was exercised: stop with a populated holder directory is what rollback and stop rely on, so give it its own case and share the chooser invocation between both. * test(ci): check a released port by its listener, not by a bind probe A holder binds 0.0.0.0, and binding 127.0.0.1 against a wildcard listener still succeeds on macOS, so the stop case asserted a port was free while the holder could still be alive: with release_holders' kill removed the test stayed green. Ask the port's listener the way the script does, and wait for the socket the killed holder releases on exit rather than on kill. * test(ci): clean leaked holders up by pid, not by their records The afterEach cleanup read the holder records back, so a regression that makes release_holders drop a record without killing the process left the Node holder running and its port bound after a red run. Track the pids the chooser started and kill those, mirroring how this file already cleans up a leaked stand-in. --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
b05be4cd23 |
fix(ci): hold the MariaDB lane's sdk-java lock once per job (#14896) (#14903)
* fix(ci): hold the MariaDB lane's sdk-java lock once per job (#14896) Co-authored-by: Qwen-Coder <[email protected]> * test(ci): pin the merged MariaDB step's order and SpotBugs witness The single-step merge dropped guarantees that the two-step layout got for free from step boundaries, and one witness became satisfiable by prose: - spotbugs-gate matched `verify` anywhere in the step body, and the merged step's own comments explain the incident with the word 'verify' twice. A later narrowing to `clean test` would stay green. Match `clean verify` on command lines only. - seed-before-write-back was a step-order invariant; both strings now live in one body with presence assertions only, and the write-back's warning arm swallows the ordering failure. Pin seed < install < verify < write-back. - `working-directory:` applied to the whole step and could not be misplaced; its `cd` replacement is positional inside the body. Pin it between the two Maven runs. - Drop the finder arm that matched the deleted `working-directory:` property: no step in either inspected job carries it any more. --------- Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: 易良 <[email protected]> Co-authored-by: Shaojin Wen <[email protected]> |
||
|
|
6ca2c0bd52 |
test(managed-agent): settle a claim retired at intent (FG11d) (#14915)
* test(managed-agent): settle a claim retired at intent (FG11d) * test(managed-agent): carry the fire answer across threads, name the admission cell * ci(managed-agent): budget the retire-at-intent cell in the hosted fork |
||
|
|
c8971faac9 |
test(managed-agent): gate a late conclusive reply after outcome_unknown (#14892)
* test(managed-agent): gate a late conclusive reply after outcome_unknown * docs(managed-agent): drop the stale late-reply gap sentence * docs(managed-agent): align the FG12f budget note with the 50 s ledger entry * test(managed-agent): budget the fourth case at +10 s on main * docs(managed-agent): align the Chinese decision order with the English one * test(managed-agent): carry the class entry from 40 s to 50 s The class re-measures at 24.16 s, so its 2x entry is 50 s, not 40 s. Main carries it at 30 s, so the delta is +20 rather than the +10 the earlier draft assumed: healthy 9485, fork 10085, Verify 179, ledger 269, job 282. The three ledger chains now name this PR's entry, so each comment still computes the literal below it, and the class Javadoc lists the fourth cell. * docs(managed-agent): restate the FG12f entry as 30 s to 50 s * ci: name the FG12f +20 s in the hosted job ceiling comment --------- Co-authored-by: 易良 <[email protected]> |
||
|
|
ef155d8398 |
test(managed-agent): gate the per-run cancel on a parked wake turn (FG11d) (#14900)
* test(managed-agent): gate the per-run cancel on a parked wake turn (FG11d) The cell was recorded as blocked for want of a hold point; the parked model is that hold point. With the wake turn kept parked, the public task cancel settles the task and the run cancelled in under a second and the schedule stays live. Releasing the model immediately after the 202 instead lets the turn finish first and the run settles completed, which is why the cell asserts before the release. The case covers the public task id from the tasks projection, one run record, one cancelled settlement, and a schedule that survives its run's cancel. Measured at 7.4 s through the packaged stack, so the fork budget follows the 2x convention: healthy 9480 s, fork 10080 s. * docs(managed-agent): extend the pom ledger for the cancel cell The js ledger gained the cell's 15 s but the pom ledger still ended at 9465 s and 10065 s, contradicting the literal beneath it. The audit trail now records the same step the pin test carries. * docs(managed-agent): align the cancel limits text with #14882 Both PRs rewrite the same Limits bullet, so different wording would conflict on whichever lands second. This takes #14882's sentence verbatim and makes the delivered note a list item in English as it already is in Chinese. * test(managed-agent): pin the cancelled task and its occurrence The cell asserted the run's state and the schedule, while the matrix also wants the task and the occurrence to settle. It now pins the projected task's kind (automation_run) so a later task cannot silently take the cancel, the task's cancelled state, and the manual occurrence firing exactly once. The Verify step sat at exactly fork + 600 s after the new cell, so its "plus margin" comment was no longer true; it moves to 179 minutes and the job to 282. * ci(managed-agent): record the sdk-java workflow's new size The workflow grew to 108273 bytes on main without bumping its baseline, so any PR that touches the file - this one bumps the hosted gate's Verify timeout - inherits a 4231-byte drift past the 4096-byte allowance. --------- Co-authored-by: 易良 <[email protected]> |
||
|
|
623cb40cf5 |
fix(ci): skip prepare's duplicate build in the daemon E2E install (#14861) (#14873)
The daemon E2E job's install ran prepare, which built and bundled the tree, then the job's next two steps built and bundled it again. The fast-tier lane failed inside that install-path prepare build. Set QWEN_SKIP_PREPARE so the install stays an install, matching the e2e build job. Co-authored-by: Qwen Autofix <[email protected]> |
||
|
|
8749bc465c |
fix(ci): skip Managed Agent reviews after the PR closes (#14774) (#14777)
* fix(ci): skip Managed Agent reviews after the PR closes (#14774) Co-authored-by: Qwen-Coder <[email protected]> * test(ci): pin closed-PR gate wiring and diagnostics (#14774) * refactor(ci): skip closed-PR reviews at the gate job level (#14774) #14857 landed the job-level review guard, so a closed-PR approval can skip before any job starts instead of selecting `none` from inside the tier step. Move the closed check into the `scope` and `gate` conditions, drop the `PR_STATE` env wiring and the tier-script branch, and restore the report text that described it — no job now reports a reason. Tests pin both jobs skipping for a closed-PR approval and keep open-PR approvals running. Resolves #14774 * docs(gate): describe an all-skipped review run precisely This branch already rewrites the lines that describe a skipped review run, so the correction belongs here rather than in a second PR touching the same paragraph. The skipped run still lists one check per job, and the reporting job's name is shown as its unevaluated expression, so "nothing reported" is wrong on both counts: three skipped checks appear, none of them named `Managed Agent gate`. Verified on run 39392964690, a `pull_request_review` event on the #14857 head. The `scope.if` comment carried the same overclaim ("it never reported the required name anyway"): on an untouched PR the review run did report `Managed Agent gate`, and only the same head's pull_request run makes that check redundant. --------- Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: 易良 <[email protected]> |
||
|
|
3745654f8a |
fix(channels): preserve Markdown structure when splitting messages (#14043)
* fix(channels): preserve Markdown structure when splitting messages * fix(channels): preserve Markdown regression fixture formatting * fix(channels): preserve Markdown chunks at budget boundaries * fix(channels): preserve deep-list delivery and background code continuations * fix(channels): Preserve Markdown fence source at chunk boundaries * fix(channels): bound markdown message chunk amplification * fix(channels): Replan after nested Markdown budget failures * fix(channels): preserve affordable markdown within bounded plans --------- Co-authored-by: Ethan Ye <[email protected]> Co-authored-by: claudeethan <[email protected]> |