Skip to main content

model-proctor

Use when substantial coding or proctor tasks require runner-governed delegation, or when the user explicitly invokes model-proctor. Do not use for trivial tasks — execute those directly. Requires the model-proctor install.

Source facts

Repository
dachent/model_proctor
Last source activity
September 16, 2026 at 13:26
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
3 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
model-proctor
description
Use when substantial coding or proctor tasks require runner-governed delegation, or when the user explicitly invokes model-proctor. Do not use for trivial tasks — execute those directly. Requires the model-proctor install.
# Model Proctor Policy for Codex The proctor assigns the exam, watches the clock, and grades it objectively — the model never marks its own work. You are the leader. Two surfaces, one doctrine: **the gated path** for substantial work (`C:/Tools/model-proctor/runner.py` init/dispatch/verify/accept — the shared runner's flash-first lifecycle with recorded-stagnation escalation), and **thin dispatch** for explicitly named consults and one-shots. Prompts do not enforce; the tools enforce. Deterministic evidence outranks every model, including you. ## The gated path (substantial work — the default) Runner state, receipts, and sealed verifier payloads live OUTSIDE the workspace (`.runner-state/` sibling) — the worker cannot rewrite its own evidence. At verify time the runner restores any tampered verification input from the sealed copy and flags it on the receipt. For substantial work without an explicitly named `luna`, `terra`, or `astra` one-shot, use the shared runner lifecycle. The runner keeps ownership of its state, verification, acceptance, recording, routing, escalation, production, resume, and stopping policies. `C:\Tools\model-proctor\task_schema.py` remains the shared task schema; do not create a Codex runner or schema. 1. **Write the task file**: `task.json` with `task_id`, `prompt`, `features`, `scope` (non-empty), `verifier.argv` (an argv ARRAY — never a shell string; use `{python}` for the interpreter), and `budget`. Tasks that drive a known production runner also require `preflight_receipts` — see **Production tasks** below. 2. **Lane**: `python C:/Tools/model-proctor/runner.py lane --task task.json` — record the decision. Override only by setting `lane` in the task file, and note why in the task record. The shared lane-to-Codex mapping is `flash -> Luna`, `glm -> Terra`, and `k3 -> Astra`. 3. **Init**: `python C:/Tools/model-proctor/runner.py init --workspace <w> --task task.json`. Refusal (`workspace_is_not_repo_root`) is final — fix the workspace, never bypass. Init pins the verification contract (`verifier`, `seal`) into external state; the task file sits inside the worker-writable tree, so from here on the pinned copy is authoritative. 4. **Dispatch**: `python C:/Tools/model-proctor/runner.py dispatch --workspace <w> --task task.json --delegate C:\Tools\model-proctor\codex-delegate\runner_delegate.py --agent-map C:\Tools\model-proctor\codex-delegate\runner-agent-map.json`. The worker owns the engineering trajectory in its own session; you own state and acceptance. Only this dispatch command receives the Codex bridge and map. 5. **Verify**: `python C:/Tools/model-proctor/runner.py verify --workspace <w> --task task.json`. The runner rejects verification if any verification-affecting file (conftest.py, pytest.ini, pyproject.toml, *.pth, ...) appeared or changed since init, if the task file's verifier diverges from the pin (`verifier_changed_since_init`), or if a workspace file shadows a module the verifier imports via `-m` (`module_shadow_detected` — the workspace is `sys.path[0]`, so a dropped `unittest.py` would otherwise swallow the run). Then it runs the verifier itself. Never trust worker-reported results. 6. **Accept**: `python C:/Tools/model-proctor/runner.py accept --workspace <w> --task task.json`. A green receipt stales automatically on any tree mutation — re-verify after every change. Accept also refuses when the receipt carries `tamper_detected` (a sealed verification input was altered and the runner restored it) and when any dispatch happened after the receipt was written. Both clear by re-running `verify` — never by re-running `accept`. 7. **Record**: `python C:/Tools/model-proctor/runner.py record --workspace <w> --task task.json [--wire <wire.jsonl> --pricing C:/Tools/model-proctor/pricing.yaml]` — appends the append-only task record. Use the **installed** pricing table, not a relative `evals/` path. Malformed, missing, or unavailable usage is **unknown, never $0** (`usage_unknown` on the row). The receipt records the tree signature, the dispatch count it was written at (`dispatch_seq`), and the `verifier_argv` that produced it — so a green receipt states *what* was verified, not merely that something was. It also carries `baseline_tree` and `verifier_nondiscriminating`; when `dispatch_seq == 0` and `verifier_nondiscriminating == true`, `accept` refuses by default — `--allow-zero-dispatch` is the reviewed, counted exception. ## Lane table (shared routing policy — flash-first with evidence-driven escalation) The shared runner's escalation ladder is **evidence-driven, not start-time guesswork** — a lane changes only on recorded stagnation (see Failure classes below). Codex identities are the fixed bridge mapping: `flash -> Luna`, `glm -> Terra`, `k3 -> Astra`. | Task shape | Lane | |---|---| | localized + bounded + known location + objective acceptance | `flash` | | multi-module / unfamiliar repo / substantial refactor | `glm` | | open-ended exploration, research engineering, marathon | `k3` | | no bounded signature, substantial | `glm` (default) | Decomposition itself is the hard problem? Optionally consult Astra for a task breakdown first — that is a planning consult, not a mandatory planner tax. ## Direct named dispatch (consults and one-shots) Use thin dispatch only for an explicitly named request in this form: ```text $model-proctor luna|terra|astra: <task text> ``` Keep the requested task text intact. Use the active repository root as the workspace; if there is no unambiguous workspace, ask for it. Encode the exact task as one UTF-8 Base64 value before putting it in a shell command. Do not embed raw task text in a PowerShell here-string or other shell literal. The helper decodes it once and passes its UTF-8 bytes straight to the adapter's standard input, resolves the desktop-bundled Codex executable, and invokes the installed adapter with `app-server` transport. Do not use a bare `codex` command, a daemon, MCP, another UI, or a task file. ```powershell $dispatcher = Join-Path $env:USERPROFILE '.codex\skills\model-proctor\scripts\dispatch.py' $taskBase64 = '<Base64 of the exact requested task, encoded as UTF-8>' $taskBase64 | & python $dispatcher --task-base64-stdin ` --preset <luna|terra|astra> --workspace '<absolute workspace path>' ``` - Read-only is the default. Add `--write` only when the user explicitly authorizes workspace changes. Never remove or overwrite `PROCTOR_CHILD`. Do not put secrets, credential values, or environment dumps into the task: the read-only sandbox is not credential isolation. - Return the normalized result, including its selected model, effort, sandbox, nested-dispatch status, and `agent_message`. A completed transport envelope is not independent acceptance of the worker's work. A detected native subagent activity is refused after it is observed. - The direct surface does not replace the gated path for substantial unnamed work. Known production-pattern tasks belong on the gated runner path. ## Production tasks If the prompt, scope, or verifier names a known production entrypoint (`run_week.ps1`, `src.run_all`, `src.run_weekly`, `run_readiness_doctor`, `morning_battery`), the runner treats the task as ops-class: - **The flash lane is refused** unless you set an explicit `lane` in the task file. `init` and `dispatch` now agree on this; an explicit override is a reviewed decision, so record why in the task record. - **`preflight_receipts` is mandatory** — a non-empty array of paths to logs or reports the orchestrator's own probe (doctor / battery / dry-run) actually produced. Missing files refuse (`preflight_receipt_required`); receipts older than 24h refuse (`preflight_receipt_stale`, override with `budget.max_preflight_age_s`). Discovery is what probes are for, not what dispatch budgets are for. This is a **known-entrypoint denylist over your own task text**, not a general ops-class detector: a prompt that never names one of those entrypoints will not trip it. Declaring features honestly is still your job. ## Failure classes and switching (not a fixed ladder) - **Provider/tool failure** (timeout, internal_error) → switch provider/harness lane, not a smarter model. - **Execution stagnation** (identical normalized failure fingerprint, 3 in a row) → lateral switch: flash→glm, glm→k3, k3→glm. The new worker gets a compact evidence packet — objective, acceptance criteria, current diff, verified test output, fingerprints, explicit switch reason — never the failed model's full rationale. - **Localized defect after broad success** → same-worker targeted repair. - Budgets are hard caps (`max_dispatches`, `max_stagnant`, `timeout_s`). A refusal is final until state changes legally. ## Stopping rules 1. Max **two adversarial QC rounds per change**; a third round is an owner call. Test-strength-only findings (no production defect) are record-and-ship — note them on the issue, do not loop. 2. Re-run only the **narrowest failing stage**; rebuild upstream stages only when an upstream input actually changed. 3. Gates (full suite + linters) re-run only **after a code change**. 4. Budgets are declared at dispatch and escalate on breach instead of continuing (`max_dispatches`, `max_stagnant`, `timeout_s` above; #83 M1 extends them to per-attempt reservations). ## Session discipline One persistent worker session per task, closed at acceptance. Externalize verified state to files continuously; do not accumulate completed task detail in your own context. If you are asked to resume a dead trajectory, restart from the evidence packet instead. ### Resuming after a gap (mandated first step) The FIRST action on any resume — new morning, reopened machine, post-crash — is `python C:/Tools/model-proctor/runner.py status --workspace <w>`: - `stall_suspected: true` (silence beyond `max(2x timeout_s, 1h)`) and any `orphaned_dispatch_ids` are **stop-and-investigate** signals. - Orphans are advisory. Investigate, then clear with `python C:/Tools/model-proctor/runner.py journal --workspace <w> --ack <dispatch_id>` so they stop re-reporting. - `last_receipt` with `dispatch_seq: 0` + `verifier_nondiscriminating: true` carries no worker evidence; `accept` refuses it unless `--allow-zero-dispatch` is supplied. That override is counted and should be treated as a reviewed exception.
View on GitHub