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
48 changes: 48 additions & 0 deletions .github/workflows/ci-lite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,54 @@ jobs:
fi
echo "gate-contract test coverage allowlist is current"

# Report-only (#5046). Measures steady-state RSS of an embedded openhuman_core
# agent roster and uploads the raw samples + a human summary. Deliberately NOT
# in `pr-ci-gate.needs`, so it can never fail a PR — it exists to accrue a
# baseline and its runner variance before the 30 MiB gate is flipped to
# blocking in a follow-up (add this job to pr-ci-gate + a threshold step then).
rust-rss-bench:
name: Rust RSS Benchmark (report-only)
needs: [changes]
if: needs.changes.outputs['rust-core'] == 'true'
runs-on: ubuntu-22.04
timeout-minutes: 40
container:
image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0
env:
CARGO_INCREMENTAL: "0"
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 1
persist-credentials: false
submodules: recursive

- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
cache-on-failure: true
shared-key: pr-rust-rss-bench

# Fixture-contract signal: the gated bin's unit tests (build_roster,
# warm-up turn) never enter the default coverage lane, so run them here.
- name: Run rss-bench fixture tests
run: bash scripts/ci-cancel-aware.sh cargo test --features rss-bench --bin rss-bench

- name: Build stripped-release rss-bench
run: bash scripts/ci-cancel-aware.sh cargo build --release --features rss-bench --bin rss-bench

- name: Measure embedded RSS (5 fresh procs x {1,8} agents)
run: ./target/release/rss-bench --out bench-rss.json | tee -a "$GITHUB_STEP_SUMMARY"

- name: Upload raw RSS samples

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the cargo test / cargo build steps above route through scripts/ci-cancel-aware.sh, but this measure step does not. It's short and report-only so the blast radius is tiny, but a cancelled run won't have its watchdog stop the in-flight measurement. Minor consistency nit.

uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: rss-bench-report
path: bench-rss.json

rust-core-coverage:
name: Rust Core Coverage (cargo-llvm-cov)
needs: [changes, rust-quality]
Expand Down
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ path = "src/bin/test_mcp_stub.rs"
name = "openhuman-fleet"
path = "src/bin/fleet.rs"

# Embedded-RSS benchmark harness (#5046). Gated behind the default-OFF
# `rss-bench` feature so no benchmark code enters the shipped build. Build with
# `cargo build --release --features rss-bench --bin rss-bench`.
[[bin]]
name = "rss-bench"
path = "src/bin/rss_bench.rs"
required-features = ["rss-bench"]

[lib]
name = "openhuman_core"
crate-type = ["rlib"]
Expand Down Expand Up @@ -491,6 +499,10 @@ whatsapp-web = ["tinychannels/whatsapp-web"]
# build (app/scripts/e2e-build.sh) flips it on. Shipped binaries never have
# this feature so the wipe RPC isn't even registered, let alone reachable.
e2e-test-support = []
# Builds the `rss-bench` benchmark binary (#5046). Default-OFF, so it is never
# part of the shipped desktop/library build and the feature-forwarding gate
# (which only inspects the `default` list) never requires forwarding it.
rss-bench = []

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage)'] }
Expand Down
4 changes: 4 additions & 0 deletions scripts/__tests__/feature-forwarding.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { fileURLToPath } from 'node:url';

import {
diffForwarding,
INTENTIONALLY_NOT_FORWARDED,
parseCoreDefaultFeatures,
parseShellForwardedFeatures,
stripComments,
Expand Down Expand Up @@ -179,6 +180,9 @@ test('the real shell manifest forwards every real core default', () => {
assert.ok(coreDefaults.length > 0, 'expected to parse at least one core default gate');
assert.equal(shell.defaultFeatures, false, 'shell is expected to set default-features = false');
for (const gate of coreDefaults) {
// Gates the shell intentionally does not forward (e.g. `tui` — a terminal
// subcommand the desktop app never runs) are exempt, matching the checker.
if (INTENTIONALLY_NOT_FORWARDED[gate]) continue;
assert.ok(
shell.features.includes(gate),
`core default gate not forwarded to the shell: ${gate}`
Expand Down
15 changes: 1 addition & 14 deletions scripts/ci/check-feature-forwarding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,13 @@ import { fileURLToPath } from 'node:url';
import {
diffForwarding,
formatReport,
INTENTIONALLY_NOT_FORWARDED,
parseCoreDefaultFeatures,
parseShellForwardedFeatures,
} from '../lib/feature-forwarding.mjs';

const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../..');

/**
* Gates the desktop shell intentionally does NOT forward, mapped to why.
*
* Empty by design: every current default-ON gate belongs in the shipped app.
* Adding an entry is a deliberate product decision, not a way to silence this
* check — the reason string is what a future reader (and reviewer) relies on to
* tell "excluded on purpose" from "forgotten". That ambiguity is exactly what
* let #4918 sit unnoticed since #4123.
*/
const INTENTIONALLY_NOT_FORWARDED = {
// 'some-gate': 'Reason it must not ship in the desktop build.',
tui: 'Terminal UI subcommand (openhuman tui/chat); the desktop app ships its own Tauri UI and never runs the ratatui terminal front-end.',
};

function usage() {
return 'Usage: check-feature-forwarding.mjs [core-manifest] [shell-manifest]';
}
Expand Down
17 changes: 17 additions & 0 deletions scripts/lib/feature-forwarding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@
// only needs two well-known shapes, and the repo has no TOML dependency for
// Node. It is regex/scanner-based in the same spirit as `checklist-parser.mjs`.

/**
* Gates the desktop shell intentionally does NOT forward, mapped to why.
*
* Adding an entry is a deliberate product decision, not a way to silence the
* forwarding guard — the reason string is what a future reader (and reviewer)
* relies on to tell "excluded on purpose" from "forgotten". That ambiguity is
* exactly what let #4918 sit unnoticed since #4123.
*
* Lives here (not in the checker) so both the CI checker and the self-test read
* the same source of truth — otherwise the self-test can demand a forward the
* checker legitimately exempts, which is exactly the drift #5084's `tui` gate hit.
*/
export const INTENTIONALLY_NOT_FORWARDED = {
// 'some-gate': 'Reason it must not ship in the desktop build.',
tui: 'Terminal UI subcommand (openhuman tui/chat); the desktop app ships its own Tauri UI and never runs the ratatui terminal front-end.',
};

/**
* Strip TOML `#` comments while respecting quoted strings, so a `#` inside a
* value (or an issue number in a comment) can't truncate a real line.
Expand Down
Loading
Loading