Proto Service Generator
Generate or complete compilable service implementations under internal/service/<module>/ from generated *ServiceHTTPServer interfaces in api/<module>/v1/*.sphere.pb.go.
If the module name is not specified, ask: "Which module should I generate service files for?"
If the proto generation has not been run yet, stop and ask the user to run make gen/proto first.
Do not guess the module from context alone if there are multiple candidates.
</HARD-GATE>
When To Use
- Proto and generated API files already exist.
- You need missing service files or method implementations for
*ServiceHTTPServer. - You need safe append-only completion for existing service files.
Out of Scope
BotServerand non-HTTP interfaces.- Redesigning proto contracts or editing generated files.
- Rewriting existing business logic unless explicitly requested.
Required Reading
Read before generation:
Load sections selectively:
- Always:
1) Interface Assertion and File Mapping,4) Append-Only Update Procedure,7) Import and Naming Checklist. - Simple CRUD:
3) Simple CRUD (Direct Ent) Template. - Unknown logic:
2) Stub Template for Unknown Logic. - Complex orchestration and DI changes:
5) Complex Logic Split to Usecase,6) Wire Injection Pattern. - Reuse checks:
8) Sphere Feature Reuse Pattern.
Companion Skill Policy
When sphere-feature-workflow is available in the current session, use it together with this skill.
Division of responsibility:
sphere-feature-workflow: framework-native end-to-end integration (routing, middleware, auth, errors, wiring flow).proto-service-generator: per-service file generation and completion from*ServiceHTTPServer.
If sphere-feature-workflow is unavailable, continue with this skill and enforce reuse-first checks from the reference.
Repository Conventions
- Keep one
Servicestruct per proto module. - Keep one Go file per proto service.
- File naming:
XxxService -> xxx.go(snake_case, removeServicesuffix). - Every service file must include an interface assertion:
var _ <pkg>.<ServiceName>HTTPServer = (*Service)(nil)
Workflow
Step 1: Discover Interface
- Find all
type XxxServiceHTTPServer interfaceinapi/<module>/v1/*.sphere.pb.go. - List all method signatures from each interface.
Step 2: Check Existing Files
- Check if
internal/service/<module>/xxx.goexists. - If exists, list implemented methods.
- If missing, mark for creation.
Step 3: Decide Implementation Strategy
| Scenario | Strategy |
|---|---|
Method is Create*, Get*, List*, Update*, Delete* on single entity | Simple CRUD via direct Ent |
| Logic cannot be inferred | Compilable stub with errors.New("not implemented") |
| Cross-entity transactions or complex orchestration | Split to usecase + wire DI |
Step 4: Implement (Append-Only)
- Create file if missing with assertion + all methods.
- If existing, append only missing methods.
- Add only required imports.
- Keep existing implementations untouched.
Step 5: Validate
- Run
go build ./internal/service/... - Report using Output Contract.
Decision Rules
- Simple CRUD: Method name matches
Create*,Get*,List*,Update*,Delete*+ single entity = direct Ent. - Stub: Logic unclear =
return nil, errors.New("not implemented: <Method>") - Usecase: Cross-entity, reusable orchestration, or long flows = split to
internal/usecase/.
Hard Rules
- Do not modify generated files under
api/*. - Do not add a new DAO wrapper for simple CRUD.
- Do not delete or rewrite existing assertions or method bodies in target service files.
- Add only required imports.
- Keep dependency injection compilable when constructor signatures change.
Output Contract
Output in this exact order:
Scaffold PlanFiles To Create/UpdateInterface Coverage CheckStub Methods AddedUsecase Split DecisionValidation Result
Minimal Validation Checklist
go test ./internal/service/...go test ./cmd/app/...- If constructor or provider signatures changed, run
make gen/wireand rerun tests.
Acceptance Checklist
- New-file case: file exists, assertion exists, all interface methods exist, and code compiles.
- Existing-file case: only missing methods are appended; existing implementations are unchanged.
- Simple CRUD case: direct Ent via
s.dbwith render helpers. - Complex-flow case: usecase split plus DI chain updates remain compilable.