--- name: director description: Discovers, starts, resumes, recovers, or inspects Factory Objectives when a user asks in natural language to use Factory or continue Factory-managed repository work. --- # Factory Director Use this skill when the user asks to start, resume, recover, run, or check Factory work. The user does not need to know an Objective number, label name, Work Item state, or MCP operation. Their prompt is the interface; resolve it to the typed Factory tools below. Factory's Supervisor owns the loop. Do not reproduce scheduling with repeated model turns and do not mutate GitHub with raw `gh`, REST, or GraphQL calls. The bundled MCP tools are the authorized surface. ## Resolve the target and request Use the repository and Objective selected by the user. Resolve "this repository" from the active checkout only after verifying its GitHub identity. If the repository itself remains ambiguous, ask which repository they mean before querying candidates or starting work. When the repository is known but the Objective number is omitted, call `factory_discover_objectives`. Discovery is read-only and is the normal first step for prompts such as "use Factory to build this repository" or "continue the Factory work here"; do not require the user to ask for discovery separately. Route the result as follows: - a complete scan with exactly one candidate selects that Objective; - multiple candidates require the user to choose by title and issue number; - an incomplete scan cannot prove uniqueness, so report the returned candidates and ask for the intended Objective; - no candidate on a complete scan means there is no discoverable existing Objective; do not create one or reinterpret an ordinary issue without the user's request. The discovery label and canonical `Objective:` title are retrieval evidence, never execution authority. After selecting a candidate, use `factory_status` to distinguish a dormant Objective from an active, terminal, or completed run and route it through the matching path in this skill. Never create a replacement Objective merely because the user did not know an existing one's number. Treat an imperative prompt to build, run, resume, or continue with Factory as execution authority for the resolved repository and Objective under the supplied policy or Factory's local-only default. Do not ask the user to repeat that intent using "activate", "compile", or an MCP tool name. A setup, installation, restart, inspection, status, explanation, or plan-only prompt remains non-executing unless the user also asks to perform the work. For an existing-plan request, including "does this Objective have a plan?", use `factory_plan` with `compile` omitted or `false`. Status and Work Item counts are not a substitute for inspecting the existing graph. Report a missing graph or unverified graph authority as returned; do not compile a replacement unless explicitly authorized. For read-only plan inspection, omit the optional local `repository` argument. Never fill a checkout argument with the current directory merely because it is available. When compilation, preflight or execution requires a checkout, use an absolute checkout verified to belong to the selected repository; ask for missing context rather than guessing. If the required tool is unavailable, explain which operation cannot be performed and what setup is needed. Do not claim to have inspected a plan or started work through a different operation. ## Choose the execution mode Collect: - `owner` and `repo`; - the Objective issue number; - an absolute local checkout of that exact repository for operations requiring one; - an optional complete run policy. If no policy was supplied, use Factory's fixed local-only default (up to two workers, further constrained by measured CPU and memory headroom). Adaptive local concurrency is an explicit policy choice until its default-enablement qualification passes. Never opt into paid backends or broaden trust on the user's behalf. A new policy containing `economics.maxModelTokens` must explicitly select `economics.modelTokenBudgetMode: "observed-stop"` to permit in-flight overshoot. Do not make that choice for a user who requested a hard cap: current model providers cannot enforce one, and Factory rejects `"hard"` before model work. Report the limitation and available provider-native controls. Status exposes the recorded budget intent; old run recovery preserves its original policy rather than inserting a new mode or resetting usage. A zero-valued dispatch-intent marker is not proof of zero consumption. Prefer **durable unattended mode** when the user asks Factory to run autonomously, survive chat disconnects, resume after login/boot, or process work in the background: 1. Call `factory_doctor` for the Objective and report any permanent preflight failure. 2. Call `factory_controller_status` for the checkout. If no repository controller is installed, call `factory_controller_install` and then `factory_controller_start` only when the user's request authorizes starting unattended execution on this host. Give each lifecycle request a unique, stable `requestId`; retry the same action with the same ID after an uncertain response. 3. Call `factory_activate` with the Objective and a unique, stable `requestId`. Pass the complete policy when the user supplied one. Omit `baseSha` to let Factory atomically record the current default-branch head, or pass the user's explicit 40-character SHA for reproducibility. Activation is durable and returns without holding the chat open. 4. Call `factory_status` to confirm the request/controller state. Do not poll it in a model loop; later user status requests are separate read-only calls. After an uncertain activation response, retry the exact same request and `requestId`. Factory repairs discovery of the accepted Objective without replacing its recorded base or policy. Do not create a replacement Objective or a new activation merely because the response was lost. Use **foreground mode** for a one-shot interactive run, or when the supported Linux host cannot run the controller lifecycle. Call `factory_run` once with `untilTerminal: true` and keep the call alive. It performs the same Supervisor workflow, but its process lifetime remains coupled to the client. Tell the user when this fallback removes unattended wake/resume behavior; never silently downgrade a request for durable operation. For a foreground restart of an active, non-terminal run, call `factory_run` the same way. For durable mode, inspect or restart the repository controller; do not submit a second activation. The recorded run policy wins over a newly supplied default, and GitHub receipts determine recovery. Do not create replacement issues or branches manually. Report the terminal result: - `completed`: the Objective and all Work Items shipped; - `cancelled`: the operator requested a fenced stop; - `escalated`: quote the concrete reason and identify the affected Work Item when present. If the user asks to stop an active or queued Objective, call `factory_cancel` with a unique, stable `requestId`. Only the GitHub identity that requested the relevant activation may cancel it. Retry the exact same request after an uncertain response, not a new cancellation identity. Before a run starts, cancellation returns an `ActivationCancellationRequested` receipt for that exact activation. Use `factory_status` to report `activation.state` as `withdrawn` separately from a cancelled run; withdrawal does not claim that a worker started or was cleaned up. If startup races with withdrawal, inspect the matching run's cancellation and resource-reconciliation outcome. Do not treat the withdrawal receipt as cleanup proof. Replaying the original activation does not undo its withdrawal. Do not simulate cancellation by closing issues or PRs. ## After terminal escalation A terminal run is stopped, not still working. If the client attached a recurring heartbeat or monitor, pause or delete it as soon as status reports `operatorAction.monitoring: "stop"`; send one actionable update and do not schedule more status reads. Resume monitoring only after the user grants the missing authority and Factory has accepted a non-terminal successor. When the user asks to continue an escalated Objective or inspect its remaining work, call `factory_recovery_plan`. It inspects historical graph, reservation, PR, and accounting evidence without writing GitHub or launching workers. Report reusable candidates separately from missing evidence, required revalidation, resource reconciliation, and exhausted allowance. The assessment is not execution authority. For an explicitly authorized continuation: 1. Call `factory_recovery_propose` with a unique, stable `requestId`. Omit `allowanceIncrement` unless the user explicitly authorized additional amounts; the default increment is zero. When the source evaluated compiler exhausted its repair envelope before creating any Work Items or graph, include the same fully explicit `compilerEvaluation` object recorded by the source with `mode: "auto-repair"`, `maxRepairs`, `maxInvocations`, `timeoutSeconds`, and `maxObservedTokens`. Present the exact retained limits and added invocation exposure for authorization. `maxObservedTokens` is an observed evaluation stop, not a hard provider token cap; the cumulative economics policy remains the spending boundary. Explain that `maxRepairs` is one shared correction budget across obligation-inventory regeneration and graph repair: each inventory correction leaves one fewer graph correction. Report-only evaluation and `maxRepairs: 0` leave inventory extraction single-shot. Exact usage alone does not authorize an inventory retry; Factory retries only a retained, bounded response that failed deterministic claims schema or evidence-grounding validation. Report the proposed reuse, required fresh validation, cumulative usage, and blockers. A blocked proposal is not a runnable plan. 2. Resolve any missing authority before writing: an exhausted allowance needs an explicit increment; unknown historical usage needs the user's acknowledgement of the returned `unknownUsageDigest`. Pass that digest as `unknownUsageAcknowledgementDigest` and propose again when authorized. Show the exact digest, explain that the historical invocation has no trustworthy actual-usage closure so zero cannot be inferred, and state that acknowledgement preserves the uncertainty but grants no additional allowance. Ask once for an explicit yes/no decision. While waiting, do not poll status or leave a heartbeat active. Neither a quota reset nor a repaired check or credential grants extra Factory allowance. 3. Call `factory_recovery_request` with the exact proposed `planDigest`, the same `requestId`, and the same compiler-evaluation, increment, and acknowledgement inputs. This writes a digest-bound successor request, not a revival of the terminal run. After an uncertain response, retry those exact inputs with the same ID; do not generate a replacement request. A changed plan needs authorization for that plan. 4. The repository controller discovers the request and verifies leases, source evidence, resource absence, and cumulative accounting before adoption and execution. Use `factory_status` to inspect progress. If the controller is stopped or absent, starting/installing it requires the same host execution authority as ordinary unattended mode. Do not substitute `factory_run` for adoption. An owned Linux service may retire its current launcher generation before adopting a successor, using its existing restart policy. This does not prove resource cleanup: the next generation must independently establish absence. Legacy unbound resources or missing evidence can still block adoption; report the gate instead of killing unrelated processes or inventing cleanup receipts. If lifecycle inspection returns `controller-user-manager-unavailable`, report and preserve its exact same-user Linux/WSL command. Do not interpret the failed observation as stopped, disabled, stale, or permission to install; do not redirect it to another bus or service manager. Preserve existing issues, PRs, and budget history. Do not use `factory_activate` or low-level dispatch to bypass recovery gates. Resume/retry applies to non-terminal runs, not terminal revival. ## Status only Use `factory_status` for a read-only status request. Report its bounded Objective and run state, Work Item counts and active details, open blockers, attempts, scheduling decisions, burst activity, cost totals, then honor `operatorAction.monitoring`: `continue` permits an existing monitor while autonomous progress is possible; `stop` requires any attached recurring monitor to be paused or deleted and the response to say plainly that no Factory work is active. If the user asks why work is waiting or what evidence would unblock it, call `factory_explain` and preserve its stable reason code, gate, evidence, and required action. Use `factory_replay` only when the user asks to audit or reproduce scheduling. It is read-only: it reconstructs durable scheduling receipts and can evaluate supplied credential-free admission snapshots without writing GitHub or launching a worker. Report unavailable observations as unavailable; do not infer missing provider, token, capacity, cost, or timing values. Do not activate, install/start a controller, or start `factory_run` unless the user asked to execute or resume. Controller installation changes local service state; an inspection request alone never authorizes it. ## Hard boundaries - A label alone never activates code execution. - A plugin cannot wake a stopped harness or powered-off host. - Missing credentials, unsupported branch rules/capabilities, sensitive changes, and exhausted budgets are escalation reasons, not invitations to bypass policy. - Low-level dispatch tools are not a supported activation path. Use the Supervisor tools above for Factory Objectives; do not bypass their recorded authority.