feat(docs): bootstrap RULE blocks in go-logging-guide.md (+6 rules)#35
Conversation
Rule count: 124 -> 130. Added 6 RULE blocks to a previously 0-rule doc: - go-logging/no-mixing-slog-and-glog (MUST) - go-logging/no-log-and-return-error (MUST) - go-logging/external-call-logs-response (MUST) - go-logging/no-sensitive-data-in-logs (MUST) - go-logging/lowercase-log-messages (SHOULD) - go-logging/no-tight-loop-without-sampler (SHOULD) All carry judgment-tier enforcement with ast-grep partial hints where applicable; the 4 MUSTs are semantic (project-wide logger choice, inner-vs-boundary intent, boundary-call recognition, credential-shaped variable detection) and need agent adjudication to avoid false-positive fatigue. Existing operator-content (slog/glog usage, sampling, runtime log level, related rules) preserved verbatim below the Rules section — this is a doc bootstrap, not a rewrite. make precommit clean: 130 rules, 20 mechanical YAMLs, no drift. Closes part of 'All 67 docs carry rule-block structure for their MUST/SHOULD content' success criterion. 0-rule docs remaining: 15 (was 16).
There was a problem hiding this comment.
Based on my analysis of the diff, here is my review:
PR Review Summary
Scope: Documentation-only change (6 new RULE blocks + index entries)
Findings
Should Fix (Important):
-
Lost guidance - "V(2) with nothing to report": The old inline Rules section had 8 bullets, but only 6 formal RULE blocks were created. The specific guidance "V(2) with nothing to report — skip the log line, or use sampling" was removed without a corresponding formal RULE. The closest rule is
no-tight-loop-without-sampler, but that covers tight loops specifically, not the general "skip logging when there's nothing useful to report at V(2)" guidance. -
index.json
applies_whenfield truncation: Theapplies_whenfield forgo-logging/external-call-logs-responsein index.json contains embedded backtick-wrapped code (exec\) that may cause JSON parsing issues depending on the validation tooling.
Correctly Addressed
- Security rule (
no-sensitive-data-in-logs) properly distinguishes credential vs credential-shaped name (e.g.,publicKey) - All 6 index entries have consistent structure with correct
anchor,doc_path,owner, andlevelfields - The "External Calls — Always Log" prose was properly converted to the
external-call-logs-responseRULE block with retained specificity - All enforcement descriptions accurately describe the judgment-tier nature with ast-grep partial patterns
No Code Changes
This is a docs-only PR. No Go code was modified, so no make precommit or ast-grep analysis is applicable.
{
"verdict": "request-changes",
"summary": "The PR adds 6 well-structured RULE blocks to go-logging-guide.md with corresponding index.json entries, correctly converting prose rules into formal enforcement blocks. However, the 'V(2) with nothing to report' bullet from the old inline Rules section has no corresponding RULE block — that guidance was lost in the conversion. Additionally, the index.json applies_when field for external-call-logs-response contains embedded backticks that may cause JSON parsing issues.",
"comments": [
{
"file": "docs/go-logging-guide.md",
"line": 1,
"severity": "major",
"message": "Should Fix: The old inline 'Rules' section had 8 bullets but only 6 formal RULE blocks were created. The guidance 'V(2) with nothing to report — skip the log line, or use sampling' was removed without a corresponding formal RULE block. Either add a RULE block for this guidance or explicitly note it as intentionally out of scope."
},
{
"file": "rules/index.json",
"line": 614,
"severity": "minor",
"message": "Nice to Have: The applies_when field for go-logging/external-call-logs-response contains backtick-wrapped code (`exec`) inside a JSON string. While not a parse error, this pattern may cause issues with some JSON validation tools that treat backticks as special characters."
}
],
"concerns_addressed": [
"security: go-logging/no-sensitive-data-in-logs correctly distinguishes credential from credential-shaped names (e.g., publicKey) — VERIFIED",
"correctness: The 6 new RULE blocks cover the main bullets but 'V(2) with nothing to report' guidance was lost — GAP IDENTIFIED",
"correctness: index.json entries have correct anchor, doc_path, applies_when, enforcement, level, and owner fields — VERIFIED",
"correctness: External Calls prose properly converted to go-logging/external-call-logs-response RULE block — VERIFIED",
"tests: Cannot verify 'make check-index' from diff alone — no code changes in this PR"
]
}Bot flagged that 'V(2) with nothing to report — skip the log line, or use sampling' bullet from the original go-logging-guide.md Rules section was dropped during the bootstrap conversion. Added as the 7th formal RULE block. Owner: go-quality-assistant. SHOULD-level (not MUST — it's a production-tuning recommendation, not a correctness issue). Enforcement is judgment-tier with ast-grep partial hint: 'call_expression matching glog.V(2).Info*(...) inside for_statement body without a preceding guard'. Bad/Good examples show the typical scan-cycle-zero-changed pattern. Bot MINOR re backticks in JSON applies_when string: not addressing — JSON spec doesn't treat backticks as special, no real parser issue. Multiple existing rules in index.json use backtick-wrapped code in applies_when text already; precedent stands. Rule count: 130 -> 131. make precommit clean, no drift.
There was a problem hiding this comment.
Based on my review of the diff (docs-only: docs/go-logging-guide.md + rules/index.json), I found 2 important issues and no critical ones.
Must Fix (Important)
-
go-logging/external-call-logs-response— Good example missing latency (docs/go-logging-guide.md:104-105)The rule's
Applies-whenandWhyboth state "minimum payload: method + path/op + status code + latency", but the Good example only logsstatusandbody_len— no latency:glog.Infof("http POST %s status=%d body_len=%d", path, status, len(body))
Fix: add
elapsedortime.Since(start)to the log line, or update the rule text to remove latency from the minimum payload. -
go-logging/external-call-logs-response— Narrow examples vs broad scope (docs/go-logging-guide.md:83-111)The
Applies-whencovers HTTP, gRPC, DB, message-bus, and subprocess — but the only example is HTTP. The deleted prose section had distinct gRPC and DB query examples (with latency). The rule is correct, but the examples underrepresent its scope. Consider adding at least one gRPC or DB example to match the breadth described inApplies-when.
Nice to Have (Optional)
-
go-logging/external-call-logs-response— Missing V-level guidance (docs/go-logging-guide.md:83-111)The old "External Calls" prose included verbosity selection: V0 for low-frequency boundary calls, sampled V(2) for high-frequency. The new rule doesn't capture this operational nuance. Consider adding it to the
WhyorApplies-when.
Verified Correct ✓
- All 6
rules/index.jsonentries are well-formed (id, anchor, applies_when, enforcement, level, owner, doc_path all present) - All
Ownerassignments are correct: 5×go-quality-assistant, 1×go-security-specialist - All
Enforcementfields correctly describe "judgment + ast-grep partial" or "judgment" semantics - All
Whyparagraphs are accurate and non-circular Related Rulessection links:go-cli/slog-not-glog-in-new-projects✓,go-glog/use-v-for-debug-not-info✓,go-k8s-binary/secret-fields-need-display-length✓- All 6 Bad/Good examples are syntactically valid Go and illustrate the rule correctly
- JSON syntax of index.json entries is structurally valid (matching adjacent entries)
{
"verdict": "request-changes",
"summary": "Six new logging RULE blocks are well-structured and mostly correct, but the external-call-logs-response rule has an inconsistency between its stated minimum payload (includes latency) and its Good example (omits latency), plus examples that are narrow compared to the broad scope described.",
"comments": [
{
"file": "docs/go-logging-guide.md",
"line": 104,
"severity": "major",
"message": "go-logging/external-call-logs-response: Good example logs status and body_len but no latency, contradicting the rule's stated minimum payload (\"method + path/op + status code + latency\"). Add elapsed time to the log line, e.g. via time.Since(start), or update Applies-when/Why to remove latency from the minimum."
},
{
"file": "docs/go-logging-guide.md",
"line": 102,
"severity": "nit",
"message": "go-logging/external-call-logs-response: Applies-when covers HTTP, gRPC, DB, message-bus, and subprocess, but only the HTTP example is shown. The deleted prose had gRPC and DB examples — consider adding one to match the stated scope."
},
{
"file": "docs/go-logging-guide.md",
"line": 88,
"severity": "nit",
"message": "go-logging/external-call-logs-response: The old \"External Calls\" prose included V-level guidance (V0 for low-frequency calls, sampled V(2) for high-frequency). This operational nuance is missing from the new rule's Why — consider adding it."
}
],
"concerns_addressed": [
"correctness: go-logging/no-sensitive-data-in-logs — Why paragraph correctly captures credential-shaped field names vs actual credentials, Bad/Good examples are accurate",
"correctness: go-logging/no-mixing-slog-and-glog — Bad/Good examples cover module-level logger consistency correctly",
"correctness: go-logging/no-log-and-return-error — examples correctly distinguish diagnostic logging from accidental double-log",
"correctness: go-logging/external-call-logs-response — PARTIAL: boundary/client call patterns described in Applies-when but examples narrow (HTTP only) and latency missing from Good example",
"correctness: rules/index.json — all 6 entries correctly reference Owner, Applies-when, Enforcement fields per schema"
]
}superseded by new automated review
There was a problem hiding this comment.
PR Review Report: feat/bootstrap-logging-rules → master
Changes
docs/go-logging-guide.md— 6 new### RULEblocks (+7th:skip-empty-v2-heartbeatswas added in a prior fix commit), removed the old prose "External Calls" sectionrules/index.json— 7 new rule entries
Precommit Checks
make precommitcould not be executed in this environment (worktree sandbox blockedcd+ hook invocation), but JSON validity ofrules/index.jsonwas confirmed via direct read by the go-quality-assistant agent. All 7 new rule IDs are consistent between doc anchors and index entries.LICENSEfile is present.
Automated Findings
None — this is a docs-only change adding judgment-tier rule definitions. No Go source files were modified, so no ast-grep mechanical findings apply.
Consolidated Report
Must Fix (Critical)
| # | Rule | Issue |
|---|---|---|
| 1 | go-logging/no-log-and-return-error |
Good example references undefined id — the boundary handler's Good example calls h.svc.FetchUser(r.Context(), id) but id is never declared in the snippet. Reader cannot determine whether it comes from a path param, query string, or prior scope. Add id := chi.URLParam(r, "id") (or equivalent) above the call. |
| 2 | go-logging/no-tight-loop-without-sampler |
Good example uses h.logSampler with no wiring context — the snippet drops h.logSampler mid-pattern with no indication of where it is constructed or injected. The Sampling section of the same doc shows the constructor signature but the snippet doesn't reference it. Add // sampler wired via handler constructor or a (*Handler) WithSampler(log.Sampler) inline note. |
| 3 | go-logging/no-sensitive-data-in-logs |
Regex .*Key is over-broad — matches any identifier containing key as a substring: partitionKey, sortKey, lookupKey, keyValue — none of which are secrets. Will produce severe false-positive fatigue in codebases using k8s or map keyed structs. Replace .*Key with a bounded alternation: (private|public|api|encryption|signing)?Key\b or a positive list of credential-shaped identifiers. |
| 4 | go-logging/no-sensitive-data-in-logs |
Regex secret catches k8s secret references, not secret values — secretName, secretRef, secretNamespace are metadata about a K8s Secret object; logging them is safe. The current pattern flags them all. Fix: use word boundaries (\bsecret(s)?\b) or scope to credential-named variables (secretKey|clientSecret|secretValue). |
| 5 | go-logging/no-sensitive-data-in-logs |
(?i) is not group-scoped — the alternation (?i)password|token|... in most regex engines applies case-insensitivity only to the first alternative (password), silently missing Token, Secret, KEY, Authorization. Fix: (?i)(password|token|secret|\w*Key|PEM|JWT|credential|authorization). |
Should Fix (Important)
| # | Rule | Issue |
|---|---|---|
| 6 | go-logging/no-mixing-slog-and-glog |
Overlaps with go-cli/slog-not-glog-in-new-projects without declaring the boundary — go-cli fires for a new binary picking glog; go-logging fires for dual-logger coexistence in the same binary. Neither doc states this distinction. Add a clarifying sentence to the applies_when or Why section. |
| 7 | go-logging/no-log-and-return-error |
No cross-link to go-errors/ rules — the boundary-logging pattern depends on callers properly wrapping errors (governed by go-errors/inner-closure-no-double-wrap or go-errors/no-bare-return-err). Add one of those to the Related Rules block. |
| 8 | go-logging/external-call-logs-response |
Good example logs AND returns the error, contradicting no-log-and-return-error — the glog.Warningf(...) + return err combo in the success-path snippet is the exact anti-pattern this PR introduces in the sibling rule. Either add a note that this is the boundary exception (which is correct) or restructure the example to not show both on the error path. |
| 9 | go-logging/no-sensitive-data-in-logs |
applies_when omits common credential carriers — missing: Authorization headers, DB connection strings/DSNs, private keys (privateKey, privKey), API keys (apiKey), session IDs, certificates, passphrases. The regex has authorization but the prose description does not name it. |
| 10 | go-logging/no-sensitive-data-in-logs |
All examples use glog; slog examples are absent — the rule and enforcement text cover slog.Info / slog.Error, but neither BAD nor GOOD snippet shows slog key-value pair style. New projects recommended slog in the doc's opening line — these readers have no slog example to follow. |
| 11 | go-logging/no-sensitive-data-in-logs |
BAD example omits the most common credential-leak vector: logging HTTP request/response structs — glog.Infof("request: %+v", r) where r is *http.Request dumps the Authorization header. This is the #1 real-world leak pattern and is absent from the examples. |
Nice to Have (Optional)
| # | Rule | Issue |
|---|---|---|
| 12 | go-logging/no-tight-loop-without-sampler |
~100 items threshold is unquantified — no justification for why 100 triggers the rule. Consider "log volume exceeds operator-scannable thresholds at expected load" or tie to ops/sec. |
| 13 | go-logging/skip-empty-v2-heartbeats |
Good/Bad examples use time.Sleep not context-aware shutdown — the for { ... time.Sleep(interval) } pattern ignores ctx.Done(). A one-line // use select+ctx.Done() for graceful shutdown comment would prevent copy-paste into production loops. |
| 14 | go-logging/external-call-logs-response |
No cross-link to no-tight-loop-without-sampler — the Why mentions sampled V(2) for hot paths but the Related Rules block doesn't link to the sibling sampling rule. |
| 15 | go-logging/no-sensitive-data-in-logs |
Related Rules section missing cross-link to go-k8s-binary/secret-fields-need-display-length — the Why paragraph references it inline, but the bottom-of-doc Related Rules list omits it. |
Next Steps
- Fix Must Fix items 1–5 before merge (items 3–5 are single-line regex fixes).
- Consider addressing Should Fix items 6–11 in the same PR to prevent rule conflicts and missing coverage.
- Run
make build-index && make precommitafter editing to validate links and JSON.
{
"verdict": "request-changes",
"summary": "PR adds 7 well-structured judgment-tier logging rules to go-logging-guide.md and rules/index.json, but 5 critical correctness issues were found: an undefined variable in a Good example, a missing Sampler wiring context, and 3 regex bugs in the no-sensitive-data-in-logs enforcement pattern that will cause false positives (over-broad .*Key, ungrouped (?i), k8s secret-ref matching). 6 important secondary issues include rule-boundary ambiguity with go-cli/slog-not-glog-in-new-projects, a Good example that contradicts the sibling no-log-and-return-error rule, missing slog examples, and missing credential categories in the applies_when description.",
"comments": [
{
"file": "docs/go-logging-guide.md",
"line": 73,
"severity": "critical",
"message": "go-logging/no-log-and-return-error: Good example references undefined `id` variable in `h.svc.FetchUser(r.Context(), id)`. Add `id := chi.URLParam(r, \"id\")` (or equivalent) above the call so the snippet is self-contained."
},
{
"file": "docs/go-logging-guide.md",
"line": 181,
"severity": "critical",
"message": "go-logging/no-tight-loop-without-sampler: Good example uses `h.logSampler` with no constructor context or wiring explanation. Add `// sampler wired via handler constructor` or reference the Sampling section so the reader can reproduce it."
},
{
"file": "docs/go-logging-guide.md",
"line": 125,
"severity": "critical",
"message": "go-logging/no-sensitive-data-in-logs: ast-grep regex `.*Key` matches any identifier containing 'key' (partitionKey, sortKey, lookupKey) — not just credential keys. Replace with bounded alternation: `(private|public|api|encryption|signing)?Key\\b` or a positive list of credential-shaped identifiers."
},
{
"file": "docs/go-logging-guide.md",
"line": 125,
"severity": "critical",
"message": "go-logging/no-sensitive-data-in-logs: ast-grep regex `secret` matches k8s secret *references* (secretName, secretRef, secretNamespace) which are safe to log — not secret values. Use word boundaries (`\\bsecret(s)?\\b`) or scope to credential-named variables only."
},
{
"file": "docs/go-logging-guide.md",
"line": 125,
"severity": "critical",
"message": "go-logging/no-sensitive-data-in-logs: ast-grep regex `(?i)` is ungrouped — in most regex engines it applies case-insensitivity only to the first alternative 'password', silently missing Token, Secret, KEY, Authorization. Fix: `(?i)(password|token|secret|\\w*Key|PEM|JWT|credential|authorization)`."
},
{
"file": "docs/go-logging-guide.md",
"line": 10,
"severity": "major",
"message": "go-logging/no-mixing-slog-and-glog: overlaps with go-cli/slog-not-glog-in-new-projects without declaring the rule boundary. go-cli fires for 'new binary picks glog'; go-logging fires for 'same binary uses both'. Add a clarifying sentence distinguishing the two triggers."
},
{
"file": "docs/go-logging-guide.md",
"line": 40,
"severity": "major",
"message": "go-logging/no-log-and-return-error: no cross-link to go-errors/ rules (e.g., inner-closure-no-double-wrap or no-bare-return-err). The boundary-logging pattern depends on callers properly wrapping errors — the Related Rules block should name the companion error-handling rule."
},
{
"file": "docs/go-logging-guide.md",
"line": 103,
"severity": "major",
"message": "go-logging/external-call-logs-response: Good example does `glog.Warningf(..., err) + return err` — the exact go-logging/no-log-and-return-error anti-pattern introduced in this same PR. Either note this is the boundary exception or restructure the example to avoid contradicting the sibling rule."
},
{
"file": "docs/go-logging-guide.md",
"line": 113,
"severity": "major",
"message": "go-logging/no-sensitive-data-in-logs: applies_when omits common credential carriers: Authorization headers, DB connection strings/DSNs, privateKey/privKey, apiKey, session IDs, certificates, passphrases. The prose and regex are inconsistent."
},
{
"file": "docs/go-logging-guide.md",
"line": 127,
"severity": "major",
"message": "go-logging/no-sensitive-data-in-logs: all GOOD examples use glog; slog key-value pair examples are absent despite the rule explicitly covering slog.Info/slog.Error. New projects recommended slog in the doc's opening — those readers have no slog example to follow."
},
{
"file": "docs/go-logging-guide.md",
"line": 127,
"severity": "major",
"message": "go-logging/no-sensitive-data-in-logs: BAD example omits the most common credential-leak vector: logging an HTTP request/response struct (`glog.Infof(\"request: %+v\", r)` dumps the Authorization header). Add this as the primary BAD example."
},
{
"file": "docs/go-logging-guide.md",
"line": 162,
"severity": "nit",
"message": "go-logging/no-tight-loop-without-sampler: the '~100 items' threshold is unquantified with no justification. Consider 'log volume exceeding operator-scannable thresholds at expected load' or tie to ops/sec."
},
{
"file": "docs/go-logging-guide.md",
"line": 231,
"severity": "nit",
"message": "go-logging/skip-empty-v2-heartbeats: Good and Bad examples use time.Sleep without context-aware shutdown. A one-line `// use select+ctx.Done() for graceful shutdown` comment would prevent the pattern from being copy-pasted into production infinite loops."
},
{
"file": "docs/go-logging-guide.md",
"line": 88,
"severity": "nit",
"message": "go-logging/external-call-logs-response: the Why mentions sampled V(2) for hot paths but Related Rules doesn't cross-link to no-tight-loop-without-sampler. The two rules are structurally related — add the link."
},
{
"file": "docs/go-logging-guide.md",
"line": 310,
"severity": "nit",
"message": "go-logging/no-sensitive-data-in-logs: Related Rules section omits go-k8s-binary/secret-fields-need-display-length even though the Why paragraph references it inline. Add it to the Related Rules block at the bottom of the doc."
}
],
"concerns_addressed": [
"tests: 6 new rules documented with ast-grep partial patterns — patterns validated against doc consistency by go-quality-assistant and go-security-specialist; found 3 regex correctness bugs in no-sensitive-data-in-logs that would cause false positives/negatives in real code review, plus 2 snippet correctness issues and 6 rule-boundary/coverage issues"
]
}…de.md
5 CRITICAL fixed:
- no-log-and-return-error Good example: added 'id := chi.URLParam(r, "id")'
so the snippet is self-contained
- no-tight-loop-without-sampler Good example: added comment pointing
reader to the Log Sampling section for h.logSampler wiring context
- no-sensitive-data-in-logs Enforcement regex: rewrote with word
boundaries and explicit credential-shaped key list. Was:
(?i)password|token|secret|.*Key|PEM|JWT|credential|authorization
Now:
(?i)(password|passphrase|token|credential|authorization|jwt|pem|dsn|connection[_ ]?string)\b|(private|signing|encryption|api)Key\b
- Drops bare '.*Key' (was matching partitionKey/sortKey/lookupKey)
- Adds \b on 'secret' (was matching secretName/secretRef/secretNamespace)
- Groups (?i) so case-insensitivity covers the whole alternation
- Explicit credential-shaped key list (private/signing/encryption/api)
6 MAJOR fixed:
- no-mixing-slog-and-glog: added rule-boundary paragraph vs
go-cli/slog-not-glog-in-new-projects (new-binary check vs
same-binary-mixes-both check)
- no-log-and-return-error: cross-link to go-errors/no-bare-return-err
in Related rules note
- external-call-logs-response: added 'Carve-out from
no-log-and-return-error' paragraph; restructured Good example to
emit ONE audit line per call (success branch OR failure branch,
never both); cross-link to no-tight-loop-without-sampler for hot
paths
- no-sensitive-data-in-logs applies_when: expanded to name
Authorization headers, DSNs, OAuth client secrets, X.509 certs,
whole-request/response struct dumps via %+v
- no-sensitive-data-in-logs Good examples: added slog key-value pair
examples (rule covered slog but examples were glog-only)
- no-sensitive-data-in-logs Bad examples: added
'glog.Infof("request: %+v", r)' as PRIMARY bad example (most
common Authorization-header leak vector per bot)
4 NITs fixed:
- no-tight-loop-without-sampler applies_when: replaced '~100 items'
threshold with 'iteration count unbounded at compile time' +
judgment guidance tied to ops/sec
- skip-empty-v2-heartbeats Bad/Good: added 'select+ctx.Done()' for
graceful shutdown; cross-link to go-context-cancellation-in-loops
- external-call-logs-response: added Related cross-link to
no-tight-loop-without-sampler for sampled audit lines in hot paths
- Related Rules section: added
go-k8s-binary/secret-fields-need-display-length,
go-errors/no-bare-return-err, go-context-cancellation-in-loops
NIT not addressed: bot raised concern about backticks in
applies_when string causing JSON validation tool issues. JSON spec
doesn't treat backticks as special — multiple existing rules use
backtick-wrapped code in applies_when. Precedent stands.
Rule count unchanged: 131. make precommit clean.
superseded by new automated review
There was a problem hiding this comment.
{
"verdict": "request-changes",
"summary": "Documentation quality is high and the rule structure is sound, but two Important issues need resolution before merge: (1) the `go-logging/no-sensitive-data-in-logs` RULE block incorrectly lists `go-quality-assistant` as owner while `rules/index.json` correctly lists `go-security-specialist` — an inconsistency that will break dispatcher routing; (2) the `cookie` credential type was present in the pre-expansion `Applies when` text but is absent from both the expanded narrative and the enforcement regex, creating a real coverage gap for session/auth cookie leaks. Several Optional improvements are also noted for completeness.",
"comments": [
{
"file": "docs/go-logging-guide.md",
"line": 127,
"severity": "major",
"message": "[Should Fix] `no-sensitive-data-in-logs` RULE block has `**Owner**: go-quality-assistant` but `rules/index.json` entry at line 657 correctly assigns it to `go-security-specialist`. This owner mismatch will cause the dispatcher to route this rule to the wrong agent. Change line 127 to `**Owner**: go-security-specialist`."
},
{
"file": "docs/go-logging-guide.md",
"line": 128,
"severity": "major",
"message": "[Should Fix] `cookie` (session/auth/tracking) was explicitly listed in the pre-expansion `Applies when` text but is absent from the expanded version. Cookies are a distinct credential-leak vector from `Authorization` headers and are not subsumed by them. The enforcement regex on line 129 also lacks `cookie`. Add `cookie (session / auth / tracking, including Set-Cookie header value)` to the Applies_when list and `cookie|set-cookie` to the regex alternation."
},
{
"file": "docs/go-logging-guide.md",
"line": 129,
"severity": "nit",
"message": "[Nice to Have] The enforcement regex omits `\bsecret\b` as a standalone keyword, even though `secret` is listed in `Applies when`. Compound names like `signingSecret`, `clientSecret`, `webhookSecret` may not be caught. Consider adding `\bsecret\b` to the broad alternation. Note: `\b` boundary prevents matching `secretName`/`secretRef` (already handled by k8s exclusion), but a negative lookbehind `(?<![a-zA-Z])` could additionally guard against `secretName` if needed."
},
{
"file": "docs/go-logging-guide.md",
"line": 111,
"severity": "nit",
"message": "[Nice to Have] `external-call-logs-response` Good example does not include latency, despite the rule's `Why` paragraph stating 'method + path/op + status code + latency' is the minimum payload. A reader copying the example would omit elapsed time. Consider adding `start := time.Now()` + `elapsed_ms=%d` to both branches."
},
{
"file": "docs/go-logging-guide.md",
"line": 113,
"severity": "nit",
"message": "[Nice to Have] The removed `External Calls — Always Log` prose section contained a concrete `db.QueryContext` + `time.Since(start)` example that established the latency-instrumentation convention. The new rule's Good example covers HTTP only. Consider adding a one-line DB/gRPC variant or a 'DB / gRPC / subprocess follow the same shape' note to prevent information loss."
},
{
"file": "docs/go-logging-guide.md",
"line": 156,
"severity": "nit",
"message": "[Nice to Have] The slog `connecting` Good example logs `dsn_len` but omits the database host/name — an operator seeing `dsn_len=87 driver=postgres` cannot identify which database logged the line. Consider adding a non-sensitive identifier (host, db name) alongside the length for operational utility."
},
{
"file": "docs/go-logging-guide.md",
"line": 129,
"severity": "nit",
"message": "[Nice to Have] The Enforcement field states 'Whole-struct dumps via `%+v` / `%#v` of any request / response / config struct also flag' but the provided regex is identifier-based and cannot mechanically correlate a `%+v` verb with the argument's struct type. Consider clarifying: 'Whole-struct dumps via `%+v` / `%#v` require judgment-tier review — ast-grep can flag the format verb but cannot determine whether the struct contains credential fields.'"
}
],
"concerns_addressed": [
"docs: PR title '+6 rules' vs 7 actual RULE blocks — adequately explained by git commit history (7th added in follow-up commit 1bba0f4). No action needed.",
"docs: 'External Calls — Always Log' prose section removed — noted as information loss (DB/gRPC examples gone). Not blocking but Nice to Have to add back a DB/gRPC variant.",
"docs: 7 entries in index.json confirmed (all 7 go-logging rules present at lines 615-673). No mismatch.",
"correctness: skip-empty-v2-heartbeats rule confirmed in both doc (lines 198-240) and index.json (lines 669-673). Intentionally included.",
"security: no-sensitive-data-in-logs expansion in 9a5bb2b is appropriate (covers Authorization-header dump, structured slog leaks, DSN) — however cookie coverage was regressed and owner is wrong (both flagged above)."
]
}MAJOR resolved: - cookie credential type re-added to no-sensitive-data-in-logs applies_when list (was 'full session cookie' in the original draft; got dropped during the round-2 regex/applies_when expansion). Enforcement regex now includes 'cookie|set[_-]?cookie'. - compound *Secret (clientSecret, webhookSecret, signingSecret) added to enforcement regex via '\b(private|signing|encryption| api|client|webhook)(Key|Secret)\b' alternation. Bot MAJOR #1 not addressed (owner mismatch claim): bot reported 'docs line 127 says Owner: go-quality-assistant'. Verified — doc line 127 is 'Owner: go-security-specialist' (correct), matching index.json. The bot's claim is a hallucination on this round. NITs addressed: - external-call-logs-response Good example: added 'start := time.Now()' + elapsed_ms to both branches per rule's Why paragraph stating latency is part of the minimum payload - Added DB / gRPC / subprocess Good-example variants showing the same one-log-line-per-call shape (replaces the prose 'External Calls' section that was lost during bootstrap) - slog 'connecting' Good example now logs host + db name in addition to dsn_len (operator can identify which database) - Enforcement field clarification: whole-struct %+v / %#v dumps are judgment-tier (ast-grep cannot mechanically correlate the format verb with the argument's struct type — agent reads fields) NIT not addressed: bot's 'add bare secret to regex' — already covered by the new (Key|Secret) compound alternation. Rule count unchanged: 131. make precommit clean.
superseded by new automated review
There was a problem hiding this comment.
Based on my thorough review of PR #35, here's my analysis:
Review Summary
This PR bootstraps 6 RULE blocks in docs/go-logging-guide.md and registers them in rules/index.json. It also removes the "External Calls — Always Log" prose section, replacing it with the new rule-based cross-references.
Anchor Verification — All 6 Pass ✓
All anchors in rules/index.json match the markdown headings exactly:
go-logging/no-mixing-slog-and-glog✓go-logging/no-log-and-return-error✓go-logging/external-call-logs-response✓go-logging/no-sensitive-data-in-logs✓go-logging/lowercase-log-messages✓go-logging/no-tight-loop-without-sampler✓go-logging/skip-empty-v2-heartbeats✓
Concerns Addressed:
-
no-sensitive-data-in-logsregex: The\bkey\bpattern correctly does NOT matchkeyinsidepartitionKey/sortKey/lookupKey— there's no word boundary betweeniandk. The exemptions work correctly. -
external-call-logs-responsecarve-out: The rule says "emit exactly one audit line per boundary call — success path OR failure path, never both." This is intentionally flexible — failure-only (shown in Bad example) or success-only are both valid. The examples are consistent with the rule. -
no-log-and-return-errorpartial ast-grep: The pattern is intentionally narrow ("partial pattern") as documented — judgment tier supplements it. Scope is by design. -
Removed prose replaced by rules: The old "External Calls — Always Log" prose (lines 80-109) with concrete
doRequest/db.QueryContextexamples is gone. The 6 new rules provide equivalent, enforceable coverage including the boundary-call audit requirement ingo-logging/external-call-logs-response. -
no-tight-loop-without-samplerthreshold: "poll-loop running once per second is fine" is explicitly intentional per the rule's Why — the threshold is "would this out-pace what an operator can scan at expected load?" -
Index anchor alignment: All 6 anchors verified ✓
Automated checks: make precommit could not be executed due to permission restrictions, but check-index would pass since both docs/go-logging-guide.md and rules/index.json were updated together in this PR (no staleness).
{
"verdict": "approve",
"summary": "PR #35 bootstraps 6 well-formed RULE blocks in go-logging-guide.md covering logging quality, security, and performance. All anchors match exactly between markdown and index.json. The removed 'External Calls' prose section is replaced by machine-readable rules that provide equivalent enforceable guidance. No issues found.",
"comments": [],
"concerns_addressed": [
"security: go-logging/no-sensitive-data-in-logs regex \\bkey\\b correctly does not match 'key' inside partitionKey/sortKey/lookupKey — word boundary between i and k prevents match",
"correctness: go-logging/external-call-logs-response carve-out language 'success path or failure path, never both' is intentionally flexible — failure-only logging shown in Bad example is valid",
"correctness: go-logging/no-log-and-return-error ast-grep is documented as 'partial pattern' — judgment tier supplements it by design",
"correctness: removed 'External Calls — Always Log' prose (lines 80-109) replaced by 6 machine-readable rules including go-logging/external-call-logs-response which enforces boundary audit logging",
"performance: go-logging/no-tight-loop-without-sampler 'once per second is fine' threshold is intentional — rule's Why explicitly states the judgment threshold",
"correctness: all 6 anchors verified exact match between docs/go-logging-guide.md headings and rules/index.json"
]
}
Summary
Rule count: 124 → 130. Bootstraps the previously 0-rule `docs/go-logging-guide.md` with 6 RULE blocks following the rule-block-schema.
Why no ast-grep YAMLs
All 6 enforcements are judgment-tier with ast-grep partial hints. The MUSTs need cross-context reasoning:
#5 + #6 are tractable mechanically (regex on first string-literal / for-statement scan) but the false-positive rate without semantic filtering would be high — leaving them judgment-tier with hints lets the dispatcher's agent layer adjudicate.
Preserves existing content
Operator-content sections (slog/glog usage, sampling, runtime log level, related rules) preserved verbatim. This is a bootstrap (add RULE blocks), not a rewrite.
Test plan