Skip to content

fix(ci): the domain e2e coverage gate was measuring a seventh of the surface - #5936

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/domain-e2e-coverage-gate
Sep 1, 2026
Merged

senamakel merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/domain-e2e-coverage-gate

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Sep 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes three independent defects in scripts/check-domain-e2e-coverage.mjs, the gate that guards Rust e2e controller coverage.
  • The gate was measuring roughly a seventh of the surface and reporting the rest as clean.
  • 1 file. No product code touched.

Problem

Three separate holes, each of which alone makes the gate unreliable:

(a) It cannot see most controllers. collectSchemaMethods() only reads files matching /(^|\/)schemas?(\.rs|\/)/. The #5856/#5857 include! split moved ControllerSchema literals into *_part_NN.rs siblings that do not match, hiding 180 controllers across 12 namespaces.

(b) Measuring nothing scores 100%. percent = expected.size === 0 ? 100 : … means a namespace whose controllers all became invisible reports 100% — indistinguishable in the gate's own output from genuinely full coverage. Four namespaces were doing exactly that: composio 0/23, threads 0/20, memory_sources 0/17, tools 0/6.

(c) MODULES omits most of the product. ~50 namespaces are not listed at all, so they are never measured at any threshold — webhooks 0/13, skill_runtime 0/6, subagent 0/2, mcp_setup 0/6, voice 2/17, flows 19/36.

Solution

Discovery over the same roots the gate already means to cover, an explicit failure when a namespace discovers zero controllers, and a MODULES extension.

The honest post-fix numbers are much worse than the pre-fix ones, and that is the point: 359/625 controllers = 57.4% across 83 namespaces (up from 17 namespaces visible). 62 namespaces fall below the unchanged 90% threshold, 39 of them at exactly 0%.

The threshold is untouched and no ratchet was added. Making the gate green today is the failure mode being removed. It should stay red and honest until the coverage is real — how to stage that is a maintainer decision, and the repo's own precedent (scripts/kernel-floor.limits, "only goes DOWN") is the obvious tool if one is wanted.

Also measured and deliberately not changed: comment-only credit is a provable no-op today (390 methods found with comments, 390 without), and separating bare-list-entry credit from real invocations needs an AST — rustfmt puts a long call's method argument on its own line, so "openhuman.flows_create", is indistinguishable from a list element by regex.

Submission Checklist

  • Tests added or updated — N/A: this changes a CI script, not product code; its behaviour is verified by the measured before/after controller counts in the Problem section.
  • Diff coverage ≥ 80% — N/A: CI script, not covered by the product coverage lanes.
  • Coverage matrix updated — N/A: behaviour-only change, no feature rows affected.
  • All affected feature IDs listed — N/A: no feature IDs affected.
  • No new external network dependencies introduced — none; the script reads the repo only.
  • Manual smoke checklist updated — N/A: no product surface changes.
  • Linked issue closed via Closes #NNN — N/A: intentionally not auto-closing; see Related.

Impact

  • CI: this gate will report far lower coverage than before. That is a correction, not a regression — the previous numbers were measuring a subset and scoring the invisible remainder as perfect.
  • Risk: confined to a reporting script. It cannot affect the product.

Related

  • Addresses the defect described in openhuman#5911. Deliberately no closing keyword — the issue also covers the honest-coverage question, which this PR measures but does not resolve.
  • Sibling: fix/rpc-methods-drift-guard fixes the same blindness in app/src/services/__tests__/rpcMethods.test.ts.

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/domain-e2e-coverage-gate
  • Commit SHA: see head of this PR

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: no app/ files changed.
  • pnpm typecheck — N/A: no TypeScript changed (the script is .mjs).
  • Focused tests: the script was run against the repo before and after; the controller counts quoted above are its own output.
  • Rust fmt/check (if changed): N/A: no .rs files changed.
  • Tauri fmt/check (if changed): N/A: app/src-tauri not touched.

Validation Blocked

  • command: re-running the gate after the most recent rebase
  • error: not attempted — local CI runs are disabled by standing instruction
  • impact: the numbers quoted were measured before the rebase onto current main; the script's logic is unchanged since, so they should hold, but CI is the authority.

Behavior Changes

  • Intended behavior change: the gate now measures the whole controller surface and fails a namespace that discovers zero controllers.
  • User-visible effect: none. CI reporting only.

Parity Contract

  • Legacy behavior preserved: no, deliberately — the previous behaviour was the defect.
  • Guard/fallback/dispatch parity checks: a namespace with zero discovered controllers now fails instead of scoring 100%.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • Tests
    • Expanded end-to-end domain coverage checks to include additional controller sources and Rust files.
    • Added support for multiple controller schema formats.
    • Coverage reporting now includes detailed row-level failures and aggregate totals.
    • Configured namespaces missing from discovery are now reported as distinct failures.

The gate reported 100% for five namespaces it had measured nothing in, and
never looked at ~50 more at all. Three defects, all provable:

(a) Discovery read only files whose PATH matched /(^|\/)schemas?(\.rs|\/)/.
    The 2026-08-30 include! split (tinyhumansai#5856/tinyhumansai#5857) moved ControllerSchema literals
    into *_part_NN.rs siblings that the pattern does not match -- flows into
    flows_schema_part_01/02.rs, and the same for threads, tools, composio,
    inference, memory/sources, mcp/registry, agent/learning, agent/orchestration.
    13 files and 180 controllers went invisible in one commit with no signal.
    Restoring the old filter on top of this change drops discovery from 625
    controllers / 83 namespaces to 445 / 72.

    The path filter bought nothing a content match does not: a file with no
    ControllerSchema literal contributes nothing either way. Dropped it.

(b) percent = expected.size === 0 ? 100 : ... turned "measured nothing" into a
    pass. On this tree the old script prints, verbatim:

        | channels       | channels       | 0/0 | 100.0% | - |
        | composio       | composio       | 0/0 | 100.0% | - |
        | threads        | threads        | 0/0 | 100.0% | - |
        | tools          | tools          | 0/0 | 100.0% | - |
        | memory_sources | memory_sources | 0/0 | 100.0% | - |

    indistinguishable from genuine full coverage. A namespace named in MODULES
    with no discovered controllers is now a hard failure with its own message,
    which says explicitly that nothing was measured.

    channels is the case that made this load-bearing rather than theoretical:
    its 20 controllers are declared in the vendored tinychannels-bus crate as
    ChannelControllerSchema literals, and openhuman's adapter only maps them
    across with a dynamic namespace field no static scan can read. Added that
    crate as a second schema root, as
    app/src/services/__tests__/rpcMethods.test.ts already does for the same
    reason. channels now measures 18/20.

(c) MODULES was the SCOPE of the check, so a namespace nobody added a line for
    was never measured at any threshold: webhooks, skill_runtime, subagent,
    mcp_setup, flows, skills, cron, voice, workflow_run, team, billing, medulla
    and ~40 more. MODULES is now presentational grouping only; every discovered
    namespace is measured whether or not it is listed. A list you must remember
    to extend is a list that silently stops covering things.

Honest numbers, not tuned -- threshold left at 90:

    before: 17 namespaces, 4 failing
    after : 83 namespaces, 625 controllers, 359 named by an e2e target (57.4%),
            62 namespaces below 90%, 39 of them at 0%

The worst are whole namespaces with no Rust e2e at all: webhooks 0/13,
learning 0/11, medulla 0/9, session_db 0/6, skill_runtime 0/6, mcp_setup 0/6,
socket 0/5, memory_goals 0/5, test_support 0/5.

Also documented, not fixed: coverage is a string match, so a method NAMED by an
e2e target counts as covered without being provably invoked. Measured both
cheap tightenings before leaving it -- comment-only credit is exactly zero
today (390 methods with comments, 390 without), and bare-list-entry credit is
not separable by line shape, because rustfmt puts a long call's method argument
on its own line and a list element looks identical. Separating them needs an AST.

scripts/__tests__/coverage-script-help.test.mjs still passes.
@M3gA-Mind
M3gA-Mind requested a review from a team September 1, 2026 13:16
@coderabbitai

coderabbitai Bot commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 780427b4-5097-40dc-ace6-4eae64d514a8

📥 Commits

Reviewing files that changed from the base of the PR and between e3cf920 and f1ba9f9.

📒 Files selected for processing (1)
  • scripts/check-domain-e2e-coverage.mjs

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The coverage script discovers controller schemas from OpenHuman and vendored TinyChannels Rust sources. It supports two schema types, groups all discovered namespaces, reports aggregate totals, and fails for missing configured namespaces or rows below the coverage threshold.

Changes

Controller coverage validation

Layer / File(s) Summary
Schema discovery expansion
scripts/check-domain-e2e-coverage.mjs
The script scans both controller roots, parses ControllerSchema and ChannelControllerSchema, and documents method coverage limitations.
Namespace grouping
scripts/check-domain-e2e-coverage.mjs
The script uses MODULES for labels and grouping while generating rows for every discovered namespace.
Coverage failure reporting
scripts/check-domain-e2e-coverage.mjs
The script reports per-row failures, aggregate controller and target totals, and missing configured namespaces as hard failures.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to f1ba9

This change corrects CI coverage reporting without changing product behavior or runtime code; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: al629176

Poem

A rabbit reads each line,
The patch grows clear beneath the moon,
Small changes hop in place,
Tests guard the garden path,
Reviews bloom before the dawn.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: correcting the CI domain E2E coverage gate, which previously measured only part of the surface.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI

Warning

Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1ba9f989f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

for (const root of SCHEMA_ROOTS) {
for (const file of walk(root, (f) => f.endsWith('.rs'))) {
const text = read(file);
const constNamespace = text.match(/const\s+NAMESPACE:\s*&str\s*=\s*"([a-z_]+)"/)?.[1];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve namespaces inherited by split schema files

When a split schema file imports NAMESPACE from its parent rather than declaring it locally, this per-file lookup returns undefined, causing every controller in that file to be skipped. Both memory/schema/schema_schema_part_01.rs and _part_02.rs have this shape, so 25 registered memory_tree controllers disappear and the script incorrectly reports that namespace as 5/5 (100%); resolve the namespace from the owning module or otherwise include inherited constants.

Useful? React with 👍 / 👎.

// `ChannelControllerSchema` is the vendored bus crate's equivalent shape.
for (const match of text.matchAll(/(?:Channel)?ControllerSchema\s*\{([\s\S]*?)\n\s*\}/g)) {
const block = match[1];
const namespaceToken = block.match(/namespace:\s*(?:NAMESPACE|"([a-z_]+)")/);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include digits when parsing controller namespaces

When a controller namespace contains a digit, this pattern fails to capture it, so the new all-namespace gate silently omits the registered web3_swap, web3_bridge, web3_dapp, and x402 surfaces. Those files define ten controllers in total, including methods already referenced by Rust E2E tests, but none appears in the generated table or totals; accept the same alphanumeric namespace vocabulary that the method matcher already supports.

Useful? React with 👍 / 👎.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tinysweeper found nothing blocking. Approving.

             $0.0188 · 51,906 in / 5,667 out · 10,270 cached (20%) · openrouter/openai/text-embedding-3-small, z-ai/glm-5.2, deepseek/deepseek-v4-flash · 464 embedded
critique:    $0.0158 · 14,432 in / 5,303 out · 10,270 cached (71%) · z-ai/glm-5.2
security:    $0.0012 · 15,046 in / 95 out    · 0 cached (0%)       · deepseek/deepseek-v4-flash
tests:       $0.0012 · 14,959 in / 145 out   · 0 cached (0%)       · deepseek/deepseek-v4-flash
description: $0.0006 · 7,469 in  / 124 out   · 0 cached (0%)       · deepseek/deepseek-v4-flash

@tinysweeper

tinysweeper Bot commented Sep 1, 2026

Copy link
Copy Markdown

How this change flows

1 changed behaviour across 4 relationships. 5 surrounding behaviours are shown (60 graph nodes walked). 53 further behaviours left out to keep the diagram readable.

flowchart LR
  n0["collectSchemaMethods<br/>changed"]:::changed
  n1["row"]:::impacted
  n2["covered"]:::impacted
  n3["namespace"]:::impacted
  n4["declaredButMissing"]:::impacted
  n5["totalCovered"]:::impacted
  n0 -->|uses| n3
  n2 -->|uses| n1
  n4 -->|uses| n3
  n5 -->|uses| n1
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading

Green: changed behaviour. Grey: surrounding behaviour. Arrows name the call, use, implementation, or test relationship. Orange: has findings. Red: has a finding that blocks the merge.

tinysweeper 0.1.0

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Sep 1, 2026
@senamakel
senamakel merged commit 9cbf11a into tinyhumansai:main Sep 1, 2026
35 checks passed
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…and the e2e gate

Three behaviours merged in the last week had no test that would fail if the
fix were reverted. Each test below drives the changed code path and was
revert-checked against the specific hunk it covers.

- tinyhumansai#5795 — the auth profile store is written owner-only. Driven through
  `auth.store_provider_credentials` rather than `AuthProfilesStore`, so the
  RPC path acquiring a different writer is caught too. The assertion is
  umask-sensitive by nature, so the test probes the ambient umask first and
  says so rather than reporting a pass it did not earn.
- tinyhumansai#5947 — `validate_only` is a dry run for the stt workload, not only tts.
  A reserved slug is used because it is the one dry-run answer fully
  determined without a network call.
- tinyhumansai#5936 — the domain e2e coverage gate itself. Its only prior test asserted
  `--help` output, so all three defects it fixed were unpinned. Fixture-driven
  cover for part-file discovery, the empty-namespace failure, and measuring a
  namespace MODULES does not name.

Refs tinyhumansai#5795, tinyhumansai#5947, tinyhumansai#5936
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…and the e2e gate

Three behaviours merged in the last week had no test that would fail if the
fix were reverted. Each test below drives the changed code path and was
revert-checked against the specific hunk it covers.

- tinyhumansai#5795 — the auth profile store is written owner-only. Driven through
  `auth.store_provider_credentials` rather than `AuthProfilesStore`, so the
  RPC path acquiring a different writer is caught too. The assertion is
  umask-sensitive by nature, so the test probes the ambient umask first and
  says so rather than reporting a pass it did not earn.
- tinyhumansai#5947 — `validate_only` is a dry run for the stt workload, not only tts.
  A reserved slug is used because it is the one dry-run answer fully
  determined without a network call.
- tinyhumansai#5936 — the domain e2e coverage gate itself. Its only prior test asserted
  `--help` output, so all three defects it fixed were unpinned. Fixture-driven
  cover for part-file discovery, the empty-namespace failure, and measuring a
  namespace MODULES does not name.

Refs tinyhumansai#5795, tinyhumansai#5947, tinyhumansai#5936
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…and the e2e gate

Three behaviours merged in the last week had no test that would fail if the
fix were reverted. Each test below drives the changed code path and was
revert-checked against the specific hunk it covers.

- tinyhumansai#5795 — the auth profile store is written owner-only. Driven through
  `auth.store_provider_credentials` rather than `AuthProfilesStore`, so the
  RPC path acquiring a different writer is caught too. The assertion is
  umask-sensitive by nature, so the test probes the ambient umask first and
  says so rather than reporting a pass it did not earn.
- tinyhumansai#5947 — `validate_only` is a dry run for the stt workload, not only tts.
  A reserved slug is used because it is the one dry-run answer fully
  determined without a network call.
- tinyhumansai#5936 — the domain e2e coverage gate itself. Its only prior test asserted
  `--help` output, so all three defects it fixed were unpinned. Fixture-driven
  cover for part-file discovery, the empty-namespace failure, and measuring a
  namespace MODULES does not name.

Refs tinyhumansai#5795, tinyhumansai#5947, tinyhumansai#5936
senamakel added a commit to HDZTony/openhuman that referenced this pull request Sep 11, 2026
…verage-gate\n\nfix(ci): the domain e2e coverage gate was measuring a seventh of the surface\n
senamakel pushed a commit to HDZTony/openhuman that referenced this pull request Sep 11, 2026
…and the e2e gate\n\nThree behaviours merged in the last week had no test that would fail if the\nfix were reverted. Each test below drives the changed code path and was\nrevert-checked against the specific hunk it covers.\n\n- tinyhumansai#5795 — the auth profile store is written owner-only. Driven through\n  `auth.store_provider_credentials` rather than `AuthProfilesStore`, so the\n  RPC path acquiring a different writer is caught too. The assertion is\n  umask-sensitive by nature, so the test probes the ambient umask first and\n  says so rather than reporting a pass it did not earn.\n- tinyhumansai#5947 — `validate_only` is a dry run for the stt workload, not only tts.\n  A reserved slug is used because it is the one dry-run answer fully\n  determined without a network call.\n- tinyhumansai#5936 — the domain e2e coverage gate itself. Its only prior test asserted\n  `--help` output, so all three defects it fixed were unpinned. Fixture-driven\n  cover for part-file discovery, the empty-namespace failure, and measuring a\n  namespace MODULES does not name.\n\nRefs tinyhumansai#5795, tinyhumansai#5947, tinyhumansai#5936\n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants