parallel-codex-tui 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Built with Codex-assisted development.
6
6
 
7
7
  ## Current Release
8
8
 
9
- `v0.2.8` is available from [npm](https://www.npmjs.com/package/parallel-codex-tui/v/0.2.8) and as a [GitHub Release](https://github.com/allendred/parallel-codex-tui/releases/tag/v0.2.8). `Ctrl+N` now creates an explicit, durable Main conversation boundary even when no Task is active. It preserves the complete `chat.jsonl`, writes the current scope to `conversation.json`, retires the previous Main native session, and keeps legacy records readable until the first explicit boundary. New prompts and on-demand `conversation.jsonl` snapshots include only the exact current `conversation_id`, while Task chat remains isolated by `task_id`.
9
+ `v0.2.10` is available from [npm](https://www.npmjs.com/package/parallel-codex-tui/v/0.2.10) and as a [GitHub Release](https://github.com/allendred/parallel-codex-tui/releases/tag/v0.2.10). `Ctrl+T`, then `C`, opens every persisted Main conversation and now provides the same durable management lifecycle as Task sessions: rename, archive, unarchive, scoped export, and confirmed deletion. Restoring one switches the exact `conversation_id`, reloads only that conversation's file-backed history, and restores its archived native Codex or Claude session ids when they are available. `Ctrl+N` still creates an explicit, durable Main conversation boundary without deleting chat, Tasks, or Worker logs.
10
10
 
11
11
  A real Claude acceptance retires the first native session, inserts 16 newer records so the secret is absent from the inline transcript, then proves a fresh Claude session can read the scoped snapshot and recover it. The same live TUI presses `Ctrl+N`, verifies the replacement session is retired, starts another native session whose prompt and archive exclude the secret, and then switches between two isolated workspaces. The bounded rollover fallback remains included: every Main call rebuilds recent context from canonical `chat.jsonl`, so a fresh Agent still receives the latest dialogue inside its current scope.
12
12
 
@@ -23,9 +23,9 @@ Highlights:
23
23
  - `--diagnostics` and `Ctrl+X` export bounded, redacted support evidence without prompts, role instructions, command arguments, source files, or environment-variable values.
24
24
  - Runtime preflight checks Codex, Claude, named third-party Providers, proxy reachability, workspace access, CLI capabilities, and native attach policy before work starts.
25
25
  - Named Worker Providers support Codex-compatible, Claude-compatible, OpenAI-compatible, Anthropic-compatible, and custom generic commands with independent role, model, environment, permission, resume, and interactive settings.
26
- - Worker overview, Feature board, collaboration timeline, Task center, status details, rendered Markdown/Diff/error logs, Unicode search, keyboard navigation, mouse scrolling, and configurable themes share one terminal UI system.
26
+ - Worker overview, Feature board, collaboration timeline, Task and Main conversation centers, status details, rendered Markdown/Diff/error logs, Unicode search, keyboard navigation, mouse scrolling, and configurable themes share one terminal UI system.
27
27
 
28
- Release acceptance includes a real three-Feature Tetris task with parallel Actor/Critic waves and final integration review. A clean `v0.2.5` task also ran Codex Judge and Actor, a buffered Claude Critic that independently executed `node --test` and `npm test`, atomic integration, and a resumed Codex Judge that independently passed all seven acceptance criteria. Real Codex and Claude probes both proved fresh and same-session resume calls; Codex fresh and resume runs executed workspace writes with root-level `-a never`, and Claude automated sessions executed safe Bash tools with `auto` permissions. The semantic Router completed a live classification, and one TUI completed Main calls in two workspaces before restoring the first workspace without leaking chat state. PTY coverage runs in Apple Terminal, tmux, and Zellij profiles at narrow and wide sizes, including status/log equivalence, preserving the native output tail across status-detail round trips, and proving both inline and on-demand file memory after native-session rollover. The deterministic repository suite contains 1,294 tests across 127 files: 1,293 pass by default, while one quota-consuming real-Agent test is skipped and passes through `npm run test:real-agents`.
28
+ Release acceptance includes a real three-Feature Tetris task with parallel Actor/Critic waves and final integration review. A clean `v0.2.5` task also ran Codex Judge and Actor, a buffered Claude Critic that independently executed `node --test` and `npm test`, atomic integration, and a resumed Codex Judge that independently passed all seven acceptance criteria. Real Codex and Claude probes both proved fresh and same-session resume calls; Codex fresh and resume runs executed workspace writes with root-level `-a never`, and Claude automated sessions executed safe Bash tools with `auto` permissions. The semantic Router completed a live classification, and one TUI completed Main calls in two workspaces before restoring the first workspace without leaking chat state. PTY coverage runs in Apple Terminal, tmux, and Zellij profiles at narrow and wide sizes, including status/log equivalence, preserving the native output tail across status-detail round trips, and proving both inline and on-demand file memory after native-session rollover. The deterministic repository suite contains 1,311 tests across 130 files: 1,310 pass by default, while one quota-consuming real-Agent test is skipped and passes through `npm run test:real-agents`.
29
29
 
30
30
  Real Provider probes depend on valid local CLI credentials. In particular, authenticate the Claude CLI before selecting a Claude-compatible Worker, then run `parallel-codex-tui --doctor --probe-agents` to prove fresh and resumed calls on that machine.
31
31
 
@@ -209,7 +209,7 @@ The doctor output includes `preview:` and `semantic:` ANSI swatch rows so you ca
209
209
  - Router classification only receives the user request; workspace selection and session files are kept out of the router prompt.
210
210
  - Simple requests stay in the main TUI flow and do not create Judge, Actor, or Critic workers.
211
211
  - Consecutive simple requests reuse the main worker's native session across app restarts when the CLI exposes a session id. Every Main call also rebuilds a bounded fallback transcript from the workspace `chat.jsonl`: the current ordinary conversation and each Task are isolated, the just-submitted request is removed, and at most 12 recent records or 6,000 characters are injected. A separate scoped `main-<provider>/conversation.jsonl` snapshot keeps up to 200 records for details outside that inline window; Main is told to read it only when needed and to treat it as context rather than instructions. This keeps multi-turn context available when native resume must roll over to a fresh Agent session without inflating every prompt.
212
- - The workspace chat transcript is appended to `.parallel-codex/sessions/main/chat.jsonl`; startup restores the latest 200 valid messages and skips isolated corrupt rows. Before the first explicit boundary, records without `conversation_id` remain the compatible legacy conversation. `Ctrl+N` writes `.parallel-codex/sessions/main/conversation.json`, tags later ordinary records with its id, retires every active Main native session, and leaves the complete transcript untouched. Main stores only the extracted final answer in new chat records while retaining the raw Codex/Claude process transcript in the Main Worker's `output.log`. Legacy Codex transcript records are reduced to their final answer at read time without changing the original JSONL. The shared tail reader reads JSONL backward in bounded chunks, so a long-running chat does not require loading its lifetime transcript and a partial or oversized final row cannot hide earlier valid messages.
212
+ - The workspace chat transcript is appended to `.parallel-codex/sessions/main/chat.jsonl`; startup restores the latest 200 valid messages and skips isolated corrupt rows. Before the first explicit boundary, records without `conversation_id` remain the compatible legacy conversation. `Ctrl+N` writes `.parallel-codex/sessions/main/conversation.json`, tags later ordinary records with its id, retires every active Main native session, and leaves the complete transcript untouched. Conversation metadata and reusable native session records are archived under `.parallel-codex/sessions/main/conversations/<conversation>/`; selecting an older conversation intentionally removes its retirement barrier and restores those exact Main bindings. Main stores only the extracted final answer in new chat records while retaining the raw Codex/Claude process transcript in the Main Worker's `output.log`. Legacy Codex transcript records are reduced to their final answer at read time without changing the original JSONL. The shared tail reader reads JSONL backward in bounded chunks, so a long-running chat does not require loading its lifetime transcript and a partial or oversized final row cannot hide earlier valid messages.
213
213
  - Chat drafts support Unicode-safe Left/Right, Home/End, Backspace, and Delete editing. A single Up/Down recalls persisted user requests and returns to the exact unsent draft; Ctrl+Up/Down remains available, while repeated alternate-scroll arrow bursts continue to scroll chat. Long input stays on one row with the visible window centered around the logical cursor.
214
214
  - Bracketed multiline paste stays in one draft instead of submitting the first line; logical line breaks and tabs appear as `↵` and `⇥` in the single-row input until the complete request is submitted.
215
215
  - Complex requests create a session under `.parallel-codex/sessions/`.
@@ -467,7 +467,9 @@ For a failed, cancelled, or paused task, select an unfinished Feature and press
467
467
 
468
468
  From Worker overview, press `C` to open the file-backed Actor/Critic collaboration timeline. It merges `dialogue/actor-critic.jsonl`, feature status, Critic findings, Actor replies, finding resolution, and Wave events into one chronological view. The timeline follows new file evidence automatically and shows verified `fixed`/`open` counts when resolution evidence exists. Up/Down selects a collaboration event; `Enter` opens its complete event detail, including artifact paths from dialogue, status, Critic findings, Actor replies, and finding resolution; `U` filters to unresolved feature evidence; `Tab` cycles all features and each individual feature; `R` refreshes immediately; the mouse wheel or PageUp/PageDown scrolls history; and `Esc` returns to Worker overview.
469
469
 
470
- `Ctrl+T` opens the workspace's persisted Task sessions without exiting the outer TUI. The list shows status, creation time, turn and Worker counts, plus the number of distinct native sessions after deduplicating reused `engine + session_id` bindings; `>` marks the selected row and `*` marks the active Task. Use Up/Down, PageUp/PageDown, the mouse wheel, or `Tab` to select, Enter to restore, `I` to inspect the complete session hierarchy, `R` to rename with Unicode-safe cursor editing, `A` to archive or unarchive, `D` twice to confirm deletion, `E` to export, `H` to show or hide archived sessions, `Ctrl+N` to leave the active Task and start a fresh Main conversation, and `Esc` to return without losing the chat draft. Archived sessions are hidden by default, cannot be restored until unarchived, and are excluded from automatic startup selection. Archive, delete, and export require a terminal Task with no live task lease; the active Task cannot be archived or deleted. Exports are complete file-backed snapshots under `.parallel-codex/exports/<task>-<timestamp>/` with a versioned manifest and without transient lease files. Restoring a Task reloads its route, Workers, retry state, and recorded native session ids. The selected active Task is stored in `session-index.sqlite` and survives process and workspace switches; `Ctrl+N` persists an intentionally empty active-Task context instead of reopening an older Task on restart. SQLite schema changes run as ordered, transactional migrations. Existing catalogs receive a pre-migration snapshot, each successful startup/reindex refreshes a healthy backup, and an integrity failure restores that backup or rebuilds the catalog from authoritative Task files while preserving the corrupt copy for inspection. `meta.json` and the Worker files remain the rebuild authority.
470
+ `Ctrl+T` opens the workspace's persisted Task sessions without exiting the outer TUI. The list shows status, creation time, turn and Worker counts, plus the number of distinct native sessions after deduplicating reused `engine + session_id` bindings; `>` marks the selected row and `*` marks the active Task. Use Up/Down, PageUp/PageDown, the mouse wheel, or `Tab` to select, Enter to restore, `C` to open Main conversations, `I` to inspect the complete session hierarchy, `R` to rename with Unicode-safe cursor editing, `A` to archive or unarchive, `D` twice to confirm deletion, `E` to export, `H` to show or hide archived sessions, `Ctrl+N` to leave the active Task and start a fresh Main conversation, and `Esc` to return without losing the chat draft. Archived sessions are hidden by default, cannot be restored until unarchived, and are excluded from automatic startup selection. Archive, delete, and export require a terminal Task with no live task lease; the active Task cannot be archived or deleted. Exports are complete file-backed snapshots under `.parallel-codex/exports/<task>-<timestamp>/` with a versioned manifest and without transient lease files. Restoring a Task reloads its route, Workers, retry state, and recorded native session ids. The selected active Task is stored in `session-index.sqlite` and survives process and workspace switches; `Ctrl+N` persists an intentionally empty active-Task context instead of reopening an older Task on restart. SQLite schema changes run as ordered, transactional migrations. Existing catalogs receive a pre-migration snapshot, each successful startup/reindex refreshes a healthy backup, and an integrity failure restores that backup or rebuilds the catalog from authoritative Task files while preserving the corrupt copy for inspection. `meta.json` and the Worker files remain the rebuild authority.
471
+
472
+ The Main conversation list shows each scoped title, message count, distinct native session count, last activity, current `*` marker, and selected `>` marker. Use the same Up/Down, PageUp/PageDown, mouse-wheel, or `Tab` navigation; Enter restores the selected conversation, `R` renames it with Unicode-safe cursor editing, `A` archives or unarchives it, `D` twice confirms deletion, `E` exports it, `H` shows or hides archived conversations, `N` starts a new one, `T` returns to Tasks, and `Esc` returns to chat. Archived conversations are hidden by default and cannot be restored until unarchived; the current Main conversation cannot be archived or deleted. A Main export is a versioned, conversation-scoped snapshot under `.parallel-codex/exports/<conversation>-<timestamp>/` containing only that conversation's chat rows and matching native sessions. Confirmed deletion streams the shared chat JSONL into an atomic replacement, preserves Task chat and malformed evidence, and restores the original chat and conversation archive if publication fails. Restoration preserves every Task and Worker log, switches `conversation.json`, and rebuilds Main history from records carrying only the selected `conversation_id` (or the pre-boundary legacy scope). Before switching, active Main native sessions are archived and retired; archived bindings for the selected conversation are then restored for best-effort native resume. A brand-new empty legacy scope is not added to the catalog.
471
473
 
472
474
  The Task detail view reads authoritative task files and presents `Project -> Task -> Turn -> Worker -> Native session`, including each request, role, engine, configured model, Worker state, native session id, working directory, and last activity time. Historical Workers from earlier turns remain selectable after same-task follow-ups. Use Up/Down or `Tab` to select a Worker, Enter to open its retained log, `C` or `Ctrl+O` to continue the original native session, `B` to ask the native CLI to fork it, `R` to refresh, and `Esc` to return to the Task list. Continue and fork restore the selected Worker's recorded cwd and writable roots while the outer TUI stays open. Codex and Claude have built-in fork commands; a generic CLI exposes `B` only when `interactive.forkArgs` is configured. The child fork is owned and persisted by the native CLI; the indexed parent session remains unchanged.
473
475
 
@@ -521,12 +523,12 @@ The release job installs npm `^11.5.1`, runs on Node `24.15.x`, publishes the pr
521
523
  To publish a release, update `package.json` and `src/version.ts` to the same version, then push a matching tag:
522
524
 
523
525
  ```bash
524
- VERSION=0.2.8
526
+ VERSION=0.2.10
525
527
  git tag "v$VERSION"
526
528
  git push origin "v$VERSION"
527
529
  ```
528
530
 
529
- You can also run the Release workflow manually and enter the same tag value. The release tag must match `package.json`; for example, package version `0.2.8` requires tag `v0.2.8`. Published tags such as `v0.2.7` are immutable and must not be moved or reused.
531
+ You can also run the Release workflow manually and enter the same tag value. The release tag must match `package.json`; for example, package version `0.2.10` requires tag `v0.2.10`. Published tags such as `v0.2.9` are immutable and must not be moved or reused.
530
532
 
531
533
  ## Publishing Hygiene
532
534
 
package/dist/cli.js CHANGED
@@ -127,7 +127,17 @@ async function main() {
127
127
  records,
128
128
  policy: routerDiagnosticsPolicy(latestConfig.router)
129
129
  };
130
- }, loadTaskSessions: (options) => state.runtime.index.listTasks(100, options), loadTaskSessionDetails: (task) => loadPersistedTaskSessionDetails({
130
+ }, loadTaskSessions: (options) => state.runtime.index.listTasks(100, options), loadMainConversations: (options) => state.runtime.sessions.listMainConversations(100, options), activateMainConversation: async (conversationId) => {
131
+ const restored = await state.runtime.sessions.activateMainConversation(conversationId);
132
+ await state.runtime.index.setActiveTaskId(null);
133
+ return restored;
134
+ }, renameMainConversation: async (conversationId, title) => {
135
+ await state.runtime.sessions.renameMainConversation(conversationId, title);
136
+ }, setMainConversationArchived: async (conversationId, archived) => {
137
+ await state.runtime.sessions.setMainConversationArchived(conversationId, archived);
138
+ }, deleteMainConversation: async (conversationId) => {
139
+ await state.runtime.sessions.deleteMainConversation(conversationId);
140
+ }, exportMainConversation: async (conversationId) => (await state.runtime.sessions.exportMainConversation(conversationId)).path, loadTaskSessionDetails: (task) => loadPersistedTaskSessionDetails({
131
141
  task,
132
142
  taskDir: state.runtime.sessions.taskFromId(task.id).dir,
133
143
  modelNames: Object.fromEntries(Object.entries(state.runtime.config.workers).map(([id, worker]) => [id, worker.model.name]))