Skip to content

feat(state): chant state diff --live drift detection (#26)#32

Merged
lex00 merged 5 commits into
mainfrom
feat/state-diff-live-issue-26
May 8, 2026
Merged

feat(state): chant state diff --live drift detection (#26)#32
lex00 merged 5 commits into
mainfrom
feat/state-diff-live-issue-26

Conversation

@lex00
Copy link
Copy Markdown
Contributor

@lex00 lex00 commented May 7, 2026

Summary

Closes #26. Implements chant state diff <env> --live — a live-cloud drift mode that catches external mutations the existing digest-only diff misses. Default (digest) behavior is unchanged; --live is opt-in for v1.

The new path:

declared (entity names)  ↔  observedNow (plugin.describeResources)
observedNow              ↔  observedThen (snapshot.resources)

Six categories per lexicon: missing, orphan, disappeared, newly observed, drifted (with attribute-level changes), and unchanged. Lexicons without describeResources() are warn-skipped, not failed.

Commits

  1. chore(test-utils): add mockPlugin factory — reusable for Zero tests on cli/handlers/{state,run,graph}.ts — refactoring is unsafe #29
  2. feat(state): live-diff comparator — pure function in packages/core/src/state/live-diff.ts, 8 unit tests
  3. feat(cli): wire --live into state diff — flag plumbing + handler split into runStateDiffLive / runStateDiffDigest, 3 handler tests
  4. docs(state): document state diff --live drift mode
  5. fix(test-utils): use relative imports in mockPlugin factory — small follow-up

What's intentionally not in this PR

Verification

  • just build clean
  • npx vitest run packages/core/ packages/test-utils/ → 1434/1434 pass (16 new tests)
  • Legacy state diff (no --live) still works — regression test included
  • Manual smoke against a real AWS env was out-of-band; the AWS lexicon's existing describeResources() is the path that will exercise this in production

Test plan

lex00 added 5 commits May 7, 2026 15:36
Adds createMockPlugin() and staticDescribeResources() helpers used by
upcoming live-diff tests (#26) and reusable for future state/run handler
tests (#29). Lifecycle methods are no-ops; describeResources is wired
through when provided so tests can simulate live cloud responses without
real cloud access.
Pure-function comparator that classifies resources across three axes:
declared (entity names from current build), observedNow (from
plugin.describeResources()), and observedThen (from previous snapshot).

Produces six categories: missing (declared, not observed), orphan
(observed, not declared), disappeared (in previous snapshot, gone now),
newlyObserved (declared, observed, no prior snapshot),
driftedSinceSnapshot (metadata diff between snapshots), and unchanged.
Drift items carry attribute-level changes for status, physicalId,
lastUpdated, and each attributes.* key.

No I/O — caller wires plugins, snapshot reads, and rendering. Eight unit
tests covering each category and a mixed scenario.
Adds --live flag (parsed in cli/main.ts, ParsedArgs.live) that switches
state diff from digest comparison to a live cloud query against the
previous snapshot. Per lexicon:

  declared (entity names)  ↔  observedNow (plugin.describeResources)
  observedNow              ↔  observedThen (snapshot.resources)

Renders six categories: missing, orphan, disappeared, newly observed,
drifted (with attribute-level changes), and unchanged. Lexicons without
describeResources are warn-skipped, not failed. Default behavior
(without --live) is unchanged — the digest path stays for fast,
offline-friendly checks.

Three handler tests cover the drift, warn-skip, and legacy paths.
@intentius/chant isn't a real workspace dep of @intentius/chant-test-utils;
the existing fixtures.ts uses ../../core/src/* relative imports for the
same reason. Match that convention so vitest can resolve types.
Splits the state diff section into two modes: default (digest, fast and
offline) and --live (calls describeResources(), reports the six drift
categories). Documents the warn-skip behavior for lexicons that don't
implement describeResources() and links to issue #27 for tracking
lexicon coverage.
@lex00 lex00 merged commit ac23d12 into main May 8, 2026
9 checks passed
@lex00 lex00 deleted the feat/state-diff-live-issue-26 branch May 8, 2026 03:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

state diff is digest-vs-digest, not live-vs-declared — doesn't catch external mutations

1 participant