Skip to content

feat: anchor feedback via GitHub Discussions#318

Merged
rdmueller merged 6 commits intoLLM-Coding:mainfrom
raifdmueller:feat/discussion-feedback
Mar 18, 2026
Merged

feat: anchor feedback via GitHub Discussions#318
rdmueller merged 6 commits intoLLM-Coding:mainfrom
raifdmueller:feat/discussion-feedback

Conversation

@raifdmueller
Copy link
Contributor

@raifdmueller raifdmueller commented Mar 18, 2026

Summary

Implements #210 — anchor feedback using GitHub Discussions as backend.

What's included

  • 104 Discussions created in "Anchor Feedback" category, one per anchor
  • scripts/create-anchor-discussions.js — idempotent script for creating discussions (detects existing ones, useful for new anchors)
  • scripts/fetch-discussion-votes.js — fetches upvote/comment counts via GraphQL, generates feedback.json
  • Card grid badges — upvote count (shown when >1) and comment indicator, linking to the GitHub Discussion
  • Modal feedback section — Vote and Discuss buttons at the bottom of the anchor modal
  • Graceful fallback — if feedback.json is missing, everything works without feedback data

Screenshots

Cards show badges when an anchor has upvotes or comments:

[⚓ arc42]  👥 3 Roles  👍 5  💬 2

Modal shows feedback section at bottom:

[👍 Vote (5)]  [💬 Discuss (2)]
Requires GitHub login

Still TODO (separate PRs)

  • Daily CI workflow to refresh feedback.json (cron schedule)
  • Auto-create discussions for newly added anchors

Test plan

  • All 87 unit tests pass
  • Build succeeds
  • Upvote/comment badges visible on cards (when data exists)
  • Modal shows Vote/Discuss buttons linking to correct GitHub Discussion
  • Cards and modal work normally when feedback.json is missing

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Neue Funktionen

    • Feedback-System sichtbar: Upvotes und Kommentarzahlen in Anker-Karten und im Anchor-Modal, inkl. Vote- und Discuss-Aktionen sowie Login-Hinweis
    • Direktlinks zu zugehörigen GitHub-Diskussionen
  • Daten & CLI

    • Feedback-Datendatei hinzugefügt; Laden und Caching beim Seitenstart
    • Zwei CLI‑Skripte zum Anlegen und Sammeln von Diskussionsdaten (inkl. Dry‑Run)
  • Design / Stil

    • Neue Styles für Feedback-Badges und -Bereiche
  • Tests

    • Anpassungen für optionale Feedback-Datenladung
  • Internationalisierung

    • Neue DE/EN Texte für Feedback-UI

- Create 104 GitHub Discussions (one per anchor) in "Anchor Feedback" category
- Add fetch-discussion-votes.js to generate feedback.json with upvote/comment counts
- Card grid: show upvote count (>1) and comment badges linking to discussions
- Anchor modal: feedback section with Vote and Discuss buttons
- data-loader: load feedback.json alongside other data (graceful fallback if missing)
- Update tests for new feedback data flow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Fügt eine GitHub‑Discussions‑Feedback‑Pipeline: zwei Node‑Skripte (Erstellen/Abrufen von Discussions), eine generierte website/public/data/feedback.json, Data‑Loader‑Caching, UI‑Integration (Anchor‑Modal, Card‑Grid), Styling, Tests und ESLint‑Ergänzung.

Changes

Cohort / File(s) Summary
Skripte für Feedback‑Management
scripts/create-anchor-discussions.js, scripts/fetch-discussion-votes.js
Neue Node.js‑Skripte: create-anchor-discussions.js erstellt Discussions pro Anchor (--dry-run, Duplicate‑Check via GraphQL, Throttling), fetch-discussion-votes.js paginiert GitHub GraphQL, extrahiert <!-- anchor-id: ... --> und schreibt website/public/data/feedback.json.
Feedback‑Daten
website/public/data/feedback.json
Neue statische JSON‑Datei: Mapping Anchor‑ID → {upvotes, comments, url} als Datenquelle für die Website.
Daten‑Utility & Tests
website/src/utils/data-loader.js, website/src/utils/data-loader.test.js
fetchData lädt optional data/feedback.json; neue exportierte fetchFeedbackData() mit Caching; Cache‑Reset in Tests angepasst; Tests erwarten zusätzlichen Fetch (feedback.json).
UI: Anchor Modal
website/src/components/anchor-modal.js, website/src/components/anchor-modal.test.js
Modal importiert fetchFeedbackData() und rendert Feedback‑Sektion (Vote/Discuss, URLs, Counts); Tests mocken fetchFeedbackData und passen Fixture‑Tiers an.
UI: Card Grid & Integration
website/src/components/card-grid.js, website/src/main.js
card-grid erhält setFeedbackData(data) und zeigt Feedback‑Badges (Upvotes/Kommentare) pro Anchor; main.js ruft setFeedbackData nach Datenladen auf.
Styling
website/src/styles/main.css
Neue CSS‑Klassen für Feedback UI (.feedback-badge, .feedback-section, .feedback-actions, .feedback-btn*) inklusive Dark‑Mode‑Varianten.
Übersetzungen
website/src/translations/en.json, website/src/translations/de.json
Neue Übersetzungskeys: feedback.vote, feedback.discuss, feedback.requiresLogin.
E2E Tests
website/tests/e2e/website.spec.js
Wartebedingungen/Selektoren für Sub‑Anchor‑UI aktualisiert; einige assertions konditionalisiert und Testnamen angepasst.
Konfiguration
scripts/eslint.config.mjs
ESLint: Node‑Globals setTimeout/setInterval/clearTimeout/clearInterval als readonly ergänzt.

Sequence Diagram(s)

sequenceDiagram
  participant FetchScript as "scripts/fetch-discussion-votes.js"
  participant CreateScript as "scripts/create-anchor-discussions.js"
  participant GitHub as "GitHub GraphQL API"
  participant FS as "website/public/data/feedback.json"
  participant DataLoader as "website/src/utils/data-loader.js"
  participant Web as "Website (main.js)"
  participant UI as "Components (anchor-modal / card-grid)"

  FetchScript->>GitHub: Query discussions (paginiert)
  GitHub-->>FetchScript: Diskussionen (title, body, upvoteCount, comments, url)
  FetchScript->>FS: Schreibe Mapping anchorId -> {upvotes,comments,url}
  CreateScript->>GitHub: List existing discussions (GraphQL) -> create Diskussionen (Mutation) [throttled]
  Web->>DataLoader: fetchData()/fetchFeedbackData()
  DataLoader-->>Web: anchors, categories, roles, feedback
  Web->>UI: setFeedbackData(feedback) / render
  UI-->>GitHub: Nutzer klickt Discuss/Upvote → öffnet Discussion URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

  • Issue #210: Direkt verwandt — implementiert dieselbe GitHub‑Discussions‑Feedback‑Pipeline (Erstell-/Fetch‑Skripte, feedback.json, Data‑Loader API, UI‑Integration).

Possibly related PRs

  • PR #107: Modifiziert ebenfalls website/src/components/anchor-modal.js — mögliche Überschneidungen bei Modal‑Rendering/Logik.
  • PR #111: Betraf ESLint‑Konfiguration — betrifft dieselbe scripts/eslint.config.mjs‑Änderung (Node‑Globals).
  • PR #146: Berührt website/src/main.js‑Initialisierung — beide PRs ändern Startup‑Wiring (Feedback vs. Onboarding).
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Der Titel beschreibt präzise und aussagekräftig die Hauptänderung: Implementierung von Anker-Feedback über GitHub Discussions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
website/src/styles/main.css (1)

180-182: Feedback-Aktionen auf kleinen Screens umbrechbar machen.

In Line 181 ist die Leiste rein horizontal; mit längeren Labels kann sie auf sehr kleinen Geräten überlaufen.

💡 Vorschlag
 .feedback-actions {
-  `@apply` flex justify-center gap-3;
+  `@apply` flex flex-wrap justify-center gap-3;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/styles/main.css` around lines 180 - 182, Die Feedback-Aktionen
(.feedback-actions) sind derzeit strikt horizontal und können auf sehr kleinen
Bildschirmen aus dem Container laufen; ändere die Klasse so dass die Leiste
umbrechen kann (z.B. flex-wrap oder responsive utilities wie flex-wrap /
sm:flex-nowrap), damit Buttons/Labels bei kleinen Viewports untereinander gehen,
behalte justify-center und gap-3 für Abstand und zentrierte Ausrichtung.
website/src/utils/data-loader.test.js (1)

283-294: Fallback-Inhalt für feedback explizit prüfen.

Der neue 404-Fall ist gut abgedeckt; eine zusätzliche Assertion auf den tatsächlichen Fallback macht den Test noch robuster.

🧪 Ergänzung
     const first = await fetchData()
     const second = await fetchData()

     expect(first).toEqual(second)
+    expect(first.feedback).toEqual({})
     expect(global.fetch).toHaveBeenCalledTimes(4)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/utils/data-loader.test.js` around lines 283 - 294, Der Test
should additionally assert that when the fetch for 'data/feedback.json' returns
404 the returned payload contains the expected fallback value for the feedback
field: after calling fetchData() (function fetchData) assert response.feedback
equals the known fallback (e.g. [] or {} depending on the implementation) so the
test explicitly verifies the fallback behavior for the 'feedback' key rather
than only checking fetch call counts and URLs.
website/src/utils/data-loader.js (1)

99-100: Fallback für feedback.json sollte nur „Datei fehlt“ abfangen.

catch(() => ({})) in Line 99 maskiert auch echte Laufzeitprobleme (z. B. 500/Netzwerk), wodurch Fehler schwer erkennbar werden.

🎯 Präziseres Error-Handling
-      fetchJson('data/feedback.json').catch(() => ({})),
+      fetchJson('data/feedback.json').catch((error) => {
+        if (error instanceof Error && /: 404$/.test(error.message)) return {}
+        throw error
+      }),

As per coding guidelines website/src/**/*.js: Check for: security issues, unused variables, proper error handling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/utils/data-loader.js` around lines 99 - 100, The current catch(()
=> ({})) on the fetchJson('data/feedback.json') call swallows all errors; change
it to only return an empty object for a missing file (HTTP 404 / ENOENT) and
rethrow all other errors. Specifically, update the Promise chain around
fetchJson('data/feedback.json') so the catch handler for that call inspects the
error (e.g., err.status, err.response?.status, err.code, or err.message includes
'404') and returns {} only when it indicates "not found"; otherwise rethrow the
error so real network/server issues surface. Ensure this change targets the
fetchJson invocation for 'data/feedback.json'.
website/src/components/card-grid.js (1)

190-214: Potenzielle XSS-Schwachstelle bei fb.url prüfen.

escapeHtml() schützt vor HTML-Injection, aber nicht vor javascript:-URLs. Falls feedback.json manipuliert oder aus einer nicht vertrauenswürdigen Quelle stammt, könnte ein bösartiger URL wie javascript:alert(1) ausgeführt werden.

Da feedback.json durch ein kontrolliertes Script generiert wird und GitHub-Discussion-URLs enthält, ist das Risiko gering – dennoch wäre eine Validierung als Defense-in-Depth sinnvoll.

🛡️ Optionale URL-Validierung
+function isValidHttpUrl(url) {
+  try {
+    const parsed = new URL(url)
+    return parsed.protocol === 'https:' || parsed.protocol === 'http:'
+  } catch {
+    return false
+  }
+}
+
 // In renderAnchorCard:
-        ${
-          fb && fb.upvotes > 1
-            ? `
-          <a href="${escapeHtml(fb.url)}" ...>
+        ${
+          fb && fb.upvotes > 1 && isValidHttpUrl(fb.url)
+            ? `
+          <a href="${escapeHtml(fb.url)}" ...>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/src/components/card-grid.js` around lines 190 - 214, The anchors
rendering fb.url should reject non-http(s) schemes to prevent javascript: XSS;
before interpolating fb.url in card-grid.js (the template that uses
escapeHtml(fb.url) for the feedback-badge links), validate the URL scheme (e.g.,
implement an isValidHttpUrl function and only render the <a> when it returns
true or when the scheme is in a whitelist like http/https), or fallback to a
safe placeholder/href="#" for invalid URLs; keep using escapeHtml for
HTML-encoding but add this scheme check around the blocks that render fb.url to
ensure no javascript: or other dangerous schemes are emitted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/create-anchor-discussions.js`:
- Around line 84-85: Fehlgeschlagene Aufrufe von createDiscussion werden derzeit
stillschweigend ignoriert; wrappe jeden createDiscussion-Aufruf (in der Schleife
über toCreate, und analog bei den anderen Schleifen) in ein try/catch,
incrementiere created nur im try nach erfolgreichem Abschluss und logge den
Fehler im catch; sammle Fehlervorkommen (z.B. failedCount oder failedIds) und am
Ende des Skripts beende mit non-zero Exit-Code (process.exit(1)) falls any
failures > 0, damit CI fehlschlägt; referenziere dabei die Variablen/IDs im Log
für einfache Nachverfolgung (toCreate, created, createDiscussion).
- Around line 24-26: ESLint is flagging use of setTimeout in the sleep(ms)
function because the ESLint config's nodeGlobals list omits setTimeout; update
the ESLint configuration where nodeGlobals is defined by adding setTimeout:
'readonly' to the nodeGlobals object so setTimeout is recognized as a read-only
global and the sleep(ms) function (and other uses) no longer error.

In `@scripts/fetch-discussion-votes.js`:
- Around line 68-78: The loop that populates feedback is silently overwriting
duplicate anchorIds (variable anchorId) when assigning feedback[anchorId] inside
the for (const d of discussions) loop; change this to detect existing
feedback[anchorId] and either merge the entries (e.g., sum up upvotes/comments
and aggregate URLs) or store duplicates as an array of entries so no data is
lost, updating the mapped counter logic accordingly; touch the feedback
assignment site and ensure any consumers of feedback handle the new structure
(e.g., expect an array or merged counts) and include anchorId, d.url,
d.upvoteCount, and d.comments.totalCount in the merged/aggregated
representation.

In `@website/src/components/anchor-modal.js`:
- Around line 271-273: The code uses fb.url directly as an href (fb.url in
anchor-modal.js after fetchFeedbackData/fb) which is unsafe; validate and
sanitize it before using as a link target by parsing it with the URL constructor
(or a robust URL parser) and enforcing an allowlist of safe protocols (e.g.,
http:, https: — optionally mailto:) and a non-empty hostname when applicable; if
validation fails, do not render the anchor or render a safe fallback (e.g.,
disabled link or plain text) and log/handle the error via the existing
error-handling path.
- Around line 281-282: The modal contains hardcoded display strings (e.g., the
Vote label rendered as <span>Vote${fb.upvotes > 1 ? ` (${fb.upvotes})` :
''}</span> and other strings around lines with fb/upvote usage) in
website/src/components/anchor-modal.js; replace these literals with i18n.t(...)
calls (create appropriate translation keys like "modal.vote" and
"modal.vote_count" or use i18n pluralization/interpolation for the upvote count)
so the Vote label and the other hardcoded strings at the referenced spots use
i18n.t(...) and include fb.upvotes via interpolation rather than string
concatenation. Ensure you update the translation files with the new keys and
keep the conditional plural/count behavior via i18n's pluralization or explicit
keys.

---

Nitpick comments:
In `@website/src/components/card-grid.js`:
- Around line 190-214: The anchors rendering fb.url should reject non-http(s)
schemes to prevent javascript: XSS; before interpolating fb.url in card-grid.js
(the template that uses escapeHtml(fb.url) for the feedback-badge links),
validate the URL scheme (e.g., implement an isValidHttpUrl function and only
render the <a> when it returns true or when the scheme is in a whitelist like
http/https), or fallback to a safe placeholder/href="#" for invalid URLs; keep
using escapeHtml for HTML-encoding but add this scheme check around the blocks
that render fb.url to ensure no javascript: or other dangerous schemes are
emitted.

In `@website/src/styles/main.css`:
- Around line 180-182: Die Feedback-Aktionen (.feedback-actions) sind derzeit
strikt horizontal und können auf sehr kleinen Bildschirmen aus dem Container
laufen; ändere die Klasse so dass die Leiste umbrechen kann (z.B. flex-wrap oder
responsive utilities wie flex-wrap / sm:flex-nowrap), damit Buttons/Labels bei
kleinen Viewports untereinander gehen, behalte justify-center und gap-3 für
Abstand und zentrierte Ausrichtung.

In `@website/src/utils/data-loader.js`:
- Around line 99-100: The current catch(() => ({})) on the
fetchJson('data/feedback.json') call swallows all errors; change it to only
return an empty object for a missing file (HTTP 404 / ENOENT) and rethrow all
other errors. Specifically, update the Promise chain around
fetchJson('data/feedback.json') so the catch handler for that call inspects the
error (e.g., err.status, err.response?.status, err.code, or err.message includes
'404') and returns {} only when it indicates "not found"; otherwise rethrow the
error so real network/server issues surface. Ensure this change targets the
fetchJson invocation for 'data/feedback.json'.

In `@website/src/utils/data-loader.test.js`:
- Around line 283-294: Der Test should additionally assert that when the fetch
for 'data/feedback.json' returns 404 the returned payload contains the expected
fallback value for the feedback field: after calling fetchData() (function
fetchData) assert response.feedback equals the known fallback (e.g. [] or {}
depending on the implementation) so the test explicitly verifies the fallback
behavior for the 'feedback' key rather than only checking fetch call counts and
URLs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 55a95057-6d05-425d-9072-a7cc8c91a882

📥 Commits

Reviewing files that changed from the base of the PR and between f8029c0 and 322c722.

📒 Files selected for processing (10)
  • scripts/create-anchor-discussions.js
  • scripts/fetch-discussion-votes.js
  • website/public/data/feedback.json
  • website/src/components/anchor-modal.js
  • website/src/components/anchor-modal.test.js
  • website/src/components/card-grid.js
  • website/src/main.js
  • website/src/styles/main.css
  • website/src/utils/data-loader.js
  • website/src/utils/data-loader.test.js

raifdmueller and others added 2 commits March 18, 2026 11:48
- Use insertAdjacentHTML instead of innerHTML += for feedback section
  (innerHTML += destroys event listeners on sub-anchor links)
- Fix ESLint no-undef for setTimeout in Node.js script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add timer globals to ESLint nodeGlobals config (revert global.setTimeout workaround)
- Track failed discussion creations and set non-zero exit code
- Warn on duplicate anchor-id mappings in fetch-discussion-votes
- Validate feedback URLs against GitHub Discussions allowlist pattern
- Localize feedback texts (Vote/Discuss/Requires GitHub login) via i18n

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
scripts/create-anchor-discussions.js (1)

21-22: Fehlende Validierung beim Laden der Anchors-Datei.

Das synchrone Laden von anchors.json auf Modulebene führt bei fehlender Datei zu einem unverständlichen Fehler. Eine defensive Prüfung wäre hilfreich.

🛡️ Vorgeschlagene Verbesserung
 const anchorsPath = path.join(__dirname, '..', 'website', 'public', 'data', 'anchors.json')
+if (!fs.existsSync(anchorsPath)) {
+  console.error(`Error: anchors.json not found at ${anchorsPath}`)
+  console.error('Run the build first to generate anchors.json')
+  process.exit(1)
+}
 const anchors = JSON.parse(fs.readFileSync(anchorsPath, 'utf-8'))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/create-anchor-discussions.js` around lines 21 - 22, Das Skript liest
die Anchors-Datei synchron auf Modulebene ohne Validierung (anchorsPath /
anchors via fs.readFileSync + JSON.parse), was bei fehlender oder ungültiger
Datei zu einem kryptischen Crash führt; fix: prüfen ob die Datei existiert (z.
B. fs.existsSync(anchorsPath)) und falls nicht, logge eine klare Fehlermeldung
und beende den Prozess, und/oder wrappe fs.readFileSync + JSON.parse in einen
try/catch, logge den genauen Fehler (inkl. anchorsPath und Parse-Fehler) und
handle ihn sauber (return/exit), sodass anchors nur gesetzt wird, wenn Lesen und
Parsen erfolgreich sind.
scripts/fetch-discussion-votes.js (1)

15-22: Fehlende Fehlerbehandlung bei GraphQL-Aufrufen.

Die Funktion ghGraphql fängt keine Fehler ab. Wenn der gh-CLI-Aufruf fehlschlägt (z.B. Netzwerkfehler, Authentifizierungsprobleme), stürzt das Skript mit einem nicht aussagekräftigen Fehler ab.

♻️ Vorgeschlagene Verbesserung
 function ghGraphql(query) {
   const payload = JSON.stringify({ query })
-  const result = execSync('gh api graphql --input -', {
-    input: payload,
-    encoding: 'utf-8',
-  })
-  return JSON.parse(result)
+  try {
+    const result = execSync('gh api graphql --input -', {
+      input: payload,
+      encoding: 'utf-8',
+    })
+    const parsed = JSON.parse(result)
+    if (parsed.errors) {
+      throw new Error(`GraphQL errors: ${JSON.stringify(parsed.errors)}`)
+    }
+    return parsed
+  } catch (err) {
+    console.error('GraphQL request failed:', err.message)
+    throw err
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/fetch-discussion-votes.js` around lines 15 - 22, The ghGraphql
function lacks error handling for the execSync call and JSON.parse, so failures
from the `gh` CLI (network/auth errors or non-JSON output) crash with unclear
messages; wrap the execSync invocation and subsequent JSON.parse in a try/catch
inside ghGraphql, capture the child process error (including stderr/exit code)
and/or parse error, and either rethrow a new Error with a clear message that
includes the captured details or return a rejected Promise/structured error;
ensure you reference the ghGraphql function and include the original
error.message/stderr in the logged/thrown error so callers can diagnose the
failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/create-anchor-discussions.js`:
- Around line 118-121: The delay condition uses `created < toCreate.length`
which fails when creations error because `created` only increments on success;
change the check to base the sleep on the loop/index of attempts (e.g., the
iteration variable) or a separate `attempted`/`processed` counter that
increments for every iteration, and call `sleep(2000)` when there are still
remaining iterations (for example when currentIndex < toCreate.length - 1);
update the condition where `sleep` is invoked to reference that iteration
variable (or `processed`) instead of `created` so the delay always occurs
between attempts regardless of success.

---

Nitpick comments:
In `@scripts/create-anchor-discussions.js`:
- Around line 21-22: Das Skript liest die Anchors-Datei synchron auf Modulebene
ohne Validierung (anchorsPath / anchors via fs.readFileSync + JSON.parse), was
bei fehlender oder ungültiger Datei zu einem kryptischen Crash führt; fix:
prüfen ob die Datei existiert (z. B. fs.existsSync(anchorsPath)) und falls
nicht, logge eine klare Fehlermeldung und beende den Prozess, und/oder wrappe
fs.readFileSync + JSON.parse in einen try/catch, logge den genauen Fehler (inkl.
anchorsPath und Parse-Fehler) und handle ihn sauber (return/exit), sodass
anchors nur gesetzt wird, wenn Lesen und Parsen erfolgreich sind.

In `@scripts/fetch-discussion-votes.js`:
- Around line 15-22: The ghGraphql function lacks error handling for the
execSync call and JSON.parse, so failures from the `gh` CLI (network/auth errors
or non-JSON output) crash with unclear messages; wrap the execSync invocation
and subsequent JSON.parse in a try/catch inside ghGraphql, capture the child
process error (including stderr/exit code) and/or parse error, and either
rethrow a new Error with a clear message that includes the captured details or
return a rejected Promise/structured error; ensure you reference the ghGraphql
function and include the original error.message/stderr in the logged/thrown
error so callers can diagnose the failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: cf771dfd-dd0e-411f-84a1-4d773189a4b9

📥 Commits

Reviewing files that changed from the base of the PR and between cdbc8eb and fda9ae0.

📒 Files selected for processing (6)
  • scripts/create-anchor-discussions.js
  • scripts/eslint.config.mjs
  • scripts/fetch-discussion-votes.js
  • website/src/components/anchor-modal.js
  • website/src/translations/de.json
  • website/src/translations/en.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/src/components/anchor-modal.js

@raifdmueller
Copy link
Contributor Author

CI Status

Lint & Format Check: ✅ Fixed (ESLint nodeGlobals, CodeRabbit findings)

E2E Tests: ❌ — but this is a pre-existing failure, not introduced by this PR. The same 2 Umbrella Anchor tests (should navigate to sub-anchor and show back button, should navigate back to umbrella from sub-anchor) are also failing on main and other recent branches:

main:                           failure
feat/tier-assignments-and-metadata: failure
feat/discussion-feedback:       failure

All other E2E tests pass. The umbrella anchor test failures should be tracked as a separate issue.

raifdmueller and others added 3 commits March 18, 2026 12:05
The delay between discussion creations was skipped on failures because
the condition used `created` (only incremented on success) instead of
the loop index.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ests

The sub-anchor-link elements need time to render after the sub-anchor-list
container appears. Wait for the link itself to be visible instead of just
the list container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tier scale is inverted (tier 3 = best, tier 1 = worst). The sub-anchor
rendering incorrectly treated tier 3 as "not a semantic anchor" and rendered
them as non-clickable spans. This caused all GoF pattern sub-anchors to be
unclickable, breaking the E2E umbrella tests.

- tier 1 → greyed out, not clickable ("not a semantic anchor")
- tier 2/3 → clickable link
- Update unit test mock data to match corrected tier semantics
- E2E test: check for tier-1 items instead of tier-3

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rdmueller rdmueller merged commit 1924ae9 into LLM-Coding:main Mar 18, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants