This file tracks manual regression and feature verification steps.
- <cleanup action, if any>
- App server is running from this repository.
- A valid Telegram bot token is available.
- Access to
~/.codex/on the host machine.
- In the app UI, open Telegram connection and submit a bot token.
- Verify file
~/.codex/telegram-bridge.jsonexists. - Open
~/.codex/telegram-bridge.jsonand confirm it contains abotTokenfield. - Restart the app server and call Telegram status endpoint from UI to confirm it still reports configured.
- Telegram token is persisted in
~/.codex/telegram-bridge.json. - Telegram bridge remains configured after restart.
- Remove
~/.codex/telegram-bridge.jsonto clear saved Telegram token.
- App server is running from this repository.
- Telegram bot already configured in the app.
- Access to
~/.codex/telegram-bridge.json.
- Send
/startto the Telegram bot from your DM. - Wait for the app to process the update, then open
~/.codex/telegram-bridge.json. - Confirm
chatIdscontains your DM chat id as the first element. - In the app, reconnect Telegram bot with the same token.
- Re-open
~/.codex/telegram-bridge.jsonand confirmchatIdsremains present.
chatIdsis written after Telegram DM activity.chatIdspersists across bot reconfiguration.botTokenandchatIdsare both present in~/.codex/telegram-bridge.json.
- Remove
chatIdsor delete~/.codex/telegram-bridge.jsonto clear persisted chat targets.
- App is running from this repository.
- At least one thread exists and can be selected.
- At least one installed skill is available.
- Open an existing thread so the message composer is enabled.
- Click the
Skillsdropdown in the composer footer. - Click any skill option in the dropdown list.
- Re-open the
Skillsdropdown and click the same skill again to unselect it.
- The skills dropdown closes immediately after each selection click.
- Selected skill appears as a chip above the composer input when checked.
- Skill chip is removed when the skill is unchecked on the next selection.
- Remove the selected skill chip(s) before leaving the thread, if needed.
- App is running from this repository.
- Open the
Skills Hubview.
- Type a unique query value in the Skills Hub search input (for example:
docker), but do not press Enter or click Search yet. - Confirm the browse results do not refresh immediately while typing.
- Click the
Searchbutton. - Change the query text to another value and press Enter in the input.
- Clear the query, then click
Searchto reload the default browse list.
- Typing alone does not trigger remote Skills Hub search requests.
- Results refresh only after explicit submit via the
Searchbutton or Enter key. - Empty-state text (if shown) references the last submitted query.
- Submitting an empty query returns the default skills listing.
- Clear the search input and run a blank search to return to default listing.
- App is running from this repository.
- Home/new-thread screen is open.
- Appearance is set to
Darkin Settings. GitHub trending projectssetting is enabled.
- On the home/new-thread screen, inspect the
Choose folderdropdown trigger. - Open the
Choose folderdropdown and confirm menu/option contrast remains readable in dark mode. - Inspect the
Trending GitHub projectssection title, scope dropdown, and project cards. - Hover a trending project card and the scope dropdown trigger.
- Toggle appearance back to
Light, then return toDark.
- Local project dropdown trigger/value uses dark theme colors with readable contrast.
- Trending section title, empty/loading text, scope dropdown, and cards use dark backgrounds/borders/text.
- Hover states in dark mode stay visible and do not switch to light backgrounds.
- Theme switch back/forth preserves correct styling for both controls.
- Reset appearance to the previous user preference.
- App is running from this repository.
- Appearance is set to
Darkin Settings. - Skills Hub route is accessible.
- Open the home/new-thread screen and inspect the
Local project / New worktreeruntime selector trigger. - Open the runtime selector and verify menu title, options, selected state, and checkmark visibility in dark mode.
- Trigger a worktree action that shows worktree status and verify running/error status blocks remain readable in dark mode.
- Open
Skills Huband verify header/subtitle, search bar, search/sort buttons, sync panel, badges, and status text. - Verify at least one skill card surface (title, owner, description, date, browse icon) in dark mode.
- Open a skill detail modal and verify panel, title/owner, close button, README/body text, and footer actions in dark mode.
- Runtime dropdown trigger and menu use dark backgrounds, borders, and readable text/icons.
- Worktree status blocks use dark-friendly contrast for both running and error states.
- Skills Hub controls and sync panel are fully dark-themed with consistent hover/active states.
- Skill cards and the skill detail modal render with dark theme colors and accessible contrast.
- Reset appearance to the previous user preference.
- App is running from this repository.
- An active thread is open.
- Local file exists at
/root/New Project (1)/qwe.txt.
- Send a message containing:
Done. Created [/root/New Project (1)/qwe.txt](/root/New Project (1)/qwe.txt) with content:. - In the rendered assistant message, click the
/root/New Project (1)/qwe.txtlink. - Right-click the same link and choose
Copy linkfrom the context menu. - Paste the copied link into a text field and inspect it.
- The markdown link renders as one clickable file link (not split into partial tokens).
- Clicking opens the local browse route for the full file path.
- Copied link includes the full encoded path and still resolves to the same file.
- Delete
/root/New Project (1)/qwe.txtif it was created only for this test.
- App is running from this repository.
- Home/new-thread screen is open.
- On the home/new-thread screen, locate the runtime control below
Choose folder. - Verify both options (
Local projectandNew worktree) are visible at once without opening a menu. - Click
New worktreeand confirm it becomes the selected option style. - Click
Local projectand confirm selection returns. - Set Appearance to
Darkin Settings and verify selected/unselected contrast remains readable.
- Runtime mode is presented as a two-option toggle (segmented control), not a dropdown menu.
- Clicking each option immediately switches the selected state.
- Selected option has a distinct active background/border in both light and dark themes.
- Leave runtime mode and appearance at the previous user preference.
- App is running from this repository.
- Home/new-thread screen is open.
- Appearance is set to
Darkin Settings.
- Locate the runtime mode toggle (
Local projectandNew worktree) underChoose folder. - Hover each option and verify hover state is visible against dark backgrounds.
- Select
New worktree, then selectLocal projectand compare active/inactive contrast. - Tab to the toggle options with keyboard navigation and verify the focus ring is visible.
- Confirm icon color remains readable for selected and unselected options.
- Toggle container, options, and text/icons use dark-friendly colors.
- Hover and selected states are clearly distinguishable in dark mode.
- Keyboard focus ring is visible and does not blend into the background.
- Return appearance and runtime selection to the previous user preference.
- App is running from this repository.
- At least one existing thread is available.
- Browser local storage is enabled.
- Open the app in a regular browser tab (
http://localhost:<port>/), select any thread, then navigate back to home route (#/). - Refresh the browser tab.
- Confirm the app remains on home route and does not auto-switch to
#/thread/:threadId. - Install/open the app in PWA standalone mode, select any thread, navigate to
#/, and relaunch the PWA.
- In regular browser-tab mode, startup does not restore and redirect to the last active thread.
- In PWA standalone mode, startup also does not restore and redirect to the last active thread.
- Existing
openProjectPathstartup behavior still opens the requested project on home.
- Clear app local storage state if you need to reset startup behavior for retesting.
pnpmis installed globally (npm i -g pnpmor via corepack).- Repository is cloned and
node_modules/does not exist (or may be stale).
- Remove
node_modules/if present:rm -rf node_modules. - Run
pnpm run dev. - Wait for Vite dev server to start and display the local URL.
- Open the displayed URL in a browser.
pnpm installruns automatically before Vite starts (dependencies are installed).- Vite dev server starts successfully and serves the app.
- No
npmcommands are invoked.
- None.
- App is running from this repository.
- An active thread is open.
- Send a message containing exactly:
`https://github.com/marmeladema`. - Find the rendered message row and inspect the backticked URL token.
- Click the rendered URL.
- The backticked URL is rendered as a clickable link, not plain inline code text.
- Clicking opens
https://github.com/marmelademain a new tab.
- None.
- App is running from this repository.
- At least one thread can run a long response (for example, request a large code explanation).
- Send a prompt that keeps the assistant generating for several seconds.
- Immediately click the
Stopbutton before the first assistant chunk fully completes. - Confirm generation halts.
- Repeat with a resumed/existing in-progress thread (reload app while a turn is running, then click
Stop).
- No error appears saying
turn/interrupt requires turnId. - Turn is interrupted successfully in both immediate-stop and resumed-thread scenarios.
- Thread state exits in-progress and the stop control returns to idle.
- None.
- App is running from this repository.
- Home/new-thread screen is open.
- At least one writable parent directory exists for creating a test project folder.
- On the home/new-thread screen, open the
Choose folderdropdown. - Click
+ Add new project. - Enter a new folder name (for example
New Project Inline Test) and clickOpen. - Confirm the app selects the newly created/opened project folder.
- Repeat step 2, but enter an absolute path to an existing folder and click
Open.
- Clicking
+ Add new projectopens inline input inside the dropdown instead of navigating to/codex-local-browse.... - Entering a folder name creates/selects that project under the current base directory.
- Entering an absolute path opens that existing folder without creating a nested directory.
- Delete the test folder created in step 3 if it was created only for verification.
- App is running from this repository.
- At least one existing thread is available.
- Browser local storage may contain previous app state.
- Open an existing thread route and confirm messages are visible.
- Open
http://localhost:<port>/(home route) in the same browser profile. - Refresh the home route once.
- Close and re-open the app/tab at the home URL again.
- The app remains on the home/new-thread screen and does not auto-navigate to
/thread/<id>. - Refreshing home still keeps the user on home.
- None.
- App is running from this repository.
- A thread exists with enough messages to scroll.
- Test on a mobile-sized viewport (for example 375x812).
- Open an existing thread and scroll up to the middle of the chat history.
- Wait for an assistant response to stream while staying at the same scroll position.
- Send a follow-up message and observe chat positioning when completion finishes.
- Open the composer on mobile and drag within the composer area.
- Open/close the on-screen keyboard on mobile and verify the page layout remains usable.
- Chat behavior matches pre-PR #16 baseline (no PR #16 scroll-preservation logic active).
- No regressions from reverting PR #16 changes in conversation rendering and composer behavior.
- Mobile layout no longer includes PR #16 visual-viewport sync changes.
- Re-apply PR #16 commits if the reverted behavior is not desired.
- App is running from this repository.
- At least one thread exists with more than 10 turns/messages.
- Open a long thread that previously caused UI lag during initial load.
- While the thread is loading, immediately click another thread in the sidebar.
- Return to the long thread.
- Count visible loaded history blocks and confirm only the newest portion is shown.
- Call
/codex-api/rpcwith methodthread/readfor the same thread and inspectresult.thread.turns.length. - Call
/codex-api/rpcwith methodthread/resumefor the same thread and inspectresult.thread.turns.length.
- Initial thread load renders only the most recent 10 turns.
- UI remains responsive during thread load.
- You can switch to another thread without the UI freezing.
thread/readandthread/resumeRPC responses contain at most 10 turns.
- No cleanup required.
- App is running from this repository.
- Browser DevTools Network tab is open.
- At least two threads exist with different
cwdvalues.
- Reload the app and wait for initial data load.
- In Network tab, inspect
/codex-api/rpcrequests with methodskills/list. - Verify request params contain
cwdswith only the currently selected thread cwd. - Switch to another thread with a different cwd.
- Inspect the next
skills/listrequest and verifycwdsnow contains only the new selected thread cwd.
skills/listno longer sends every thread cwd in one request.- Each
skills/listcall includes at most one cwd for the active thread context. - Skills list still updates when changing selected thread.
- No cleanup required.
- The
docs/index.htmlfile has been updated with the new design. - A browser is available to view the page locally or via GitHub Pages.
- Open
docs/index.htmlin a browser (local file or via GitHub Pages). - Verify the fixed navigation bar at top with brand logo, section links, and "Get the App" CTA.
- Verify the announcement banner below nav shows the XCodex WASM link.
- Verify hero section displays lobster emoji, "AnyClaw" title with gradient, tagline, and four CTA buttons: "Try Web Demo", "Google Play", "Download APK", "GitHub".
- Click "Try Web Demo" button — confirm it navigates to
https://xcodex.slrv.md/#/. - Verify the stats bar shows key metrics (2 AI Agents, 1 APK, 0 Root Required, 73MB, infinity).
- Scroll to Live Demo section — verify embedded iframe loads
https://xcodex.slrv.md/#/with mock browser chrome. - Scroll to Screenshots section — verify four images render (2 desktop, 2 mobile).
- Scroll to Features section — verify 6 feature cards in a 3-column grid.
- Scroll to Testimonials section — verify two rows of auto-scrolling marquee cards (row 2 scrolls reverse). Hover to pause.
- Scroll through Architecture, Boot Sequence, Quick Start, and Tech Stack sections — verify content renders.
- Verify the footer includes a "Web Demo" link to
https://xcodex.slrv.md/#/. - Test responsive at 768px and 480px — nav links collapse, grids single-column, buttons stack vertically.
- Page has a dark, premium feel with gradient accents, grain overlay, and smooth animations.
- All links to
https://xcodex.slrv.md/#/work (announcement, hero CTA, demo section, quick start text, footer). - Marquee testimonials scroll continuously and pause on hover.
- Embedded iframe demo loads successfully.
- Mobile responsive layout works at all breakpoints.
- Revert
docs/index.htmlto previous commit if needed.
- App is running from this repository.
- A thread exists with enough history to allow scrolling away from bottom.
- Open the thread and scroll upward so latest messages are not visible.
- Send a new message that produces a streaming assistant response.
- During streaming, do not scroll and observe viewport position.
- After streaming completes, verify the viewport remains at the same manual position.
- Streaming updates do not force auto-scroll to the bottom when user has manually scrolled away.
- User can continue reading older history while the response streams.
- If the thread is already at the bottom when streaming starts, the latest streaming overlay remains visible.
- Revert the scroll-preservation change in
src/components/content/ThreadConversation.vueif manual scroll locking needs to be removed.
- App is running from this repository.
- A thread exists with at least 2 completed turns.
- Rollback control is visible in the thread conversation message actions.
- Open any existing thread with multiple turns.
- In DevTools Network tab, keep
/codex-api/rpcrequests visible. - Click rollback on a user or assistant message that is not the newest one.
- Confirm rollback succeeds and the thread is truncated to the selected turn.
- Inspect the UI event flow by repeating rollback from a different turn and confirm the selected message can rollback without relying on a numeric turn index.
- Use dictation resend flow (or "rollback latest user turn" flow) and confirm the latest user turn is rolled back correctly.
- Rollback works when triggered from message actions using
turnIdas the identifier. - No UI path depends on
turnIndexin rollback event payloads. - Latest-user-turn rollback flow still works and targets the latest user
turnId. - No TypeScript/runtime errors are introduced in rollback interaction.
- Revert the updated files if this behavior is not desired:
src/types/codex.tssrc/api/normalizers/v2.tssrc/components/content/ThreadConversation.vuesrc/App.vuesrc/composables/useDesktopState.ts
- App server is running from this repository.
- Use a fresh temporary project directory with no existing
.codex/rollbacks/.githistory.
- In a fresh test project folder, trigger rollback automation init by calling
/codex-api/worktree/auto-commitwith a valid commit message. - Verify rollback repo exists at
.codex/rollbacks/.git. - In that rollback repo, run
git --git-dir .codex/rollbacks/.git --work-tree . show --name-only --pretty=format: HEAD. - Confirm
.codex/.gitignoreappears in the file list for the init commit. - Open
.codex/.gitignoreand verifyrollbacks/exists.
- First rollback-history commit is
Initialize rollback history. - That commit includes
.codex/.gitignore. .codex/.gitignorecontainsrollbacks/.
- Remove the temporary test folder after verification.
- App server is running from this repository.
worktree git automationis enabled in UI settings.- Test thread available where you can send at least 3 user turns.
- Send a user turn that changes files and completes.
- Send a user turn that produces no file edits and completes.
- Send a third user turn and complete it.
- In rollback git history (
.codex/rollbacks/.git), verify each completed turn created a commit, including the no-edit turn. - Inspect one rollback commit body and confirm it contains the user message text plus
Rollback-User-Message-SHA256: <hash>. - Trigger rollback to the second turn message via UI rollback action.
- Verify server logs contain
[rollback-debug]entries for lookup, stash (if dirty), reset, and completion. - Temporarily test missing-commit path by calling
/codex-api/worktree/rollback-to-messagewith a non-existent message text.
- Auto-commit creates a rollback commit for every completed turn (
--allow-emptybehavior). - Commit body includes the user message and stable hash trailer.
- Rollback uses exact hash-based commit lookup only.
- If exact commit is missing, rollback returns error and does not continue.
- Server logs include
[rollback-debug]records for commit creation, lookup, stash, reset, and error paths. - Browser console includes
[rollback-debug]client-side start/success/error logs for auto-commit and rollback API calls. - Rollback init no longer fails when
.codexis ignored globally; init force-adds.codex/.gitignore.
- Revert the changed files if you want previous non-deterministic behavior back.
- App server running from this repository.
- Worktree git automation enabled.
- A thread with at least one completed turn that touched files.
- Open a thread and locate a
Worked for ...separator message. - Expand the worked separator.
- Verify a changed-files panel appears above command details.
- Confirm file list entries show file path and
+/-counts. - Click one changed file row to expand it.
- Verify diff content loads only after expansion (lazy load behavior).
- Collapse and re-expand the same file row; verify diff reuses loaded content.
- Switch to another thread and back; verify panel reloads for the active thread context.
- Each worked message can show changed files for its turn.
- Diff for a file is fetched only on expand, not for all files upfront.
- Errors (missing commit/diff load failure) are shown inline in the panel.
- Existing command output expand/collapse behavior remains unchanged.
- Changed-files panel still resolves after page refresh or app-server restart.
- Changed-files panel appears at the end of the worked message block (after command rows).
- No cleanup required.
- App server running from this repository.
- A thread with at least one
Worked for ...separator.
- Open a thread and locate a
Worked for ...message. - Click the separator line/text area.
- Verify no expand/collapse behavior is triggered on the separator itself.
- Verify changed-files panel still appears below the separator when data exists.
Worked for ...acts as a visual separator only (non-interactive).- Changed-files and command sections are not gated by a worked-separator expand toggle.
- No cleanup required.
- App server running from this repository.
- Playwright CLI available.
- Create/prepare a test workspace (example:
/tmp/rollback-pw). - Call
/codex-api/worktree/auto-commitwith:cwd=/tmp/rollback-pwmessage='pw-msg-turn-1'turnId='turn-real-1'
- Call
/codex-api/worktree/message-changeswith:- same
cwd - same
message - mismatched
turnId='turn-wrong'
- same
- Verify response is still
200and returns the matching commit data (message-hash fallback). - Capture Playwright artifact screenshot.
message-changesfirst attempts turnId lookup.- If turnId lookup misses, it falls back to exact message-hash lookup.
- API returns commit data instead of
No matching commit found for this user messagewhen message matches.
- Remove temporary test workspace if created.
- App server running from this repository.
- Existing thread in
TestChatproject with completed assistant messages. - Worktree rollback auto-commit enabled.
- Open a
TestChatthread and confirm assistant message cards render. - Verify changed-files panel is shown at the end of assistant messages that have rollback commit data.
- Hard refresh the page.
- Re-open the same
TestChatthread. - Verify changed-files panel is still shown for the same assistant message(s).
- Expand one file diff and verify diff content loads.
- Changed-files panel is attached to assistant messages (not transient worked separators).
- Changed-files panel appears only once per turn (on the last assistant message in that turn).
- Changed-files panel is hidden while a turn is still in progress.
- Panels remain available after refresh/restart because lookup is turnId/message-hash based.
- File diff expansion still lazy-loads and displays content.
- No cleanup required.
- App server stopped.
- Edit
.envdirectly, and use.env.localfor private local overrides.
- Set
ROLLBACK_DEBUG=0andVITE_ROLLBACK_DEBUG=0in.env. - Start app and trigger rollback auto-commit/message-changes flow.
- Verify
[rollback-debug]logs are not emitted in terminal/browser console. - Set
ROLLBACK_DEBUG=1andVITE_ROLLBACK_DEBUG=1in.env. - Restart app and trigger the same flow again.
- Verify
[rollback-debug]logs appear in terminal/browser console.
- Debug logs are disabled when env flags are
0. - Debug logs are enabled when env flags are
1.
- Restore
.envvalues to preferred defaults.
- App server running from this repository.
- Browser local storage key
codex-web-local.worktree-git-automation.v1is absent (new user state).
- Open the app in a fresh browser profile (or clear only
codex-web-local.worktree-git-automation.v1). - Open Settings and inspect the
Rollback commitstoggle state. - Confirm it starts in the disabled/off state.
- Enable the toggle manually.
- Reload the page and confirm the toggle remains enabled.
- Disable it again, reload, and confirm it remains disabled.
- Default state is disabled when no prior preference exists.
- User-selected state persists via local storage across reloads.
- No cleanup required.
- App running from this repository with Skills Hub available.
- GitHub skills sync configured and connected.
- At least one skill update available in the sync source (new or edited skill metadata).
- Open the app and note the currently visible installed skills for the active thread cwd.
- In Skills Hub, trigger
Pullfrom GitHub sync. - Wait for the pull success toast.
- Without restarting the app/server, navigate to thread composer skill picker and verify the installed skills list.
- Switch to another thread and back to force a normal UI refresh path.
- Pull completes successfully.
- Installed skills list reflects pulled changes immediately without app/server restart.
- Thread switch keeps showing the updated skills list (no stale cache rollback).
- If needed, run another sync pull/push to restore previous skill state in the sync repo.
- App running from this repository with Skills Hub route accessible.
- At least one installed skill is available for the current thread cwd.
- Open
Skills Hub. - In
Skills Sync (GitHub), clickForce Refresh Skills. - Verify button text changes to
Refreshing...during the request and returns after completion. - Verify success toast appears.
- Open the thread composer skills picker and confirm installed skills list is present and current.
- Switch to another thread and back to ensure refreshed list remains consistent.
Force Refresh Skillstriggers a manual refresh without requiring pull/push.- Loading state prevents duplicate clicks while refresh is in progress.
- Installed skills list updates immediately and remains updated across thread switches.
- No cleanup required.
- App running from this repository.
- At least one invalid installed skill file exists (for example unresolved merge markers in
SKILL.md).
- Open
Skills Hub. - Trigger
Force Refresh Skills. - Locate the
Some skills failed to loadpanel above the skills sections. - Verify each row shows:
- the failing
SKILL.mdpath - the exact parser error message from app server (for example invalid YAML line/column details).
- the failing
- Fix the invalid skill file and trigger
Force Refresh Skillsagain.
- SkillHub surfaces app-server load failures with detailed path and message.
- Messages are specific enough to identify the broken file and parser failure reason.
- Error panel disappears after invalid skills are fixed and refreshed.
- Restore any intentionally broken local skill files used for testing.
- Skills sync configured to a private GitHub fork.
- Local skills repo has a tracked edit in an existing skill file.
- Remote
mainhas at least one newer commit than local (simulate from another machine or commit directly on GitHub).
- Edit a local skill file (for example update description text in
SKILL.md) and keep the change. - Trigger
Startup Syncin Skills Hub. - If a non-fast-forward condition exists, allow startup sync to complete retry path.
- Re-open the same local skill file and verify your edit remains.
- Trigger
Force Refresh Skillsand verify no unexpected skill removals occurred.
- Startup sync no longer fails with non-fast-forward push due to missing remote integration.
- Local tracked skill edits remain after sync (not overwritten by remote state).
- Sync path rebases/pulls with autostash and auto-resolves conflicts by mtime policy:
- choose remote (
theirs) when remote file commit time is newer than local file mtime. - choose local (
ours) otherwise.
- choose remote (
- No manual conflict intervention is required during startup sync retries.
- Revert test-only skill text changes if they were not intended to keep.
- Skills sync repo contains a conflict candidate where only one side exists for a path (for example delete/modify scenario).
- Skills Hub is accessible.
- Open
Skills Hub. - Click
Startup Sync. - Wait for sync completion or error toast.
- Verify no toast/error contains
does not have our version.
- Sync conflict resolver handles missing
--ours/--theirsversions safely. - Startup sync does not fail with
git checkout --ours/--theirsmissing-version errors.
- None.
- Skills sync configured with GitHub.
- Local skills repo working tree is clean (
git status --porcelainempty under skills dir). - Remote skills repo has newer commits touching existing skill files.
- Confirm no local uncommitted changes in skills directory.
- Trigger
Startup Syncin Skills Hub. - After sync, inspect the skill file changed remotely.
- Trigger
Force Refresh Skillsand confirm loaded skill content matches remote update.
- Sync pull/reconcile does not preserve stale local file content when local tree is clean.
- Remote updates are applied locally and remain after startup sync completes.
- None.
- Skills sync configured to
friuns2/codexskills. - Remote
maincontainsAGENTS.md. - Local skills repo is clean before startup sync.
- Confirm remote
AGENTS.mdexists onmain. - Confirm local
~/.codex/skillsis clean. - Trigger
Startup Sync. - After completion, inspect latest commit created by sync (if any).
- Verify
AGENTS.mdstill exists locally and in remoteorigin/main.
- Startup sync may update manifest, but must not delete
AGENTS.md. - If sync creates a commit, changed files do not include
D AGENTS.md. - Local and remote
AGENTS.mdhashes remain equal after sync.
- None.
- Skills sync configured to
friuns2/codexskills. ~/.codex/skillsis a clean git working tree before each sub-test.- Skills Hub startup sync endpoint is reachable.
- Remote -> Local:
- Add a unique marker to remote
AGENTS.mdonmain. - Confirm local
HEADis behindorigin/main. - Trigger
Startup Sync. - Verify local
AGENTS.mdcontains the remote marker and localHEAD == origin/main. - Local -> Remote:
- Add a different unique marker to local
~/.codex/skills/AGENTS.md. - Confirm local working tree shows
M AGENTS.md. - Trigger
Startup Sync. - Verify remote
origin/main:AGENTS.mdcontains the local marker and localHEAD == origin/main.
- Remote-only AGENTS edits are pulled into local without deletion.
- Local AGENTS edits are pushed to remote after startup sync.
- After each sync direction, local and remote commit SHAs match.
- Remove temporary test markers from
AGENTS.mdif required.
- Skills sync configured and working.
- Local skills repo clean before test start.
- Add marker
Ato remoteAGENTS.md. - Add marker
Bto localAGENTS.mdbefore syncing. - Trigger
Startup Sync. - Wait for startup status to finish (
inProgress=false). - Verify sync outcome explicitly:
- If sync succeeds, local/remote SHAs match and expected merged marker result is present.
- If sync fails, status includes a concrete error message (not silent success).
- Startup sync must not report success while local remains behind remote.
- No stale stash side-effects are introduced (no unexpected conflict from old stash entries).
- Final state is either a valid synchronized result or an explicit failure status with actionable error.
- Reset local skills repo to
origin/mainafter test if needed.
- Skills sync is logged in and targets
friuns2/codexskills. - Local repo path is
~/.codex/skills. - Startup Sync endpoint is reachable at
/codex-api/skills-sync/startup-sync.
- Remote-only case:
- Commit a unique marker to remote
AGENTS.mdonmain. - Ensure local repo is clean and reset to
origin/main, then triggerStartup Sync. - Confirm marker appears locally and
HEAD == origin/main. - Local-only case:
- Add a unique local marker to
~/.codex/skills/AGENTS.md(uncommitted), triggerStartup Sync. - Confirm marker is pushed and
HEAD == origin/mainwith clean worktree. - Mixed case:
- Add local marker first, then commit a newer remote marker.
- Trigger
Startup Syncand verify mtime policy result (newer remote marker wins, older local marker dropped). - Confirm final state is clean with
HEAD == origin/main.
- Startup sync does not fail with missing merge refs (
MERGE_HEAD/REBASE_HEAD) in this path. - Remote-only changes are always pulled first and visible locally.
- Local-only changes are preserved and pushed during the same startup sync run.
- Mixed local+remote edits converge automatically with no manual conflict handling.
- Remove temporary test markers from
AGENTS.mdif not needed.
- App builds successfully (
pnpm run build). - Open a thread with enough messages to scroll.
- Composer is visible in the main chat view.
- Open a long thread and scroll upward away from bottom.
- Trigger live overlay updates (for example by sending a new prompt) and observe scroll behavior.
- Confirm message list horizontal overflow behavior in conversation and desktop main area.
- In composer, verify there is no drag/drop overlay UI when dragging files over the input.
- In composer, paste an image from clipboard and verify it is not auto-attached through paste handler.
- Use file picker/camera attach buttons and confirm attachments still work.
- Confirm Fast mode UI/toggle remains present and unchanged.
- Scroll behavior follows reverted layout logic for conversation/desktop containers.
- Composer drag-active overlay is removed from the input field layout.
- Clipboard image paste no longer triggers drag/paste attachment flow.
- Standard picker-based attachments still work.
- Fast mode button and related controls are unchanged.
git restore src/components/content/ThreadComposer.vue src/components/content/ThreadConversation.vue src/components/layout/DesktopLayout.vue src/style.css tests.md
- App server is running from this repository.
- Open a thread that contains rendered
.message-file-linkanchors (for example Markdown file links).
- In a message with a file link, right-click the file link text.
- Verify the custom context menu appears near the pointer.
- Click
Open linkand confirm the link opens in a new tab. - Right-click the same file link again and click
Copy link, then paste into a text input to verify copied value. - For links under
/codex-local-browse..., right-click and clickEdit file. - Click outside the menu and press
Escapewhile the menu is open.
- Right-clicking any
.message-file-linkopens the custom context menu. - Menu includes
Open linkandCopy linkfor all links. - Menu includes
Edit fileonly for browseable local file links. - Pointer-down outside, blur, and
Escapeclose the menu.
- Close any tabs opened during the test.
- App is running from this repository.
- Open any thread that contains command execution entries.
- Appearance is set to
Darkin Settings.
- Open a thread with one or more command execution rows in the conversation.
- Verify command label text, grouped command label text, and status text in collapsed rows.
- Locate a file-change summary row (for example:
▶ 2 files changed · 2 edited) and verify the chevron and summary text are readable. - Expand a command row to show output and inspect the output panel border contrast.
- Confirm status colors for running/success/error command rows are distinguishable in dark mode.
- Toggle back to
Lighttheme and confirm command rows still use the existing light styling.
- Command labels and grouped command labels are readable against dark row backgrounds.
- File-change summary rows keep readable chevron and summary text in dark mode.
- Default status text is readable in dark mode.
- Running/success/error status colors remain visible in dark mode.
- Expanded command output border is visible without using a bright light-theme border.
- Light theme command row styling is unchanged.
- Return appearance setting to the previous user preference.