Skip to main content

kind: Project

What it is

kind: Project is the declarative representation of a Crewship project — the workspace-scoped container that groups missions, tracks delivery health, and assigns a lead agent. Use it in a manifest when you want crewship apply to create new projects, keep an existing roadmap aligned with version-controlled YAML, or round-trip workspace state through crewship export for backup and migration. One YAML document maps to exactly one row in the projects table.

YAML schema

Every field except apiVersion, kind, metadata.name, and metadata.slug is optional. Empty fields are treated as “leave server-side default in place” — they do not overwrite values an operator changed via the UI.

Examples

Minimal — slug + name only

crewship apply creates the project with server defaults: color=blue, status=backlog, priority=none, health=on_track.

Realistic — all common fields

Cross-kind FK — Milestone referencing a Project

The Apply pipeline runs Projects (Phase 3) before Milestones (Phase 5), so the slug resolves cleanly even on a from-scratch deploy.

CLI reference

The existing crewship project ... subcommands cover ad-hoc admin tasks; the manifest is the recommended path for repeatable deploys.

REST endpoint mapping

Endpoints touched:

Validation rules

  • apiVersion must equal crewship/v1.
  • kind must equal Project.
  • metadata.name is required and non-empty.
  • metadata.slug is required and non-empty.
  • spec.status, when set, must be one of planned, active, completed, archived.
  • spec.priority, when set, must be one of low, medium, high, urgent.
  • spec.health, when set, must be one of on_track, at_risk, off_track.
  • spec.color, when set, must match ^#[0-9A-Fa-f]{6}$.
  • spec.target_date, when set, must parse as YYYY-MM-DD.
  • spec.lead_agent_slug, when set, must reference an Agent present in either the declared manifest or the workspace’s existing agents.
Validation is executed before any HTTP call, so a malformed document fails fast without partial mutations.

Apply behavior

Default — ApplyUpsert

  1. Fetch GET /api/v1/projects and look up the slug client-side (the server has no ?slug= filter).
  2. If not found: emit Action=Create and POST /api/v1/projects with the full body.
  3. If found and identical: emit Action=Unchanged (no HTTP call).
  4. If found and drifted: emit Action=Update and PATCH /api/v1/projects/{id} with only the drifted fields. Fields the manifest leaves empty are skipped — they never overwrite a non-empty server value.

ApplyStrict

Same as Upsert except step (2) is the only allowed outcome. If a project with the same slug already exists, apply fails with already exists. Use this in CI for “expect-fresh-deploy” pipelines.

ApplyReplace

For every declared project that already exists remotely, emit Action=Delete (DELETE /api/v1/projects/{id}) before the Create. New projects skip the Delete and behave like Upsert. This mode also unlinks every mission whose project_id pointed at the old row, because the handler’s DELETE path wraps the operation in a transaction that nulls the FK.

Round-trip via export

crewship export workspace calls ExportProjects, which:
  1. Issues GET /api/v1/projects for every project in the workspace.
  2. Issues GET /api/v1/agents once and builds an id → slug map.
  3. Maps each row into a ProjectDocument:
    • Server columns id, workspace_id, created_at, updated_at, issue_count, done_count, progress, and icon are dropped (manifest doesn’t model server-managed state).
    • lead_type=agent + a known lead_id resolves back to spec.lead_agent_slug. User-leads (lead_type=user) and unknown agent ids are dropped silently — manifest only models agent leads.
    • Empty description / target_date collapse to omitted YAML keys via omitempty.
  4. Sorts the result by slug so repeated exports produce identical files (clean git diffs).
crewship export emits the project as a standalone YAML doc separated by --- from other kinds; --split-dir <dir> writes it as project-<slug>.yaml instead.

See also

  • Milestone — references projects via spec.project_slug.
  • RecurringIssue — pre-creates issues into a template.project_slug.
  • TriageRule — can route incoming issues into a project via actions.assign_to_project_slug.
  • SavedView — filters its result set by filter.project_slug.
  • SPEC-2 §1 Project (.claude/context/specs/SPEC-2-manifest-complete.md) — implementation contract.