Skip to content

fix(runtime): expose terminal output observations without inferring working state - #146

Merged
ChesterRa merged 2 commits into
ChesterRa:mainfrom
chriscoveries:fix/pty-output-activity
Oct 23, 2026
Merged

ChesterRa merged 2 commits into
ChesterRa:mainfrom
chriscoveries:fix/pty-output-activity

Conversation

@chriscoveries

@chriscoveries chriscoveries commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Revised per review. Terminal output does not establish whether a process is
working: a model can compute silently for long periods, and a spinner or a
prompt waiting for input can keep printing. This version separates
observation from inference.

What changes

  • cccc-runtime records when each terminal session last wrote output, as
    a wall-clock time for display and a monotonic instant for the quiet
    duration. cccc_runtime::last_output(group_id, actor_id) returns it for
    the live session only. A new session starts without an observation.
  • Actor fields add two display-only values for a running terminal Actor:
    pty_last_output_at (RFC 3339) and pty_quiet_seconds. They are null
    before the first output, for stopped Actors and for non-terminal runners.

What does not change

  • A terminal Actor without authoritative turn information still reports
    waiting / pty_running_state_unknown. idle_seconds and
    effective_working_updated_at keep their current values. The new fields
    never feed the working state.
  • Managed sessions, event-driven runtimes and headless runners keep
    precedence and behave as before.
  • There is no timing window and no new setting.

Tests (unix, real PTY processes)

  • quiet ongoing work (prints once, then computes silently): the state stays unknown;
  • noisy input-waiting (a prompt redrawn every 0.2 s): the state stays unknown while the observation advances;
  • print-then-sleep: observations only, and the last-output time is stable;
  • a new PTY session resets the observations;
  • a managed session keeps its state while its terminal prints.

Verification: GitHub Actions CI on the fork at exact head 337a6b2a421e6a57bf8b56cc6c33d8f0b1a2d361 (run 39806606736) passed all six jobs, including rust-linux. The test-only red reference 7413e80c22e598e5a8072c5d4b12bd50fb60fc08 on the #146 head c4c9e7a02048aa36320dc3a807ea5e8e03ce65f6 (run 39806615317) fails exactly the four output-inference cases and the managed-session case, where the observation field is absent.

…tput

A terminal (PTY) Actor without a managed session, such as a Hermes or Devin
TUI or a custom command, was always reported as
waiting / pty_running_state_unknown, so its status ring never moved.

The daemon already reads every byte such a process writes to its terminal.
Record when the session last produced output and report it:

- output within the last 10 seconds: working (pty_output_recent)
- otherwise: idle (pty_output_quiet), with idle_seconds since the last output
- no output yet: unchanged (waiting / pty_running_state_unknown)

The rule does not depend on the runtime. CCCC_PTY_ACTIVE_WINDOW_SECONDS
(1-600) overrides the 10-second window. A restart starts a new session, so
the record never carries over from a previous process.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EHHL9uWYgNe2MEc7uMqddX
@chriscoveries

chriscoveries commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Live end-to-end run (claw: Debian 13, Skylake 8vCPU AVX2/AVX-512, 15G RAM), 2026-10-21, built cccc binaries in a throwaway CCCC_HOME, real daemon and real PTY. A custom-runtime Actor prints one line a second for 8 seconds, then stays alive and silent; cccc actor list is read every 0.5 s for 35 s.

  • upstream main 3d3d10cb: waiting / pty_running_state_unknown the whole time, idle_seconds null.
  • this branch (merged locally on main with the rest of this batch, 1664c16f): working / pty_output_recent from the first line (0.35 s after start) while it prints; idle / pty_output_quiet 10 s after the last line (17.3 s), with idle_seconds counting up from there (28 at the end).

Copy link
Copy Markdown
Owner

The missing PTY observability is real, but I am holding this version because output activity does not establish working or idle. A model can compute silently for longer than ten seconds; a spinner or a process waiting for input can keep printing. Changing the window cannot resolve those counterexamples.

Please separate observation from inference: expose last-output time / quiet duration for display, while retaining an unknown working state when the runtime supplies no authoritative turn information. Preserve managed-session precedence and reset observations on a new PTY session. Add cases for quiet ongoing work and noisy input-waiting, rather than only print-then-sleep.

That narrower observability change would be useful without changing the meaning of the shared working-state fields or introducing a global timing knob.

…unknown

Terminal output does not establish whether a process is working: a model
can compute silently for a long time, and a spinner or a prompt waiting
for input can keep printing. This replaces the output-window inference
with display-only observations.

- The runtime records when each terminal session last wrote output
  (wall-clock time for display, monotonic time for the quiet duration).
  A new session starts without an observation.
- Actor fields gain pty_last_output_at and pty_quiet_seconds for a
  running terminal Actor. They are never read by the working state.
- A terminal Actor without authoritative turn information keeps
  waiting / pty_running_state_unknown. Managed sessions keep precedence.
  idle_seconds and effective_working_updated_at keep their meaning, and
  there is no timing setting.

Tests cover quiet ongoing work, a noisy prompt waiting for input,
print-then-sleep, a new session resetting the observation, and a
managed session keeping precedence while its terminal prints.
@chriscoveries chriscoveries changed the title fix(daemon): report terminal Actors working or idle from their PTY output fix(runtime): expose terminal output observations without inferring working state Oct 22, 2026
@chriscoveries

Copy link
Copy Markdown
Contributor Author

CI note: on current main, rust-linux fails the five real-Chrome fixtures added in 1e5651b2 on every pull request. #175 moves them to the nightly job.

@ChesterRa
ChesterRa merged commit bb43e84 into ChesterRa:main Oct 23, 2026
4 of 6 checks passed
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