Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
b0e93f2
refactor(dcode): replace Nemotron source patch with profile plugin
ericksoa Jul 8, 2026
cb57c5d
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
c999f82
test(dcode): harden profile validation boundaries
ericksoa Jul 8, 2026
e338b57
test(dcode): keep profile fixtures branchless
ericksoa Jul 8, 2026
59850e3
fix(dcode): verify profile plugin installation
ericksoa Jul 8, 2026
1563670
test(dcode): cover profile adapter edge cases
ericksoa Jul 8, 2026
9a48778
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
c9ab37e
test(dcode): reject incomplete profile dependencies
ericksoa Jul 8, 2026
c425fb4
test(dcode): harden profile import gate
ericksoa Jul 8, 2026
44fbc75
test(dcode): keep wheel fixture branchless
ericksoa Jul 8, 2026
4ad79de
test(dcode): support runner wheel tooling
ericksoa Jul 8, 2026
5ae2267
test(dcode): resolve profile review feedback
ericksoa Jul 8, 2026
3521591
test(dcode): resolve final advisor feedback
ericksoa Jul 8, 2026
4791ec5
test(dcode): clarify entry point failures
ericksoa Jul 8, 2026
08c5652
test(dcode): close import gate review gaps
ericksoa Jul 8, 2026
499fe9d
test(dcode): close final advisor gaps
ericksoa Jul 8, 2026
74750c5
test(dcode): keep profile fixture branchless
ericksoa Jul 8, 2026
3213b57
Merge origin/main into fix/dcode-nemotron-ultra-profile-plugin
ericksoa Jul 8, 2026
4c6b763
test(dcode): stay within image test budget
ericksoa Jul 8, 2026
4205201
test(dcode): split image contracts by boundary
ericksoa Jul 8, 2026
afa632f
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
5ed0ab6
test(dcode): harden split test fixtures
ericksoa Jul 8, 2026
d396018
test(dcode): preserve conditional budget
ericksoa Jul 8, 2026
424b312
test(dcode): share fixture drift guards
ericksoa Jul 8, 2026
a38fef6
fix(dcode): close advisor security findings
ericksoa Jul 8, 2026
0a54909
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
3a15d47
fix(dcode): align credential pattern parity
ericksoa Jul 8, 2026
cd20fc4
test(dcode): reject import gate marker drift
ericksoa Jul 8, 2026
6ac06c8
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
f15a7f3
docs(dcode): state import gate ARG boundary
ericksoa Jul 8, 2026
4a91b54
docs(dcode): clarify profile build boundaries
ericksoa Jul 8, 2026
ce2bd1c
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
1f31139
fix(security): complete pass redaction parity
ericksoa Jul 8, 2026
1f84f4e
test(dcode): keep gate fixture setup linear
ericksoa Jul 8, 2026
af424e7
fix(security): close password pattern bypasses
ericksoa Jul 8, 2026
90e1635
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
c7f08a1
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
bb2b138
test(security): cover password secret fingerprint
cv Jul 8, 2026
4da1018
fix(security): redact space-separated passwords
cv Jul 8, 2026
e587097
fix(security): align credential redaction boundaries
ericksoa Jul 8, 2026
e78d3ef
Merge remote-tracking branch 'origin/fix/dcode-nemotron-ultra-profile…
ericksoa Jul 8, 2026
0d835a9
fix(dcode): configure Ultra coding-agent requests
ericksoa Jul 8, 2026
06598f1
fix(dcode): reject Ultra execute placeholders
ericksoa Jul 8, 2026
29b003d
fix(dcode): address Ultra compatibility review
ericksoa Jul 8, 2026
3f92362
test(dcode): trigger profile bootstrap in E2E
ericksoa Jul 8, 2026
7682d0e
test(dcode): trigger profile bootstrap in E2E
ericksoa Jul 8, 2026
a9608a9
fix(security): preserve managed redaction references
ericksoa Jul 8, 2026
c1fe500
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
58ed2e2
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
7c7efc6
Merge branch 'fix/dcode-nemotron-ultra-profile-plugin' into fix/dcode…
ericksoa Jul 8, 2026
7baa42d
test(dcode): align redaction boundary probe
cjagwani Jul 8, 2026
1a69ee5
fix(dcode): close profile and redaction review gaps
ericksoa Jul 8, 2026
1b51e6a
Merge remote-tracking branch 'origin/fix/dcode-nemotron-ultra-profile…
ericksoa Jul 8, 2026
30917bf
test(dcode): deduplicate redaction probe boundary
ericksoa Jul 8, 2026
9114501
Merge branch 'fix/dcode-nemotron-ultra-profile-plugin' into fix/dcode…
cjagwani Jul 8, 2026
5b1a89d
fix(dcode): close profile security review
ericksoa Jul 8, 2026
0381d81
fix(security): fail closed on reply token values
ericksoa Jul 8, 2026
6980298
Merge remote-tracking branch 'origin/fix/dcode-nemotron-ultra-profile…
ericksoa Jul 8, 2026
e46b3da
test(dcode): deduplicate reply token vectors
cjagwani Jul 8, 2026
ed4fada
test(e2e): preserve reply correlation markers
ericksoa Jul 8, 2026
63d9907
Merge remote-tracking branch 'origin/fix/dcode-nemotron-ultra-profile…
ericksoa Jul 8, 2026
39bfc83
test(e2e): cover reply marker redaction path
ericksoa Jul 8, 2026
7607a95
Merge remote-tracking branch 'origin/main' into fix/dcode-nemotron-ul…
ericksoa Jul 8, 2026
79c3d85
fix(e2e): accept reviewed DCode approval arg
cjagwani Jul 8, 2026
10a814c
Merge branch 'fix/dcode-nemotron-ultra-profile-plugin' into fix/dcode…
cjagwani Jul 8, 2026
be07748
Merge merged profile base into fix/dcode-ultra-managed-compat/ericksoa
cjagwani Jul 8, 2026
be579d5
Merge main into fix/dcode-ultra-managed-compat/ericksoa
cjagwani Jul 8, 2026
1ac3660
fix(e2e): restore DCode live harness isolation
cjagwani Jul 8, 2026
5965b0e
Merge origin/main into fix/dcode-ultra-managed-compat/ericksoa
ericksoa Jul 8, 2026
aa836e2
Merge remote-tracking branch 'origin/fix/dcode-ultra-managed-compat/e…
ericksoa Jul 8, 2026
258c531
test(e2e): restore observability after policy cleanup
cjagwani Jul 8, 2026
5b60c73
chore(e2e): format observability restore
ericksoa Jul 8, 2026
63c9b45
test(e2e): exercise policy cleanup boundary
cjagwani Jul 8, 2026
750fc5b
test(e2e): document deferred shell expansion
cjagwani Jul 8, 2026
edbfe8c
fix(e2e): clean up Tavily after early exit
ericksoa Jul 8, 2026
09bb65a
Merge commit '750fc5b6b1b1b820b4a7f785ad8f700125d9d784' into tmp/6494…
ericksoa Jul 8, 2026
1e8a043
chore(e2e): use documented deferred expansion
ericksoa Jul 8, 2026
2063384
fix(dcode): harden managed Ultra profile registration
ericksoa Jul 8, 2026
0a1963c
Merge origin/main into fix/dcode-ultra-managed-compat/ericksoa
ericksoa Jul 8, 2026
ff2984e
test(e2e): snapshot observability after policy add
cjagwani Jul 8, 2026
74526e9
test(e2e): keep workflow ordering test linear
cjagwani Jul 8, 2026
78aa054
test(e2e): move workflow guards into helper
cjagwani Jul 8, 2026
d6430f2
fix(dcode): persist observability marker
ericksoa Jul 8, 2026
0269247
docs(dcode): record lifecycle repair boundaries
ericksoa Jul 8, 2026
5afdaeb
fix(dcode): preserve observability across policy restarts
ericksoa Jul 8, 2026
68f3665
Merge main into fix/dcode-ultra-managed-compat/ericksoa
ericksoa Jul 8, 2026
8980845
Merge origin/main into fix/dcode-ultra-managed-compat/ericksoa
ericksoa Jul 8, 2026
20e35b0
test(dcode): close observability CI gaps
cjagwani Jul 8, 2026
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
28 changes: 28 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2987,6 +2987,34 @@ jobs:
set -euo pipefail
printf 'NEMOCLAW_TRACE_DIR=%s\n' "${RUNNER_TEMP}/nemoclaw-cloud-onboard-traces" >> "${GITHUB_ENV}"

# invalidState: the cloud-onboard DCode TUI check requires a PTY driver,
# but the fixed GitHub-hosted runner image does not provide expect.
# sourceBoundary: this trusted workflow owns host setup; the repository
# check only verifies and consumes expect without privilege.
# whyNotSourceFix: GitHub-hosted jobs cannot use a repository-owned host
# image, and caching privileged dpkg state between clean runners is not
# supported.
# regressionTest: workflow-boundary tests pin the ordering and exact
# one-package apt allowlist.
# removalCondition: remove when the hosted runner supplies expect or the
# cloud-onboard acceptance check no longer requires a PTY.
- name: Install cloud-onboard DCode TUI host dependencies
shell: bash
run: |
set -euo pipefail
for attempt in 1 2 3; do
if sudo apt-get update; then
break
fi
if [ "$attempt" -eq 3 ]; then
echo "::error::apt-get update failed after 3 attempts." >&2
exit 1
fi
echo "::warning::apt-get update attempt ${attempt} failed; retrying." >&2
sleep $((attempt * 5))
done
sudo apt-get install -y --no-install-recommends expect

- name: Prepare E2E workspace
uses: NVIDIA/NemoClaw/.github/actions/prepare-e2e@50281ee84c4a6fc759da95ea28fc0b7d9c378a28

Expand Down
2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ RUN chmod 444 /opt/nemoclaw-deepagents-code/generate-config.ts /opt/nemoclaw-dee
&& cmp -s /usr/local/lib/nemoclaw/dcode-launcher.sh /usr/local/lib/nemoclaw/dcode-managed-exec \
&& chmod -R a+rX /opt/nemoclaw-blueprint \
&& test "$(find /opt/nemoclaw-deepagents-profile-plugin -type f -print | LC_ALL=C sort)" = "$(printf '%s\n' '/opt/nemoclaw-deepagents-profile-plugin/pyproject.toml' '/opt/nemoclaw-deepagents-profile-plugin/src/nemoclaw_deepagents_profile/__init__.py')" \
&& printf '%s %s\n' '75ff7e7a5142cad4305126ccb1b8fc756306e82d4c559ddbc624012fb54ebfc4' '/opt/nemoclaw-deepagents-profile-plugin/src/nemoclaw_deepagents_profile/__init__.py' '7ba7b77bd6f889cc861eddbe3e38fc1f4433a85b7bc2a9b516e19a19a37a7686' '/opt/nemoclaw-deepagents-profile-plugin/pyproject.toml' | sha256sum -c - \
&& printf '%s %s\n' '1cee6afafcbe545f5d095c94cb0ad81ff2a1512f84ad9d128a69a9b3d72b3def' '/opt/nemoclaw-deepagents-profile-plugin/src/nemoclaw_deepagents_profile/__init__.py' '7ba7b77bd6f889cc861eddbe3e38fc1f4433a85b7bc2a9b516e19a19a37a7686' '/opt/nemoclaw-deepagents-profile-plugin/pyproject.toml' | sha256sum -c - \
&& /opt/venv/bin/pip3 install --no-index --no-cache-dir --no-deps --no-build-isolation /opt/nemoclaw-deepagents-profile-plugin \
&& /opt/venv/bin/python3 -I -c 'import nemoclaw_deepagents_profile; print("NEMOCLAW_DCODE_PROFILE_" + "IMPORT_GATE", flush=True); import deepagents; import deepagents_code' \
&& /opt/venv/bin/pip3 check \
Expand Down
2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/dcode-launcher.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ unset _nemoclaw_auto_approval_env

readonly MANAGED_DCODE_WRAPPER="/usr/local/lib/nemoclaw/dcode-wrapper.sh"
readonly MANAGED_EXEC_LAUNCHER="/usr/local/lib/nemoclaw/dcode-managed-exec"
readonly MANAGED_OBSERVABILITY_MARKER="/tmp/nemoclaw-observability-enabled"
readonly MANAGED_OBSERVABILITY_MARKER="/sandbox/.deepagents/.nemoclaw-observability-enabled"
export HOME=/sandbox
export PATH="/usr/local/bin:/opt/venv/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin"

Expand Down
111 changes: 102 additions & 9 deletions agents/langchain-deepagents-code/dependency-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ NemoClaw no longer vendors or overlays that source.
- Native profile SHA-256: `c8e8dd2b0182334b54be4f46ff0c7b45fbb95dc13bd9a92c249eb47a14fa13d7`
- Unmodified built-in bootstrap SHA-256: `005a91e7fc4ca6b21220673dd9d02d6686bf63e1e4f1102d124b01f96886efcf`
- First-party adapter: `nemoclaw-deepagents-profile==0.1.0`
- Adapter module SHA-256: `75ff7e7a5142cad4305126ccb1b8fc756306e82d4c559ddbc624012fb54ebfc4`
- Adapter module SHA-256: `1cee6afafcbe545f5d095c94cb0ad81ff2a1512f84ad9d128a69a9b3d72b3def`
- Adapter project metadata SHA-256: `7ba7b77bd6f889cc861eddbe3e38fc1f4433a85b7bc2a9b516e19a19a37a7686`
- Adapter wheel license expression: `Apache-2.0`
- Adapter dependency audit result: `No known vulnerabilities found`. Its only
Expand Down Expand Up @@ -73,19 +73,77 @@ without consulting an index. Its `deepagents.harness_profiles` entry
point runs after built-in profiles are registered, reads the reviewed canonical
profile through one exact-version/hash-gated private registry lookup, and uses
Deep Agents' public registration API to map it to the two exact `openai:` model
keys used by NemoClaw's managed OpenAI-compatible `ChatOpenAI` route. The
keys used by NemoClaw's managed OpenAI-compatible `ChatOpenAI` route. It layers
one first-party middleware onto those aliases that rejects only a
case-insensitive `[content]` value, with optional whitespace around the token
and brackets, passed as the complete `execute` command;
the canonical NVIDIA profile and unrelated models remain unchanged. The
released SDK has no public profile getter or alias API. The adapter does not add
a provider-wide OpenAI profile.

### Managed Ultra compatibility workarounds

Two localized behaviors close separate invalid states on the managed Ultra
aliases. They are not a new provider profile and do not modify the reviewed
canonical NVIDIA profile.

The two managed model IDs remain language-local constants in the TypeScript
config generator and the isolated Python image/plugin validators. Those
components run on opposite sides of the offline wheel-install boundary, so a
shared runtime data file would enlarge the installed trust surface solely to
deduplicate two immutable strings. The focused profile-plugin suite extracts
the identifiers from every production consumer and requires the exact sets to
match, preventing drift without adding another mutable build artifact.

For `force_nonempty_content`, the invalid state originates in the NVIDIA Ultra
chat template/serving path: a Chat Completions response that combines reasoning
and tool calls can otherwise carry empty assistant content. That response shape
is outside NemoClaw; this repository owns only the generated DCode provider
configuration, so `generate-config.ts` supplies the model-specific template
argument at that request boundary. Fixing the serving template, model, or
third-party client in this repository would require vendoring an upstream
component and would violate the released-dependency boundary. The focused config
tests prove both managed Ultra IDs receive the argument and unrelated models do
not; the Deep Agents E2E verifies the installed request shape. Remove this
argument only after a reviewed serving-template or client update produces
nonempty assistant content for reasoning-plus-tool-call turns without it, and
the live DCode Ultra E2E passes for both managed model IDs with the override
deleted.

For the `[content]` guard, the invalid state is a model-produced tool call whose
complete `execute.command` is the placeholder, ignoring case and whitespace
around the token and brackets. The released Deep Agents parser/profile can carry that
argument to normal tool middleware, where an unrestricted execute backend would
otherwise treat it as a shell command. The model/provider emission and the
hash-locked `deepagents==0.7.0a6` canonical profile are upstream boundaries;
NemoClaw owns the two managed aliases and the final middleware immediately before
dispatch. The adapter therefore rejects only that observed complete argument and
leaves concrete commands, other tools, the canonical NVIDIA profile, and
unrelated models unchanged. Focused fixture tests plus the isolated image
validator cover sync and async rejection, concrete and non-execute pass-through,
and graph dispatch with shell restrictions disabled; the Deep Agents E2E repeats
the installed guard contract. Remove the guard only after a reviewed model,
serving-template, and Deep Agents update no longer emits or converts `[content]`
into an execute call across native and repaired tool-call paths, and those tests
plus the live DCode Ultra E2E pass with the middleware removed.

The adapter verifies the exact DCode and Deep Agents versions plus the official
native-profile and bootstrap source hashes. It also binds the imported Deep
Agents package to the distribution that supplied the reviewed version.
Registration is atomic, idempotent, and rejects missing canonical, partial, or
conflicting alias state. The image validator runs under isolated Python,
verifies the installed entry-point metadata and adapter source hash before the
upstream source checks, checks both upstream files again after profile loading,
resolves the complete native middleware for both aliases, compiles a graph,
proves parser/native dispatch parity, and confirms an unrelated OpenAI model
Registration uses the Deep Agents registry itself as its only idempotency
source, serializes the multi-key transaction for concurrent plugin discovery
within one Python interpreter, and rejects missing canonical, partial, or
conflicting alias state. The Deep Agents registry is process-local, so separate
agent processes have separate registries and cannot interleave writes; a
filesystem lock would not protect shared state. Revisit that assumption if an
upstream release moves the registry out of process. The image validator runs
under isolated Python, verifies the installed entry-point metadata and adapter
source hash before the upstream source checks, checks both upstream files again
after profile loading,
resolves the complete native middleware plus the managed guard for both aliases,
proves the canonical middleware remains unchanged, compiles a graph, exercises
sync and async placeholder rejection, proves concrete-command and parser/native
dispatch parity through the actual graph, and confirms an unrelated OpenAI model
receives no Ultra behavior. The Docker build separately imports the adapter,
Deep Agents, and DCode under isolated Python immediately after installation;
the validator then binds the installed module to its distribution and rechecks
Expand All @@ -98,7 +156,8 @@ the fake-Docker unit suite separately pins its diagnostic failure branches.

The reviewed native-profile and bootstrap files stay byte-for-byte unchanged.
Focused fixtures cover the reviewed version/hash, missing-source,
missing-canonical, partial/conflicting, rollback, and idempotence states. The
missing-canonical, partial/conflicting, rollback, idempotence, exact placeholder
rejection, and unchanged concrete-command states. The
deleted source-backport license path, `LICENSE.langchain-deepagents`, is not
staged into the image, and image regression tests enforce that absence.

Expand All @@ -115,3 +174,37 @@ this review to revalidate the managed adapter. Remove it instead of refreshing
its hashes only if a future reviewed dependency already provides both exact
mappings; no external contribution is required. Issue #6424 records the
NemoClaw-owned replacement of the previous installed-bootstrap mutation.

## Managed observability and ordered policy cleanup

The managed observability marker closes a sandbox lifecycle gap rather than an
authorization gap. OpenShell policy replacement can clear ephemeral `/tmp`, and
independent sandbox exec/login processes do not inherit the entrypoint's
environment, while the host registry and the active OTLP network policy remain
enabled. OpenShell owns those lifecycle semantics; NemoClaw owns the DCode
startup and launcher boundary but does not modify OpenShell here. Create,
rebuild, and snapshot-clone paths pass an explicit `1` or `0`; an environment-
less policy restart preserves the validated durable state. The startup script
writes only the credential-free enable bit to persistent
`/sandbox/.deepagents/.nemoclaw-observability-enabled`. The launcher accepts
only a non-symlink regular marker containing exactly `1`, and the network policy
remains the authority for OTLP access.

Focused launcher fixtures delete unrelated ephemeral state and prove the marker
survives, reject unsafe directory and marker types, and cover enabled and
disabled values. The ordered live checks prove Tavily removal restores the
deny-by-default policy while check 11 independently requires the host registry,
live policy, and durable sandbox marker to agree. Remove this marker and its
launcher recovery only when OpenShell propagates the selected observability bit
to every exec/login process across policy replacement, or when DCode no longer
needs the bit.

Tavily cleanup persists across sandbox rebuilds because `policy-remove` first
applies the narrowed live policy and then removes the preset from the sandbox's
registry-backed policy list, which is the source used by rebuild. The
`policy-add-remove-session-sync` tests cover successful persisted removal, and
the snapshot regression `does not resurrect an earlier removed preset` guards
restore behavior. The E2E EXIT trap is still required for early probe failures
so the ordered suite cannot leave the current sandbox broader than the registry.
Remove that trap only when each check receives an isolated sandbox or no longer
mutates policy.
19 changes: 19 additions & 0 deletions agents/langchain-deepagents-code/generate-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ type Settings = {
inferenceApi: string;
};

const NEMOTRON_ULTRA_MODEL_IDS = new Set([
"nvidia/nemotron-3-ultra-550b-a55b",
"nvidia/nvidia/nemotron-3-ultra",
]);

function readSettings(env: NodeJS.ProcessEnv): Settings {
const providerKey = normalizeCommentMetadata(
env.NEMOCLAW_PROVIDER_KEY || "inference",
Expand Down Expand Up @@ -94,6 +99,19 @@ function modelNameForOpenAiProvider(model: string): string {
function buildConfig(settings: Settings): string {
const model = modelNameForOpenAiProvider(settings.model);
const defaultModel = `openai:${model}`;
// Source boundary: NVIDIA's Ultra serving template owns the empty assistant
// content behavior; this generator owns only the managed per-model request
// parameters. Keep the exact invalid state, regression proof, and separate
// removal conditions for this option and the dispatch guard in
// dependency-review.md under "Managed Ultra compatibility workarounds."
const modelParams = NEMOTRON_ULTRA_MODEL_IDS.has(model)
? [
"",
`[models.providers.openai.params.${tomlString(model)}]`,
"# Nemotron Ultra coding-agent requests need nonempty content when tool calls and reasoning are combined.",
"extra_body = { chat_template_kwargs = { force_nonempty_content = true } }",
]
: [];
return [
"# Generated by NemoClaw. This file contains no provider secrets.",
`# NemoClaw provider route: ${settings.providerKey}; upstream provider: ${settings.upstreamProvider}; API: ${settings.inferenceApi}.`,
Expand All @@ -111,6 +129,7 @@ function buildConfig(settings: Settings): string {
"# NemoClaw-managed inference.local currently exposes Chat Completions.",
"# Remove this override when that route supports OpenAI Responses API.",
"use_responses_api = false",
...modelParams,
"",
"[update]",
"check = false",
Expand Down
Loading
Loading