Projects and Tasks¶
A project is the scheduling and policy boundary around related work. New
projects are paused unless explicitly activated. Tasks can be staged separately
with --no-dispatch; the hold lives at metadata.no_dispatch=true and is
removed by task release.
This example creates an active project, stages one report task, proves that the task exists, then releases it for dispatch.
mac --db "$DOCS_DB" admin init
mac --db "$DOCS_DB" project create tutorial --active
task_id="$(mac --db "$DOCS_DB" --json task create \
"Summarize the tutorial" --project tutorial --kind report \
--no-dispatch --no-decompose | \
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
mac --db "$DOCS_DB" task show "$task_id" >/dev/null
mac --db "$DOCS_DB" task release "$task_id"
mac --db "$DOCS_DB" task ready --project tutorial --limit 10
From inside an existing checkout, the shortest repository-backed onboarding command is:
Pass . explicitly or provide another checkout path when useful:
Local registration reads the origin remote and prefers origin/HEAD for the
branch, falling back to the current branch. --branch overrides discovery.
Remote-first onboarding uses one branch-qualified registration string,
GIT_URL#BRANCH. The fragment defaults to main, so these are equivalent:
mac project register git@github.com:org/widget.git
mac project register git@github.com:org/widget.git#main
register creates the project record and its contract-authoring task. A second
registration for another branch is an internal project fork:
mac project register git@github.com:org/widget.git#release/next
# default project name: widget@release/next
The URL-and-branch pair is unique. The same URL may be registered again only
with a different branch. Once .mac/project.yaml exists in a hub-visible
checkout, register that checkout with mac admin bridge repository register.
The checkout attachment is an internal execution detail; the operator-facing
resource remains the project.
The CLI provides project CRUD:
mac project create manual-project
mac project list
mac project show widget
mac project update widget --branch release/next
mac project update widget --description "Release maintenance"
mac project unregister widget --force
The HTTP API exposes the same lifecycle:
POST /projects
POST /projects/register
GET /projects
GET /projects/{project}
PUT /projects/{project}
DELETE /projects/{project}?force=true
POST /projects/{project}/dispatch
POST /projects/register accepts the existing repository-onboarding body; put
the canonical string in repository_url. PUT /projects/{project} accepts
repository_registration or default_branch in addition to name,
description, metadata, and status.
Creating a task expresses intent; it does not grant an agent permission to work. The claim and lease in the next chapter provide that fence.
Before the first repository-task claim, the dispatcher records a bounded
scope_estimate. Broad work is marked plan_first while it is still unleased,
so sizing does not consume an execution attempt. Work-package nodes and
explicitly non-decomposable tasks retain their own admission policy.
Scheduling remains work-conserving but supports an optional
metadata.dispatch_class:
urgentandrecoveryrun ahead of ordinary backlog when a slot opens;normalis the default;backgroundyields to the other classes;metadata.due_atormetadata.deadline_atadds a small, bounded aging bonus after the time passes.
These are routing hints, not correctness gates. task show and the dispatch
explanation expose the resolved class and bonuses.
Retries are intentionally narrow. A transient worker or transport failure gets
one retry after a short backoff and excludes the worker that just failed. A
timeout gets the same single retry with plan_first=true. Deterministic
contract/work failures, and the same failure fingerprint seen twice, stop
instead of consuming the remaining attempt budget. Repeated shared
control-plane failures create one fingerprinted fleet incident rather than one
repair child per victim.
An exhausted environment attempt creates a separate recovery prerequisite only
when the task explicitly opts in with
metadata.repair_policy.environment_prerequisite=true and its history contains
a concrete output, preserved-work record, or explicit failure/remediation
diagnosis. Bare lease expiries with no telemetry fail visibly instead of
creating an unactionable repair task. Verification-contract failures stay with
the original task by default; a repository with a genuinely independent repair
workflow may opt in with
metadata.repair_policy.contract_prerequisite=true.