Encode intent/decision/plan workflow for Snowflake platform delivery so engagements share a durable recipe instead of one-off LLM chats. Co-authored-by: Cursor <cursoragent@cursor.com>
34 lines
1.3 KiB
Python
34 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import typer
|
|
from rich.console import Console
|
|
|
|
from skylattice.commands import discover_cmd
|
|
from skylattice.core.paths import find_customer_root, load_yaml
|
|
|
|
console = Console()
|
|
|
|
|
|
def run(
|
|
path: Path | None = typer.Option(None, "--path"),
|
|
inventory: Path | None = typer.Option(None, "--inventory"),
|
|
) -> None:
|
|
"""Re-discover and highlight drift vs last apply / intent."""
|
|
customer_root = path.resolve() if path else find_customer_root()
|
|
discover_cmd.run(path=customer_root, inventory=inventory)
|
|
|
|
report_path = customer_root / "observed" / "discover-latest.yaml"
|
|
if not report_path.exists():
|
|
raise typer.Exit(1)
|
|
report = load_yaml(report_path)
|
|
drifted = [o for o in report.get("objects") or [] if o.get("classification") in ("drifted_managed", "unmanaged_live")]
|
|
missing = [o for o in report.get("objects") or [] if o.get("classification") == "blueprint_match"]
|
|
|
|
console.print(f"[bold]Drift summary[/bold]: unmanaged_or_drifted={len(drifted)} desired_missing_live={len(missing)}")
|
|
for o in drifted[:20]:
|
|
console.print(f" ! {o.get('classification')} {o.get('kind')}:{o.get('name')}")
|
|
for o in missing[:20]:
|
|
console.print(f" + desired not in inventory: {o.get('kind')}:{o.get('name')}")
|