Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .agents/skills/draft-release-notes/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
name: draft-release-notes
description: Compare NeMo Relay release branches and draft or update the documentation-site release notes. Use when preparing a release-notes update under docs/about-nemo-relay/release-notes, reviewing release-to-release changes, or gathering evidence for a current release summary.
---

# Draft Release Notes

Draft the three documentation-site release-notes pages from verified repository
evidence. Keep complete, PR-by-PR release history in GitHub Releases.

## Gather Evidence

Run the read-only helper with explicit release refs and the target minor version:

```bash
python3 .agents/skills/draft-release-notes/scripts/collect_release_evidence.py \
--previous release/<previous-major>.<previous-minor> \
--current HEAD \
--version <major>.<minor>
```

The report verifies both refs, compares their release-notes trees, identifies
version text currently present in those pages, and groups commits into review
candidates. Treat the groups as an evidence index, not publication-ready copy.

## Workflow

1. Confirm the target release version from the release branch and package
metadata. Preserve unrelated working-tree changes.
2. Run the helper. It reports an absent prior release-notes directory without
failing, which is expected for early release branches.
3. Verify each candidate claim in the changed public docs, API types, command
help, or source before including it. Prioritize breaking changes, migrations,
user-visible features, and ongoing support limitations.
4. Update only these pages unless the release changes their route or entry
points:
- `docs/about-nemo-relay/release-notes/index.mdx`
- `docs/about-nemo-relay/release-notes/highlights.mdx`
- `docs/about-nemo-relay/release-notes/known-issues.mdx`
5. Keep the existing page roles:
- `index.mdx` gives the current-release summary, compatibility notes, scope,
and curated feature links.
- `highlights.mdx` groups notable changes by user-facing theme.
- `known-issues.mdx` records current limitations, compatibility migrations,
current-release fixes, and the complete fixed-item history recorded in
earlier release-note pages. Preserve every prior fixed-item bullet under
release-labelled subsections; do not summarize, deduplicate, or omit it.
GitHub Releases remains the complete PR-by-PR history.
6. Preserve MDX front matter and the JSX SPDX comment. State the full history
is available in GitHub Releases; do not create a changelog or GitHub Release
body from this skill.

## Validate

Run the helper for the target release and for an early branch without release
notes when available. Review public claims, then run:

```bash
git diff --check
just docs
just docs-linkcheck
```

Check product names, commands, package names, support claims, and links against
the current repository before handing off the draft.
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Collect read-only Git evidence for NeMo Relay documentation release notes."""

from __future__ import annotations

import argparse
import re
import subprocess
from dataclasses import dataclass
from pathlib import Path

RELEASE_NOTES_DIR = "docs/about-nemo-relay/release-notes"
VERSION_PATTERN = re.compile(r"(?:NVIDIA )?NeMo Relay (\d+\.\d+(?:\.\d+)?)")


@dataclass(frozen=True)
class Commit:
"""One non-merge commit and its changed paths."""

sha: str
subject: str
paths: tuple[str, ...]


def run_git(repo: Path, *args: str) -> str:
"""Run Git without a shell and return stdout or raise a readable error."""
result = subprocess.run(
["git", *args],
cwd=repo,
check=False,
capture_output=True,
encoding="utf-8",
)
if result.returncode:
detail = result.stderr.strip() or result.stdout.strip()
raise RuntimeError(f"git {' '.join(args)} failed: {detail}")
return result.stdout


def resolve_ref(repo: Path, ref: str) -> str:
"""Return the commit ID for a user-supplied ref."""
return run_git(repo, "rev-parse", "--verify", "--quiet", f"{ref}^{{commit}}").strip()


def note_files(repo: Path, ref: str) -> tuple[str, ...]:
"""List release-note files that exist at a ref."""
output = run_git(repo, "ls-tree", "-r", "--name-only", ref, "--", RELEASE_NOTES_DIR)
return tuple(path for path in output.splitlines() if path)


def note_versions(repo: Path, ref: str, paths: tuple[str, ...]) -> tuple[str, ...]:
"""Return the NeMo Relay versions mentioned in release-note files."""
versions: set[str] = set()
for path in paths:
content = run_git(repo, "show", f"{ref}:{path}")
versions.update(VERSION_PATTERN.findall(content))
return tuple(sorted(versions))


def commits(repo: Path, previous: str, current: str) -> tuple[Commit, ...]:
"""Read non-merge commits and their changed paths, newest first."""
output = run_git(repo, "log", "--no-merges", "--format=%H%x09%s", f"{previous}..{current}")
collected: list[Commit] = []
for line in output.splitlines():
sha, subject = line.split("\t", maxsplit=1)
names = run_git(repo, "diff-tree", "--no-commit-id", "--name-status", "-r", sha)
paths = tuple(entry.rsplit("\t", maxsplit=1)[-1] for entry in names.splitlines() if entry)
collected.append(Commit(sha=sha, subject=subject, paths=paths))
return tuple(collected)


def category(commit: Commit) -> str:
"""Classify a commit for review without treating the result as a release claim."""
subject = commit.subject.lower()
if "!" in commit.subject.split(":", maxsplit=1)[0] or re.search(
r"\b(remove|drop|breaking|deprecat|migration)\b", subject
):
return "Breaking and migration candidates"
if subject.startswith("feat"):
return "Feature candidates"
if subject.startswith(("fix", "perf")):
return "Fix candidates"
return "Documentation and tooling candidates"


def public_paths(commits_to_report: tuple[Commit, ...]) -> tuple[str, ...]:
"""Return changed paths likely to support public release-note claims."""
package_paths = {
"Cargo.toml",
"crates/node/package.json",
"integrations/openclaw/package.json",
"python/plugin/pyproject.toml",
}
return tuple(
sorted(
{
path
for commit in commits_to_report
for path in commit.paths
if path == "README.md"
or path.startswith("docs/")
or path.endswith("/README.md")
or path in package_paths
}
)
)


def print_note_tree(repo: Path, label: str, ref: str) -> None:
"""Print structure and version mentions for one release ref."""
paths = note_files(repo, ref)
print(f"## {label} Release-Notes Tree")
if not paths:
print(f"No files exist under `{RELEASE_NOTES_DIR}` at `{ref}`.\n")
return
print("Files:")
for path in paths:
print(f"- `{path}`")
versions = note_versions(repo, ref, paths)
description = ", ".join(versions) if versions else "no NeMo Relay version text detected"
print(f"Version text: {description}\n")


def main() -> int:
"""Parse arguments and print the evidence report."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--previous", required=True, help="Previous release branch or commit")
parser.add_argument("--current", required=True, help="Current release branch or commit")
parser.add_argument("--version", required=True, help="Target major.minor release version")
parser.add_argument("--repo", default=".", help="Repository root (default: current directory)")
args = parser.parse_args()

repo = Path(args.repo).resolve()
try:
previous_sha = resolve_ref(repo, args.previous)
current_sha = resolve_ref(repo, args.current)
run_git(repo, "merge-base", "--is-ancestor", previous_sha, current_sha)
except RuntimeError as error:
parser.error(str(error))

print(f"# Release-Note Evidence: {args.version}")
print()
print(f"- Previous: `{args.previous}` ({previous_sha[:12]})")
print(f"- Current: `{args.current}` ({current_sha[:12]})")
print(f"- Merge base: `{run_git(repo, 'merge-base', previous_sha, current_sha).strip()[:12]}`")
print()
print_note_tree(repo, "Previous", args.previous)
print_note_tree(repo, "Current", args.current)

changes = commits(repo, previous_sha, current_sha)
grouped: dict[str, list[Commit]] = {
"Breaking and migration candidates": [],
"Feature candidates": [],
"Fix candidates": [],
"Documentation and tooling candidates": [],
}
for commit in changes:
grouped[category(commit)].append(commit)

print("## Commit Candidates")
for heading, entries in grouped.items():
print(f"### {heading}")
if not entries:
print("- None")
for commit in entries:
paths = ", ".join(f"`{path}`" for path in commit.paths[:4])
suffix = f" — {paths}" if paths else ""
print(f"- `{commit.sha[:12]}` {commit.subject}{suffix}")
print()

print("## Changed Public Documentation and Package Surfaces")
paths = public_paths(changes)
if paths:
for path in paths:
print(f"- `{path}`")
else:
print("- None")
print()
print("Review every candidate against current public docs and APIs before drafting prose.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
128 changes: 59 additions & 69 deletions docs/about-nemo-relay/release-notes/highlights.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,75 +9,65 @@ SPDX-License-Identifier: Apache-2.0 */}
This page summarizes the notable capabilities in the current release
documentation set.

## NVIDIA NeMo Relay 0.4

NVIDIA NeMo Relay 0.4 adds host plugin installation, first-party PII redaction, local
Guardrails execution, pricing-aware observability, streaming raw-event export,
and stronger coding-agent trace fidelity.

### Compatibility Notes

- The Python-only NeMo Guardrails example plugin was removed. Applications
should use the built-in `nemo_guardrails` component instead.
- Pricing estimates require an inline, file-backed, or embedding-provided
pricing source. NeMo Relay does not ship provider price data by default.
- Local NeMo Guardrails mode requires Python 3.11 or newer and
`nemoguardrails==0.22.0` in the runtime environment.

### CLI And Plugin Configuration

- Added `nemo-relay install`, `uninstall`, and `doctor --plugin` flows for
Claude Code and Codex host plugins.
- Added generated local marketplace support so Claude Code and Codex can load
NeMo Relay through native host plugin mechanisms.
- Layered code-driven plugin configuration over materialized global, project,
and user plugin files while preserving documented file precedence.
- Added pricing source management commands for validating catalogs, adding
file-backed sources, and resolving model pricing.

### Guardrails And Redaction

- Added a local Python-backed backend for the built-in `nemo_guardrails`
component.
- Expanded Guardrails configuration docs for local and remote backend behavior,
supported codecs, request defaults, tool boundaries, and streaming behavior.
- Added the first-party PII redaction plugin crate with deterministic local
backend support and Python and Node.js helper surfaces.

### Observability

- Added ATOF streaming endpoints for HTTP POST, WebSocket, and long-lived
NDJSON uploads.
- Added ATIF HTTP storage export alongside S3-compatible storage destinations.
- Added model-pricing lookup and cost layering for managed LLM responses.
- Propagated normalized LLM cost into ATIF step metrics, OpenInference
attributes, and OpenTelemetry attributes.
- Set OpenTelemetry span status from NeMo Relay execution results.
- Preserved sanitized LLM request payloads in annotations and start-event
output.

### Integrations

- Improved Hermes hook injection, routed-provider observability, wrapped ATIF
fidelity, subagent lineage, and error-path export consistency.
- Added Codex observability contract coverage and suppressed noisy Claude Code
lifecycle events.
- Added nested subagent session lineage and more consistent cost, provenance,
replay, placeholder, and hook-only fallback exports for OpenClaw.
- Improved LangChain input serialization and fixed plugin context-manager
deadlock behavior.
- Added flattened OpenInference LLM attributes for annotations and replay.
- Annotated Deep Agents model responses and refreshed LangGraph callback
coverage.

### Documentation And Tooling

- Updated installation documentation for 0.4 packages and host plugin setup.
- Clarified Hermes integration paths and coding-agent plugin source manifests.
- Added NVSkills CI request workflow and regenerated NeMo Relay skill eval
datasets.
- Updated dependency attribution files and isolated Rust test behavior for CI
and SonarQube cleanup.
## NVIDIA NeMo Relay 0.5

NVIDIA NeMo Relay 0.5 adds dynamic plugin SDKs and controls, verified CLI
installation and diagnostics, clearer runtime contracts, and improved lineage
for managed LLM requests.

### Compatibility and Migration

- Move plugin configuration from `config.toml` into `plugins.toml`. The
`--plugin-config` CLI option and hook-forwarding input have been removed.
- Update every registered LLM request and tool execution intercept to return
its canonical outcome. The outcomes can include ordered pending marks while
Relay retains lifecycle ownership.
- Rebuild development native plugins and `grpc-v1` workers against 0.5 because
the native ABI and worker outcome contracts are now finalized.
- Migrate away from the removed experimental `nemo-relay-wasm` package, Cursor
CLI support, and patch-based integrations.

### Dynamic Plugins and Configuration

- Added dynamic plugin discovery from `plugins.toml`, host policy and
attestation gates, and lifecycle commands for inspecting, validating,
enabling, and disabling plugins.
- Added the Rust SDK for trusted in-process `rust_dynamic` plugins and the
`grpc-v1` worker protocol with Rust and Python worker SDKs.
- Added schema-aware dynamic-plugin configuration, validation, secret-aware
editing, and merged TOML preview in the CLI.
- Added Python worker-environment management and worker invocation
cancellation.

### CLI Installation and Diagnostics

- Added verified Unix and Windows installers that select the release asset,
verify its SHA-256 checksum, and support version pinning.
- Expanded `nemo-relay doctor` with agent-host readiness checks, persistent
host-plugin diagnostics, and discovered `plugins.toml` source and validation
reporting.
- Added gateway status reporting for bind, exporter, and remote ATIF storage
destinations.

### Runtime and Observability

- Added canonical LLM request and tool execution outcomes across Rust, Python,
Node.js, Go, C FFI, native plugins, and worker plugins.
- Added ordered pending marks to managed LLM and tool lifecycles without adding
control data to application-visible requests or tool results.
- Added automatic Dynamo session and parent-session headers to managed LLM
requests, plus bounded CLI turn scopes for trace correlation.
- Documented stable normalized token and cost semantics, including provider
mapping and exporter projection behavior.
- Hardened ATOF HTTP output and ensured gateway shutdown flushes queued events.

### Documentation and Tooling

- Added public contract references for LLM request and tool execution intercept
outcomes.
- Expanded dynamic plugin, configuration, runtime-contract, installation, and
integration examples.
- Updated package, build, test, and release guidance for the primary Rust, Python, and Node.js surfaces, plus experimental Go and raw C FFI notes.

The complete changelog and release artifacts can be viewed on
[GitHub Releases](https://github.com/NVIDIA/NeMo-Relay/releases).
Loading
Loading