← Memova.aiCONTENT HISTORY

Update to Memova.ai

Snapshot Oct 24, 2026 · 13:10 UTC · version 1.15.1

WHAT CHANGED

Package or technical metadata updated

Package or technical metadata updated

Observed in package metadata. These changes alone do not establish a new customer-facing feature.

Save Memova.ai and check future changes in Following.

Up to 3 plugins free · no card required.

All fields and original values.

These are saved file metadata. Open a changed file to read its text edits.

Package file

Before

Sep 30, 2026 · 23:00 UTC

333caf4b33faceae5e71a169c696a070f4ffbcf5392c83f22704ce8a8b058311

After

Oct 24, 2026 · 13:10 UTC

af9ff37fc68dfba75882c0f49b53ceb412fbd6924d3e97fe08efee3dedaffe77

Package file

Before

Sep 30, 2026 · 23:00 UTC

127

After

Oct 24, 2026 · 13:10 UTC

98

Package file

Before

Sep 30, 2026 · 23:00 UTC

b09aeecc839ac6fbdaffa93c985edcda36eae4a10cd319f4d2e306b772f83e4b

After

Oct 24, 2026 · 13:10 UTC

4d721d3b50a321c7069b5ab068b3709adbb9fb2fcbb57df56e857d7290ec7a5a

Package file

Before

Sep 30, 2026 · 23:00 UTC

1223

After

Oct 24, 2026 · 13:10 UTC

10908

Compare saved observations

Download comparison JSON

Changed files

Choose a file to see its text changes. Binary or large files show metadata only.

.app.json →

.codex-plugin/plugin.json →

.mcp.json →

assets/icon.svg →

assets/logo.svg →

contracts/resource_access_plugin_binding_v1.json →

contracts/upstream/memova_resource_access_v1.json →

menu_catalog.json →

scripts/agent_archive.py →

scripts/check_menu_catalog.py →

scripts/ensure_mcp_login.py →

scripts/kb_setup_reminder.py →

scripts/mcp_connection_auth.py →

scripts/mcp_credential_store.py →

scripts/memova_menu.py →

scripts/validate_resource_access_contract.py →

scripts/version_check.py →

skills/memova-agent-archive/SKILL.md →

skills/memova-agent-archive/agents/openai.yaml →

skills/memova-connect/SKILL.md →

skills/memova-connect/agents/openai.yaml →

skills/memova-explicit-import/SKILL.md →

skills/memova-explicit-import/agents/openai.yaml →

skills/memova-explicit-import/scripts/preview_selected_import.py →

skills/memova-knowledge/SKILL.md →

skills/memova-knowledge/agents/openai.yaml →

skills/memova-menu/SKILL.md →

skills/memova-menu/agents/openai.yaml →

skills/memova-personal-manual/SKILL.md →

skills/memova-personal-manual/agents/openai.yaml →

skills/memova-personal-manual/references/local-artifacts.md →

skills/memova-personal-manual/scripts/prepare_personal_manual.py →

skills/memova-resource-access/SKILL.md →

skills/memova-resource-access/agents/openai.yaml →

skills/memova-vault-diagnose/SKILL.md →

skills/memova-vault-diagnose/agents/openai.yaml →

skills/memova-vault-setup/SKILL.md →

skills/memova-vault-setup/agents/openai.yaml →

skills/memova-vault-setup/scripts/create_memova_vault.py →

skills/memova-vault-setup/scripts/diagnose_memova_vault.py →

skills/memova-vault-setup/scripts/find_vault_locations.py →

skills/memova-vault-setup/scripts/inspect_vault.py →

skills/memova-vault-setup/scripts/memova_vault_lib.py →

skills/memova-vault-setup/scripts/setup_fixture_harness.py →

skills/memova-vault-setup/scripts/validate_memova_vault.py →

skills/memova-workflow/SKILL.md →

skills/memova-workflow/agents/openai.yaml →

scripts/version_check.py

− removed · + added

--- before
+++ after
@@ -0,0 +1,280 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import json
+import os
+import re
+import urllib.error
+import urllib.request
+from datetime import datetime, timedelta, timezone
+from pathlib import Path
+from typing import Any
+
+DEFAULT_STATE_PATH = Path.home() / ".cache" / "memova-codex-plugin" / "version-check-v1.json"
+DEFAULT_COMPATIBILITY_URL = "https://api.memova.ai/.well-known/memova-plugin-compatibility"
+MARKETPLACE_NAME = "memova-codex-plugin"
+CHECK_INTERVAL = timedelta(hours=24)
+REMINDER_INTERVAL = timedelta(days=1)
+NETWORK_TIMEOUT_SECONDS = 4
+
+
+def main() -> int:
+    parser = argparse.ArgumentParser(
+        description="Check whether the installed Memova Codex plugin is outdated.",
+    )
+    parser.add_argument("--force", action="store_true", help="Ignore the 24-hour network check cache.")
+    parser.add_argument("--current-version", help="Override current version for validation.")
+    parser.add_argument("--compatibility-url", help="Override the compatibility endpoint URL.")
+    parser.add_argument(
+        "--state-path",
+        type=Path,
+        help="Override the local cache path for validation.",
+    )
+    args = parser.parse_args()
+
+    now = datetime.now(timezone.utc)
+    state_path = args.state_path or state_path_from_environment()
+    state = read_state(state_path)
+    state["run_count"] = int(state.get("run_count") or 0) + 1
+
+    current_version = args.current_version or read_current_version()
+    compatibility_url = (
+        args.compatibility_url
+        or os.getenv("MEMOVA_PLUGIN_COMPATIBILITY_URL")
+        or DEFAULT_COMPATIBILITY_URL
+    )
+    compatibility, source, skipped_reason, error = resolve_compatibility(
+        state=state,
+        compatibility_url=compatibility_url,
+        now=now,
+        force=args.force,
+    )
+    latest_version = compatibility.get("latest_version") if compatibility else None
+    minimum_supported_version = (
+        compatibility.get("minimum_supported_version") if compatibility else None
+    )
+
+    update_available = (
+        latest_version is not None
+        and current_version is not None
+        and is_newer_version(latest_version, current_version)
+    )
+    unsupported_version = (
+        minimum_supported_version is not None
+        and current_version is not None
+        and is_newer_version(minimum_supported_version, current_version)
+    )
+    should_remind = should_show_update_reminder(
+        state=state,
+        latest_version=latest_version,
+        update_available=update_available,
+        now=now,
+    )
+
+    state["current_version"] = current_version
+    state["compatibility_url"] = compatibility_url
+    state["last_update_available"] = update_available
+    if should_remind:
+        state["last_reminded_at"] = to_iso(now)
+        state["last_reminded_version"] = latest_version
+    elif not update_available and current_version:
+        state["last_reminded_version"] = None
+    try:
+        write_state(state_path, state)
+    except OSError as exc:
+        state_error = f"state cache write failed: {exc}"
+        error = f"{error}; {state_error}" if error else state_error
+
+    print_json(
+        {
+            "schema_version": "memova_plugin_version_check_v1",
+            "should_remind": should_remind,
+            "update_available": update_available,
+            "current_version": current_version,
+            "latest_version": latest_version,
+            "minimum_supported_version": minimum_supported_version,
+            "unsupported_version": unsupported_version,
+            "latest_source": source,
+            "state_path": str(state_path),
+            "skipped_reason": skipped_reason,
+            "error": error,
+            "message": update_message(current_version, latest_version) if should_remind else None,
+        },
+    )
+    return 0
+
+
+def read_current_version() -> str | None:
+    manifest_path = Path(__file__).resolve().parents[1] / ".codex-plugin" / "plugin.json"
+    try:
+        return str(json.loads(manifest_path.read_text(encoding="utf-8")).get("version") or "")
+    except (OSError, json.JSONDecodeError):
+        return None
+
+
+def resolve_compatibility(
+    *,
+    state: dict[str, Any],
+    compatibility_url: str,
+    now: datetime,
+    force: bool,
+) -> tuple[dict[str, str] | None, str, str | None, str | None]:
+    last_checked_at = parse_iso(state.get("last_checked_at"))
+    cached_latest = state.get("latest_version")
+    cached_minimum = state.get("minimum_supported_version")
+    cached_url = state.get("compatibility_url")
+    if (
+        not force
+        and cached_url == compatibility_url
+        and last_checked_at is not None
+        and now - last_checked_at < CHECK_INTERVAL
+    ):
+        return (
+            compatibility_values(cached_latest, cached_minimum) if cached_latest else None,
+            "cache",
+            "check_interval_not_elapsed",
+            None,
+        )
+
+    try:
+        compatibility = fetch_compatibility(compatibility_url)
+    except (OSError, urllib.error.URLError, json.JSONDecodeError, ValueError) as exc:
+        state["last_checked_at"] = to_iso(now)
+        cached_for_url = cached_url == compatibility_url and cached_latest
+        cached = compatibility_values(cached_latest, cached_minimum) if cached_for_url else None
+        return cached, "cache", "latest_check_failed", str(exc)
+
+    state.update(compatibility)
+    state["last_checked_at"] = to_iso(now)
+    state["latest_check_error"] = None
+    return compatibility, "network", None, None
+
+
+def fetch_compatibility(compatibility_url: str) -> dict[str, str]:
+    request = urllib.request.Request(
+        compatibility_url,
+        headers={
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "Pragma": "no-cache",
+            "User-Agent": "memova-codex-plugin-version-check/1.0",
+        },
+    )
+    with urllib.request.urlopen(request, timeout=NETWORK_TIMEOUT_SECONDS) as response:
+        payload = json.loads(response.read().decode("utf-8"))
+    if payload.get("schema_version") != "memova_plugin_compatibility_v1":
+        raise ValueError("unsupported compatibility schema")
+    if payload.get("plugin_name") != "memova":
+        raise ValueError("compatibility response is for a different plugin")
+    latest_version = str(payload.get("latest_version") or "").strip()
+    minimum_supported_version = str(payload.get("minimum_supported_version") or "").strip()
+    if parse_version_parts(latest_version) is None:
+        raise ValueError("compatibility response has an invalid latest version")
+    if parse_version_parts(minimum_supported_version) is None:
+        raise ValueError("compatibility response has an invalid minimum supported version")
+    return compatibility_values(latest_version, minimum_supported_version)
+
+
+def compatibility_values(
+    latest_version: Any,
+    minimum_supported_version: Any,
+) -> dict[str, str]:
+    values = {"latest_version": str(latest_version)}
+    if minimum_supported_version:
+        values["minimum_supported_version"] = str(minimum_supported_version)
+    return values
+
+
+def should_show_update_reminder(
+    *,
+    state: dict[str, Any],
+    latest_version: str | None,
+    update_available: bool,
+    now: datetime,
+) -> bool:
+    if not update_available or not latest_version:
+        return False
+    if state.get("last_reminded_version") != latest_version:
+        return True
+    last_reminded_at = parse_iso(state.get("last_reminded_at"))
+    if last_reminded_at is None:
+        return True
+    return now - last_reminded_at >= REMINDER_INTERVAL
+
+
+def is_newer_version(latest_version: str, current_version: str) -> bool:
+    latest = parse_version_parts(latest_version)
+    current = parse_version_parts(current_version)
+    return latest is not None and current is not None and latest > current
+
+
+def parse_version_parts(
+    version: str,
+) -> tuple[int, int, int, int, tuple[tuple[int, int | str], ...]] | None:
+    match = re.fullmatch(
+        r"\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?\s*",
+        version,
+    )
+    if not match:
+        return None
+    major = int(match.group(1) or 0)
+    minor = int(match.group(2) or 0)
+    patch = int(match.group(3) or 0)
+    prerelease = match.group(4)
+    if prerelease is None:
+        return (major, minor, patch, 1, ())
+    prerelease_parts: tuple[tuple[int, int | str], ...] = tuple(
+        (0, int(part)) if part.isdigit() else (1, part.lower())
+        for part in prerelease.split(".")
+    )
+    return (major, minor, patch, 0, prerelease_parts)
+
+
+def update_message(current_version: str | None, latest_version: str | None) -> str:
+    current = current_version or "unknown"
+    latest = latest_version or "unknown"
+    return (
+        f"Memova Codex plugin update available: installed {current}, latest {latest}. "
+        f"Run `codex plugin marketplace upgrade {MARKETPLACE_NAME}`, then restart Codex or start a new thread."
+    )
+
+
+def state_path_from_environment() -> Path:
+    configured = os.getenv("MEMOVA_PLUGIN_VERSION_STATE_PATH")
+    return Path(configured).expanduser() if configured else DEFAULT_STATE_PATH
+
+
+def read_state(state_path: Path) -> dict[str, Any]:
+    if not state_path.exists():
+        return {}
+    try:
+        return json.loads(state_path.read_text(encoding="utf-8"))
+    except (OSError, json.JSONDecodeError):
+        return {}
+
+
+def write_state(state_path: Path, state: dict[str, Any]) -> None:
+    state_path.parent.mkdir(parents=True, exist_ok=True)
+    state_path.write_text(json.dumps(state, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
+
+
+def parse_iso(value: Any) -> datetime | None:
+    if not isinstance(value, str) or not value:
+        return None
+    try:
+        return datetime.fromisoformat(value.replace("Z", "+00:00"))
+    except ValueError:
+        return None
+
+
+def to_iso(value: datetime) -> str:
+    return value.astimezone(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
+
+
+def print_json(data: dict[str, Any]) -> None:
+    print(json.dumps(data, indent=2, ensure_ascii=False))
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())
Full technical diff · 49 changed fields

changed /files/.app.json/sha256

BEFORE
"333caf4b33faceae5e71a169c696a070f4ffbcf5392c83f22704ce8a8b058311"
AFTER
"af9ff37fc68dfba75882c0f49b53ceb412fbd6924d3e97fe08efee3dedaffe77"

changed /files/.app.json/size

BEFORE
127
AFTER
98

changed /files/.codex-plugin~1plugin.json/sha256

BEFORE
"b09aeecc839ac6fbdaffa93c985edcda36eae4a10cd319f4d2e306b772f83e4b"
AFTER
"4d721d3b50a321c7069b5ab068b3709adbb9fb2fcbb57df56e857d7290ec7a5a"

changed /files/.codex-plugin~1plugin.json/size

BEFORE
1223
AFTER
10908

added /files/.mcp.json

BEFORE
Field was absent
AFTER
{
  "sha256": "be8708abebf3e796509ad32a83d2a62c427ace502f3d662daac054eece711903",
  "size": 89
}

added /files/assets~1icon.svg

BEFORE
Field was absent
AFTER
{
  "sha256": "54bd50b6408ef5c658fe724373919e3edbb220232ebd6938ab69c0517f72e7f7",
  "size": 685
}

added /files/assets~1logo.svg

BEFORE
Field was absent
AFTER
{
  "sha256": "427a49d8196f8daf05e6f948d43670f801040e3596261d7be902cdd6223897db",
  "size": 866
}

added /files/contracts~1resource_access_plugin_binding_v1.json

BEFORE
Field was absent
AFTER
{
  "sha256": "ca0e91ab63d1d80d92593d24db60e62911e9c96c1316e07391654b66f274e9be",
  "size": 3406
}

added /files/contracts~1upstream~1memova_resource_access_v1.json

BEFORE
Field was absent
AFTER
{
  "sha256": "6bef5e8c35934a2ff9d6a0dd55c7d70470ced995337f28f6c3b083ed28a4c78d",
  "size": 9185
}

added /files/menu_catalog.json

BEFORE
Field was absent
AFTER
{
  "sha256": "894363bbecb738df6aa6cea91dac994d381067049d4d866930a065cd1c6945b3",
  "size": 2509
}

added /files/scripts~1agent_archive.py

BEFORE
Field was absent
AFTER
{
  "sha256": "7ef5fe9d8292847c59543395104ec80709aedd56a992718ecefec793dd1f67c9",
  "size": 15116
}

added /files/scripts~1check_menu_catalog.py

BEFORE
Field was absent
AFTER
{
  "sha256": "d89afb741c7f73a2ac3857f3379268f00c61eec05ae2e8700738e440477bbe2f",
  "size": 638
}

added /files/scripts~1ensure_mcp_login.py

BEFORE
Field was absent
AFTER
{
  "sha256": "dd2ce35ecaa4ce7ec8f249ab962660f134515f9adcb5d714dd5e33222039bf92",
  "size": 20246
}

added /files/scripts~1kb_setup_reminder.py

BEFORE
Field was absent
AFTER
{
  "sha256": "cdb69e55bcf1faa65fa6664a4bd6a91abf7f9ab11db0ff7be5245c4c2a713fe5",
  "size": 5470
}

added /files/scripts~1mcp_connection_auth.py

BEFORE
Field was absent
AFTER
{
  "sha256": "3df8962e9d5c66a5298d9a9e6cbdc4d17755cc9d73d2f139bc3ee26256ed9bc2",
  "size": 21361
}

added /files/scripts~1mcp_credential_store.py

BEFORE
Field was absent
AFTER
{
  "sha256": "106077ee2270b0168ff15a7caded91da9fad252f1c1164b6e1d4228028b1712b",
  "size": 13043
}

added /files/scripts~1memova_menu.py

BEFORE
Field was absent
AFTER
{
  "sha256": "a31d626d81f92189782138cd438a7c070e4bb0104d4a47ad2024013816cf7c66",
  "size": 2503
}

added /files/scripts~1validate_resource_access_contract.py

BEFORE
Field was absent
AFTER
{
  "sha256": "130b4b179e301d7b0984822721c1c9633ff824c7e00f280f89fb98f1aebe486e",
  "size": 19271
}

added /files/scripts~1version_check.py

BEFORE
Field was absent
AFTER
{
  "sha256": "431220554511a5ffc66b14ac414259dbc50f24e97a050358fb35e1cc19b4c72e",
  "size": 10129
}

added /files/skills~1memova-agent-archive~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "f5acafcc0aded82b7173384f3be02bf2be31ab85b0842a15828c29e40c5539d1",
  "size": 6335
}

added /files/skills~1memova-agent-archive~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "080bd0c786e329c6538576681bc233bebcc0419dfa0dc34e78a7dd056bd46fec",
  "size": 463
}

added /files/skills~1memova-connect~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "8254a65d2ebe8a9e518fc0be28b0494a3b002e61d2b540812579fdf2b04ac19b",
  "size": 3181
}

added /files/skills~1memova-connect~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "7265de61625ee0b57733e64ab4807ac422a15bfd96a35b609f012c666cba3d71",
  "size": 248
}

added /files/skills~1memova-explicit-import~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "a9846d3d749b53a822c2b955cb75974dee16bfea84c33be3e2aba4170b6a318e",
  "size": 7700
}

added /files/skills~1memova-explicit-import~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "eb925da8a56261a8efb3869710fdba83fd4641da830acb3544c2c17145c4c115",
  "size": 483
}

added /files/skills~1memova-explicit-import~1scripts~1preview_selected_import.py

BEFORE
Field was absent
AFTER
{
  "sha256": "f4f01224c0b245dcb7ec5021714162293c758b8a1b7ec7d468ac1b197d9d06fb",
  "size": 7909
}

added /files/skills~1memova-knowledge~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "08da7d9d3589124da1d35524587ef2080c2455d191bb86ee4ed528695bcdf083",
  "size": 5445
}

added /files/skills~1memova-knowledge~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "5b2b81d6559f0d588fb352b303082607953d0cac2b2bc093210862253c68998a",
  "size": 496
}

added /files/skills~1memova-menu~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "88e9ce6c3a261ae5e6f633228e6f7188d2c7884abf15efc8941f417d1d23fc5e",
  "size": 8933
}

added /files/skills~1memova-menu~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "a3543b03bd48af221f0f0354f37fc32d5062bbf38c34993d8dad4cf3be05b1ee",
  "size": 204
}

added /files/skills~1memova-personal-manual~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "5e2ee8b0ae48ac8a469dc61de899e515e0356f48115cd7fa6371cb7a6d2f9b7d",
  "size": 11321
}

added /files/skills~1memova-personal-manual~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "409d332354b3bfbbd1a30e2262ad44cb393774360e067d359c196ccd4dbf7d9a",
  "size": 536
}

added /files/skills~1memova-personal-manual~1references~1local-artifacts.md

BEFORE
Field was absent
AFTER
{
  "sha256": "b7aa91d7a130338792a57cbe2937aea23fe6c94f7389dee3c7bd01035854dfa6",
  "size": 1914
}

added /files/skills~1memova-personal-manual~1scripts~1prepare_personal_manual.py

BEFORE
Field was absent
AFTER
{
  "sha256": "51cd409550a765c45b0fa3e78c9eb7309d308c769ac5aa83443f46616644bcc8",
  "size": 19703
}

added /files/skills~1memova-resource-access~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "360b19832d8891f20b05a0ec0d6eca849b4afb80915909edc7596fc335b932b3",
  "size": 13511
}

added /files/skills~1memova-resource-access~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "8f089f456a2cf60ce08dd3f006f8c835255c1b6b7f2f07af54aedc7c75c42d08",
  "size": 580
}

added /files/skills~1memova-vault-diagnose~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "b4c38e582baeb21e69ec8b04d5efa690739989a38c82468d1d3ad19465203a34",
  "size": 4809
}

added /files/skills~1memova-vault-diagnose~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "cc32fa628fb4f5c3c91f750dcf72bfdf4704fda2efb33dd1281f11b5ecaf49b6",
  "size": 469
}

added /files/skills~1memova-vault-setup~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "3c4410dac28396080939f749581e42a7ce67fa704975f7d4b19aa8eee31d4537",
  "size": 12497
}

added /files/skills~1memova-vault-setup~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "0c1cbe0d82408b2b2c885f90b70d0a85bcb34ec0ac20a17386c5220af5189841",
  "size": 475
}

added /files/skills~1memova-vault-setup~1scripts~1create_memova_vault.py

BEFORE
Field was absent
AFTER
{
  "sha256": "3272b0f7f648e402f5035e5f10b75ca18fd143c86031fa470bd162a17e054c22",
  "size": 4151
}

added /files/skills~1memova-vault-setup~1scripts~1diagnose_memova_vault.py

BEFORE
Field was absent
AFTER
{
  "sha256": "b4d6501f56f865473cda4aa7ca188735338011f7c962795bd0b4145a1e8e95a8",
  "size": 8060
}

added /files/skills~1memova-vault-setup~1scripts~1find_vault_locations.py

BEFORE
Field was absent
AFTER
{
  "sha256": "850c56ae9b5aa729964d2eb7e22a0ff7d37fd8d2fe89e0e6bc6d469caa6c5bd6",
  "size": 1965
}

added /files/skills~1memova-vault-setup~1scripts~1inspect_vault.py

BEFORE
Field was absent
AFTER
{
  "sha256": "7515a4d226c3a8acecfc662fb573e64a136f60aedb2460f6ed8afef212abee18",
  "size": 748
}

added /files/skills~1memova-vault-setup~1scripts~1memova_vault_lib.py

BEFORE
Field was absent
AFTER
{
  "sha256": "0d7977b3485222bbebf7cf6520c01b0c55712679a7939c30689b729bcbe23bef",
  "size": 97146
}

added /files/skills~1memova-vault-setup~1scripts~1setup_fixture_harness.py

BEFORE
Field was absent
AFTER
{
  "sha256": "605d8d19a51b551611bca2cdd612651e27a490a66d9f9b5958d39d876e27e3a6",
  "size": 50807
}

added /files/skills~1memova-vault-setup~1scripts~1validate_memova_vault.py

BEFORE
Field was absent
AFTER
{
  "sha256": "0c0632e1a8e192fae3b9802501cc298a2c3887ce63a552a469e32b83d6737269",
  "size": 2681
}

added /files/skills~1memova-workflow~1SKILL.md

BEFORE
Field was absent
AFTER
{
  "sha256": "7b98b4534cdec921a6b82f422f445a46d3a4f78cbb4feeabdfee1b3b924cb264",
  "size": 10156
}

added /files/skills~1memova-workflow~1agents~1openai.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "ade51e2a4a35f1ce6b1d05bda9d183ce58a10aedeab183bedc6382fbe5b47bbd",
  "size": 445
}
Full snapshot data
{
  "files": {
    ".app.json": {
      "sha256": "af9ff37fc68dfba75882c0f49b53ceb412fbd6924d3e97fe08efee3dedaffe77",
      "size": 98
    },
    ".codex-plugin/plugin.json": {
      "sha256": "4d721d3b50a321c7069b5ab068b3709adbb9fb2fcbb57df56e857d7290ec7a5a",
      "size": 10908
    },
    ".mcp.json": {
      "sha256": "be8708abebf3e796509ad32a83d2a62c427ace502f3d662daac054eece711903",
      "size": 89
    },
    "assets/icon.svg": {
      "sha256": "54bd50b6408ef5c658fe724373919e3edbb220232ebd6938ab69c0517f72e7f7",
      "size": 685
    },
    "assets/logo.svg": {
      "sha256": "427a49d8196f8daf05e6f948d43670f801040e3596261d7be902cdd6223897db",
      "size": 866
    },
    "contracts/resource_access_plugin_binding_v1.json": {
      "sha256": "ca0e91ab63d1d80d92593d24db60e62911e9c96c1316e07391654b66f274e9be",
      "size": 3406
    },
    "contracts/upstream/memova_resource_access_v1.json": {
      "sha256": "6bef5e8c35934a2ff9d6a0dd55c7d70470ced995337f28f6c3b083ed28a4c78d",
      "size": 9185
    },
    "menu_catalog.json": {
      "sha256": "894363bbecb738df6aa6cea91dac994d381067049d4d866930a065cd1c6945b3",
      "size": 2509
    },
    "scripts/agent_archive.py": {
      "sha256": "7ef5fe9d8292847c59543395104ec80709aedd56a992718ecefec793dd1f67c9",
      "size": 15116
    },
    "scripts/check_menu_catalog.py": {
      "sha256": "d89afb741c7f73a2ac3857f3379268f00c61eec05ae2e8700738e440477bbe2f",
      "size": 638
    },
    "scripts/ensure_mcp_login.py": {
      "sha256": "dd2ce35ecaa4ce7ec8f249ab962660f134515f9adcb5d714dd5e33222039bf92",
      "size": 20246
    },
    "scripts/kb_setup_reminder.py": {
      "sha256": "cdb69e55bcf1faa65fa6664a4bd6a91abf7f9ab11db0ff7be5245c4c2a713fe5",
      "size": 5470
    },
    "scripts/mcp_connection_auth.py": {
      "sha256": "3df8962e9d5c66a5298d9a9e6cbdc4d17755cc9d73d2f139bc3ee26256ed9bc2",
      "size": 21361
    },
    "scripts/mcp_credential_store.py": {
      "sha256": "106077ee2270b0168ff15a7caded91da9fad252f1c1164b6e1d4228028b1712b",
      "size": 13043
    },
    "scripts/memova_menu.py": {
      "sha256": "a31d626d81f92189782138cd438a7c070e4bb0104d4a47ad2024013816cf7c66",
      "size": 2503
    },
    "scripts/validate_resource_access_contract.py": {
      "sha256": "130b4b179e301d7b0984822721c1c9633ff824c7e00f280f89fb98f1aebe486e",
      "size": 19271
    },
    "scripts/version_check.py": {
      "sha256": "431220554511a5ffc66b14ac414259dbc50f24e97a050358fb35e1cc19b4c72e",
      "size": 10129
    },
    "skills/memova-agent-archive/SKILL.md": {
      "sha256": "f5acafcc0aded82b7173384f3be02bf2be31ab85b0842a15828c29e40c5539d1",
      "size": 6335
    },
    "skills/memova-agent-archive/agents/openai.yaml": {
      "sha256": "080bd0c786e329c6538576681bc233bebcc0419dfa0dc34e78a7dd056bd46fec",
      "size": 463
    },
    "skills/memova-connect/SKILL.md": {
      "sha256": "8254a65d2ebe8a9e518fc0be28b0494a3b002e61d2b540812579fdf2b04ac19b",
      "size": 3181
    },
    "skills/memova-connect/agents/openai.yaml": {
      "sha256": "7265de61625ee0b57733e64ab4807ac422a15bfd96a35b609f012c666cba3d71",
      "size": 248
    },
    "skills/memova-explicit-import/SKILL.md": {
      "sha256": "a9846d3d749b53a822c2b955cb75974dee16bfea84c33be3e2aba4170b6a318e",
      "size": 7700
    },
    "skills/memova-explicit-import/agents/openai.yaml": {
      "sha256": "eb925da8a56261a8efb3869710fdba83fd4641da830acb3544c2c17145c4c115",
      "size": 483
    },
    "skills/memova-explicit-import/scripts/preview_selected_import.py": {
      "sha256": "f4f01224c0b245dcb7ec5021714162293c758b8a1b7ec7d468ac1b197d9d06fb",
      "size": 7909
    },
    "skills/memova-knowledge/SKILL.md": {
      "sha256": "08da7d9d3589124da1d35524587ef2080c2455d191bb86ee4ed528695bcdf083",
      "size": 5445
    },
    "skills/memova-knowledge/agents/openai.yaml": {
      "sha256": "5b2b81d6559f0d588fb352b303082607953d0cac2b2bc093210862253c68998a",
      "size": 496
    },
    "skills/memova-menu/SKILL.md": {
      "sha256": "88e9ce6c3a261ae5e6f633228e6f7188d2c7884abf15efc8941f417d1d23fc5e",
      "size": 8933
    },
    "skills/memova-menu/agents/openai.yaml": {
      "sha256": "a3543b03bd48af221f0f0354f37fc32d5062bbf38c34993d8dad4cf3be05b1ee",
      "size": 204
    },
    "skills/memova-personal-manual/SKILL.md": {
      "sha256": "5e2ee8b0ae48ac8a469dc61de899e515e0356f48115cd7fa6371cb7a6d2f9b7d",
      "size": 11321
    },
    "skills/memova-personal-manual/agents/openai.yaml": {
      "sha256": "409d332354b3bfbbd1a30e2262ad44cb393774360e067d359c196ccd4dbf7d9a",
      "size": 536
    },
    "skills/memova-personal-manual/references/local-artifacts.md": {
      "sha256": "b7aa91d7a130338792a57cbe2937aea23fe6c94f7389dee3c7bd01035854dfa6",
      "size": 1914
    },
    "skills/memova-personal-manual/scripts/prepare_personal_manual.py": {
      "sha256": "51cd409550a765c45b0fa3e78c9eb7309d308c769ac5aa83443f46616644bcc8",
      "size": 19703
    },
    "skills/memova-resource-access/SKILL.md": {
      "sha256": "360b19832d8891f20b05a0ec0d6eca849b4afb80915909edc7596fc335b932b3",
      "size": 13511
    },
    "skills/memova-resource-access/agents/openai.yaml": {
      "sha256": "8f089f456a2cf60ce08dd3f006f8c835255c1b6b7f2f07af54aedc7c75c42d08",
      "size": 580
    },
    "skills/memova-vault-diagnose/SKILL.md": {
      "sha256": "b4c38e582baeb21e69ec8b04d5efa690739989a38c82468d1d3ad19465203a34",
      "size": 4809
    },
    "skills/memova-vault-diagnose/agents/openai.yaml": {
      "sha256": "cc32fa628fb4f5c3c91f750dcf72bfdf4704fda2efb33dd1281f11b5ecaf49b6",
      "size": 469
    },
    "skills/memova-vault-setup/SKILL.md": {
      "sha256": "3c4410dac28396080939f749581e42a7ce67fa704975f7d4b19aa8eee31d4537",
      "size": 12497
    },
    "skills/memova-vault-setup/agents/openai.yaml": {
      "sha256": "0c1cbe0d82408b2b2c885f90b70d0a85bcb34ec0ac20a17386c5220af5189841",
      "size": 475
    },
    "skills/memova-vault-setup/scripts/create_memova_vault.py": {
      "sha256": "3272b0f7f648e402f5035e5f10b75ca18fd143c86031fa470bd162a17e054c22",
      "size": 4151
    },
    "skills/memova-vault-setup/scripts/diagnose_memova_vault.py": {
      "sha256": "b4d6501f56f865473cda4aa7ca188735338011f7c962795bd0b4145a1e8e95a8",
      "size": 8060
    },
    "skills/memova-vault-setup/scripts/find_vault_locations.py": {
      "sha256": "850c56ae9b5aa729964d2eb7e22a0ff7d37fd8d2fe89e0e6bc6d469caa6c5bd6",
      "size": 1965
    },
    "skills/memova-vault-setup/scripts/inspect_vault.py": {
      "sha256": "7515a4d226c3a8acecfc662fb573e64a136f60aedb2460f6ed8afef212abee18",
      "size": 748
    },
    "skills/memova-vault-setup/scripts/memova_vault_lib.py": {
      "sha256": "0d7977b3485222bbebf7cf6520c01b0c55712679a7939c30689b729bcbe23bef",
      "size": 97146
    },
    "skills/memova-vault-setup/scripts/setup_fixture_harness.py": {
      "sha256": "605d8d19a51b551611bca2cdd612651e27a490a66d9f9b5958d39d876e27e3a6",
      "size": 50807
    },
    "skills/memova-vault-setup/scripts/validate_memova_vault.py": {
      "sha256": "0c0632e1a8e192fae3b9802501cc298a2c3887ce63a552a469e32b83d6737269",
      "size": 2681
    },
    "skills/memova-workflow/SKILL.md": {
      "sha256": "7b98b4534cdec921a6b82f422f445a46d3a4f78cbb4feeabdfee1b3b924cb264",
      "size": 10156
    },
    "skills/memova-workflow/agents/openai.yaml": {
      "sha256": "ade51e2a4a35f1ce6b1d05bda9d183ce58a10aedeab183bedc6382fbe5b47bbd",
      "size": 445
    }
  }
}

SHA-256 of public snapshot: c9fc0f7767b2429980a672046ee55277b419ec8f437b75a2051fe27afb04c9d8