Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,20 @@ Universal rules every change should respect. The file is capped at
Anchor: `bench_test.go` PR #76 commit `869450b`; `impl_test.go` PR
#78 commit `06b9ddf`.

- **Cross-receiver join contracts resolve at design-lock, not
implementation-merge.** Every `M-X emits Y` rubric line in
MILESTONES.md is implicitly a contract with every `M-Z consumes Y`
receiver. Before opening a receiver-scope RFC PR, grep MILESTONES.md
and every sibling RFC for each attribute name, label name, or field
name the new receiver introduces; reconcile divergences in the same
PR (or its sibling-RFC's PR), not in a FOLLOWUPS row saying
"whichever lands first". The "first-author-pays, second-author-fights-the-amendment"
pattern is the failure mode. Anchor: PR #94 found that the M15
rubric's pod-label fallback `tracecore.io/rank` diverged from
RFC-0009's `gen_ai.training.io/rank`; Phase-3 review caught it,
amended MILESTONES.md line 358 in-PR, and the FOLLOWUPS row was
marked resolved in the same commit.

## Topic index — repo-wide

Per-topic notes that apply to anyone working in this codebase. Read
Expand All @@ -125,6 +139,11 @@ the relevant note when work touches that area. Format conventions:
gates.
- [Branch protection](docs/notes/branch-protection.md) — rule
trade-offs on main, three-sources-of-truth, escape hatches.
- [RFC authoring](docs/rfcs/README.md) — receiver-scope RFC required
sections (Operator surfaces, Rubric trace, Performance budget),
cross-checks (wire-attribute table, sibling-symbol resolve,
cross-RFC join-key), and the `components.yaml` + `make generate`
codegen pattern.

## Topic index — agent-internal

Expand Down
57 changes: 57 additions & 0 deletions docs/notes/reviews.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,60 @@ wins and clutters the follow-up list.
Anchor: `docs/FOLLOWUPS.md` § `k8sevents post-merge` — every deferral
in that section has a real out-of-PR dependency (extension surface,
milestone-blocked, breaking change).

### Multi-pass review accretes propagation gaps; grep after every applied fix

A 5-phase review on a 338-line RFC produced 80+ findings across
Phases 1-4. Three of the "applied" fixes (a Kind split, a ClusterRole
rename, a cross-doc reference qualification) each landed correctly
in the section that raised the finding but were missed in one to
three sibling sections of the same RFC. Phase 3's adversarial pass
caught the propagation gaps by grepping the whole file for every
introduced or removed symbol. The fix is mechanical (one Edit per
sibling site) but the reviewer who DOESN'T grep ships the
inconsistency.

Anchor: RFC-0010 commit `63dccbb` (the adversarial-review pushback
table) — specifically the `KindCardinality` split at line 188 missed
line 172 and line 368; the `tracecore-containerstdout-clusterrole`
rename at line 196 missed line 369. Both caught only because the adversarial
reviewer ran `grep -n` against the whole file after reading the
diff. Promoted to a binding RFC-authoring rule at
[`docs/rfcs/README.md` § Authoring conventions](../rfcs/README.md#authoring-conventions-binding-derived-from-rfc-0009--rfc-0010-review-trail).

### Rubric self-violation sneaks in when the rubric is fresh

When a review phase accepts a new binding rubric ("alpha-receiver
RFCs MUST contain §Operator-surfaces"), the same phase's "deferred
to FOLLOWUPS" list tends to include exactly the work the new rubric
forbids deferring. The rubric is too new to feel binding to the
author; deferring is the path of least resistance. The next phase
catches the violation — at which point the cost to inline the
deferred work is mechanical (one new subsection) but the cycle ran
twice. Lesson: when a phase proposes AND accepts a rubric in the same
session, the synthesis step MUST re-check the current PR's deferral
list against the new rubric before committing.

Anchor: RFC-0010 Phase-2 accepted "alpha-receiver RFCs MUST contain
§Operator-surfaces" AND deferred the §Operator-surfaces subsection to
FOLLOWUPS in the same commit. Phase-4 A+ pass flagged it; commit
`be3db09` (the A+ aspiration pushback table) inlined the section.
One avoidable cycle.

### Single-maintainer projects collapse stakeholder-meeting processes to solo decision exercises

Multi-stakeholder design RFCs often include a §"How to resolve OD-N
in one week" section presuming roles like "M16 owner, O2 stakeholder,
milestone-planning lead". In a single-maintainer project, all three
roles are the same person; the literal stakeholder meeting collapses
to a ~1-hour solo decision exercise (pre-declare M16's preferred
implementation approach; decide O4 namespace posture; record OD
resolution in a decision artifact). The RFC framing presuming a team
is still correct for the project's eventual multi-maintainer state
but should not block solo execution today.

Anchor: RFC-0010 § 15.6 reads as a multi-stakeholder meeting agenda
but was actually resolved by Tree wearing all three hats in ~30
minutes during the session that closed PR #94. Documented for the
next single-maintainer RFC author so they don't read the framing as
a literal blocker.
31 changes: 31 additions & 0 deletions docs/rfcs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,34 @@ naming inconsistency (`0006` is `RFC-0006-*.md`, others are
the old one. The superseded RFC's `Status:` flips to
`superseded by RFC-NNNN` and the body stays in-tree as historical
record.

## Authoring conventions (binding, derived from RFC-0009 + RFC-0010 review trail)

Apply to every receiver-scope RFC. Each rule is falsifiable by the grep / test stated.

**Required sections in alpha-receiver RFCs:**

- §Operator surfaces — names `components/receivers/<name>/RUNBOOK.md`, `prometheus-alerts.example.yaml`, and `docs/FAILURE-MODES.md` rows as Phase-4 deliverables (one alert row per `IncError(Kind)`). Inline OR explicitly waive with a stated reason. Falsifying: `grep -L "RUNBOOK.md\|prometheus-alerts" docs/rfcs/000[7-9]*.md docs/rfcs/0010*.md docs/rfcs/0011*.md` returns empty.
- §Rubric trace appendix — table mapping every MILESTONES.md `M<X>` rubric line to the RFC subsection that addresses it (or to a FOLLOWUPS trigger + out-of-scope rationale). Falsifying: row count in the trace table equals bullet count under the rubric block.
- §Performance budget — required when MILESTONES rubric states CPU / RSS / Mbps thresholds. Table of (Concern, Commitment, Falsifying bench). Falsifying: `grep -nE "benchmem|alloc/op|ns/op" docs/rfcs/<RFC>.md` returns ≥1 per stated threshold.

**Required cross-checks:**

- **Wire-attribute name table** when the RFC declares a typed record consumed by downstream receivers — every exported field has a row, and the row's wire-attribute name string greps against the relevant MILESTONES rubric block.
- **Sibling-package symbol compile-resolve** — every `<pkg>.<Sym>` cited in RFC prose must resolve under `git grep -nE "<Sym>\b" components/` at HEAD, OR carry the `(planned per <rubric line>; not yet at HEAD)` marker. "Compile-time pin" / "enforced at compile time" reserved for symbols that resolve today.
- **Cross-RFC join-keys** — label names, attribute namespaces, and any field both M<X> and M<Y> read or write MUST resolve to one canonical spelling at design-lock. Resolve in this PR or the sibling RFC's PR; do not defer to "whichever lands first" (the second author pays).

**Review-hygiene gates (apply during the review of an RFC PR):**

- **Symbol consistency after every applied fix** — when a fix renames or splits a symbol (Kind, ClusterRole, attribute), grep the whole RFC for the old name before commit. Phase-N "applied" findings consistently miss sibling-section propagation; the grep audit closes the loop.
- **FOLLOWUPS entries resolved by the closing PR** MUST be struck-through with a "Resolved by RFC-XXXX §Y" pointer, not silently left as open boxes. Preserves the audit trail and prevents inverse-drift (FOLLOWUPS rows that no longer correspond to live deferrals).

## Component registration (receiver factory codegen)

Receivers register via `cmd/tracecore/components.yaml` + `make generate`:

1. Add a new receiver entry to `cmd/tracecore/components.yaml` with `type:` and `package:` keys (sorted alphabetically; the generator enforces order).
2. Run `make generate` to regenerate `cmd/tracecore/components.go` from the YAML. Do NOT hand-edit the generated file — the header carries a `DO NOT EDIT` warning.
3. The generator (`tools/components-gen/main.go`) emits an import alias and a factory map entry like `pipeline.MustNewType("<type>"): <alias>.NewFactory()`.

This is the only file edit the registration step requires; the receiver's own factory function lives in `components/receivers/<name>/factory.go` per the [`0004-clockreceiver-stdoutexporter.md`](0004-clockreceiver-stdoutexporter.md) contract.