sitectl compose up performs a command-scoped reconcile for local contexts owned by an installed plugin. The contract belongs to core sitectl, not to an individual app template.
The goal is a smooth first start for setup-only checkouts:
compose up can initialize missing files, build missing local images, and start the stack. A fresh sitectl create --setup-only may already run clone-time init; reconcile checks artifacts before deciding what is still needed. Later calls use a local cache unless the plugin create metadata or image override file changes. Cache entries expire after 7 days so long-lived local checkouts are rechecked periodically.
Flow
For local plugin-owned contexts, coresitectl compose up:
- Loads the active context and the plugin’s default create definition, or the first create definition when none is marked default.
- Checks the local reconcile cache. The cache key includes host, user, plugin, canonical project directory,
docker-compose.override.ymlfingerprint, and create spec fingerprint. Entries older than 7 days are ignored. - If there is no cache hit, inspects desired state:
- missing or empty
InitArtifactsmakeInitialized=False - missing
InitVolumesmakeInitialized=False - missing local images or build-arg overrides make
ImagesAvailable=False - when explicit metadata is absent, core falls back to
docker compose config --format jsonand checks file-backed secrets, named service volumes, and buildable services
- missing or empty
- Runs
DockerComposeInitwhen init is needed. - Runs
DockerComposeBuildwhen images are needed. - Runs
DockerComposeUp. - Marks the current host, user, project, override fingerprint, and create-spec fingerprint as checked after the commands succeed.
sitectl compose up inspects and retries instead of assuming the project is reconciled.
Operator Commands
Run reconcile directly when you want to inspect or repair the init/build/up workflow without relying on the automaticcompose up hook:
--force bypasses the cache and reruns build/up. It only reruns init when the declared init state is missing. --reset-init removes plugin-declared init artifacts and init volumes first, then runs reconcile.
Use sitectl compose clean when local runtime state should be destroyed:
clean runs docker compose down -v, removes plugin-declared init artifacts, and clears the reconcile cache entry. It requires typed confirmation because database volumes, uploaded files stored in named volumes, generated secrets, certificates, and declared env files can be lost.
Conditions
Reconcile status uses Kubernetes-style condition vocabulary for local facts:| Condition | Meaning |
|---|---|
Initialized | Required init files and volumes are present, or fallback Compose checks pass. |
ImagesAvailable | Required local images exist, no build policy requires a build, and build-arg overrides have been applied. |
Reconciled | No init or build work is needed for this project/spec/override state. |
True or False. ObservedGeneration records the create-spec fingerprint that was inspected.
Kubernetes Analogy Boundary
The vocabulary is deliberately familiar to contributors who have used Kubernetes controllers:- “reconcile” means compare desired metadata with observed local project state, then run the missing lifecycle steps
conditionsreport current facts rather than command historyObservedGenerationrecords which desired create-spec fingerprint was checked
sitectl compose up after a failure, but core does not provide a persistent controller that will eventually converge the project without another CLI invocation.
Plugin Authoring Contract
Create definitions that participate in reconcile should follow these rules:- Keep
DockerComposeInit,DockerComposeBuild, andDockerComposeUpidempotent enough to rerun after partial failure. - Make
InitArtifactsexplicit and deterministic. Prefer files such as.envand secret files over probing container state. - Use
ValueFrom: plugin.InitArtifactValueFromHostUIDwhen a generated marker file must match the local host user. - List named Compose volumes that prove first-start state in
InitVolumes. Core resolves the actual Docker volume name throughdocker compose config. - List locally built images in
Imageswith the Compose service name, image reference, and build policy. - Use
BuildPolicyIfNotPresentfor normal local images,BuildPolicyAlwaysonly when everycompose upshould rebuild, andBuildPolicyNeverfor images that should not trigger the build phase. - Avoid global mutable state in lifecycle commands. The same project path, create spec, and override file should produce the same result.
- Do not make init destructive. Existing application data must survive a repeated init command.
- Declare app services that require MariaDB with
depends_on: {mariadb: {condition: service_healthy}}so startup and healthcheck behavior match the template contract. - Keep plugin namespace commands app-specific. Shared lifecycle belongs to core
sitectl compose.
Image Overrides
Coresitectl image set writes docker-compose.override.yml for local contexts:
- an explicit image override for a service means core does not require the plugin’s default image to exist locally
- a build-arg override triggers the build phase so the new arguments are applied
- the override file fingerprint is part of the reconcile cache key
--image or --build-arg for app-specific services that are not known to the shared --tag map.
Use sitectl image clear [SERVICE...] to remove image/build-arg override keys while preserving unrelated local override content such as dev-mode bind mounts or port remaps.
