lab infocheck: canonical pattern for non-service binaries in lib workspaces (hero_lib, hero_rpc)? #258

Closed
opened 2026-05-17 19:14:03 +00:00 by mik-tf · 2 comments
Owner

Situation

Running lab infocheck across the 35 demo-set repos: 11 clean, 24 with findings (~300 total). Two of the foundational libraries fail for the same surprising reason — they contain helper/demo binaries that aren't real services.

  • hero_lib — 3 of 4 crates fail (ai_archive, clients, web). These ship a main.rs but are internal helpers, not services. Same situation as the cleanup we filed at hero_lib#139.
  • hero_rpc — all 5 crates fail (generator, service, petstore_client, petstore_server, recipe_server). Codegen tooling + OpenRPC examples, not services.

Each binary triggers the same 4 findings: missing service.toml, service_base!(), validate_service_toml, handle_info_flag. Combined that's 39 of the ~300 findings — but it's one underlying problem, not 39.

Question

What's the canonical pattern for helper / demo / codegen binaries that live in a lib workspace but aren't services?

  1. Delete the binary targets from Cargo.toml → pure library crates. Cleanest, but loses ergonomic cargo run --bin <demo> usage.
  2. Add minimal service_base!() with kind = "cmdline" + trivial service.toml. Satisfies the contract.
  3. Opt-out metadata — e.g. [package.metadata.lab_builder] skip_info_check = true — so lab infocheck and lab build's --info gate both skip non-service binaries.

Should lab build --repair bootstrap canonical-base wiring on wholesale-shape repos (0/N service_base!() coverage)? A pilot on hero_editor showed --repair doesn't engage on --info-gate failures, only on cargo compile errors. If by design, the path for those repos is manual or lab agent-driven sweep — just confirming.

## Situation Running `lab infocheck` across the 35 demo-set repos: **11 clean, 24 with findings (~300 total).** Two of the foundational libraries fail for the same surprising reason — they contain helper/demo binaries that aren't real services. - **hero_lib** — 3 of 4 crates fail (`ai_archive`, `clients`, `web`). These ship a `main.rs` but are internal helpers, not services. Same situation as the cleanup we filed at [hero_lib#139](https://forge.ourworld.tf/lhumina_code/hero_lib/issues/139). - **hero_rpc** — all 5 crates fail (`generator`, `service`, `petstore_client`, `petstore_server`, `recipe_server`). Codegen tooling + OpenRPC examples, not services. Each binary triggers the same 4 findings: missing `service.toml`, `service_base!()`, `validate_service_toml`, `handle_info_flag`. Combined that's 39 of the ~300 findings — but it's one underlying problem, not 39. ## Question What's the canonical pattern for helper / demo / codegen binaries that live in a lib workspace but aren't services? 1. **Delete the binary targets** from `Cargo.toml` → pure library crates. Cleanest, but loses ergonomic `cargo run --bin <demo>` usage. 2. **Add minimal `service_base!()`** with `kind = "cmdline"` + trivial `service.toml`. Satisfies the contract. 3. **Opt-out metadata** — e.g. `[package.metadata.lab_builder] skip_info_check = true` — so `lab infocheck` and `lab build`'s `--info` gate both skip non-service binaries. ## Related clarification Should `lab build --repair` bootstrap canonical-base wiring on wholesale-shape repos (0/N `service_base!()` coverage)? A pilot on `hero_editor` showed `--repair` doesn't engage on `--info`-gate failures, only on cargo compile errors. If by design, the path for those repos is manual or `lab agent`-driven sweep — just confirming.
Author
Owner

Decision: Option 2 (canonical service_base!() triad + kind = "cmdline" service.toml)

Applying the same canonical wiring as service binaries to non-service helper / demo / codegen bins. Locked as D-11 (workspace decision file at decisions/D-11-non-service-bin-canonical-pattern.md).

Pattern for the affected crates:

  1. service.toml at the crate root with kind = "cmdline", category = "tool" (or ai / ui / core as fits), no [[binaries.sockets]] / [[binaries.tcp]] blocks, optional [[env]] PATH_ROOT if the bin pulls in any herolib_core::base path helpers.
  2. main.rs (or src/bin/<name>.rs):
    • use herolib_core::service_base; + service_base!(); at module scope (canonical case), OR inline const SERVICE_TOML: &str = include_str!("../../service.toml"); + const BUILD_NR: u64 = { ... option_env!("HERO_BUILD_NR") ... }; for src/bin/<name>.rs shape (Lesson #20 workaround).
    • herolib_core::base::validate_service_toml(SERVICE_TOML); as first line of fn main().
    • herolib_core::base::handle_info_flag(SERVICE_TOML); next.
    • No print_startup_banner / prepare_sockets calls — cmdline bins don't bind sockets and shouldn't emit a startup banner.

Reasoning:

  • Established precedent. Already shipping across the D-10 arc — hero_books (hero_docs), hero_os (hero_os_app, hero_os_web), hero_voice, hero_lib_rhai (hero_do), and others. Applying the same pattern to hero_lib + hero_rpc keeps the workspace coherent.
  • Satisfies D-10 criterion 2 literally. No "non-service exception" class needed; every binary crate has canonical wiring.
  • Preserves ergonomics. cargo run --bin <demo> keeps working for codegen (hero_rpc generator), test runners (ai_direct_test, herolib_clients opencode demo/tester), and helper CLIs (hero_lifecycle).
  • lab infocheck lib+bin false-positives are documented at #265 as cosmetic. Runtime --info --json roundtrip is the operational gate (per s123 hero_osis_server precedent — that closure also accepted the same false-positive class).

Why not Option 1 (delete bins). Loses useful demo/codegen ergonomics. Some bins are actively used (e.g. hero_rpc::generator::scaffold runs codegen during build.rs in downstream repos).

Why not Option 3 (opt-out metadata). Requires a lab tooling change; weakens the "every binary has --info" contract; adds a per-crate exception surface that needs maintenance. Option 2 piggybacks on the existing canonical pattern with zero new tooling.

lab build --repair clarification (from the bottom of the issue). Confirmed working as designed — --repair engages on cargo compile errors only, not on --info-gate or source-side wiring failures. For wholesale-shape (0/N service_base!() coverage) repos the path is manual sweep or lab agent-driven, which is what the D-10 arc has been doing.

Applied in s124 to hero_lib (3 crates: ai_archive, clients, web) and hero_rpc (5 crates: generator, hero_lifecycle, petstore_client, petstore_server, recipe_server) — see s124 squash commits + tracker update at #102#33220.

Closing as decided.

## Decision: Option 2 (canonical `service_base!()` triad + `kind = "cmdline"` service.toml) Applying the same canonical wiring as service binaries to non-service helper / demo / codegen bins. Locked as D-11 (workspace decision file at `decisions/D-11-non-service-bin-canonical-pattern.md`). **Pattern for the affected crates:** 1. **`service.toml`** at the crate root with `kind = "cmdline"`, `category = "tool"` (or `ai` / `ui` / `core` as fits), no `[[binaries.sockets]]` / `[[binaries.tcp]]` blocks, optional `[[env]] PATH_ROOT` if the bin pulls in any `herolib_core::base` path helpers. 2. **`main.rs`** (or `src/bin/<name>.rs`): - `use herolib_core::service_base;` + `service_base!();` at module scope (canonical case), **OR** inline `const SERVICE_TOML: &str = include_str!("../../service.toml");` + `const BUILD_NR: u64 = { ... option_env!("HERO_BUILD_NR") ... };` for `src/bin/<name>.rs` shape (Lesson #20 workaround). - `herolib_core::base::validate_service_toml(SERVICE_TOML);` as first line of `fn main()`. - `herolib_core::base::handle_info_flag(SERVICE_TOML);` next. - No `print_startup_banner` / `prepare_sockets` calls — `cmdline` bins don't bind sockets and shouldn't emit a startup banner. **Reasoning:** - **Established precedent.** Already shipping across the D-10 arc — hero_books (`hero_docs`), hero_os (`hero_os_app`, `hero_os_web`), hero_voice, hero_lib_rhai (`hero_do`), and others. Applying the same pattern to hero_lib + hero_rpc keeps the workspace coherent. - **Satisfies D-10 criterion 2 literally.** No "non-service exception" class needed; every binary crate has canonical wiring. - **Preserves ergonomics.** `cargo run --bin <demo>` keeps working for codegen (hero_rpc generator), test runners (ai_direct_test, herolib_clients opencode demo/tester), and helper CLIs (hero_lifecycle). - **`lab infocheck` lib+bin false-positives** are documented at #265 as cosmetic. Runtime `--info --json` roundtrip is the operational gate (per s123 hero_osis_server precedent — that closure also accepted the same false-positive class). **Why not Option 1 (delete bins).** Loses useful demo/codegen ergonomics. Some bins are actively used (e.g. `hero_rpc::generator::scaffold` runs codegen during build.rs in downstream repos). **Why not Option 3 (opt-out metadata).** Requires a lab tooling change; weakens the "every binary has `--info`" contract; adds a per-crate exception surface that needs maintenance. Option 2 piggybacks on the existing canonical pattern with zero new tooling. **`lab build --repair` clarification (from the bottom of the issue).** Confirmed working as designed — `--repair` engages on cargo compile errors only, not on `--info`-gate or source-side wiring failures. For wholesale-shape (0/N `service_base!()` coverage) repos the path is manual sweep or `lab agent`-driven, which is what the D-10 arc has been doing. **Applied in s124** to hero_lib (3 crates: `ai_archive`, `clients`, `web`) and hero_rpc (5 crates: `generator`, `hero_lifecycle`, `petstore_client`, `petstore_server`, `recipe_server`) — see s124 squash commits + tracker update at [#102#33220](https://forge.ourworld.tf/lhumina_code/hero_proc/issues/102#issuecomment-33220). Closing as decided.
Author
Owner

s124 close

Both blocked repos are now D-11 compliant and squashed to development:

  • hero_lib33b5a3fb — 3 crates / 4 bins wired (ai_archive, clients, web).
  • hero_rpcb1c8621 — 5 crates / 5 bins wired (generator, hero_lifecycle, petstore_server, petstore_client, recipe_server).

D-10 effective state: 34/35 (~97%). Only mycelium_network remains (manual pass, outside lab infocheck purview).

Lab infocheck source-side false-positives remain on the 4 lib+bin crates (ai_archive + clients in hero_lib, generator + hero_lifecycle in hero_rpc) — accepted as cosmetic per s123 hero_osis_server precedent; runtime --info --json roundtrip is the operational gate. Tracked at hero_skills#265.

Closing — pattern locked at D-11, applied across both repos. Tracker #102#33220 updated with the s124 section.

## s124 close Both blocked repos are now D-11 compliant and squashed to `development`: - `hero_lib` — [`33b5a3fb`](https://forge.ourworld.tf/lhumina_code/hero_lib/commit/33b5a3fb) — 3 crates / 4 bins wired (`ai_archive`, `clients`, `web`). - `hero_rpc` — [`b1c8621`](https://forge.ourworld.tf/lhumina_code/hero_rpc/commit/b1c8621) — 5 crates / 5 bins wired (`generator`, `hero_lifecycle`, `petstore_server`, `petstore_client`, `recipe_server`). **D-10 effective state: 34/35 (~97%).** Only `mycelium_network` remains (manual pass, outside lab infocheck purview). Lab infocheck source-side false-positives remain on the 4 lib+bin crates (ai_archive + clients in hero_lib, generator + hero_lifecycle in hero_rpc) — accepted as cosmetic per s123 hero_osis_server precedent; runtime `--info --json` roundtrip is the operational gate. Tracked at [hero_skills#265](https://forge.ourworld.tf/lhumina_code/hero_skills/issues/265). Closing — pattern locked at D-11, applied across both repos. Tracker [#102#33220](https://forge.ourworld.tf/lhumina_code/hero_proc/issues/102#issuecomment-33220) updated with the s124 section.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_skills#258
No description provided.