Issue
The issue pipeline connects user-reported bugs to fixes. Anyone clicks "Report an Issue" in the UI, a GitHub issue is created, a human takes or rejects it, and the report agent fixes what was taken.
Report an Issue (User-Facing)
Every page in hogwarts, mkan and kun carries a "Report an issue" link or icon. It
opens one canonical component (src/components/report-issue/dialog.tsx, source of
truth in kun, copied verbatim to the other repos):
- ≥ 768px — a centred dialog: title, textarea, hint, captcha (anonymous only), Submit.
- < 768px — a full-height bottom sheet shaped like the iOS Books search sheet: the
title on top, a quiet state area in the middle, and a pill composer pinned right
above the on-screen keyboard with a round send button inside it and a round ✕
beside it. The pill follows the keyboard through
window.visualViewport. The page address, viewport, direction and browser are attached automatically; the user only types what went wrong.
Language comes from the [lang] route param (never from document at render time),
and direction is set on the portal explicitly so the Arabic sheet renders RTL.
Where It Appears
| Repo | Location | Variant |
|---|---|---|
| kun | Site footer, every page | text |
| hogwarts | Dashboard footer, marketing pages, auth, onboarding, exam wizard | text |
| hogwarts | Application form wizard footer | icon |
| mkan | Site footer, hosting/travel/auth layouts | text / icon |
Intake limits
The dialog and the server read the same numbers from src/lib/report/limits.ts:
| Reporter | min chars | min unique words |
|---|---|---|
| anonymous | 30 | 5 |
| signed-in | 10 | 3 |
Max 2000 chars. The send button enables exactly when the server will accept the text. (Before 2026-09-13 hogwarts enabled submit on any text while the server demanded 30 chars — short team reports drew a success toast and created nothing.)
Server Action
src/actions/report-issue.ts # kun
src/lib/actions/report-issue.ts # hogwarts, mkan
A thin wrapper around runReportPipeline() (src/lib/report/pipeline.ts):
schema → reporter → pure filters (junk stops here, zero network)
→ rate limit → [captcha ‖ recent-self ‖ banned] → context filters
→ [GitHub dedup search ‖ AI triage] → score → bucket → GitHub issue
The client always receives the same "Submitted. Thank you!" — silent rejects are indistinguishable from real submissions, so spammers cannot probe the filter.
Issue Body Format
<user's description>
---
**Page**: `https://demo.balqalam.com/en/students/enroll`
**Reporter**: team · ADMIN (id:cmrkybll…)
**Time**: 2026-09-13T01:20:00.000Z
**Category**: other
**Viewport**: 390x844
**Direction**: ltr
**Browser**: Mozilla/5.0 (iPhone; …)
<!-- score-block
{ "score": 58, "bucket": "needs-human", "team": true, "reporterKind": "authenticated",
"classification": "unknown", "severity": "medium", "language": "other",
"scores": { "R": 30, "Q": 8, "C": 10, "A": 0, "P": 0 }, "rationale": "" }
-->Title is the description, truncated to 80 characters. classification: "unknown"
with A: 0 is the normal case: AI triage only runs when ANTHROPIC_API_KEY is set,
and under the subscription-only billing posture it is not.
Labels the pipeline sets
| Label | Meaning |
|---|---|
report | Every dialog-created issue |
team | The reporter is a databayt team member (kun contributor session; hogwarts DEVELOPER, team account, or demo-tenant admin) — listed first, never below needs-human |
verified-report | Score ≥ 75 with an AI-confirmed bug, or three corroborating reporters |
needs-human / low-confidence | Score bands — hints that order the list |
severity/*, lang/* | Only when AI triage ran |
The human gate
The queue is listed. Abdout chooses. Nothing is auto-processed.
report # list the whole org queue, then take / reject
report hogwarts # one repo
report hogwarts#382 # skip the list — treat as accepted and fix it
report --status # the table only
Passive triggers, no slash needed: "list the reports", "what did the team report", "fix reports", "البلاغات", "بلاغات الفريق".
- LIST — one
gh search issues --owner databayt --label report --state opencall renders a numbered table ordered accepted → verified → team → needs-human → low-confidence → legacy, oldest first within a lane, with reporter, score and page. - CHOOSE — "take 1,3 reject 2 — not a bug". Up to four rows the skill asks with a multi-select; more than four it asks in prose.
- APPLY — taken →
acceptedlabel + a one-line comment; rejected → closed as not planned with the reason; unmentioned rows stay untouched. - FIX — the report agent runs on every
accepted(orverified-report) issue, oldest first.
Report Agent (the fix lane)
READ → LOCATE → CONTEXT → VALIDATE → SEE → DEBUG → IDENTIFY → FIX → BUILD → PUSH → VERIFY → CLOSE
| Step | What It Does |
|---|---|
| READ | gh issue view — description, page URL, reporter, score-block |
| LOCATE | Map URL to route directory (src/app/) and component directory (src/components/) |
| CONTEXT | Read CLAUDE.md, README.md, ISSUE.md in the component directory |
| VALIDATE | Accepted means "fix it if it is a bug the QA scope allows" — no schema/auth/middleware; data gaps and feature requests go back to the human with a comment |
| SEE / DEBUG | Screenshot, console, network |
| FIX | Minimum diff, documented patterns |
| BUILD | pnpm tsc --noEmit + pnpm build (hogwarts ignores type errors in the build) |
| PUSH | fix: commit with Closes #N, straight to main — no branches, no PRs |
| VERIFY | kun redeploys itself on push (Vercel); hogwarts and mkan need /deploy (Cloudflare) |
| CLOSE | gh issue close with root cause, fix, files, verification — and which platform has it |
Escalation
| Situation | Action |
|---|---|
| Build error after fix | Hand off to build agent |
| Server-side exception | Hand off to sse agent |
| Performance issue | Hand off to performance agent |
| Security concern | Hand off to guardian agent |
| Needs schema / auth / architecture change | Comment, leave open for Abdout |
| Cannot reproduce | Comment + cannot-reproduce label |
Agent Definition
.claude/agents/report.md
Session-Start Hook
Every Claude Code session in a databayt repo runs ~/.claude/hooks/session-start-reports.sh
(canonical copy kun/.claude/hooks/, wired in .claude/settings.json). One search call, one compact table:
📋 Open reports: 5 (0 accepted, 0 from the team). Say "report" to take or reject them.
kun#108 needs-human 111d i got stuck in 4/8 step, also read whole terminal…
hogwarts#382 low-confidence 59d in the student drop down list not all the students appears
It lists; it never starts the agent. The policy lives in ~/.claude/rules/session-start.md.
Why a human gate (since 2026-09-13). The buckets used to be verdicts. But AI triage never ran in production — there is no API-key spend under the subscription-only billing posture — so every real report was scored on reporter and content signals alone, and the "auto-fix" bucket was unreachable. The pipeline still scores every submission and kills junk before an issue exists, but the score now only orders the list; Abdout takes or rejects each row.
Scheduled Trigger (Paused)
A remote trigger exists that runs the report agent every 2 hours in Anthropic's cloud. Currently paused — the human gate makes an unattended run pointless until reports are accepted.
| Field | Value |
|---|---|
| Name | Report Auto-Fix (Every 2h) |
| ID | trig_01MFLRtUTfMMNTDGBBGQtZLq |
| Schedule | 0 */2 * * * (every 2 hours) |
| Status | Disabled |
| Repo | databayt/hogwarts |
| Manage | https://claude.ai/code/scheduled |
Full Pipeline Flow
User taps "Report an issue" (dialog on desktop, sheet above the keyboard on mobile)
↓
Server action → credibility pipeline (junk dies, the rest is scored)
↓
GitHub issue (report + lane label, `team` when a teammate filed it)
↓
Next Claude Code session → hook lists the queue
↓
Abdout says "report" → table → take / reject → `accepted` label / closed not planned
↓
Agent: READ → LOCATE → CONTEXT → VALIDATE → FIX → BUILD → PUSH
↓
Issue closed with structured comment; kun live on push, hogwarts/mkan after /deploy
Files
Product repos (hogwarts, mkan, kun)
| File | Role |
|---|---|
src/components/report-issue/dialog.tsx | The canonical dialog + mobile sheet (copied from kun) |
src/components/report-issue/index.tsx | Per-repo wrapper: session, server action, language |
src/components/report-issue/dictionary.ts | Built-in bilingual strings (mkan overrides through strings) |
src/lib/report/ | The credibility pipeline (copied from kun; only adapter.ts differs) |
src/lib/report/limits.ts | Intake floors — the one place both sides read from |
src/actions/report-issue.ts or src/lib/actions/report-issue.ts | Server action |
Kun (Engine)
| File | Role |
|---|---|
.claude/skills/report/SKILL.md | List → choose → apply → fix |
.claude/agents/report.md | The fix lane (12 steps) |
.claude/hooks/session-start-reports.sh | Session hook, canonical copy |
.claude/rules-global/session-start.md | The hook lists, the human chooses |
content/docs/issue.mdx | This documentation |
Issue Creation (CLI)
Issues can also be created from Claude Code or Slack, not just the dialog.
Usage
# From Claude Code
/issue "Login crashes on Safari mobile" --repo hogwarts
# From keyword
issue "Add dark mode to dashboard"Repo Mapping
| Repo | Scope |
|---|---|
databayt/kun | Engine: agents, skills, MCP, hooks, rules, memory |
databayt/hogwarts | Education: features, bugs, LMS, SIS, billing |
databayt/souq | E-commerce: vendors, cart, checkout |
databayt/mkan | Rentals: listings, booking, search |
databayt/shifa | Medical: appointments, patient records |
databayt/codebase | Shared: patterns, components, templates |
databayt/shadcn | UI: component library |
databayt/ios-app | Mobile: iOS app |
databayt/android-app | Mobile: Android app |
databayt/marketing | Marketing: landing pages |
Labels
Priority
| Label | When |
|---|---|
P0-critical | Production down, data loss, security |
P1-high | Blocks current sprint, customer-facing bug |
P2-medium | Important but not blocking |
P3-low | Nice to have, cleanup |
Type
| Label | When |
|---|---|
report | User-reported via dialog — listed for the human gate |
team | Reported by a databayt team member |
accepted | A human took it — the report agent may fix it |
bug | Something is broken |
enhancement | Improve existing feature |
needs-human | Score band; undecided until listed |
cannot-reproduce | Agent couldn't reproduce the reported issue |
Issue Body Template (CLI)
## Context
Why this matters — user impact, business context, or technical debt.
## Action
- [ ] Step 1
- [ ] Step 2
- [ ] Step 3
## Verification
How to confirm it's done — test commands, URLs to check, expected behavior.On This Page
IssueReport an Issue (User-Facing)Where It AppearsIntake limitsServer ActionIssue Body FormatLabels the pipeline setsThe human gateReport Agent (the fix lane)EscalationAgent DefinitionSession-Start HookScheduled Trigger (Paused)Full Pipeline FlowFilesProduct repos (hogwarts, mkan, kun)Kun (Engine)Issue Creation (CLI)UsageRepo MappingLabelsPriorityTypeIssue Body Template (CLI)