{
  "events": [
    {
      "name": "artifacts received",
      "kind": "hook",
      "source": "the repository's after-receive hook, run by Fossil's backoffice after a sync or a post in the forum editor brings new artifacts",
      "carries": "the artifacts received since the hook last ran, one per line on standard input: hash, type and short hash",
      "behaviors": [
        "export to git",
        "wake its session",
        "run CI on a check-in",
        "queue a review",
        "ensure the daemon runs from the hook",
        "hand posts to the daemon",
        "note an unheard post",
        "answer runs for its node",
        "watch a run",
        "give a session its deliveries"
      ]
    },
    {
      "name": "console page opened",
      "kind": "request",
      "source": "a GET to OCX's CGI: a console view, the status endpoint or a git fetch",
      "carries": "the viewer, their capabilities and the query",
      "behaviors": [
        "render a console view",
        "answer a thread's status",
        "serve a git fetch",
        "ensure the daemon runs from the console",
        "serve status as JSON"
      ]
    },
    {
      "name": "console button pressed",
      "kind": "request",
      "source": "a POST to OCX's CGI from a console button, with the token",
      "carries": "the viewer, the action and the form's fields",
      "behaviors": [
        "start a session",
        "stop a session",
        "provision an agent login",
        "accept a release",
        "roll back a release",
        "install the wake hook",
        "add a listener",
        "remove a listener",
        "withdraw an agent login",
        "add a workspace",
        "terminate a workspace",
        "restart stopped sessions"
      ]
    },
    {
      "name": "command run",
      "kind": "command",
      "source": "a person, or an agent in its sandbox, running an OCX tool",
      "carries": "the arguments and the directory it is run in",
      "behaviors": [
        "stage a release",
        "record an audit",
        "write a turn",
        "create a workspace",
        "measure coverage",
        "collect workspaces",
        "check the node's runs"
      ]
    },
    {
      "name": "wake read",
      "kind": "pipe",
      "source": "a post's hash read from the workspace's wake pipe by task --wait, which blocks on it",
      "carries": "the hash of the post that waits on the session's login",
      "behaviors": [
        "answer a post",
        "stop on request",
        "end on its report"
      ]
    },
    {
      "name": "process ended",
      "kind": "exit",
      "source": "a process OCX started (a session's turn, a job) exiting",
      "carries": "its exit status and its output",
      "behaviors": [
        "record a turn's end",
        "report a job's result",
        "record a session's end",
        "launch for a waiting check-in"
      ]
    },
    {
      "name": "daemon read",
      "kind": "pipe",
      "source": "the daemon's own pipe, AGENTS/ocxd/wake: `post REPOSITORY HASH` from the hook and the console, `stop LOGIN KEY` from the console",
      "carries": "a post's hash, or the console's request",
      "behaviors": [
        "launch a session",
        "re-exec the daemon"
      ]
    }
  ],
  "behaviors": [
    {
      "name": "export to git",
      "cause": "artifacts received",
      "writes": "the repository's git mirror",
      "once_per": "check-in (fossil git export's own marks)",
      "today": "built: the host's hook runs fossil git export"
    },
    {
      "name": "wake its session",
      "cause": "artifacts received",
      "writes": "the post's hash into the wake pipe of the workspace bound to its thread; nothing when no session reads the pipe",
      "once_per": "post and workspace",
      "today": "built: bin/wake, run by the after-receive hook once installed on the host"
    },
    {
      "name": "answer a post",
      "cause": "wake read",
      "writes": "the session's answer, as a reply to the post it answers",
      "once_per": "post answered",
      "today": "built: task --wait and workspace serve block on the wake pipe"
    },
    {
      "name": "stop on request",
      "cause": "wake read",
      "writes": "a note on the record that the session stopped",
      "once_per": "stop request",
      "today": "built: a stop posted on the record wakes the session like any post"
    },
    {
      "name": "run CI on a check-in",
      "cause": "artifacts received",
      "writes": "a ci tag on the check-in, green or red with the command's last line; a red one also as a note on the CI session's record",
      "once_per": "check-in",
      "today": "not built: today a `stays` command session is woken; it is to be a `completes` session the daemon launches per check-in (257b282d36)"
    },
    {
      "name": "queue a review",
      "cause": "artifacts received",
      "writes": "nothing: the reviewer's queue is derived",
      "once_per": "check-in",
      "today": "timer: reviewer --wait sleeps between syncs"
    },
    {
      "name": "render a console view",
      "cause": "console page opened",
      "writes": "nothing",
      "once_per": "request",
      "today": "built"
    },
    {
      "name": "answer a thread's status",
      "cause": "console page opened",
      "writes": "nothing",
      "once_per": "request",
      "today": "built"
    },
    {
      "name": "serve a git fetch",
      "cause": "console page opened",
      "writes": "nothing",
      "once_per": "request",
      "today": "built"
    },
    {
      "name": "start a session",
      "cause": "console button pressed",
      "writes": "the session and workspace definitions and a launch note on the record, handed to the daemon, which starts the process",
      "once_per": "record and login: a second start restarts",
      "today": "built"
    },
    {
      "name": "stop a session",
      "cause": "console button pressed",
      "writes": "a stop request to the daemon for a session it started, which sends its process group TERM and reaps its end; TERM to any other (at a terminal); nothing waits for the end",
      "once_per": "running session",
      "today": "built"
    },
    {
      "name": "add a listener",
      "cause": "console button pressed",
      "writes": "a listen note on the record listened to, and the session's listening index",
      "once_per": "session and record or branch",
      "today": "built"
    },
    {
      "name": "remove a listener",
      "cause": "console button pressed",
      "writes": "an unlisten note on the record listened to, and the session's listening index",
      "once_per": "session and record or branch",
      "today": "built"
    },
    {
      "name": "provision an agent login",
      "cause": "console button pressed",
      "writes": "the login's account and kept password",
      "once_per": "login and repository",
      "today": "built"
    },
    {
      "name": "accept a release",
      "cause": "console button pressed",
      "writes": "the release root's links",
      "once_per": "staged release",
      "today": "built; the host checks are not run yet"
    },
    {
      "name": "roll back a release",
      "cause": "console button pressed",
      "writes": "the release root's links",
      "once_per": "previous release",
      "today": "built"
    },
    {
      "name": "install the wake hook",
      "cause": "console button pressed",
      "writes": "the repository's hooks setting: the wake hook added, replaced or removed",
      "once_per": "repository: installing again replaces the one there",
      "today": "built"
    },
    {
      "name": "stage a release",
      "cause": "command run",
      "writes": "staged/<check-in> and staged/next",
      "once_per": "check-in",
      "today": "built"
    },
    {
      "name": "record an audit",
      "cause": "command run",
      "writes": "an audited tag on the check-in",
      "once_per": "check-in and auditor",
      "today": "built"
    },
    {
      "name": "write a turn",
      "cause": "command run",
      "writes": "a post or ticket change on the record",
      "once_per": "turn written",
      "today": "built"
    },
    {
      "name": "create a workspace",
      "cause": "command run",
      "writes": "the workspace directory",
      "once_per": "record and login",
      "today": "built"
    },
    {
      "name": "collect workspaces",
      "cause": "command run",
      "writes": "removes workspaces whose record no longer needs them; never a workspace a running process's command line names",
      "once_per": "workspace",
      "today": "built"
    },
    {
      "name": "measure coverage",
      "cause": "command run",
      "writes": "nothing in the tree; a report",
      "once_per": "run",
      "today": "built"
    },
    {
      "name": "record a turn's end",
      "cause": "process ended",
      "writes": "the answer or report on the record, and the session's state",
      "once_per": "turn",
      "today": "built, inside the session's loop"
    },
    {
      "name": "report a job's result",
      "cause": "process ended",
      "writes": "a result replying to the request that asked for it",
      "once_per": "request",
      "today": "not built: jobs wait on the session design"
    },
    {
      "name": "withdraw an agent login",
      "cause": "console button pressed",
      "writes": "the login's capabilities on this repository, taken away",
      "once_per": "login and repository",
      "today": "built"
    },
    {
      "name": "add a workspace",
      "cause": "console button pressed",
      "writes": "a workspace definition on its record, and the workspace made from it",
      "once_per": "login and project",
      "today": "built"
    },
    {
      "name": "terminate a workspace",
      "cause": "console button pressed",
      "writes": "a terminated note on the workspace's record, and the workspace removed",
      "once_per": "workspace",
      "today": "built"
    },
    {
      "name": "ensure the daemon runs from the hook",
      "cause": "artifacts received",
      "writes": "starts `ocxd` when no process holds AGENTS/ocxd.lock",
      "once_per": "host: the lock admits one daemon",
      "today": "built"
    },
    {
      "name": "ensure the daemon runs from the console",
      "cause": "console page opened",
      "writes": "starts `ocxd` when no process holds AGENTS/ocxd.lock",
      "once_per": "host: the lock admits one daemon",
      "today": "built"
    },
    {
      "name": "hand posts to the daemon",
      "cause": "artifacts received",
      "writes": "each artifact received, as `post REPOSITORY HASH`, into the daemon's pipe; the console hands its launch note the same way",
      "once_per": "post",
      "today": "built"
    },
    {
      "name": "launch a session",
      "cause": "daemon read",
      "writes": "`workspace serve` as the daemon's child in its own process group, for a launch note or for a check-in on a branch a `completes` session listens to; refused, with a note on the record, while a process already names the workspace",
      "once_per": "launch note, or check-in on a listened branch (its result tag)",
      "today": "built"
    },
    {
      "name": "record a session's end",
      "cause": "process ended",
      "writes": "an end note with the exit status on the session's record",
      "once_per": "session process (PID and start time)",
      "today": "built"
    },
    {
      "name": "restart stopped sessions",
      "cause": "console button pressed",
      "writes": "a launch note, on the release chosen (current or previous), for each stays session whose record shows a start and no running process",
      "once_per": "stopped session",
      "today": "not built: the daemon design, agreed in 14d8477f84"
    },
    {
      "name": "re-exec the daemon",
      "cause": "daemon read",
      "writes": "nothing: the daemon execs the current release's `ocxd` in place, keeping its PID and its children",
      "once_per": "accepted or rolled-back release",
      "today": "not built: the daemon design, agreed in 14d8477f84"
    },
    {
      "name": "serve status as JSON",
      "cause": "console page opened",
      "writes": "nothing: GET /state gives hooks, agent logins, workspaces, sessions and listeners as JSON (docs/design/state.schema.json), derived from the record, the workspace directories and the process table",
      "once_per": "request",
      "today": "built"
    },
    {
      "name": "end on its report",
      "cause": "wake read",
      "writes": "nothing more: a `completes` session exits once its report is on the record: an llm session's done or failed report on its own record, or a mechanical session's ci tag, green or red, on the check-in it tested (a red one also said on its own record); a question it asked keeps it running",
      "once_per": "session",
      "today": "not built: the lifetime design, agreed in 257b282d36"
    },
    {
      "name": "launch for a waiting check-in",
      "cause": "process ended",
      "writes": "a launch of the branch listener's `completes` session again, when a listened branch still has a check-in with no result of its login's",
      "once_per": "check-in (its result tag)",
      "today": "not built: the lifetime design, agreed in 257b282d36"
    },
    {
      "name": "note an unheard post",
      "cause": "artifacts received",
      "writes": "a note on the record, as the session's agent login, that a person's post reached it while nothing held its wake pipe; never for an agent's post",
      "once_per": "post and session",
      "today": "built"
    },
    {
      "name": "answer runs for its node",
      "cause": "artifacts received",
      "writes": "an ended for each run for the node it names that it refuses, finds stopped before it started, or finds lost, as a reply in the run's thread or a change to its ticket, as the node user",
      "once_per": "run: a run with an ended is never decided again",
      "today": "built (docs/slices-v1.md, slice v1.3): the hook, given --node USER, answers the runs among the artifacts Fossil lists, or named by a listed stop, and nothing else (HISTORY.md decision 39); a run it would start it hands to a watcher (slice v1.5)"
    },
    {
      "name": "watch a run",
      "cause": "artifacts received",
      "writes": "a run's started and ended, as the node user, in its thread or on its ticket; a fresh password on the run's user, and the run's workspace",
      "once_per": "run: the watcher holds the run's lock, and a run with a started is never launched again",
      "today": "built (docs/slices-v1.md, slices v1.5 and v1.6): the hook hands each run it decided to start to a watcher, itself again through the release root's link with --watch; the program the run names, with its environment and home files (HISTORY.md decisions 41 and 42); a watcher that ends hands on the next waiting run of its user"
    },
    {
      "name": "give a session its deliveries",
      "cause": "artifacts received",
      "writes": "a line of JSON in a running session's inbox, in the node's directory, for each post in its thread or change to its ticket from a user it hears and each check-in on a branch it names, that arrived after its started; its watcher passes each line on to the program's standard input",
      "once_per": "artifact and run: Fossil lists an artifact to the hook once, and the hook gives it once",
      "today": "built (docs/slices-v1.md, slice v1.6): every session, as lines of JSON on its program's standard input"
    },
    {
      "name": "check the node's runs",
      "cause": "command run",
      "writes": "an ended, lost, for each run for the node whose started counts with no program in its care, and any other answer a run never answered calls for, as the node user; each run never started handed to a watcher; a line in the hook's log, checked",
      "once_per": "node start: hook --node USER, run when the node starts and again after its host restarts; a run with an ended is never decided again",
      "today": "built (docs/slices-v1.md, slice v1.6): docs/protocol-v1-fossil.md, section 5's check when a node starts"
    }
  ]
}
