Skip to content

feat(host-runtime): add archive health inspection and safe force-archive entry (Refs #424) - #614

Draft
Tericerice wants to merge 7 commits into
BytePioneer-AI:mainfrom
Tericerice:feat/archive-health-and-force-archive
Draft

Tericerice wants to merge 7 commits into
BytePioneer-AI:mainfrom
Tericerice:feat/archive-health-and-force-archive

Conversation

@Tericerice

@Tericerice Tericerice commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds archive health inspection and a safe force-archive entry point to CodexHost, so users and tools can diagnose inconsistent or failed archive states and recover threads without data loss.

Part 2 of Issue #424 resolution.

1. Archive health inspection (codexhost/archive/health · GET /api/archive/health)

  • External Threads: inspects MappingStore records and loaded runtime instances for failed session releases, unavailable/faulted sessions, uncommitted creating records, and in-memory instances with no persisted record. Already-archived records and healthy prewarm drafts are not reported.
  • Official Codex sessions: lists live Codex CLI processes holding official sessions, matching the real executable only (Codex.app bundles, its helpers, and any codexhost-owned process are excluded; the Host's whole process subtree is skipped) and returning PID, command line, and a platform-appropriate termination hint.
  • Summary metrics: totalInconsistent, officialOccupied, externalRecoverable.
  • A MappingStore read failure fails the inspection explicitly instead of reporting a healthy Host.

2. Safe force-archive (codexhost/archive/force · POST /api/archive/force)

  • Rejects Threads with a running Turn or background work with -32072.
  • Closes the loaded session and drains its outputs under a 60s bound. If the close is rejected or does not settle, the instance stays loaded and the request fails with -32075, so recovery can never open a second writer on the same native session.
  • Only after a confirmed close does it detach the instance, persist archived=true, and emit thread/archived. No transcript, Turn mapping, or native history is modified or deleted.
  • Supports detaching pure in-memory orphans that have no MappingStore record.
  • A MappingStore read failure returns -32081; only a successful read returning nothing is treated as "not found" (-32602).
  • Surrounding whitespace in the Thread ID is rejected (-32602), so a padded ID cannot open a second per-Thread queue for the same instance.

3. Console integration and serialization

  • codexhost/archive/health and codexhost/archive/force added to CONSOLE_HOST_METHODS and exposed as REST routes.
  • Console force-archive joins the same per-Thread request queue and idle-release operation tracking as Desktop requests.
  • Console REST maps Host errors to real HTTP statuses (404 / 409 / 500) instead of returning 200 with an error envelope.

4. OpenSpec and tests

  • openspec/specs/external-thread-list-archive-routing/spec.md gains archive-health and forced-archive requirements and scenarios.
  • Unit tests cover close rejection, close and drain timeouts, store read failures, busy Threads, orphan detach, prewarm drafts, process recognition, quoted paths, and descendant-tree exclusion.
  • RPC integration tests cover the health/force entry points and the whitespace-ID rejection.

Refs #424

🤖 Generated with Claude Code

…ive entry (BytePioneer-AI#424)

- Add ArchiveHealthService to inspect inconsistent external threads (failed release, session unavailable, uncommitted provisional records, orphaned runtime entries)
- Detect live codex CLI processes occupying official Codex sessions with actionable remediation hints
- Provide safe force-archive entry (codexhost/archive/force) updating MappingStore metadata and detaching runtime session without deleting turns or data
- Expose console RPC methods codexhost/archive/health and codexhost/archive/force with REST endpoints /api/archive/health and /api/archive/force
- Add unit tests for ArchiveHealthService and RPC integration tests in console-server and app-server-host

Co-Authored-By: Claude Code <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Tericerice and others added 6 commits October 26, 2026 11:23
…rchive (BytePioneer-AI#424)

- Address Round 1 review findings from Codex and Pi:
  - Guard forceArchive: safely close loaded sessions, drain output tasks, and reject active running turns or busy background work (-32072)
  - Allow forceArchive to detach orphaned in-memory instances without MappingStore records
  - Skip already archived records during inspection, and align provisional records with 'creating' state
  - Refine process inspection: strictly match codex CLI executables, filter out Electron renderers/helpers and codexhost child processes, and support PowerShell on Windows
  - Map console REST errors to appropriate HTTP status codes (404/409/500)
  - Sync OpenSpec with archive health inspection and safe forced archive requirements
  - Fix test type errors in server.test.ts and archive-health-service.test.ts

Co-Authored-By: Claude Code <noreply@anthropic.com>
…iving (BytePioneer-AI#424)

Round 2 review findings from Codex and Pi:

- forceArchive now rejects active turns and background work (-32072), then closes the
  session and drains the output task under a 60s bound; a failed or timed-out close
  keeps the instance loaded and returns -32075 so recovery cannot open a second writer
- Console force-archive joins the per-thread request queue and idle-release operation
  tracking, so it can no longer interleave with Desktop requests on the same Thread
- A MappingStore read failure returns -32081 instead of being mistaken for a pure
  in-memory orphan, which previously archived without any durable write
- Process detection matches the real executable (rejecting Codex.app bundles, helpers,
  and any codexhost-owned process) and excludes the Host's whole process subtree
- Notifications after a durable archive write are best-effort, so a dropped Desktop
  connection no longer reports a completed archive as failed
- Tests cover close rejection, store read failure, busy threads, orphans, prewarm
  drafts, process recognition, and argument parsing

Co-Authored-By: Claude Code <noreply@anthropic.com>
… quoted scripts (BytePioneer-AI#424)

Round 3 review findings from Codex:

- Reject force-archive requests whose Thread ID carries surrounding whitespace, and
  key the console lane by the canonical ID, so a padded ID cannot open a second
  per-Thread queue while operating on the same instance
- Parse interpreter script arguments on quote boundaries, so
  `node "/opt/my tools/codex.js" app-server` is recognised as a Codex CLI
- Add tests for a whitespace Thread ID through the real RPC entry point, for a close
  that never settles, for an output drain that never settles, and for quoted scripts

Co-Authored-By: Claude Code <noreply@anthropic.com>
…PC fast (BytePioneer-AI#424)

The cross-platform CI run showed the archive-health RPC test timing out on Windows: the
inspection shells out to powershell/ps, which can exceed the fixture's 10s wait. Two fixes:

- Summaries now carry processScan = ok | failed | skipped, so a scan that could not run
  is never reported as 'no official sessions occupied', and includeOfficial=false reports
  skipped rather than a silent zero
- Bound the scan to 10s and keep the RPC integration test on includeOfficial=false, so it
  asserts Host routing rather than the runner's process table

Co-Authored-By: Claude Code <noreply@anthropic.com>
…or mapping (BytePioneer-AI#424)

Round 2 Pi findings that still applied to the head:

- Persist archived=true before detaching the instance; a failed archive write returns
  -32081 and leaves the Thread registered, so a caller never sees 'archived' while the
  durable state says otherwise
- Drop the never-produced occupyingPid/occupyingCommand fields and the 'official' kind
  from the inconsistent-thread contract
- Cover the console REST error mapping (-32602 → 404, -32072 → 409, other → 500) and
  the archive-write failure path
- Document both archive entries, their failure codes, and processScan in
  docs/operations/codexhost-console.md

Co-Authored-By: Claude Code <noreply@anthropic.com>
…ytePioneer-AI#424)

Pi's round-3 review found the identity guard checked only the Thread object, which a
delegation request can revive in place by swapping thread.session while the archive write
is in flight. Detaching then dropped a live native session with no owner, and the next
resume would open a second writer on it.

- Record the Session that was closed and only detach while the Thread still owns it; a
  revival now returns -32076 and keeps the live Session registered
- Mirror the delete path by forgetting route observation once a Thread is detached
- Exclude Desktop's own CLI copies (app/resources/codex.exe, CodexCLI.app, cached
  OpenAI/Codex/bin) from process detection, so Windows no longer reports Desktop's helper
  as an occupying process with a kill hint
- Report a Mapping Store read failure from health inspection as -32081, not -32603
- Hide the PowerShell window the Windows scan spawns
- Share one idle policy between idle release and forced archive
- Correct the console doc that still said no Thread operations are accepted

Co-Authored-By: Claude Code <noreply@anthropic.com>
@BytePioneer-AI

Copy link
Copy Markdown
Owner

感谢贡献!我们已关注到这个 PR,会尽快安排审查。
Thanks for your contribution! This PR is on our radar, and we’ll review it as soon as possible.

@BytePioneer-AI

Copy link
Copy Markdown
Owner

感谢你的贡献!想确认一下,这个 PR 当前是否已经准备好转为正式 PR(Ready for review),进入评审?

如果已经准备好,欢迎取消草稿状态;如果仍在开发、存在阻塞或希望暂缓,也欢迎简单说明当前进展,方便我们安排后续评审。谢谢!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants