Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/skills/verify/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ description: Build/launch/drive recipe for verifying codev-code changes end-to-e

# Verifying codev-code changes

## Typecheck first

Always include typecheck in the first verification run: run `bun typecheck` from the
touched package dirs (e.g. `packages/tui`, `packages/opencode`) before launching the
TUI, and again after every follow-up edit before re-verifying — don't defer it to the
pre-push hook. Never bare `tsc`, never from repo root.

## Launch the TUI

The TUI must be launched with cwd = `packages/opencode` — its `bunfig.toml` preloads
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ jobs:
uses: ./.github/actions/setup-bun

- name: Run typecheck
run: bun typecheck
# Concurrency capped: default (10) runs enough parallel tsgo compilers
# (opencode alone peaks ~4.6 GB) to OOM the 16 GB runner, which dies with
# "The runner has received a shutdown signal" instead of a type error.
# The runner has 4 cores, so the cap costs little wall time.
run: bun turbo typecheck --concurrency=3
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ file is the human-readable summary of what changed and why.

## Unreleased

### Sidebar

- **Hidden-sidebar hint shows while busy** — the `ctrl+b N todos` hint from
[#69](https://github.com/quickbeard/codev-code/pull/69) now also renders while
a turn is running (next to `esc interrupt`), not just when the session is
idle — todos created mid-turn are visible immediately. It still yields to the
retry error row.
([#107](https://github.com/quickbeard/codev-code/pull/107))

## 1.17.18-2

### App lifecycle
Expand Down
3 changes: 2 additions & 1 deletion DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ from the squash message first, or use a plain merge.
| `packages/tui/src/component/dialog-provider.tsx` | The "Other" custom-provider option routes into the fork-only `runCustomProviderFlow` (component/dialog-custom-provider.tsx, new file) — id → API key → optional base URL → model discovery via `/v1/models` → `provider.<id>` block PATCHed into global codev.json (key stays in auth.json) — instead of upstream's credential-only `ApiMethod`; the local `promptCustomProviderID` helper moved into that flow (upstream's "only stores a credential" description no longer holds). `ApiMethod`'s `custom` prop is now unreferenced but left in place. | An empty base URL keeps upstream's credential-only behavior; with one, the provider is usable without hand-editing codev.json. The configure gate's "Custom provider" option shares the same flow. | Keep our `onSelect` + import and the helper deletion; take upstream's changes to `ApiMethod`/other methods (the flow only wraps the entry point). |
| `packages/tui/src/component/prompt/index.tsx` | Gated the prompt footer's model/provider indicator on `useConnected()` (the shared "a real provider is configured" predicate) | Don't advertise the free hosted Zen default (e.g. "Big Pickle · OpenCode Zen") in the footer while nothing is configured — same rationale and predicate as `app.tsx`'s startup gate and the provider/model filters. A configured gateway/real provider, or a deliberately-authenticated opencode/opencode-go, still shows its model. | Keep the extra `Show` condition; take upstream's surrounding changes. |
| `packages/tui/src/component/prompt/index.tsx` | Added a `directoryLabel` memo (abbreviated cwd, `:branch` suffix when known, middle-truncated; last path segment + branch in text color, parent path muted, matching the sidebar footer) rendered as the first item of the prompt footer's right-side group, left of the editor open-file label. The memo delegates to `directoryFooterLabel(...)` and the render goes through a `<DirectoryLabel ... hidden={props.sidebarVisible}>` component — both in the fork-only `./directory-label.tsx`. `Prompt` takes a `sidebarVisible?: boolean` prop that `routes/session/index.tsx` passes from its `sidebarVisible()` memo. | Keep the working directory and branch visible at a glance from the prompt (the home-footer `Directory` only shows once a destination is selected, and the sidebar — the other place showing the branch — is hidden by default), but suppress the label while the sidebar is visible since the sidebar footer already shows the same `cwd:branch`. | Keep the `directoryLabel` memo, the `directoryFooterLabel`/`DirectoryLabel` imports from the fork-only `./directory-label.tsx`, the `sidebarVisible` prop + the `hidden={props.sidebarVisible}` gate on `<DirectoryLabel>`, and the `sidebarVisible={sidebarVisible()}` prop on `<Prompt>`; take upstream's surrounding footer changes. |
| `packages/tui/src/component/prompt/index.tsx` | The busy-state footer arm (`status().type !== "idle"`) also renders `props.hint` after the `esc interrupt` text, gated on `status().type !== "retry"` | The hidden-sidebar hint (see the `routes/session/index.tsx` hint row) only rendered in the footer `Switch`'s idle fallback arm, so it vanished for the whole duration of a running turn — exactly when todos are being created. Retry keeps its `space-between` error row uncluttered. | Keep the `<Show when={status().type !== "retry"}>{props.hint}</Show>` line in the busy `Match` arm (additive); take upstream's surrounding changes. |
| `packages/app/index.html` | `<title>` → "CoDev Code" | Web UI tab title. | Keep our title. |
| `packages/app/src/pages/layout.tsx`, `packages/app/src/pages/layout-new.tsx` | Dropped the `<TabsInfoPopup />` mount and its import from both layouts (added upstream in v1.17.18); `HelpButton` stays. | `TabsInfoPopup` is a dev-channel-only "Introducing Tabs" promo whose `muted autoplay loop` `<video>` mounts on every layout render. The fork's Windows e2e runs on GPU-less GitHub-hosted runners (software GPU — see the runner-swap row), where continuous video decode wedges the GPU command buffer (`kTransientFailure`), making the whole app-e2e suite flaky and ~3–5× slower. It never ships (release builds use a non-`dev` `CODEV_CHANNEL`), so unmounting it costs users nothing. | Keep ours: don't re-add the `<TabsInfoPopup />` mount or restore it to the import. |
| `packages/app/src/components/help-button.tsx` | Removed the `TabsInfoPopup` component, its `introducing-tabs.mp4` import, and the imports only it used; `HelpButton` stays. (The file's `VITE_OPENCODE_CHANNEL` → `VITE_CODEV_CHANNEL` gates follow the env-var rename row.) | The popup is upstream's temporary, OpenCode-branded "Introducing Tabs" promo (upstream's own comment says it's removable after the rollout), already unmounted per the row above; removing the definition lets the 13 MB video be deleted (row below). | Keep our removal; take upstream's changes to `HelpButton`. If upstream mounts `TabsInfoPopup` somewhere new, drop that mount per the row above. When upstream deletes the popup itself, this row and the two rows around it retire. |
Expand Down Expand Up @@ -141,7 +142,7 @@ from the squash message first, or use a plain merge.
| `.github/TEAM_MEMBERS` | Deleted | Upstream's team roster. The five workflows that read it (pr-standards, pr-management, triage, duplicate-issues, compliance-close) fetch it from a `dev` branch this fork doesn't have, so they are already inert here. | Keep deleted. |
| `packages/script/src/index.ts` | Guard the `.github/TEAM_MEMBERS` read: fall back to an empty team list when the file is absent instead of throwing at module load | This module is imported by the publish path (`publish.ts`); the deleted `TEAM_MEMBERS` (row above) made `bun run release` crash with ENOENT. `Script.team` has no consumers in the fork. | Keep our `exists()` guard; take upstream's surrounding changes. |
| `.github/workflows/` — 22 upstream workflows deleted (beta, close-issues, close-prs, compliance-close, containers, deploy, docs-locale-sync, docs-update, duplicate-issues, generate, nix-hashes, notify-discord, opencode, pr-management, pr-standards, publish, publish-github-action, publish-vscode, release-github-action, review, stats, triage) | Deleted | All inert or upstream-only here: gated on `anomalyco/opencode`, publish/deploy to upstream infra, need upstream secrets (`OPENCODE_APP_SECRET`, `OPENCODE_API_KEY`, marketplace/Discord/PostHog tokens), trigger only on a `dev` branch the fork lacks, or read the deleted `TEAM_MEMBERS`. | Keep deleted; delete new upstream workflows too unless they're generic self-contained CI. |
| `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest`; test.yml unit-test step wrapped in a 2-attempt retry loop (`bun turbo test`, re-run once on failure) with `timeout-minutes` 20 → 60; test.yml exerciser step gains `timeout-minutes: 30`; test.yml Windows unit job pre-installs ripgrep via choco | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. GitHub-hosted `windows-latest` needs well over 20 minutes for the spawn-heavy opencode suite, and several process-spawn/timing-sensitive tests (snapshot-tool-race, skill discovery, flock contention, ...) flake individually there; bun has no per-test retry (`--only-failures` doesn't persist across invocations), so one flake failed the whole job. The retry re-runs only the flaked package (turbo cache-hits the rest); 60 min covers one re-run of the ~27min opencode suite. A wedged exerciser run otherwise holds the job for GitHub's 6-hour ceiling. The file-search index is built by a background ripgrep walk with swallowed errors; Windows's first-use rg.exe download left it permanently empty, failing httpapi-file's search test every run. | Keep our branches + runners + retry loop + timeouts; take upstream's other changes. |
| `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest`; test.yml unit-test step wrapped in a 2-attempt retry loop (`bun turbo test`, re-run once on failure) with `timeout-minutes` 20 → 60; test.yml exerciser step gains `timeout-minutes: 30`; test.yml Windows unit job pre-installs ripgrep via choco; typecheck.yml runs `bun turbo typecheck --concurrency=3` (was `bun typecheck`, default concurrency 10) | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. GitHub-hosted `windows-latest` needs well over 20 minutes for the spawn-heavy opencode suite, and several process-spawn/timing-sensitive tests (snapshot-tool-race, skill discovery, flock contention, ...) flake individually there; bun has no per-test retry (`--only-failures` doesn't persist across invocations), so one flake failed the whole job. The retry re-runs only the flaked package (turbo cache-hits the rest); 60 min covers one re-run of the ~27min opencode suite. A wedged exerciser run otherwise holds the job for GitHub's 6-hour ceiling. The file-search index is built by a background ripgrep walk with swallowed errors; Windows's first-use rg.exe download left it permanently empty, failing httpapi-file's search test every run. Turbo's default concurrency (10) runs enough parallel tsgo compilers (opencode alone peaks ~4.6 GB) to OOM the 16 GB ubuntu-latest runner — the job dies with a runner-shutdown signal, no type error; with 4 cores the cap costs little wall time. | Keep our branches + runners + retry loop + timeouts + typecheck concurrency cap; take upstream's other changes. |
| `packages/core/test/ripgrep.test.ts` | `120_000` timeout on both `it.live` tests | First use downloads + extracts the ripgrep binary; GitHub-hosted Windows runners blow bun's 5s default. | Keep our timeouts; take upstream's test changes. |
| `packages/opencode/test/cli/run/run-process.test.ts`, `packages/opencode/test/cli/acp/lifecycle.test.ts`, `packages/opencode/test/server/httpapi-file.test.ts`, `packages/opencode/test/server/httpapi-sdk.test.ts`, `packages/opencode/test/effect/runner.test.ts`, `packages/opencode/test/session/prompt.test.ts`, `packages/opencode/test/project/instance-bootstrap.test.ts` | Slow-runner headroom: unknown-model test `timeoutMs`/bound 15s → 30s (test timeout 60s); the two unknown-stream-finish `codev run` subprocess tests ("unknown stream finish preserves partial output…", "--format json records partial output for an unknown stream finish") `timeoutMs` 30s → 60s and test timeout 60s → 120s (pure-upstream spawn tests that pay `codev run` cold-start; neither asserts on duration, so headroom only); the three tool-executing `codev run` subprocess tests ("prints each completed text part in order around a tool continuation", "--format json preserves reasoning, tool, and continuation ordering", "rejects requested permissions by default and allows them with the dangerous flag") `timeoutMs` 30s (harness default) → 60s explicitly, test timeout 60s → 120s — 240s for the permissions test, which pays three sequential `codev run` spawns; these pay cold-start *plus* a real `bash` tool spawn and a continuation turn, and were timing out at exactly the 30s harness default on loaded runners; none asserts on duration, so headroom only; ACP stdin-EOF exit timeout 5s → 30s; file-search-index poll 5s → 120s with a 150s test timeout (the search-endpoints test pays ripgrep's first-use download on Windows runners, like ripgrep.test.ts); Runner fiber-coordination `Effect.timeout` guards 250ms/1s → 10s (pure hang-detectors on already-unblocked awaits; Windows runners starve the event loop past 250ms); prompt.test.ts's two `sleep`-based loop/shell tests ("loop waits while shell runs…", "shell completion resumes queued loop callers") moved from `it.instance` to the file's own `unix` helper so they skip on Windows like their `unixNoLLMServer` siblings (`sleep` isn't on Windows, so the shell fiber hangs to the budget — a genuine hang, not slowness); instance-bootstrap's first test 30s → 60s (pays instance cold-start) | Loaded GitHub-hosted runners spawn processes, fetch ripgrep, and build the lazy file index slower than upstream's Blacksmith runners; 250ms–30s budgets flake or fail outright, and Unix-shell tests can't run on Windows at all. Hang regressions are still caught (a hang exceeds the bound; polls return as soon as ready). | Keep our numbers and the `unix` gating; take upstream's test changes. |
| `packages/opencode/test/tool/external-directory.test.ts`, `packages/opencode/test/tool/read.test.ts` | Windows path-variant tests keep the drive letter in the `alt` form (drop the `.replace(/^[A-Za-z]:/, "")` step) | A drive-less path is drive-relative: it resolves against the CWD's drive (D: on GitHub-hosted Windows) while the temp dir lives on C:, so the file genuinely isn't there. Slash + case variants still exercise normalization. | Keep our `alt` construction; take upstream's test changes. |
Expand Down
1 change: 1 addition & 0 deletions packages/tui/src/component/prompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,7 @@ export function Prompt(props: PromptProps) {
{store.interrupt > 0 ? "again to interrupt" : "interrupt"}
</span>
</text>
<Show when={status().type !== "retry"}>{props.hint}</Show>
</box>
</Match>
<Match when={workspace.notice()}>
Expand Down
2 changes: 1 addition & 1 deletion packages/tui/src/routes/session/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,7 @@ export function Session() {
hint={
<Show when={sidebarHint()} fallback={<text />}>
{(hint) => (
<box paddingLeft={3}>
<box paddingLeft={3} paddingRight={2}>
<text fg={theme.text}>
{sidebarShortcut()} <span style={{ fg: theme.textMuted }}>{hint()}</span>
</text>
Expand Down
Loading