feat(core): attribute location boot phases and bound wellknown fetches - #354
Merged
Conversation
Adopted from upstream anomalyco/opencode v2 commit c22942c (Dax Raad). A failing wellknown resolve no longer dies the config load; it logs a warning and contributes no documents until the integration reconnects. Resolved against our tree's config entry ordering, which keeps wellknown at highest priority. Relates to #352: loadWellknown() sits on the location build path, so a failing origin previously killed cold location builds outright.
Cold location builds logged one opaque durationMs, which made tail incidents unattributable (#352 observed 16.2s with no way to tell config discovery from project resolve from network waits). Controlled measurement shows the reported concurrent-build "serialization" is fair time-slicing of CPU-bound builds on the single JS thread: concurrent cold builds are work-conserving (6 concurrent builds complete in less total wall-clock than 6 sequential ones) but each observes ~N x latency and all finish clustered. The tail therefore hides in an off-CPU await inside a specific phase. Add BootPhase: a per-boot recorder provided to the location layer build via fiber context. The critical-path phases -- config discovery, wellknown (nested inside config), project resolve, and the initial config-root watch reconcile -- record wall-clock durations, and the "location services booted" line now carries the phaseMs breakdown so the next tail incident names its phase. Plugin activation and repository watches are forked off the boot path and stay uninstrumented. Bound both wellknown HTTP fetches (manifest inspect and remote config) with a 10s timeout. Combined with the tolerated-failure handling, an unresponsive origin now degrades into a logged warning instead of stalling every cold build for that location indefinitely.
shuv1337
added a commit
that referenced
this pull request
Aug 13, 2026
Merge anomalyco/opencode upstream/v2 (283258e, 187 commits) into integration-v2 (00e7c54), aligning with upstream everywhere except fork-critical features, per PLAN-upstream-v2-merge.md. Preserved fork features: identity/publish/updater/launcher, managed service lifecycle (ServiceLifecycle.ensure everywhere), Anthropic Claude Pro/Max subscription provider, structured output, session tool policy, strict prompt retry identity (durable admitted-event reconciliation), mobile pairing removal, and prior fork fixes (#350/#353/#354). Adopted from upstream: session_v2 rename, skills prompt attachments, plugin hook rename request -> http.request/http.response, new CLI commands (models/export/import/debug config), workspace_domain, legacy-credential import, docs/app/desktop changes. Database bridge (M2): DatabaseMigration.apply now detects a fork-tip session table (fork_boundary column, tool-policy migration present, no session_v2) and renames it to session_v2 in one transaction before upstream migrations run, rebuilding session_v2_* indexes and marking the upstream squash migration as already applied so its destructive SQL never executes. Validated against a real dev DB copy (12 sessions/16 messages/86 events preserved) and via a fork-tip fixture test. Data-safety corrections (M3): V1Migration no longer globally wipes events when V2 sessions already exist (gated on empty session_v2); imported legacy Anthropic OAuth credentials now map to methodID claude-pro-max. CLI/service wiring (M4): new upstream handlers registered without pair; every server-start path (auth login, debug config, server-connection) routes through ServiceLifecycle.ensure. Regeneration & docs (M5): protocol/client/www regenerated; publish.yml gains a github.ref_name == integration-v2 guard; merged docs rebranded to Shuvcode while preserving SDK/API symbols; migrate-v1.mdx documents the DB bridge, scoped event deletion, and the hook rename; AGENTS.md records the session_v2/bridge and hook-name invariants. Upstream-bug follow-ups (M6): symlinked mutation targets now resolve through the nearest existing ancestor's real path before authorization, closing an external-directory approval bypass; desktop background-cli prefers the canonical managed state root over the first running candidate; failed server replacement no longer removes existing tabs. Validated: full per-package typecheck+test pass (schema, protocol, core, server, client, cli, tui, app) plus a live smoke test against an isolated standalone server pointed at a scratch copy of a real dev database, confirming existing sessions/transcripts render and that a live prompt round-trips both structured output and a skill attachment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #352.
Diagnosis
The reported "serialization" of concurrent cold location builds is not a lock. A controlled benchmark at the
LocationServiceMaplevel (6 fresh directories, warm globals) reproduces the issue's completion-clustering signature and shows the concurrency is work-conserving:RcMap.getforks each key's lookup into its own fiber andLayer.MemoMaponly shares same-layer builds through a deferred, so N concurrent CPU-bound builds time-slice fairly on the single JS thread: each observes ~N× latency and all complete together. That fully explains the issue's 10× repro (6 × ~30 ms of work ⇒ everyone finishes at ~330 ms) and the p99 clustering. It does not explain the 16.2 s incident, which must be an off-CPU await inside a specific phase — exactly what the missing instrumentation hides.Changes
BootPhase(new,packages/core/src/boot-phase.ts) — a per-boot phase recorder provided to the location layer build via fiber context.location services bootednow carries aphaseMsbreakdown:config(discovery),wellknown(nested inside config),project(resolve incl. git), andwatch(initial config-root reconcile — the incident's watcher-subscribe evidence). Plugin activation and repository watches are forked off the boot critical path and stay uninstrumented. The unattributed remainder is node construction plus time-slicing against concurrent boots.inspect+ remote config GET). Previously unbounded and on the response path.anomalyco/opencode@c22942c1f3(fix(core): tolerate unavailable wellknown config): a failingwellknown.resolvelogs a warning and contributes no documents instead of dying the config load. Resolved against our entry ordering (wellknown stays highest priority). With (2), an unresponsive origin now degrades into a warning instead of stalling every cold build for that location indefinitely.Upstream
v2was checked for a fix to the serialization itself: none exists (only the adopted tolerance commit touches this path).Not changed, deliberately
phaseMsdata names the dominant phase.Validation
bun typecheckclean inpackages/core,packages/server,packages/cliattributes boot phases in the booted log) asserting the booted log carries all four phase keys bounded bydurationMstolerates unavailable authenticated wellknown config and reloads it later)