.agents/skills/review-helpers/SKILL.md
Assume the @maintainer persona. Scope: finders, status, waiters, sweepers, data sources, list resources. Loaded from review-pr.
find<Resource>ByID(ctx context.Context, conn *<svc>.Client, id string) (*awstypes.<Type>, error). Variants by ARN/Name use the same shape.*awstypes.ResourceNotFoundException, return smarterr.NewError(&retry.NotFoundError{LastError: err}).retry.StateRefreshFunc. Design status so one function powers create, update, and delete waiters.retry.StateChangeConf. Created/updated waiters typically set NotFoundChecks: 20 and ContinuousTargetOccurence: 2. Deleted waiters use empty Target with Pending covering deletion-in-progress states.awstypes.StatusInProgress) over package-level string consts.ResName<Name> constants referenced in tests must be re-exported via exports_test.go.Flag finders that return raw errors (must wrap with smarterr.NewError), status that duplicates finder logic, or hand-rolled polling loops in place of retry.StateChangeConf.
Each new resource needs a sweeper. Iterate the SDK paginator, build via framework.NewSweepResource(new<Resource>Resource, client, framework.NewAttribute(names.AttrID, aws.ToString(v.<Thing>Id))) (where framework is internal/sweep/framework), and register in the package's sweep.go with awsv2.Register("aws_<svc>_<thing>", sweep<Resource>s, ...optionalDeps). Pass multiple framework.NewAttribute(...) arguments for composite identity.
Flag new resources without a sweeper, sweepers that don't propagate paginator errors via smarterr.NewError, and sweepers using import aliases other than framework for internal/sweep/framework.
Data sources have only a Read method.
framework.DataSourceWithModel[T].Required or Optional for search criteria; everything else is Computed.Required on the corresponding resource are typically Computed on the data source unless they form lookup criteria.tags attribute (no tags_all).Framework path embeds the corresponding underlying resource. SDKv2 path uses framework.ListResourceWithSDKv2Resource.
The List method:
tflog.SetField(ctx, logging.ResourceAttributeKey(...), ...).result.DisplayName to a human-readable identifier (typically the resource name).The listing helper uses an iterator over the SDK paginator:
func list<Thing>s(ctx context.Context, conn *<svc>.Client, input *<svc>.List<Thing>sInput) iter.Seq2[awstypes.<Thing>, error]
The flatten function shared by Read and List lives in the resource file (r.flatten for Framework, resource<Name>Flatten for SDKv2).
Flag list resources that don't set DisplayName, that re-implement flatten logic instead of sharing with Read, or that omit the tflog.SetField per-item logging hook.