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-hub": {
        "local_path": "~/proj/scitex-hub",
        "pypi_name": "scitex-hub",
        "github_repo": "ywatanabe1989/scitex-hub",
        "import_name": "scitex_hub",
        "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-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-todo": {
        "local_path": "~/proj/scitex-todo",
        "pypi_name": "scitex-todo",
        "github_repo": "ywatanabe1989/scitex-todo",
        "import_name": "scitex_todo",
        "category": "library",
    },
    "scitex-web": {
        "local_path": "~/proj/scitex-web",
        "pypi_name": "scitex-web",
        "github_repo": "ywatanabe1989/scitex-web",
        "import_name": "scitex_web",
        "category": "library",
    },
}


[docs] 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()
[docs] 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(), }
[docs] 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