|
oc_orchestrator
|
Classes | |
| class | DispatchError |
| class | DispatchHooks |
| class | _NoHooks |
| class | DispatchRequest |
| class | DispatchResult |
| class | _PlanDispatchData |
| class | PlanAnchors |
Functions | |
| subprocess.CompletedProcess[str] | _run_git (Path repo_root, *str args, bool check=True) |
| Path | _resolve_plan (Path plans_dir, str plan_number) |
| dict[str, Any] | _frontmatter (Path path) |
| str | _nonblank (dict[str, Any] data, str field, *, str context) |
| _PlanDispatchData | _load_plan (Path path, str plan_number, str|None thinking_override) |
| PlanAnchors | resolve_plan_anchors (Path plans_dir, str plan_number) |
| str | _require_committed_on_master (Path repo_root, Path plan_path) |
| bool | _branch_exists (Path repo_root, str branch) |
| str | _base_sha (Path repo_root, str branch, str master_sha) |
| set[str] | _template_field_names (str template) |
| str | render_launch_template (Path template_path, dict[str, str] fields) |
| PrepareResult | _prepare_worktree_env (DispatchRequest request, _PlanDispatchData plan, *, bool use_worktree_venv) |
| None | _write_launch (Path path, str text) |
| dict[str, str] | _launch_fields (DispatchRequest request, _PlanDispatchData plan, *, str base_sha, Path launch_path, str agent_id, bool use_worktree_venv) |
| DispatchResult | dispatch (DispatchRequest request) |
| None | _announce_dispatched (DispatchHooks hooks, DispatchResult result) |
| list[str] | format_dispatch_suggestion (DispatchResult result, *, str model_attested, Path registry_path) |
| str | _open_instance_summary (Path registry_path, str exclude_agent_id) |
Variables | |
| str | _TEMPLATES_DIR = Path(__file__).resolve().parent / "templates" |
| str | DEFAULT_LAUNCH_TEMPLATE = _TEMPLATES_DIR / "launch.md" |
| str | SHARED_VENV_LAUNCH_TEMPLATE = _TEMPLATES_DIR / "launch_shared_venv.md" |
| tuple | _REQUIRED_REQUIRES = ("tier", "repo", "thinking", "session") |
| _VALID_THINKING = frozenset({"off", "low", "medium", "high", "max"}) | |
| _VALID_SESSION = frozenset({"fresh", "continue", "either"}) | |
| _LEFTOVER_TOKEN_RE = re.compile(r"\{[^{}\n]+\}|<[^<>\n]+>") | |
| _PLAN_NUMBER_RE = re.compile(r"^[0-9]{3}$") | |
| dict | _SESSION_EXPLANATIONS |
Fail-closed, one-shot plan dispatch orchestration.
Purpose
-------
Plan 221 P2/P3 (design §4.1). Every step of dispatching a plan either
goes through this module — which fills it correctly — or refuses loudly
with the reason named. It resolves the plan by number, validates its
``requires:`` block, creates branch and worktree idempotently, allocates
the ``agent-NNN`` identity, renders the launch file from the ONE
committed template, and refuses the WHOLE dispatch if any template field
would render unfilled. Hand-authoring a launch file is a workflow
violation from the moment this landed.
Responsibilities
----------------
- :class:`DispatchRequest` / :class:`DispatchResult` — the operator's
inputs and the committed outputs of one attempt.
- :class:`DispatchHooks` / :data:`NO_HOOKS` — the plan-259 seam: one
announcement after a dispatch commits, and an empty default.
- :class:`DispatchError` — the named refusal at the dispatch boundary.
- The refusal matrix (W3): missing/incomplete ``requires:``, plan absent
from master, an open instance without ``--again``.
- All-or-nothing rendering (W4): no instance allocated and no launch
file written when anything refuses.
Diagnostics
-----------
Domain: OC_CHAT.MAIN
Levels:
L2 — lifecycle events (dispatch attempted, refused, completed).
L3 — semantic details (plan resolution, template rendering).
L4 — deep tracing.
Contracts
---------
- BASE_SHA is the point the branch actually diverges from master,
recorded in the launch file and never re-derived: master's SHA for a
branch created by this dispatch, and the merge-base of master and the
branch tip for a pre-existing one (plan 223 P4). The two values
coincide at creation, so a fresh dispatch is unchanged.
- Refusals raise :class:`DispatchError` BEFORE any state mutates; the
registry allocation and the launch-file write share one transaction
(via :meth:`AgentInstanceRegistry.dispatch_allocation`).
- Git operations run against the caller's ``repo_root`` only.
- The plan-259 hook is told AFTER everything has committed and its
failure is reported on stderr, never raised: by then the worktree
exists, and unmaking a real worktree because a log was unreachable
would be the worse failure.
Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- oc_orchestrator.agent_instances (the runtime instance registry)
- yaml (plan frontmatter parsing; already a project dependency)
- oc_orchestrator.worktree_env (the git anchors, the per-worktree venv prepare and the dispatch timing ledger)
|
protected |
Tell the hooks once, after the dispatch has committed. Never raise. Plan 259 P6. By the time this runs the branch, the worktree, its venv, the instance row and the launch file all exist; a listener that cannot record the fact is a reason to say so, not a reason to unmake any of that. Undoing a real worktree because a log was unreachable would be the worse failure by a wide margin.
Definition at line 666 of file dispatch.py.
|
protected |
Return the SHA the worker's BASE diff should be measured against. Plan 223 P4 (from the 225 gate finding). Recording master's CURRENT SHA for a branch that was cut earlier is a lie the moment master moves: the 2026-09-01 dispatch rendered ``344fe8ce`` for a branch cut at ``b7962f5f``, so the worker's "diff against BASE" silently spanned every commit master had gained in between. The truthful anchor for an existing branch is where it diverged — the merge-base. A branch this dispatch is about to CREATE has no divergence yet, so master's SHA is both values at once and the fresh path is unchanged.
Definition at line 381 of file dispatch.py.
|
protected |
Definition at line 370 of file dispatch.py.
|
protected |
|
protected |
|
protected |
Definition at line 256 of file dispatch.py.
|
protected |
|
protected |
Render open instances as ``agent-NNN (plan-id, state)``, or ``none``. The instance this dispatch just allocated is excluded: it is the thing being launched, not a candidate to reuse for it. A registry that cannot be read reports that fact rather than claiming an empty pool, because "none" and "unknown" are different answers to the operator's question.
Definition at line 738 of file dispatch.py.
|
protected |
Create the git anchors and, by default, the worktree's own venv. Plan 241 P1/P4. ``--shared-venv`` (``use_worktree_venv=False``) keeps the legacy behaviour — anchors only, the shared main venv in the brief. Otherwise the anchors and the per-worktree environment are made in one step and every refusal inside it aborts the whole dispatch: a silent fallback to the shared venv would re-open the F17 shadow.
Definition at line 459 of file dispatch.py.
|
protected |
Definition at line 326 of file dispatch.py.
|
protected |
|
protected |
|
protected |
|
protected |
| DispatchResult oc_orchestrator.dispatch.dispatch | ( | DispatchRequest | request | ) |
Validate, prepare git state, allocate an instance, and render launch.
Definition at line 573 of file dispatch.py.
| list[str] oc_orchestrator.dispatch.format_dispatch_suggestion | ( | DispatchResult | result, |
| * | , | ||
| str | model_attested, | ||
| Path | registry_path ) |
Build the operator-facing suggestion lines for a completed dispatch. Plan 223 P4b. The suggestion line spells out what the session field constrains, and a following line names the instances that are actually open right now — the concrete reuse candidates, rather than leaving the operator to remember which windows are still alive. NOTE (scope): these are candidate INSTANCES, not sessions. Naming the actual session to continue requires ``agents.sqlite.session_uuid`` to be populated, which is plan 224's session-linkage territory and deliberately out of scope here; until then the operator maps instance to window.
Definition at line 702 of file dispatch.py.
| str oc_orchestrator.dispatch.render_launch_template | ( | Path | template_path, |
| dict[str, str] | fields ) |
Render the single launch template or refuse any unresolved field.
Definition at line 437 of file dispatch.py.
| PlanAnchors oc_orchestrator.dispatch.resolve_plan_anchors | ( | Path | plans_dir, |
| str | plan_number ) |
Resolve one plan number to the branch and worktree it declares. Plan 241 P1/P5. ``prepare-worktree`` and ``teardown-worktree`` act on exactly the anchors ``dispatch`` would use, from the same parser, so the three commands can never disagree about which tree they mean.
Definition at line 311 of file dispatch.py.
|
protected |
Definition at line 110 of file dispatch.py.
|
protected |
Definition at line 111 of file dispatch.py.
|
protected |
Definition at line 107 of file dispatch.py.
|
protected |
Definition at line 695 of file dispatch.py.
|
protected |
Definition at line 102 of file dispatch.py.
|
protected |
Definition at line 109 of file dispatch.py.
|
protected |
Definition at line 108 of file dispatch.py.
| str oc_orchestrator.dispatch.DEFAULT_LAUNCH_TEMPLATE = _TEMPLATES_DIR / "launch.md" |
Definition at line 103 of file dispatch.py.
| str oc_orchestrator.dispatch.SHARED_VENV_LAUNCH_TEMPLATE = _TEMPLATES_DIR / "launch_shared_venv.md" |
Definition at line 106 of file dispatch.py.