Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ecf3f35
M1: quality-report -coverage-out flag + per-package TSV regen helper
randomizedcoder May 20, 2026
ffa1514
M2: update-quality-report --with-microvm wiring
randomizedcoder May 20, 2026
c75780b
docs: refresh report after M1-M2 — microvm merge → overall 91.1%
randomizedcoder May 20, 2026
63ee929
M4: also merge microvm-coverage-iouring VM coverage
randomizedcoder May 20, 2026
66fd7fb
docs: refresh report after M4 — iouring VM merged → overall 91.7%
randomizedcoder May 20, 2026
b229f3e
M5: self-test ns-lifecycle + TCP-in-ns checks (drive ns_watch/nsAdd/D…
randomizedcoder May 20, 2026
59cacc9
Fix prom-label key in NS_LIFECYCLE + NS_TRAFFIC checks
randomizedcoder May 20, 2026
0948ea5
Add diagnostics to NS_LIFECYCLE check + fix NS_TRAFFIC label
randomizedcoder May 20, 2026
7a606c2
Suppress SC2012 in NS_LIFECYCLE diagnostic ls
randomizedcoder May 20, 2026
675123c
Fix metric_value label filter — Prom orders labels alphabetically
randomizedcoder May 20, 2026
9d9bb29
Fix lint findings: noctx + unused + unconvert + gofmt
randomizedcoder May 20, 2026
309c38c
Cover redisClientAdapter Publish/Ping/Close methods
randomizedcoder May 20, 2026
8db6dec
M6: exercise /run/docker/netns/ watch path (NS_DOCKER check)
randomizedcoder May 20, 2026
aafcbc2
docs: refresh report after M6 — pkg/xtcp 89.2% → 89.4%
randomizedcoder May 20, 2026
3b19fcb
Fix Check 3 NETLINK + Check 5 GRPC_ROUNDTRIP — coverage VM OVERALL_PASS
randomizedcoder May 20, 2026
cf2895a
NetlinkerIoUring: emit the parsed-socket count counter
randomizedcoder May 20, 2026
d03bf5b
docs: refresh report — both coverage VMs OVERALL_PASS for the first time
randomizedcoder May 20, 2026
7ec6183
Delete dead registerProtobufSchemaRestful + add newKafkaDest debug-lo…
randomizedcoder May 20, 2026
81a55b3
gofmt cleanup after kafka dead-code removal
randomizedcoder May 20, 2026
e29c6b4
Fix SA9003 + refresh report
randomizedcoder May 20, 2026
588f710
docs: refresh report — 0 findings, 92.4% coverage, all checks green
randomizedcoder May 20, 2026
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
10 changes: 8 additions & 2 deletions cmd/xtcp2client/xtcp2client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ const (
signalChannelSizeCst = 10

tagertHostnameCst = "localhost"
grpcPortCst = "8888"
// grpcPortCst MUST match the xtcp2 daemon's default in cmd/xtcp2
// (currently 8889). Keeping these in sync is a footgun — a future
// CLAUDE: the daemon's port is exposed via a const in cmd/xtcp2,
// and shipping them out-of-step turns every gRPC roundtrip into a
// silent connection refused.
grpcPortCst = "8889"

pollFrequencyCst = 10 * time.Second

Expand Down Expand Up @@ -116,6 +121,7 @@ func runMain(ctx context.Context, args []string, stdout, stderr io.Writer) int {
fs := flag.NewFlagSet("xtcp2client", flag.ContinueOnError)
fs.SetOutput(stderr)
target := fs.String("target", tagertHostnameCst, "Target hostanme")
port := fs.String("port", grpcPortCst, "Target gRPC port (must match the xtcp2 daemon's -grpcPort flag)")
poll := fs.Bool("poll", false, "poll mode means the client will trigger polling via the PollFlatRecords service")
pollFrequency := fs.Duration("pollFrequency", pollFrequencyCst, "poll mode frequency")
workers := fs.Int("workers", 10, "workers")
Expand All @@ -133,7 +139,7 @@ func runMain(ctx context.Context, args []string, stdout, stderr io.Writer) int {
debugLevel = *d

complete := make(chan struct{}, signalChannelSizeCst)
addr := *target + ":" + grpcPortCst
addr := *target + ":" + *port
if *poll {
pollMode(ctx, addr, &complete, *pollFrequency, *json, debugLevel)
} else {
Expand Down
75 changes: 27 additions & 48 deletions docs/quality-report.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# xtcp2 code-quality report

Generated: 2026-05-20T15:24:56Z
Generated: 2026-05-20T20:35:42Z

Tool versions: go=go1.25.10; golangci-lint=2.12.2; gosec=2.26.1; nixfmt=1.2.0;

Expand All @@ -15,12 +15,12 @@ between commits reveals exactly what changed.

| Metric | Value |
|---|---|
| Total findings | 4 |
| Total findings | 0 |
| Findings (Tier 0) | 0 |
| Findings (Tier 1) | 0 |
| Findings (Tier 2) | 1 |
| Findings (non-tiered) | 3 |
| Files with at least one finding | 4 |
| Findings (Tier 2) | 0 |
| Findings (non-tiered) | 0 |
| Files with at least one finding | 0 |
| Test failures (new) | 0 |
| Test failures (pre-existing) | 0 |
| Config exclusions reviewed | 4 |
Expand All @@ -31,19 +31,19 @@ between commits reveals exactly what changed.

| Tool | Status | Findings | Runtime |
|---|---|---|---|
| golangci-lint (comprehensive) | findings | 1 | 5s |
| golangci-lint (comprehensive) | clean | 0 | 5s |
| golangci-lint (standard) | clean | 0 | 5s |
| golangci-lint (quick) | findings | 1 | 15s |
| golangci-lint (quick) | clean | 0 | 14s |
| gosec | clean | 0 | 1s |
| go vet | clean | 0 | 2s |
| gofmt | findings | 2 | 0s |
| nixfmt | clean | 0 | 1s |
| gofmt | clean | 0 | 1s |
| nixfmt | clean | 0 | 0s |
| netlink-audit | clean | 0 | 0s |
| iouring-audit | clean | 0 | 0s |
| metrics-audit | clean | 0 | 0s |
| proto-field-audit | clean | 0 | 0s |
| go test | clean | 0 | 8s |
| go test -cover | findings | 1 | 0s |
| proto-field-audit | clean | 0 | 1s |
| go test | clean | 0 | 9s |
| go test -cover | clean | 0 | 0s |


---
Expand All @@ -52,40 +52,24 @@ between commits reveals exactly what changed.

| Tier | Linters | Findings | Quick-fixable¹ |
|---|---|---|---|
| 0 (`lint-quick`) | govet, errcheck, ineffassign, unused, staticcheck | 0 | 2 |
| 0 (`lint-quick`) | govet, errcheck, ineffassign, unused, staticcheck | 0 | 0 |
| 1 (`lint` / CI) | Tier 0 + gosec, gocritic, revive, noctx, contextcheck, durationcheck | 0 | 0 |
| 2 (`lint-comprehensive`) | Tier 1 + exhaustive, prealloc, gocyclo, funlen, goconst, dupl, unconvert, nakedret, misspell | 1 | 1 |
| 2 (`lint-comprehensive`) | Tier 1 + exhaustive, prealloc, gocyclo, funlen, goconst, dupl, unconvert, nakedret, misspell | 0 | 0 |

¹ Quick-fixable = produced by a linter that supports `golangci-lint run --fix` (gofmt, goimports, misspell, unconvert, …).

---

## 4. Hotspot files (top 10)

| File | Findings | Top rules |
|---|---|---|
| `pkg/xtcp` | 1 | below-90pct×1 |
| `pkg/xtcp/destinations_kafka_test.go` | 1 | format×1 |
| `pkg/xtcp/destinations_valkey_test.go` | 1 | format×1 |
| `pkg/xtcpnl/xtcpnl_fatalf_test.go` | 1 | unconvert×1 |
*No file-attributed findings.*


---

## 5. Findings by linter

### gofmt / format — 2

- `pkg/xtcp/destinations_kafka_test.go`: file not formatted
- `pkg/xtcp/destinations_valkey_test.go`: file not formatted

### go-test-cover / below-90pct — 1

- `pkg/xtcp`: package coverage 85.2% < 90%

### golangci-lint / unconvert — 1

- `pkg/xtcpnl/xtcpnl_fatalf_test.go:95`: unnecessary conversion
*No linter findings.*

---

Expand All @@ -107,10 +91,10 @@ between commits reveals exactly what changed.

| Status | Count |
|---|---|
| Pass | 1284 |
| Pass | 1290 |
| Fail (new) | 0 |
| Fail (pre-existing) | 0 |
| Skip | 7 |
| Skip | 9 |



Expand All @@ -125,10 +109,8 @@ between commits reveals exactly what changed.

## 10. Format checks

**`gofmt` would reformat (2 files):**
`gofmt`: clean.

- `pkg/xtcp/destinations_kafka_test.go`
- `pkg/xtcp/destinations_valkey_test.go`
`nixfmt`: clean.

---
Expand All @@ -150,17 +132,14 @@ the adjacent YAML comment. Rows with no justification need review.

## 12. Recommendations

- Top contributor: **gofmt/format** with 2 findings (50% of total). Concentrate effort here for the biggest quality win.
- Run `lint-fix` (or `golangci-lint run --fix`) to auto-resolve ~3 quick-fixable findings before manual review.
- Hotspot file: `pkg/xtcp` carries 1 findings (below-90pct×1). Refactor here before touching adjacent code.
- Format files are out of sync — run `gofmt -w .` and `nixfmt **/*.nix` to bring formatting back to baseline.
- No specific recommendations — the codebase is clean across every tier the report measures.


---

## 13. Test coverage

**Overall:** 90.3% of statements (target: 90% per package).
**Overall:** 92.4% of statements (target: 90% per package).

| Package | Coverage | Status |
|---|---|---|
Expand All @@ -171,20 +150,20 @@ the adjacent YAML comment. Rows with no justification need review.
| `cmd/ns` | 93.9% | 🟢 OK |
| `cmd/nsTest` | 94.1% | 🟢 OK |
| `cmd/register_schema` | 91.4% | 🟢 OK |
| `cmd/xtcp2` | 92.4% | 🟢 OK |
| `cmd/xtcp2` | 95.9% | 🟢 OK |
| `cmd/xtcp2_kafka_client` | 93.0% | 🟢 OK |
| `cmd/xtcp2client` | 91.5% | 🟢 OK |
| `cmd/xtcp2client` | 91.6% | 🟢 OK |
| `pkg/io_uring` | 92.6% | 🟢 OK |
| `pkg/misc` | 93.8% | 🟢 OK |
| `pkg/xtcp` | 85.2% | 🔴 below 90% |
| `pkg/xtcpnl` | 91.4% | 🟢 OK |
| `pkg/xtcp` | 90.8% | 🟢 OK |
| `pkg/xtcpnl` | 91.8% | 🟢 OK |
| `tools/iouring-audit` | 95.2% | 🟢 OK |
| `tools/kafka_topic_reader` | 94.7% | 🟢 OK |
| `tools/metrics-audit` | 97.2% | 🟢 OK |
| `tools/netlink-audit` | 95.8% | 🟢 OK |
| `tools/proto-field-audit` | 96.7% | 🟢 OK |
| `tools/quality-report` | 94.5% | 🟢 OK |
| `tools/tcp_client` | 90.3% | 🟢 OK |
| `tools/quality-report` | 92.8% | 🟢 OK |
| `tools/tcp_client` | 93.1% | 🟢 OK |
| `tools/tcp_server` | 94.6% | 🟢 OK |
| `tools/udp_receiver_server` | 97.9% | 🟢 OK |

Expand Down
27 changes: 19 additions & 8 deletions nix/coverage-merge.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
# Usage:
# nix run .#coverage-merge -- \
# --host /path/to/host-coverage.out \
# --vm-dir /path/to/xtcp2cov \
# --vm-dir /path/to/xtcp2cov [--vm-dir /path/to/xtcp2cov-iouring …] \
# --out /tmp/merged.profile
#
# Produces a `mode: set` profile usable with `go tool cover -func`
# or `go tool cover -html`. Uses the host profile's block universe
# (so build-tag-gated destination files don't drag the total down)
# and upgrades the count when a block was also covered in the VM run.
#
# Multiple --vm-dir args are concatenated via `go tool covdata textfmt
# -i a,b,…` so the merge picks up every block any VM run covered.
#
{ pkgs }:

pkgs.writeShellApplication {
Expand All @@ -31,31 +34,39 @@ pkgs.writeShellApplication {
set -euo pipefail

HOST=""
VMDIR=""
VMDIRS=""
OUT=""
while [ $# -gt 0 ]; do
case "$1" in
--host) HOST="$2"; shift 2 ;;
--vm-dir) VMDIR="$2"; shift 2 ;;
--vm-dir)
# Accumulate as a comma-separated list for go tool covdata's -i.
if [ -z "$VMDIRS" ]; then VMDIRS="$2"; else VMDIRS="$VMDIRS,$2"; fi
shift 2
;;
--out) OUT="$2"; shift 2 ;;
-h|--help)
echo "usage: $0 --host <host.out> --vm-dir <covdir> --out <merged.out>"
echo "usage: $0 --host <host.out> --vm-dir <covdir> [--vm-dir <covdir> …] --out <merged.out>"
exit 0
;;
*) echo "unknown arg: $1" >&2; exit 1 ;;
esac
done
if [ -z "$HOST" ] || [ -z "$VMDIR" ] || [ -z "$OUT" ]; then
echo "usage: $0 --host <host.out> --vm-dir <covdir> --out <merged.out>" >&2
if [ -z "$HOST" ] || [ -z "$VMDIRS" ] || [ -z "$OUT" ]; then
echo "usage: $0 --host <host.out> --vm-dir <covdir> [--vm-dir <covdir> …] --out <merged.out>" >&2
exit 1
fi
if [ ! -s "$HOST" ]; then echo "host profile missing: $HOST" >&2; exit 1; fi
if [ ! -d "$VMDIR" ]; then echo "vm dir missing: $VMDIR" >&2; exit 1; fi
# Validate each VMDIR exists.
IFS=, read -ra _dirs <<< "$VMDIRS"
for d in "''${_dirs[@]}"; do
if [ ! -d "$d" ]; then echo "vm dir missing: $d" >&2; exit 1; fi
done

VM_PROFILE=$(mktemp)
trap 'rm -f "$VM_PROFILE"' EXIT

go tool covdata textfmt -i "$VMDIR" -o "$VM_PROFILE"
go tool covdata textfmt -i "$VMDIRS" -o "$VM_PROFILE"

skipPkg='github.com/randomizedcoder/xtcp2/pkg/xtcp_config|github.com/randomizedcoder/xtcp2/pkg/xtcp_flat_record|github.com/randomizedcoder/xtcp2/pkg/clickhouse_protolist'
VM_FILTERED=$(mktemp)
Expand Down
96 changes: 94 additions & 2 deletions nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -148,28 +148,120 @@ let

# User-facing wrapper that refreshes docs/quality-report.md from the
# current source tree. Invoked via `nix run .#update-quality-report`.
#
# With --with-microvm, additionally:
# 1. Boot the coverage-instrumented microvm via
# `nix run .#microvm-x86_64-lifecycle-coverage` and scrape the
# Go coverage data dump from its serial console.
# 2. Merge the VM profile with the host-only profile produced by
# .#quality-report via `nix run .#coverage-merge`.
# 3. Re-run the quality-report aggregator binary with the merged
# profile through the new -coverage-out flag (no Nix rebuild
# needed for the merge step).
# Result: the headline coverage % in docs/quality-report.md
# reflects io_uring + real netlink + namespace paths the host
# sandbox can't exercise.
updateQualityReport = pkgs.writeShellApplication {
name = "xtcp2-update-quality-report";
runtimeInputs = with pkgs; [
coreutils
git
versions.go
];
text = ''
set -eu

WITH_MICROVM=0
while [ $# -gt 0 ]; do
case "$1" in
--with-microvm) WITH_MICROVM=1; shift ;;
-h|--help)
echo "usage: update-quality-report [--with-microvm]"
exit 0
;;
*) echo "unknown arg: $1" >&2; exit 2 ;;
esac
done

if [ ! -f flake.nix ]; then
echo "update-quality-report: must be run from the xtcp2 repo root" >&2
exit 2
fi

# Step 1: optionally run both microvm-coverage lifecycles
# (stdlib + iouring) and collect their coverage scrape dirs.
# Each variant exercises different code paths inside the daemon
# — the iouring one is the only way to reach the netlinkerIoUring
# body without a real io_uring-capable kernel.
VMDIR_STD=""
VMDIR_IOU=""
if [ "$WITH_MICROVM" = "1" ]; then
VMDIR_STD="$(mktemp -d -t xtcp2cov-std-XXXXXX)"
echo "==> running .#microvm-x86_64-lifecycle-coverage (stdlib)"
echo " scrape dir: $VMDIR_STD"
XTCP2_COVERDIR="$VMDIR_STD" \
nix run --accept-flake-config .#microvm-x86_64-lifecycle-coverage \
|| echo "WARNING: stdlib microvm lifecycle exited non-zero; coverage may be partial"

VMDIR_IOU="$(mktemp -d -t xtcp2cov-iou-XXXXXX)"
echo "==> running .#microvm-x86_64-lifecycle-coverage-iouring"
echo " scrape dir: $VMDIR_IOU"
XTCP2_COVERDIR="$VMDIR_IOU" \
nix run --accept-flake-config .#microvm-x86_64-lifecycle-coverage-iouring \
|| echo "WARNING: iouring microvm lifecycle exited non-zero; coverage may be partial"

n_std=$(find "$VMDIR_STD" -type f 2>/dev/null | wc -l)
n_iou=$(find "$VMDIR_IOU" -type f 2>/dev/null | wc -l)
echo "==> microvm coverage files: stdlib=$n_std iouring=$n_iou"
if [ "$n_std" -eq 0 ] && [ "$n_iou" -eq 0 ]; then
echo "WARNING: no coverage files scraped from either VM; falling back to host-only"
WITH_MICROVM=0
fi
fi

echo "==> building .#quality-report (Tier 2 takes ~10 min on a cold cache;"
echo " Nix-cached on subsequent runs)"
result=$(nix build --no-link --print-out-paths --accept-flake-config .#quality-report)

mkdir -p docs
cp "$result/quality-report.md" docs/quality-report.md
chmod +w docs/quality-report.md

if [ "$WITH_MICROVM" = "1" ]; then
echo "==> merging host + microvm coverage profiles"
MERGED=$(mktemp -t merged-cov-XXXXXX.out)
# nix run .#coverage-merge handles host+VM merge: produces a
# mode-set profile keyed on the host's block universe with
# counts upgraded where any VM run also covered the block.
# Multiple --vm-dir flags are union-merged via covdata textfmt.
MERGE_ARGS=(--host "$result/raw/coverage.out" --out "$MERGED")
n_std=$(find "$VMDIR_STD" -type f 2>/dev/null | wc -l)
n_iou=$(find "$VMDIR_IOU" -type f 2>/dev/null | wc -l)
if [ "$n_std" -gt 0 ]; then MERGE_ARGS+=(--vm-dir "$VMDIR_STD"); fi
if [ "$n_iou" -gt 0 ]; then MERGE_ARGS+=(--vm-dir "$VMDIR_IOU"); fi
nix run --accept-flake-config .#coverage-merge -- "''${MERGE_ARGS[@]}" >&2

# Copy raw/ to a writable temp dir so we can re-run the
# aggregator with the merged profile in-place. The Nix store
# path is read-only; we need a writable rawDir for the
# -coverage-out regeneration step.
MERGED_RAW=$(mktemp -d -t merged-raw-XXXXXX)
cp -r "$result/raw/." "$MERGED_RAW/"
chmod -R +w "$MERGED_RAW"

echo "==> re-running quality-report with merged profile"
go run ./tools/quality-report \
-raw-dir "$MERGED_RAW" \
-repo-root . \
-known-failures ./tools/quality-report/known-failures.txt \
-coverage-baseline ./docs/coverage-baseline.txt \
-coverage-max-drop 0.5 \
-coverage-out "$MERGED" \
> docs/quality-report.md \
|| echo "WARNING: aggregator exited non-zero; report may be incomplete"
else
cp "$result/quality-report.md" docs/quality-report.md
fi

chmod +w docs/quality-report.md
echo
echo "==> wrote docs/quality-report.md"

Expand Down
Loading