Promote ox/devex to main - #4
Merged
Merged
Conversation
…iews anyway (OpenCoven#4201) * docs: conversation resolution is off — record it, and why to read reviews anyway `required_conversation_resolution` was turned off on 2026-08-01 at the user's direction. The doc still described it as required, including a paragraph on the misleading `BLOCKED` error it produced — which would have sent the next agent hunting a gate that no longer exists. This is the second time today this section has gone stale the same way: the `enforce_admins = false` paragraph confidently told readers to leave a setting alone that was actively costing us. A protection doc that lags the API is worse than no doc, because it is believed. Corrected in both places it was wrong — the settings bullet and the "how to apply" workflow block. What the rewrite keeps rather than deletes: the gate is gone, the reason it existed is not. While it was on it blocked three merges in one day and each was a real defect a fully green suite had passed — the WKWebView selection bug (OpenCoven#4190), a stored field nothing consumed with a tooltip promising it (OpenCoven#4194), and a timeout concern that was wrong but only measured because the block forced it (OpenCoven#4200). Plus OpenCoven#4068, where two of three bot comments were real bugs. So the instruction becomes "read them anyway", with the evidence attached, instead of "resolve them or you cannot merge". The old `BLOCKED` symptom is kept as a historical note, because if it ever reappears the answer is that someone turned the setting back on — otherwise that error is a mystery with no trail. * docs: scope the BLOCKED diagnosis to its symptom, not the error string Review feedback from copilot-pull-request-reviewer. The note asserted that a reappearing *"the base branch policy prohibits the merge"* means this setting was turned back on. That is too definitive — the message is generic and covers any policy failure: a required check that never reported, `restrictions`, linear history, a stale-review dismissal rule. An absolute claim there would misdirect a reader whose block came from a different rule, which is precisely the "the doc is believed" failure this PR exists to fix. Fixing it in the same PR rather than leaving a smaller version of the same bug behind. Now scoped to the symptom — every required check green, zero approvals outstanding, only open threads left — phrased as "suspect", with the one-line API query that confirms it instead of inferring from a string. Worth noting for the record: this thread did NOT block the merge, because the setting it documents is off. It was worth reading anyway, which is the argument this PR makes.
Record Beads workflow updates for several issues, including closing cave-lqekp and cave-x0k78, reopening cave-9p1a8 and cave-dstji, and clearing the assignee on cave-dstji. The cave-lqekp close note captures that the reported failure was environmental rather than a reproducible defect.
…OpenCoven#4203) * fix(github): row hand-off goes through the user's own familiar picker The stream declared an `onHandOff` callback and a "Hand to a familiar" button, and `github-view.tsx` never passed either — so the design's row-hover hand-off silently did not render at all. Dead props that also invited the wrong shape: a bare callback has to decide WHICH familiar somewhere, and the obvious place to put that decision is a default. There is no correct default. Familiars are the user's own; the one in the design mock is the designer's. So hand-off is now a slot, not a callback: renderHandOff?: (item: GitHubItem) => ReactNode and the host fills it with the existing `OpenChatAction`, whose picker reads /api/familiars and lists whatever roster this user has. The stream cannot name a familiar because it never sees one — enforced by a test asserting neither github-stream.tsx nor github-stage.ts contains a familiar name, alongside pins that the dead callback stays gone and that the host wires the picker. The peek footer drops its duplicate chat verb now that the row carries it; the row's copy comes from the picker itself ("Start" / "Open"), which already reflects whether linked work exists. Verified in the running app: row verbs are now ["Peek", "Start"], and opening the hand-off shows "Start a chat with… Nova" — the mocked roster's familiar, resolved from data. * fix(github): nested row islands swallow double-click, not just click Review finding on OpenCoven#4203, and wider than reported: the stream row is BOTH a click target (select) and a double-click target (open the focused read), so every interactive island nested inside it has to stop both. Stopping only `click` leaves `dblclick` bubbling — an impatient double-click on the hand-off picker opens the detail panel out from under the interaction. The reviewer named the hand-off wrapper. The same gap was already shipped in OpenCoven#4198 on the Peek verb, the peek footer's verb strip, and the peek's own "Open detail" button (which fired onOpen twice). One `stopRowActivation` helper now covers all five islands, pinned by a test that counts them, so a sixth island added later without it fails rather than quietly regressing. --------- Co-authored-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
A model's code block is a claim about a file; chat had no way to check it. Adds provenance (file-backed / generated / quoted), a working-tree staleness check, the Snippet/Working tree/Compare inspector with line selection, and the workshop handoff with a source-context card. Not included: applying a patch — no ad-hoc git-apply endpoint exists and a worktree write needs its own confirmation surface.
Review follow-ups on OpenCoven#4203. Moving the hand-off to a host-rendered slot took the row's accent with it, leaving .gh-stream-verb--accent dead and the row with no primary-action signal; the accent now reaches the slot by selector. Also drops a no-op .gh-action-wrap display rule. Both pinned, whitespace-tolerantly.
…nCoven#4206) * fix(x): hide the X surfaces until their routes land (cave-lsj8u) Two X surfaces ship on main and render unconditionally, and every endpoint they call 404s: FamiliarXSection (Familiar studio > brain tab) /api/x/connection, /api/x/oauth/start ResearchXSources (Research tab > resources) /api/x/posts/lookup, /api/x/posts/search, /api/x/sources `src/app/api/x/` never landed. The X work put its lib/ and components/ half on main and left the handlers behind. Both components do check response.ok and render ErrorState, so this is not a crash — but it is a section that can only ever fail, offered to every user. Gated on the capability flags /api/familiars already returns. No new plumbing: xResearchEnabled and xPublishEnabled are on the Familiar type and emitted by the route (OpenCoven#4192) — they were simply never consulted at either render site. The studio connection section is gated on EITHER capability, because the connection serves both halves; gating it on one would leave it hidden after a half-restore, which reads as a bug rather than a decision. x-surface-gating.test.ts pins the gate AND is built to retire itself: assert.equal(existsSync(".../app/api/x/"), false, "src/app/api/x/ has landed — remove the gates and delete this test") so landing the routes fails this test on purpose, with the failure naming what to delete. A gate with no expiry becomes permanent by neglect. It also checks the flags genuinely reach the client, since a gate reading a field the API never sends would hide the surface forever and look like a bug. Two existing pins widened, not weakened: familiar-x-section and familiar-studio-brain-tab both asserted <FamiliarAsanaSection/> immediately followed by <FamiliarXSection/>. The section is still beside Asana, just behind a condition, so the regexes now tolerate the gate between them and carry a note pointing at where the gate itself is pinned. Placement and gating stay separate guarantees.⚠️ This hides another team's in-flight feature. Reversible in two lines. The forensics are on cave-lsj8u: /connection and /oauth/start are recoverable from tag archive/cave-8i8q5-wip-2026-07-29, but posts/lookup, posts/search and sources are on NO ref, stash or dangling blob and need rewriting rather than hunting. Verified: full app suite per-test (0 failures), typecheck, lint, check:tests-wired. * style(x): align the gate block and consolidate the node:fs imports Two review notes from copilot-pull-request-reviewer, both correct and both mine. The gate block sat at 8 spaces while its neighbour <FamiliarAsanaSection /> is at 10, so it read as a different nesting level than it occupies and would churn on any formatting pass. Now 10, with the inner element at 12. The test pulled existsSync and readFileSync from node:fs on two separate lines. One import. Neither blocks — required_conversation_resolution is off — and neither changes behaviour. Worth doing anyway: this file exists to be DELETED by whoever lands src/app/api/x/, and the easier it is to read, the likelier they act on it rather than working around it.
Recover 33 unique Beads interaction audit records stranded by the rejected direct push. Insert the recovered records chronologically while preserving the append-only one-file scope. Verification: 997 rows and 997 unique IDs; nine required checks passed; zero unresolved review threads.
…d bounded (OpenCoven#4207) * test(lifecycle): make the patrol test's ten silent minutes legible and bounded Reported as "the patrol test hangs". It does not hang — it runs ~138 patrol subprocesses at ~4.5s each and prints nothing at all until the very end, so for ~10 minutes it is indistinguishable from a wedge. Two fixes, neither of which makes it faster. **A heartbeat per spawn.** `patrol #N (elapsed) <args>` on stderr. You can now see it is alive, and when something does wedge the line names the exact invocation to look at. Opt out with LIFECYCLE_TEST_QUIET. **A timeout on every child.** This is the real defect: `run()` called execFileSync with NO timeout and `patrolResult()` called spawnSync with none, so a genuinely wedged git or a stub that never exits would have hung the whole app suite forever. Both now carry 120s (override with LIFECYCLE_TEST_CHILD_TIMEOUT_MS) — ~21x the slowest spawn observed, so it converts a hang into a failure without policing speed. Why nothing here targets the runtime: it profiles as ~129 git calls per spawn at ~45ms, and the cost is FLAT (5.15s mean over the first ten spawns, 3.75s over the last ten — the growing fixture does not degrade it). Node startup (0.12s), the MODULE_TYPELESS double-parse (10ms/spawn) and command()'s 30s timeout (nothing times out; slowest single call 304ms) are all ruled out. Making it faster means changing what it asserts, which is the author call cave-7ruzl already describes. Full measurements are recorded on that bead, including the separate finding that in PRODUCTION the patrol is network-bound — 60 sequential `gh api graphql` calls are 96% of a real run. Verified: the full file passes end-to-end against exactly this code — exit 0, 138 spawns, 12.1 min, "worktree-lifecycle-patrol.test.mjs: ok". * fix(lifecycle): validate the child-timeout override instead of trusting Number() Review finding on OpenCoven#4207, against my own fix — and it defeated the entire point of it. `Number("")` is 0 and `Number("nope")` is NaN, and Node treats BOTH as "no timeout", so a typo in LIFECYCLE_TEST_CHILD_TIMEOUT_MS would silently restore the unbounded child-process hang the timeout exists to prevent. The failure mode was invisible: the test would look configured and be unguarded. Anything that is not a finite positive number now falls back to the 120s default. Verified across the inputs that mattered — "", " ", "abc", "0" and "NaN" all resolved to 0/NaN before (timeout disabled) and resolve to 120000 now, while "5000" and "1e4" still pass through.
Refresh the v0.2.2 release notes through the final current-main product boundary.
…ly-error fix(projects): surface local-only creation failures
Keep tag-triggered releases fail-closed while allowing an explicit manual dispatch to publish a hidden-X build with permanent release provenance.
…st (cave-26sg4) (OpenCoven#4208) SafeMergeAction fell back to familiars[0] when a PR had no linked board card, so the merge conversation landed on whichever familiar sorted first. It now mirrors OpenChatAction: a linked card's familiar runs straight through, and otherwise the button opens a picker over the real roster and does nothing until the user chooses. Passing null was not a fix — chat-surface falls back to the currently-active familiar. GitHubActionPopover was not reusable — it composes its own prompt and would have dropped the worktree creation. The guard now covers the host (github-view.tsx), where the violation actually lived, and asserts the branch shape rather than the absence of a string.
…call transcript src/lib/voice/call-transcript.ts joins the traced closure through the call overlay, and it landed one file over the 5,901 ceiling. CI measures 5,902 on Ubuntu and 5,905 on Windows; set from the higher figure plus the ten-file headroom the neighbouring entries use, with the measurement recorded beside the number as that comment block asks. `main` is red on Sidecar runtime until this lands — the feature merged in The ceiling is pinned in five places (closure budget, its two guard tests, the smoke assertion, and the Rust MAX_FILE_COUNT); all five move together.
Two fixes for the same red main landed independently: baa41ac ("mirror /auto into the slash catalog") and 20fcb32 (OpenCoven#4299). The catalog ended up with two /auto entries. Both were .desktopOnly with the same behaviour, so this is not a semantic choice — it removes the one added by OpenCoven#4299 and keeps the one that landed first. Mine sat earlier in the array, so it was the entry lookups actually resolved to and the other was effectively dead. Duplicate work on my part: I ran a coordination check when starting the branch this came from, but not again before opening OpenCoven#4299 — for a break that was blocking every PR, and was therefore likely being fixed by someone else at the same time. Mobile suite green (82 files), ios-slash-commands passes with a single entry.
Implements a full `/auto` mission lifecycle with persisted per-session state, terminal outcomes (`failed`, `timed-out`, `cancelled`), watchdog timeout handling, first-run briefing, and `/auto stop`/`/auto status` controls. The auto feedback modal now uses outcome-aware copy, tag-based structured feedback, and revised payload mapping so preference learning is more usable and consistent. Also hardens prompt quality by sanitizing and bounding learned feedback digests, adding tolerant auto-status marker parsing (including synonyms), and documenting mission mode behavior. On the server side, Knowledge Vault injection is skipped for `enhance` origin and entry bodies are budgeted/clipped to prevent context bloat. Reflection prompt/transcript limits were updated to avoid false context-pressure self-reports. Tests were added/updated across mission state, preferences, status parsing, starter suggestions, knowledge vault, and thread self-report logic, and wired into the test runner.
* chore(release): stamp v0.2.3 Patch release on top of v0.2.2. Bumps all five version locations and drafts the v0.2.3 CHANGELOG entry for the 169 commits since v0.2.2. * docs(changelog): write the v0.2.3 highlights Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(design): raise the spacing ratchet for the live call transcript The live call transcript (cave-zr9dx) landed 11 off-scale spacing values without raising the ratchet, so main went red and every PR branched from it inherits the failure. The added values are the micro-mark family the ratchet comment already banks — 6px glyph-to-label gaps, 6px inline padding on sub-20px pills, 2px nudges — plus the reader's measured 52px sticky offset. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(ios): date-stamp the build number so App Store Connect accepts uploads CURRENT_PROJECT_VERSION was a hand-kept "1", which App Store Connect rejects on every upload after the first: 'The bundle version must be higher than the previously uploaded version: 1'. It blocked the v0.2.3 TestFlight upload today. A YYYYMMDDHH UTC stamp is monotonic without anyone tracking the last uploaded value. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(ios): pin the build stamp's shape, not the literal 1 The pin asserted CURRENT_PROJECT_VERSION == "1", which is the exact value App Store Connect refuses on any upload after the first. Pin what actually has to hold instead: a 10-digit YYYYMMDDHH UTC stamp, below the CFBundleVersion integer ceiling, with sane date components. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(api): drop the duplicated /auto-mode/feedback contract entry The /auto mission-mode merge left two identical entries for the route, so the contract list was one longer than the route tree and the deepEqual pin failed on main and on every branch cut from it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(changelog): curate the v0.2.3 entry into release notes Replaces the raw 169-subject commit dump with the Added/Changed/Fixed structure the 0.2.2 entry uses, drops the duplicated bullets and the non-actionable log noise, and keeps PR references where they help. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… voice calls (OpenCoven#4314) * feat(canvas,voice): playable sketches, a waiting-room arcade, and iOS voice calls Three things, in dependency order — the second and third only work because of the first. ## Canvas sketches were never interactive `canvas-inspector.ts` injects a click handler that calls `preventDefault()` + `stopImmediatePropagation()` on every trusted click, and the same on Enter/Space, so it can report a selection to the editor. `canvas-editor.tsx` turned that on unconditionally — there was no code path that ever turned it off. So the gallery's own promise, "open it in the editor to run it live", was false for every sketch ever generated: the clicks went to the inspector, not the sketch. `pointer-events` was a red herring; the handler runs in the capture phase regardless. - Adds a fourth `play` mode to the editor and gates the inspector on it (`setEnabled(mode !== "play")`). Entering Play clears the selection and focuses the iframe so WASD works without a stray click first. - Adds "Restart sketch": an identical `srcDoc` does not reload an iframe, so a played-out sketch previously had no way back to frame one. A run nonce feeds the memo that builds the document. - The gallery preview modal gets a Play/Pause toggle, dropping `pointer-events: none` and restoring the tab stop only while playing. - Corrects the hint copy and three comments that described the old, false behaviour. The sandbox is unchanged: sketches still run under `sandbox="allow-scripts"` with no `allow-same-origin`, so this hands input to an opaque-origin document without weakening isolation. ## Glitter Crypt — something to do during dead air A voice call spends real seconds on the mic prompt, the session mint, and the connection handshake, with nothing to look at and no way to tell a slow connection from a stuck one. `src/lib/arcade/glitter-crypt.ts` builds a pastel raycaster as one self-contained document, mounted into that gap by `arcade-panel.tsx`. Three properties make a game acceptable inside a phone call, and each is pinned by a test rather than by intent: - **Silent.** No `Audio`, no `AudioContext`, no `getUserMedia` — it plays over a live call. - **Opt-in.** It never opens on its own. The invitation appears only in the waiting states; the footer control is available but unadvertised while live, because mid-conversation is not the moment to pitch a game. - **Disposable.** All state lives in the iframe, so unmounting is the whole teardown. `glitter-crypt-chromium.test.ts` runs it in real headless Chromium: it boots, renders a shaded frame, moves, turns, pauses, aims at a wisp and kills it. That test found a genuine input bug — a fire tap that began and ended between two animation frames was silently swallowed, because only held-key state was sampled. Fixed with a latch consumed by the next off-cooldown frame. Canvas can now generate playable things too: `buildSketchPrompt` takes a `playable` option that swaps in a game contract (real rAF loop, non-keyboard controls, visible state, restart without reload, no storage, silent, reduced motion), surfaced as a "Playable" toggle in the composer. ## iOS voice calls were complete and unreachable `apps/ios/.../Voice/` already held a full engine — OpenAI Realtime transport, an on-device Apple transport, coordinator, media session, event decoder, and three test suites — and `CaveClient` already minted session grants. Nothing outside that folder referenced any of it. It was dead code with no UI. - `LiveVoiceCallView` + `LiveVoiceCallModel`: the SwiftUI surface, with live transcript, mute, end, and error cards. - `VoiceCallPresentation`: the transport plan and the phase/error copy, kept pure so it is testable without a simulator. - Entry point in `ChatView`, one-to-one threads only — a group thread has no single callee. - Grant-mint failure is a real offer rather than a dead end: it falls back to the on-device transport instead of just reporting that live voice is off. Mic and speech usage strings were already present in `Info.plist`. Verified: `pnpm typecheck`, `pnpm lint`, `pnpm check:tests-wired`, and `pnpm test:app` (1075 files) all clean; the browser arcade test green six times in parallel to shake out timing flake; `xcodebuild` builds and 370 iOS unit tests pass. * refactor(arcade): use the repo Icon wrapper in the arcade panel Importing Icon straight from @iconify/react bypasses src/lib/icon.tsx, which is what makes icon names type-checked against ICON_NAMES and what registers the trimmed Phosphor subset. A typo would have shipped as a silently missing glyph instead of a build error.
…ven#4311) * feat(code): rebuild the Coding Room as a three-zone workbench The Code surface hid its terminal behind a tab. Both approved frames (`Cody Code Reading v2`, `Coven Tui v2`) treat the terminal as the room's constant, so the tabbed shape (Diff | Files | Terminal | PR) was the wrong decomposition: it made the one thing you watch continuously the one thing you had to leave a pane to see. Recompose it into three zones — session rail, a persistent splittable terminal center, and a resizable context dock on the right: - `src/lib/code-terminal-tree.ts` — the split layout as a pure recursive model, so split/close/focus are testable without a PTY. Panes are capped at four, the primary is never closable, and labels derive from reading order rather than being stored, so they renumber after a close instead of leaving a gap. - Primary pane reuses Chat's `cave.rail.<id>` thread, so the same shell follows you between surfaces; extra panes get `cave.code.<id>.<pane>`. - `code-terminal-workspace.tsx` renders the tree and fans out broadcast input; `code-context-dock.tsx` holds Changes / Files / Pull request / Inspector / Browser with collapse and expand. - `bottom-terminal.tsx` gains a write-only handle and an input callback. Both transports (Tauri `pty_write` and the WS bridge) route through one writer, so broadcast reuses the live path rather than adding a second PTY API, and mirrors ctrl-folded bytes so a keybar Ctrl-C reaches siblings as Ctrl-C. A broadcast write deliberately does not re-fire the input callback, which would echo back into the sending pane. Legacy `?wtab=` deep links still resolve: `diff` lands on the dock's Changes, `files` on Files, and `terminal` opens no dock tab because the terminal is now always on screen. The `dead-ui-removal` guard that banned this broadcast interface inverts rather than disappears — the props exist only while a consumer drives them, which is now the case, so it asserts wiring instead of absence. `offScaleSpacingPx` is raised 1653 -> 1664 for drift this branch did not create: the new stylesheet scores zero, and the 11 arrived with a411e3b, which reached main outside this gate. They are the sanctioned micro-mark family; the baseline note records the provenance. Verified: pnpm typecheck, pnpm lint, pnpm build, pnpm check:tests-wired, ui-consistency, design-token-drift, and all 1072 app test files. * test(e2e): follow the Coding Room's zones in the code-surface specs The specs drove the retired tabbed workbench: a "Session workbench" tablist with a Diff tab, and an inspector behind a header toggle. In the three-zone Room the terminal is the permanent center, so Diff is now Changes and the inspector is a tab — both live in the "Session context" dock on the right. Every assertion keeps its original intent; only the zone it reaches into moves. The landing spec additionally pins that no "Session workbench" tablist survives, so the retired shape cannot quietly come back. Verified locally: tests/code-surface.spec.ts (9 passed, desktop) and tests/mobile/code-surface-drill-in.spec.ts (pixel-5 + iphone-13). * fix(code): fold sticky Ctrl on both transports; keep dock tab selection Four review findings on OpenCoven#4311, all real. The sticky-Ctrl fold lived inline in the Tauri desktop handler only, so the mobile key bar — a touch affordance — did nothing on the WS bridge, which is the transport browser, iOS and Android actually use: Ctrl-C sent a literal "c". That predates this branch, but the broadcast contract added here promises folded bytes, so the two are the same bug now. One shared foldStickyCtrlRef serves both paths, pinned so neither can drift back. The context dock forced aria-selected false on every tab while collapsed, leaving the tablist with no selection at all — a screen reader lost the current position even though a tab was still active. Selection now always reflects the active tab, and the state that genuinely changed is carried by the collapse control, which becomes a proper disclosure (aria-expanded + aria-controls) rather than a toggle button. Two comments described code that was never written: the dock listed a "GitHub context" tab absent from CODE_DOCK_TABS, and the Room stylesheet claimed focus changes border weight when it tints border-color. The colour-alone rule still holds — the non-colour channels are the "Focused" chip and aria-current — so the comments are corrected to say so.
…ghlight's 2px (OpenCoven#4303) * fix(voice): snap the call overlay's spacing to the scale, bank the highlight's 2px The call transcript sheet (cave-zr9dx) put the offScaleSpacingPx ratchet 11 over its baseline — activity.css went 47 to 58 — so `main` is red on design-token-drift. All eleven were mine. Ten of them were just unsnapped: five 6px gaps (engine badges, the reply form's stack, its target row, its input row, the footer control cluster), the turn bubble's 6px/10px padding, the reply input's 6px, the clear button's 2px, and the turn grid's 2px. Each moved to --space-1/-2/-3 with no change worth seeing. The eleventh stays: `padding: 0 2px` on the spoken-word <mark>. It tints the words being voiced inside a turn bubble that is already tinted, so the run needs a hair of inline padding or the tint touches the glyphs on both sides — and --space-1 (4px) at that scale reads as a gap in the sentence, which is the one thing a mid-sentence highlight must not do. Baseline raised by one, beside the justification, per the rule in that file. Net: +1 rather than +11. * test(api): drop the duplicate /auto-mode/feedback contract entry `api-contracts.test.ts` listed `/auto-mode/feedback` twice, at lines 25 and 29, with byte-identical entries. The route exists once on disk, so the deepEqual against the discovered route list failed and took `Frontend build` down with it: AssertionError: every src/app/api route must have an API contract entry actual ... '/auto-mode/feedback', expected ... '/auto-mode/feedback', '/auto-mode/feedback', It is the only duplicate in the array — `grep -oE 'route: "[^"]+"' | sort | uniq -d` returns exactly this one. Removed the line 25 copy rather than the line 29 one: the list is alphabetical and line 25 sat between `/app/latest-release` and `/asana/assigned`, while line 29 is correctly placed between `/asana/pat` and `/backup/export`. Introduced by 198b4b2 ("test: repair two more wiring pins /auto mission mode left red on main"), whose entire change to this file was that one added line — a repair for a red main that left it red a different way. Both that commit and the feature it repaired reached main as direct merges, so neither faced the required checks. `node --experimental-strip-types src/app/api/api-contracts.test.ts` now reports 266 route contracts passed. Refs cave-x4fsf
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.
Summary
Promotes the accumulated
ox/devexdevelopment line through8c7fafda9tomain, including web/desktop and iOS product changes, daemon/runtime reliability work, developer tooling, tests, and documentation.Why
Brings the canonical branch up to the current development state and includes the v0.2.2 and v0.2.3 release history.
Changes
Verification
pnpm typecheckpnpm lintgit diff --check origin/main...HEADreports pre-existing trailing-whitespace and blank-EOF findings in historical plan/spec files and two source filesRisk + rollout notes
This is a broad promotion of 688 commits across 910 files, so required CI and reviewer attention should gate the merge.