X22a-2-arch-traits: P11-minio → P21-tekton-pipeline#
Scorecard#
| Project | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | Composite |
|---|---|---|---|---|---|---|---|---|---|
| P11-minio | 1 | 0 | 1 | 1 | 1 | 2 | 1 | 1 | 8 |
| P12-consul | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | 13 |
| P13-vault | 2 | 1 | 2 | 1 | 2 | 2 | 3 | 2 | 15 |
| P14-terraform | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 3 | 14 |
| P15-nomad | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | 13 |
| P16-dapr | 2 | 1 | 2 | 1 | 1 | 2 | 1 | 2 | 12 |
| P17-k3s | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 9 |
| P18-helm | 2 | 2 | 2 | 1 | 2 | 2 | 3 | 2 | 16 |
| P19-istio | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | 13 |
| P20-argo-cd | 2 | 1 | 2 | 1 | 1 | 2 | 1 | 2 | 12 |
| P21-tekton-pipeline | 3 | 1 | 2 | 2 | 2 | 2 | 1 | 2 | 15 |
Evidence#
P11-minio#
P11-minio / T1 (score 1): report:P11-minio–interfaces.md: bimodal — ObjectLayer (~40 methods) and StorageAPI (~35) dominate; narrow interfaces (WarmBackend 5, event.Target 6, RWLocker 4) exist but are secondary; provider-defined large interfaces characterize the public boundary.
P11-minio / T2 (score 0): report:P11-minio–architecture.md: all subsystems initialized as package-level globals (
globalIAMSys,globalObjectAPI,globalGrid,globalEventNotifier, etc.); every subsystem is a named global incmd/; no meaningful separation from package singletons.
P11-minio / T3 (score 1): report:P11-minio–architecture.md:
serverMain()has a single bootstrapTrace()-ordered init sequence (one composition point), but all wiring flows intoglobal*vars rather than explicit constructor parameters — the “root” creates globals, not an explicit graph.
P11-minio / T4 (score 1): report:P11-minio–patterns.md: context used throughout (1714 occurrences) for cancellation; no evidence of injected clock interface or parameterized randomness/IO; rate limiting via
x/time/rateis narrow and ambient.
P11-minio / T5 (score 1): report:P11-minio–structure.md: 34
internal/sub-packages ring the singlecmd/god package (~453 Go files all in packagecmd); utility packages (bpool, cachevalue) are pure, but business logic is thoroughly mixed with IO in the dominant cmd package.
P11-minio / T6 (score 2): report:P11-minio–architecture.md:
ObjectLayeris the single seam replacing the storage hierarchy; internal grid RPC and background workers use concrete types throughout; the narrow use of interfaces at real replacement points (ObjectLayer, event.Target) reflects correct boundary discipline.
P11-minio / T7 (score 1): report:P11-minio–api-surface.md: server-binary only with no exported Go library API; external SDK lives in the separate
github.com/minio/pkgrepo; extension is via compiled-in event targets and Object Lambda, not an importable package.
P11-minio / T8 (score 1): report:P11-minio–structure.md:
internal/wraps 34 sub-packages correctly, but the dominantcmd/is a single 453-file god package with no visibility enforcement; no sub-package discipline within the most import-heavy portion of the codebase.
P12-consul#
P12-consul / T1 (score 2): report:P12-consul–interfaces.md: modal size 1–3 methods; 20 single-method
proxycfgNotify interfaces; consumer-defined pattern throughout; outlierAuthorizer(~35 methods) is a legitimately wide protocol contract, not design laziness.
P12-consul / T2 (score 1): report:P12-consul–architecture.md:
BaseDepsstruct for explicit DI; butapi-surface.mdnotes HTTP routes registered viainit()inagent/http_register.go; some package-level sentinels; not pervasive but present.
P12-consul / T3 (score 2): report:P12-consul–architecture.md:
BaseDepsis an explicit manual DI root passed through Server/Client constructors; wiring is discoverable and greppable; no framework, no service locator.
P12-consul / T4 (score 1): report:P12-consul–patterns.md:
shutdownCh+ context coexistence noted as an in-progress migration; no explicit clock injection or parameterized IO described; context used for request scope but not the primary lifecycle signal.
P12-consul / T5 (score 1): report:P12-consul–structure.md:
agent/structs/is a god package for shared domain types — business logic and IO are entangled at the center; domain-driven layout at top level is correct butstructspackage prevents true core/IO separation.
P12-consul / T6 (score 2): report:P12-consul–interfaces.md:
ca.Provider(9 methods with ISP sub-interfaces),storage.Backend(6),Reconciler(1) — interfaces at real replacement boundaries; internal coordinator/delegate uses concrete types.
P12-consul / T7 (score 2): report:P12-consul–structure.md:
api/sub-module is a public Go client library;sdk/sub-module as reusable primitives;proto-public/as stable external proto contracts — three distinct public-facing layers.
P12-consul / T8 (score 2): report:P12-consul–structure.md: 5 sub-modules (
api/,sdk/,proto-public/,envoyextensions/,troubleshoot/);internal/for v2 architecture; domain-driven root layout with intentional visibility separation.
P13-vault#
P13-vault / T1 (score 2): report:P13-vault–interfaces.md: SDK provides narrow clean interfaces (
physical.Backend4,logical.Storage4,physical.HABackend2); optional capability extension via type assertions rather than wider interfaces; Core has legitimately wideSecurityBarrier(~25) as protocol contract.
P13-vault / T2 (score 1): report:P13-vault–patterns.md: factory maps in
CoreConfig(functions, not instances) keep globals lean;sync.Onceguards (72 uses) for lazy singletons; some package-level vars for CA state; limited but present.
P13-vault / T3 (score 2): report:P13-vault–architecture.md:
CoreConfigstruct carries factory maps (not instances) — explicit DI container; plugins never imported directly; radix-tree router as the dispatch mechanism; composition root is clearlyvault.NewCore(CoreConfig{...}).
P13-vault / T4 (score 1): report:P13-vault–patterns.md:
ShutdownCh chan struct{}pattern throughout;helper/fairshare/worker pool with explicit context; no documented clock injection interface;api/auth/uses functional options but not time parameterization.
P13-vault / T5 (score 2): report:P13-vault–structure.md:
sdk/andapi/as separate Go modules with clean boundaries;physical/backends separated from core logic;sdk/logical.Backendas a pure plugin contract that carries no IO dependencies itself.
P13-vault / T6 (score 2): report:P13-vault–architecture.md: plugins never imported directly into
CoreConfig— only factory functions;sdk/logical.Backendis the universal plugin contract at the real external boundary; internalvault/package uses concrete collaborators.
P13-vault / T7 (score 3): report:P13-vault–structure.md: three Go modules (root,
sdk/,api/);api/is an independent library used by all Vault clients;sdk/provides the stable plugin development kit for third-party secrets engines and auth methods — textbook multi-module library design.
P13-vault / T8 (score 2): report:P13-vault–structure.md:
internal/used throughout; Enterprise/CE split via_stubs_oss.gobuild stubs; three distinct modules with explicit visibility;internalshared/as a cross-module seam.
P14-terraform#
P14-terraform / T1 (score 2): report:P14-terraform–interfaces.md:
GraphNodeExecutable(1 method),GraphTransformer(1) alongsideproviders.Interface(~35),EvalContext(~30);statemgr.Fullis exemplary interface composition (5 interfaces composed); bimodal but consumer-defined throughout.
P14-terraform / T2 (score 2): report:P14-terraform–architecture.md: all-internal architecture with zero exported packages; factory map registry for backends; no package singletons visible in reports;
ContextOptsDI container; cleaner than most projects in this chunk.
P14-terraform / T3 (score 2): report:P14-terraform–architecture.md:
ContextOptsas explicit DI container; each operation builds a fresh DAG; composition root inmain.gois thin but explicit; no service locator.
P14-terraform / T4 (score 1): report:P14-terraform–patterns.md: atomic stop flag used instead of context cancellation for stopping operations; no documented clock injection or parameterized IO beyond context; consistent with the graph/batch model.
P14-terraform / T5 (score 1): report:P14-terraform–architecture.md: DAG logic in
internal/dagis pure; providers run as subprocesses (zero in-process IO mixing);internal/promising/uses generics for pure promise combinators; limited to specific packages.
P14-terraform / T6 (score 2): report:P14-terraform–architecture.md:
providers.Interfaceonly at the subprocess boundary (all providers are out-of-process gRPC); internal graph transformers use concrete types;EvalContextwraps the internal pipeline but is a necessary abstraction for the walk.
P14-terraform / T7 (score 1): report:P14-terraform–structure.md: zero exported packages (all
internal/);rpcapiprovides gRPC automation interface; no importable library; downstream tools consume via CLI or gRPC protocol, not Go packages.
P14-terraform / T8 (score 3): report:P14-terraform–structure.md: all
internal/, 9 remote-state backends as separate Go modules, clean layering with no import cycles reported;tfplugin5/tfplugin6dual protocol separation; textbook package boundary discipline.
P15-nomad#
P15-nomad / T1 (score 2): report:P15-nomad–interfaces.md:
Scheduler(1 method),FeasibleIterator/RankIterator(2 each),admissionController(1) are consumer-defined narrow interfaces;StateDB(30+) andDriverPlugin(15) are broader protocol contracts at real external boundaries.
P15-nomad / T2 (score 1): report:P15-nomad–patterns.md:
init()subprocess dispatch trick inmain.gofor task drivers;shutdownCh+ context coexistence; limitedinternal/enforcement; not pervasive but present.
P15-nomad / T3 (score 2): report:P15-nomad–patterns.md: manual DI via constructor functions;
ServerandClientconstructed with explicit dependency parameters; no service locator; greppable wiring.
P15-nomad / T4 (score 1): report:P15-nomad–patterns.md:
shutdownCh+ context coexistence (incomplete migration); blocking query/watch semantics via go-memdb; no explicit clock injection described; context present but not the primary mechanism.
P15-nomad / T5 (score 1): report:P15-nomad–structure.md:
scheduler/isolated with no server imports (clear separation); butnomad/structs/as monolithic domain model entangles domain types with the rest; partial functional core isolation.
P15-nomad / T6 (score 2): report:P15-nomad–interfaces.md: CQRS-style boundary — read from
State, write viaPlanner;Schedulerinterface at the scheduling seam; internal server/client use concrete types for collaboration.
P15-nomad / T7 (score 2): report:P15-nomad–structure.md:
api/is a separate Go module providing the public Go client library; used by third-party tooling to interact with Nomad clusters.
P15-nomad / T8 (score 2): report:P15-nomad–structure.md: domain-driven layout at root level;
scheduler/cleanly isolated;api/as separate module; onlyinternal/testing/for internal enforcement — less strict than ideal but intentional structure.
P16-dapr#
P16-dapr / T1 (score 2): report:P16-dapr–interfaces.md: leaf/transport interfaces are small (
http.API2 methods,wfengine.Interface5,channel.AppChannel5); core subsystem interfaces are broader (actors.Interface12,security.Handler16 with//nolint:interfacebloat); deliberate ISP split between subsystem and leaf boundaries.
P16-dapr / T2 (score 1): report:P16-dapr–patterns.md: component registration via
init()blank imports with build-tag-controlled flavors (allcomponents.govsstablecomponents.go);DefaultRegistrysingletons per building block type; contained but present.
P16-dapr / T3 (score 2): report:P16-dapr–architecture.md:
DaprRuntimestruct as composition root;newDaprRuntime()wires all subsystems withOptionsstructs;concurrency.RunnerCloserManagermanages structured goroutine lifecycle; explicit and greppable.
P16-dapr / T4 (score 1): report:P16-dapr–patterns.md: context propagation pervasive (4702
context.Contextreferences);context.WithCancelCausein newer subsystems; no documented clock injection or parameterized randomness.
P16-dapr / T5 (score 1): report:P16-dapr–structure.md:
compstoreis a leaf package (no deps) — closest to pure;pkg/api/universal/as shared semantic layer is not pure (calls IO); no systematic functional core/IO separation.
P16-dapr / T6 (score 2): report:P16-dapr–interfaces.md:
channel.AppChannel(app protocol selection),hotreload/loader.Interface(disk vs operator),resiliency.Provider— interfaces at real deployment-mode and replacement boundaries; internal Options struct wiring is concrete.
P16-dapr / T7 (score 1): report:P16-dapr–api-surface.md: sidecar binary with no importable Go library; extension via pluggable component gRPC protocol (any language can implement); no
pkg/action-style embeddable library.
P16-dapr / T8 (score 2): report:P16-dapr–structure.md: standard Go layout (
cmd/+pkg/);pkg/internal/for non-export; co-locatedfake/andmock/sub-packages; clean per-service isolation (pkg/placement,pkg/sentryonly depended on by theircmd/).
P17-k3s#
P17-k3s / T1 (score 1): report:P17-k3s–interfaces.md:
Executor(17 methods) andDriver(14) dominate the interface landscape; smallerCluster(3) andstore.ReadCloser(3) exist but are exceptions; provider-defined large interfaces characterize the primary abstractions.
P17-k3s / T2 (score 1): report:P17-k3s–patterns.md:
executorsingleton as package-level var;init()registration via blank import inmain.go;managed.RegisterDriver()appends to a package-level slice; contained but structural.
P17-k3s / T3 (score 1): report:P17-k3s–patterns.md:
executor.Set()is the injection point but it writes to a package-level global var — a service locator pattern rather than true constructor injection; large config structs pass deps through the call stack but the centralexecutoris a global.
P17-k3s / T4 (score 1): report:P17-k3s–patterns.md: functional options
WithCACertificate,WithTimeoutfor HTTP client configuration; context cancellation viasignals.SetupSignalContext(); no documented clock injection for time-dependent operations.
P17-k3s / T5 (score 1): report:P17-k3s–structure.md:
pkg/configfilearg/is a pure preprocessing step; no pure-logic packages beyond that; executor implementation imports upstream Kubernetesapp.Run()entry points directly — IO is deeply embedded.
P17-k3s / T6 (score 2): report:P17-k3s–architecture.md:
Executorinterface is a deliberate seam isolating k3s orchestration from upstream k8s code; most internal wiring uses concrete large config structs (Control,Node); correct placement of the one major interface.
P17-k3s / T7 (score 1): report:P17-k3s–api-surface.md:
StartupHookArgs/StartupHookandRouterFuncas extension points for downstream builds (RKE2);Executorinterface as compile-time seam; no versioned public library API.
P17-k3s / T8 (score 1): report:P17-k3s–structure.md: no
internal/directory — all packages underpkg/are technically importable; no import cycle enforcement; package visibility entirely implicit; unusual for a project of this size.
P18-helm#
P18-helm / T1 (score 2): report:P18-helm–interfaces.md:
PostRenderer(1 method),Getter(1),RESTClientGetter(3) are exemplary minimal interfaces;driver.Driverexplicitly decomposed intoCreator/Updator/Deletor/Queryorrole interfaces;kube.Interface(10) is broad but documented as intentionally wide.
P18-helm / T2 (score 2): report:P18-helm–architecture.md: no package singletons;
cobra.OnInitializedefers storage driver init until command execution; no Viper; no global registries;ConfigurationOptionfor customization — cleanest T2 in this chunk outside Terraform.
P18-helm / T3 (score 2): report:P18-helm–architecture.md:
Configurationstruct as DI container;cobra.OnInitializedeferred init pattern;NewInstall(cfg),NewUpgrade(cfg)constructors receive*Configurationexplicitly — clear, greppable composition root.
P18-helm / T4 (score 1): report:P18-helm–patterns.md:
sync.Oncelazy init for Kubernetes client (lazyClient);With*functional options pervasive; no clock injection interface documented; context propagated through action layer.
P18-helm / T5 (score 2): report:P18-helm–architecture.md:
pkg/enginerenders Go templates with sprig — pure function, no IO dependency;pkg/storage/driver/memoryis a pure in-process store; clear separation of rendering logic from Kubernetes apply logic.
P18-helm / T6 (score 2): report:P18-helm–interfaces.md:
kube.Interfacefor cluster operation swappability (enables full test suite without a cluster);driver.Driverfor storage backend selection; internal rendering and coalescing logic uses concrete types throughout.
P18-helm / T7 (score 3): report:P18-helm–architecture.md:
pkg/actionexplicitly documented as “a library for calling top-level Helm actions”; imported by Flux, Argo CD, and other ecosystem tools;ConfigurationOptionandWith*functional options provide stable extension points — textbook embeddable library.
P18-helm / T8 (score 2): report:P18-helm–architecture.md:
internal/used for plugin runtime and logging;pkg/exports only intentional surfaces; clean layering (cmd → action → kube/storage/engine); no import cycles reported.
P19-istio#
P19-istio / T1 (score 2): report:P19-istio–interfaces.md:
XdsResourceGenerator(1 method!) is near-perfect ISP;XdsDeltaResourceGeneratorembeds and extends it cleanly;ConfigStore(7),XDSUpdater(6);Collection[T]small generic interface — strong ISP in the xDS layer, slightly wider in the model layer.
P19-istio / T2 (score 1): report:P19-istio–patterns.md: feature flags registered at
init()time viapkg/env.Register*Var()inpkg/features/packages; xDS generator map populated duringInitGenerators(); limited but structural.
P19-istio / T3 (score 2): report:P19-istio–architecture.md:
bootstrap.Serveras composition root with a 24-step explicitly ordered init sequence;server.Instance.AddStartFunc()component runner; manual wiring — no DI framework, no service locator.
P19-istio / T4 (score 1): report:P19-istio–patterns.md: stop-channel lifecycle dominates (538
<-chan struct{}occurrences) over context (341); no documented clock injection;atomic.Valuefor readiness state; stop channels are ambient lifecycle signals, not parameterized time.
P19-istio / T5 (score 2): report:P19-istio–patterns.md:
PushContextis built as an immutable snapshot per push cycle — generators read it without locks, effectively a pure-read data structure;krt.Collection[T]framework provides declarative reactive transforms as functional pipelines over Kubernetes data.
P19-istio / T6 (score 2): report:P19-istio–interfaces.md:
XdsResourceGeneratorplugin map at the xDS extensibility boundary;ConfigStore/ConfigStoreControllerfor backend selection;ServiceDiscoveryaggregate for registry multiplexing; internal generator implementations use concretePushContextsnapshots.
P19-istio / T7 (score 1): report:P19-istio–architecture.md: control plane binary (
pilot-discovery);pkg/kube/krtandpkg/kube/kclientare internally used packages; no versioned public library API; not designed for external import.
P19-istio / T8 (score 2): report:P19-istio–architecture.md: 263 interface definitions in
pilot/pkg/model; clean package layering (krt → kclient → model → xds → bootstrap); modular per-concern packages; no import cycles in the core path reported.
P20-argo-cd#
P20-argo-cd / T1 (score 2): report:P20-argo-cd–interfaces.md:
AppStateManager(3 methods!),Generator(3 methods) are exemplary;ClusterCache(14) andArgoDB(~40) are wide but cover complete domain contracts; mix of narrow purpose-built and wider repository-style interfaces.
P20-argo-cd / T2 (score 1): report:P20-argo-cd–patterns.md: 76
init()functions (majority in generated protobuf/Kubernetes client code); non-generated uses register Prometheus metrics at startup; Kubernetes-standard pattern, tolerable but not clean.
P20-argo-cd / T3 (score 2): report:P20-argo-cd–architecture.md:
ArgoCDServerOptsstruct as “composition root manifest”; manual wiring incobra.Command.Runfor each service; all dependencies injected at the constructor boundary — explicit and auditable.
P20-argo-cd / T4 (score 1): report:P20-argo-cd–patterns.md: context propagation pervasive (4094 occurrences);
context.WithTimeoutused at all I/O boundaries; no documented clock injection; context is the deadline mechanism, not parameterized time.
P20-argo-cd / T5 (score 1): report:P20-argo-cd–architecture.md:
gitops-engine/pkg/diffandpkg/healthcontain pure diff/health logic (Lua + built-in rules); but these are embedded as a sub-module, not distinctly separated packages; partial isolation rather than systematic.
P20-argo-cd / T6 (score 2): report:P20-argo-cd–interfaces.md:
AppStateManager,LiveStateCache,Kubectl,ResourceTrackingat real testability/replacement boundaries;ClusterCachefrom gitops-engine at the cluster-backend boundary; internal controller uses concrete types for reconcile loop wiring.
P20-argo-cd / T7 (score 1): report:P20-argo-cd–architecture.md: single binary, multiple personas; no importable Go library; CMP sidecar gRPC protocol and
Generatorinterface enable community extensions; no versioned library API.
P20-argo-cd / T8 (score 2): report:P20-argo-cd–architecture.md:
gitops-engineas embedded sub-module with its own import path; per-service package separation (controller/,server/,reposerver/,applicationset/); someinternal/usage; generally clean boundaries.
P21-tekton-pipeline#
P21-tekton-pipeline / T1 (score 3): report:P21-tekton-pipeline–interfaces.md:
Requester(1 method),Waiter/Runner/PostWriter(1 each),ResolvedResource(3),dag.Task(2),dag.Tasks(1) — overwhelmingly single-method or narrow; consumer-defined throughout; optional capabilities (TimedResolution,ConfigWatcher) split correctly as ISP sub-interfaces.
P21-tekton-pipeline / T2 (score 1): report:P21-tekton-pipeline–architecture.md: Knative context-based injection — clients extracted via
kubeclient.Get(ctx),taskruninformer.Get(ctx)— is a service-locator pattern through context;init()in generated Kubernetes client code; structurally present even if not pervasive in hand-written code.
P21-tekton-pipeline / T3 (score 2): report:P21-tekton-pipeline–architecture.md:
sharedmain.MainWithConfigas composition root; factory functionstaskrun.NewController(opts, clock),pipelinerun.NewController(opts, clock)per controller; explicit, discoverable wiring point; Knative framework provides the runner.
P21-tekton-pipeline / T4 (score 2): report:P21-tekton-pipeline–interfaces.md:
Waiter,Runner,PostWriterare explicit IO abstractions injected intoEntrypointer— each wraps a single IO concern (polling semaphore files, executing a subprocess, writing a result file); parameterized IO at the step-execution boundary is textbook T4 applied narrowly but correctly.
P21-tekton-pipeline / T5 (score 2): report:P21-tekton-pipeline–architecture.md:
pkg/reconciler/pipeline/daghas zero Kubernetes dependencies — pure DAG logic tested without any cluster API;pkg/substitutionis a pure parameter interpolation package; clear functional core within the reconciler layer.
P21-tekton-pipeline / T6 (score 2): report:P21-tekton-pipeline–interfaces.md:
Resolverinterface at the remote source extensibility boundary;Requesterat the CRD protocol boundary; SPIRE interfaces (ControllerAPIClient,EntrypointerAPIClient) at the security subsystem boundary; internal DAG and substitution logic uses concrete types.
P21-tekton-pipeline / T7 (score 1): report:P21-tekton-pipeline–architecture.md: Kubernetes operator binary;
Resolverinterface is a plugin extension point for community resolvers; no versioned importable library;RunObject/TaskObjectinterfaces enableCustomRunextensibility but require CRD implementation.
P21-tekton-pipeline / T8 (score 2): report:P21-tekton-pipeline–architecture.md: Knative-style package layout with explicit
pkg/boundaries;pkg/remoteresolutionand legacypkg/resolutioncoexist (migration in progress);internal/computeresourcesfor hidden computation; generally disciplined but dual-framework coexistence creates some noise.
Confidence note (chunk-local)#
High confidence: P13-vault (T7=3), P14-terraform (T8=3), P18-helm (T7=3), P21-tekton-pipeline (T1=3) — all strongly evidenced by multiple reports with explicit codebase references.
Medium confidence:
- T4 universally scored 1 across most projects: reports rarely document clock injection explicitly; the absence of evidence is likely genuine absence of the pattern rather than a reporting gap, but T4=1 vs T4=0 is a judgment call (1 chosen because context propagation demonstrates awareness of parametric dependencies even when time/IO are not fully parameterized).
- P11-minio T7=1 vs T7=0: MinIO ships no library API but does have
github.com/minio/pkgin separate repos; scored 1 for minimal rather than 0 for absent. - P17-k3s T3=1: the
executorinjection point is genuinely a package-level global, not constructor injection; however theinit()/blank-import pattern is a deliberate architectural seam; scored 1 rather than 2.
Hardest-to-assign:
- T5 for projects 11, 12, 15, 16, 20 (all scored 1): reports give mixed signals about which packages are “pure” — some have clear utility packages but no systematic functional-core discipline; the boundary between 1 and 2 here is particularly uncertain.
- T2 for P14-terraform (scored 2): reports describe “all-internal” and “factory maps” but do not explicitly confirm absence of package-level singletons; this is a positive inference rather than direct observation.
- T6 is uniformly 2 across all 11 projects: the rubric’s T6 is “contrarian” (high interface count ≠ high T6) and every project in this chunk uses interfaces at real boundaries without pervasive over-abstraction of internals. Score 2 (“present”) reflects this consistent pattern; none reached 3 (“textbook”) because none had strong positive evidence of explicit internal-collaborators-are-concrete design enforcement.