Stop regenerating herolib_core::base ServiceToml types per-service #72
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#72
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?
Problem
crates/<name>/src/<domain>/types_generated.rsincludes generated Rust types forKind,Category,Protocol,SockType,Binary,Socket,ServiceMeta, etc. — i.e. the ServiceToml schema that already lives inherolib_core::base.Example:
hero_service/crates/hero_service/src/catalog/types_generated.rs.This is duplicated work + a maintenance trap: the canonical types live in
herolib_coreandlabparsesservice.tomlagainst those types directly. No service code should ever need re-emitted copies.Why is it happening?
Likely the scaffolder's seed schema (
services.oschema) for thehero_servicetoy domain mirrors the ServiceToml shape, so the generator dutifully emits Rust types for it. Two fixes apply:hero_servicetemplate'sservices.oschemashould not redeclare types that already exist inherolib_core::base. It should reference / import them.What to do
herolib_core::base" so the generator emits an import, not a redefinition.hero_service'sservices.oschemato use it for the ServiceToml types.hero_servicerebuilds with the canonical types in scope and zero duplicate definitions.Acceptance
hero_service/crates/hero_service/src/.../types_generated.rsno longer containsKind/Category/Protocol/SockType/Binary/Socket/ServiceMetaredefinitions.herolib_core::baseinstead.Design proposal — OSchema external types
Picking up #72. Before coding, I'd like to lock the OSchema syntax for declaring "this type lives in an external Rust crate, don't redefine it." Posting here for sign-off.
Context — what the failure case actually looks like
The issue points at
hero_service. The on-disk file iscrates/hero_service/schemas/catalog/catalog.oschema(notservices.oschema—services.oschemagot renamed tocatalog.oschemaafter the refactor that introducedServiceDefinition).Today that file redeclares what
herolib_core::basealready owns:herolib_core::base)BinaryKindKindSocketKindSockTypeSocketProtocolProtocolServiceCategoryCategorySocketDefSocketBinaryDefBinaryThe closed-set enums even drift (e.g.
BinaryKindhasApp,Kinddoesn't;ServiceCategoryistool/framework/infrastructure/examplevsCategory'score/storage/ai/network/ui/tool). That drift is exactly the maintenance trap #72 calls out.Proposed syntax —
usestatementsI propose a top-level
usestatement that mirrors Rust'suseexactly. It's familiar, unambiguous, and trivially translates to the Rust generator's output:Single-import form (for the one-type case) also accepted:
Why
useand not an attribute on the existing redefinition?I considered an alternative — keep the redeclaration but tag it
@external("herolib_core::base::Binary"):I'm proposing against it because the redeclaration is the bug — the whole point of #72 is that the local shape is a copy that can drift. Letting authors keep writing a shape next to an
@externalannotation invites that drift back in.usemakes the name visible without ever writing a shape, which is exactly what we want.Semantics — what the model + generators do
Parser / model:
use <crate>::<path>::{Ident, Ident, ...}oruse <crate>::<path>::Ident.Schemaas aVec<ExternalImport>(each carries the crate path + imported names).TypeExprKind::Named(name)— references compile through with no local definition required.Xis both imported and defined locally").Rust generator (
types_generated.rs):use crate::path::{A, B}→ emituse crate::path::{A, B};at the top of the file.schema.definitions— imports are not in there, so imported names are never redefined.Rust WASM generator (
types_wasm_generated.rs):herolib_coremay not be wasm-friendly. Two reasonable choices:useand let cargo sort it out (simpler — if the external crate isn't wasm-compatible, the user finds out at compile time, which is honest).use crate::path::{A, B} for wasm = "..."— adds syntax for an edge case nobody's hit yet.OpenRPC generator:
{ "$ref": "#/components/schemas/Name" }references like any other named type.Nameis emitted as{ "type": "object", "description": "External type from <crate path>" }— opaque, but valid JSON Schema. Generators of typed clients (TS, Python) get a black-box type they can pass through. If we ever need a richer description, the external crate can ship its own JSON Schema alongside.Rhai / JS / Python generators:
Binarywill get one from the upstream crate.Acceptance, restated against this design
After the change,
hero_service/crates/hero_service/src/catalog/types_generated.rswill:use herolib_core::base::{Kind, Category, Protocol, SockType, Binary, Socket, ServiceMeta, ServiceToml};near the top.pub enum Kind,pub struct Binary, etc.ServiceDefinition(the one typehero_servicelegitimately owns).cargo build -p hero_serviceclean — no duplicates, references resolve through the import.Open questions for sign-off
usekeyword OK? It collides with nothing in OSchema today (useis not a reserved identifier). If you'd rather a less Rust-flavored word (import,extern), say so — easy to change.herolib_core::basevs renamingKind→BinaryKind—Kindis a generic name; importing it bare pollutes the catalog file's namespace. Should I supportuse ... asaliasing (use herolib_core::base::Kind as BinaryKind)? My instinct: yes, mirror Rust, but only implement if you confirm — otherwise I just import as-is.ServiceCategoryandBinaryKindenums with different variants (the drift mentioned above)? Or do we want the catalog to be a strict mirror ofServiceTomland drop the catalog-specific variants? The issue body implies the latter — please confirm before I delete those local enums.Will hold off on implementation until I see a thumbs-up (or counter-proposal) on the syntax + the answer to Q3.
sid/created_at/updated_at— generator already auto-injects them #275ServiceDefinitionto name + description + interfaces #1Follow-up — corrections + reframed scope
You're right; my first comment got two things wrong:
ServiceDefinitionshould not declaresid/created_at/updated_at. Those are auto-injected for any[rootobject]and silently swallowed if declared (crates/generator/src/rust/rust_struct.rs:368-389). Theoschemaskill inhero_skillsactively tells authors to declare them, which is wrong — filed as lhumina_code/hero_skills#275.ServiceDefinitionitself is over-modelled — the catalog should be a thin name + description + interfaces record, not a parallelServiceToml. The on-diskservice.tomlis already the source of truth forbinaries/sockets/category/ etc.; the catalog just needs enough to locate a service. Filed as lhumina_code/hero_service#1.\n\nOnce hero_service#1 lands, this issue's headline symptom (Kind/Category/Protocol/SockType/Binary/Socket/ServiceMetaredefinitions intypes_generated.rs) goes away on its own — nouse-import language feature needed for the immediate fix.What's left of #72
The OSchema
use-import feature still has merit as a generic language addition: future schemas that legitimately need to reference canonical types (e.g. alabplugin schema that takesServiceTomlas a method parameter) shouldn't be forced to redeclare them either. But it's no longer the path to closing this issue's acceptance — it's a separate enhancement.Proposed: keep #72 open as the umbrella for "no service ever redeclares
herolib_core::basetypes," link it tohero_service#1for the immediate hero_service fix, and decide separately whether to land theuse-import language feature now or defer until there's a second consumer that actually needs it.Will hold off on any code in this branch until you confirm whether to:
use-import design entirely.use-import language feature here inhero_rpcafter hero_service#1 lands.use-import first, then collapse hero_service catalog as the dogfooding consumer.Worktree at
/tmp/hero_rpc_72on branchissue-72-oschema-external-typesis still parked with no commits.Going with (a). The real fix lives in
hero_service— collapse the catalog soServiceTomlfshape isn't mirrored at all, and elevatehero_serviceinto a meta-service that bootstraps / refactors / checks / verifies other hero services (usinghero_rpcfor codegen,hero_skillsfor guidance, AI where needed).Tracking that there: lhumina_code/hero_service#1 (expanded scope, comment to follow on that issue). Closing this as superseded; the
use-import OSchema language feature is parked unless a second consumer needs it.ServiceDefinitionto name + description + interfaces #1ServiceDefinitionto name + description + interfaces #1sid-field requirement on root objects (#85) #88