Skip to content

Reconciling Lifecycle

Drift detection tells you the cloud and your source disagree. Reconciliation closes the gap. There are two directions, and chant exposes each as an Op composite. Which one you reach for — and whether you reach for either — is the dial, chosen per environment.

observe → reconcile → authoritative
(report) (cloud→code (code→cloud
PRs) apply)

When the live system is ahead of source — someone created or changed a resource by hand — pull reality back into source so declarations track it. ReconcileOp does this by opening a PR:

import { ReconcileOp } from "@intentius/chant-lexicon-temporal";
const { op, schedule } = ReconcileOp({
name: "prod-reconcile",
env: "prod",
schedule: "0 * * * *", // hourly, on Temporal
scope: { owned: true }, // only chant-owned resources
onDrift: "pull-request", // or "issue" | "report"
});
export default op; // the Op — discovered by `chant run prod-reconcile`
export { schedule }; // the TemporalSchedule — deployed by `chant build`

Phases: Snapshot → Plan → Reconcile, where the Reconcile phase’s reconcilePr activity regenerates source (live import) and opens the PR in one step. Run chant run prod-reconcile for a one-shot reconcile on the local executor; give it a schedule to run continuously on Temporal. The PR’s diff is the regenerated TypeScript, so review is a normal code review.

Reconcile never mutates the cloud. It only changes source — the safest reconciliation direction, and a good first step past pure observation.

When source is the intended truth and the cloud should follow, ApplyOp pushes declared source into the live system via the target’s native mechanism — kubectl apply, CloudFormation deploy, or an ARM deployment:

import { ApplyOp } from "@intentius/chant-lexicon-temporal";
const { op } = ApplyOp({
name: "prod-apply",
env: "prod",
target: "kubectl",
delete: "gated", // "never" | "owned-only" | "gated"
gate: { signalName: "approve-apply" },
});
export default op;

Authority stays with the platform — chant hosts no state file. Deletes ride the native delete path scoped to the ownership marker, so they only ever touch chant-owned orphans. A destructive apply gets an approval gate and saga-style rollback; see Gates and compensation for why that half is Temporal-bound.

The same project can sit at different positions per environment:

EnvironmentPositionWhat runs
devobservechant lifecycle diff --live in CI; no reconciliation
stagingreconcileReconcileOp opens PRs when staging drifts
prodauthoritativeApplyOp with delete: "gated" behind approval

Nothing forces an environment past the position you chose for it. Turn the dial up as trust and tooling allow.

  • Observe when the cloud is changed by other tools you don’t want to fight, and you just need visibility.
  • Reconcile when source should track reality and humans should review each adoption — the default for shared or partially-managed environments.
  • Apply when source is authoritative and you want the cloud reconciled to it, with deletes limited to what chant owns. Gate it in production.