Codegen alignment with current standards (service.toml, SDK, _admin, lab lifecycle) #55
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_rpc#55
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
hero_rpc's codegen predates several recent ecosystem changes. The generated output does not match what current Hero services need to compile and run cleanly. This issue tracks bringing the generator output up to current standards.
Reference services (pulled latest,
developmentbranch):hero_proc— canonical wiring reference.hero_proc_server/src/main.rsusesservice_base!(),validate_service_toml,handle_info_flagexactly as the skills mandate.hero_compute— reference for workspace layout + hero_rpc OSchema deps. (Note: its_server/src/main.rsuses an olderrun/start/stop/statussubcommand pattern with noservice_base!()— do not mimic that.)Generator output should let a service look like
hero_procwithout manual fix-ups.Source-of-truth direction (flipped from initial draft)
service.tomlis the single source of truth, written at scaffold time (#54). Codegen READS from it; it does NOT generate it.This way the user has a single place to specify what the service is. The codegen never overwrites
service.toml.Misalignments to fix
1.
OschemaBuildConfig::from_service_toml()constructorNew entry point: read the embedded or sibling
service.toml, deserialize asherolib_core::base::ServiceToml, derive service name / domain / output paths from it. Service-sidebuild.rscollapses to:(Depends on #56 for the modularization that enables ≤5-line
build.rs.)Codegen MUST NOT write
service.toml— that file is owned by scaffold + the contributor.2. Generate the SDK crate — decision pending: own codegen vs
hero_rpc2SDKs are hand-written in every Hero service today. Two paths:
Path A — Generate from OpenRPC ourselves. Continue using hero_rpc's existing JSON Schema / OpenRPC output to emit a
hero_<name>_sdkcrate with typed client methods (UDS + HTTP viaherolib_coreopenrpc-transportfeature). Pros: full control, reuses existing pipeline, same generator produces JS/TS + Rhai bindings. Cons: more code we maintain.Path B — Adopt
delandtj/hero_rpc2. Lean JSON-RPC framework on top ofjsonrpsee0.26 with Unix-socket transports and OpenRPC discovery built in. The#[rpc(server, client)]trait macro auto-generates the client alongside the server impl — no separate SDK codegen step. README explicitly positions it as a replacement for the heavier hero_rpc ("axum + tower-http + ACL + tenancy + OSchema codegen") for MOS daemons.#[rpc(client)].oschemafilesOsisObject,DBTyped<T>, SmartID)X-Hero-ContextroutingAction items for this issue:
delandtj/hero_rpc2'sdocs/PRD.mdand code, write a 1-page evaluation in this thread.hero_<name>_sdkcrate scaffold (from #54) using the chosen mechanism.Do not unblock the SDK generation work until this evaluation is done.
3. Generate the
_admincrate scaffoldMinimal admin binary using
hero_website_lib(drop thehero_admin_libalias — see hero_website_framework#5). Default screens come from the framework (hero_website_framework#4); this generator just wires the binary, sockets, and reads itsservice.toml.Templating: Askama by default. Hero ecosystem default is compile-time Askama (matches
hero_proc_admin). Tera is used only where runtime template loading is genuinely needed (user-editable content). Codegen emits Askama for the scaffolded_admin's own templates.hero_website_framework's existing Tera-based default screens stay Tera until/unless migrated separately (hero_website_framework#4).4. Reconcile dual lifecycle paths
Today two abstractions coexist:
hero_rpc/crates/service/—HeroLifecycle,HeroRpcServer,HeroUiServer(used by out-of-datehero_inspector).herolib_core::base+service_base!()+lablifecycle (used by currenthero_proc, documented inhero_skills/skills/hero/service/).Decision: delete
hero_rpc/crates/service/. Generated code, the scaffoldedmain.rs, and docs referenceherolib_core::base+labonly.Action items:
crates/service/from this repo.hero_service = { ... }from workspace deps inhero_rpc/Cargo.tomland any downstream consumers — verify nothing in lhumina_code references the deleted crate (grep across all repos).main.rsboilerplate accordingly (noHeroLifecycle::new(...)).5. Update generated
main.rsboilerplateMust include, in this order, matching
hero_proc_server/src/main.rs:service_base!()at module scopevalidate_service_toml(SERVICE_TOML)first inmainhandle_info_flag(SERVICE_TOML)second — unless the--infodeprecation question (below) landsprint_startup_banner(...)fromherolib_core::base— no hand-rolledprint_startup_infoprepare_sockets(...)fromherolib_core::base— no hand-rolledresolve_socket_dirThis is what
lab infocheckvalidates (§0a ofhero_service_check_fix).5a.
--info/--info --json— status check@timur flagged that
--infomay have been deprecated. Current evidence says it is NOT deprecated:hero_skills/skills/hero/service/mandate--infoand--info --json(hero_service.mdline 6,hero_service_toml_info.mdheaders "--infoflag — mandatory for every Hero binary, no exceptions",hero_service_check_fix.md§0a).hero_procbinaries callherolib_core::base::handle_info_flag.lab infocheckliterally executes<bin> --info --jsonand re-deserialises the output to validate it.Action items before changing anything:
lab service <name> --info?).hero_skillsto remove--inforequirements from all three service skills, file an issue inherolib_coreto removehandle_info_flag, and propagate to current consumers (hero_proc, etc.) before this codegen drops--info.main.rskeepshandle_info_flag.6. Naming suffixes
Generator currently has no opinion. Enforce
_server,_admin,_sdk,_web,_appperhero_service_check_fix§2 — never_ui,_cli,_cmd.Acceptance
lab infocheckclean with zero manual edits._serverbinary--info --jsondeserialises intoServiceToml(unless--infois removed per §5a).hero_rpc/crates/service/is deleted; no lhumina_code repo references it.hero_inspectorremoved from any "reference" mentions in hero_rpc docs.Related
service.tomlcreation).generator/src/build/build.rs(enables the ≤5-linebuild.rsshape).example/recipe_server(consumes this).hero_admin_libalias.delandtj/hero_rpc2— SDK-generation alternative being evaluated.hero_proc(wiring),hero_compute(layout).hero_rpc scaffold) #54well, service.toml is more of a part of the scaffold then generation. in fact, oschema build config can use service name etc from there instead of other way around so we have a single place to specify our service. For the sdk crate lets explore the possibility of using https://forge.ourworld.tf/delandtj/hero_rpc2 as well and how that might effect our services and pros and cons. for 3. again lets link the mentioned issue. 4) yes delete hero_rpc/crates/service/. --info and --json was deprecated to my knowledge. lets check on that and if that is the case lets also remove it from whatever gave the impression if was necessary in hero_skills. only service.toml is for service info. edit description to link related issues and repos with actual links
lets use hybrid approach for now, hero_rpc2 stuff for client and transport etc. lets move hero_rpc2 into hero_rpc as a crate. We still want schema source to be oschema files, so perhaps those are used to create code that has the traits that hero_rpc2 uses to create the server client etc. we also still want OSchema storage layer. we still want js/ts + rhai bindings, in fact even python generated in sdk, but rust client can come from hero_rpc2 via macros and such. Multi-tenant X-Hero-Context routing requires more explaining, but this is how i would look at it: hero_rpc2 is less opinionated, we can have it extended to carry certain headers from http calls into the context of a call and have it pass that to the handler as an optional field such that it can work without context as well. So then x-hero-context id can be carried in a context struct into the handled rpc call, and stuff that uses the OSIS storage for instance then can store / operate in the db of the hero-context id provided in the transport context. Checking on 5.
Confirmed — hybrid (Path C). Working sketch of how the pieces fit:
Architecture
OSchema stays the schema source of truth. hero_rpc2 owns the wire protocol + transport + Rust client. OSIS storage, JS/TS, Rhai, and Python all keep coming from our OSchema codegen.
Action items
hero_rpc/crates/hero_rpc2/. Coordinate with @delandtj — is the upstreamdelandtj/hero_rpc2repo still active, or do we take ownership? Either way, we'll need to fork or copy. Once vendored, update workspace deps + this issue's references.#[rpc(server, client)]fromhero_rpc2::prelude(matches the hero_rpc2 README example). Trait impl stub for the contributor lives in a preserved file (src/<domain>/server/rpc.rs) like today.hero_rpc/crates/service/(already agreed; still ours to do).OsisObject,DBTyped<T>, SmartID) stays as-is — codegen still emits it.X-Hero-Context proposal — extending hero_rpc2
Following your sketch: hero_rpc2 is unopinionated about per-request context, so we add it as an opt-in extension. Strawman API:
Design notes:
HeroRequestContextis a typed struct generated from a config (which headers, types, defaults).Option<...>lets the same trait work over the line transport (no headers) and HTTP transport (with headers).None), so the handler signature stays the same..scope(context)method to namespace byX-Hero-Context— replacing today's implicit per-socket multiplexing.X-Hero-Claims) ride the same mechanism for the openrpc_authorize layer.Open questions on this:
Option<HeroRequestContext>(works without context) or always-present-but-defaulted (HeroRequestContextwithis_anonymous())? I lean toward always-present-defaulted — simpler trait, nounwrap_orboilerplate everywhere.labneed to know about this (e.g., to route specific contexts to specific socket dirs)?Still pending
--infodeprecation check — your investigation underway.Will update the issue body with this hybrid decision once the open questions above settle — keeping the body frozen until then so the comment thread tracks the iteration.
—info just gives the toml, so not deprecated. Lets keep HeroReqCtx option, for now its a fork and extend (but just copy over dont actually fork). there is no longer ever a case where contexts are routed to specific context socket dirs, and any mention should be removed.
Locked in:
--infostays — confirmed it just prints the embeddedservice.toml, not deprecated. §5a will be removed in the consolidation pass.Option<HeroRequestContext>stays as the trait-arg shape (over the always-defaulted alternative).hero_rpc/crates/hero_rpc2/, no fork relationship, no upstream PR. We treat it as ours from that point.X-Hero-Contextheader — period.Cleanup needed in this repo
Grep turned up legacy socket-per-context surface that should go:
crates/osis/src/rpc/unix_server.rs:32Binds one socket per context.crates/server/src/server/unified_server.rs:58Per-context dispatch functions (for service method fallback).crates/server/README.mdAction: delete the legacy
unix_servercode path (and its docs) entirely once the hero_rpc2-backed server lands. README references go too. No "legacy mode" / "socket-per-domain" framing — just the one single-socket model.I'll roll this into the §5a removal during the consolidation pass on the body once the remaining open items settle. Sweep across other lhumina_code repos for the same wording is a follow-up — agent can do it standalone.
Still open (carried forward)
_admincrate scaffold output shape (mostly settled — Askama, framework consumption pattern).Parent / context tracker: hero_skills#262 — read it before starting work on this issue. Locked decisions, reference materials, and execution order live there. Iterate via comments here; consolidation passes on the body only after feedback settles.
hero_rpc scaffold) #54State refresh + action correction
Pulled latest
development. Several relevant deltas since I drafted this:crates/osis/src/rpc/server.rswas reduced by 755 lines in recent commits — legacy socket-per-context surface is partly already gone.unix_server.rsstill exists incrates/osis/src/rpc/; verify what role it plays now before deleting.crates/service/is being actively modified (recent commits touchedhero_server.rs,lifecycle.rs,service.rs,lib.rs,cli.rs, plus a newbin/andtest.rs). So the earlier decision to delete the crate (comment 33659) is wrong — code is still landing there.hero_service, rename this crate to free the name. So the action becomes a rename, not a delete:Corrected action for §4 ("Reconcile dual lifecycle paths")
Deletehero_rpc/crates/service/hero_rpc/crates/service/→hero_rpc/crates/hero_lifecycle/and update the packagename = "hero_service"→name = "hero_lifecycle". Update all[workspace.dependencies]references in this repo + every downstream consumer (grephero_service =acrosslhumina_coderepos).crates/service/suggests this crate is the path forward, not a dead end. Generatedmain.rsshould still useservice_base!()+validate_service_toml+handle_info_flagfromherolib_core::base(perhero_proc_serverreference), and call into the renamedhero_lifecycleonly for the hero_proc registration glue.Other §4–§5a status
--info): resolved — not deprecated. Comment 33681 confirmed it just prints the embedded TOML. Will drop §5a in the body consolidation pass.service.tomlsource-of-truth flip): still pending implementation, not yet in dev._admincrate scaffold): not yet — scaffolder still emits_ui. Tracked in #54.Body consolidation pass to happen once these corrections settle.
generator/src/build/build.rs#56example/recipe_serverto end-to-end demo of new pattern #57hero_servicetemplate repo (toy domain: managing Hero services) #261generator/src/build/build.rs#56crate::generate::Generatorper-target emission into modules #59§4 rename — landed on
issue-55-codegen-alignmentaad9f81—crates/service/→crates/hero_lifecycle/, packagehero_service→hero_lifecycle. Workspacecargo checkclean.In-repo touches: workspace
Cargo.toml, the renamed crate's own sources (Cargo.toml + lib/hero_server/service/test doc-comments,src/bin/main.rsbinary name + clap config,examples/test_server.rs),crates/server/(Cargo.toml + lib.rs re-export + cli/server/spawn use-sites + README), and the generator emitters that handhero_servicedown to scaffolded/generated code (emit/bin.rs,scaffold.rs).No behavioural change. The
Cargo.toml.hero_builder_backupfiles (legacy build_lib leftovers) were left untouched.Downstream consumer bumps next (per q3a in the thread): walking through
hero_osis,hero_inspector,hero_proxy,hero_fossil,hero_archipelagos(and grep for any I missed) — one commit per repo on a matching branch.Then §1 (
OschemaBuildConfig::from_service_toml()), §5+§6 (generatedmain.rsboilerplate matchinghero_proc_server+ naming-suffix enforcement), §3 (_adminscaffold), and §2 (hero_rpc2vendor + hybrid SDK — likely splits into its own PR given size).§4 — downstream sweep done (7 repos)
Branch
issue-55-hero-lifecycle-renamepushed on each affected repo; workspace-roothero_lifecycledep is temporarily pinned tobranch = "issue-55-codegen-alignment"of hero_rpc. After the hero_rpc PR squash-merges, a one-line follow-up per repo flips the pin back tobranch = "development".hero_proxy66e55675Cargo.tomlhero_osis13add9c2hero_osis_admin/src/main.rshero_index_ui_oldbca62d30src/main.rshero_computebe0c2b37Cargo.toml—cargo check --workspaceclean against issue branchhero_osf914378d+0467ab63hero_os_server/src/main.rs; second commit reverts an over-eager string-literal rewrite inisland_content.rswhere"hero_service"is a Dioxus island ID matched against thehero_archipelagos_hero_servicecrate, not our renamed dephero_router842eec55Cargo.tomlhero_voice7d4fed85hero_voice/src/lifecycle.rsSkipped (upstream redirects revealed stale local clones)
hero_inspectorhero_routerhero_fossilhero_foundryhero_authhero_auth_archivehero_indexer_uihero_index_ui_old_oldclone we processedhero_foundrycrates/hero_foundry_server/Cargo.tomlno longer has ahero_servicedep on latest dev — already migrated in commite6d17e3(D-10 sweep). No-op.Side branches archived
Three repos had uncommitted local changes; archived to
development_wipon the respective remotes before sweeping:hero_os,hero_voice,hero_foundry.Follow-up after merge
One-liner per repo:
perl -pi -e 's|branch = "issue-55-codegen-alignment"|branch = "development"|' Cargo.toml, commit, push. I'll bundle into a small "flip pins" PR once §1/§5/§6/§3 ship and the hero_rpc PR is approved.Next
→ §1
OschemaBuildConfig::from_service_toml()constructor (additive; reducesrecipe_server/build.rsfrom 41 lines to ≤5).§1 landed —
6174a00service.tomlis now codegen's single source of truth. Two new entry points:Both call
herolib_core::base::validate_service_toml(so a malformed file fails at build time with a clear panic) and emitcargo:rerun-if-changed=service.toml. ParsedServiceTomlis stored onOschemaBuildConfig::service_tomlso future emitters (§3_adminscaffold, §5 generatedmain.rs) can read service name / version / binaries without re-parsing.Modern defaults applied automatically when constructed via
from_service_toml:schemas_dir = "schemas"nested_layout = truetarget = GenerationTarget::ServerCaller chains further builder methods to override.
Generator now owns rustfmt
Dropped the hand-rolled
format_generated_sources()helper that every service had to copy into itsbuild.rs.OschemaBuilder::generate()now runsrustfmt --edition 2024oversrc/,sdk/, and any configured client/server crate dirs after emission. Best-effort: missing rustfmt is silently skipped. Newfs::rustfmt_dir(dir, debug)+fs::collect_rs_fileshelpers handle the walk.recipe_server/build.rs— 41 lines → 5Before:
After:
Paired with a new
example/recipe_server/service.toml(contributor-owned, codegen never writes it).cargo check --workspace✅cargo fmt --check✅Next
→ §5 + §6 — update the generated
main.rstemplate inemit/bin.rsto matchhero_proc_server/src/main.rs(service_base!(),validate_service_toml,handle_info_flag,print_startup_banner,prepare_sockets— in that order), dropHeroLifecycle::new(...), and enforce the_server/_admin/_sdk/_web/_appnaming suffixes in the scaffolder.§5 + §6 landed —
36eaf2f§6 — naming
Scaffolded crates now follow the canonical
_server/_admin/_sdksuffixes perhero_service_check_fix.md._uiand_clientare gone in the scaffolder; the API renamed accordingly:crates/<name>_ui→crates/<name>_admin(workspace member, dir layout, package name, buildenv.sh, helper fns:generate_admin_crate,generate_admin_main_rs)crates/<name>_client→crates/<name>_sdk(workspace member, dir layout, package name,OschemaBuildConfig::client_crate_dirtarget, helpergenerate_sdk_crate)WorkspaceScaffolder::with_ui()/without_ui()→with_admin()/without_admin(); deprecatedwith_http()/without_http()shims dropped--no-adminis the new flag;--no-uikept as a back-compat aliasGrep across
lhumina_codeconfirms no external call sites of the renamed builder methods.§5 — main.rs boilerplate
Scaffolded
_serverand_adminmain.rsnow follow the spec exactly:Banner + sockets are inside the
OServer::run_clicallback so they fire only in foreground mode (skipped on--start/--stopdispatch).HeroLifecycleimport flipped fromhero_rpc_server::{OServer, HeroLifecycle}to the canonicalhero_lifecycle::HeroLifecycle(§4 rename).Per-crate
service.tomlwritesservice_base!()expands toinclude_str!("../service.toml"), so every binary crate needs its ownservice.tomlat the crate root. Newwrite_binary_service_tomlscaffolder helper emits one per binary crate (server + admin), write-only-if-missing so it never clobbers contributor edits (per §1: scaffolder + contributor ownservice.toml, codegen never writes it).Tests
6 new assertions in
test_scaffold_server_main_*pin the §5 boilerplate; 2 new intest_scaffold_admin_main_uses_hero_ui_server. All 8 scaffold tests + the full 105-test generator suite pass.Deliberate scope gap (filing as follow-up)
The per-domain bin emitter (
emit/bin.rs::generate_per_domain_bins) and the single-bin orchestrator (generate_single_bin) still emitHeroLifecycle::new(...)withoutservice_base!(). Those bins live atsrc/bin/<name>.rsinside an existing crate, soinclude_str!("../service.toml")resolves tosrc/service.toml— wrong. Two ways to fix:service_base_at_path!()macro that accepts an explicit path._server/_admin/_sdk).Neither feels in-scope for this PR — flagging now so it can be tracked separately.
Next
→ §3 — generate the
_admincrate scaffold usinghero_website_lib/hero_admin_libdefault screens (replaces the placeholderHeroUiServer+ axum router ingenerate_admin_main_rswith the framework-driven version).§3 landed —
f3bce13Scaffolded
_admincrate now consumeshero_admin_lib(fromhero_website_framework) for the standard admin surface — per the parent tracker's correction of §3 ("Build new admin features on hero_admin_lib, not from scratch").What the generated
_adminbinary looks like nowIndex stays a placeholder for the contributor to extend. The framework provides everything underneath: standard routes, hero_router header lifting, socket lifecycle (create dir + remove stale +
0o770perms + bind), and embedded Bootstrap / Unpoly / highlight.js / marked / Chart.js / the hero web components (<hero-connection-status>,<hero-api-docs>,<hero-logs-viewer>, …) viahero_admin_lib's rust-embed asset bundle.Cargo.toml diff
hero_lifecycledep (HeroUiServer no longer used here)tower-http(CORS isn't needed for hero_router-fronted admins)hero_admin_lib = { git = "…hero_website_framework.git", branch = "development" }0.7→0.8(matches hero_admin_lib){macros, rt-multi-thread, signal}featuresTests
test_scaffold_admin_main_uses_hero_admin_lib(renamed from…_uses_hero_ui_server) asserts the new imports, the socket path, the standard route helpers, thebase_path_middlewarewiring, and explicitly thatHeroUiServeris gone. 8/8 scaffold tests + the full 105-test generator suite pass.cargo check --workspace✅cargo fmt --check✅What's left
→ §2 —
hero_rpc2vendor + hybrid SDK + Python target +HeroRequestContextheader-lift. By far the largest piece, with an external dep copy (delandtj/hero_rpc2) + new codegen target + extension work in the vendored crate. Per my opener (q1), this will be its own PR; I'll start by vendoring the upstream as-is and post a separate plan-of-attack comment before the SDK-codegen work proper.§2 progress — 3 of 5 parts landed on the same branch
Keeping §2 on
issue-55-codegen-alignmentafter all (yourcontinueopener). Three commits in:e2f4d27crates/hero_rpc2/— copy-over fromdelandtj/hero_rpc2, workspace member, shared deps via[workspace.dependencies],Cargo.lockdropped,VENDOR.mdtraces what was kept / what changes are planned in-place479a558crate::context::{HeroRequestContext, current, with_context},tokio::task_local!REQUEST_CONTEXT,ServerBuilder::with_lifted_headers([...])+lifted_headers()getter, prelude re-exports. 4 lib tests pin behaviourc16ddc0serve_http+dispatchthreadArc<Vec<String>>lift list through; newbuild_context(&HeaderMap, &[String])materialisesX-Hero-Context+X-Hero-Claimsinto typed fields and any other configured header intoextras; dispatch wrapsdispatch_jsoninwith_context(...)so handlers can read viacurrent_context(). Line transport is unaffectedNew test file
tests/http_context_lift.rs(3 tests, all green) covers: (a) bare request → default ctx in scope; (b) typed headers always lifted even without config; (c) configured extras flow throughextrasmap while typed wins on overlap.All 22+ vendored + new tests pass.
cargo check --workspace✅.What's left in §2
#[rpc(server, client)]traits. Replace the existing hand-typed client inemit/rust_sdk.rs(363 LOC) with a hero_rpc2-trait emitter. For each domain method on a rootobject, the emitted trait hasctx: Option<HeroRequestContext>as the first arg per the locked design. Generated traits live in the_sdkcrate; the server impl stub stays in the server crate as a preserved file. This is the substantial piece.I'll keep pushing on part 4 next. If the codegen design ends up needing your input on trait shape (e.g. when methods return SSE streams vs unary, or how Subscription methods map), I'll pause and post here before going further.
§2 — all five parts on the branch (parts 4 & 5 scaffolded)
Following up the earlier §2 progress comment. Two more commits in:
c55a74aemit/rust_rpc2.rs+OschemaBuildConfig::with_hero_rpc2_sdk()+ builder dispatch. Per-domain<sdk>/src/<domain>.rscontaining#[rpc(server, client)] pub trait <Pascal>+compile_error!opt-in marker. Auto-indexed via emittedlib.rs(preserved when hand-written). 3 unit tests.df7f187emit/python_sdk.rs+OschemaBuildConfig::with_python_sdk()+ builder dispatch. Per-domain<sdk>/python/hero_<svc>_sdk/<domain>.pycontaining a<Pascal>Clientskeleton +# TODOmarker.__init__.pyre-export + minimal PEP 621pyproject.toml(hatchling, Python ≥3.10, httpx). 3 unit tests.Why scaffolds, not finished translators
Both part 4 and part 5 carry the codegen rails (file emission, config flag, builder dispatch, lib.rs/init.py indexing, test coverage of the wiring) but stop short of OSchema-method → output-language translation. That translation is the substantial piece in each case:
crate::generate::Generator+crate::rust::rust_structto turn OSchemaRpcMethodparams and return types intoRpcResult<T>signatures withctx: Option<HeroRequestContext>as the first arg.@dataclass+ Python type-hint translator (SmartId → str, optional →Optional[...], closed enums →StrEnum/Literal[...]), plus async client emission.The
compile_error!(Rust) and# TODOmarkers (Python) in the emitted scaffolds make those gaps explicit — consumers opting in get a clear signal to wait for the follow-up commits rather than silently shipping a half feature. Both follow-ups are bounded; each is roughly the size of anemit/rust_sdk.rsrewrite and would benefit from being its own focused commit.Whole-branch summary now
7 commits on
issue-55-codegen-alignment:aad9f81crates/service/→crates/hero_lifecycle/rename + 7 downstream PRs (see earlier comment)6174a00OschemaBuildConfig::from_service_toml()+recipe_server/build.rscollapsed 41→5 lines + generator owns rustfmt36eaf2fmain.rsmatcheshero_proc_server(service_base + validate + handle_info + banner + sockets),_ui→_admin,_client→_sdk, per-crateservice.tomlwritesf3bce13_adminconsumeshero_admin_libinstead ofHeroUiServere2f4d27crates/hero_rpc2/vendor fromdelandtj/hero_rpc2479a558HeroRequestContexttypes +ServerBuilder::with_lifted_headers+ prelude exportsc16ddc0c55a74adf7f187111 generator tests + 22 hero_rpc2 tests + 8 scaffold tests = 141 unit/integration tests on the branch pass.
cargo check --workspaceandcargo fmt --checkboth clean.Ready-for-PR
Branch is in a coherent shape for review now — each commit is independently meaningful. The two outstanding §2 method-translators are a clean follow-up: same codegen rails, just filled in. Happy to keep pushing on them next, or pause for review here — your call.
hero_rpc scaffold) #54