diff --git a/tools/check.sh b/tools/check.sh
--- a/tools/check.sh
+++ b/tools/check.sh
@@ -377,6 +377,18 @@
return "$rc"
}
+step "landing observer fixtures"
+if ! python3 tools/test_landing_observer.py; then
+ fail=1
+fi
+if command -v node >/dev/null 2>&1; then
+ if ! node --test .agents/skills/observing-misaligned-landings/tests/interpret-anomalies.test.mjs; then
+ fail=1
+ fi
+else
+ echo "SKIP: node unavailable; optional interpreter fixtures not run."
+fi
+
if [ "$rust_gate" -eq 1 ]; then
if ! run_rust_gate; then
fail=1
diff --git a/tools/test_landing_observer.py b/tools/test_landing_observer.py
new file mode 100644
--- /dev/null
+++ b/tools/test_landing_observer.py
@@ -0,0 +1,841 @@
+#!/usr/bin/env python3
+"""Focused fixtures for the strictly read-only landing observer."""
+
+from __future__ import annotations
+
+import copy
+import hashlib
+import importlib.util
+import json
+import os
+from pathlib import Path
+import subprocess
+import sys
+import tempfile
+import unittest
+
+
+ROOT = Path(__file__).resolve().parent.parent
+OBSERVER = ROOT / ".agents/skills/observing-misaligned-landings/scripts/observe-landing.py"
+TITLE = "Misaligned — WORK / THINK / LIE"
+ZERO_SHA = "0" * 40
+AGENT_ID = "agent-observer-fixture"
+TASK = "observer-fixture"
+
+spec = importlib.util.spec_from_file_location("landing_observer", OBSERVER)
+assert spec is not None and spec.loader is not None
+landing_observer = importlib.util.module_from_spec(spec)
+sys.modules[spec.name] = landing_observer
+spec.loader.exec_module(landing_observer)
+
+
+def run(
+ command: list[str],
+ cwd: Path,
+ env: dict[str, str] | None = None,
+) -> subprocess.CompletedProcess[str]:
+ completed = subprocess.run(
+ command,
+ cwd=cwd,
+ env=env,
+ text=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ check=False,
+ )
+ if completed.returncode != 0:
+ raise AssertionError(
+ f"command failed ({completed.returncode}): {' '.join(command)}\n"
+ f"stdout:\n{completed.stdout}\nstderr:\n{completed.stderr}"
+ )
+ return completed
+
+
+def git(cwd: Path, *args: str) -> str:
+ return run(["git", *args], cwd).stdout.strip()
+
+
+def filesystem_fingerprint(root: Path) -> dict[str, str]:
+ """Fingerprint every fixture byte, link target, and mode without following links."""
+ if not root.exists():
+ return {".": "missing"}
+ fingerprint: dict[str, str] = {}
+ for candidate in sorted(root.rglob("*")):
+ relative = str(candidate.relative_to(root))
+ metadata = candidate.lstat()
+ mode = oct(metadata.st_mode)
+ if candidate.is_symlink():
+ fingerprint[relative] = f"symlink:{mode}:{os.readlink(candidate)}"
+ elif candidate.is_file():
+ digest = hashlib.sha256(candidate.read_bytes()).hexdigest()
+ fingerprint[relative] = f"file:{mode}:{digest}"
+ elif candidate.is_dir():
+ fingerprint[relative] = f"directory:{mode}"
+ else:
+ fingerprint[relative] = f"other:{mode}"
+ return fingerprint
+
+
+def codes(rows: list[dict[str, str]]) -> set[str]:
+ return {row["code"] for row in rows}
+
+
+def gate_payload(revision: str, status: str = "pass") -> dict[str, str]:
+ return {
+ "revision": revision,
+ "schema": landing_observer.GATE_SCHEMA,
+ "status": status,
+ }
+
+
+
+def deployment_payload(
+ revision: str,
+ pages_revision: str | None = None,
+ status: str = "pass",
+) -> dict[str, object]:
+ return {
+ "pages_revision": pages_revision,
+ "schema": landing_observer.DEPLOYMENT_SCHEMA,
+ "source_revision": revision,
+ "status": status,
+ }
+
+def channel_payload(
+ revision: str,
+ status: str = "delivered",
+ message_id: str | None = "491",
+) -> dict[str, object]:
+ payload: dict[str, object] = {
+ "channel": "telegram",
+ "revision": revision,
+ "schema": landing_observer.CHANNEL_SCHEMA,
+ "status": status,
+ }
+ if message_id is not None:
+ payload["message_id"] = message_id
+ return payload
+
+
+def base_evidence(revision: str = "1" * 40, main: str = "2" * 40) -> dict[str, object]:
+ return {
+ "input": {"agent_id": AGENT_ID, "task": TASK},
+ "pages": {
+ "available": True,
+ "read_error": None,
+ "snapshot_matches_ref": True,
+ "snapshot_revision": "3" * 40,
+ "source_is_expected": False,
+ "source_revision": main,
+ "title_contract": True,
+ },
+ "primary_worktree": {
+ "dirty": False,
+ "present": True,
+ },
+ "project_status": {
+ "consistent": True,
+ "generated_ledgers_fresh": True,
+ "generated_work_orders_fresh": True,
+ "readable": True,
+ "target_run": {
+ "agent_id": AGENT_ID,
+ "phase": "check-land",
+ "present": True,
+ "status": "running",
+ "worktree": "/tmp/observer-fixture",
+ },
+ "target_run_ambiguous": False,
+ "target_worktree_ambiguous": False,
+ },
+ "public_site": {
+ "attempted": True,
+ "contract_ok": False,
+ "source_is_expected": False,
+ "source_revision": main,
+ },
+ "receipts": {
+ "channel": {
+ "provided": False,
+ "read_error": None,
+ "valid": None,
+ },
+ "deployment": {
+ "provided": False,
+ "read_error": None,
+ "valid": None,
+ },
+ "gate": {
+ "provided": True,
+ "read_error": None,
+ "revision": revision,
+ "status": "pass",
+ "valid": True,
+ },
+ },
+ "repository": {
+ "candidate_head_stable": True,
+ "hinted_root_matches": True,
+ "local_main_revision": main,
+ "readable": True,
+ "remote_main_contains_expected": False,
+ "remote_main_is_expected": False,
+ "remote_main_revision": main,
+ "remote_pages_revision": "3" * 40,
+ "remote_refs_readable": True,
+ "remote_refs_stable": True,
+ "snapshot_main_matches_ref": True,
+ "snapshot_main_revision": main,
+ },
+ "target_worktree": {
+ "ahead": 1,
+ "behind": 0,
+ "dirty": False,
+ "head_revision": revision,
+ "path": "/tmp/observer-fixture",
+ "present": True,
+ },
+ }
+
+
+def landed_evidence(revision: str = "1" * 40) -> dict[str, object]:
+ evidence = base_evidence(revision, revision)
+ evidence["repository"].update(
+ remote_main_contains_expected=True,
+ remote_main_is_expected=True,
+ )
+ evidence["pages"].update(
+ source_is_expected=True,
+ source_revision=revision,
+ )
+ evidence["public_site"].update(
+ contract_ok=True,
+ source_is_expected=True,
+ source_revision=revision,
+ )
+ evidence["project_status"]["target_run"].update(
+ phase="site-publish",
+ status="ok",
+ )
+ evidence["target_worktree"].update(
+ ahead=None,
+ behind=None,
+ dirty=None,
+ head_revision=None,
+ present=False,
+ )
+ evidence["receipts"]["channel"] = {
+ "channel": "telegram",
+ "message_id": "491",
+ "provided": True,
+ "read_error": None,
+ "revision": revision,
+ "status": "delivered",
+ "valid": True,
+ }
+ return evidence
+
+
+class ReceiptParsingTests(unittest.TestCase):
+ def test_non_delivered_channel_receipt_still_requires_exact_revision(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ path = Path(raw_tmp) / "channel.json"
+ payload = {
+ "channel": "telegram",
+ "schema": landing_observer.CHANNEL_SCHEMA,
+ "status": "unavailable",
+ }
+ path.write_text(json.dumps(payload), encoding="utf-8")
+ receipt = landing_observer.read_receipt(path, "channel")
+ self.assertEqual(receipt["valid"], False)
+ self.assertIn("invalid fields", receipt["read_error"])
+
+
+class ClassificationMatrixTests(unittest.TestCase):
+ def classify(self, evidence: dict[str, object], revision: str = "1" * 40):
+ return landing_observer.classify(evidence, revision)
+
+ def test_ready_requires_exact_gate_clean_rebase_and_owned_running_task(self) -> None:
+ state, missing, ownership, anomalies, _ = self.classify(base_evidence())
+ self.assertEqual(state, "ready")
+ self.assertEqual(codes(missing), {"land_candidate"})
+ self.assertEqual(ownership, [])
+ self.assertEqual(anomalies, [])
+
+ def test_ready_prerequisite_failures_are_coherent_blocks(self) -> None:
+ cases = {
+ "task_worktree_dirty": ("target_worktree", "dirty", True),
+ "local_remote_ref_stale": ("repository", "local_main_revision", "4" * 40),
+ "candidate_requires_rebase": ("target_worktree", "behind", 1),
+ "no_candidate_delta": ("target_worktree", "ahead", 0),
+ "generated_ledgers_stale": ("project_status", "generated_ledgers_fresh", False),
+ "generated_work_orders_stale": (
+ "project_status",
+ "generated_work_orders_fresh",
+ False,
+ ),
+ }
+ for expected_code, (section, key, value) in cases.items():
+ with self.subTest(expected_code):
+ evidence = base_evidence()
+ evidence[section][key] = value
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertIn(expected_code, codes(missing))
+ self.assertEqual(anomalies, [])
+
+ def test_foreign_or_unknown_ownership_blocks_ready_without_claiming_it(self) -> None:
+ for owner in ("another-agent", None):
+ with self.subTest(owner=owner):
+ evidence = base_evidence()
+ evidence["project_status"]["target_run"]["agent_id"] = owner
+ state, missing, ownership, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertIn("task_ownership_unproven", codes(missing))
+ self.assertTrue(ownership)
+ self.assertEqual(anomalies, [])
+
+ def test_missing_gate_reports_only_presence_blocker(self) -> None:
+ evidence = base_evidence()
+ evidence["receipts"]["gate"] = {
+ "provided": False,
+ "read_error": None,
+ "valid": None,
+ }
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertEqual(codes(missing), {"gate_receipt_missing"})
+ self.assertEqual(anomalies, [])
+
+ def test_absent_target_reports_only_missing_target_blocker(self) -> None:
+ evidence = base_evidence()
+ evidence["target_worktree"].update(
+ present=False,
+ dirty=None,
+ head_revision=None,
+ ahead=None,
+ behind=None,
+ )
+ evidence["project_status"]["target_run"]["status"] = "running"
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertEqual(
+ codes(missing),
+ {"target_worktree_missing"},
+ )
+ self.assertEqual(anomalies, [])
+
+ def test_dirty_primary_is_ownership_warning_while_ready(self) -> None:
+ evidence = base_evidence()
+ evidence["primary_worktree"]["dirty"] = True
+ state, missing, ownership, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "ready")
+ self.assertEqual(codes(missing), {"land_candidate"})
+ self.assertEqual(codes(ownership), {"unrelated_primary_checkout_dirty"})
+ self.assertEqual(anomalies, [])
+
+ def test_landed_requires_remote_pages_gate_terminal_run_and_cleanup(self) -> None:
+ state, missing, ownership, anomalies, summary = self.classify(landed_evidence())
+ self.assertEqual(state, "landed")
+ self.assertEqual(missing, [])
+ self.assertEqual(ownership, [])
+ self.assertEqual(anomalies, [])
+ self.assertIn("Landed", summary)
+
+ def test_exact_remote_without_gate_is_blocked_not_landed(self) -> None:
+ evidence = landed_evidence()
+ evidence["receipts"]["gate"] = {
+ "provided": False,
+ "read_error": None,
+ "valid": None,
+ }
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertIn("gate_receipt_missing", codes(missing))
+ self.assertEqual(anomalies, [])
+
+ def test_cleanup_pending_is_distinct_from_failed_landing(self) -> None:
+ evidence = landed_evidence()
+ evidence["project_status"]["target_run"]["status"] = "running"
+ evidence["target_worktree"].update(
+ present=True,
+ dirty=False,
+ head_revision="1" * 40,
+ )
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "blocked")
+ self.assertEqual(
+ codes(missing),
+ {"cleanup_pending", "run_completion_pending"},
+ )
+ self.assertEqual(anomalies, [])
+
+ def test_remote_pages_is_authoritative_while_public_edge_converges(self) -> None:
+ evidence = landed_evidence()
+ evidence["public_site"].update(
+ contract_ok=False,
+ source_is_expected=False,
+ source_revision="0" * 40,
+ )
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "landed")
+ self.assertEqual(missing, [])
+ self.assertEqual(codes(anomalies), {"public_edge_converging"})
+
+ def test_unavailable_telegram_preserves_landing_and_delivery_gap(self) -> None:
+ evidence = landed_evidence()
+ evidence["receipts"]["channel"] = {
+ "channel": "telegram",
+ "message_id": None,
+ "provided": True,
+ "read_error": None,
+ "revision": "1" * 40,
+ "status": "unavailable",
+ "valid": True,
+ }
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "landed")
+ self.assertEqual(codes(missing), {"telegram_delivery_pending"})
+ self.assertEqual(codes(anomalies), {"telegram_runtime_unavailable"})
+
+ def test_unrelated_dirty_primary_does_not_undo_completed_owned_cleanup(self) -> None:
+ evidence = landed_evidence()
+ evidence["primary_worktree"]["dirty"] = True
+ state, missing, ownership, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "landed")
+ self.assertEqual(missing, [])
+ self.assertEqual(codes(ownership), {"unrelated_primary_checkout_dirty"})
+ self.assertEqual(anomalies, [])
+
+ def test_superseded_historical_landing_remains_landed(self) -> None:
+ evidence = landed_evidence()
+ newer = "9" * 40
+ evidence["repository"].update(
+ remote_main_revision=newer,
+ remote_main_is_expected=False,
+ remote_main_contains_expected=True,
+ )
+ evidence["pages"].update(
+ source_revision="8" * 40,
+ source_is_expected=False,
+ )
+ evidence["public_site"].update(
+ source_revision=newer,
+ source_is_expected=False,
+ )
+ state, missing, _, anomalies, summary = self.classify(evidence)
+ self.assertEqual(state, "landed")
+ self.assertEqual(missing, [])
+ self.assertEqual(codes(anomalies), {"current_main_unpublished"})
+ self.assertIn("supersedes", summary)
+
+ def test_stale_post_rebase_gate_receipt_is_inconsistent(self) -> None:
+ evidence = base_evidence()
+ evidence["receipts"]["gate"]["revision"] = "8" * 40
+ state, missing, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "inconsistent")
+ self.assertEqual(missing, [])
+ self.assertEqual(codes(anomalies), {"gate_revision_mismatch"})
+
+ def test_optional_receipts_must_match_exact_remote_addresses(self) -> None:
+ deployment = landed_evidence()
+ deployment["receipts"]["deployment"] = {
+ "pages_revision": "8" * 40,
+ "provided": True,
+ "read_error": None,
+ "source_revision": "1" * 40,
+ "status": "pass",
+ "valid": True,
+ }
+ state, _, _, anomalies, _ = self.classify(deployment)
+ self.assertEqual(state, "inconsistent")
+ self.assertIn("deployment_pages_revision_mismatch", codes(anomalies))
+
+ channel = landed_evidence()
+ channel["receipts"]["channel"].update(
+ message_id=None,
+ revision="8" * 40,
+ status="unavailable",
+ )
+ state, _, _, anomalies, _ = self.classify(channel)
+ self.assertEqual(state, "inconsistent")
+ self.assertIn("channel_revision_mismatch", codes(anomalies))
+
+ def test_terminal_run_and_remote_contradictions_take_precedence(self) -> None:
+ evidence = base_evidence()
+ evidence["project_status"]["target_run"]["status"] = "ok"
+ evidence["target_worktree"]["present"] = False
+ state, _, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "inconsistent")
+ self.assertIn("terminal_run_without_remote_landing", codes(anomalies))
+
+ def test_invalid_receipt_project_state_and_impossible_pages_fail_closed(self) -> None:
+ cases = {
+ "gate_receipt_invalid": lambda row: row["receipts"].update(
+ gate={"provided": True, "read_error": "bad", "valid": False}
+ ),
+ "project_status_inconsistent": lambda row: row["project_status"].update(
+ consistent=False
+ ),
+ "published_revision_not_on_main": lambda row: row["pages"].update(
+ source_is_expected=True,
+ source_revision="1" * 40,
+ ),
+ "remote_refs_moved_during_observation": lambda row: row["repository"].update(
+ remote_refs_stable=False
+ ),
+ "pages_authority_unreadable": lambda row: row["pages"].update(
+ available=None,
+ read_error="fetch failed",
+ ),
+ }
+ for expected_code, mutate in cases.items():
+ with self.subTest(expected_code):
+ evidence = base_evidence()
+ mutate(evidence)
+ state, _, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "inconsistent")
+ self.assertIn(expected_code, codes(anomalies))
+
+ def test_unknown_authorities_remain_unknown_and_fail_closed(self) -> None:
+ evidence = base_evidence()
+ evidence["repository"].update(
+ remote_refs_readable=None,
+ remote_refs_stable=None,
+ )
+ evidence["project_status"].update(readable=False, consistent=None)
+ state, _, _, anomalies, _ = self.classify(evidence)
+ self.assertEqual(state, "inconsistent")
+ self.assertEqual(
+ codes(anomalies),
+ {"project_status_unreadable", "remote_refs_unreadable"},
+ )
+
+
+class LandingFixture:
+ def __init__(self, base: Path) -> None:
+ self.base = base
+ self.remote = base / "remote.git"
+ self.root = base / "work"
+ self.pages = base / "pages"
+ self.target = base / TASK
+ self.status_json = base / "project-status.json"
+ self.gate_receipt = base / "gate.json"
+ self.channel_receipt = base / "channel.json"
+ self.deployment_receipt = base / "deployment.json"
+
+ run(["git", "init", "--bare", "-q", str(self.remote)], base)
+ run(["git", "init", "-q", "-b", "main", str(self.root)], base)
+ git(self.root, "config", "user.name", "Observer Fixture")
+ git(self.root, "config", "user.email", "observer@example.invalid")
+ git(self.root, "remote", "add", "origin", str(self.remote))
+
+ tools = self.root / "tools"
+ tools.mkdir()
+ (tools / "project-status.py").write_text(
+ """import json, os
+with open(os.environ["OBSERVER_STATUS_JSON"], encoding="utf-8") as handle:
+ print(json.dumps(json.load(handle), sort_keys=True))
+""",
+ encoding="utf-8",
+ )
+ (tools / "site-smoke.sh").write_text(
+ f"""#!/usr/bin/env bash
+set -euo pipefail
+source_revision="${{OBSERVER_PUBLIC_SOURCE:-${{SITE_SOURCE_REVISION}}}}"
+echo "site-smoke: attempt 1/1 source=${{source_revision}}, expected=${{SITE_SOURCE_REVISION}}" >&2
+if [ "${{OBSERVER_SMOKE_FAIL:-0}}" = 1 ]; then
+ exit 1
+fi
+echo "site-smoke: OK ${{SITE_SMOKE_URL}}"
+echo "site-smoke: source=${{source_revision}}"
+""",
+ encoding="utf-8",
+ )
+ (self.root / "README.md").write_text("fixture base\n", encoding="utf-8")
+ git(self.root, "add", "README.md", "tools/project-status.py", "tools/site-smoke.sh")
+ git(self.root, "commit", "-q", "-m", "fixture base")
+ self.base_revision = git(self.root, "rev-parse", "HEAD")
+ git(self.root, "push", "-q", "-u", "origin", "main")
+ git(self.root, "update-ref", "refs/remotes/origin/main", self.base_revision)
+
+ run(["git", "init", "-q", "-b", "pages", str(self.pages)], base)
+ git(self.pages, "config", "user.name", "Observer Fixture")
+ git(self.pages, "config", "user.email", "observer@example.invalid")
+ git(self.pages, "remote", "add", "origin", str(self.remote))
+ self.write_page(self.base_revision, "fixture base pages")
+
+ git(self.root, "worktree", "add", "-q", "-b", f"worktree-{TASK}", str(self.target))
+ (self.target / "README.md").write_text("fixture candidate\n", encoding="utf-8")
+ git(self.target, "add", "README.md")
+ git(self.target, "commit", "-q", "-m", "fixture candidate")
+ self.revision = git(self.target, "rev-parse", "HEAD")
+ self.write_receipt(self.gate_receipt, gate_payload(self.revision))
+ self.write_project_status("running", include_target=True)
+
+ @staticmethod
+ def write_receipt(path: Path, payload: dict[str, object]) -> None:
+ path.write_text(json.dumps(payload, sort_keys=True), encoding="utf-8")
+
+ def write_project_status(
+ self,
+ status: str,
+ *,
+ include_target: bool,
+ consistent: bool = True,
+ ) -> None:
+ worktrees = [
+ {
+ "branch": "main",
+ "path": str(self.root),
+ }
+ ]
+ if include_target:
+ worktrees.append(
+ {
+ "branch": f"worktree-{TASK}",
+ "path": str(self.target),
+ }
+ )
+ payload = {
+ "active_arcs": [],
+ "consistency": {
+ "errors": [] if consistent else ["fixture inconsistency"],
+ "ok": consistent,
+ "warnings": [],
+ },
+ "freshness": {
+ "ledgers": True,
+ "work_orders": True,
+ },
+ "runs": [
+ {
+ "agent_id": AGENT_ID,
+ "id": TASK,
+ "phase": "check-land" if status == "running" else "site-publish",
+ "status": status,
+ "worktree": str(self.target),
+ }
+ ],
+ "worktrees": worktrees,
+ }
+ self.status_json.write_text(json.dumps(payload, sort_keys=True), encoding="utf-8")
+
+ def write_page(self, source: str, message: str) -> None:
+ (self.pages / "index.html").write_text(
+ "
"
+ f"{TITLE}"
+ f''
+ "\n",
+ encoding="utf-8",
+ )
+ git(self.pages, "add", "index.html")
+ git(self.pages, "commit", "-q", "-m", message)
+ git(self.pages, "push", "-q", "origin", "HEAD:pages")
+
+ def land(self, *, cleanup: bool = True, page_source: str | None = None) -> None:
+ git(self.root, "merge", "-q", "--ff-only", f"worktree-{TASK}")
+ git(self.root, "push", "-q", "origin", "main")
+ git(self.root, "update-ref", "refs/remotes/origin/main", self.revision)
+ self.write_page(page_source or self.revision, "fixture candidate pages")
+ if cleanup:
+ git(self.root, "worktree", "remove", str(self.target))
+ git(self.root, "branch", "-D", f"worktree-{TASK}")
+ self.write_project_status("ok", include_target=False)
+ else:
+ self.write_project_status("running", include_target=True)
+
+ def observe(
+ self,
+ *,
+ root: Path | None = None,
+ gate: Path | None = None,
+ channel: Path | None = None,
+ deployment: Path | None = None,
+ extra_env: dict[str, str] | None = None,
+ ) -> subprocess.CompletedProcess[str]:
+ env = os.environ.copy()
+ env.update(
+ {
+ "AGENT_ID": AGENT_ID,
+ "OBSERVER_STATUS_JSON": str(self.status_json),
+ }
+ )
+ if extra_env:
+ env.update(extra_env)
+ command = [
+ sys.executable,
+ str(OBSERVER),
+ "--root",
+ str(root or (self.target if self.target.exists() else self.root)),
+ "--task",
+ TASK,
+ "--revision",
+ self.revision,
+ "--site-url",
+ "https://example.invalid/misaligned/",
+ "--gate-receipt",
+ str(gate or self.gate_receipt),
+ ]
+ if channel is not None:
+ command.extend(["--channel-receipt", str(channel)])
+ if deployment is not None:
+ command.extend(["--deployment-receipt", str(deployment)])
+ return subprocess.run(
+ command,
+ cwd=root or (self.target if self.target.exists() else self.root),
+ env=env,
+ text=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ check=False,
+ )
+
+
+class IntegrationTests(unittest.TestCase):
+ def test_ready_receipt_is_byte_stable_and_does_not_touch_observed_git(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ before = filesystem_fingerprint(fixture.base)
+ first = fixture.observe()
+ middle = filesystem_fingerprint(fixture.base)
+ second = fixture.observe()
+ after = filesystem_fingerprint(fixture.base)
+
+ self.assertEqual(first.returncode, 0, first.stderr)
+ self.assertEqual(second.returncode, 0, second.stderr)
+ self.assertEqual(first.stdout, second.stdout)
+ self.assertEqual(before, middle)
+ self.assertEqual(before, after)
+ receipt = json.loads(first.stdout)
+ self.assertEqual(receipt["schema"], landing_observer.SCHEMA)
+ self.assertEqual(receipt["state"], "ready")
+ self.assertEqual(receipt["exact_revision"], fixture.revision)
+ self.assertEqual(codes(receipt["missing_steps"]), {"land_candidate"})
+ self.assertEqual(receipt["anomalies"], [])
+ self.assertEqual(receipt["evidence"]["target_worktree"]["present"], True)
+
+ def test_completed_landing_reads_cleaned_path_and_exact_receipts(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ fixture.land()
+ fixture.write_receipt(
+ fixture.channel_receipt,
+ channel_payload(fixture.revision),
+ )
+ before = filesystem_fingerprint(fixture.base)
+ observed = fixture.observe(channel=fixture.channel_receipt)
+ after = filesystem_fingerprint(fixture.base)
+
+ self.assertEqual(observed.returncode, 0, observed.stderr)
+ self.assertEqual(before, after)
+ self.assertFalse(fixture.target.exists())
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(receipt["state"], "landed")
+ self.assertEqual(receipt["missing_steps"], [])
+ self.assertEqual(receipt["anomalies"], [])
+ self.assertEqual(receipt["evidence"]["target_worktree"]["present"], False)
+ self.assertEqual(
+ receipt["evidence"]["pages"]["source_revision"],
+ fixture.revision,
+ )
+
+ def test_remote_pages_can_prove_landing_while_public_edge_lags(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ fixture.land()
+ fixture.write_receipt(
+ fixture.channel_receipt,
+ channel_payload(fixture.revision),
+ )
+ observed = fixture.observe(
+ channel=fixture.channel_receipt,
+ extra_env={
+ "OBSERVER_PUBLIC_SOURCE": ZERO_SHA,
+ "OBSERVER_SMOKE_FAIL": "1",
+ },
+ )
+
+ self.assertEqual(observed.returncode, 0, observed.stderr)
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(receipt["state"], "landed")
+ self.assertEqual(codes(receipt["anomalies"]), {"public_edge_converging"})
+ self.assertEqual(
+ receipt["evidence"]["public_site"]["source_revision"],
+ ZERO_SHA,
+ )
+
+ def test_deployment_receipt_conflict_is_inconsistent(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ fixture.land()
+ fixture.write_page(fixture.base_revision, "fixture stale pages")
+ fixture.write_receipt(
+ fixture.deployment_receipt,
+ deployment_payload(fixture.revision, status="pass"),
+ )
+ observed = fixture.observe(deployment=fixture.deployment_receipt)
+ self.assertEqual(observed.returncode, 2, observed.stderr)
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(receipt["state"], "inconsistent")
+ self.assertIn(
+ "deployment_receipt_conflicts_with_pages",
+ codes(receipt["anomalies"]),
+ )
+
+ def test_recorded_target_path_cannot_escape_into_primary_checkout(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ nested = fixture.root / ".letta" / "worktrees" / TASK
+ git(fixture.root, "worktree", "remove", str(fixture.target))
+ nested.mkdir(parents=True)
+ fixture.write_project_status("running", include_target=False)
+ payload = json.loads(fixture.status_json.read_text())
+ payload["runs"][0]["worktree"] = str(nested)
+ fixture.status_json.write_text(json.dumps(payload, sort_keys=True))
+ observed = fixture.observe(root=fixture.root)
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(observed.returncode, 2, observed.stderr + observed.stdout)
+ self.assertIn("target_path_escaped", codes(receipt["anomalies"]))
+
+ def test_stale_gate_and_project_contradiction_are_inconsistent(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ stale_gate = fixture.base / "stale-gate.json"
+ fixture.write_receipt(stale_gate, gate_payload(fixture.base_revision))
+ fixture.write_project_status("running", include_target=True, consistent=False)
+ before = filesystem_fingerprint(fixture.base)
+ observed = fixture.observe(gate=stale_gate)
+ after = filesystem_fingerprint(fixture.base)
+
+ self.assertEqual(observed.returncode, 2, observed.stderr)
+ self.assertEqual(before, after)
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(receipt["state"], "inconsistent")
+ self.assertEqual(
+ codes(receipt["anomalies"]),
+ {"gate_revision_mismatch", "project_status_inconsistent"},
+ )
+
+ def test_dirty_primary_is_only_an_ownership_warning_after_cleanup(self) -> None:
+ with tempfile.TemporaryDirectory() as raw_tmp:
+ fixture = LandingFixture(Path(raw_tmp))
+ fixture.land()
+ fixture.write_receipt(
+ fixture.channel_receipt,
+ channel_payload(fixture.revision),
+ )
+ (fixture.root / "unrelated.txt").write_text("unrelated\n", encoding="utf-8")
+ observed = fixture.observe(channel=fixture.channel_receipt)
+
+ self.assertEqual(observed.returncode, 0, observed.stderr)
+ receipt = json.loads(observed.stdout)
+ self.assertEqual(receipt["state"], "landed")
+ self.assertEqual(
+ codes(receipt["ownership_warnings"]),
+ {"unrelated_primary_checkout_dirty"},
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/wiki/log/2026-08-12-one-shot-landing-observer.md b/wiki/log/2026-08-12-one-shot-landing-observer.md
new file mode 100644
--- /dev/null
+++ b/wiki/log/2026-08-12-one-shot-landing-observer.md
@@ -0,0 +1,69 @@
+# One-shot landing observation without a second landing authority
+
+```
+Type: log
+```
+
+## Why
+
+A successful landing leaves evidence at several addresses: the exact candidate,
+remote `main`, remote `pages`, the public edge, project-operation state, cleanup,
+and any explicit gate, deployment, or channel receipts. Reading those surfaces by
+hand could confuse an ordinary stale edge with a broken landing, trust mutable local
+tracking refs, or let an interpretive agent quietly become another source of landing
+truth.
+
+The observer needed to answer one narrow question once: does one exact candidate
+cohere across the authorities the existing landing workflow already owns? It must be
+able to explain uncertainty without acquiring any channel that could change the
+answer.
+
+## Implemented
+
+- Added the registered `observing-misaligned-landings` repository skill and a
+ deterministic Python observer. It requires an exact revision and task id, samples
+ remote `main` and `pages` twice, fetches only into a disposable bare repository,
+ inspects the isolated page bytes, reads offline project status and optional exact
+ receipts, performs one public smoke read, and emits one byte-stable JSON receipt.
+- The classifier has only `ready`, `blocked`, `landed`, and `inconsistent` states.
+ Unknown evidence fails closed. A later coherent `main` descendant preserves the
+ historical landing, while a lagging public edge remains a named benign anomaly
+ behind the authoritative remote `pages` snapshot.
+- The target and primary repositories are opened with optional Git locks disabled.
+ No fetch enters the project, no ref moves, and no push, deployment, notification,
+ schedule, repair, or cleanup channel exists. Integration fixtures fingerprint the
+ complete fixture filesystem before and after ready, landed, and inconsistent reads.
+- Added optional anomaly interpretation through pinned
+ `@letta-ai/letta-agent-sdk` `0.7.1`. It finds exactly one retained specialist
+ named `Misaligned Landing Observer`, creates it only when absent with empty memory,
+ MemFS disabled, and no server tools, and fails closed on duplicate exact names.
+ Every anomaly read opens a fresh stateless conversation with no client tools or
+ skills. A strict allowlist strips paths, URLs, raw errors, and arbitrary receipt
+ fields before evidence crosses the repository boundary.
+- The interpreter does not load the SDK for clean receipts, explicitly superseded
+ candidates, or public-edge convergence alone. Its output is separate and cannot
+ upgrade or downgrade the deterministic classification.
+- Registered focused Python and Node fixtures in `tools/check.sh`; the deterministic
+ suite always runs, while the optional interpreter suite runs only where Node is
+ installed. The checked-in lockfile pins pnpm `10.20.0` and the SDK dependency.
+
+## Verification
+
+Focused classifier and repository fixtures cover coherent ready and landed states,
+cleanup and receipt gaps, stale evidence, impossible project-operation combinations,
+remote-ref motion, page authority, path escape, supersession, one-shot public-edge
+convergence, byte stability, and whole-fixture non-mutation. Node fixtures cover
+receipt minimization, benign-anomaly suppression, exact-name reuse, duplicate-name
+failure, supported creation options, and fresh stateless zero-authority prompting.
+The generated corpus indexes and exact project gate are the final landing checks on
+the fresh reconciled candidate.
+
+## Not done
+
+This does not create gate, deployment, or channel receipts; change `tools/task.sh`;
+land or repair a candidate; poll publication; or make interpretation mandatory.
+
+**Defense:** every effect remains on the thing that owns it. Git and project
+operations produce landing truth; the deterministic observer reads exact addresses;
+the optional specialist explains only minimized contradictions. No interpretive path
+can acquire a mutation channel or rewrite the state it was asked to explain.
diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md
--- a/wiki/log/DEVLOG.md
+++ b/wiki/log/DEVLOG.md
@@ -11,6 +11,11 @@
+## 2026-08-12 - One-shot landing observation without a second landing authority
+
+- Intent: (see session log)
+- Log: [wiki/log/2026-08-12-one-shot-landing-observer.md](2026-08-12-one-shot-landing-observer.md)
+
## 2026-08-11 - Territorial Personas core
- Intent: (see session log)
diff --git a/wiki/log/decisions.md b/wiki/log/decisions.md
--- a/wiki/log/decisions.md
+++ b/wiki/log/decisions.md
@@ -42,3 +42,4 @@
- [2026-08-05](decisions/2026-08-05.md)
- [2026-08-06](decisions/2026-08-06.md)
- [2026-08-11](decisions/2026-08-11.md)
+- [2026-08-12](decisions/2026-08-12.md)
diff --git a/wiki/process/repository-skills.md b/wiki/process/repository-skills.md
--- a/wiki/process/repository-skills.md
+++ b/wiki/process/repository-skills.md
@@ -40,6 +40,7 @@
| `design-companion` | `.agents/skills/design-companion/SKILL.md` | Explore and explain unsettled game-design choices in conversation without mutating the repository; hand adopted choices to `design-session`. |
| `design-session` | `.agents/skills/design-session/SKILL.md`
`.claude/skills/design-session/SKILL.md` | Capture affirmed design decisions into their owning law/spec pages, decision history, and session trace. |
| `playtesting-misaligned` | `.agents/skills/playtesting-misaligned/SKILL.md` | Run evidence-bearing naive and informed playtests against the current player surface and corpus. |
+| `observing-misaligned-landings` | `.agents/skills/observing-misaligned-landings/SKILL.md` | Read one exact candidate across isolated remote snapshots, public/site and project-operation evidence, classify it without mutation, and optionally ask one retained exact-name, zero-tool Letta specialist in a fresh conversation to interpret only non-benign anomalies. |
| `session-wrap` | `.agents/skills/session-wrap/SKILL.md`
`.claude/skills/session-wrap/SKILL.md` | Finish or preserve owned work, read exact current project state from live authorities, and report one bounded next step without maintaining a parallel checked-in handoff ledger. |
| `tick` | `.agents/skills/tick/SKILL.md`
`.claude/skills/tick/SKILL.md` | Invoke the project's bounded stewardship heartbeat: audit one corpus slice, act on one finding, and leave a trace. |
@@ -65,3 +66,18 @@
5. A skill that reports current execution state reads live Git, worktree,
project-status, and issue authorities; it does not maintain another tracked
current-state file or hard-code one agent harness's memory tool.
+6. A read-only observer fingerprints the target repository before and after the
+ observation, isolates remote fetches outside the repository, preserves unknown
+ evidence, and cannot mutate or repair the state it classifies.
+7. Optional agent interpretation cannot override deterministic state. It reuses
+ exactly one retained `Misaligned Landing Observer` with empty memory, MemFS and
+ tools disabled, opens a fresh conversation over minimized evidence for each
+ observation, provisions only when absent, and fails closed on duplicate exact names.
+
+## Defense
+
+The landing observer is registered here because it is a checked-in operational
+entry point, while the landing workflow remains owned by
+[workflows.md](workflows.md#git-conventions). Keeping deterministic evidence and
+optional interpretation subordinate to that law prevents a convenient observer from
+becoming a second landing authority or a mutation doorway.
diff --git a/wiki/process/workflows.md b/wiki/process/workflows.md
--- a/wiki/process/workflows.md
+++ b/wiki/process/workflows.md
@@ -282,6 +282,19 @@
push. Optional later step: move the same publish into CI once a write secret
exists; keep the exact source marker and smoke contract either way.
+A completed landing may be checked once with the registered
+`observing-misaligned-landings` skill. Its deterministic receipt samples remote
+`main` and `pages` into a disposable bare repository, compares public and
+project-operation evidence, and classifies the exact candidate as `ready`, `blocked`,
+`landed`, or `inconsistent`. The observer is strictly read-only: it does not fetch
+into the project, alter refs, push, deploy, notify, schedule, or clean worktrees.
+Unknown evidence fails closed. A later coherent landing supersedes an older candidate
+rather than retroactively making that older landing inconsistent. Optional Letta
+interpretation is subordinate and cannot change the state. It reuses one retained
+exact-name, empty-memory, zero-tool specialist but opens a fresh conversation for each
+observation; duplicate exact names fail closed.
+Do not poll the edge merely because its one public read still serves an older source.
+
Starlight is the documentation renderer. Its sync copies root `DESIGN.md` to
the `/constitution/` doorway and parses `wiki/SUMMARY.md` for navigation. The
Rust/check pipeline enforces structural wiki correctness through
@@ -350,7 +363,8 @@
union-edit them. After sources/specs are reconciled, run the generator and
take its complete output.
- Spec-driven rule: functional change commits amend the owning `Type: law`
- or `Type: spec` page and update affected knowledge.
+ or `Type: spec` page and update affected knowledge. Operational observers do
+ not replace those owners; their receipts are evidence, not authority.
- Remote: `origin` is a Tangled knot (`tangled.org`, SSH). **Land changes
by merging to `main` directly** after the appropriate scoped verification
passes (full `./tools/check.sh` for Rust-impacting work; focused checks for
@@ -392,3 +406,13 @@
2. `Type: knowledge` wiki page updates (if reality changed).
3. `wiki/log/YYYY-MM-DD-topic.md` session writeup; `wiki/log/DEVLOG.md`
gets the short ledger line.
+
+## Defense: one-shot landing evidence
+
+The observer reads the same exact revision and authorities already required by this
+workflow, but cannot produce any landing effect. Isolated remote snapshots prevent
+its proof from depending on stale local tracking refs; pre/post repository
+fingerprints make the read-only boundary testable; explicit unknowns prevent missing
+transport, project-status, receipt, or public evidence from becoming a false green.
+Keeping agent interpretation optional and unable to override the four-state classifier
+preserves the executable workflow as the only landing authority.
diff --git a/.agents/skills/observing-misaligned-landings/.gitignore b/.agents/skills/observing-misaligned-landings/.gitignore
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+__pycache__/
+*.py[cod]
diff --git a/.agents/skills/observing-misaligned-landings/SKILL.md b/.agents/skills/observing-misaligned-landings/SKILL.md
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/SKILL.md
@@ -0,0 +1,119 @@
+---
+name: observing-misaligned-landings
+description: Observe one completed Misaligned landing without changing it. Use after a main/pages publication, when asked whether a landing really reached the remote and public site, or when deterministic landing evidence needs optional Trace interpretation through the Letta Agent SDK.
+---
+
+# Observing Misaligned Landings
+
+Emit one machine-readable receipt proving whether an exact revision agrees across
+checked-out Git state, remote `main`, remote `pages`, the public homepage, and the
+project-operation dashboard. This skill observes; it never lands, deploys, repairs,
+notifies, schedules, or cleans anything.
+
+The binding landing and publication workflow remains
+`wiki/process/workflows.md#git-conventions`. `tools/project-status.py` and
+`tools/site-smoke.sh` remain the project authorities this observer composes.
+
+## Safety boundary
+
+The observer may only:
+
+- resolve local Git objects and refs;
+- read remote refs with `git ls-remote`;
+- fetch sampled remote `main`, remote `pages`, and the exact candidate into one
+ disposable bare repository under the system temp directory, inspect only that
+ isolated snapshot, then delete the repository;
+- run `tools/project-status.py --json --check --offline`;
+- run one `tools/site-smoke.sh` attempt against the exact revision.
+
+It must not fetch into the observed repository, update a ref, checkout, commit,
+push, deploy, create an issue, send a message, invoke a schedule, or remove a
+worktree. A failed receipt reports an anomaly and stops. It does not repair it.
+Do not turn the one-shot public read into propagation polling unless Cameron asks
+or an actual deployment failure is being diagnosed.
+
+## Emit the deterministic receipt
+
+Run from the exact landed checkout and name the full landed revision when it is
+known:
+
+```bash
+SKILL=.agents/skills/observing-misaligned-landings
+python3 "$SKILL/scripts/observe-landing.py" \
+ --root "$PWD" \
+ --task landing-task-id \
+ --revision fd1e6accfbe90075f67e8389b46d3bf8014c1837 \
+ > /tmp/misaligned-landing.json
+status=$?
+python3 -m json.tool /tmp/misaligned-landing.json
+```
+
+`--revision` is required and must name the exact full candidate revision being
+proved. `--remote` defaults to `origin`; `--site-url` defaults to the production
+Misaligned URL (and respects the existing `SITE_SMOKE_URL` override).
+
+The command always emits its deterministic state and named evidence before exiting.
+The receipt has no observation timestamp or temporary path, has sorted keys and
+stable row ordering, and produces identical bytes when the observed authorities do
+not change.
+
+The checks are deliberately stricter than a successful push:
+
+1. the exact candidate remains stable while observed;
+2. independently sampled remote `main` and `pages` refs remain stable and match the
+ objects fetched into the isolated snapshot;
+3. ancestry classifies the candidate as current, unlanded, or superseded rather
+ than treating every later `main` commit as a failed landing;
+4. the isolated `pages` snapshot embeds the requested source revision plus the
+ homepage title contract, or honestly shows that a newer source superseded it;
+5. project-operation records, generated projections, exact gate/deployment/channel
+ receipts, ownership, cleanup, and one public-site read agree.
+
+The top-level deterministic state is `ready`, `blocked`, `landed`, or
+`inconsistent`. Exit `0` means `ready` or `landed`; `blocked` exits `1`, and
+`inconsistent` exits `2`. Unknown or unreadable evidence is preserved and fails
+closed instead of being collapsed into absence. A dirty primary checkout is an
+ownership warning unless it touches the observed landing surface; a later clean
+landing is reported as superseding the candidate instead of contradicting it.
+
+## Ask Trace only about anomalies
+
+Deterministic checks decide classification. Agent interpretation is optional,
+supplemental, and only when non-benign anomalies remain. Ordinary public-edge
+convergence and explicitly superseded landings do not invoke it by themselves.
+
+Install the pinned SDK once for this checked-in skill, then pass the receipt:
+
+```bash
+pnpm --dir "$SKILL" install --frozen-lockfile
+node "$SKILL/scripts/interpret-anomalies.mjs" /tmp/misaligned-landing.json
+```
+
+The interpreter uses `@letta-ai/letta-agent-sdk` to find exactly one retained
+`letta/auto` specialist named `Misaligned Landing Observer`, provisioning it only when
+absent. More than one exact-name match fails closed. The specialist stays discoverable
+for exact-name reuse, with empty memory, MemFS disabled, no tools or skills, and a strict
+zero-action prompt.
+Each observation uses SDK `prompt()` with `stateless: true`, which opens a fresh
+conversation for that retained agent rather than resuming an earlier receipt and
+loads no persisted MemFS state. Only minimized evidence
+crosses the repository boundary: local paths, remote URLs, task paths, and raw read
+errors are removed. Interpretation may explain likely convergence, stale evidence, or
+project-operation inconsistency, but cannot alter the receipt or its deterministic
+state.
+
+If no non-benign anomaly remains, the interpreter returns `status: not-needed`
+without loading the SDK or contacting Letta. If credentials, SDK installation, exact
+agent lookup/provisioning, or prompting fail, report interpretation failure
+separately; never downgrade or upgrade the deterministic landing result.
+
+## Verify changes to this skill
+
+```bash
+python3 tools/test_landing_observer.py
+node --test .agents/skills/observing-misaligned-landings/tests/*.test.mjs
+```
+
+The fixture proves byte-stable clean receipts, exact anomaly codes, optional-SDK
+fail-closed behavior, and that observing leaves the target repository's Git bytes
+unchanged.
diff --git a/.agents/skills/observing-misaligned-landings/package.json b/.agents/skills/observing-misaligned-landings/package.json
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "@misaligned/landing-observer",
+ "version": "1.0.0",
+ "private": true,
+ "type": "module",
+ "packageManager": "pnpm@10.20.0",
+ "scripts": {
+ "interpret": "node scripts/interpret-anomalies.mjs",
+ "test": "node --test tests/*.test.mjs"
+ },
+ "dependencies": {
+ "@letta-ai/letta-agent-sdk": "0.7.1"
+ }
+}
diff --git a/.agents/skills/observing-misaligned-landings/pnpm-lock.yaml b/.agents/skills/observing-misaligned-landings/pnpm-lock.yaml
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/pnpm-lock.yaml
@@ -0,0 +1,3065 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@letta-ai/letta-agent-sdk':
+ specifier: 0.7.1
+ version: 0.7.1(ink@7.1.1(react@18.2.0))(react-dom@19.2.8(react@18.2.0))(zod@4.4.3)
+
+packages:
+
+ '@alcalzone/ansi-tokenize@0.3.0':
+ resolution: {integrity: sha512-p+CMKJ93HFmLkjXKlXiVGlMQEuRb6H0MokBSwUsX+S6BRX8eV5naFZpQJFfJHjRZY0Hmnqy1/r6UWl3x+19zYA==}
+ engines: {node: '>=18'}
+
+ '@anthropic-ai/sdk@0.91.1':
+ resolution: {integrity: sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==}
+ hasBin: true
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+
+ '@aws-crypto/sha256-browser@5.2.0':
+ resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
+
+ '@aws-crypto/sha256-js@5.2.0':
+ resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-crypto/supports-web-crypto@5.2.0':
+ resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==}
+
+ '@aws-crypto/util@5.2.0':
+ resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
+
+ '@aws-sdk/client-bedrock-runtime@3.1048.0':
+ resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/core@3.977.7':
+ resolution: {integrity: sha512-I88Iov89NVmjSmJLKSv7Cn9M2J+a2942OkA8nZCbz+sl4ZeY4zEOcoLOrbt1GRfQ8zEQKnjAJdXixA3J/p1fDQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-env@3.972.68':
+ resolution: {integrity: sha512-2a20A/IdNOwUvaDq91iqqS7BA0XlNMfW3iLGZGZLJv0EbUqhSxB0PIx4rQQqssvWj1uXImb3/UCCdHz/+1dOiA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-http@3.972.70':
+ resolution: {integrity: sha512-0yRem2Fs52r/Nn6UAqIlpjexfaYj8ziEozOe9tamtAVT/5bzFLKx8O2r7MaRqgS3hGKHIa1Jij9nKHSsNnb04A==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-ini@3.973.13':
+ resolution: {integrity: sha512-2M39DE02XpYYaSWYk/4AsImXYUU/1L2xmTMLUpMMWq7DfLv191/vCRy3baKtdr45AkJQyVgSjmuVOLm15SwrRQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-login@3.972.75':
+ resolution: {integrity: sha512-jaTESuJlQsoUZ44f/i2puyPt8VlF/dMMJ9HM3cStYtk7eKX4N9UWi83OLixUkoOJH3BwWlPLCq9YIK9nfWhVBg==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-node@3.972.79':
+ resolution: {integrity: sha512-RIw5dof1EHkWubrZzPC941CDtnFG1iAXsxbFgLkhdYZXHc4icU13c/uxSMI0J5eUx9bxa7LjfpdjfClBB1QsDA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-process@3.972.68':
+ resolution: {integrity: sha512-nLP3Pda2MQTFJ25hKBMmUuB9Uv+bTZQNlufbeCwklP549Vwnkd8bRLJoCKp5k6xjmdyptrPrOfGOhN0mKuca8A==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-sso@3.973.12':
+ resolution: {integrity: sha512-EmgyyHn+f9WCcelp3L/vci+LGbX8GigWaVphRArjVo5Pktkr9YnLy/mQ6VDkDyBD72dtfRNTgHmD2ts4rTDXKQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/credential-provider-web-identity@3.972.74':
+ resolution: {integrity: sha512-0YfczxGXF3RjGj8z7QG/Ho2HnLGKDHfPSHiTs47UU1U/+mmwISDN+rvGKt2zh+3FX8NdT4xd95LGBGyhQw2dgQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/eventstream-handler-node@3.972.32':
+ resolution: {integrity: sha512-rlbmsMG7ZNgrVhWSqqXpq6y9hfiREyzCg3CNTk9UK+AoP7+65kOkqpWmqwLfV1UrRSHATdLnZF2rt9ZTUxYQJA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/middleware-eventstream@3.972.27':
+ resolution: {integrity: sha512-M7Ay1VpBpf/YFfic9kkjwE3wyCh4G0gEM4RypRXYm7aPjyfqi+D8FEYMR2E3IqbvN+qi2rEFYAiwWL0XHtQYdQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/middleware-websocket@3.972.50':
+ resolution: {integrity: sha512-gdcWRbmIf1dWA/prf44Bnnzgqj+AbsXX2yfhZhOQLwSm7NfKIYPmkRlPqP0CTepHzjxMIBdWBDdtQB+Y/dFUeg==}
+ engines: {node: '>= 14.0.0'}
+
+ '@aws-sdk/nested-clients@3.997.42':
+ resolution: {integrity: sha512-XWRyon2MTHXD/zMoo0Mbge6Vwf+iE0qQaM/RyGO6NfZ9WukCFiQL27nQVZjYy2JwSIg+iXZxKOX95OBXqlSM4w==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/signature-v4-multi-region@3.996.44':
+ resolution: {integrity: sha512-ZSfQ35Qn4MhSY+A0Whyr+KBx+wJKZUyBsOrjB2pSHOafRzbFe47T8XcXM8hZqUAC69qnqIy0C9ArxTuud0CC2w==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/token-providers@3.1048.0':
+ resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/token-providers@3.1108.0':
+ resolution: {integrity: sha512-rI80zxDxGJ6904eC/YbjkdjY6JdaZvQ01kOmrMvw7cFQGIHo27fhnIVbMSVDS4T6foQImjxYSRoOu/uSJscXDw==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/types@3.974.3':
+ resolution: {integrity: sha512-ECAqfpNsef+7MO8qtR0h9KcFIBAygaE7Cm6UOiQl+ft+uVap+1G7bNEjs4mdJE2OnA4m6k7i8peH8uGIAsOMGw==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/util-locate-window@3.965.9':
+ resolution: {integrity: sha512-wB/ho7pTJKqWz3WYDt2ZWDWI8bxQpN/xwf+5ZQ1zWaj+HDY9B8Fn434i6qZ6j6ZG3aCiIJtZaQVqwajx5xYsQA==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws-sdk/xml-builder@3.972.38':
+ resolution: {integrity: sha512-grf7mzfVxBS5AlsuTvBN7uDpzqohFww9fRPCO+EBSUdvtsYMcPSKdz54h/7XiscqNcUM1Ae1MF7JLHmiYYuzbQ==}
+ engines: {node: '>=20.0.0'}
+
+ '@aws/lambda-invoke-store@0.3.0':
+ resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
+ engines: {node: '>=18.0.0'}
+
+ '@babel/runtime@7.29.7':
+ resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
+ engines: {node: '>=6.9.0'}
+
+ '@earendil-works/pi-ai@0.82.1':
+ resolution: {integrity: sha512-3WFYRhEp3lQB3444EhPMBcM7zSaEUE3eJgHOR7s4081NLqbw/FsWilIKWXSua0Gv3sRr7m9xMidR3pPDE7jI/A==}
+ engines: {node: '>=22.19.0'}
+ hasBin: true
+
+ '@emnapi/runtime@1.11.3':
+ resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+
+ '@google/genai@1.52.0':
+ resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==}
+ engines: {node: '>=20.0.0'}
+ peerDependencies:
+ '@modelcontextprotocol/sdk': ^1.25.2
+ peerDependenciesMeta:
+ '@modelcontextprotocol/sdk':
+ optional: true
+
+ '@hono/node-server@2.1.0':
+ resolution: {integrity: sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ hono: ^4
+
+ '@img/colour@1.1.0':
+ resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
+ engines: {node: '>=18'}
+
+ '@img/sharp-darwin-arm64@0.34.5':
+ resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-darwin-x64@0.34.5':
+ resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
+ cpu: [arm]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-linux-arm64@0.34.5':
+ resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-linux-arm@0.34.5':
+ resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@img/sharp-linux-ppc64@0.34.5':
+ resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-linux-s390x@0.34.5':
+ resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [s390x]
+ os: [linux]
+
+ '@img/sharp-linux-x64@0.34.5':
+ resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-wasm32@0.34.5':
+ resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [wasm32]
+
+ '@img/sharp-win32-arm64@0.34.5':
+ resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@img/sharp-win32-ia32@0.34.5':
+ resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@img/sharp-win32-x64@0.34.5':
+ resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@letta-ai/letta-agent-sdk@0.7.1':
+ resolution: {integrity: sha512-pwzEzBwTtqj88Z8uRNmU/mRor5N57Sbzcz0dKT3t284kQWNwQDvBrhPeDVdh+Z1ARZOSY4BKrIcthiv30RhwEA==}
+ engines: {node: '>=22.19.0'}
+
+ '@letta-ai/letta-client@1.12.1':
+ resolution: {integrity: sha512-rYjXMXpkfssj7VBBX3qCp6mdpNRv6YPNrliYsjkhWoQDqGg3J9bsgIQ28ZhQTddabYxRUIwcdzuaizFx8pvZ7A==}
+
+ '@letta-ai/letta-code@0.30.11':
+ resolution: {integrity: sha512-BPnpFVnCC0YinSu/LUKlzZur94pVPMytrUT4Qv8mGknJE77t15vNcALhspq+bESu2Lj67ZaQ6n2FgIy9dwmteQ==}
+ engines: {node: '>=22.19.0'}
+ hasBin: true
+
+ '@letta-ai/trajectory@0.2.0':
+ resolution: {integrity: sha512-biCyT0z8nh4Q8kIqBrPgmzoalacPmosmCpvEjdN9ILpL85+T75b8ahcN9MHPHQUVRj/J7UyQuRahJ4/JdrpCcA==}
+ engines: {node: '>=20'}
+
+ '@mistralai/mistralai@2.2.6':
+ resolution: {integrity: sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==}
+ peerDependencies:
+ '@opentelemetry/api': ^1.9.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+
+ '@modelcontextprotocol/sdk@1.30.0':
+ resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@cfworker/json-schema': ^4.1.1
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ '@cfworker/json-schema':
+ optional: true
+
+ '@opentelemetry/api@1.9.0':
+ resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/semantic-conventions@1.43.0':
+ resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==}
+ engines: {node: '>=14'}
+
+ '@pierre/diffs@1.2.2':
+ resolution: {integrity: sha512-MvWLv2oSOJOF8oYXWLdhicguHM11G/VNWu6OPR5ZETolp2NM2/KPQG3cZTnKpJ6ImqEHwvw6Gl6z2gmmy2FQmQ==}
+ peerDependencies:
+ react: ^18.3.1 || ^19.0.0
+ react-dom: ^18.3.1 || ^19.0.0
+
+ '@pierre/theme@1.0.3':
+ resolution: {integrity: sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA==}
+ engines: {vscode: ^1.0.0}
+
+ '@protobufjs/aspromise@1.1.2':
+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
+
+ '@protobufjs/base64@1.1.2':
+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
+
+ '@protobufjs/codegen@2.0.5':
+ resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
+
+ '@protobufjs/eventemitter@1.1.1':
+ resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==}
+
+ '@protobufjs/fetch@1.1.1':
+ resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==}
+
+ '@protobufjs/float@1.0.2':
+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
+
+ '@protobufjs/path@1.1.2':
+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
+
+ '@protobufjs/pool@1.1.0':
+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
+
+ '@protobufjs/utf8@1.1.2':
+ resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==}
+
+ '@scarf/scarf@1.4.0':
+ resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==}
+
+ '@shikijs/core@3.23.0':
+ resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==}
+
+ '@shikijs/core@4.4.3':
+ resolution: {integrity: sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==}
+ engines: {node: '>=20'}
+
+ '@shikijs/engine-javascript@3.23.0':
+ resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==}
+
+ '@shikijs/engine-javascript@4.4.3':
+ resolution: {integrity: sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==}
+ engines: {node: '>=20'}
+
+ '@shikijs/engine-oniguruma@3.23.0':
+ resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==}
+
+ '@shikijs/engine-oniguruma@4.4.3':
+ resolution: {integrity: sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==}
+ engines: {node: '>=20'}
+
+ '@shikijs/langs@3.23.0':
+ resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==}
+
+ '@shikijs/langs@4.4.3':
+ resolution: {integrity: sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==}
+ engines: {node: '>=20'}
+
+ '@shikijs/primitive@4.4.3':
+ resolution: {integrity: sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==}
+ engines: {node: '>=20'}
+
+ '@shikijs/themes@3.23.0':
+ resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==}
+
+ '@shikijs/themes@4.4.3':
+ resolution: {integrity: sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==}
+ engines: {node: '>=20'}
+
+ '@shikijs/transformers@3.23.0':
+ resolution: {integrity: sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ==}
+
+ '@shikijs/types@3.23.0':
+ resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==}
+
+ '@shikijs/types@4.4.3':
+ resolution: {integrity: sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==}
+ engines: {node: '>=20'}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
+ '@smithy/core@3.32.0':
+ resolution: {integrity: sha512-NAiCSC78fzbNIEWoheoF74Ob5ZorLijCHpMY26Fqvqg/+9LuyIqMfHDg2p8Yk1rqOyowtiL3y7WX0AW+teL6zw==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/credential-provider-imds@4.5.0':
+ resolution: {integrity: sha512-2jsPi+7Zv2hSzD9IXR9D7DTqSn7mv4XalzRm+bESh53jiaUS3NKEUbpQFTJP0HhQy9qzZvluxQ3yS24zdRrqsA==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/fetch-http-handler@5.7.0':
+ resolution: {integrity: sha512-W/exA8T0LEzCQtJ02w4IzaEQPIspgarqZprb7W8FwnYiDowgCrjl2fTQ6FvuSSUnJORuepBF81abmBJwqh+0XQ==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/is-array-buffer@2.2.0':
+ resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==}
+ engines: {node: '>=14.0.0'}
+
+ '@smithy/node-http-handler@4.10.0':
+ resolution: {integrity: sha512-nrh7VxqzPQS/ip1hS293aI/OAWDWARQvjUxCfuKhyrfHa2gTdk28066RNeWLI1uuoHXaKAkOF8IcSAHuOp0+SA==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/node-http-handler@4.7.3':
+ resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/signature-v4@5.7.0':
+ resolution: {integrity: sha512-hCynhm22wMJ8wTF9crcwu8mxggtUrSLLJgDcGUvYFBqpofxycYJCGKOMYg4xtPPFtgNiDJSYmhsWLTrcU/g59Q==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/types@4.17.0':
+ resolution: {integrity: sha512-Aw4joiM0ZdErpo39lCj8phT2lxoiKZV+KZzBxnnQhWVtU2Is/WffQSL04uUWRcXUse9Ln8vXZK6V/FwqRVnQpg==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/util-buffer-from@2.2.0':
+ resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
+ engines: {node: '>=14.0.0'}
+
+ '@smithy/util-utf8@2.3.0':
+ resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
+ engines: {node: '>=14.0.0'}
+
+ '@types/hast@3.0.5':
+ resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==}
+
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+ '@types/node@26.2.0':
+ resolution: {integrity: sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==}
+
+ '@types/retry@0.12.0':
+ resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
+ '@ungap/structured-clone@1.3.3':
+ resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==}
+
+ '@vscode/ripgrep-darwin-arm64@1.18.0':
+ resolution: {integrity: sha512-r3ktHSvbFycQNF6sl7sNDPocpsI7J+mEzh1IaZFkY0spm3k2Z9t8hPAeOK7+p0l6p6/swkQC14XWX01low+94Q==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@vscode/ripgrep-darwin-x64@1.18.0':
+ resolution: {integrity: sha512-25b4gWbL138dGuQU244ebCKKc0q05ULBMoFSz9oAEUHNeqK/lOJViDS7DRvbDazzAzSEdan391Znks/R5mkaTQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@vscode/ripgrep-linux-arm64@1.18.0':
+ resolution: {integrity: sha512-lQ/5zTG++U0E3IhVgS4EPTTn/U4okncaRMM5GOFfOYZywS4nuD31GhkHbNYlDk5CuDC68+hYJ0/eQeyCKJDA+g==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-arm@1.18.0':
+ resolution: {integrity: sha512-GDAvufNDHu8zqLEmXstalQF0Wh6wQvdsBi/Vg3Yi3CK4a8XoFXqqXVEHEZ9xQz3t0NfoSEc9JbvK9DDS6FxyxQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-ia32@1.18.0':
+ resolution: {integrity: sha512-YWLkSUtFd4Jh5EepIhA9RJSfv3uMAVMo+2rBIGHPBnvgLrZciIs2cDKei1/p6Wc/aCzUoHyMAg2R6tw4ZCBKGg==}
+ cpu: [ia32]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-ppc64@1.18.0':
+ resolution: {integrity: sha512-quXVY8fwQ8O/lvU1yrSqSl3jlUzysRSb+AfUfCL/tRtphxsKlFvPAejryZ6vg4Bgvn8XL74xb4qMCDmWgYrT5w==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-riscv64@1.18.0':
+ resolution: {integrity: sha512-f5kBQBrWfQt8Q7OhSORuNDei5dkYagBj3y4jImSUXGMy8B/Ke7SltSRcUtjPv166FAFfHCAmWuZp3+cWnX2/Vw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-s390x@1.18.0':
+ resolution: {integrity: sha512-rTOcJFGGcl2c07RUOWUo4U1ndnemKhY6A9hnMB18uk7jSgJc0d/QLBGWMWpumdtoJtpizn/wIv5mXIisJukusQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@vscode/ripgrep-linux-x64@1.18.0':
+ resolution: {integrity: sha512-mQ3bVrUpnD2vs7QT0vX90Lt0cnUq467uFtEktIdsJJmW296RoSULRGqWgzG1AKxyBpNDD6l4ZO4qKf6SgyC23Q==}
+ cpu: [x64]
+ os: [linux]
+
+ '@vscode/ripgrep-win32-arm64@1.18.0':
+ resolution: {integrity: sha512-vfTIjq1OHnzUjxZcHVQAMbnggp8dpGf+0QKFOZHwWPqFwXxQC8eCWM+5NUdoJ6yrElCeMzoUTXoK/LdZaniB+Q==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@vscode/ripgrep-win32-ia32@1.18.0':
+ resolution: {integrity: sha512-//rfAE+BOw5AC2EMmepmiE36jUuevtQYNQqqlw1s3m9FlRxjxEut97RkRPHAu9BG4mSojatZx+kXZXNdyI9caQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@vscode/ripgrep-win32-x64@1.18.0':
+ resolution: {integrity: sha512-KNPvtElldqILHdnAetujPaowkNbpqJy3ssIGGN6F6Kve9Qi+nNLI2DN01O83JjCEVQbCzl8Ov3QZ9Eov3BR8Dg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@vscode/ripgrep@1.18.0':
+ resolution: {integrity: sha512-ns5lWe44tSfbTMbVUsyB+I1819PVSw4AdpgK0RNkzfWfwy6+3IUNSxwSrfTno1/oWaS/hERNz+XLWVyga2aJBQ==}
+
+ accepts@2.0.0:
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+ engines: {node: '>= 0.6'}
+
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ ajv-formats@3.0.1:
+ resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv@8.20.0:
+ resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
+
+ ansi-escapes@7.3.0:
+ resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==}
+ engines: {node: '>=18'}
+
+ ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
+ engines: {node: '>=12'}
+
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+ engines: {node: '>=12'}
+
+ auto-bind@5.0.1:
+ resolution: {integrity: sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ bignumber.js@9.3.1:
+ resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
+
+ body-parser@2.3.0:
+ resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==}
+ engines: {node: '>=18'}
+
+ bowser@2.14.1:
+ resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
+
+ brace-expansion@5.0.9:
+ resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
+ engines: {node: 20 || >=22}
+
+ buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
+ bundle-name@4.1.0:
+ resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ engines: {node: '>=18'}
+
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
+ chalk@5.6.2:
+ resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ cli-boxes@4.0.1:
+ resolution: {integrity: sha512-5IOn+jcCEHEraYolBPs/sT4BxYCe2nHg374OPiItB1O96KZFseS2gthU4twyYzeDcFew4DaUM/xwc5BQf08JJw==}
+ engines: {node: '>=18.20 <19 || >=20.10'}
+
+ cli-cursor@4.0.0:
+ resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ cli-truncate@6.1.1:
+ resolution: {integrity: sha512-06p9vyLahLa4zkGcgsGxU6iEkSOiuI4fhCH6Emhe2lPAcoUv73n72DnODsnHA+5wwXGnV0n9M9/qOQJSjYhFhw==}
+ engines: {node: '>=22'}
+
+ code-excerpt@4.0.0:
+ resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
+ content-disposition@1.1.0:
+ resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
+ engines: {node: '>=18'}
+
+ content-type@1.0.5:
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+ engines: {node: '>= 0.6'}
+
+ content-type@2.0.0:
+ resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==}
+ engines: {node: '>=18'}
+
+ convert-to-spaces@2.0.1:
+ resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ cookie-signature@1.2.2:
+ resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
+ engines: {node: '>=6.6.0'}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
+ cors@2.8.6:
+ resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==}
+ engines: {node: '>= 0.10'}
+
+ cron-parser@5.8.1:
+ resolution: {integrity: sha512-fVw5nGEkTVmiPKo3fY0j28Thq6jR00VKWyL22llWrsbII4sDHI+8Kx1kcL+QzGQJfCfk64bbMotrgTZRpzYpLQ==}
+ engines: {node: '>=18'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ default-browser-id@5.0.1:
+ resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
+ engines: {node: '>=18'}
+
+ default-browser@5.5.0:
+ resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==}
+ engines: {node: '>=18'}
+
+ define-lazy-prop@3.0.0:
+ resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+ engines: {node: '>=12'}
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
+ diff@8.0.3:
+ resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==}
+ engines: {node: '>=0.3.1'}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ ecdsa-sig-formatter@1.0.11:
+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
+ environment@1.1.0:
+ resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
+ engines: {node: '>=18'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.2:
+ resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
+ engines: {node: '>= 0.4'}
+
+ es-toolkit@1.50.0:
+ resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==}
+
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+ escape-string-regexp@2.0.0:
+ resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+ engines: {node: '>=8'}
+
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ eventsource-parser@3.1.1:
+ resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==}
+ engines: {node: '>=18.0.0'}
+
+ eventsource@3.0.7:
+ resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
+ engines: {node: '>=18.0.0'}
+
+ express-rate-limit@8.6.2:
+ resolution: {integrity: sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==}
+ engines: {node: '>= 16'}
+ peerDependencies:
+ express: '>= 4.11'
+
+ express@5.2.1:
+ resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
+ engines: {node: '>= 18'}
+
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-uri@3.1.5:
+ resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==}
+
+ fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+
+ finalhandler@2.1.1:
+ resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==}
+ engines: {node: '>= 18.0.0'}
+
+ formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ gaxios@7.3.0:
+ resolution: {integrity: sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==}
+ engines: {node: '>=18'}
+
+ gcp-metadata@8.1.2:
+ resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==}
+ engines: {node: '>=18'}
+
+ get-east-asian-width@1.6.0:
+ resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
+ engines: {node: '>=18'}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
+ google-auth-library@10.9.1:
+ resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==}
+ engines: {node: '>=18'}
+
+ google-logging-utils@1.1.3:
+ resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==}
+ engines: {node: '>=14'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ has-flag@5.0.1:
+ resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==}
+ engines: {node: '>=12'}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.4:
+ resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+ engines: {node: '>= 0.4'}
+
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ hono@4.13.1:
+ resolution: {integrity: sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==}
+ engines: {node: '>=16.9.0'}
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
+ http-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ engines: {node: '>= 14'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ iconv-lite@0.7.3:
+ resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==}
+ engines: {node: '>=0.10.0'}
+
+ indent-string@5.0.0:
+ resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
+ engines: {node: '>=12'}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ink-link@5.0.0:
+ resolution: {integrity: sha512-TFDXc/0mwUW7LMjsr0/LeLxPVV5BnHDuDQff9RCgP4rb3R+V/4dIwGBZbCevcJZtQnVcW+Iz1LUrUbpq+UDwYA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ ink: '>=6'
+
+ ink@7.1.1:
+ resolution: {integrity: sha512-Y43xxa1ZSPvpmfLHcN5o+OdP8Rf8ykkNJEuKYOUNZKT8wXVNLFTtEm1nSDMQkfBH+YANF4Xuu0hhZ4ejqAtN2w==}
+ engines: {node: '>=22'}
+ peerDependencies:
+ '@types/react': '>=19.2.0'
+ react: '>=19.2.0'
+ react-devtools-core: '>=6.1.2'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react-devtools-core:
+ optional: true
+
+ ip-address@10.5.0:
+ resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==}
+ engines: {node: '>= 12'}
+
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
+ is-fullwidth-code-point@5.1.0:
+ resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
+ engines: {node: '>=18'}
+
+ is-in-ci@2.0.0:
+ resolution: {integrity: sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
+ is-wsl@3.1.1:
+ resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
+ engines: {node: '>=16'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jose@6.2.8:
+ resolution: {integrity: sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ json-bigint@1.0.0:
+ resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
+
+ json-schema-to-ts@3.1.1:
+ resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==}
+ engines: {node: '>=16'}
+
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+ json-schema-typed@8.0.2:
+ resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==}
+
+ jwa@2.0.1:
+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
+
+ jws@4.0.1:
+ resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
+
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ lru-cache@11.5.2:
+ resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
+ engines: {node: 20 || >=22}
+
+ lru_map@0.4.1:
+ resolution: {integrity: sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==}
+
+ luxon@3.7.2:
+ resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
+ engines: {node: '>=12'}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ media-typer@1.1.1:
+ resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==}
+ engines: {node: '>= 0.8'}
+
+ merge-descriptors@2.0.0:
+ resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
+ engines: {node: '>=18'}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@3.0.2:
+ resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
+ engines: {node: '>=18'}
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ minimatch@10.2.6:
+ resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
+ engines: {node: 18 || 20 || >=22}
+
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
+ node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ deprecated: Use your platform's native DOMException instead
+
+ node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ node-pty@1.1.0:
+ resolution: {integrity: sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ oniguruma-parser@0.12.2:
+ resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==}
+
+ oniguruma-to-es@4.3.6:
+ resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==}
+
+ open@10.2.0:
+ resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
+ engines: {node: '>=18'}
+
+ openai@6.26.0:
+ resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==}
+ hasBin: true
+ peerDependencies:
+ ws: ^8.18.0
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ ws:
+ optional: true
+ zod:
+ optional: true
+
+ p-retry@4.6.2:
+ resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
+ engines: {node: '>=8'}
+
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
+ partial-json@0.1.7:
+ resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==}
+
+ patch-console@2.0.0:
+ resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
+ path-to-regexp@8.4.2:
+ resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
+
+ pkce-challenge@5.0.1:
+ resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==}
+ engines: {node: '>=16.20.0'}
+
+ property-information@7.2.0:
+ resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
+
+ protobufjs@7.6.5:
+ resolution: {integrity: sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==}
+ engines: {node: '>=12.0.0'}
+
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
+ qs@6.15.3:
+ resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==}
+ engines: {node: '>=0.6'}
+
+ range-parser@1.3.0:
+ resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==}
+ engines: {node: '>= 0.6'}
+
+ raw-body@3.0.2:
+ resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==}
+ engines: {node: '>= 0.10'}
+
+ react-dom@19.2.8:
+ resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
+ peerDependencies:
+ react: ^19.2.8
+
+ react-reconciler@0.33.0:
+ resolution: {integrity: sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==}
+ engines: {node: '>=0.10.0'}
+ peerDependencies:
+ react: ^19.2.0
+
+ react@18.2.0:
+ resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
+ engines: {node: '>=0.10.0'}
+
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.1.0:
+ resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ restore-cursor@4.0.0:
+ resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
+ router@2.2.0:
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+ engines: {node: '>= 18'}
+
+ run-applescript@7.1.0:
+ resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+ engines: {node: '>=18'}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+ semver@7.8.5:
+ resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ send@1.2.1:
+ resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
+ engines: {node: '>= 18'}
+
+ serve-static@2.2.1:
+ resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
+ engines: {node: '>= 18'}
+
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+ sharp@0.34.5:
+ resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ shiki@3.23.0:
+ resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==}
+
+ shiki@4.4.3:
+ resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==}
+ engines: {node: '>=20'}
+
+ side-channel-list@1.0.1:
+ resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.1:
+ resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
+ engines: {node: '>= 0.4'}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ slice-ansi@9.0.0:
+ resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==}
+ engines: {node: '>=22'}
+
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
+ stack-utils@2.0.6:
+ resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+ engines: {node: '>=10'}
+
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
+ string-width@8.2.2:
+ resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==}
+ engines: {node: '>=20'}
+
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
+ strip-ansi@7.2.0:
+ resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
+ engines: {node: '>=12'}
+
+ supports-color@10.2.2:
+ resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
+ engines: {node: '>=18'}
+
+ supports-hyperlinks@4.5.0:
+ resolution: {integrity: sha512-ZW2OvfeCXrNTbLakPUzjQG922EeGCOteFSVoek5DKStTh898wf7zgtuFlzQN8HfZCxC3Eh02yJVrRW51hADf+w==}
+ engines: {node: '>=20'}
+
+ tagged-tag@1.0.0:
+ resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
+ engines: {node: '>=20'}
+
+ terminal-link@5.0.0:
+ resolution: {integrity: sha512-qFAy10MTMwjzjU8U16YS4YoZD+NQLHzLssFMNqgravjbvIPNiqkGFR4yjhJfmY9R5OFU7+yHxc6y+uGHkKwLRA==}
+ engines: {node: '>=20'}
+
+ terminal-size@4.0.1:
+ resolution: {integrity: sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==}
+ engines: {node: '>=18'}
+
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ ts-algebra@2.0.0:
+ resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ type-fest@5.8.0:
+ resolution: {integrity: sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==}
+ engines: {node: '>=20'}
+
+ type-is@2.1.0:
+ resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
+ engines: {node: '>= 18'}
+
+ typebox@1.1.38:
+ resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==}
+
+ undici-types@8.3.0:
+ resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.1.0:
+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
+ web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ widest-line@6.0.0:
+ resolution: {integrity: sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA==}
+ engines: {node: '>=20'}
+
+ wrap-ansi@10.0.0:
+ resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==}
+ engines: {node: '>=20'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ ws@8.21.3:
+ resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ wsl-utils@0.1.0:
+ resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
+ engines: {node: '>=18'}
+
+ yoga-layout@3.2.1:
+ resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==}
+
+ zod-to-json-schema@3.25.2:
+ resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==}
+ peerDependencies:
+ zod: ^3.25.28 || ^4
+
+ zod@4.4.3:
+ resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
+
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
+snapshots:
+
+ '@alcalzone/ansi-tokenize@0.3.0':
+ dependencies:
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 5.1.0
+
+ '@anthropic-ai/sdk@0.91.1(zod@4.4.3)':
+ dependencies:
+ json-schema-to-ts: 3.1.1
+ optionalDependencies:
+ zod: 4.4.3
+
+ '@aws-crypto/sha256-browser@5.2.0':
+ dependencies:
+ '@aws-crypto/sha256-js': 5.2.0
+ '@aws-crypto/supports-web-crypto': 5.2.0
+ '@aws-crypto/util': 5.2.0
+ '@aws-sdk/types': 3.974.3
+ '@aws-sdk/util-locate-window': 3.965.9
+ '@smithy/util-utf8': 2.3.0
+ tslib: 2.8.1
+
+ '@aws-crypto/sha256-js@5.2.0':
+ dependencies:
+ '@aws-crypto/util': 5.2.0
+ '@aws-sdk/types': 3.974.3
+ tslib: 2.8.1
+
+ '@aws-crypto/supports-web-crypto@5.2.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@aws-crypto/util@5.2.0':
+ dependencies:
+ '@aws-sdk/types': 3.974.3
+ '@smithy/util-utf8': 2.3.0
+ tslib: 2.8.1
+
+ '@aws-sdk/client-bedrock-runtime@3.1048.0':
+ dependencies:
+ '@aws-crypto/sha256-browser': 5.2.0
+ '@aws-crypto/sha256-js': 5.2.0
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/credential-provider-node': 3.972.79
+ '@aws-sdk/eventstream-handler-node': 3.972.32
+ '@aws-sdk/middleware-eventstream': 3.972.27
+ '@aws-sdk/middleware-websocket': 3.972.50
+ '@aws-sdk/token-providers': 3.1048.0
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/fetch-http-handler': 5.7.0
+ '@smithy/node-http-handler': 4.10.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/core@3.977.7':
+ dependencies:
+ '@aws-sdk/types': 3.974.3
+ '@aws-sdk/xml-builder': 3.972.38
+ '@aws/lambda-invoke-store': 0.3.0
+ '@smithy/core': 3.32.0
+ '@smithy/signature-v4': 5.7.0
+ '@smithy/types': 4.17.0
+ bowser: 2.14.1
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-env@3.972.68':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-http@3.972.70':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/fetch-http-handler': 5.7.0
+ '@smithy/node-http-handler': 4.10.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-ini@3.973.13':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/credential-provider-env': 3.972.68
+ '@aws-sdk/credential-provider-http': 3.972.70
+ '@aws-sdk/credential-provider-login': 3.972.75
+ '@aws-sdk/credential-provider-process': 3.972.68
+ '@aws-sdk/credential-provider-sso': 3.973.12
+ '@aws-sdk/credential-provider-web-identity': 3.972.74
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/credential-provider-imds': 4.5.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-login@3.972.75':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-node@3.972.79':
+ dependencies:
+ '@aws-sdk/credential-provider-env': 3.972.68
+ '@aws-sdk/credential-provider-http': 3.972.70
+ '@aws-sdk/credential-provider-ini': 3.973.13
+ '@aws-sdk/credential-provider-process': 3.972.68
+ '@aws-sdk/credential-provider-sso': 3.973.12
+ '@aws-sdk/credential-provider-web-identity': 3.972.74
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/credential-provider-imds': 4.5.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-process@3.972.68':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-sso@3.973.12':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/token-providers': 3.1108.0
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/credential-provider-web-identity@3.972.74':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/eventstream-handler-node@3.972.32':
+ dependencies:
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/middleware-eventstream@3.972.27':
+ dependencies:
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/middleware-websocket@3.972.50':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/fetch-http-handler': 5.7.0
+ '@smithy/signature-v4': 5.7.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/nested-clients@3.997.42':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/signature-v4-multi-region': 3.996.44
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/fetch-http-handler': 5.7.0
+ '@smithy/node-http-handler': 4.10.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/signature-v4-multi-region@3.996.44':
+ dependencies:
+ '@aws-sdk/types': 3.974.3
+ '@smithy/signature-v4': 5.7.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/token-providers@3.1048.0':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/token-providers@3.1108.0':
+ dependencies:
+ '@aws-sdk/core': 3.977.7
+ '@aws-sdk/nested-clients': 3.997.42
+ '@aws-sdk/types': 3.974.3
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/types@3.974.3':
+ dependencies:
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws-sdk/util-locate-window@3.965.9':
+ dependencies:
+ tslib: 2.8.1
+
+ '@aws-sdk/xml-builder@3.972.38':
+ dependencies:
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@aws/lambda-invoke-store@0.3.0': {}
+
+ '@babel/runtime@7.29.7': {}
+
+ '@earendil-works/pi-ai@0.82.1(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.3)(zod@4.4.3)':
+ dependencies:
+ '@anthropic-ai/sdk': 0.91.1(zod@4.4.3)
+ '@aws-sdk/client-bedrock-runtime': 3.1048.0
+ '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))
+ '@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0)
+ '@opentelemetry/api': 1.9.0
+ '@smithy/node-http-handler': 4.7.3
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ openai: 6.26.0(ws@8.21.3)(zod@4.4.3)
+ partial-json: 0.1.7
+ typebox: 1.1.38
+ transitivePeerDependencies:
+ - '@modelcontextprotocol/sdk'
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ - ws
+ - zod
+
+ '@emnapi/runtime@1.11.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))':
+ dependencies:
+ google-auth-library: 10.9.1
+ p-retry: 4.6.2
+ protobufjs: 7.6.5
+ ws: 8.21.3
+ optionalDependencies:
+ '@modelcontextprotocol/sdk': 1.30.0(zod@4.4.3)
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@hono/node-server@2.1.0(hono@4.13.1)':
+ dependencies:
+ hono: 4.13.1
+
+ '@img/colour@1.1.0': {}
+
+ '@img/sharp-darwin-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-darwin-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-linux-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-arm@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-ppc64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-s390x@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-wasm32@0.34.5':
+ dependencies:
+ '@emnapi/runtime': 1.11.3
+ optional: true
+
+ '@img/sharp-win32-arm64@0.34.5':
+ optional: true
+
+ '@img/sharp-win32-ia32@0.34.5':
+ optional: true
+
+ '@img/sharp-win32-x64@0.34.5':
+ optional: true
+
+ '@letta-ai/letta-agent-sdk@0.7.1(ink@7.1.1(react@18.2.0))(react-dom@19.2.8(react@18.2.0))(zod@4.4.3)':
+ dependencies:
+ '@letta-ai/letta-client': 1.12.1
+ '@letta-ai/letta-code': 0.30.11(ink@7.1.1(react@18.2.0))(react-dom@19.2.8(react@18.2.0))(zod@4.4.3)
+ transitivePeerDependencies:
+ - '@cfworker/json-schema'
+ - bufferutil
+ - ink
+ - react-dom
+ - supports-color
+ - utf-8-validate
+ - zod
+
+ '@letta-ai/letta-client@1.12.1': {}
+
+ '@letta-ai/letta-code@0.30.11(ink@7.1.1(react@18.2.0))(react-dom@19.2.8(react@18.2.0))(zod@4.4.3)':
+ dependencies:
+ '@earendil-works/pi-ai': 0.82.1(@modelcontextprotocol/sdk@1.30.0(zod@4.4.3))(ws@8.21.3)(zod@4.4.3)
+ '@letta-ai/letta-client': 1.12.1
+ '@letta-ai/trajectory': 0.2.0
+ '@modelcontextprotocol/sdk': 1.30.0(zod@4.4.3)
+ '@pierre/diffs': 1.2.2(react-dom@19.2.8(react@18.2.0))(react@18.2.0)
+ '@scarf/scarf': 1.4.0
+ cron-parser: 5.8.1
+ cross-spawn: 7.0.6
+ glob: 13.0.6
+ ink-link: 5.0.0(ink@7.1.1(react@18.2.0))
+ node-pty: 1.1.0
+ open: 10.2.0
+ react: 18.2.0
+ sharp: 0.34.5
+ shiki: 4.4.3
+ strip-ansi: 7.2.0
+ ws: 8.21.3
+ optionalDependencies:
+ '@vscode/ripgrep': 1.18.0
+ transitivePeerDependencies:
+ - '@cfworker/json-schema'
+ - bufferutil
+ - ink
+ - react-dom
+ - supports-color
+ - utf-8-validate
+ - zod
+
+ '@letta-ai/trajectory@0.2.0': {}
+
+ '@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)':
+ dependencies:
+ '@opentelemetry/semantic-conventions': 1.43.0
+ ws: 8.21.3
+ zod: 4.4.3
+ zod-to-json-schema: 3.25.2(zod@4.4.3)
+ optionalDependencies:
+ '@opentelemetry/api': 1.9.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)':
+ dependencies:
+ '@hono/node-server': 2.1.0(hono@4.13.1)
+ ajv: 8.20.0
+ ajv-formats: 3.0.1(ajv@8.20.0)
+ content-type: 1.0.5
+ cors: 2.8.6
+ cross-spawn: 7.0.6
+ eventsource: 3.0.7
+ eventsource-parser: 3.1.1
+ express: 5.2.1
+ express-rate-limit: 8.6.2(express@5.2.1)
+ hono: 4.13.1
+ jose: 6.2.8
+ json-schema-typed: 8.0.2
+ pkce-challenge: 5.0.1
+ raw-body: 3.0.2
+ zod: 4.4.3
+ zod-to-json-schema: 3.25.2(zod@4.4.3)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/api@1.9.0': {}
+
+ '@opentelemetry/semantic-conventions@1.43.0': {}
+
+ '@pierre/diffs@1.2.2(react-dom@19.2.8(react@18.2.0))(react@18.2.0)':
+ dependencies:
+ '@pierre/theme': 1.0.3
+ '@shikijs/transformers': 3.23.0
+ diff: 8.0.3
+ hast-util-to-html: 9.0.5
+ lru_map: 0.4.1
+ react: 18.2.0
+ react-dom: 19.2.8(react@18.2.0)
+ shiki: 3.23.0
+
+ '@pierre/theme@1.0.3': {}
+
+ '@protobufjs/aspromise@1.1.2': {}
+
+ '@protobufjs/base64@1.1.2': {}
+
+ '@protobufjs/codegen@2.0.5': {}
+
+ '@protobufjs/eventemitter@1.1.1': {}
+
+ '@protobufjs/fetch@1.1.1':
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+
+ '@protobufjs/float@1.0.2': {}
+
+ '@protobufjs/path@1.1.2': {}
+
+ '@protobufjs/pool@1.1.0': {}
+
+ '@protobufjs/utf8@1.1.2': {}
+
+ '@scarf/scarf@1.4.0': {}
+
+ '@shikijs/core@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/core@4.4.3':
+ dependencies:
+ '@shikijs/primitive': 4.4.3
+ '@shikijs/types': 4.4.3
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.6
+
+ '@shikijs/engine-javascript@4.4.3':
+ dependencies:
+ '@shikijs/types': 4.4.3
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.6
+
+ '@shikijs/engine-oniguruma@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/engine-oniguruma@4.4.3':
+ dependencies:
+ '@shikijs/types': 4.4.3
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+
+ '@shikijs/langs@4.4.3':
+ dependencies:
+ '@shikijs/types': 4.4.3
+
+ '@shikijs/primitive@4.4.3':
+ dependencies:
+ '@shikijs/types': 4.4.3
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+
+ '@shikijs/themes@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+
+ '@shikijs/themes@4.4.3':
+ dependencies:
+ '@shikijs/types': 4.4.3
+
+ '@shikijs/transformers@3.23.0':
+ dependencies:
+ '@shikijs/core': 3.23.0
+ '@shikijs/types': 3.23.0
+
+ '@shikijs/types@3.23.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+
+ '@shikijs/types@4.4.3':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
+ '@smithy/core@3.32.0':
+ dependencies:
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/credential-provider-imds@4.5.0':
+ dependencies:
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/fetch-http-handler@5.7.0':
+ dependencies:
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/is-array-buffer@2.2.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@smithy/node-http-handler@4.10.0':
+ dependencies:
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/node-http-handler@4.7.3':
+ dependencies:
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/signature-v4@5.7.0':
+ dependencies:
+ '@smithy/core': 3.32.0
+ '@smithy/types': 4.17.0
+ tslib: 2.8.1
+
+ '@smithy/types@4.17.0':
+ dependencies:
+ tslib: 2.8.1
+
+ '@smithy/util-buffer-from@2.2.0':
+ dependencies:
+ '@smithy/is-array-buffer': 2.2.0
+ tslib: 2.8.1
+
+ '@smithy/util-utf8@2.3.0':
+ dependencies:
+ '@smithy/util-buffer-from': 2.2.0
+ tslib: 2.8.1
+
+ '@types/hast@3.0.5':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/node@26.2.0':
+ dependencies:
+ undici-types: 8.3.0
+
+ '@types/retry@0.12.0': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@ungap/structured-clone@1.3.3': {}
+
+ '@vscode/ripgrep-darwin-arm64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-darwin-x64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-arm64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-arm@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-ia32@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-ppc64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-riscv64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-s390x@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-linux-x64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-win32-arm64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-win32-ia32@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep-win32-x64@1.18.0':
+ optional: true
+
+ '@vscode/ripgrep@1.18.0':
+ optionalDependencies:
+ '@vscode/ripgrep-darwin-arm64': 1.18.0
+ '@vscode/ripgrep-darwin-x64': 1.18.0
+ '@vscode/ripgrep-linux-arm': 1.18.0
+ '@vscode/ripgrep-linux-arm64': 1.18.0
+ '@vscode/ripgrep-linux-ia32': 1.18.0
+ '@vscode/ripgrep-linux-ppc64': 1.18.0
+ '@vscode/ripgrep-linux-riscv64': 1.18.0
+ '@vscode/ripgrep-linux-s390x': 1.18.0
+ '@vscode/ripgrep-linux-x64': 1.18.0
+ '@vscode/ripgrep-win32-arm64': 1.18.0
+ '@vscode/ripgrep-win32-ia32': 1.18.0
+ '@vscode/ripgrep-win32-x64': 1.18.0
+ optional: true
+
+ accepts@2.0.0:
+ dependencies:
+ mime-types: 3.0.2
+ negotiator: 1.0.0
+
+ agent-base@7.1.4: {}
+
+ ajv-formats@3.0.1(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
+ ajv@8.20.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-uri: 3.1.5
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+
+ ansi-escapes@7.3.0:
+ dependencies:
+ environment: 1.1.0
+
+ ansi-regex@6.2.2: {}
+
+ ansi-styles@6.2.3: {}
+
+ auto-bind@5.0.1: {}
+
+ balanced-match@4.0.4: {}
+
+ base64-js@1.5.1: {}
+
+ bignumber.js@9.3.1: {}
+
+ body-parser@2.3.0:
+ dependencies:
+ bytes: 3.1.2
+ content-type: 2.0.0
+ debug: 4.4.3
+ http-errors: 2.0.1
+ iconv-lite: 0.7.3
+ on-finished: 2.4.1
+ qs: 6.15.3
+ raw-body: 3.0.2
+ type-is: 2.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ bowser@2.14.1: {}
+
+ brace-expansion@5.0.9:
+ dependencies:
+ balanced-match: 4.0.4
+
+ buffer-equal-constant-time@1.0.1: {}
+
+ bundle-name@4.1.0:
+ dependencies:
+ run-applescript: 7.1.0
+
+ bytes@3.1.2: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ ccount@2.0.1: {}
+
+ chalk@5.6.2: {}
+
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ cli-boxes@4.0.1: {}
+
+ cli-cursor@4.0.0:
+ dependencies:
+ restore-cursor: 4.0.0
+
+ cli-truncate@6.1.1:
+ dependencies:
+ slice-ansi: 9.0.0
+ string-width: 8.2.2
+
+ code-excerpt@4.0.0:
+ dependencies:
+ convert-to-spaces: 2.0.1
+
+ comma-separated-tokens@2.0.3: {}
+
+ content-disposition@1.1.0: {}
+
+ content-type@1.0.5: {}
+
+ content-type@2.0.0: {}
+
+ convert-to-spaces@2.0.1: {}
+
+ cookie-signature@1.2.2: {}
+
+ cookie@0.7.2: {}
+
+ cors@2.8.6:
+ dependencies:
+ object-assign: 4.1.1
+ vary: 1.1.2
+
+ cron-parser@5.8.1:
+ dependencies:
+ luxon: 3.7.2
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ data-uri-to-buffer@4.0.1: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ default-browser-id@5.0.1: {}
+
+ default-browser@5.5.0:
+ dependencies:
+ bundle-name: 4.1.0
+ default-browser-id: 5.0.1
+
+ define-lazy-prop@3.0.0: {}
+
+ depd@2.0.0: {}
+
+ dequal@2.0.3: {}
+
+ detect-libc@2.1.2: {}
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
+ diff@8.0.3: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ ecdsa-sig-formatter@1.0.11:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ ee-first@1.1.1: {}
+
+ encodeurl@2.0.0: {}
+
+ environment@1.1.0: {}
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-object-atoms@1.1.2:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-toolkit@1.50.0: {}
+
+ escape-html@1.0.3: {}
+
+ escape-string-regexp@2.0.0: {}
+
+ etag@1.8.1: {}
+
+ eventsource-parser@3.1.1: {}
+
+ eventsource@3.0.7:
+ dependencies:
+ eventsource-parser: 3.1.1
+
+ express-rate-limit@8.6.2(express@5.2.1):
+ dependencies:
+ debug: 4.4.3
+ express: 5.2.1
+ ip-address: 10.5.0
+ transitivePeerDependencies:
+ - supports-color
+
+ express@5.2.1:
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.3.0
+ content-disposition: 1.1.0
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.2.2
+ debug: 4.4.3
+ depd: 2.0.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 2.1.1
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ merge-descriptors: 2.0.0
+ mime-types: 3.0.2
+ on-finished: 2.4.1
+ once: 1.4.0
+ parseurl: 1.3.3
+ proxy-addr: 2.0.7
+ qs: 6.15.3
+ range-parser: 1.3.0
+ router: 2.2.0
+ send: 1.2.1
+ serve-static: 2.2.1
+ statuses: 2.0.2
+ type-is: 2.1.0
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ extend@3.0.2: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-uri@3.1.5: {}
+
+ fetch-blob@3.2.0:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+
+ finalhandler@2.1.1:
+ dependencies:
+ debug: 4.4.3
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ formdata-polyfill@4.0.10:
+ dependencies:
+ fetch-blob: 3.2.0
+
+ forwarded@0.2.0: {}
+
+ fresh@2.0.0: {}
+
+ function-bind@1.1.2: {}
+
+ gaxios@7.3.0:
+ dependencies:
+ extend: 3.0.2
+ https-proxy-agent: 7.0.6
+ node-fetch: 3.3.2
+ transitivePeerDependencies:
+ - supports-color
+
+ gcp-metadata@8.1.2:
+ dependencies:
+ gaxios: 7.3.0
+ google-logging-utils: 1.1.3
+ json-bigint: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ get-east-asian-width@1.6.0: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.2
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.4
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.2
+
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.6
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
+ google-auth-library@10.9.1:
+ dependencies:
+ base64-js: 1.5.1
+ ecdsa-sig-formatter: 1.0.11
+ gaxios: 7.3.0
+ gcp-metadata: 8.1.2
+ google-logging-utils: 1.1.3
+ jws: 4.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ google-logging-utils@1.1.3: {}
+
+ gopd@1.2.0: {}
+
+ has-flag@5.0.1: {}
+
+ has-symbols@1.1.0: {}
+
+ hasown@2.0.4:
+ dependencies:
+ function-bind: 1.1.2
+
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.5
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.5
+
+ hono@4.13.1: {}
+
+ html-void-elements@3.0.0: {}
+
+ http-errors@2.0.1:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ toidentifier: 1.0.1
+
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ iconv-lite@0.7.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ indent-string@5.0.0: {}
+
+ inherits@2.0.4: {}
+
+ ink-link@5.0.0(ink@7.1.1(react@18.2.0)):
+ dependencies:
+ ink: 7.1.1(react@18.2.0)
+ terminal-link: 5.0.0
+
+ ink@7.1.1(react@18.2.0):
+ dependencies:
+ '@alcalzone/ansi-tokenize': 0.3.0
+ ansi-escapes: 7.3.0
+ ansi-styles: 6.2.3
+ auto-bind: 5.0.1
+ chalk: 5.6.2
+ cli-boxes: 4.0.1
+ cli-cursor: 4.0.0
+ cli-truncate: 6.1.1
+ code-excerpt: 4.0.0
+ es-toolkit: 1.50.0
+ indent-string: 5.0.0
+ is-in-ci: 2.0.0
+ patch-console: 2.0.0
+ react: 18.2.0
+ react-reconciler: 0.33.0(react@18.2.0)
+ scheduler: 0.27.0
+ signal-exit: 3.0.7
+ slice-ansi: 9.0.0
+ stack-utils: 2.0.6
+ string-width: 8.2.2
+ terminal-size: 4.0.1
+ type-fest: 5.8.0
+ widest-line: 6.0.0
+ wrap-ansi: 10.0.0
+ ws: 8.21.3
+ yoga-layout: 3.2.1
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ ip-address@10.5.0: {}
+
+ ipaddr.js@1.9.1: {}
+
+ is-docker@3.0.0: {}
+
+ is-fullwidth-code-point@5.1.0:
+ dependencies:
+ get-east-asian-width: 1.6.0
+
+ is-in-ci@2.0.0: {}
+
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
+ is-promise@4.0.0: {}
+
+ is-wsl@3.1.1:
+ dependencies:
+ is-inside-container: 1.0.0
+
+ isexe@2.0.0: {}
+
+ jose@6.2.8: {}
+
+ js-tokens@4.0.0: {}
+
+ json-bigint@1.0.0:
+ dependencies:
+ bignumber.js: 9.3.1
+
+ json-schema-to-ts@3.1.1:
+ dependencies:
+ '@babel/runtime': 7.29.7
+ ts-algebra: 2.0.0
+
+ json-schema-traverse@1.0.0: {}
+
+ json-schema-typed@8.0.2: {}
+
+ jwa@2.0.1:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+
+ jws@4.0.1:
+ dependencies:
+ jwa: 2.0.1
+ safe-buffer: 5.2.1
+
+ long@5.3.2: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ lru-cache@11.5.2: {}
+
+ lru_map@0.4.1: {}
+
+ luxon@3.7.2: {}
+
+ math-intrinsics@1.1.0: {}
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.3
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+
+ media-typer@1.1.1: {}
+
+ merge-descriptors@2.0.0: {}
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ mime-db@1.54.0: {}
+
+ mime-types@3.0.2:
+ dependencies:
+ mime-db: 1.54.0
+
+ mimic-fn@2.1.0: {}
+
+ minimatch@10.2.6:
+ dependencies:
+ brace-expansion: 5.0.9
+
+ minipass@7.1.3: {}
+
+ ms@2.1.3: {}
+
+ negotiator@1.0.0: {}
+
+ node-addon-api@7.1.1: {}
+
+ node-domexception@1.0.0: {}
+
+ node-fetch@3.3.2:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
+ node-pty@1.1.0:
+ dependencies:
+ node-addon-api: 7.1.1
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.4: {}
+
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ oniguruma-parser@0.12.2: {}
+
+ oniguruma-to-es@4.3.6:
+ dependencies:
+ oniguruma-parser: 0.12.2
+ regex: 6.1.0
+ regex-recursion: 6.0.2
+
+ open@10.2.0:
+ dependencies:
+ default-browser: 5.5.0
+ define-lazy-prop: 3.0.0
+ is-inside-container: 1.0.0
+ wsl-utils: 0.1.0
+
+ openai@6.26.0(ws@8.21.3)(zod@4.4.3):
+ optionalDependencies:
+ ws: 8.21.3
+ zod: 4.4.3
+
+ p-retry@4.6.2:
+ dependencies:
+ '@types/retry': 0.12.0
+ retry: 0.13.1
+
+ parseurl@1.3.3: {}
+
+ partial-json@0.1.7: {}
+
+ patch-console@2.0.0: {}
+
+ path-key@3.1.1: {}
+
+ path-scurry@2.0.2:
+ dependencies:
+ lru-cache: 11.5.2
+ minipass: 7.1.3
+
+ path-to-regexp@8.4.2: {}
+
+ pkce-challenge@5.0.1: {}
+
+ property-information@7.2.0: {}
+
+ protobufjs@7.6.5:
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/base64': 1.1.2
+ '@protobufjs/codegen': 2.0.5
+ '@protobufjs/eventemitter': 1.1.1
+ '@protobufjs/fetch': 1.1.1
+ '@protobufjs/float': 1.0.2
+ '@protobufjs/path': 1.1.2
+ '@protobufjs/pool': 1.1.0
+ '@protobufjs/utf8': 1.1.2
+ '@types/node': 26.2.0
+ long: 5.3.2
+
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.1
+
+ qs@6.15.3:
+ dependencies:
+ es-define-property: 1.0.1
+ side-channel: 1.1.1
+
+ range-parser@1.3.0: {}
+
+ raw-body@3.0.2:
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.1
+ iconv-lite: 0.7.3
+ unpipe: 1.0.0
+
+ react-dom@19.2.8(react@18.2.0):
+ dependencies:
+ react: 18.2.0
+ scheduler: 0.27.0
+
+ react-reconciler@0.33.0(react@18.2.0):
+ dependencies:
+ react: 18.2.0
+ scheduler: 0.27.0
+
+ react@18.2.0:
+ dependencies:
+ loose-envify: 1.4.0
+
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.1.0:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ require-from-string@2.0.2: {}
+
+ restore-cursor@4.0.0:
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+
+ retry@0.13.1: {}
+
+ router@2.2.0:
+ dependencies:
+ debug: 4.4.3
+ depd: 2.0.0
+ is-promise: 4.0.0
+ parseurl: 1.3.3
+ path-to-regexp: 8.4.2
+ transitivePeerDependencies:
+ - supports-color
+
+ run-applescript@7.1.0: {}
+
+ safe-buffer@5.2.1: {}
+
+ safer-buffer@2.1.2: {}
+
+ scheduler@0.27.0: {}
+
+ semver@7.8.5: {}
+
+ send@1.2.1:
+ dependencies:
+ debug: 4.4.3
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ mime-types: 3.0.2
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.3.0
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ serve-static@2.2.1:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 1.2.1
+ transitivePeerDependencies:
+ - supports-color
+
+ setprototypeof@1.2.0: {}
+
+ sharp@0.34.5:
+ dependencies:
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.5
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.34.5
+ '@img/sharp-darwin-x64': 0.34.5
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ '@img/sharp-linux-arm': 0.34.5
+ '@img/sharp-linux-arm64': 0.34.5
+ '@img/sharp-linux-ppc64': 0.34.5
+ '@img/sharp-linux-riscv64': 0.34.5
+ '@img/sharp-linux-s390x': 0.34.5
+ '@img/sharp-linux-x64': 0.34.5
+ '@img/sharp-linuxmusl-arm64': 0.34.5
+ '@img/sharp-linuxmusl-x64': 0.34.5
+ '@img/sharp-wasm32': 0.34.5
+ '@img/sharp-win32-arm64': 0.34.5
+ '@img/sharp-win32-ia32': 0.34.5
+ '@img/sharp-win32-x64': 0.34.5
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ shiki@3.23.0:
+ dependencies:
+ '@shikijs/core': 3.23.0
+ '@shikijs/engine-javascript': 3.23.0
+ '@shikijs/engine-oniguruma': 3.23.0
+ '@shikijs/langs': 3.23.0
+ '@shikijs/themes': 3.23.0
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+
+ shiki@4.4.3:
+ dependencies:
+ '@shikijs/core': 4.4.3
+ '@shikijs/engine-javascript': 4.4.3
+ '@shikijs/engine-oniguruma': 4.4.3
+ '@shikijs/langs': 4.4.3
+ '@shikijs/themes': 4.4.3
+ '@shikijs/types': 4.4.3
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.5
+
+ side-channel-list@1.0.1:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.1
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
+ signal-exit@3.0.7: {}
+
+ slice-ansi@9.0.0:
+ dependencies:
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 5.1.0
+
+ space-separated-tokens@2.0.2: {}
+
+ stack-utils@2.0.6:
+ dependencies:
+ escape-string-regexp: 2.0.0
+
+ statuses@2.0.2: {}
+
+ string-width@8.2.2:
+ dependencies:
+ get-east-asian-width: 1.6.0
+ strip-ansi: 7.2.0
+
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
+ strip-ansi@7.2.0:
+ dependencies:
+ ansi-regex: 6.2.2
+
+ supports-color@10.2.2: {}
+
+ supports-hyperlinks@4.5.0:
+ dependencies:
+ has-flag: 5.0.1
+ supports-color: 10.2.2
+
+ tagged-tag@1.0.0: {}
+
+ terminal-link@5.0.0:
+ dependencies:
+ ansi-escapes: 7.3.0
+ supports-hyperlinks: 4.5.0
+
+ terminal-size@4.0.1: {}
+
+ toidentifier@1.0.1: {}
+
+ trim-lines@3.0.1: {}
+
+ ts-algebra@2.0.0: {}
+
+ tslib@2.8.1: {}
+
+ type-fest@5.8.0:
+ dependencies:
+ tagged-tag: 1.0.0
+
+ type-is@2.1.0:
+ dependencies:
+ content-type: 2.0.0
+ media-typer: 1.1.1
+ mime-types: 3.0.2
+
+ typebox@1.1.38: {}
+
+ undici-types@8.3.0: {}
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.1.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ unpipe@1.0.0: {}
+
+ vary@1.1.2: {}
+
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ web-streams-polyfill@3.3.3: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ widest-line@6.0.0:
+ dependencies:
+ string-width: 8.2.2
+
+ wrap-ansi@10.0.0:
+ dependencies:
+ ansi-styles: 6.2.3
+ string-width: 8.2.2
+ strip-ansi: 7.2.0
+
+ wrappy@1.0.2: {}
+
+ ws@8.21.3: {}
+
+ wsl-utils@0.1.0:
+ dependencies:
+ is-wsl: 3.1.1
+
+ yoga-layout@3.2.1: {}
+
+ zod-to-json-schema@3.25.2(zod@4.4.3):
+ dependencies:
+ zod: 4.4.3
+
+ zod@4.4.3: {}
+
+ zwitch@2.0.4: {}
diff --git a/wiki/log/decisions/2026-08-12.md b/wiki/log/decisions/2026-08-12.md
new file mode 100644
--- /dev/null
+++ b/wiki/log/decisions/2026-08-12.md
@@ -0,0 +1,47 @@
+# Decisions — 2026-08-12
+
+```
+Type: log
+```
+
+## Landing observation is one exact read, not another landing path
+
+### DECIDED
+
+- One exact candidate may be classified as `ready`, `blocked`, `landed`, or
+ `inconsistent` by composing the repository, remote `main`, remote `pages`, public
+ site, project-operation state, cleanup, and explicit receipt authorities already
+ required by the landing workflow. The observer creates no new source of landing
+ truth.
+- Remote refs are sampled independently and their objects are fetched only into a
+ disposable bare repository. The observed checkout is fingerprinted around the
+ read. Unknown or contradictory evidence fails closed rather than becoming absence
+ or a false green.
+- The public edge receives one read. A remote `pages` snapshot carrying the exact
+ source can prove publication while an older public edge is still converging; that
+ ordinary lag is named but not polled.
+- Optional interpretation is subordinate to deterministic classification. Exactly
+ one retained agent named `Misaligned Landing Observer` is reused; absence
+ provisions it, while duplicate exact names fail closed. It has empty memory, MemFS
+ disabled, and no tools or skills. Every observation opens a fresh stateless
+ conversation over minimized evidence, and its answer cannot change the receipt.
+- Receipt production and `tools/task.sh` integration remain outside this slice. The
+ observer accepts optional exact receipts without inventing or backfilling them.
+
+### REJECTED
+
+- **Let the specialist decide whether the landing succeeded.** Interpretation is
+ useful around anomalies, but an LLM judgment is not an execution receipt.
+- **Create and delete a worker for every observation.** One retained agent preserves
+ a stable identity without carrying receipt history because every conversation is
+ fresh and stateless.
+- **Reuse the specialist's default conversation.** Prior evidence must not leak into
+ the next exact read.
+- **Fetch into, repair, deploy, notify from, schedule through, or clean the observed
+ repository.** Observation has no mutation doorway.
+- **Poll until the public edge agrees.** Remote publication and edge convergence are
+ separate facts; one read is enough unless a real deployment failure is being
+ diagnosed.
+
+Owners: [repository skills](../../process/repository-skills.md) and
+[landing workflow](../../process/workflows.md#git-conventions).
diff --git a/.agents/skills/observing-misaligned-landings/scripts/interpret-anomalies.mjs b/.agents/skills/observing-misaligned-landings/scripts/interpret-anomalies.mjs
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/scripts/interpret-anomalies.mjs
@@ -0,0 +1,312 @@
+#!/usr/bin/env node
+
+import { readFile } from "node:fs/promises";
+import { stdin } from "node:process";
+import { pathToFileURL } from "node:url";
+
+export const RECEIPT_SCHEMA = "network.comind.misaligned.landing-observation/v2";
+export const INTERPRETATION_SCHEMA =
+ "network.comind.misaligned.landing-interpretation/v1";
+export const MODEL = "letta/auto";
+export const SPECIALIST_NAME = "Misaligned Landing Observer";
+const MAX_RECEIPT_BYTES = 256 * 1024;
+const BENIGN_ANOMALY_CODES = new Set(["public_edge_converging"]);
+const INTERPRETER_SYSTEM_PROMPT = [
+ "You are the retained Misaligned Landing Observer interpreting exactly one minimized deterministic landing receipt in a fresh stateless conversation.",
+ "You have no tools, skills, repository access, or authority to mutate anything.",
+ "The supplied classifier state is authoritative and immutable; explain anomalies without changing that state, acting, or promising action.",
+].join(" ");
+
+function validateFacts(value, field) {
+ if (!Array.isArray(value)) {
+ throw new Error(`landing receipt must carry a ${field} array`);
+ }
+ for (const row of value) {
+ if (
+ !row ||
+ typeof row !== "object" ||
+ Array.isArray(row) ||
+ typeof row.code !== "string" ||
+ row.code.length === 0 ||
+ typeof row.summary !== "string" ||
+ row.summary.length === 0
+ ) {
+ throw new Error(`landing receipt ${field} entries must carry code and summary strings`);
+ }
+ }
+}
+
+export function validateReceipt(value) {
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
+ throw new Error("landing receipt must be a JSON object");
+ }
+ if (value.schema !== RECEIPT_SCHEMA) {
+ throw new Error(`unsupported landing receipt schema: ${String(value.schema)}`);
+ }
+ const states = new Set(["ready", "blocked", "landed", "inconsistent"]);
+ if (!states.has(value.state)) {
+ throw new Error(
+ "landing receipt state must be ready, blocked, landed, or inconsistent",
+ );
+ }
+ validateFacts(value.missing_steps, "missing_steps");
+ validateFacts(value.ownership_warnings, "ownership_warnings");
+ validateFacts(value.anomalies, "anomalies");
+ if (value.state === "inconsistent" && value.anomalies.length === 0) {
+ throw new Error("an inconsistent landing receipt must name at least one anomaly");
+ }
+ if (
+ value.state !== "inconsistent" &&
+ value.state !== "landed" &&
+ value.anomalies.length !== 0
+ ) {
+ throw new Error("only inconsistent or landed receipts may carry anomalies");
+ }
+ if (!value.evidence || typeof value.evidence !== "object" || Array.isArray(value.evidence)) {
+ throw new Error("landing receipt evidence must be a JSON object");
+ }
+ return value;
+}
+
+export function needsInterpretation(receipt) {
+ return validateReceipt(receipt).anomalies.some(
+ (row) => !BENIGN_ANOMALY_CODES.has(row.code),
+ );
+}
+
+function pick(source, keys) {
+ if (!source || typeof source !== "object" || Array.isArray(source)) {
+ return {};
+ }
+ return Object.fromEntries(
+ keys.filter((key) => Object.hasOwn(source, key)).map((key) => [key, source[key]]),
+ );
+}
+
+function safeFacts(rows, { summaries = true } = {}) {
+ return rows.map((row) => (summaries ? { code: row.code, summary: row.summary } : { code: row.code }));
+}
+
+/** Minimize evidence before it crosses the repository boundary. */
+export function interpretationReceipt(receipt) {
+ const value = validateReceipt(receipt);
+ const evidence = value.evidence;
+ const project = pick(evidence.project_status, [
+ "consistent",
+ "error_count",
+ "generated_ledgers_fresh",
+ "generated_work_orders_fresh",
+ "readable",
+ "target_run_ambiguous",
+ "target_worktree_ambiguous",
+ "warning_count",
+ ]);
+ project.target_run = pick(evidence.project_status?.target_run, [
+ "phase",
+ "present",
+ "status",
+ ]);
+ const target = pick(evidence.target_worktree, [
+ "ahead",
+ "behind",
+ "dirty",
+ "head_revision",
+ "present",
+ ]);
+ target.path_escape_detected = Boolean(evidence.target_worktree?.path_escape);
+
+ const receipts = {};
+ for (const kind of ["gate", "deployment", "channel"]) {
+ receipts[kind] = pick(evidence.receipts?.[kind], [
+ "channel",
+ "pages_revision",
+ "provided",
+ "revision",
+ "source_revision",
+ "status",
+ "valid",
+ ]);
+ }
+
+ return {
+ anomalies: safeFacts(value.anomalies),
+ evidence: {
+ pages: pick(evidence.pages, [
+ "available",
+ "snapshot_matches_ref",
+ "snapshot_revision",
+ "source_is_expected",
+ "source_revision",
+ "title_contract",
+ ]),
+ primary_worktree: pick(evidence.primary_worktree, ["dirty", "present"]),
+ project_status: project,
+ public_site: pick(evidence.public_site, [
+ "attempted",
+ "contract_ok",
+ "source_is_expected",
+ "source_revision",
+ ]),
+ receipts,
+ repository: pick(evidence.repository, [
+ "candidate_head_stable",
+ "hinted_root_matches",
+ "local_main_revision",
+ "readable",
+ "remote_main_contains_expected",
+ "remote_main_is_expected",
+ "remote_main_revision",
+ "remote_pages_revision",
+ "remote_refs_readable",
+ "remote_refs_stable",
+ "snapshot_main_matches_ref",
+ "snapshot_main_revision",
+ ]),
+ target_worktree: target,
+ },
+ exact_revision: value.exact_revision ?? null,
+ missing_steps: safeFacts(value.missing_steps),
+ ownership_warnings: safeFacts(value.ownership_warnings, { summaries: false }),
+ plain_summary:
+ typeof value.plain_summary === "string" ? value.plain_summary : null,
+ schema: value.schema,
+ state: value.state,
+ };
+}
+
+export function buildPrompt(receipt) {
+ const projected = interpretationReceipt(receipt);
+ return [
+ "A strictly read-only Misaligned landing observer found deterministic anomalies.",
+ `The deterministic state is ${projected.state}; you may explain it but must not change it.`,
+ "Interpret only the supplied evidence. Do not use tools, request repository access, mutate state, promise future work, or treat your judgment as replacing the classifier.",
+ "Omitted, null, or empty evidence is unknown, never proof that a step is intact. Do not invent a revision, placeholder meaning, classifier state, or absent fact.",
+ "Separate likely transient publication convergence from a broken landing, stale evidence, task-ownership ambiguity, or project-operation inconsistency.",
+ "Return: (1) the smallest plain-language diagnosis, (2) which exact supplied evidence supports it, and (3) at most one read-only next verification if the supplied evidence cannot decide the diagnosis. Do not recommend polling.",
+ "",
+ "MINIMIZED LANDING RECEIPT",
+ JSON.stringify(projected, null, 2),
+ ].join("\n");
+}
+
+async function readReceipt(path) {
+ const chunks = [];
+ if (!path || path === "-") {
+ for await (const chunk of stdin) {
+ chunks.push(Buffer.from(chunk));
+ }
+ }
+ const input = path && path !== "-" ? await readFile(path) : Buffer.concat(chunks);
+ if (input.byteLength > MAX_RECEIPT_BYTES) {
+ throw new Error(`landing receipt exceeds ${MAX_RECEIPT_BYTES} bytes`);
+ }
+ return validateReceipt(JSON.parse(input.toString("utf8")));
+}
+
+function agentId(agent) {
+ return agent && typeof agent.id === "string" && agent.id.length > 0
+ ? agent.id
+ : null;
+}
+
+export async function findOrCreateSpecialist(client) {
+ const listed = await client.agents.list({ name: SPECIALIST_NAME, limit: 100 });
+ if (!Array.isArray(listed)) {
+ throw new Error("Letta agent lookup returned an unsupported result");
+ }
+ const exact = listed.filter((agent) => agent?.name === SPECIALIST_NAME);
+ if (exact.length > 1) {
+ throw new Error(`more than one Letta agent is named ${SPECIALIST_NAME}`);
+ }
+ if (exact.length === 1) {
+ const existingId = agentId(exact[0]);
+ if (!existingId) {
+ throw new Error("the retained landing observer has no usable agent id");
+ }
+ return { agentId: existingId, created: false };
+ }
+ const createdId = await client.createAgent({
+ baseTools: [],
+ description:
+ "Retained zero-tool specialist for interpreting deterministic Misaligned landing anomalies",
+ memfs: false,
+ memory: [],
+ model: MODEL,
+ name: SPECIALIST_NAME,
+ systemPrompt: INTERPRETER_SYSTEM_PROMPT,
+ });
+ if (typeof createdId !== "string" || createdId.length === 0) {
+ throw new Error("creating the retained landing observer returned no usable agent id");
+ }
+ return { agentId: createdId, created: true };
+}
+
+export async function interpret(
+ receipt,
+ env = process.env,
+ sdkLoader = () => import("@letta-ai/letta-agent-sdk"),
+) {
+ const validated = validateReceipt(receipt);
+ if (!needsInterpretation(validated)) {
+ return {
+ interpretation: null,
+ model: MODEL,
+ reason:
+ validated.anomalies.length === 0
+ ? "deterministic receipt has no anomalies"
+ : "deterministic receipt has only benign public-edge convergence",
+ schema: INTERPRETATION_SCHEMA,
+ status: "not-needed",
+ };
+ }
+ const { LettaAgentClient } = await sdkLoader();
+ const clientOptions = {
+ backend: "cloud",
+ ...(env.LETTA_API_KEY ? { apiKey: env.LETTA_API_KEY } : {}),
+ ...(env.LETTA_BASE_URL ? { apiBaseUrl: env.LETTA_BASE_URL } : {}),
+ };
+ const client = new LettaAgentClient(clientOptions);
+ const specialist = await findOrCreateSpecialist(client);
+ const result = await client.prompt(buildPrompt(validated), specialist.agentId, {
+ allowedTools: [],
+ permissionMode: "strict",
+ skillSources: [],
+ stateless: true,
+ tools: [],
+ toolset: { base: "none" },
+ });
+ return {
+ agent_created: specialist.created,
+ agent_id: specialist.agentId,
+ agent_name: SPECIALIST_NAME,
+ conversation_id: result.conversationId,
+ interpretation: result.result ?? result.errorDetail ?? result.error ?? null,
+ model: MODEL,
+ schema: INTERPRETATION_SCHEMA,
+ status: result.success ? "ok" : "failed",
+ stop_reason: result.stopReason ?? null,
+ };
+}
+
+async function main(argv = process.argv.slice(2)) {
+ if (argv.length > 1 || argv[0] === "--help" || argv[0] === "-h") {
+ const stream = argv[0] === "--help" || argv[0] === "-h" ? process.stdout : process.stderr;
+ stream.write("usage: interpret-anomalies.mjs [receipt.json|-]\n");
+ return argv.length > 1 ? 2 : 0;
+ }
+ try {
+ const receipt = await readReceipt(argv[0] ?? "-");
+ const result = await interpret(receipt);
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
+ return result.status === "failed" ? 1 : 0;
+ } catch (error) {
+ process.stderr.write(
+ `landing interpretation: ${error instanceof Error ? error.message : String(error)}\n`,
+ );
+ return 2;
+ }
+}
+
+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
+ process.exitCode = await main();
+}
diff --git a/.agents/skills/observing-misaligned-landings/scripts/observe-landing.py b/.agents/skills/observing-misaligned-landings/scripts/observe-landing.py
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/scripts/observe-landing.py
@@ -0,0 +1,1282 @@
+#!/usr/bin/env python3
+"""Emit one deterministic, strictly read-only Misaligned landing observation."""
+
+from __future__ import annotations
+
+import argparse
+from dataclasses import dataclass
+from html.parser import HTMLParser
+import json
+import os
+from pathlib import Path
+import re
+import subprocess
+import sys
+import tempfile
+from typing import Callable
+from urllib.parse import urlsplit, urlunsplit
+
+
+SCHEMA = "network.comind.misaligned.landing-observation/v2"
+GATE_SCHEMA = "network.comind.misaligned.landing-gate-receipt/v1"
+DEPLOYMENT_SCHEMA = "network.comind.misaligned.deployment-receipt/v1"
+CHANNEL_SCHEMA = "network.comind.misaligned.channel-delivery-receipt/v1"
+TITLE = "Misaligned — WORK / THINK / LIE"
+DEFAULT_SITE_URL = "https://cameron.tngl.io/misaligned/"
+SHA_RE = re.compile(r"^[0-9a-f]{40}$")
+SOURCE_OUTPUT_RE = re.compile(r"(?:source=)([0-9a-f]{40}|missing)")
+
+
+@dataclass(frozen=True)
+class CommandResult:
+ returncode: int
+ stdout: str = ""
+ stderr: str = ""
+
+
+Runner = Callable[..., CommandResult]
+
+
+class PageContractParser(HTMLParser):
+ def __init__(self) -> None:
+ super().__init__()
+ self.source_revision: str | None = None
+ self._in_title = False
+ self._title_parts: list[str] = []
+
+ @property
+ def title(self) -> str:
+ return "".join(self._title_parts).strip()
+
+ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
+ if tag.lower() == "title":
+ self._in_title = True
+ if tag.lower() != "meta":
+ return
+ values = {key.lower(): value for key, value in attrs}
+ if values.get("name") == "misaligned-source-revision":
+ self.source_revision = values.get("content")
+
+ def handle_endtag(self, tag: str) -> None:
+ if tag.lower() == "title":
+ self._in_title = False
+
+ def handle_data(self, data: str) -> None:
+ if self._in_title:
+ self._title_parts.append(data)
+
+
+def read_only_env(extra: dict[str, str] | None = None) -> dict[str, str]:
+ environment = os.environ.copy()
+ environment["GIT_OPTIONAL_LOCKS"] = "0"
+ if extra:
+ environment.update(extra)
+ return environment
+
+
+def command_runner(
+ command: list[str],
+ *,
+ cwd: Path,
+ env: dict[str, str] | None = None,
+ timeout: int = 45,
+) -> CommandResult:
+ try:
+ completed = subprocess.run(
+ command,
+ cwd=cwd,
+ env=env or read_only_env(),
+ text=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ timeout=timeout,
+ check=False,
+ )
+ return CommandResult(completed.returncode, completed.stdout, completed.stderr)
+ except (OSError, subprocess.TimeoutExpired) as exc:
+ return CommandResult(127, "", str(exc))
+
+
+def redact_url(value: str) -> str:
+ try:
+ parsed = urlsplit(value)
+ except ValueError:
+ return value
+ if parsed.scheme not in {"http", "https", "ssh"}:
+ return value
+ host = parsed.hostname or ""
+ if parsed.port:
+ host = f"{host}:{parsed.port}"
+ return urlunsplit((parsed.scheme, host, parsed.path, "" if parsed.query else "", ""))
+
+
+def clean_line(result: CommandResult) -> str:
+ lines = (result.stderr or result.stdout).strip().splitlines()
+ if not lines:
+ return f"command exited {result.returncode}"
+ line = lines[-1]
+ line = re.sub(r"(https?://)[^/@\s]+@", r"\1@", line)
+ line = re.sub(r"(?i)(token|api[_-]?key|password)=([^\s&]+)", r"\1=", line)
+ for candidate in re.findall(r"(?:https?|ssh)://[^\s]+", line):
+ line = line.replace(candidate, redact_url(candidate))
+ return line[:240]
+
+
+def git(runner: Runner, root: Path, *args: str, **kwargs: object) -> CommandResult:
+ kwargs.setdefault("env", read_only_env())
+ return runner(["git", "-C", str(root), *args], cwd=root, **kwargs)
+
+
+def one_sha(result: CommandResult) -> str | None:
+ value = result.stdout.strip()
+ return value if result.returncode == 0 and SHA_RE.fullmatch(value) else None
+
+
+def bool_or_none(value: object) -> bool | None:
+ return value if isinstance(value, bool) else None
+
+
+def remote_refs(result: CommandResult) -> dict[str, str]:
+ refs: dict[str, str] = {}
+ if result.returncode != 0:
+ return refs
+ for line in result.stdout.splitlines():
+ sha, separator, ref = line.partition("\t")
+ if separator and SHA_RE.fullmatch(sha):
+ refs[ref] = sha
+ return refs
+
+
+def page_contract(html: str) -> tuple[str | None, bool]:
+ parser = PageContractParser()
+ parser.feed(html)
+ source = parser.source_revision
+ if source is not None and not SHA_RE.fullmatch(source):
+ source = None
+ return source, parser.title == TITLE
+
+
+def public_source(output: str) -> str | None:
+ for value in reversed(SOURCE_OUTPUT_RE.findall(output)):
+ if SHA_RE.fullmatch(value):
+ return value
+ return None
+
+
+def list_output(result: CommandResult) -> list[str]:
+ if result.returncode != 0:
+ return []
+ return sorted(line for line in result.stdout.splitlines() if line)
+
+
+def count_pair(result: CommandResult) -> tuple[int | None, int | None]:
+ if result.returncode != 0:
+ return None, None
+ parts = result.stdout.split()
+ if len(parts) != 2 or not all(part.isdigit() for part in parts):
+ return None, None
+ return int(parts[0]), int(parts[1])
+
+
+def primary_root(runner: Runner, root: Path) -> Path | None:
+ result = git(
+ runner,
+ root,
+ "rev-parse",
+ "--path-format=absolute",
+ "--git-common-dir",
+ )
+ if result.returncode != 0:
+ return None
+ common = Path(result.stdout.strip())
+ if common.name == ".git":
+ return common.parent
+ marker = "/.git/worktrees/"
+ raw = str(common)
+ if marker in raw:
+ return Path(raw.split(marker, 1)[0])
+ return None
+
+
+def live_worktree(runner: Runner, path: Path | None) -> dict[str, object]:
+ evidence: dict[str, object] = {
+ "ahead": None,
+ "behind": None,
+ "branch": None,
+ "dirty": None,
+ "head_revision": None,
+ "path": str(path) if path is not None else None,
+ "path_escape": None,
+ "present": None if path is None else False,
+ "touching": [],
+ "upstream": None,
+ }
+ if path is None:
+ return evidence
+ root_result = git(runner, path, "rev-parse", "--show-toplevel")
+ if root_result.returncode != 0:
+ return evidence
+ canonical = Path(root_result.stdout.strip())
+ requested = path.resolve()
+ if canonical.resolve() != requested:
+ evidence["path_escape"] = str(canonical)
+ return evidence
+ evidence["path"] = str(canonical)
+ evidence["present"] = True
+ evidence["head_revision"] = one_sha(
+ git(runner, canonical, "rev-parse", "--verify", "HEAD^{commit}")
+ )
+ branch = git(runner, canonical, "branch", "--show-current")
+ evidence["branch"] = branch.stdout.strip() if branch.returncode == 0 else None
+ status = git(runner, canonical, "status", "--porcelain", "--untracked-files=normal")
+ evidence["dirty"] = bool(status.stdout) if status.returncode == 0 else None
+ upstream = git(runner, canonical, "rev-parse", "--abbrev-ref", "@{upstream}")
+ evidence["upstream"] = upstream.stdout.strip() if upstream.returncode == 0 else None
+ return evidence
+
+
+def path_matches_task(row: dict[str, object], task: str) -> bool:
+ raw_path = row.get("path")
+ branch = str(row.get("branch", ""))
+ path_name = Path(raw_path).name if isinstance(raw_path, str) and raw_path else ""
+ tail = branch.rsplit("/", 1)[-1]
+ return (
+ path_name == task
+ or branch == f"worktree-{task}"
+ or tail == task
+ or tail.startswith(f"{task}-")
+ )
+
+
+def normalize_run(row: dict[str, object]) -> dict[str, object]:
+ return {
+ "agent_id": row.get("agent_id") if isinstance(row.get("agent_id"), str) else None,
+ "phase": row.get("phase") if isinstance(row.get("phase"), str) else None,
+ "present": True,
+ "status": row.get("status") if isinstance(row.get("status"), str) else None,
+ "worktree": row.get("worktree") if isinstance(row.get("worktree"), str) else None,
+ }
+
+
+def project_observation(
+ runner: Runner,
+ root: Path,
+ task: str,
+ primary: Path | None,
+) -> tuple[dict[str, object], Path | None]:
+ project_script = root / "tools/project-status.py"
+ result = runner(
+ [
+ sys.executable,
+ str(project_script),
+ "--root",
+ str(root),
+ "--json",
+ "--check",
+ "--offline",
+ ],
+ cwd=root,
+ env=read_only_env(),
+ timeout=45,
+ )
+ evidence: dict[str, object] = {
+ "consistent": None,
+ "error_count": None,
+ "generated_ledgers_fresh": None,
+ "generated_work_orders_fresh": None,
+ "read_error": None,
+ "readable": False,
+ "target_run": {
+ "agent_id": None,
+ "phase": None,
+ "present": None,
+ "status": None,
+ "worktree": None,
+ },
+ "target_run_ambiguous": None,
+ "target_worktree_ambiguous": None,
+ "warning_count": None,
+ }
+ try:
+ payload = json.loads(result.stdout)
+ except json.JSONDecodeError:
+ payload = None
+ if not isinstance(payload, dict):
+ evidence["read_error"] = clean_line(result)
+ return evidence, None
+
+ consistency = payload.get("consistency")
+ freshness = payload.get("freshness")
+ runs = payload.get("runs")
+ worktrees = payload.get("worktrees")
+ if not (
+ isinstance(consistency, dict)
+ and isinstance(freshness, dict)
+ and isinstance(runs, list)
+ and isinstance(worktrees, list)
+ and isinstance(consistency.get("ok"), bool)
+ ):
+ evidence["read_error"] = "project-status returned an unsupported JSON shape"
+ return evidence, None
+
+ evidence["readable"] = True
+ evidence["consistent"] = consistency["ok"]
+ errors = consistency.get("errors") if isinstance(consistency.get("errors"), list) else []
+ warnings = consistency.get("warnings") if isinstance(consistency.get("warnings"), list) else []
+ evidence["error_count"] = len(errors)
+ evidence["warning_count"] = len(warnings)
+ evidence["generated_ledgers_fresh"] = bool_or_none(freshness.get("ledgers"))
+ evidence["generated_work_orders_fresh"] = bool_or_none(freshness.get("work_orders"))
+
+ matching_runs = [row for row in runs if isinstance(row, dict) and row.get("id") == task]
+ evidence["target_run_ambiguous"] = len(matching_runs) > 1
+ target_run = matching_runs[0] if len(matching_runs) == 1 else None
+ if target_run is not None:
+ evidence["target_run"] = normalize_run(target_run)
+ else:
+ evidence["target_run"]["present"] = False if len(matching_runs) == 0 else None
+
+ registered = [row for row in worktrees if isinstance(row, dict) and "error" not in row]
+ explicit = target_run.get("worktree") if isinstance(target_run, dict) else None
+ candidates: list[dict[str, object]] = []
+ for row in registered:
+ raw_path = row.get("path")
+ if not isinstance(raw_path, str) or not raw_path:
+ continue
+ if (
+ isinstance(explicit, str)
+ and explicit
+ and Path(raw_path).resolve() == Path(explicit).resolve()
+ ) or path_matches_task(row, task):
+ if row not in candidates:
+ candidates.append(row)
+ evidence["target_worktree_ambiguous"] = len(candidates) > 1
+ target_path = None
+ if len(candidates) == 1 and isinstance(candidates[0].get("path"), str):
+ target_path = Path(str(candidates[0]["path"]))
+ elif (
+ len(candidates) == 0
+ and isinstance(explicit, str)
+ and explicit
+ ):
+ # A completed run retains the exact path after normal cleanup. Reading
+ # that absent path is the cleanup proof; do not guess a worktree root.
+ target_path = Path(explicit)
+ return evidence, target_path
+
+
+def isolated_remote_snapshot(
+ runner: Runner,
+ root: Path,
+ remote_url: str,
+ ssh_command: str | None,
+ expected: str | None,
+ sampled_main: str | None,
+ sampled_pages: str | None,
+) -> dict[str, object]:
+ """Read remote history and page bytes in a disposable bare repository."""
+ snapshot: dict[str, object] = {
+ "changed_paths": None,
+ "main_contains_expected": None,
+ "main_read_error": None,
+ "main_revision": None,
+ "page_read_error": None,
+ "page_revision": None,
+ "page_source_revision": None,
+ "page_title_contract": None,
+ "target_ahead": None,
+ "target_behind": None,
+ }
+ with tempfile.TemporaryDirectory(prefix="misaligned-landing-observer-") as raw_tmp:
+ tmp = Path(raw_tmp)
+ initialized = runner(
+ ["git", "init", "--bare", "-q", str(tmp)],
+ cwd=root,
+ env=read_only_env(),
+ )
+ if initialized.returncode != 0:
+ message = clean_line(initialized)
+ snapshot["main_read_error"] = message
+ snapshot["page_read_error"] = message
+ return snapshot
+
+ fetch_env = read_only_env()
+ if ssh_command:
+ fetch_env["GIT_SSH_COMMAND"] = ssh_command
+
+ if sampled_main is not None:
+ fetched_main = runner(
+ [
+ "git",
+ "-C",
+ str(tmp),
+ "fetch",
+ "--quiet",
+ "--no-tags",
+ remote_url,
+ "+refs/heads/main:refs/observer/main",
+ ],
+ cwd=root,
+ env=fetch_env,
+ timeout=60,
+ )
+ if fetched_main.returncode != 0:
+ snapshot["main_read_error"] = clean_line(fetched_main)
+ else:
+ snapshot["main_revision"] = one_sha(
+ git(runner, tmp, "rev-parse", "--verify", "refs/observer/main^{commit}")
+ )
+ if snapshot["main_revision"] != sampled_main:
+ snapshot["main_read_error"] = (
+ "disposable main snapshot does not match the sampled remote ref"
+ )
+
+ if sampled_pages is not None:
+ fetched_pages = runner(
+ [
+ "git",
+ "-C",
+ str(tmp),
+ "fetch",
+ "--quiet",
+ "--no-tags",
+ "--depth=1",
+ remote_url,
+ "+refs/heads/pages:refs/observer/pages",
+ ],
+ cwd=root,
+ env=fetch_env,
+ timeout=60,
+ )
+ if fetched_pages.returncode != 0:
+ snapshot["page_read_error"] = clean_line(fetched_pages)
+ else:
+ page_revision = one_sha(
+ git(runner, tmp, "rev-parse", "--verify", "refs/observer/pages^{commit}")
+ )
+ snapshot["page_revision"] = page_revision
+ if page_revision != sampled_pages:
+ snapshot["page_read_error"] = (
+ "disposable pages snapshot does not match the sampled remote ref"
+ )
+ return snapshot
+ shown = git(runner, tmp, "show", "refs/observer/pages:index.html")
+ if page_revision is None or shown.returncode != 0:
+ snapshot["page_read_error"] = clean_line(shown)
+ else:
+ source, title_ok = page_contract(shown.stdout)
+ snapshot["page_source_revision"] = source
+ snapshot["page_title_contract"] = title_ok
+
+ main_revision = snapshot["main_revision"]
+ if expected is None or not isinstance(main_revision, str):
+ return snapshot
+
+ candidate_ref = "refs/observer/main"
+ if expected != main_revision:
+ candidate_ref = "refs/observer/candidate"
+ fetched_candidate = runner(
+ [
+ "git",
+ "-C",
+ str(tmp),
+ "fetch",
+ "--quiet",
+ "--no-tags",
+ str(root),
+ f"+{expected}:{candidate_ref}",
+ ],
+ cwd=root,
+ env=read_only_env(),
+ timeout=60,
+ )
+ if fetched_candidate.returncode != 0:
+ snapshot["main_read_error"] = clean_line(fetched_candidate)
+ return snapshot
+ candidate_revision = one_sha(
+ git(runner, tmp, "rev-parse", "--verify", f"{candidate_ref}^{{commit}}")
+ )
+ if candidate_revision != expected:
+ snapshot["main_read_error"] = "disposable candidate snapshot did not resolve the expected revision"
+ return snapshot
+
+ if expected == main_revision:
+ snapshot["main_contains_expected"] = True
+ else:
+ ancestry = git(
+ runner,
+ tmp,
+ "merge-base",
+ "--is-ancestor",
+ candidate_ref,
+ "refs/observer/main",
+ )
+ snapshot["main_contains_expected"] = (
+ True if ancestry.returncode == 0 else False if ancestry.returncode == 1 else None
+ )
+ if ancestry.returncode not in {0, 1}:
+ snapshot["main_read_error"] = clean_line(ancestry)
+ return snapshot
+
+ counts = git(
+ runner,
+ tmp,
+ "rev-list",
+ "--left-right",
+ "--count",
+ f"refs/observer/main...{candidate_ref}",
+ )
+ behind, ahead = count_pair(counts)
+ snapshot["target_behind"] = behind
+ snapshot["target_ahead"] = ahead
+ if behind is None or ahead is None:
+ snapshot["main_read_error"] = clean_line(counts)
+ return snapshot
+ changed = git(
+ runner,
+ tmp,
+ "diff",
+ "--name-only",
+ f"refs/observer/main...{candidate_ref}",
+ )
+ snapshot["changed_paths"] = (
+ list_output(changed) if changed.returncode == 0 else None
+ )
+ return snapshot
+
+
+def read_receipt(path: Path | None, kind: str) -> dict[str, object]:
+ schema = {
+ "gate": GATE_SCHEMA,
+ "deployment": DEPLOYMENT_SCHEMA,
+ "channel": CHANNEL_SCHEMA,
+ }[kind]
+ normalized: dict[str, object] = {
+ "provided": path is not None,
+ "read_error": None,
+ "valid": None,
+ }
+ if path is None:
+ return normalized
+ try:
+ payload = json.loads(path.read_text(encoding="utf-8"))
+ except (OSError, json.JSONDecodeError) as exc:
+ normalized.update(valid=False, read_error=f"{kind} receipt unreadable: {exc}")
+ return normalized
+ if not isinstance(payload, dict) or payload.get("schema") != schema:
+ normalized.update(valid=False, read_error=f"{kind} receipt has an unsupported schema")
+ return normalized
+
+ if kind == "gate":
+ status = payload.get("status")
+ revision = payload.get("revision")
+ valid = status in {"pass", "fail"} and isinstance(revision, str) and bool(
+ SHA_RE.fullmatch(revision)
+ )
+ normalized.update(status=status, revision=revision, valid=valid)
+ elif kind == "deployment":
+ status = payload.get("status")
+ source = payload.get("source_revision")
+ pages = payload.get("pages_revision")
+ valid = (
+ status in {"pass", "fail"}
+ and isinstance(source, str)
+ and bool(SHA_RE.fullmatch(source))
+ and (pages is None or (isinstance(pages, str) and bool(SHA_RE.fullmatch(pages))))
+ )
+ normalized.update(
+ status=status,
+ source_revision=source,
+ pages_revision=pages,
+ valid=valid,
+ )
+ else:
+ status = payload.get("status")
+ channel = payload.get("channel")
+ revision = payload.get("revision")
+ raw_message_id = payload.get("message_id")
+ message_id = str(raw_message_id) if isinstance(raw_message_id, (str, int)) else None
+ revision_valid = isinstance(revision, str) and bool(SHA_RE.fullmatch(revision))
+ message_valid = (
+ status != "delivered"
+ or (isinstance(message_id, str) and message_id.isdigit())
+ )
+ valid = (
+ channel == "telegram"
+ and status in {"delivered", "unavailable", "failed", "unknown"}
+ and revision_valid
+ and message_valid
+ )
+ normalized.update(
+ channel=channel,
+ message_id=message_id,
+ revision=revision if isinstance(revision, str) else None,
+ status=status,
+ valid=valid,
+ )
+ if normalized["valid"] is False and normalized["read_error"] is None:
+ normalized["read_error"] = f"{kind} receipt has invalid fields"
+ return normalized
+
+
+def fact(code: str, summary: str) -> dict[str, str]:
+ return {"code": code, "summary": summary}
+
+
+def append_once(rows: list[dict[str, str]], code: str, summary: str) -> None:
+ if not any(row["code"] == code for row in rows):
+ rows.append(fact(code, summary))
+
+
+def classify(
+ evidence: dict[str, object],
+ exact_revision: str | None,
+) -> tuple[str, list[dict[str, str]], list[dict[str, str]], list[dict[str, str]], str]:
+ """Classify one immutable evidence manifest without I/O or agent judgment."""
+ missing: list[dict[str, str]] = []
+ ownership: list[dict[str, str]] = []
+ anomalies: list[dict[str, str]] = []
+
+ repository = evidence.get("repository") if isinstance(evidence.get("repository"), dict) else {}
+ pages = evidence.get("pages") if isinstance(evidence.get("pages"), dict) else {}
+ public = evidence.get("public_site") if isinstance(evidence.get("public_site"), dict) else {}
+ project = evidence.get("project_status") if isinstance(evidence.get("project_status"), dict) else {}
+ receipts = evidence.get("receipts") if isinstance(evidence.get("receipts"), dict) else {}
+ gate = receipts.get("gate") if isinstance(receipts.get("gate"), dict) else {}
+ deployment = receipts.get("deployment") if isinstance(receipts.get("deployment"), dict) else {}
+ channel = receipts.get("channel") if isinstance(receipts.get("channel"), dict) else {}
+ target_run = project.get("target_run") if isinstance(project.get("target_run"), dict) else {}
+ target = evidence.get("target_worktree") if isinstance(evidence.get("target_worktree"), dict) else {}
+ primary = evidence.get("primary_worktree") if isinstance(evidence.get("primary_worktree"), dict) else {}
+
+ def conflict(code: str, summary: str) -> None:
+ append_once(anomalies, code, summary)
+
+ if repository.get("readable") is not True:
+ conflict("repository_unreadable", "the supplied path is not a readable Git worktree")
+ elif repository.get("hinted_root_matches") is not True:
+ conflict("repository_path_escaped", "the supplied root resolves to a different enclosing Git worktree")
+ if exact_revision is None:
+ conflict("expected_revision_unresolved", "the expected candidate does not resolve to one commit")
+ if repository.get("remote_refs_readable") is not True:
+ conflict("remote_refs_unreadable", "the remote main/pages refs could not be read authoritatively")
+ elif repository.get("remote_refs_stable") is not True:
+ conflict("remote_refs_moved_during_observation", "main or pages moved during the one-shot observation")
+ elif repository.get("remote_main_revision") is None:
+ conflict("remote_main_absent", "the authoritative remote has no main branch")
+ elif repository.get("snapshot_main_matches_ref") is not True:
+ code = (
+ "remote_main_snapshot_mismatched_ref"
+ if repository.get("snapshot_main_revision") is not None
+ else "remote_main_snapshot_unreadable"
+ )
+ conflict(code, "the disposable remote-main snapshot could not prove the sampled main ref")
+ elif (
+ exact_revision is not None
+ and repository.get("remote_main_is_expected") is False
+ and not isinstance(repository.get("remote_main_contains_expected"), bool)
+ ):
+ conflict("remote_ancestry_unreadable", "the disposable snapshot could not determine whether remote main contains the candidate")
+ if repository.get("candidate_head_stable") is None:
+ conflict("candidate_head_unreadable", "the observed candidate HEAD could not be read twice")
+ elif repository.get("candidate_head_stable") is False:
+ conflict("candidate_moved_during_observation", "the target worktree HEAD changed during observation")
+ if project.get("readable") is not True:
+ conflict("project_status_unreadable", "project-status did not return supported JSON")
+ elif project.get("consistent") is not True:
+ conflict("project_status_inconsistent", "project-operation records contradict each other")
+ if project.get("target_run_ambiguous") is True:
+ conflict("target_run_ambiguous", "more than one run record claims the target task id")
+ if project.get("target_worktree_ambiguous") is True:
+ conflict("target_worktree_ambiguous", "more than one registered worktree matches the target task")
+ if pages.get("available") is None and repository.get("remote_pages_revision") is not None:
+ conflict("pages_authority_unreadable", "the remote pages branch exists but its isolated snapshot could not be read")
+ if pages.get("snapshot_revision") is not None and pages.get("snapshot_matches_ref") is not True:
+ conflict("pages_snapshot_mismatched_ref", "the isolated pages snapshot does not match the sampled pages ref")
+
+ for kind, receipt in (("gate", gate), ("deployment", deployment), ("channel", channel)):
+ if receipt.get("provided") is True and receipt.get("valid") is not True:
+ conflict(f"{kind}_receipt_invalid", f"the supplied {kind} receipt is malformed or unreadable")
+
+ if exact_revision is not None and gate.get("valid") is True:
+ if gate.get("revision") != exact_revision:
+ conflict("gate_revision_mismatch", "the gate receipt belongs to a different revision")
+ elif gate.get("status") == "fail" and repository.get("remote_main_contains_expected") is True:
+ conflict("landed_without_passing_gate_receipt", "remote state contains a revision whose supplied gate receipt failed")
+ if exact_revision is not None and deployment.get("valid") is True:
+ if deployment.get("source_revision") != exact_revision:
+ conflict("deployment_revision_mismatch", "the deployment receipt belongs to a different source revision")
+ receipt_pages = deployment.get("pages_revision")
+ if isinstance(receipt_pages, str) and receipt_pages != repository.get("remote_pages_revision"):
+ conflict("deployment_pages_revision_mismatch", "the deployment receipt names a different remote pages revision")
+ if (
+ deployment.get("status") == "pass"
+ and repository.get("remote_main_is_expected") is True
+ and pages.get("source_is_expected") is False
+ ):
+ conflict("deployment_receipt_conflicts_with_pages", "a passing deployment receipt conflicts with remote pages")
+ if exact_revision is not None and channel.get("valid") is True:
+ if channel.get("revision") != exact_revision:
+ conflict("channel_revision_mismatch", "the Telegram delivery receipt belongs to a different revision")
+
+ remote_contains = repository.get("remote_main_contains_expected")
+ page_exact = pages.get("source_is_expected") is True
+ if page_exact and remote_contains is False:
+ conflict("published_revision_not_on_main", "remote pages names a revision absent from remote main")
+ run_status = target_run.get("status")
+ if run_status == "ok" and remote_contains is False:
+ conflict("terminal_run_without_remote_landing", "the task run is complete but remote main does not contain the candidate")
+ if run_status == "fail" and remote_contains is True:
+ conflict("failed_run_contains_remote_landing", "the task run failed even though remote main contains the candidate")
+ if target.get("path_escape") is not None:
+ conflict(
+ "target_path_escaped",
+ "the recorded target path resolves to a different enclosing Git worktree",
+ )
+
+ if anomalies:
+ short = exact_revision[:12] if exact_revision else "the requested candidate"
+ return (
+ "inconsistent",
+ missing,
+ ownership,
+ anomalies,
+ f"Evidence conflicts for {short}; no landing conclusion is safe.",
+ )
+
+ caller = evidence.get("input") if isinstance(evidence.get("input"), dict) else {}
+ caller_agent = caller.get("agent_id")
+ owner = target_run.get("agent_id")
+ owner_matches = (
+ isinstance(caller_agent, str)
+ and bool(caller_agent)
+ and isinstance(owner, str)
+ and bool(owner)
+ and caller_agent == owner
+ )
+ if isinstance(caller_agent, str) and caller_agent and isinstance(owner, str) and owner and not owner_matches:
+ append_once(ownership, "foreign_task_owner", f"the target run belongs to {owner}, not {caller_agent}")
+ elif not owner_matches:
+ append_once(ownership, "task_ownership_unproven", "the current agent cannot be matched to the target run owner")
+
+ cleanup_complete = run_status == "ok" and target.get("present") is False
+ exact_remote = repository.get("remote_main_is_expected") is True
+ current_pages = (
+ pages.get("snapshot_matches_ref") is True
+ and pages.get("title_contract") is True
+ and page_exact
+ )
+ superseded_landing = (
+ repository.get("remote_main_contains_expected") is True
+ and not exact_remote
+ and cleanup_complete
+ )
+ authoritative_landing = (exact_remote and current_pages) or superseded_landing
+ exact_gate_pass = (
+ gate.get("valid") is True
+ and gate.get("status") == "pass"
+ and gate.get("revision") == exact_revision
+ )
+
+ if authoritative_landing and cleanup_complete and exact_gate_pass:
+ if primary.get("dirty") is True:
+ append_once(
+ ownership,
+ "unrelated_primary_checkout_dirty",
+ "the current primary checkout is dirty, but immutable remote and cleanup proof already establish this landing",
+ )
+ if superseded_landing and (
+ pages.get("snapshot_matches_ref") is not True
+ or pages.get("title_contract") is not True
+ or pages.get("source_revision") != repository.get("remote_main_revision")
+ ):
+ append_once(
+ anomalies,
+ "current_main_unpublished",
+ "the candidate is landed, but current remote pages does not publish the newer main head",
+ )
+ if public.get("source_is_expected") is False and exact_remote:
+ append_once(
+ anomalies,
+ "public_edge_converging",
+ "remote pages is exact while the one-shot public edge still serves another source",
+ )
+ elif public.get("contract_ok") is not True and exact_remote:
+ append_once(
+ anomalies,
+ "public_edge_unverified",
+ "remote pages is exact but the one-shot public read did not prove the edge contract",
+ )
+ if channel.get("valid") is True and channel.get("status") == "delivered":
+ pass
+ elif channel.get("valid") is True and channel.get("status") in {"unavailable", "failed"}:
+ append_once(
+ missing,
+ "telegram_delivery_pending",
+ "deliver the landing result through Telegram when an outbound channel is available",
+ )
+ append_once(
+ anomalies,
+ "telegram_runtime_unavailable",
+ "the supplied channel receipt does not prove outbound Telegram delivery",
+ )
+ else:
+ append_once(
+ missing,
+ "telegram_delivery_unproven",
+ "a real Telegram message id is still needed to prove user-visible delivery",
+ )
+ short = exact_revision[:12] if exact_revision else "unknown"
+ if superseded_landing:
+ summary = f"Landed {short}; a newer main/pages revision now supersedes it and owned cleanup is complete."
+ elif any(row["code"] == "public_edge_converging" for row in anomalies):
+ summary = f"Landed {short}; remote main/pages are exact and cleanup is complete while the public edge converges."
+ else:
+ summary = f"Landed {short}; remote main/pages are exact and owned cleanup is complete."
+ return "landed", missing, ownership, anomalies, summary
+
+ remote_is_candidate = exact_remote
+ if remote_is_candidate:
+ if not exact_gate_pass:
+ append_once(
+ missing,
+ "gate_receipt_missing" if gate.get("provided") is not True else "landing_gate_failed",
+ "supply a passing landing-gate receipt bound to the exact candidate",
+ )
+ if not current_pages:
+ append_once(missing, "publication_pending", "publish remote pages from the exact landed revision")
+ if run_status != "ok":
+ append_once(missing, "run_completion_pending", "complete the target run after publication")
+ if target.get("present") is not False:
+ append_once(missing, "cleanup_pending", "remove the owned task worktree and branch through the normal cleanup path")
+ return (
+ "blocked",
+ missing,
+ ownership,
+ anomalies,
+ f"Main contains {exact_revision[:12] if exact_revision else 'the candidate'}, but publication or owned cleanup is incomplete.",
+ )
+
+ if repository.get("remote_main_contains_expected") is True:
+ if not exact_gate_pass:
+ append_once(
+ missing,
+ "gate_receipt_missing" if gate.get("provided") is not True else "landing_gate_failed",
+ "supply a passing landing-gate receipt bound to the exact candidate",
+ )
+ if run_status != "ok":
+ append_once(missing, "run_completion_pending", "supply the completed target-run evidence for the superseded candidate")
+ if target.get("present") is not False:
+ append_once(missing, "cleanup_pending", "prove that the superseded candidate's owned worktree is removed")
+ return (
+ "blocked",
+ missing,
+ ownership,
+ anomalies,
+ f"Remote main contains {exact_revision[:12] if exact_revision else 'the candidate'}, but its completed landing receipt is incomplete.",
+ )
+
+ if primary.get("dirty") is True:
+ append_once(
+ ownership,
+ "unrelated_primary_checkout_dirty",
+ "the primary checkout is dirty; land from the owned worktree without disturbing it",
+ )
+
+ ready_conditions: list[tuple[str, bool]] = []
+ target_present = target.get("present") is True
+ ready_conditions.append(("target_worktree_missing", target_present))
+ if target_present:
+ ready_conditions.extend(
+ [
+ ("candidate_head_mismatch", target.get("head_revision") == exact_revision),
+ ("task_worktree_dirty", target.get("dirty") is False),
+ ("candidate_requires_rebase", target.get("behind") == 0),
+ ("no_candidate_delta", isinstance(target.get("ahead"), int) and target.get("ahead", 0) > 0),
+ ]
+ )
+ ready_conditions.extend(
+ [
+ ("local_remote_ref_stale", repository.get("local_main_revision") == repository.get("remote_main_revision")),
+ ("target_run_not_running", run_status == "running"),
+ ("task_ownership_unproven", owner_matches),
+ ("generated_work_orders_stale", project.get("generated_work_orders_fresh") is True),
+ ("generated_ledgers_stale", project.get("generated_ledgers_fresh") is True),
+ ]
+ )
+ if gate.get("provided") is not True:
+ ready_conditions.append(("gate_receipt_missing", False))
+ elif gate.get("valid") is not True:
+ ready_conditions.append(("gate_receipt_invalid", False))
+ elif gate.get("status") != "pass":
+ ready_conditions.append(("landing_gate_failed", False))
+ summaries = {
+ "target_worktree_missing": "restore or identify the owned target worktree",
+ "candidate_head_mismatch": "make the target worktree name the expected candidate",
+ "task_worktree_dirty": "commit or otherwise resolve the target worktree dirt before landing",
+ "local_remote_ref_stale": "refresh and reconcile the local remote-main evidence",
+ "candidate_requires_rebase": "rebase the candidate onto current remote main",
+ "no_candidate_delta": "produce a candidate commit ahead of remote main",
+ "target_run_not_running": "restore a coherent running target heartbeat",
+ "task_ownership_unproven": "prove that the current agent owns the target run and worktree",
+ "gate_receipt_missing": "supply an exact-revision landing-gate receipt",
+ "gate_receipt_invalid": "replace the malformed gate receipt",
+ "landing_gate_failed": "run and pass the landing gate on the exact candidate",
+ "generated_work_orders_stale": "regenerate the work-order projection",
+ "generated_ledgers_stale": "regenerate the corpus ledger indexes",
+ }
+ failed = [code for code, ok in ready_conditions if not ok]
+ if not failed:
+ append_once(missing, "land_candidate", "run the repository's existing serialized landing path")
+ return (
+ "ready",
+ missing,
+ ownership,
+ anomalies,
+ f"Candidate {exact_revision[:12] if exact_revision else 'unknown'} is coherent and ready for the existing landing path.",
+ )
+ for code in failed:
+ append_once(missing, code, summaries[code])
+ return (
+ "blocked",
+ missing,
+ ownership,
+ anomalies,
+ f"Candidate {exact_revision[:12] if exact_revision else 'unknown'} is coherent, but required landing evidence or prerequisites are missing.",
+ )
+
+
+def observe(
+ root_hint: Path,
+ task: str,
+ revision: str,
+ remote: str,
+ site_url: str,
+ gate_receipt: Path | None,
+ deployment_receipt: Path | None,
+ channel_receipt: Path | None,
+ *,
+ runner: Runner = command_runner,
+) -> tuple[dict[str, object], int]:
+ root_result = runner(
+ ["git", "-C", str(root_hint), "rev-parse", "--show-toplevel"],
+ cwd=root_hint,
+ env=read_only_env(),
+ )
+ root = Path(root_result.stdout.strip()) if root_result.returncode == 0 else root_hint
+ hinted_root_matches = (
+ root.resolve() == root_hint.resolve() if root_result.returncode == 0 else None
+ )
+ caller_agent = os.environ.get("AGENT_ID") or os.environ.get("LETTA_AGENT_ID") or None
+ evidence: dict[str, object] = {
+ "input": {
+ "agent_id": caller_agent,
+ "remote": redact_url(remote),
+ "repository_path": str(root),
+ "site_url": redact_url(site_url),
+ "task": task,
+ },
+ "pages": {
+ "available": None,
+ "read_error": None,
+ "snapshot_matches_ref": None,
+ "snapshot_revision": None,
+ "source_is_expected": None,
+ "source_revision": None,
+ "title_contract": None,
+ },
+ "primary_worktree": live_worktree(runner, None),
+ "project_status": {
+ "consistent": None,
+ "error_count": None,
+ "generated_ledgers_fresh": None,
+ "generated_work_orders_fresh": None,
+ "read_error": None,
+ "readable": False,
+ "target_run": {
+ "agent_id": None,
+ "phase": None,
+ "present": None,
+ "status": None,
+ "worktree": None,
+ },
+ "target_run_ambiguous": None,
+ "target_worktree_ambiguous": None,
+ "warning_count": None,
+ },
+ "public_site": {
+ "attempted": False,
+ "contract_ok": None,
+ "read_error": None,
+ "source_is_expected": None,
+ "source_revision": None,
+ },
+ "receipts": {
+ "channel": read_receipt(channel_receipt, "channel"),
+ "deployment": read_receipt(deployment_receipt, "deployment"),
+ "gate": read_receipt(gate_receipt, "gate"),
+ },
+ "repository": {
+ "candidate_head_stable": None,
+ "hinted_root_matches": hinted_root_matches,
+ "changed_paths": None,
+ "local_main_revision": None,
+ "read_error": None,
+ "readable": root_result.returncode == 0,
+ "remote_main_contains_expected": None,
+ "remote_main_is_expected": None,
+ "remote_main_revision": None,
+ "remote_pages_revision": None,
+ "remote_refs_readable": None,
+ "remote_refs_stable": None,
+ "snapshot_main_matches_ref": None,
+ "snapshot_main_revision": None,
+ },
+ "target_worktree": live_worktree(runner, None),
+ }
+
+ if root_result.returncode != 0:
+ evidence["repository"]["read_error"] = clean_line(root_result)
+ state, missing, ownership, anomalies, summary = classify(evidence, None)
+ receipt = {
+ "anomalies": anomalies,
+ "evidence": evidence,
+ "exact_revision": None,
+ "missing_steps": missing,
+ "ownership_warnings": ownership,
+ "plain_summary": summary,
+ "schema": SCHEMA,
+ "state": state,
+ }
+ return receipt, 2
+
+ expected = None
+ if SHA_RE.fullmatch(revision):
+ expected = one_sha(
+ git(runner, root, "rev-parse", "--verify", f"{revision}^{{commit}}")
+ )
+ observed_head_first = one_sha(git(runner, root, "rev-parse", "--verify", "HEAD^{commit}"))
+ primary = primary_root(runner, root)
+
+ refs_command = [
+ "ls-remote",
+ "--heads",
+ remote,
+ "refs/heads/main",
+ "refs/heads/pages",
+ ]
+ first_result = git(runner, root, *refs_command, timeout=45)
+ first_refs = remote_refs(first_result)
+ first_main = first_refs.get("refs/heads/main")
+ first_pages = first_refs.get("refs/heads/pages")
+
+ remote_url_result = git(runner, root, "remote", "get-url", remote)
+ ssh_result = git(runner, root, "config", "--get", "core.sshCommand")
+ remote_url = remote_url_result.stdout.strip() if remote_url_result.returncode == 0 else ""
+ ssh_command = ssh_result.stdout.strip() if ssh_result.returncode == 0 else None
+ snapshot: dict[str, object] = {
+ "changed_paths": None,
+ "main_contains_expected": None,
+ "main_read_error": None,
+ "main_revision": None,
+ "page_read_error": None,
+ "page_revision": None,
+ "page_source_revision": None,
+ "page_title_contract": None,
+ "target_ahead": None,
+ "target_behind": None,
+ }
+ if remote_url and expected is not None:
+ snapshot = isolated_remote_snapshot(
+ runner,
+ root,
+ remote_url,
+ ssh_command,
+ expected,
+ first_main,
+ first_pages,
+ )
+ elif not remote_url:
+ error = clean_line(remote_url_result)
+ snapshot["main_read_error"] = error
+ snapshot["page_read_error"] = error
+ elif expected is None:
+ snapshot["main_read_error"] = "the expected candidate could not be resolved locally"
+
+ project, target_path = project_observation(runner, root, task, primary)
+ evidence["project_status"] = project
+ target = live_worktree(runner, target_path)
+ primary_live = live_worktree(runner, primary)
+ evidence["target_worktree"] = target
+ evidence["primary_worktree"] = primary_live
+
+ repository = evidence["repository"]
+ repository["read_error"] = snapshot.get("main_read_error")
+ repository["remote_main_contains_expected"] = snapshot.get("main_contains_expected")
+ repository["remote_main_is_expected"] = (
+ first_main == expected if first_main is not None and expected is not None else None
+ )
+ changed_paths = snapshot.get("changed_paths")
+ repository["changed_paths"] = changed_paths if isinstance(changed_paths, list) else None
+ target["behind"] = snapshot.get("target_behind")
+ target["ahead"] = snapshot.get("target_ahead")
+
+ local_main = one_sha(
+ git(runner, root, "rev-parse", "--verify", f"refs/remotes/{remote}/main^{{commit}}")
+ )
+ evidence["repository"]["local_main_revision"] = local_main
+
+ site_env = read_only_env(
+ {
+ "SITE_SMOKE_URL": site_url,
+ "SITE_SMOKE_ATTEMPTS": "1",
+ "SITE_SMOKE_DELAY_SECONDS": "0",
+ }
+ )
+ if expected is not None:
+ site_env["SITE_SOURCE_REVISION"] = expected
+ site_script = root / "tools/site-smoke.sh"
+ site_result = runner(["bash", str(site_script)], cwd=root, env=site_env, timeout=30)
+ site_output = "\n".join(part for part in (site_result.stdout, site_result.stderr) if part)
+ site_source = public_source(site_output)
+ evidence["public_site"] = {
+ "attempted": True,
+ "contract_ok": site_result.returncode == 0,
+ "read_error": clean_line(site_result) if site_result.returncode != 0 else None,
+ "source_is_expected": (
+ site_source == expected if site_source is not None and expected is not None else None
+ ),
+ "source_revision": site_source,
+ }
+
+ second_result = git(runner, root, *refs_command, timeout=45)
+ second_refs = remote_refs(second_result)
+ second_main = second_refs.get("refs/heads/main")
+ second_pages = second_refs.get("refs/heads/pages")
+ remote_readable = first_result.returncode == 0 and second_result.returncode == 0
+ remote_stable = remote_readable and first_refs == second_refs
+ observed_head_second = one_sha(git(runner, root, "rev-parse", "--verify", "HEAD^{commit}"))
+ target_head_second = None
+ if target.get("present") is True and isinstance(target.get("path"), str):
+ target_head_second = one_sha(
+ git(runner, Path(str(target["path"])), "rev-parse", "--verify", "HEAD^{commit}")
+ )
+
+ repository = evidence["repository"]
+ first_candidate_head = (
+ target.get("head_revision")
+ if target.get("present") is True
+ else observed_head_first
+ )
+ second_candidate_head = (
+ target_head_second
+ if target.get("present") is True
+ else observed_head_second
+ )
+ repository["candidate_head_stable"] = (
+ first_candidate_head == second_candidate_head
+ if isinstance(first_candidate_head, str) and isinstance(second_candidate_head, str)
+ else None
+ )
+ repository["remote_main_revision"] = second_main
+ repository["remote_pages_revision"] = second_pages
+ repository["remote_refs_readable"] = remote_readable
+ repository["remote_refs_stable"] = remote_stable
+ snapshot_main = snapshot.get("main_revision")
+ repository["snapshot_main_revision"] = snapshot_main
+ repository["snapshot_main_matches_ref"] = (
+ snapshot_main == second_main
+ if isinstance(snapshot_main, str) and isinstance(second_main, str)
+ else None
+ )
+ if expected is not None and remote_stable and second_main is not None:
+ repository["remote_main_is_expected"] = second_main == expected
+ if second_main == expected:
+ repository["remote_main_contains_expected"] = True
+ elif repository["snapshot_main_matches_ref"] is True:
+ repository["remote_main_contains_expected"] = snapshot.get(
+ "main_contains_expected"
+ )
+
+ page_commit = snapshot.get("page_revision")
+ page_source = snapshot.get("page_source_revision")
+ page_error = snapshot.get("page_read_error")
+ page_title_ok = snapshot.get("page_title_contract")
+ evidence["pages"] = {
+ "available": (
+ True
+ if isinstance(page_commit, str)
+ else False
+ if second_pages is None and remote_stable
+ else None
+ ),
+ "read_error": page_error,
+ "snapshot_matches_ref": (
+ page_commit == second_pages
+ if isinstance(page_commit, str) and isinstance(second_pages, str)
+ else None
+ ),
+ "snapshot_revision": page_commit,
+ "source_is_expected": (
+ page_source == expected
+ if isinstance(page_source, str) and expected is not None
+ else None
+ ),
+ "source_revision": page_source,
+ "title_contract": page_title_ok,
+ }
+
+ state, missing, ownership, anomalies, summary = classify(evidence, expected)
+ receipt = {
+ "anomalies": anomalies,
+ "evidence": evidence,
+ "exact_revision": expected,
+ "missing_steps": missing,
+ "ownership_warnings": ownership,
+ "plain_summary": summary,
+ "schema": SCHEMA,
+ "state": state,
+ }
+ return receipt, {"ready": 0, "landed": 0, "blocked": 1, "inconsistent": 2}[state]
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--root", type=Path, default=Path.cwd())
+ parser.add_argument("--task", required=True, help="owned task/worktree id")
+ parser.add_argument("--revision", required=True, help="expected candidate Git revision")
+ parser.add_argument("--remote", default="origin", help="remote carrying main and pages")
+ parser.add_argument("--site-url", default=os.environ.get("SITE_SMOKE_URL", DEFAULT_SITE_URL))
+ parser.add_argument("--gate-receipt", type=Path)
+ parser.add_argument("--deployment-receipt", type=Path)
+ parser.add_argument("--channel-receipt", type=Path)
+ args = parser.parse_args()
+ try:
+ receipt, status = observe(
+ args.root,
+ args.task,
+ args.revision,
+ args.remote,
+ args.site_url,
+ args.gate_receipt,
+ args.deployment_receipt,
+ args.channel_receipt,
+ )
+ except Exception as exc: # Last-resort stable failure packet; never emit a traceback.
+ receipt = {
+ "anomalies": [fact("observer_internal_error", f"the observer could not complete: {type(exc).__name__}")],
+ "evidence": {},
+ "exact_revision": None,
+ "missing_steps": [],
+ "ownership_warnings": [],
+ "plain_summary": "The one-shot observation failed before a safe conclusion was possible.",
+ "schema": SCHEMA,
+ "state": "inconsistent",
+ }
+ status = 2
+ print(json.dumps(receipt, indent=2, sort_keys=True))
+ return status
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/.agents/skills/observing-misaligned-landings/tests/interpret-anomalies.test.mjs b/.agents/skills/observing-misaligned-landings/tests/interpret-anomalies.test.mjs
new file mode 100644
--- /dev/null
+++ b/.agents/skills/observing-misaligned-landings/tests/interpret-anomalies.test.mjs
@@ -0,0 +1,320 @@
+import assert from "node:assert/strict";
+import http from "node:http";
+import test from "node:test";
+
+import {
+ INTERPRETATION_SCHEMA,
+ MODEL,
+ SPECIALIST_NAME,
+ buildPrompt,
+ findOrCreateSpecialist,
+ interpretationReceipt,
+ interpret,
+ needsInterpretation,
+ validateReceipt,
+} from "../scripts/interpret-anomalies.mjs";
+
+function receipt(overrides = {}) {
+ return {
+ schema: "network.comind.misaligned.landing-observation/v2",
+ state: "inconsistent",
+ exact_revision: "a".repeat(40),
+ plain_summary: "Landing evidence contradicts itself.",
+ missing_steps: [],
+ ownership_warnings: [],
+ anomalies: [{ code: "remote_refs_moved", summary: "Remote refs moved." }],
+ evidence: {
+ repository: {
+ hinted_root_matches: true,
+ remote_main_revision: "a".repeat(40),
+ remote_pages_revision: "b".repeat(40),
+ remote_refs_readable: true,
+ remote_refs_stable: false,
+ secret: "must-not-cross-boundary",
+ },
+ primary_worktree: { dirty: false, path: "/private/checkout" },
+ target_worktree: {
+ ahead: 0,
+ behind: 0,
+ dirty: false,
+ path: "/private/task",
+ path_escape: "/outside/repository",
+ present: true,
+ },
+ project_status: {
+ consistent: true,
+ target_run: { present: true, phase: "landing", raw: "not allowed" },
+ },
+ receipts: {
+ gate: { provided: true, valid: true, path: "/secret/gate.json" },
+ deployment: { provided: false },
+ channel: { provided: false },
+ },
+ pages: { available: true },
+ public_site: { attempted: false },
+ },
+ ...overrides,
+ };
+}
+
+test("receipt validation rejects unsupported states", () => {
+ assert.throws(
+ () => validateReceipt(receipt({ state: "guessing" })),
+ /state must be ready, blocked, landed, or inconsistent/,
+ );
+});
+
+test("receipt validation rejects non-object evidence", () => {
+ assert.throws(
+ () => validateReceipt(receipt({ evidence: null })),
+ /evidence must be a JSON object/,
+ );
+});
+
+test("only non-benign anomalies need interpretation", () => {
+ const clean = receipt({ state: "landed", anomalies: [] });
+ assert.equal(needsInterpretation(clean), false);
+ const converging = receipt({
+ state: "landed",
+ anomalies: [
+ { code: "public_edge_converging", summary: "The public edge is converging." },
+ ],
+ });
+ assert.equal(needsInterpretation(converging), false);
+ assert.equal(needsInterpretation(receipt()), true);
+});
+
+test("interpretation receipt strips paths and arbitrary evidence", () => {
+ const projected = interpretationReceipt(receipt());
+ const serialized = JSON.stringify(projected);
+ assert.equal(projected.state, "inconsistent");
+ assert.equal(projected.evidence.target_worktree.path_escape_detected, true);
+ assert.equal(projected.evidence.repository.remote_refs_stable, false);
+ assert.equal(projected.evidence.receipts.gate.valid, true);
+ assert.equal(serialized.includes("/private"), false);
+ assert.equal(serialized.includes("/outside"), false);
+ assert.equal(serialized.includes("/secret"), false);
+ assert.equal(serialized.includes("must-not-cross-boundary"), false);
+ assert.equal(serialized.includes("not allowed"), false);
+});
+
+test("prompt freezes classifier authority", () => {
+ const prompt = buildPrompt(receipt());
+ assert.match(prompt, /deterministic state is inconsistent/);
+ assert.match(prompt, /must not change it/);
+ assert.match(prompt, /Do not use tools/);
+ assert.match(prompt, /empty evidence is unknown/);
+ assert.match(prompt, /Do not recommend polling/);
+ assert.match(prompt, /MINIMIZED LANDING RECEIPT/);
+});
+
+test("specialist lookup reuses the exact retained name", async () => {
+ const calls = [];
+ const client = {
+ agents: {
+ async list(query) {
+ calls.push(["list", query]);
+ return [
+ { id: "agent-near", name: `${SPECIALIST_NAME} copy` },
+ { id: "agent-exact", name: SPECIALIST_NAME },
+ ];
+ },
+ },
+ async createAgent() {
+ calls.push(["create"]);
+ throw new Error("must not create");
+ },
+ };
+ assert.deepEqual(await findOrCreateSpecialist(client), {
+ agentId: "agent-exact",
+ created: false,
+ });
+ assert.deepEqual(calls, [["list", { name: SPECIALIST_NAME, limit: 100 }]]);
+});
+
+test("specialist creation is empty-memory, zero-tool, and persistent", async () => {
+ const calls = [];
+ const client = {
+ agents: {
+ async list(query) {
+ calls.push(["list", query]);
+ return [];
+ },
+ },
+ async createAgent(options) {
+ calls.push(["create", options]);
+ return "agent-created";
+ },
+ };
+ assert.deepEqual(await findOrCreateSpecialist(client), {
+ agentId: "agent-created",
+ created: true,
+ });
+ const options = calls[1][1];
+ assert.equal(options.name, SPECIALIST_NAME);
+ assert.equal(options.model, MODEL);
+ assert.equal(options.memfs, false);
+ assert.equal(options.hidden, undefined);
+ assert.deepEqual(options.memory, []);
+ assert.deepEqual(options.baseTools, []);
+ assert.deepEqual(Object.keys(options).sort(), [
+ "baseTools",
+ "description",
+ "memfs",
+ "memory",
+ "model",
+ "name",
+ "systemPrompt",
+ ]);
+ assert.equal(calls.some(([kind]) => kind === "delete"), false);
+});
+
+test("installed SDK translates specialist creation to an empty-memory zero-tool agent", async (t) => {
+ let LettaAgentClient;
+ try {
+ ({ LettaAgentClient } = await import("@letta-ai/letta-agent-sdk"));
+ } catch (error) {
+ if (
+ error?.code === "ERR_MODULE_NOT_FOUND" &&
+ String(error.message).includes("@letta-ai/letta-agent-sdk")
+ ) {
+ t.skip("pinned SDK dependencies are not installed in this checkout");
+ return;
+ }
+ throw error;
+ }
+
+ let observedRequest = null;
+ const server = http.createServer((request, response) => {
+ const chunks = [];
+ request.on("data", (chunk) => chunks.push(chunk));
+ request.on("end", () => {
+ observedRequest = {
+ body: JSON.parse(Buffer.concat(chunks).toString("utf8")),
+ method: request.method,
+ url: request.url,
+ };
+ response.writeHead(200, { "content-type": "application/json" });
+ response.end(JSON.stringify({ id: "agent-sdk-contract", name: SPECIALIST_NAME }));
+ });
+ });
+ await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
+ const address = server.address();
+ assert.ok(address && typeof address === "object");
+
+ try {
+ const client = new LettaAgentClient({
+ apiBaseUrl: `http://127.0.0.1:${address.port}`,
+ apiKey: "hermetic-contract-key",
+ backend: "cloud",
+ });
+ const specialist = await findOrCreateSpecialist({
+ agents: { list: async () => [] },
+ createAgent: (options) => client.createAgent(options),
+ });
+ assert.deepEqual(specialist, { agentId: "agent-sdk-contract", created: true });
+ } finally {
+ await new Promise((resolve) => server.close(resolve));
+ }
+
+ assert.ok(observedRequest);
+ assert.equal(observedRequest.method, "POST");
+ assert.equal(observedRequest.url, "/v1/agents/");
+ assert.equal(observedRequest.body.name, SPECIALIST_NAME);
+ assert.equal(observedRequest.body.model, MODEL);
+ assert.equal(observedRequest.body.hidden, undefined);
+ assert.deepEqual(observedRequest.body.memory_blocks, []);
+ assert.deepEqual(observedRequest.body.tools, []);
+ assert.equal(observedRequest.body.include_base_tools, false);
+ assert.equal(observedRequest.body.include_base_tool_rules, false);
+ assert.deepEqual(observedRequest.body.tags, ["origin:letta-code"]);
+ assert.match(observedRequest.body.system, /no tools, skills, repository access/);
+});
+
+test("duplicate exact-name specialists fail closed", async () => {
+ const client = {
+ agents: {
+ async list() {
+ return [
+ { id: "one", name: SPECIALIST_NAME },
+ { id: "two", name: SPECIALIST_NAME },
+ ];
+ },
+ },
+ };
+ await assert.rejects(
+ findOrCreateSpecialist(client),
+ /more than one Letta agent is named/,
+ );
+});
+
+test("clean and benign receipts avoid SDK loading", async () => {
+ let loaded = false;
+ for (const value of [
+ receipt({ state: "landed", anomalies: [] }),
+ receipt({
+ state: "landed",
+ anomalies: [
+ { code: "public_edge_converging", summary: "The public edge is converging." },
+ ],
+ }),
+ ]) {
+ const result = await interpret(value, {}, async () => {
+ loaded = true;
+ throw new Error("must not load SDK");
+ });
+ assert.equal(result.schema, INTERPRETATION_SCHEMA);
+ assert.equal(result.status, "not-needed");
+ assert.equal(result.interpretation, null);
+ }
+ assert.equal(loaded, false);
+});
+
+test("anomaly interpretation uses retained specialist and a fresh zero-authority conversation", async () => {
+ const calls = [];
+ class FakeClient {
+ constructor(options) {
+ calls.push(["construct", options]);
+ this.agents = {
+ list: async (query) => {
+ calls.push(["list", query]);
+ return [{ id: "agent-observer", name: SPECIALIST_NAME }];
+ },
+ };
+ }
+
+ async prompt(prompt, agentId, options) {
+ calls.push(["prompt", prompt, agentId, options]);
+ return {
+ success: true,
+ result: "The remote moved during observation.",
+ conversationId: "conv-one-shot",
+ stopReason: "end_turn",
+ };
+ }
+ }
+ const result = await interpret(
+ receipt(),
+ { LETTA_API_KEY: "key", LETTA_BASE_URL: "https://letta.example" },
+ async () => ({ LettaAgentClient: FakeClient }),
+ );
+ assert.equal(result.status, "ok");
+ assert.equal(result.agent_id, "agent-observer");
+ assert.equal(result.agent_name, SPECIALIST_NAME);
+ assert.equal(result.agent_created, false);
+ assert.equal(result.conversation_id, "conv-one-shot");
+ const promptCall = calls.find(([kind]) => kind === "prompt");
+ assert.ok(promptCall);
+ assert.equal(promptCall[2], "agent-observer");
+ assert.deepEqual(promptCall[3].allowedTools, []);
+ assert.deepEqual(promptCall[3].skillSources, []);
+ assert.deepEqual(promptCall[3].tools, []);
+ assert.deepEqual(promptCall[3].toolset, { base: "none" });
+ assert.equal(promptCall[3].permissionMode, "strict");
+ assert.equal(promptCall[3].stateless, true);
+ assert.equal(Object.hasOwn(promptCall[3], "model"), false);
+ assert.equal(Object.hasOwn(promptCall[3], "systemInfoReminder"), false);
+ assert.equal(JSON.stringify(promptCall).includes("/private"), false);
+ assert.equal(calls.some(([kind]) => kind === "delete"), false);
+ assert.equal(calls.some(([kind]) => kind === "resume"), false);
+});