AIWorkhub
Integrates GitHub Copilot as a coding worker/model route in AIWorkHub's multi-model workforce, allowing the manager to dispatch dependency-safe task cards to Copilot and review its submitted changes, tests, logs, and tool receipts before accepting work.
AIWorkHub
Proof, from this repository's own history:
1,984 commits since 2026-07-20, written through its own task loop
347 work cards accepted into its own tree
651 times a worker's change was sent back with code-level findings
621 independent reviewer passes
620 test files, about 262k lines of Python
What makes it different:
Semantic edit: workers change hash-verified line ranges, never rewrite whole files.
Review loop: mechanical gates and tests run first, then an independent reviewer reads the code; the manager accepts, returns with findings, or blocks — the same turn.

What AIWorkHub is
AIWorkHub is a VS Code extension and an MCP server. You talk to one manager AI. It splits your goal into task cards and hands each card to a worker AI (Codex, Claude, Copilot-hosted models, DeepSeek, GLM and others). Nothing lands in your tree until independent review and measured validation accept it.
Every repository owns its own .aiworkhub/ state. There is no AIWorkHub cloud
account, and the MCP server speaks stdio only.
Related MCP server: Agent Delegation MCP
How it works
flowchart LR
A[Task card] --> B[Isolated worker worktree]
B --> C[Validation gates]
C --> D[Reviewer lenses]
D --> E{Accept or reject}
E -->|accept| F[Promoted into your tree]
E -->|reject| G[NeedFix ledger]
G --> ACard. The manager writes a bounded card: objective, acceptance criteria, dependencies, allowed writes and validation.
Isolated worker. A worker runs the exact card in its own worktree, with Source Graph and repository context. It never finalizes its own work.
Validation gates. Mechanical checks and the card's declared tests run first.
Reviewer lenses. Independent correctness, security and code-quality reviewers read the candidate. One aggregate decision packet reaches the manager.
Accept or reject. The manager promotes verified work, or rejects it with exact residual work.
NeedFix ledger. Findings are tracked as NeedFix records until a verified fix resolves them.
Key features
Multi-provider workforce routing. Cards are routed to models by cost and observed outcome: premium models for hard judgment and review, cheaper capable models for bounded work.
Source Graph. A repository-local, incrementally refreshed code index (including Dart) that gives managers and workers bounded symbol, call, test and impact queries instead of broad file scans, across exactly 38 Source Graph query modes. The exact-target modes are
file,function,class,body,bodygrepanddeps. Workers change hash-verified line ranges through semantic edit, not whole-file rewrites. See the full-resolution Source Graph architecture diagram for the complete index and query pipeline.Sandboxed workers. Worker processes run inside a Windows AppContainer or a Linux Landlock sandbox with explicit write scopes.
NeedFix on the dashboard. The dashboard groups NeedFix records by work state, so open, in-progress and finished work are visible at a glance.
Callback loop. When a worker reaches review, a durable callback wakes the verified manager chat. A callback is a wake-up, not an approval.
Release cut.
scripts/release_cut.pyruns a release as one ordered run (version, changelog and README checks, host suite, VSIX package, release commit, receipt, tag) and stops at the first failing step.Context that persists. Session Manager, AI Memory and KB are repository-scoped and available to managers and workers.
Install and quick start
VS Code
Install AIWorkHub from the VS Code Marketplace, or download the VSIX from the latest GitHub release and run
code --install-extension ./aiworkhub-<version>.vsix.Open a Git repository and run AIWorkHub: Open Dashboard.
Choose Initialize AIWorkHub once. It is explicit and idempotent: it creates
.aiworkhub/and starts the first Source Graph index.Open a new Codex, Claude or other MCP-capable chat after initializing, so the chat discovers the repository's MCP tools.
Describe the outcome you want. The manager creates cards and launches workers; you inspect the evidence in Review and accept or reject.
The built-in dashboard Manager chat and Claude Code are woken automatically when a worker finishes. A Codex sidebar chat is inbox-only and polls the review queue itself; see Callback delivery.
Any MCP client
AIWorkHub speaks MCP over stdio, so any MCP client can run it against a repository.
Option A: uvx. Add the server to your client's MCP configuration (until the PyPI package is published, use the release wheel: "args": ["--from", "/path/to/aiworkhub-<version>-py3-none-any.whl", "aiworkhub"]):
{
"mcpServers": {
"aiworkhub": {
"command": "uvx",
"args": ["aiworkhub"],
"env": {
"AIWORKHUB_REPO_ROOT": "/path/to/your/repo"
}
}
}
}Option B: Docker. Build the image from an AIWorkHub checkout, then run it from the repository you want managed:
docker build -t aiworkhub-mcp .
docker run -i --rm -v "$PWD:/workspace/repo" aiworkhub-mcpThe image defaults to AIWORKHUB_REPO_ROOT=/workspace/repo with writes and
launches off.
Writes and worker launches are off by default. Enable them only in a trusted
manager process with AIWORKHUB_ALLOW_WRITES=1 and AIWORKHUB_ALLOW_LAUNCH=1.
AIWORKHUB_MAX_PROCESSES caps concurrent workers. Launched workers never
inherit the manager's launch capability.
Requirements
VS Code 1.93 or newer for the extension.
Python 3.12 or newer for the MCP runtime (the extension packages its own).
At least one authenticated model route: an editor Language Model provider or a logged-in Codex or Claude Code CLI. AIWorkHub does not copy or proxy credentials. The Dashboard's Preflight shows which routes are ready.
Linux, macOS, native Windows, WSL and Remote-SSH are supported; Linux is the canonical development and validation host.
Measured claims and limits
semantic-edit-historical-cap-boundary: historical capped a/b observation at 20k/200k ops shows a 29.329% reduction; this is a capped historical sample, not eligible as a live guarantee.
context-bundle-v2-structural-only: structural-only validation; live fleet remeasurement pending.
What's new in 0.13.0
Quality reviewer launches start reliably in large working trees: the read-only reviewer workspace copies the tracked canonical delta plus only the untracked files the review names, instead of every untracked file, and launch progress names the workspace materialize phase.
Lower RAM and token use: the dashboard snapshot halves its memory peak by indexing only the process-event fields the cost ledger reads, Claude workers receive only the built-in tools their card needs, and failed model probes are cached instead of re-run every snapshot.
The full release history is in CHANGELOG.md.
Documentation
Guide | Covers |
First run, manager prompts, Remote-SSH, recovery | |
The whole system and its control loop | |
Index, query modes and semantic edit | |
Opt-in manager conversation evidence | |
Callback delivery per client | |
Measured benefits and their limits | |
Release channels and owner setup | |
Where the product is going |
Also: Security policy, Contributing, Product site.
Development
python -m pip install -e ".[dev]"
ruff check src/aiworkhub scripts tests
mypy
python -m pytest -q
npm --prefix vscode-extension install
npm --prefix vscode-extension testAIWorkHub is open source under the MIT License.
Available Tools
117 toolsaiworkhub_agent_accept_previewARead-only
READ-ONLY: what would block aiworkhub_agent_accept_review right now, before any work.
Use this for the cheap accept blockers of one candidate; use aiworkhub_review_packet for that candidate's full review evidence.
Measured 2026-09-08: 49 of 159 accept attempts (31%) failed on a blocker that was knowable in advance -- a required lens still running, a target not yet review_ready, an approval not given -- but only after the combined tree had been materialized and two validation runs paid for. This folds exactly those cheap blockers and writes nothing.
A clear preview is NOT an acceptance and NOT a promise of one. The
expensive half -- combined tree, declared validations, mechanical gate,
reviewer receipt verification by request id -- runs only in aiworkhub_agent_accept_review
and can still refuse. blocked False means only that nothing cheap is
refusing yet. Leave requested_risk_tier unset to read the tier the
finalizer measured; an explicit value can only raise it.
Inputs: task_id, request_id, confirm_high_risk, requested_risk_tier, +2 more. Returns: object
aiworkhub_agent_accept_reviewA
COORDINATOR/WRITE-GATED: accept one review_ready request, phase 2.
Re-runs scope, required-output, and validation gates against the
retained isolated worktree, compares every changed path's hash against
the ones recorded when the request first reached review, and only then
promotes into the canonical repo and finalizes the task as done. Any
precondition or revalidation failure leaves the canonical repo untouched
and the task in review. Idempotent: accepting the same already-finished
request again returns already_accepted instead of re-promoting.
Medium-and-higher risk profiles also validate a fresh canonical+candidate
combined tree and require strict reviewer findings; high/critical review
requires an explicit confirm_high_risk decision.
manager_correction -- unset by default, and every other behaviour is
then exactly as before -- accepts the sealed candidate PLUS a manager patch
instead of rejecting it:
{"patch": <unified diff>, "finding_ids": ["reviewer:<lens>:<id>", ...], "reason": str}. It lifts the refinement_required blocker of each
named finding that a selected reviewer reported and
aiworkhub_manager_review_finding_dispose already recorded as
confirmed, provided its severity is not blocking. The patch is
validated before any promotion or state change and refuses with
manager_correction_invalid:<reason> when the manager is unverified, the
patch does not apply to the sealed candidate bytes, a touched path is
outside the card's allowed_writes or not part of the candidate, no
finding is named, or a named finding is unconfirmed or blocking. The
declared validations and the mechanical gate then run on the CORRECTED
bytes, those are the bytes promoted, and the accepted-outcome receipt binds
the patch digest with the candidate and corrected hashes.
An optional "allowed_writes_amendment": [<repo-relative path>, ...]
(NF-2026-02241) lets the patch also touch those exact paths -- e.g. a
neighbour test the accept revalidation showed red. Every amended path must
be touched by the patch and obey the allowed_writes path rules
(allowed_writes_amendment_* refusals otherwise); a path outside the
candidate is patched against its canonical bytes and promoted with it.
After the accept lands the paths are added to the card's allowed_writes,
add-only, and the reply names them under allowed_writes_amendment.
Without the key a path outside allowed_writes is refused as before.
A successful reply is the receipt (aiworkhub.accept_review_receipt.v1):
promoted_paths, reviewer_finalization, acceptance_evidence_record,
accepted_outcome_receipt, needfix_closure, learning_commit_owed, plus the
finalized card's status and card_sha256/card_bytes. include_card =
none (default) | summary | full adds the card view. Errors are unchanged.
lesson_candidate / no_new_lesson_reason -- both unset by default, and
the reply is then exactly as before -- close this decision's learning out in
the same call, AFTER the accept landed. lesson_candidate (with optional
promote_ai_memory and extra_evidence_ids) runs
aiworkhub_manager_learning_commit for this request and returns its reply
under learning_commit; no_new_lesson_reason (one of
learning_commit_store.NO_NEW_LESSON_REASONS) records that disposition and
returns it under learning_disposition. Both together
(learning_inline_conflict), an unknown reason, or promote_ai_memory
without a lesson are refused before anything changes. A failed close-out
never undoes the accept: ok stays true, the failure is reported under
its own key, and learning_commit_owed stays in the reply.
commit (accept_commit) is {state: committed|skipped|failed, sha?, reason?, paths, message_subject}; a skip or failure never undoes the accept.
Inputs: task_id (required), request_id (required), auto_commit, include_card, +12 more. Returns: object
aiworkhub_agent_cancel_taskB
DUAL-GATED: terminate one exact process group recorded by this server.
Inputs: request_id (required), reason. Returns: object
aiworkhub_agent_collect_resultARead-only
READ-ONLY: collect bounded worker output and review-readiness evidence.
Use this for one request's raw output and readiness; use aiworkhub_review_packet for the folded review evidence before deciding.
Inputs: request_id (required), max_log_bytes. Returns: object
aiworkhub_agent_launch_taskA
DUAL-GATED: launch one exact local Claude/Codex worker process.
Requires both AIWORKHUB_ALLOW_LAUNCH=1 and
AIWORKHUB_ALLOW_WRITES=1. The task card, runner, topic, pending state,
allowed-write scope, collision guard, adapter, and process limit are all
validated before a shell-free child process can start.
timeout_seconds is retained only as non-enforcing compatibility
metadata; this API never installs a provider wall-clock deadline.
runner, topic and adapter_id are optional because the server
already owns them: the card carries runner and topic (the launcher refused
any value that differed, so typing them asserted rather than decided), and
the adapter is a pure function of the runner narrowed to the first
pinnable, policy-allowed entry in canonical tuple order. Omit them and the
reply's launch_identity_derivation records exactly what was derived;
pass them and the explicit value wins and is validated as before. The
manager identity codex is never a worker runner.
Inputs: task_id (required), model, topic, runner, +3 more. Returns: object
aiworkhub_agent_list_processesARead-only
READ-ONLY: summarize latest processes; use detail='full' for legacy records.
Use this for the newest worker processes across all tasks; use aiworkhub_agent_task_status for one launched request in detail.
Inputs: limit, detail. Returns: object
aiworkhub_agent_retry_finalizationA
COORDINATOR/WRITE-GATED: retry one retained finalization request.
The provider/model is never launched again. The exact successful worker
request, retained workspace, task identity and supervisor exit receipt are
revalidated before deterministic validation/finalization is re-entered.
A validation failure is eligible only when its durable reason is the
operational validation_exec_scratch_unavailable condition; ordinary
product/test failures remain non-retryable. A scope_rejected request is
eligible: the re-run repeats the scope check and reaches review_ready only
if the retained delta is now in scope (NF-2026-01345).
validation_lane="manager_host" is the manager's explicit opt-in for a
candidate whose declared validations failed only because the sandbox
validation lane cannot execute them (NF-2026-01030). It makes any
validation_failed/finalize_failed request whose retained candidate
seal still verifies retryable, and re-runs the SAME declared commands with
the validation route forced to the host backend. All pass -> the normal
finalize path to review_ready; any failure -> validation_failed again,
now with host receipts. The lane is never derived from candidate output.
manager_host applies only to VS Code LM adapters: its forced backend is
the editor-hosted one, which never runs a native CLI route outside its OS
sandbox, so a request from a CLI adapter (e.g. claude_cli) is refused up
front with validation_lane_forbidden_for_adapter:<adapter> before any
event write or card transition, leaving the request and card unchanged
(NF-2026-01645).
Inputs: task_id (required), request_id (required), validation_lane. Returns: object
aiworkhub_agent_task_statusARead-only
READ-ONLY: inspect one launched process and its authoritative task card.
Use this for one launched request and its card; use aiworkhub_agent_list_processes to find recent requests or aiworkhub_task_show for a card by task_id alone.
detail="brief" (default) keeps only the lifecycle facts a manager reads
to learn state: the identity and lifecycle fields, the card's scalar
lifecycle fields and the latest event's state, exit code, timestamps and
usage totals. Measured over 21 days the former summary default averaged
12,765 B/call (792 calls); review decisions come from aiworkhub_review_packet.
detail="summary" folds the card's baseline hash maps and
evidence blobs, its terminal_failure/rework_predecessor/
template_provenance.expanded_contract, and its static contract text
(objective/acceptance/validation/read_first/template_provenance/
project_context/forbidden/required_outputs/mandatory_changed_outputs) to
{summarized, bytes, sha256} -- identity and lifecycle fields (task_id,
title, status, substatus, runner, topic, request ids, allowed_writes
count) stay exact. The latest event's validation/quality_gate/
worker_mcp_gate/token_budget/project_context fold the same way, without
redundant field-name inventories. Repeated retry/reroute reasons and the
minimality contract fold to identity; named artifact/delivery/review receipts
retain status, errors and explicit observed/unknown flags alongside identity.
Failure/liveness fields and usage metrics stay exact.
The manager-authored bodies (review_feedback, recovery_feedback,
history) fold the same way, and the reply carries
card_sha256/card_bytes plus review_findings_count when the card
records reviewer reports: measured avg 11 KB/call over 48 calls, max 33 KB
(NF-2026-01447).
"evidence" keeps all of the above exact (baselines still folded);
"full" returns the raw status payload.
"evidence" is bounded (NF-2026-02256): when the compact JSON of the
task_card and latest_event sections exceeds
evidence_paging.EVIDENCE_PAGE_CAP_BYTES (64 KB) the reply carries the
leading section keys that fit plus evidence_truncated,
evidence_total_bytes, evidence_sha256 and continuation_cursor;
pass that cursor back to read the next page. A cursor for a card that
changed since refuses with evidence_cursor_stale.
Inputs: cursor, detail, task_id, request_id. Returns: object
aiworkhub_claude_callback_ackB
WRITE: acknowledge one exact callback batch returned to this same verified Claude manager session.
Inputs: batch_id (required), lease_id (required). Returns: object
aiworkhub_claude_callback_waitARead-only
BLOCKING READ/CLAIM: wait for a callback for this verified Claude
Code manager session. Acknowledge the previous batch by passing its
batch_id/lease_id as ack_batch_id/ack_lease_id here, or
call aiworkhub_claude_callback_ack; an unacknowledged lease is
retried, never lost.
Inputs: ack_batch_id, ack_lease_id, timeout_seconds. Returns: object
aiworkhub_completion_inboxARead-only
READ-ONLY: combined completion-inbox facts for Codex orchestration.
Returns five facets in one call: review_queue (tasks awaiting Codex
review, as aiworkhub_task_review_queue lists them),
operational_failures (legacy finalizer failures eligible for
retained retry), stale_processing (claimed tasks with no recent
artifact/validation activity, default threshold 24h), runner_mismatch_warnings
(batch-token mismatches between a runner name and the task_id it
claimed -- a local pure replica of
AITools/taskctl.py::_runner_task_batch_mismatch), and
latest_validation_facts (the most recently recorded validation_status/
validation_error/blocker_reason per task).
FROZEN READ-ONLY CONTRACT -- no write-gate toggle, no mutation
parameters. Only issues taskctl list/taskctl show (both read-only).
Never calls taskctl done/review/start/auto-pickup/add-card/export-jsonl.
Never mutates queue or audit state. Never launches agents or processes
beyond the existing taskctl.py read-only child-process calls.
Inputs: limit, topic, stale_processing_hours. Returns: object
aiworkhub_dashboard_needfix_transitionA
USER WRITE: apply one confirmed lifecycle transition to one NeedFix or up to 25.
Use this to triage, accept, reject, defer, mark duplicate or task_planned, resolve, or recover a conversion claim; archive, restore and convert have their own tools. Requires confirm=True and returns a transition receipt.
A task-less fix closes with action=resolve_verified (readiness_score=100, evidence, evidence_refs) or a Resolves: NF-YYYY-NNNNN commit trailer. With needfix_ids the reply is {results, succeeded, failed} and a refused row leaves the others applied.
Inputs: action, reason, confirm, evidence, +7 more. Returns: object
aiworkhub_dashboard_snapshotARead-only
READ-ONLY: build the canonical dashboard queue, health, and storage snapshot for the active repository.
Use the default compact mode for manager queue summaries and status counts, or full=True for the native Webview payload; use the cheap connection-check view or the single task-card detail view instead. Reads canonical SQLite state and cached storage telemetry without mutating tasks or launching processes.
Inputs: full, previous, previous_snapshot, known_contract_sha256. Returns: object
aiworkhub_dispatcher_ensure_startedAIdempotent
Idempotently ensure exactly one callback dispatcher is running for the active repository, bound to the currently-selected coordinator target (B857). Called by the VS Code extension after every MCP handshake (activation, tab-deserialization, reload) and after an explicit coordinator-target switch -- never starts a second thread and never marks an uninitialized repository as degraded.
Inputs: no named parameters. Returns: object
aiworkhub_dispatcher_healthARead-only
READ-ONLY: dispatcher running/stopped, selected coordinator target, repository identity, pending callback count, and last delivery/error. Use this when callbacks stop arriving; use aiworkhub_source_graph_health when Source Graph answers look stale, and for a cross-subsystem verdict run the one-call doctor check.
Inputs: no named parameters. Returns: object
aiworkhub_doctor_diagnoseARead-only
READ-ONLY: what is wrong right now. Runs the task, dispatcher, source-graph and manager-route health probes concurrently and returns one verdict (ok/problem/unavailable) with the non-ok probes and the tool to call next, plus server_process: this answering process's pid, memory and runtime generation. Use first when something fails and the cause is unknown; use aiworkhub_environment_preflight for pre-launch readiness.
Inputs: no named parameters. Returns: object
aiworkhub_environment_preflightARead-only
READ-ONLY: unified repository/policy/Source Graph/provider readiness. Use before launching workers to confirm readiness; use aiworkhub_doctor_diagnose when something is already failing.
Provider access is reported as observed only when an adapter-specific
bridge or credential readiness source proves it; installed CLI binaries
alone remain installed_unverified_access.
detail="summary" (default) folds Source Graph's refresh-job report to
identity plus state, providers to a flat {adapter_id: status}
map, provider_route_contracts.route_families to one
{family, status, count} row each, policy to its verdict fields,
worker_finalization to its state fields, and each of
provider_summary's route/capability lists and its
route_status_questions block to a count plus a short id preview (or
identity); with adapter_id given, providers and
provider_observability.adapters/providers are filtered to that
adapter. detail="evidence" behaves like "full": both return
repo_policy.build_preflight exactly.
Inputs: detail, adapter_id. Returns: object
aiworkhub_manager_ai_memory_getARead-only
MANAGER READ: exact active canonical AI Memory lookup.
Inputs: key (required). Returns: object
aiworkhub_manager_ai_memory_searchCRead-only
MANAGER READ: bounded canonical AI Memory search.
Inputs: query (required), limit. Returns: object
aiworkhub_manager_ai_memory_writeB
MANAGER WRITE: remember, update, supersede, or archive canonical memory.
Inputs: key (required), action (required), provenance (required), idempotency_key (required), +3 more. Returns: object
aiworkhub_manager_bootstrapA
CALL FIRST: mandatory repository manager contract and callback workflow.
The identity block -- role, verified route, repository and storage
readiness, task health, the last hygiene pass and the Claude-route
dispatcher state -- is on every reply, so repository_current and
aiworkhub_task_health need no call of their own. The contract prose is delivered
once per verified session and then suppressed with its sha; pass
include_contract=true to re-read it, or known_contract_sha256 to prove you
already hold it.
A reply that suppresses the contract (contract_delivered=false) is the
steady-state one, and it was measured at up to 11 KB -- most of it the last
hygiene pass's per-task detail and the reconciler's own internals, which no
caller gates on (NF-2026-01447). Those bodies are dropped from
task_hygiene/task_health and replaced by the names omitted plus the
block's sha256/bytes, so nothing silently disappears; the verdicts and
counts beside them stay exact. include_diagnostics=true keeps them.
Inputs: include_contract, include_diagnostics, known_contract_sha256. Returns: object
aiworkhub_manager_callback_lane_claimA
MANAGER WRITE: take the callback lane back for this verified manager.
Selects the caller's own verified provider and session in the repository's
coordinator-target file (atomic replace, unrelated keys kept), so callbacks
and aiworkhub_task_create route to this manager again. Refuses with a stable reason,
leaving the file unchanged, when the caller has no verified route, is Codex
without a live route, or another live Manager Chat or Codex route holds the
lane. Every claim and refusal appends one audit row.
Inputs: no named parameters. Returns: object
aiworkhub_manager_candidate_treeARead-only
MANAGER READ: path and state of a request's full candidate tree.
The tree is built by the host validation stage (host_commands/host_sweep) from canonical plus the candidate overlay; ready means the stage finished.
Inputs: request_id (required). Returns: object
aiworkhub_manager_context_graph_rangeBRead-only
MANAGER READ: retrieve an exact bounded transcript range around one event.
Inputs: thread_id (required), around_event_id (required), after, before. Returns: object
aiworkhub_manager_context_graph_searchBRead-only
MANAGER READ: search exact transcript-backed Context Graph evidence.
Inputs: query (required), limit. Returns: object
aiworkhub_manager_context_write_intent_disposeB
MANAGER WRITE: explicitly accept or reject one worker proposal.
Inputs: reason (required), decision (required), intent_id (required), request_id (required). Returns: object
aiworkhub_manager_context_write_intentsARead-only
MANAGER READ: inspect authenticated worker context-write proposals.
Inputs: request_id (required). Returns: object
aiworkhub_manager_kb_getARead-only
MANAGER READ: exact canonical KB entry lookup.
Inputs: key (required). Returns: object
aiworkhub_manager_kb_searchCRead-only
MANAGER READ: bounded canonical KB search.
Inputs: query (required), limit. Returns: object
aiworkhub_manager_kb_writeC
MANAGER WRITE: upsert, ingest, supersede, or archive canonical KB data.
Inputs: key (required), action (required), provenance (required), idempotency_key (required), +6 more. Returns: object
aiworkhub_manager_learning_commitA
MANAGER WRITE: persist and project one verified Learning Commit.
SHORT FORM -- the one to use: task_id, request_id and the lesson.
Everything mechanical is resolved server-side from the card's OWN decision
event: outcome is read from the adjudication (never asserted),
repo_area from the paths that decision was taken over, evidence_ids
from the sealed FIXED_AND_VERIFIED acceptance reference, and
idempotency_key/provenance are the deterministic strings the
learning_commit_owed payload in your accept/reject reply already carried.
failure_category is always derived server-side from the card's structured
terminal evidence and is never caller-suppliable. repo_area omitted is
derived from the decision's paths; any explicitly supplied value is
normalized and honored, while an empty or whitespace value is refused with
learning_commit_repo_area_invalid:empty.
Add your own references with extra_evidence_ids. An evidence id must
carry an allowed scheme -- file:, http: or https:. A sha256:
receipt id is refused, and any refusal here returns
allowed_evidence_id_schemes.
outcome is accepted, rejected or inconclusive; only the first
two may promote, and each promotion needs what its store demands (a lesson
for AI Memory, an invariant for KB, an edge plus an acceptance for Context
Graph).
LONG FORM (compatibility): supply repo_area, outcome, evidence_ids, idempotency_key and provenance yourself and nothing is resolved. The lesson text is always the caller's; nothing is written without this call.
Inputs: task_id (required), request_id (required), outcome, repo_area, +11 more. Returns: object
aiworkhub_manager_loop_eventsARead-only
MANAGER READ: bounded session events, for incremental client polling.
Events with seq greater than after_seq, bounded to limit, and partial:
the running turn's streamed, unfinished text for this session, or null.
The partial is display only; it is never persisted or sent to a model.
Inputs: session_id (required), limit, after_seq. Returns: object
aiworkhub_manager_loop_statusARead-only
MANAGER READ: the active session, whether a turn is running, queued owner sends, and the last turn's outcome.
Inputs: no named parameters. Returns: object
aiworkhub_manager_needfix_draftARead-only
READ-ONLY: draft the NeedFixes one request's own review evidence justifies.
A NeedFix could not be drafted from the evidence that justifies it, so it was retyped. Measured 2026-09-08: of 204 manual filings, 76 had an accept/ reject/status/collect result within the previous 15 calls, 43 carried a 32-hex request id, and 355 of 540 typed identifiers (66%) appeared verbatim in the previous 15 tool results; 453 of 557 stored rows carry a hand-typed evidence dict at p50 549 B. Meanwhile 589 accepted-shape reviewer findings and 1,623 failed-gate payloads became a NeedFix only if someone retyped them, and reviewer cards are archived (1,796 so far), taking every unconverted finding with them.
Everything returned is mechanical: title from the failing check id or the
finding summary, kind and severity from the finding category through a
fixed map, scope_files from the card's changed paths, evidence from
terminal_review.evidence (error, returncode, declared command) plus the
finding's own path/line/check_id, evidence_refs from the attempt
-artifact manifest reference and this request id, and provenance
{origin: server_draft, request_id, verified: false}.
The DESCRIPTION is deliberately empty -- it is your judgement about what to
do, not a fact on the card, and this never invents one. Writes nothing:
file a candidate with needfix_add once you have written that
description. finding_id / check_id narrow the draft to exactly one
finding or one failing check.
Inputs: request_id (required), check_id, finding_id. Returns: object
aiworkhub_manager_recipe_listARead-only
MANAGER READ: bounded identity/contract listing of persisted recipes.
Returns each manifest's identity, digest, purpose, risk, capabilities and
parameter signature -- never its argv template. An empty store is a
legitimate repository state and returns registry_count zero.
Inputs: limit, offset. Returns: object
aiworkhub_manager_recipe_runA
MANAGER EXECUTE: run one PERSISTED recipe and return a bounded digest.
What runs is the immutable stored manifest resolved from the registry, not
a mapping typed at call time: argv[0] is a manifest literal, the vector
is built from typed slots, and it is spawned as an execve list with no
shell. Read-only by default -- tool_recipes.validate_invocation refuses
a recipe whose declared capabilities grant_capabilities does not name,
and a write/network recipe additionally requires the repository
write gate to be open.
A non-zero exit is a RESULT, not an error: the digest carries the return
code, the duration, stdout/stderr tails capped at 4096 characters with
explicit truncation flags, and the path plus SHA-256 of the full output
file, so the whole stream stays retrievable without being carried here.
Every run persists a tool_recipes invocation receipt.
Inputs: recipe_id (required), detach, params, version, +3 more. Returns: object
aiworkhub_manager_recipe_run_statusARead-only
MANAGER READ: the state of one detached recipe run, optionally waiting for it to finish.
Returns the run's state (queued, waiting_memory, running, completed, failed, refused or lost). A completed run carries the same bounded digest the synchronous aiworkhub_manager_recipe_run returns, plus the child log path. A run whose process died before finishing reads as lost.
Inputs: run_id (required), wait_seconds. Returns: object
aiworkhub_manager_recipe_seed_canonicalA
MANAGER WRITE: install the catalogue of this repository's own invocations.
Each entry of manager_recipe_tools.CANONICAL_RECIPES describes an argv
vector AIWorkHub genuinely builds (the card validation commands, the worker
worktree provisioning sequence, the finalization Git probes), naming its
call site in its purpose. Idempotent: an entry already stored is reported as
already_registered and its row is left untouched.
Per-project, not a fixed list. The universal entries -- the git
workspace/finalization/diff probes and the packaged aiworkhub.recipes.*
operator modules -- install everywhere. The entries that depend on a
toolchain or on paths that must exist in THIS project install only when
toolchain_authority measures them present, so a project without Node
never receives validation.node_test. withheld names every skipped
entry with its measured reason.
Inputs: no named parameters. Returns: object
aiworkhub_manager_recipe_showARead-only
MANAGER READ: one persisted recipe in its exact canonical manifest form.
With version omitted the highest stored version wins, ordered by the
registry's own version key. The returned manifest is exactly the payload
the recipe digest hashes, so the reported digest is independently checkable.
Inputs: recipe_id (required), version. Returns: object
aiworkhub_manager_recipe_usageARead-only
MANAGER READ: which registered recipes are actually used, and by whom.
aiworkhub_manager_recipe_list answers how many recipes EXIST. This
answers whether anything uses them: every registered recipe appears with
its run count, how many DISTINCT verified actors ran it, its first and last
run, its exit-code distribution and the bytes those runs returned -- and a
recipe with no runs appears with used false rather than being omitted,
because "registered and never run" is the actionable state.
The actor on every receipt is derived by the server from the verified
route, never from a caller-supplied string, so distinct_actors cannot
be inflated by typing a new name. Runs recorded before actors existed are
reported as unattributed_runs rather than credited to anyone.
since is an ISO-8601 UTC timestamp bounding the evidence window;
registered_count still covers every stored manifest, and window_only
marks the asymmetry.
Inputs: limit, since. Returns: object
aiworkhub_manager_reconcile_dead_processingB
MANAGER WRITE: reconcile one exact authenticated dead blocked claim.
Inputs: task_id (required), request_id (required), claim_epoch (required). Returns: object
aiworkhub_manager_resource_statusARead-only
MANAGER READ: queue of a hub-managed resource such as cpu_heavy.
Returns the holder, the waiters in the order they will be served, and each entry's priority and wait time, from the runtime database.
Inputs: resource. Returns: object
aiworkhub_manager_review_finding_disposeA
MANAGER WRITE: record one audited disposition of one reviewer finding.
dismissed needs non-empty counter_evidence and lifts that
finding's refinement_required blocker at accept. A HIGH finding may
only be dismissed, and its counter_evidence must cite the contract (a
path:line or card:/kb: quote; otherwise
review_finding_disposition_contract_citation_required); the receipt is
manager_signed. A CRITICAL finding can never be disposed. A replay is idempotent; changing
a disposition needs a reason and keeps the prior receipt in history.
Frozen once the target is accepted. Bound server-side to the reviewer
receipt and candidate digest; never edits the report or accepts the target.
Reproduction runs only on dismissal. When the finding's reproduction is a spec (pytest: or probe:) and the disposition is dismissed, the coordinator first runs it in the validation sandbox on the candidate and on its base, and stores the signed receipt with the disposition. A confirmed disposition needs no proof and never runs it. Only a failed test, or a probe's assertion failure or explicit exit 1, counts as failed; any other error is unrunnable. A reproduced finding can be dismissed only when counter_evidence cites the contract as for HIGH (manager_signed); otherwise review_finding_reproduced_not_dismissable and nothing is stored. not_reproduced or pre_existing may replace counter_evidence for a LOW/MEDIUM finding (HIGH still needs the citation, CRITICAL never); unrunnable changes nothing. A replay reuses the stored receipt.
Inputs: task_id (required), finding_id (required), request_id (required), disposition (required), +3 more. Returns: object
aiworkhub_manager_review_hold_resolveA
MANAGER WRITE: resolve one exact durable reviewer-route hold.
Every chain, candidate and retired-attempt identity is mandatory. The action can only expose an already-recorded callback, authorize the one bounded distinct-route successor, or re-arm the exact pre-provider reviewer attempt after its operational blocker was repaired. It never accepts the target and never relaunches its implementation worker.
Inputs: lens (required), decision (required), claim_epoch (required), attempt_index (required), +5 more. Returns: object
aiworkhub_manager_sdlc_outcome_metricsCRead-only
READ-ONLY: bounded outcome metrics from canonical task/review events.
Inputs: limit. Returns: object
aiworkhub_manager_semantic_edit_applyA
MANAGER EDIT: replace exactly one prepared, hash-bound range.
new replaces the WHOLE prepared range; re-emit every line you keep.
allow_escape_level_change: true only for an intentional regex/escape fix.
Inputs: new (required), target_id (required), idempotency_key (required), allow_escape_level_change. Returns: object
aiworkhub_manager_semantic_edit_prepareB
MANAGER EDIT: bind one verified file range before changing it.
Inputs: end_line (required), file_path (required), start_line (required), include_fragment, +2 more. Returns: object
aiworkhub_manager_session_current_stateCRead-only
MANAGER READ: bounded canonical Session Manager current state.
Inputs: limit, topic. Returns: object
aiworkhub_manager_session_writeA
MANAGER WRITE: append one audited canonical Session Manager event, or edit one existing event.
Append actions: start, event, checkpoint, state, handoff, close (no
document_id). Edit actions: amend rewrites the
content of one exact existing document (FTS rebuilt, audit row recorded,
context-graph mirror rewritten); redact deletes that document, its
FTS row and its graph mirror (audit keeps the fact of the redaction,
never the content). Both require document_id and leave the document
count/id audit trail truthful.
Inputs: topic (required), action (required), content (required), provenance (required), +2 more. Returns: object
aiworkhub_manager_skill_add_evidenceA
MANAGER WRITE: append one MANAGER evidence entry to a skill version.
CLOSED VOCABULARIES -- a guess is refused before a turn is spent:
outcome accepted | negative
actor_id ^[a-z][a-z0-9_.-]{0,127}$, and it may NOT contain the reserved
role tokens worker, reviewer, coordinator, agent
or owner. Those name a DERIVED identity read off a task
card's own runner and can never be typed here.
Two spellings of one manager are ONE actor: identities are compared in their
canonical form, so manager.claude.7e and claude_manager_7e do not
make an activation independent. Genuinely independent evidence comes from a
card: it is appended automatically when a decision is recorded on a card the
skill was injected into, and can be filed for one card at a time through the
task-derived path.
When resolve_negative_source is set, no row is appended: the one
unresolved negative row with that source is marked resolved instead, with
note as the REQUIRED reason (source and outcome are ignored).
Inputs: source (required), outcome (required), version (required), actor_id (required), +3 more. Returns: object
aiworkhub_manager_skill_evidence_sweepA
MANAGER WRITE: backfill learning-commit evidence for every recorded commit.
Bounded and resumable like every other sweep here: pass back
next_cursor to continue past a ledger larger than limit. Reports
skipped_by_reason (why a window's commit produced no row -- rejected,
no selection vocabulary, and so on) and activated (every
identity/version this window's evidence pushed across the registry's own
two-actor activation gate). A second sweep over an unchanged window
records nothing new and activates nothing twice.
Inputs: limit, cursor. Returns: object
aiworkhub_manager_skill_mineARead-only
MANAGER READ: mine the correction record into gated skill PROPOSALS.
Clusters every stored rejection instruction and adjudicated invariant by the
RULE it asserts -- instance vocabulary (paths, identifiers, ids, digits) is
deleted before anything is compared -- then promotes only families that
recurred across at least min_cards distinct cards in min_files
distinct files. Each candidate carries the exact card ids and request ids
where the rule was violated, plus a proposal draft whose closed-vocabulary
selection dimensions are left blank for the manager to fill in.
Read-only. It produces proposals, never activations: the returned draft reaches the store only if a manager proposes it through the skill-proposal step, and activation remains gated on evidence from two distinct actor identities.
Inputs: min_cards, min_files, threshold, include_sensitivity. Returns: object
aiworkhub_manager_skill_retirement_reportARead-only
MANAGER READ: measure every stored skill against its own failure class.
Reports, per skill, whether it is injectable at all, the cards its evidence anchors to, and the adjudicated outcome of those cards. It also reports whether the injection denominator exists in this repository -- and when it does not, says so with both counts instead of computing a rate against a zero denominator. Verdicts are recommendations; retirement stays manager-gated and this never writes.
Summary mode (default) folds each skill's evidence_anchors list to
{count, sha256} (digest of its canonical JSON); full=true returns
the anchor-card lists unchanged.
Inputs: full, min_anchors. Returns: object
aiworkhub_manager_skill_usageARead-only
MANAGER READ: per-skill usage statistics, measured from the stored record.
For every stored skill version: how many versions of that identity are proposed, its evidence rows split by outcome (accepted/negative), the number of CANONICAL independent actor identities its accepted evidence rests on (not the raw strings -- two spellings of one manager count once), the cards it was injected into according to the persisted selection receipts, whether it is injectable at all, and when it is not, the exact named reason:
lifecycle_state_is_retired unresolved_negative_evidence activation_evidence_below_two_distinct_actors lifecycle_state_is_proposed_not_active
Read-only. It never activates, retires or evidences anything.
Inputs: min_accepted_evidence. Returns: object
aiworkhub_manager_source_graph_queryBRead-only
MANAGER CODE DISCOVERY: use first and continuously before built-in file search.
Inputs: mode (required), query (required), budget, cursor, +5 more. Returns: object
aiworkhub_manager_workforce_catalogBRead-only
MANAGER READ: configured models joined to observed canonical outcomes.
full=True returns the complete payload exactly as before: every worker
field plus outcome history. The default keeps every top-level key that is
not the worker list verbatim (summary, revision, manager envelope, ...)
and folds the per-worker list to one compact row per worker -- worker_id,
adapter_id, model, enabled, launch_eligible (build_routing_catalog's
launchability key) and the row's outcomes sample_count and
accepted_rate (read only from worker["outcomes"], omitted when
absent, never invented) -- beside detail_omitted (bytes/sha256 of the canonical
JSON of the full worker list) and a detail_request naming the full
call (NF-2026-01566). The default also omits workers whose enabled
and launch_eligible are both falsy, reporting disabled_omitted_count;
include_disabled=True keeps them as compact rows (NF-2026-01830).
An error result passes through untouched.
Inputs: full, include_disabled. Returns: object
aiworkhub_manager_workforce_rankBRead-only
MANAGER READ: explainable cheapest-capable routing from current evidence.
detail="summary" (default) keeps every top-level selection field
(selected_*, economic_advisory, etc.) exact; the selected compatible
candidate and the next two keep their full row, every other compatible
candidate is reduced to worker_id/adapter_id/model/score; excluded
candidates are reduced to a count per exclusion reason plus the first
10 as worker_id/adapter_id/model. detail="evidence" behaves like
"full": both return today's payload exactly.
Inputs: kinds (required), task_id (required), risk, detail, +3 more. Returns: object
aiworkhub_manager_workforce_upsertBIdempotent
MANAGER WRITE: audited bounded upsert of one repository worker model.
Inputs: model (required), provider (required), supports (required), worker_id (required), +7 more. Returns: object
aiworkhub_quality_evidence_packetARead-only
READ-ONLY: full canonical evidence packet -- profile, declared checks, risk-based optional-gate policy metadata (not_available != passed), and the cross-provider read-only quality_reviewer contract.
Inputs: changed_paths. Returns: object
aiworkhub_quality_reviewer_launchB
DUAL-GATED: launch one independent anti-anchored quality reviewer.
timeout_seconds is retained only as non-enforcing compatibility
metadata; this API never installs a reviewer wall-clock deadline.
Inputs: lens (required), runner (required), adapter_id (required), target_task_id (required), +4 more. Returns: object
aiworkhub_quality_run_checksA
Run repo-declared .aiworkhub/quality.json build/test/lint/typecheck
commands (argv arrays only, shell=False). Fails closed on malformed
config. Diff/new-code-first: pass changed_paths to scope evidence.
Use to gate a change on the declared checks; read the declared profile first if unsure what is declared.
Inputs: changed_paths. Returns: object
aiworkhub_repo_currentBRead-only
READ-ONLY: exact current repository, binding source, and manager route.
Inputs: no named parameters. Returns: object
aiworkhub_repo_listCRead-only
READ-ONLY: bounded live repository identities available to this manager.
Inputs: limit, include_inactive. Returns: object
aiworkhub_repo_switchB
MANAGER OPERATION: atomically switch to one live manager-owned repo_id.
Inputs: repo_id (required). Returns: object
aiworkhub_review_packetARead-only
READ-ONLY: ONE bounded review packet for a review_ready candidate.
Every fact a manager needs to decide a candidate is already persisted -- validation rows with their declared commands and output tails, the quality gate's checks and blockers, the worker MCP gate and its receipt-conformance verdict, required outputs, destructive-diff checks, the effective tier and its per-lens status, the deduped reviewer findings, the reachability observation -- spread across six nested objects on one card. This returns them together, under a measured byte bound.
Measured over all 419 real cards carrying a quality gate: min 1,662 B, p50 6,387 B, p90 8,813 B, max 13,799 B, 0 needing truncation. It replaces per candidate 10 task-scoped calls at p50 (p90 21) and, session-wide, 1,688 hand-written Bash re-derivations (pytest 611, attempt-artifact reads 242, task_queue.sqlite scripts 250, log tails 113, git diff 155) totalling 1.45 MB.
Nothing here is a verdict: every status was decided by the gate that
recorded it, and accepting still runs the whole fold in
aiworkhub_agent_accept_review. The one live computation is
aiworkhub_agent_accept_preview -- itself read-only -- which
aiworkhub_completion_inbox cannot call because it holds no launch
authority, so it is computed here and passed in.
The decision section prefills the argument dicts for
aiworkhub_agent_accept_review, one aiworkhub_manager_review_finding_dispose
per undisposed finding, and aiworkhub_task_reject_review; it
never picks a disposition or a verdict and is never dropped before an
evidence section.
Inputs: task_id, max_bytes, request_id, request_ids. Returns: object
aiworkhub_session_token_profileARead-only
READ-ONLY: observed provider tokens plus separately-labelled prompt bytes. Use to see where one session's input tokens went; use aiworkhub_task_cost_ledger for per-task cost instead.
Inputs: task_id. Returns: object
aiworkhub_source_graph_ensure_startedAIdempotent
Idempotently ensure exactly one Source Graph indexing daemon is running for the active repository. Safe to call repeatedly (InitRepo, activation, tab-deserialization, reload) -- never starts a second thread and never fabricates a running daemon for an uninitialized repository.
Inputs: no named parameters. Returns: object
aiworkhub_source_graph_healthARead-only
READ-ONLY: Source Graph indexing daemon health for the active repository -- indexing/ready/degraded status, last report/error/time. Use this when Source Graph answers look stale or fail; use aiworkhub_dispatcher_health when callbacks stop arriving, and for a cross-subsystem verdict run the one-call doctor check.
detail="summary" (default) keeps every top-level scalar exact and folds
each top-level dict/list to {summarized, bytes, sha256} plus its own
status/state/degraded/ok and degraded_reasons; detail="full"
("evidence" behaves the same) returns the daemon payload unchanged.
Inputs: detail. Returns: object
aiworkhub_source_graph_refresh_nowA
Force one bounded incremental (or first-ever full) Source Graph build now, non-overlapping with the periodic background refresh.
The reply is the daemon health payload: detail="summary" (default)
folds it exactly like aiworkhub_source_graph_health; detail="full"
("evidence" behaves the same) returns it unchanged. An unknown
detail is refused before any refresh is requested.
Inputs: detail. Returns: object
aiworkhub_source_graph_stopAIdempotent
Stop and unregister the active repository's Source Graph indexing daemon, if any. Called on workspace/repository switch and extension deactivation so no cross-repository indexing thread survives.
Inputs: no named parameters. Returns: object
aiworkhub_storage_recover_stranded_worktreesA
Recover retained worktrees stranded outside every reclamation path.
NF-2026-00279: the storage observability surface recommends this recovery, but it had no tool/MCP/CLI entry point, so an operator was told to run something they could not. This exposes it as a real action.
READ-ONLY first: confirm=False (the default) returns a report of the
worktrees that would be re-registered and those that are orphaned-but-
reclaimable, mutating nothing. confirm=True requires a non-empty
reason, reinstates the provably-owned registrations, and records the
reason in the audit log.
Inputs: reason, confirm. Returns: object
aiworkhub_supervisor_loop_statusARead-only
READ-ONLY: derive supervisor_state + error taxonomy for a task_id.
Use this for the derived supervisor state and error class of one task; use aiworkhub_agent_task_status for the raw launched request and its card.
Implements the B08 contract's 7-step derivation over the LIVE queue (task_mcp_supervisor_loop_status_tool_b08_v1.json): fetch_status via core.show_task, then runner_topic_mismatch / missing_artifact / collision / stale_task / failed_validation checks, falling through to a read-only lifecycle_state -> supervisor_state mapping when none trip.
FROZEN READ-ONLY CONTRACT -- no write-gate toggle, no mutation parameters. Never calls taskctl done/review/start/auto-pickup/add-card. Never mutates queue or audit state. Never launches agents or processes. Writes remain default-off regardless of input values.
Inputs: task_id (required), topic, runner, previous_snapshot, +2 more. Returns: object
aiworkhub_task_amend_pendingA
MANAGER WRITE: amend a pending card that no request was ever launched for.
Use this to widen a card's scope or fix its validation before its first
launch, instead of archiving and re-creating it. allowed_writes and
read_first are ADD-ONLY (deduplicated; the existing entries stay);
validation REPLACES the whole list, with validation_roles aligned
one-to-one (omitted roles default to generic, which a bugfix/refactor/...
card's work_kind role gate refuses exactly as aiworkhub_task_create does). Paths and
commands obey the same rules as aiworkhub_task_create and
aiworkhub_task_reject_review's amendments, with the same refusal codes.
Only a never-launched pending card qualifies: a launched, claimed,
archived or non-pending card is refused with
task_amend_pending_refused:<card_already_launched|card_claimed| card_archived|card_not_pending:<state>|task_not_found>. The amendment is
recorded as a card_amended_pending event in the card history (the card
stays launchable) and the reply carries the new card_sha256.
Inputs: task_id (required), runner, read_first, validation, +2 more. Returns: object
aiworkhub_task_archiveAIdempotent
COORDINATOR WRITE: archive stale non-processing tasks atomically
(archived_at + card_json + an archived task_events row each). Runs the
full coordinator-capability write gate per item -- use this instead of
patching SQLite. For an active/orphaned card use supersede.
Targets: one task_id, task_ids (<= 200), or a selector
(status/topic/older_than_hours/task_id_prefix, conjunctive).
dry_run=True previews the exact ids (and the processing cards that
would be refused) without writing. Replies with per-id receipts
{task_id, ok, status_after, error?}; one refusal never hides the rest.
Inputs: topic, reason, status, dry_run, +4 more. Returns: object
aiworkhub_task_auto_pickup_dryrunARead-only
READ-ONLY: preview which task the write-gated claim WOULD take for a runner/topic.
Reports the candidate task_id, a compact card, and runner/topic filtering
counts WITHOUT mutating the parent queue and WITHOUT touching the write gate.
Never invokes the write-gated auto-pickup command; uses only the read-only
export path. The real write-gated claim tool stays behind
AIWORKHUB_ALLOW_WRITES; this preview provides no alternate write path
and cannot bypass that gate.
Inputs: runner (required), topic. Returns: object
aiworkhub_task_codex_handoffARead-only
READ-ONLY: Codex-ready HANDOFF report for review-queue tasks.
Use this for the handoff as JSON; use aiworkhub_task_codex_handoff_markdown for the same report rendered as Markdown.
For each task waiting on Codex review, summarizes task_id, runner, topic, allowed_writes, validation commands, derived risks, commit-hygiene status, and a scoped stage/finalize command list — WITHOUT mutating the parent task queue.
FROZEN READ-ONLY CONTRACT — no write-gate toggle, no mutation parameters. Never calls taskctl done/review/start/auto-pickup/add-card. Never mutates queue or audit state. Never launches agents or processes. Writes remain default-off regardless of input values.
Inputs: task_ids, batch_label. Returns: object
aiworkhub_task_codex_handoff_markdownARead-only
READ-ONLY: Codex-ready HANDOFF report rendered as compact Markdown.
Builds the same B116 handoff report as aiworkhub_task_codex_handoff (via
the identical read-only review-queue + show calls, never a write
command) and adds a deterministic markdown field — a compact review
packet Codex can read directly instead of manually parsing the JSON.
FROZEN READ-ONLY CONTRACT — no write-gate toggle, no mutation parameters. Never calls taskctl done/review/start/auto-pickup/add-card. Never mutates queue or audit state. Never launches agents or processes. Writes remain default-off regardless of input values.
Inputs: task_ids, batch_label. Returns: object
aiworkhub_task_collision_guardCRead-only
Run the task collision guard for active cards.
Inputs: print_json. Returns: object
aiworkhub_task_cost_ledgerARead-only
READ-ONLY: bounded cost summary, with opt-in detailed dimensions.
Default mode retains cost/cache truth plus provider, model and day
aggregates, and stays bounded as usage history grows. by_model,
cost_per_accepted_outcome.routes and model_outcomes.models
each return at most _COST_LEDGER_SUMMARY_TOP_N rows. by_day
is bounded as two independent groups -- up to
_COST_LEDGER_SUMMARY_TOP_N most-recent dated buckets beside up to
_COST_LEDGER_SUMMARY_TOP_N undated ones -- so its exact ceiling is
2 * _COST_LEDGER_SUMMARY_TOP_N rows, not N; undated spend is
retained rather than made to compete with real days for one shared
bound. Every bounded dimension carries explicit total_count/
returned_count/truncated/ranked_by metadata under
summary_row_bounds, so no row is dropped silently. The two
model-keyed dimensions rank by observed dollars rather than tokens; a
bucket whose provider reported no price ranks on its activity instead
of being cut as though it were free, and a partially priced bucket
ranks in both orders so one cheap priced record cannot hide the
magnitude whose dollars are still unknown. Per-runner and per-topic
maps are available with full=true; task rows remain independently
opt-in through include_tasks.
Kept rows are also narrower than full=true. Each kept model's
cost_per_accepted_outcome.routes adapter folds its family/risk
partitions into one total row, re-derived from summed counters so an
UNKNOWN partition keeps it UNKNOWN; the fold is receipted under
summary_row_bounds. by_day rows keep records,
total_tokens, cost_usd, cost_unknown_records and
cache_hit_ratio. full=true returns both exactly as built.
The repository binding is what makes those aggregates answerable.
build_cost_ledger reads canonical usage events only when it is given a
root; without one it parses the human-readable usage report, whose lines
carry no model, provider or timestamp, so every dimension this docstring
promises collapsed to unknown. Measured 2026-09-02 on this repository:
unbound 590 rows / 1 model / 1 provider / 1 day / 0 usage-observed / 0
cache-observed / 0 routes; bound 3,509 rows / 28 models / 8 providers / 36
days / 2,267 usage-observed / 1,869 cache-observed / 13 routes. Every
other caller (dashboard, manager tools, evidence instruments) already
passed a root; this tool -- the manager's own cost surface -- did not, so
routing by cost and difficulty had no measurement to steer by
(NF-2026-00542).
Inputs: full, topic, runner, status, +1 more. Returns: object
aiworkhub_task_createA
MANAGER WRITE: create one new canonical repo-local task card.
Creation choices (also exposed as field hints): difficulty: bounded, standard, complex (optional; never inferred). work_kind: generic, bugfix, refactor, performance, security, data_ml. validation_roles: generic, reproduction, regression, parity, baseline, delta, negative_fixture, schema, distribution, suite_vs_base; one per validation command. suite_vs_base: a pytest command that passes when every failing test also fails on the candidate's base. Required roles: bugfix=reproduction+regression; refactor=parity; performance=baseline+delta; security=negative_fixture; data_ml=schema+distribution. validation: shell-free executable commands; no environment assignments, pipes, redirects or chaining. Set environment outside validation argv. custom_template_escape: audited_custom_unclassified, explicitly audited unclassified cards only, not an automatic bypass; writable escaped cards require non-empty required_outputs covered by allowed_writes.
Replies with a creation receipt (aiworkhub.task_create_receipt.v1):
task_id, created/reconciled/receipt_state, scope_warnings, the
server-derived validation_roles, risk_tier/origin/signals,
difficulty/origin, validation_exemption, template_provenance, the
project_context
Source Graph query, and card_sha256/card_bytes -- never the card the
caller just typed. echo_card=True returns the full CLI envelope with
the persisted card in stdout instead. A refusal names every
violation at once (violations) with field, length and limit.
The live manager session supplies callback provider/origin identity;
callers cannot route a task into another chat, disable the mandatory
review callback, or overwrite an existing id.
depends_on (optional) names other task_ids in this repo that must
finish before this card is Plan-DAG ready; omit it for the pre-DAG
behavior.
Tasks are uncapped by default. Never infer, estimate, or auto-assign
max_live_tokens from task complexity, model, historical usage, or
cost. Supply it only when the owner explicitly requests an exact cap or a
repository policy pre-registers one. Process efficiency must come from
focused context, bounded reads, minimal edits, fewer retries, and useful
validation rather than from truncating work. An authorized cap is enforced
only when the selected provider exposes structured usage while running;
terminal-only usage remains posthoc evidence, never a false live-
enforcement claim.
A writable task's required_outputs may be empty ONLY when template
classification matches a contract that declares that default itself
(e.g. implementation_with_tests/cross_boundary_bugfix, whose
combined production+test scope keeps a deliberate empty default per
NF-2026-00456) or an explicit, in-scope mandatory list resolves that way.
Every other writable outcome -- including the audited custom-escape path,
which has no template contract of its own to fall back on -- requires a
non-empty required_outputs (NF-2026-00772); it contains only
repo-relative file paths or glob patterns covered by allowed_writes.
Human-readable outcome descriptions belong in acceptance; mixing
prose into required_outputs is rejected before a provider run is
launched.
allow_unchanged_required_outputs explicitly names required files that
are evidence inputs/outputs permitted to remain byte-identical to both
launch baselines; they are verified and hashed but never promoted.
allow_empty_required_outputs is the equivalent explicit exception for
deliberately zero-byte outputs. Neither exception is inferred.
read_only=True is required for a task that intentionally declares
both allowed_writes=[] and required_outputs=[]. Read-only intent is
never inferred from missing output authority.
runner is the worker execution identity returned by
aiworkhub_manager_workforce_rank.launch_contract.runner. The exact
value codex is reserved for the verified manager and is rejected for
worker cards.
work_kind is an explicit behavioral contract, never inferred from the
title or worker prose. Specialized values require one validation_roles
entry per validation command: bugfix=reproduction+regression,
refactor=parity, performance=baseline+delta, security=negative_fixture,
and data_ml=schema+distribution. Missing roles are rejected before launch.
suite_vs_base: a pytest command that passes when every failing test also
fails on the candidate's base.
risk_tier is optional explicit routing/economic evidence. It is never
inferred from priority or prose; omitted historical cards remain unknown.
It is a FLOOR: the observed write scope may escalate it, never lower it.
The skill_* fields are the card's skill selection vocabulary, drawn
from closed sets (aiworkhub_manager_skill_mine and
skill_registry.SELECTION_VOCABULARIES name them). An unknown token is
refused at create rather than silently matching nothing.
skill_task_family and skill_path_scope are derivable from the
template and the write set and may be omitted; skill_stage,
skill_triggers and skill_applicability are not derivable, and a
card that omits them selects no skill at all.
Default creation is template-first: generic Python production-plus-test
cards classify against the frozen registry, and unclassified raw cards
fail closed unless custom_template_escape is the audited token.
wave_goal_binding (optional) is exactly {roadmap_id, goal_id, predecessor_task_id} and makes this card that active wave goal's current
task in place of the predecessor. It is never inferred from a title,
topic, version suffix or prose; the receipt names its state.
Inputs: title (required), topic (required), runner (required), task_id (required), +35 more. Returns: object
aiworkhub_task_create_from_templateA
MANAGER WRITE: create one task from an authenticated template.
Replies with the same creation receipt as aiworkhub_task_create
(template_provenance once, from the persisted card); echo_card=True
returns the full CLI envelope with the card in stdout.
Callers supply routing fields, task text/acceptance, a template ID, and
explicit production/test paths. Generated allowed_writes,
required_outputs, read_first, read_only, task_type,
work_kind are taken from template expansion. Validation commands and
their one-to-one roles may be overridden together; when both are omitted,
the generated defaults are preserved. Malformed, stale, or forged template
IDs, unsafe paths, and incomplete validation overrides fail closed before
create_task. Provenance authenticates the final expanded contract.
The skill_* fields are the card's skill selection vocabulary, drawn
from the same closed sets core.create_task validates against
(skill_registry.SELECTION_VOCABULARIES); an unknown token is refused
at create rather than silently matching nothing. They are card fields,
not path fields: they never enter allowed_writes or
required_outputs, so declaring one can never make an output
mandatory. skill_task_family defaults to the family the template
itself declares (task_templates.skill_task_family of its declared
work kind), and an explicit value overrides that default;
skill_stage, skill_triggers and skill_applicability describe
the occasion rather than the template genre, so no template can supply
them and a card that omits them selects no skill at all.
wave_goal_binding (optional) is exactly {roadmap_id, goal_id, predecessor_task_id} and is forwarded to core.create_task unchanged,
exactly as aiworkhub_task_create does; it is never inferred from the
template, title or prose, and core refuses a malformed binding.
difficulty (optional) is bounded, standard or complex and
is forwarded to core.create_task unchanged; core alone validates it.
It only selects the worker's reasoning effort and is never inferred from
the template, title or prose: omitted means undeclared.
Inputs: title (required), topic (required), runner (required), task_id (required), +24 more. Returns: object
aiworkhub_task_dependency_autolaunch_reconcileB
MANAGER WRITE: bounded startup reconciliation for dependency-ready children.
Inputs: capacity. Returns: object
aiworkhub_task_healthARead-only
Check parent AIWorkHub task queue health and write-gate state. Use for the task queue and write gate only; use aiworkhub_doctor_diagnose for a cross-subsystem verdict.
Inputs: no named parameters. Returns: object
aiworkhub_task_listARead-only
List task cards by status and optional topic.
Use this for a flat card list by status; use aiworkhub_task_show for one card in full or aiworkhub_task_plan_snapshot for the dependency DAG.
Inputs: limit, topic, status. Returns: object
aiworkhub_task_plan_snapshotARead-only
READ-ONLY: bounded Plan-DAG summary, or the complete DAG with full.
Use this for the dependency DAG across cards; use aiworkhub_task_list for a flat card list by status.
Default mode reports actionable lifecycle, ready work, blockers,
write-scope overlaps, orphaned processing and DAG validity without
repeating every finished card's dependency history. Use full=true
for exact historical dependency/layer inspection. This tool never claims
work; the write-gated claim tool and its read-only preview remain the
claim surfaces.
Inputs: full. Returns: object
aiworkhub_task_recover_blocked_reworkB
Recover one exact blocked task through the canonical transaction.
scope_rejection_resolved is the manager's explicit, audited clean-root
resolution of a scope_rejected card; it requires feedback_reason.
A feedback_reason over 8000 UTF-8 bytes is refused with
feedback_reason_too_large:<bytes>><cap>; it is never truncated.
When the core result's stdout parses to a card dict the reply is the
shared _lifecycle_receipt projection
(aiworkhub.recover_blocked_rework_receipt.v1, include_card="none"):
task_id/status/worker_status plus card_sha256/card_bytes from the
canonical _card_identity (the same basis as aiworkhub_task_show),
the card's runner/recovery_epoch/recovery_predecessor when present, a
detail_request for aiworkhub_task_show, and every extra top-level
key the core call attached -- never the whole recovered card
(NF-2026-01566). command is never echoed: its argv carries
feedback_reason (up to 8000 bytes). A not-ok or card-less result is
returned unchanged minus the argv echo, so error text is never hidden.
Inputs: task_id (required), feedback_reason, validation_amendment, validation_only_replay, +5 more. Returns: object
aiworkhub_task_reject_reviewA
Write-gated Codex action: reject a reviewed task with exact feedback and
an explicit disposition. to = pending (rework, default) | blocked |
archived | superseded -- so a task whose real next step is a dependency-
gated replacement is not silently requeued to pending.
predecessor_request_id selects an exact retained review request as
the rework workspace authority. Omitted (None) defaults to the current
review request. An empty string fails closed.
failure_category is a verified-manager escape hatch for a mechanical
review failure. It is accepted only with to=blocked and only from the
closed infrastructure taxonomy, so it cannot relabel candidate code.
allowed_writes_amendment (a list of repo-relative paths) widens the
card's allowed_writes add-only and is accepted only with to=pending.
read_first_amendment (a list of existing repo files, each optionally
suffixed :N or :N-M) appends to the card's read_first add-only
and is accepted only with to=pending.
reason is capped at 8000 UTF-8 bytes after strip; over it the call is
refused with reject_reason_too_large:<bytes>><cap> and nothing changes.
Replies with a receipt (aiworkhub.reject_review_receipt.v1): task_id,
to, status, request_id, claim_epoch, prior_episode, failure_category,
reason_identity (sha256 + bytes, never the text), predecessor changed-path
and residual counts, rework_delta_recovery, reviewer_finalization,
learning_commit_owed, card_sha256/card_bytes. The reason and the argv are
never echoed; include_card = none (default) | summary | full.
A base_drift or validation_environment reject also starts one provider-free
replay of the retained candidate and adds automatic_validation_replay
{attempted, succeeded, reason, request_id}; a replay that cannot start
leaves the reject and the card as they were, and no other reject has the key.
A validation_environment replay runs at most once per candidate and failure
signature: a repeat is skipped with attempted false and reason
environment_failure_repeated:validation_environment. After the replay
the receipt's status/worker_status/card identity are re-read from the live
card (the same view as aiworkhub_task_show); the status the reject itself
left is kept under status_at_reject when it differs.
lesson_candidate / no_new_lesson_reason -- both unset by default, and
the reply is then exactly as before -- close this decision's learning out in
the same call, AFTER the reject landed. lesson_candidate (with optional
promote_ai_memory and extra_evidence_ids) runs
aiworkhub_manager_learning_commit for the rejected request and returns
its reply under learning_commit; no_new_lesson_reason (one of
learning_commit_store.NO_NEW_LESSON_REASONS) records that disposition and
returns it under learning_disposition. Both together
(learning_inline_conflict), an unknown reason, or promote_ai_memory
without a lesson are refused before anything changes. A failed close-out
never undoes the reject: ok stays true, the failure is reported under
its own key, and learning_commit_owed stays in the reply. None of these
parameters reaches the core rejection call.
relaunch (default false, and the reply is then unchanged) launches the
card's retry after the reject landed and returns the launch reply under
relaunch. A failed or raising launch never undoes the reject: ok
stays true and the failure is reported under relaunch.
Inputs: reason (required), task_id (required), to, relaunch, +15 more. Returns: object
aiworkhub_task_reroute_launch_identityA
COORDINATOR WRITE: explicitly reroute one pending retry launch identity.
Replies with a receipt (aiworkhub.reroute_launch_identity_receipt.v1):
task_id, status, worker_status, card_sha256/card_bytes, and every
server-derived key the reroute attached (from_runner, to_runner, to_model,
refusal and authorization receipts). The whole post-reroute card measured
55,156 chars (NF-2026-00500); include_card = none (default) | summary |
full brings it back.
Inputs: task_id (required), to_model (required), to_runner (required), from_runner (required), +4 more. Returns: object
aiworkhub_task_retry_terminalA
COORDINATOR WRITE: retry one exact operational terminal episode.
Only blocked cancelled/timed-out/launch/worker/process/liveness failures are eligible. The exact prior request id and substatus are mandatory; semantic validation/review failures remain on their established review workflow. The same task ID is requeued and its append-only audit history is preserved.
Replies with a receipt (aiworkhub.retry_terminal_receipt.v1): task_id,
status, worker_status, card_sha256/card_bytes, and every server-derived
key the transition attached -- retried_request_id,
terminal_substatus, request_linkage, workspace_retention,
idempotent. One measured call echoed the whole requeued card at 67,395
chars, review_feedback and rework_predecessor included (NF-2026-01447);
include_card = none (default) | summary | full brings it back.
Inputs: task_id (required), request_id (required), terminal_substatus (required), reason, +1 more. Returns: object
aiworkhub_task_review_queueARead-only
List tasks waiting for Codex review.
Use this for the bare list of review-queue cards; use aiworkhub_review_packet for one candidate's full review evidence or aiworkhub_completion_inbox for the queue together with failures and stale work.
Inputs: no named parameters. Returns: object
aiworkhub_task_review_summarizeARead-only
READ-ONLY: Inspect review queue, group tasks by topic/runner, return Codex review checklist.
Use this for a topic/runner-grouped review checklist; use aiworkhub_task_codex_handoff for per-task risks and finalize commands.
Calls the B110 review_summarizer core (read-only contract). Returns grouped tasks, validation commands, allowed_writes counts, and a Codex-ready review checklist shape.
FROZEN INPUT SCHEMA — no write-gate toggle, no mutation parameters. Never calls taskctl done/review/start/auto-pickup/add-card. Never mutates queue or audit state. Never launches agents or model processes. Writes remain default-off regardless of input values.
Inputs: task_ids, batch_label. Returns: object
aiworkhub_task_showARead-only
Show a single task card by task_id.
Use this for one card by task_id; use aiworkhub_task_list to find cards or aiworkhub_agent_task_status for a launched request's live state.
detail="brief" (default) keeps the card's lifecycle facts only (status,
substatus, title, runner, topic, current/last request ids and the
terminal_review verdict and blocker) plus the identity fields. Measured over
21 days the former summary default averaged 11,255 B/call (424 calls, 96%
the stdout card string). A red card still returns its validation_failed_packet.
detail="summary": retained baseline hash maps (tree, workspace and
parent baselines) are folded to entry count plus sha256, and the evidence
blobs (terminal_review.evidence.{validation, quality_gate, quality_review,
quality_review_receipt, worker_mcp_gate, workspace} and
accept_evidence.{validation, quality_gate}) are folded to
{summarized, bytes, sha256, verdict/status, failed_count, first_failure}.
terminal_failure and rework_predecessor are folded to the facts a
reviewer reads (substatus/reason/category/first_error and
task_id/request_id/outcome/reason); template_provenance.expanded_contract
is folded to identity only. detail="evidence" keeps all of the above
exact (baselines still folded); detail="full" or full=True returns
the exact stored card. Summary/evidence renders are compact JSON; full
keeps the indented one.
The manager-authored bodies (review_feedback, recovery_feedback,
history) fold to identity plus their counts in the summary render, and
every summary/evidence reply carries card_sha256/card_bytes plus
review_findings_count when the card records reviewer reports: measured
avg 11.5 KB/call over 31 calls (NF-2026-01447).
detail="evidence" is bounded (NF-2026-02256): when the card's compact
JSON exceeds evidence_paging.EVIDENCE_PAGE_CAP_BYTES (64 KB) stdout
holds the leading card keys that fit and the reply carries
evidence_truncated, evidence_total_bytes, evidence_sha256 and
continuation_cursor; pass that cursor back to read the next page. A
cursor for a card that changed since refuses with evidence_cursor_stale.
Inputs: task_id (required), full, cursor, detail. Returns: object
aiworkhub_task_stale_recovery_recommendARead-only
READ-ONLY: recommend recovery actions for stale processing tasks or blocked cards.
scope="processing" (default) covers stale processing tasks. scope="blocked"
triages the blocked-card queue: one recommendation per card, limit bounds the
cards read (see bounds.truncated) and sample the rows listed per group.
Produces recommendations only. It never calls taskctl write commands and
never kills a process.
Inputs: limit, scope, topic, sample. Returns: object
aiworkhub_task_supersedeA
COORDINATOR WRITE: supersede a stale/active task with a replacement.
Archives the card as superseded (allowed even from processing) and
records the optional replacement task id via by. Full coordinator-
capability gate; atomic; no direct SQLite patching.
Replies with a receipt (aiworkhub.task_supersede_receipt.v1): task_id,
status, card_sha256/card_bytes plus any server-derived keys the core call
attached. include_card = none (default) | summary (baselines and
evidence folded) | full (the exact post-transition card).
Inputs: task_id (required), by, reason, include_card, +1 more. Returns: object
aiworkhub_task_template_listARead-only
MANAGER READ: list the bounded repository-bound template registry.
The seven built-ins are followed by one extra custom_validation entry
(language_neutral, validation_source="caller") for repositories
in any language, e.g. C++ with MSBuild and CTest commands.
Inputs: no named parameters. Returns: object
aiworkhub_task_template_showARead-only
MANAGER READ: show one exact short or full template ID, fail closed.
Inputs: template_id (required). Returns: object
aiworkhub_task_usage_reportARead-only
Return task usage report, optionally filtered.
full=True returns the core usage-report payload exactly as
before. The default keeps every other top-level key verbatim
(schema_id, record_count, *_observed_records,
*_unknown_records, ...) and replaces stdout with a bounded
summary: a header line, one line per runner (records, observed
total_tokens sum, observed cost_usd sum, usage-unknown count) and then
the top 20 records by observed total_tokens in the existing pipe
format, beside detail_omitted (fingerprint of the full stdout) and
a detail_request naming the full call (NF-2026-01830). Error and
no-records results pass through untouched.
Inputs: full, topic, runner, status. Returns: object
needfix_addA
Manager-authority add of a NeedFix (dedupe-aware).
kind must be one of: bug, feature, improvement, idea, technical_debt,
optimization, benchmark_gap, documentation_drift, security_risk,
investigation, roadmap_candidate, refactor, security, docs, other.
Common synonyms are normalised server-side and reported as
kind_normalized: gap->improvement, defect->bug,
performance->optimization, design->refactor, dead_code->technical_debt,
test_coverage->improvement.
severity must be one of: critical, high, medium, low, info.
status defaults to captured; its authoritative choices are published
in the field hint. Store lifecycle and manager authority still govern it.
Replies with a receipt (aiworkhub.needfix_add_receipt.v1): id,
dedupe_key, status, kind, severity, created_at, provenance.origin,
deduped with existing_id when the dedupe key matched a live row
(the existing row is returned, nothing new is written), kind_normalized.
The row itself is one needfix_show away.
Inputs: title (required), description (required), kind, tags, +10 more.
needfix_archiveAIdempotent
Explicitly archive (soft, audited, restorable) a NeedFix.
Use this to retire a NeedFix from the active inbox; use needfix_restore to bring an archived one back or needfix_update to edit its fields instead.
Inputs: needfix_id (required), reason.
needfix_convertA
Convert an accepted NeedFix into a task card; task_plan alone commits in one call.
With task_plan and no plan_digest this previews the plan and, only when
the preview is convertible with no input refusal, commits it with the digest
that preview returned, in the same call. A captured or triaged NeedFix whose
task_plan names non-empty allowed_writes is auto-promoted to accepted (reason
auto_promoted_by_convert) first. Any refusal returns the preview and commits
nothing. plan_digest alone also commits the exact plan its preview signed;
a digest this server no longer holds is refused with previewed_plan_unavailable.
The digest re-check is unchanged, so NeedFix drift still fails closed.
Inputs: needfix_id (required), task_plan, plan_digest, include_plan.
needfix_countARead-only
Bounded count of NeedFix entries.
Use this for a single number; use needfix_list for the matching rows themselves. With breakdown=true the reply is {count, by_work_state, by_status, derived, underived_reason}: count is the same number, and the two maps split the same candidate rows by work state (untriaged, decided_no_card, in_work, stalled, reopened, deferred, closed) and by status.
Inputs: kind, status, severity, breakdown. Returns: result
needfix_eventsARead-only
List events for a NeedFix entry.
Use this for one NeedFix's audit history; use needfix_show for its current fields.
Inputs: needfix_id (required), limit. Returns: result
needfix_link_existing_taskA
Manager-only: atomically link a NeedFix to an existing, finished, accepted task.
Inputs: needfix_id (required), existing_task_id (required), integrated_commit.
needfix_listARead-only
List repo-scoped NeedFix entries (bounded); rows are a compact projection.
Measured: 379 rows were 452 KB, about 1.2 KB each (NF-2026-01722, NF-2026-01726). By default each row keeps only id, title, status, severity, kind, converted_task_id and updated_at; full=true or needfix_show returns the full row, which on the derived listing also carries work_state and linked_card_id/linked_card_status.
Inputs: full, kind, limit, query, +6 more. Returns: result
needfix_preview_convertA
Preview an explicit workforce-bound task conversion.
The reply keeps plan_digest, plan_digest_accepted_alone and
validation_roles_requirement -- the three facts the commit decision
actually turns on -- and folds the signed plan body to its identity plus
title/runner/topic/work_kind and the allowed_writes and required_outputs
counts. include_plan=true returns the plan verbatim. Measured
2026-10-09 on NF-2026-01452: ~6 KB of plan echoed three times, because
convert then refused plan_digest alone (NF-2026-01447). It no longer
does, so the previewed plan never has to be resent.
Inputs: needfix_id (required), task_plan, include_plan.
needfix_reopen_superseded_task_linkAIdempotent
Manager-only: reopen a NeedFix whose exact linked task was superseded.
Inputs: reason (required), needfix_id (required).
needfix_restoreAIdempotent
Explicitly restore an archived NeedFix.
Use this to bring an archived NeedFix back into the inbox; use needfix_archive to retire an active one.
Inputs: needfix_id (required), target_status.
needfix_showARead-only
Show one NeedFix by id, or up to 25 in one call; a body over 1 KB folds to its own identity.
Use this for the current fields of one NeedFix, or pass needfix_ids to read several in one call; use needfix_list to find ids or needfix_events for its audit history.
Measured 2026-10-09: 51 calls, avg 4 KB, max 12 KB, almost all of it the
description and evidence bodies the filer wrote (NF-2026-01447). Each body
whose own canonical bytes exceed core.NEEDFIX_BODY_MAX_BYTES is
replaced by {summarized, bytes, length, sha256} so it stays
addressable; a smaller body is returned verbatim and full=true returns
every byte. With needfix_ids the reply is {items, count} in input
order, each row folded the same way; an unknown id is its own row with
ok: false and error and never fails the others.
Inputs: full, needfix_id, needfix_ids.
needfix_updateAIdempotent
Manager update of mutable NeedFix fields.
None keeps a field. evidence is an explicit FULL REPLACE of the
evidence object; evidence_patch is a JSON merge patch (keys merged,
nested objects merged, null deletes a key) applied server-side to the
stored object, so one measurement can be added without re-sending the
rest. The two are mutually exclusive. evidence_refs_add/remove,
tags_add/remove, scope_files_add and scope_symbols_add edit
the lists in place (add appends missing values, remove filters).
expected_updated_at is optimistic concurrency: the update is refused
(needfix_update_stale) when the stored updated_at differs.
kind vocabulary and synonym normalisation are as in needfix_add.
Replies with a delta receipt (aiworkhub.needfix_update_receipt.v1):
id, status, fields_changed, updated_at, evidence_keys_after, event_id,
kind_normalized. The updated audit event records the same
fields_changed plus the evidence sha256 before and after.
Inputs: needfix_id (required), kind, tags, scope, +16 more.
roadmap_addA
Manager-only Roadmap proposal; does not create or launch a task.
Inputs: title (required), outcome (required), priority, milestone, +5 more.
roadmap_link_taskA
Link one existing canonical task to a Roadmap outcome.
Use this to attach a task to an outcome; use roadmap_transition to change the outcome's status.
Inputs: task_id (required), roadmap_id (required).
roadmap_listARead-only
List bounded repository Roadmap outcomes; outcome and acceptance bodies fold to their identity.
Measured: the same rows roadmap_snapshot(limit=60) returned were 174 KB, 61% outcome and acceptance bodies (NF-2026-01726). By default both fold to {summarized, bytes, length, sha256}; full=true or roadmap_show gives the full row.
Inputs: full, limit, query, offset, +2 more. Returns: result
roadmap_showARead-only
Show one Roadmap outcome.
Use this for one outcome's stored fields by id; use roadmap_list to find ids or roadmap_snapshot for every outcome joined to its linked tasks.
Inputs: roadmap_id (required).
roadmap_snapshotARead-only
Return the Roadmap with each outcome joined to the live status of its linked tasks.
Measured: limit=60 replied 174 KB, 61% of it the outcome and acceptance bodies (NF-2026-01726). By default each row's outcome and acceptance fold to {summarized, bytes, length, sha256}; full=true or roadmap_show gives the full row.
Use this to see what is done, blocked or ready across the roadmap in one call. The
other roadmap tools return stored fields only: roadmap_list the outcome rows,
roadmap_show one outcome with its stored fields. Read-only.
The reply is aiworkhub.roadmap_snapshot.v1: total and active outcome
counts, status_counts, items (up to limit outcome rows) and truncated.
Each row is the stored outcome plus tasks (task id and live status, or missing
/ purged:<status> once the task record is gone), linked_total, accepted
(finished tasks), unresolved (the rest), dependency_blockers and
dependency_ready.
Inputs: full, limit, include_archived.
roadmap_transitionA
Manager-only guarded Roadmap lifecycle transition.
Use this to change an outcome's status; use roadmap_link_task to attach a task without changing status.
Inputs: reason (required), roadmap_id (required), target_status (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 117 tools
Many tools carry explicit routing prose ('use X for..., use Y for...'), which genuinely helps separate lookalikes such as task_show vs agent_task_status vs supervisor_loop_status and task_list vs review_queue vs plan_snapshot. But the set still has real overlap clusters: completion_inbox vs dashboard_snapshot vs task_review_queue, codex_handoff vs codex_handoff_markdown vs review_summarize, needfix_archive vs dashboard_needfix_transition vs needfix_update, and needfix_add vs manager_needfix_draft. At 117 tools the reader must hold a large disambiguation graph in working memory even though each individual pair is documented.
The dominant style is snake_case, and the manager_* family (manager_kb_get/search/related, manager_recipe_list/show/run) is internally consistent. However the set mixes an aiworkhub_ prefix on most tools with unprefixed needfix_* and roadmap_* families, and mixes verb_noun names (task_create, needfix_archive) with bare noun names (review_packet, completion_inbox, dashboard_snapshot, task_health, task_collision_guard, task_review_queue). It is readable but not predictable from name alone.
The platform genuinely spans many subsystems (task lifecycle, review, NeedFix, roadmap, skills, recipes, KB/memory/context graph, source graph, dispatcher, storage), so a large surface is partly earned. Still, 117 tools is far past what an agent can reliably select from, and several near-duplicate or facet-of-a-larger-tool entries (needfix_count, codex_handoff_markdown, dashboard_snapshot) look like candidates for folding into callers that already exist. This is over-scoped for reliable tool choice even if few tools are individually trivial.
Coverage is unusually thorough: create/amend/list/show/archive/supersede/supersede-recover/retry/reroute for cards, full review evidence plus accept/preview/reject/finding-dispose/hold-resolve, and complete lifecycle sets for NeedFix (add/update/archive/restore/convert/events/count), roadmap, skills, recipes, KB, AI memory and context graph. Preview/commit/status/health/diagnose/doctor companion tools mean few workflows dead-end, and read-only previews exist alongside every gated write. No material gap is apparent for the stated orchestration purpose.
Maintenance
Related MCP Connectors
MCP Server for an Agent Task Marketplace
Agent Delegation MCP Server by MEOK AI Labs
MCP server for Pinchwork - an agent-to-agent task marketplace with credits-based economy
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAgent Negotiation - MCP server providing AI-powered tools and automation by MEOK AI Labs9 npm139 PyPIMIT
- AlicenseNot gradedqualityCmaintenanceAgent Delegation - MCP server providing AI-powered tools and automation by MEOK AI Labs6 npm125 PyPIMIT
- AlicenseNot gradedqualityFmaintenanceEnables AI agents to communicate, coordinate, and collaborate on complex tasks through a local MCP server.5 npm8ISC
- FlicenseNot gradedqualityDmaintenanceMulti-agent coordination MCP server using RPG raid mechanics for task assignment, context management, and knowledge persistence.1-