# Source code for scitex_dev._ecosystem._core

    #!/usr/bin/env python3
    # Timestamp: 2026-02-03
    # File: scitex_dev/ecosystem.py

    """SciTeX ecosystem package registry."""

    from pathlib import Path
    from typing import Dict, List, Optional, TypedDict

    class PackageInfo(TypedDict, total=False):
        """Package information structure.

        `category` controls how the auditor and ecosystem CLI treat the entry:

        - ``umbrella``     — the top-level scitex package; full audit
        - ``library``      — standard scitex-* leaf; full audit
        - ``external-lib`` — non-scitex-prefixed lib in the ecosystem
                              (figrecipe, socialia); full audit
        - ``template``     — scaffolds; auditor skips §C5/§E/§L by default
        - ``dataset``      — data-only repos (crossref-local, openalex-local);
                              auditor skips §E (no SKILL.md required)

        `archived` (optional, default False) — set ``True`` for repos that have
        been GitHub-archived (read-only) and superseded. The CLA / quality /
        publish auditors should skip archived entries by default; the entry is
        kept in the registry so historical references resolve.

        `umbrella_subcommand` (optional) — the name this package mounts as
        under the umbrella ``scitex`` CLI / MCP server. For ``scitex-<x>`` the
        default is the part after ``scitex-`` (so ``scitex-dataset`` →
        ``dataset``). Branded packages without the prefix (``socialia`` →
        ``social``, ``figrecipe`` → ``plt``) MUST set this explicitly; the
        umbrella shim and ``audit-cli §5b`` / ``audit-mcp-tools §1`` read it
        to know how to rewrite the program name and validate the mount
        namespace. See
        ``_skills/general/03_interface_02_cli/05a_umbrella-passthrough.md``.
        """

        local_path: str
        pypi_name: str
        github_repo: str
        import_name: str
        category: str
        archived: bool
        umbrella_subcommand: str

    # Ordered dict - order matters for display
    ECOSYSTEM: Dict[str, PackageInfo] = {
        "scitex": {
            "local_path": "~/proj/scitex-python",
            "pypi_name": "scitex",
            "github_repo": "ywatanabe1989/scitex-python",
            "import_name": "scitex",
            "category": "umbrella",
        },
        "scitex-io": {
            "local_path": "~/proj/scitex-io",
            "pypi_name": "scitex-io",
            "github_repo": "ywatanabe1989/scitex-io",
            "import_name": "scitex_io",
            "category": "library",
        },
        "scitex-stats": {
            "local_path": "~/proj/scitex-stats",
            "pypi_name": "scitex-stats",
            "github_repo": "ywatanabe1989/scitex-stats",
            "import_name": "scitex_stats",
            "category": "library",
        },
        "scitex-clew": {
            "local_path": "~/proj/scitex-clew",
            "pypi_name": "scitex-clew",
            "github_repo": "ywatanabe1989/scitex-clew",
            "import_name": "scitex_clew",
            "category": "library",
        },
        "scitex-cloud": {
            "local_path": "~/proj/scitex-cloud",
            "pypi_name": "scitex-cloud",
            "github_repo": "ywatanabe1989/scitex-cloud",
            "import_name": "scitex_cloud",
            "category": "library",
        },
        "figrecipe": {
            "local_path": "~/proj/figrecipe",
            "pypi_name": "figrecipe",
            "github_repo": "ywatanabe1989/figrecipe",
            "import_name": "figrecipe",
            "category": "external-lib",
        },
        "newb": {
            "local_path": "~/proj/newb",
            "pypi_name": "newb",
            "github_repo": "ywatanabe1989/newb",
            "import_name": "newb",
            "category": "external-lib",
        },
        "openalex-local": {
            "local_path": "~/proj/openalex-local",
            "pypi_name": "openalex-local",
            "github_repo": "ywatanabe1989/openalex-local",
            "import_name": "openalex_local",
            "category": "dataset",
        },
        "crossref-local": {
            "local_path": "~/proj/crossref-local",
            "pypi_name": "crossref-local",
            "github_repo": "ywatanabe1989/crossref-local",
            "import_name": "crossref_local",
            "category": "dataset",
        },
        "scitex-writer": {
            "local_path": "~/proj/scitex-writer",
            "pypi_name": "scitex-writer",
            "github_repo": "ywatanabe1989/scitex-writer",
            "import_name": "scitex_writer",
            "category": "library",
        },
        "scitex-dataset": {
            "local_path": "~/proj/scitex-dataset",
            "pypi_name": "scitex-dataset",
            "github_repo": "ywatanabe1989/scitex-dataset",
            "import_name": "scitex_dataset",
            "category": "library",
        },
        "socialia": {
            "local_path": "~/proj/socialia",
            "pypi_name": "socialia",
            "github_repo": "ywatanabe1989/socialia",
            "import_name": "socialia",
            "category": "external-lib",
        },
        "scitex-container": {
            "local_path": "~/proj/scitex-container",
            "pypi_name": "scitex-container",
            "github_repo": "ywatanabe1989/scitex-container",
            "import_name": "scitex_container",
            "category": "library",
        },
        "scitex-ssh": {
            "local_path": "~/proj/scitex-ssh",
            "pypi_name": "scitex-ssh",
            "github_repo": "ywatanabe1989/scitex-ssh",
            "import_name": "scitex_ssh",
            "category": "library",
        },
        "scitex-ui": {
            "local_path": "~/proj/scitex-ui",
            "pypi_name": "scitex-ui",
            "github_repo": "ywatanabe1989/scitex-ui",
            "import_name": "scitex_ui",
            "category": "library",
        },
        "scitex-app": {
            "local_path": "~/proj/scitex-app",
            "pypi_name": "scitex-app",
            "github_repo": "ywatanabe1989/scitex-app",
            "import_name": "scitex_app",
            "category": "library",
        },
        "scitex-audio": {
            "local_path": "~/proj/scitex-audio",
            "pypi_name": "scitex-audio",
            "github_repo": "ywatanabe1989/scitex-audio",
            "import_name": "scitex_audio",
            "category": "library",
        },
        "scitex-parallel": {
            "local_path": "~/proj/scitex-parallel",
            "pypi_name": "scitex-parallel",
            "github_repo": "ywatanabe1989/scitex-parallel",
            "import_name": "scitex_parallel",
            "category": "library",
        },
        "scitex-types": {
            "local_path": "~/proj/scitex-types",
            "pypi_name": "scitex-types",
            "github_repo": "ywatanabe1989/scitex-types",
            "import_name": "scitex_types",
            "category": "library",
        },
        "scitex-path": {
            "local_path": "~/proj/scitex-path",
            "pypi_name": "scitex-path",
            "github_repo": "ywatanabe1989/scitex-path",
            "import_name": "scitex_path",
            "category": "library",
        },
        "scitex-repro": {
            "local_path": "~/proj/scitex-repro",
            "pypi_name": "scitex-repro",
            "github_repo": "ywatanabe1989/scitex-repro",
            "import_name": "scitex_repro",
            "category": "library",
        },
        "scitex-compat": {
            "local_path": "~/proj/scitex-compat",
            "pypi_name": "scitex-compat",
            "github_repo": "ywatanabe1989/scitex-compat",
            "import_name": "scitex_compat",
            "category": "library",
        },
        "scitex-etc": {
            "local_path": "~/proj/scitex-etc",
            "pypi_name": "scitex-etc",
            "github_repo": "ywatanabe1989/scitex-etc",
            "import_name": "scitex_etc",
            "category": "library",
        },
        "scitex-gists": {
            "local_path": "~/proj/scitex-gists",
            "pypi_name": "scitex-gists",
            "github_repo": "ywatanabe1989/scitex-gists",
            "import_name": "scitex_gists",
            "category": "library",
        },
        "scitex-audit": {
            "local_path": "~/proj/scitex-audit",
            "pypi_name": "scitex-audit",
            "github_repo": "ywatanabe1989/scitex-audit",
            "import_name": "scitex_audit",
            "category": "library",
        },
        "scitex-db": {
            "local_path": "~/proj/scitex-db",
            "pypi_name": "scitex-db",
            "github_repo": "ywatanabe1989/scitex-db",
            "import_name": "scitex_db",
            "category": "library",
        },
        "scitex-scholar": {
            "local_path": "~/proj/scitex-scholar",
            "pypi_name": "scitex-scholar",
            "github_repo": "ywatanabe1989/scitex-scholar",
            "import_name": "scitex_scholar",
            "category": "library",
        },
        "scitex-seizure-metrics": {
            "local_path": "~/proj/scitex-seizure-metrics",
            "pypi_name": "scitex-seizure-metrics",
            "github_repo": "ywatanabe1989/scitex-seizure-metrics",
            "import_name": "scitex_seizure_metrics",
            "category": "library",
        },
        "scitex-template": {
            "local_path": "~/proj/scitex-template",
            "pypi_name": "scitex-template",
            "github_repo": "ywatanabe1989/scitex-template",
            "import_name": "scitex_template",
            "category": "template",
        },
        "scitex-dev": {
            "local_path": "~/proj/scitex-dev",
            "pypi_name": "scitex-dev",
            "github_repo": "ywatanabe1989/scitex-dev",
            "import_name": "scitex_dev",
            "category": "library",
        },
        "scitex-agent-container": {
            "local_path": "~/proj/scitex-agent-container",
            "pypi_name": "scitex-agent-container",
            "github_repo": "ywatanabe1989/scitex-agent-container",
            "import_name": "scitex_agent_container",
            "category": "library",
        },
        "scitex-orochi": {
            "local_path": "~/proj/scitex-orochi",
            "pypi_name": "scitex-orochi",
            "github_repo": "ywatanabe1989/scitex-orochi",
            "import_name": "scitex_orochi",
            "category": "library",
        },
        "scitex-str": {
            "local_path": "~/proj/scitex-str",
            "pypi_name": "scitex-str",
            "github_repo": "ywatanabe1989/scitex-str",
            "import_name": "scitex_str",
            "category": "library",
        },
        "scitex-logging": {
            "local_path": "~/proj/scitex-logging",
            "pypi_name": "scitex-logging",
            "github_repo": "ywatanabe1989/scitex-logging",
            "import_name": "scitex_logging",
            "category": "library",
        },
        "scitex-dict": {
            "local_path": "~/proj/scitex-dict",
            "pypi_name": "scitex-dict",
            "github_repo": "ywatanabe1989/scitex-dict",
            "import_name": "scitex_dict",
            "category": "library",
        },
        "scitex-browser": {
            "local_path": "~/proj/scitex-browser",
            "pypi_name": "scitex-browser",
            "github_repo": "ywatanabe1989/scitex-browser",
            "import_name": "scitex_browser",
            "category": "library",
        },
        "scitex-config": {
            "local_path": "~/proj/scitex-config",
            "pypi_name": "scitex-config",
            "github_repo": "ywatanabe1989/scitex-config",
            "import_name": "scitex_config",
            "category": "library",
        },
        "scitex-events": {
            "local_path": "~/proj/scitex-events",
            "pypi_name": "scitex-events",
            "github_repo": "ywatanabe1989/scitex-events",
            "import_name": "scitex_events",
            "category": "library",
        },
        "scitex-hpc": {
            "local_path": "~/proj/scitex-hpc",
            "pypi_name": "scitex-hpc",
            "github_repo": "ywatanabe1989/scitex-hpc",
            "import_name": "scitex_hpc",
            "category": "library",
        },
        "scitex-decorators": {
            "local_path": "~/proj/scitex-decorators",
            "pypi_name": "scitex-decorators",
            "github_repo": "ywatanabe1989/scitex-decorators",
            "import_name": "scitex_decorators",
            "category": "library",
        },
        "scitex-pd": {
            "local_path": "~/proj/scitex-pd",
            "pypi_name": "scitex-pd",
            "github_repo": "ywatanabe1989/scitex-pd",
            "import_name": "scitex_pd",
            "category": "library",
        },
        "scitex-plt": {
            "local_path": "~/proj/scitex-plt",
            "pypi_name": "scitex-plt",
            "github_repo": "ywatanabe1989/scitex-plt",
            "import_name": "scitex_plt",
            "category": "library",
        },
        "scitex-nn": {
            "local_path": "~/proj/scitex-nn",
            "pypi_name": "scitex-nn",
            "github_repo": "ywatanabe1989/scitex-nn",
            "import_name": "scitex_nn",
            "category": "library",
        },
        "scitex-ml": {
            "local_path": "~/proj/scitex-ml",
            "pypi_name": "scitex-ml",
            "github_repo": "ywatanabe1989/scitex-ml",
            "import_name": "scitex_ml",
            "category": "library",
        },
        "scitex-genai": {
            "local_path": "~/proj/scitex-genai",
            "pypi_name": "scitex-genai",
            "github_repo": "ywatanabe1989/scitex-genai",
            "import_name": "scitex_genai",
            "category": "library",
        },
        "scitex-gen": {
            "local_path": "~/proj/scitex-gen",
            "pypi_name": "scitex-gen",
            "github_repo": "ywatanabe1989/scitex-gen",
            "import_name": "scitex_gen",
            "category": "library",
        },
        "scitex-dsp": {
            "local_path": "~/proj/scitex-dsp",
            "pypi_name": "scitex-dsp",
            "github_repo": "ywatanabe1989/scitex-dsp",
            "import_name": "scitex_dsp",
            "category": "library",
        },
        "scitex-benchmark": {
            "local_path": "~/proj/scitex-benchmark",
            "pypi_name": "scitex-benchmark",
            "github_repo": "ywatanabe1989/scitex-benchmark",
            "import_name": "scitex_benchmark",
            "category": "library",
        },
        "scitex-bridge": {
            "local_path": "~/proj/scitex-bridge",
            "pypi_name": "scitex-bridge",
            "github_repo": "ywatanabe1989/scitex-bridge",
            "import_name": "scitex_bridge",
            "category": "library",
        },
        "scitex-capture": {
            "local_path": "~/proj/scitex-capture",
            "pypi_name": "scitex-capture",
            "github_repo": "ywatanabe1989/scitex-capture",
            "import_name": "scitex_capture",
            "category": "library",
        },
        "scitex-context": {
            "local_path": "~/proj/scitex-context",
            "pypi_name": "scitex-context",
            "github_repo": "ywatanabe1989/scitex-context",
            "import_name": "scitex_context",
            "category": "library",
        },
        "scitex-cv": {
            "local_path": "~/proj/scitex-cv",
            "pypi_name": "scitex-cv",
            "github_repo": "ywatanabe1989/scitex-cv",
            "import_name": "scitex_cv",
            "category": "library",
        },
        "scitex-datetime": {
            "local_path": "~/proj/scitex-datetime",
            "pypi_name": "scitex-datetime",
            "github_repo": "ywatanabe1989/scitex-datetime",
            "import_name": "scitex_datetime",
            "category": "library",
        },
        "scitex-git": {
            "local_path": "~/proj/scitex-git",
            "pypi_name": "scitex-git",
            "github_repo": "ywatanabe1989/scitex-git",
            "import_name": "scitex_git",
            "category": "library",
        },
        "scitex-introspect": {
            "local_path": "~/proj/scitex-introspect",
            "pypi_name": "scitex-introspect",
            "github_repo": "ywatanabe1989/scitex-introspect",
            "import_name": "scitex_introspect",
            "category": "library",
        },
        "scitex-linalg": {
            "local_path": "~/proj/scitex-linalg",
            "pypi_name": "scitex-linalg",
            "github_repo": "ywatanabe1989/scitex-linalg",
            "import_name": "scitex_linalg",
            "category": "library",
        },
        "scitex-msword": {
            "local_path": "~/proj/scitex-msword",
            "pypi_name": "scitex-msword",
            "github_repo": "ywatanabe1989/scitex-msword",
            "import_name": "scitex_msword",
            "category": "library",
        },
        "scitex-notebook": {
            "local_path": "~/proj/scitex-notebook",
            "pypi_name": "scitex-notebook",
            "github_repo": "ywatanabe1989/scitex-notebook",
            "import_name": "scitex_notebook",
            "category": "library",
        },
        "scitex-notification": {
            "local_path": "~/proj/scitex-notification",
            "pypi_name": "scitex-notification",
            "github_repo": "ywatanabe1989/scitex-notification",
            "import_name": "scitex_notification",
            "category": "library",
        },
        "scitex-os": {
            "local_path": "~/proj/scitex-os",
            "pypi_name": "scitex-os",
            "github_repo": "ywatanabe1989/scitex-os",
            "import_name": "scitex_os",
            "category": "library",
        },
        "scitex-resource": {
            "local_path": "~/proj/scitex-resource",
            "pypi_name": "scitex-resource",
            "github_repo": "ywatanabe1989/scitex-resource",
            "import_name": "scitex_resource",
            "category": "library",
        },
        "scitex-security": {
            "local_path": "~/proj/scitex-security",
            "pypi_name": "scitex-security",
            "github_repo": "ywatanabe1989/scitex-security",
            "import_name": "scitex_security",
            "category": "library",
        },
        "scitex-session": {
            "local_path": "~/proj/scitex-session",
            "pypi_name": "scitex-session",
            "github_repo": "ywatanabe1989/scitex-session",
            "import_name": "scitex_session",
            "category": "library",
        },
        "scitex-sh": {
            "local_path": "~/proj/scitex-sh",
            "pypi_name": "scitex-sh",
            "github_repo": "ywatanabe1989/scitex-sh",
            "import_name": "scitex_sh",
            "category": "library",
        },
        "scitex-tex": {
            "local_path": "~/proj/scitex-tex",
            "pypi_name": "scitex-tex",
            "github_repo": "ywatanabe1989/scitex-tex",
            "import_name": "scitex_tex",
            "category": "library",
        },
        "scitex-web": {
            "local_path": "~/proj/scitex-web",
            "pypi_name": "scitex-web",
            "github_repo": "ywatanabe1989/scitex-web",
            "import_name": "scitex_web",
            "category": "library",
        },
    }

    def get_local_path(package: str) -> Optional[Path]:
        """Get expanded local path for a package."""
        if package not in ECOSYSTEM:
            return None
        return Path(ECOSYSTEM[package]["local_path"]).expanduser()

    def get_all_packages() -> List[str]:
        """Get list of all ecosystem package names."""
        return list(ECOSYSTEM.keys())

    # --------------------------------------------------------------------- #
    # Category-aware audit skip                                              #
    # --------------------------------------------------------------------- #

    # Per-auditor list of ECOSYSTEM categories that don't apply.
    # `archived` is short-circuited separately (every auditor skips archived).
    _CATEGORY_SKIP: dict[str, frozenset[str]] = {
        "audit-cli": frozenset({"template"}),
        "audit-mcp-tools": frozenset({"template", "dataset", "umbrella"}),
        "audit-skills": frozenset(),
        "audit-python-apis": frozenset({"template"}),
        "audit-project": frozenset(),
    }

    def should_skip_audit(package: str, auditor: str) -> tuple[bool, str]:
        """Return (skip, reason) for running `auditor` on `package`.

        `auditor` is one of the keys in `_CATEGORY_SKIP`. Unknown auditors
        return (False, "") — fail open so a typo doesn't silently skip.

        Skip semantics:
        - archived packages are skipped for *every* auditor.
        - per-auditor categories listed in _CATEGORY_SKIP are skipped.
        - unknown package (not in ECOSYSTEM) is NOT skipped — the auditor's
          own not-found path will handle it.
        """
        info = ECOSYSTEM.get(package)
        if info is None:
            return False, ""
        if info.get("archived"):
            return True, "archived"
        cat = info.get("category", "")
        skip_set = _CATEGORY_SKIP.get(auditor, frozenset())
        if cat in skip_set:
            return True, f"category={cat}"
        return False, ""

    # EOF