diff --git a/.agents/skills/codex-panel-app-server-update/SKILL.md b/.agents/skills/codex-panel-app-server-update/SKILL.md index 79e974a4..27252ad1 100644 --- a/.agents/skills/codex-panel-app-server-update/SKILL.md +++ b/.agents/skills/codex-panel-app-server-update/SKILL.md @@ -10,13 +10,14 @@ Use this skill when Codex Panel needs to follow Codex CLI or experimental `codex ## Ground Rules - Treat `src/generated/app-server/` as generated output. Do not hand-edit generated bindings. +- Use `docs/design.md` for app-server boundary and source-of-truth decisions before adding compatibility layers or product behavior. - Prefer current Codex CLI behavior over broad backward compatibility unless a concrete user need requires compatibility code. - Separate required compatibility fixes from optional cleanup or product improvements. - Do not rely on local Git hooks. Run required generation and verification commands explicitly. ## Procedure -1. Read the README Compatibility and Development sections, `package.json`, and app-server-related source around requests, notifications, threads, approvals, Plan mode, hooks, and model listing. +1. Read the README Compatibility section, `docs/design.md`, `docs/development.md`, `package.json`, and app-server-related source around requests, notifications, threads, approvals, runtime settings, hooks, and model listing. 2. Compare the README Compatibility table's `codex.testedCliVersion` with the target `codex --version`. 3. Check official Codex CLI or app-server release information when the target version is newer or behavior is uncertain. 4. Regenerate bindings with `npm run generate:app-server-types`. diff --git a/.agents/skills/codex-panel-obsidian-dev/SKILL.md b/.agents/skills/codex-panel-obsidian-dev/SKILL.md index a74ede11..8fafe59f 100644 --- a/.agents/skills/codex-panel-obsidian-dev/SKILL.md +++ b/.agents/skills/codex-panel-obsidian-dev/SKILL.md @@ -10,6 +10,7 @@ Use this skill for live Obsidian checks after building Codex Panel or when inves ## Ground Rules - Work from the Codex Panel repository root. +- Use `docs/development.md` for the build and generated-asset expectations before live Obsidian validation. - Treat `obsidian plugin:reload id=codex-panel`, `obsidian reload`, `obsidian restart`, `obsidian devtools`, `obsidian eval`, `obsidian dev:cdp`, and `obsidian dev:mobile` as state-changing or intrusive. Ask the user before running them. - Prefer read-only inspection first: `plugin`, `commands`, `dev:errors`, `dev:dom`, `dev:css`, `dev:console`, `dev:screenshot`, `version`. - If `dev:console` reports that the debugger is not attached, ask before running `obsidian dev:debug on`. diff --git a/AGENTS.md b/AGENTS.md index 7836bb74..66041557 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,9 +1,13 @@ -This repository contains the Codex Panel Obsidian plugin. Use the tracked docs as the source of truth: `README.md` for user-facing behavior, `docs/development.md` for development workflow, and `docs/release.md` for releases. +This repository contains the Codex Panel Obsidian plugin. Jujutsu is the recommended local change-management workflow when available. -## Working Rules +## What To Read -- Follow the documented ownership and source layout boundaries. -- Do not hand-edit generated app-server bindings. -- Keep internal validation notes and reasoning out of public release notes. +- Read `README.md` for user-facing behavior, requirements, commands, privacy, and compatibility. +- Read `docs/design.md` when changing responsibility boundaries, runtime ownership, app-server source-of-truth behavior, UI ownership, or testing philosophy. +- Read `docs/development.md` before implementation work, generated binding work, source layout decisions, validation, or compatibility baseline changes. +- Read `docs/release.md` for release preparation, release notes, preflight, tagging, pushing, and release repair. +- Use the repo-local skills in `.agents/skills/` when a task matches a more specific workflow. + +When implementation, design, or workflow changes create drift from docs or lint policy, update the affected docs or lint settings in the same change and report that update. diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 00000000..ae1370f3 --- /dev/null +++ b/docs/design.md @@ -0,0 +1,67 @@ +# Design + +Codex Panel is an Obsidian surface for Codex. It exists to put Codex beside vault notes without becoming a separate AI client, runtime policy editor, terminal, search product, or writing suite. + +This document records durable design direction. User-facing behavior belongs in `README.md`; daily workflow, source layout, generated files, and compatibility checks belong in `docs/development.md`. + +## Product Boundary + +Keep the panel thin. Codex Panel owns the Obsidian experience around Codex: panels, thread display, composing, approvals and user input, vault-aware link handoff, archive export, settings for panel preferences, diagnostics, and selection rewrite review. + +Codex owns runtime policy and thread truth. Model defaults, sandboxing, approvals, MCP servers, hooks, providers, network access, thread history, archived threads, effective configuration, goals, and runtime settings should come from Codex through `codex app-server`. + +Panel settings should store only panel-specific preferences. Do not duplicate Codex configuration into Obsidian settings just because a value is useful to display or inspect. + +## Sources of Truth + +The repository checkout is the source of truth for implementation, version control, and release work. Ignored release assets are generated outputs, even when Obsidian loads them at runtime. + +`codex app-server` is the source of truth for Codex state. Panel-side caches exist to keep the UI stable across transient failures; failed reads or stale panels must not become authoritative empty state. + +The app-server API is experimental. The project tracks the supported Codex CLI minor and favors a clean current flow over broad old-protocol compatibility. Current optional and nullable fields are still part of the contract and must be normalized before display. + +## Code Boundaries + +Generated app-server protocol types should stay behind `src/app-server/`. Services at that boundary adapt protocol payloads into panel-owned domain models or small projections before data reaches features, workspace coordination, settings, or UI. + +Turn stream conversion is the main exception: raw app-server stream payloads may be consumed at the conversion boundary because the event set is broad and changes with Codex. The rest of chat state and UI should still use panel-owned display models. + +Source modules should be organized by reason to change, not by the single Obsidian plugin entrypoint. Obsidian lifecycle, app-server transport, chat state, runtime display, thread management, selection rewrite, settings, and workspace coordination should each stay close to the state or API they own. + +Feature-to-feature imports are acceptable when the imported feature owns a real capability. Generic helpers belong in `src/shared/`, generated-independent meaning belongs in `src/domain/`, and protocol adaptation belongs in `src/app-server/`. + +Do not hide complexity behind forwarding layers. Add an abstraction only when it owns a lifecycle, boundary, state transition, or reusable domain capability. + +## UI Ownership + +Runtime UI composition is Preact-owned. Preact components should render the panel shell, toolbar, message stream, composer, and request controls. + +Obsidian and app-server boundaries stay outside Preact components. `ItemView` classes, plugin lifecycle, app-server connections, controllers, `MarkdownRenderer`, editor APIs, notices, and workspace operations belong in boundary modules. + +Chat-visible state belongs in `ChatStateStore` and named reducer actions. Signals and components may project that state, but they should not become parallel sources of truth for turns, pending requests, runtime settings, history cursors, or open details. + +Imperative DOM bridges are allowed when an external API or measurement problem requires an `HTMLElement`, such as Obsidian markdown rendering, rendered link binding, diff rendering, icon rendering, textarea measurement, and virtualized list measurement. They should not become a second UI composition system inside Preact-owned surfaces. + +## Interaction Principles + +Multiple panels are separate Obsidian leaves. Treat each panel as its own Codex working surface with independent connection, thread, turn state, composer, and pending requests. + +Thread history, archived state, forks, and catalog data should follow app-server semantics. Obsidian integrations such as archive note export are convenience views of Codex state, not replacements for Codex history. + +Selection rewrite is intentionally scoped: use the live editor buffer, ask Codex for a replacement candidate, show a focused diff, and apply only after user confirmation. Avoid expanding it into a broader writing assistant without a separate design decision. + +Server requests should become panel UI only when the user can naturally answer them in context. Unknown or unsupported requests should stay diagnostic instead of pretending to be normal conversation text. + +Message stream display should separate primary conversation from diagnostic detail and progress/status. Preserve stable item identity across history reads, streaming updates, virtualization, delayed rendering, and scroll anchoring. + +Codex Panel UI should feel native inside Obsidian. Prefer Obsidian variables, standard classes, and side-panel patterns. Add custom visual treatment only when Codex-specific state would otherwise be hard to read. + +## Testing Direction + +Tests should protect user expectations, app-server/panel responsibility boundaries, and state-transition invariants. + +Prefer tests for visible behavior: independent panels, thread-scoped resets, pending request handling, approval flows, readable transcript/detail/status grouping, scroll preservation, and display fallbacks for structured app-server values. + +Avoid tests that freeze incidental implementation details such as exact DOM nesting, render counts, node reuse, helper decomposition, or no-op array updates unless those details directly protect a user-visible invariant. + +Panel tests may define how received structured values are displayed, retained, or normalized. They should not redefine Codex-owned runtime policy, model lists, sandbox behavior, approval policy, or thread history semantics. diff --git a/docs/development.md b/docs/development.md index 20092ad4..8765edb4 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,5 +1,9 @@ # Development +Use this document for day-to-day implementation workflow: commands, source layout, generated files, naming, and common pitfalls. For the rationale behind responsibility boundaries and UI/runtime ownership, see `docs/design.md`. + +## Commands + ```sh npm ci npm run format @@ -9,7 +13,20 @@ npm run build Run `npm run format` after edits and before `npm run check` so Prettier-only issues are fixed upfront. `npm run check` runs TypeScript type checking, unit tests, lint checks, Prettier check, CSS build verification, and a production esbuild bundle. The local `npm run check` path runs checks in parallel and uses local caches where available. Use `npm run check:ci` when you need to reproduce the sequential, non-cached CI validation path. -`main.js`, `styles.css`, `data.json`, and `node_modules/` are ignored by Git. `main.js` and `styles.css` are still the files Obsidian loads, so run `npm run build` after source changes. CSS is authored in `src/styles/` and generated into the ignored root `styles.css` release asset. Use `npm run build:styles` when only regenerating CSS, or `npm run build:styles:check` to verify that the authored CSS can be rendered. +## Generated and Loaded Files + +`main.js`, `styles.css`, `data.json`, and `node_modules/` are ignored by Git. `main.js` and `styles.css` are still the files Obsidian loads, so run `npm run build` after source changes. + +CSS is authored in `src/styles/` and generated into the ignored root `styles.css` release asset. Use `npm run build:styles` when only regenerating CSS, or `npm run build:styles:check` to verify that the authored CSS can be rendered. + +The app-server TypeScript bindings in `src/generated/app-server/` are generated from the installed Codex CLI: + +```sh +npm run generate:app-server-types +npm run check +``` + +The generation script uses `codex app-server generate-ts --experimental` because the panel depends on experimental app-server fields. Do not hand-edit generated bindings. ## Source Layout @@ -30,9 +47,9 @@ The source tree is organized by responsibility rather than by the original singl ## Implementation Conventions -Keep new code near the state or API it owns. A feature may import another feature only for a capability that feature owns; feature-neutral behavior belongs in `src/shared/`, `src/domain/`, or `src/app-server/`. Lower-level modules must not import `src/features/`, and generated app-server types should stay behind `src/app-server/`. +Keep new code near the state or API it owns. A feature may import another feature only for a capability that feature owns; feature-neutral behavior belongs in `src/shared/`, `src/domain/`, or `src/app-server/`. Lower-level modules must not import `src/features/`, and generated app-server types should stay behind `src/app-server/`. `docs/design.md` records the rationale and exception rules for these boundaries. -Codex Panel's runtime UI is Preact-owned. Use imperative DOM writes only for explicit bridge modules, Obsidian-owned API boundaries, or rendering and measurement code that cannot be expressed cleanly as Preact components. Chat panel-visible state belongs in `ChatStateStore` and should flow through named reducer actions and the shell-state adapter. Revisit the project design notes before adding a parallel UI state or runtime path. +Codex Panel's runtime UI is Preact-owned. Use imperative DOM writes only for explicit bridge modules, Obsidian-owned API boundaries, or rendering and measurement code that cannot be expressed cleanly as Preact components. Chat panel-visible state belongs in `ChatStateStore` and should flow through named reducer actions and the shell-state adapter. Revisit `docs/design.md` before adding a parallel UI state or runtime path. ## Naming Conventions @@ -40,16 +57,14 @@ Name modules by responsibility: use `Controller` only for stateful lifecycle/con Prefer functions and factory-created objects over classes. Use a class only when it owns mutable lifecycle/resource state, extends or implements an external class-based API such as Obsidian views/modals/tabs, or represents an `Error`; do not use a class merely to group pure functions or dependencies. -## App-Server Bindings +## Common Pitfalls -The app-server TypeScript bindings in `src/generated/app-server/` are generated from the installed Codex CLI: - -```sh -npm run generate:app-server-types -npm run check -``` - -The generation script uses `codex app-server generate-ts --experimental` because the panel depends on experimental app-server fields such as collaboration mode and generated v2 types. +- Build before Obsidian validation. Obsidian loads ignored root assets, not the TypeScript or authored CSS sources directly. +- Keep generated app-server types behind `src/app-server/` unless `docs/design.md` documents a boundary exception. +- Preserve last-known-good app-server state on refresh failure. Do not turn disconnected reads into authoritative empty thread lists, settings snapshots, hook inventories, or diagnostics. +- Normalize optional and nullable app-server values before display. Users should not see raw `undefined`, `null`, protocol enum gaps, or fallback labels that imply Panel owns a Codex runtime setting. +- Route chat-visible state through `ChatStateStore` when it must synchronize with app-server notifications, turns, pending requests, runtime settings, history cursors, or open details. +- Do not use DOM order as message history state. Message stream virtualization means offscreen items may not exist in the DOM, and delayed Markdown rendering can change heights after initial render. ## API Baselines