diff --git a/.golangci.yml b/.golangci.yml index 6ee6ce82..db566d98 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -64,6 +64,24 @@ linters: desc: "in-binary auto-update forbidden by RFC-0008; operators drive updates via Flux/Argo CD/RenovateBot/kubectl set image" - pkg: github.com/tj/go-update desc: "in-binary auto-update forbidden by RFC-0008; operators drive updates via Flux/Argo CD/RenovateBot/kubectl set image" + # PRINCIPLES §6: defaults bias toward private. `internal/` first; + # `pkg/` only by RFC. The allow list below is the set of `pkg/` + # subpaths ratified by RFC-0013; adding a new sibling requires + # an RFC and an entry here. depguard's `allow` takes precedence + # over `deny`, so listed paths import normally; unlisted ones + # under `module/pkg/` fail the lint. + pkg-private: + list-mode: lax + allow: + - github.com/tracecoreai/tracecore/module/pkg/nccl + - github.com/tracecoreai/tracecore/module/pkg/patterns + - github.com/tracecoreai/tracecore/module/pkg/replay + - github.com/tracecoreai/tracecore/module/pkg/runtime + - github.com/tracecoreai/tracecore/module/pkg/selftel + - github.com/tracecoreai/tracecore/module/pkg/testutil + deny: + - pkg: github.com/tracecoreai/tracecore/module/pkg + desc: "PRINCIPLES §6: new `pkg/` subpaths require an RFC and an explicit allow entry in .golangci.yml; default to `internal/`" errorlint: errorf: true asserts: true diff --git a/CODEOWNERS b/CODEOWNERS index dc9734fe..5566485a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,7 +1,49 @@ # CODEOWNERS — path-specific review requirements. # GitHub matches the LAST matching pattern, so order matters. +# +# Layering convention: +# 1. Default owner (catch-all) — lowest precedence. +# 2. Top-level directory rules — broaden coverage to ≥80% of code +# paths (NORTHSTARS O7 supporting KPI). Single-owner today; when a +# second non-author maintainer joins, split sub-team rules land +# under each directory block (see docs/maintainership.md +# § "Proposed: bar to join"). +# 3. File-scoped governance + supply-chain rules — highest precedence. + +# Default owner — catches anything not matched by a later rule. +* @TraceCoreAI/core + +# ---- Top-level source directories -------------------------------------- + +# In-repo Go submodule (RFC-0013 receivers, processors, exporters). +/module/ @TraceCoreAI/core + +# In-tree components staged for RFC-0013 §7 deletion path. +/components/ @TraceCoreAI/core + +# Shared Go code (internal/-first per PRINCIPLES §6). +/internal/ @TraceCoreAI/core + +# Helm chart + Kubernetes manifests. +/install/ @TraceCoreAI/core + +# Documentation tree (102+ markdown files; doc-check.sh enforces). +/docs/ @TraceCoreAI/core + +# CI/build scripts (lint, doc-check, register-lint, etc.). +/scripts/ @TraceCoreAI/core + +# Code-gen tools (components-gen, etc.). +/tools/ @TraceCoreAI/core + +# Benchmark fixtures + overhead harness. +/bench/ @TraceCoreAI/core + +# tracecore-pyspy helper. +/python/ @TraceCoreAI/core + +# ---- Governance & policy files ---------------------------------------- -# Governance & policy files /LICENSE @TraceCoreAI/core /SECURITY.md @TraceCoreAI/core /CODE_OF_CONDUCT.md @TraceCoreAI/core diff --git a/PRINCIPLES.md b/PRINCIPLES.md index 5aa6de51..4cadac0c 100644 --- a/PRINCIPLES.md +++ b/PRINCIPLES.md @@ -180,6 +180,39 @@ When tracecore ships against an in-flight upstream patch, the `go.mod` `replace` --- +## Enforcement map + +Per §5 ("Linter is law"), every principle that *can* be machine-checked should be machine-checked. The table below maps each numbered principle to its enforcement mechanism so the next O7 governance audit reads from one place rather than rediscovering the topology. + +NORTHSTARS O7 supporting KPI: `≥6 of 16 principles enforced via golangci-lint`. Count today: **5** (§3, §6, §8, §9, §13). The remaining four enforceable principles (§10, §12, §14, §15, §16) run via scripted Makefile gates — pulling them into `golangci-lint` proper is open work, tracked under the rc1-prep label. + +| # | Principle | Enforcement | Mechanism | +|---|---|---|---| +| 1 | Trust under load is the product | **partial lint** | `gosec` (panic / recovery hygiene), `errcheck` (no swallowed errors); `recover()`-wrapped vendor calls are convention, not lint-enforceable | +| 2 | Reversibility before optionality | cultural | RFC discipline + `docs/rfcs/README.md` status index | +| 3 | One mechanism over many | **lint** | `depguard` (denies `github.com/pkg/errors`, `hashicorp/go-multierror`, `io/ioutil`, `math/rand`) — forces stdlib alternates | +| 4 | Don't police what you don't have | meta-cultural | applied during lint-rule review (this very table is its concrete artefact) | +| 5 | Linter is law (no prose duplication) | meta-cultural | enforced in PR review; STYLE.md does not duplicate lint rules | +| 6 | Defaults bias toward private | **lint** | `depguard` `pkg-private` rule — `internal/` is default; new `module/pkg/...` subpaths require an explicit allowlist entry (RFC-gated) | +| 7 | Comments earn their place | cultural | enforced in PR review | +| 8 | Names earn their slot | **lint** | `revive` (`var-naming`, `exported`, `package-comments`, `error-naming`), `predeclared` | +| 9 | Failure modes are part of the API | **lint** | `errcheck`, `errorlint`, `wrapcheck`, `nilerr`, `revive` (`errorf`, `error-return`, `if-return`) | +| 10 | Fast feedback over thorough | scripted gate | `make ci` recipe wall-time budget | +| 11 | Backwards compatibility | cultural | `CHANGELOG.md` + semver post-v1.0.0 | +| 12 | Reproducibility is a feature | scripted gate | `-trimpath`, `SOURCE_DATE_EPOCH`, `tidy-check`, `mod-verify`, `generate-fixtures-check`, `base-digest-check` | +| 13 | Operability is owed to the operator | **partial lint** | `loggercheck` (slog), `contextcheck` | +| 14 | Honest commits, honest history | scripted gate | DCO sign-off check, `.github/workflows/pr-lint.yml` (release-notes block + ≤72-char subject) | +| 15 | Decide late, write it down | scripted gate | `docs/rfcs/README.md` status index — every RFC has a `Status:` line; `scripts/doc-check.sh` validates cross-doc invariants | +| 16 | Adopt > build | scripted gate | `register-lint.sh` (factory-location), `no-autoupdate-check.sh` (RFC-0008), `depguard` `inconshreveable/go-update` family bans | + +When a new principle violation lands in a PR, the response order is: + +1. **Add the lint rule** if the linter can express it (§5 corollary: enforcement beats documentation). +2. **Add a scripted gate** if only a custom check can express it. +3. **Update this table.** A principle without an enforcement column entry is a principle that nobody will remember in six months. + +--- + ## When this guide is wrong These are principles, not laws. When applying one would produce a worse outcome than ignoring it, ignore it - and open an RFC explaining why. The next reader needs the same shortcut.