审计
+
{findings.length} {tab}
+
+
+ {isRunning ? '审查进行中…' : '立即运行'}
+
+
刷新
+ {err &&
{err}
}
+
-
仓库审查 Findings
-
- 每日定时仓库审查(确定性检查 + LLM 复审)将在
P5 上线。
- 届时本页展示 cc_audit_findings 的 open / resolved 列表与处理入口。
+
运行历史
+ {runs.length === 0 ? (
+
暂无审查记录。点击「立即运行」触发一次审查。
+ ) : (
+
+
+
+ #
+ kind
+ 状态
+ 开始
+ 耗时
+ findings
+ summary
+
+
+
+ {runs.map((r) => (
+
+ {r.id}
+ {r.kind}
+
+
+ {r.status}
+
+
+ {fmtTime(r.started_at)}
+ {runDuration(r)}
+ {r.findings}
+
+ {r.error || r.summary}
+
+
+ ))}
+
+
+ )}
+
+
+
+
Findings
+
+ {(['open', 'converted', 'dismissed'] as FindingStatus[]).map((s) => (
+ setTab(s)}>
+ {s}
+
+ ))}
+ severity:
+ setSeverity(e.target.value)}>
+ 全部
+ critical
+ high
+ medium
+ low
+
+ {findings.length === 0 ? (
+
当前过滤条件下没有 findings。
+ ) : (
+ findings.map((f) =>
)
+ )}
)
diff --git a/control-center/web/src/types.ts b/control-center/web/src/types.ts
index 0b391804..95c62939 100644
--- a/control-center/web/src/types.ts
+++ b/control-center/web/src/types.ts
@@ -204,3 +204,28 @@ export interface SearchResponse {
count: number
results: SearchResult[]
}
+
+export interface AuditRun {
+ id: number
+ kind: string
+ status: string
+ summary: string
+ error: string
+ started_at: string
+ finished_at?: string
+ findings: number
+}
+
+export interface AuditFinding {
+ id: string
+ run_id: number
+ severity: string
+ kind: string
+ title: string
+ detail_md: string
+ refs: string[]
+ status: string
+ task_id?: string
+ created_at: string
+ run_started_at: string
+}
diff --git a/internal/controlcenter/audit/audit.go b/internal/controlcenter/audit/audit.go
new file mode 100644
index 00000000..83b01f1f
--- /dev/null
+++ b/internal/controlcenter/audit/audit.go
@@ -0,0 +1,250 @@
+// Package audit runs the daily repository review: deterministic checks over
+// cc_tasks (pure SQL + git), plus an optional LLM review, writing runs into
+// cc_audit_runs and findings into cc_audit_findings. It also owns the
+// findings lifecycle (convert to task, dismiss).
+package audit
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "log/slog"
+ "time"
+
+ "github.com/jackc/pgx/v5"
+
+ "chat-agent-system/internal/controlcenter/llm"
+ "chat-agent-system/internal/controlcenter/store"
+)
+
+var (
+ ErrAlreadyRunning = errors.New("audit: a run is already in progress")
+ ErrNotFound = errors.New("audit: not found")
+ ErrBadState = errors.New("audit: bad state")
+)
+
+// advisoryLockKey serializes run creation across processes.
+const advisoryLockKey int64 = 0x6363_6175_6469_74 // "ccaudit"
+
+// Runner executes audit runs against the store and the local git repo.
+// Chat may be nil: the run then covers deterministic checks only.
+type Runner struct {
+ st *store.Store
+ repoRoot string
+ chat llm.ChatClient
+}
+
+func New(st *store.Store, repoRoot string, chat llm.ChatClient) *Runner {
+ return &Runner{st: st, repoRoot: repoRoot, chat: chat}
+}
+
+type Finding struct {
+ ID string `json:"id"`
+ RunID int64 `json:"run_id"`
+ Severity string `json:"severity"`
+ Kind string `json:"kind"`
+ Title string `json:"title"`
+ DetailMD string `json:"detail_md"`
+ Refs []string `json:"refs"`
+ Status string `json:"status"`
+ TaskID *string `json:"task_id,omitempty"`
+ CreatedAt time.Time `json:"created_at"`
+}
+
+var validSeverity = map[string]bool{"low": true, "medium": true, "high": true, "critical": true}
+var validKind = map[string]bool{"bug": true, "gap": true, "unfinished": true, "doc-drift": true}
+
+// Run executes one audit synchronously: inserts a running cc_audit_runs row
+// (ErrAlreadyRunning when one exists), then the deterministic checks, then the
+// LLM review when configured. The run row always ends completed or failed;
+// an LLM failure degrades into the summary instead of failing the run.
+func (r *Runner) Run(ctx context.Context, kind string) (int64, error) {
+ runID, err := r.startRun(ctx, kind)
+ if err != nil {
+ return 0, err
+ }
+ return runID, r.executeRun(ctx, runID, kind)
+}
+
+// StartManual reserves a run row and executes it in a background goroutine,
+// returning the run id immediately. A second call while a run is in flight
+// gets ErrAlreadyRunning.
+func StartManual(ctx context.Context, r *Runner) (int64, error) {
+ runID, err := r.startRun(ctx, "manual")
+ if err != nil {
+ return 0, err
+ }
+ go func() {
+ runCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
+ defer cancel()
+ if err := r.executeRun(runCtx, runID, "manual"); err != nil {
+ slog.Error("manual audit run", "run", runID, "err", err)
+ }
+ }()
+ return runID, nil
+}
+
+// executeRun performs the checks and finalizes the run row.
+func (r *Runner) executeRun(ctx context.Context, runID int64, kind string) (err error) {
+ slog.Info("audit run started", "run", runID, "kind", kind)
+
+ var summary string
+ defer func() {
+ finCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ if err != nil {
+ _, _ = r.st.Pool.Exec(finCtx,
+ `UPDATE cc_audit_runs SET status='failed', error=$2, summary=$3, finished_at=now() WHERE id=$1`,
+ runID, err.Error(), summary)
+ return
+ }
+ _, _ = r.st.Pool.Exec(finCtx,
+ `UPDATE cc_audit_runs SET status='completed', summary=$2, finished_at=now() WHERE id=$1`,
+ runID, summary)
+ }()
+
+ var detCount, llmCount int
+ var notes []string
+
+ findings, ferr := r.deterministicChecks(ctx)
+ if ferr != nil {
+ return fmt.Errorf("deterministic checks: %w", ferr)
+ }
+ for _, f := range findings {
+ inserted, ierr := r.insertFinding(ctx, runID, f)
+ if ierr != nil {
+ return fmt.Errorf("insert finding %q: %w", f.Title, ierr)
+ }
+ if inserted {
+ detCount++
+ }
+ }
+
+ if r.chat == nil {
+ notes = append(notes, "LLM 未接入,仅确定性检查")
+ } else {
+ llmFindings, lerr := r.llmReview(ctx, runID)
+ switch {
+ case errors.Is(lerr, llm.ErrNotConfigured):
+ notes = append(notes, "LLM 未配置,仅确定性检查")
+ case lerr != nil:
+ notes = append(notes, "LLM 审查降级: "+lerr.Error())
+ default:
+ for _, f := range llmFindings {
+ inserted, ierr := r.insertFinding(ctx, runID, f)
+ if ierr != nil {
+ notes = append(notes, fmt.Sprintf("LLM finding %q 写入失败: %v", f.Title, ierr))
+ continue
+ }
+ if inserted {
+ llmCount++
+ }
+ }
+ }
+ }
+
+ summary = fmt.Sprintf("确定性 findings: %d;LLM findings: %d", detCount, llmCount)
+ for _, n := range notes {
+ summary += ";" + n
+ }
+ slog.Info("audit run finished", "run", runID, "summary", summary)
+ return nil
+}
+
+// startRun inserts the running row; an advisory lock serializes the
+// check-then-insert so concurrent triggers cannot both start a run.
+func (r *Runner) startRun(ctx context.Context, kind string) (int64, error) {
+ if kind == "" {
+ kind = "daily"
+ }
+ tx, err := r.st.Pool.Begin(ctx)
+ if err != nil {
+ return 0, err
+ }
+ defer tx.Rollback(ctx)
+ if _, err := tx.Exec(ctx, `SELECT pg_advisory_xact_lock($1)`, advisoryLockKey); err != nil {
+ return 0, err
+ }
+ var busy int
+ if err := tx.QueryRow(ctx,
+ `SELECT count(*) FROM cc_audit_runs WHERE status='running'`).Scan(&busy); err != nil {
+ return 0, err
+ }
+ if busy > 0 {
+ return 0, ErrAlreadyRunning
+ }
+ var id int64
+ if err := tx.QueryRow(ctx,
+ `INSERT INTO cc_audit_runs (kind) VALUES ($1) RETURNING id`, kind).Scan(&id); err != nil {
+ return 0, err
+ }
+ return id, tx.Commit(ctx)
+}
+
+// insertFinding inserts a finding, skipping duplicates: an open finding with
+// the same title (from any earlier run) suppresses the insert.
+func (r *Runner) insertFinding(ctx context.Context, runID int64, f Finding) (bool, error) {
+ refs, err := json.Marshal(f.Refs)
+ if err != nil {
+ return false, err
+ }
+ var id string
+ err = r.st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_findings (run_id, severity, kind, title, detail_md, refs)
+ SELECT $1,$2,$3,$4,$5,$6
+ WHERE NOT EXISTS (SELECT 1 FROM cc_audit_findings WHERE status='open' AND title=$4)
+ RETURNING id`,
+ runID, f.Severity, f.Kind, f.Title, f.DetailMD, refs).Scan(&id)
+ if errors.Is(err, pgx.ErrNoRows) {
+ return false, nil
+ }
+ if err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// NextFire computes the next local wall-clock trigger for dailyAt ("HH:MM"),
+// strictly after now. An unparsable dailyAt falls back to 03:30.
+func NextFire(now time.Time, dailyAt string) time.Time {
+ hh, mm := 3, 30
+ if _, err := fmt.Sscanf(dailyAt, "%d:%d", &hh, &mm); err != nil || hh < 0 || hh > 23 || mm < 0 || mm > 59 {
+ hh, mm = 3, 30
+ }
+ loc := now.Location()
+ next := time.Date(now.Year(), now.Month(), now.Day(), hh, mm, 0, 0, loc)
+ if !next.After(now) {
+ next = next.AddDate(0, 0, 1)
+ }
+ return next
+}
+
+// StartScheduler fires a daily run at dailyAt (local time), checking once per
+// minute, until ctx is cancelled. Returns immediately.
+func (r *Runner) StartScheduler(ctx context.Context, dailyAt string) {
+ go func() {
+ next := NextFire(time.Now(), dailyAt)
+ slog.Info("audit scheduler armed", "daily_at", dailyAt, "next", next.Format(time.RFC3339))
+ t := time.NewTicker(time.Minute)
+ defer t.Stop()
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case now := <-t.C:
+ if now.Before(next) {
+ continue
+ }
+ next = NextFire(now, dailyAt)
+ go func() {
+ runCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
+ defer cancel()
+ if _, err := r.Run(runCtx, "daily"); err != nil && !errors.Is(err, ErrAlreadyRunning) {
+ slog.Error("scheduled audit", "err", err)
+ }
+ }()
+ }
+ }
+ }()
+}
diff --git a/internal/controlcenter/audit/audit_test.go b/internal/controlcenter/audit/audit_test.go
new file mode 100644
index 00000000..8f01ad61
--- /dev/null
+++ b/internal/controlcenter/audit/audit_test.go
@@ -0,0 +1,90 @@
+package audit
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestParseFindingsJSON(t *testing.T) {
+ t.Run("fenced block with surrounding prose", func(t *testing.T) {
+ raw := "以下是审查结果:\n```json\n[{\"severity\":\"high\",\"kind\":\"bug\",\"title\":\"空指针\",\"detail\":\"d\",\"refs\":[\"a.go\"]}]\n```\n以上。"
+ fs, err := parseFindingsJSON(raw)
+ require.NoError(t, err)
+ require.Len(t, fs, 1)
+ assert.Equal(t, "high", fs[0].Severity)
+ assert.Equal(t, "bug", fs[0].Kind)
+ assert.Equal(t, "空指针", fs[0].Title)
+ assert.Equal(t, []string{"a.go"}, fs[0].Refs)
+ })
+
+ t.Run("bare array", func(t *testing.T) {
+ fs, err := parseFindingsJSON(`[{"title":"t1"}]`)
+ require.NoError(t, err)
+ require.Len(t, fs, 1)
+ assert.Equal(t, "medium", fs[0].Severity, "invalid severity defaults to medium")
+ assert.Equal(t, "gap", fs[0].Kind, "invalid kind defaults to gap")
+ assert.Equal(t, []string{}, fs[0].Refs)
+ })
+
+ t.Run("empty array", func(t *testing.T) {
+ fs, err := parseFindingsJSON("没有问题。\n[]")
+ require.NoError(t, err)
+ assert.Empty(t, fs)
+ })
+
+ t.Run("entries without title dropped", func(t *testing.T) {
+ fs, err := parseFindingsJSON(`[{"severity":"low","kind":"gap","detail":"no title"},{"title":"ok"}]`)
+ require.NoError(t, err)
+ require.Len(t, fs, 1)
+ assert.Equal(t, "ok", fs[0].Title)
+ })
+
+ t.Run("bad json", func(t *testing.T) {
+ _, err := parseFindingsJSON("模型没有输出数组")
+ require.Error(t, err)
+
+ _, err = parseFindingsJSON("[{\"title\": 不合法}")
+ require.Error(t, err)
+ })
+
+ t.Run("severity/kind case normalized", func(t *testing.T) {
+ fs, err := parseFindingsJSON(`[{"severity":"HIGH","kind":"Doc-Drift","title":"x"}]`)
+ require.NoError(t, err)
+ assert.Equal(t, "high", fs[0].Severity)
+ assert.Equal(t, "doc-drift", fs[0].Kind)
+ })
+}
+
+func TestNextFire(t *testing.T) {
+ loc := time.Local
+ at := func(h, m int) time.Time { return time.Date(2026, 9, 17, h, m, 0, 0, loc) }
+
+ t.Run("before daily time fires today", func(t *testing.T) {
+ next := NextFire(at(2, 0), "03:30")
+ assert.Equal(t, at(3, 30), next)
+ })
+ t.Run("after daily time fires tomorrow", func(t *testing.T) {
+ next := NextFire(at(10, 0), "03:30")
+ assert.Equal(t, at(3, 30).AddDate(0, 0, 1), next)
+ })
+ t.Run("exactly at daily time fires tomorrow (strictly after)", func(t *testing.T) {
+ next := NextFire(at(3, 30), "03:30")
+ assert.Equal(t, at(3, 30).AddDate(0, 0, 1), next)
+ })
+ t.Run("invalid value falls back to 03:30", func(t *testing.T) {
+ next := NextFire(at(10, 0), "junk")
+ assert.Equal(t, at(3, 30).AddDate(0, 0, 1), next)
+ })
+ t.Run("out of range falls back to 03:30", func(t *testing.T) {
+ next := NextFire(at(1, 0), "25:99")
+ assert.Equal(t, at(3, 30), next)
+ })
+ t.Run("non-zero seconds still fire same day", func(t *testing.T) {
+ now := time.Date(2026, 9, 17, 3, 29, 59, 0, loc)
+ next := NextFire(now, "03:30")
+ assert.Equal(t, at(3, 30), next)
+ })
+}
diff --git a/internal/controlcenter/audit/checks.go b/internal/controlcenter/audit/checks.go
new file mode 100644
index 00000000..e89d71b3
--- /dev/null
+++ b/internal/controlcenter/audit/checks.go
@@ -0,0 +1,172 @@
+package audit
+
+import (
+ "context"
+ "fmt"
+ "os/exec"
+ "sort"
+ "strings"
+ "time"
+)
+
+type staleTask struct {
+ ID string
+ Slug string
+ Title string
+ Status string
+ Stage string
+ Branch string
+ UpdatedAt time.Time
+}
+
+// deterministicChecks runs the SQL + git checks that must always execute,
+// regardless of LLM availability.
+func (r *Runner) deterministicChecks(ctx context.Context) ([]Finding, error) {
+ var out []Finding
+
+ query := func(sql, titleFn, kind, severity, detailFmt string) error {
+ rows, err := r.st.Pool.Query(ctx, sql)
+ if err != nil {
+ return err
+ }
+ defer rows.Close()
+ for rows.Next() {
+ var t staleTask
+ if err := rows.Scan(&t.ID, &t.Slug, &t.Title, &t.Status, &t.Stage, &t.UpdatedAt); err != nil {
+ return err
+ }
+ out = append(out, Finding{
+ Severity: severity,
+ Kind: kind,
+ Title: fmt.Sprintf(titleFn, t.Slug),
+ DetailMD: fmt.Sprintf(detailFmt, t.Slug, t.Title, t.Status, t.Stage, t.UpdatedAt.Format(time.RFC3339)),
+ Refs: []string{"cc_tasks/" + t.Slug},
+ })
+ }
+ return rows.Err()
+ }
+
+ const cols = `SELECT id, slug, title, status, stage, updated_at FROM cc_tasks `
+ const detail = "任务 `%s`(%s)\n\n- status: `%s`\n- stage: `%s`\n- updated_at: %s\n"
+
+ // 1. awaiting_review for more than 24h.
+ if err := query(
+ cols+`WHERE stage_state='awaiting_review' AND status NOT IN ('done','cancelled')
+ AND updated_at < now() - interval '24 hours'`,
+ "任务 %s 待审(awaiting_review)超过 24h", "unfinished", "medium", detail); err != nil {
+ return nil, err
+ }
+ // 3. blocked_pending_decision for more than 48h.
+ if err := query(
+ cols+`WHERE status='blocked_pending_decision' AND updated_at < now() - interval '48 hours'`,
+ "任务 %s 决策阻塞超过 48h", "gap", "high", detail); err != nil {
+ return nil, err
+ }
+ // 4. planned for more than 7 days without movement.
+ if err := query(
+ cols+`WHERE status='planned' AND updated_at < now() - interval '7 days'`,
+ "任务 %s planned 超过 7 天未推进", "gap", "low", detail); err != nil {
+ return nil, err
+ }
+
+ // 2. in_progress with a stale heartbeat (>30min) or an expired lease.
+ rows, err := r.st.Pool.Query(ctx,
+ cols+`WHERE stage_state='in_progress' AND status NOT IN ('done','cancelled')
+ AND (heartbeat_at IS NULL OR heartbeat_at < now() - interval '30 minutes'
+ OR (lease_expires_at IS NOT NULL AND lease_expires_at < now()))`)
+ if err != nil {
+ return nil, err
+ }
+ for rows.Next() {
+ var t staleTask
+ if err := rows.Scan(&t.ID, &t.Slug, &t.Title, &t.Status, &t.Stage, &t.UpdatedAt); err != nil {
+ rows.Close()
+ return nil, err
+ }
+ out = append(out, Finding{
+ Severity: "high",
+ Kind: "unfinished",
+ Title: fmt.Sprintf("任务 %s in_progress 心跳过期或租约过期", t.Slug),
+ DetailMD: fmt.Sprintf(detail, t.Slug, t.Title, t.Status, t.Stage, t.UpdatedAt.Format(time.RFC3339)),
+ Refs: []string{"cc_tasks/" + t.Slug},
+ })
+ }
+ rows.Close()
+ if err := rows.Err(); err != nil {
+ return nil, err
+ }
+
+ // 5. Declared branch missing from the local repo.
+ branches, err := r.missingBranches(ctx)
+ if err != nil {
+ return nil, err
+ }
+ out = append(out, branches...)
+
+ sortFindings(out)
+ return out, nil
+}
+
+func (r *Runner) missingBranches(ctx context.Context) ([]Finding, error) {
+ rows, err := r.st.Pool.Query(ctx,
+ `SELECT slug, title, branch FROM cc_tasks
+ WHERE branch <> '' AND status NOT IN ('done','cancelled')
+ ORDER BY slug`)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ type row struct{ slug, title, branch string }
+ var declared []row
+ uniq := map[string]bool{}
+ for rows.Next() {
+ var t row
+ if err := rows.Scan(&t.slug, &t.title, &t.branch); err != nil {
+ return nil, err
+ }
+ if uniq[t.branch] {
+ continue
+ }
+ uniq[t.branch] = true
+ declared = append(declared, t)
+ }
+ if err := rows.Err(); err != nil {
+ return nil, err
+ }
+
+ var out []Finding
+ for _, t := range declared {
+ if strings.Contains(t.branch, "..") || strings.HasPrefix(t.branch, "-") {
+ continue // not a valid ref name; treat as non-git metadata
+ }
+ if branchExists(ctx, r.repoRoot, t.branch) {
+ continue
+ }
+ out = append(out, Finding{
+ Severity: "medium",
+ Kind: "doc-drift",
+ Title: fmt.Sprintf("任务 %s 声明的分支 %s 在本地仓库不存在", t.slug, t.branch),
+ DetailMD: fmt.Sprintf("任务 `%s`(%s)声明 branch=`%s`,但 `git show-ref --verify refs/heads/%s` 未命中。", t.slug, t.title, t.branch, t.branch),
+ Refs: []string{"cc_tasks/" + t.slug, "refs/heads/" + t.branch},
+ })
+ }
+ return out, nil
+}
+
+func branchExists(ctx context.Context, repoRoot, branch string) bool {
+ gitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
+ defer cancel()
+ cmd := exec.CommandContext(gitCtx, "git", "-C", repoRoot, "show-ref", "--verify", "--quiet", "refs/heads/"+branch)
+ return cmd.Run() == nil
+}
+
+// sortFindings gives output a stable order: severity desc, then title.
+func sortFindings(fs []Finding) {
+ rank := map[string]int{"critical": 0, "high": 1, "medium": 2, "low": 3}
+ sort.SliceStable(fs, func(i, j int) bool {
+ if rank[fs[i].Severity] != rank[fs[j].Severity] {
+ return rank[fs[i].Severity] < rank[fs[j].Severity]
+ }
+ return fs[i].Title < fs[j].Title
+ })
+}
diff --git a/internal/controlcenter/audit/integration_test.go b/internal/controlcenter/audit/integration_test.go
new file mode 100644
index 00000000..adaa158c
--- /dev/null
+++ b/internal/controlcenter/audit/integration_test.go
@@ -0,0 +1,372 @@
+package audit
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/jackc/pgx/v5"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "chat-agent-system/internal/controlcenter/store"
+)
+
+type fakeChat struct {
+ resp string
+ err error
+ blockCh chan struct{} // when non-nil, Chat blocks until closed
+}
+
+func (f *fakeChat) Chat(ctx context.Context, system, user string) (string, error) {
+ if f.blockCh != nil {
+ select {
+ case <-f.blockCh:
+ case <-ctx.Done():
+ return "", ctx.Err()
+ }
+ }
+ return f.resp, f.err
+}
+
+func newTestStore(t *testing.T) *store.Store {
+ t.Helper()
+ dsn := os.Getenv("TEST_CC_DB_DSN")
+ if dsn == "" {
+ t.Skip("TEST_CC_DB_DSN not set")
+ }
+ _, thisFile, _, _ := runtime.Caller(0)
+ migrationsDir := filepath.Join(filepath.Dir(thisFile), "..", "..", "..", "deploy", "control-center", "goose")
+ ctx := t.Context()
+ require.NoError(t, store.Migrate(ctx, dsn, migrationsDir))
+ st, err := store.Connect(ctx, dsn)
+ require.NoError(t, err)
+ t.Cleanup(st.Close)
+ return st
+}
+
+// newTempRepo initializes a git repo with one commit and the given extra branches.
+func newTempRepo(t *testing.T, extraBranches ...string) string {
+ t.Helper()
+ dir := t.TempDir()
+ run := func(args ...string) {
+ cmd := exec.Command("git", append([]string{"-C", dir}, args...)...)
+ out, err := cmd.CombinedOutput()
+ require.NoError(t, err, "git %v: %s", args, out)
+ }
+ run("init", "-b", "main")
+ run("config", "user.email", "test@example.com")
+ run("config", "user.name", "test")
+ require.NoError(t, os.WriteFile(filepath.Join(dir, "README.md"), []byte("hi"), 0o644))
+ run("add", ".")
+ run("commit", "-m", "init")
+ for _, b := range extraBranches {
+ run("branch", b)
+ }
+ return dir
+}
+
+// runSync runs an audit, waiting out any concurrently active run: the gated
+// integration tests share one dev DB, and the single-running guard is global.
+func runSync(t *testing.T, r *Runner) int64 {
+ t.Helper()
+ deadline := time.Now().Add(30 * time.Second)
+ for {
+ id, err := r.Run(t.Context(), "manual")
+ if err == nil {
+ return id
+ }
+ if !errors.Is(err, ErrAlreadyRunning) || time.Now().After(deadline) {
+ require.NoError(t, err)
+ }
+ time.Sleep(200 * time.Millisecond)
+ }
+}
+
+func uniqSlug(prefix string) string {
+ return fmt.Sprintf("aud-it-%s-%d", prefix, time.Now().UnixNano())
+}
+
+func seedStaleTasks(t *testing.T, st *store.Store, repoRoot string) map[string]string {
+ t.Helper()
+ ctx := t.Context()
+ slugs := map[string]string{}
+ mk := func(key string) string {
+ s := uniqSlug(key)
+ slugs[key] = s
+ return s
+ }
+
+ ins := func(slug, sets string) {
+ _, err := st.Pool.Exec(ctx,
+ `INSERT INTO cc_tasks (slug, title) VALUES ($1, 't-'||$1)`, slug)
+ require.NoError(t, err)
+ if sets != "" {
+ _, err = st.Pool.Exec(ctx, `UPDATE cc_tasks SET `+sets+` WHERE slug=$1`, slug)
+ require.NoError(t, err)
+ }
+ }
+
+ // Hits.
+ ins(mk("review24"), `stage_state='awaiting_review', status='in_progress', updated_at=now()-interval '2 days'`)
+ ins(mk("stalehb"), `status='in_progress', stage_state='in_progress', heartbeat_at=now()-interval '1 hour'`)
+ ins(mk("blocked48"), `status='blocked_pending_decision', updated_at=now()-interval '3 days'`)
+ ins(mk("planned7"), `status='planned', updated_at=now()-interval '8 days'`)
+ ins(mk("missingbr"), `status='in_progress', branch='no-such-branch-`+fmt.Sprint(time.Now().UnixNano())+`'`)
+ // Controls: must NOT produce findings.
+ ins(mk("freshreview"), `stage_state='awaiting_review', status='in_progress'`)
+ ins(mk("livehb"), `status='in_progress', stage_state='in_progress', heartbeat_at=now(), lease_expires_at=now()+interval '1 hour'`)
+ ins(mk("okbranch"), `status='in_progress', branch='main'`)
+ return slugs
+}
+
+func findingTitles(t *testing.T, st *store.Store, runID int64) map[string]Finding {
+ t.Helper()
+ rows, err := st.Pool.Query(t.Context(),
+ `SELECT id, severity, kind, title, status FROM cc_audit_findings WHERE run_id=$1`, runID)
+ require.NoError(t, err)
+ defer rows.Close()
+ out := map[string]Finding{}
+ for rows.Next() {
+ var f Finding
+ require.NoError(t, rows.Scan(&f.ID, &f.Severity, &f.Kind, &f.Title, &f.Status))
+ out[f.Title] = f
+ }
+ return out
+}
+
+// openFindingBySlug finds the newest open finding whose title contains slug.
+// Findings may belong to a run from another test binary sharing the dev DB:
+// whichever run reaches the dedup check first owns the row.
+func openFindingBySlug(t *testing.T, st *store.Store, slug string) *Finding {
+ t.Helper()
+ var f Finding
+ err := st.Pool.QueryRow(t.Context(),
+ `SELECT id, severity, kind, title, status FROM cc_audit_findings
+ WHERE status='open' AND strpos(title, $1) > 0
+ ORDER BY created_at DESC LIMIT 1`, slug).
+ Scan(&f.ID, &f.Severity, &f.Kind, &f.Title, &f.Status)
+ if errors.Is(err, pgx.ErrNoRows) {
+ return nil
+ }
+ require.NoError(t, err)
+ return &f
+}
+
+func TestDeterministicChecksAndDedup(t *testing.T) {
+ st := newTestStore(t)
+ repo := newTempRepo(t)
+ slugs := seedStaleTasks(t, st, repo)
+ r := New(st, repo, nil)
+
+ ctx := t.Context()
+ runID := runSync(t, r)
+
+ var status, summary string
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `SELECT status, summary FROM cc_audit_runs WHERE id=$1`, runID).Scan(&status, &summary))
+ assert.Equal(t, "completed", status)
+ assert.Contains(t, summary, "仅确定性检查", "nil chat client degrades to deterministic-only")
+
+ expect := []struct{ key, kind, sev string }{
+ {"review24", "unfinished", "medium"},
+ {"stalehb", "unfinished", "high"},
+ {"blocked48", "gap", "high"},
+ {"planned7", "gap", "low"},
+ {"missingbr", "doc-drift", "medium"},
+ }
+ for _, e := range expect {
+ hit := openFindingBySlug(t, st, slugs[e.key])
+ require.NotNil(t, hit, "expected open finding for %s (%s)", e.key, slugs[e.key])
+ assert.Equal(t, e.kind, hit.Kind, e.key)
+ assert.Equal(t, e.sev, hit.Severity, e.key)
+ }
+ for _, key := range []string{"freshreview", "livehb", "okbranch"} {
+ assert.Nil(t, openFindingBySlug(t, st, slugs[key]),
+ "control task %s must not produce a finding", key)
+ }
+
+ // Second run: same open titles are deduped — zero new findings.
+ runID2 := runSync(t, r)
+ got2 := findingTitles(t, st, runID2)
+ assert.Empty(t, got2, "second run must not duplicate open findings")
+}
+
+func TestLLMReviewAndDegradation(t *testing.T) {
+ st := newTestStore(t)
+ repo := newTempRepo(t)
+ ctx := t.Context()
+
+ // Healthy LLM: fenced JSON output is parsed and stored.
+ good := &fakeChat{resp: "结果:\n```json\n[{\"severity\":\"high\",\"kind\":\"bug\",\"title\":\"LLM-发现的潜在 bug " + uniqSlug("llm") + "\",\"detail\":\"详情\",\"refs\":[\"x.go\"]}]\n```"}
+ r := New(st, repo, good)
+ runID := runSync(t, r)
+ var summary string
+ require.NoError(t, st.Pool.QueryRow(ctx, `SELECT summary FROM cc_audit_runs WHERE id=$1`, runID).Scan(&summary))
+ assert.Contains(t, summary, "LLM findings: 1")
+ got := findingTitles(t, st, runID)
+ found := false
+ for title := range got {
+ if strings.Contains(title, "LLM-发现的潜在 bug") {
+ found = true
+ }
+ }
+ assert.True(t, found, "LLM finding should be stored, got %v", got)
+
+ // Broken LLM output: run still completes, summary notes degradation.
+ bad := &fakeChat{resp: "我无法输出 JSON"}
+ r2 := New(st, repo, bad)
+ runID2 := runSync(t, r2)
+ var status2, summary2 string
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `SELECT status, summary FROM cc_audit_runs WHERE id=$1`, runID2).Scan(&status2, &summary2))
+ assert.Equal(t, "completed", status2, "LLM parse failure must not fail the run")
+ assert.Contains(t, summary2, "LLM 审查降级")
+}
+
+func TestConvertAndDismiss(t *testing.T) {
+ st := newTestStore(t)
+ ctx := t.Context()
+
+ mkFinding := func(title string) string {
+ var runID int64
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_runs (kind, status, finished_at) VALUES ('manual','completed',now()) RETURNING id`).Scan(&runID))
+ var id string
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_findings (run_id, severity, kind, title, detail_md, refs)
+ VALUES ($1,'medium','gap',$2,'细节内容','["ref-a","ref-b"]'::jsonb) RETURNING id`,
+ runID, title).Scan(&id))
+ return id
+ }
+
+ // Convert: proposal task created, finding converted + task_id backfilled.
+ fid := mkFinding("convert me " + uniqSlug("c"))
+ fi, err := ConvertFinding(ctx, st, fid)
+ require.NoError(t, err)
+ assert.Equal(t, "converted", fi.Status)
+ require.NotNil(t, fi.TaskID)
+ var kind, stage, stageState, status, title, instr string
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `SELECT kind, stage, stage_state, status, title, instruction_md FROM cc_tasks WHERE id=$1`,
+ *fi.TaskID).Scan(&kind, &stage, &stageState, &status, &title, &instr))
+ assert.Equal(t, "proposal", kind)
+ assert.Equal(t, "proposal", stage)
+ assert.Equal(t, "idle", stageState)
+ assert.Equal(t, "planned", status)
+ assert.True(t, len(title) > len("[audit] ") && title[:len("[audit] ")] == "[audit] ", "title prefix: %s", title)
+ assert.Contains(t, instr, "细节内容")
+ assert.Contains(t, instr, "ref-a")
+
+ // Converting again is a conflict.
+ _, err = ConvertFinding(ctx, st, fid)
+ require.ErrorIs(t, err, ErrBadState)
+
+ // Dismiss.
+ fid2 := mkFinding("dismiss me " + uniqSlug("d"))
+ require.NoError(t, DismissFinding(ctx, st, fid2))
+ var st2 string
+ require.NoError(t, st.Pool.QueryRow(ctx, `SELECT status FROM cc_audit_findings WHERE id=$1`, fid2).Scan(&st2))
+ assert.Equal(t, "dismissed", st2)
+
+ // Dismiss again / unknown id.
+ require.ErrorIs(t, DismissFinding(ctx, st, fid2), ErrBadState)
+ require.ErrorIs(t, DismissFinding(ctx, st, "00000000-0000-0000-0000-000000000000"), ErrNotFound)
+}
+
+func TestConcurrentRunConflict(t *testing.T) {
+ st := newTestStore(t)
+ repo := newTempRepo(t)
+ ctx := t.Context()
+
+ // A pre-existing running row blocks new runs.
+ var busyID int64
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_runs (kind, status) VALUES ('manual','running') RETURNING id`).Scan(&busyID))
+ r := New(st, repo, nil)
+ _, err := r.Run(ctx, "manual")
+ require.ErrorIs(t, err, ErrAlreadyRunning)
+ _, err = st.Pool.Exec(ctx, `DELETE FROM cc_audit_runs WHERE id=$1`, busyID)
+ require.NoError(t, err)
+
+ // True concurrency: a slow LLM holds the first run open while a second
+ // Run arrives and must get ErrAlreadyRunning. The gated tests share one
+ // dev DB, so both sides retry until the slow run holds the guard.
+ release := make(chan struct{})
+ slow := New(st, repo, &fakeChat{resp: "[]", blockCh: release})
+ done := make(chan error, 1)
+ go func() {
+ deadline := time.Now().Add(30 * time.Second)
+ for {
+ _, err := slow.Run(ctx, "manual")
+ if errors.Is(err, ErrAlreadyRunning) && time.Now().Before(deadline) {
+ time.Sleep(100 * time.Millisecond)
+ continue
+ }
+ done <- err
+ return
+ }
+ }()
+ deadline := time.Now().Add(30 * time.Second)
+ for {
+ _, err = New(st, repo, nil).Run(ctx, "manual")
+ if errors.Is(err, ErrAlreadyRunning) {
+ break
+ }
+ require.NoError(t, err)
+ require.False(t, time.Now().After(deadline), "slow run never held the guard")
+ time.Sleep(100 * time.Millisecond)
+ }
+ close(release)
+ require.NoError(t, <-done)
+}
+
+func TestListRunsAndFindings(t *testing.T) {
+ st := newTestStore(t)
+ repo := newTempRepo(t)
+ ctx := t.Context()
+
+ r := New(st, repo, &fakeChat{resp: "[]"})
+ runSync(t, r)
+
+ runs, err := ListRuns(ctx, st, 5)
+ require.NoError(t, err)
+ require.NotEmpty(t, runs)
+ assert.Equal(t, "completed", runs[0].Status)
+ assert.NotNil(t, runs[0].FinishedAt)
+
+ // No findings seeded here; check filtering plumbing with a manual finding.
+ var runID int64
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_runs (kind, status, finished_at) VALUES ('manual','completed',now()) RETURNING id`).Scan(&runID))
+ title := "list me " + uniqSlug("l")
+ var fid string
+ require.NoError(t, st.Pool.QueryRow(ctx,
+ `INSERT INTO cc_audit_findings (run_id, severity, kind, title) VALUES ($1,'high','bug',$2) RETURNING id`,
+ runID, title).Scan(&fid))
+
+ items, err := ListFindings(ctx, st, "open", "high", 100)
+ require.NoError(t, err)
+ seen := false
+ for _, it := range items {
+ if it.ID == fid {
+ seen = true
+ assert.False(t, it.RunStartedAt.IsZero())
+ assert.Equal(t, []string{}, it.Refs)
+ }
+ }
+ assert.True(t, seen, "new finding should appear in open/high list")
+
+ items, err = ListFindings(ctx, st, "dismissed", "", 100)
+ require.NoError(t, err)
+ for _, it := range items {
+ assert.NotEqual(t, fid, it.ID, "status filter must exclude open findings")
+ }
+}
diff --git a/internal/controlcenter/audit/llm_review.go b/internal/controlcenter/audit/llm_review.go
new file mode 100644
index 00000000..2007d242
--- /dev/null
+++ b/internal/controlcenter/audit/llm_review.go
@@ -0,0 +1,208 @@
+package audit
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "os/exec"
+ "strings"
+ "time"
+)
+
+const (
+ gitLogMaxLines = 200
+ taskCtxLimit = 50
+ eventCtxLimit = 100
+ openFindLimit = 50
+)
+
+const reviewSystemPrompt = `你是个人研发仓库的审查员。基于给出的最近 git 提交、任务状态、事件流与已有 findings,
+找出潜在的 bug、不完善处与未完成的工作。只输出一个纯 JSON 数组,不要输出任何其他文字,
+每个元素形如 {"severity":"low|medium|high|critical","kind":"bug|gap|unfinished|doc-drift",
+"title":"简短标题","detail":"markdown 详情","refs":["相关文件或任务 slug"]}。
+不要重复已有 open findings 中已列出的问题。没有问题就输出 []。`
+
+// llmReview gathers repo context, asks the model, and parses findings.
+// Parse failures and transport errors are returned to the caller, which folds
+// them into the run summary instead of failing the run.
+func (r *Runner) llmReview(ctx context.Context, runID int64) ([]Finding, error) {
+ since, err := r.lastCompletedRunStart(ctx, runID)
+ if err != nil {
+ return nil, err
+ }
+
+ var sb strings.Builder
+ sb.WriteString("## 最近 git 提交(自上次审查以来)\n")
+ sb.WriteString(r.gitLog(ctx, since))
+ sb.WriteString("\n\n## 当前未完成任务\n")
+ if err := r.appendTaskSummary(ctx, &sb); err != nil {
+ return nil, err
+ }
+ sb.WriteString("\n\n## 最近事件(最新 100 条)\n")
+ if err := r.appendEventSummary(ctx, &sb); err != nil {
+ return nil, err
+ }
+ sb.WriteString("\n\n## 已有 open findings\n")
+ if err := r.appendOpenFindings(ctx, &sb); err != nil {
+ return nil, err
+ }
+
+ raw, err := r.chat.Chat(ctx, reviewSystemPrompt, sb.String())
+ if err != nil {
+ return nil, err
+ }
+ return parseFindingsJSON(raw)
+}
+
+// lastCompletedRunStart returns the start time of the most recent completed
+// run before runID; with no prior run it falls back to 24h ago.
+func (r *Runner) lastCompletedRunStart(ctx context.Context, runID int64) (time.Time, error) {
+ var t time.Time
+ err := r.st.Pool.QueryRow(ctx,
+ `SELECT started_at FROM cc_audit_runs
+ WHERE status='completed' AND id <> $1
+ ORDER BY id DESC LIMIT 1`, runID).Scan(&t)
+ if err != nil {
+ return time.Now().Add(-24 * time.Hour), nil
+ }
+ return t, nil
+}
+
+func (r *Runner) gitLog(ctx context.Context, since time.Time) string {
+ gitCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
+ defer cancel()
+ cmd := exec.CommandContext(gitCtx, "git", "-C", r.repoRoot, "log",
+ "--oneline", "--stat", "--since="+since.Format(time.RFC3339))
+ raw, err := cmd.Output()
+ if err != nil {
+ return "(git log 不可用)\n"
+ }
+ lines := strings.Split(strings.TrimRight(string(raw), "\n"), "\n")
+ if len(lines) > gitLogMaxLines {
+ lines = append(lines[:gitLogMaxLines], fmt.Sprintf("…(截断,共 %d 行)", len(lines)))
+ }
+ if len(lines) == 0 || (len(lines) == 1 && lines[0] == "") {
+ return "(无提交)\n"
+ }
+ return strings.Join(lines, "\n") + "\n"
+}
+
+func (r *Runner) appendTaskSummary(ctx context.Context, sb *strings.Builder) error {
+ rows, err := r.st.Pool.Query(ctx,
+ `SELECT slug, title, status, stage, stage_state, assigned_agent
+ FROM cc_tasks WHERE status NOT IN ('done','cancelled')
+ ORDER BY updated_at DESC LIMIT $1`, taskCtxLimit)
+ if err != nil {
+ return err
+ }
+ defer rows.Close()
+ n := 0
+ for rows.Next() {
+ var slug, title, status, stage, state, agent string
+ if err := rows.Scan(&slug, &title, &status, &stage, &state, &agent); err != nil {
+ return err
+ }
+ fmt.Fprintf(sb, "- %s [%s/%s/%s agent=%s] %s\n", slug, status, stage, state, agent, title)
+ n++
+ }
+ if n == 0 {
+ sb.WriteString("(无)\n")
+ }
+ return rows.Err()
+}
+
+func (r *Runner) appendEventSummary(ctx context.Context, sb *strings.Builder) error {
+ rows, err := r.st.Pool.Query(ctx,
+ `SELECT t.slug, e.agent, e.phase, e.message, e.ts
+ FROM cc_task_events e JOIN cc_tasks t ON t.id = e.task_id
+ ORDER BY e.id DESC LIMIT $1`, eventCtxLimit)
+ if err != nil {
+ return err
+ }
+ defer rows.Close()
+ n := 0
+ for rows.Next() {
+ var slug, agent, phase, msg string
+ var ts time.Time
+ if err := rows.Scan(&slug, &agent, &phase, &msg, &ts); err != nil {
+ return err
+ }
+ msg = strings.ReplaceAll(msg, "\n", " ")
+ if len(msg) > 160 {
+ msg = msg[:160] + "…"
+ }
+ fmt.Fprintf(sb, "- %s %s %s %s: %s\n", ts.Format("01-02 15:04"), slug, agent, phase, msg)
+ n++
+ }
+ if n == 0 {
+ sb.WriteString("(无)\n")
+ }
+ return rows.Err()
+}
+
+func (r *Runner) appendOpenFindings(ctx context.Context, sb *strings.Builder) error {
+ rows, err := r.st.Pool.Query(ctx,
+ `SELECT severity, kind, title FROM cc_audit_findings
+ WHERE status='open' ORDER BY created_at DESC LIMIT $1`, openFindLimit)
+ if err != nil {
+ return err
+ }
+ defer rows.Close()
+ n := 0
+ for rows.Next() {
+ var sev, kind, title string
+ if err := rows.Scan(&sev, &kind, &title); err != nil {
+ return err
+ }
+ fmt.Fprintf(sb, "- [%s/%s] %s\n", sev, kind, title)
+ n++
+ }
+ if n == 0 {
+ sb.WriteString("(无)\n")
+ }
+ return rows.Err()
+}
+
+type llmFinding struct {
+ Severity string `json:"severity"`
+ Kind string `json:"kind"`
+ Title string `json:"title"`
+ Detail string `json:"detail"`
+ Refs []string `json:"refs"`
+}
+
+// parseFindingsJSON tolerates ```json fences and prose around the payload by
+// extracting the span from the first '[' to the last ']'. Invalid severity or
+// kind values fall back to medium / gap; entries without a title are dropped.
+func parseFindingsJSON(raw string) ([]Finding, error) {
+ start := strings.Index(raw, "[")
+ end := strings.LastIndex(raw, "]")
+ if start < 0 || end < start {
+ return nil, fmt.Errorf("audit: no JSON array in model output (%d bytes)", len(raw))
+ }
+ var parsed []llmFinding
+ if err := json.Unmarshal([]byte(raw[start:end+1]), &parsed); err != nil {
+ return nil, fmt.Errorf("audit: decode findings: %w", err)
+ }
+ out := []Finding{}
+ for _, f := range parsed {
+ title := strings.TrimSpace(f.Title)
+ if title == "" {
+ continue
+ }
+ sev := strings.ToLower(strings.TrimSpace(f.Severity))
+ if !validSeverity[sev] {
+ sev = "medium"
+ }
+ kind := strings.ToLower(strings.TrimSpace(f.Kind))
+ if !validKind[kind] {
+ kind = "gap"
+ }
+ refs := f.Refs
+ if refs == nil {
+ refs = []string{}
+ }
+ out = append(out, Finding{Severity: sev, Kind: kind, Title: title, DetailMD: f.Detail, Refs: refs})
+ }
+ return out, nil
+}
diff --git a/internal/controlcenter/audit/queries.go b/internal/controlcenter/audit/queries.go
new file mode 100644
index 00000000..d84b9650
--- /dev/null
+++ b/internal/controlcenter/audit/queries.go
@@ -0,0 +1,176 @@
+package audit
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/jackc/pgx/v5"
+
+ "chat-agent-system/internal/controlcenter/store"
+)
+
+// RunInfo is one row of cc_audit_runs plus its finding count.
+type RunInfo struct {
+ ID int64 `json:"id"`
+ Kind string `json:"kind"`
+ Status string `json:"status"`
+ Summary string `json:"summary"`
+ Error string `json:"error"`
+ StartedAt time.Time `json:"started_at"`
+ FinishedAt *time.Time `json:"finished_at,omitempty"`
+ Findings int `json:"findings"`
+}
+
+func ListRuns(ctx context.Context, st *store.Store, limit int) ([]RunInfo, error) {
+ if limit <= 0 || limit > 200 {
+ limit = 20
+ }
+ rows, err := st.Pool.Query(ctx,
+ `SELECT r.id, r.kind, r.status, r.summary, r.error, r.started_at, r.finished_at,
+ (SELECT count(*) FROM cc_audit_findings f WHERE f.run_id = r.id) AS findings
+ FROM cc_audit_runs r ORDER BY r.id DESC LIMIT $1`, limit)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ out := []RunInfo{}
+ for rows.Next() {
+ var ri RunInfo
+ if err := rows.Scan(&ri.ID, &ri.Kind, &ri.Status, &ri.Summary, &ri.Error,
+ &ri.StartedAt, &ri.FinishedAt, &ri.Findings); err != nil {
+ return nil, err
+ }
+ out = append(out, ri)
+ }
+ return out, rows.Err()
+}
+
+// FindingItem extends Finding with the run's start time for display.
+type FindingItem struct {
+ Finding
+ RunStartedAt time.Time `json:"run_started_at"`
+}
+
+func ListFindings(ctx context.Context, st *store.Store, status, severity string, limit int) ([]FindingItem, error) {
+ if limit <= 0 || limit > 500 {
+ limit = 100
+ }
+ q := `SELECT f.id, f.run_id, f.severity, f.kind, f.title, f.detail_md, f.refs,
+ f.status, f.task_id, f.created_at, r.started_at
+ FROM cc_audit_findings f JOIN cc_audit_runs r ON r.id = f.run_id
+ WHERE true`
+ args := []any{}
+ if status != "" {
+ args = append(args, status)
+ q += fmt.Sprintf(` AND f.status = $%d`, len(args))
+ }
+ if severity != "" {
+ args = append(args, severity)
+ q += fmt.Sprintf(` AND f.severity = $%d`, len(args))
+ }
+ args = append(args, limit)
+ q += fmt.Sprintf(` ORDER BY f.created_at DESC LIMIT $%d`, len(args))
+
+ rows, err := st.Pool.Query(ctx, q, args...)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ out := []FindingItem{}
+ for rows.Next() {
+ var fi FindingItem
+ var refsRaw json.RawMessage
+ if err := rows.Scan(&fi.ID, &fi.RunID, &fi.Severity, &fi.Kind, &fi.Title,
+ &fi.DetailMD, &refsRaw, &fi.Status, &fi.TaskID, &fi.CreatedAt, &fi.RunStartedAt); err != nil {
+ return nil, err
+ }
+ if err := json.Unmarshal(refsRaw, &fi.Refs); err != nil {
+ fi.Refs = []string{}
+ }
+ out = append(out, fi)
+ }
+ return out, rows.Err()
+}
+
+// ConvertFinding creates a proposal task from an open finding and marks the
+// finding converted. Returns the updated finding.
+func ConvertFinding(ctx context.Context, st *store.Store, findingID string) (*FindingItem, error) {
+ tx, err := st.Pool.Begin(ctx)
+ if err != nil {
+ return nil, err
+ }
+ defer tx.Rollback(ctx)
+
+ var fi FindingItem
+ var refsRaw json.RawMessage
+ err = tx.QueryRow(ctx,
+ `SELECT id, run_id, severity, kind, title, detail_md, refs, status, task_id, created_at
+ FROM cc_audit_findings WHERE id = $1 FOR UPDATE`, findingID).
+ Scan(&fi.ID, &fi.RunID, &fi.Severity, &fi.Kind, &fi.Title, &fi.DetailMD,
+ &refsRaw, &fi.Status, &fi.TaskID, &fi.CreatedAt)
+ if errors.Is(err, pgx.ErrNoRows) {
+ return nil, ErrNotFound
+ }
+ if err != nil {
+ return nil, err
+ }
+ if fi.Status != "open" {
+ return nil, fmt.Errorf("%w: finding is %s", ErrBadState, fi.Status)
+ }
+ if err := json.Unmarshal(refsRaw, &fi.Refs); err != nil {
+ fi.Refs = []string{}
+ }
+
+ var sb strings.Builder
+ sb.WriteString(fi.DetailMD)
+ if len(fi.Refs) > 0 {
+ sb.WriteString("\n\n## 引用\n")
+ for _, ref := range fi.Refs {
+ sb.WriteString("- " + ref + "\n")
+ }
+ }
+ slug := "audit-" + strings.ReplaceAll(fi.ID, "-", "")[:12]
+ var taskID string
+ if err := tx.QueryRow(ctx,
+ `INSERT INTO cc_tasks (slug, title, kind, instruction_md)
+ VALUES ($1, $2, 'proposal', $3) RETURNING id`,
+ slug, "[audit] "+fi.Title, sb.String()).Scan(&taskID); err != nil {
+ return nil, err
+ }
+ if _, err := tx.Exec(ctx,
+ `UPDATE cc_audit_findings SET status='converted', task_id=$2 WHERE id=$1`,
+ findingID, taskID); err != nil {
+ return nil, err
+ }
+ if err := tx.Commit(ctx); err != nil {
+ return nil, err
+ }
+ fi.Status = "converted"
+ fi.TaskID = &taskID
+ return &fi, nil
+}
+
+// DismissFinding marks an open finding dismissed.
+func DismissFinding(ctx context.Context, st *store.Store, findingID string) error {
+ tag, err := st.Pool.Exec(ctx,
+ `UPDATE cc_audit_findings SET status='dismissed' WHERE id=$1 AND status='open'`, findingID)
+ if err != nil {
+ return err
+ }
+ if tag.RowsAffected() == 0 {
+ var exists int
+ if err := st.Pool.QueryRow(ctx,
+ `SELECT count(*) FROM cc_audit_findings WHERE id=$1`, findingID).Scan(&exists); err != nil {
+ return err
+ }
+ if exists == 0 {
+ return ErrNotFound
+ }
+ return fmt.Errorf("%w: finding is not open", ErrBadState)
+ }
+ return nil
+}
diff --git a/internal/controlcenter/llm/llm.go b/internal/controlcenter/llm/llm.go
new file mode 100644
index 00000000..283ea956
--- /dev/null
+++ b/internal/controlcenter/llm/llm.go
@@ -0,0 +1,141 @@
+// Package llm is a thin OpenAI-compatible chat-completions client used by the
+// Control Center audit reviewer. Self-contained: modeled on
+// internal/controlcenter/embed but for /chat/completions. API keys are never
+// logged.
+package llm
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+const httpTimeout = 180 * time.Second
+
+// ErrNotConfigured is returned when the endpoint or model is missing; callers
+// should degrade gracefully (skip the LLM stage) rather than fail.
+var ErrNotConfigured = errors.New("llm: endpoint or model not configured")
+
+// ChatClient is the minimal surface the audit runner needs.
+type ChatClient interface {
+ Chat(ctx context.Context, system, user string) (string, error)
+}
+
+// HTTPClient talks to an OpenAI-compatible /chat/completions endpoint.
+type HTTPClient struct {
+ endpoint string
+ apiKey string
+ model string
+ http *http.Client
+}
+
+// NewHTTP builds a client; endpoint may already include /v1 (or the full
+// /chat/completions suffix). An empty endpoint or model yields a client whose
+// Chat always returns ErrNotConfigured.
+func NewHTTP(endpoint, apiKey, model string) *HTTPClient {
+ return &HTTPClient{
+ endpoint: normalizeEndpoint(endpoint),
+ apiKey: apiKey,
+ model: model,
+ http: &http.Client{Timeout: httpTimeout},
+ }
+}
+
+// Configured reports whether Chat can be attempted.
+func (c *HTTPClient) Configured() bool {
+ return c.endpoint != "" && c.model != ""
+}
+
+// Chat sends a system+user pair and returns the assistant message content.
+// 5xx and network errors are retried once; 4xx is returned immediately.
+func (c *HTTPClient) Chat(ctx context.Context, system, user string) (string, error) {
+ if !c.Configured() {
+ return "", ErrNotConfigured
+ }
+ var lastErr error
+ for attempt := 0; attempt < 2; attempt++ {
+ content, retryable, err := c.post(ctx, system, user)
+ if err == nil {
+ return content, nil
+ }
+ if !retryable {
+ return "", err
+ }
+ lastErr = err
+ }
+ return "", lastErr
+}
+
+func (c *HTTPClient) post(ctx context.Context, system, user string) (string, bool, error) {
+ body, _ := json.Marshal(map[string]any{
+ "model": c.model,
+ "messages": []map[string]string{
+ {"role": "system", "content": system},
+ {"role": "user", "content": user},
+ },
+ "temperature": 0.2,
+ })
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpoint, bytes.NewReader(body))
+ if err != nil {
+ return "", false, err
+ }
+ req.Header.Set("Content-Type", "application/json")
+ if c.apiKey != "" {
+ req.Header.Set("Authorization", "Bearer "+c.apiKey)
+ }
+ resp, err := c.http.Do(req)
+ if err != nil {
+ return "", true, fmt.Errorf("llm request: %w", err)
+ }
+ defer resp.Body.Close()
+ raw, _ := io.ReadAll(io.LimitReader(resp.Body, 8<<20))
+ if resp.StatusCode >= 300 {
+ retryable := resp.StatusCode >= 500
+ return "", retryable, fmt.Errorf("llm http %d: %s", resp.StatusCode, truncateUTF8(strings.TrimSpace(string(raw)), 300))
+ }
+ var parsed struct {
+ Choices []struct {
+ Message struct {
+ Content string `json:"content"`
+ } `json:"message"`
+ } `json:"choices"`
+ }
+ if err := json.Unmarshal(raw, &parsed); err != nil {
+ return "", false, fmt.Errorf("llm decode: %w", err)
+ }
+ if len(parsed.Choices) == 0 {
+ return "", false, fmt.Errorf("llm: empty choices")
+ }
+ return parsed.Choices[0].Message.Content, false, nil
+}
+
+func normalizeEndpoint(endpoint string) string {
+ endpoint = strings.TrimRight(strings.TrimSpace(endpoint), "/")
+ if endpoint == "" {
+ return ""
+ }
+ if strings.HasSuffix(endpoint, "/chat/completions") {
+ return endpoint
+ }
+ if strings.HasSuffix(endpoint, "/v1") || strings.Contains(endpoint, "/v1/") {
+ return endpoint + "/chat/completions"
+ }
+ return endpoint + "/v1/chat/completions"
+}
+
+func truncateUTF8(s string, n int) string {
+ if n <= 0 || len(s) <= n {
+ return s
+ }
+ for n > 0 && !utf8.RuneStart(s[n]) {
+ n--
+ }
+ return s[:n]
+}
diff --git a/internal/controlcenter/llm/llm_test.go b/internal/controlcenter/llm/llm_test.go
new file mode 100644
index 00000000..a65e81a0
--- /dev/null
+++ b/internal/controlcenter/llm/llm_test.go
@@ -0,0 +1,99 @@
+package llm
+
+import (
+ "context"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "sync/atomic"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestEndpointNormalization(t *testing.T) {
+ cases := map[string]string{
+ "": "",
+ "http://x": "http://x/v1/chat/completions",
+ "http://x/": "http://x/v1/chat/completions",
+ "http://x/v1": "http://x/v1/chat/completions",
+ "http://x/v1/": "http://x/v1/chat/completions",
+ "http://x/v1/chat/completions": "http://x/v1/chat/completions",
+ "http://x/proxy/v1": "http://x/proxy/v1/chat/completions",
+ }
+ for in, want := range cases {
+ assert.Equal(t, want, normalizeEndpoint(in), "input %q", in)
+ }
+}
+
+func TestNotConfigured(t *testing.T) {
+ _, err := NewHTTP("", "k", "m").Chat(context.Background(), "s", "u")
+ require.ErrorIs(t, err, ErrNotConfigured)
+ _, err = NewHTTP("http://x", "k", "").Chat(context.Background(), "s", "u")
+ require.ErrorIs(t, err, ErrNotConfigured)
+ assert.False(t, NewHTTP("", "k", "m").Configured())
+ assert.True(t, NewHTTP("http://x", "k", "m").Configured())
+}
+
+func TestChatSuccessAndKeyNotLogged(t *testing.T) {
+ const key = "sk-secret-never-log"
+ var gotAuth, gotBody string
+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, "/v1/chat/completions", r.URL.Path)
+ gotAuth = r.Header.Get("Authorization")
+ raw, _ := io.ReadAll(r.Body)
+ gotBody = string(raw)
+ w.Header().Set("Content-Type", "application/json")
+ _, _ = w.Write([]byte(`{"choices":[{"message":{"content":"hello"}}]}`))
+ }))
+ defer srv.Close()
+
+ c := NewHTTP(srv.URL, key, "m1")
+ out, err := c.Chat(context.Background(), "sys", "usr")
+ require.NoError(t, err)
+ assert.Equal(t, "hello", out)
+ assert.Equal(t, "Bearer "+key, gotAuth)
+ assert.Contains(t, gotBody, `"temperature":0.2`)
+ assert.Contains(t, gotBody, `"model":"m1"`)
+
+ // Error paths must never echo the key.
+ failSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, "upstream died", http.StatusBadGateway)
+ }))
+ defer failSrv.Close()
+ _, err = NewHTTP(failSrv.URL, key, "m1").Chat(context.Background(), "s", "u")
+ require.Error(t, err)
+ assert.False(t, strings.Contains(err.Error(), key), "error leaks api key: %v", err)
+}
+
+func TestChatRetryPolicy(t *testing.T) {
+ var calls int32
+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ n := atomic.AddInt32(&calls, 1)
+ if n == 1 {
+ http.Error(w, "boom", http.StatusInternalServerError)
+ return
+ }
+ _, _ = w.Write([]byte(`{"choices":[{"message":{"content":"ok after retry"}}]}`))
+ }))
+ defer srv.Close()
+ out, err := NewHTTP(srv.URL, "", "m").Chat(context.Background(), "s", "u")
+ require.NoError(t, err)
+ assert.Equal(t, "ok after retry", out)
+ assert.EqualValues(t, 2, calls, "5xx retried once")
+
+ // 4xx: no retry.
+ atomic.StoreInt32(&calls, 0)
+ srv4 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ atomic.AddInt32(&calls, 1)
+ http.Error(w, "bad request", http.StatusBadRequest)
+ }))
+ defer srv4.Close()
+ _, err = NewHTTP(srv4.URL, "", "m").Chat(context.Background(), "s", "u")
+ require.Error(t, err)
+ assert.EqualValues(t, 1, calls, "4xx not retried")
+ assert.True(t, strings.Contains(err.Error(), "400"))
+ assert.NotErrorIs(t, err, ErrNotConfigured)
+}
diff --git a/internal/controlcenter/server/audit_handlers.go b/internal/controlcenter/server/audit_handlers.go
new file mode 100644
index 00000000..87b1a50b
--- /dev/null
+++ b/internal/controlcenter/server/audit_handlers.go
@@ -0,0 +1,83 @@
+package server
+
+import (
+ "errors"
+ "log/slog"
+ "net/http"
+ "strconv"
+
+ "chat-agent-system/internal/controlcenter/audit"
+)
+
+// SetAudit attaches the audit runner used by the /api/v1/audits routes.
+func (s *Server) SetAudit(r *audit.Runner) { s.audit = r }
+
+func (s *Server) handleAuditRunList(w http.ResponseWriter, r *http.Request) {
+ limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
+ out, err := audit.ListRuns(r.Context(), s.store, limit)
+ if err != nil {
+ writeAuditError(w, err)
+ return
+ }
+ writeJSON(w, http.StatusOK, out)
+}
+
+func (s *Server) handleAuditFindingList(w http.ResponseWriter, r *http.Request) {
+ q := r.URL.Query()
+ limit, _ := strconv.Atoi(q.Get("limit"))
+ out, err := audit.ListFindings(r.Context(), s.store, q.Get("status"), q.Get("severity"), limit)
+ if err != nil {
+ writeAuditError(w, err)
+ return
+ }
+ writeJSON(w, http.StatusOK, out)
+}
+
+// handleAuditRun triggers a manual run in the background and returns the run
+// id immediately; a second trigger while one is running gets 409.
+func (s *Server) handleAuditRun(w http.ResponseWriter, r *http.Request) {
+ if s.audit == nil {
+ writeError(w, http.StatusServiceUnavailable, "audit runner not configured")
+ return
+ }
+ runID, err := audit.StartManual(r.Context(), s.audit)
+ if err != nil {
+ writeAuditError(w, err)
+ return
+ }
+ writeJSON(w, http.StatusAccepted, map[string]any{"run_id": runID})
+}
+
+func (s *Server) handleAuditFindingConvert(w http.ResponseWriter, r *http.Request) {
+ fi, err := audit.ConvertFinding(r.Context(), s.store, r.PathValue("id"))
+ if err != nil {
+ writeAuditError(w, err)
+ return
+ }
+ slog.Info("audit finding converted", "finding", fi.ID, "task", fi.TaskID)
+ writeJSON(w, http.StatusOK, fi)
+}
+
+func (s *Server) handleAuditFindingDismiss(w http.ResponseWriter, r *http.Request) {
+ id := r.PathValue("id")
+ if err := audit.DismissFinding(r.Context(), s.store, id); err != nil {
+ writeAuditError(w, err)
+ return
+ }
+ slog.Info("audit finding dismissed", "finding", id)
+ writeJSON(w, http.StatusOK, map[string]string{"status": "dismissed"})
+}
+
+func writeAuditError(w http.ResponseWriter, err error) {
+ switch {
+ case errors.Is(err, audit.ErrAlreadyRunning):
+ writeError(w, http.StatusConflict, err.Error())
+ case errors.Is(err, audit.ErrNotFound):
+ writeError(w, http.StatusNotFound, err.Error())
+ case errors.Is(err, audit.ErrBadState):
+ writeError(w, http.StatusConflict, err.Error())
+ default:
+ slog.Error("audit handler", "err", err)
+ writeError(w, http.StatusInternalServerError, "internal error")
+ }
+}
diff --git a/internal/controlcenter/server/audit_test.go b/internal/controlcenter/server/audit_test.go
new file mode 100644
index 00000000..da1af41d
--- /dev/null
+++ b/internal/controlcenter/server/audit_test.go
@@ -0,0 +1,159 @@
+package server
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "path/filepath"
+ "runtime"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "chat-agent-system/internal/controlcenter/audit"
+ "chat-agent-system/internal/controlcenter/config"
+ "chat-agent-system/internal/controlcenter/store"
+)
+
+// newAuditTestServer builds a console server with an audit runner attached.
+// The runner points at the real repo root so git checks behave like
+// production (a temp dir would flag every declared branch as missing).
+func newAuditTestServer(t *testing.T) (*httptest.Server, *store.Store) {
+ t.Helper()
+ ts, st := newTestServer(t)
+ ts.Close()
+ _, thisFile, _, _ := runtime.Caller(0)
+ repoRoot := filepath.Join(filepath.Dir(thisFile), "..", "..", "..")
+ srv := New(config.Config{ConsoleToken: testConsoleToken}, st)
+ srv.SetAudit(audit.New(st, repoRoot, nil))
+ ts = httptest.NewServer(srv.Handler())
+ t.Cleanup(ts.Close)
+ return ts, st
+}
+
+func decodeArray(t *testing.T, raw []byte) []map[string]any {
+ t.Helper()
+ var m []map[string]any
+ require.NoError(t, json.Unmarshal(raw, &m))
+ return m
+}
+
+func TestAuditEndpoints(t *testing.T) {
+ ts, _ := newAuditTestServer(t)
+
+ // List endpoints work before any run.
+ code, raw := doReq(t, "GET", ts.URL+"/api/v1/audits/runs?limit=5", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code, string(raw))
+ code, raw = doReq(t, "GET", ts.URL+"/api/v1/audits/findings?status=open", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code, string(raw))
+
+ // Manual trigger returns a run id immediately. A parallel test binary
+ // sharing the dev DB may briefly hold the single-running guard: retry 409s.
+ var runID float64
+ triggerDeadline := time.Now().Add(30 * time.Second)
+ for {
+ code, raw = doReq(t, "POST", ts.URL+"/api/v1/audits/run", testConsoleToken, nil)
+ if code == http.StatusAccepted {
+ runID = decodeBody(t, raw)["run_id"].(float64)
+ break
+ }
+ require.Equal(t, http.StatusConflict, code, string(raw))
+ require.False(t, time.Now().After(triggerDeadline), "run never accepted")
+ time.Sleep(200 * time.Millisecond)
+ }
+ require.Greater(t, runID, float64(0))
+
+ // The run finishes (repo root is the real repo, so git checks work).
+ deadline := time.Now().Add(15 * time.Second)
+ for {
+ code, raw = doReq(t, "GET", ts.URL+"/api/v1/audits/runs?limit=20", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code)
+ var ours map[string]any
+ for _, r := range decodeArray(t, raw) {
+ if r["id"] == runID {
+ ours = r
+ }
+ }
+ require.NotNil(t, ours, "our run must appear in history")
+ if ours["status"] != "running" {
+ assert.Equal(t, "completed", ours["status"], "run error: %v", ours["error"])
+ break
+ }
+ require.False(t, time.Now().After(deadline), "run never finished")
+ time.Sleep(100 * time.Millisecond)
+ }
+}
+
+func TestAuditRunConflict(t *testing.T) {
+ ts, st := newAuditTestServer(t)
+
+ // A pre-existing running row makes the manual trigger 409.
+ var busyID int64
+ require.NoError(t, st.Pool.QueryRow(t.Context(),
+ `INSERT INTO cc_audit_runs (kind, status) VALUES ('manual','running') RETURNING id`).Scan(&busyID))
+ t.Cleanup(func() {
+ // Delete only this test's row; a parallel package may hold its own run.
+ _, _ = st.Pool.Exec(context.Background(),
+ `DELETE FROM cc_audit_runs WHERE id=$1`, busyID)
+ })
+ code, _ := doReq(t, "POST", ts.URL+"/api/v1/audits/run", testConsoleToken, nil)
+ assert.Equal(t, http.StatusConflict, code)
+}
+
+func TestAuditFindingConvertDismissEndpoints(t *testing.T) {
+ ts, st := newTestServer(t)
+
+ var runID int64
+ require.NoError(t, st.Pool.QueryRow(t.Context(),
+ `INSERT INTO cc_audit_runs (kind, status, finished_at) VALUES ('manual','completed',now()) RETURNING id`).Scan(&runID))
+ mk := func(title string) string {
+ var id string
+ require.NoError(t, st.Pool.QueryRow(t.Context(),
+ `INSERT INTO cc_audit_findings (run_id, severity, kind, title, detail_md, refs)
+ VALUES ($1,'high','bug',$2,'细节','["r1"]'::jsonb) RETURNING id`, runID, title).Scan(&id))
+ return id
+ }
+
+ // Convert creates a proposal task and flips the finding.
+ fid := mk("endpoint convert " + slug("c"))
+ code, raw := doReq(t, "POST", ts.URL+"/api/v1/audits/findings/"+fid+"/convert", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code, string(raw))
+ m := decodeBody(t, raw)
+ assert.Equal(t, "converted", m["status"])
+ require.NotNil(t, m["task_id"])
+
+ code, _ = doReq(t, "POST", ts.URL+"/api/v1/audits/findings/"+fid+"/convert", testConsoleToken, nil)
+ assert.Equal(t, http.StatusConflict, code, "converting twice must conflict")
+
+ // Dismiss.
+ fid2 := mk("endpoint dismiss " + slug("d"))
+ code, raw = doReq(t, "POST", ts.URL+"/api/v1/audits/findings/"+fid2+"/dismiss", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code, string(raw))
+ code, _ = doReq(t, "POST", ts.URL+"/api/v1/audits/findings/"+fid2+"/dismiss", testConsoleToken, nil)
+ assert.Equal(t, http.StatusConflict, code)
+
+ // Unknown finding 404s.
+ code, _ = doReq(t, "POST", ts.URL+"/api/v1/audits/findings/00000000-0000-0000-0000-000000000000/dismiss", testConsoleToken, nil)
+ assert.Equal(t, http.StatusNotFound, code)
+
+ // Converted/dismissed findings show up under their status filter.
+ code, raw = doReq(t, "GET", ts.URL+"/api/v1/audits/findings?status=converted&limit=50", testConsoleToken, nil)
+ require.Equal(t, http.StatusOK, code)
+ found := false
+ for _, it := range decodeArray(t, raw) {
+ if it["id"] == fid {
+ found = true
+ }
+ }
+ assert.True(t, found, "converted finding must appear in converted filter")
+}
+
+// Without an attached runner the manual trigger reports 503.
+func TestAuditRunWithoutRunner(t *testing.T) {
+ ts, _ := newTestServer(t)
+ code, _ := doReq(t, "POST", ts.URL+"/api/v1/audits/run", testConsoleToken, nil)
+ assert.Equal(t, http.StatusServiceUnavailable, code)
+}
diff --git a/internal/controlcenter/server/server.go b/internal/controlcenter/server/server.go
index 4256b362..3b0aebc4 100644
--- a/internal/controlcenter/server/server.go
+++ b/internal/controlcenter/server/server.go
@@ -14,6 +14,7 @@ import (
"strings"
"time"
+ "chat-agent-system/internal/controlcenter/audit"
"chat-agent-system/internal/controlcenter/config"
"chat-agent-system/internal/controlcenter/docs"
"chat-agent-system/internal/controlcenter/embed"
@@ -37,8 +38,9 @@ type Server struct {
agents *AgentAuthenticator
mux *http.ServeMux
broker *Broker
- emb embed.Embedder // nil = search degrades to keyword-only
- docSync *docs.Syncer // nil = artifact indexing disabled
+ emb embed.Embedder // nil = search degrades to keyword-only
+ docSync *docs.Syncer // nil = artifact indexing disabled
+ audit *audit.Runner // nil = audit endpoints unavailable
}
func New(cfg config.Config, st *store.Store) *Server {
@@ -94,6 +96,11 @@ func (s *Server) routes() {
s.mux.HandleFunc("GET /api/v1/docs", s.handleDocList)
s.mux.HandleFunc("GET /api/v1/docs/search", s.handleDocSearch)
s.mux.HandleFunc("GET /api/v1/docs/{id}", s.handleDocGet)
+ s.mux.HandleFunc("GET /api/v1/audits/runs", s.handleAuditRunList)
+ s.mux.HandleFunc("GET /api/v1/audits/findings", s.handleAuditFindingList)
+ s.mux.HandleFunc("POST /api/v1/audits/run", s.handleAuditRun)
+ s.mux.HandleFunc("POST /api/v1/audits/findings/{id}/convert", s.handleAuditFindingConvert)
+ s.mux.HandleFunc("POST /api/v1/audits/findings/{id}/dismiss", s.handleAuditFindingDismiss)
// SPA (embedded build of control-center/web); auth middleware already
// passes non-/api paths through.
diff --git a/internal/controlcenter/webui/dist/assets/index-COtJS61m.js b/internal/controlcenter/webui/dist/assets/index-COtJS61m.js
deleted file mode 100644
index a873eba2..00000000
--- a/internal/controlcenter/webui/dist/assets/index-COtJS61m.js
+++ /dev/null
@@ -1,76 +0,0 @@
-(function(){const c=document.createElement("link").relList;if(c&&c.supports&&c.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))f(d);new MutationObserver(d=>{for(const m of d)if(m.type==="childList")for(const b of m.addedNodes)b.tagName==="LINK"&&b.rel==="modulepreload"&&f(b)}).observe(document,{childList:!0,subtree:!0});function r(d){const m={};return d.integrity&&(m.integrity=d.integrity),d.referrerPolicy&&(m.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?m.credentials="include":d.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function f(d){if(d.ep)return;d.ep=!0;const m=r(d);fetch(d.href,m)}})();var Jf={exports:{}},Tu={};var Qm;function vy(){if(Qm)return Tu;Qm=1;var s=Symbol.for("react.transitional.element"),c=Symbol.for("react.fragment");function r(f,d,m){var b=null;if(m!==void 0&&(b=""+m),d.key!==void 0&&(b=""+d.key),"key"in d){m={};for(var y in d)y!=="key"&&(m[y]=d[y])}else m=d;return d=m.ref,{$$typeof:s,type:f,key:b,ref:d!==void 0?d:null,props:m}}return Tu.Fragment=c,Tu.jsx=r,Tu.jsxs=r,Tu}var Xm;function yy(){return Xm||(Xm=1,Jf.exports=vy()),Jf.exports}var o=yy(),$f={exports:{}},_u={},Wf={exports:{}},Ff={};var Zm;function py(){return Zm||(Zm=1,(function(s){function c(w,W){var I=w.length;w.push(W);t:for(;0
>>1,bt=w[zt];if(0>>1;ztd(ua,I))Sd(M,ua)?(w[zt]=M,w[S]=I,zt=S):(w[zt]=ua,w[fl]=I,zt=fl);else if(Sd(M,I))w[zt]=M,w[S]=I,zt=S;else break t}}return W}function d(w,W){var I=w.sortIndex-W.sortIndex;return I!==0?I:w.id-W.id}if(s.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var m=performance;s.unstable_now=function(){return m.now()}}else{var b=Date,y=b.now();s.unstable_now=function(){return b.now()-y}}var j=[],E=[],O=1,p=null,D=3,J=!1,Q=!1,B=!1,F=!1,K=typeof setTimeout=="function"?setTimeout:null,pt=typeof clearTimeout=="function"?clearTimeout:null,Ht=typeof setImmediate<"u"?setImmediate:null;function U(w){for(var W=r(E);W!==null;){if(W.callback===null)f(E);else if(W.startTime<=w)f(E),W.sortIndex=W.expirationTime,c(j,W);else break;W=r(E)}}function et(w){if(B=!1,U(w),!Q)if(r(j)!==null)Q=!0,Y||(Y=!0,me());else{var W=r(E);W!==null&&Qt(et,W.startTime-w)}}var Y=!1,nt=-1,ot=5,Je=-1;function je(){return F?!0:!(s.unstable_now()-Jew&&je());){var zt=p.callback;if(typeof zt=="function"){p.callback=null,D=p.priorityLevel;var bt=zt(p.expirationTime<=w);if(w=s.unstable_now(),typeof bt=="function"){p.callback=bt,U(w),W=!0;break e}p===r(j)&&f(j),U(w)}else f(j);p=r(j)}if(p!==null)W=!0;else{var Be=r(E);Be!==null&&Qt(et,Be.startTime-w),W=!1}}break t}finally{p=null,D=I,J=!1}W=void 0}}finally{W?me():Y=!1}}}var me;if(typeof Ht=="function")me=function(){Ht(Ae)};else if(typeof MessageChannel<"u"){var jl=new MessageChannel,na=jl.port2;jl.port1.onmessage=Ae,me=function(){na.postMessage(null)}}else me=function(){K(Ae,0)};function Qt(w,W){nt=K(function(){w(s.unstable_now())},W)}s.unstable_IdlePriority=5,s.unstable_ImmediatePriority=1,s.unstable_LowPriority=4,s.unstable_NormalPriority=3,s.unstable_Profiling=null,s.unstable_UserBlockingPriority=2,s.unstable_cancelCallback=function(w){w.callback=null},s.unstable_forceFrameRate=function(w){0>w||125zt?(w.sortIndex=I,c(E,w),r(j)===null&&w===r(E)&&(B?(pt(nt),nt=-1):B=!0,Qt(et,I-zt))):(w.sortIndex=bt,c(j,w),Q||J||(Q=!0,Y||(Y=!0,me()))),w},s.unstable_shouldYield=je,s.unstable_wrapCallback=function(w){var W=D;return function(){var I=D;D=W;try{return w.apply(this,arguments)}finally{D=I}}}})(Ff)),Ff}var Lm;function by(){return Lm||(Lm=1,Wf.exports=py()),Wf.exports}var If={exports:{}},tt={};var Vm;function Sy(){if(Vm)return tt;Vm=1;var s=Symbol.for("react.transitional.element"),c=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),m=Symbol.for("react.consumer"),b=Symbol.for("react.context"),y=Symbol.for("react.forward_ref"),j=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),p=Symbol.for("react.activity"),D=Symbol.for("react.view_transition"),J=Symbol.iterator;function Q(S){return S===null||typeof S!="object"?null:(S=J&&S[J]||S["@@iterator"],typeof S=="function"?S:null)}var B={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},F=Object.assign,K={};function pt(S,M,L){this.props=S,this.context=M,this.refs=K,this.updater=L||B}pt.prototype.isReactComponent={},pt.prototype.setState=function(S,M){if(typeof S!="object"&&typeof S!="function"&&S!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,S,M,"setState")},pt.prototype.forceUpdate=function(S){this.updater.enqueueForceUpdate(this,S,"forceUpdate")};function Ht(){}Ht.prototype=pt.prototype;function U(S,M,L){this.props=S,this.context=M,this.refs=K,this.updater=L||B}var et=U.prototype=new Ht;et.constructor=U,F(et,pt.prototype),et.isPureReactComponent=!0;var Y=Array.isArray;function nt(){}var ot={H:null,A:null,T:null,S:null},Je=Object.prototype.hasOwnProperty;function je(S,M,L){var V=L.ref;return{$$typeof:s,type:S,key:M,ref:V!==void 0?V:null,props:L}}function Ae(S,M){return je(S.type,M,S.props)}function me(S){return typeof S=="object"&&S!==null&&S.$$typeof===s}function jl(S){var M={"=":"=0",":":"=2"};return"$"+S.replace(/[=:]/g,function(L){return M[L]})}var na=/\/+/g;function Qt(S,M){return typeof S=="object"&&S!==null&&S.key!=null?jl(""+S.key):M.toString(36)}function w(S){switch(S.status){case"fulfilled":return S.value;case"rejected":throw S.reason;default:switch(typeof S.status=="string"?S.then(nt,nt):(S.status="pending",S.then(function(M){S.status==="pending"&&(S.status="fulfilled",S.value=M)},function(M){S.status==="pending"&&(S.status="rejected",S.reason=M)})),S.status){case"fulfilled":return S.value;case"rejected":throw S.reason}}throw S}function W(S,M,L,V,dt){var mt=typeof S;(mt==="undefined"||mt==="boolean")&&(S=null);var vt=!1;if(S===null)vt=!0;else switch(mt){case"bigint":case"string":case"number":vt=!0;break;case"object":switch(S.$$typeof){case s:case c:vt=!0;break;case O:return vt=S._init,W(vt(S._payload),M,L,V,dt)}}if(vt)return dt=dt(S),vt=V===""?"."+Qt(S,0):V,Y(dt)?(L="",vt!=null&&(L=vt.replace(na,"$&/")+"/"),W(dt,M,L,"",function(rl){return rl})):dt!=null&&(me(dt)&&(dt=Ae(dt,L+(dt.key==null||S&&S.key===dt.key?"":(""+dt.key).replace(na,"$&/")+"/")+vt)),M.push(dt)),1;vt=0;var X=V===""?".":V+":";if(Y(S))for(var P=0;P"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(c){console.error(c)}}return s(),Pf.exports=xy(),Pf.exports}var Wm;function _y(){if(Wm)return _u;Wm=1;var s=by(),c=ir(),r=Ty();function f(t){var e="https://react.dev/errors/"+t;if(1Ma||(t.current=hc[Ma],hc[Ma]=null,Ma--)}function At(t,e){Ma++,hc[Ma]=t.current,t.current=e}var We=$e(null),An=$e(null),Al=$e(null),Ou=$e(null);function Ru(t,e){switch(At(Al,e),At(An,t),At(We,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?Fd(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=Fd(e),t=Id(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}Jt(We),At(We,t)}function Ua(){Jt(We),Jt(An),Jt(Al)}function dc(t){var e=t.memoizedState;e!==null&&(Tn._currentValue=e.memoizedState,At(Ou,t)),e=We.current;var l=Id(e,t.type);e!==l&&(At(An,t),At(We,l))}function Cu(t){An.current===t&&(Jt(We),Jt(An)),Ou.current===t&&(Jt(Ou),Tn._currentValue=rl)}var mc,yr;function Ol(t){if(mc===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);mc=e&&e[1]||"",yr=-1)":-1n||g[a]!==_[n]){var A=`
-`+g[a].replace(" at new "," at ");return t.displayName&&A.includes("")&&(A=A.replace("",t.displayName)),A}while(1<=a&&0<=n);break}}}finally{gc=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?Ol(l):""}function Sg(t,e){switch(t.tag){case 26:case 27:case 5:return Ol(t.type);case 16:return Ol("Lazy");case 13:return t.child!==e&&e!==null?Ol("Suspense Fallback"):Ol("Suspense");case 19:return Ol("SuspenseList");case 0:case 15:return vc(t.type,!1);case 11:return vc(t.type.render,!1);case 1:return vc(t.type,!0);case 31:return Ol("Activity");case 30:return Ol("ViewTransition");default:return""}}function pr(t){try{var e="",l=null;do e+=Sg(t,l),l=t,t=t.return;while(t);return e}catch(a){return`
-Error generating stack: `+a.message+`
-`+a.stack}}var yc=Object.prototype.hasOwnProperty,pc=s.unstable_scheduleCallback,bc=s.unstable_cancelCallback,xg=s.unstable_shouldYield,Tg=s.unstable_requestPaint,ge=s.unstable_now,_g=s.unstable_getCurrentPriorityLevel,br=s.unstable_ImmediatePriority,Sr=s.unstable_UserBlockingPriority,Du=s.unstable_NormalPriority,Eg=s.unstable_LowPriority,xr=s.unstable_IdlePriority,zg=s.log,Ng=s.unstable_setDisableYieldValue,On=null,ve=null;function Rl(t){if(typeof zg=="function"&&Ng(t),ve&&typeof ve.setStrictMode=="function")try{ve.setStrictMode(On,t)}catch{}}var ye=Math.clz32?Math.clz32:Og,jg=Math.log,Ag=Math.LN2;function Og(t){return t>>>=0,t===0?32:31-(jg(t)/Ag|0)|0}var Mu=256,Uu=262144,Hu=4194304;function ia(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function qu(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var n=0,u=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var h=a&134217727;return h!==0?(a=h&~u,a!==0?n=ia(a):(i&=h,i!==0?n=ia(i):l||(l=h&~t,l!==0&&(n=ia(l))))):(h=a&~u,h!==0?n=ia(h):i!==0?n=ia(i):l||(l=a&~t,l!==0&&(n=ia(l)))),n===0?0:e!==0&&e!==n&&(e&u)===0&&(u=n&-n,l=e&-e,u>=l||u===32&&(l&4194048)!==0)?e:n}function Rn(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function Tr(t,e){(e&8)!==0&&(e|=e&32);var l=t.entangledLanes;if(l!==0)for(t=t.entanglements,l&=e;0l;l++)e.push(t);return e}function Cn(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function Cg(t,e,l,a,n,u){var i=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var h=t.entanglements,g=t.expirationTimes,_=t.hiddenUpdates;for(l=i&~l;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Rc=!1;if(dl)try{var Hn={};Object.defineProperty(Hn,"passive",{get:function(){Rc=!0}}),window.addEventListener("test",Hn,Hn),window.removeEventListener("test",Hn,Hn)}catch{Rc=!1}var Cl=null,Cc=null,Qu=null;function Vr(){if(Qu)return Qu;var t,e=Cc,l=e.length,a,n="value"in Cl?Cl.value:Cl.textContent,u=n.length;for(t=0;t=Bn),Ir=" ",Pr=!1;function to(t,e){switch(t){case"keyup":return d0.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function eo(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Xa=!1;function g0(t,e){switch(t){case"compositionend":return eo(e);case"keypress":return e.which!==32?null:(Pr=!0,Ir);case"textInput":return t=e.data,t===Ir&&Pr?null:t;default:return null}}function v0(t,e){if(Xa)return t==="compositionend"||!qc&&to(t,e)?(t=Vr(),Qu=Cc=Cl=null,Xa=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function fo(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function ro(t,e){var l=fo(t);t=0;for(var a;l;){if(l.nodeType===3){if(a=t+l.textContent.length,t<=e&&a>=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=fo(l)}}function oo(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?oo(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function ho(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=kc(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=kc(t.document)}return e}function Yc(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var E0=dl&&"documentMode"in document&&11>=document.documentMode,Za=null,Gc=null,Qn=null,Qc=!1;function mo(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Qc||Za==null||Za!==kc(a)||(a=Za,"selectionStart"in a&&Yc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Qn&&Gn(Qn,a)||(Qn=a,a=Ki(Gc,"onSelect"),0>=i,n-=i,Ie=1<<32-ye(e)+n|l<$?(Yt=Z,Z=null):Yt=Z.sibling;var ht=x(T,Z,z[$],R);if(ht===null){Z===null&&(Z=Yt);break}t&&Z&&ht.alternate===null&&e(T,Z),v=u(ht,v,$),rt===null?k=ht:rt.sibling=ht,rt=ht,Z=Yt}if($===z.length)return l(T,Z),it&&yl(T,$),k;if(Z===null){for(;$$?(Yt=Z,Z=null):Yt=Z.sibling;var la=x(T,Z,ht.value,R);if(la===null){Z===null&&(Z=Yt);break}t&&Z&&la.alternate===null&&e(T,Z),v=u(la,v,$),rt===null?k=la:rt.sibling=la,rt=la,Z=Yt}if(ht.done)return l(T,Z),it&&yl(T,$),k;if(Z===null){for(;!ht.done;$++,ht=z.next())ht=C(T,ht.value,R),ht!==null&&(v=u(ht,v,$),rt===null?k=ht:rt.sibling=ht,rt=ht);return it&&yl(T,$),k}for(Z=a(Z);!ht.done;$++,ht=z.next())ht=N(Z,T,$,ht.value,R),ht!==null&&(t&&(Yt=ht.alternate,Yt!==null&&Z.delete(Yt.key===null?$:Yt.key)),v=u(ht,v,$),rt===null?k=ht:rt.sibling=ht,rt=ht);return t&&Z.forEach(function(gy){return e(T,gy)}),it&&yl(T,$),k}function at(T,v,z,R){if(typeof z=="object"&&z!==null&&z.type===Ae&&z.key===null&&z.props.ref===void 0&&(z=z.props.children),typeof z=="object"&&z!==null){switch(z.$$typeof){case Je:t:{for(var k=z.key;v!==null;){if(v.key===k){if(k=z.type,k===Ae){if(v.tag===7){l(T,v.sibling),R=n(v,z.props.children),wl(R,z),R.return=T,T=R;break t}}else if(v.elementType===k||typeof k=="object"&&k!==null&&k.$$typeof===bt&&ba(k)===v.type){l(T,v.sibling),R=n(v,z.props),wl(R,z),R.return=T,T=R;break t}l(T,v);break}else e(T,v);v=v.sibling}z.type===Ae?(R=ha(z.props.children,T.mode,R,z.key),wl(R,z),R.return=T,T=R):(R=Iu(z.type,z.key,z.props,null,T.mode,R),wl(R,z),R.return=T,T=R)}return i(T);case je:t:{for(k=z.key;v!==null;){if(v.key===k)if(v.tag===4&&v.stateNode.containerInfo===z.containerInfo&&v.stateNode.implementation===z.implementation){l(T,v.sibling),R=n(v,z.children||[]),R.return=T,T=R;break t}else{l(T,v);break}else e(T,v);v=v.sibling}R=$c(z,T.mode,R),R.return=T,T=R}return i(T);case bt:return z=ba(z),at(T,v,z,R)}if(vt(z))return H(T,v,z,R);if(V(z)){if(k=V(z),typeof k!="function")throw Error(f(150));return z=k.call(z),G(T,v,z,R)}if(typeof z.then=="function")return at(T,v,si(z),R);if(z.$$typeof===Qt)return at(T,v,ni(T,z),R);fi(T,z)}return typeof z=="string"&&z!==""||typeof z=="number"||typeof z=="bigint"?(z=""+z,v!==null&&v.tag===6?(l(T,v.sibling),R=n(v,z),R.return=T,T=R):(l(T,v),R=Jc(z,T.mode,R),R.return=T,T=R),i(T)):l(T,v)}return function(T,v,z,R){try{Jn=0;var k=at(T,v,z,R);return Pa=null,k}catch(Z){if(Z===Ia||Z===ii)throw Z;var rt=fe(29,Z,null,T.mode);return rt.lanes=R,rt.return=T,rt}}}var xa=Bo(!0),ko=Bo(!1),Bl=!1;function us(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function is(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function kl(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Yl(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(yt&2)!==0){var n=a.pending;return n===null?e.next=e:(e.next=n.next,n.next=e),a.pending=e,e=Fu(t),To(t,null,l),e}return Wu(t,a,e,l),Fu(t)}function $n(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,zr(t,l)}}function cs(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,l=l.next}while(l!==null);u===null?n=u=e:u=u.next=e}else n=u=e;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var ss=!1;function Wn(){if(ss){var t=Fa;if(t!==null)throw t}}function Fn(t,e,l,a){ss=!1;var n=t.updateQueue;Bl=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,h=n.shared.pending;if(h!==null){n.shared.pending=null;var g=h,_=g.next;g.next=null,i===null?u=_:i.next=_,i=g;var A=t.alternate;A!==null&&(A=A.updateQueue,h=A.lastBaseUpdate,h!==i&&(h===null?A.firstBaseUpdate=_:h.next=_,A.lastBaseUpdate=g))}if(u!==null){var C=n.baseState;i=0,A=_=g=null,h=u;do{var x=h.lane&-536870913,N=x!==h.lane;if(N?(ft&x)===x:(a&x)===x){x!==0&&x===ya&&(ss=!0),A!==null&&(A=A.next={lane:0,tag:h.tag,payload:h.payload,callback:null,next:null});t:{var H=t,G=h;x=e;var at=l;switch(G.tag){case 1:if(H=G.payload,typeof H=="function"){C=H.call(at,C,x);break t}C=H;break t;case 3:H.flags=H.flags&-65537|128;case 0:if(H=G.payload,x=typeof H=="function"?H.call(at,C,x):H,x==null)break t;C=nt({},C,x);break t;case 2:Bl=!0}}x=h.callback,x!==null&&(t.flags|=64,N&&(t.flags|=8192),N=n.callbacks,N===null?n.callbacks=[x]:N.push(x))}else N={lane:x,tag:h.tag,payload:h.payload,callback:h.callback,next:null},A===null?(_=A=N,g=C):A=A.next=N,i|=x;if(h=h.next,h===null){if(h=n.shared.pending,h===null)break;N=h,h=N.next,N.next=null,n.lastBaseUpdate=N,n.shared.pending=null}}while(!0);A===null&&(g=C),n.baseState=g,n.firstBaseUpdate=_,n.lastBaseUpdate=A,u===null&&(n.shared.lanes=0),Kl|=i,t.lanes=i,t.memoizedState=C}}function Yo(t,e){if(typeof t!="function")throw Error(f(191,t));t.call(e)}function Go(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;tu?u:8;var i=X.T,h={};h.types=i!==null?i.types:null,X.T=h,As(t,!1,e,l);try{var g=n(),_=X.S;if(_!==null&&_(h,g),g!==null&&typeof g=="object"&&typeof g.then=="function"){var A=H0(g,a);eu(t,e,A,Ee(t))}else eu(t,e,a,Ee(t))}catch(C){eu(t,e,{then:function(){},status:"rejected",reason:C},Ee())}finally{P.p=u,i!==null&&h.types!==null&&(i.types=h.types),X.T=i}}function G0(){}function Ns(t,e,l,a){if(t.tag!==5)throw Error(f(476));var n=bh(t).queue;ph(t,n,e,rl,l===null?G0:function(){return Sh(t),l(a)})}function bh(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:rl,baseState:rl,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:rl},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:xl,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function Sh(t){var e=bh(t);e.next===null&&(e=t.alternate.memoizedState),eu(t,e.next.queue,{},Ee())}function js(){return Wt(Tn)}function xh(){return qt().memoizedState}function Th(){return qt().memoizedState}function Q0(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=Ee();t=kl(l);var a=Yl(e,t,l);a!==null&&(de(a,e,l),$n(a,e,l)),e={cache:es()},t.payload=e;return}e=e.return}}function X0(t,e,l){var a=Ee();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},bi(t)?Eh(e,l):(l=Vc(t,e,l,a),l!==null&&(de(l,t,a),zh(l,e,a)))}function _h(t,e,l){var a=Ee();eu(t,e,l,a)}function eu(t,e,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(bi(t))Eh(e,n);else{var u=t.alternate;if(t.lanes===0&&(u===null||u.lanes===0)&&(u=e.lastRenderedReducer,u!==null))try{var i=e.lastRenderedState,h=u(i,l);if(n.hasEagerState=!0,n.eagerState=h,be(h,i))return Wu(t,e,n,0),Nt===null&&$u(),!1}catch{}if(l=Vc(t,e,n,a),l!==null)return de(l,t,a),zh(l,e,a),!0}return!1}function As(t,e,l,a){if(a={lane:2,revertLane:bf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},bi(t)){if(e)throw Error(f(479))}else e=Vc(t,l,a,2),e!==null&&de(e,t,2)}function bi(t){var e=t.alternate;return t===lt||e!==null&&e===lt}function Eh(t,e){tn=hi=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function zh(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,zr(t,l)}}var Si={readContext:Wt,use:gi,useCallback:Mt,useContext:Mt,useEffect:Mt,useImperativeHandle:Mt,useLayoutEffect:Mt,useInsertionEffect:Mt,useMemo:Mt,useReducer:Mt,useRef:Mt,useState:Mt,useDebugValue:Mt,useDeferredValue:Mt,useTransition:Mt,useSyncExternalStore:Mt,useId:Mt,useHostTransitionStatus:Mt,useFormState:Mt,useActionState:Mt,useOptimistic:Mt,useMemoCache:Mt,useCacheRefresh:Mt,useEffectEvent:Mt},Nh={readContext:Wt,use:gi,useCallback:function(t,e){return ue().memoizedState=[t,e===void 0?null:e],t},useContext:Wt,useEffect:fh,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,yi(4194308,4,dh.bind(null,e,t),l)},useLayoutEffect:function(t,e){return yi(4194308,4,t,e)},useInsertionEffect:function(t,e){yi(4,2,t,e)},useMemo:function(t,e){var l=ue();e=e===void 0?null:e;var a=t();if(Ta){Rl(!0);try{t()}finally{Rl(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=ue();if(l!==void 0){var n=l(e);if(Ta){Rl(!0);try{l(e)}finally{Rl(!1)}}}else n=e;return a.memoizedState=a.baseState=n,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:n},a.queue=t,t=t.dispatch=X0.bind(null,lt,t),[a.memoizedState,t]},useRef:function(t){var e=ue();return t={current:t},e.memoizedState=t},useState:function(t){t=xs(t);var e=t.queue,l=_h.bind(null,lt,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Es,useDeferredValue:function(t,e){var l=ue();return zs(l,t,e)},useTransition:function(){var t=xs(!1);return t=ph.bind(null,lt,t.queue,!0,!1),ue().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=lt,n=ue();if(it){if(l===void 0)throw Error(f(407));l=l()}else{if(l=e(),Nt===null)throw Error(f(349));(ft&127)!==0||Ko(a,e,l)}n.memoizedState=l;var u={value:l,getSnapshot:e};return n.queue=u,fh($o.bind(null,a,u,t),[t]),a.flags|=2048,ln(9,{destroy:void 0},Jo.bind(null,a,u,l,e),null),l},useId:function(){var t=ue(),e=Nt.identifierPrefix;if(it){var l=Pe,a=Ie;l=(a&~(1<<32-ye(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=di++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[$t]=e,u[se]=a;t:for(i=e.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===e)break t;for(;i.sibling===null;){if(i.return===null||i.return===e)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}e.stateNode=u;t:switch(te(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&_l(e)}}return Rt(e),e.subtreeFlags&=-33554433,Gs(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&_l(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(f(166));if(t=Al.current,Wa(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,n=Zt,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}t[$t]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||$d(t.nodeValue,l)),t||Hl(e,!0)}else t=mu(t).createTextNode(a),t[$t]=e,e.stateNode=t}return Rt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=Wa(e),l!==null){if(t===null){if(!a)throw Error(f(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(f(557));t[$t]=e}else da(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Rt(e),t=!1}else l=Ic(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(Se(e),e):(Se(e),null);if((e.flags&128)!==0)throw Error(f(558))}return Rt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(n=Wa(e),a!==null&&a.dehydrated!==null){if(t===null){if(!n)throw Error(f(318));if(n=e.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(f(317));n[$t]=e}else da(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Rt(e),n=!1}else n=Ic(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),n=!0;if(!n)return e.flags&256?(Se(e),e):(Se(e),null)}return Se(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),Ni(e,e.updateQueue),Rt(e),null);case 4:return Ua(),t===null&&_f(e.stateNode.containerInfo),e.flags|=67108864,Rt(e),null;case 10:return bl(e.type),Rt(e),null;case 19:if(hs(e),a=e.memoizedState,a===null)return Rt(e),null;if(n=(e.flags&128)!==0,u=a.rendering,u===null)if(n)au(a,!1);else{if(Ut!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(u=oi(t),u!==null){for(e.flags|=128,au(a,!1),t=u.updateQueue,e.updateQueue=t,Ni(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)_o(l,t),l=l.sibling;return In(e,It.current&1|2),it&&yl(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&ge()>Bi&&(e.flags|=128,n=!0,au(a,!1),e.lanes=4194304)}else{if(!n)if(t=oi(u),t!==null){if(e.flags|=128,n=!0,t=t.updateQueue,e.updateQueue=t,Ni(e,t),au(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!u.alternate&&!it)return Rt(e),null}else 2*ge()-a.renderingStartTime>Bi&&l!==536870912&&(e.flags|=128,n=!0,au(a,!1),e.lanes=4194304);a.isBackwards?(u.sibling=e.child,e.child=u):(t=a.last,t!==null?t.sibling=u:e.child=u,a.last=u)}if(a.tail!==null){t=a.tail;t:{for(l=t;l!==null;){if(l.alternate!==null){l=!1;break t}l=l.sibling}l=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=ge(),t.sibling=null,u=It.current,u=n?u&1|2:u&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!l||it?In(e,u):(l=u,At(Ft,e),At(It,l),le===null&&(le=e)),it&&yl(e,a.treeForkCount),t}return Rt(e),null;case 22:case 23:return Se(e),rs(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(Rt(e),e.subtreeFlags&6&&(e.flags|=8192)):Rt(e),l=e.updateQueue,l!==null&&Ni(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&Jt(pa),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),bl(wt),Rt(e),null;case 25:return null;case 30:return e.flags|=33554432,Rt(e),null}throw Error(f(156,e.tag))}function W0(t,e){switch(Wc(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return bl(wt),Ua(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return Cu(e),null;case 31:if(e.memoizedState!==null){if(Se(e),e.alternate===null)throw Error(f(340));da()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(Se(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(f(340));da()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return hs(e),t=e.flags,t&65536?(e.flags=t&-65537|128,t=e.memoizedState,t!==null&&(t.rendering=null,t.tail=null),e.flags|=4,e):null;case 4:return Ua(),null;case 10:return bl(e.type),null;case 22:case 23:return Se(e),rs(),t!==null&&Jt(pa),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return bl(wt),null;case 25:return null;default:return null}}function Fh(t,e){switch(Wc(e),e.tag){case 3:bl(wt),Ua();break;case 26:case 27:case 5:Cu(e);break;case 4:Ua();break;case 31:e.memoizedState!==null&&Se(e);break;case 13:Se(e);break;case 19:hs(e);break;case 10:bl(e.type);break;case 22:case 23:Se(e),rs(),t!==null&&Jt(pa);break;case 24:bl(wt)}}function nu(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&t)===t){a=void 0;var u=l.create,i=l.inst;a=u(),i.destroy=a}l=l.next}while(l!==n)}}catch(h){Tt(e,e.return,h)}}function Zl(t,e,l){try{var a=e.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&t)===t){var i=a.inst,h=i.destroy;if(h!==void 0){i.destroy=void 0,n=e;var g=l,_=h;try{_()}catch(A){Tt(n,g,A)}}}a=a.next}while(a!==u)}}catch(A){Tt(e,e.return,A)}}function Ih(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{Go(e,l)}catch(a){Tt(t,t.return,a)}}}function Ph(t,e,l){l.props=_a(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){Tt(t,e,a)}}function tl(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var n=t.stateNode,u=ml(t.memoizedProps,n);(n.ref===null||n.ref.name!==u)&&(n.ref=im(u)),a=n.ref;break;case 7:if(t.stateNode===null){var i=new ze(t);p(t.child,!1,Yv,i,void 0,void 0),t.stateNode=i}a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(h){Tt(t,e,h)}}function Pt(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Tt(t,e,n)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Tt(t,e,n)}else l.current=null}function ji(t,e){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&e!==null)for(var l=0;l title"))),te(a,e,l),a[$t]=t,Xt(a),e=a;break t;case"link":if(u=_m("link","href",n).get(e+(l.href||""))){for(i=0;iat&&(i=at,at=G,G=i);var T=ro(h,G),v=ro(h,at);if(T&&v&&(N.rangeCount!==1||N.anchorNode!==T.node||N.anchorOffset!==T.offset||N.focusNode!==v.node||N.focusOffset!==v.offset)){var z=C.createRange();z.setStart(T.node,T.offset),N.removeAllRanges(),G>at?(N.addRange(z),N.extend(v.node,v.offset)):(z.setEnd(v.node,v.offset),N.addRange(z))}}}}for(C=[],N=h;N=N.parentNode;)N.nodeType===1&&C.push({element:N,left:N.scrollLeft,top:N.scrollTop});for(typeof h.focus=="function"&&h.focus(),h=0;hl?32:l,X.T=null,l=ff,ff=null;var u=Xe,i=il;if(Dt=0,ja=Xe=null,il=0,(yt&6)!==0)throw Error(f(331));var h=yt;if(yt|=4,Td(u.current),bd(u,u.current,i,l),yt=h,ou(0,!1),ve&&typeof ve.onPostCommitFiberRoot=="function")try{ve.onPostCommitFiberRoot(On,u)}catch{}return!0}finally{P.p=n,X.T=a,wd(t,e)}}function Bd(t,e,l){e=Ce(l,e),e=Cs(t.stateNode,e,2),t=Yl(t,e,2),t!==null&&(Cn(t,2),cl(t))}function Tt(t,e,l){if(t.tag===3)Bd(t,t,l);else for(;e!==null;){if(e.tag===3){Bd(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Jl===null||!Jl.has(a))){t=Ce(l,t),l=Uh(2),a=Yl(e,l,2),a!==null&&(Hh(l,a,e,t),Cn(a,2),cl(a));break}}e=e.return}}function vf(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new tv;var n=new Set;a.set(e,n)}else n=a.get(e),n===void 0&&(n=new Set,a.set(e,n));n.has(l)||(uf=!0,n.add(l),t=sv.bind(null,t,e,l),e.then(t,t))}function sv(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,Nt===t&&(ft&l)===l&&((Ut===4||Ut===3&&(ft&62914560)===ft&&300>ge()-wi)&&(yt&2)===0?mn(t,0):qi|=l,fn===ft&&(fn=0)),cl(t)}function kd(t,e){e===0&&(e=_r()),t=oa(t,e),t!==null&&(Cn(t,e),cl(t))}function fv(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),kd(t,l)}function rv(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,n=t.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(f(314))}a!==null&&a.delete(e),kd(t,l)}function ov(t,e){return pc(t,e)}var vn=null,yn=null,yf=!1,Li=!1,pf=!1,Wl=0;function cl(t){t!==yn&&t.next===null&&(yn===null?vn=yn=t:yn=yn.next=t),Li=!0,yf||(yf=!0,dv())}function ou(t,e){if(!pf&&Li){pf=!0;do for(var l=!1,a=vn;a!==null;){if(t!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,h=a.pingedLanes;u=(1<<31-ye(42|t)+1)-1,u&=n&~(i&~h),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Xd(a,u))}else u=ft,u=qu(a,a===Nt?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Rn(a,u)||(l=!0,Xd(a,u));a=a.next}while(l);pf=!1}}function hv(){Yd()}function Yd(){Li=yf=!1;var t=0;Wl!==0&&Ev()&&(t=Wl);for(var e=ge(),l=null,a=vn;a!==null;){var n=a.next,u=Gd(a,e);u===0?(a.next=null,l===null?vn=n:l.next=n,n===null&&(yn=l)):(l=a,(t!==0||(u&3)!==0)&&(Li=!0)),a=n}Dt!==0&&Dt!==5||ou(t),Wl!==0&&(Wl=0)}function Gd(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,n=t.expirationTimes,u=t.pendingLanes&-62914561;0h)break;var A=g.transferSize,C=g.initiatorType;A&&Wd(C)&&(g=g.responseEnd,i+=A*(gWi){G.length=H;break}z=new Promise(Rv.bind(z)),G.push(z)}}}if(0"u"?null:document;function bm(t,e,l){var a=bn;if(a&&typeof e=="string"&&e){var n=Oe(e);n='link[rel="'+t+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),pm.has(n)||(pm.add(n),t={rel:t,crossOrigin:l,href:e},a.querySelector(n)===null&&(e=a.createElement("link"),te(e,"link",t),Xt(e),a.head.appendChild(e)))}}function $v(t){zl.D(t),bm("dns-prefetch",t,null)}function Wv(t,e){zl.C(t,e),bm("preconnect",t,e)}function Fv(t,e,l){zl.L(t,e,l);var a=bn;if(a&&t&&e){var n='link[rel="preload"][as="'+Oe(e)+'"]';e==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Oe(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Oe(l.imageSizes)+'"]')):n+='[href="'+Oe(t)+'"]';var u=n;switch(e){case"style":u=Sn(t);break;case"script":u=xn(t)}if(!(we.has(u)||(t=nt({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),we.set(u,t),a.querySelector(n)!==null||e==="style"&&a.querySelector(vu(u))||e==="script"&&a.querySelector(yu(u))))){var i=a.createElement("link");te(i,"link",t),e==="style"&&(i[wu]=!0,i.onload=i.onerror=function(){Cr(i)}),Xt(i),a.head.appendChild(i)}}}function Iv(t,e){zl.m(t,e);var l=bn;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",n='link[rel="modulepreload"][as="'+Oe(a)+'"][href="'+Oe(t)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=xn(t)}if(!we.has(u)&&(t=nt({rel:"modulepreload",href:t},e),we.set(u,t),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(yu(u)))return}a=l.createElement("link"),te(a,"link",t),Xt(a),l.head.appendChild(a)}}}function Pv(t,e,l){zl.S(t,e,l);var a=bn;if(a&&t){var n=wa(a).hoistableStyles,u=Sn(t);e=e||"default";var i=n.get(u);if(!i){var h={loading:0,preload:null};if(i=a.querySelector(vu(u)))h.loading=5;else{t=nt({rel:"stylesheet",href:t,"data-precedence":e},l),(l=we.get(u))&&kf(t,l);var g=i=a.createElement("link");Xt(g),te(g,"link",t),g._p=new Promise(function(_,A){g.onload=_,g.onerror=A}),g.addEventListener("load",function(){h.loading|=1}),g.addEventListener("error",function(){h.loading|=2}),h.loading|=4,Ji(i,e,a)}i={type:"stylesheet",instance:i,count:1,state:h},n.set(u,i)}}}function ty(t,e){zl.X(t,e);var l=bn;if(l&&t){var a=wa(l).hoistableScripts,n=xn(t),u=a.get(n);u||(u=l.querySelector(yu(n)),u||(t=nt({src:t,async:!0},e),(e=we.get(n))&&Yf(t,e),u=l.createElement("script"),Xt(u),te(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ey(t,e){zl.M(t,e);var l=bn;if(l&&t){var a=wa(l).hoistableScripts,n=xn(t),u=a.get(n);u||(u=l.querySelector(yu(n)),u||(t=nt({src:t,async:!0,type:"module"},e),(e=we.get(n))&&Yf(t,e),u=l.createElement("script"),Xt(u),te(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Sm(t,e,l,a){var n=(n=Al.current)?gu(n):null;if(!n)throw Error(f(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(l=Sn(l.href),e=wa(n).hoistableStyles,a=e.get(l),a||(a={type:"style",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=Sn(l.href);var u=wa(n).hoistableStyles,i=u.get(t);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(t,i),(u=n.querySelector(vu(t)))?u._p||(i.instance=u,i.state.loading=5):(u=we.get(t),u||(u={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},we.set(t,u)),ly(n,t,u,i.state))),e&&a===null)throw Error(f(528,""));return i}if(e&&a!==null)throw Error(f(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(l=xn(l),e=wa(n).hoistableScripts,a=e.get(l),a||(a={type:"script",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(f(444,t))}}function Sn(t){return'href="'+Oe(t)+'"'}function vu(t){return'link[rel="stylesheet"]['+t+"]"}function xm(t){return nt({},t,{"data-precedence":t.precedence,precedence:null})}function ly(t,e,l,a){if(e=t.querySelector('link[rel="preload"][as="style"]['+e+"]")){if(e[wu]!==!0){a.loading=1;return}}else e=t.createElement("link"),e[wu]=!0,e.onload=e.onerror=Cr.bind(null,e),te(e,"link",l),Xt(e),t.head.appendChild(e);a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2})}function xn(t){return'[src="'+Oe(t)+'"]'}function yu(t){return"script[async]"+t}function Tm(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+Oe(l.href)+'"]');if(a)return e.instance=a,Xt(a),a;var n=nt({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),Xt(a),te(a,"style",n),Ji(a,l.precedence,t),e.instance=a;case"stylesheet":n=Sn(l.href);var u=t.querySelector(vu(n));if(u)return e.state.loading|=4,e.instance=u,Xt(u),u;a=xm(l),(n=we.get(n))&&kf(a,n),u=(t.ownerDocument||t).createElement("link"),Xt(u);var i=u;return i._p=new Promise(function(h,g){i.onload=h,i.onerror=g}),te(u,"link",a),e.state.loading|=4,Ji(u,l.precedence,t),e.instance=u;case"script":return u=xn(l.src),(n=t.querySelector(yu(u)))?(e.instance=n,Xt(n),n):(a=l,(n=we.get(u))&&(a=nt({},l),Yf(a,n)),t=t.ownerDocument||t,n=t.createElement("script"),Xt(n),te(n,"link",a),t.head.appendChild(n),e.instance=n);case"void":return null;default:throw Error(f(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,Ji(a,l.precedence,t));return e.instance}function Ji(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i title"):null)}function ay(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;return e.rel==="stylesheet"?(t=e.disabled,typeof e.precedence=="string"&&t==null):!0;case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function Em(t,e){return t==="img"&&e.src!=null&&e.src!==""&&e.onLoad==null&&e.loading!=="lazy"}function zm(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Nm(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function jm(t,e){typeof e.decode=="function"&&(t.imgCount++,e.complete||(t.imgBytes+=Nm(e),t.suspenseyImages.push(e)),t=iy.bind(t),e.decode().then(t,t))}function ny(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Sn(a.href),u=e.querySelector(vu(n));if(u){e=u._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=pu.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=u,Xt(u);return}u=e.ownerDocument||e,a=xm(a),(n=we.get(n))&&kf(a,n),u=u.createElement("link"),Xt(u);var i=u;i._p=new Promise(function(h,g){i.onload=h,i.onerror=g}),te(u,"link",a),l.instance=u}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=pu.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var Wi=0;function uy(t,e){return t.stylesheets&&t.count===0&&Ii(t,t.stylesheets),0Wi?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Am(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Ii(t,t.stylesheets);else if(t.unsuspend){var e=t.unsuspend;t.unsuspend=null,e()}}}function pu(){this.count--,Am(this)}function iy(){this.imgCount--,Am(this)}var Fi=null;function Ii(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Fi=new Map,e.forEach(cy,t),Fi=null,pu.call(t))}function cy(t,e){if(!(e.state.loading&4)){var l=Fi.get(t);if(l)var a=l.get(null);else{l=new Map,Fi.set(t,l);for(var n=t.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(c){console.error(c)}}return s(),$f.exports=_y(),$f.exports}var zy=Ey(),q=ir();const tr="cc_console_token";let rg=()=>{};function cr(){return localStorage.getItem(tr)??""}function sr(s){s?localStorage.setItem(tr,s):localStorage.removeItem(tr)}function Ny(s){rg=s}class Im extends Error{status;constructor(c,r){super(r),this.status=c}}async function uc(s,c,r){const f={Authorization:`Bearer ${cr()}`};r!==void 0&&(f["Content-Type"]="application/json");const d=await fetch(`/api/v1${c}`,{method:s,headers:f,body:r===void 0?void 0:JSON.stringify(r)});if(d.status===401)throw sr(""),rg(),new Im(401,"unauthorized");if(!d.ok){let m=`http ${d.status}`;try{const b=await d.json();b.error&&(m=b.error)}catch{}throw new Im(d.status,m)}if(d.status!==204)return await d.json()}const Kt={get:s=>uc("GET",s),post:(s,c)=>uc("POST",s,c),patch:(s,c)=>uc("PATCH",s,c),put:(s,c)=>uc("PUT",s,c)};function er(s){const c=new URLSearchParams;for(const[f,d]of Object.entries(s))d&&c.set(f,d);const r=c.toString();return r?`?${r}`:""}function jy(){const[s,c]=q.useState(()=>window.location.hash.slice(1)||"/");return q.useEffect(()=>{const r=()=>c(window.location.hash.slice(1)||"/");return window.addEventListener("hashchange",r),()=>window.removeEventListener("hashchange",r)},[]),s}function Ra(s){window.location.hash=s}function Ke(s){if(!s)return"-";const c=new Date(s);if(Number.isNaN(c.getTime()))return s;const r=f=>String(f).padStart(2,"0");return`${c.getFullYear()}-${r(c.getMonth()+1)}-${r(c.getDate())} ${r(c.getHours())}:${r(c.getMinutes())}:${r(c.getSeconds())}`}function Ay(s){if(!s)return"never";const c=Date.now()-new Date(s).getTime();return Number.isNaN(c)?s:c<6e4?`${Math.max(0,Math.floor(c/1e3))}s ago`:c<36e5?`${Math.floor(c/6e4)}m ago`:c<864e5?`${Math.floor(c/36e5)}h ago`:`${Math.floor(c/864e5)}d ago`}const Nn=["proposal","analysis","design","review","implementation","testing","evaluation","confirmation"],Pm=["idle","assigned","in_progress","awaiting_review","changes_requested","approved"],Oy=["planned","in_progress","blocked_pending_decision","done","cancelled"];function Ry(s){const[c,r]=q.useState([]),[f,d]=q.useState("connecting"),m=q.useRef(s);return m.current=s,q.useEffect(()=>{let b=!1,y,j,E;const O=()=>{j||b||(d("poll"),j=setInterval(()=>m.current(),1e4))},p=async()=>{if(!b){E=new AbortController;try{const D=await fetch("/api/v1/stream",{headers:{Authorization:`Bearer ${cr()}`},signal:E.signal});if(!D.ok||!D.body)throw new Error(`stream http ${D.status}`);j&&(clearInterval(j),j=void 0),d("sse");const J=D.body.pipeThrough(new TextDecoderStream).getReader();let Q="";for(;;){const{done:B,value:F}=await J.read();if(B)break;Q+=F;let K;for(;(K=Q.indexOf(`
-
-`))>=0;){const pt=Q.slice(0,K);Q=Q.slice(K+2);for(const Ht of pt.split(`
-`))if(Ht.startsWith("data:"))try{const U=JSON.parse(Ht.slice(5).trim());r(et=>[U,...et].slice(0,50)),m.current()}catch{}}}throw new Error("stream closed")}catch{if(b)return;O(),y=setTimeout(p,1e4)}}};return p(),()=>{b=!0,E?.abort(),y&&clearTimeout(y),j&&clearInterval(j)}},[]),{events:c,mode:f}}function tg(){const[s,c]=q.useState(null),[r,f]=q.useState(""),d=q.useCallback(()=>{Kt.get("/overview").then(c).catch(j=>{j.message!=="unauthorized"&&f(j.message)})},[]);q.useEffect(()=>{d()},[d]);const{events:m,mode:b}=Ry(d),y=(j,E)=>s?.task_counts.find(O=>O.stage===j&&O.stage_state===E)?.count??0;return o.jsxs("div",{children:[o.jsxs("div",{className:"page-head",children:[o.jsx("h2",{children:"总览"}),o.jsx("span",{className:"badge",children:b==="sse"?"SSE 实时":b==="poll"?"10s 轮询":"连接中"}),o.jsx("div",{className:"spacer"}),o.jsx("button",{onClick:d,children:"刷新"})]}),r&&o.jsx("div",{className:"error-box",children:r}),o.jsxs("div",{className:"stat-cards",children:[o.jsxs("div",{className:`stat-card ${s&&s.open_decisions>0?"crit":"ok"}`,onClick:()=>Ra("/decisions"),children:[o.jsx("div",{className:"num",children:s?.open_decisions??"-"}),o.jsx("div",{className:"lbl",children:"待裁决决策"})]}),o.jsxs("div",{className:`stat-card ${s&&s.awaiting_review>0?"warn":"ok"}`,onClick:()=>Ra("/board"),children:[o.jsx("div",{className:"num",children:s?.awaiting_review??"-"}),o.jsx("div",{className:"lbl",children:"待审推进"})]}),o.jsxs("div",{className:"stat-card",onClick:()=>Ra("/audit"),children:[o.jsx("div",{className:"num",children:s?.open_findings??"-"}),o.jsx("div",{className:"lbl",children:"Open Findings"})]})]}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"阶段 × 状态矩阵"}),o.jsxs("table",{className:"matrix",children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:"stage"}),Pm.map(j=>o.jsx("th",{children:j},j))]})}),o.jsx("tbody",{children:Nn.map(j=>o.jsxs("tr",{children:[o.jsx("td",{children:j}),Pm.map(E=>{const O=y(j,E);return o.jsx("td",{className:O>0&&(E==="awaiting_review"||E==="changes_requested")?"hot":"",children:O||""},E)})]},j))})]})]}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"Agent 心跳活性"}),!s||s.agents.length===0?o.jsx("div",{className:"dim mono-sm",children:"暂无 agent 活动记录"}):s.agents.map(j=>o.jsxs("div",{className:"agent-row",children:[o.jsx("span",{className:`dot ${j.stale?"stale":"live"}`}),o.jsx("span",{children:j.agent}),o.jsxs("span",{className:"dim mono-sm",children:[j.stale?"stale":"live"," · last heartbeat ",Ay(j.last_heartbeat_at)]})]},j.agent))]}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"最近事件"}),o.jsx("div",{className:"event-feed",children:m.length===0?o.jsx("div",{className:"dim mono-sm",children:b==="sse"?"等待事件…":"事件流不可用,已切换轮询模式"}):m.map(j=>o.jsxs("div",{className:"ev",children:[o.jsx("span",{className:"ts",children:Ke(j.ts)}),o.jsx("span",{className:"phase",children:j.phase}),o.jsxs("span",{children:[j.agent&&o.jsxs("strong",{children:[j.agent," "]}),j.message]})]},j.id))})]})]})}function Cy({plans:s,onCreated:c,onClose:r}){const[f,d]=q.useState(""),[m,b]=q.useState(""),[y,j]=q.useState("task"),[E,O]=q.useState(""),[p,D]=q.useState(!0),[J,Q]=q.useState(0),[B,F]=q.useState(""),[K,pt]=q.useState(""),[Ht,U]=q.useState(!1),et=async Y=>{Y.preventDefault(),U(!0),pt("");try{await Kt.post("/tasks",{slug:f.trim(),title:m.trim(),kind:y,plan_id:E||void 0,testing_required:p,priority:J,instruction_md:B}),c()}catch(nt){pt(nt.message),U(!1)}};return o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"新建任务"}),K&&o.jsx("div",{className:"error-box",children:K}),o.jsxs("form",{onSubmit:et,children:[o.jsxs("div",{className:"op-row",children:[o.jsxs("label",{children:["slug",o.jsx("input",{required:!0,value:f,onChange:Y=>d(Y.target.value),placeholder:"my-task-slug"})]}),o.jsxs("label",{style:{flex:1,minWidth:220},children:["title",o.jsx("input",{required:!0,value:m,onChange:Y=>b(Y.target.value)})]}),o.jsxs("label",{children:["kind",o.jsxs("select",{value:y,onChange:Y=>j(Y.target.value),children:[o.jsx("option",{value:"task",children:"task"}),o.jsx("option",{value:"proposal",children:"proposal"})]})]}),o.jsxs("label",{children:["plan",o.jsxs("select",{value:E,onChange:Y=>O(Y.target.value),children:[o.jsx("option",{value:"",children:"(none)"}),s.map(Y=>o.jsx("option",{value:Y.id,children:Y.slug},Y.id))]})]}),o.jsxs("label",{children:["priority",o.jsx("input",{type:"number",style:{width:80},value:J,onChange:Y=>Q(Number(Y.target.value))})]}),o.jsxs("label",{style:{flexDirection:"row",alignItems:"center",gap:6},children:[o.jsx("input",{type:"checkbox",checked:p,onChange:Y=>D(Y.target.checked)}),"testing_required"]})]}),o.jsx("label",{className:"dim mono-sm",children:"instruction_md"}),o.jsx("textarea",{rows:5,value:B,onChange:Y=>F(Y.target.value),placeholder:"任务指令(markdown)"}),o.jsxs("div",{className:"op-row",style:{marginTop:8},children:[o.jsx("button",{className:"primary",type:"submit",disabled:Ht,children:"创建"}),o.jsx("button",{type:"button",onClick:r,children:"取消"})]})]})]})}function Dy(){const[s,c]=q.useState([]),[r,f]=q.useState([]),[d,m]=q.useState(""),[b,y]=q.useState(""),[j,E]=q.useState(""),[O,p]=q.useState(!1),[D,J]=q.useState(""),Q=q.useCallback(()=>{Kt.get(`/tasks${er({status:d,plan_id:b,q:j})}`).then(B=>{c(B),J("")}).catch(B=>{B.message!=="unauthorized"&&J(B.message)})},[d,b,j]);return q.useEffect(()=>{Q()},[Q]),q.useEffect(()=>{Kt.get("/plans").then(f).catch(()=>{})},[]),o.jsxs("div",{children:[o.jsxs("div",{className:"page-head",children:[o.jsx("h2",{children:"看板"}),o.jsxs("div",{className:"filters",children:[o.jsxs("select",{value:b,onChange:B=>y(B.target.value),children:[o.jsx("option",{value:"",children:"全部 plan"}),r.map(B=>o.jsx("option",{value:B.id,children:B.slug},B.id))]}),o.jsxs("select",{value:d,onChange:B=>m(B.target.value),children:[o.jsx("option",{value:"",children:"全部状态"}),Oy.map(B=>o.jsx("option",{value:B,children:B},B))]}),o.jsx("input",{placeholder:"搜索 slug/title",value:j,onChange:B=>E(B.target.value)})]}),o.jsx("div",{className:"spacer"}),o.jsx("button",{className:"primary",onClick:()=>p(B=>!B),children:O?"收起":"新建任务"})]}),D&&o.jsx("div",{className:"error-box",children:D}),O&&o.jsx(Cy,{plans:r,onClose:()=>p(!1),onCreated:()=>{p(!1),Q()}}),o.jsx("div",{className:"board",children:Nn.map(B=>{const F=s.filter(K=>K.stage===B);return o.jsxs("div",{className:"lane",children:[o.jsxs("h4",{children:[o.jsx("span",{children:B}),o.jsx("span",{children:F.length})]}),F.map(K=>o.jsxs("div",{className:"card",onClick:()=>Ra(`/tasks/${K.id}`),children:[o.jsx("div",{className:"title",children:K.title}),o.jsx("div",{className:"meta",children:o.jsx("span",{className:"mono-sm",children:K.slug})}),o.jsxs("div",{className:"meta",style:{marginTop:4},children:[o.jsx("span",{className:`badge st-${K.stage_state}`,children:K.stage_state}),o.jsx("span",{className:`badge status-${K.status}`,children:K.status}),o.jsxs("span",{children:["P",K.priority]}),K.assigned_agent&&o.jsxs("span",{children:["@",K.assigned_agent]})]})]},K.id))]},B)})})]})}function fr(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Da=fr();function og(s){Da=s}var Oa={exec:()=>null};function zn(s){let c=[];return r=>{let f=Math.max(0,Math.min(3,r-1)),d=c[f];return d||(d=s(f),c[f]=d),d}}function ut(s,c=""){let r=typeof s=="string"?s:s.source,f={replace:(d,m)=>{let b=typeof m=="string"?m:m.source;return b=b.replace(ae.caret,"$1"),r=r.replace(d,b),f},getRegex:()=>new RegExp(r,c)};return f}var My=((s="")=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:s=>new RegExp(`^( {0,3}${s})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:zn(s=>new RegExp(`^ {0,${s}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)),hrRegex:zn(s=>new RegExp(`^ {0,${s}}((?:-[ ]*){3,}|(?:_[ ]*){3,}|(?:\\*[ ]*){3,})(?:\\n+|$)`)),fencesBeginRegex:zn(s=>new RegExp(`^ {0,${s}}(?:\`\`\`|~~~)`)),headingBeginRegex:zn(s=>new RegExp(`^ {0,${s}}#`)),htmlBeginRegex:zn(s=>new RegExp(`^ {0,${s}}(?:?(?:${ju})(?: +|$|/?>)|<(?:script|pre|style|textarea|!--))`,"i")),blockquoteBeginRegex:zn(s=>new RegExp(`^ {0,${s}}>`))},Uy=/^(?:[ \t]*(?:\n|$))+/,Hy=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,qy=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,Nu=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,wy=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,rr=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,hg=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,dg=ut(hg).replace(/bull/g,rr).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\s|$)/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),By=ut(hg).replace(/bull/g,rr).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\s|$)/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),or=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/,ky=/^[^\n]+/,hr=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,Yy=ut(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",hr).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Gy=ut(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g,rr).getRegex(),ju="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",dr=/|$))/,Qy=ut("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|[^\\n]*\\n*|$)|[^\\n]*\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][a-z0-9-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?!script|pre|style|textarea)[a-z][a-z0-9-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",dr).replace("tag",ju).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),mg=s=>ut(or).replace("hr",Nu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list",s).replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex(),Xy=mg(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/),Zy=mg(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/),Ly=ut(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Zy).getRegex(),mr={blockquote:Ly,code:Hy,def:Yy,fences:qy,heading:wy,hr:Nu,html:Qy,lheading:dg,list:Gy,newline:Uy,paragraph:Xy,table:Oa,text:ky},eg=ut("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",Nu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex(),Vy={...mr,lheading:By,table:eg,paragraph:ut(or).replace("hr",Nu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",eg).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex()},Ky={...mr,html:ut(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)| \\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",dr).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Oa,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:ut(or).replace("hr",Nu).replace("heading",` *#{1,6} *[^
-]`).replace("lheading",dg).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Jy=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,$y=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,gg=/^( {2,}|\\)\n(?!\s*$)[ \t]*/,Wy=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k (?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",My?"(?`+)[^`]+\k(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),yg=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,lp=ut(yg,"u").replace(/punct/g,Nl).getRegex(),ap=ut(yg,"u").replace(/punct/g,vg).getRegex(),np=/^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/,up=ut(np,"u").replace(/openQuote/g,Iy).replace(/punct/g,Nl).getRegex(),pg="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",ip=ut(pg,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,Nl).getRegex(),cp=ut(pg,"gu").replace(/notPunctSpace/g,tp).replace(/punctSpace/g,Py).replace(/punct/g,vg).getRegex(),sp="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)",fp=ut(sp,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,Nl).getRegex(),rp=ut("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,Nl).getRegex(),op="^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\s](_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)",hp=ut(op,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,Nl).getRegex(),dp=ut(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,Nl).getRegex(),mp="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",gp=ut(mp,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,Nl).getRegex(),vp=ut(/\\(punct)/,"gu").replace(/punct/g,Nl).getRegex(),yp=ut(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),pp=ut(dr).replace("(?:-->|$)","-->").getRegex(),bp=ut("^comment|^[a-zA-Z][a-zA-Z0-9-]*\\s*>|^<[a-zA-Z][a-zA-Z0-9-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",pp).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),bg=/\[(?:\\[\s\S]|[^\[\]\\])*\]/,cc=ut(/(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/).replace("brackets",bg).getRegex(),Sp=ut(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",cc).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),xp=ut(/^!?\[(label)\]\[(ref)\]/).replace("label",cc).replace("ref",hr).getRegex(),Tp=ut(/^!?\[(ref)\](?:\[\])?/).replace("ref",hr).getRegex(),lg=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\]){1,999}/,_p=ut(/(?:[^\[\]\\`]*(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\]))){0,999}?[^\[\]\\`]*?/).replace("brackets",bg).getRegex(),Ep=ut("reflink|nolink(?!\\()","g").replace("reflink",ut(/^!?\[(label)\]\[(ref)\]/).replace("label",_p).replace("ref",lg).getRegex()).replace("nolink",ut(/^!?\[(ref)\](?:\[\])?/).replace("ref",lg).getRegex()).getRegex(),ag=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,gr={_backpedal:Oa,anyPunctuation:vp,autolink:yp,blockSkip:ep,br:gg,code:$y,del:Oa,delLDelim:Oa,delRDelim:Oa,emStrongLDelim:lp,emStrongRDelimAst:ip,emStrongRDelimUnd:rp,escape:Jy,link:Sp,nolink:Tp,punctuation:Fy,reflink:xp,reflinkSearch:Ep,tag:bp,text:Wy,url:Oa},zp={...gr,emStrongLDelim:up,emStrongRDelimAst:fp,emStrongRDelimUnd:hp,link:ut(/^!?\[(label)\]\((.*?)\)/).replace("label",cc).getRegex(),reflink:ut(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",cc).getRegex()},lr={...gr,emStrongRDelimAst:cp,emStrongLDelim:ap,delLDelim:dp,delRDelim:gp,url:ut(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ag).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![\w-])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:ut(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},ng=s=>jp[s];function Ne(s,c){if(c){if(ae.escapeTest.test(s))return s.replace(ae.escapeReplace,ng)}else if(ae.escapeTestNoEncode.test(s))return s.replace(ae.escapeReplaceNoEncode,ng);return s}function ug(s){try{s=encodeURI(s).replace(ae.percentDecode,"%")}catch{return null}return s}function ig(s,c){let r=s.replace(ae.findPipe,(m,b,y)=>{let j=!1,E=b;for(;--E>=0&&y[E]==="\\";)j=!j;return j?"|":" |"}),f=r.split(ae.splitPipe),d=0;if(f[0].trim()||f.shift(),f.length>0&&!f.at(-1)?.trim()&&f.pop(),c)if(f.length>c)f.splice(c);else for(;f.length=0&&ae.blankLine.test(c[r]);)r--;return c.length-r<=2?s:c.slice(0,r+1).join(`
-`)}function sc(s){return s.toLowerCase().toUpperCase().toLowerCase()}function Ap(s,c){if(s.indexOf(c[1])===-1)return-1;let r=0;for(let f=0;f0?-2:-1}function Op(s,c=0){let r=c,f="";for(let d of s)if(d===" "){let m=4-r%4;f+=" ".repeat(m),r+=m}else f+=d,r++;return f}function sg(s,c,r,f,d){let m=c.href,b=c.title||null,y=s[1].replace(d.other.outputLinkReplace,"$1"),j=s[0].charAt(0)==="!";f.state.inLink=!0;let E=f.state.linkEmitted,O=f.state.inRawBlock;f.state.linkEmitted=!1;let p=f.inlineTokens(y),D=f.state.linkEmitted;if(f.state.linkEmitted=E,f.state.inLink=!1,!j){if(D){f.state.inRawBlock=O;return}f.state.linkEmitted=!0}return{type:j?"image":"link",raw:r,href:m,title:b,text:y,tokens:p}}function Rp(s,c,r){let f=s.match(r.other.indentCodeCompensation);if(f===null)return c;let d=f[1];return c.split(`
-`).map(m=>{let b=m.match(r.other.beginningSpace);if(b===null)return m;let[y]=b;return m.slice(Math.min(y.length,d.length))}).join(`
-`)}function fg(s,c,r,f){if(!c.includes("<"))return!1;for(let d=0;dc.length-d)return!0;d+=b[0].length-1}}return!1}var fc=class{options;rules;lexer;constructor(s){this.options=s||Da}space(s){let c=this.rules.block.newline.exec(s);if(c&&c[0].length>0)return{type:"space",raw:c[0]}}code(s){let c=this.rules.block.code.exec(s);if(c){let r=this.options.pedantic?c[0]:cg(c[0]),f=r.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:r,codeBlockStyle:"indented",text:f}}}fences(s){let c=this.rules.block.fences.exec(s);if(c){let r=c[0],f=Rp(r,c[3]||"",this.rules);return{type:"code",raw:r,lang:c[2]?c[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):c[2],text:f}}}heading(s){let c=this.rules.block.heading.exec(s);if(c){let r=c[2].trim();if(this.rules.other.endingHash.test(r)){let f=aa(r,"#");(this.options.pedantic||!f||this.rules.other.endingSpaceTabChar.test(f))&&(r=f.trim())}return{type:"heading",raw:aa(c[0],`
-`),depth:c[1].length,text:r,tokens:this.lexer.inline(r)}}}hr(s){let c=this.rules.block.hr.exec(s);if(c)return{type:"hr",raw:aa(c[0],`
-`)}}blockquote(s){let c=this.rules.block.blockquote.exec(s);if(c){let r=aa(c[0],`
-`).split(`
-`),f="",d="",m=[];for(;r.length>0;){let b=!1,y=[],j;for(j=0;j1,d={type:"list",raw:"",ordered:f,start:f?+r.slice(0,-1):"",loose:!1,items:[]};r=f?`\\d{1,9}\\${r.slice(-1)}`:`\\${r}`,this.options.pedantic&&(r=f?r:"[*+-]");let m=this.rules.other.listItemRegex(r),b=!1;for(;s;){let j=!1,E="",O="";if(!(c=m.exec(s))||this.rules.block.hr.test(s))break;E=c[0],s=s.substring(E.length);let p=Op(c[2].split(`
-`,1)[0],c[1].length),D=s.split(`
-`,1)[0],J=!p.trim(),Q=0;if(this.options.pedantic?(Q=2,O=p.trimStart()):J?Q=c[1].length+1:(Q=p.search(this.rules.other.nonSpaceChar),Q=Q>4?1:Q,O=p.slice(Q),Q+=c[1].length),J&&this.rules.other.blankLine.test(D)&&(E+=D+`
-`,s=s.substring(D.length+1),j=!0),!j){let B=this.rules.other.nextBulletRegex(Q),F=this.rules.other.hrRegex(Q),K=this.rules.other.fencesBeginRegex(Q),pt=this.rules.other.headingBeginRegex(Q),Ht=this.rules.other.htmlBeginRegex(Q),U=this.rules.other.blockquoteBeginRegex(Q);for(;s;){let et=s.split(`
-`,1)[0],Y;if(D=et,this.options.pedantic?(D=D.replace(this.rules.other.listReplaceNesting," "),Y=D):Y=D.replace(this.rules.other.tabCharGlobal," "),K.test(D)||pt.test(D)||Ht.test(D)||U.test(D)||B.test(D)||F.test(D))break;if(Y.search(this.rules.other.nonSpaceChar)>=Q||!D.trim())O+=`
-`+Y.slice(Q);else{if(J||p.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||K.test(p)||pt.test(p)||F.test(p))break;O+=`
-`+D}J=!D.trim(),E+=et+`
-`,s=s.substring(et.length+1),p=Y.slice(Q)}}d.loose||(b?d.loose=!0:this.rules.other.doubleBlankLine.test(E)&&(b=!0)),d.items.push({type:"list_item",raw:E,task:!!this.options.gfm&&this.rules.other.listIsTask.test(O),loose:!1,text:O,tokens:[]}),d.raw+=E}let y=d.items.at(-1);if(y)y.raw=y.raw.trimEnd(),y.text=y.text.trimEnd();else return;d.raw=d.raw.trimEnd();for(let j of d.items)if(this.lexer.state.top=!1,j.tokens=this.lexer.blockTokens(j.text,[]),!d.loose){let E=j.tokens.filter(p=>p.type==="space"),O=E.length>0&&E.some(p=>this.rules.other.anyLine.test(p.raw));d.loose=O}for(let j of d.items){let E=j.tokens[0];if(j.task&&(E?.type==="text"||E?.type==="paragraph")){j.text=j.text.replace(this.rules.other.listReplaceTask,""),E.raw=E.raw.replace(this.rules.other.listReplaceTask,""),E.text=E.text.replace(this.rules.other.listReplaceTask,"");for(let p=this.lexer.inlineQueue.length-1;p>=0;p--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[p].src)){this.lexer.inlineQueue[p].src=this.lexer.inlineQueue[p].src.replace(this.rules.other.listReplaceTask,"");break}let O=this.rules.other.listTaskCheckbox.exec(j.raw);if(O){let p={type:"checkbox",raw:O[0]+" ",checked:O[0]!=="[ ]"};j.checked=p.checked,d.loose?j.tokens[0]&&["paragraph","text"].includes(j.tokens[0].type)&&"tokens"in j.tokens[0]&&j.tokens[0].tokens?(j.tokens[0].raw=p.raw+j.tokens[0].raw,j.tokens[0].text=p.raw+j.tokens[0].text,j.tokens[0].tokens.unshift(p)):j.tokens.unshift({type:"paragraph",raw:p.raw,text:p.raw,tokens:[p]}):j.tokens.unshift(p)}}else j.task&&(j.task=!1)}if(d.loose)for(let j of d.items){j.loose=!0;for(let E of j.tokens)E.type==="text"&&(E.type="paragraph")}return d}}html(s){let c=this.rules.block.html.exec(s);if(c){let r=cg(c[0]);return{type:"html",block:!0,raw:r,pre:c[1]==="pre"||c[1]==="script"||c[1]==="style",text:r}}}def(s){let c=this.rules.block.def.exec(s);if(c){let r=sc(c[1]).replace(this.rules.other.multipleSpaceGlobal," "),f=c[2]?c[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",d=c[3]?c[3].substring(1,c[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):c[3];return{type:"def",tag:r,raw:aa(c[0],`
-`),href:f,title:d}}}table(s){let c=this.rules.block.table.exec(s);if(!c||!this.rules.other.tableDelimiter.test(c[2]))return;let r=ig(c[1]),f=c[2].replace(this.rules.other.tableAlignChars,"").split("|"),d=c[3]?.trim()?c[3].replace(this.rules.other.tableRowBlankLine,"").split(`
-`):[],m={type:"table",raw:aa(c[0],`
-`),header:[],align:[],rows:[]};if(r.length===f.length){for(let b of f)this.rules.other.tableAlignRight.test(b)?m.align.push("right"):this.rules.other.tableAlignCenter.test(b)?m.align.push("center"):this.rules.other.tableAlignLeft.test(b)?m.align.push("left"):m.align.push(null);for(let b=0;b({text:y,tokens:this.lexer.inline(y),header:!1,align:m.align[j]})));return m}}lheading(s){let c=this.rules.block.lheading.exec(s);if(c){let r=c[1].trim();return{type:"heading",raw:aa(c[0],`
-`),depth:c[2].charAt(0)==="="?1:2,text:r,tokens:this.lexer.inline(r)}}}paragraph(s){let c=this.rules.block.paragraph.exec(s);if(c){let r=c[1].charAt(c[1].length-1)===`
-`?c[1].slice(0,-1):c[1];return{type:"paragraph",raw:c[0],text:r,tokens:this.lexer.inline(r)}}}text(s){let c=this.rules.block.text.exec(s);if(c)return{type:"text",raw:c[0],text:c[0],tokens:this.lexer.inline(c[0])}}escape(s){let c=this.rules.inline.escape.exec(s);if(c)return{type:"escape",raw:c[0],text:c[1]}}tag(s){let c=this.rules.inline.tag.exec(s);if(c)return!this.lexer.state.inLink&&this.rules.other.startATag.test(c[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(c[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(c[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(c[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:c[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:c[0]}}link(s){let c=this.rules.inline.link.exec(s);if(c){let r=c[0].charAt(0)==="!"?2:1;if(!this.options.pedantic&&fg(s,c[1],r,this.rules))return;let f=c[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(f)){if(!this.rules.other.endAngleBracket.test(f))return;let b=aa(f.slice(0,-1),"\\");if((f.length-b.length)%2===0)return}else{let b=Ap(c[2],"()");if(b===-2)return;if(b>-1){let y=(c[0].indexOf("!")===0?5:4)+c[1].length+b;c[2]=c[2].substring(0,b),c[0]=c[0].substring(0,y).trim(),c[3]=""}}let d=c[2],m="";if(this.options.pedantic){let b=this.rules.other.pedanticHrefTitle.exec(d);b&&(d=b[1],m=b[3])}else m=c[3]?c[3].slice(1,-1):"";return d=d.trim(),this.rules.other.startAngleBracket.test(d)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(f)?d=d.slice(1):d=d.slice(1,-1)),sg(c,{href:d&&d.replace(this.rules.inline.anyPunctuation,"$1"),title:m&&m.replace(this.rules.inline.anyPunctuation,"$1")},c[0],this.lexer,this.rules)}}reflink(s,c){let r;if((r=this.rules.inline.reflink.exec(s))||(r=this.rules.inline.nolink.exec(s))){let f=r[0].charAt(0)==="!"?2:1;if(!this.options.pedantic&&fg(s,r[1],f,this.rules))return;let d=(r[2]||r[1]).replace(this.rules.other.multipleSpaceGlobal," "),m=c[sc(d)];if(!m){let b=r[0].charAt(0);return{type:"text",raw:b,text:b}}return sg(r,m,r[0],this.lexer,this.rules)}}emStrong(s,c,r=""){let f=this.rules.inline.emStrongLDelim.exec(s);if(!(!f||!f[1]&&!f[2]&&!f[3]&&!f[4]||f[4]&&r.match(this.rules.other.unicodeAlphaNumeric))&&(!(f[1]||f[3])||!r||this.rules.inline.punctuation.exec(r))){let d=[...f[0]].length-1,m,b,y=d,j=0,E=f[0][0],O=r===E,p=E==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(p.lastIndex=0,c=c.slice(-1*s.length+d);(f=p.exec(c))!==null;){if(m=f[1]||f[2]||f[3]||f[4]||f[5]||f[6],!m)continue;if(b=[...m].length,f[3]||f[4]){y+=b;continue}else if(f[5]||f[6]){if(d%3&&!((d+b)%3)){j+=b;continue}if(O)break}if(y-=b,y>0)continue;b=Math.min(b,b+y+j);let D=[...f[0]][0].length,J=s.slice(0,d+f.index+D+b);if(Math.min(d,b)%2){let B=J.slice(1,-1);return{type:"em",raw:J,text:B,tokens:this.lexer.inlineTokens(B)}}let Q=J.slice(2,-2);return{type:"strong",raw:J,text:Q,tokens:this.lexer.inlineTokens(Q)}}}}codespan(s){let c=this.rules.inline.code.exec(s);if(c){let r=c[2].replace(this.rules.other.newLineCharGlobal," "),f=this.rules.other.nonSpaceChar.test(r),d=this.rules.other.startingSpaceChar.test(r)&&this.rules.other.endingSpaceChar.test(r);return f&&d&&(r=r.substring(1,r.length-1)),{type:"codespan",raw:c[0],text:r}}}br(s){let c=this.rules.inline.br.exec(s);if(c)return{type:"br",raw:c[0]}}del(s,c,r=""){let f=this.rules.inline.delLDelim.exec(s);if(f&&(!f[1]||!r||this.rules.inline.punctuation.exec(r))){let d=[...f[0]].length-1,m,b,y=d,j=this.rules.inline.delRDelim;for(j.lastIndex=0,c=c.slice(-1*s.length+d);(f=j.exec(c))!==null;){if(m=f[1]||f[2]||f[3]||f[4]||f[5]||f[6],!m||(b=[...m].length,b!==d))continue;if(f[3]||f[4]){y+=b;continue}if(y-=b,y>0)continue;b=Math.min(b,b+y);let E=[...f[0]][0].length,O=s.slice(0,d+f.index+E+b),p=O.slice(d,-d);return{type:"del",raw:O,text:p,tokens:this.lexer.inlineTokens(p)}}}}autolink(s){let c=this.rules.inline.autolink.exec(s);if(c){let r,f;return c[2]==="@"?(r=c[1],f="mailto:"+r):(r=c[1],f=r),{type:"link",raw:c[0],text:r,href:f,autolink:!0,tokens:[{type:"text",raw:r,text:r}]}}}url(s){let c;if(c=this.rules.inline.url.exec(s)){let r,f;if(c[2]==="@")r=c[0],f="mailto:"+r;else{let d;do d=c[0],c[0]=this.rules.inline._backpedal.exec(c[0])?.[0]??"";while(d!==c[0]);r=c[0],c[1]==="www."?f="http://"+c[0]:f=c[0]}return{type:"link",raw:c[0],text:r,href:f,autolink:!0,tokens:[{type:"text",raw:r,text:r}]}}}inlineText(s){let c=this.rules.inline.text.exec(s);if(c){let r=this.lexer.state.inRawBlock;return{type:"text",raw:c[0],text:c[0],escaped:r}}}},Le=class ar{tokens;options;state;inlineQueue;tokenizer;constructor(c){this.tokens=[],this.tokens.links=Object.create(null),this.options=c||Da,this.options.tokenizer=this.options.tokenizer||new fc,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,linkEmitted:!1,top:!0};let r={other:ae,block:ic.normal,inline:Eu.normal};this.options.pedantic?(r.block=ic.pedantic,r.inline=Eu.pedantic):this.options.gfm&&(r.block=ic.gfm,this.options.breaks?r.inline=Eu.breaks:r.inline=Eu.gfm),this.tokenizer.rules=r}static get rules(){return{block:ic,inline:Eu}}static lex(c,r){return new ar(r).lex(c)}static lexInline(c,r){return new ar(r).inlineTokens(c)}lex(c){c=c.replace(ae.carriageReturn,`
-`),this.blockTokens(c,this.tokens);for(let r=0;r(m=y.call({lexer:this},c,r))?(c=c.substring(m.raw.length),r.push(m),!0):!1))continue;if(m=this.tokenizer.space(c)){c=c.substring(m.raw.length);let y=r.at(-1);m.raw.length===1&&y!==void 0?y.raw+=`
-`:r.push(m);continue}if(m=this.tokenizer.code(c)){c=c.substring(m.raw.length);let y=r.at(-1);y?.type==="paragraph"||y?.type==="text"?(y.raw+=(y.raw.endsWith(`
-`)?"":`
-`)+m.raw,y.text+=`
-`+m.text,this.inlineQueue.at(-1).src=y.text):r.push(m);continue}if(m=this.tokenizer.fences(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.heading(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.hr(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.blockquote(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.list(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.html(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.def(c)){c=c.substring(m.raw.length);let y=r.at(-1);y?.type==="paragraph"||y?.type==="text"?(y.raw+=(y.raw.endsWith(`
-`)?"":`
-`)+m.raw,y.text+=`
-`+m.raw,this.inlineQueue.at(-1).src=y.text):this.tokens.links[m.tag]||(this.tokens.links[m.tag]={href:m.href,title:m.title},r.push(m));continue}if(m=this.tokenizer.table(c)){c=c.substring(m.raw.length),r.push(m);continue}if(m=this.tokenizer.lheading(c)){c=c.substring(m.raw.length),r.push(m);continue}let b=c;if(this.options.extensions?.startBlock){let y=1/0,j=c.slice(1),E;this.options.extensions.startBlock.forEach(O=>{E=O.call({lexer:this},j),typeof E=="number"&&E>=0&&(y=Math.min(y,E))}),y<1/0&&y>=0&&(b=c.substring(0,y+1))}if(this.state.top&&(m=this.tokenizer.paragraph(b))){let y=r.at(-1);f&&y?.type==="paragraph"?(y.raw+=(y.raw.endsWith(`
-`)?"":`
-`)+m.raw,y.text+=`
-`+m.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=y.text):r.push(m),f=b.length!==c.length,c=c.substring(m.raw.length);continue}if(m=this.tokenizer.text(c)){c=c.substring(m.raw.length);let y=r.at(-1);y?.type==="text"?(y.raw+=(y.raw.endsWith(`
-`)?"":`
-`)+m.raw,y.text+=`
-`+m.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=y.text):r.push(m);continue}if(c){this.infiniteLoopError(c.charCodeAt(0));break}}return this.state.top=!0,r}inline(c,r=[]){return this.inlineQueue.push({src:c,tokens:r}),r}linkInText(c){if(!c.includes("["))return!1;let r=this.tokenizer.rules.inline.link;for(let f of c.matchAll(this.tokenizer.rules.inline.blockSkip))if(r.test(f[0])&&c.charAt(f.index-1)!=="!")return!0;for(let f of c.matchAll(this.tokenizer.rules.inline.reflinkSearch)){let d=f[0],m=d.lastIndexOf("[");if(!(d.charAt(0)==="!"||!Object.hasOwn(this.tokens.links,sc(d.slice(m+1,-1))))&&!(m>1&&this.linkInText(d.slice(1,m-1))))return!0}return!1}inlineTokens(c,r=[]){this.tokenizer.lexer=this;let f=c;if(this.tokens.links&&c.includes("[")){let y=this.tokenizer.rules.inline.reflinkSearch,j=E=>{let O=E.lastIndexOf("[");if(!Object.hasOwn(this.tokens.links,sc(E.slice(O+1,-1))))return E;if(O>1&&E.charAt(0)!=="!"){let p=E.slice(1,O-1);if(this.linkInText(p))return"["+p.replace(y,j)+"]["+"a".repeat(E.length-O-2)+"]"}return"["+"a".repeat(E.length-2)+"]"};f=f.replace(y,j)}f=f.replace(this.tokenizer.rules.inline.anyPunctuation,y=>"+".repeat(y.length)),f=f.replace(this.tokenizer.rules.inline.blockSkip,(y,j,E)=>{let O=E?E.length:0;return y.slice(0,O)+"["+"a".repeat(y.length-O-2)+"]"}),f=this.options.hooks?.emStrongMask?.call({lexer:this},f)??f;let d=!1,m="",b=1/0;for(;c;){if(c.length(y=E.call({lexer:this},c,r))?(c=c.substring(y.raw.length),r.push(y),!0):!1))continue;if(y=this.tokenizer.escape(c)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.tag(c)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.link(c)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.reflink(c,this.tokens.links)){c=c.substring(y.raw.length);let E=r.at(-1);y.type==="text"&&E?.type==="text"?(E.raw+=y.raw,E.text+=y.text):r.push(y);continue}if(y=this.tokenizer.emStrong(c,f,m)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.codespan(c)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.br(c)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.del(c,f,m)){c=c.substring(y.raw.length),r.push(y);continue}if(y=this.tokenizer.autolink(c)){c=c.substring(y.raw.length),r.push(y);continue}if(!this.state.inLink&&(y=this.tokenizer.url(c))){c=c.substring(y.raw.length),r.push(y);continue}let j=c;if(this.options.extensions?.startInline){let E=1/0,O=c.slice(1),p;this.options.extensions.startInline.forEach(D=>{p=D.call({lexer:this},O),typeof p=="number"&&p>=0&&(E=Math.min(E,p))}),E<1/0&&E>=0&&(j=c.substring(0,E+1))}if(y=this.tokenizer.inlineText(j)){c=c.substring(y.raw.length),y.raw.slice(-1)!=="_"&&(m=y.raw.slice(-1)),d=!0;let E=r.at(-1);E?.type==="text"?(E.raw+=y.raw,E.text+=y.text):r.push(y);continue}if(c){this.infiniteLoopError(c.charCodeAt(0));break}}return r}infiniteLoopError(c){let r="Infinite loop on byte: "+c;if(this.options.silent)console.error(r);else throw new Error(r)}},rc=class{options;parser;constructor(s){this.options=s||Da}space(s){return""}code({text:s,lang:c,escaped:r}){let f=(c||"").match(ae.notSpaceStart)?.[0],d=s?s.replace(ae.endingNewline,"")+`
-`:"";return f?''+(r?d:Ne(d,!0))+`
-`:""+(r?d:Ne(d,!0))+`
-`}blockquote({tokens:s}){return`
-${this.parser.parse(s)}
-`}html({text:s}){return s}def(s){return""}heading({tokens:s,depth:c}){return`${this.parser.parseInline(s)}
-`}hr(s){return`
-`}list(s){let c=s.ordered,r=s.start,f="";for(let b=0;b
-`+f+""+d+`>
-`}listitem(s){return`${this.parser.parse(s.tokens)}
-`}checkbox({checked:s}){return" '}paragraph({tokens:s}){return`${this.parser.parseInline(s)}
-`}table(s){let c="",r="";for(let d=0;d${f}`),`
-`}tablerow({text:s}){return`
-${s}
-`}tablecell(s){let c=this.parser.parseInline(s.tokens),r=s.header?"th":"td";return(s.align?`<${r} align="${s.align}">`:`<${r}>`)+c+`${r}>
-`}strong({tokens:s}){return`${this.parser.parseInline(s)} `}em({tokens:s}){return`${this.parser.parseInline(s)} `}codespan({text:s}){return`${Ne(s,!0)}`}br(s){return" "}del({tokens:s}){return`${this.parser.parseInline(s)}`}link({href:s,title:c,text:r,tokens:f,autolink:d}){let m=d?Ne(r,!0):this.parser.parseInline(f),b=ug(s);if(b===null)return m;s=Ne(b,d);let y='"+m+" ",y}image({href:s,title:c,text:r,tokens:f}){f&&(r=this.parser.parseInline(f,this.parser.textRenderer));let d=ug(s);if(d===null)return Ne(r);s=d;let m=` ",m}text(s){return"tokens"in s&&s.tokens?this.parser.parseInline(s.tokens):"escaped"in s&&s.escaped?s.text:Ne(s.text)}},vr=class{strong({text:s}){return s}em({text:s}){return s}codespan({text:s}){return s}del({text:s}){return s}html({text:s}){return s}text({text:s}){return s}link({text:s}){return""+s}image({text:s}){return""+s}br(){return""}checkbox({raw:s}){return s}},Ve=class nr{options;renderer;textRenderer;constructor(c){this.options=c||Da,this.options.renderer=this.options.renderer||new rc,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new vr}static parse(c,r){return new nr(r).parse(c)}static parseInline(c,r){return new nr(r).parseInline(c)}parse(c){this.renderer.parser=this;let r="";for(let f=0;f{let b=d[m].flat(1/0);r=r.concat(this.walkTokens(b,c))}):d.tokens&&(r=r.concat(this.walkTokens(d.tokens,c)))}}return r}use(...s){let c=this.defaults.extensions||{renderers:{},childTokens:{}};return s.forEach(r=>{let f={...r};if(f.async=this.defaults.async||f.async||!1,r.extensions&&(r.extensions.forEach(d=>{if(!d.name)throw new Error("extension name required");if("renderer"in d){let m=c.renderers[d.name];m?c.renderers[d.name]=function(...b){let y=d.renderer.apply(this,b);return y===!1&&(y=m.apply(this,b)),y}:c.renderers[d.name]=d.renderer}if("tokenizer"in d){if(!d.level||d.level!=="block"&&d.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let m=c[d.level];m?m.unshift(d.tokenizer):c[d.level]=[d.tokenizer],d.start&&(d.level==="block"?c.startBlock?c.startBlock.push(d.start):c.startBlock=[d.start]:d.level==="inline"&&(c.startInline?c.startInline.push(d.start):c.startInline=[d.start]))}"childTokens"in d&&d.childTokens&&(c.childTokens[d.name]=d.childTokens)}),f.extensions=c),r.renderer){let d=this.defaults.renderer||new rc(this.defaults);for(let m in r.renderer){if(!(m in d))throw new Error(`renderer '${m}' does not exist`);if(["options","parser"].includes(m))continue;let b=m,y=r.renderer[b],j=d[b];d[b]=(...E)=>{let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O||""}}f.renderer=d}if(r.tokenizer){let d=this.defaults.tokenizer||new fc(this.defaults);for(let m in r.tokenizer){if(!(m in d))throw new Error(`tokenizer '${m}' does not exist`);if(["options","rules","lexer"].includes(m))continue;let b=m,y=r.tokenizer[b],j=d[b];d[b]=(...E)=>{let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O}}f.tokenizer=d}if(r.hooks){let d=this.defaults.hooks||new zu;for(let m in r.hooks){if(!(m in d))throw new Error(`hook '${m}' does not exist`);if(["options","block"].includes(m))continue;let b=m,y=r.hooks[b],j=d[b];zu.passThroughHooks.has(m)?d[b]=E=>{if(this.defaults.async&&zu.passThroughHooksRespectAsync.has(m))return(async()=>{let p=await y.call(d,E);return j.call(d,p)})();let O=y.call(d,E);return j.call(d,O)}:d[b]=(...E)=>{if(this.defaults.async)return(async()=>{let p=await y.apply(d,E);return p===!1&&(p=await j.apply(d,E)),p})();let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O}}f.hooks=d}if(r.walkTokens){let d=this.defaults.walkTokens,m=r.walkTokens;f.walkTokens=function(b){let y=[];return y.push(m.call(this,b)),d&&(y=y.concat(d.call(this,b))),y}}this.defaults={...this.defaults,...f}}),this}setOptions(s){return this.defaults={...this.defaults,...s},this}lexer(s,c){return Le.lex(s,c??this.defaults)}parser(s,c){return Ve.parse(s,c??this.defaults)}parseMarkdown(s){return(c,r)=>{let f={...r},d={...this.defaults,...f},m=this.onError(!!d.silent,!!d.async);if(this.defaults.async===!0&&f.async===!1)return m(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof c>"u"||c===null)return m(new Error("marked(): input parameter is undefined or null"));if(typeof c!="string")return m(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(c)+", string expected"));if(d.hooks&&(d.hooks.options=d,d.hooks.block=s),d.async)return(async()=>{let b=d.hooks?await d.hooks.preprocess(c):c,y=await(d.hooks?await d.hooks.provideLexer(s):s?Le.lex:Le.lexInline)(b,d),j=d.hooks?await d.hooks.processAllTokens(y):y;d.walkTokens&&await Promise.all(this.walkTokens(j,d.walkTokens));let E=await(d.hooks?await d.hooks.provideParser(s):s?Ve.parse:Ve.parseInline)(j,d);return d.hooks?await d.hooks.postprocess(E):E})().catch(m);try{d.hooks&&(c=d.hooks.preprocess(c));let b=(d.hooks?d.hooks.provideLexer(s):s?Le.lex:Le.lexInline)(c,d);d.hooks&&(b=d.hooks.processAllTokens(b)),d.walkTokens&&this.walkTokens(b,d.walkTokens);let y=(d.hooks?d.hooks.provideParser(s):s?Ve.parse:Ve.parseInline)(b,d);return d.hooks&&(y=d.hooks.postprocess(y)),y}catch(b){return m(b)}}}onError(s,c){return r=>{if(r.message+=`
-Please report this to https://github.com/markedjs/marked.`,s){let f="An error occurred:
"+Ne(r.message+"",!0)+" ";return c?Promise.resolve(f):f}if(c)return Promise.reject(r);throw r}}},Ca=new Cp;function jt(s,c){return Ca.parse(s,c)}jt.options=jt.setOptions=function(s){return Ca.setOptions(s),jt.defaults=Ca.defaults,og(jt.defaults),jt};jt.getDefaults=fr;jt.defaults=Da;function Dp(...s){return Ca.use(...s),jt.defaults=Ca.defaults,og(jt.defaults),jt}jt.use=Dp;jt.walkTokens=function(s,c){return Ca.walkTokens(s,c)};jt.parseInline=Ca.parseInline;jt.Parser=Ve;jt.parser=Ve.parse;jt.Renderer=rc;jt.TextRenderer=vr;jt.Lexer=Le;jt.lexer=Le.lex;jt.Tokenizer=fc;jt.Hooks=zu;jt.parse=jt;jt.options;jt.setOptions;jt.walkTokens;jt.parseInline;Ve.parse;var Mp=Le.lex;function Up(s){const c=s.trim();if(/^(https?:|mailto:)/i.test(c)||c.startsWith("/")||c.startsWith("#"))return c}function sl(s){return s?s.map((c,r)=>{switch(c.type){case"strong":return o.jsx("strong",{children:sl(c.tokens)},r);case"em":return o.jsx("em",{children:sl(c.tokens)},r);case"del":return o.jsx("del",{children:sl(c.tokens)},r);case"codespan":return o.jsx("code",{children:c.text},r);case"link":{const f=c,d=Up(f.href);return d?o.jsx("a",{href:d,target:"_blank",rel:"noreferrer",children:f.tokens?sl(f.tokens):f.text},r):o.jsx("span",{children:f.text},r)}case"image":{const f=c;return o.jsxs("span",{className:"md-image",children:["[img: ",f.text||f.href,"]"]},r)}case"br":return o.jsx("br",{},r);case"escape":return o.jsx("span",{children:c.text},r);case"html":return o.jsx("code",{children:c.text},r);case"text":{const f=c;return o.jsx("span",{children:f.tokens?sl(f.tokens):f.text},r)}default:return o.jsx("span",{children:"raw"in c?String(c.raw??""):""},r)}}):[]}function ur(s){return s.map((c,r)=>{switch(c.type){case"heading":{const f=c,d=sl(f.tokens);switch(f.depth){case 1:return o.jsx("h2",{children:d},r);case 2:return o.jsx("h3",{children:d},r);case 3:return o.jsx("h4",{children:d},r);default:return o.jsx("h5",{children:d},r)}}case"paragraph":return o.jsx("p",{children:sl(c.tokens)},r);case"code":{const f=c;return o.jsx("pre",{className:"md-code",children:o.jsx("code",{children:f.text})},r)}case"blockquote":return o.jsx("blockquote",{children:ur(c.tokens)},r);case"list":{const f=c,d=f.items.map((m,b)=>o.jsx("li",{children:ur(m.tokens)},b));return f.ordered?o.jsx("ol",{start:f.start||1,children:d},r):o.jsx("ul",{children:d},r)}case"table":{const f=c;return o.jsxs("table",{className:"md-table",children:[o.jsx("thead",{children:o.jsx("tr",{children:f.header.map((d,m)=>o.jsx("th",{children:sl(d.tokens)},m))})}),o.jsx("tbody",{children:f.rows.map((d,m)=>o.jsx("tr",{children:d.map((b,y)=>o.jsx("td",{children:sl(b.tokens)},y))},m))})]},r)}case"hr":return o.jsx("hr",{},r);case"space":return null;case"html":return o.jsx("pre",{className:"md-code",children:o.jsx("code",{children:c.text})},r);case"text":return o.jsx("p",{children:sl([c])},r);default:return o.jsx("pre",{className:"md-code",children:o.jsx("code",{children:"raw"in c?String(c.raw??""):""})},r)}})}function oc({text:s}){return s.trim()?o.jsx("div",{className:"md",children:ur(Mp(s))}):null}function Hp({d:s}){return o.jsxs("div",{className:`decision-card ${s.status==="resolved"?"resolved":""}`,children:[o.jsxs("div",{children:[o.jsx("span",{className:`badge ${s.status==="open"?"st-awaiting_review":"st-approved"}`,children:s.status})," ",o.jsx("strong",{children:s.question})]}),s.context_md&&o.jsx(oc,{text:s.context_md}),s.status==="resolved"&&o.jsxs("div",{className:"mono-sm dim",style:{marginTop:4},children:["resolution: ",s.resolution," · by ",s.decided_by," · ",Ke(s.resolved_at)]})]})}function qp({view:s,currentStage:c,open:r,onToggle:f}){const d=s.stage===c;return o.jsxs("div",{className:"stage-panel",children:[o.jsxs("header",{onClick:f,children:[o.jsx("span",{children:r?"▾":"▸"}),o.jsx("strong",{style:d?{color:"var(--accent)"}:void 0,children:s.stage}),d&&o.jsx("span",{className:"badge st-in_progress",children:"current"}),o.jsxs("span",{className:"counts",children:["artifacts ",s.artifacts.length," · transitions ",s.transitions.length," · decisions ",s.decisions.length]})]}),r&&o.jsxs("div",{className:"body",children:[s.artifacts.length>0&&o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"Artifacts"}),s.artifacts.map(m=>o.jsxs("details",{className:"fold",style:{marginBottom:8},children:[o.jsxs("summary",{children:[o.jsx("span",{className:"badge",children:m.kind})," ",m.title," ",o.jsxs("span",{className:"dim mono-sm",children:[m.source_type,":",m.source_ref," · ",Ke(m.created_at)]})]}),m.content_md?o.jsx(oc,{text:m.content_md}):o.jsx("div",{className:"dim mono-sm",children:"(无内容)"})]},m.id))]}),s.transitions.length>0&&o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"Transitions"}),o.jsxs("table",{className:"settings-table",children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:"ts"}),o.jsx("th",{children:"from → to"}),o.jsx("th",{children:"actor"}),o.jsx("th",{children:"approved_by"}),o.jsx("th",{children:"note"})]})}),o.jsx("tbody",{children:s.transitions.map(m=>o.jsxs("tr",{children:[o.jsx("td",{className:"mono-sm",children:Ke(m.ts)}),o.jsxs("td",{className:"mono-sm",children:[m.from_stage," → ",m.to_stage]}),o.jsx("td",{children:m.actor}),o.jsx("td",{children:m.approved_by}),o.jsx("td",{children:m.note})]},m.id))})]})]}),s.decisions.length>0&&o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"Decisions"}),s.decisions.map(m=>o.jsx(Hp,{d:m},m.id))]}),s.artifacts.length===0&&s.transitions.length===0&&s.decisions.length===0&&o.jsx("div",{className:"dim mono-sm",children:"本阶段暂无记录"})]})]})}function wp({task:s,onDone:c}){const[r,f]=q.useState(""),[d,m]=q.useState(""),[b,y]=q.useState(""),[j,E]=q.useState(!1),[O,p]=q.useState(""),[D,J]=q.useState(""),[Q,B]=q.useState(!1),F=async K=>{K.preventDefault(),B(!0),J("");try{await Kt.post(`/tasks/${s.id}/stages/${s.stage}/external-submit`,{title:r.trim(),content_md:d,kind:b||void 0,advance:j,note:O||void 0}),f(""),m(""),p(""),c()}catch(pt){J(pt.message)}finally{B(!1)}};return o.jsxs("details",{className:"fold panel",children:[o.jsxs("summary",{children:["外部产物提交(external-submit,当前阶段 ",s.stage,")"]}),D&&o.jsx("div",{className:"error-box",children:D}),o.jsxs("form",{onSubmit:F,children:[o.jsxs("div",{className:"op-row",children:[o.jsxs("label",{style:{flex:1,minWidth:200},children:["title",o.jsx("input",{required:!0,value:r,onChange:K=>f(K.target.value)})]}),o.jsxs("label",{children:["kind",o.jsx("input",{value:b,onChange:K=>y(K.target.value),placeholder:"note",style:{width:120}})]}),o.jsxs("label",{style:{flexDirection:"row",alignItems:"center",gap:6},children:[o.jsx("input",{type:"checkbox",checked:j,onChange:K=>E(K.target.checked)}),"提交后推进"]})]}),o.jsx("textarea",{rows:6,required:!0,value:d,onChange:K=>m(K.target.value),placeholder:"content_md(markdown)"}),j&&o.jsxs("div",{style:{marginTop:6},children:[o.jsx("label",{className:"dim mono-sm",children:"note(推进备注)"}),o.jsx("input",{style:{width:"100%"},value:O,onChange:K=>p(K.target.value)})]}),o.jsx("div",{className:"op-row",style:{marginTop:8},children:o.jsx("button",{className:"primary",type:"submit",disabled:Q,children:"提交"})})]})]})}function Bp({id:s}){const[c,r]=q.useState(null),[f,d]=q.useState(null),[m,b]=q.useState({}),[y,j]=q.useState(""),[E,O]=q.useState(""),[p,D]=q.useState(""),[J,Q]=q.useState(""),B=q.useCallback(()=>{Promise.all([Kt.get(`/tasks/${s}`),Kt.get(`/tasks/${s}/pipeline`)]).then(([U,et])=>{r(U),d(et),j(U.assigned_agent),b(Y=>Object.keys(Y).length===0?{[U.stage]:!0}:Y),D("")}).catch(U=>{U.message!=="unauthorized"&&D(U.message)})},[s]);q.useEffect(()=>{B()},[B]);const F=async(U,et)=>{D(""),Q("");try{await U(),Q(et),O(""),B()}catch(Y){D(Y.message)}};if(!c||!f)return o.jsxs("div",{children:[o.jsx("div",{className:"page-head",children:o.jsx("h2",{children:"任务详情"})}),p?o.jsx("div",{className:"error-box",children:p}):o.jsx("div",{className:"dim",children:"加载中…"})]});const K=Nn.indexOf(c.stage),pt=c.stage_state==="awaiting_review",Ht=c.status==="done"||c.status==="cancelled";return o.jsxs("div",{children:[o.jsxs("div",{className:"page-head",children:[o.jsx("a",{href:"#/board",className:"mono-sm",children:"← 看板"}),o.jsx("h2",{children:c.title}),o.jsx("span",{className:"dim mono-sm",children:c.slug}),o.jsx("span",{className:`badge st-${c.stage_state}`,children:c.stage_state}),o.jsx("span",{className:`badge status-${c.status}`,children:c.status}),o.jsxs("span",{className:"badge",children:["P",c.priority]}),o.jsx("span",{className:"badge",children:c.kind})]}),p&&o.jsx("div",{className:"error-box",children:p}),J&&o.jsx("div",{className:"panel mono-sm",style:{borderColor:"var(--green)",color:"var(--green)"},children:J}),o.jsx("div",{className:"stepper",children:Nn.map((U,et)=>{const Y=c.status==="done"||etb(ot=>({...ot,[U]:!ot[U]})),children:[Y&&o.jsx("span",{className:"check",children:"✓"}),U]},U)})}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"操作"}),o.jsxs("div",{className:"op-row",children:[o.jsxs("label",{children:["assign agent",o.jsx("input",{value:y,onChange:U=>j(U.target.value),placeholder:"agent 名",style:{width:140}})]}),o.jsx("button",{disabled:!y.trim()||Ht,onClick:()=>F(()=>Kt.patch(`/tasks/${c.id}`,{assign:y.trim()}),`已指派给 ${y.trim()}`),children:"指派"}),o.jsx("span",{style:{width:16}}),o.jsxs("label",{children:["note",o.jsx("input",{value:E,onChange:U=>O(U.target.value),placeholder:"审批备注",style:{width:260}})]}),o.jsx("button",{className:"primary",disabled:!pt,title:pt?"":"仅 awaiting_review 可推进",onClick:()=>F(()=>Kt.post(`/tasks/${c.id}/stages/advance`,{note:E}),"已推进"),children:"批准推进"}),o.jsx("button",{className:"danger",disabled:!pt,title:pt?"":"仅 awaiting_review 可退回",onClick:()=>F(()=>Kt.post(`/tasks/${c.id}/stages/send-back`,{note:E}),"已退回 changes_requested"),children:"退回修改"})]}),o.jsxs("div",{className:"dim mono-sm",children:["assigned: ",c.assigned_agent||"(none)"," · heartbeat ",Ke(c.heartbeat_at)," · lease ",Ke(c.lease_expires_at)]})]}),!Ht&&o.jsx(wp,{task:c,onDone:B}),c.instruction_md&&o.jsxs("details",{className:"fold panel",children:[o.jsx("summary",{children:"任务指令(instruction_md)"}),o.jsx(oc,{text:c.instruction_md})]}),o.jsx("div",{children:f.stages.map(U=>o.jsx(qp,{view:U,currentStage:f.stage,open:!!m[U.stage],onToggle:()=>b(et=>({...et,[U.stage]:!et[U.stage]}))},U.stage))}),o.jsxs("div",{className:"dim mono-sm",style:{marginTop:8},children:["created ",Ke(c.created_at)," · updated ",Ke(c.updated_at)," ·"," ",o.jsx("a",{href:"#/board",onClick:U=>{U.preventDefault(),Ra("/board")},children:"返回看板"})]})]})}function kp({d:s,onResolved:c}){const[r,f]=q.useState(""),[d,m]=q.useState(""),[b,y]=q.useState(!1),j=async E=>{y(!0),m("");try{await Kt.post(`/decisions/${s.id}/resolve`,E),c()}catch(O){m(O.message),y(!1)}};return o.jsxs("div",{className:"decision-card",children:[o.jsxs("div",{style:{marginBottom:6},children:[o.jsx("a",{href:`#/tasks/${s.task_id}`,onClick:E=>{E.preventDefault(),Ra(`/tasks/${s.task_id}`)},children:s.task_slug})," ",o.jsx("span",{className:"dim",children:s.task_title})," ",o.jsx("span",{className:"badge",children:s.stage})," ",o.jsx("span",{className:"dim mono-sm",children:Ke(s.created_at)})]}),o.jsx("div",{style:{fontWeight:600,marginBottom:6},children:s.question}),s.context_md&&o.jsx(oc,{text:s.context_md}),d&&o.jsx("div",{className:"error-box",children:d}),o.jsx("div",{style:{marginTop:8},children:s.suggestions.map((E,O)=>o.jsxs("div",{className:"suggestion",children:[o.jsxs("div",{className:"opt",children:["建议 ",O+1,": ",E.option,o.jsxs("button",{style:{marginLeft:10},disabled:b,onClick:()=>j({suggestion_index:O}),children:["采纳建议 ",O+1]})]}),o.jsxs("div",{className:"why",children:["理由: ",E.rationale]}),o.jsxs("div",{className:"why",children:["影响: ",E.impact]})]},O))}),o.jsxs("div",{className:"op-row",style:{marginTop:8},children:[o.jsxs("label",{style:{flex:1,minWidth:260},children:["自定义 resolution",o.jsx("input",{style:{width:"100%"},value:r,onChange:E=>f(E.target.value)})]}),o.jsx("button",{className:"primary",disabled:b||!r.trim(),onClick:()=>j({resolution:r.trim()}),children:"提交裁决"})]})]})}function Yp(){const[s,c]=q.useState([]),[r,f]=q.useState(null),[d,m]=q.useState(!1),[b,y]=q.useState(""),j=q.useCallback(()=>{Kt.get("/decisions?status=open").then(E=>{c(E),y("")}).catch(E=>{E.message!=="unauthorized"&&y(E.message)})},[]);return q.useEffect(()=>{j()},[j]),q.useEffect(()=>{!d||r!==null||Kt.get("/decisions?status=resolved").then(f).catch(()=>{})},[d,r]),o.jsxs("div",{children:[o.jsxs("div",{className:"page-head",children:[o.jsx("h2",{children:"决策收件箱"}),o.jsxs("span",{className:`badge ${s.length>0?"st-awaiting_review":""}`,children:[s.length," open"]}),o.jsx("div",{className:"spacer"}),o.jsx("button",{onClick:j,children:"刷新"})]}),b&&o.jsx("div",{className:"error-box",children:b}),s.length===0&&o.jsx("div",{className:"panel dim",children:"没有待裁决的决策。"}),s.map(E=>o.jsx(kp,{d:E,onResolved:j},E.id)),o.jsxs("details",{className:"fold",style:{marginTop:16},onToggle:E=>m(E.target.open),children:[o.jsxs("summary",{children:["已解决(",r?.length??"…",")"]}),(r??[]).map(E=>o.jsxs("div",{className:"decision-card resolved",children:[o.jsxs("div",{children:[o.jsx("span",{className:"dim",children:E.task_slug})," ",o.jsx("strong",{children:E.question})]}),o.jsxs("div",{className:"mono-sm dim",style:{marginTop:4},children:["resolution: ",E.resolution," · by ",E.decided_by," · ",Ke(E.resolved_at)]})]},E.id)),d&&r!==null&&r.length===0&&o.jsx("div",{className:"dim mono-sm",children:"暂无已解决决策"})]})]})}function Gp(){const[s,c]=q.useState([]),[r,f]=q.useState(""),[d,m]=q.useState(""),[b,y]=q.useState(null),[j,E]=q.useState(""),[O,p]=q.useState("hybrid"),[D,J]=q.useState(null),[Q,B]=q.useState(""),F=(U,et)=>{Kt.get(`/docs${er({taxonomy:U,q:et})}`).then(Y=>c(Y.items)).catch(Y=>{Y.message!=="unauthorized"&&B(Y.message)})};q.useEffect(()=>{F(r,d)},[r,d]);const K=q.useMemo(()=>{const U=new Map;for(const et of s)U.set(et.taxonomy,(U.get(et.taxonomy)??0)+1);return[...U.entries()].sort((et,Y)=>et[0].localeCompare(Y[0]))},[s]),pt=async U=>{if(U.preventDefault(),!!j.trim()){B("");try{const et=await Kt.get(`/docs/search${er({q:j.trim(),mode:O,limit:"20"})}`);J(et)}catch(et){B(et.message)}}},Ht=U=>{Kt.get(`/docs/${U}`).then(y).catch(et=>B(et.message))};return o.jsxs("div",{children:[o.jsx("div",{className:"page-head",children:o.jsx("h2",{children:"文档库"})}),Q&&o.jsx("div",{className:"error-box",children:Q}),o.jsx("div",{className:"panel",children:o.jsxs("form",{className:"filters",onSubmit:pt,children:[o.jsx("input",{style:{flex:1,minWidth:240},placeholder:"搜索文档与阶段产物…",value:j,onChange:U=>E(U.target.value)}),o.jsxs("select",{value:O,onChange:U=>p(U.target.value),children:[o.jsx("option",{value:"hybrid",children:"hybrid"}),o.jsx("option",{value:"semantic",children:"semantic"}),o.jsx("option",{value:"keyword",children:"keyword"})]}),o.jsx("button",{className:"primary",type:"submit",children:"搜索"})]})}),D&&o.jsxs("div",{className:"panel",children:[o.jsxs("h3",{children:["搜索结果 · ",D.mode," · ",D.count," 条",D.degraded&&o.jsx("span",{className:"badge st-awaiting_review",style:{marginLeft:8},children:"degraded:语义检索不可用,已回落关键词"})]}),D.results.map((U,et)=>o.jsxs("div",{className:"hit",children:[o.jsxs("div",{children:[o.jsx("span",{className:"score",children:U.score.toFixed(3)})," ",U.heading&&o.jsxs("strong",{children:[U.heading," "]}),o.jsx("span",{className:"dim mono-sm",children:U.source.type==="doc"?`doc: ${U.source.path} (${U.source.title})`:`artifact: ${U.source.task_slug} / ${U.source.stage} (${U.source.title})`}),U.doc_id&&o.jsxs(o.Fragment,{children:[" ",o.jsx("a",{href:"#/docs",onClick:Y=>{Y.preventDefault(),Ht(U.doc_id)},children:"查看文档"})]})]}),o.jsx("div",{className:"snippet",children:U.snippet})]},et)),D.count===0&&o.jsx("div",{className:"dim mono-sm",children:"无结果"})]}),o.jsxs("div",{className:"docs-layout",children:[o.jsx("div",{className:"docs-side",children:o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"浏览"}),o.jsx("input",{style:{width:"100%",marginBottom:8},placeholder:"过滤 path/title",value:d,onChange:U=>m(U.target.value)}),o.jsxs("div",{className:`tax-name ${r===""?"active":""}`,style:{cursor:"pointer",color:r===""?"var(--accent)":void 0,marginBottom:6},onClick:()=>f(""),children:["全部 (",s.length,")"]}),K.map(([U,et])=>o.jsxs("div",{className:"tax-group",children:[o.jsxs("div",{className:"tax-name",onClick:()=>f(U===r?"":U),children:[U||"(no taxonomy)"," (",et,")"]}),r===U&&s.filter(Y=>Y.taxonomy===U).map(Y=>o.jsx("div",{className:`doc-item ${b?.id===Y.id?"active":""}`,onClick:()=>Ht(Y.id),title:Y.path,children:Y.title||Y.path},Y.id))]},U||"(none)")),r===""&&s.slice(0,80).map(U=>o.jsx("div",{className:`doc-item ${b?.id===U.id?"active":""}`,onClick:()=>Ht(U.id),title:U.path,children:U.title||U.path},U.id))]})}),o.jsx("div",{className:"docs-main",children:b?o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:b.title||b.path}),o.jsx("table",{className:"settings-table",style:{marginBottom:10},children:o.jsxs("tbody",{children:[o.jsxs("tr",{children:[o.jsx("th",{children:"path"}),o.jsx("td",{className:"mono-sm",children:b.path})]}),o.jsxs("tr",{children:[o.jsx("th",{children:"taxonomy"}),o.jsx("td",{children:b.taxonomy})]}),o.jsxs("tr",{children:[o.jsx("th",{children:"chunks"}),o.jsx("td",{children:b.chunks})]}),o.jsxs("tr",{children:[o.jsx("th",{children:"synced_at"}),o.jsx("td",{className:"mono-sm",children:Ke(b.synced_at)})]})]})}),o.jsx("h3",{children:"Front Matter"}),o.jsx("pre",{className:"md-code",children:o.jsx("code",{children:JSON.stringify(b.frontmatter,null,2)})})]}):o.jsx("div",{className:"panel dim",children:"点击左侧文档查看详情,或使用上方搜索。"})})]})]})}const Qp=["agent","human","external"];function Xp(){const[s,c]=q.useState({}),[r,f]=q.useState(""),[d,m]=q.useState(""),[b,y]=q.useState(!1);q.useEffect(()=>{Kt.get("/stage-settings").then(E=>{const O={};for(const p of Nn){const D=E.find(J=>J.stage===p);O[p]={model:D?.model??"",executor:D?.executor??"agent"}}c(O)}).catch(E=>{E.message!=="unauthorized"&&f(E.message)})},[]);const j=async()=>{y(!0),f(""),m("");try{await Kt.put("/stage-settings",{settings:s}),m("已保存全局阶段设置")}catch(E){f(E.message)}finally{y(!1)}};return o.jsxs("div",{children:[o.jsx("div",{className:"page-head",children:o.jsx("h2",{children:"设置"})}),r&&o.jsx("div",{className:"error-box",children:r}),d&&o.jsx("div",{className:"panel mono-sm",style:{borderColor:"var(--green)",color:"var(--green)"},children:d}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"全局阶段设置(stage → model / executor)"}),o.jsxs("table",{className:"settings-table",children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:"stage"}),o.jsx("th",{children:"model"}),o.jsx("th",{children:"executor"})]})}),o.jsx("tbody",{children:Nn.map(E=>o.jsxs("tr",{children:[o.jsx("td",{children:E}),o.jsx("td",{children:o.jsx("input",{value:s[E]?.model??"",placeholder:"(默认模型)",onChange:O=>c(p=>({...p,[E]:{model:O.target.value,executor:p[E]?.executor??"agent"}}))})}),o.jsx("td",{children:o.jsx("select",{value:s[E]?.executor??"agent",onChange:O=>c(p=>({...p,[E]:{model:p[E]?.model??"",executor:O.target.value}})),children:Qp.map(O=>o.jsx("option",{value:O,children:O},O))})})]},E))})]}),o.jsx("div",{className:"op-row",style:{marginTop:10},children:o.jsx("button",{className:"primary",disabled:b,onClick:j,children:"保存"})}),o.jsx("div",{className:"dim mono-sm",style:{marginTop:6},children:"executor=human/external 的阶段不会派发给 agent;任务级覆盖可通过 API PUT /api/v1/stage-settings?task_id= 设置。"})]}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"Agent 接入"}),o.jsxs("div",{className:"dim mono-sm",children:["agent token 通过 ",o.jsx("code",{children:"scripts/control-center.sh register-agent -name [-kind ]"})," 注册(plaintext token 只显示一次)。 agent 使用 Bearer token 调用 ",o.jsx("code",{children:"/api/v1/agent/*"})," 路由认领任务、上报事件与产物;本控制台不使用 agent 路由。"]})]})]})}function Zp(){return o.jsxs("div",{children:[o.jsx("div",{className:"page-head",children:o.jsx("h2",{children:"审计"})}),o.jsxs("div",{className:"panel",children:[o.jsx("h3",{children:"仓库审查 Findings"}),o.jsxs("div",{className:"dim",children:["每日定时仓库审查(确定性检查 + LLM 复审)将在 ",o.jsx("strong",{children:"P5"})," 上线。 届时本页展示 cc_audit_findings 的 open / resolved 列表与处理入口。"]})]})]})}const Lp=[{path:"/",label:"总览"},{path:"/board",label:"看板"},{path:"/decisions",label:"决策收件箱"},{path:"/docs",label:"文档库"},{path:"/settings",label:"设置"},{path:"/audit",label:"审计"}];function Vp({onLogin:s}){const[c,r]=q.useState(""),f=d=>{d.preventDefault(),c.trim()&&(sr(c.trim()),s())};return o.jsx("div",{className:"login-wrap",children:o.jsxs("div",{className:"panel login-box",children:[o.jsx("h3",{children:"Control Center"}),o.jsxs("form",{onSubmit:f,children:[o.jsx("label",{className:"dim mono-sm",htmlFor:"token",children:"Console Token"}),o.jsx("input",{id:"token",type:"password",autoFocus:!0,value:c,onChange:d=>r(d.target.value),placeholder:"CC_CONSOLE_TOKEN"}),o.jsx("button",{className:"primary",type:"submit",children:"进入"}),o.jsx("span",{className:"dim mono-sm",children:"token 存于 localStorage,401 时自动清除。"})]})]})})}function Kp({path:s}){const c=s.match(/^\/tasks\/([^/]+)$/);if(c)return o.jsx(Bp,{id:c[1]});switch(s){case"/":return o.jsx(tg,{});case"/board":return o.jsx(Dy,{});case"/decisions":return o.jsx(Yp,{});case"/docs":return o.jsx(Gp,{});case"/settings":return o.jsx(Xp,{});case"/audit":return o.jsx(Zp,{});default:return o.jsx(tg,{})}}function Jp(){const[s,c]=q.useState(()=>cr()!==""),r=jy();if(q.useEffect(()=>{Ny(()=>c(!1))},[]),!s)return o.jsx(Vp,{onLogin:()=>c(!0)});const f=r.startsWith("/tasks/")||r==="/board"?"/board":r;return o.jsxs("div",{className:"layout",children:[o.jsxs("nav",{className:"sidebar",children:[o.jsx("h1",{children:"Control Center"}),Lp.map(d=>o.jsx("a",{href:`#${d.path}`,className:f===d.path?"active":"",children:d.label},d.path)),o.jsx("div",{style:{marginTop:16,padding:"0 8px"},children:o.jsx("button",{className:"mono-sm",onClick:()=>{sr(""),c(!1),Ra("/")},children:"退出登录"})})]}),o.jsx("main",{className:"main",children:o.jsx(Kp,{path:r})})]})}zy.createRoot(document.getElementById("root")).render(o.jsx(Jp,{}));
diff --git a/internal/controlcenter/webui/dist/assets/index-D-QUwwcl.css b/internal/controlcenter/webui/dist/assets/index-D-QUwwcl.css
deleted file mode 100644
index 21ef1d11..00000000
--- a/internal/controlcenter/webui/dist/assets/index-D-QUwwcl.css
+++ /dev/null
@@ -1 +0,0 @@
-:root{--bg: #0d1117;--bg-panel: #161b22;--bg-hover: #1c2330;--border: #2b3442;--fg: #d6dde6;--fg-dim: #8b97a7;--accent: #4f9cf9;--green: #3fb950;--red: #f85149;--yellow: #d29922;--purple: #bc8cff;--cyan: #39c5cf;font-size:14px}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font-family:SF Mono,Cascadia Code,Menlo,Consolas,PingFang SC,Microsoft YaHei,monospace}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button{background:var(--bg-hover);color:var(--fg);border:1px solid var(--border);border-radius:4px;padding:4px 10px;font:inherit;cursor:pointer}button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.4;cursor:not-allowed}button.primary{background:var(--accent);border-color:var(--accent);color:#0d1117;font-weight:600}button.primary:hover:not(:disabled){color:#0d1117;filter:brightness(1.15)}button.danger{border-color:var(--red);color:var(--red)}input,select,textarea{background:var(--bg);color:var(--fg);border:1px solid var(--border);border-radius:4px;padding:4px 8px;font:inherit}input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent)}textarea{width:100%;resize:vertical}.layout{display:flex;min-height:100vh}.sidebar{width:180px;flex:0 0 180px;background:var(--bg-panel);border-right:1px solid var(--border);padding:12px 8px;position:sticky;top:0;height:100vh}.sidebar h1{font-size:13px;letter-spacing:1px;color:var(--fg-dim);margin:4px 8px 14px;text-transform:uppercase}.sidebar a{display:block;padding:6px 10px;border-radius:4px;color:var(--fg);margin-bottom:2px}.sidebar a:hover{background:var(--bg-hover);text-decoration:none}.sidebar a.active{background:var(--bg-hover);color:var(--accent);border-left:2px solid var(--accent)}.main{flex:1;padding:16px 20px;min-width:0}.page-head{display:flex;align-items:center;gap:12px;margin-bottom:14px;flex-wrap:wrap}.page-head h2{margin:0;font-size:16px}.page-head .spacer{flex:1}.panel{background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:12px;margin-bottom:14px}.panel h3{margin:0 0 10px;font-size:13px;color:var(--fg-dim);text-transform:uppercase;letter-spacing:1px}.error-box{background:#f851491a;border:1px solid var(--red);border-radius:4px;color:var(--red);padding:8px 12px;margin-bottom:12px;white-space:pre-wrap}.dim{color:var(--fg-dim)}.mono-sm{font-size:12px}.login-wrap{display:flex;align-items:center;justify-content:center;min-height:100vh}.login-box{width:380px}.login-box form{display:flex;flex-direction:column;gap:10px}.badge{display:inline-block;padding:1px 7px;border-radius:10px;font-size:11px;border:1px solid var(--border);color:var(--fg-dim);white-space:nowrap}.badge.st-idle{color:var(--fg-dim)}.badge.st-assigned{color:var(--cyan);border-color:var(--cyan)}.badge.st-in_progress{color:var(--accent);border-color:var(--accent)}.badge.st-awaiting_review{color:var(--yellow);border-color:var(--yellow)}.badge.st-changes_requested{color:var(--red);border-color:var(--red)}.badge.st-approved{color:var(--green);border-color:var(--green)}.badge.status-blocked_pending_decision{color:var(--purple);border-color:var(--purple)}.badge.status-done{color:var(--green);border-color:var(--green)}.badge.status-in_progress{color:var(--accent);border-color:var(--accent)}.badge.status-cancelled{color:var(--fg-dim)}.stat-cards{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}.stat-card{background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:10px 16px;min-width:130px;cursor:pointer}.stat-card .num{font-size:26px;font-weight:700}.stat-card .lbl{color:var(--fg-dim);font-size:12px}.stat-card.warn .num{color:var(--yellow)}.stat-card.crit .num{color:var(--red)}.stat-card.ok .num{color:var(--green)}.matrix{border-collapse:collapse;width:100%}.matrix th,.matrix td{border:1px solid var(--border);padding:4px 8px;text-align:center;font-size:12px}.matrix th{color:var(--fg-dim);font-weight:500;background:var(--bg-hover)}.matrix td:first-child,.matrix th:first-child{text-align:left}.matrix td.hot{color:var(--yellow);font-weight:700}.agent-row{display:flex;gap:10px;align-items:center;padding:3px 0}.dot{width:8px;height:8px;border-radius:50%;display:inline-block}.dot.live{background:var(--green)}.dot.stale{background:var(--red)}.event-feed{max-height:300px;overflow-y:auto;font-size:12px}.event-feed .ev{padding:3px 0;border-bottom:1px solid var(--border);display:flex;gap:8px}.event-feed .ev .ts{color:var(--fg-dim);flex:0 0 auto}.event-feed .ev .phase{color:var(--purple);flex:0 0 auto}.board{display:flex;gap:10px;overflow-x:auto;padding-bottom:8px;align-items:flex-start}.lane{flex:0 0 240px;background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:8px}.lane h4{margin:0 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:1px;color:var(--fg-dim);display:flex;justify-content:space-between}.card{background:var(--bg-hover);border:1px solid var(--border);border-radius:4px;padding:8px;margin-bottom:8px;cursor:pointer}.card:hover{border-color:var(--accent)}.card .title{font-weight:600;margin-bottom:4px}.card .meta{display:flex;gap:6px;flex-wrap:wrap;align-items:center;font-size:11px;color:var(--fg-dim)}.stepper{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:14px}.step{flex:1;min-width:90px;text-align:center;padding:6px 4px;border:1px solid var(--border);border-radius:4px;font-size:12px;color:var(--fg-dim);cursor:pointer;background:var(--bg-panel)}.step.done{color:var(--green);border-color:var(--green)}.step.current{color:var(--accent);border-color:var(--accent);background:#4f9cf914;font-weight:700}.step .check{margin-right:4px}.stage-panel{border:1px solid var(--border);border-radius:6px;margin-bottom:8px;background:var(--bg-panel)}.stage-panel>header{padding:8px 12px;cursor:pointer;display:flex;gap:10px;align-items:center}.stage-panel>header:hover{background:var(--bg-hover)}.stage-panel>header .counts{margin-left:auto;font-size:11px;color:var(--fg-dim)}.stage-panel .body{border-top:1px solid var(--border);padding:10px 12px}.op-row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;margin-bottom:10px}.op-row label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--fg-dim)}.md{font-size:13px;line-height:1.55}.md h2,.md h3,.md h4,.md h5{margin:10px 0 6px}.md p{margin:6px 0}.md-code{background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:8px;overflow-x:auto;font-size:12px}.md code{background:var(--bg);border-radius:3px;padding:1px 4px}.md pre.md-code code{padding:0;background:transparent}.md blockquote{border-left:3px solid var(--border);margin:6px 0;padding:2px 10px;color:var(--fg-dim)}.md-table{border-collapse:collapse}.md-table th,.md-table td{border:1px solid var(--border);padding:3px 8px;font-size:12px}.md-image{color:var(--fg-dim)}.decision-card{border:1px solid var(--yellow);border-radius:6px;padding:12px;margin-bottom:12px;background:var(--bg-panel)}.decision-card.resolved{border-color:var(--border)}.suggestion{border:1px solid var(--border);border-radius:4px;padding:8px;margin:6px 0;background:var(--bg-hover)}.suggestion .opt{font-weight:600;margin-bottom:4px}.suggestion .why{font-size:12px;color:var(--fg-dim)}.docs-layout{display:flex;gap:14px;align-items:flex-start}.docs-side{flex:0 0 260px;max-height:75vh;overflow-y:auto}.docs-main{flex:1;min-width:0}.tax-group{margin-bottom:8px}.tax-group>.tax-name{color:var(--accent);cursor:pointer;font-size:12px;text-transform:uppercase;letter-spacing:1px}.doc-item{padding:3px 0 3px 10px;cursor:pointer;font-size:12px}.doc-item:hover,.doc-item.active{color:var(--accent)}.hit{border:1px solid var(--border);border-radius:4px;padding:8px;margin-bottom:8px;background:var(--bg-panel)}.hit .snippet{font-size:12px;color:var(--fg-dim);margin-top:4px;white-space:pre-wrap}.hit .score{color:var(--green);font-size:11px}.settings-table{border-collapse:collapse;width:100%}.settings-table th,.settings-table td{border:1px solid var(--border);padding:6px 8px;text-align:left}.settings-table th{color:var(--fg-dim);font-weight:500;background:var(--bg-hover)}.filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap}details.fold>summary{cursor:pointer;color:var(--fg-dim);margin-bottom:8px}
diff --git a/internal/controlcenter/webui/dist/assets/index-Dj6oWpHL.js b/internal/controlcenter/webui/dist/assets/index-Dj6oWpHL.js
new file mode 100644
index 00000000..85b933ac
--- /dev/null
+++ b/internal/controlcenter/webui/dist/assets/index-Dj6oWpHL.js
@@ -0,0 +1,76 @@
+(function(){const c=document.createElement("link").relList;if(c&&c.supports&&c.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))r(d);new MutationObserver(d=>{for(const m of d)if(m.type==="childList")for(const v of m.addedNodes)v.tagName==="LINK"&&v.rel==="modulepreload"&&r(v)}).observe(document,{childList:!0,subtree:!0});function o(d){const m={};return d.integrity&&(m.integrity=d.integrity),d.referrerPolicy&&(m.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?m.credentials="include":d.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function r(d){if(d.ep)return;d.ep=!0;const m=o(d);fetch(d.href,m)}})();var Jf={exports:{}},Tu={};var Qm;function vy(){if(Qm)return Tu;Qm=1;var s=Symbol.for("react.transitional.element"),c=Symbol.for("react.fragment");function o(r,d,m){var v=null;if(m!==void 0&&(v=""+m),d.key!==void 0&&(v=""+d.key),"key"in d){m={};for(var y in d)y!=="key"&&(m[y]=d[y])}else m=d;return d=m.ref,{$$typeof:s,type:r,key:v,ref:d!==void 0?d:null,props:m}}return Tu.Fragment=c,Tu.jsx=o,Tu.jsxs=o,Tu}var Xm;function yy(){return Xm||(Xm=1,Jf.exports=vy()),Jf.exports}var f=yy(),$f={exports:{}},_u={},Ff={exports:{}},Wf={};var Zm;function py(){return Zm||(Zm=1,(function(s){function c(k,W){var I=k.length;k.push(W);t:for(;0>>1,bt=k[Nt];if(0>>1;Ntd(ia,I))xd(M,ia)?(k[Nt]=M,k[x]=I,Nt=x):(k[Nt]=ia,k[fl]=I,Nt=fl);else if(xd(M,I))k[Nt]=M,k[x]=I,Nt=x;else break t}}return W}function d(k,W){var I=k.sortIndex-W.sortIndex;return I!==0?I:k.id-W.id}if(s.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var m=performance;s.unstable_now=function(){return m.now()}}else{var v=Date,y=v.now();s.unstable_now=function(){return v.now()-y}}var j=[],E=[],O=1,b=null,D=3,V=!1,G=!1,B=!1,$=!1,H=typeof setTimeout=="function"?setTimeout:null,mt=typeof clearTimeout=="function"?clearTimeout:null,qt=typeof setImmediate<"u"?setImmediate:null;function q(k){for(var W=o(E);W!==null;){if(W.callback===null)r(E);else if(W.startTime<=k)r(E),W.sortIndex=W.expirationTime,c(j,W);else break;W=o(E)}}function et(k){if(B=!1,q(k),!G)if(o(j)!==null)G=!0,Q||(Q=!0,ge());else{var W=o(E);W!==null&&Xt(et,W.startTime-k)}}var Q=!1,nt=-1,ot=5,Je=-1;function Ae(){return $?!0:!(s.unstable_now()-Jek&&Ae());){var Nt=b.callback;if(typeof Nt=="function"){b.callback=null,D=b.priorityLevel;var bt=Nt(b.expirationTime<=k);if(k=s.unstable_now(),typeof bt=="function"){b.callback=bt,q(k),W=!0;break e}b===o(j)&&r(j),q(k)}else r(j);b=o(j)}if(b!==null)W=!0;else{var Be=o(E);Be!==null&&Xt(et,Be.startTime-k),W=!1}}break t}finally{b=null,D=I,V=!1}W=void 0}}finally{W?ge():Q=!1}}}var ge;if(typeof qt=="function")ge=function(){qt(Oe)};else if(typeof MessageChannel<"u"){var jl=new MessageChannel,ua=jl.port2;jl.port1.onmessage=Oe,ge=function(){ua.postMessage(null)}}else ge=function(){H(Oe,0)};function Xt(k,W){nt=H(function(){k(s.unstable_now())},W)}s.unstable_IdlePriority=5,s.unstable_ImmediatePriority=1,s.unstable_LowPriority=4,s.unstable_NormalPriority=3,s.unstable_Profiling=null,s.unstable_UserBlockingPriority=2,s.unstable_cancelCallback=function(k){k.callback=null},s.unstable_forceFrameRate=function(k){0>k||125Nt?(k.sortIndex=I,c(E,k),o(j)===null&&k===o(E)&&(B?(mt(nt),nt=-1):B=!0,Xt(et,I-Nt))):(k.sortIndex=bt,c(j,k),G||V||(G=!0,Q||(Q=!0,ge()))),k},s.unstable_shouldYield=Ae,s.unstable_wrapCallback=function(k){var W=D;return function(){var I=D;D=W;try{return k.apply(this,arguments)}finally{D=I}}}})(Wf)),Wf}var Lm;function by(){return Lm||(Lm=1,Ff.exports=py()),Ff.exports}var If={exports:{}},tt={};var Vm;function xy(){if(Vm)return tt;Vm=1;var s=Symbol.for("react.transitional.element"),c=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),m=Symbol.for("react.consumer"),v=Symbol.for("react.context"),y=Symbol.for("react.forward_ref"),j=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),D=Symbol.for("react.view_transition"),V=Symbol.iterator;function G(x){return x===null||typeof x!="object"?null:(x=V&&x[V]||x["@@iterator"],typeof x=="function"?x:null)}var B={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},$=Object.assign,H={};function mt(x,M,K){this.props=x,this.context=M,this.refs=H,this.updater=K||B}mt.prototype.isReactComponent={},mt.prototype.setState=function(x,M){if(typeof x!="object"&&typeof x!="function"&&x!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,x,M,"setState")},mt.prototype.forceUpdate=function(x){this.updater.enqueueForceUpdate(this,x,"forceUpdate")};function qt(){}qt.prototype=mt.prototype;function q(x,M,K){this.props=x,this.context=M,this.refs=H,this.updater=K||B}var et=q.prototype=new qt;et.constructor=q,$(et,mt.prototype),et.isPureReactComponent=!0;var Q=Array.isArray;function nt(){}var ot={H:null,A:null,T:null,S:null},Je=Object.prototype.hasOwnProperty;function Ae(x,M,K){var J=K.ref;return{$$typeof:s,type:x,key:M,ref:J!==void 0?J:null,props:K}}function Oe(x,M){return Ae(x.type,M,x.props)}function ge(x){return typeof x=="object"&&x!==null&&x.$$typeof===s}function jl(x){var M={"=":"=0",":":"=2"};return"$"+x.replace(/[=:]/g,function(K){return M[K]})}var ua=/\/+/g;function Xt(x,M){return typeof x=="object"&&x!==null&&x.key!=null?jl(""+x.key):M.toString(36)}function k(x){switch(x.status){case"fulfilled":return x.value;case"rejected":throw x.reason;default:switch(typeof x.status=="string"?x.then(nt,nt):(x.status="pending",x.then(function(M){x.status==="pending"&&(x.status="fulfilled",x.value=M)},function(M){x.status==="pending"&&(x.status="rejected",x.reason=M)})),x.status){case"fulfilled":return x.value;case"rejected":throw x.reason}}throw x}function W(x,M,K,J,dt){var gt=typeof x;(gt==="undefined"||gt==="boolean")&&(x=null);var yt=!1;if(x===null)yt=!0;else switch(gt){case"bigint":case"string":case"number":yt=!0;break;case"object":switch(x.$$typeof){case s:case c:yt=!0;break;case O:return yt=x._init,W(yt(x._payload),M,K,J,dt)}}if(yt)return dt=dt(x),yt=J===""?"."+Xt(x,0):J,Q(dt)?(K="",yt!=null&&(K=yt.replace(ua,"$&/")+"/"),W(dt,M,K,"",function(rl){return rl})):dt!=null&&(ge(dt)&&(dt=Oe(dt,K+(dt.key==null||x&&x.key===dt.key?"":(""+dt.key).replace(ua,"$&/")+"/")+yt)),M.push(dt)),1;yt=0;var Z=J===""?".":J+":";if(Q(x))for(var P=0;P"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(c){console.error(c)}}return s(),Pf.exports=Sy(),Pf.exports}var Fm;function _y(){if(Fm)return _u;Fm=1;var s=by(),c=ir(),o=Ty();function r(t){var e="https://react.dev/errors/"+t;if(1Ma||(t.current=hc[Ma],hc[Ma]=null,Ma--)}function At(t,e){Ma++,hc[Ma]=t.current,t.current=e}var Fe=$e(null),An=$e(null),Al=$e(null),Ru=$e(null);function Cu(t,e){switch(At(Al,e),At(An,t),At(Fe,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?Wd(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=Wd(e),t=Id(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}Jt(Fe),At(Fe,t)}function Ua(){Jt(Fe),Jt(An),Jt(Al)}function dc(t){var e=t.memoizedState;e!==null&&(Tn._currentValue=e.memoizedState,At(Ru,t)),e=Fe.current;var l=Id(e,t.type);e!==l&&(At(An,t),At(Fe,l))}function Du(t){An.current===t&&(Jt(Fe),Jt(An)),Ru.current===t&&(Jt(Ru),Tn._currentValue=rl)}var mc,yr;function Ol(t){if(mc===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);mc=e&&e[1]||"",yr=-1)":-1n||g[a]!==_[n]){var A=`
+`+g[a].replace(" at new "," at ");return t.displayName&&A.includes("")&&(A=A.replace("",t.displayName)),A}while(1<=a&&0<=n);break}}}finally{gc=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?Ol(l):""}function xg(t,e){switch(t.tag){case 26:case 27:case 5:return Ol(t.type);case 16:return Ol("Lazy");case 13:return t.child!==e&&e!==null?Ol("Suspense Fallback"):Ol("Suspense");case 19:return Ol("SuspenseList");case 0:case 15:return vc(t.type,!1);case 11:return vc(t.type.render,!1);case 1:return vc(t.type,!0);case 31:return Ol("Activity");case 30:return Ol("ViewTransition");default:return""}}function pr(t){try{var e="",l=null;do e+=xg(t,l),l=t,t=t.return;while(t);return e}catch(a){return`
+Error generating stack: `+a.message+`
+`+a.stack}}var yc=Object.prototype.hasOwnProperty,pc=s.unstable_scheduleCallback,bc=s.unstable_cancelCallback,Sg=s.unstable_shouldYield,Tg=s.unstable_requestPaint,ve=s.unstable_now,_g=s.unstable_getCurrentPriorityLevel,br=s.unstable_ImmediatePriority,xr=s.unstable_UserBlockingPriority,Mu=s.unstable_NormalPriority,Eg=s.unstable_LowPriority,Sr=s.unstable_IdlePriority,Ng=s.log,zg=s.unstable_setDisableYieldValue,On=null,ye=null;function Rl(t){if(typeof Ng=="function"&&zg(t),ye&&typeof ye.setStrictMode=="function")try{ye.setStrictMode(On,t)}catch{}}var pe=Math.clz32?Math.clz32:Og,jg=Math.log,Ag=Math.LN2;function Og(t){return t>>>=0,t===0?32:31-(jg(t)/Ag|0)|0}var Uu=256,Hu=262144,qu=4194304;function ca(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function wu(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var n=0,u=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var h=a&134217727;return h!==0?(a=h&~u,a!==0?n=ca(a):(i&=h,i!==0?n=ca(i):l||(l=h&~t,l!==0&&(n=ca(l))))):(h=a&~u,h!==0?n=ca(h):i!==0?n=ca(i):l||(l=a&~t,l!==0&&(n=ca(l)))),n===0?0:e!==0&&e!==n&&(e&u)===0&&(u=n&-n,l=e&-e,u>=l||u===32&&(l&4194048)!==0)?e:n}function Rn(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function Tr(t,e){(e&8)!==0&&(e|=e&32);var l=t.entangledLanes;if(l!==0)for(t=t.entanglements,l&=e;0l;l++)e.push(t);return e}function Cn(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function Cg(t,e,l,a,n,u){var i=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var h=t.entanglements,g=t.expirationTimes,_=t.hiddenUpdates;for(l=i&~l;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Rc=!1;if(dl)try{var Hn={};Object.defineProperty(Hn,"passive",{get:function(){Rc=!0}}),window.addEventListener("test",Hn,Hn),window.removeEventListener("test",Hn,Hn)}catch{Rc=!1}var Cl=null,Cc=null,Xu=null;function Vr(){if(Xu)return Xu;var t,e=Cc,l=e.length,a,n="value"in Cl?Cl.value:Cl.textContent,u=n.length;for(t=0;t=kn),Ir=" ",Pr=!1;function to(t,e){switch(t){case"keyup":return d0.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function eo(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Xa=!1;function g0(t,e){switch(t){case"compositionend":return eo(e);case"keypress":return e.which!==32?null:(Pr=!0,Ir);case"textInput":return t=e.data,t===Ir&&Pr?null:t;default:return null}}function v0(t,e){if(Xa)return t==="compositionend"||!qc&&to(t,e)?(t=Vr(),Xu=Cc=Cl=null,Xa=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function fo(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function ro(t,e){var l=fo(t);t=0;for(var a;l;){if(l.nodeType===3){if(a=t+l.textContent.length,t<=e&&a>=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=fo(l)}}function oo(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?oo(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function ho(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=Bc(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=Bc(t.document)}return e}function Yc(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var E0=dl&&"documentMode"in document&&11>=document.documentMode,Za=null,Gc=null,Qn=null,Qc=!1;function mo(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Qc||Za==null||Za!==Bc(a)||(a=Za,"selectionStart"in a&&Yc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Qn&&Gn(Qn,a)||(Qn=a,a=Ji(Gc,"onSelect"),0>=i,n-=i,Ie=1<<32-pe(e)+n|l<F?(Gt=L,L=null):Gt=L.sibling;var ht=S(T,L,N[F],R);if(ht===null){L===null&&(L=Gt);break}t&&L&&ht.alternate===null&&e(T,L),p=u(ht,p,F),rt===null?Y=ht:rt.sibling=ht,rt=ht,L=Gt}if(F===N.length)return l(T,L),it&&yl(T,F),Y;if(L===null){for(;FF?(Gt=L,L=null):Gt=L.sibling;var la=S(T,L,ht.value,R);if(la===null){L===null&&(L=Gt);break}t&&L&&la.alternate===null&&e(T,L),p=u(la,p,F),rt===null?Y=la:rt.sibling=la,rt=la,L=Gt}if(ht.done)return l(T,L),it&&yl(T,F),Y;if(L===null){for(;!ht.done;F++,ht=N.next())ht=C(T,ht.value,R),ht!==null&&(p=u(ht,p,F),rt===null?Y=ht:rt.sibling=ht,rt=ht);return it&&yl(T,F),Y}for(L=a(L);!ht.done;F++,ht=N.next())ht=z(L,T,F,ht.value,R),ht!==null&&(t&&(Gt=ht.alternate,Gt!==null&&L.delete(Gt.key===null?F:Gt.key)),p=u(ht,p,F),rt===null?Y=ht:rt.sibling=ht,rt=ht);return t&&L.forEach(function(gy){return e(T,gy)}),it&&yl(T,F),Y}function at(T,p,N,R){if(typeof N=="object"&&N!==null&&N.type===Oe&&N.key===null&&N.props.ref===void 0&&(N=N.props.children),typeof N=="object"&&N!==null){switch(N.$$typeof){case Je:t:{for(var Y=N.key;p!==null;){if(p.key===Y){if(Y=N.type,Y===Oe){if(p.tag===7){l(T,p.sibling),R=n(p,N.props.children),wl(R,N),R.return=T,T=R;break t}}else if(p.elementType===Y||typeof Y=="object"&&Y!==null&&Y.$$typeof===bt&&xa(Y)===p.type){l(T,p.sibling),R=n(p,N.props),wl(R,N),R.return=T,T=R;break t}l(T,p);break}else e(T,p);p=p.sibling}N.type===Oe?(R=da(N.props.children,T.mode,R,N.key),wl(R,N),R.return=T,T=R):(R=Pu(N.type,N.key,N.props,null,T.mode,R),wl(R,N),R.return=T,T=R)}return i(T);case Ae:t:{for(Y=N.key;p!==null;){if(p.key===Y)if(p.tag===4&&p.stateNode.containerInfo===N.containerInfo&&p.stateNode.implementation===N.implementation){l(T,p.sibling),R=n(p,N.children||[]),R.return=T,T=R;break t}else{l(T,p);break}else e(T,p);p=p.sibling}R=$c(N,T.mode,R),R.return=T,T=R}return i(T);case bt:return N=xa(N),at(T,p,N,R)}if(yt(N))return w(T,p,N,R);if(J(N)){if(Y=J(N),typeof Y!="function")throw Error(r(150));return N=Y.call(N),X(T,p,N,R)}if(typeof N.then=="function")return at(T,p,fi(N),R);if(N.$$typeof===Xt)return at(T,p,ui(T,N),R);ri(T,N)}return typeof N=="string"&&N!==""||typeof N=="number"||typeof N=="bigint"?(N=""+N,p!==null&&p.tag===6?(l(T,p.sibling),R=n(p,N),R.return=T,T=R):(l(T,p),R=Jc(N,T.mode,R),R.return=T,T=R),i(T)):l(T,p)}return function(T,p,N,R){try{Jn=0;var Y=at(T,p,N,R);return Pa=null,Y}catch(L){if(L===Ia||L===ci)throw L;var rt=fe(29,L,null,T.mode);return rt.lanes=R,rt.return=T,rt}}}var Ta=ko(!0),Bo=ko(!1),kl=!1;function us(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function is(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Bl(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Yl(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(pt&2)!==0){var n=a.pending;return n===null?e.next=e:(e.next=n.next,n.next=e),a.pending=e,e=Iu(t),To(t,null,l),e}return Wu(t,a,e,l),Iu(t)}function $n(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,Nr(t,l)}}function cs(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,l=l.next}while(l!==null);u===null?n=u=e:u=u.next=e}else n=u=e;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var ss=!1;function Fn(){if(ss){var t=Wa;if(t!==null)throw t}}function Wn(t,e,l,a){ss=!1;var n=t.updateQueue;kl=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,h=n.shared.pending;if(h!==null){n.shared.pending=null;var g=h,_=g.next;g.next=null,i===null?u=_:i.next=_,i=g;var A=t.alternate;A!==null&&(A=A.updateQueue,h=A.lastBaseUpdate,h!==i&&(h===null?A.firstBaseUpdate=_:h.next=_,A.lastBaseUpdate=g))}if(u!==null){var C=n.baseState;i=0,A=_=g=null,h=u;do{var S=h.lane&-536870913,z=S!==h.lane;if(z?(ft&S)===S:(a&S)===S){S!==0&&S===pa&&(ss=!0),A!==null&&(A=A.next={lane:0,tag:h.tag,payload:h.payload,callback:null,next:null});t:{var w=t,X=h;S=e;var at=l;switch(X.tag){case 1:if(w=X.payload,typeof w=="function"){C=w.call(at,C,S);break t}C=w;break t;case 3:w.flags=w.flags&-65537|128;case 0:if(w=X.payload,S=typeof w=="function"?w.call(at,C,S):w,S==null)break t;C=nt({},C,S);break t;case 2:kl=!0}}S=h.callback,S!==null&&(t.flags|=64,z&&(t.flags|=8192),z=n.callbacks,z===null?n.callbacks=[S]:z.push(S))}else z={lane:S,tag:h.tag,payload:h.payload,callback:h.callback,next:null},A===null?(_=A=z,g=C):A=A.next=z,i|=S;if(h=h.next,h===null){if(h=n.shared.pending,h===null)break;z=h,h=z.next,z.next=null,n.lastBaseUpdate=z,n.shared.pending=null}}while(!0);A===null&&(g=C),n.baseState=g,n.firstBaseUpdate=_,n.lastBaseUpdate=A,u===null&&(n.shared.lanes=0),Kl|=i,t.lanes=i,t.memoizedState=C}}function Yo(t,e){if(typeof t!="function")throw Error(r(191,t));t.call(e)}function Go(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;tu?u:8;var i=Z.T,h={};h.types=i!==null?i.types:null,Z.T=h,As(t,!1,e,l);try{var g=n(),_=Z.S;if(_!==null&&_(h,g),g!==null&&typeof g=="object"&&typeof g.then=="function"){var A=H0(g,a);eu(t,e,A,Ne(t))}else eu(t,e,a,Ne(t))}catch(C){eu(t,e,{then:function(){},status:"rejected",reason:C},Ne())}finally{P.p=u,i!==null&&h.types!==null&&(i.types=h.types),Z.T=i}}function G0(){}function zs(t,e,l,a){if(t.tag!==5)throw Error(r(476));var n=bh(t).queue;ph(t,n,e,rl,l===null?G0:function(){return xh(t),l(a)})}function bh(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:rl,baseState:rl,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sl,lastRenderedState:rl},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sl,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function xh(t){var e=bh(t);e.next===null&&(e=t.alternate.memoizedState),eu(t,e.next.queue,{},Ne())}function js(){return Ft(Tn)}function Sh(){return wt().memoizedState}function Th(){return wt().memoizedState}function Q0(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=Ne();t=Bl(l);var a=Yl(e,t,l);a!==null&&(de(a,e,l),$n(a,e,l)),e={cache:es()},t.payload=e;return}e=e.return}}function X0(t,e,l){var a=Ne();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},xi(t)?Eh(e,l):(l=Vc(t,e,l,a),l!==null&&(de(l,t,a),Nh(l,e,a)))}function _h(t,e,l){var a=Ne();eu(t,e,l,a)}function eu(t,e,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(xi(t))Eh(e,n);else{var u=t.alternate;if(t.lanes===0&&(u===null||u.lanes===0)&&(u=e.lastRenderedReducer,u!==null))try{var i=e.lastRenderedState,h=u(i,l);if(n.hasEagerState=!0,n.eagerState=h,xe(h,i))return Wu(t,e,n,0),zt===null&&Fu(),!1}catch{}if(l=Vc(t,e,n,a),l!==null)return de(l,t,a),Nh(l,e,a),!0}return!1}function As(t,e,l,a){if(a={lane:2,revertLane:bf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},xi(t)){if(e)throw Error(r(479))}else e=Vc(t,l,a,2),e!==null&&de(e,t,2)}function xi(t){var e=t.alternate;return t===lt||e!==null&&e===lt}function Eh(t,e){tn=di=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function Nh(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,Nr(t,l)}}var Si={readContext:Ft,use:vi,useCallback:Mt,useContext:Mt,useEffect:Mt,useImperativeHandle:Mt,useLayoutEffect:Mt,useInsertionEffect:Mt,useMemo:Mt,useReducer:Mt,useRef:Mt,useState:Mt,useDebugValue:Mt,useDeferredValue:Mt,useTransition:Mt,useSyncExternalStore:Mt,useId:Mt,useHostTransitionStatus:Mt,useFormState:Mt,useActionState:Mt,useOptimistic:Mt,useMemoCache:Mt,useCacheRefresh:Mt,useEffectEvent:Mt},zh={readContext:Ft,use:vi,useCallback:function(t,e){return ue().memoizedState=[t,e===void 0?null:e],t},useContext:Ft,useEffect:fh,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,pi(4194308,4,dh.bind(null,e,t),l)},useLayoutEffect:function(t,e){return pi(4194308,4,t,e)},useInsertionEffect:function(t,e){pi(4,2,t,e)},useMemo:function(t,e){var l=ue();e=e===void 0?null:e;var a=t();if(_a){Rl(!0);try{t()}finally{Rl(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=ue();if(l!==void 0){var n=l(e);if(_a){Rl(!0);try{l(e)}finally{Rl(!1)}}}else n=e;return a.memoizedState=a.baseState=n,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:n},a.queue=t,t=t.dispatch=X0.bind(null,lt,t),[a.memoizedState,t]},useRef:function(t){var e=ue();return t={current:t},e.memoizedState=t},useState:function(t){t=Ss(t);var e=t.queue,l=_h.bind(null,lt,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Es,useDeferredValue:function(t,e){var l=ue();return Ns(l,t,e)},useTransition:function(){var t=Ss(!1);return t=ph.bind(null,lt,t.queue,!0,!1),ue().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=lt,n=ue();if(it){if(l===void 0)throw Error(r(407));l=l()}else{if(l=e(),zt===null)throw Error(r(349));(ft&127)!==0||Ko(a,e,l)}n.memoizedState=l;var u={value:l,getSnapshot:e};return n.queue=u,fh($o.bind(null,a,u,t),[t]),a.flags|=2048,ln(9,{destroy:void 0},Jo.bind(null,a,u,l,e),null),l},useId:function(){var t=ue(),e=zt.identifierPrefix;if(it){var l=Pe,a=Ie;l=(a&~(1<<32-pe(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=mi++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[$t]=e,u[se]=a;t:for(i=e.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===e)break t;for(;i.sibling===null;){if(i.return===null||i.return===e)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}e.stateNode=u;t:switch(te(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&_l(e)}}return Rt(e),e.subtreeFlags&=-33554433,Gs(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&_l(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(r(166));if(t=Al.current,Fa(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,n=Lt,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}t[$t]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||$d(t.nodeValue,l)),t||Hl(e,!0)}else t=mu(t).createTextNode(a),t[$t]=e,e.stateNode=t}return Rt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=Fa(e),l!==null){if(t===null){if(!a)throw Error(r(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(r(557));t[$t]=e}else ma(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Rt(e),t=!1}else l=Ic(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(Se(e),e):(Se(e),null);if((e.flags&128)!==0)throw Error(r(558))}return Rt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(n=Fa(e),a!==null&&a.dehydrated!==null){if(t===null){if(!n)throw Error(r(318));if(n=e.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[$t]=e}else ma(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Rt(e),n=!1}else n=Ic(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),n=!0;if(!n)return e.flags&256?(Se(e),e):(Se(e),null)}return Se(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),ji(e,e.updateQueue),Rt(e),null);case 4:return Ua(),t===null&&_f(e.stateNode.containerInfo),e.flags|=67108864,Rt(e),null;case 10:return bl(e.type),Rt(e),null;case 19:if(hs(e),a=e.memoizedState,a===null)return Rt(e),null;if(n=(e.flags&128)!==0,u=a.rendering,u===null)if(n)au(a,!1);else{if(Ut!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(u=hi(t),u!==null){for(e.flags|=128,au(a,!1),t=u.updateQueue,e.updateQueue=t,ji(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)_o(l,t),l=l.sibling;return In(e,It.current&1|2),it&&yl(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&ve()>Bi&&(e.flags|=128,n=!0,au(a,!1),e.lanes=4194304)}else{if(!n)if(t=hi(u),t!==null){if(e.flags|=128,n=!0,t=t.updateQueue,e.updateQueue=t,ji(e,t),au(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!u.alternate&&!it)return Rt(e),null}else 2*ve()-a.renderingStartTime>Bi&&l!==536870912&&(e.flags|=128,n=!0,au(a,!1),e.lanes=4194304);a.isBackwards?(u.sibling=e.child,e.child=u):(t=a.last,t!==null?t.sibling=u:e.child=u,a.last=u)}if(a.tail!==null){t=a.tail;t:{for(l=t;l!==null;){if(l.alternate!==null){l=!1;break t}l=l.sibling}l=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=ve(),t.sibling=null,u=It.current,u=n?u&1|2:u&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!l||it?In(e,u):(l=u,At(Wt,e),At(It,l),le===null&&(le=e)),it&&yl(e,a.treeForkCount),t}return Rt(e),null;case 22:case 23:return Se(e),rs(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(Rt(e),e.subtreeFlags&6&&(e.flags|=8192)):Rt(e),l=e.updateQueue,l!==null&&ji(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&Jt(ba),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),bl(kt),Rt(e),null;case 25:return null;case 30:return e.flags|=33554432,Rt(e),null}throw Error(r(156,e.tag))}function F0(t,e){switch(Fc(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return bl(kt),Ua(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return Du(e),null;case 31:if(e.memoizedState!==null){if(Se(e),e.alternate===null)throw Error(r(340));ma()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(Se(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(r(340));ma()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return hs(e),t=e.flags,t&65536?(e.flags=t&-65537|128,t=e.memoizedState,t!==null&&(t.rendering=null,t.tail=null),e.flags|=4,e):null;case 4:return Ua(),null;case 10:return bl(e.type),null;case 22:case 23:return Se(e),rs(),t!==null&&Jt(ba),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return bl(kt),null;case 25:return null;default:return null}}function Wh(t,e){switch(Fc(e),e.tag){case 3:bl(kt),Ua();break;case 26:case 27:case 5:Du(e);break;case 4:Ua();break;case 31:e.memoizedState!==null&&Se(e);break;case 13:Se(e);break;case 19:hs(e);break;case 10:bl(e.type);break;case 22:case 23:Se(e),rs(),t!==null&&Jt(ba);break;case 24:bl(kt)}}function nu(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&t)===t){a=void 0;var u=l.create,i=l.inst;a=u(),i.destroy=a}l=l.next}while(l!==n)}}catch(h){Tt(e,e.return,h)}}function Zl(t,e,l){try{var a=e.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&t)===t){var i=a.inst,h=i.destroy;if(h!==void 0){i.destroy=void 0,n=e;var g=l,_=h;try{_()}catch(A){Tt(n,g,A)}}}a=a.next}while(a!==u)}}catch(A){Tt(e,e.return,A)}}function Ih(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{Go(e,l)}catch(a){Tt(t,t.return,a)}}}function Ph(t,e,l){l.props=Ea(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){Tt(t,e,a)}}function tl(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var n=t.stateNode,u=ml(t.memoizedProps,n);(n.ref===null||n.ref.name!==u)&&(n.ref=im(u)),a=n.ref;break;case 7:if(t.stateNode===null){var i=new ze(t);b(t.child,!1,Yv,i,void 0,void 0),t.stateNode=i}a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(h){Tt(t,e,h)}}function Pt(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Tt(t,e,n)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Tt(t,e,n)}else l.current=null}function Ai(t,e){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&e!==null)for(var l=0;l title"))),te(a,e,l),a[$t]=t,Zt(a),e=a;break t;case"link":if(u=_m("link","href",n).get(e+(l.href||""))){for(i=0;iat&&(i=at,at=X,X=i);var T=ro(h,X),p=ro(h,at);if(T&&p&&(z.rangeCount!==1||z.anchorNode!==T.node||z.anchorOffset!==T.offset||z.focusNode!==p.node||z.focusOffset!==p.offset)){var N=C.createRange();N.setStart(T.node,T.offset),z.removeAllRanges(),X>at?(z.addRange(N),z.extend(p.node,p.offset)):(N.setEnd(p.node,p.offset),z.addRange(N))}}}}for(C=[],z=h;z=z.parentNode;)z.nodeType===1&&C.push({element:z,left:z.scrollLeft,top:z.scrollTop});for(typeof h.focus=="function"&&h.focus(),h=0;hl?32:l,Z.T=null,l=ff,ff=null;var u=Ze,i=il;if(Dt=0,Aa=Ze=null,il=0,(pt&6)!==0)throw Error(r(331));var h=pt;if(pt|=4,Td(u.current),bd(u,u.current,i,l),pt=h,ou(0,!1),ye&&typeof ye.onPostCommitFiberRoot=="function")try{ye.onPostCommitFiberRoot(On,u)}catch{}return!0}finally{P.p=n,Z.T=a,wd(t,e)}}function kd(t,e,l){e=De(l,e),e=Cs(t.stateNode,e,2),t=Yl(t,e,2),t!==null&&(Cn(t,2),cl(t))}function Tt(t,e,l){if(t.tag===3)kd(t,t,l);else for(;e!==null;){if(e.tag===3){kd(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Jl===null||!Jl.has(a))){t=De(l,t),l=Uh(2),a=Yl(e,l,2),a!==null&&(Hh(l,a,e,t),Cn(a,2),cl(a));break}}e=e.return}}function vf(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new tv;var n=new Set;a.set(e,n)}else n=a.get(e),n===void 0&&(n=new Set,a.set(e,n));n.has(l)||(uf=!0,n.add(l),t=sv.bind(null,t,e,l),e.then(t,t))}function sv(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,zt===t&&(ft&l)===l&&((Ut===4||Ut===3&&(ft&62914560)===ft&&300>ve()-ki)&&(pt&2)===0?mn(t,0):wi|=l,fn===ft&&(fn=0)),cl(t)}function Bd(t,e){e===0&&(e=_r()),t=ha(t,e),t!==null&&(Cn(t,e),cl(t))}function fv(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),Bd(t,l)}function rv(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,n=t.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(e),Bd(t,l)}function ov(t,e){return pc(t,e)}var vn=null,yn=null,yf=!1,Vi=!1,pf=!1,Fl=0;function cl(t){t!==yn&&t.next===null&&(yn===null?vn=yn=t:yn=yn.next=t),Vi=!0,yf||(yf=!0,dv())}function ou(t,e){if(!pf&&Vi){pf=!0;do for(var l=!1,a=vn;a!==null;){if(t!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,h=a.pingedLanes;u=(1<<31-pe(42|t)+1)-1,u&=n&~(i&~h),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Xd(a,u))}else u=ft,u=wu(a,a===zt?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Rn(a,u)||(l=!0,Xd(a,u));a=a.next}while(l);pf=!1}}function hv(){Yd()}function Yd(){Vi=yf=!1;var t=0;Fl!==0&&Ev()&&(t=Fl);for(var e=ve(),l=null,a=vn;a!==null;){var n=a.next,u=Gd(a,e);u===0?(a.next=null,l===null?vn=n:l.next=n,n===null&&(yn=l)):(l=a,(t!==0||(u&3)!==0)&&(Vi=!0)),a=n}Dt!==0&&Dt!==5||ou(t),Fl!==0&&(Fl=0)}function Gd(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,n=t.expirationTimes,u=t.pendingLanes&-62914561;0h)break;var A=g.transferSize,C=g.initiatorType;A&&Fd(C)&&(g=g.responseEnd,i+=A*(gWi){X.length=w;break}N=new Promise(Rv.bind(N)),X.push(N)}}}if(0"u"?null:document;function bm(t,e,l){var a=bn;if(a&&typeof e=="string"&&e){var n=Re(e);n='link[rel="'+t+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),pm.has(n)||(pm.add(n),t={rel:t,crossOrigin:l,href:e},a.querySelector(n)===null&&(e=a.createElement("link"),te(e,"link",t),Zt(e),a.head.appendChild(e)))}}function $v(t){Nl.D(t),bm("dns-prefetch",t,null)}function Fv(t,e){Nl.C(t,e),bm("preconnect",t,e)}function Wv(t,e,l){Nl.L(t,e,l);var a=bn;if(a&&t&&e){var n='link[rel="preload"][as="'+Re(e)+'"]';e==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Re(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Re(l.imageSizes)+'"]')):n+='[href="'+Re(t)+'"]';var u=n;switch(e){case"style":u=xn(t);break;case"script":u=Sn(t)}if(!(ke.has(u)||(t=nt({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),ke.set(u,t),a.querySelector(n)!==null||e==="style"&&a.querySelector(vu(u))||e==="script"&&a.querySelector(yu(u))))){var i=a.createElement("link");te(i,"link",t),e==="style"&&(i[ku]=!0,i.onload=i.onerror=function(){Cr(i)}),Zt(i),a.head.appendChild(i)}}}function Iv(t,e){Nl.m(t,e);var l=bn;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",n='link[rel="modulepreload"][as="'+Re(a)+'"][href="'+Re(t)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Sn(t)}if(!ke.has(u)&&(t=nt({rel:"modulepreload",href:t},e),ke.set(u,t),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(yu(u)))return}a=l.createElement("link"),te(a,"link",t),Zt(a),l.head.appendChild(a)}}}function Pv(t,e,l){Nl.S(t,e,l);var a=bn;if(a&&t){var n=wa(a).hoistableStyles,u=xn(t);e=e||"default";var i=n.get(u);if(!i){var h={loading:0,preload:null};if(i=a.querySelector(vu(u)))h.loading=5;else{t=nt({rel:"stylesheet",href:t,"data-precedence":e},l),(l=ke.get(u))&&Bf(t,l);var g=i=a.createElement("link");Zt(g),te(g,"link",t),g._p=new Promise(function(_,A){g.onload=_,g.onerror=A}),g.addEventListener("load",function(){h.loading|=1}),g.addEventListener("error",function(){h.loading|=2}),h.loading|=4,$i(i,e,a)}i={type:"stylesheet",instance:i,count:1,state:h},n.set(u,i)}}}function ty(t,e){Nl.X(t,e);var l=bn;if(l&&t){var a=wa(l).hoistableScripts,n=Sn(t),u=a.get(n);u||(u=l.querySelector(yu(n)),u||(t=nt({src:t,async:!0},e),(e=ke.get(n))&&Yf(t,e),u=l.createElement("script"),Zt(u),te(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ey(t,e){Nl.M(t,e);var l=bn;if(l&&t){var a=wa(l).hoistableScripts,n=Sn(t),u=a.get(n);u||(u=l.querySelector(yu(n)),u||(t=nt({src:t,async:!0,type:"module"},e),(e=ke.get(n))&&Yf(t,e),u=l.createElement("script"),Zt(u),te(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function xm(t,e,l,a){var n=(n=Al.current)?gu(n):null;if(!n)throw Error(r(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(l=xn(l.href),e=wa(n).hoistableStyles,a=e.get(l),a||(a={type:"style",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=xn(l.href);var u=wa(n).hoistableStyles,i=u.get(t);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(t,i),(u=n.querySelector(vu(t)))?u._p||(i.instance=u,i.state.loading=5):(u=ke.get(t),u||(u={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},ke.set(t,u)),ly(n,t,u,i.state))),e&&a===null)throw Error(r(528,""));return i}if(e&&a!==null)throw Error(r(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(l=Sn(l),e=wa(n).hoistableScripts,a=e.get(l),a||(a={type:"script",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,t))}}function xn(t){return'href="'+Re(t)+'"'}function vu(t){return'link[rel="stylesheet"]['+t+"]"}function Sm(t){return nt({},t,{"data-precedence":t.precedence,precedence:null})}function ly(t,e,l,a){if(e=t.querySelector('link[rel="preload"][as="style"]['+e+"]")){if(e[ku]!==!0){a.loading=1;return}}else e=t.createElement("link"),e[ku]=!0,e.onload=e.onerror=Cr.bind(null,e),te(e,"link",l),Zt(e),t.head.appendChild(e);a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2})}function Sn(t){return'[src="'+Re(t)+'"]'}function yu(t){return"script[async]"+t}function Tm(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+Re(l.href)+'"]');if(a)return e.instance=a,Zt(a),a;var n=nt({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),Zt(a),te(a,"style",n),$i(a,l.precedence,t),e.instance=a;case"stylesheet":n=xn(l.href);var u=t.querySelector(vu(n));if(u)return e.state.loading|=4,e.instance=u,Zt(u),u;a=Sm(l),(n=ke.get(n))&&Bf(a,n),u=(t.ownerDocument||t).createElement("link"),Zt(u);var i=u;return i._p=new Promise(function(h,g){i.onload=h,i.onerror=g}),te(u,"link",a),e.state.loading|=4,$i(u,l.precedence,t),e.instance=u;case"script":return u=Sn(l.src),(n=t.querySelector(yu(u)))?(e.instance=n,Zt(n),n):(a=l,(n=ke.get(u))&&(a=nt({},l),Yf(a,n)),t=t.ownerDocument||t,n=t.createElement("script"),Zt(n),te(n,"link",a),t.head.appendChild(n),e.instance=n);case"void":return null;default:throw Error(r(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,$i(a,l.precedence,t));return e.instance}function $i(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i title"):null)}function ay(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;return e.rel==="stylesheet"?(t=e.disabled,typeof e.precedence=="string"&&t==null):!0;case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function Em(t,e){return t==="img"&&e.src!=null&&e.src!==""&&e.onLoad==null&&e.loading!=="lazy"}function Nm(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function zm(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function jm(t,e){typeof e.decode=="function"&&(t.imgCount++,e.complete||(t.imgBytes+=zm(e),t.suspenseyImages.push(e)),t=iy.bind(t),e.decode().then(t,t))}function ny(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=xn(a.href),u=e.querySelector(vu(n));if(u){e=u._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=pu.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=u,Zt(u);return}u=e.ownerDocument||e,a=Sm(a),(n=ke.get(n))&&Bf(a,n),u=u.createElement("link"),Zt(u);var i=u;i._p=new Promise(function(h,g){i.onload=h,i.onerror=g}),te(u,"link",a),l.instance=u}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=pu.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var Wi=0;function uy(t,e){return t.stylesheets&&t.count===0&&Pi(t,t.stylesheets),0Wi?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Am(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Pi(t,t.stylesheets);else if(t.unsuspend){var e=t.unsuspend;t.unsuspend=null,e()}}}function pu(){this.count--,Am(this)}function iy(){this.imgCount--,Am(this)}var Ii=null;function Pi(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Ii=new Map,e.forEach(cy,t),Ii=null,pu.call(t))}function cy(t,e){if(!(e.state.loading&4)){var l=Ii.get(t);if(l)var a=l.get(null);else{l=new Map,Ii.set(t,l);for(var n=t.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(c){console.error(c)}}return s(),$f.exports=_y(),$f.exports}var Ny=Ey(),U=ir();const tr="cc_console_token";let rg=()=>{};function cr(){return localStorage.getItem(tr)??""}function sr(s){s?localStorage.setItem(tr,s):localStorage.removeItem(tr)}function zy(s){rg=s}class Im extends Error{status;constructor(c,o){super(o),this.status=c}}async function ic(s,c,o){const r={Authorization:`Bearer ${cr()}`};o!==void 0&&(r["Content-Type"]="application/json");const d=await fetch(`/api/v1${c}`,{method:s,headers:r,body:o===void 0?void 0:JSON.stringify(o)});if(d.status===401)throw sr(""),rg(),new Im(401,"unauthorized");if(!d.ok){let m=`http ${d.status}`;try{const v=await d.json();v.error&&(m=v.error)}catch{}throw new Im(d.status,m)}if(d.status!==204)return await d.json()}const Ht={get:s=>ic("GET",s),post:(s,c)=>ic("POST",s,c),patch:(s,c)=>ic("PATCH",s,c),put:(s,c)=>ic("PUT",s,c)};function er(s){const c=new URLSearchParams;for(const[r,d]of Object.entries(s))d&&c.set(r,d);const o=c.toString();return o?`?${o}`:""}function jy(){const[s,c]=U.useState(()=>window.location.hash.slice(1)||"/");return U.useEffect(()=>{const o=()=>c(window.location.hash.slice(1)||"/");return window.addEventListener("hashchange",o),()=>window.removeEventListener("hashchange",o)},[]),s}function na(s){window.location.hash=s}function me(s){if(!s)return"-";const c=new Date(s);if(Number.isNaN(c.getTime()))return s;const o=r=>String(r).padStart(2,"0");return`${c.getFullYear()}-${o(c.getMonth()+1)}-${o(c.getDate())} ${o(c.getHours())}:${o(c.getMinutes())}:${o(c.getSeconds())}`}function Ay(s){if(!s)return"never";const c=Date.now()-new Date(s).getTime();return Number.isNaN(c)?s:c<6e4?`${Math.max(0,Math.floor(c/1e3))}s ago`:c<36e5?`${Math.floor(c/6e4)}m ago`:c<864e5?`${Math.floor(c/36e5)}h ago`:`${Math.floor(c/864e5)}d ago`}const zn=["proposal","analysis","design","review","implementation","testing","evaluation","confirmation"],Pm=["idle","assigned","in_progress","awaiting_review","changes_requested","approved"],Oy=["planned","in_progress","blocked_pending_decision","done","cancelled"];function Ry(s){const[c,o]=U.useState([]),[r,d]=U.useState("connecting"),m=U.useRef(s);return m.current=s,U.useEffect(()=>{let v=!1,y,j,E;const O=()=>{j||v||(d("poll"),j=setInterval(()=>m.current(),1e4))},b=async()=>{if(!v){E=new AbortController;try{const D=await fetch("/api/v1/stream",{headers:{Authorization:`Bearer ${cr()}`},signal:E.signal});if(!D.ok||!D.body)throw new Error(`stream http ${D.status}`);j&&(clearInterval(j),j=void 0),d("sse");const V=D.body.pipeThrough(new TextDecoderStream).getReader();let G="";for(;;){const{done:B,value:$}=await V.read();if(B)break;G+=$;let H;for(;(H=G.indexOf(`
+
+`))>=0;){const mt=G.slice(0,H);G=G.slice(H+2);for(const qt of mt.split(`
+`))if(qt.startsWith("data:"))try{const q=JSON.parse(qt.slice(5).trim());o(et=>[q,...et].slice(0,50)),m.current()}catch{}}}throw new Error("stream closed")}catch{if(v)return;O(),y=setTimeout(b,1e4)}}};return b(),()=>{v=!0,E?.abort(),y&&clearTimeout(y),j&&clearInterval(j)}},[]),{events:c,mode:r}}function tg(){const[s,c]=U.useState(null),[o,r]=U.useState(""),d=U.useCallback(()=>{Ht.get("/overview").then(c).catch(j=>{j.message!=="unauthorized"&&r(j.message)})},[]);U.useEffect(()=>{d()},[d]);const{events:m,mode:v}=Ry(d),y=(j,E)=>s?.task_counts.find(O=>O.stage===j&&O.stage_state===E)?.count??0;return f.jsxs("div",{children:[f.jsxs("div",{className:"page-head",children:[f.jsx("h2",{children:"总览"}),f.jsx("span",{className:"badge",children:v==="sse"?"SSE 实时":v==="poll"?"10s 轮询":"连接中"}),f.jsx("div",{className:"spacer"}),f.jsx("button",{onClick:d,children:"刷新"})]}),o&&f.jsx("div",{className:"error-box",children:o}),f.jsxs("div",{className:"stat-cards",children:[f.jsxs("div",{className:`stat-card ${s&&s.open_decisions>0?"crit":"ok"}`,onClick:()=>na("/decisions"),children:[f.jsx("div",{className:"num",children:s?.open_decisions??"-"}),f.jsx("div",{className:"lbl",children:"待裁决决策"})]}),f.jsxs("div",{className:`stat-card ${s&&s.awaiting_review>0?"warn":"ok"}`,onClick:()=>na("/board"),children:[f.jsx("div",{className:"num",children:s?.awaiting_review??"-"}),f.jsx("div",{className:"lbl",children:"待审推进"})]}),f.jsxs("div",{className:"stat-card",onClick:()=>na("/audit"),children:[f.jsx("div",{className:"num",children:s?.open_findings??"-"}),f.jsx("div",{className:"lbl",children:"Open Findings"})]})]}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"阶段 × 状态矩阵"}),f.jsxs("table",{className:"matrix",children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"stage"}),Pm.map(j=>f.jsx("th",{children:j},j))]})}),f.jsx("tbody",{children:zn.map(j=>f.jsxs("tr",{children:[f.jsx("td",{children:j}),Pm.map(E=>{const O=y(j,E);return f.jsx("td",{className:O>0&&(E==="awaiting_review"||E==="changes_requested")?"hot":"",children:O||""},E)})]},j))})]})]}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Agent 心跳活性"}),!s||s.agents.length===0?f.jsx("div",{className:"dim mono-sm",children:"暂无 agent 活动记录"}):s.agents.map(j=>f.jsxs("div",{className:"agent-row",children:[f.jsx("span",{className:`dot ${j.stale?"stale":"live"}`}),f.jsx("span",{children:j.agent}),f.jsxs("span",{className:"dim mono-sm",children:[j.stale?"stale":"live"," · last heartbeat ",Ay(j.last_heartbeat_at)]})]},j.agent))]}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"最近事件"}),f.jsx("div",{className:"event-feed",children:m.length===0?f.jsx("div",{className:"dim mono-sm",children:v==="sse"?"等待事件…":"事件流不可用,已切换轮询模式"}):m.map(j=>f.jsxs("div",{className:"ev",children:[f.jsx("span",{className:"ts",children:me(j.ts)}),f.jsx("span",{className:"phase",children:j.phase}),f.jsxs("span",{children:[j.agent&&f.jsxs("strong",{children:[j.agent," "]}),j.message]})]},j.id))})]})]})}function Cy({plans:s,onCreated:c,onClose:o}){const[r,d]=U.useState(""),[m,v]=U.useState(""),[y,j]=U.useState("task"),[E,O]=U.useState(""),[b,D]=U.useState(!0),[V,G]=U.useState(0),[B,$]=U.useState(""),[H,mt]=U.useState(""),[qt,q]=U.useState(!1),et=async Q=>{Q.preventDefault(),q(!0),mt("");try{await Ht.post("/tasks",{slug:r.trim(),title:m.trim(),kind:y,plan_id:E||void 0,testing_required:b,priority:V,instruction_md:B}),c()}catch(nt){mt(nt.message),q(!1)}};return f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"新建任务"}),H&&f.jsx("div",{className:"error-box",children:H}),f.jsxs("form",{onSubmit:et,children:[f.jsxs("div",{className:"op-row",children:[f.jsxs("label",{children:["slug",f.jsx("input",{required:!0,value:r,onChange:Q=>d(Q.target.value),placeholder:"my-task-slug"})]}),f.jsxs("label",{style:{flex:1,minWidth:220},children:["title",f.jsx("input",{required:!0,value:m,onChange:Q=>v(Q.target.value)})]}),f.jsxs("label",{children:["kind",f.jsxs("select",{value:y,onChange:Q=>j(Q.target.value),children:[f.jsx("option",{value:"task",children:"task"}),f.jsx("option",{value:"proposal",children:"proposal"})]})]}),f.jsxs("label",{children:["plan",f.jsxs("select",{value:E,onChange:Q=>O(Q.target.value),children:[f.jsx("option",{value:"",children:"(none)"}),s.map(Q=>f.jsx("option",{value:Q.id,children:Q.slug},Q.id))]})]}),f.jsxs("label",{children:["priority",f.jsx("input",{type:"number",style:{width:80},value:V,onChange:Q=>G(Number(Q.target.value))})]}),f.jsxs("label",{style:{flexDirection:"row",alignItems:"center",gap:6},children:[f.jsx("input",{type:"checkbox",checked:b,onChange:Q=>D(Q.target.checked)}),"testing_required"]})]}),f.jsx("label",{className:"dim mono-sm",children:"instruction_md"}),f.jsx("textarea",{rows:5,value:B,onChange:Q=>$(Q.target.value),placeholder:"任务指令(markdown)"}),f.jsxs("div",{className:"op-row",style:{marginTop:8},children:[f.jsx("button",{className:"primary",type:"submit",disabled:qt,children:"创建"}),f.jsx("button",{type:"button",onClick:o,children:"取消"})]})]})]})}function Dy(){const[s,c]=U.useState([]),[o,r]=U.useState([]),[d,m]=U.useState(""),[v,y]=U.useState(""),[j,E]=U.useState(""),[O,b]=U.useState(!1),[D,V]=U.useState(""),G=U.useCallback(()=>{Ht.get(`/tasks${er({status:d,plan_id:v,q:j})}`).then(B=>{c(B),V("")}).catch(B=>{B.message!=="unauthorized"&&V(B.message)})},[d,v,j]);return U.useEffect(()=>{G()},[G]),U.useEffect(()=>{Ht.get("/plans").then(r).catch(()=>{})},[]),f.jsxs("div",{children:[f.jsxs("div",{className:"page-head",children:[f.jsx("h2",{children:"看板"}),f.jsxs("div",{className:"filters",children:[f.jsxs("select",{value:v,onChange:B=>y(B.target.value),children:[f.jsx("option",{value:"",children:"全部 plan"}),o.map(B=>f.jsx("option",{value:B.id,children:B.slug},B.id))]}),f.jsxs("select",{value:d,onChange:B=>m(B.target.value),children:[f.jsx("option",{value:"",children:"全部状态"}),Oy.map(B=>f.jsx("option",{value:B,children:B},B))]}),f.jsx("input",{placeholder:"搜索 slug/title",value:j,onChange:B=>E(B.target.value)})]}),f.jsx("div",{className:"spacer"}),f.jsx("button",{className:"primary",onClick:()=>b(B=>!B),children:O?"收起":"新建任务"})]}),D&&f.jsx("div",{className:"error-box",children:D}),O&&f.jsx(Cy,{plans:o,onClose:()=>b(!1),onCreated:()=>{b(!1),G()}}),f.jsx("div",{className:"board",children:zn.map(B=>{const $=s.filter(H=>H.stage===B);return f.jsxs("div",{className:"lane",children:[f.jsxs("h4",{children:[f.jsx("span",{children:B}),f.jsx("span",{children:$.length})]}),$.map(H=>f.jsxs("div",{className:"card",onClick:()=>na(`/tasks/${H.id}`),children:[f.jsx("div",{className:"title",children:H.title}),f.jsx("div",{className:"meta",children:f.jsx("span",{className:"mono-sm",children:H.slug})}),f.jsxs("div",{className:"meta",style:{marginTop:4},children:[f.jsx("span",{className:`badge st-${H.stage_state}`,children:H.stage_state}),f.jsx("span",{className:`badge status-${H.status}`,children:H.status}),f.jsxs("span",{children:["P",H.priority]}),H.assigned_agent&&f.jsxs("span",{children:["@",H.assigned_agent]})]})]},H.id))]},B)})})]})}function fr(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Da=fr();function og(s){Da=s}var Ra={exec:()=>null};function Nn(s){let c=[];return o=>{let r=Math.max(0,Math.min(3,o-1)),d=c[r];return d||(d=s(r),c[r]=d),d}}function ut(s,c=""){let o=typeof s=="string"?s:s.source,r={replace:(d,m)=>{let v=typeof m=="string"?m:m.source;return v=v.replace(ae.caret,"$1"),o=o.replace(d,v),r},getRegex:()=>new RegExp(o,c)};return r}var My=((s="")=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:s=>new RegExp(`^( {0,3}${s})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:Nn(s=>new RegExp(`^ {0,${s}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)),hrRegex:Nn(s=>new RegExp(`^ {0,${s}}((?:-[ ]*){3,}|(?:_[ ]*){3,}|(?:\\*[ ]*){3,})(?:\\n+|$)`)),fencesBeginRegex:Nn(s=>new RegExp(`^ {0,${s}}(?:\`\`\`|~~~)`)),headingBeginRegex:Nn(s=>new RegExp(`^ {0,${s}}#`)),htmlBeginRegex:Nn(s=>new RegExp(`^ {0,${s}}(?:?(?:${ju})(?: +|$|/?>)|<(?:script|pre|style|textarea|!--))`,"i")),blockquoteBeginRegex:Nn(s=>new RegExp(`^ {0,${s}}>`))},Uy=/^(?:[ \t]*(?:\n|$))+/,Hy=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,qy=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,zu=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,wy=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,rr=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,hg=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,dg=ut(hg).replace(/bull/g,rr).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\s|$)/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),ky=ut(hg).replace(/bull/g,rr).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\s|$)/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),or=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/,By=/^[^\n]+/,hr=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,Yy=ut(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",hr).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Gy=ut(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g,rr).getRegex(),ju="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",dr=/|$))/,Qy=ut("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|[^\\n]*\\n*|$)|[^\\n]*\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][a-z0-9-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?!script|pre|style|textarea)[a-z][a-z0-9-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",dr).replace("tag",ju).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),mg=s=>ut(or).replace("hr",zu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list",s).replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex(),Xy=mg(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/),Zy=mg(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/),Ly=ut(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Zy).getRegex(),mr={blockquote:Ly,code:Hy,def:Yy,fences:qy,heading:wy,hr:zu,html:Qy,lheading:dg,list:Gy,newline:Uy,paragraph:Xy,table:Ra,text:By},eg=ut("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",zu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex(),Vy={...mr,lheading:ky,table:eg,paragraph:ut(or).replace("hr",zu).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",eg).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",ju).getRegex()},Ky={...mr,html:ut(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)| \\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",dr).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Ra,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:ut(or).replace("hr",zu).replace("heading",` *#{1,6} *[^
+]`).replace("lheading",dg).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Jy=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,$y=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,gg=/^( {2,}|\\)\n(?!\s*$)[ \t]*/,Fy=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k (?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",My?"(?`+)[^`]+\k(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),yg=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,lp=ut(yg,"u").replace(/punct/g,zl).getRegex(),ap=ut(yg,"u").replace(/punct/g,vg).getRegex(),np=/^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/,up=ut(np,"u").replace(/openQuote/g,Iy).replace(/punct/g,zl).getRegex(),pg="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",ip=ut(pg,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,zl).getRegex(),cp=ut(pg,"gu").replace(/notPunctSpace/g,tp).replace(/punctSpace/g,Py).replace(/punct/g,vg).getRegex(),sp="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)",fp=ut(sp,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,zl).getRegex(),rp=ut("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,zl).getRegex(),op="^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\s](_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)",hp=ut(op,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,zl).getRegex(),dp=ut(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,zl).getRegex(),mp="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",gp=ut(mp,"gu").replace(/notPunctSpace/g,Au).replace(/punctSpace/g,jn).replace(/punct/g,zl).getRegex(),vp=ut(/\\(punct)/,"gu").replace(/punct/g,zl).getRegex(),yp=ut(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),pp=ut(dr).replace("(?:-->|$)","-->").getRegex(),bp=ut("^comment|^[a-zA-Z][a-zA-Z0-9-]*\\s*>|^<[a-zA-Z][a-zA-Z0-9-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",pp).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),bg=/\[(?:\\[\s\S]|[^\[\]\\])*\]/,sc=ut(/(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/).replace("brackets",bg).getRegex(),xp=ut(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",sc).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Sp=ut(/^!?\[(label)\]\[(ref)\]/).replace("label",sc).replace("ref",hr).getRegex(),Tp=ut(/^!?\[(ref)\](?:\[\])?/).replace("ref",hr).getRegex(),lg=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\]){1,999}/,_p=ut(/(?:[^\[\]\\`]*(?:\[(?:brackets|\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\]))){0,999}?[^\[\]\\`]*?/).replace("brackets",bg).getRegex(),Ep=ut("reflink|nolink(?!\\()","g").replace("reflink",ut(/^!?\[(label)\]\[(ref)\]/).replace("label",_p).replace("ref",lg).getRegex()).replace("nolink",ut(/^!?\[(ref)\](?:\[\])?/).replace("ref",lg).getRegex()).getRegex(),ag=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,gr={_backpedal:Ra,anyPunctuation:vp,autolink:yp,blockSkip:ep,br:gg,code:$y,del:Ra,delLDelim:Ra,delRDelim:Ra,emStrongLDelim:lp,emStrongRDelimAst:ip,emStrongRDelimUnd:rp,escape:Jy,link:xp,nolink:Tp,punctuation:Wy,reflink:Sp,reflinkSearch:Ep,tag:bp,text:Fy,url:Ra},Np={...gr,emStrongLDelim:up,emStrongRDelimAst:fp,emStrongRDelimUnd:hp,link:ut(/^!?\[(label)\]\((.*?)\)/).replace("label",sc).getRegex(),reflink:ut(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",sc).getRegex()},lr={...gr,emStrongRDelimAst:cp,emStrongLDelim:ap,delLDelim:dp,delRDelim:gp,url:ut(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ag).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![\w-])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:ut(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},ng=s=>jp[s];function je(s,c){if(c){if(ae.escapeTest.test(s))return s.replace(ae.escapeReplace,ng)}else if(ae.escapeTestNoEncode.test(s))return s.replace(ae.escapeReplaceNoEncode,ng);return s}function ug(s){try{s=encodeURI(s).replace(ae.percentDecode,"%")}catch{return null}return s}function ig(s,c){let o=s.replace(ae.findPipe,(m,v,y)=>{let j=!1,E=v;for(;--E>=0&&y[E]==="\\";)j=!j;return j?"|":" |"}),r=o.split(ae.splitPipe),d=0;if(r[0].trim()||r.shift(),r.length>0&&!r.at(-1)?.trim()&&r.pop(),c)if(r.length>c)r.splice(c);else for(;r.length=0&&ae.blankLine.test(c[o]);)o--;return c.length-o<=2?s:c.slice(0,o+1).join(`
+`)}function fc(s){return s.toLowerCase().toUpperCase().toLowerCase()}function Ap(s,c){if(s.indexOf(c[1])===-1)return-1;let o=0;for(let r=0;r0?-2:-1}function Op(s,c=0){let o=c,r="";for(let d of s)if(d===" "){let m=4-o%4;r+=" ".repeat(m),o+=m}else r+=d,o++;return r}function sg(s,c,o,r,d){let m=c.href,v=c.title||null,y=s[1].replace(d.other.outputLinkReplace,"$1"),j=s[0].charAt(0)==="!";r.state.inLink=!0;let E=r.state.linkEmitted,O=r.state.inRawBlock;r.state.linkEmitted=!1;let b=r.inlineTokens(y),D=r.state.linkEmitted;if(r.state.linkEmitted=E,r.state.inLink=!1,!j){if(D){r.state.inRawBlock=O;return}r.state.linkEmitted=!0}return{type:j?"image":"link",raw:o,href:m,title:v,text:y,tokens:b}}function Rp(s,c,o){let r=s.match(o.other.indentCodeCompensation);if(r===null)return c;let d=r[1];return c.split(`
+`).map(m=>{let v=m.match(o.other.beginningSpace);if(v===null)return m;let[y]=v;return m.slice(Math.min(y.length,d.length))}).join(`
+`)}function fg(s,c,o,r){if(!c.includes("<"))return!1;for(let d=0;dc.length-d)return!0;d+=v[0].length-1}}return!1}var rc=class{options;rules;lexer;constructor(s){this.options=s||Da}space(s){let c=this.rules.block.newline.exec(s);if(c&&c[0].length>0)return{type:"space",raw:c[0]}}code(s){let c=this.rules.block.code.exec(s);if(c){let o=this.options.pedantic?c[0]:cg(c[0]),r=o.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:o,codeBlockStyle:"indented",text:r}}}fences(s){let c=this.rules.block.fences.exec(s);if(c){let o=c[0],r=Rp(o,c[3]||"",this.rules);return{type:"code",raw:o,lang:c[2]?c[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):c[2],text:r}}}heading(s){let c=this.rules.block.heading.exec(s);if(c){let o=c[2].trim();if(this.rules.other.endingHash.test(o)){let r=aa(o,"#");(this.options.pedantic||!r||this.rules.other.endingSpaceTabChar.test(r))&&(o=r.trim())}return{type:"heading",raw:aa(c[0],`
+`),depth:c[1].length,text:o,tokens:this.lexer.inline(o)}}}hr(s){let c=this.rules.block.hr.exec(s);if(c)return{type:"hr",raw:aa(c[0],`
+`)}}blockquote(s){let c=this.rules.block.blockquote.exec(s);if(c){let o=aa(c[0],`
+`).split(`
+`),r="",d="",m=[];for(;o.length>0;){let v=!1,y=[],j;for(j=0;j1,d={type:"list",raw:"",ordered:r,start:r?+o.slice(0,-1):"",loose:!1,items:[]};o=r?`\\d{1,9}\\${o.slice(-1)}`:`\\${o}`,this.options.pedantic&&(o=r?o:"[*+-]");let m=this.rules.other.listItemRegex(o),v=!1;for(;s;){let j=!1,E="",O="";if(!(c=m.exec(s))||this.rules.block.hr.test(s))break;E=c[0],s=s.substring(E.length);let b=Op(c[2].split(`
+`,1)[0],c[1].length),D=s.split(`
+`,1)[0],V=!b.trim(),G=0;if(this.options.pedantic?(G=2,O=b.trimStart()):V?G=c[1].length+1:(G=b.search(this.rules.other.nonSpaceChar),G=G>4?1:G,O=b.slice(G),G+=c[1].length),V&&this.rules.other.blankLine.test(D)&&(E+=D+`
+`,s=s.substring(D.length+1),j=!0),!j){let B=this.rules.other.nextBulletRegex(G),$=this.rules.other.hrRegex(G),H=this.rules.other.fencesBeginRegex(G),mt=this.rules.other.headingBeginRegex(G),qt=this.rules.other.htmlBeginRegex(G),q=this.rules.other.blockquoteBeginRegex(G);for(;s;){let et=s.split(`
+`,1)[0],Q;if(D=et,this.options.pedantic?(D=D.replace(this.rules.other.listReplaceNesting," "),Q=D):Q=D.replace(this.rules.other.tabCharGlobal," "),H.test(D)||mt.test(D)||qt.test(D)||q.test(D)||B.test(D)||$.test(D))break;if(Q.search(this.rules.other.nonSpaceChar)>=G||!D.trim())O+=`
+`+Q.slice(G);else{if(V||b.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||H.test(b)||mt.test(b)||$.test(b))break;O+=`
+`+D}V=!D.trim(),E+=et+`
+`,s=s.substring(et.length+1),b=Q.slice(G)}}d.loose||(v?d.loose=!0:this.rules.other.doubleBlankLine.test(E)&&(v=!0)),d.items.push({type:"list_item",raw:E,task:!!this.options.gfm&&this.rules.other.listIsTask.test(O),loose:!1,text:O,tokens:[]}),d.raw+=E}let y=d.items.at(-1);if(y)y.raw=y.raw.trimEnd(),y.text=y.text.trimEnd();else return;d.raw=d.raw.trimEnd();for(let j of d.items)if(this.lexer.state.top=!1,j.tokens=this.lexer.blockTokens(j.text,[]),!d.loose){let E=j.tokens.filter(b=>b.type==="space"),O=E.length>0&&E.some(b=>this.rules.other.anyLine.test(b.raw));d.loose=O}for(let j of d.items){let E=j.tokens[0];if(j.task&&(E?.type==="text"||E?.type==="paragraph")){j.text=j.text.replace(this.rules.other.listReplaceTask,""),E.raw=E.raw.replace(this.rules.other.listReplaceTask,""),E.text=E.text.replace(this.rules.other.listReplaceTask,"");for(let b=this.lexer.inlineQueue.length-1;b>=0;b--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[b].src)){this.lexer.inlineQueue[b].src=this.lexer.inlineQueue[b].src.replace(this.rules.other.listReplaceTask,"");break}let O=this.rules.other.listTaskCheckbox.exec(j.raw);if(O){let b={type:"checkbox",raw:O[0]+" ",checked:O[0]!=="[ ]"};j.checked=b.checked,d.loose?j.tokens[0]&&["paragraph","text"].includes(j.tokens[0].type)&&"tokens"in j.tokens[0]&&j.tokens[0].tokens?(j.tokens[0].raw=b.raw+j.tokens[0].raw,j.tokens[0].text=b.raw+j.tokens[0].text,j.tokens[0].tokens.unshift(b)):j.tokens.unshift({type:"paragraph",raw:b.raw,text:b.raw,tokens:[b]}):j.tokens.unshift(b)}}else j.task&&(j.task=!1)}if(d.loose)for(let j of d.items){j.loose=!0;for(let E of j.tokens)E.type==="text"&&(E.type="paragraph")}return d}}html(s){let c=this.rules.block.html.exec(s);if(c){let o=cg(c[0]);return{type:"html",block:!0,raw:o,pre:c[1]==="pre"||c[1]==="script"||c[1]==="style",text:o}}}def(s){let c=this.rules.block.def.exec(s);if(c){let o=fc(c[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=c[2]?c[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",d=c[3]?c[3].substring(1,c[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):c[3];return{type:"def",tag:o,raw:aa(c[0],`
+`),href:r,title:d}}}table(s){let c=this.rules.block.table.exec(s);if(!c||!this.rules.other.tableDelimiter.test(c[2]))return;let o=ig(c[1]),r=c[2].replace(this.rules.other.tableAlignChars,"").split("|"),d=c[3]?.trim()?c[3].replace(this.rules.other.tableRowBlankLine,"").split(`
+`):[],m={type:"table",raw:aa(c[0],`
+`),header:[],align:[],rows:[]};if(o.length===r.length){for(let v of r)this.rules.other.tableAlignRight.test(v)?m.align.push("right"):this.rules.other.tableAlignCenter.test(v)?m.align.push("center"):this.rules.other.tableAlignLeft.test(v)?m.align.push("left"):m.align.push(null);for(let v=0;v({text:y,tokens:this.lexer.inline(y),header:!1,align:m.align[j]})));return m}}lheading(s){let c=this.rules.block.lheading.exec(s);if(c){let o=c[1].trim();return{type:"heading",raw:aa(c[0],`
+`),depth:c[2].charAt(0)==="="?1:2,text:o,tokens:this.lexer.inline(o)}}}paragraph(s){let c=this.rules.block.paragraph.exec(s);if(c){let o=c[1].charAt(c[1].length-1)===`
+`?c[1].slice(0,-1):c[1];return{type:"paragraph",raw:c[0],text:o,tokens:this.lexer.inline(o)}}}text(s){let c=this.rules.block.text.exec(s);if(c)return{type:"text",raw:c[0],text:c[0],tokens:this.lexer.inline(c[0])}}escape(s){let c=this.rules.inline.escape.exec(s);if(c)return{type:"escape",raw:c[0],text:c[1]}}tag(s){let c=this.rules.inline.tag.exec(s);if(c)return!this.lexer.state.inLink&&this.rules.other.startATag.test(c[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(c[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(c[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(c[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:c[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:c[0]}}link(s){let c=this.rules.inline.link.exec(s);if(c){let o=c[0].charAt(0)==="!"?2:1;if(!this.options.pedantic&&fg(s,c[1],o,this.rules))return;let r=c[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(r)){if(!this.rules.other.endAngleBracket.test(r))return;let v=aa(r.slice(0,-1),"\\");if((r.length-v.length)%2===0)return}else{let v=Ap(c[2],"()");if(v===-2)return;if(v>-1){let y=(c[0].indexOf("!")===0?5:4)+c[1].length+v;c[2]=c[2].substring(0,v),c[0]=c[0].substring(0,y).trim(),c[3]=""}}let d=c[2],m="";if(this.options.pedantic){let v=this.rules.other.pedanticHrefTitle.exec(d);v&&(d=v[1],m=v[3])}else m=c[3]?c[3].slice(1,-1):"";return d=d.trim(),this.rules.other.startAngleBracket.test(d)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(r)?d=d.slice(1):d=d.slice(1,-1)),sg(c,{href:d&&d.replace(this.rules.inline.anyPunctuation,"$1"),title:m&&m.replace(this.rules.inline.anyPunctuation,"$1")},c[0],this.lexer,this.rules)}}reflink(s,c){let o;if((o=this.rules.inline.reflink.exec(s))||(o=this.rules.inline.nolink.exec(s))){let r=o[0].charAt(0)==="!"?2:1;if(!this.options.pedantic&&fg(s,o[1],r,this.rules))return;let d=(o[2]||o[1]).replace(this.rules.other.multipleSpaceGlobal," "),m=c[fc(d)];if(!m){let v=o[0].charAt(0);return{type:"text",raw:v,text:v}}return sg(o,m,o[0],this.lexer,this.rules)}}emStrong(s,c,o=""){let r=this.rules.inline.emStrongLDelim.exec(s);if(!(!r||!r[1]&&!r[2]&&!r[3]&&!r[4]||r[4]&&o.match(this.rules.other.unicodeAlphaNumeric))&&(!(r[1]||r[3])||!o||this.rules.inline.punctuation.exec(o))){let d=[...r[0]].length-1,m,v,y=d,j=0,E=r[0][0],O=o===E,b=E==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(b.lastIndex=0,c=c.slice(-1*s.length+d);(r=b.exec(c))!==null;){if(m=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!m)continue;if(v=[...m].length,r[3]||r[4]){y+=v;continue}else if(r[5]||r[6]){if(d%3&&!((d+v)%3)){j+=v;continue}if(O)break}if(y-=v,y>0)continue;v=Math.min(v,v+y+j);let D=[...r[0]][0].length,V=s.slice(0,d+r.index+D+v);if(Math.min(d,v)%2){let B=V.slice(1,-1);return{type:"em",raw:V,text:B,tokens:this.lexer.inlineTokens(B)}}let G=V.slice(2,-2);return{type:"strong",raw:V,text:G,tokens:this.lexer.inlineTokens(G)}}}}codespan(s){let c=this.rules.inline.code.exec(s);if(c){let o=c[2].replace(this.rules.other.newLineCharGlobal," "),r=this.rules.other.nonSpaceChar.test(o),d=this.rules.other.startingSpaceChar.test(o)&&this.rules.other.endingSpaceChar.test(o);return r&&d&&(o=o.substring(1,o.length-1)),{type:"codespan",raw:c[0],text:o}}}br(s){let c=this.rules.inline.br.exec(s);if(c)return{type:"br",raw:c[0]}}del(s,c,o=""){let r=this.rules.inline.delLDelim.exec(s);if(r&&(!r[1]||!o||this.rules.inline.punctuation.exec(o))){let d=[...r[0]].length-1,m,v,y=d,j=this.rules.inline.delRDelim;for(j.lastIndex=0,c=c.slice(-1*s.length+d);(r=j.exec(c))!==null;){if(m=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!m||(v=[...m].length,v!==d))continue;if(r[3]||r[4]){y+=v;continue}if(y-=v,y>0)continue;v=Math.min(v,v+y);let E=[...r[0]][0].length,O=s.slice(0,d+r.index+E+v),b=O.slice(d,-d);return{type:"del",raw:O,text:b,tokens:this.lexer.inlineTokens(b)}}}}autolink(s){let c=this.rules.inline.autolink.exec(s);if(c){let o,r;return c[2]==="@"?(o=c[1],r="mailto:"+o):(o=c[1],r=o),{type:"link",raw:c[0],text:o,href:r,autolink:!0,tokens:[{type:"text",raw:o,text:o}]}}}url(s){let c;if(c=this.rules.inline.url.exec(s)){let o,r;if(c[2]==="@")o=c[0],r="mailto:"+o;else{let d;do d=c[0],c[0]=this.rules.inline._backpedal.exec(c[0])?.[0]??"";while(d!==c[0]);o=c[0],c[1]==="www."?r="http://"+c[0]:r=c[0]}return{type:"link",raw:c[0],text:o,href:r,autolink:!0,tokens:[{type:"text",raw:o,text:o}]}}}inlineText(s){let c=this.rules.inline.text.exec(s);if(c){let o=this.lexer.state.inRawBlock;return{type:"text",raw:c[0],text:c[0],escaped:o}}}},Ve=class ar{tokens;options;state;inlineQueue;tokenizer;constructor(c){this.tokens=[],this.tokens.links=Object.create(null),this.options=c||Da,this.options.tokenizer=this.options.tokenizer||new rc,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,linkEmitted:!1,top:!0};let o={other:ae,block:cc.normal,inline:Eu.normal};this.options.pedantic?(o.block=cc.pedantic,o.inline=Eu.pedantic):this.options.gfm&&(o.block=cc.gfm,this.options.breaks?o.inline=Eu.breaks:o.inline=Eu.gfm),this.tokenizer.rules=o}static get rules(){return{block:cc,inline:Eu}}static lex(c,o){return new ar(o).lex(c)}static lexInline(c,o){return new ar(o).inlineTokens(c)}lex(c){c=c.replace(ae.carriageReturn,`
+`),this.blockTokens(c,this.tokens);for(let o=0;o(m=y.call({lexer:this},c,o))?(c=c.substring(m.raw.length),o.push(m),!0):!1))continue;if(m=this.tokenizer.space(c)){c=c.substring(m.raw.length);let y=o.at(-1);m.raw.length===1&&y!==void 0?y.raw+=`
+`:o.push(m);continue}if(m=this.tokenizer.code(c)){c=c.substring(m.raw.length);let y=o.at(-1);y?.type==="paragraph"||y?.type==="text"?(y.raw+=(y.raw.endsWith(`
+`)?"":`
+`)+m.raw,y.text+=`
+`+m.text,this.inlineQueue.at(-1).src=y.text):o.push(m);continue}if(m=this.tokenizer.fences(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.heading(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.hr(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.blockquote(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.list(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.html(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.def(c)){c=c.substring(m.raw.length);let y=o.at(-1);y?.type==="paragraph"||y?.type==="text"?(y.raw+=(y.raw.endsWith(`
+`)?"":`
+`)+m.raw,y.text+=`
+`+m.raw,this.inlineQueue.at(-1).src=y.text):this.tokens.links[m.tag]||(this.tokens.links[m.tag]={href:m.href,title:m.title},o.push(m));continue}if(m=this.tokenizer.table(c)){c=c.substring(m.raw.length),o.push(m);continue}if(m=this.tokenizer.lheading(c)){c=c.substring(m.raw.length),o.push(m);continue}let v=c;if(this.options.extensions?.startBlock){let y=1/0,j=c.slice(1),E;this.options.extensions.startBlock.forEach(O=>{E=O.call({lexer:this},j),typeof E=="number"&&E>=0&&(y=Math.min(y,E))}),y<1/0&&y>=0&&(v=c.substring(0,y+1))}if(this.state.top&&(m=this.tokenizer.paragraph(v))){let y=o.at(-1);r&&y?.type==="paragraph"?(y.raw+=(y.raw.endsWith(`
+`)?"":`
+`)+m.raw,y.text+=`
+`+m.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=y.text):o.push(m),r=v.length!==c.length,c=c.substring(m.raw.length);continue}if(m=this.tokenizer.text(c)){c=c.substring(m.raw.length);let y=o.at(-1);y?.type==="text"?(y.raw+=(y.raw.endsWith(`
+`)?"":`
+`)+m.raw,y.text+=`
+`+m.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=y.text):o.push(m);continue}if(c){this.infiniteLoopError(c.charCodeAt(0));break}}return this.state.top=!0,o}inline(c,o=[]){return this.inlineQueue.push({src:c,tokens:o}),o}linkInText(c){if(!c.includes("["))return!1;let o=this.tokenizer.rules.inline.link;for(let r of c.matchAll(this.tokenizer.rules.inline.blockSkip))if(o.test(r[0])&&c.charAt(r.index-1)!=="!")return!0;for(let r of c.matchAll(this.tokenizer.rules.inline.reflinkSearch)){let d=r[0],m=d.lastIndexOf("[");if(!(d.charAt(0)==="!"||!Object.hasOwn(this.tokens.links,fc(d.slice(m+1,-1))))&&!(m>1&&this.linkInText(d.slice(1,m-1))))return!0}return!1}inlineTokens(c,o=[]){this.tokenizer.lexer=this;let r=c;if(this.tokens.links&&c.includes("[")){let y=this.tokenizer.rules.inline.reflinkSearch,j=E=>{let O=E.lastIndexOf("[");if(!Object.hasOwn(this.tokens.links,fc(E.slice(O+1,-1))))return E;if(O>1&&E.charAt(0)!=="!"){let b=E.slice(1,O-1);if(this.linkInText(b))return"["+b.replace(y,j)+"]["+"a".repeat(E.length-O-2)+"]"}return"["+"a".repeat(E.length-2)+"]"};r=r.replace(y,j)}r=r.replace(this.tokenizer.rules.inline.anyPunctuation,y=>"+".repeat(y.length)),r=r.replace(this.tokenizer.rules.inline.blockSkip,(y,j,E)=>{let O=E?E.length:0;return y.slice(0,O)+"["+"a".repeat(y.length-O-2)+"]"}),r=this.options.hooks?.emStrongMask?.call({lexer:this},r)??r;let d=!1,m="",v=1/0;for(;c;){if(c.length(y=E.call({lexer:this},c,o))?(c=c.substring(y.raw.length),o.push(y),!0):!1))continue;if(y=this.tokenizer.escape(c)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.tag(c)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.link(c)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.reflink(c,this.tokens.links)){c=c.substring(y.raw.length);let E=o.at(-1);y.type==="text"&&E?.type==="text"?(E.raw+=y.raw,E.text+=y.text):o.push(y);continue}if(y=this.tokenizer.emStrong(c,r,m)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.codespan(c)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.br(c)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.del(c,r,m)){c=c.substring(y.raw.length),o.push(y);continue}if(y=this.tokenizer.autolink(c)){c=c.substring(y.raw.length),o.push(y);continue}if(!this.state.inLink&&(y=this.tokenizer.url(c))){c=c.substring(y.raw.length),o.push(y);continue}let j=c;if(this.options.extensions?.startInline){let E=1/0,O=c.slice(1),b;this.options.extensions.startInline.forEach(D=>{b=D.call({lexer:this},O),typeof b=="number"&&b>=0&&(E=Math.min(E,b))}),E<1/0&&E>=0&&(j=c.substring(0,E+1))}if(y=this.tokenizer.inlineText(j)){c=c.substring(y.raw.length),y.raw.slice(-1)!=="_"&&(m=y.raw.slice(-1)),d=!0;let E=o.at(-1);E?.type==="text"?(E.raw+=y.raw,E.text+=y.text):o.push(y);continue}if(c){this.infiniteLoopError(c.charCodeAt(0));break}}return o}infiniteLoopError(c){let o="Infinite loop on byte: "+c;if(this.options.silent)console.error(o);else throw new Error(o)}},oc=class{options;parser;constructor(s){this.options=s||Da}space(s){return""}code({text:s,lang:c,escaped:o}){let r=(c||"").match(ae.notSpaceStart)?.[0],d=s?s.replace(ae.endingNewline,"")+`
+`:"";return r?''+(o?d:je(d,!0))+`
+`:""+(o?d:je(d,!0))+`
+`}blockquote({tokens:s}){return`
+${this.parser.parse(s)}
+`}html({text:s}){return s}def(s){return""}heading({tokens:s,depth:c}){return`${this.parser.parseInline(s)}
+`}hr(s){return`
+`}list(s){let c=s.ordered,o=s.start,r="";for(let v=0;v
+`+r+""+d+`>
+`}listitem(s){return`${this.parser.parse(s.tokens)}
+`}checkbox({checked:s}){return" '}paragraph({tokens:s}){return`${this.parser.parseInline(s)}
+`}table(s){let c="",o="";for(let d=0;d${r}`),`
+`}tablerow({text:s}){return`
+${s}
+`}tablecell(s){let c=this.parser.parseInline(s.tokens),o=s.header?"th":"td";return(s.align?`<${o} align="${s.align}">`:`<${o}>`)+c+`${o}>
+`}strong({tokens:s}){return`${this.parser.parseInline(s)} `}em({tokens:s}){return`${this.parser.parseInline(s)} `}codespan({text:s}){return`${je(s,!0)}`}br(s){return" "}del({tokens:s}){return`${this.parser.parseInline(s)}`}link({href:s,title:c,text:o,tokens:r,autolink:d}){let m=d?je(o,!0):this.parser.parseInline(r),v=ug(s);if(v===null)return m;s=je(v,d);let y='"+m+" ",y}image({href:s,title:c,text:o,tokens:r}){r&&(o=this.parser.parseInline(r,this.parser.textRenderer));let d=ug(s);if(d===null)return je(o);s=d;let m=` ",m}text(s){return"tokens"in s&&s.tokens?this.parser.parseInline(s.tokens):"escaped"in s&&s.escaped?s.text:je(s.text)}},vr=class{strong({text:s}){return s}em({text:s}){return s}codespan({text:s}){return s}del({text:s}){return s}html({text:s}){return s}text({text:s}){return s}link({text:s}){return""+s}image({text:s}){return""+s}br(){return""}checkbox({raw:s}){return s}},Ke=class nr{options;renderer;textRenderer;constructor(c){this.options=c||Da,this.options.renderer=this.options.renderer||new oc,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new vr}static parse(c,o){return new nr(o).parse(c)}static parseInline(c,o){return new nr(o).parseInline(c)}parse(c){this.renderer.parser=this;let o="";for(let r=0;r{let v=d[m].flat(1/0);o=o.concat(this.walkTokens(v,c))}):d.tokens&&(o=o.concat(this.walkTokens(d.tokens,c)))}}return o}use(...s){let c=this.defaults.extensions||{renderers:{},childTokens:{}};return s.forEach(o=>{let r={...o};if(r.async=this.defaults.async||r.async||!1,o.extensions&&(o.extensions.forEach(d=>{if(!d.name)throw new Error("extension name required");if("renderer"in d){let m=c.renderers[d.name];m?c.renderers[d.name]=function(...v){let y=d.renderer.apply(this,v);return y===!1&&(y=m.apply(this,v)),y}:c.renderers[d.name]=d.renderer}if("tokenizer"in d){if(!d.level||d.level!=="block"&&d.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let m=c[d.level];m?m.unshift(d.tokenizer):c[d.level]=[d.tokenizer],d.start&&(d.level==="block"?c.startBlock?c.startBlock.push(d.start):c.startBlock=[d.start]:d.level==="inline"&&(c.startInline?c.startInline.push(d.start):c.startInline=[d.start]))}"childTokens"in d&&d.childTokens&&(c.childTokens[d.name]=d.childTokens)}),r.extensions=c),o.renderer){let d=this.defaults.renderer||new oc(this.defaults);for(let m in o.renderer){if(!(m in d))throw new Error(`renderer '${m}' does not exist`);if(["options","parser"].includes(m))continue;let v=m,y=o.renderer[v],j=d[v];d[v]=(...E)=>{let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O||""}}r.renderer=d}if(o.tokenizer){let d=this.defaults.tokenizer||new rc(this.defaults);for(let m in o.tokenizer){if(!(m in d))throw new Error(`tokenizer '${m}' does not exist`);if(["options","rules","lexer"].includes(m))continue;let v=m,y=o.tokenizer[v],j=d[v];d[v]=(...E)=>{let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O}}r.tokenizer=d}if(o.hooks){let d=this.defaults.hooks||new Nu;for(let m in o.hooks){if(!(m in d))throw new Error(`hook '${m}' does not exist`);if(["options","block"].includes(m))continue;let v=m,y=o.hooks[v],j=d[v];Nu.passThroughHooks.has(m)?d[v]=E=>{if(this.defaults.async&&Nu.passThroughHooksRespectAsync.has(m))return(async()=>{let b=await y.call(d,E);return j.call(d,b)})();let O=y.call(d,E);return j.call(d,O)}:d[v]=(...E)=>{if(this.defaults.async)return(async()=>{let b=await y.apply(d,E);return b===!1&&(b=await j.apply(d,E)),b})();let O=y.apply(d,E);return O===!1&&(O=j.apply(d,E)),O}}r.hooks=d}if(o.walkTokens){let d=this.defaults.walkTokens,m=o.walkTokens;r.walkTokens=function(v){let y=[];return y.push(m.call(this,v)),d&&(y=y.concat(d.call(this,v))),y}}this.defaults={...this.defaults,...r}}),this}setOptions(s){return this.defaults={...this.defaults,...s},this}lexer(s,c){return Ve.lex(s,c??this.defaults)}parser(s,c){return Ke.parse(s,c??this.defaults)}parseMarkdown(s){return(c,o)=>{let r={...o},d={...this.defaults,...r},m=this.onError(!!d.silent,!!d.async);if(this.defaults.async===!0&&r.async===!1)return m(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof c>"u"||c===null)return m(new Error("marked(): input parameter is undefined or null"));if(typeof c!="string")return m(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(c)+", string expected"));if(d.hooks&&(d.hooks.options=d,d.hooks.block=s),d.async)return(async()=>{let v=d.hooks?await d.hooks.preprocess(c):c,y=await(d.hooks?await d.hooks.provideLexer(s):s?Ve.lex:Ve.lexInline)(v,d),j=d.hooks?await d.hooks.processAllTokens(y):y;d.walkTokens&&await Promise.all(this.walkTokens(j,d.walkTokens));let E=await(d.hooks?await d.hooks.provideParser(s):s?Ke.parse:Ke.parseInline)(j,d);return d.hooks?await d.hooks.postprocess(E):E})().catch(m);try{d.hooks&&(c=d.hooks.preprocess(c));let v=(d.hooks?d.hooks.provideLexer(s):s?Ve.lex:Ve.lexInline)(c,d);d.hooks&&(v=d.hooks.processAllTokens(v)),d.walkTokens&&this.walkTokens(v,d.walkTokens);let y=(d.hooks?d.hooks.provideParser(s):s?Ke.parse:Ke.parseInline)(v,d);return d.hooks&&(y=d.hooks.postprocess(y)),y}catch(v){return m(v)}}}onError(s,c){return o=>{if(o.message+=`
+Please report this to https://github.com/markedjs/marked.`,s){let r="An error occurred:
"+je(o.message+"",!0)+" ";return c?Promise.resolve(r):r}if(c)return Promise.reject(o);throw o}}},Ca=new Cp;function jt(s,c){return Ca.parse(s,c)}jt.options=jt.setOptions=function(s){return Ca.setOptions(s),jt.defaults=Ca.defaults,og(jt.defaults),jt};jt.getDefaults=fr;jt.defaults=Da;function Dp(...s){return Ca.use(...s),jt.defaults=Ca.defaults,og(jt.defaults),jt}jt.use=Dp;jt.walkTokens=function(s,c){return Ca.walkTokens(s,c)};jt.parseInline=Ca.parseInline;jt.Parser=Ke;jt.parser=Ke.parse;jt.Renderer=oc;jt.TextRenderer=vr;jt.Lexer=Ve;jt.lexer=Ve.lex;jt.Tokenizer=rc;jt.Hooks=Nu;jt.parse=jt;jt.options;jt.setOptions;jt.walkTokens;jt.parseInline;Ke.parse;var Mp=Ve.lex;function Up(s){const c=s.trim();if(/^(https?:|mailto:)/i.test(c)||c.startsWith("/")||c.startsWith("#"))return c}function sl(s){return s?s.map((c,o)=>{switch(c.type){case"strong":return f.jsx("strong",{children:sl(c.tokens)},o);case"em":return f.jsx("em",{children:sl(c.tokens)},o);case"del":return f.jsx("del",{children:sl(c.tokens)},o);case"codespan":return f.jsx("code",{children:c.text},o);case"link":{const r=c,d=Up(r.href);return d?f.jsx("a",{href:d,target:"_blank",rel:"noreferrer",children:r.tokens?sl(r.tokens):r.text},o):f.jsx("span",{children:r.text},o)}case"image":{const r=c;return f.jsxs("span",{className:"md-image",children:["[img: ",r.text||r.href,"]"]},o)}case"br":return f.jsx("br",{},o);case"escape":return f.jsx("span",{children:c.text},o);case"html":return f.jsx("code",{children:c.text},o);case"text":{const r=c;return f.jsx("span",{children:r.tokens?sl(r.tokens):r.text},o)}default:return f.jsx("span",{children:"raw"in c?String(c.raw??""):""},o)}}):[]}function ur(s){return s.map((c,o)=>{switch(c.type){case"heading":{const r=c,d=sl(r.tokens);switch(r.depth){case 1:return f.jsx("h2",{children:d},o);case 2:return f.jsx("h3",{children:d},o);case 3:return f.jsx("h4",{children:d},o);default:return f.jsx("h5",{children:d},o)}}case"paragraph":return f.jsx("p",{children:sl(c.tokens)},o);case"code":{const r=c;return f.jsx("pre",{className:"md-code",children:f.jsx("code",{children:r.text})},o)}case"blockquote":return f.jsx("blockquote",{children:ur(c.tokens)},o);case"list":{const r=c,d=r.items.map((m,v)=>f.jsx("li",{children:ur(m.tokens)},v));return r.ordered?f.jsx("ol",{start:r.start||1,children:d},o):f.jsx("ul",{children:d},o)}case"table":{const r=c;return f.jsxs("table",{className:"md-table",children:[f.jsx("thead",{children:f.jsx("tr",{children:r.header.map((d,m)=>f.jsx("th",{children:sl(d.tokens)},m))})}),f.jsx("tbody",{children:r.rows.map((d,m)=>f.jsx("tr",{children:d.map((v,y)=>f.jsx("td",{children:sl(v.tokens)},y))},m))})]},o)}case"hr":return f.jsx("hr",{},o);case"space":return null;case"html":return f.jsx("pre",{className:"md-code",children:f.jsx("code",{children:c.text})},o);case"text":return f.jsx("p",{children:sl([c])},o);default:return f.jsx("pre",{className:"md-code",children:f.jsx("code",{children:"raw"in c?String(c.raw??""):""})},o)}})}function Ou({text:s}){return s.trim()?f.jsx("div",{className:"md",children:ur(Mp(s))}):null}function Hp({d:s}){return f.jsxs("div",{className:`decision-card ${s.status==="resolved"?"resolved":""}`,children:[f.jsxs("div",{children:[f.jsx("span",{className:`badge ${s.status==="open"?"st-awaiting_review":"st-approved"}`,children:s.status})," ",f.jsx("strong",{children:s.question})]}),s.context_md&&f.jsx(Ou,{text:s.context_md}),s.status==="resolved"&&f.jsxs("div",{className:"mono-sm dim",style:{marginTop:4},children:["resolution: ",s.resolution," · by ",s.decided_by," · ",me(s.resolved_at)]})]})}function qp({view:s,currentStage:c,open:o,onToggle:r}){const d=s.stage===c;return f.jsxs("div",{className:"stage-panel",children:[f.jsxs("header",{onClick:r,children:[f.jsx("span",{children:o?"▾":"▸"}),f.jsx("strong",{style:d?{color:"var(--accent)"}:void 0,children:s.stage}),d&&f.jsx("span",{className:"badge st-in_progress",children:"current"}),f.jsxs("span",{className:"counts",children:["artifacts ",s.artifacts.length," · transitions ",s.transitions.length," · decisions ",s.decisions.length]})]}),o&&f.jsxs("div",{className:"body",children:[s.artifacts.length>0&&f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Artifacts"}),s.artifacts.map(m=>f.jsxs("details",{className:"fold",style:{marginBottom:8},children:[f.jsxs("summary",{children:[f.jsx("span",{className:"badge",children:m.kind})," ",m.title," ",f.jsxs("span",{className:"dim mono-sm",children:[m.source_type,":",m.source_ref," · ",me(m.created_at)]})]}),m.content_md?f.jsx(Ou,{text:m.content_md}):f.jsx("div",{className:"dim mono-sm",children:"(无内容)"})]},m.id))]}),s.transitions.length>0&&f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Transitions"}),f.jsxs("table",{className:"settings-table",children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"ts"}),f.jsx("th",{children:"from → to"}),f.jsx("th",{children:"actor"}),f.jsx("th",{children:"approved_by"}),f.jsx("th",{children:"note"})]})}),f.jsx("tbody",{children:s.transitions.map(m=>f.jsxs("tr",{children:[f.jsx("td",{className:"mono-sm",children:me(m.ts)}),f.jsxs("td",{className:"mono-sm",children:[m.from_stage," → ",m.to_stage]}),f.jsx("td",{children:m.actor}),f.jsx("td",{children:m.approved_by}),f.jsx("td",{children:m.note})]},m.id))})]})]}),s.decisions.length>0&&f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Decisions"}),s.decisions.map(m=>f.jsx(Hp,{d:m},m.id))]}),s.artifacts.length===0&&s.transitions.length===0&&s.decisions.length===0&&f.jsx("div",{className:"dim mono-sm",children:"本阶段暂无记录"})]})]})}function wp({task:s,onDone:c}){const[o,r]=U.useState(""),[d,m]=U.useState(""),[v,y]=U.useState(""),[j,E]=U.useState(!1),[O,b]=U.useState(""),[D,V]=U.useState(""),[G,B]=U.useState(!1),$=async H=>{H.preventDefault(),B(!0),V("");try{await Ht.post(`/tasks/${s.id}/stages/${s.stage}/external-submit`,{title:o.trim(),content_md:d,kind:v||void 0,advance:j,note:O||void 0}),r(""),m(""),b(""),c()}catch(mt){V(mt.message)}finally{B(!1)}};return f.jsxs("details",{className:"fold panel",children:[f.jsxs("summary",{children:["外部产物提交(external-submit,当前阶段 ",s.stage,")"]}),D&&f.jsx("div",{className:"error-box",children:D}),f.jsxs("form",{onSubmit:$,children:[f.jsxs("div",{className:"op-row",children:[f.jsxs("label",{style:{flex:1,minWidth:200},children:["title",f.jsx("input",{required:!0,value:o,onChange:H=>r(H.target.value)})]}),f.jsxs("label",{children:["kind",f.jsx("input",{value:v,onChange:H=>y(H.target.value),placeholder:"note",style:{width:120}})]}),f.jsxs("label",{style:{flexDirection:"row",alignItems:"center",gap:6},children:[f.jsx("input",{type:"checkbox",checked:j,onChange:H=>E(H.target.checked)}),"提交后推进"]})]}),f.jsx("textarea",{rows:6,required:!0,value:d,onChange:H=>m(H.target.value),placeholder:"content_md(markdown)"}),j&&f.jsxs("div",{style:{marginTop:6},children:[f.jsx("label",{className:"dim mono-sm",children:"note(推进备注)"}),f.jsx("input",{style:{width:"100%"},value:O,onChange:H=>b(H.target.value)})]}),f.jsx("div",{className:"op-row",style:{marginTop:8},children:f.jsx("button",{className:"primary",type:"submit",disabled:G,children:"提交"})})]})]})}function kp({id:s}){const[c,o]=U.useState(null),[r,d]=U.useState(null),[m,v]=U.useState({}),[y,j]=U.useState(""),[E,O]=U.useState(""),[b,D]=U.useState(""),[V,G]=U.useState(""),B=U.useCallback(()=>{Promise.all([Ht.get(`/tasks/${s}`),Ht.get(`/tasks/${s}/pipeline`)]).then(([q,et])=>{o(q),d(et),j(q.assigned_agent),v(Q=>Object.keys(Q).length===0?{[q.stage]:!0}:Q),D("")}).catch(q=>{q.message!=="unauthorized"&&D(q.message)})},[s]);U.useEffect(()=>{B()},[B]);const $=async(q,et)=>{D(""),G("");try{await q(),G(et),O(""),B()}catch(Q){D(Q.message)}};if(!c||!r)return f.jsxs("div",{children:[f.jsx("div",{className:"page-head",children:f.jsx("h2",{children:"任务详情"})}),b?f.jsx("div",{className:"error-box",children:b}):f.jsx("div",{className:"dim",children:"加载中…"})]});const H=zn.indexOf(c.stage),mt=c.stage_state==="awaiting_review",qt=c.status==="done"||c.status==="cancelled";return f.jsxs("div",{children:[f.jsxs("div",{className:"page-head",children:[f.jsx("a",{href:"#/board",className:"mono-sm",children:"← 看板"}),f.jsx("h2",{children:c.title}),f.jsx("span",{className:"dim mono-sm",children:c.slug}),f.jsx("span",{className:`badge st-${c.stage_state}`,children:c.stage_state}),f.jsx("span",{className:`badge status-${c.status}`,children:c.status}),f.jsxs("span",{className:"badge",children:["P",c.priority]}),f.jsx("span",{className:"badge",children:c.kind})]}),b&&f.jsx("div",{className:"error-box",children:b}),V&&f.jsx("div",{className:"panel mono-sm",style:{borderColor:"var(--green)",color:"var(--green)"},children:V}),f.jsx("div",{className:"stepper",children:zn.map((q,et)=>{const Q=c.status==="done"||etv(ot=>({...ot,[q]:!ot[q]})),children:[Q&&f.jsx("span",{className:"check",children:"✓"}),q]},q)})}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"操作"}),f.jsxs("div",{className:"op-row",children:[f.jsxs("label",{children:["assign agent",f.jsx("input",{value:y,onChange:q=>j(q.target.value),placeholder:"agent 名",style:{width:140}})]}),f.jsx("button",{disabled:!y.trim()||qt,onClick:()=>$(()=>Ht.patch(`/tasks/${c.id}`,{assign:y.trim()}),`已指派给 ${y.trim()}`),children:"指派"}),f.jsx("span",{style:{width:16}}),f.jsxs("label",{children:["note",f.jsx("input",{value:E,onChange:q=>O(q.target.value),placeholder:"审批备注",style:{width:260}})]}),f.jsx("button",{className:"primary",disabled:!mt,title:mt?"":"仅 awaiting_review 可推进",onClick:()=>$(()=>Ht.post(`/tasks/${c.id}/stages/advance`,{note:E}),"已推进"),children:"批准推进"}),f.jsx("button",{className:"danger",disabled:!mt,title:mt?"":"仅 awaiting_review 可退回",onClick:()=>$(()=>Ht.post(`/tasks/${c.id}/stages/send-back`,{note:E}),"已退回 changes_requested"),children:"退回修改"})]}),f.jsxs("div",{className:"dim mono-sm",children:["assigned: ",c.assigned_agent||"(none)"," · heartbeat ",me(c.heartbeat_at)," · lease ",me(c.lease_expires_at)]})]}),!qt&&f.jsx(wp,{task:c,onDone:B}),c.instruction_md&&f.jsxs("details",{className:"fold panel",children:[f.jsx("summary",{children:"任务指令(instruction_md)"}),f.jsx(Ou,{text:c.instruction_md})]}),f.jsx("div",{children:r.stages.map(q=>f.jsx(qp,{view:q,currentStage:r.stage,open:!!m[q.stage],onToggle:()=>v(et=>({...et,[q.stage]:!et[q.stage]}))},q.stage))}),f.jsxs("div",{className:"dim mono-sm",style:{marginTop:8},children:["created ",me(c.created_at)," · updated ",me(c.updated_at)," ·"," ",f.jsx("a",{href:"#/board",onClick:q=>{q.preventDefault(),na("/board")},children:"返回看板"})]})]})}function Bp({d:s,onResolved:c}){const[o,r]=U.useState(""),[d,m]=U.useState(""),[v,y]=U.useState(!1),j=async E=>{y(!0),m("");try{await Ht.post(`/decisions/${s.id}/resolve`,E),c()}catch(O){m(O.message),y(!1)}};return f.jsxs("div",{className:"decision-card",children:[f.jsxs("div",{style:{marginBottom:6},children:[f.jsx("a",{href:`#/tasks/${s.task_id}`,onClick:E=>{E.preventDefault(),na(`/tasks/${s.task_id}`)},children:s.task_slug})," ",f.jsx("span",{className:"dim",children:s.task_title})," ",f.jsx("span",{className:"badge",children:s.stage})," ",f.jsx("span",{className:"dim mono-sm",children:me(s.created_at)})]}),f.jsx("div",{style:{fontWeight:600,marginBottom:6},children:s.question}),s.context_md&&f.jsx(Ou,{text:s.context_md}),d&&f.jsx("div",{className:"error-box",children:d}),f.jsx("div",{style:{marginTop:8},children:s.suggestions.map((E,O)=>f.jsxs("div",{className:"suggestion",children:[f.jsxs("div",{className:"opt",children:["建议 ",O+1,": ",E.option,f.jsxs("button",{style:{marginLeft:10},disabled:v,onClick:()=>j({suggestion_index:O}),children:["采纳建议 ",O+1]})]}),f.jsxs("div",{className:"why",children:["理由: ",E.rationale]}),f.jsxs("div",{className:"why",children:["影响: ",E.impact]})]},O))}),f.jsxs("div",{className:"op-row",style:{marginTop:8},children:[f.jsxs("label",{style:{flex:1,minWidth:260},children:["自定义 resolution",f.jsx("input",{style:{width:"100%"},value:o,onChange:E=>r(E.target.value)})]}),f.jsx("button",{className:"primary",disabled:v||!o.trim(),onClick:()=>j({resolution:o.trim()}),children:"提交裁决"})]})]})}function Yp(){const[s,c]=U.useState([]),[o,r]=U.useState(null),[d,m]=U.useState(!1),[v,y]=U.useState(""),j=U.useCallback(()=>{Ht.get("/decisions?status=open").then(E=>{c(E),y("")}).catch(E=>{E.message!=="unauthorized"&&y(E.message)})},[]);return U.useEffect(()=>{j()},[j]),U.useEffect(()=>{!d||o!==null||Ht.get("/decisions?status=resolved").then(r).catch(()=>{})},[d,o]),f.jsxs("div",{children:[f.jsxs("div",{className:"page-head",children:[f.jsx("h2",{children:"决策收件箱"}),f.jsxs("span",{className:`badge ${s.length>0?"st-awaiting_review":""}`,children:[s.length," open"]}),f.jsx("div",{className:"spacer"}),f.jsx("button",{onClick:j,children:"刷新"})]}),v&&f.jsx("div",{className:"error-box",children:v}),s.length===0&&f.jsx("div",{className:"panel dim",children:"没有待裁决的决策。"}),s.map(E=>f.jsx(Bp,{d:E,onResolved:j},E.id)),f.jsxs("details",{className:"fold",style:{marginTop:16},onToggle:E=>m(E.target.open),children:[f.jsxs("summary",{children:["已解决(",o?.length??"…",")"]}),(o??[]).map(E=>f.jsxs("div",{className:"decision-card resolved",children:[f.jsxs("div",{children:[f.jsx("span",{className:"dim",children:E.task_slug})," ",f.jsx("strong",{children:E.question})]}),f.jsxs("div",{className:"mono-sm dim",style:{marginTop:4},children:["resolution: ",E.resolution," · by ",E.decided_by," · ",me(E.resolved_at)]})]},E.id)),d&&o!==null&&o.length===0&&f.jsx("div",{className:"dim mono-sm",children:"暂无已解决决策"})]})]})}function Gp(){const[s,c]=U.useState([]),[o,r]=U.useState(""),[d,m]=U.useState(""),[v,y]=U.useState(null),[j,E]=U.useState(""),[O,b]=U.useState("hybrid"),[D,V]=U.useState(null),[G,B]=U.useState(""),$=(q,et)=>{Ht.get(`/docs${er({taxonomy:q,q:et})}`).then(Q=>c(Q.items)).catch(Q=>{Q.message!=="unauthorized"&&B(Q.message)})};U.useEffect(()=>{$(o,d)},[o,d]);const H=U.useMemo(()=>{const q=new Map;for(const et of s)q.set(et.taxonomy,(q.get(et.taxonomy)??0)+1);return[...q.entries()].sort((et,Q)=>et[0].localeCompare(Q[0]))},[s]),mt=async q=>{if(q.preventDefault(),!!j.trim()){B("");try{const et=await Ht.get(`/docs/search${er({q:j.trim(),mode:O,limit:"20"})}`);V(et)}catch(et){B(et.message)}}},qt=q=>{Ht.get(`/docs/${q}`).then(y).catch(et=>B(et.message))};return f.jsxs("div",{children:[f.jsx("div",{className:"page-head",children:f.jsx("h2",{children:"文档库"})}),G&&f.jsx("div",{className:"error-box",children:G}),f.jsx("div",{className:"panel",children:f.jsxs("form",{className:"filters",onSubmit:mt,children:[f.jsx("input",{style:{flex:1,minWidth:240},placeholder:"搜索文档与阶段产物…",value:j,onChange:q=>E(q.target.value)}),f.jsxs("select",{value:O,onChange:q=>b(q.target.value),children:[f.jsx("option",{value:"hybrid",children:"hybrid"}),f.jsx("option",{value:"semantic",children:"semantic"}),f.jsx("option",{value:"keyword",children:"keyword"})]}),f.jsx("button",{className:"primary",type:"submit",children:"搜索"})]})}),D&&f.jsxs("div",{className:"panel",children:[f.jsxs("h3",{children:["搜索结果 · ",D.mode," · ",D.count," 条",D.degraded&&f.jsx("span",{className:"badge st-awaiting_review",style:{marginLeft:8},children:"degraded:语义检索不可用,已回落关键词"})]}),D.results.map((q,et)=>f.jsxs("div",{className:"hit",children:[f.jsxs("div",{children:[f.jsx("span",{className:"score",children:q.score.toFixed(3)})," ",q.heading&&f.jsxs("strong",{children:[q.heading," "]}),f.jsx("span",{className:"dim mono-sm",children:q.source.type==="doc"?`doc: ${q.source.path} (${q.source.title})`:`artifact: ${q.source.task_slug} / ${q.source.stage} (${q.source.title})`}),q.doc_id&&f.jsxs(f.Fragment,{children:[" ",f.jsx("a",{href:"#/docs",onClick:Q=>{Q.preventDefault(),qt(q.doc_id)},children:"查看文档"})]})]}),f.jsx("div",{className:"snippet",children:q.snippet})]},et)),D.count===0&&f.jsx("div",{className:"dim mono-sm",children:"无结果"})]}),f.jsxs("div",{className:"docs-layout",children:[f.jsx("div",{className:"docs-side",children:f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"浏览"}),f.jsx("input",{style:{width:"100%",marginBottom:8},placeholder:"过滤 path/title",value:d,onChange:q=>m(q.target.value)}),f.jsxs("div",{className:`tax-name ${o===""?"active":""}`,style:{cursor:"pointer",color:o===""?"var(--accent)":void 0,marginBottom:6},onClick:()=>r(""),children:["全部 (",s.length,")"]}),H.map(([q,et])=>f.jsxs("div",{className:"tax-group",children:[f.jsxs("div",{className:"tax-name",onClick:()=>r(q===o?"":q),children:[q||"(no taxonomy)"," (",et,")"]}),o===q&&s.filter(Q=>Q.taxonomy===q).map(Q=>f.jsx("div",{className:`doc-item ${v?.id===Q.id?"active":""}`,onClick:()=>qt(Q.id),title:Q.path,children:Q.title||Q.path},Q.id))]},q||"(none)")),o===""&&s.slice(0,80).map(q=>f.jsx("div",{className:`doc-item ${v?.id===q.id?"active":""}`,onClick:()=>qt(q.id),title:q.path,children:q.title||q.path},q.id))]})}),f.jsx("div",{className:"docs-main",children:v?f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:v.title||v.path}),f.jsx("table",{className:"settings-table",style:{marginBottom:10},children:f.jsxs("tbody",{children:[f.jsxs("tr",{children:[f.jsx("th",{children:"path"}),f.jsx("td",{className:"mono-sm",children:v.path})]}),f.jsxs("tr",{children:[f.jsx("th",{children:"taxonomy"}),f.jsx("td",{children:v.taxonomy})]}),f.jsxs("tr",{children:[f.jsx("th",{children:"chunks"}),f.jsx("td",{children:v.chunks})]}),f.jsxs("tr",{children:[f.jsx("th",{children:"synced_at"}),f.jsx("td",{className:"mono-sm",children:me(v.synced_at)})]})]})}),f.jsx("h3",{children:"Front Matter"}),f.jsx("pre",{className:"md-code",children:f.jsx("code",{children:JSON.stringify(v.frontmatter,null,2)})})]}):f.jsx("div",{className:"panel dim",children:"点击左侧文档查看详情,或使用上方搜索。"})})]})]})}const Qp=["agent","human","external"];function Xp(){const[s,c]=U.useState({}),[o,r]=U.useState(""),[d,m]=U.useState(""),[v,y]=U.useState(!1);U.useEffect(()=>{Ht.get("/stage-settings").then(E=>{const O={};for(const b of zn){const D=E.find(V=>V.stage===b);O[b]={model:D?.model??"",executor:D?.executor??"agent"}}c(O)}).catch(E=>{E.message!=="unauthorized"&&r(E.message)})},[]);const j=async()=>{y(!0),r(""),m("");try{await Ht.put("/stage-settings",{settings:s}),m("已保存全局阶段设置")}catch(E){r(E.message)}finally{y(!1)}};return f.jsxs("div",{children:[f.jsx("div",{className:"page-head",children:f.jsx("h2",{children:"设置"})}),o&&f.jsx("div",{className:"error-box",children:o}),d&&f.jsx("div",{className:"panel mono-sm",style:{borderColor:"var(--green)",color:"var(--green)"},children:d}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"全局阶段设置(stage → model / executor)"}),f.jsxs("table",{className:"settings-table",children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"stage"}),f.jsx("th",{children:"model"}),f.jsx("th",{children:"executor"})]})}),f.jsx("tbody",{children:zn.map(E=>f.jsxs("tr",{children:[f.jsx("td",{children:E}),f.jsx("td",{children:f.jsx("input",{value:s[E]?.model??"",placeholder:"(默认模型)",onChange:O=>c(b=>({...b,[E]:{model:O.target.value,executor:b[E]?.executor??"agent"}}))})}),f.jsx("td",{children:f.jsx("select",{value:s[E]?.executor??"agent",onChange:O=>c(b=>({...b,[E]:{model:b[E]?.model??"",executor:O.target.value}})),children:Qp.map(O=>f.jsx("option",{value:O,children:O},O))})})]},E))})]}),f.jsx("div",{className:"op-row",style:{marginTop:10},children:f.jsx("button",{className:"primary",disabled:v,onClick:j,children:"保存"})}),f.jsx("div",{className:"dim mono-sm",style:{marginTop:6},children:"executor=human/external 的阶段不会派发给 agent;任务级覆盖可通过 API PUT /api/v1/stage-settings?task_id= 设置。"})]}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Agent 接入"}),f.jsxs("div",{className:"dim mono-sm",children:["agent token 通过 ",f.jsx("code",{children:"scripts/control-center.sh register-agent -name [-kind ]"})," 注册(plaintext token 只显示一次)。 agent 使用 Bearer token 调用 ",f.jsx("code",{children:"/api/v1/agent/*"})," 路由认领任务、上报事件与产物;本控制台不使用 agent 路由。"]})]})]})}function Zp(s){if(!s.finished_at)return"-";const c=new Date(s.finished_at).getTime()-new Date(s.started_at).getTime();return Number.isNaN(c)?"-":`${(c/1e3).toFixed(1)}s`}function Lp({f:s,onChanged:c}){const[o,r]=U.useState(!1),[d,m]=U.useState(!1),[v,y]=U.useState(""),j=async E=>{m(!0),y("");try{await Ht.post(`/audits/findings/${s.id}/${E}`),c()}catch(O){y(O.message),m(!1)}};return f.jsxs("div",{className:`finding-card sev-${s.severity}`,children:[f.jsxs("div",{className:"f-head",onClick:()=>r(!o),children:[f.jsx("span",{className:`badge sev-${s.severity}`,children:s.severity}),f.jsx("span",{className:"badge",children:s.kind}),f.jsx("span",{className:"f-title",children:s.title}),f.jsx("span",{className:"dim mono-sm",children:me(s.created_at)}),f.jsx("span",{className:"dim mono-sm",children:o?"▾":"▸"})]}),o&&f.jsxs("div",{className:"f-body",children:[f.jsx(Ou,{text:s.detail_md}),s.refs.length>0&&f.jsxs("div",{className:"f-refs",children:["refs: ",s.refs.join(" · ")]}),f.jsxs("div",{className:"f-refs",children:["run #",s.run_id," · ",me(s.run_started_at),s.task_id&&f.jsxs(f.Fragment,{children:[" · 已转任务 ",f.jsx("a",{href:`#/tasks/${s.task_id}`,onClick:E=>{E.preventDefault(),na(`/tasks/${s.task_id}`)},children:s.task_id.slice(0,8)})]})]}),v&&f.jsx("div",{className:"error-box",children:v}),s.status==="open"&&f.jsxs("div",{className:"f-actions",onClick:E=>E.stopPropagation(),children:[f.jsx("button",{className:"primary",disabled:d,onClick:()=>j("convert"),children:"转任务"}),f.jsx("button",{disabled:d,onClick:()=>j("dismiss"),children:"忽略"})]})]})]})}function Vp(){const[s,c]=U.useState([]),[o,r]=U.useState([]),[d,m]=U.useState("open"),[v,y]=U.useState(""),[j,E]=U.useState(""),[O,b]=U.useState(!1),D=U.useCallback(()=>{Ht.get("/audits/runs?limit=20").then(c).catch(()=>{})},[]),V=U.useCallback(()=>{Ht.get(`/audits/findings?status=${d}${v?`&severity=${v}`:""}&limit=100`).then(H=>{r(H),E("")}).catch(H=>{H.message!=="unauthorized"&&E(H.message)})},[d,v]),G=U.useCallback(()=>{D(),V()},[D,V]);U.useEffect(()=>{G()},[G]),U.useEffect(()=>{if(!s.some(mt=>mt.status==="running"))return;const H=setInterval(G,3e3);return()=>clearInterval(H)},[s,G]);const B=async()=>{b(!0),E("");try{await Ht.post("/audits/run"),D()}catch(H){E(H.message)}finally{b(!1)}},$=s.some(H=>H.status==="running");return f.jsxs("div",{children:[f.jsxs("div",{className:"page-head",children:[f.jsx("h2",{children:"审计"}),f.jsxs("span",{className:"badge",children:[o.length," ",d]}),f.jsx("div",{className:"spacer"}),f.jsx("button",{className:"primary",disabled:O||$,onClick:B,children:$?"审查进行中…":"立即运行"}),f.jsx("button",{onClick:G,children:"刷新"})]}),j&&f.jsx("div",{className:"error-box",children:j}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"运行历史"}),s.length===0?f.jsx("div",{className:"dim mono-sm",children:"暂无审查记录。点击「立即运行」触发一次审查。"}):f.jsxs("table",{className:"runs-table",children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"#"}),f.jsx("th",{children:"kind"}),f.jsx("th",{children:"状态"}),f.jsx("th",{children:"开始"}),f.jsx("th",{children:"耗时"}),f.jsx("th",{children:"findings"}),f.jsx("th",{children:"summary"})]})}),f.jsx("tbody",{children:s.map(H=>f.jsxs("tr",{children:[f.jsx("td",{children:H.id}),f.jsx("td",{children:H.kind}),f.jsx("td",{children:f.jsx("span",{className:`badge ${H.status==="failed"?"sev-critical":H.status==="running"?"st-in_progress":"status-done"}`,children:H.status})}),f.jsx("td",{children:me(H.started_at)}),f.jsx("td",{children:Zp(H)}),f.jsx("td",{children:H.findings}),f.jsx("td",{children:f.jsx("span",{className:"summary",children:H.error||H.summary})})]},H.id))})]})]}),f.jsxs("div",{className:"panel",children:[f.jsx("h3",{children:"Findings"}),f.jsxs("div",{className:"filters",style:{marginBottom:10},children:[["open","converted","dismissed"].map(H=>f.jsx("button",{className:d===H?"primary":"",onClick:()=>m(H),children:H},H)),f.jsx("span",{className:"dim mono-sm",children:"severity:"}),f.jsxs("select",{value:v,onChange:H=>y(H.target.value),children:[f.jsx("option",{value:"",children:"全部"}),f.jsx("option",{value:"critical",children:"critical"}),f.jsx("option",{value:"high",children:"high"}),f.jsx("option",{value:"medium",children:"medium"}),f.jsx("option",{value:"low",children:"low"})]})]}),o.length===0?f.jsx("div",{className:"dim mono-sm",children:"当前过滤条件下没有 findings。"}):o.map(H=>f.jsx(Lp,{f:H,onChanged:G},H.id))]})]})}const Kp=[{path:"/",label:"总览"},{path:"/board",label:"看板"},{path:"/decisions",label:"决策收件箱"},{path:"/docs",label:"文档库"},{path:"/settings",label:"设置"},{path:"/audit",label:"审计"}];function Jp({onLogin:s}){const[c,o]=U.useState(""),r=d=>{d.preventDefault(),c.trim()&&(sr(c.trim()),s())};return f.jsx("div",{className:"login-wrap",children:f.jsxs("div",{className:"panel login-box",children:[f.jsx("h3",{children:"Control Center"}),f.jsxs("form",{onSubmit:r,children:[f.jsx("label",{className:"dim mono-sm",htmlFor:"token",children:"Console Token"}),f.jsx("input",{id:"token",type:"password",autoFocus:!0,value:c,onChange:d=>o(d.target.value),placeholder:"CC_CONSOLE_TOKEN"}),f.jsx("button",{className:"primary",type:"submit",children:"进入"}),f.jsx("span",{className:"dim mono-sm",children:"token 存于 localStorage,401 时自动清除。"})]})]})})}function $p({path:s}){const c=s.match(/^\/tasks\/([^/]+)$/);if(c)return f.jsx(kp,{id:c[1]});switch(s){case"/":return f.jsx(tg,{});case"/board":return f.jsx(Dy,{});case"/decisions":return f.jsx(Yp,{});case"/docs":return f.jsx(Gp,{});case"/settings":return f.jsx(Xp,{});case"/audit":return f.jsx(Vp,{});default:return f.jsx(tg,{})}}function Fp(){const[s,c]=U.useState(()=>cr()!==""),o=jy();if(U.useEffect(()=>{zy(()=>c(!1))},[]),!s)return f.jsx(Jp,{onLogin:()=>c(!0)});const r=o.startsWith("/tasks/")||o==="/board"?"/board":o;return f.jsxs("div",{className:"layout",children:[f.jsxs("nav",{className:"sidebar",children:[f.jsx("h1",{children:"Control Center"}),Kp.map(d=>f.jsx("a",{href:`#${d.path}`,className:r===d.path?"active":"",children:d.label},d.path)),f.jsx("div",{style:{marginTop:16,padding:"0 8px"},children:f.jsx("button",{className:"mono-sm",onClick:()=>{sr(""),c(!1),na("/")},children:"退出登录"})})]}),f.jsx("main",{className:"main",children:f.jsx($p,{path:o})})]})}Ny.createRoot(document.getElementById("root")).render(f.jsx(Fp,{}));
diff --git a/internal/controlcenter/webui/dist/assets/index-DyNgdwvP.css b/internal/controlcenter/webui/dist/assets/index-DyNgdwvP.css
new file mode 100644
index 00000000..8c9b3950
--- /dev/null
+++ b/internal/controlcenter/webui/dist/assets/index-DyNgdwvP.css
@@ -0,0 +1 @@
+:root{--bg: #0d1117;--bg-panel: #161b22;--bg-hover: #1c2330;--border: #2b3442;--fg: #d6dde6;--fg-dim: #8b97a7;--accent: #4f9cf9;--green: #3fb950;--red: #f85149;--yellow: #d29922;--purple: #bc8cff;--cyan: #39c5cf;font-size:14px}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font-family:SF Mono,Cascadia Code,Menlo,Consolas,PingFang SC,Microsoft YaHei,monospace}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button{background:var(--bg-hover);color:var(--fg);border:1px solid var(--border);border-radius:4px;padding:4px 10px;font:inherit;cursor:pointer}button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}button:disabled{opacity:.4;cursor:not-allowed}button.primary{background:var(--accent);border-color:var(--accent);color:#0d1117;font-weight:600}button.primary:hover:not(:disabled){color:#0d1117;filter:brightness(1.15)}button.danger{border-color:var(--red);color:var(--red)}input,select,textarea{background:var(--bg);color:var(--fg);border:1px solid var(--border);border-radius:4px;padding:4px 8px;font:inherit}input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent)}textarea{width:100%;resize:vertical}.layout{display:flex;min-height:100vh}.sidebar{width:180px;flex:0 0 180px;background:var(--bg-panel);border-right:1px solid var(--border);padding:12px 8px;position:sticky;top:0;height:100vh}.sidebar h1{font-size:13px;letter-spacing:1px;color:var(--fg-dim);margin:4px 8px 14px;text-transform:uppercase}.sidebar a{display:block;padding:6px 10px;border-radius:4px;color:var(--fg);margin-bottom:2px}.sidebar a:hover{background:var(--bg-hover);text-decoration:none}.sidebar a.active{background:var(--bg-hover);color:var(--accent);border-left:2px solid var(--accent)}.main{flex:1;padding:16px 20px;min-width:0}.page-head{display:flex;align-items:center;gap:12px;margin-bottom:14px;flex-wrap:wrap}.page-head h2{margin:0;font-size:16px}.page-head .spacer{flex:1}.panel{background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:12px;margin-bottom:14px}.panel h3{margin:0 0 10px;font-size:13px;color:var(--fg-dim);text-transform:uppercase;letter-spacing:1px}.error-box{background:#f851491a;border:1px solid var(--red);border-radius:4px;color:var(--red);padding:8px 12px;margin-bottom:12px;white-space:pre-wrap}.dim{color:var(--fg-dim)}.mono-sm{font-size:12px}.login-wrap{display:flex;align-items:center;justify-content:center;min-height:100vh}.login-box{width:380px}.login-box form{display:flex;flex-direction:column;gap:10px}.badge{display:inline-block;padding:1px 7px;border-radius:10px;font-size:11px;border:1px solid var(--border);color:var(--fg-dim);white-space:nowrap}.badge.st-idle{color:var(--fg-dim)}.badge.st-assigned{color:var(--cyan);border-color:var(--cyan)}.badge.st-in_progress{color:var(--accent);border-color:var(--accent)}.badge.st-awaiting_review{color:var(--yellow);border-color:var(--yellow)}.badge.st-changes_requested{color:var(--red);border-color:var(--red)}.badge.st-approved{color:var(--green);border-color:var(--green)}.badge.status-blocked_pending_decision{color:var(--purple);border-color:var(--purple)}.badge.status-done{color:var(--green);border-color:var(--green)}.badge.status-in_progress{color:var(--accent);border-color:var(--accent)}.badge.status-cancelled,.badge.sev-low{color:var(--fg-dim)}.badge.sev-medium{color:var(--accent);border-color:var(--accent)}.badge.sev-high{color:var(--yellow);border-color:var(--yellow)}.badge.sev-critical{color:var(--red);border-color:var(--red)}.finding-card{border:1px solid var(--border);border-radius:6px;padding:10px 12px;margin-bottom:10px;background:var(--bg-panel)}.finding-card.sev-high,.finding-card.sev-critical{border-left:3px solid var(--yellow)}.finding-card.sev-critical{border-left-color:var(--red)}.finding-card .f-head{display:flex;gap:8px;align-items:center;flex-wrap:wrap;cursor:pointer}.finding-card .f-title{font-weight:600}.finding-card .f-body{margin-top:8px;border-top:1px solid var(--border);padding-top:8px}.finding-card .f-refs{font-size:12px;color:var(--fg-dim);margin-top:6px}.finding-card .f-actions{display:flex;gap:8px;margin-top:8px}.runs-table{border-collapse:collapse;width:100%}.runs-table th,.runs-table td{border:1px solid var(--border);padding:5px 8px;text-align:left;font-size:12px}.runs-table th{color:var(--fg-dim);font-weight:500;background:var(--bg-hover)}.runs-table td .summary{color:var(--fg-dim)}.stat-cards{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}.stat-card{background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:10px 16px;min-width:130px;cursor:pointer}.stat-card .num{font-size:26px;font-weight:700}.stat-card .lbl{color:var(--fg-dim);font-size:12px}.stat-card.warn .num{color:var(--yellow)}.stat-card.crit .num{color:var(--red)}.stat-card.ok .num{color:var(--green)}.matrix{border-collapse:collapse;width:100%}.matrix th,.matrix td{border:1px solid var(--border);padding:4px 8px;text-align:center;font-size:12px}.matrix th{color:var(--fg-dim);font-weight:500;background:var(--bg-hover)}.matrix td:first-child,.matrix th:first-child{text-align:left}.matrix td.hot{color:var(--yellow);font-weight:700}.agent-row{display:flex;gap:10px;align-items:center;padding:3px 0}.dot{width:8px;height:8px;border-radius:50%;display:inline-block}.dot.live{background:var(--green)}.dot.stale{background:var(--red)}.event-feed{max-height:300px;overflow-y:auto;font-size:12px}.event-feed .ev{padding:3px 0;border-bottom:1px solid var(--border);display:flex;gap:8px}.event-feed .ev .ts{color:var(--fg-dim);flex:0 0 auto}.event-feed .ev .phase{color:var(--purple);flex:0 0 auto}.board{display:flex;gap:10px;overflow-x:auto;padding-bottom:8px;align-items:flex-start}.lane{flex:0 0 240px;background:var(--bg-panel);border:1px solid var(--border);border-radius:6px;padding:8px}.lane h4{margin:0 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:1px;color:var(--fg-dim);display:flex;justify-content:space-between}.card{background:var(--bg-hover);border:1px solid var(--border);border-radius:4px;padding:8px;margin-bottom:8px;cursor:pointer}.card:hover{border-color:var(--accent)}.card .title{font-weight:600;margin-bottom:4px}.card .meta{display:flex;gap:6px;flex-wrap:wrap;align-items:center;font-size:11px;color:var(--fg-dim)}.stepper{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:14px}.step{flex:1;min-width:90px;text-align:center;padding:6px 4px;border:1px solid var(--border);border-radius:4px;font-size:12px;color:var(--fg-dim);cursor:pointer;background:var(--bg-panel)}.step.done{color:var(--green);border-color:var(--green)}.step.current{color:var(--accent);border-color:var(--accent);background:#4f9cf914;font-weight:700}.step .check{margin-right:4px}.stage-panel{border:1px solid var(--border);border-radius:6px;margin-bottom:8px;background:var(--bg-panel)}.stage-panel>header{padding:8px 12px;cursor:pointer;display:flex;gap:10px;align-items:center}.stage-panel>header:hover{background:var(--bg-hover)}.stage-panel>header .counts{margin-left:auto;font-size:11px;color:var(--fg-dim)}.stage-panel .body{border-top:1px solid var(--border);padding:10px 12px}.op-row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;margin-bottom:10px}.op-row label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--fg-dim)}.md{font-size:13px;line-height:1.55}.md h2,.md h3,.md h4,.md h5{margin:10px 0 6px}.md p{margin:6px 0}.md-code{background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:8px;overflow-x:auto;font-size:12px}.md code{background:var(--bg);border-radius:3px;padding:1px 4px}.md pre.md-code code{padding:0;background:transparent}.md blockquote{border-left:3px solid var(--border);margin:6px 0;padding:2px 10px;color:var(--fg-dim)}.md-table{border-collapse:collapse}.md-table th,.md-table td{border:1px solid var(--border);padding:3px 8px;font-size:12px}.md-image{color:var(--fg-dim)}.decision-card{border:1px solid var(--yellow);border-radius:6px;padding:12px;margin-bottom:12px;background:var(--bg-panel)}.decision-card.resolved{border-color:var(--border)}.suggestion{border:1px solid var(--border);border-radius:4px;padding:8px;margin:6px 0;background:var(--bg-hover)}.suggestion .opt{font-weight:600;margin-bottom:4px}.suggestion .why{font-size:12px;color:var(--fg-dim)}.docs-layout{display:flex;gap:14px;align-items:flex-start}.docs-side{flex:0 0 260px;max-height:75vh;overflow-y:auto}.docs-main{flex:1;min-width:0}.tax-group{margin-bottom:8px}.tax-group>.tax-name{color:var(--accent);cursor:pointer;font-size:12px;text-transform:uppercase;letter-spacing:1px}.doc-item{padding:3px 0 3px 10px;cursor:pointer;font-size:12px}.doc-item:hover,.doc-item.active{color:var(--accent)}.hit{border:1px solid var(--border);border-radius:4px;padding:8px;margin-bottom:8px;background:var(--bg-panel)}.hit .snippet{font-size:12px;color:var(--fg-dim);margin-top:4px;white-space:pre-wrap}.hit .score{color:var(--green);font-size:11px}.settings-table{border-collapse:collapse;width:100%}.settings-table th,.settings-table td{border:1px solid var(--border);padding:6px 8px;text-align:left}.settings-table th{color:var(--fg-dim);font-weight:500;background:var(--bg-hover)}.filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap}details.fold>summary{cursor:pointer;color:var(--fg-dim);margin-bottom:8px}
diff --git a/internal/controlcenter/webui/dist/index.html b/internal/controlcenter/webui/dist/index.html
index dd2bcfbf..47d4fe08 100644
--- a/internal/controlcenter/webui/dist/index.html
+++ b/internal/controlcenter/webui/dist/index.html
@@ -4,8 +4,8 @@
Control Center
-
-
+
+