Skip to content

fixing/merge-conflict - #1

Open
Pavitra-programmers wants to merge 4679 commits into
Pavitra-programmers:merge-conflictfrom
different-ai:dev
Open

fixing/merge-conflict#1
Pavitra-programmers wants to merge 4679 commits into
Pavitra-programmers:merge-conflictfrom
different-ai:dev

Conversation

@Pavitra-programmers

Copy link
Copy Markdown
Owner

Summary

Why

Issue

  • Closes #

Scope

Out of scope

Testing

Ran

  • ...

Result

  • pass/fail:
  • if fail, exact files/errors:

CI status

  • pass:
  • code-related failures:
  • external/env/auth blockers:

Manual verification

Evidence

  • video/screenshot link, or N/A (docs-only)

Risk

Rollback

benjaminshafii and others added 30 commits August 19, 2026 00:14
* fix(ci): restore npm trusted publishing

* fix(ci): isolate npm publish credentials
* fix(den): bound GitHub token minting

* test(den): default empty retry witness env

* test(den): isolate GitHub retry classifier
* fix(desktop): recover rejected automation credentials

* test(evals): publish automation auth evidence

* fix(evals): use current assertion evidence API
* test(evals): prove OpenCode MCP OAuth flow

* fix(ci): install OpenCode before Daytona auth

* ci(evals): install opencode CLI without lifecycle scripts before Daytona credentials
* feat(app): replace Library Add menu with kind-picker radio rows

The Add dropdown boxed six actions as menu items. Open a picker that matches the Paper add-flow: radio rows, fill-only selection, then Continue into the existing create dialog. Soften Just me / Everyone on that form the same way.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(app): drop stacked borders on Library create fields

Name, description, and prompt inputs stacked a hairline with a drop shadow or inset ring, so they read as a thick frame in the app. Use a fill well only, matching the Paper form.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(app): keep Library picker selection stable

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(ci): use supported runner for npm OIDC

* fix(evals): use current evidence recorder API
Co-authored-by: Benjamin Shafii <benjamin.shafii@gmail.com>
* fix(mcp): close unused agent sse listener

* fix(mcp): preserve agent get auth challenge

* fix(mcp): close agent get probe compatibly
* fix(desktop): reduce automation runner polling

* test(evals): update automation runner polling assertions
* feat(den): add skill-created MCP app

* fix(den): package MCP app in Docker image
* fix(den): cache hot auth lookups

* fix(den): invalidate deleted org auth caches

* fix(den): clear session liveness on bearer revoke

* fix(den): renew cached mcp session liveness

* fix(den): clear admin deleted user session caches

* fix(den): avoid db checks on cache hits

* fix(den): tombstone revoked auth cache entries
* fix(mcp): tolerate newer protocol-version headers

* fix(mcp): keep protocol-version witness free of workspace builds
…#3775)

A desktop occurrence was claimable for 60 seconds and then permanently
skipped, so a laptop that was asleep, restarting, or between networks at
the scheduled time lost the run even when it returned moments later.

Give scheduled desktop occurrences a bounded recovery window (default
15 minutes, clamped to the automation's own next occurrence, never below
one minute) and keep manual runs on the deliberate one-minute deadline.
A desktop that returns inside the window discovers the still-queued run
through the existing work query — no new claim path, no second attempt.

Name the cause when an occurrence is still missed: busy with another run
(exact, from the run table), never connected, or present but silent. The
receipt code stays runner_unavailable so existing clients read it
unchanged; the app renders the recorded message and falls back to the
previous wording for older receipts.

Report presence to management clients as a read-only view of the
liveness the work poll already records (GET
/v1/automation-runners/presence). The desktop treats a Den without the
route as presence unknown — one probe, no further polling, no warning —
so a newer desktop against an older Den keeps its Automations page
intact; only an authoritative disconnected answer renders the warning.

Align wake handling with the polling runner lifecycle: powerMonitor
resume and unlock-screen trigger an immediate deduplicated work poll (an
active run keeps its lease; no overlapping claim loops), the renderer
re-registers on the online event, and the idle work poll is bounded so a
socket left half-open by a suspended machine retries instead of parking
the loop.
* feat(den): scope MCP token liveness to OAuth grants

* test(evals): build workspace deps for grant witnesses
…reads (#3942)

* fix(automations): report Desktop execution outcomes accurately

The runner interpreted only one narrow execution-result shape. A nested
provider error or an assistant turn that reported an explicit error in
the local thread snapshot was still reported to Den as a successful run,
while a run whose assistant turn completed only tool calls — with no
closing text — was treated as incomplete until it timed out. Terminal
failure and cancellation paths also dropped the native session and
workspace identifiers the desktop engine had already supplied, so the
receipt lost the one handle a person needs to inspect what happened.

Classify the outcome from what the engine actually reported: extract
nested error messages, treat an assistant turn carrying an error as the
run's failure, and accept an idle thread whose assistant turn completed
a tool call as a successful run even without assistant text. Attach the
created session and workspace to errors thrown after thread creation so
failed and cancelled completions carry the same native identifiers a
successful one does, without fabricating identifiers the engine never
returned.

Reconnect, backoff, wake, and credential-retirement behavior is
unchanged and re-proven by the existing runner suite alongside the new
regression coverage.

* fix(automations): persist and open Desktop execution threads (#3945)

The Desktop runner reports the native session and workspace of each
execution, but Den only retained an engine receipt for cloud runs, so
the identity of the local thread never survived into the run receipt.
The Automations UI therefore could not open the thread a run actually
executed in, and a receipt fetched for a previously selected run could
be rendered — and navigated — against the currently selected one.

Persist the runner-reported session and workspace as the desktop run's
engine receipt on success, failure, and cancellation, and map it through
the existing executionThread shape for every execution target. The
receipt field is additive: older runs keep rendering exactly as before,
and the run contract is unchanged for clients that ignore the thread.

In the app, resolve a desktop thread to its local workspace session
route, render an Open local thread action on the selected run, and
accept a receipt only when it belongs to the currently selected run so
a stale response cannot navigate to an unrelated thread.

Cover the journey end to end with a Desktop lifecycle spec: UI-triggered
and scheduled runs with durable receipts and correct thread opening,
restart with queued work, concurrent manual requests, cancellation
before claim, provider outage with linked failed threads and recovery,
duplicate claim protection, expired-lease recovery, and stale-completion
rejection.
…3948)

* feat(mcp): first-party MCP App cards for connect steering flows

Every "go do X in OpenWork Cloud" moment the gateway used to steer with
plain text now renders a standard MCP App card, built from one shared
React design system in @openwork/mcp-apps:

- skill-created app restyled on the shared components, and a new
  update_skill tool publishes new immutable versions through the same
  card (updated mode) instead of raw postConfigObjectsVersions calls.
- connection-action app: executing a connection_status capability now
  returns a successful live probe whose result mounts an actionable
  card (sign in, admin setup, provider fix, connected) via a
  same-server openwork/mcpApp launch, with the app-only
  connection_action tool backing refresh probes.
- plugin-flow app: successful postMarketplacesPlugins, postPluginsAccess,
  and postMarketplacesAccess executions attach a confirmation card.

Steering text (gateway instructions, search hints, builtin skills, and
the desktop Connect instruction) now tells the model to execute
connection_status matches once so members get the card, and the
mcp-apps build stages per-app bundles atomically so parallel test runs
never observe a half-built dist.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(evals): settle session sync before card screenshots

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(evals): record card screenshots as ambient evidence

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(mcp-apps): open links from cards and match the app's design language

The desktop bridge never handled ui/open-link requests, so card buttons
(Open in Library, Connect) silently did nothing; it now routes them
through openDesktopUrl (electron shell / noopener fallback). The host
also passed no style variables, so cards rendered on fallback styling:
it now maps the live DLS tokens (surface, border, text, accent, radix
status scales, radius, shadow) onto the standard MCP Apps style
vocabulary, and the shared card UI is rebuilt to the app's native card
language — sectioned rounded-2xl cards with hairline dividers, round
soft-tone icon tiles, and the dls-accent primary button.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(app): apply trailing MCP App resize so tall cards are not clipped

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lockfile): restore xlsx tarball integrity dropped by filtered install

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
reachjalil and others added 30 commits August 28, 2026 15:22
* fix(app): dedupe session search results

* test(evals): record session search identity evidence
)

Dragging the left sidebar wider than 420px silently did nothing: the
width clamp swallowed the drag, so long session and workspace titles
stayed clipped even though the user was explicitly asking for more
room. Raise the ceiling to 600px (the right sidebar already allows
960px) so expansion past the old cap actually grants titles the space.

Covered by evals/specs/sidebar-left-width-expansion.test.ts: widths past
the old 420px ceiling are stored, and the min/max guardrails still
clamp.
* feat(automations): pin Automations to an explicit workspace

Automations carried no workspace: both the desktop runner and the cloud
executor resolved the runner's *currently active* workspace at run time
(activeId ?? workspaces[0]), so activating a different workspace silently
retargeted every automation.

A revision now carries an optional workspaceId captured at creation:

- packages/types: workspaceId on revision, legacy create, proposal, update,
  and desktop runner assignment schemas (all optional/nullable)
- digest: includes workspaceId only when set, so existing revision digests
  stay byte-identical
- den-db: nullable automation_revision.workspace_id + migration 0083
- den-api: create/update persist the pin; the desktop assignment and the
  cloud executor input carry it; cloud recovery still prefers the receipt's
  workspace, then the pin, then the worker's active workspace
- desktop runner: a pinned workspace must exist locally or the run fails
  with execution_runtime_unavailable instead of silently retargeting;
  unpinned (legacy) assignments keep the active-workspace fallback
- creation surfaces: the automation.propose affordance pins the proposing
  conversation's workspace; the proposal card falls back to the pane it
  renders in; the manual editor pins the selected workspace

Validation: desktop runner suite 38/38 (4 new witnesses), evals
automation-runner-reconnect-backoff green, den-api automation suites green
(1 pre-existing readyWorker source-witness failure exists on clean dev and
is not run in CI), den-db tests green, tsc clean for app/server/den-api.

* refactor(server): make the Connect MCP desired config account-global (#4225)

The openwork-cloud Connect MCP entry was persisted per workspace: N runtime
rows carrying the same org-scoped token, reconciled per workspace, where a
stale legacy row could shadow a fresh one and workspace switching could
rewrite the engine-visible entry and bounce the connection.

Desired config now lives in the single ENGINE_GLOBAL runtime row:

- persistDesiredConfig writes global (host connect-state copy kept as cache)
- idempotent migration promotes the newest valid legacy workspace entry to
  global before cleaning openwork-cloud out of every workspace row, runs at
  startup (cli/embedded), before persisted reconcile, and before the
  all-workspaces engine sync; read-only servers never mutate
- effective-config merge: the global openwork-cloud entry wins over any
  leftover legacy workspace copy
- dynamic engine MCP sync reads the effective config so every directory
  instance receives the global entry; delivery/health stay per directory
- token/config changes fan out disconnect+re-register to other workspaces
  only when the persisted config actually changed
- DELETE of openwork-cloud removes global desired state and disconnects
  every workspace directory; generic MCP CRUD stays workspace-scoped
- Connect catalogs, passive inspection, and agent-context diagnostics read
  the global entry first (legacy fallback kept for the migration window)

Validation: server tsc clean; health/state/inspect/skill-catalog 40 pass;
cloud-mcp-reconcile e2e 26 pass; engine-sync e2e 22 pass; diagnostics +
app-host 90 pass; full apps/server suite 787 pass / 8 skip with only the
two known environment failures (DNS guard fixture, bun node:sqlite) that
reproduce identically on clean origin/dev.
* fix(app): make composer draft hydration atomic

* fix(app): stabilize draft store snapshots

* fix(app): ignore stale draft persistence effects

* test(evals): harden composer draft reload proof

* fix(dev): build Electron workspace dependencies

* fix(app): gate draft persistence on hydration
* fix(app): keep desktop restriction checker stable

* test(evals): bound Library lifecycle requests
* fix(app): stop den-session settings echo loop

* test(evals): wait for the skill card before opening it

* test(evals): assert signed-in inventory stability
* fix(security): remediate CodeQL findings

* docs(security): record CodeQL verification

* fix(security): remove ambiguous password hash paths

* fix(security): harden CodeQL remediation boundaries

* fix(security): remove assessment reports and key OAuth bindings

* fix(desktop): mirror server HTML parser dependency

* fix(ci): make Daytona regression CLI install portable

* fix(ci): locate global OpenCode package under pnpm 11

* fix(ci): select the installed OpenCode package path

* fix(evals): audit the shared Daytona regression lane

* fix(evals): clear eligible Daytona regression failures

* fix(evals): target the visible composer model picker

* fix(evals): scope the composer model trigger

* fix(evals): select the current composer model button

* fix(evals): enter the compact model submenu

* fix(evals): wait for workspace session row
* fix(server): isolate provider sync contexts

Signed-off-by: Jalil <reachjalil@gmail.com>

* test(server): make concurrent sync join deterministic

---------

Signed-off-by: Jalil <reachjalil@gmail.com>
…view (#4249)

* fix(app): drain queued composer messages while the session is not in view

Queued drafts and the drain machine are module-level, but the only driver
feeding engine status and sending lived in SessionSurface effects, so a
queued message never sent unless its session stayed on screen — and
switching workspaces disposed the SSE stream so idle was never observed.

Add a global queue drainer that keeps workspace session sync alive for
sessions with queued drafts and runs the same admission protocol
(claimQueuedSend before any await) when idle is observed, coexisting
race-free with mounted surfaces. The mounted surface registers a
per-session send context; draftToParts moves out of session-route so
sends work outside React.

Proven by evals/specs/composer-queued-drain-while-away.e2e.test.ts:
a gated mock keeps session A busy, the user queues a follow-up and
switches to workspace B, and after release the follow-up lands in A
exactly once (engine API + provider request log) while B stays clean;
negative control on unfixed code reproduces the stuck queue.

* test(evals): count the away-drain spec in the Daytona regression audit

composer-queued-drain-while-away.e2e.test.ts imports desktop from
@openwork/hosts, so the audited inventory grows to 147 files and the
raw-desktop set to 53; the eligible shared-topology count is unchanged.
Live "Working Ns" counters (main chat loading row and sub-agent task
lines) kept counting raw seconds forever, reading "Working 403s" while
the settled line already reads "Worked for 1m 55s". Format live elapsed
time the same way once a run crosses a minute: "Working 6m 43s".
…#4255)

The engine event fan-in had no deadline on establishing its per-connection
streams: one pool sibling that accepted the socket without answering kept
Promise.allSettled pending and the client's live feed never started, even
with a healthy primary. Both SSE frame parsers (the merged client body and
the drain activity watch) also grew an unbounded buffer on a frame that
never terminates.

- Give each event-stream fetch a 5s establishment deadline (matching
  proxyEngineAggregateRead) that is cleared once headers arrive, so the
  long-lived body itself is never put on a timer; lease aborts still tear
  bodies down through reader cancellation, and bodies the merged stream
  will not own are cancelled instead of leaking.
- Share one bounded SSE frame splitter between the client fan-in and the
  drain watch; on overflow the malformed connection is dropped (the drain
  watch re-dials) instead of buffering the frame forever.
- Release reader locks in the cancel/finally paths for consistency with
  readBoundedEngineMcpRegistrationResponse.
session.error lowered the run level in the activity store (sidebar) but
never wrote the react-query status cache the chat surface derives its
thread status from, and never gave status listeners an idle edge. A run
that errors without a follow-up idle event left the transcript's
"Working…" row counting forever beside the error card and wedged queued
sends behind a run that would never finish. Mirror the session.idle
handling: write idle to the status cache for tracked sessions and notify
status listeners.
* fix(desktop): serialize and bound automation runner lifecycle requests

* test(evals): track expanded automation-runner lifecycle suite
…ry (#4256)

* feat(app): report web boot failures and Stripe webhook errors to Sentry

Web deployments previously had no error reporting: a web instance that
failed to load, or any uncaught runtime error, was invisible. Stripe
webhook processing failures were also converted to HTTP responses by a
local catch before the observability middleware could see them.

- apps/app: zero-dependency, env-gated Sentry reporter
  (VITE_OPENWORK_SENTRY_DSN + web deployment only, never inside
  Electron), started before the bootstrap await, respecting the
  analyticsEnabled preference, with bounded, deduped, identity-only
  payloads.
- apps/app/index.html: inline pre-boot beacon so an entry bundle that
  never loads is still reported; hands over to the in-app monitor.
- den-api: capture Stripe webhook 500-path failures to observability
  with a stripe_webhook component tag; signature 400s stay excluded.

Proof: evals/specs/web-error-monitoring.test.ts (pnpm evals:pr),
apps/app bun tests, apps/app typecheck, web/desktop build gate checks.

* fix(app): strip query and fragment from web error report URLs

Sign-in and deep-link URLs can carry credentials (grant, openworkToken,
accessToken) in the query string. Report only origin + path from both the
pre-boot beacon and the runtime monitor, sanitize failed-resource URLs,
and return empty for unparseable input instead of leaking it.
)

* fix(app): archive sessions from non-selected workspaces correctly

The sidebar archive button silently failed for sessions outside the
selected workspace: session.update was sent with the selected
workspace's directory, and even after resolving the owning workspace
the sidebar never refetched a non-selected workspace's session list
(planRouteWorkspaceLoads skips already-loaded workspaces), so the row
never moved to Archived.

- resolve the session's owning workspace in handleArchiveSession and
  pass its path to setSessionArchived
- add reloadWorkspaceSessions(workspaceId) and call it after
  archiving so the owning workspace's list refetches
- update sessionsByWorkspaceIdRef synchronously in the background
  loader so refreshRouteState cannot clobber a fresh list
- canonicalize macOS /private/tmp to /tmp in normalizeDirectoryPath;
  the mismatch filtered refreshed sessions out of /tmp workspaces
- add session-archive-button.e2e.test.ts covering archive/unarchive
  in the selected workspace and cross-workspace archive, with
  negative halves

* test(evals): count session-archive-button spec in the Daytona regression audit
Give new contributors one fast path from clone to running dev build:
prerequisites (Node 24, pnpm via corepack, DCO sign-off), first-run
commands, a repository layout map, the testing entry points, and the
PR checklist. Also correct the dev banner CDP port example to the
actual default (9823).

Signed-off-by: Jalil <reachjalil@gmail.com>
- release: add the standard YAML frontmatter (name + description) so
  the skill is discoverable like every other repo skill.
- build-a-witness: point at the current witness sources in
  @openwork/labs (evals/packages/labs/src) instead of the removed
  labs/mock-mcp path.
- browser-automation: replace a machine-specific temp log path with a
  portable /tmp path.

Signed-off-by: Jalil <reachjalil@gmail.com>
* feat(evals): add script worlds — plain executable TS worlds alongside topology DSL

Worlds can now be ordinary executable TypeScript files instead of declarative
topology objects. A script world composes the same primitives specs already
use (server, createAdmin, createOrg, inviteMember, liteLlmPerMemberProvider,
app) with native `AsyncDisposableStack` for lifecycle, and calls `hold()` to
register a snapshot and block until torn down.

- packages/world: new `hold()` + script-world runtime; loader classifies
  `worlds/*.ts` as `definition` or `script` without importing (discovery
  stays import-free); CLI gains `world down <name>` and script-aware
  `up [--detach] [--timeout]` / `list` / `forget`.
- evals/packages/env: extract `liteLlmPerMemberProvider` out of the topology
  interpreter into a standalone exported primitive (interpreter now delegates
  to it, unchanged behavior); export `createAdmin`/`createOrg` so scripts can
  compose an org without the `server({ org })` bundle.
- worlds/litellm-per-member.ts: rewritten as an import-safe script
  (`if (import.meta.main)`) demonstrating the new shape; the topology
  definition is gone.
- evals/specs: litellm-per-member-world.e2e.test.ts updated to the new
  builder; new script-world-lifecycle.test.ts (PR lane) covers detached
  launch ownership, duplicate-launch/unknown-teardown isolation, and graceful
  stack disposal on `world down`.

Verified: script-world-lifecycle + shared-world-engine specs pass; full evals
package suite (242 tests) passes; litellm-per-member-world.e2e.test.ts passes
cold against a fresh local Den; typecheck diagnostics unchanged from the
origin/dev baseline (571, none in touched files).

* refactor(evals): remove declarative world layer

* docs(world): document script-only lifecycle

* docs(world): remove declarative lifecycle guidance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants