mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
main
16
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e7fe14ee83 |
docs(managed-agent): generate the server configuration reference from its metadata (#15939)
* docs(managed-agent): generate the server configuration reference from its metadata
The server has about 180 settings, 84 of them mapped to QWEN_MANAGED_AGENT_*
variables, and no list of them with their variables, defaults and limits:
operators read a 2000-line developer README for them.
- The server module runs spring-boot-configuration-processor once more,
over ManagedAgentProperties only (the two Druid beans share a prefix,
which the processor refuses), and writes the configuration metadata.
The compiled classes are unchanged. runtime-broker.ssh is marked
@NestedConfigurationProperty, and STRICT_HARNESS_KEYS @Getter(NONE), so
the metadata lists the one and not the other.
- configuration-descriptions.json holds an English and a Chinese
description for each setting and section.
- scripts/generate-managed-agent-configuration-reference.mjs writes
docs/users/managed-agent-configuration-reference{,.zh-CN}.md from the
metadata, the packaged application.yml (variables and defaults), the
${qwen.managed-agent.*} placeholders in the main sources (settings read
outside the properties class) and the descriptions. --check fails on a
setting without a description, a description of no setting, or a stale
page; the reference workflow runs it after the Java build.
- The archive ships the pages as docs/configuration{,.zh-CN}.md, and the
deployment guide and the README link them.
* fix(managed-agent): link the shipped documents by their archive names
The archive renames each document it ships, so a link written against
the repository, such as the configuration reference's language switch or
the guide's link to it, named a file the archive does not have. The
packager now points every link between shipped documents at the
document's name in the archive and leaves every other link as written.
* build(managed-agent): take the configuration processor's version from the BOM
spring-boot.version is defined nowhere in this build, so the processor
path's <version> only resolved because the compiler plugin falls back to
dependency management. Say so by naming no version.
* test(managed-agent): name no tracked Markdown in a link fixture
classify-profile.test.mjs requires every Markdown file a test names to be
in TEST_READ_MARKDOWN, and the kept-link fixture's docs/runtime-broker.md
matched packages/managed-agent-server/docs/runtime-broker.md, which no
test reads. The fixture only needs a link to a file the archive does not
ship, so it names one that does not exist.
|
||
|
|
9ebd2de171 |
feat(managed): add experimental Kubernetes deployment (#15492)
* feat(managed): add experimental Kubernetes Helm deployment * feat(managed): add trusted-node tools and dedicated WebShell gateway * test(web-shell): isolate Managed gateway in boot tests * docs(managed): clarify Kubernetes gateway requirements * fix(managed): align Helm workspace identity with runtime broker * fix(web-shell): keep managed permission rules key distinct * fix(managed): align Helm lint and web test boundaries * codex: address PR review feedback (#15492) |
||
|
|
f3af3dd857 |
refactor(managed-agent): Split server into Maven modules (#15871)
* refactor(managed-agent): split server into Maven modules Separate contracts, orchestration, persistence, adapters, assembly, and verification while retaining the existing service delivery model. Move tests and build consumers together and document local evidence and pending CI acceptance. Co-authored-by: Qwen-Coder <[email protected]> * refactor(managed-agent): reduce configuration and SDK boilerplate Co-authored-by: Qwen-Coder <[email protected]> * refactor(managed-agent): narrow contracts and simplify test scaffolding Co-authored-by: Qwen-Coder <[email protected]> * fix(managed-agent): repair verification after module migration Resolve shared fixtures and worker paths from the Maven module root, update CI packaging assertions, and align existing test fixtures with the extracted contracts. Restore restricted Workspace constructors and remove redundant test visibility changes without altering inherited MySQL coverage. Co-authored-by: Qwen-Coder <[email protected]> * test(managed-agent): align remaining Harness and OSS fixtures Preserve SDK refusal messages and register the managed OSS adapter at fixture injection points. Keep the existing retry and client shutdown assertions intact. Co-authored-by: Qwen-Coder <[email protected]> * style(managed-agent): order Hosted cleanup Harness imports Co-authored-by: Qwen-Coder <[email protected]> * test(managed-agent): fix recovery smoke fixture and import order Supply the required transcript coverage in the recovery browser fixture and wait for history before testing a complete handoff. Preserve its existing safety and submission assertions. Order the cleanup coordinator test imports for Checkstyle. Co-authored-by: Qwen-Coder <[email protected]> --------- Co-authored-by: Qwen-Coder <[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]> |
||
|
|
73aa65a4b4 |
chore(desktop): rename packages/desktop-shell to packages/desktop (#12653)
* chore(desktop): rename packages/desktop-shell to packages/desktop The Electron-era packages/desktop was removed in #9085 and the OpenWork downstream has forked, so the short name is free and the shell suffix is the only thing left of the transition. Rename the package directory and every load-bearing reference: workspace negations (npm + pnpm), the ci.yml crate filter, desktop-release.yml, the isolation guard, lint/ignore configs, scripts tests, CLI workspace-fixture tests, and living docs. User-facing identity is untouched: the crate stays qwen-code-desktop, productName stays "Qwen Code Desktop", the bundle identifier, updater feed, release tag scheme, and the legacy electron-bridge asset names are all unchanged. check-desktop-isolation now guards both path names so the old one cannot re-enter a workspace set. Dated design docs under docs/design/ keep their historical paths deliberately. Refs #8596 * docs(design): follow the rename in the undated notification design notes The web-shell-browser-notification-details pair is a living doc without a date prefix, so it falls under the PR's update rule rather than the historical-record exception. * docs(desktop): stop citing paths the rename invalidated Three prose sites and one CI comment still described the pre-rename world, or contradicted themselves once `packages/desktop` named both the removed Electron app and the living Tauri shell. - ci.yml `desktop_shell`: the comment this branch added credited the Cargo.toml guard with keeping "branches from either side of the rename" green. It does not. A pre-rename head's files sit under `packages/desktop-shell`, which the changed-files filter no longer matches, so the job skips before the guard ever runs. Say that, and say what the guard does cover (a head the filter matched because ci.yml itself changed, with no crate at the new path). - docs/design/web-shell-user-message-links.md: "desktop-shell routing" / "desktop-shell clicks" -> "desktop-host", the wording this branch already chose in LinkifiedText.tsx for the same rule. - docs/design/telemetry-runtime-client-attribution-design.md: repoint the `runtime.rs` citation. It backs the live `QWEN_CODE_DESKTOP=1` claim, and the other document of record for that invariant -- the comment in acp-channel-fallback.ts -- was already repointed by this branch, so the two disagreed. Only the path token changes; the doc's dated findings are untouched. - brand-create.mjs / SKILL.md / src-tauri/src/main.rs: name the historical referent as historical (the Electron `packages/desktop` removed in PR 9085) instead of letting it read as a self-reference. In main.rs the citation `packages/desktop/packages/shared/src/config/storage.ts` now looked like a subpath of the file's own package. Rewritten, not deleted: the `QWEN_DEFAULT_WORKSPACE_DIR` clause next to it is the only in-code documentation of that override and still resolves. Deliberately not swept: `scripts/check-desktop-isolation.js`'s `packages/desktop-shell` tripwire, ci.yml's #8132 history comment, `docs/design/9152-architecture-invariant-classification.md` (names both spellings and is accurate), and the date-prefixed `docs/design/2026-07-31-desktop-web-shell-release.md`. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmug1iw422v * test(scripts): pin the desktop crate path and the isolation guard's coverage Both invariants fail green today, and this rename is the second time the crate directory has moved. `scripts/check-desktop-isolation.js` gained `'packages/desktop'` in `nativePrefixes` -- the only production-logic line in this branch -- and nothing read it. Deleting that line leaves the guard's output and exit code byte-identical, because `isNativeLocation('packages/desktop')` then matches no remaining prefix; a later PR that drops `!packages/desktop` from the root workspace list would re-admit the package with CI green. The `desktop_shell` job names the crate directory in five places (the changed-files filter, the Cargo.toml guard and its `::notice::` text, the rust-cache `workspaces:`, and two `working-directory:` values). Nothing asserted they agree with each other or with a directory that exists, so the next drift reports a skipped job as a passed one. The new suite parses both instead of re-running them, and is superset-shaped on purpose: `nativePrefixes` carries a fourth entry (the `packages/desktop-shell` tripwire) that nothing negates, and an exact-match assertion would invite deleting it. The npm/pnpm mirror of the negation list is already pinned by package-scripts.test.js, so this reads package.json only. Verified by mutation, each applied alone and then restored: reverting the filter alternative or either `working-directory` to `packages/desktop-shell`, dropping `'packages/desktop'` from `nativePrefixes`, and dropping `!packages/desktop` from package.json all turn this suite red. Today no other test does. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmug1iw422v * test(scripts): pin what the desktop-isolation tests actually claim Four review findings on scripts/tests/desktop-isolation.test.js, each verified by mutating the thing it claims to pin, before and after. - The comment above the local `isNativeLocation` copy claimed a change to the script's rule "has to be made here too". Nothing reads the rule back from the producer -- `nativePrefixesFromSource` parses the array literal only -- and narrowing the script's rule to prefix equality leaves the suite green. Describe the copy instead of claiming coupling that does not exist. - `still carries the Cargo.toml existence guard` matched only the guard's condition text. Flip the body's `changed=false` to `changed=true`, or move it after `fi`, and the suite stayed green at 5/5 while the job runs every gated step against a crate that is not there. Assert the assignment sits inside the guard's own `if ... fi` body. - Both on-disk checks keyed on the bare directory, so git-ignored residue under `packages/desktop-shell` (`node_modules`, which survives a branch switch with an empty `git status`) reddened two tests on a tree with no defect and blamed the root workspace set. Key on `package.json`, which is what `packages/*` requires to make a directory a workspace member; a real re-entry still reddens both. - The `startsWith(filterAlternative)` assertion compared a path built from `crateDir` -- `filterAlternative` with one trailing slash stripped -- back against `filterAlternative`, so it could not fail for any input. Dropping the trailing slash from the changed-files filter in ci.yml left it green. Replace it with the property that makes the alternative a path prefix rather than a bare string prefix. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmugedurp3j --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
b7543aeb1b |
feat(browser-use): add Chrome Native Messaging relay (#11242)
* feat(browser-use): add Playwright browser SDK
* docs(browser-use): document browser use architecture
* fix(browser-use): make browser input actions reliable
* feat(browser-use): preserve screenshot coordinate metadata
* fix(browser-use): recover stale sockets across VM realms
* fix(browser-use): bound locator action retries
* fix(browser-use): keep page input in the background
* fix(browser-use): reject ambiguous input arguments
* fix(browser-use): validate locator composition identity
* fix(browser-use): recover socket locks across VM realms
* fix(browser-use): preserve input results across navigation
* fix(browser-use): capture screenshots through bounded CDP frames
* fix(browser-use): separate input and navigation waits
* feat(browser-use): add Chrome native relay
* fix(chrome-extension): avoid foreground tabs and stale cursor markup
* fix(chrome-extension): require Chrome 125 for flat sessions
* feat(browser-use): add product integration
* test(browser-use): add managed Chrome smoke coverage
* feat(node-repl): expose structured image metadata
* test(browser-use): preserve complete smoke reports
* feat(browser-use): bundle skill and runtime with CLI
* fix(browser-use): install pinned Playwright in fresh workspaces
* feat(browser-use): require explicit skill opt-in
* feat(browser-use): make bundled skill available by default
Keep explicit skill disables authoritative, update documentation and tests, and use the latest Node REPL package in setup instructions.
* fix(ci): build browser-use before Live Host publish
Build the bundled browser runtime before core in the Live Host npm dependency chain, and cover that prerequisite order with a regression test.
* fix(browser-use): output screenshot metadata explicitly
* fix(node-repl): preserve image metadata outside prose budget
* fix(browser-use): address review round on workspace wiring and runtime correctness
- register the workspace in .pnpmfile.mjs, pnpm-lock.yaml, and the
unit-vitest-configs registry, with the shared-pool timeout ternary and
off-Linux unhandled-error exemption (fixes the red Install/Test checks)
- map Playwright's 'warning' console type to the contract's 'warn' level
- reject captures whose pixel dimensions contradict the css-pixels
coordinate contract instead of certifying rescaled images
- keep one unattachable derived tab from failing tabs.list while still
propagating a lost session
- clear the cached dialog when Chrome resolves it out of band or the page
navigates, guarded by dialog identity so a newer dialog survives
- synthesize a parseable Browser.getVersion (numeric Chrome major, host
platform token) so Playwright enables the right keyboard editing commands
- keep YAML-quoted snapshot keys and link props in interactive listings and
stop claiming subtrees that filtering removed
- always release the mouse button when a drag gesture fails
* fix(dev): build browser-use runtime before startup
* fix(browser-use): isolate cleanup and correct smoke checks
* fix(browser-use): resolve managed Chrome through Playwright
* fix(browser-use): harden native relay and tab lifecycle
* fix(browser-use): drain host output and persist restored tab state
* fix(browser-use): scope dialog handles and clean navigation waiters
* fix(browser-use): preserve input outcomes and release modifiers
* fix(browser-use): drain session teardown and release debugger attachments
* fix(browser-use): correct locator validation and evaluation
* fix(dev): reuse prebuilt Browser Use runtime
* fix(browser-use): address review round on locator, bridge, and screenshot correctness
Co-authored-by: Qwen-Coder <[email protected]>
* fix(browser-use): require installed extension before native host setup
* fix(browser-use): address review round on schema probe bound and regex validation
* fix(browser-use): start transport before Chrome preflight
* fix(browser-use): exclude staged runtime from code checks
* fix(core): declare Browser Use build dependency
* fix(browser-use): preserve successful navigation and dialog input
* fix(browser-use): harden input drain and tab registration cleanup
* fix(browser-use): keep sessions bound to one Chrome profile
* fix(browser-use): bound commands and validate evaluation JSON
* fix(browser-use): reuse unchanged Native Host registration
* fix(browser-use): wait for fresh extension installation
* fix(browser-use): address review round on screenshot origin, dialog scope, and bridge privacy
- screenshot: tolerate settle-probe failure (measure the ratio from the
captured pixels, re-capture on HiDPI), measure layout after the settle
wait, and reject screencast frames whose scroll offsets disagree with
the published origin
- session: clear the cached dialog only on main-frame navigation;
abort tab attachment when the tab is removed mid-attach
- errors: classify crashes and timeouts by Playwright's structured error
name instead of page-influenced message text
- locator.press: release chord modifiers when a later token is rejected;
cap locator.type at the 60k characters its per-character budget can
deliver inside the 120s ceiling
- snapshot: keep AI-mode [cursor=pointer] generic nodes in the
interactive listing
- bridge: derive the fallback socket directory as an env-independent
per-user 0700 subdirectory on all POSIX hosts and verify ownership
before binding
* fix(browser-use): close review-critical gaps in error mapping, budgets, and downloads
- errors: classify by Playwright error name first; text phrases match only
the start of the first message line so page-controlled text (log tails,
quoted markup, page-thrown values) cannot pick the reported code, and a
TimeoutError name wins over crash-shaped page text
- transport: cdp.send bridge requests default to 130s so operations up to
the 120s schema ceiling report their own deadline; other requests keep
the 30s default
- transport: the /tmp fallback socket directory is a per-user leaf directly
under the sticky root (no shared intermediate a first mover could own);
ensureSocketDirectory re-verifies the leaf after creation and walks
ancestors up to the sticky root, requiring each to be owned by this user
or root and not group/other-writable
- runtime: withModifiers no longer rewrites a completed action into a
failure when a modifier release fails; chord failure cleanup releases the
chord's own tokens (including non-modifiers) instead of four fixed names
- playwright: enable CDP download events on tab attach (Playwright's
noDefaults connect leaves them off, so waitForEvent('download') could
never resolve); locator.downloadMedia races the caller deadline, aborts
the in-page fetch at it, resolves media contained in a located wrapper
before an ancestor link, restricts URL schemes, and names CORS rejections
distinctly; locator.allTextContents waits for the first match within the
caller budget and still resolves [] when nothing attaches
- screenshot: full-page captures get a 16 Mi-pixel budget (1920x3000 pages
now succeed) and the encoded byte ceiling drops to the 4 MiB model image
limit so captures are not dropped at the model boundary
- snapshot: interactiveOnly promotes only a terminal [cursor=pointer]
attribute (page text quoting the marker no longer promotes the line), and
truncation skips over-long lines instead of discarding the rest
- schemas: reject empty string/regex matchers and exact:true combined with
a regex matcher (Playwright silently drops exact for regexes)
- tests: the SDK evaluate fixture now mirrors production serialization;
POSIX socket tests carry win32 gates; posix.join keeps the derived socket
path a pure function of uid and platform on every host
* fix(browser-use): close review criticals in error mapping, chords, downloads, and snapshots
- errors: classify Playwright's genuine strict-mode violation, which
crosses CDP as the raw exception description and reaches the client
behind an "Error: " layer ("locator.click: Error: strict mode
violation: ... resolved to N elements:"); requiring the element count
keeps a page-thrown lookalike from forging LOCATOR_NOT_UNIQUE
- runtime-helpers: on a failed chord press, release the tokens
Playwright actually derived ('+' separates only after a non-empty
token, so a standalone '+' is a literal key) rather than the caller's
array elements; an element embedding '+' previously released nothing
and left modifiers held. locator.press uses the same tokenizer
- locator.downloadMedia: resolve an ordered candidate list (element,
media descendants, anchor descendants, closest ancestor) and keep the
first candidate that exposes a URL, so a wrapping anchor no longer
beats the image it contains and a source srcset or an unloaded
video's source child can supply the URL
- snapshot: unwrap Playwright's single-quoted YAML key before the
[cursor=pointer] suffix test, so clickable nodes whose accessible
name forces key quoting stay in the interactive listing
- docs: align the Input completion contract with the shipped modifier
cleanup semantics (cleanup failures are discarded; only the action's
own error propagates) in both languages
* fix(browser-use): close round-13 review criticals in errors, srcset, evaluateAll, snapshots, and screenshot origin
* fix(browser-use): point the pnpm importer at a vitest snapshot that exists
Merging main brought in #11625, which regenerated pnpm-lock.yaml and
dropped the [email protected] snapshot keyed with @vitest/browser and
[email protected]. The packages/browser-use importer still referenced
that key, so every Install leg failed with
ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY. Re-key the importer to the snapshot
its sibling packages already use; nothing else in the lockfile changes.
* fix(browser-use): close round-14 criticals in error classification, dialog ordering and screenshot ratio
R13-2: the strict-mode branch of sanitizeOperationError was the only
text-phrase branch not gated on the evaluate channel, so a page-thrown
primitive "strict mode violation: ... resolved to 2 elements:" picked
LOCATOR_NOT_UNIQUE. On that channel only Playwright's "Error: "-wrapped
form classifies now; other channels keep the unwrapped form.
R14-1: Playwright hands a dialog over on a later turn than the bridge
reports its CDP events (a microtask in CRSession plus the in-process
dispatcher's setImmediate), so an open+close pair delivered in one chunk
left a phantom dialog that blocked the tab. Each tab now traces dialog
openings and closes in bridge order and drops a delivered dialog the
bridge already reported closed; a close with no traced opening (a dialog
open before the tab was attached) is never charged to a later dialog, and
the microtask clear stays for the delivered case.
R14-2: window.devicePixelRatio is page script, and a spoofed value became
an unbounded clip.scale while the pixel re-measure only ran when the
probe failed. The probed ratio is now trusted only within 0.25..8, and the
measure-and-recapture correction runs whenever the first fallback capture
disagrees with the requested CSS region, deriving the real ratio from
Chrome's own pixels (measured / (width * scale)).
Also resolve the temp root in the ensureSocketDirectory tests: the
ancestor sweep rejects symlinks, and macOS reaches os.tmpdir() through
/var -> /private/var, so the tests failed locally on macOS.
* fix(browser-use): tear down accepted peers on start failure and pin the transport's untested paths
The esbuild banner declared require/__filename/__dirname/process bindings
the bundle never uses, so any bundled module declaring one of them built
green but failed to load; drop it (and the unused .wasm loader) and import
dist/index.js after bundling so an unloadable bundle fails the build.
When start() fails after listen (chmod, handshake), a peer validated in
between kept server.close() waiting forever; destroy and clear the
accepted sockets first, mirroring stop(). net.Server has no
closeAllConnections(), so that is the whole fix.
Tests now cover the QWEN_BROWSER_USE_SOCKET_PATH override, a hello with a
mismatched protocol version or extension id, onConnectionChange on the
real transport, an in-flight request when the extension disconnects and
the configured request budget, the ok:false error-code mapping,
FrameDecoder split-frame reassembly and its length ceiling, the
start-failure teardown, and all five schema refine predicates.
* fix(browser-use): mirror the contract bounds in the SDK and state the documented limits
nth() now rejects indexes outside the contract's -10000..10000 before
dispatch, and all() fails closed when the plan already has 32 steps or
the match count exceeds what nth() can address, instead of handing back
locators that only fail on first use. Both evaluate script builders
normalise method-shorthand and class-method sources the way Playwright
does (compile-only vm.Script probe, then a function prefix), so those
well-typed callbacks no longer die as a page-side SyntaxError.
providerTab clamps title and url to the claimTab schema's 20000-char cap
so the documented openTabs() -> claimTab() round trip survives long URLs,
and orderOpenTabs() establishes the http(s)-only, newest-first listing
the model documentation promises. downloadMedia derives the file name
from the URL path only for http(s) sources and leaves blob:/data: names
to the browser.
The model-facing documentation now states the 1s read default, that
dom_cua.scroll's x/y are wheel deltas rather than coordinates, and that
a cross-origin resource without CORS headers cannot be downloaded from
the page origin; the design docs record that boundary as follow-up work.
Tests pin every one of these, plus buildLocator's frame, combinator,
filter and positional branches, the file-chooser SDK surface, and the
claimTab argument guards.
* fix(browser-use): keep background tab registration from moving the selection
registerTab selected every tab it registered, and two of its callers are
background paths (derivedTabTracked, syncDerivedTabs via tabs.list), so
a read-only tabs.list could move tabs.selected onto a popup. Selection is
now set only by newTab and claimTab from the info they return.
Also: tabs.get is allowed while a dialog is open, matching tabs.list and
tabs.selected, which already return the dialog-safe TabInfo; the
auxiliary-button click moves Playwright's tracked cursor before sending
the CDP button events so a later wheel lands where the click did; the
dead providerTabId lookup is removed; openTabs applies orderOpenTabs.
Tests: the runtime test file mocks node:timers so vi.useFakeTimers()
actually controls the input drain bound (the 250ms test drops to ~0ms),
and new cases pin the drain clearTimeout, the registration probe's
session detach, promptText pass-through, tabs.get under a dialog, the
openTabs/claimTab fail-closed guards and ordering, popup adoption from
derivedTabTracked, the abandoned navigation waiter's swallowed rejection,
the uploadFiles path guards, and the screencast fallback and byte budget
on the unconstrained capture path.
* test(browser-use): pin the element bindings the runtime gives evaluate scripts
The SDK emits scripts that read the free variables `element` and
`elements`, and the runtime binds them when it compiles the script inside
the page; no test ran either page-side callback, so swapping the binding
name on one side kept the suite green while every locator.evaluate would
throw a ReferenceError in production. Run the real callbacks with fake
elements so the contract is pinned from both ends.
* fix(browser-use): fail closed on page-controlled strict-mode text and prefer contained media over anchor hrefs
* fix(browser-use): bound page title reads and download a located anchor's file over its icon
* fix(browser-use): correct media downloads and frame composition
* fix(browser-use): bound locator.count and allTextContents by the caller deadline
* fix(browser-use): preserve native snapshots for DOM CUA
Co-authored-by: Qwen-Coder <[email protected]>
* fix(browser-use): classify a closed tab from the tab's own state
The pinned playwright-core client renders a closed target as a plain Error:
only TimeoutError sets `name`, so the `name === 'TargetClosedError'` branch
in sanitizeOperationError never fired, and because evaluate-channel text
fails closed by design, a tab that closed or crashed while a page command
ran was reported as OPERATION_FAILED instead of the documented STALE_TAB.
Decide tab-gone in the dispatcher from `tab.stale` and `page.isClosed()`,
which the page observers keep current, before the text classifier runs.
Drop the dead name branch and replace the test that fabricated the name
with one built the way the client builds the error, plus dispatch-level
cases for both signals that fail without the dispatcher check.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
* fix(browser-use): restore the kernel realm process binding and land the round-5 review batch
Criticals from review round 5, each reproduced before fixing:
- The bundled skill imports the staged runtime inside the node_repl kernel,
whose untrusted vm context has no `process` global and denies the
`node:process` specifier.
|
||
|
|
3ecfaffdf8 |
perf(dev): add pnpm worktree bootstrap foundation (#10449)
* perf(dev): add pnpm worktree bootstrap foundation Co-authored-by: Qwen-Coder <[email protected]> * fix(dev): harden worktree bootstrap process handling Co-authored-by: Qwen-Coder <[email protected]> * perf(dev): prefer cache-only worktree installs Co-authored-by: Qwen-Coder <[email protected]> * fix(dev): preserve cached install cancellation Co-authored-by: Qwen-Coder <[email protected]> * fix(build): harden pnpm worktree bootstrap Validate pnpm lock updates in releases and exercise real installs and builds across supported hosts. Preserve npm release compatibility and keep dependency-only setup from rewriting npm-layout notices. Co-authored-by: Qwen-Coder <[email protected]> * chore: record merge attribution Record the required attribution for the Stage 1 merge without rewriting published history. Co-authored-by: Qwen-Coder <[email protected]> * fix(dev): keep worktree bootstrap clean Use a bootstrap-scoped notice guard because nested npm lifecycle commands replace npm_lifecycle_event. This preserves explicit notice generation while preventing dependency setup from rewriting tracked output. Co-authored-by: Qwen-Coder <[email protected]> * ci: track pnpm smoke workflow size Register the new workflow in the repository size ratchet as required by the main CI gate. Co-authored-by: Qwen-Coder <[email protected]> * fix(ci): drop stale importers from the new pnpm lockfile The lockfile was generated before the WebShell cutover (#9811) removed @qwen-code/webui from web-shell and the tailwind tooling plus @qwen-code/webui from vscode-ide-companion, so frozen-lockfile installs fail on all three smoke platforms with ERR_PNPM_OUTDATED_LOCKFILE. Drop the five stale importer entries so the lockfile matches the current package.json manifests; verified with pnpm 11.24.0 install --frozen-lockfile --lockfile-only. Co-authored-by: Qwen-Coder <[email protected]> * fix(ci): refresh pnpm lockfile after merging main The merge of origin/main added remend@^1.3.1 to packages/cli/package.json without updating pnpm-lock.yaml, breaking the pnpm Worktree Smoke workflow frozen-lockfile install. Regenerated with pnpm install. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmtid3rse9h * fix(scripts): resolve the path variable case-insensitively on Windows A spread of process.env is an ordinary object, and native Windows shells expose the path variable as `Path`, so `env.PATH` was undefined there and findOnPath never located corepack — the offline-first Corepack bootstrap silently degraded to npx on exactly the hosts it exists for. Co-authored-by: Qwen-Coder <[email protected]> * test(scripts): pin the worktree bootstrap guards against mutation - Split the fallback log on /\r?\n/ like the sibling cmd.exe mocks, so the assertion holds on the Windows lane's CRLF output. - Add a win32 variant bootstrapping with the native `Path` casing to pin the case-insensitive lookup. - Assert the smoke workflow's fail-fast flag, the install-before-clean step order, and the no-build guard via a substring on the raw job text. - Extend the pnpmfile rewrite fixture to devDependencies and optionalDependencies, which the committed lockfile already uses. - Assert the notice-skip guard by effect (writeFile never called) and add the flag-absent companion test with I/O stubbed. Co-authored-by: Qwen-Coder <[email protected]> * chore(deps): sync pnpm-lock.yaml with qwen-live ACP backend deps Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmtjyz3tdco * fix(dev): stop patch-package from corrupting the pnpm store The root postinstall runs patch-package, which rewrites files under node_modules in place. With pnpm's default import method those files are hard links into the content-addressable store, so the patch rewrites the store entry too and its contents stop matching the sha512 it is filed under. Every subsequent fresh worktree then fails its --offline stage with ERR_PNPM_NO_OFFLINE_TARBALL, silently falls back to the registry (exit 0), and the fallback's postinstall corrupts the store again, so the offline path never hits. The advertised offline timing was only reachable on a same-tree reinstall, which needs no relinking. Set packageImportMethod to clone-or-copy: a copy-on-write clone where the filesystem supports it, a plain copy elsewhere. Either way patch-package edits only the worktree's own copy and the store entry stays intact, so later worktrees resolve entirely from the store. Verified on an isolated fixture store: under the default method the node_modules file and its store entry share an inode, and an in-place edit moves the store file's sha512 off its address, after which a fresh offline install fails with ERR_PNPM_NO_OFFLINE_TARBALL; under clone-or-copy the same edit leaves the store hash unchanged and the fresh offline install reports reused 1, downloaded 0. Also add pnpm-lock.yaml to .prettierignore. prettier reflows it into a shape pnpm does not emit, so `npm run format` and `pnpm install` fight over the file; .yamllint.yml already ignores it for the same reason. Both facts are pinned by tests in scripts/tests/package-scripts.test.js. Claude-Session: https://claude.ai/code/session_012797rgiteWJxLT9TLkKq8G * fix(ci): refresh pnpm-lock.yaml for qwen-live prompts deps Main added prompts/@types/prompts (and the ACP sdk) to packages/qwen-live/package.json after this branch generated its lockfile, so the pnpm Worktree Smoke frozen-lockfile install failed with ERR_PNPM_OUTDATED_LOCKFILE. Regenerated with pnpm 11.24.0 (--lockfile-only); frozen-lockfile and supply-chain policy checks pass. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-conflict/jmtlc9sozfg * fix(pnpm): close review findings on worktree bootstrap - Declare @qwen-code/qwen-code-core in vscode-ide-companion so the pnpm linker materializes it; regenerate both lockfiles and assert the link in the smoke workflow (R5-1) - Pin @types/node 20.19.1 in packages/core so the pnpm layout compiles against the same types npm hoists (D6-1) - Accept and pin the corepack +sha512 integrity suffix on packageManager; strip it for the npx fallback spec (D6-2) - Cover every workspace member in the pnpmfile rewrite set, mirror the npm channel list in pnpm-workspace.yaml, and cross-check both in tests - Run setup-worktree.js installs with cwd pinned to the checkout, gate the smoke clean-check on git status --porcelain, stop post-merge runs from cancelling each other, and extend check-lockfile.js to pnpm-lock.yaml * merge(main): realign pnpm workspace set and lockfiles Main removed the webui and cua-driver packages; drop both from the pnpm rewrite set and regenerate the pnpm lockfile against the merged manifests (picks up playwright, react-markdown, and the other main-side dependency changes) so the frozen bootstrap matches what the PR merge ref will run. * style(ci): quote smoke workflow scalars per yamllint * fix(dev): require Corepack for pnpm bootstrap * fix(dev): close pnpm bootstrap review blockers --------- Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: yiliang114 <[email protected]> |
||
|
|
5b470befa0 |
ci: make the Prettier lane a real gate (#11117)
* chore: format the 35 files CI had been silently rewriting `scripts/lint.js --prettier` and the release workflow's `Format Project` step both run `prettier --write`, which reformats in place and exits 0. Neither is followed by a dirty-tree check, so the rewrites are discarded when the job ends and these files have stayed unformatted on `main`. This is the output of `prettier --write` over exactly those files, so the next commit can turn the check into a real gate without failing on a backlog. No behaviour change: every hunk is whitespace, quoting or wrapping. Verified with prettier 3.6.1, the version pinned in package-lock.json. `prettier --check .` over the whole repo reports these 35 and nothing else. Refs #11109 * fix(ci): make the Prettier lane a real gate `runPrettier()` ran `prettier --write .`. Prettier exits 0 after reformatting, and no caller checks the tree afterwards, so the lane passed on unformatted code and CI threw the rewrites away — the 35 files in the previous commit are what it had been silently fixing and discarding. ESLint does not cover the gap: eslint.config.js loads eslint-config-prettier, which disables formatting rules rather than enforcing them. With this change the only enforcement point outside the husky pre-commit hook actually enforces something. `npm run lint:all` now reports unformatted files instead of fixing them; `npm run format` is the fix. Prettier's own failure message says so. Refs #11109 * fix(release): drop Format Project, it writes and discards The step ran `npm run format` (`prettier --write .`) and nothing in release.yml inspected the tree afterwards — no `git diff --exit-code`, no `git status --porcelain` anywhere in the file. The rewrites died with the job, so the only failure it could produce was Prettier crashing on an unparsable file, which the Run Lint step reports anyway. It cost 13m58s on a quiet host and 20m45s on a contended one, against a 30-minute cap that `quality_static` hit twice today (runs 33957952281 and 33963757913, both cancelled mid-lint with nothing failing). The remaining steps are `npm ci` (1m44s) and `lint:ci` (~8m20s), so the job now has real headroom instead of finishing 24 seconds over the wall. Formatting is now gated where it belongs: the previous commit makes the PR-CI Prettier lane `--check`. Refs #11109 * fix(ci): keep prettier --check out of .qwen/ and the pre-paint theme script Two things the `--write` → `--check` flip broke that `--write` had hidden. `.qwen/` is gitignored as `.qwen/*` and holds machine-written state — pending-skills/, auto-skill-*/, learned-skill-*/, computer-use/installed.json. Prettier does not read .gitignore, so it was walking in and silently reformatting whatever a contributor had there; under `--check` that turns into a failed `npm run lint:all` on files git does not even track. CI never saw it (fresh checkout, tracked files only), which is exactly why it went unnoticed. Adding `.qwen/` to .prettierignore also drops the one tracked file under it — skills/find-simplifications/SKILL.md, force-added past .gitignore — from the previous formatting commit, since a directory the gate should not police should not be reformatted for it either. The inline theme script in web-shell's index.html is restored to its original single line behind `<!-- prettier-ignore -->`. It is a render-blocking script in <head> that applies the stored theme before first paint; the expanded form ships ~600 more bytes on the critical path and buys no readability the comment above it does not already give. A change about CI hygiene should not be reshaping that. Refs #11109 * fix(ci): keep prettier --check out of vendored packages/mobile-mcp eslint.config.js has ignored `packages/mobile-mcp/**` since it landed — "vendored mobile-next/mobile-mcp; has own eslint config" — and .prettierignore already carries its sibling `packages/cua-driver/`, listed one line above with the same rationale. mobile-mcp was simply missed. `--write` hid that: it reformatted the vendored package's own eslint config to our house style every run and threw the result away. The formatting commit in this PR would have made that permanent, widening the diff against upstream on the next sync for a package this repo has already decided not to lint. That file is reverted here and the directory is ignored. Same class as the .qwen/ fix in the previous commit: the gate reaching somewhere the repo had already decided it should not. Refs #11109 * fix(ci): mirror eslint's remaining global ignores in .prettierignore `--check` makes .prettierignore load-bearing in a way `--write` never was: under `--write` a file prettier should not touch was reformatted and the result discarded, so nobody noticed; under `--check` it fails the lane. These three are the rest of eslint.config.js's global ignores, added for the reasons it already states. `scripts/codemod/fixtures/` is the one that matters: those files are "intentionally non-idiomatic ink input/output", so the obvious response to a `--check` failure there — reformat to house style — would corrupt the fixtures the codemod tests assert against. The trap is not live today (all three currently satisfy prettier), which is precisely why it is worth closing before someone meets it. Refs #11109 * chore: format converter.test.ts, which drifted onto main since this branch This branch merged main 32 commits after its base and `prettier --check .` found one new offender. It is the same gate failing the same way: nothing enforces formatting, so `--write` reformatted this file on every CI run since it landed and threw the result away. Worth noting as evidence rather than noise — the backlog this PR fixes was not a one-off from before someone got careless; it accrues continuously, and it accrued again while the PR was open. Refs #11109 * Revert "fix(release): drop Format Project, it writes and discards" This reverts the release.yml half of this PR. #11195 removes that step on its own, in one file and four lines, and two PRs racing on the same deletion helps nobody. The reasoning and the evidence are unchanged and now live on #11195: the dry-run release dispatched from this branch with the step removed (34022919438) went 18/18 green in 65m43s, quality_static finished in 7m00s against main's 8m57s, and Run Lint was 4m52s vs 4m43s — nothing downstream ever read what the step produced. Dropping release.yml from this PR also widens who can review it. It was the only file here owned by @pomelo-nwu and @wenshao alone; what remains under CODEOWNERS is /packages/core/, whose owner list is six people. The Prettier gate no longer waits on the two maintainers who must sign off on release workflow changes. Refs #11109, #11195 * fix(ci): make the gate resolve the file set npm run format resolves Two review findings, one root cause: the gate was checking a different set of files than the tree it is supposed to police. **The `.qwen/` ignore rested on a false premise (R1-1, @chiga0).** Prettier 3.6's `--ignore-path` already defaults to `[.gitignore, .prettierignore]`, so every machine-written path that entry's comment named — `pending-skills/`, `auto-skill-*/`, `learned-skill-*/` — was outside the gate before it via `.gitignore:32`. What the entry actually excluded is the corpus `.gitignore` deliberately re-includes: `.qwen/commands/**`, `skills/**`, `agents/**`, `team-memory/**`, `review-context.json` — 57 tracked, hand-authored files. The gate then passed because the surface had been narrowed, not because the tree was formatted, and contributors editing those docs could ship them unformatted with both enforcement points silent. The entry is dropped and the first commit's formatting of `skills/find-simplifications/SKILL.md`, reverted alongside it, is re-landed. **The gate and the remedy used different CLIs (R1-2).** `runPrettier()` ran the classic `prettier --check .` while `npm run format` runs `prettier --experimental-cli --write .`. The classic CLI reads only the repo-root `.gitignore`; the experimental one also honours nested ones, and this repo has 23 of those. Verified on a scratch tree: given `pkg/.gitignore` containing `lib/`, classic reports `pkg/lib/nested.js` and experimental skips it. So the lane could go red on a locally built package's output that `npm run format` provably cannot clear. The gate now uses the same CLI as the remedy it names. Refs #11109 * fix(ci): let the pre-commit hook cover what the gate now checks, and pin it **The hook was narrower than the gate (R1-5).** `lint-staged` formatted only `*.{js,jsx,ts,tsx}` and `*.{json,md}`, but the gate checks every extension Prettier has a parser for. Of the 35 files the first commit formatted, 29 (83%) are in classes the hook never touched — 13 `.yml`, 12 `.mjs`, 3 `.css`, 1 `.html`. Left alone, the backlog this PR just cleared would re-accumulate, and now as a red CI step on someone else's PR rather than as silent drift. `.mjs`, `.cjs`, `.yml`, `.yaml`, `.css` and `.html` join the Prettier-only group; ESLint's globs are unchanged, since the gap is about formatting coverage, not lint coverage. **Nothing pinned the flag (R1-4).** `scripts/tests/lint.test.js` exercised only the linter-directory helpers, and `ci-platform-lanes.test.js` asserts that the `Run Prettier` step exists and is profile-gated, not what it runs. A refactor, or a well-meant "make lint auto-fix again", could restore the silent pass with every suite green. Two assertions now pin it: that `runPrettier()` checks rather than writes, and that it uses the same Prettier CLI as `npm run format`, so the two cannot drift apart again the way R1-2 found them. Refs #11109 * docs: correct the instructions and comments the --check flip falsified **Three tracked instructions to automation agents now say the opposite of what the code does (R1-9), and one is fed to a CI lane today** — `.github/workflows/qwen-triage.yml` re-pins `verify-pr` from the base commit and hands it to the verifying agent. - `verify-pr/SKILL.md` told agents never to run `scripts/lint.js` with no arguments because it would rewrite the working tree under their A/B harness. That is no longer why. The prohibition is kept — it is still right — but re-grounded in what the no-arg form actually does now (`setupLinters()` wipes the linter temp dir and re-downloads three pinned binaries), and `--prettier` joins the enumerated non-mutating checks it was the only flag missing from. - `find-simplifications/SKILL.md` and its `references/land.md` told the simplification agent that a formatting diff "carries zero signal" because CI runs `--write`. An agent believing that would skip `npm run format` after a deletion changed line shape — on the very extensions the hook does not cover — and go red on formatting it was told could not matter. - `update-ecs-runner-qwen-workflow.test.js`'s comment justified parsing two matrix layouts by "CI runs `prettier --write .` before this suite". CI no longer rewrites anything; the two layouts are still worth parsing, so the comment is re-grounded in the checked-in form versus older branches. **The index.html rationale overstated its own number (R1-8, @chiga0).** It claimed the expanded script ships "~600 more bytes"; measured against this repo's Prettier 3.6.1 and its `tabWidth: 2`, it is +258 source and +8 gzipped here, +287/+20 by the reviewer's method — either way roughly half what was claimed, and "~600" is what the same expansion costs at `--tab-width 4`. Since the prose ships verbatim inside the built `index.html`, the fix is to drop the contested figure and keep the comment short. The `<!-- prettier-ignore -->` guard itself stays: it is load-bearing. Refs #11109 * chore: format classify-profile.test.mjs, drifted again after commit 1 Third instance in this PR's lifetime, and the sharpest: commit `b1b94a8762` formatted this exact file as one of the 35, and `main` reintroduced unformatted content in it within a day. The other two were `converter.test.ts` at the first merge and this file at the second. The gate is the fix; until it lands, every merge from `main` re-opens the same hole. Refs #11109 |
||
|
|
ce72ddbe6c |
feat(desktop): remove packages/desktop after OpenWork fork; keep the Tauri upgrade bridge (#9085)
OpenWork (modelstudioai/openwork) has forked the Electron desktop code and is self-contained now, so retire the Electron package and its release/sync machinery from this repo: - Delete packages/desktop (Electron app, live-host app, bun workspace). - Retire scripts/desktop-openwork-sync.ts and the desktop-openwork-sync root script; the OpenWork sync is no longer needed. - Retire .github/workflows/live-host.yml, live-host-release.yml and sync-live-host-to-oss.yml; live-host releases now live in OpenWork. The CLI-side packages/cli/src/serve/live code stays for now (separate cleanup). - Retire scripts/check-voice-guard-sync.js (cli<->desktop parity only) and its CI step. - Clean up remaining references: root package.json workspaces negation and package-lock.json, eslint/prettier/yamllint ignores, architecture docs, web-shell skill descriptions, and review-lib workspace fixtures/comments (renamed to point at packages/desktop-shell, the remaining negation). Deliberately kept: the Electron->Tauri upgrade bridge — desktop-release.yml (incl. the electron_bridge input), create-electron-bridge-manifest.mjs, sync-desktop-to-oss.yml (mirrors Tauri desktop-shell artifacts only) and everything under packages/desktop-shell. |
||
|
|
fa8b2ad87a |
feat(acp): support /cd command in ACP sessions (#5903)
* feat(acp): support /cd command in ACP sessions Implements the server-side /cd command for ACP multi-session architecture: - Infrastructure: ext-method constant, bridge types, CdWhilePromptActiveError - Core: skipProcessChdir option in Config.relocateWorkingDirectory() - ACP child handler: trust check, fs validation, sandbox guard - Bridge: promptQueue-serialized changeSessionCwd with event publishing - HTTP route: POST /session/:id/cd with error-to-status mapping - directory_not_found → 400 - directory_not_trusted → 403 - restrictive_sandbox → 403 - session_busy (CdWhilePromptActiveError) → 409 SDK client wrappers and capability registration are deferred to a follow-up PR once the server-side implementation is validated end-to-end. Closes #5677 * qwen: address PR review feedback (#5903) - [Critical] Thread skipProcessChdir through prepareSessionArtifactMigration to prevent corrupting shared daemon process.cwd() on rollback in ACP mode - [Suggestion] Raise cd timeout to Math.max(initTimeoutMs, 30_000) for large-project fs ops and memory refresh - [Suggestion] Move errorKind-to-HTTP mapping (restrictive_sandbox, directory_not_found, directory_not_trusted) into sendBridgeErrorImpl; cd route catch block now matches /branch and /fork pattern * fix(acp): address review feedback on /cd implementation (#5903) Critical fixes: - Do not overwrite entry.workspaceCwd — session stays listed under the daemon's bound workspace; logical cwd lives in agent Config only - Queue tail tied to raw extMethod settlement, not timeout — subsequent prompts cannot run against unknown cwd state after caller timeout - Add realpath equality check for skipProcessChdir path to guard against TOCTOU symlink swaps between trust check and state update - Skip artifact migration for ACP /cd (skipArtifactMigration option) — storage stays at bound workspace so branch/load/lifecycle remain consistent Suggestions addressed: - Add response shape validation for extMethod result - Rename CdWhilePromptActiveError HTTP code from 'session_busy' to 'cd_while_prompt_active' (avoids collision with SessionBusyError) - Add null-byte path validation in ACP sessionCd handler - Add operator logging on successful cwd change (warnings included) * chore: revert unrelated cua-driver formatting, add to .prettierignore Reverts 23 cua-driver files that picked up Prettier formatting noise during merge conflict resolution. Adds packages/cua-driver/ to .prettierignore since it's a vendored package whose content should not be auto-formatted by local hooks. --------- Co-authored-by: qwen-code-dev-bot <[email protected]> |
||
|
|
62e45c567f | feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) | ||
|
|
32fbedabd6 |
feat(ci): add auto-generated CHANGELOG.md synced from releases (#4872) (#4881)
* feat(ci): add auto-generated CHANGELOG.md synced from releases (#4872) Add a Keep a Changelog CHANGELOG.md that is fully derived from the project's GitHub Releases, so users no longer have to dig through commit history to see what changed between versions. - scripts/generate-changelog.js: fetch releases via the gh CLI, keep only stable vX.Y.Z tags (nightly/preview omitted), and re-group each release's auto-generated "What's Changed" list into Added/Changed/Fixed/Performance/ Documentation/Other sections by the conventional-commit prefix every PR title uses. Zero runtime deps (node builtins + gh). - release.yml: regenerate and commit CHANGELOG.md on stable releases; the commit rides the existing release-branch PR into main. - package.json: add 'npm run changelog'. - .prettierignore: skip the generated file. - Seed CHANGELOG.md from the current stable release history. Closes #4872 * ci(release): make CHANGELOG regeneration non-blocking Add continue-on-error to the CHANGELOG step. Its only realistic failures (the gh API read and the git push) are transient, and the generator rebuilds from the full release history each run, so a skipped update self-heals on the next stable release. This keeps a changelog hiccup from blocking the version-bump PR to main that follows. * fix(ci): harden changelog generator per review Address review findings on the changelog generator: - Command injection: fetchReleasesJsonl built a shell string with the repo interpolated; switch to execFileSync (no shell) plus an owner/name format check so --repo can never be a shell payload. - Empty-response clobber: if the API returns zero stable releases (rate limit, auth, 5xx), refuse to overwrite CHANGELOG.md and exit 1 instead of committing a header-only stub. Paired with set -euo pipefail in the workflow so the failure is visible and the non-blocking step self-heals next release. - Arg parsing: switch getArgs() to parseArgs() (already imported) so a --dryrun typo errors instead of silently overwriting, and -h works as documented. - Breaking changes: capture the conventional-commit ! marker and prefix the entry with **BREAKING** (the repo uses feat()!:/refactor()!: in practice). - Bot authors: ENTRY_RE now accepts a trailing [bot] so GitHub App authors (e.g. @dependabot[bot]) are not dropped from release notes. Regenerates CHANGELOG.md (two entries now flagged **BREAKING**). * refactor(ci): simplify changelog generator Quality-only cleanup (output is byte-identical; 23 tests green): - Single source of truth for sections: derive TYPE_TO_SECTION and SECTION_ORDER from one SECTIONS list so they can't drift. - Parse each entry once: formatRelease now reuses the categorize() result for the noise check, section lookup, and formatEntry (was parsed up to 3x). - Drop the redundant sortKey field; sort directly from version. - Collapse the duplicated double-.map() setup in the selectStableReleases test. |
||
|
|
f027fdf621 | Merge branch 'main' into feat/add-vscode-settings-json-schema | ||
|
|
6d68d6ec24 | feat: update JSON Schema for VS Code settings with improved formatting | ||
|
|
d61ec772a3 | Refactor code structure for improved readability and maintainability | ||
|
|
bedd1d2c20 |
Add .prettierignore file (#6914)
|