X22a-1-arch-traits: P01-kubernetes … P10-fyne#
Scorecard rows#
| Project | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | Composite |
|---|---|---|---|---|---|---|---|---|---|
| P01-kubernetes | 2 | 1 | 3 | 3 | 1 | 1 | 3 | 2 | 16 |
| P02-moby | 1 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 16 |
| P03-etcd | 3 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 22 |
| P04-prometheus | 2 | 1 | 3 | 2 | 2 | 2 | 1 | 1 | 14 |
| P05-grafana | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 2 | 20 |
| P06-hugo | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 14 |
| P07-traefik | 2 | 2 | 3 | 1 | 2 | 2 | 2 | 1 | 15 |
| P08-caddy | 3 | 1 | 3 | 1 | 1 | 2 | 3 | 3 | 17 |
| P09-cockroach | 2 | 1 | 3 | 3 | 2 | 1 | 0 | 2 | 14 |
| P10-fyne | 3 | 3 | 3 | 1 | 1 | 2 | 3 | 3 | 19 |
Evidence#
P01-kubernetes / T1 (score 2): report:P01-kubernetes–interfaces.md: dominant style is 2–4 method interfaces (runtime.Object 2, FilterPlugin 2, ScorePlugin 2); broader legacy interfaces exist (storage.Interface 13, SharedInformer 15) but are acknowledged accumulation points P01-kubernetes / T2 (score 1): report:P01-kubernetes–patterns.md: 827
func init()calls populating the Scheme global mutable registry; explicitly described as “a deliberate trade-off for API extensibility” P01-kubernetes / T3 (score 3): report:P01-kubernetes–architecture.md: “No dependency injection framework is used. Wiring is manual: each New(config) function receives all its dependencies explicitly”; CreateServerChain assembles server chain at startup P01-kubernetes / T4 (score 3): report:P01-kubernetes–patterns.md: 16,784 context.Context parameters; 1,013 context.WithCancel/WithTimeout/WithDeadline calls; external effects flow through injected parameters throughout P01-kubernetes / T5 (score 1): report:P01-kubernetes–structure.md: monolithic pkg/ tree mixes domain logic with I/O; staging module extraction helps public packages but main codebase has no explicit pure-logic boundary P01-kubernetes / T6 (score 1): report:P01-kubernetes–interfaces.md: 2,498 interface definitions; “every major collaboration point is abstracted behind an interface”; type assertions used pervasively for capability discovery P01-kubernetes / T7 (score 3): report:P01-kubernetes–api-surface.md: 20+ independently published staging modules (client-go, apimachinery, apiserver, component-base); sample-controller as reference integrator; dedicated staging pipeline with semantic versioning P01-kubernetes / T8 (score 2): report:P01-kubernetes–structure.md: custom import-boss tool enforces layering via .import-restrictions files rather than Go’s internal/; staging sub-modules published independently; non-standard but effective
P02-moby / T1 (score 1): report:P02-moby–interfaces.md: ImageService has 35 methods, ContainerAPIClient 30; “Large (10+ methods)” interfaces appear at critical seams; some narrow marker interfaces in errdefs but insufficient to offset P02-moby / T2 (score 2): report:P02-moby–patterns.md: Registry pattern for layers/volumes/plugins uses init-time self-registration; no widespread init() side effects beyond plugin registry; constructor-based wiring for Daemon struct P02-moby / T3 (score 3): report:P02-moby–architecture.md: daemonCLI.start() ~400 lines of sequential manual wiring; no DI framework; explicit bootstrap without abstraction P02-moby / T4 (score 3): report:P02-moby–patterns.md: 2,267 context.Context function parameter occurrences; rate limiting via golang.org/x/time/rate; external effects flow through parameters throughout P02-moby / T5 (score 1): report:P02-moby–architecture.md: Daemon is a large layered monolith; api/ is pure types only but daemon/ mixes logic and I/O heavily; no functional core isolation P02-moby / T6 (score 2): report:P02-moby–interfaces.md: handler packages define consumer-side Backend interfaces (ISP pattern); but ImageService, libcontainerd.Client, driverapi.Driver are pervasive complex interfaces; mixed P02-moby / T7 (score 2): report:P02-moby–api-surface.md: github.com/moby/moby/client published as independent module with functional options; api/ as type-only module; well-defined but narrower ecosystem than k8s P02-moby / T8 (score 2): report:P02-moby–structure.md: daemon/internal/ with ~45 private packages; non-standard sub-directory internal/ enforcement; dual storage path (graphdriver/snapshotter) indicates some boundary tension
P03-etcd / T1 (score 3): report:P03-etcd–interfaces.md: UberApplier 1 method, Watchable 1, Wait 3, Raft 4; narrow consumer-side interfaces dominate at nearly all seams; AuthStore (~30 methods) is internal-only exception P03-etcd / T2 (score 3): report:P03-etcd–patterns.md: manual constructor wiring in bootstrap.go; no DI framework; no package-level mutable state or problematic init() blocks observed P03-etcd / T3 (score 3): report:P03-etcd–architecture.md: embed.StartEtcd() and bootstrap() form explicit named composition root; bootstrappedServer struct carries all deps; dependency order is explicit and observable P03-etcd / T4 (score 2): report:P03-etcd–patterns.md: 1,490 context.Context usages as first argument; context-based timeouts for linearizable reads; some ambient Raft timing clock usage remains in raft internals P03-etcd / T5 (score 3): report:P03-etcd–architecture.md: go.etcd.io/raft/v3 is a pure state machine with no I/O; apply layer handles effects; storage and MVCC layers are algorithmic; clear shell/core separation P03-etcd / T6 (score 3): report:P03-etcd–interfaces.md: decorators (applierV3) and storage subsystems (mvcc.store) are concrete structs; interfaces only at external seams (rafthttp.Transporter, Queryable, Appendable) P03-etcd / T7 (score 2): report:P03-etcd–api-surface.md: embed.Config and embed.StartEtcd() provide clear embedding surface; client/v3 has functional options; solid but infrastructure-centric rather than library-oriented P03-etcd / T8 (score 3): report:P03-etcd–structure.md: 13-module Go workspace enforces boundaries via module separation rather than internal/; clean dependency hierarchy (root → api → server → client) with no circular imports
P04-prometheus / T1 (score 2): report:P04-prometheus–interfaces.md: bimodal distribution — Discoverer 1 method, Queryable 1 method, Storage 8 with embedding are excellent; rules.Rule 15+ methods is an outlier; ~60% under 8 methods P04-prometheus / T2 (score 1): report:P04-prometheus–patterns.md: service discovery plugins call discovery.RegisterConfig() in init() at startup; global registry built from init-time side effects; consistent pattern across all SD providers P04-prometheus / T3 (score 3): report:P04-prometheus–architecture.md: main.go ~1700 lines with explicit sequential dependency order (readyStorage → remoteStorage → fanout → discovery managers → scrape manager → engine → rules manager → web handler); no framework P04-prometheus / T4 (score 2): report:P04-prometheus–patterns.md: 732 context.Context usages as first arg; deadline-based scrape timeouts; ambient cloud SDK calls in discovery layer (AWS/Azure/GCP) limit score P04-prometheus / T5 (score 2): report:P04-prometheus–dependencies.md: PromQL parser uses stdlib only; TSDB is algorithmic; storage layer couples query engine to concrete backends with some I/O interleaving in scrape/discovery P04-prometheus / T6 (score 2): report:P04-prometheus–interfaces.md: consumer-defined interfaces (TargetRetriever, RulesRetriever) show good ISP inside web/api; scrape, discovery, fanout subsystems are concrete; flat structure weakens overall discipline P04-prometheus / T7 (score 1): report:P04-prometheus–api-surface.md: promql.Engine, tsdb.DB, storage interfaces are public; no dedicated builder patterns or test helpers package; minimal embedding affordances; config via structs P04-prometheus / T8 (score 1): report:P04-prometheus–structure.md: domain-driven flat layout with no pkg/; minimal internal/; packages depend on concrete types from peers; no strict layering or visibility enforcement
P05-grafana / T1 (score 2): report:P05-grafana–interfaces.md: infrastructure interfaces exemplary (BackgroundService 1, CacheStorage 3, Bus 2, PluginSource 3); domain service interfaces broad (DashboardService ~20 methods); two tiers co-exist P05-grafana / T2 (score 3): report:P05-grafana–architecture.md: Wire DI eliminates globals; setting.Cfg and all dependencies are explicit constructor parameters; no ambient init() side effects beyond bounded startup sequence in Server.Init() P05-grafana / T3 (score 3): report:P05-grafana–architecture.md: pkg/server/wire_gen.go is a 1939-line generated composition root; Wire validates full dependency graph at compile time; constructors are the only way to obtain dependencies P05-grafana / T4 (score 2): report:P05-grafana–patterns.md: context pervasive (14,694 usages); rates parameterized via golang.org/x/time/rate and workqueue limiters; some legacy ambient patterns expected in large codebase P05-grafana / T5 (score 3): report:P05-grafana–architecture.md: clear layering — pkg/infra/ has no domain imports, pkg/services/ implements business logic, pkg/api/ is the HTTP shell; pure packages explicitly avoid IO imports P05-grafana / T6 (score 3): report:P05-grafana–interfaces.md: concrete internal service implementations throughout; interfaces at plugin system (gRPC), infrastructure (CacheStorage, DB) boundaries; Wire-validated explicit dependencies prevent accidental abstraction P05-grafana / T7 (score 2): report:P05-grafana–api-surface.md: plugin SDK, apimachinery, apiserver documented as external-facing; Wire providers are public; no dedicated pkg/test pattern; formal integrator surface not explicitly documented P05-grafana / T8 (score 2): report:P05-grafana–structure.md: go.work manages 35+ modules; individual packages have internal/ subdirs; layering enforced by Wire compile-time validation; some public imports of internal services remain possible
P06-hugo / T1 (score 2): report:P06-hugo–interfaces.md: most interfaces narrow (Identity 1, Converter 1–2, Template 2, SignalRebuilder 1); two large facades (page.Page ~50, config.AllProvider ~45) are intentional system-boundary aggregates P06-hugo / T2 (score 2): report:P06-hugo–architecture.md: Deps is passed explicitly (not a global singleton); init side effects concentrated in Deps.Init(); no package-level mutable state but Deps is a god-object with centralized lifecycle P06-hugo / T3 (score 2): report:P06-hugo–architecture.md: hugoBuilder.newHugoSites() constructs Deps with all providers explicitly; no DI framework; composition is explicit but Deps container is not a clearly named “root” P06-hugo / T4 (score 2): report:P06-hugo–patterns.md: context pervasive (448 uses); file I/O through hugofs abstraction; time mockable via bep/clocks; effects flow through Deps parameter rather than individual function args P06-hugo / T5 (score 2): report:P06-hugo–architecture.md: identity package deliberately minimal (no domain imports); converters (markup/converter) are pure logic; page.Page implementation mixes domain+I/O; no strict enforcement P06-hugo / T6 (score 2): report:P06-hugo–interfaces.md: goldmarkConverter and filecache.Caches are concrete; interfaces at extension points (Converter, Provider) and domain boundaries (page.Page); afero wrapping introduces extra abstraction layers P06-hugo / T7 (score 1): report:P06-hugo–api-surface.md: Template API rich (~30 namespaces, ~400 functions); hugolib explicitly flagged as unstable API; no dedicated pkg/test pattern; no integrator builder surface documented P06-hugo / T8 (score 1): report:P06-hugo–structure.md: root-level packages dominate; internal/ minimal (WASM/JS only); no import cycle prevention mechanism visible; circular import avoidance via convention not enforcement
P07-traefik / T1 (score 2): report:P07-traefik–interfaces.md: hand-authored interfaces predominantly 1–3 methods (Provider 2, tcp.Handler 1, udp.Handler 1, ProxyBuilder 2, ServiceBuilder 1); metrics.Registry ~20 methods is a service-boundary exception P07-traefik / T2 (score 2): report:P07-traefik–patterns.md: manual constructor injection throughout; setupServer() is the composition root; global state limited to observability registration; no heavy init() side effects for core logic P07-traefik / T3 (score 3): report:P07-traefik–architecture.md: setupServer() ~220 lines in cmd/traefik/traefik.go is the explicit, obvious composition root; all components manually constructed and passed; no DI framework P07-traefik / T4 (score 1): report:P07-traefik–patterns.md: channel-based event bus provides some parameterization; no systematic evidence of injecting time/RNG/IO as seams; ambient call patterns persist for ACME/TLS operations P07-traefik / T5 (score 2): report:P07-traefik–structure.md: protocol layers (muxer/http, tcp, udp) separated from application logic; middleware packages isolated per-concern; separation present in most subsystems but not explicitly enforced P07-traefik / T6 (score 2): report:P07-traefik–interfaces.md: Provider and ProxyBuilder interfaces at external/replaceable boundaries; serviceManager used locally; good ISP discipline; some internal interfaces for flexibility without reaching mock-everything P07-traefik / T7 (score 2): report:P07-traefik–api-surface.md: REST API, CLI (healthcheck/version), 30+ middleware catalog, plugin system (yaegi/WASM); good surface but no dedicated pkg/test or formal integrator builder API P07-traefik / T8 (score 1): report:P07-traefik–structure.md: pkg/ packages are openly importable without internal/ discipline; only cmd/internal/gen uses internal/; layering described as “generally one direction” but not Go-enforced
P08-caddy / T1 (score 3): report:P08-caddy–interfaces.md: vast majority of interfaces 1–2 methods (Module 1, App 2, Provisioner 1, Validator 1, MiddlewareHandler 1, Adapter 1); textbook ISP compliance throughout P08-caddy / T2 (score 1): report:P08-caddy–patterns.md: entire extensibility model driven by init() side effects; 112 init functions and 136 RegisterModule calls populating global module registry before main(); architecture.md confirms “global modules map built before main()” P08-caddy / T3 (score 3): report:P08-caddy–architecture.md: provisionContext() + ctx.LoadModule() form clear composition root; cmd/caddy/main.go deliberately minimal (43 lines); manual context-passing enables explicit wiring; no DI framework P08-caddy / T4 (score 1): report:P08-caddy–patterns.md: modules receive caddy.Context in Provision(); context-passing provides flexibility but no systematic evidence of parameterizing time/RNG/IO as injected seams P08-caddy / T5 (score 1): report:P08-caddy–architecture.md: caddyconfig/caddyfile is a pure parser; modules are inherently effectful by design; no functional core / IO shell separation enforced at package level P08-caddy / T6 (score 2): report:P08-caddy–interfaces.md: interfaces ubiquitous by design (Module, Provisioner, MiddlewareHandler at every extension point); 125 compile-time interface satisfaction checks; pragmatic for plugin model but not concrete-first internally P08-caddy / T7 (score 3): report:P08-caddy–api-surface.md: dedicated public integrator surface — Module interface, lifecycle hooks (Provisioner/Validator/CleanerUpper), plugin registration pattern, xcaddy build tool; cmd/caddy/main.go is a deliberate copy-paste template for custom builds P08-caddy / T8 (score 3): report:P08-caddy–structure.md: strict layering (root → caddyconfig → modules); modules/internal/ for sub-tree visibility; root package is stable public boundary; intentional use of Go visibility rules at sub-tree granularity
P09-cockroach / T1 (score 2): report:P09-cockroach–interfaces.md: kv.Sender is 1 method; Processor and Resumer are narrow (1–5); but batcheval.EvalContext ~35 methods and storage.Engine ~30 methods at critical internal seams; mixed across layer depth P09-cockroach / T2 (score 1): report:P09-cockroach–patterns.md: ~15 CCL feature hooks injected via init() function variables at package level; CCL builds mutate package-level function vars to add enterprise features; more than “one or two” init() side effects P09-cockroach / T3 (score 3): report:P09-cockroach–architecture.md: NewServer() in pkg/server/server.go is ~1200 lines of explicit construction; numbered dependency order (1–13 steps); no DI framework; manual injection throughout P09-cockroach / T4 (score 3): report:P09-cockroach–patterns.md: context propagation in 26,543 usages; every function that does I/O or RPC accepts context.Context as first parameter; I/O through Engine/Reader/Writer interfaces; HLC for temporal concerns P09-cockroach / T5 (score 2): report:P09-cockroach–architecture.md: strict bottom-up layering with pkg/raft as pure algorithm module; SQL optimizer (pkg/sql/opt) is cost-based logic; most packages mix logic and I/O at their level; no explicit IO prohibition in logic packages P09-cockroach / T6 (score 1): report:P09-cockroach–interfaces.md: 1,481 interface definitions; every internal component implements multiple interfaces (Sender, TxnSender, Reader, Writer, Processor); architecture described as having near-universal interface abstraction at internal seams P09-cockroach / T8 (score 2): report:P09-cockroach–structure.md: clear functional domain layering and CCL separation via blank imports; no top-level internal/ directory; pkg/ is a domain monolith; layering enforced by design and documentation but not Go conventions
P10-fyne / T1 (score 3): report:P10-fyne–interfaces.md: behavior interfaces median 2 methods (Tappable 1, Draggable 2, Focusable 4, DoubleTappable 1); all behavior interfaces 1–4 methods; App (17) and Canvas (20) are explicit facade exceptions P10-fyne / T2 (score 3): report:P10-fyne–patterns.md: single app singleton stored in atomic.Pointer[fyne.App]; no package-level mutable state beyond this; no init() side effects; described as “zero application-wide globals except the app singleton” P10-fyne / T3 (score 3): report:P10-fyne–architecture.md: explicit sequence app.New() → NewWithID() → NewGLDriver() → newAppWithDriver() in app/app.go; no DI framework; build tags select driver at compile time; fully traceable P10-fyne / T4 (score 1): report:P10-fyne–patterns.md: only 5 context.Context references in entire repo; deliberate omission — fyne.Do() marshals work to UI thread as the cancellation model; idiomatic for GUI but scores low on rubric P10-fyne / T5 (score 1): report:P10-fyne–architecture.md: software painter uses only stdlib image/*; but no explicit pure-logic/IO separation at package level; internal/ is 32 packages mixing all concerns vertically by rendering layer P10-fyne / T6 (score 2): report:P10-fyne–interfaces.md: internal collaborators fyneApp, glCanvas, gLDriver are concrete structs; interfaces at driver/painter boundaries; root package is interface-only but internal implementations are concrete, not mock-heavy P10-fyne / T7 (score 3): report:P10-fyne–api-surface.md: 63+ exported widget constructors (NewButton, NewEntry, etc.), container layouts, dialogs, data binding, storage API, driver extensions, test helpers; primary library designed for integrators P10-fyne / T8 (score 3): report:P10-fyne–structure.md: root package is interface-only (no concrete implementations exported); entire rendering stack in internal/ making it refactorable without API breakage; feature packages public; textbook visibility discipline
Confidence note (chunk-local)#
Hardest-to-assign scores:
P01-kubernetes T5 (1): The staging module extraction is architecturally meaningful but the in-tree pkg/ monolith has no enforced pure/IO separation. The 1 is correct but a reader emphasizing the staging side might score 2.
P02-moby T1 (1): The consumer-defined Backend interfaces per router are excellent ISP, but the critical path runs through ImageService (35 methods) and ContainerAPIClient (30 methods). Debated 1 vs 2; settled on 1 because the wide interfaces are on load-bearing seams.
P05-grafana T6 (3): Domain service interfaces (~20 methods each) introduce some abstraction at non-external boundaries. Readers who treat service-layer interfaces as “internal” may score 2. Flagged per rubric instruction — readers should consider this borderline.
P08-caddy T6 (2): The plugin model makes interface ubiquity structural rather than incidental, unlike Kubernetes’ mock-everything culture. Score follows the rubric’s “internal collaborators often interfaces” criterion; a sympathetic reading of the domain might accept 3.
P09-cockroach T7 (0): CockroachDB is a deployed binary application, not a library. The trait literally does not apply. Zero is the correct score but will look like a gap in cross-project analysis — reduce step should note this.
P06-hugo and P04-prometheus T8 (both 1): Both use flat package layouts without enforced internal/ boundaries. This may surprise readers who expect mature OSS projects to score higher; the flat domain-driven layout is a deliberate choice in both cases, not an oversight.
T4 scores for GUI projects (P10-fyne score 1): The rubric’s framing targets traditional dependency injection. Fyne deliberately avoids context threading because GUI main-thread constraints demand a different model. The 1 is accurate per rubric but architecturally misleading if read as “poor design.”