diff --git a/skills/nemo-retriever/BENCHMARK.md b/skills/nemo-retriever/BENCHMARK.md index 27afb225df..c42eb4eb62 100644 --- a/skills/nemo-retriever/BENCHMARK.md +++ b/skills/nemo-retriever/BENCHMARK.md @@ -9,7 +9,7 @@ This benchmark summarizes 3-Tier Evaluation from NVSkills-Eval results for the s - Skill: `nemo-retriever` - Evaluation date: 2026-05-29 - NVSkills-Eval profile: `external` -- Overall verdict: FAIL +- Overall verdict: PASS - Tier 3 live agent evaluation: not available in this report ## Agents Used @@ -40,7 +40,7 @@ Tier 3 dimension rollup was not available in this report. ## Tier 1: Static Validation Summary -Tier 1 validation passed with observations. NVSkills-Eval ran 9 checks and found 20 total findings. +Tier 1 validation passed with observations. NVSkills-Eval ran 9 checks and found 21 total findings. Top findings: @@ -52,14 +52,13 @@ Top findings: ## Tier 2: Deduplication Summary -Tier 2 validation reported findings. NVSkills-Eval ran 2 checks and found 1 total findings. +Tier 2 validation passed. NVSkills-Eval ran 2 checks and found 0 total findings. -Top findings: +Notable observations: -- HIGH DUPLICATE/duplicate: Duplicate content found across references/cli/query.md and references/pitfalls.md: - "## Common failure modes" in references/cli/query.md (lines 78-90) - vs "## Failure modes (expected, not errors)" in references/pitfalls.md (lines 18-26) (`references/cli/query.md:78`) +- Context Deduplication: Collected 9 file(s) +- Inter-Skill Deduplication: Parsed skill 'nemo-retriever': 276 char description ## Publication Recommendation -The skill should be reviewed before NVSkills-Eval publication. Skill owners should address the findings above and rerun NVSkills-Eval to refresh this benchmark. +The skill is suitable to proceed toward NVSkills-Eval publication based on this benchmark. Skill owners should keep this file with the skill and refresh it when the evaluation dataset, skill behavior, or target agents materially change. diff --git a/skills/nemo-retriever/SKILL.md b/skills/nemo-retriever/SKILL.md index 63a5aa8a46..a479bfabc6 100644 --- a/skills/nemo-retriever/SKILL.md +++ b/skills/nemo-retriever/SKILL.md @@ -26,7 +26,7 @@ If `command -v retriever` returns nothing, follow `references/install.md` to ins | Turn type | Read this once | Then execute | | :--- | :--- | :--- | | **Setup turn** (first turn — `./lancedb/nv-ingest.lance` doesn't exist) | `references/setup.md` | Build the index | -| **Query turn** (every subsequent turn — user asks a question) | `references/query.md` | One `retriever query` call, then `Write` `./output.json` | +| **Query turn** (every subsequent turn — user asks a question) | `references/query.md` | One `retriever query` call, then synthesize the answer | | Anything errored or returned empty | `references/pitfalls.md` | Apply the named recovery; do not improvise | For the full `retriever ingest` / `retriever query` CLI specs, see `references/cli/ingest.md` and `references/cli/query.md`. You do not need these for routine turns — `/bin/retriever --help` is faster. @@ -34,8 +34,8 @@ For the full `retriever ingest` / `retriever query` CLI specs, see `references/c ## Hard limits (apply to every turn) - **Setup turn**: build the index in one shell command (see `references/setup.md`). STOP after the index lands. -- **Query turn**: at most **2 Bash calls** — 1 `retriever query`, +1 optional targeted text-extract per `references/query.md`. Then `Write` `./output.json` and STOP. -- **No narration between tool calls.** Tokens you emit between calls become input + cached input for every later turn — quadratic cost. Go straight from reading the summary to writing the JSON file. +- **Query turn**: at most **2 Bash calls** — 1 `retriever query`, +1 optional targeted text-extract per `references/query.md`. Then STOP. +- **No narration between tool calls.** Tokens you emit between calls become input + cached input for every later turn — quadratic cost. Go straight from reading the summary to producing the answer. - **Banned**: `TodoWrite`, Glob, Grep, `Read` of whole PDFs, re-running setup, spawning subagents, speculative "confirmation" calls. Long query turns (5+ tool calls, 1M+ cache-read tokens) cost ~5× a disciplined turn and almost always still produce the wrong answer. **Answering partially beats timing out.** diff --git a/skills/nemo-retriever/references/pitfalls.md b/skills/nemo-retriever/references/pitfalls.md index 9d43574871..8322755e06 100644 --- a/skills/nemo-retriever/references/pitfalls.md +++ b/skills/nemo-retriever/references/pitfalls.md @@ -17,12 +17,11 @@ For an unlisted subcommand: `/bin/retriever --help` ## Failure modes (expected, not errors) -- **First `ingest` takes ~60s+** — vLLM warmup. Expected. -- **First `query` takes ~10–15s** — embedder cold-start. Expected. -- **Empty result** — ingest didn't run. Use the fallback above. +- **Empty result** — ingest didn't run. **Use the fallback above** (don't re-ingest). - **`Clamping num_partitions ...`** — informational on tiny corpora, not an error. -- **Low-relevance top hit on tiny corpus** — look at `_distance` *gaps* between hits, not absolute values. -- **Page-element-detection warnings during ingest** — non-fatal as long as the embedding step itself succeeds (and they're silenced by `--quiet` on a successful run). +- **Page-element-detection warnings during ingest** — non-fatal; silenced by `--quiet`. + +For cold-start latencies, `Table not found` errors, and low-relevance diagnostics see `references/cli/query.md` and `references/cli/ingest.md`. ## You ran more than 2 Bash calls on a query turn diff --git a/skills/nemo-retriever/references/query.md b/skills/nemo-retriever/references/query.md index fc98e08c52..669c5da4f3 100644 --- a/skills/nemo-retriever/references/query.md +++ b/skills/nemo-retriever/references/query.md @@ -2,7 +2,7 @@ ## Filename fast path — try BEFORE `retriever query` -If the user's question literally contains a PDF basename from `./pdfs/` (stem ≥6 chars, with or without `.pdf`, case-insensitive), skip semantic search. Direct pdfium extraction on the named file is faster and avoids semantic-search misses — the right doc is given, and pages rank by query-token overlap. +If the user's question literally contains a PDF basename from `./pdfs/` **including the `.pdf` extension** (stem ≥6 chars, case-insensitive), skip semantic search. Direct pdfium extraction on the named file is faster and avoids semantic-search misses — the right doc is given, and pages rank by query-token overlap. ```bash /bin/python /scripts/filename_fast_path.py "" diff --git a/skills/nemo-retriever/scripts/filename_fast_path.py b/skills/nemo-retriever/scripts/filename_fast_path.py index f11bfd8223..5eb8974006 100644 --- a/skills/nemo-retriever/scripts/filename_fast_path.py +++ b/skills/nemo-retriever/scripts/filename_fast_path.py @@ -1,8 +1,8 @@ """Query-turn filename fast path for the nemo-retriever skill. Reads `./pdfs/` from the current working directory. If the query string -literally contains any PDF basename (with or without the `.pdf` extension, -stem ≥6 chars, case-insensitive), runs `retriever pdf stage page-elements` +literally contains any PDF basename **including the `.pdf` extension** +(stem ≥6 chars, case-insensitive), runs `retriever pdf stage page-elements` on each matched file via pdfium, ranks pages by query-token frequency, and emits a top-10 ranking + the top page's raw text. @@ -21,8 +21,10 @@ pages, up to 10), followed by the top- ranked page's raw text (first 4000 chars). -Exit code is 0 in all three success outcomes; non-zero only on hard errors -(missing ./pdfs, page-elements subprocess failure, malformed sidecar JSON). +Exit code is 0 in all three success outcomes; non-zero only when `./pdfs/` is +missing or unreadable. Per-file errors (extraction subprocess failure, malformed +sidecar JSON) log a warning to stderr and are skipped — if every match is bad, +the script falls through to `NO_TEXT`. """ from __future__ import annotations @@ -47,43 +49,51 @@ def find_matches(query_lower: str, basenames: list[str]) -> list[str]: - """Return PDF basenames whose name (with or without .pdf) appears verbatim - in the lowercased query. Skip stems shorter than MIN_STEM_LEN.""" + """Return PDF basenames whose full name (including the `.pdf` extension) + appears verbatim in the lowercased query. Skip stems shorter than MIN_STEM_LEN. + Requiring the extension avoids false positives on common English words that + happen to appear as PDF stems (e.g. `report.pdf`, `market.pdf`).""" matches = [] for name in basenames: stem, ext = os.path.splitext(name) if ext.lower() != ".pdf" or len(stem) < MIN_STEM_LEN: continue - if name.lower() in query_lower or stem.lower() in query_lower: + if name.lower() in query_lower: matches.append(name) return matches def extract_pages(retriever_bin: str, matches: list[str]) -> None: + """Extract each matched PDF; log per-file failures and continue so a single + bad PDF doesn't block remaining matches.""" os.makedirs(EXTRACT_OUT, exist_ok=True) for m in matches: - subprocess.run( - [ - retriever_bin, - "pdf", - "stage", - "page-elements", - f"{PDF_DIR}/{m}", - "--method", - "pdfium", - "--json-output-dir", - EXTRACT_OUT, - "--compact-json", - ], - check=True, - ) + try: + subprocess.run( + [ + retriever_bin, + "pdf", + "stage", + "page-elements", + f"{PDF_DIR}/{m}", + "--method", + "pdfium", + "--json-output-dir", + EXTRACT_OUT, + "--compact-json", + ], + check=True, + stdout=subprocess.DEVNULL, + ) + except subprocess.CalledProcessError as exc: + print(f"WARN: page-elements failed on {m}: exit {exc.returncode}", file=sys.stderr) def sidecar_path(pdf_name: str) -> str | None: stem = os.path.splitext(pdf_name)[0] candidates = ( f"{EXTRACT_OUT}/{pdf_name}.pdf_extraction.json", - f"{EXTRACT_OUT}/{stem}.pdf.pdf_extraction.json", + f"{EXTRACT_OUT}/{stem}.pdf_extraction.json", ) for c in candidates: if os.path.exists(c): @@ -92,7 +102,12 @@ def sidecar_path(pdf_name: str) -> str | None: def page_records(sidecar: str) -> list[dict]: - data = json.load(open(sidecar)) + try: + with open(sidecar) as fh: + data = json.load(fh) + except json.JSONDecodeError as exc: + print(f"ERROR: malformed JSON in sidecar {sidecar!r}: {exc}", file=sys.stderr) + return [] if isinstance(data, list): return data if isinstance(data, dict): @@ -138,7 +153,11 @@ def main() -> int: ql = query.lower() retriever_bin = os.path.join(os.path.dirname(sys.executable), "retriever") - basenames = sorted(p for p in os.listdir(PDF_DIR) if p.lower().endswith(".pdf")) + try: + basenames = sorted(p for p in os.listdir(PDF_DIR) if p.lower().endswith(".pdf")) + except (FileNotFoundError, PermissionError) as exc: + print(f"ERROR: cannot list {PDF_DIR}: {exc}", file=sys.stderr) + return 1 matches = find_matches(ql, basenames) if not matches: print("NO_MATCH") diff --git a/skills/nemo-retriever/skill-card.md b/skills/nemo-retriever/skill-card.md index 76ab4b7582..5ee0ff2bc4 100644 --- a/skills/nemo-retriever/skill-card.md +++ b/skills/nemo-retriever/skill-card.md @@ -9,7 +9,7 @@ NVIDIA
### License/Terms of Use:
Apache 2.0
## Use Case:
-Developers and engineers who need to search, index, or answer questions across PDF and document collections using RAG and vector search via the retriever CLI.
+Developers and engineers who need to search, index, or answer questions over collections of PDFs and documents using a local RAG/vector-search pipeline powered by the retriever CLI.
### Deployment Geography for Use:
Global
@@ -20,22 +20,22 @@ Mitigation: Review and scan skill before deployment.
## Reference(s):
- [NeMo Retriever Library Documentation](https://docs.nvidia.com/nemo/retriever/latest/extraction/overview/)
-- [Install Guide](references/install.md)
-- [Setup Guide](references/setup.md)
-- [Query Workflow](references/query.md)
-- [Pitfalls and Recovery](references/pitfalls.md)
-- [CLI: ingest](references/cli/ingest.md)
-- [CLI: query](references/cli/query.md)
+- [CLI reference: retriever ingest](references/cli/ingest.md)
+- [CLI reference: retriever query](references/cli/query.md)
+- [Installation guide](references/install.md)
+- [Query workflow](references/query.md)
+- [Setup guide](references/setup.md)
+- [Pitfalls and recovery](references/pitfalls.md)
## Skill Output:
-**Output Type(s):** [Shell commands, JSON]
-**Output Format:** [JSON]
+**Output Type(s):** [Shell commands, JSON, Synthesized answers]
+**Output Format:** [Markdown with inline bash code blocks and JSON query results]
**Output Parameters:** [1D]
-**Other Properties Related to Output:** [None]
+**Other Properties Related to Output:** [Query results are JSON arrays sorted by vector distance; final answers are synthesized from retrieved context]
## Evaluation Tasks:
-NVSkills-Eval 3-Tier evaluation (external profile); Tier 1 static validation (9 checks, 20 findings), Tier 2 deduplication (2 checks, 1 finding). Tier 3 live agent evaluation not available in this report.
+Evaluated through NVSkills-Eval 3-Tier framework (profile: external). Tier 1: 9 static validation checks (21 findings, passed with observations). Tier 2: 2 deduplication checks (0 findings, passed). Overall verdict: PASS.
## Evaluation Metrics Used:
Reported benchmark dimensions:
@@ -48,7 +48,7 @@ Reported benchmark dimensions:
## Skill Version(s):
-3fa00d94 (source: git SHA, committed 2026-05-28)
+25.3.0-1014-gb7fdbb45 (source: git describe)
## Ethical Considerations:
NVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. When downloaded or used in accordance with our terms of service, developers should work with their internal team to ensure this skill meets requirements for the relevant industry and use case and addresses unforeseen product misuse.
diff --git a/skills/nemo-retriever/skill.oms.sig b/skills/nemo-retriever/skill.oms.sig index 7a24f2c1f8..f3c4b36e2f 100644 --- a/skills/nemo-retriever/skill.oms.sig +++ b/skills/nemo-retriever/skill.oms.sig @@ -1 +1 @@ -{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"x509CertificateChain":{"certificates":[{"rawBytes":"MIICgzCCAgmgAwIBAgIUKIyS7SxNteQIiWzK1dWj85E6520wCgYIKoZIzj0EAwMwVTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjEpMCcGA1UEAwwgTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBJQ0EgMDEwHhcNMjYwNDAxMDAwMDAwWhcNMjgwNDIyMTUzMzA5WjBUMQswCQYDVQQGEwJVUzEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMSgwJgYDVQQDDB9OVklESUEgQWdlbnQgU2tpbGxzIFNpZ25pbmcgMDAxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEYoRM9bQl/dGlwSRNi6bTpIJUXH8Nv9GciP6LSflJYYMLCc296kpyuTSsk5ddbAWiDcFX3C/ydX3jwc+qCLYP6uHy9XphyLjOQ27Yb2J6rBLVtRBS1mgGco/Gr7fL6ODco4GaMIGXMB0GA1UdDgQWBBRQ/5ZW3nJ6lmo9SVk7I15o7UGmpTAfBgNVHSMEGDAWgBRPGpILxMBBleJSsBGjrMKsby1CgjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLm5kaXMubnZpZGlhLmNvbTAKBggqhkjOPQQDAwNoADBlAjAUygu/GiOCIXrgGr4SmLgeEVDcEitfFUv7ALbvLVGVyMysB3mxmO/uInZfXzWcJZsCMQDxuoxj4ZmO30jhkPIcCxGFCOvnUsnfU3TfGcouYm4M6iRpbKvtVnHPiy4bi6pcKf0="},{"rawBytes":"MIICiDCCAg6gAwIBAgIUZsIuSv9NkpJCNqtYEfCouVv5BzowCgYIKoZIzj0EAwMwUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTAgFw0yNjA0MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjEpMCcGA1UEAwwgTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBJQ0EgMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASI72cR3ctKGg4VWnB3bNja6g1Z2PnOmFEopkPof+QeIcPk9rT+g9MjJnq51EQXL93a7C2GJ9J985G4o2V85VD7wJ1RaXhluHW2rf3y8bQGeAYaKMr5s/hUgn+M3/9WlWejgaAwgZ0wHQYDVR0OBBYEFE8akgvEwEGV4lKwEaOswqxvLUKCMB8GA1UdIwQYMBaAFItnoAjjfuCEUvzyvWyI2vOGvwPjMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AubmRpcy5udmlkaWEuY29tMAoGCCqGSM49BAMDA2gAMGUCMQCeIMMfAbyzPDacw2MxG+Yt1cikrJX/DVxiGfXuHmkkXn6VgSzE79+lkqDErpVO2gYCMCNEColOyvUvkzZGUEI1hQ3PfMgi3FIo9tHoBKMw4/wGBLFpu/0ubtmbBXM6/UMOEw=="},{"rawBytes":"MIICRTCCAcygAwIBAgIUeJdY3rV86EdvFmG7L8LJBsyQFYkwCgYIKoZIzj0EAwMwUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTAgFw0yNjA0MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABAYpiXCDjJ9NT2eSDhyHJVSw1Tbze18cGG2F/578oWvHxg23eQAhNRYdq88i1iOshZSO6C29doKui5Xpmo/7Ctw9Sx4PP2RzOmIuOLCuTdNtKcTRwi4GEsd5BAFvWj42M6NjMGEwHQYDVR0OBBYEFItnoAjjfuCEUvzyvWyI2vOGvwPjMB8GA1UdIwQYMBaAFItnoAjjfuCEUvzyvWyI2vOGvwPjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMCwtAjWLaNwgGWNCgdyNoTyvNhqWRECRJV2r3+7w8g0PL6NHLOsbkgE09BH95h8XlgIwTaQmbbUh2ChAJ5TA1wRiVDnCcvbzHlZl2jM2FcwQQZlk19LOAbyGMRixbu2Ww/rj"}]},"tlogEntries":[]},"dsseEnvelope":{"payload":"ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YxIiwKICAic3ViamVjdCI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAibmVtby1yZXRyaWV2ZXIiLAogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiODUyNDNkOGJhYjgwMWY3OTEwY2Q1NDU4ZmRkYzIwZmE5YjI0NTYzMTRkMTk3MTcyYzQ2ZGU1NDA0N2RjOWRiYiIKICAgICAgfQogICAgfQogIF0sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9tb2RlbF9zaWduaW5nL3NpZ25hdHVyZS92MS4wIiwKICAicHJlZGljYXRlIjogewogICAgInNlcmlhbGl6YXRpb24iOiB7CiAgICAgICJtZXRob2QiOiAiZmlsZXMiLAogICAgICAiaWdub3JlX3BhdGhzIjogWwogICAgICAgICIuZ2l0aWdub3JlIiwKICAgICAgICAiLmdpdGh1YiIsCiAgICAgICAgIi5naXQiLAogICAgICAgICIuZ2l0YXR0cmlidXRlcyIKICAgICAgXSwKICAgICAgImhhc2hfdHlwZSI6ICJzaGEyNTYiLAogICAgICAiYWxsb3dfc3ltbGlua3MiOiBmYWxzZQogICAgfSwKICAgICJyZXNvdXJjZXMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjU0ZmMwZDYyOGY1ODlmOWJkM2NhZjVmYjYxZGEwNGM4NTJjMWNhOTI3MGJlYTY0ODc1ODhlZjVlMGFjNzIxNTUiLAogICAgICAgICJuYW1lIjogIkJFTkNITUFSSy5tZCIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjEyNDQ3NWU0MjhjYjE0Y2Y4ZWIyNzZhODhjZmM4M2E1MTQ4OTIwMjJlMzU2MzY3MDUzNmRlYjVlMWM4MDAyYzUiLAogICAgICAgICJuYW1lIjogIlNLSUxMLm1kIiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiOWIxNTlhNjcxY2RlY2VlNzY2YmMzOTA4MDYxNTE2YzE2MTFkNzQwNDIyMGZhYjhmYWZlZTBmMTc0MTE4NDU3MiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9jbGkvaW5nZXN0Lm1kIiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiMGM2MmZmZmNiMGY4NDRmOGJmZDRmMjlhZGM5NjFkNWJhYTAwYzFlMDlkYTVhYTlmNTE2OGI3NjY1YzkyNzQ5NiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9jbGkvcXVlcnkubWQiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICI5OWUyYjBiODU2YWM4MGUyMWUwOWRlNjc1MzE4MGY3YTYxOTYyNGE0MzcyMTJkM2M2NjljZDMyNzE4MGY0NzI5IiwKICAgICAgICAibmFtZSI6ICJyZWZlcmVuY2VzL2luc3RhbGwubWQiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICJmNzQ0OTczZWRmZTEwZDc2N2NlMjc0NjEyNGEzYWRiYTg3MzY1MDc4NDQ2N2MwMDExNzI2MGEwNTdkMThhMTZkIiwKICAgICAgICAibmFtZSI6ICJyZWZlcmVuY2VzL3BpdGZhbGxzLm1kIiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiNjZhNWU0YzliNzFkODU4NjY4YjlmODg1OTBhNDAzOTU2NTgwZTI2MjE1Njg3M2UwYjNiMWYzZDg0NTY5NDg5ZiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9xdWVyeS5tZCIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjEzMjUyNzRlMWFhZmExMTcyOGQwMzMwMGRmYjZmODA5MWIxMGM0YjFmNzU4NjAzZjZjNjVkNTAyNWIxN2EyYjciLAogICAgICAgICJuYW1lIjogInJlZmVyZW5jZXMvc2V0dXAubWQiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICI2YTI0NjkxNjY1ZGE0MDJmYWMwYzllOTQwMzExMmExY2RiZWJiOWNkNGQ2NTM5NTUwY2RlYmQyNDZkYWUwNzUwIiwKICAgICAgICAibmFtZSI6ICJzY3JpcHRzL2ZpbGVuYW1lX2Zhc3RfcGF0aC5weSIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjljNjUzOTkxYmU3NTNlZTYwMmU0NTllMTU1N2ZlYjAwNmFlZWIxMjQ0MDI5OGMwODIxYmRlYWQxMThlZTk2MzgiLAogICAgICAgICJuYW1lIjogInNjcmlwdHMvZ3JlcF9jb3JwdXMucHkiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICI5ZThiMTU5MzQwMzZhZGMzMjJmODE5N2UxNzlmODQzZTM2YTg3ZjM5NWM3NDk0NmJhZWU5ODUwMjFlZDk1MWI5IiwKICAgICAgICAibmFtZSI6ICJza2lsbC1jYXJkLm1kIiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIKICAgICAgfQogICAgXQogIH0KfQ==","payloadType":"application/vnd.in-toto+json","signatures":[{"sig":"MGYCMQDsdEkyBxLW9Zcl1KDY7nz8x01dAXjwrah5KyFsMuu8F38rLCczyjaGpoO1gq6uX/4CMQCcAo5nsnRaf3XyAQsnF7jQyKJmITphJ4E9dHuQE5duIxRXpjCA3BB9cnMidfq7mQk=","keyid":""}]}} +{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"x509CertificateChain":{"certificates":[{"rawBytes":"MIICgzCCAgmgAwIBAgIUKIyS7SxNteQIiWzK1dWj85E6520wCgYIKoZIzj0EAwMwVTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjEpMCcGA1UEAwwgTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBJQ0EgMDEwHhcNMjYwNDAxMDAwMDAwWhcNMjgwNDIyMTUzMzA5WjBUMQswCQYDVQQGEwJVUzEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMSgwJgYDVQQDDB9OVklESUEgQWdlbnQgU2tpbGxzIFNpZ25pbmcgMDAxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEYoRM9bQl/dGlwSRNi6bTpIJUXH8Nv9GciP6LSflJYYMLCc296kpyuTSsk5ddbAWiDcFX3C/ydX3jwc+qCLYP6uHy9XphyLjOQ27Yb2J6rBLVtRBS1mgGco/Gr7fL6ODco4GaMIGXMB0GA1UdDgQWBBRQ/5ZW3nJ6lmo9SVk7I15o7UGmpTAfBgNVHSMEGDAWgBRPGpILxMBBleJSsBGjrMKsby1CgjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLm5kaXMubnZpZGlhLmNvbTAKBggqhkjOPQQDAwNoADBlAjAUygu/GiOCIXrgGr4SmLgeEVDcEitfFUv7ALbvLVGVyMysB3mxmO/uInZfXzWcJZsCMQDxuoxj4ZmO30jhkPIcCxGFCOvnUsnfU3TfGcouYm4M6iRpbKvtVnHPiy4bi6pcKf0="},{"rawBytes":"MIICiDCCAg6gAwIBAgIUZsIuSv9NkpJCNqtYEfCouVv5BzowCgYIKoZIzj0EAwMwUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTAgFw0yNjA0MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowVTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjEpMCcGA1UEAwwgTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBJQ0EgMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASI72cR3ctKGg4VWnB3bNja6g1Z2PnOmFEopkPof+QeIcPk9rT+g9MjJnq51EQXL93a7C2GJ9J985G4o2V85VD7wJ1RaXhluHW2rf3y8bQGeAYaKMr5s/hUgn+M3/9WlWejgaAwgZ0wHQYDVR0OBBYEFE8akgvEwEGV4lKwEaOswqxvLUKCMB8GA1UdIwQYMBaAFItnoAjjfuCEUvzyvWyI2vOGvwPjMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AubmRpcy5udmlkaWEuY29tMAoGCCqGSM49BAMDA2gAMGUCMQCeIMMfAbyzPDacw2MxG+Yt1cikrJX/DVxiGfXuHmkkXn6VgSzE79+lkqDErpVO2gYCMCNEColOyvUvkzZGUEI1hQ3PfMgi3FIo9tHoBKMw4/wGBLFpu/0ubtmbBXM6/UMOEw=="},{"rawBytes":"MIICRTCCAcygAwIBAgIUeJdY3rV86EdvFmG7L8LJBsyQFYkwCgYIKoZIzj0EAwMwUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTAgFw0yNjA0MDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowUTELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEk5WSURJQSBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcTlZJRElBIEFnZW50IENhcGFiaWxpdGllcyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABAYpiXCDjJ9NT2eSDhyHJVSw1Tbze18cGG2F/578oWvHxg23eQAhNRYdq88i1iOshZSO6C29doKui5Xpmo/7Ctw9Sx4PP2RzOmIuOLCuTdNtKcTRwi4GEsd5BAFvWj42M6NjMGEwHQYDVR0OBBYEFItnoAjjfuCEUvzyvWyI2vOGvwPjMB8GA1UdIwQYMBaAFItnoAjjfuCEUvzyvWyI2vOGvwPjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMCwtAjWLaNwgGWNCgdyNoTyvNhqWRECRJV2r3+7w8g0PL6NHLOsbkgE09BH95h8XlgIwTaQmbbUh2ChAJ5TA1wRiVDnCcvbzHlZl2jM2FcwQQZlk19LOAbyGMRixbu2Ww/rj"}]},"tlogEntries":[]},"dsseEnvelope":{"payload":"ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YxIiwKICAic3ViamVjdCI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAibmVtby1yZXRyaWV2ZXIiLAogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiOTNlOTNiZDFlYTIxMWM3NDUxMjNhMTNmNTRmMWE0MTllMDhjZjJkNzU4NWEyOWM5NTdkZjBlNTAwMjI0ZTY1MCIKICAgICAgfQogICAgfQogIF0sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9tb2RlbF9zaWduaW5nL3NpZ25hdHVyZS92MS4wIiwKICAicHJlZGljYXRlIjogewogICAgInJlc291cmNlcyI6IFsKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiNzIxNTZjNDIwYTc2ZjFjNjc4YzYwYjliODY4ODkzNTdiM2UyMTM5Y2QyZjM1NmM2Y2QxZDFjZTE1ZjI2M2ZiYiIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiLAogICAgICAgICJuYW1lIjogIkJFTkNITUFSSy5tZCIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiOTYwNDFhNzI2ZmFiOGE2NTExYjJlZjZkYmRjYTY3Y2Q2ZmMyYmY4Nzg1YmZhYjkwYTE2ODRjNmY0N2Q1NGUwZiIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiLAogICAgICAgICJuYW1lIjogIlNLSUxMLm1kIgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICI5YjE1OWE2NzFjZGVjZWU3NjZiYzM5MDgwNjE1MTZjMTYxMWQ3NDA0MjIwZmFiOGZhZmVlMGYxNzQxMTg0NTcyIiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9jbGkvaW5nZXN0Lm1kIgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICIwYzYyZmZmY2IwZjg0NGY4YmZkNGYyOWFkYzk2MWQ1YmFhMDBjMWUwOWRhNWFhOWY1MTY4Yjc2NjVjOTI3NDk2IiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9jbGkvcXVlcnkubWQiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjk5ZTJiMGI4NTZhYzgwZTIxZTA5ZGU2NzUzMTgwZjdhNjE5NjI0YTQzNzIxMmQzYzY2OWNkMzI3MTgwZjQ3MjkiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IiwKICAgICAgICAibmFtZSI6ICJyZWZlcmVuY2VzL2luc3RhbGwubWQiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogIjNjNDljZmU5YTM0OTliYTZjMDliNjQ4ZjQxMjE3M2E4ZTExMzc5ZmRhZGMyZDIzMWQ0MDhjOGVhOGUyZTY5MDQiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IiwKICAgICAgICAibmFtZSI6ICJyZWZlcmVuY2VzL3BpdGZhbGxzLm1kIgogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6ICI2ZDlkZjg5NGM2ZTg5MjM5MmVlZjBiYTU5NGU3YjRjNGVhMTM5NmIyZmMwNWE0MTMwZjIyOWE3ZDJiOTdjZjU3IiwKICAgICAgICAiYWxnb3JpdGhtIjogInNoYTI1NiIsCiAgICAgICAgIm5hbWUiOiAicmVmZXJlbmNlcy9xdWVyeS5tZCIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiMTMyNTI3NGUxYWFmYTExNzI4ZDAzMzAwZGZiNmY4MDkxYjEwYzRiMWY3NTg2MDNmNmM2NWQ1MDI1YjE3YTJiNyIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiLAogICAgICAgICJuYW1lIjogInJlZmVyZW5jZXMvc2V0dXAubWQiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogImQ5Y2Y5ZmNmZTA5OTZmYTdkODBmZWI3OGY0NjdlYzFiZTg5ZmQ5YjhjMTFjYjNlOWEwNzgyMDJlODlmMzA5NjkiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IiwKICAgICAgICAibmFtZSI6ICJzY3JpcHRzL2ZpbGVuYW1lX2Zhc3RfcGF0aC5weSIKICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiAiOWM2NTM5OTFiZTc1M2VlNjAyZTQ1OWUxNTU3ZmViMDA2YWVlYjEyNDQwMjk4YzA4MjFiZGVhZDExOGVlOTYzOCIsCiAgICAgICAgImFsZ29yaXRobSI6ICJzaGEyNTYiLAogICAgICAgICJuYW1lIjogInNjcmlwdHMvZ3JlcF9jb3JwdXMucHkiCiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogImQ3NzRiZjk0ZmUxZjg4MDJjYjRkZDE5OTIxZTIwZjhmMzVmYzg1NmFiMjlhZDNhNTQ3M2Y5MGVlOTFmN2I0YTYiLAogICAgICAgICJhbGdvcml0aG0iOiAic2hhMjU2IiwKICAgICAgICAibmFtZSI6ICJza2lsbC1jYXJkLm1kIgogICAgICB9CiAgICBdLAogICAgInNlcmlhbGl6YXRpb24iOiB7CiAgICAgICJhbGxvd19zeW1saW5rcyI6IGZhbHNlLAogICAgICAiaGFzaF90eXBlIjogInNoYTI1NiIsCiAgICAgICJpZ25vcmVfcGF0aHMiOiBbCiAgICAgICAgIi5naXRhdHRyaWJ1dGVzIiwKICAgICAgICAiLmdpdGlnbm9yZSIsCiAgICAgICAgIi5naXRodWIiLAogICAgICAgICIuZ2l0IgogICAgICBdLAogICAgICAibWV0aG9kIjogImZpbGVzIgogICAgfQogIH0KfQ==","payloadType":"application/vnd.in-toto+json","signatures":[{"sig":"MGQCMCEcrwB06Q9QNlEVugiCtr7OlEFXBNW2Ck5GCOUHwUYnLsGbEbU4w+EvLx9aGdUy0QIwcpJhKTrjlkWxofdVE0ZytXDepPq5WzDBYJfLkNlDMfcINAEgJsj7YDP69fJSm6p6","keyid":""}]}}