Skip to content
Closed
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/docs/resources/starter-prompt.md text eol=lf
/docs/resources/prompt-assets/*.md text eol=lf
/docs/resources/local-credential-form.html text eol=lf
/tools/e2e/contracts/v1/jetson-dispatch.json text eol=lf

/skills/nemoclaw/** linguist-generated=true
/skills/nemoclaw/**/*.md diff=markdown
Expand Down
10 changes: 6 additions & 4 deletions test/e2e/docs/jetson-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ content, and a noncanonical archive.

The static vectors in
`tools/e2e/contracts/v1/jetson-dispatch.json` are the compatibility boundary
shared with the operator-owned service. They include one request, queued and
completed responses, one artifact, and rejected request examples. Change the
contract version, parser tests, client tests, and vectors together when an
incompatible wire change is required.
shared with the operator-owned service. Contract v1 is immutable at SHA-256
`d50e381860ec131e92f78c25272bfdcbacb790adc9552c3aaf0778427171314c`.
The receiver's CI and deployment gate compare its copy against NemoClaw
`main`. The vectors include one request, queued and completed responses, one
artifact, and rejected request examples. Publish a coordinated v2 contract
instead of editing v1 when an incompatible wire change is required.

## Trusted GitHub Dispatch

Expand Down
13 changes: 10 additions & 3 deletions test/e2e/support/jetson-dispatch-client.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { createHash } from "node:crypto";
import fs from "node:fs";
import path from "node:path";

Expand All @@ -14,6 +15,7 @@ import {
import {
JETSON_DISPATCH_AUDIENCE,
JETSON_DISPATCH_CONTRACT_VERSION,
JETSON_DISPATCH_V1_SHA256,
type JetsonDispatchArtifact,
type JetsonDispatchRequest,
type JetsonDispatchStatus,
Expand All @@ -32,9 +34,10 @@ interface CompatibilityVectors {
queuedResponse: unknown;
}

const vectors = JSON.parse(
fs.readFileSync(path.join(process.cwd(), "tools/e2e/contracts/v1/jetson-dispatch.json"), "utf8"),
) as CompatibilityVectors;
const vectorBytes = fs.readFileSync(
path.join(process.cwd(), "tools/e2e/contracts/v1/jetson-dispatch.json"),
);
const vectors = JSON.parse(vectorBytes.toString("utf8")) as CompatibilityVectors;
const request = parseJetsonDispatchRequest(vectors.request);
const queuedStatus = parseJetsonDispatchStatusResponse(vectors.queuedResponse);
const completedStatus = parseJetsonDispatchStatus(vectors.completedStatus);
Expand All @@ -49,6 +52,10 @@ afterEach(() => {
});

describe("Jetson dispatch static HTTP contract", () => {
it("keeps the published v1 bytes immutable (#8142)", () => {
expect(createHash("sha256").update(vectorBytes).digest("hex")).toBe(JETSON_DISPATCH_V1_SHA256);
});

it("accepts every version 1.0.0 compatibility vector (#8142)", () => {
expect(vectors.contractVersion).toBe(JETSON_DISPATCH_CONTRACT_VERSION);
expect(request).toEqual(vectors.request);
Expand Down
2 changes: 2 additions & 0 deletions tools/e2e/jetson-dispatch-contract.mts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import { createHash } from "node:crypto";

export const JETSON_DISPATCH_CONTRACT_VERSION = "1.0.0";
export const JETSON_DISPATCH_V1_SHA256 =
"d50e381860ec131e92f78c25272bfdcbacb790adc9552c3aaf0778427171314c";
export const JETSON_DISPATCH_AUDIENCE = "nemoclaw-jetson-dispatch";
export const JETSON_DISPATCH_TARGET = "jetson-nvmap-gpu";

Expand Down
Loading