From 69d1834015776c5f294b9dc0dd779513be78034d Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 16 Oct 2026 13:03:58 -0700 Subject: [PATCH 1/2] Bundle product documentation and deployment context for the agent Stage tracked product Markdown beside existing skill references and preload documentation discovery guidance. Provide a credential-free module profile, check bundle freshness in CI, and validate packaged offline startup while preserving existing manuals and tools. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- .github/workflows/ci.yml | 3 ++ docs/building.md | 16 ++++++++ docs/package_agent_docs.py | 32 ++++++++++++++++ .../files/agent-documentation.tar.gz | Bin 0 -> 25807 bytes .../skills/agent-documentation/SKILL.md | 30 +++++++++++++++ .../files/openclaw-seed/workspace/AGENTS.md | 4 ++ .../templates/openclaw-seed-configmap.yaml | 17 +++++++++ helm/mosaic-stack/templates/openclaw.yaml | 6 +++ helm/mosaic-stack/tests/chart-render.test.mjs | 36 +++++++++++++++++- 9 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 docs/package_agent_docs.py create mode 100644 helm/mosaic-stack/files/agent-documentation.tar.gz create mode 100644 helm/mosaic-stack/files/openclaw-seed/skills/agent-documentation/SKILL.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19c8aae..68b89a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,9 @@ jobs: - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 with: version: 0.12.6 + - name: Check agent documentation bundle + run: uv run --no-project docs/package_agent_docs.py --check + - name: Prepare chart test dependencies run: | set -euo pipefail diff --git a/docs/building.md b/docs/building.md index de4d66a..1a767ab 100644 --- a/docs/building.md +++ b/docs/building.md @@ -23,3 +23,19 @@ The footprint catalog is generated during each HTML build by rendering the track The documentation workflow builds pull requests without publishing. After a change lands on `main`, it publishes the generated static site to GitHub Pages using the `github-pages` environment. A repository administrator must first enable **Settings → Pages → Build and deployment → Source: GitHub Actions**. The intended URL is `https://nvidia.github.io/AI-Factory-Operations-Agent/`. Until Pages is enabled and a deployment succeeds, that URL will not serve the documentation. No registry or inference credentials are needed for the documentation build. + +## Agent reference bundle + +The Helm chart also includes the tracked product Markdown for the agent to read +inside its sandbox, alongside any Base Command Manager manuals. After editing +`README.md` or Markdown under `docs/`, refresh the bundle before packaging the chart: + +```bash +uv run --no-project docs/package_agent_docs.py +``` + +CI checks that the bundle matches its sources. Startup stages it under the agent +workspace's `skills/agent-documentation/docs`, with a deployment profile containing +module enablement and registered cluster names. Credentials are excluded from that +profile. The current tool catalog and live tool results remain authoritative for +capabilities and infrastructure state. diff --git a/docs/package_agent_docs.py b/docs/package_agent_docs.py new file mode 100644 index 0000000..571d2a9 --- /dev/null +++ b/docs/package_agent_docs.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Bundle tracked Markdown for the agent workspace; --check verifies freshness.""" +import gzip +import io +from pathlib import Path +import subprocess +import sys +import tarfile + +root = Path(__file__).resolve().parents[1] +output = root / "helm/mosaic-stack/files/agent-documentation.tar.gz" +paths = subprocess.check_output( + ["git", "ls-files", "-z", "README.md", "docs"], cwd=root +).decode().split("\0") +archive = io.BytesIO() +with tarfile.open(fileobj=archive, mode="w") as tar: + for name in sorted(name for name in paths if name.endswith(".md")): + content = (root / name).read_bytes() + entry = tarfile.TarInfo(name) + entry.size, entry.mode = len(content), 0o644 + tar.addfile(entry, io.BytesIO(content)) +compressed = io.BytesIO() +with gzip.GzipFile(fileobj=compressed, mode="wb", filename="", mtime=0) as stream: + stream.write(archive.getvalue()) +bundle = compressed.getvalue() +if "--check" in sys.argv: + if not output.exists() or output.read_bytes() != bundle: + sys.exit("Agent documentation is stale: run uv run --no-project docs/package_agent_docs.py") +else: + output.write_bytes(bundle) diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..2d9c6ecdb17d3124fb10cd0c6d039f725badf44d GIT binary patch literal 25807 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 + + +# Agent documentation + +The product's Markdown documentation is bundled under `skills/agent-documentation/docs` +in the agent workspace. In OpenShell, locate the copied references with sandbox-local +`exec` before reading them; workspace copy locations can vary: + +```sh +find /sandbox -type f -path '*/skills/agent-documentation/docs/README.md' +``` + +Use the returned file's directory as the documentation root. Start with `README.md`, +`docs/installation.md`, `docs/security_model.md`, or `docs/multitenancy.md` as appropriate. + +Read `../deployment.json` relative to that documentation root for this installation's module settings, release, +namespace and configured Kubernetes cluster names. Documentation describes supported +behavior; it does not establish that an integration is enabled, reachable or authorized. +Use the current session's registered tools and runtime context to establish available +capabilities, and their results for live state. Sandbox-local binaries and server-side +integration tools are separate execution environments; inspect the registered tools +before concluding that an infrastructure capability is unavailable. + +Base Command Manager manuals remain under `skills/bcm/docs` when that module is enabled. diff --git a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md index 882084f..ccefddf 100644 --- a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md +++ b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md @@ -14,6 +14,10 @@ Before investigating or remediating a fault, follow the evidence sequence in the For a cause investigation, establish which resources and path the workload actually uses. Keep observations, candidate explanations, and verified causes distinct. Supply specialists with measured facts and explicitly label assumptions; never invent a hardware rating or expected result for their question. Research responses suggest discriminating checks, not proof of the local cause. After consultation, perform those checks on the participating resources and resolve contradictory evidence before choosing a correction. A warning on an unused resource does not explain the workload. Continue available checks rather than ending with a list of possible causes. Report only conclusions supported by the resulting evidence and preserve genuine uncertainty. +## Preloaded skill: agent-documentation + +{{ .Files.Get "files/openclaw-seed/skills/agent-documentation/SKILL.md" }} + ## Local execution and remote diagnostics Local `exec` runs inside the per-session OpenShell sandbox in every access mode. Use it for sandbox-local commands, scripts, and data processing; OpenShell enforces the execution boundary. A local command rejection does not establish that other tools or integrations are unavailable. diff --git a/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml b/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml index 1894397..1e1c440 100644 --- a/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml +++ b/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml @@ -8,7 +8,24 @@ metadata: name: openclaw-seed labels: {{- include "mosaic-stack.labels" . | nindent 4 }} +binaryData: + agent-documentation.tar.gz: {{ required "Packaged agent documentation is missing" (.Files.Get "files/agent-documentation.tar.gz") | b64enc | quote }} data: + agent-documentation.SKILL.md: |- +{{ .Files.Get "files/openclaw-seed/skills/agent-documentation/SKILL.md" | indent 4 }} + agent-deployment.json: |- + { + "release": {{ .Release.Name | quote }}, + "namespace": {{ .Release.Namespace | quote }}, + "chartVersion": {{ .Chart.Version | quote }}, + "modules": { + {{- range $name, $module := .Values.modules }} + {{ $name | quote }}: {{ $module.enabled }}, + {{- end }} + "bcmConfigured": {{ eq (include "mosaic-stack.bcmEnabled" .) "true" }} + }, + "kubernetesClusters": {{ keys (include "mosaic-stack.kubernetesClusters" . | fromJson) | sortAlpha | toJson }} + } openclaw.json: |- {{ tpl (.Files.Get "files/openclaw-seed/nemoclaw.json") . | indent 4 }} gpu-networking.SKILL.md: |- diff --git a/helm/mosaic-stack/templates/openclaw.yaml b/helm/mosaic-stack/templates/openclaw.yaml index 0622a5c..bf26c06 100644 --- a/helm/mosaic-stack/templates/openclaw.yaml +++ b/helm/mosaic-stack/templates/openclaw.yaml @@ -214,6 +214,12 @@ spec: rm -rf /home/node/.openclaw/identity /home/node/.openclaw/devices mkdir -p /home/node/.openclaw/workspace/skills/gpu-networking cp /seed/gpu-networking.SKILL.md /home/node/.openclaw/workspace/skills/gpu-networking/SKILL.md + documentation=/home/node/.openclaw/workspace/skills/agent-documentation + rm -rf "$documentation" + mkdir -p "$documentation/docs" + tar -xzf /seed/agent-documentation.tar.gz -C "$documentation/docs" + cp /seed/agent-documentation.SKILL.md "$documentation/SKILL.md" + cp /seed/agent-deployment.json "$documentation/deployment.json" cp /seed/AGENTS.md /home/node/.openclaw/workspace/AGENTS.md cp /seed/HEARTBEAT.md /home/node/.openclaw/workspace/HEARTBEAT.md cp /seed/IDENTITY.md /home/node/.openclaw/workspace/IDENTITY.md diff --git a/helm/mosaic-stack/tests/chart-render.test.mjs b/helm/mosaic-stack/tests/chart-render.test.mjs index a599df8..c7b3d14 100644 --- a/helm/mosaic-stack/tests/chart-render.test.mjs +++ b/helm/mosaic-stack/tests/chart-render.test.mjs @@ -1084,7 +1084,7 @@ test("preloads selected skill instructions from their authoritative files", () = } }); -test("packaged GPU documentation installs locally with research and UI disabled", () => { +test("packaged product and GPU documentation installs locally with research, UI and BCM disabled", () => { const directory = mkdtempSync(join(tmpdir(), "skill-offline-")); try { execFileSync("helm", ["package", chart, "--destination", directory]); @@ -1098,6 +1098,13 @@ test("packaged GPU documentation installs locally with research and UI disabled" const home = join(directory, "home"); execFileSync("mkdir", ["-p", seed, home]); const seedSection = output.split("name: openclaw-seed\n")[1].split("\n---")[0]; + const binaryData = seedSection.split("binaryData:\n")[1].split("\ndata:")[0]; + for (const line of binaryData.trim().split("\n")) { + const [name, encoded] = line.trim().split(": "); + writeFileSync(join(seed, name), Buffer.from(JSON.parse(encoded), "base64")); + } + execFileSync("mkdir", ["-p", join(home, "workspace/docs")]); + writeFileSync(join(home, "workspace/docs/existing-manual.md"), "Existing manual"); for (const line of seedSection.split("\n")) { if (line.startsWith(" ") && !line.startsWith(" ") && line.endsWith(": |-")) { const key = line.trim().slice(0, -4); @@ -1109,6 +1116,16 @@ test("packaged GPU documentation installs locally with research and UI disabled" .map(line => line.slice(14)).join("\n") .replaceAll("/home/node/.openclaw", home).replaceAll("/seed/", `${seed}/`); execFileSync("sh", ["-eu", "-c", script]); + const documentation = join(home, "workspace/skills/agent-documentation"); + const root = join(chart, "../.."); + const sources = execFileSync("git", ["ls-files", "-z", "README.md", "docs"], {cwd: root, encoding: "utf8"}) + .split("\0").filter(name => name.endsWith(".md")); + for (const source of sources) { + assert.deepEqual(readFileSync(join(documentation, "docs", source)), readFileSync(join(root, source))); + } + assert.ok(readFileSync(join(documentation, "SKILL.md"), "utf8").startsWith("---\n")); + assert.equal(JSON.parse(readFileSync(join(documentation, "deployment.json"), "utf8")).modules.kubernetes, false); + assert.equal(readFileSync(join(home, "workspace/docs/existing-manual.md"), "utf8"), "Existing manual"); const relative = "skills/gpu-networking"; const workspace = join(home, "workspace"); const references = join(workspace, relative, "references"); @@ -1154,3 +1171,20 @@ test("configures optional Loki access without exposing its credential to UI or s const defaults = render("--show-only", "templates/openclaw.yaml"); assert.doesNotMatch(defaults, /name: MOSAIC_LOKI_AUTHORIZATION/); }); + +test("deployment reference reflects module settings without exporting credentials", () => { + for (const enabled of [true, false]) { + const seed = render("--set", `modules.kubernetes.enabled=${enabled}`, + "--set-string", "observability.grafanaAuth.existingSecret=private-secret-ref", + "--set-string", "modules.research.secrets.nvidiaApiKey=private-test-value", + "--show-only", "templates/openclaw-seed-configmap.yaml"); + const text = configMapBlock(seed, "agent-deployment.json"); + const profile = JSON.parse(text); + assert.equal(profile.modules.kubernetes, enabled); + assert.equal(profile.namespace, "mosaic-test"); + assert.deepEqual(profile.kubernetesClusters, ["local"]); + assert.equal(text.includes("private-secret-ref"), false); + assert.equal(text.includes("private-test-value"), false); + assert.ok(Buffer.byteLength(seed) < 1048576); + } +}); From d6690e18d98215e3045198cec10fd7a1e57f2901 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Mon, 26 Oct 2026 10:00:23 -0700 Subject: [PATCH 2/2] Reference local product docs directly from sandbox instructions Replace the separate documentation skill with one sentence in AGENTS.md. Stage product docs and the deployment profile under product-docs, remove the obsolete skill on upgrade, and retain offline reference access and existing vendor manuals. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/building.md | 2 +- .../files/agent-documentation.tar.gz | Bin 29860 -> 29857 bytes .../skills/agent-documentation/SKILL.md | 30 ------------------ .../files/openclaw-seed/workspace/AGENTS.md | 6 ++-- .../templates/openclaw-seed-configmap.yaml | 2 -- helm/mosaic-stack/templates/openclaw.yaml | 9 +++--- helm/mosaic-stack/tests/chart-render.test.mjs | 9 ++++-- 7 files changed, 13 insertions(+), 45 deletions(-) delete mode 100644 helm/mosaic-stack/files/openclaw-seed/skills/agent-documentation/SKILL.md diff --git a/docs/building.md b/docs/building.md index 1a767ab..5ef1d46 100644 --- a/docs/building.md +++ b/docs/building.md @@ -35,7 +35,7 @@ uv run --no-project docs/package_agent_docs.py ``` CI checks that the bundle matches its sources. Startup stages it under the agent -workspace's `skills/agent-documentation/docs`, with a deployment profile containing +workspace's `product-docs/`, with a deployment profile containing module enablement and registered cluster names. Credentials are excluded from that profile. The current tool catalog and live tool results remain authoritative for capabilities and infrastructure state. diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index afdef26570a0c73ead866394e5326b24d8e2bea8..4edf4b8909b4de0bd50347dee65192a88f4d6b97 100644 GIT binary patch delta 9952 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 delta 9955 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 diff --git a/helm/mosaic-stack/files/openclaw-seed/skills/agent-documentation/SKILL.md b/helm/mosaic-stack/files/openclaw-seed/skills/agent-documentation/SKILL.md deleted file mode 100644 index 2079b57..0000000 --- a/helm/mosaic-stack/files/openclaw-seed/skills/agent-documentation/SKILL.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: agent-documentation -description: Explain this agent's architecture, integrations, configuration and execution boundaries using its bundled product documentation and deployment profile. ---- - - - - -# Agent documentation - -The product's Markdown documentation is bundled under `skills/agent-documentation/docs` -in the agent workspace. In OpenShell, locate the copied references with sandbox-local -`exec` before reading them; workspace copy locations can vary: - -```sh -find /sandbox -type f -path '*/skills/agent-documentation/docs/README.md' -``` - -Use the returned file's directory as the documentation root. Start with `README.md`, -`docs/installation.md`, `docs/security_model.md`, or `docs/multitenancy.md` as appropriate. - -Read `../deployment.json` relative to that documentation root for this installation's module settings, release, -namespace and configured Kubernetes cluster names. Documentation describes supported -behavior; it does not establish that an integration is enabled, reachable or authorized. -Use the current session's registered tools and runtime context to establish available -capabilities, and their results for live state. Sandbox-local binaries and server-side -integration tools are separate execution environments; inspect the registered tools -before concluding that an infrastructure capability is unavailable. - -Base Command Manager manuals remain under `skills/bcm/docs` when that module is enabled. diff --git a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md index ccefddf..10951bf 100644 --- a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md +++ b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md @@ -14,14 +14,12 @@ Before investigating or remediating a fault, follow the evidence sequence in the For a cause investigation, establish which resources and path the workload actually uses. Keep observations, candidate explanations, and verified causes distinct. Supply specialists with measured facts and explicitly label assumptions; never invent a hardware rating or expected result for their question. Research responses suggest discriminating checks, not proof of the local cause. After consultation, perform those checks on the participating resources and resolve contradictory evidence before choosing a correction. A warning on an unused resource does not explain the workload. Continue available checks rather than ending with a list of possible causes. Report only conclusions supported by the resulting evidence and preserve genuine uncertainty. -## Preloaded skill: agent-documentation - -{{ .Files.Get "files/openclaw-seed/skills/agent-documentation/SKILL.md" }} - ## Local execution and remote diagnostics Local `exec` runs inside the per-session OpenShell sandbox in every access mode. Use it for sandbox-local commands, scripts, and data processing; OpenShell enforces the execution boundary. A local command rejection does not establish that other tools or integrations are unavailable. +Read bundled product docs and `deployment.json` from `product-docs/` in the sandbox workspace. + The bundled sandbox does not include BCM's `cmsh` CLI. Use the registered BCM tools to access BCM when that integration is enabled. If those tools are absent, report that BCM is not configured for this deployment. Changing the session access mode does not install commands or enable integrations. `run_remote_ssh` executes on an installer-configured host outside the sandbox. In View mode, use only its supported read-only diagnostic argv. Remote commands outside that policy require Edit; do not rewrite a rejected command to bypass the policy. diff --git a/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml b/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml index 1e1c440..5d64d61 100644 --- a/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml +++ b/helm/mosaic-stack/templates/openclaw-seed-configmap.yaml @@ -11,8 +11,6 @@ metadata: binaryData: agent-documentation.tar.gz: {{ required "Packaged agent documentation is missing" (.Files.Get "files/agent-documentation.tar.gz") | b64enc | quote }} data: - agent-documentation.SKILL.md: |- -{{ .Files.Get "files/openclaw-seed/skills/agent-documentation/SKILL.md" | indent 4 }} agent-deployment.json: |- { "release": {{ .Release.Name | quote }}, diff --git a/helm/mosaic-stack/templates/openclaw.yaml b/helm/mosaic-stack/templates/openclaw.yaml index 5901caf..ddf835d 100644 --- a/helm/mosaic-stack/templates/openclaw.yaml +++ b/helm/mosaic-stack/templates/openclaw.yaml @@ -214,11 +214,10 @@ spec: rm -rf /home/node/.openclaw/identity /home/node/.openclaw/devices mkdir -p /home/node/.openclaw/workspace/skills/gpu-networking cp /seed/gpu-networking.SKILL.md /home/node/.openclaw/workspace/skills/gpu-networking/SKILL.md - documentation=/home/node/.openclaw/workspace/skills/agent-documentation - rm -rf "$documentation" - mkdir -p "$documentation/docs" - tar -xzf /seed/agent-documentation.tar.gz -C "$documentation/docs" - cp /seed/agent-documentation.SKILL.md "$documentation/SKILL.md" + documentation=/home/node/.openclaw/workspace/product-docs + rm -rf "$documentation" /home/node/.openclaw/workspace/skills/agent-documentation + mkdir -p "$documentation" + tar -xzf /seed/agent-documentation.tar.gz -C "$documentation" cp /seed/agent-deployment.json "$documentation/deployment.json" cp /seed/AGENTS.md /home/node/.openclaw/workspace/AGENTS.md cp /seed/HEARTBEAT.md /home/node/.openclaw/workspace/HEARTBEAT.md diff --git a/helm/mosaic-stack/tests/chart-render.test.mjs b/helm/mosaic-stack/tests/chart-render.test.mjs index cce856d..d342e03 100644 --- a/helm/mosaic-stack/tests/chart-render.test.mjs +++ b/helm/mosaic-stack/tests/chart-render.test.mjs @@ -1097,6 +1097,9 @@ test("packaged product and GPU documentation installs locally with research, UI const seed = join(directory, "seed"); const home = join(directory, "home"); execFileSync("mkdir", ["-p", seed, home]); + const legacySkill = join(home, "workspace/skills/agent-documentation"); + execFileSync("mkdir", ["-p", legacySkill]); + writeFileSync(join(legacySkill, "SKILL.md"), "Previous documentation skill"); const seedSection = output.split("name: openclaw-seed\n")[1].split("\n---")[0]; const binaryData = seedSection.split("binaryData:\n")[1].split("\ndata:")[0]; for (const line of binaryData.trim().split("\n")) { @@ -1116,14 +1119,14 @@ test("packaged product and GPU documentation installs locally with research, UI .map(line => line.slice(14)).join("\n") .replaceAll("/home/node/.openclaw", home).replaceAll("/seed/", `${seed}/`); execFileSync("sh", ["-eu", "-c", script]); - const documentation = join(home, "workspace/skills/agent-documentation"); + assert.equal(existsSync(legacySkill), false); + const documentation = join(home, "workspace/product-docs"); const root = join(chart, "../.."); const sources = execFileSync("git", ["ls-files", "-z", "README.md", "docs"], {cwd: root, encoding: "utf8"}) .split("\0").filter(name => name.endsWith(".md")); for (const source of sources) { - assert.deepEqual(readFileSync(join(documentation, "docs", source)), readFileSync(join(root, source))); + assert.deepEqual(readFileSync(join(documentation, source)), readFileSync(join(root, source))); } - assert.ok(readFileSync(join(documentation, "SKILL.md"), "utf8").startsWith("---\n")); assert.equal(JSON.parse(readFileSync(join(documentation, "deployment.json"), "utf8")).modules.kubernetes, false); assert.equal(readFileSync(join(home, "workspace/docs/existing-manual.md"), "utf8"), "Existing manual"); const relative = "skills/gpu-networking";