From 8a65ae71d8d27ed745976147d5eef21e7e14ac15 Mon Sep 17 00:00:00 2001 From: Johnny Greco Date: Fri, 11 Sep 2026 21:42:55 +0000 Subject: [PATCH 1/3] Add theme-aware OAR logo to README and documentation --- docs/stylesheets/documentation.css | 13 ++++++++++ projects/openshell-agent-runner/README.md | 4 +++ .../docs/assets/oar-logo.svg | 25 +++++++++++++++++++ projects/openshell-agent-runner/docs/index.md | 2 ++ 4 files changed, 44 insertions(+) create mode 100644 projects/openshell-agent-runner/docs/assets/oar-logo.svg diff --git a/docs/stylesheets/documentation.css b/docs/stylesheets/documentation.css index aa3da39e..08d6f038 100644 --- a/docs/stylesheets/documentation.css +++ b/docs/stylesheets/documentation.css @@ -1,6 +1,19 @@ /* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ /* SPDX-License-Identifier: Apache-2.0 */ +.md-typeset .documentation-logo { + display: block; + width: 360px; + max-width: 100%; + height: auto; + margin: 1.5rem auto 2rem; + color-scheme: light; +} + +body[data-md-color-scheme="slate"] .md-typeset .documentation-logo { + color-scheme: dark; +} + /* Documentation figures use one quiet visual treatment across light and dark pages. */ .md-typeset .documentation-figure { width: 100%; diff --git a/projects/openshell-agent-runner/README.md b/projects/openshell-agent-runner/README.md index 3ef1ecf9..03000c6a 100644 --- a/projects/openshell-agent-runner/README.md +++ b/projects/openshell-agent-runner/README.md @@ -1,5 +1,9 @@ # OpenShell Agent Runner +

+ OAR — OpenShell Agent Runner +

+ OpenShell Agent Runner (OAR) launches ephemeral [Pi coding agents](https://github.com/earendil-works/pi/tree/main/packages/coding-agent) in OpenShell sandboxes. Each agent works on a task using the prompts, skills, diff --git a/projects/openshell-agent-runner/docs/assets/oar-logo.svg b/projects/openshell-agent-runner/docs/assets/oar-logo.svg new file mode 100644 index 00000000..a100a91d --- /dev/null +++ b/projects/openshell-agent-runner/docs/assets/oar-logo.svg @@ -0,0 +1,25 @@ + + OAR — OpenShell Agent Runner + An oar forms the left stroke of the A, with a terminal prompt cut out of its blade and two water ripples. NVIDIA green accents remain constant; lettering adapts to light and dark color schemes. + + + + + + + + + + + + + diff --git a/projects/openshell-agent-runner/docs/index.md b/projects/openshell-agent-runner/docs/index.md index 041750d0..7fc360f4 100644 --- a/projects/openshell-agent-runner/docs/index.md +++ b/projects/openshell-agent-runner/docs/index.md @@ -6,6 +6,8 @@ agent_markdown: true # OpenShell Agent Runner + + OpenShell Agent Runner (OAR) launches ephemeral [Pi coding agents](https://github.com/earendil-works/pi/tree/main/packages/coding-agent) in OpenShell sandboxes. Each agent works on a task using the prompts, skills, From 763a2ce63ee6db896922196e2a945181360744fb Mon Sep 17 00:00:00 2001 From: Johnny Greco Date: Fri, 11 Sep 2026 21:47:44 +0000 Subject: [PATCH 2/3] Fix branch-relative OAR logo and stage shared project assets --- .github/workflows/docs-preview-deploy.yml | 2 +- .github/workflows/docs-preview.yml | 2 +- docs/development/index.md | 5 +++ projects/openshell-agent-runner/README.md | 2 +- .../{docs => }/assets/oar-logo.svg | 0 .../openshell-agent-runner/pyproject.toml | 1 + scripts/stage-project-docs.py | 36 +++++++++++++++---- tests/test_stage_project_docs.py | 33 +++++++++++++++++ 8 files changed, 71 insertions(+), 10 deletions(-) rename projects/openshell-agent-runner/{docs => }/assets/oar-logo.svg (100%) diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index 4c0b3599..2420f368 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -109,7 +109,7 @@ jobs: const docsChanged = files.some( ({ filename }) => filename.startsWith('docs/') || filename.startsWith('overrides/') || - /^projects\/[^/]+\/docs\//.test(filename) || + /^projects\/[^/]+\/(docs|assets)\//.test(filename) || exactInputs.has(filename), ); operation = docsChanged ? 'deploy' : 'remove'; diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index cc1b03e9..695497dd 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -57,7 +57,7 @@ jobs: const docsChanged = files.some( ({ filename }) => filename.startsWith('docs/') || filename.startsWith('overrides/') || - /^projects\/[^/]+\/docs\//.test(filename) || + /^projects\/[^/]+\/(docs|assets)\//.test(filename) || exactInputs.has(filename), ); core.setOutput('operation', docsChanged ? 'deploy' : 'remove'); diff --git a/docs/development/index.md b/docs/development/index.md index a5c99ec4..fe48f766 100644 --- a/docs/development/index.md +++ b/docs/development/index.md @@ -73,6 +73,11 @@ Commit any generated changes with the source change. ## Theme and brand assets +Project logos shared by a README and the site belong in `projects//assets/`. +Register that directory in `PROJECT_ASSETS` in `scripts/stage-project-docs.py`; +the build copies it into the staged documentation's `assets/` directory. +README image links should be relative so they work on feature branches. + Keep shared brand assets in `docs/assets/brand/`. Use the compact SVG mark for `project.theme.logo`, `favicon.svg` for the browser icon, and the light and dark PNG banners for full OpenShell Research lockups. Never reference files from a diff --git a/projects/openshell-agent-runner/README.md b/projects/openshell-agent-runner/README.md index 03000c6a..940093c3 100644 --- a/projects/openshell-agent-runner/README.md +++ b/projects/openshell-agent-runner/README.md @@ -1,7 +1,7 @@ # OpenShell Agent Runner

- OAR — OpenShell Agent Runner + OAR — OpenShell Agent Runner

OpenShell Agent Runner (OAR) launches ephemeral diff --git a/projects/openshell-agent-runner/docs/assets/oar-logo.svg b/projects/openshell-agent-runner/assets/oar-logo.svg similarity index 100% rename from projects/openshell-agent-runner/docs/assets/oar-logo.svg rename to projects/openshell-agent-runner/assets/oar-logo.svg diff --git a/projects/openshell-agent-runner/pyproject.toml b/projects/openshell-agent-runner/pyproject.toml index 0762d7a5..e3b48ea4 100644 --- a/projects/openshell-agent-runner/pyproject.toml +++ b/projects/openshell-agent-runner/pyproject.toml @@ -59,6 +59,7 @@ packages = ["src/openshell_agent_runner"] [tool.hatch.build.targets.sdist] include = [ + "/assets", "/src/openshell_agent_runner", "/LICENSE", "/README.md", diff --git a/scripts/stage-project-docs.py b/scripts/stage-project-docs.py index 5fd5cd11..df686a07 100644 --- a/scripts/stage-project-docs.py +++ b/scripts/stage-project-docs.py @@ -14,15 +14,17 @@ ROOT = Path(__file__).resolve().parents[1] PROJECT_DOCUMENTATION = { "egress-gate": ROOT / "projects" / "egress-gate" / "docs", - "openshell-agent-runner": ROOT - / "projects" - / "openshell-agent-runner" - / "docs", + "openshell-agent-runner": ROOT / "projects" / "openshell-agent-runner" / "docs", } DOCUMENTATION_ROOT = ROOT / "docs" / "documentation" +PROJECT_ASSETS = { + "openshell-agent-runner": ROOT / "projects" / "openshell-agent-runner" / "assets", +} -def stage_project_docs(source: Path, destination: Path) -> None: +def stage_project_docs( + source: Path, destination: Path, assets: Path | None = None +) -> None: """Replace one generated site mirror with its canonical project-docs tree.""" source = source.resolve() @@ -31,7 +33,9 @@ def stage_project_docs(source: Path, destination: Path) -> None: if not source.is_dir(): raise ValueError(f"documentation source does not exist: {source}") if destination_is_symlink: - raise ValueError(f"documentation destination must not be a symlink: {destination}") + raise ValueError( + f"documentation destination must not be a symlink: {destination}" + ) if source.is_relative_to(destination) or destination.is_relative_to(source): raise ValueError("documentation source and destination must not overlap") @@ -40,11 +44,27 @@ def stage_project_docs(source: Path, destination: Path) -> None: paths = "\n".join(f" - {path}" for path in symlinks) raise ValueError(f"project documentation must not contain symlinks:\n{paths}") + if assets is not None: + if assets.is_symlink() or any(path.is_symlink() for path in assets.rglob("*")): + raise ValueError("project assets must not contain symlinks") + if not assets.is_dir(): + raise ValueError(f"project assets directory does not exist: {assets}") + for path in assets.rglob("*"): + if ( + path.is_file() + and (source / "assets" / path.relative_to(assets)).exists() + ): + raise ValueError( + f"project asset conflicts with documentation asset: {path}" + ) + destination.parent.mkdir(parents=True, exist_ok=True) staging = destination.with_name(f".{destination.name}.staging") if staging.exists(): shutil.rmtree(staging) shutil.copytree(source, staging) + if assets is not None: + shutil.copytree(assets, staging / "assets", dirs_exist_ok=True) if destination.exists(): shutil.rmtree(destination) @@ -53,7 +73,9 @@ def stage_project_docs(source: Path, destination: Path) -> None: def main() -> int: for project, source in PROJECT_DOCUMENTATION.items(): - stage_project_docs(source, DOCUMENTATION_ROOT / project) + stage_project_docs( + source, DOCUMENTATION_ROOT / project, PROJECT_ASSETS.get(project) + ) print(f"Staged {project} documentation from {source}.") return 0 diff --git a/tests/test_stage_project_docs.py b/tests/test_stage_project_docs.py index fbca7017..2ceb75e6 100644 --- a/tests/test_stage_project_docs.py +++ b/tests/test_stage_project_docs.py @@ -81,5 +81,38 @@ def test_stage_rejects_source_inside_destination(self) -> None: STAGER.stage_project_docs(source, destination) +def test_stage_includes_project_assets_without_changing_canonical_docs(tmp_path): + source = tmp_path / "project" / "docs" + assets = tmp_path / "project" / "assets" + destination = tmp_path / "published" + (source / "assets").mkdir(parents=True) + assets.mkdir() + (source / "index.md").write_text('') + (source / "assets" / "diagram.svg").write_text("") + (assets / "logo.svg").write_text('') + + STAGER.stage_project_docs(source, destination, assets) + + assert (destination / "assets" / "logo.svg").read_bytes() == ( + assets / "logo.svg" + ).read_bytes() + assert (destination / "assets" / "diagram.svg").is_file() + assert not (source / "assets" / "logo.svg").exists() + + +def test_stage_rejects_conflicting_project_assets(tmp_path): + import pytest + + source = tmp_path / "docs" + assets = tmp_path / "assets" + (source / "assets").mkdir(parents=True) + assets.mkdir() + (source / "assets" / "logo.svg").write_text("") + (assets / "logo.svg").write_text("") + + with pytest.raises(ValueError, match="conflicts"): + STAGER.stage_project_docs(source, tmp_path / "published", assets) + + if __name__ == "__main__": unittest.main() From dcc22deda8405a61113aab7e67e8c4caece97159 Mon Sep 17 00:00:00 2001 From: Johnny Greco Date: Fri, 11 Sep 2026 21:49:05 +0000 Subject: [PATCH 3/3] Enlarge OAR documentation header logo --- docs/stylesheets/documentation.css | 2 +- projects/openshell-agent-runner/docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/stylesheets/documentation.css b/docs/stylesheets/documentation.css index 08d6f038..c3c5ec81 100644 --- a/docs/stylesheets/documentation.css +++ b/docs/stylesheets/documentation.css @@ -3,7 +3,7 @@ .md-typeset .documentation-logo { display: block; - width: 360px; + width: 540px; max-width: 100%; height: auto; margin: 1.5rem auto 2rem; diff --git a/projects/openshell-agent-runner/docs/index.md b/projects/openshell-agent-runner/docs/index.md index 7fc360f4..ef104091 100644 --- a/projects/openshell-agent-runner/docs/index.md +++ b/projects/openshell-agent-runner/docs/index.md @@ -6,7 +6,7 @@ agent_markdown: true # OpenShell Agent Runner - + OpenShell Agent Runner (OAR) launches ephemeral [Pi coding agents](https://github.com/earendil-works/pi/tree/main/packages/coding-agent)