Skip to content

fix(e2e): remove scenario advisor yaml dependency#4081

Merged
cv merged 1 commit into
mainfrom
fix/e2e-scenario-advisor-no-js-yaml
May 22, 2026
Merged

fix(e2e): remove scenario advisor yaml dependency#4081
cv merged 1 commit into
mainfrom
fix/e2e-scenario-advisor-no-js-yaml

Conversation

@jyaunches
Copy link
Copy Markdown
Contributor

@jyaunches jyaunches commented May 22, 2026

Summary

  • remove the scenario advisor runtime dependency on js-yaml
  • parse the small scenario/suite metadata subset directly from checked-in YAML text
  • keep existing scenario advisor recommendations and tests intact

Root cause

The E2E advisor job only installs the Pi SDK under the trusted advisor checkout, not the repo's npm dependencies. scenarios.mts required js-yaml, so the deterministic scenario advisor step failed before writing its summary artifact; the scenario comment step then skipped because the summary was missing.

Test plan

  • npm test -- --run test/e2e-scenario-advisor.test.ts
  • npx tsc --noEmit --allowImportingTsExtensions --moduleResolution bundler --module esnext --target es2022 --skipLibCheck --types node tools/e2e-advisor/scenarios.mts test/e2e-scenario-advisor.test.ts
  • node --experimental-strip-types tools/e2e-advisor/scenarios.mts --base HEAD~1 --head HEAD --out-dir /tmp/e2e-scenario-advisor-no-yaml-test

Summary by CodeRabbit

  • Refactor
    • Updated internal test tooling to improve configuration file processing.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

📝 Walkthrough

Walkthrough

This PR replaces the js-yaml library dependency in the e2e-advisor with custom line-based YAML parsing. The script now reads YAML files as raw text and extracts top-level sections and scenario/suite entries using regex-driven line scanning, eliminating the dependency on external YAML parsing.

Changes

YAML Parsing Migration

Layer / File(s) Summary
Replace js-yaml with custom line-based YAML parsing
tools/e2e-advisor/scenarios.mts
Remove createRequire/js-yaml imports and intermediate typed shapes. Rewrite loadScenarios and loadSuiteScriptMap to read YAML files as raw text and implement helper functions (parseScenarioSection, parseSuiteScripts, extractTopLevelSection) that perform line-based parsing to extract sections, scenario entries, and suite scripts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#4004: Prior changes to tools/e2e-advisor/scenarios.mts that modified scenario-advisor logic for reading and parsing scenario/suite metadata.

Suggested labels

fix, E2E

Suggested reviewers

  • cv

Poem

🐰 No yaml lib needed, just lines and regex cheer,
Parsing sections clean, the logic crystal clear,
Custom helpers dance through scenarios with grace,
Dependencies gone—simplicity wins the race! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(e2e): remove scenario advisor yaml dependency' directly and clearly describes the main change: removing the js-yaml dependency from the scenario advisor tool.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/e2e-scenario-advisor-no-js-yaml

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: None

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • None. No product/runtime E2E is recommended. The PR only changes E2E advisor tooling and cannot directly affect NemoClaw user flows. Product scenario E2E jobs would not validate the parser change; existing non-E2E advisor/unit coverage such as test/e2e-scenario-advisor.test.ts is the appropriate validation target.

Optional E2E

  • None.

New E2E recommendations

  • None.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tools/e2e-advisor/scenarios.mts (1)

300-346: ⚡ Quick win

Validate regex indentation expectations against scenarios.yaml

parseScenarioSection’s indentation-specific regexes line up with the actual YAML in test/e2e/nemoclaw_scenarios/scenarios.yaml:

  • No tabs found (parser’s “spaces-only” assumption holds for this file)
  • Scenario headings match the expected ^ <id>:$ shape
  • suites: matches ^ suites: and list items match ^ - <item>
  • No YAML anchors/aliases detected on suites/runner_requirements fields

The parser will still fail silently if future YAML deviates from this exact formatting (spacing/tabs/other YAML constructs), so adding validation/error reporting (or using a real YAML parser) would make it more robust.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/e2e-advisor/scenarios.mts` around lines 300 - 346, parseScenarioSection
assumes strict space-based indentation and exact line formats, which will
silently mis-parse if scenarios.yaml deviates; update parseScenarioSection to
validate and surface errors (or switch to a YAML parser): either (1) replace the
hand-rolled line/regex logic in parseScenarioSection with a proper YAML parse of
the extracted section (using a YAML library) to populate
scenarios[currentId].suites and .runner_requirements, or (2) add explicit
validation checks after parsing (e.g., detect unexpected indentation, missing
currentId before list items, or unrecognized lines) and throw/report a clear
error referencing the section name and currentId so formatting issues are
visible; reference the parseScenarioSection function and the
scenarios/currentId/suites/runner_requirements symbols when making changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/e2e-advisor/scenarios.mts`:
- Around line 348-366: parseSuiteScripts currently uses regexes to parse the
"suites" section line-by-line so YAML aliases like "steps: *id" are ignored
(causing 6 suites to appear empty); update parseSuiteScripts to use a proper
YAML parser that resolves aliases (or at minimum detect a
"steps:\s*\*[A-Za-z0-9_-]+" pattern and follow the alias lookup) so script lists
are populated. Specifically, replace the indentation/regex parsing in
parseSuiteScripts (and its dependency extractTopLevelSection if needed) with a
YAML parse of the suites block (e.g., parse into objects and read suiteId ->
steps/script arrays) or add logic to resolve alias references from the same YAML
content before returning suites.

---

Nitpick comments:
In `@tools/e2e-advisor/scenarios.mts`:
- Around line 300-346: parseScenarioSection assumes strict space-based
indentation and exact line formats, which will silently mis-parse if
scenarios.yaml deviates; update parseScenarioSection to validate and surface
errors (or switch to a YAML parser): either (1) replace the hand-rolled
line/regex logic in parseScenarioSection with a proper YAML parse of the
extracted section (using a YAML library) to populate scenarios[currentId].suites
and .runner_requirements, or (2) add explicit validation checks after parsing
(e.g., detect unexpected indentation, missing currentId before list items, or
unrecognized lines) and throw/report a clear error referencing the section name
and currentId so formatting issues are visible; reference the
parseScenarioSection function and the
scenarios/currentId/suites/runner_requirements symbols when making changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7d5a699c-d3f9-4dd4-9aa8-65aba3370e37

📥 Commits

Reviewing files that changed from the base of the PR and between cf588ed and 0ada910.

📒 Files selected for processing (1)
  • tools/e2e-advisor/scenarios.mts

Comment on lines +348 to +366
function parseSuiteScripts(text: string): Record<string, string[]> {
const section = extractTopLevelSection(text, "suites");
const suites: Record<string, string[]> = {};
let currentId: string | undefined;

for (const line of section.split(/\r?\n/)) {
const suiteMatch = line.match(/^ ([A-Za-z0-9_.-]+):\s*$/);
if (suiteMatch) {
currentId = suiteMatch[1];
suites[currentId] = [];
continue;
}
if (!currentId) continue;
const scriptMatch = line.match(/^ script:\s*([A-Za-z0-9_./-]+)\s*$/);
if (scriptMatch) suites[currentId].push(scriptMatch[1]);
}

return suites;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify custom parser correctly extracts suite scripts

SUITES_FILE="test/e2e/validation_suites/suites.yaml"

if [ ! -f "$SUITES_FILE" ]; then
  echo "ERROR: $SUITES_FILE not found"
  exit 1
fi

echo "=== Checking for tabs ==="
if grep -P '^\t' "$SUITES_FILE"; then
  echo "ERROR: Found tabs. Parser expects spaces only."
  exit 1
fi
echo "✓ No tabs found"

echo ""
echo "=== Sample suite entries (should match pattern: 2 spaces + name + colon) ==="
grep -P '^  [A-Za-z0-9_.-]+:\s*$' "$SUITES_FILE" | head -5

echo ""
echo "=== Sample script entries (should match pattern: 6 spaces + 'script:' + path) ==="
grep -P '^      script:\s*[A-Za-z0-9_./-]+\s*$' "$SUITES_FILE" | head -10

echo ""
echo "=== Checking for YAML anchors on steps (parser won't follow aliases) ==="
if grep -P '^    steps:.*[&*]' "$SUITES_FILE"; then
  echo "WARNING: Found anchors/aliases on steps. Parser won't follow alias references."
fi

echo ""
echo "=== Count of suite definitions vs script extractions ==="
SUITE_COUNT=$(grep -cP '^  [A-Za-z0-9_.-]+:\s*$' "$SUITES_FILE")
SCRIPT_COUNT=$(grep -cP '^      script:\s*[A-Za-z0-9_./-]+\s*$' "$SUITES_FILE")
echo "Suites: $SUITE_COUNT"
echo "Scripts: $SCRIPT_COUNT"
echo "✓ Verification complete"

Repository: NVIDIA/NemoClaw

Length of output: 1293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

SUITES_FILE="test/e2e/validation_suites/suites.yaml"

python3 - <<'PY'
import re, sys, collections
path="test/e2e/validation_suites/suites.yaml"
text=open(path,"r",encoding="utf-8").read()

# Extract top-level 'suites:' section (best-effort)
m=re.search(r'(?ms)^suites:\s*\n(.*)$', text)
if not m:
    print("Could not find 'suites:' top-level key")
    sys.exit(1)
section=m.group(1)

suite_re=re.compile(r'^  ([A-Za-z0-9_.-]+):\s*$')
script_re=re.compile(r'^      script:\s*([A-Za-z0-9_./-]+)\s*$')
steps_alias_re=re.compile(r'^    steps:\s*\*')

suites_scripts=collections.defaultdict(list)
suites_has_steps_alias=set()
current=None

for line in section.splitlines():
    sm=suite_re.match(line)
    if sm:
        current=sm.group(1)
        continue
    if current is None:
        continue
    if steps_alias_re.match(line):
        suites_has_steps_alias.add(current)
    sm2=script_re.match(line)
    if sm2:
        suites_scripts[current].append(sm2.group(1))

# Summarize
all_suites=sorted(set(suite_re.findall(section)))
zero=[s for s in all_suites if len(suites_scripts.get(s,[]))==0]
alias_only=[s for s in sorted(suites_has_steps_alias) if len(suites_scripts.get(s,[]))==0]

print("Total suites in section:", len(all_suites))
print("Suites with 0 extracted scripts:", len(zero))
if zero:
    print("First 15 zero-script suites:", zero[:15])

print("Suites that use steps aliases and have 0 extracted scripts:", len(alias_only))
if alias_only:
    print("First 15 alias-only suites:", alias_only[:15])

# Show a few non-zero samples for sanity
nonzero=[s for s in all_suites if len(suites_scripts.get(s,[]))>0]
print("Sample non-zero suites (up to 10):")
for s in nonzero[:10]:
    scripts=suites_scripts[s]
    print(f"- {s}: {len(scripts)} scripts; first: {scripts[0]}")
PY

Repository: NVIDIA/NemoClaw

Length of output: 366


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="test/e2e/validation_suites/suites.yaml"

# Show the suite blocks for a few suites that were "alias-only" (0 extracted scripts by the indentation parser)
for suite in cloud-inference diagnostics docs-validation gateway-health openai-compatible-inference sandbox-shell; do
  echo "================ ${suite} ================"
  # Print from the suite key line until the next top-level suite key (2 spaces + name + colon)
  awk -v s="$suite" '
    $0 ~ "^  " s ":\\s*$" {inblock=1}
    inblock {print}
    inblock && $0 ~ "^  [A-Za-z0-9_.-]+:\\s*$" && $0 !~ "^  " s ":\\s*$" {inblock=0}
  ' "$FILE" | head -n 120
done

# Also confirm what "script:" lines exist (and their indentation) within these suites
echo "================ script lines (with leading whitespace counts) ================"
python3 - <<'PY'
import re
file="test/e2e/validation_suites/suites.yaml"
suites=["cloud-inference","diagnostics","docs-validation","gateway-health","openai-compatible-inference","sandbox-shell"]
lines=open(file,'r',encoding='utf-8').read().splitlines()
suite_re=re.compile(r'^  ([A-Za-z0-9_.-]+):\s*$')
script_re=re.compile(r'^(\s*)script:\s*(.+?)\s*$')

current=None
wanted=set(suites)
out={s:[] for s in suites}
for line in lines:
    m=suite_re.match(line)
    if m:
        current=m.group(1)
    if current in wanted:
        sm=script_re.match(line)
        if sm:
            indent=len(sm.group(1).replace('\t','    '))
            out[current].append((indent, sm.group(2)))
for s in suites:
    print(s, "script lines:", len(out[s]))
    if out[s]:
        print("  indent samples:", out[s][:5])
PY

Repository: NVIDIA/NemoClaw

Length of output: 1157


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="tools/e2e-advisor/scenarios.mts"

# 1) Locate parseSuiteScripts + extractTopLevelSection implementation
rg -n "function parseSuiteScripts|extractTopLevelSection" "$FILE"
# Show surrounding code (avoid huge output by limiting lines around matches)
python3 - <<'PY'
import subprocess, re
file="tools/e2e-advisor/scenarios.mts"
# get line numbers for parseSuiteScripts and extractTopLevelSection
text=open(file,'r',encoding='utf-8').read().splitlines()
targets=[]
for i,l in enumerate(text,1):
    if "function parseSuiteScripts" in l or "extractTopLevelSection" in l:
        targets.append(i)
for t in sorted(set(targets)):
    start=max(1,t-20); end=min(len(text),t+60)
    print("\n### Snippet around line",t,"###\n")
    for j in range(start,end+1):
        print(f"{j}:{text[j-1]}")
PY

# 2) Re-run the parser logic in Python using the same regex expectations:
#    - take the "suites" top-level section the way extractTopLevelSection likely does (between "suites:" and next top-level key)
python3 - <<'PY'
import re, sys, collections

text=open("test/e2e/validation_suites/suites.yaml","r",encoding="utf-8").read()

# Best-effort mimic: extract from "^suites:" to next "^\\S" (top-level key)
m=re.search(r'(?ms)^suites:\s*\n(.*?)(?:\n^[^ \t].*?:\s*$|\Z)', text)
if not m:
    # fallback: from suites: to EOF
    m=re.search(r'(?ms)^suites:\s*\n(.*)$', text)
    if not m:
        print("Could not locate suites: section")
        sys.exit(1)

section=m.group(1)

suite_re=re.compile(r'^  ([A-Za-z0-9_.-]+):\s*$')
script_re=re.compile(r'^      script:\s*([A-Za-z0-9_./-]+)\s*$')

suites=collections.defaultdict(list)
current=None
for line in section.splitlines():
    sm=suite_re.match(line)
    if sm:
        current=sm.group(1)
        suites[current]=[]
        continue
    if not current:
        continue
    sm2=script_re.match(line)
    if sm2:
        suites[current].append(sm2.group(1))

all_suites=sorted(suites.keys())
zero=[s for s in all_suites if len(suites[s])==0]

print("Parsed suites:", len(all_suites))
print("Suites with 0 extracted scripts (would fail to map scripts for alias-based suites):", len(zero))
print("First 30 zero-script suites:", zero[:30])

# Count how many script lines exist in file under exact indentation (for sanity)
file_script_re=re.compile(r'^      script:\s*[A-Za-z0-9_./-]+\s*$', re.M)
print("Total inline 'script:' lines matching exact indentation:", len(file_script_re.findall(text)))
PY

Repository: NVIDIA/NemoClaw

Length of output: 12268


Fix parseSuiteScripts to handle YAML aliases (it currently misses 6 suites)

  • In tools/e2e-advisor/scenarios.mts:348-366, the regexes correctly match inline suite/script entries in test/e2e/validation_suites/suites.yaml ( <suite>: and script:).
  • However, 6 suites define steps: *id... without any inline script: keys (cloud-inference, diagnostics, docs-validation, gateway-health, openai-compatible-inference, sandbox-shell), so parseSuiteScripts returns an empty list for them.
  • Downstream mapping that relies on this will treat those suites as having no scripts—use a YAML parser that resolves aliases (instead of indentation-based regex parsing) or explicitly handle/skip alias-based suites.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/e2e-advisor/scenarios.mts` around lines 348 - 366, parseSuiteScripts
currently uses regexes to parse the "suites" section line-by-line so YAML
aliases like "steps: *id" are ignored (causing 6 suites to appear empty); update
parseSuiteScripts to use a proper YAML parser that resolves aliases (or at
minimum detect a "steps:\s*\*[A-Za-z0-9_-]+" pattern and follow the alias
lookup) so script lists are populated. Specifically, replace the
indentation/regex parsing in parseSuiteScripts (and its dependency
extractTopLevelSection if needed) with a YAML parse of the suites block (e.g.,
parse into objects and read suiteId -> steps/script arrays) or add logic to
resolve alias references from the same YAML content before returning suites.

@github-actions
Copy link
Copy Markdown
Contributor

PR Review Advisor

Recommendation: blocked
Confidence: medium
Analyzed HEAD: 0ada91092e9f6c5baf2cfd28724624b351a13884
Findings: 1 blocker(s), 1 warning(s), 0 suggestion(s)

This is an automated advisory review. A human maintainer must make the final merge decision.

Limitations: Review used read-only inspection and trusted collected metadata; no scripts, tests, npm commands, or package-manager commands were executed by this advisor.; GitHub review-thread state was not fully available; CodeRabbit was observed pending/in-progress in collected metadata.; No linked issues were present in the trusted context, so acceptance mapping is based on PR body/comment clauses rather than linked issue clauses.; The provided diff was truncated after the changed parser area, so final judgment also used repository file reads for tools/e2e-advisor/scenarios.mts.

Workflow run

Full advisor summary

PR Review Advisor

Base: origin/main
Head: HEAD
Analyzed SHA: 0ada91092e9f6c5baf2cfd28724624b351a13884
Recommendation: blocked
Confidence: medium

The code change is narrowly scoped and appears to remove the js-yaml runtime dependency as intended, but the PR is not merge-ready while GitHub reports mergeStateStatus=BLOCKED and review-thread state is unavailable.

Gate status

  • CI: pass — 5 required status context(s) completed with no failures for head SHA 0ada910: checks, commit-lint, dco-check, check-hash, changes. Additional non-required contexts were still pending per trusted context; E2E recommendation completed successfully.
  • Mergeability: fail — GitHub GraphQL reported mergeStateStatus=BLOCKED and reviewDecision=REVIEW_REQUIRED for head SHA 0ada910.
  • Review threads: unknown — No review thread state was available from the trusted gate context; GraphQL returned an empty reviewThreads node list, but CodeRabbit status was still pending/in-progress in the collected metadata.
  • Risky code tested: pass — Trusted path heuristics detected no high-risk product/runtime/security areas. The changed file is E2E advisor tooling only: tools/e2e-advisor/scenarios.mts.

🔴 Blockers

  • PR is blocked by repository merge gates: GitHub reports the PR is blocked even though required status checks passed. The collected metadata shows mergeStateStatus=BLOCKED and reviewDecision=REVIEW_REQUIRED, with review-thread state not fully available to this advisory review.
    • Recommendation: Do not treat the PR as merge-ready until repository merge gates are satisfied and any pending review/automation state is resolved by maintainers.
    • Evidence: Trusted context: mergeability.status=fail with evidence mergeStateStatus=BLOCKED; GraphQL reviewDecision=REVIEW_REQUIRED for head SHA 0ada910.

🟡 Warnings

  • Parser replacement has limited direct edge-case coverage in the diff (tools/e2e-advisor/scenarios.mts:300): The PR replaces js-yaml with a hand-rolled parser for scenario and suite metadata. Existing advisor tests exercise representative repository fixtures, and CI passed, but the diff does not add focused negative/edge tests for the supported YAML subset such as quoted script paths, comments, blank sections, alternate indentation, empty suites, and runner_requirements parsing.
    • Recommendation: Consider adding focused unit tests that lock the intentionally supported YAML subset and failure behavior, especially because this advisor controls E2E recommendations and missed parsing can lead to missed scenario coverage.
    • Evidence: tools/e2e-advisor/scenarios.mts now implements parseScenarioSection, parseSuiteScripts, and extractTopLevelSection directly; changedFiles contains only tools/e2e-advisor/scenarios.mts, with no changed test file.

🔵 Suggestions

  • None.

Acceptance coverage

  • met — remove the scenario advisor runtime dependency on js-yaml: The diff removes createRequire and require("js-yaml"); scenarios.mts now imports only node:fs, node:path, node:url, and local advisor modules.
  • met — parse the small scenario/suite metadata subset directly from checked-in YAML text: loadScenarios now reads scenarios.yaml text and calls parseScenarioSection for test_plans and setup_scenarios; loadSuiteScriptMap now calls parseSuiteScripts on suites.yaml text.
  • partial — keep existing scenario advisor recommendations and tests intact: The changed file preserves analyzeScenarioRecommendations and renderScenarioSummary public exports, and CI checks plus unit-vitest-linux succeeded. However, no test file was changed in this PR, so direct new coverage for the parser replacement is limited to existing tests.
  • met — The E2E advisor job only installs the Pi SDK under the trusted advisor checkout, not the repo's npm dependencies.: The implementation no longer depends on repo npm dependency resolution for js-yaml at runtime in tools/e2e-advisor/scenarios.mts.
  • metscenarios.mts required js-yaml, so the deterministic scenario advisor step failed before writing its summary artifact; the scenario comment step then skipped because the summary was missing.: Removing the js-yaml require path addresses the described failure mode; the trusted GitHub Actions comment shows the E2E Advisor Recommendation was posted successfully for this head SHA.
  • unknown — npm test -- --run test/e2e-scenario-advisor.test.ts: This is stated in the PR body test plan, which is untrusted evidence. Trusted CI shows unit-vitest-linux and checks succeeded, but this advisory review did not execute commands.
  • unknown — npx tsc --noEmit --allowImportingTsExtensions --moduleResolution bundler --module esnext --target es2022 --skipLibCheck --types node tools/e2e-advisor/scenarios.mts test/e2e-scenario-advisor.test.ts: This is stated in the PR body test plan, which is untrusted evidence. Trusted CI checks succeeded, but this advisory review did not execute commands or verify the exact command.
  • unknown — node --experimental-strip-types tools/e2e-advisor/scenarios.mts --base HEAD~1 --head HEAD --out-dir /tmp/e2e-scenario-advisor-no-yaml-test: This is stated in the PR body test plan, which is untrusted evidence. Trusted GitHub Actions did run E2E recommendation successfully and posted an advisor comment, but this advisory review did not execute the exact command.
  • met — Required E2E: None: The trusted E2E Advisor comment for this PR says Required E2E: _None_ and the E2E recommendation check completed successfully.
  • met — Optional E2E: None: The trusted E2E Advisor comment for this PR says Optional E2E: _None_.

Security review

  • pass — 1. Secrets and Credentials: No hardcoded secrets, tokens, passwords, PEM material, or credential JSON were introduced. The change reads checked-in scenario/suite metadata only.
  • pass — 2. Input Validation and Data Sanitization: The new parser uses restrictive regex allowlists for scenario IDs, suite IDs, runner requirements, and suite script paths, and does not use eval, unsafe deserialization, command execution, or network access. Dispatch command values continue to be shell-quoted.
  • pass — 3. Authentication and Authorization: Not applicable — the changed E2E advisor tooling does not add or modify authenticated endpoints, authorization decisions, token validation, or user/resource access controls.
  • pass — 4. Dependencies and Third-Party Libraries: The change removes the runtime dependency on js-yaml from this script path and adds no new third-party dependency or registry source.
  • pass — 5. Error Handling and Logging: The CLI error boundary remains unchanged and prints caught error messages only. The changed parser does not log secrets or sensitive metadata.
  • pass — 6. Cryptography and Data Protection: Not applicable — no cryptographic operations, key handling, hashing for security, or data protection mechanisms are changed.
  • pass — 7. Configuration and Security Headers: Not applicable — no HTTP endpoints, CORS/CSP policy, Dockerfile, container user, port exposure, or security configuration defaults are changed.
  • warning — 8. Security Testing: Existing CI and advisor tests passed, and the E2E Advisor reported no product E2E required. However, the diff introduces a hand-rolled YAML subset parser without adding focused parser edge-case tests, so missed parsing of security-sensitive scenario metadata could reduce future E2E recommendation quality.
  • pass — 9. Holistic Security Posture: The change reduces runtime dependency/supply-chain exposure for trusted advisor execution and does not touch sandbox isolation, SSRF controls, network policy, credentials, installer trust, Dockerfiles, or workflow trusted-code boundaries. The main residual risk is correctness/coverage of the intentionally narrow parser.

Test / E2E status

  • Test depth: e2e_required — Trusted path analysis marked tools/e2e-advisor/scenarios.mts as runtime/sandbox/infrastructure-adjacent advisor tooling requiring confirmation that the E2E Advisor required jobs passed for the current PR head SHA. The actual E2E Advisor recommendation for this PR found no product scenario E2E required because only advisor tooling changed.
  • E2E Advisor: ok

✅ What looks good

  • Codebase drift check: tools/e2e-advisor/scenarios.mts still exists and was recently touched by active E2E advisor work (ci(e2e): add scenario advisor comment #4004), with no open PR overlap reported by trusted context.
  • The change is narrowly scoped to one advisor tooling file and removes a runtime dependency from a trusted GitHub Actions advisor path.
  • Required status checks passed for the collected head SHA, and CodeQL/ShellCheck related checks also completed successfully in the status rollup.
  • The E2E Advisor comment was successfully posted for this PR, which is consistent with the dependency-removal goal.

Review completeness

  • Review used read-only inspection and trusted collected metadata; no scripts, tests, npm commands, or package-manager commands were executed by this advisor.
  • GitHub review-thread state was not fully available; CodeRabbit was observed pending/in-progress in collected metadata.
  • No linked issues were present in the trusted context, so acceptance mapping is based on PR body/comment clauses rather than linked issue clauses.
  • The provided diff was truncated after the changed parser area, so final judgment also used repository file reads for tools/e2e-advisor/scenarios.mts.
  • Human maintainer review required: yes

@cv cv merged commit 7f1b91a into main May 22, 2026
28 checks passed
jyaunches added a commit that referenced this pull request May 27, 2026
…ite from source-shape scanner

Two batched fixes for CI on the scenario-suite isolation PR:

- Update test/e2e-scenario-advisor.test.ts to expect the registry scenario id
  ubuntu-repo-cloud-openclaw-telegram. The advisor switched to listScenarios()
  in #4081 so the legacy YAML id ubuntu-repo-docker__cloud-nvidia-openclaw-telegram
  is no longer produced.
- Treat the isolated test/e2e-scenario/ tree as test fixtures in
  scripts/find-source-shape-tests.ts. The migration-inventory-lock test reads
  scenario manifests, expected-states, and validation_suites YAML; those are
  declarative test assets, not product source. Exempting test/e2e-scenario/
  brings source_shape_cases back to 0 without losing scanner coverage of
  product source under src/, agents/, nemoclaw/, etc.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants