Parent: #42 (architectural review)
Context
This issue bundles small, independent polish items from the architectural review. Each item is small enough that a separate issue would be overhead — pick any one and ship it. They are unrelated, so a single PR that fixes one is fine; do not bundle these into one mega-PR.
Checklist
pkg/template/functions.go:74 — panic on registry registration failure
The current code panics on handler.AddRegistries(...) failure. Acceptable, but a must-style helper is more idiomatic in Go and easier to grep. Replace with mustAddRegistries or similar.
pkg/cmd/template_list.go:153,157 — silent JSON unmarshal swallow
loadMetadataForListing returns nil, nil on both missing-file and malformed-JSON. Missing is fine (annotated //nolint:nilerr), but malformed metadata is a real diagnostic signal that's being dropped.
pkg/cmd/use.go:65 — load-bearing constraint hidden in a comment
The comment "go-git requires the destination to not exist; use a subdirectory" describes a constraint that will silently break if a future refactor removes the subdirectory step.
pkg/template/template.go:43 — hard-coded ignoredFiles map
{".DS_Store": true, "Thumbs.db": true} is reasonable but inflexible. Consider:
go.mod — go 1.26.1 is bleeding edge
Not a problem today, but it restricts go install github.com/specsnl/specs-cli@latest for users on older Go versions. Two options:
pkg/cmd/app.go — App mutable fields are race-prone
App.SafeMode and App.HookEnvPrefix are mutated by PersistentPreRunE (pkg/cmd/root.go:32-37). Fine for single-shot CLI invocations, but it's an awkward pattern that complicates testing (tests must reset state between cases). A typed config struct passed explicitly to commands would be cleaner.
Acceptance criteria
Each unchecked box above is a candidate task. None are blockers for the main review (#42). Consider closing this issue once half are done, and opening fresh issues for the rest if they grow in scope.
References
See the line/file references inside each section.
Parent: #42 (architectural review)
Context
This issue bundles small, independent polish items from the architectural review. Each item is small enough that a separate issue would be overhead — pick any one and ship it. They are unrelated, so a single PR that fixes one is fine; do not bundle these into one mega-PR.
Checklist
pkg/template/functions.go:74—panicon registry registration failureThe current code panics on
handler.AddRegistries(...)failure. Acceptable, but amust-style helper is more idiomatic in Go and easier to grep. Replace withmustAddRegistriesor similar.must….pkg/cmd/template_list.go:153,157— silent JSON unmarshal swallowloadMetadataForListingreturnsnil, nilon both missing-file and malformed-JSON. Missing is fine (annotated//nolint:nilerr), but malformed metadata is a real diagnostic signal that's being dropped.Debuglevel via the App logger before returningnil.pkg/cmd/use.go:65— load-bearing constraint hidden in a commentThe comment "go-git requires the destination to not exist; use a subdirectory" describes a constraint that will silently break if a future refactor removes the subdirectory step.
pkggit.CloneInto(parent, name string, opts CloneOptions) (cloneDir string, err error)that internally guarantees the destination doesn't pre-exist.runUseand any other callers to use the new helper.pkg/template/template.go:43— hard-codedignoredFilesmap{".DS_Store": true, "Thumbs.db": true}is reasonable but inflexible. Consider:.specsignorefile (gitignore-style) for per-template additions. Be careful: the existing.specsverbatimalready exists; don't duplicate semantics..specsignorewould mean "do not copy at all";.specsverbatimmeans "copy but don't render".docs/content/docs/architecture/template-engine.md.go.mod—go 1.26.1is bleeding edgeNot a problem today, but it restricts
go install github.com/specsnl/specs-cli@latestfor users on older Go versions. Two options:go 1.25(or oldest still-supported) if no language features beyond that are used.go vet), document the requirement prominently in README under Installation.pkg/cmd/app.go—Appmutable fields are race-proneApp.SafeModeandApp.HookEnvPrefixare mutated byPersistentPreRunE(pkg/cmd/root.go:32-37). Fine for single-shot CLI invocations, but it's an awkward pattern that complicates testing (tests must reset state between cases). A typed config struct passed explicitly to commands would be cleaner.cmd.RunConfig(or similar) holdingSafeMode,HookEnvPrefix, etc.PersistentPreRunEbuilds a*RunConfigand stashes it on the cobra command's context (cmd.SetContext(ctx)).ctx, not fromApp.Appkeeps only truly app-wide singletons (Logger, Output).Acceptance criteria
Each unchecked box above is a candidate task. None are blockers for the main review (#42). Consider closing this issue once half are done, and opening fresh issues for the rest if they grow in scope.
References
See the line/file references inside each section.