Problem
DING needs an opt-in reliable answer to “may input be delivered now?” for long-lived agent PTYs. Current PTY state cannot distinguish an active model turn, an idle harness prompt, or a long-running tool/child command. Screen text, title churn, elapsed time, attached-client count, remote st2 presence, and durable event-log tails are not authoritative.
Core DING must remain harness-neutral and preserve its current aggressive behavior when no richer policy is configured. Codex/Claude-specific parsing belongs in optional adapters selected by catalog KDL.
Small generic contract
Add explicit daemon-live activity state and expose it through the existing STATUS response / queryStats() / pty stats --json:
activity: {
state: "unknown" | "active" | "child_command" | "idle";
generation: string;
producerEpoch: string | null;
sequence: number;
turnId?: string;
source?: string;
}
- New daemon generation starts
unknown; never hydrate authority from JSONL.
- A local generic publisher claims a producer epoch, initially forcing
unknown, then submits strictly increasing transitions. Reject stale epoch/sequence updates.
idle is accepted only from an explicit adapter/hook transition; never derive it from screen/title/time/presence.
- Optionally append
session_activity JSONL records for audit/fixtures, but live daemon state is authoritative.
- The generic PTY publisher/read API contains no Codex or Claude schema knowledge.
- Unconfigured DING keeps current aggressive behavior. A KDL-selected adapter uses this state and fails closed on
unknown, unreachable daemon, generation change, or invalid transition.
Adapter comparison
- Hook publisher (preferred): Codex/Claude hooks translate turn/tool/prompt-ready transitions into the generic activity protocol. Lowest latency and no JSONL replay ambiguity. A Stop hook must not claim
idle until the harness-specific input-ready boundary.
- Session JSONL adapter (fallback): external adapter tails Codex/Claude extension data and publishes generic transitions. It must bind file identity/session ID, handle compaction/truncation/clear/crash, claim a new epoch as
unknown, and never replay an old terminal idle record as current authority.
Model-free acceptance tests
- message during
active turn is held;
- message at explicit
idle is eligible exactly once;
child_command remains non-idle despite silence;
- compaction and clear do not synthesize idle;
- adapter crash/epoch replacement resets to unknown;
- daemon restart/new generation resets to unknown;
- stale activity JSONL cannot authorize live input;
- Codex and Claude fixture adapters produce the same generic state trace.
No deployment or harness-specific code in PTY core.
Problem
DING needs an opt-in reliable answer to “may input be delivered now?” for long-lived agent PTYs. Current PTY state cannot distinguish an active model turn, an idle harness prompt, or a long-running tool/child command. Screen text, title churn, elapsed time, attached-client count, remote st2 presence, and durable event-log tails are not authoritative.
Core DING must remain harness-neutral and preserve its current aggressive behavior when no richer policy is configured. Codex/Claude-specific parsing belongs in optional adapters selected by catalog KDL.
Small generic contract
Add explicit daemon-live activity state and expose it through the existing
STATUSresponse /queryStats()/pty stats --json:unknown; never hydrate authority from JSONL.unknown, then submits strictly increasing transitions. Reject stale epoch/sequence updates.idleis accepted only from an explicit adapter/hook transition; never derive it from screen/title/time/presence.session_activityJSONL records for audit/fixtures, but live daemon state is authoritative.unknown, unreachable daemon, generation change, or invalid transition.Adapter comparison
idleuntil the harness-specific input-ready boundary.unknown, and never replay an old terminalidlerecord as current authority.Model-free acceptance tests
activeturn is held;idleis eligible exactly once;child_commandremains non-idle despite silence;No deployment or harness-specific code in PTY core.