Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ Repo-native agent orchestration and public Codex signal publishing.

- Rust CLI and runtime for repo-native retained coding-agent lanes.
- Explicit project registry under `~/.codex/decodex/projects/<service-id>/`.
- Local operator listener with a read-only dashboard at `/` and `/dashboard`, plus
`GET /state` for JSON snapshots.
- Local operator listener with a dashboard at `/` and `/dashboard`, WebSocket
snapshot/control traffic at `/dashboard/control`, and `GET /livez` for liveness.
- Static Astro site that publishes GitHub-backed Codex change signals.
- Deterministic GitHub signal pipeline for change bundles, release deltas, rendered
signal entries, and content validation.
Expand Down Expand Up @@ -185,11 +185,12 @@ The governing workflow lives at `docs/runbook/local-github-signal-workflow.md`.

## Operator Dashboard

`decodex serve` owns the local operator listener. It serves one read-only operator
console from `GET /` and `GET /dashboard`, plus the same JSON status snapshot model from
`GET /state`.
`decodex serve` owns the local operator listener. It serves the operator dashboard from
`GET /` and `GET /dashboard`; published snapshots, active-run updates, and local
dashboard controls flow through the `/dashboard/control` WebSocket. The HTTP surface is
kept to dashboard pages/assets and `GET /livez`.

For dashboard UI development, use the mock operator state server:
For dashboard UI development, use the mock operator dashboard server:

```sh
node dev/operator-dashboard-mock.mjs --listen-address 127.0.0.1:57399
Expand Down
2 changes: 0 additions & 2 deletions apps/decodex/src/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ const TRACKER_RATE_LIMIT_WARNING: &str = "tracker_rate_limited";
const OPERATOR_DASHBOARD_ENDPOINT_PATH: &str = "/";
const OPERATOR_DASHBOARD_ALIAS_ENDPOINT_PATH: &str = "/dashboard";
const OPERATOR_DASHBOARD_WS_ENDPOINT_PATH: &str = "/dashboard/control";
const OPERATOR_STATE_ENDPOINT_PATH: &str = "/state";
const OPERATOR_LIVE_ENDPOINT_PATH: &str = "/livez";
const OPERATOR_READY_ENDPOINT_PATH: &str = "/readyz";
const OPERATOR_STATE_MAX_REQUEST_BYTES: usize = 8_192;
const OPERATOR_DASHBOARD_WS_CLIENT_MESSAGE_MAX_BYTES: usize = 64 * 1_024;
const OPERATOR_STATE_HEADER_TERMINATOR: &[u8] = b"\r\n\r\n";
Expand Down
4 changes: 0 additions & 4 deletions apps/decodex/src/orchestrator/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,6 @@ where
Ok(snapshot)
}

fn operator_snapshot_ready_stale_after(poll_interval: Duration) -> Duration {
poll_interval.checked_mul(2).unwrap_or(Duration::MAX)
}

fn inspect_or_clear_active_children<T>(
active_children: &mut Vec<DaemonRunChild>,
retry_queue: &mut RetryQueue,
Expand Down
10 changes: 4 additions & 6 deletions apps/decodex/src/orchestrator/entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,8 @@ pub(crate) fn run_control_plane(request: ServeRequest<'_>) -> Result<()> {
runtime::register_project_config(&state_store, &config_path, true)?;
}

let operator_state_endpoint = OperatorStateEndpoint::start(
request.listen_address,
operator_snapshot_ready_stale_after(request.poll_interval),
Arc::clone(&state_store),
)?;
let operator_state_endpoint =
OperatorStateEndpoint::start(request.listen_address, Arc::clone(&state_store))?;
let runtime_db_path = runtime::runtime_db_path()?;
let global_config_path = runtime::global_config_path()?;
let project_config_dir = runtime::project_config_dir()?;
Expand All @@ -133,7 +130,8 @@ pub(crate) fn run_control_plane(request: ServeRequest<'_>) -> Result<()> {
tracing::info!(
poll_interval_s = request.poll_interval.as_secs(),
listen_address = %operator_state_endpoint.listen_address(),
path = OPERATOR_STATE_ENDPOINT_PATH,
path = OPERATOR_DASHBOARD_ALIAS_ENDPOINT_PATH,
ws_path = OPERATOR_DASHBOARD_WS_ENDPOINT_PATH,
runtime_db_path = %runtime_db_path.display(),
global_config_path = %global_config_path.display(),
project_config_dir = %project_config_dir.display(),
Expand Down
Loading