fix(github): align PR comment severity glyphs with the shared vocabulary - #1135
Conversation
241de35 to
f830783
Compare
f830783 to
1b90b32
Compare
There was a problem hiding this comment.
Pull request overview
This PR standardizes severity glyphs across GitHub PR-comment templates by switching hard-coded emoji to the shared pkg/glyph vocabulary, and adjusts a few headings/callouts so the glyph meaning matches the underlying event (refusal vs failure vs attention).
Changes:
- Replace raw severity glyphs in
pkg/webhook/templates/*withpkg/glyphconstants (e.g.,Attention,Failed,Refused,Info,Escalation). - Update “unsafe changes” apply rejection and “Apply Blocked” headings to use the refusal glyph (⛔) and update error/first-failure callouts to use the failure glyph (❌).
- Refresh template previews and documentation to reflect the new glyph semantics.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| TEMPLATES.md | Updates rendered preview snippets to match the new glyph vocabulary and corrected headings/callouts. |
| pkg/webhook/templates/sharded_apply.go | Switches sharded failure callouts to glyph.Failed. |
| pkg/webhook/templates/sharded_apply_test.go | Updates expectations for sharded failure callouts. |
| pkg/webhook/templates/reconciliation.go | Uses glyph.Attention for the reconciliation-required heading. |
| pkg/webhook/templates/plan.go | Replaces severity glyph literals with glyph.* constants in plan comment rendering. |
| pkg/webhook/templates/multi_apply.go | Switches multi-deployment first-failure callout to glyph.Failed. |
| pkg/webhook/templates/multi_apply_test.go | Updates expectations for multi-deployment first-failure callout. |
| pkg/webhook/templates/existing_copy.go | Uses glyph.Attention / glyph.Info for the discarded-copies disclosure marker. |
| pkg/webhook/templates/errors.go | Converts error templates to use glyph.Attention / glyph.Info / glyph.Failed constants. |
| pkg/webhook/templates/common.go | Changes error blockquote markers from glyph.Failed for Error: / Last error: lines. |
| pkg/webhook/templates/common_test.go | Updates expectations for the new error blockquote glyph. |
| pkg/webhook/templates/apply.go | Uses glyph.Failed in headings / grouped emoji selection, plus glyph.Info in informational bullets. |
| pkg/webhook/templates/apply_test.go | Updates expectations for Apply Blocked headings and error markers. |
| pkg/webhook/templates/apply_commands.go | Updates unsafe-change rejection copy and apply-blocked headings to use glyph.Refused / glyph.Escalation / glyph.Attention. |
| pkg/webhook/sharded_apply_test.go | Updates sharded summary expectation for the apply-level failure callout. |
| pkg/webhook/plan_test.go | Updates unsafe-changes rejection copy expectations. |
| docs/lint-and-safety-levels.md | Updates documentation to reflect revised glyph semantics and adds ❌ to the legend. |
Suppressed comments (1)
pkg/webhook/templates/common.go:322
- writeTableErrorLine now always prefixes with the failure glyph (❌), but apply progress rendering calls this for retryable interruptions (state.Task.FailedRetryable in apply.go). That makes an in-progress retry read like a terminal failure; consider letting the caller choose glyph.Attention vs glyph.Failed (or split into two helpers) based on task/apply state.
if sanitized == "" {
return
}
fmt.Fprintf(sb, "> "+glyph.Failed+" Last error: %s\n", quoteBlockLines(html.EscapeString(sanitized)))
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Migrate every raw severity glyph in the webhook templates to the pkg/glyph constants and correct the sites whose glyph misled: - The unsafe-changes rejection heading attaches Refused to the refusal itself: "Apply rejected: N unsafe changes detected", matching the engine-blocked rejection heading's style. - Error and last-error callouts quote a recorded failure, not a pre-proceed warning; they now carry Failed. - Multi-deployment and sharded first-failure callouts carry Failed, matching the row they point at. - The Apply Blocked headings are safety-gate refusals, not attempted failures, so they move from Failed to Refused — matching the merged/closed-PR blocks that already carried it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-table failed rows spelled the failure glyph as a unicode escape, hiding it from the vocabulary migration. Reference glyph.Failed like every other severity site, and correct the writeErrorBlock doc comment that still described a warning emoji. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Section headings already carry a bold label, so bolding the count as
well double-emphasized the line. The count stays bold only in the plan
summary ("**2** tables to create"), where it is the line's sole
emphasis.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bb8b258 to
e473cee
Compare
|
🤖 Review findings - created by Kiran's code review agent - for schemabot/pull/1135, e473cee. Verdict: 6 findings — 3 non-blocking (glyph overshoot on auto-retrying paths, doc overclaim, ⛔ on transient read errors), 3 suggestions. Non-blocking1. The
// Failed marks an attempted operation that failed. The system already
// stopped on its own; the operator's job is triage.
Failed = "❌"Three of the migrated sites render on states where the system has not stopped and no triage is due:
Failure scenario: an apply hits a transient lock-wait timeout, SchemaBot retries on its own, and the live progress comment an operator is watching now carries ❌. Nothing has stopped and there is nothing to triage, but the glyph asserts both. This also contradicts the PR body's own stated criterion for the first-failure move ("they point at a deployment/shard row already marked ❌") — for the sharded retryable case the row is marked 🔁, not ❌. Note the multi-deployment sibling is fine: Secondary, weaker instance of the same shape: 2. The generalized ⛔ row in the vocabulary table now overclaims — four live templates render those exact headings with a different glyph. — | ⛔ | Plan comment (**Cannot apply**), apply-rejection comments (**Apply rejected**, **Apply Blocked**), CLI apply-blocked headings (**Apply blocked**) | Refusal: this will not or did not proceed |The pre-PR row named specific headings (
Failure scenario: a contributor adding a new apply-rejection heading consults the table, reads that Apply Blocked carries ⛔, and picks ⛔ for a wait-and-retry case that the existing code spells ⏳. Doc-only, no runtime effect, but this is the table the vocabulary work exists to keep honest. 3. ⛔ on transient check-read errors conflicts with
The divergence this creates is concrete: General suggestions4. Two safety-gate guards went vacuous with the heading rename. — assert.NotContains(t, body, "Unsafe Change", "unsafe prompt must not outrank the freshness rejection")
5. The one ❌→⛔ flip with no unit test. — writeEnvironmentTitle(&sb, glyph.Refused+" Apply Blocked", environment)Every other blocked-apply template got its assertion updated in this PR (apply_test.go:57, :1998, :2027, :2045, :2062, :2094, :2106, :2128, :2138). A repo-wide grep for 6. The "no raw severity glyph" northstar still has un-migrated members of the same vocabulary. —
The one thing that could have broken, verifiedThe blanket rewrite of two shared helpers, Mechanically it is safe. None of the five Semantically it is not safe at two of the five call sites, which is finding 1: Verified correct
This review was generated by Claude Code (claude-opus-5). |
The shared error helpers hard-coded the failure glyph, so auto-retrying applies and shards — where nothing has stopped and no triage is due — carried the same mark as hard failures. The severity now comes from the call site: retrying and stopped contexts render the attention glyph, hard failures keep the failure glyph. Check-status read errors move from the refusal glyph back to the failure glyph — an unchanged retry can succeed, so they are failed verifications, not refusals — matching the review gate's rendering of the same class of error. The iconography table now scopes the refusal glyph to true refusals and names the state icons deliberately outside the severity vocabulary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 All six findings addressed in d500591:
This reply was written by Claude (Fable 5). |
…t-dialect-classify * origin/main: fix(github): keep the PR progress comment updating between operation dispatch waves (#1104) fix(tern): classify materialized change DDL with the target dialect parser (#1187) fix(engine): resolve a cancel or stop that arrives before remote dispatch (#1184) fix: default connect and write timeouts on managed database connections (#1182) fix(storage): index the apply-operation claim ordering (#1180) fix(tern): generalize control resume state and complete cancels with no live engine work (#1179) fix(github): name each table's outcome in unsuccessful apply summaries (#1186) ci: peel tern and webhook into a dedicated integration shard (#1166) fix(engine): report a drained schema change's terminal outcome instead of pending (#1114) feat(serve): contain gRPC handler panics with recovery interceptors (#1164) feat(observability): tell operators when a log window hides older entries (#1185) fix(tern): settle sequential tasks when the engine loses in-flight work (#1113) fix(github): align PR comment severity glyphs with the shared vocabulary (#1135) fix(tern): release a database held by a stopped schema change (#1175) fix(plan): canonicalize drift DDL with the target's dialect parser (#1177) fix(e2e): stop injecting connection kills once the k8s pause is observed (#1178) # Conflicts: # pkg/webhook/templates/plan.go
…lassify' into kiran01bm/apply-comment-dialect * origin/kiran01bm/plan-comment-dialect-classify: fix(github): line-break non-MySQL DDL, schema labels for postgres fix(github): keep the PR progress comment updating between operation dispatch waves (#1104) fix(tern): classify materialized change DDL with the target dialect parser (#1187) fix(engine): resolve a cancel or stop that arrives before remote dispatch (#1184) fix: default connect and write timeouts on managed database connections (#1182) fix(storage): index the apply-operation claim ordering (#1180) fix(tern): generalize control resume state and complete cancels with no live engine work (#1179) fix(github): name each table's outcome in unsuccessful apply summaries (#1186) ci: peel tern and webhook into a dedicated integration shard (#1166) fix(engine): report a drained schema change's terminal outcome instead of pending (#1114) feat(serve): contain gRPC handler panics with recovery interceptors (#1164) feat(observability): tell operators when a log window hides older entries (#1185) fix(tern): settle sequential tasks when the engine loses in-flight work (#1113) fix(github): align PR comment severity glyphs with the shared vocabulary (#1135) fix(tern): release a database held by a stopped schema change (#1175) fix(plan): canonicalize drift DDL with the target's dialect parser (#1177) fix(e2e): stop injecting connection kills once the k8s pause is observed (#1178) # Conflicts: # pkg/webhook/templates/apply.go
Why this matters
The PR-comment surface spells every severity glyph inline, so the same situation reads differently from comment to comment: a recorded failure renders⚠️ — one notch below a plan-time warning — safety-gate refusals split between ❌ and ⛔, and the unsafe-changes rejection heading pins ⛔ to the changes themselves rather than the refusal. Operators triage urgency from these glyphs, and
pkg/glyphalready defines the one-glyph-per-meaning vocabulary the CLI surface uses. This PR moves the PR-comment surface onto it and corrects the sites whose glyph said the wrong thing.What it does
Migrates every raw severity glyph in
pkg/webhook/templatesto thepkg/glyphconstants, and fixes the misleads:**⛔ Apply rejected**: N unsafe changes detected, matching the engine-blocked rejection heading, instead of labeling the changes.> **Error:**and> Last error:quotes render ❌ once the system has stopped on the failure and triage is due; while SchemaBot is still retrying on its own, or the apply was stopped by request, they renderApply Blockedheadings where retrying unchanged refuses again move from ❌ to ⛔. Prior-environment gate, non-passing PR checks, missing/untrusted prior-environment check, unlisted environment — all are refusals by a safety gate, matching theApply Blocked: PR Is Merged/Closedheadings that already carried ⛔. Check-read errors that fail closed keep ❌: an unchanged retry can succeed, so they are failed verifications, not refusals — the same rendering the required-checks review gate uses for that error class.Everything else (escalation, info notices, config-error templates) keeps its rendering and now references the constants. Cancelled/stopped state glyphs are a separate vocabulary and are untouched here; the iconography table in
docs/lint-and-safety-levels.mdnow names which icons are severities and which are states.Apply rejected over unsafe changes — before / after
Before:
After:
Failed apply error callouts — before / after
Before:
After (apply failed — system stopped):
Unchanged (SchemaBot retrying on its own — no triage due yet):
Multi-deployment / sharded first failure — before / after
Before:
After (shard failed — system stopped):
Unchanged (shard retrying):
Apply blocked by a safety gate — before / after
Before:
After:
Unbolded heading counts — before / after
Before:
After:
How it moves us toward the northstar
This completes the PR-comment half of the shared severity vocabulary: with the CLI surface already migrated, both operator surfaces now read from
pkg/glyph, so a glyph can never drift on one surface without the other. That unblocks the final step of the vocabulary work — the analyzer that forbids raw severity glyph literals outsidepkg/glyph— which can only be turned on once no surface spells its own.Opened by Claude (Fable 5).