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.
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
BotServer and non-HTTP interfaces.
- Redesigning proto contracts or editing generated files.
- Rewriting existing business logic unless explicitly requested.
Required Reading
Read before generation:
- references/service-implementation-best-practices.md
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.
- Server-streaming methods:
9) Server-Streaming SSE Template.
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
Service struct per proto module.
- Keep one Go file per proto service.
- File naming:
XxxService -> xxx.go (snake_case, remove Service suffix).
- Every service file must include an interface assertion:
var _ <pkg>.<ServiceName>HTTPServer = (*Service)(nil)
Workflow
Step 1: Discover Interface
- Find all
type XxxServiceHTTPServer interface in api/<module>/v1/*.sphere.pb.go.
- List all method signatures from each interface.
Step 2: Check Existing Files
- Check if
internal/service/<module>/xxx.go exists.
- If exists, list implemented methods.
- If missing, mark for creation.
Step 3: Decide Implementation Strategy
| Scenario |
Strategy |
Signature ends with send func(*Reply) error) error |
Server-streaming producer; honor cancellation and send errors |
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
- Server stream first: A
send func(*Reply) error signature always uses the streaming template, even when the method name starts with List or another CRUD verb.
- Simple CRUD: Method name matches
Create*, Get*, List*, Update*, Delete* + single entity = direct Ent.
- Stub: Logic unclear =
return nil, errors.New("not implemented: <Method>"); streaming stubs return only the error.
- 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.
- Never retain or use
httpx.Context in a streaming producer. The generated interface supplies a standard context.Context, request, and send callback.
Output Contract
Output in this exact order:
Scaffold Plan
Files To Create/Update
Interface Coverage Check
Stub Methods Added
Usecase Split Decision
Validation Result
Minimal Validation Checklist
go test ./internal/service/...
go test ./cmd/app/...
- If constructor or provider signatures changed, run
make gen/wire and 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.db with render helpers.
- Complex-flow case: usecase split plus DI chain updates remain compilable.
- Server-streaming case: signature matches the generated interface, every send error is handled, and the producer observes context cancellation.
1---2name: proto-service-generator3description: Generate or complete unary and server-streaming Go service implementations from protobuf-generated HTTP interfaces in go-sphere scaffold projects. Use when creating internal service files, adding missing method implementations, or generating compilable stubs for new proto endpoints. Trigger for: service implementation, proto handler, SSE producer, append-only update, interface assertion, CRUD via Ent, stub method generation.4---56# Proto Service Generator78Generate or complete compilable service implementations under `internal/service/<module>/` from generated `*ServiceHTTPServer` interfaces in `api/<module>/v1/*.sphere.pb.go`.910<HARD-GATE>11Do not generate or modify any service file until:121. The target module is known (e.g., `task`, `user`, `order`)132. The generated `*ServiceHTTPServer` interface exists in `api/<module>/v1/*.sphere.pb.go`1415If the module name is not specified, ask: "Which module should I generate service files for?"16If the proto generation has not been run yet, stop and ask the user to run `make gen/proto` first.17Do not guess the module from context alone if there are multiple candidates.18</HARD-GATE>1920## When To Use21221. Proto and generated API files already exist.232. You need missing service files or method implementations for `*ServiceHTTPServer`.243. You need safe append-only completion for existing service files.2526## Out of Scope27281. `BotServer` and non-HTTP interfaces.292. Redesigning proto contracts or editing generated files.303. Rewriting existing business logic unless explicitly requested.3132## Required Reading3334Read before generation:351. [references/service-implementation-best-practices.md](references/service-implementation-best-practices.md)3637Load sections selectively:381. Always: `1) Interface Assertion and File Mapping`, `4) Append-Only Update Procedure`, `7) Import and Naming Checklist`.392. Simple CRUD: `3) Simple CRUD (Direct Ent) Template`.403. Unknown logic: `2) Stub Template for Unknown Logic`.414. Complex orchestration and DI changes: `5) Complex Logic Split to Usecase`, `6) Wire Injection Pattern`.425. Reuse checks: `8) Sphere Feature Reuse Pattern`.436. Server-streaming methods: `9) Server-Streaming SSE Template`.4445## Companion Skill Policy4647When `sphere-feature-workflow` is available in the current session, use it together with this skill.4849Division of responsibility:501. `sphere-feature-workflow`: framework-native end-to-end integration (routing, middleware, auth, errors, wiring flow).512. `proto-service-generator`: per-service file generation and completion from `*ServiceHTTPServer`.5253If `sphere-feature-workflow` is unavailable, continue with this skill and enforce reuse-first checks from the reference.5455## Repository Conventions56571. Keep one `Service` struct per proto module.582. Keep one Go file per proto service.593. File naming: `XxxService -> xxx.go` (snake_case, remove `Service` suffix).604. Every service file must include an interface assertion:61`var _ <pkg>.<ServiceName>HTTPServer = (*Service)(nil)`6263## Workflow6465### Step 1: Discover Interface661. Find all `type XxxServiceHTTPServer interface` in `api/<module>/v1/*.sphere.pb.go`.672. List all method signatures from each interface.6869### Step 2: Check Existing Files701. Check if `internal/service/<module>/xxx.go` exists.712. If exists, list implemented methods.723. If missing, mark for creation.7374### Step 3: Decide Implementation Strategy7576| Scenario | Strategy |77|----------|----------|78| Signature ends with `send func(*Reply) error) error` | Server-streaming producer; honor cancellation and send errors |79| Method is `Create*`, `Get*`, `List*`, `Update*`, `Delete*` on single entity | Simple CRUD via direct Ent |80| Logic cannot be inferred | Compilable stub with `errors.New("not implemented")` |81| Cross-entity transactions or complex orchestration | Split to usecase + wire DI |8283### Step 4: Implement (Append-Only)841. Create file if missing with assertion + all methods.852. If existing, append only missing methods.863. Add only required imports.874. Keep existing implementations untouched.8889### Step 5: Validate901. Run `go build ./internal/service/...`912. Report using Output Contract.9293## Decision Rules94951. **Server stream first**: A `send func(*Reply) error` signature always uses the streaming template, even when the method name starts with `List` or another CRUD verb.962. **Simple CRUD**: Method name matches `Create*`, `Get*`, `List*`, `Update*`, `Delete*` + single entity = direct Ent.973. **Stub**: Logic unclear = `return nil, errors.New("not implemented: <Method>")`; streaming stubs return only the error.984. **Usecase**: Cross-entity, reusable orchestration, or long flows = split to `internal/usecase/`.99100## Hard Rules1011021. Do not modify generated files under `api/*`.1032. Do not add a new DAO wrapper for simple CRUD.1043. Do not delete or rewrite existing assertions or method bodies in target service files.1054. Add only required imports.1065. Keep dependency injection compilable when constructor signatures change.1076. Never retain or use `httpx.Context` in a streaming producer. The generated interface supplies a standard `context.Context`, request, and send callback.108109## Output Contract110111Output in this exact order:1121. `Scaffold Plan`1132. `Files To Create/Update`1143. `Interface Coverage Check`1154. `Stub Methods Added`1165. `Usecase Split Decision`1176. `Validation Result`118119## Minimal Validation Checklist1201211. `go test ./internal/service/...`1222. `go test ./cmd/app/...`1233. If constructor or provider signatures changed, run `make gen/wire` and rerun tests.124125## Acceptance Checklist1261271. New-file case: file exists, assertion exists, all interface methods exist, and code compiles.1282. Existing-file case: only missing methods are appended; existing implementations are unchanged.1293. Simple CRUD case: direct Ent via `s.db` with render helpers.1304. Complex-flow case: usecase split plus DI chain updates remain compilable.1315. Server-streaming case: signature matches the generated interface, every send error is handled, and the producer observes context cancellation.