155 lines
12 KiB
JSON
155 lines
12 KiB
JSON
[
|
|
{
|
|
"id": 1,
|
|
"name": "param-objects-many-deps",
|
|
"description": "Tests use of dig.In parameter objects when a constructor has many dependencies",
|
|
"prompt": "I'm wiring a Go service with uber-go/dig. I have a NewServer constructor that needs *zap.Logger, *sql.DB, *redis.Client, *Config, and *MetricsRegistry. The signature is getting unwieldy. How should I clean it up?",
|
|
"trap": "Without the skill, the model keeps the long signature or wraps args in an ad-hoc struct without dig.In, missing the parameter-object pattern that lets the container fill the fields.",
|
|
"assertions": [
|
|
{"id": "1.1", "text": "Embeds dig.In in the parameter struct"},
|
|
{"id": "1.2", "text": "Constructor takes the params struct as a single argument"},
|
|
{"id": "1.3", "text": "Does NOT just keep the long parameter list as the answer"},
|
|
{"id": "1.4", "text": "Does NOT use a plain struct without dig.In (which would not be filled by the container)"},
|
|
{"id": "1.5", "text": "Mentions readability/maintainability benefit (adding a new dep is a one-line change)"}
|
|
]
|
|
},
|
|
{
|
|
"id": 2,
|
|
"name": "value-groups-for-handlers",
|
|
"description": "Tests value groups when many constructors must contribute to one slice",
|
|
"prompt": "In my Go HTTP server wired with uber-go/dig, I have several constructors (NewUserHandler, NewPostHandler, NewHealthHandler) and a NewRouter that should consume all of them. Each handler is registered independently. How do I wire this without the router knowing which handlers exist?",
|
|
"trap": "Without the skill, the model invokes each handler individually inside main() and passes a slice to NewRouter, missing the group:\"...\" tag that decouples producers from consumers.",
|
|
"assertions": [
|
|
{"id": "2.1", "text": "Each handler constructor returns a dig.Out struct (or uses dig.Group via Provide option) tagged with group:\"routes\" (or similar group name)"},
|
|
{"id": "2.2", "text": "NewRouter consumes a dig.In with a slice field tagged group:\"routes\""},
|
|
{"id": "2.3", "text": "Handlers are added with c.Provide — no manual slice assembly in main()"},
|
|
{"id": "2.4", "text": "Does NOT manually assemble the handler slice and pass it to NewRouter"},
|
|
{"id": "2.5", "text": "Mentions that group order is not guaranteed (or is silent on it; does NOT claim a specific order is guaranteed)"}
|
|
]
|
|
},
|
|
{
|
|
"id": 3,
|
|
"name": "named-values-multiple-dbs",
|
|
"description": "Tests dig.Name for multiple instances of the same type",
|
|
"prompt": "My Go app needs two *sql.DB connections — one to the primary write database and one to a read replica. Both use the same *sql.DB type. Show me how to register and consume them with uber-go/dig.",
|
|
"trap": "Without the skill, the model wraps the two connections in different types (struct PrimaryDB / struct ReadOnlyDB) instead of using dig.Name on a single type.",
|
|
"assertions": [
|
|
{"id": "3.1", "text": "Uses dig.Name(\"...\") on c.Provide for at least one of the two databases (or uses dig.Out result tags name:\"...\")"},
|
|
{"id": "3.2", "text": "Both providers register the same *sql.DB type, distinguished by name"},
|
|
{"id": "3.3", "text": "Consumer uses dig.In with name:\"primary\" / name:\"readonly\" tags"},
|
|
{"id": "3.4", "text": "Does NOT introduce wrapper types like type PrimaryDB *sql.DB just to disambiguate"},
|
|
{"id": "3.5", "text": "Does NOT register both as plain *sql.DB without names (which dig rejects at Provide time)"}
|
|
]
|
|
},
|
|
{
|
|
"id": 4,
|
|
"name": "as-to-hide-concrete",
|
|
"description": "Tests dig.As to expose only an interface to consumers",
|
|
"prompt": "I have a *PostgresDB concrete struct in my Go code that has many internal fields and methods. I want consumers to depend only on a Database interface (Query, Exec). How do I register it with uber-go/dig so consumers can never accidentally see the concrete type?",
|
|
"trap": "Without the skill, the model registers the constructor returning Database (interface) directly, which works but loses type info; or writes a separate adapter constructor — missing dig.As that does this in one line.",
|
|
"assertions": [
|
|
{"id": "4.1", "text": "Uses dig.As(new(Database)) as a Provide option on the *PostgresDB constructor"},
|
|
{"id": "4.2", "text": "The constructor itself returns the concrete *PostgresDB"},
|
|
{"id": "4.3", "text": "Consumers ask for the Database interface, not *PostgresDB"},
|
|
{"id": "4.4", "text": "Does NOT write a separate wrapper/adapter constructor that just returns the interface"},
|
|
{"id": "4.5", "text": "Mentions or demonstrates that only the interface is exposed in the graph"}
|
|
]
|
|
},
|
|
{
|
|
"id": 5,
|
|
"name": "scopes-for-request-locals",
|
|
"description": "Tests scopes for per-request dependencies",
|
|
"prompt": "In my Go web app wired with uber-go/dig, I have global services (logger, database) and per-request data (current user, request ID). How do I keep request-scoped values from leaking across concurrent requests?",
|
|
"trap": "Without the skill, the model registers everything in the root container and uses context.Value for per-request data — missing dig.Scope which provides isolated child containers.",
|
|
"assertions": [
|
|
{"id": "5.1", "text": "Uses c.Scope(\"request\") (or root.Scope) to create a child container per request"},
|
|
{"id": "5.2", "text": "Global services (logger, database) stay registered on the root"},
|
|
{"id": "5.3", "text": "Per-request providers are registered on the request scope, not on the root"},
|
|
{"id": "5.4", "text": "Mentions that the child scope inherits root providers"},
|
|
{"id": "5.5", "text": "Does NOT register per-request providers globally where they would be shared across requests"}
|
|
]
|
|
},
|
|
{
|
|
"id": 6,
|
|
"name": "container-not-passed-around",
|
|
"description": "Tests that the container stays at the composition root",
|
|
"prompt": "I'm using uber-go/dig in my Go service. My UserHandler depends on UserService and AuditLogger. Should I inject *dig.Container into UserHandler so it can resolve its own dependencies on demand?",
|
|
"trap": "Without the skill, the model agrees to pass the container, turning it into a service-locator anti-pattern that hides dependencies and breaks testability.",
|
|
"assertions": [
|
|
{"id": "6.1", "text": "Advises against passing *dig.Container into business code"},
|
|
{"id": "6.2", "text": "States that the container should only live at the composition root (main / startup)"},
|
|
{"id": "6.3", "text": "Recommends UserHandler take typed dependencies (UserService, AuditLogger) as constructor parameters"},
|
|
{"id": "6.4", "text": "Mentions service locator anti-pattern OR explains the testability/visibility downside"},
|
|
{"id": "6.5", "text": "Does NOT show example code that injects the container into a handler"}
|
|
]
|
|
},
|
|
{
|
|
"id": 7,
|
|
"name": "graph-validation-dryrun",
|
|
"description": "Tests dig.DryRun for validating the graph in CI without running constructors",
|
|
"prompt": "I want a Go test that catches missing-provider errors and cycles in my uber-go/dig wiring without actually starting database connections, HTTP servers, or any real side effects. How do I write that test?",
|
|
"trap": "Without the skill, the model spins up a real container with real constructors, or skips validation entirely — missing dig.DryRun(true) which validates types without invocation.",
|
|
"assertions": [
|
|
{"id": "7.1", "text": "Uses dig.New(dig.DryRun(true)) to build the test container"},
|
|
{"id": "7.2", "text": "Registers the same Provides as the production binary"},
|
|
{"id": "7.3", "text": "Calls c.Invoke against the composition root (or top-level dependency) to trigger validation"},
|
|
{"id": "7.4", "text": "Asserts no error is returned"},
|
|
{"id": "7.5", "text": "Does NOT actually instantiate real services in the test"}
|
|
]
|
|
},
|
|
{
|
|
"id": 8,
|
|
"name": "decorate-not-rewrite",
|
|
"description": "Tests Decorate to wrap an existing value (e.g., logger) instead of replacing the constructor",
|
|
"prompt": "In my Go app using uber-go/dig, I want every component in the 'worker' module to receive a *zap.Logger that is named 'worker' (i.e., adds a 'logger':'worker' field). Other modules should keep the unnamed logger. What's the cleanest way?",
|
|
"trap": "Without the skill, the model rewrites NewLogger or wraps every constructor manually — missing c.Decorate which transforms the value at the scope/module boundary.",
|
|
"assertions": [
|
|
{"id": "8.1", "text": "Uses Decorate (c.Decorate or scope.Decorate) on *zap.Logger"},
|
|
{"id": "8.2", "text": "The decorator returns log.Named(\"worker\") (or equivalent)"},
|
|
{"id": "8.3", "text": "Decorate is applied at the worker scope/module, not globally"},
|
|
{"id": "8.4", "text": "Does NOT modify or duplicate the original NewLogger constructor"},
|
|
{"id": "8.5", "text": "Mentions decorator scope semantics (applies to scope and descendants only) OR places Decorate inside a scope"}
|
|
]
|
|
},
|
|
{
|
|
"id": 9,
|
|
"name": "panic-recovery-option",
|
|
"description": "Tests RecoverFromPanics container option",
|
|
"prompt": "Some third-party constructors I'm registering with uber-go/dig occasionally panic on invalid configuration. I want my Go app to convert those panics into error returns from c.Invoke instead of crashing the process. How do I configure the container?",
|
|
"trap": "Without the skill, the model wraps every constructor in defer/recover — missing dig.RecoverFromPanics() which does this at the container level.",
|
|
"assertions": [
|
|
{"id": "9.1", "text": "Uses dig.New(dig.RecoverFromPanics()) (or passes the option to dig.New)"},
|
|
{"id": "9.2", "text": "Mentions or shows that the panic surfaces as a typed dig.PanicError"},
|
|
{"id": "9.3", "text": "Does NOT recommend wrapping every constructor in defer recover() manually"},
|
|
{"id": "9.4", "text": "Uses errors.As(err, &dig.PanicError{}) or equivalent to detect the panic case"}
|
|
]
|
|
},
|
|
{
|
|
"id": 10,
|
|
"name": "groups-flatten-tag",
|
|
"description": "Tests group:\",flatten\" tag when one constructor produces multiple group entries",
|
|
"prompt": "I have a NewMigrations constructor in my Go app (using uber-go/dig) that returns a slice of Migration values. I want every Migration in this slice to be visible to consumers that consume the 'migrations' group as []Migration. How do I do this without nesting?",
|
|
"trap": "Without the skill, the model registers []Migration as a single group entry, leaving consumers with [][]Migration. The right answer is the ',flatten' tag on the group.",
|
|
"assertions": [
|
|
{"id": "10.1", "text": "Uses group:\"migrations,flatten\" tag (with the flatten suffix)"},
|
|
{"id": "10.2", "text": "Result struct has a slice field []Migration with the tag"},
|
|
{"id": "10.3", "text": "Consumer receives []Migration (flat slice), not [][]Migration"},
|
|
{"id": "10.4", "text": "Does NOT silently produce a nested-slice consumer signature"}
|
|
]
|
|
},
|
|
{
|
|
"id": 11,
|
|
"name": "fx-vs-dig-when-lifecycle",
|
|
"description": "Tests recommending fx (instead of raw dig) when the user needs lifecycle/signal handling",
|
|
"prompt": "I'm starting a new Go service with uber-go/dig. The service needs to gracefully shut down on SIGTERM, run startup migrations, and start a background worker. Should I implement signal handling and start/stop sequencing on top of dig myself?",
|
|
"trap": "Without the skill, the model writes custom signal handling code on top of raw dig — missing that uber-go/fx is built specifically for this and provides fx.Lifecycle, fx.Hook, and signal-aware Run().",
|
|
"assertions": [
|
|
{"id": "11.1", "text": "Recommends migrating to or considering uber-go/fx for the lifecycle requirements"},
|
|
{"id": "11.2", "text": "Mentions that fx is built on top of dig (so existing wiring patterns transfer)"},
|
|
{"id": "11.3", "text": "Mentions fx.Lifecycle / fx.Hook (OnStart/OnStop) for graceful boot/shutdown"},
|
|
{"id": "11.4", "text": "Mentions app.Run() handling SIGINT/SIGTERM"},
|
|
{"id": "11.5", "text": "Does NOT walk the user through writing custom signal handling on top of raw dig as the primary recommendation"}
|
|
]
|
|
}
|
|
]
|