From d25fa1d9a58c536c29093d84f100b4abb10fb8e3 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Wed, 1 Apr 2026 06:07:53 -0500 Subject: [PATCH] Revert "docs: expand architecture and release documentation (#173)" This reverts commit 075ba2794e461a3a8968db4ec25b9e6f9b6231d9. --- README.md | 286 +++++++----------- apps/marketing/app/globals.css | 8 +- apps/marketing/components/ai-section.tsx | 2 +- .../components/dashboard/dashboard-inbox.tsx | 2 +- .../dashboard/dashboard-issue-detail.tsx | 4 +- .../dashboard/dashboard-sidebar.tsx | 2 +- apps/marketing/components/logo-cloud.tsx | 6 +- .../components/product-direction-section.tsx | 6 +- apps/marketing/components/ui-panel-inbox.tsx | 4 +- apps/marketing/components/ui/carousel.tsx | 27 +- apps/marketing/components/ui/chart.tsx | 3 +- apps/marketing/components/ui/field.tsx | 6 +- apps/marketing/components/ui/form.tsx | 7 +- apps/marketing/components/ui/toggle-group.tsx | 5 +- apps/mobile/ios/App/CapApp-SPM/README.md | 89 +----- apps/web/src/components/DiffPanel.tsx | 8 +- .../components/pr-review/RawPatchViewer.tsx | 29 +- apps/web/src/store.ts | 42 ++- docs/releases/README.md | 205 ++----------- 19 files changed, 207 insertions(+), 534 deletions(-) diff --git a/README.md b/README.md index d6e6fae97..24dd1679b 100644 --- a/README.md +++ b/README.md @@ -1,225 +1,163 @@ # OK Code -## 1) What this project is - -OK Code is a desktop-first orchestration platform for interactive coding agents. -It connects a local runtime (`apps/server`) that manages provider sessions with a -React client (`apps/web`) that renders live orchestration events and session state. - -## 2) Architecture and core flow - -### High-level flow - -```mermaid -flowchart LR - User["Developer"] --> UI["apps/web (React/Vite)"] - UI --> WS["apps/server/src/wsServer.ts
NativeApi + WS routing"] - WS --> PM["apps/server/src/providerManager.ts
Session request orchestration"] - PM --> SM["apps/server/src/codexAppServerManager.ts
Provider process lifecycle"] - SM --> Codex["codex app-server (process)"] - PM --> Contracts["@okcode/contracts"] - WS --> Contracts - Shared["packages/shared/*"] --> PM - Shared --> UI -``` +A minimal web GUI for coding agents. Currently supports Codex and Claude, with more providers coming. + +## Quick Start -### Component responsibilities - -- `apps/server` - - Owns session lifecycle: start/resume, reconnect handling, provider multiplexing. - - Provides the WebSocket API that the web app talks to. - - Converts provider output into shared orchestration-domain events. -- `apps/web` - - Owns user interaction, streaming UI, logs, and local state. - - Consumes server events and sends control actions back through `NativeApi`. -- `packages/contracts` - - Shared protocol/event types (`effect/Schema`) used by both sides. - - Keep this package schema-focused and stable. -- `packages/shared` - - Cross-package runtime helpers with explicit subpath exports (for example `@okcode/shared/git`). - - Use shared helpers instead of duplicating transport/session utility code. - -## 3) Repository map - -```text -apps/ - server/ Runtime orchestration and websocket gateway. - web/ React conversation and orchestration UI. - desktop/ Electron shell and client bootstrap. - marketing/ Marketing/public site. - mobile/ Capacitor app wrapper/build tooling. -packages/ - contracts/ Shared protocol/schema definitions. - shared/ Shared runtime utilities. -docs/ - releases/ Release process, release notes, and asset manifests. -scripts/ - Build/release/bootstrap scripts and local tooling. +```bash +npx okcodes ``` -## 4) Setup and local development +This starts the OK Code server and opens your browser. The app automatically detects which providers you have installed. -### Required tooling +Or install the [desktop app from the Releases page](https://github.com/OpenKnots/okcode/releases). -- Bun (matching project engine): `bun@1.3.11+` -- Node 24+ (repo declares `bun` + `node` engine compatibility) -- Xcode for iOS-related work -- macOS or Linux for development +### Provider Setup -### Install +OK Code supports multiple AI providers. You need **at least one** configured to start coding. -```bash -bun install -``` +
+Option A: OpenAI (Codex CLI) -### Run everything +1. Install: `npm install -g @openai/codex` +2. Authenticate: `codex login` +3. Verify: `codex login status` -```bash -bun dev -``` +If using a custom model provider (Azure OpenAI, Portkey, etc.), configure `model_provider` in `~/.codex/config.toml` instead — no `codex login` needed. -### Common workflows +
-```bash -bun dev:server # apps/server only -bun dev:web # apps/web only -bun dev:desktop # desktop shell + electron dev flow -bun dev:marketing # marketing site -``` +
+Option B: Anthropic (Claude Code) -Build marketing directly: +1. Install: `npm install -g @anthropic-ai/claude-code` +2. Authenticate: `claude auth login` +3. Verify: `claude auth status` -```bash -bun install -bun run build:marketing -``` +
-If `bun run build:marketing` fails with `next: command not found`, run `bun install` first to restore workspace dependencies. +> [!TIP] +> You can install both providers and switch between them per session. -### Package scoped examples +### Troubleshooting + +Run the built-in diagnostic to check your setup: ```bash -bun --filter @okcode/web dev -bun --filter okcodes dev -bun --filter @okcode/desktop build -bun --filter @okcode/contracts typecheck +npx okcodes doctor ``` -> `bun --filter okcodes dev` is useful when you explicitly want the server package by -> its legacy package name (`okcodes`). +If OK Code shows a provider error banner after launch: -### Quick-start operator matrix +| Banner message | Fix | +| ------------------------------ | ------------------------------------------------- | +| "not installed or not on PATH" | Install the CLI (see above), then restart OK Code | +| "not authenticated" | Run the login command for that provider | +| "version check failed" | Update the CLI to the latest version | -| Intent | Command | Expected result | Where to verify | -| ------------------------- | -------------------------------- | ------------------------------------------------ | ------------------------------------------------------ | -| Boot full local stack | `bun dev` | workspace starts dev scripts and shared services | logs show dev server/process startup | -| Run desktop app flow only | `bun dev:desktop` | local Electron + web bundle pipeline starts | verify desktop window opens and server socket connects | -| Build desktop artifacts | `bun build:desktop` | production desktop build output generated | workspace build pipeline succeeds in logs | -| Build web app | `bun --filter @okcode/web build` | Vite build output produced | check dist artifacts and exit code 0 | -| Validate formatting | `bun run fmt:check` | no formatting diffs | command exits 0 | -| Validate lint rules | `bun run lint` | lint passes | no lints in output | -| Validate TypeScript | `bun run typecheck` | no compile errors | all package typechecks pass | -| Run tests | `bun run test` | Vitest suites execute | exit code 0, no failing tests | +> [!NOTE] +> OK Code launches even without providers configured — you can explore the UI and configure provider binary paths from **Settings** before starting a session. -## 5) Runtime behavior (what happens during a session) +## Development Setup -1. Web UI opens WebSocket and subscribes to orchestration events. -2. UI submits user action to a `NativeApi` endpoint in `wsServer.ts`. -3. Server dispatches the request through `providerManager`. -4. `codexAppServerManager` starts or resumes the underlying `codex app-server` process. -5. Process outputs are parsed, normalized into shared events, and pushed back to UI. -6. UI applies deterministic reducers for rendering logs, state, and action controls. +**Prerequisites**: [Bun](https://bun.sh) >= 1.3.9, [Node.js](https://nodejs.org) >= 24.13.1 -Reconnect and recovery are first-class behaviors: +```bash +bun install +bun dev # start server + web in parallel +``` -- active process restarts should resume context when session state is available, -- failed parses are surfaced as explicit error states instead of silent fallback behavior. +This runs the contracts build, then starts the server (port 3773) and web app (port 5733) together via Turbo. -## 6) Contracts and compatibility +Other dev commands: -- All contract changes should begin in `packages/contracts`. -- Update both producer (`apps/server`) and consumer (`apps/web`) in the same commit. -- Validate generated type surface with: - - `bun run typecheck` - - targeted package `typecheck` scripts when needed. +```bash +bun dev:server # server only +bun dev:web # web only +bun dev:desktop # Electron desktop + web +bun dev:marketing # Astro marketing site +``` -## 7) Build and quality gates +Build marketing directly: ```bash -bun run fmt -bun run fmt:check -bun run lint -bun run typecheck -bun run test +bun install +bun run build:marketing ``` -Notes: - -- `bun run test` is the required test entrypoint. -- Formatting uses `oxfmt`; lint uses `oxlint`. -- Release tasks in CI are intentionally strict and require clean checks to proceed. +If `bun run build:marketing` fails with `next: command not found`, run `bun install` first to restore workspace dependencies. -## 8) Release operations +Quality checks: -Release is mostly driven by `.github/workflows/release.yml` and docs in `docs/releases`. +```bash +bun fmt # format (oxfmt) +bun lint # lint (oxlint) +bun typecheck # type-check all packages +bun run test # run tests (Vitest) +``` -- Trigger on tag push (`vX.Y.Z`) or `workflow_dispatch`. -- Preflight does `bun run lint`, `bun run typecheck`, `bun run test`, - and release smoke. -- Artifact build step executes `bun run dist:desktop:artifact`. -- Publishing requires release notes + asset manifest for the version. +## Architecture -For a practical walkthrough, use the release playbook in -[`docs/releases/README.md`](/Users/buns/.okcode/worktrees/okcode/okcode-ddc899c0/docs/releases/README.md). +OK Code is a monorepo with four apps and two shared packages, orchestrated by [Turbo](https://turbo.build). -## 9) Extending the system (recommended pattern) +``` +┌─────────────────────────────────┐ +│ Browser (React + Vite) │ +│ wsTransport (state machine) │ +│ Typed push decode at boundary │ +└──────────┬──────────────────────┘ + │ ws://localhost:3773 +┌──────────▼──────────────────────┐ +│ apps/server (Node.js) │ +│ WebSocket + HTTP static server │ +│ OrchestrationEngine │ +│ ProviderService │ +└──────────┬──────────────────────┘ + │ JSON-RPC over stdio +┌──────────▼──────────────────────┐ +│ codex app-server │ +└─────────────────────────────────┘ +``` -1. Start at the boundary where behavior changes: - - event shape → `packages/contracts` - - runtime orchestration → `apps/server` - - rendering/state handling → `apps/web` -2. Add/update shared types first. -3. Update server-side translation/projection next. -4. Update UI consumers and add tests or focused regression checks. -5. Run all quality gates before commit. +The server spawns `codex app-server` as a child process, communicating over JSON-RPC on stdio. Provider runtime events are normalized into orchestration domain events and pushed to the browser over WebSocket. -## 10) Security and operational posture +### Packages -- No secrets in files tracked by git. -- Validate untrusted inputs before invoking spawn/process APIs. -- Keep cleanup idempotent (process kill, temp files, sockets). -- Emit explicit telemetry for failure modes to avoid hidden partial failures. +| Package | Path | Role | +| ------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `okcodes` | `apps/server` | Node.js CLI and WebSocket server. Wraps Codex app-server, serves the React web app, and manages provider sessions. | +| `@okcode/web` | `apps/web` | React 19 + Vite SPA. Session UX, conversation rendering, and client-side state via Zustand. Connects to the server over WebSocket. | +| `@okcode/desktop` | `apps/desktop` | Electron shell that bundles the server and web app into a native desktop application with auto-updates. | +| `@okcode/marketing` | `apps/marketing` | Astro marketing site. | +| `@okcode/contracts` | `packages/contracts` | Shared [Effect](https://effect.website) schemas and TypeScript contracts for the WebSocket protocol, provider events, orchestration model, and session types. Schema-only — no runtime logic. | +| `@okcode/shared` | `packages/shared` | Shared runtime utilities (git, logging, shell, networking). Uses explicit subpath exports (`@okcode/shared/git`, etc.) — no barrel index. | -## 11) FAQ +### Key Technologies -- **Why are x64 macOS artifacts sometimes absent from release matrix?** - The release workflow can be configured to build only Apple Silicon by default for `workflow_dispatch` with `mac_arm64_only=true`. -- **Why strict release gates?** - They prevent format/type drift from reaching published artifacts. -- **Can I run release checks locally first?** - Yes, run the section 7 checks and create your release notes manifest files before creating a tag. +- **Runtime**: Node.js + Bun +- **UI**: React 19, Vite 8, Tailwind CSS 4, TanStack Router & Query +- **Server**: Effect, WebSocket (`ws`), node-pty +- **Desktop**: Electron +- **Schemas**: Effect Schema (in `@okcode/contracts`) +- **Build**: Turbo, tsdown +- **Lint/Format**: oxlint, oxfmt +- **Tests**: Vitest, Playwright -## 12) Operational checklists +### Event Flow -### Pre-PR gate +1. The browser opens a WebSocket to the server and registers typed listeners. +2. User actions become typed requests sent through the WebSocket transport. +3. The server routes requests to `ProviderService`, which talks to `codex app-server` over JSON-RPC. +4. Provider events are ingested, normalized into orchestration events, and persisted. +5. The server pushes domain events back to the browser through an ordered push bus (`orchestration.domainEvent` channel). +6. Async work (checkpoints, command reactions) runs through queue-backed workers and emits typed receipts on completion. -1. `bun run fmt:check` -2. `bun run lint` -3. `bun run typecheck` -4. `bun run test` -5. targeted package checks if changing app/domain boundaries +For the full architecture with sequence diagrams, see [.docs/architecture.md](.docs/architecture.md). -### Pre-release hardening +## Contributing -1. Ensure release notes and asset manifest are prepared. -2. Confirm release matrix intent (`mac_arm64_only` expectation). -3. Confirm signing secrets availability for macOS/Windows targets. -4. Confirm `docs/releases/v.md` and `docs/releases/v/assets.md` exist. -5. Trigger release and monitor all jobs. +Read [CONTRIBUTING.md](./CONTRIBUTING.md) before opening an issue or PR. -## 12) Contributing expectations +## Support -- Favor small scoped changes with clear ownership. -- Keep protocol surfaces version-consistent and documented. -- Update docs whenever startup flow, payload contracts, or release behavior changes. -- Prefer correctness over convenience in stream/retry code. +Join the [Discord](https://discord.gg/openknot). diff --git a/apps/marketing/app/globals.css b/apps/marketing/app/globals.css index 2a2a53483..e1f14def5 100644 --- a/apps/marketing/app/globals.css +++ b/apps/marketing/app/globals.css @@ -78,10 +78,10 @@ } @theme inline { - --font-sans: - var(--font-dm-sans), "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, - sans-serif; - --font-mono: "SF Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + --font-sans: var(--font-dm-sans), "DM Sans", -apple-system, BlinkMacSystemFont, + "Segoe UI", system-ui, sans-serif; + --font-mono: "SF Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, + monospace; --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); diff --git a/apps/marketing/components/ai-section.tsx b/apps/marketing/components/ai-section.tsx index 0c14deabe..9bd2708e3 100644 --- a/apps/marketing/components/ai-section.tsx +++ b/apps/marketing/components/ai-section.tsx @@ -310,7 +310,7 @@ export function AISection() { {/* MCP Code Snippet - Use semantic tokens for code syntax */}
-

{"//mcp.sprint.app/sse"}

+

//mcp.sprint.app/sse

"mcpServers" diff --git a/apps/marketing/components/dashboard/dashboard-inbox.tsx b/apps/marketing/components/dashboard/dashboard-inbox.tsx index 5c6e8e387..6365b52a2 100644 --- a/apps/marketing/components/dashboard/dashboard-inbox.tsx +++ b/apps/marketing/components/dashboard/dashboard-inbox.tsx @@ -184,7 +184,7 @@ function IssueRow({ issue, selected, onClick, - isMobile: _isMobile, + isMobile, }: { issue: Issue; selected: boolean; diff --git a/apps/marketing/components/dashboard/dashboard-issue-detail.tsx b/apps/marketing/components/dashboard/dashboard-issue-detail.tsx index 81e02b51d..dc6507422 100644 --- a/apps/marketing/components/dashboard/dashboard-issue-detail.tsx +++ b/apps/marketing/components/dashboard/dashboard-issue-detail.tsx @@ -484,9 +484,9 @@ export function DashboardIssueDetail({

- {issue.activity.map((activity) => ( + {issue.activity.map((activity, index) => ( {/* Logo grid with variety */}
- {companies.map((company, companyIndex) => { + {companies.map((company, i) => { const Icon = company.icon; return ( diff --git a/apps/marketing/components/product-direction-section.tsx b/apps/marketing/components/product-direction-section.tsx index 8b1b462c3..e6bdc0f45 100644 --- a/apps/marketing/components/product-direction-section.tsx +++ b/apps/marketing/components/product-direction-section.tsx @@ -77,13 +77,13 @@ export function ProductDirectionSection() {
{/* Tick marks row */}
- {Array.from({ length: 60 }, (_, tickIndex) => tickIndex).map((tickIndex) => ( + {Array.from({ length: 60 }).map((_, i) => (
))} diff --git a/apps/marketing/components/ui-panel-inbox.tsx b/apps/marketing/components/ui-panel-inbox.tsx index d345c3f14..299263bcc 100644 --- a/apps/marketing/components/ui-panel-inbox.tsx +++ b/apps/marketing/components/ui-panel-inbox.tsx @@ -87,9 +87,9 @@ export function UIPanelInbox() { {/* List */}
- {items.map((item) => ( + {items.map((item, index) => (
diff --git a/apps/marketing/components/ui/carousel.tsx b/apps/marketing/components/ui/carousel.tsx index cd7c9bec5..c43b82623 100644 --- a/apps/marketing/components/ui/carousel.tsx +++ b/apps/marketing/components/ui/carousel.tsx @@ -102,22 +102,19 @@ function Carousel({ }; }, [api, onSelect]); - const contextValue = React.useMemo( - () => ({ - carouselRef, - api: api, - opts, - orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), - scrollPrev, - scrollNext, - canScrollPrev, - canScrollNext, - }), - [api, canScrollNext, canScrollPrev, carouselRef, orientation, opts, scrollNext, scrollPrev], - ); - return ( - +
({ config }), [config]); return ( - +
- {errors - .filter((error): error is { message: string } => typeof error?.message === "string") - .map((error) => ( -
  • {error.message}
  • - ))} + {errors.map((error, index) => error?.message &&
  • {error.message}
  • )} ); }, [children, errors]); diff --git a/apps/marketing/components/ui/form.tsx b/apps/marketing/components/ui/form.tsx index 4c908e57f..c2c8525db 100644 --- a/apps/marketing/components/ui/form.tsx +++ b/apps/marketing/components/ui/form.tsx @@ -33,10 +33,8 @@ const FormField = < >({ ...props }: ControllerProps) => { - const fieldContextValue = React.useMemo(() => ({ name: props.name }), [props.name]); - return ( - + ); @@ -73,10 +71,9 @@ const FormItemContext = React.createContext({} as FormItem function FormItem({ className, ...props }: React.ComponentProps<"div">) { const id = React.useId(); - const itemContextValue = React.useMemo(() => ({ id }), [id]); return ( - +
    ); diff --git a/apps/marketing/components/ui/toggle-group.tsx b/apps/marketing/components/ui/toggle-group.tsx index 224760998..c93b7ae65 100644 --- a/apps/marketing/components/ui/toggle-group.tsx +++ b/apps/marketing/components/ui/toggle-group.tsx @@ -19,7 +19,6 @@ function ToggleGroup({ children, ...props }: React.ComponentProps & VariantProps) { - const contextValue = React.useMemo(() => ({ variant, size }), [size, variant]); return ( - {children} + + {children} + ); } diff --git a/apps/mobile/ios/App/CapApp-SPM/README.md b/apps/mobile/ios/App/CapApp-SPM/README.md index 24f5e2ffc..03964db90 100644 --- a/apps/mobile/ios/App/CapApp-SPM/README.md +++ b/apps/mobile/ios/App/CapApp-SPM/README.md @@ -1,88 +1,5 @@ -# CapApp-SPM (Capacitor Swift Package) +# CapApp-SPM -This directory is a generated Swift Package integration point for the native mobile -shell. It is managed by Capacitor tooling and should be treated as a reproducible -native dependency boundary. +This package is used to host SPM dependencies for your Capacitor project -## 1) What this package is - -- Package name: `CapApp-SPM` -- Product: `CapApp-SPM` -- Target(s): `CapApp-SPM` -- Platforms: iOS 15+ - -Primary goals: - -- provide a stable dependency entrypoint into the native layer, -- keep native package metadata separate from app JS source trees, -- avoid hand-editing generated package internals. - -## 2) Files here - -- `Package.swift` -- `Sources/` (package targets/source) - -The current `Package.swift` includes local package links into Bun-managed `node_modules` -paths, which is why it is intentionally generated rather than hand-maintained. - -## 3) Install and wire into an Xcode project - -1. In Xcode, open your `.xcworkspace` / `.xcodeproj`. -2. Go to **File → Add Packages…**. -3. Add by local path: - - `apps/mobile/ios/App/CapApp-SPM` -4. Add the `CapApp-SPM` product to the appropriate app target. - -### Target mapping quick reference - -- Package: `CapApp-SPM` -- Product: `CapApp-SPM` -- Usually added to the main app target and the extensions that depend on Capacitor modules. - -## 4) Regenerating after dependency changes - -When web/native dependency versions change in `apps/mobile`, regenerate this package -using your normal Capacitor sync workflow (outside this folder) and commit generated -updates if required. - -Recommended sequence: - -```bash -cd apps/mobile -bun run sync -cd ios/App -# regenerate native project references through your normal mobile tooling -``` - -Then reopen Xcode and run package resolve. - -## 5) Build and debug checks - -### Before a build - -- Open the workspace cleanly. -- Remove stale derived data if dependency resolution changed. -- Validate package resolve on local machine first. - -### Common failure states - -- **Package not found / cannot resolve product** - - verify path points to `CapApp-SPM/` and Xcode selected the correct package product. -- **Build fails with module resolution issues** - - clean build folder and re-resolve package dependencies. -- **Code signing breaks after package edits** - - re-check provisioning profile and signing identity for native targets. - -## 6) CI/release implications - -For release and package integrity: - -- keep native package updates deterministic, -- avoid ad-hoc local path edits that are not reflected in source control, -- verify any package-manager-driven changes are generated and committed with the - corresponding release or mobile update. - -## 7) Reference - -This package is separate from release docs in [`docs/releases/README.md`](/Users/buns/.okcode/worktrees/okcode/okcode-ddc899c0/docs/releases/README.md), -which controls desktop artifact publication and GitHub release behavior. +Do not modify the contents of it or there may be unintended consequences. diff --git a/apps/web/src/components/DiffPanel.tsx b/apps/web/src/components/DiffPanel.tsx index 98deb8199..70a23e26e 100644 --- a/apps/web/src/components/DiffPanel.tsx +++ b/apps/web/src/components/DiffPanel.tsx @@ -418,11 +418,9 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { () => renderableFiles.map((fileDiff) => resolveFileDiffPath(fileDiff)), [renderableFiles], ); - const activeReviewState = useMemo(() => { - return patchReviewSelectionKey - ? (reviewStateBySelectionKey[patchReviewSelectionKey] ?? {}) - : {}; - }, [patchReviewSelectionKey, reviewStateBySelectionKey]); + const activeReviewState = patchReviewSelectionKey + ? (reviewStateBySelectionKey[patchReviewSelectionKey] ?? {}) + : {}; const acceptedFileCount = useMemo( () => renderableFilePaths.reduce( diff --git a/apps/web/src/components/pr-review/RawPatchViewer.tsx b/apps/web/src/components/pr-review/RawPatchViewer.tsx index c5aad3187..7d6d1be86 100644 --- a/apps/web/src/components/pr-review/RawPatchViewer.tsx +++ b/apps/web/src/components/pr-review/RawPatchViewer.tsx @@ -446,27 +446,14 @@ export function RawPatchViewer({ text, reason }: { text: string; reason: string ) : ( /* Fallback: no file structure detected, render all lines with highlighting */
    - {lines - .reduce>( - (items, line, lineIndex) => { - const lineNumber = lineIndex + 1; - items.push({ - line, - lineNumber, - key: `${lineNumber}-${line}`, - }); - return items; - }, - [], - ) - .map(({ key, line, lineNumber }) => ( - - ))} + {lines.map((line, index) => ( + + ))}
    )}
    diff --git a/apps/web/src/store.ts b/apps/web/src/store.ts index 06f3b3274..ea1051421 100644 --- a/apps/web/src/store.ts +++ b/apps/web/src/store.ts @@ -260,28 +260,26 @@ export function syncServerReadModel(state: AppState, readModel: OrchestrationRea } : null, messages: thread.messages.map((message) => { - const attachments = message.attachments?.map((attachment) => { - const baseAttachment = { - id: attachment.id, - name: attachment.name, - mimeType: attachment.mimeType, - sizeBytes: attachment.sizeBytes, - url: toAttachmentPreviewUrl(attachmentPreviewRoutePath(attachment.id)), - }; - - if (attachment.type === "image") { - return { - type: "image" as const, - previewUrl: toAttachmentPreviewUrl(attachmentPreviewRoutePath(attachment.id)), - ...baseAttachment, - }; - } - - return { - type: "file" as const, - ...baseAttachment, - }; - }); + const attachments = message.attachments?.map((attachment) => ({ + ...(attachment.type === "image" + ? { + type: "image" as const, + id: attachment.id, + name: attachment.name, + mimeType: attachment.mimeType, + sizeBytes: attachment.sizeBytes, + url: toAttachmentPreviewUrl(attachmentPreviewRoutePath(attachment.id)), + previewUrl: toAttachmentPreviewUrl(attachmentPreviewRoutePath(attachment.id)), + } + : { + type: "file" as const, + id: attachment.id, + name: attachment.name, + mimeType: attachment.mimeType, + sizeBytes: attachment.sizeBytes, + url: toAttachmentPreviewUrl(attachmentPreviewRoutePath(attachment.id)), + }), + })); const normalizedMessage: ChatMessage = { id: message.id, role: message.role, diff --git a/docs/releases/README.md b/docs/releases/README.md index d01fafe27..5d00dd6fe 100644 --- a/docs/releases/README.md +++ b/docs/releases/README.md @@ -1,180 +1,25 @@ -# Release Playbook (Desktop + site assets) - -This document defines how to produce, validate, and publish official releases from -`main` with the current GitHub Actions pipeline. - -## 1) Trigger modes - -### 1.1 Tag-driven release - -- Push a tag in the form `v` (for example `v0.0.10`). -- `preflight` resolves `version` from the tag and runs required checks. - -### 1.2 Manual dispatch - -- Uses `workflow_dispatch` inputs: - - `version` (required; examples: `0.0.10` or `0.0.10-rc.1`) - - `mac_arm64_only` (default: `true`) -- Useful for controlled smoke/release dry-runs. - -## 2) Current CI stages - -### 2.1 `configure` - -- Selects release matrix. -- macOS default is Apple Silicon only when `mac_arm64_only=true`: - - `macos-14` + `mac` + `dmg` + `arm64` -- Full matrix (default for manual off switch) includes: - - `macos-14` + `arm64` - - `ubuntu-24.04` + `x64` AppImage - - `windows-2022` + `x64` NSIS - -### 2.2 `preflight` - -Executed on Ubuntu and includes: - -- dependency install (`bun install --frozen-lockfile`) -- `bun run lint` -- `bun run typecheck` -- `bun run test` -- `bun run release:smoke` - -Any failure here blocks build and publish jobs. - -### 2.3 `build` (matrixed) - -For each target: - -1. Checkout release ref. -2. Install dependencies. -3. Align package versions (`scripts/update-release-package-versions.ts`). -4. Build desktop artifact with `bun run dist:desktop:artifact`. -5. Collect release outputs (`release/*.dmg`, `release/*.AppImage`, `release/*.exe`, blockmaps, `latest*.yml`). -6. Upload per-platform artifact bundle. - -### 2.4 `release` - -- downloads all uploaded build artifacts, -- requires release docs to exist: - - `docs/releases/v.md` - - `docs/releases/v/assets.md` -- stages these as release body artifacts, then publishes release via `softprops/action-gh-release`. - -### 2.5 `finalize` - -- validates `RELEASE_APP_ID` / `RELEASE_APP_PRIVATE_KEY`, -- creates GitHub App token and bot identity, -- re-runs version bump flow and updates lockfile if needed, -- pushes version updates back to `main`. - -## 2.6 Operational matrix (release commands) - -| Trigger | Command/target | Expected output | Failure signal | Recovery | -| -------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------- | -| Tag-driven release | push `v` | `configure` → `preflight` → matrix `build` → `release` → `finalize` all succeed | missing/failed preflight gate | fix local violations, update commit, re-tag if needed | -| Manual release | workflow_dispatch with `version` | same stages as tag-driven | matrix wrong for architecture targets | set `mac_arm64_only` explicitly | -| Format regression | `bun run fmt` | files rewritten | `bun run fmt:check` fails in `preflight` | commit formatter output | -| Type/contract regressions | `bun run typecheck` | clean compile output | `TS` errors in preflight | update contracts and both producer/consumer sides together | -| Release content regression | `git show` on `docs/releases/v.md` + `docs/releases/v/assets.md` | both files present and committed | `release` job fails missing files | add both files and rerun release | -| Asset mismatch | build logs / upload-artifact | expected platform assets in `release-publish` | `if-no-files-found: error` or missing files | verify `release/` output names and rerun build | - -## 3) Required release assets - -For each release version `X.Y.Z`, commit: - -- `docs/releases/vX.Y.Z.md` (release notes body) -- `docs/releases/vX.Y.Z/assets.md` (asset manifest used in release publish step) - -The publish step copies both into `release-assets` and uses them for release artifacts. - -## 4) Standard release checklist - -1. Start from `main`: - - ```bash - git checkout main - git pull --ff-only - ``` - -2. Ensure current format/lint/type/test gates are green locally: - - ```bash - bun run fmt - bun run fmt:check - bun run lint - bun run typecheck - bun run test - ``` - -3. Prepare release notes and asset manifest: - - ```bash - mkdir -p docs/releases/v0.0.10 - touch docs/releases/v0.0.10.md - touch docs/releases/v0.0.10/assets.md - ``` - -4. Commit release notes updates. - -5. Cut and push tag: - - ```bash - git tag -a v0.0.10 -m "Release 0.0.10" - git push origin v0.0.10 - ``` - -6. Watch workflow progress: - - `Release Desktop / preflight` - - `Release Desktop / build (...)` - - `Release Desktop / release` - - `Release Desktop / finalize` - -7. Verify final output includes: - - expected platform artifacts, - - release body and assets manifest, - - optional signing/ notarization status, - - version bumps committed by finalize job (if any). - -## 5) Failure triage - -### 5.1 Preflight failures - -- **Lint/typecheck/test failure** - - reproduce locally with the same command from section 4. - - fix at source, rerun gate, then re-run tag/release path. - -- **Release smoke failure** - - inspect `bun run release:smoke` logs and confirm expected runtime prerequisites. - -### 5.2 Build failures - -- **Wrong architecture in matrix** - - confirm intended architecture matrix by checking `configure` job output. - - for Apple Silicon-only runs, ensure `mac_arm64_only` is true. -- **Signing/notarization failure** - - confirm required GitHub secrets are present in repository settings. -- **No files found during upload** - - check artifact output paths (`release/*.dmg`, `release/*.AppImage`, etc.) - - verify build command produced files in `release/`. - -### 5.3 Release staging failures - -- **Missing `docs/releases/vX.md` or `docs/releases/vX/assets.md`** - - create both files before triggering release. -- **`softprops` failures (`fail_on_unmatched_files`)** - - ensure all build artifacts + docs copies exist in `release-assets`. - -## 6) Release policy and best practices - -- Prefer single-purpose PRs for release content vs release infra changes. -- Keep release notes and manifest content deterministic for reproducibility. -- Prefer appending bugfixes/notes to the current patch version before bumping major/minor. -- Keep signing certificates and identity changes centralized in CI secrets. -- Use the changelog + release notes as a single source for user-visible changes. - -## 7) Optional manual triggers - -- For staging-only release runs, use `workflow_dispatch` with explicit version and - `mac_arm64_only` preference. -- For normal full desktop releases, set `mac_arm64_only=false` only when x64 macOS, - Linux, and Windows artifacts are all required. +# Release notes + +Human-readable notes and asset inventories for tagged releases. + +| Version | Notes | Assets | +| -------------------- | ------------------------------------------------------------ | ----------------------------- | +| [0.0.12](v0.0.12.md) | Release 0.0.12 with latest preflight fixes and Apple Silicon | [manifest](v0.0.12/assets.md) | +| [0.0.12](v0.0.12.md) | Release 0.0.12 with latest preflight fixes and Apple Silicon | [manifest](v0.0.12/assets.md) | +| [0.0.11](v0.0.11.md) | Release 0.0.11 with Apple Silicon-only macOS default asset m | [manifest](v0.0.11/assets.md) | +| [0.0.11](v0.0.11.md) | Release 0.0.11 with Apple Silicon-only macOS default asset m | [manifest](v0.0.11/assets.md) | +| [0.0.11](v0.0.11.md) | Release 0.0.11 with Apple Silicon-only macOS default asset m | [manifest](v0.0.11/assets.md) | +| [0.0.10](v0.0.10.md) | Release 0.0.10 with desktop packaging matrix updated to Appl | [manifest](v0.0.10/assets.md) | +| [0.0.9](v0.0.9.md) | Review fixes, skill dialog polish, and marketing refresh | [manifest](v0.0.9/assets.md) | +| [0.0.8](v0.0.8.md) | Skills, localization, attachment flow, and UI hardening | [manifest](v0.0.8/assets.md) | +| [0.0.7](v0.0.7.md) | Navigation, clone flow, plan checklists, preview presets | [manifest](v0.0.7/assets.md) | +| [0.0.6](v0.0.6.md) | PR + preview polish, env persistence, search, landing page | [manifest](v0.0.6/assets.md) | +| [0.0.5](v0.0.5.md) | Git workflows, PR review, mobile shell | [manifest](v0.0.5/assets.md) | +| [0.0.4](v0.0.4.md) | PR review, desktop preview, release tooling | [manifest](v0.0.4/assets.md) | +| [0.0.3](v0.0.3.md) | Onboarding, code viewer, PRs | [manifest](v0.0.3/assets.md) | +| [0.0.2](v0.0.2.md) | Patch release | [manifest](v0.0.2/assets.md) | +| [0.0.1](v0.0.1.md) | First public tag | [manifest](v0.0.1/assets.md) | + +The repository root [CHANGELOG.md](../../CHANGELOG.md) summarizes versions in Keep a Changelog form. + +Each release workflow also uploads **`okcode-CHANGELOG.md`**, **`okcode-RELEASE-NOTES.md`**, and **`okcode-ASSETS-MANIFEST.md`** to the GitHub Release (see [.github/workflows/release.yml](../../.github/workflows/release.yml)).