What's New
A hand-curated rollup of capabilities shipped recently. If you learned chant before this lands, this page is the catch-up. Each entry links to the closing issue or PR for the full context.
For the day-to-day reference docs see Lifecycle Models, chant lifecycle, Live Import, Reconciling Lifecycle, Drift Detection, and Implementing Observation.
Provisioned infrastructure diagrams
Section titled “Provisioned infrastructure diagrams”The newest thread. chant graph gained a live data source: chant graph --live --env <name> graphs the actually-provisioned infrastructure, not the declared source — nodes from each lexicon’s observation, edges reconstructed from the live references between resources (a subnet’s VPC, an ALB’s target group), and containment (VPC ⊃ subnet ⊃ resource) as boundary structure. --overlay classifies each resource against declared source — managed / foreign / pending — so the diagram shows drift. The companion painter, pinhole, renders the result as an AWS-style architecture diagram. AWS is enriched from the deployed CloudFormation template, so a managed AWS stack draws its real topology. Scope is managed-only (owned resources); a full-account scan is the natural next phase. See chant graph --live and Implementing Observation for the lexicon-author hooks.
| # | Capability |
|---|---|
| #777 | chant graph --live — project observed resources into IR nodes (physicalId + ownership) |
| #778 | Live edge reconstruction — a per-lexicon referenceCatalog (identities + reference/containment rules) + AWS catalog |
| #779 | Live containment grouping (byContainer) — VPC / subnet boundaries for the renderer |
| #784 | enrichLiveAttrs — real AWS edges by resolving the deployed CloudFormation template’s {Ref}/{Fn::GetAtt} to node ids |
| #780 | --overlay — declared-vs-provisioned drift (managed / foreign / pending) on the diagram |
| pinhole#74, pinhole#75 | pinhole architecture render (nested boundary boxes) + AWS icon pack |
Components & supply-chain attestations
Section titled “Components & supply-chain attestations”An earlier thread. The components release model — a deploy composed from a bounded set of capabilities, run by one generic orchestrator — gained supply-chain attestations: SBOM, SLSA provenance, and keyless signing attached to the artifact digest, with a verify gate that halts a deploy before apply. chant run --components runs a component’s deploy composition on the local executor by default. The dir/zip/jar SBOM path is hermetic — no external tool. See Supply-Chain Attestations.
| # | Capability |
|---|---|
| #606, #608 | SBOM generation + attach for build-producing components |
| #613, #615 | Native SPDX/CycloneDX BOM writer — hermetic lockfile SBOM (no external tool) + IaC config-BOM |
| #614, #619 | Per-artifact reproducibility/provenance + component BOM aggregation |
| #610, #620 | Real SbomGenerator (syft/buildx), ReferrerLookup (oras), publish-time referrer attach |
| #622, #624 | Keyless cosign signing + SLSA provenance + verify gate |
| #623, #625 | Supply-Chain Attestations — first-timer docs page |
| #628, #631 | vuln-gate correctness hardening |
| #629, #632 | Wire chant.config.ts sbom/signing/vulnPolicy into run --components |
| #630, #633 | Runnable examples/supply-chain + hermetic SBOM default |
| #634, #635 | Default vuln-gate/scan-vulnerabilities to a real auto-detecting scanner (grype → trivy) |
| #637, #638 | Apply chant.config defaults on the Temporal codegen path |
Pipeline context for agents
Section titled “Pipeline context for agents”chant now exposes what chant build already computes about a pipeline — its jobs and run order, what it pulls in from outside, its security findings, where each job came from — as a set of read-only MCP tools. They give an agent a before-it-runs view of a pipeline change, complementary to the after-it-ran view live tooling provides. Every tool builds from source and never touches a live instance, reads run history, or writes anything — that boundary is what keeps chant a context producer, not a copy of the live tooling. See Agent Integration for the full tool reference.
| # | Capability |
|---|---|
| #328, #331 | GitLab read-only context tools — gitlab:checks (WGL findings), gitlab:pipeline (stages/jobs/order), gitlab:references (includes/components/images + pinned?), gitlab:affected (needs chain), gitlab:pipeline-yaml |
| #333 | The parallel github:* set for Actions workflows — github:checks (GHA findings), github:workflow, github:references (actions/images + SHA-pinned?), github:affected, github:workflow-yaml |
| #334 | gitlab:source + gitlab:owns, on a new entity-level build-provenance side channel in core — trace a job back to its declaring file and composite; report whether a job is declared by chant here (declared-in-source, since pipeline jobs are not taggable cloud resources) |
| #335 | gitlab:compare — migrate a GitHub workflow to GitLab and report which security properties survive the edge (translated / approximated / needs-review / lost), reusing the security-fate model |
| #329, #332 | chant lifecycle plan --report gitlab-mr + the MrPlanReport composite — publish the plan as the GitLab merge-request plan widget (artifacts:reports:terraform); counts only (create/update/delete) |
| #336 | A Docker runtime E2E (just gitlab-runtime-e2e) that actually executes a chant-generated .gitlab-ci.yml via gitlab-ci-local — proves GitLab CI accepts and runs the output, not just that it is well-formed |
Forgejo lexicon (Codeberg / Forgejo / Gitea)
Section titled “Forgejo lexicon (Codeberg / Forgejo / Gitea)”A new lexicon for Forgejo Actions — the CI behind Codeberg, self-hosted Forgejo, and Gitea — built as a thin dialect of the github lexicon. Forgejo runs GitHub-Actions-compatible YAML, so you author exactly as for GitHub (same entities and composites, imported from @intentius/chant-lexicon-forgejo) and the dialect applies on build. The differentiated value is the github→forgejo compare: what the move silently costs.
| # | Capability |
|---|---|
| #339 | Serializer dialect — emits .forgejo/workflows/ (or .gitea/workflows/); drops keys the Forgejo runner ignores (permissions, continue-on-error) with build warnings; maps runner labels (ubuntu-latest → docker, override via forgejo.runnerLabels) |
| #340 | uses: action-ref resolver — Forgejo has no Marketplace, so common actions/* rewrite under forgejo.actionsRoot (default https://code.forgejo.org), docker/* pin to GitHub URLs, and unmapped refs are reported |
| #341 | chant migrate --to forgejo + the forgejo:compare MCP tool — a per-property security-fate report (translated / approximated / needs-review / lost) of what survives the move |
| #342 | Parity surface — the full forgejo:* read-only context tools, WFJ010/011 lint checks, init templates, a chant-forgejo skill, and a reference page |
CI/CD pipeline security audit
Section titled “CI/CD pipeline security audit”A workflow/pipeline security pass across the github and gitlab lexicons, split along chant’s architectural boundary: deterministic checks run in the pure build, live-resolution checks run in the operational layer. Both lexicons were abstracted to the same core problems — pin & vet external references, least-privilege tokens, trust boundaries against untrusted input, secret containment, unsound expressions, artifact/cache hygiene — so the GitHub → GitLab migration can map problem → problem and carry the security invariant across the edge.
| # | Capability |
|---|---|
| #296 | Epic: GitHub workflow security audit — GHA029–058 post-synth checks generalize SHA-pinning to every uses:/image:, flag over-broad token scopes, taint untrusted input into run:, contain secrets, reject unsound/obfuscated expressions, and enforce artifact/cache hygiene |
| #305 | Epic: GitLab pipeline security audit — WGL029–048, the same problems on GitLab primitives (includes/components, CI_JOB_TOKEN/id_tokens, masked/protected variables, rules:) |
| #292, #303 | WorkflowAuditOp / PipelineAuditOp — the live, always-fresh half: resolve pinned refs against moving upstreams (stale SHAs, impostor refs, advisories, archived projects), one-shot on the local executor or scheduled on Temporal, reporting via report / issue / pull-request (or merge-request) |
| #294 | Dependabot composite + resource — models .github/dependabot.yml so it’s emitted and lintable, with safe defaults (cooldown window, external code execution denied); checks GHA057/058 |
| #306 | Security-aware migration — a security-fate classification (Translated / Approximated / NeedsReview / Lost) on the migration provenance model, new MIG-* security rules, and a --validate security backend that runs the GitLab checks against migrated output |
| #293 | Fixed a duplicate lint ID — the post-synth “missing job-level permissions” check moved to GHA013, freeing GHA020 for the secret-detection rule |
Live import & the lifecycle dial
Section titled “Live import & the lifecycle dial”The follow-on to the observation thread: chant turned its single observational drift workflow into a full family — observe → reconcile → authoritative, chosen per environment. It gained live import (regenerate TypeScript from running cloud/cluster state) and projection + cloud-side ownership (a precise create/update/delete change set computed against live), without hosting an authoritative state file. The snapshot is never load-bearing — the projection reads ownership from the live resource only. Primitives need no executor; only gated/destructive Ops require Temporal.
| # | Capability |
|---|---|
| #113 | exportResources() on the LexiconPlugin contract — full-fidelity import IR from a live API, branded distinct from the scrubbed observation types so a secret-bearing export can never reach the lifecycle code paths |
| #114 | chant import --from <env> — live import driver with --type / --name / --owned / --verbatim selectors and a secrets warning |
| #115, #116, #117 | Live export for AWS (CloudFormation get-template), Kubernetes (kubectl get -o json, stripped to declared shape), and GCP Config Connector |
| #159 | Live export for Azure (az group export) — makes Azure a full live-import peer alongside AWS, GCP, and Kubernetes; --owned filtering via the chant-managed-by tag |
| #118 | chant lifecycle plan — typed ChangeSet (create / update / delete / adopt / noop) from the live diff; strictly read-only |
| #119 | Ownership marker contract + serializer stamping — provider-native marker (AWS/Azure tags, K8s/GCP labels) carrying stack identity, stamped at synthesis. Opt-in via ownership config; walk-away cost stays zero |
| #120 | owned filter on describe/export — query the marker live; marker present + undeclared → delete candidate, absent → foreign (adopt only); degrades to detect-only where no marker channel exists |
| #121 | Ownership-gated delete in the change set — delete only for owned orphans, read from the live marker, never from the snapshot |
| #122 | reconcilePr Op activity — regenerate drifted/orphaned entities and open a reviewable PR (modes: pull-request / issue / report); never commits to the main branch |
| #123 | ReconcileOp composite — the cloud → code workflow (snapshot → plan → reconcile); one-shot on the local executor, continuous on a Temporal cron |
| #124 | ApplyOp composite — the code → cloud workflow via native apply (kubectl apply / CloudFormation deploy / ARM); deletes ride the marker-scoped native prune, so they only ever touch owned orphans |
| #125 | Approval gates + compensation for destructive apply — durable wait-for-signal, saga-style onFailure rollback, crash-resume; where Temporal is load-bearing |
| #126–#131 | Docs: new Lifecycle Models (three-axis model + dial) and Durable Workflows concept pages; Live Import and Reconciling Lifecycle guides; Implementing Live Export authoring guide; governance/comparison revised to retire the “no plan” concession; cross-page tone audit |
Observation & drift detection
Section titled “Observation & drift detection”The biggest single thread. chant lifecycle diff went from a digest-vs-digest fingerprint check to a real live-vs-declared-vs-snapshot diff that catches out-of-band cloud mutations across nine lexicons.
| # | Capability |
|---|---|
| #26 | chant lifecycle diff <env> --live — three-way diff (declared / observed-now / observed-then), six resource categories (missing / orphan / disappeared / newly observed / drifted / unchanged) with attribute-level deltas |
| #27 | Temporal lexicon describeResources() — namespaces, search attributes, schedules |
| #39 | describeResources() contract gains entity-prop pass-through — lexicons now receive declared props (e.g. K8s metadata.name/namespace) and can map cloud-side identifiers back to chant entity names |
| #42 | Five describeResources() implementations — AWS, Azure, GCP (Config Connector), Kubernetes, Temporal |
| #51 | listArtifacts() plugin contract — context-keyed observation for lexicons whose chant entities describe authoring primitives rather than 1:1 cloud resources |
| #52 | Helm listArtifacts() — Helm releases via helm list -A -o json |
| #53 | Docker listArtifacts() — containers / images / networks via three independent NDJSON queries |
| #56 | GitHub / GitLab — runtime observation documented as N/A; both describe git-tracked authoring primitives where drift is git diff |
| #30 | chant/lifecycle orphan branch concurrency — pushes use --force-with-lease; concurrent snapshots fail fast instead of silently overwriting |
| #31 | WatchOp composite — periodic lifecycle observation by pairing an Op (Snapshot + Diff phases) with a TemporalSchedule |
Op runtime
Section titled “Op runtime”The Op composite gained two ergonomic upgrades that were previously hand-coded boilerplate in every example.
| # | Capability |
|---|---|
| #28 | Op codegen auto-emits upsertSearchAttributes() — OpName at workflow start, Phase at each phase boundary, plus any user-declared searchAttributes. No more hand-rolled boilerplate; chant run list and Temporal UI filters work out of the box |
| #41 | outcomeAttribute on activity steps — capture an activity’s return value (e.g. lifecycleDiff’s drifted boolean) as a workflow search attribute. Used by WatchOp to surface Drift = "true"/"false" per run |
| #29, #40 | Test coverage for cli/handlers/lifecycle.ts (then state.ts), run.ts, graph.ts, and runOp — refactor surface is now safe |
| #161 | Temporal runtime harness — runs the serializer’s actual generated workflow under a time-skipping TestWorkflowEnvironment: phase ordering, gate waits for the approval signal (not the timeout), onFailure compensation in reverse, and ApplyOp’s gated destructive apply (#125) |
| #162 | Compile-smoke for generated Op output — type-checks the emitted workflow.ts/worker.ts/activities.ts against the live activity signatures, so an activity-signature change that the serializer doesn’t track fails at compile time instead of drifting silently |
| #173 | Generated workflows are workflow-sandbox-safe — activity profiles import from the import-free config leaf instead of the package root, so the Temporal worker’s bundler no longer drags node:fs/node:path into the deterministic workflow VM (the generated workflow now bundles and runs). Surfaced by the #161 harness |
Cross-lexicon migration
Section titled “Cross-lexicon migration”A typed-compiler port of the upstream gitlab-org/ci-cd/github-actions-to-gitlab-ci Agent Skill (MIT). Translates .github/workflows/*.yml into .gitlab-ci.yml (or chant TypeScript) with per-key provenance recorded as SARIF, a curated mapping registry for the top 33 marketplace actions, and optional composite-pattern recognition for Node-shaped pipelines. The gitlab plugin exposes the same translation via a gitlab:migrate MCP tool and a chant-gitlab-migrate skill.
| # | Capability |
|---|---|
| #85 | GitHub → GitLab IR transformer with per-key provenance side channel; Kahn topo-sort stage inference; 30+ rule IDs for translation events |
| #86 | chant migrate CLI — top-level command dispatching through a new optional migrationSource(from) hook on LexiconPlugin |
| #87 | ActionMapping[] registry — Tier 1 (14 essentials): checkout, setup-, cache, artifacts, docker/ |
| #88 | ActionMapping Tier 2 (14 common) + Tier 3 (5 niche) — covers all 33 actions from the upstream skill’s reference table |
| #98 | Fixtures lifted from the upstream skill’s syntax-mapping + marketplace-actions before/after pairs; 16 fixture-driven tests asserting canonical-YAML and shape-of-report equality |
| #89 | --emit ts mode — produces typed chant TypeScript the user owns and rebuilds with chant build |
| #90 | SARIF v2.1.0 report (--report <path>) + --strict exit-code escalation on needs-review diagnostics |
| #91 | --validate shells out to glci (offline) or glab ci lint (fallback); skips gracefully when neither is on PATH |
| #92 | --use-composites IR-level recogniser — collapses 2-job Node pipelines into a single NodePipeline({...}) call |
| #93 | lexicons/gitlab/scripts/migrate-samples.sh — local roundtrip harness over real public GitHub workflows; 70% pass-rate threshold |
| #95 | chant-gitlab-migrate skill + new chant init --skill <name> filter to install a single skill |
| #96 | gitlab:migrate MCP tool registered on the gitlab plugin’s MCP server |
| #94 | Migration docs page with inspiration / lineage section crediting the upstream MIT-licensed skill |
| #97 | Umbrella — full work landed on PR #99 (draft) |
Build pipeline & lexicon fixes
Section titled “Build pipeline & lexicon fixes”| # | Capability |
|---|---|
| #21 | Lexicon root index.ts re-exports — three composites that examples imported through deep paths now exported from the package root; silent build failures resolved |
| #23, #25 | Azure schema parser — upstream renamed NetworkInterfaceIPConfiguration / SubnetPropertiesFormat / SecurityRule to Common*-prefixed names; bare property aliases now apply correctly, CI green |
| #38 | chant build writes output paths whose parent directory doesn’t exist (mkdir-p) — previously failed with ENOENT on first build of a project with nested output dirs |
Doc rollup
Section titled “Doc rollup”After all the runtime work shipped, the docs site got a sweep to surface it:
| # | Capability |
|---|---|
| #63 | Accuracy fixes — stale claims, broken links, rollup misses across index.mdx, comparison, philosophy, installation, quick-start, cli/overview |
| #64 | Watching Lifecycle — first-class user-guide page for WatchOp (was previously a subsection of the Ops guide) |
| #65 | Implementing Observation — lexicon-author walkthrough of describeResources() and listArtifacts() with patterns from every shipping implementation |
| #66 | Drift Detection — concept page for the observational lifecycle model, ten diff categories, and when drift detection earns its keep |
| #67 | This page + the lexicon observation coverage matrix |
Earlier — the Op core (#5–#11)
Section titled “Earlier — the Op core (#5–#11)”These shipped before the observation thread but underpin everything above. Listed for completeness:
- #5 Node.js migration + dev toolchain cleanup
- #6 Temporal lexicon —
TemporalNamespace,TemporalSchedule,SearchAttribute, plus the lint rules and composites - #7 Op composite + build pipeline integration
- #8
chant runCLI - #9 MCP tools for Op
- #10 Migrate spells to Ops
- #11 Op replaces spells with Temporal-backed deployment workflows