neondeck 1.0.0-beta.6 → 1.0.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/config/dashboard.json +7 -1
  3. package/dist/assets/{app-CYRclf6Z.js → app-kQMyZcgk.js} +260 -19
  4. package/dist/assets/app-kQMyZcgk.js.map +1 -0
  5. package/dist/assets/{autopilot-CuVDqfcB.js → autopilot-BB7mZq1T.js} +31410 -30682
  6. package/dist/assets/autopilot-BB7mZq1T.js.map +1 -0
  7. package/dist/assets/{briefing-ChEViTLI.js → briefing-DiyTAcGr.js} +4 -4
  8. package/dist/assets/{briefing-ChEViTLI.js.map → briefing-DiyTAcGr.js.map} +1 -1
  9. package/dist/assets/briefing-LON1W671.js +2 -0
  10. package/dist/assets/{briefings-BnBRFYeL.js → briefings-DNfGmgfx.js} +30 -16
  11. package/dist/assets/briefings-DNfGmgfx.js.map +1 -0
  12. package/dist/assets/command-run-BIByV1D4.js +2 -0
  13. package/dist/assets/{command-run-DwdX-9QT.js → command-run-DpsXopbz.js} +4 -4
  14. package/dist/assets/{command-run-DwdX-9QT.js.map → command-run-DpsXopbz.js.map} +1 -1
  15. package/dist/assets/{display-assistant-dSLjFfLP.js → display-assistant-9iqf71qj.js} +8 -8
  16. package/dist/assets/{display-assistant-dSLjFfLP.js.map → display-assistant-9iqf71qj.js.map} +1 -1
  17. package/dist/assets/{fix-pr-ci-QUEotFqt.js → fix-pr-ci-DIJj3je4.js} +2 -2
  18. package/dist/assets/{fix-pr-ci-QUEotFqt.js.map → fix-pr-ci-DIJj3je4.js.map} +1 -1
  19. package/dist/assets/fix-pr-ci-Dqn8RwHg.js +2 -0
  20. package/dist/assets/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +55 -169
  21. package/dist/assets/migrations/20260714191624_worktree_lock_revocation/migration.sql +1 -0
  22. package/dist/assets/migrations/20260714191624_worktree_lock_revocation/snapshot.json +7468 -0
  23. package/dist/assets/migrations/20260714213018_pr_reviews/migration.sql +34 -0
  24. package/dist/assets/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
  25. package/dist/assets/pr-reviews-D1kgrd3B.js +389 -0
  26. package/dist/assets/pr-reviews-D1kgrd3B.js.map +1 -0
  27. package/dist/assets/{prepare-pr-worktree-CgSjjz_X.js → prepare-pr-worktree-DDlVS5Ug.js} +1 -1
  28. package/dist/assets/{prepare-pr-worktree-BaYwvAEG.js → prepare-pr-worktree-D_QmohmG.js} +3 -3
  29. package/dist/assets/{prepare-pr-worktree-BaYwvAEG.js.map → prepare-pr-worktree-D_QmohmG.js.map} +1 -1
  30. package/dist/assets/{push-pr-autofix-jUKVyyZZ.js → push-pr-autofix-D6c-v-4C.js} +1 -1
  31. package/dist/assets/{push-pr-autofix-BMEzf-5-.js → push-pr-autofix-Dm6pEM39.js} +3 -3
  32. package/dist/assets/{push-pr-autofix-BMEzf-5-.js.map → push-pr-autofix-Dm6pEM39.js.map} +1 -1
  33. package/dist/assets/{review-pr-for-human-CUiMGwmG.js → review-pr-for-human-BSlPTs2t.js} +1 -1
  34. package/dist/assets/{review-pr-for-human-BNgddpGs.js → review-pr-for-human-C25YX93Q.js} +60 -15
  35. package/dist/assets/review-pr-for-human-C25YX93Q.js.map +1 -0
  36. package/dist/assets/{safety-D1Y07udx.js → safety-Bjw5dbyq.js} +19 -7
  37. package/dist/assets/safety-Bjw5dbyq.js.map +1 -0
  38. package/dist/assets/{scheduled-agent-instruction-B8ECLDh_.js → scheduled-agent-instruction-6sxkQZ7u.js} +3 -3
  39. package/dist/assets/{scheduled-agent-instruction-B8ECLDh_.js.map → scheduled-agent-instruction-6sxkQZ7u.js.map} +1 -1
  40. package/dist/assets/{scheduled-agent-instruction-HvIQ2fKF.js → scheduled-agent-instruction-Bk4kfeKF.js} +1 -1
  41. package/dist/assets/{scheduler-tick-HqkOkEhU.js → scheduler-tick-CpUBkC78.js} +4 -4
  42. package/dist/assets/{scheduler-tick-HqkOkEhU.js.map → scheduler-tick-CpUBkC78.js.map} +1 -1
  43. package/dist/assets/{scheduler-workflow-9_PuAHiC.js → scheduler-workflow-C8Z2EPml.js} +2 -2
  44. package/dist/assets/{scheduler-workflow-9_PuAHiC.js.map → scheduler-workflow-C8Z2EPml.js.map} +1 -1
  45. package/dist/assets/skills/neondeck/SKILL.md +3 -1
  46. package/dist/assets/{triage-pr-event-8-HupTb3.js → triage-pr-event-CkVVzCjs.js} +1 -1
  47. package/dist/assets/{triage-pr-event-CqE6tOYA.js → triage-pr-event-CsiNPAxU.js} +3 -3
  48. package/dist/assets/{triage-pr-event-CqE6tOYA.js.map → triage-pr-event-CsiNPAxU.js.map} +1 -1
  49. package/dist/assets/{verify-then-push-pr-autofix-CKnTC8yC.js → verify-then-push-pr-autofix-CS4KZOs2.js} +1 -1
  50. package/dist/assets/{verify-then-push-pr-autofix-D5j1yWDP.js → verify-then-push-pr-autofix-DZ_Ksu9s.js} +3 -3
  51. package/dist/assets/{verify-then-push-pr-autofix-D5j1yWDP.js.map → verify-then-push-pr-autofix-DZ_Ksu9s.js.map} +1 -1
  52. package/dist/config/dashboard.json +7 -1
  53. package/dist/server.mjs +14 -14
  54. package/dist/skills/neondeck/SKILL.md +3 -1
  55. package/package.json +1 -1
  56. package/src/agents/display-assistant.ts +2 -2
  57. package/src/cli/onboarding.ts +0 -1
  58. package/src/cli/options.ts +1 -2
  59. package/src/modules/autopilot/actions.ts +23 -2
  60. package/src/modules/autopilot/ci-fix.ts +28 -2
  61. package/src/modules/autopilot/github-facts.ts +3 -0
  62. package/src/modules/autopilot/push-support.ts +1 -29
  63. package/src/modules/autopilot/push.ts +9 -0
  64. package/src/modules/autopilot/review-feedback.ts +32 -34
  65. package/src/modules/autopilot/state-mappers.ts +9 -4
  66. package/src/modules/autopilot/state-schemas.ts +0 -1
  67. package/src/modules/autopilot/worktree.ts +18 -3
  68. package/src/modules/autopilot-policy/config.ts +19 -28
  69. package/src/modules/autopilot-policy/schemas.ts +21 -76
  70. package/src/modules/autopilot-policy/service.ts +51 -83
  71. package/src/modules/commands/handlers/queue.ts +30 -14
  72. package/src/modules/commands/schemas.ts +4 -2
  73. package/src/modules/commands/summaries.ts +16 -0
  74. package/src/modules/config/actions.ts +1 -1
  75. package/src/modules/config/mutations/dashboard.ts +13 -2
  76. package/src/modules/config/mutations/repos.ts +62 -19
  77. package/src/modules/config/read.ts +1 -6
  78. package/src/modules/config/schemas.ts +3 -4
  79. package/src/modules/flue/execution-context.ts +1 -2
  80. package/src/modules/flue/index.ts +2 -0
  81. package/src/modules/flue/origin.ts +7 -0
  82. package/src/modules/github/queue.ts +8 -0
  83. package/src/modules/kilo/results/verify.ts +1 -1
  84. package/src/modules/pr-events/index.ts +1 -0
  85. package/src/modules/pr-review-assist/actions.ts +53 -13
  86. package/src/modules/pr-review-assist/schemas.ts +2 -0
  87. package/src/modules/pr-review-assist/service.ts +15 -3
  88. package/src/modules/pr-reviews/events.ts +40 -0
  89. package/src/modules/pr-reviews/index.ts +4 -0
  90. package/src/modules/pr-reviews/service.ts +455 -0
  91. package/src/modules/pr-reviews/store.ts +185 -0
  92. package/src/modules/pr-reviews/types.ts +47 -0
  93. package/src/modules/prepared-diffs/service.ts +20 -6
  94. package/src/modules/prepared-diffs/store.ts +72 -0
  95. package/src/modules/repo-guardrails/config.ts +61 -0
  96. package/src/modules/repo-guardrails/index.ts +162 -0
  97. package/src/modules/repo-guardrails/risk.ts +2 -0
  98. package/src/modules/reports/service.ts +21 -6
  99. package/src/modules/runtime/status.ts +7 -8
  100. package/src/modules/safety/policy-entries.ts +39 -3
  101. package/src/modules/scheduler/dispatch.ts +80 -14
  102. package/src/modules/sessions/activity.ts +122 -0
  103. package/src/modules/sessions/agent-context.ts +6 -0
  104. package/src/modules/sessions/index.ts +2 -0
  105. package/src/modules/sessions/repo-context.ts +131 -0
  106. package/src/modules/sessions/schemas.ts +22 -0
  107. package/src/modules/watches/service.ts +6 -7
  108. package/src/modules/worktrees/ensure-pr-worktree.ts +63 -0
  109. package/src/modules/worktrees/index.ts +2 -0
  110. package/src/modules/worktrees/locks.ts +45 -6
  111. package/src/modules/worktrees/push-target.ts +39 -0
  112. package/src/modules/worktrees/schemas.ts +3 -0
  113. package/src/modules/worktrees/service.ts +24 -1
  114. package/src/modules/worktrees/store.ts +1 -0
  115. package/src/repo-edit/actions.ts +380 -0
  116. package/src/repo-edit/git.ts +47 -1
  117. package/src/repo-edit/path-safety.ts +7 -2
  118. package/src/repo-edit/schemas.ts +19 -0
  119. package/src/runtime-home/app-db/migrations/20260710061339_neondeck_pre_1_0_baseline/snapshot.json +55 -169
  120. package/src/runtime-home/app-db/migrations/20260714191624_worktree_lock_revocation/migration.sql +1 -0
  121. package/src/runtime-home/app-db/migrations/20260714191624_worktree_lock_revocation/snapshot.json +7468 -0
  122. package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/migration.sql +34 -0
  123. package/src/runtime-home/app-db/migrations/20260714213018_pr_reviews/snapshot.json +7809 -0
  124. package/src/runtime-home/app-db/schema.ts +45 -0
  125. package/src/runtime-home/defaults.ts +16 -4
  126. package/src/runtime-home/guardrails.ts +77 -0
  127. package/src/runtime-home/index.ts +6 -4
  128. package/src/runtime-home/schemas.ts +2 -15
  129. package/src/server/create-app.ts +4 -0
  130. package/src/server/events/review-stream.ts +45 -0
  131. package/src/server/learning-hooks.ts +42 -0
  132. package/src/server/routes/github.ts +77 -1
  133. package/src/server/routes/reports.ts +2 -1
  134. package/src/server/routes/reviews.ts +213 -0
  135. package/src/server/routes/scheduled-tasks.ts +3 -1
  136. package/src/server/routes/sessions.ts +13 -0
  137. package/src/skills/neondeck/SKILL.md +3 -1
  138. package/web/dist/assets/GitHubPrReview-Dg9eIH1f.js +2 -0
  139. package/web/dist/assets/{MultiFileView-CQJqxTQ8.js → MultiFileView-Ct2tUq4T.js} +7 -7
  140. package/web/dist/assets/index-BATSzvO9.js +44 -0
  141. package/web/dist/assets/index-CtNuydm9.css +2 -0
  142. package/web/dist/assets/{surfaces-qKFDNruV.js → surfaces-CK-wQGjJ.js} +1 -1
  143. package/web/dist/index.html +2 -2
  144. package/dist/assets/app-CYRclf6Z.js.map +0 -1
  145. package/dist/assets/autopilot-CuVDqfcB.js.map +0 -1
  146. package/dist/assets/briefing-CbV2CoJn.js +0 -2
  147. package/dist/assets/briefings-BnBRFYeL.js.map +0 -1
  148. package/dist/assets/command-run-B06IW3oE.js +0 -2
  149. package/dist/assets/fix-pr-ci-DsWwd7IG.js +0 -2
  150. package/dist/assets/review-pr-for-human-BNgddpGs.js.map +0 -1
  151. package/dist/assets/safety-D1Y07udx.js.map +0 -1
  152. package/web/dist/assets/GitHubPrReview-CwvkD5lM.js +0 -2
  153. package/web/dist/assets/index-CKMkB_Mn.js +0 -44
  154. package/web/dist/assets/index-peIf41FX.css +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0-beta.8
4
+
5
+ ### Minor Changes
6
+
7
+ - [#113](https://github.com/pandemicsyn/neondeck/pull/113) [`8eaa12d`](https://github.com/pandemicsyn/neondeck/commit/8eaa12df1c4b0344f1f7a11f0fbf491d76678be0) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Add a durable PR review inbox with live chat and dashboard updates, queue-independent review workbenches, linked local reports, and explicit whole-review GitHub submission.
8
+
9
+ ## 1.0.0-beta.7
10
+
11
+ ### Minor Changes
12
+
13
+ - [#111](https://github.com/pandemicsyn/neondeck/pull/111) [`bf72138`](https://github.com/pandemicsyn/neondeck/commit/bf7213830b1df5f378913b2857a7781fe97c1187) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Separate interactive repo authority from autopilot policy, add typed commit and linked-PR push actions, and share objective repo guardrails across both origins. Existing local config must move any `autopilot.limits` values to the top-level `guardrails` block; the legacy location is no longer read.
14
+
15
+ ### Patch Changes
16
+
17
+ - [#108](https://github.com/pandemicsyn/neondeck/pull/108) [`37296be`](https://github.com/pandemicsyn/neondeck/commit/37296beb48ed4c811f775caae5492656b0f422f7) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Keep dashboard slash-command completion synchronized with the backend command registry and restore `/review-pr` completion for existing runtime homes.
18
+
19
+ - [#109](https://github.com/pandemicsyn/neondeck/pull/109) [`0f7d4b8`](https://github.com/pandemicsyn/neondeck/commit/0f7d4b8770752afb6103939fe11a8d56d788302e) Thanks [@pandemicsyn](https://github.com/pandemicsyn)! - Explain why a pull request watch needs attention, show durable watch activity inline in linked chat sessions, and require fresh deterministic evidence before the agent answers watch-status questions.
20
+
3
21
  ## 1.0.0-beta.6
4
22
 
5
23
  ### Patch Changes
@@ -47,8 +47,14 @@
47
47
  "row": 1,
48
48
  "columnSpan": 4,
49
49
  "rowSpan": 5,
50
- "defaultTab": "github",
50
+ "defaultTab": "reviews",
51
51
  "tabs": [
52
+ {
53
+ "id": "reviews",
54
+ "title": "REVIEWS",
55
+ "pluginId": "reviews-panel",
56
+ "config": {}
57
+ },
52
58
  {
53
59
  "id": "github",
54
60
  "title": "GITHUB",
@@ -1,15 +1,16 @@
1
- import { $ as readLearningOperatorState, $n as listGitHubPrQueue, $t as getGitHubPrFiles, A as readReport, Aa as providerRuntimeRegistrations, Ai as switchChatSession, An as listTaskRecords, At as reviewKiloResult, Ba as parseAppConfig, Bi as listMemories, Bt as readRepoFile, Ca as markNotificationRead, Ci as createChatSession, Cn as resolvePrReference, Cr as updateAgentModels, D as fixPrReviewFeedback, Da as nonEmptyStringSchema, Di as pinChatSession, Dr as updateDashboardLayout, E as commentPrAutofixResult, Ea as subscribeNotificationEvents, Ei as listChatSessionCommandEvents, Er as applyDashboardPreset, Fa as ensureRuntimeHome, Fr as bearerToken, Ga as failedAction, Gi as replayConfigEventsAfter, Gr as listRuntimeSkills, Gt as pushPrAutofix, Ha as runtimePaths, Hi as upsertMemory, Ht as searchRepoFiles, I as recordConversationTurnAndMaybeQueueLearning, Ia as ensureRuntimeHomeSync, Ir as localApiAuthHeader, J as rejectSkillPatchCandidate, Ja as __commonJSMin, Jn as verifyPrWorktree, Jt as deleteGitHubPrReviewDraft, K as applySkillPatchCandidate, Ka as invalidInputAction, Ki as subscribeConfigEvents, Kr as loadRuntimeSkill, L as recordHandledPrFromWorkflowResult, La as readRuntimeJson, Li as decideMemoryCandidate, Lr as localApiTokenMatches, Lt as patchRepoFiles, Ma as loadNeondeckEnv, Mi as formatChatSessionServerSentEvent, Mn as removeTask, Mt as recordDocsDriftFixTaskBoundary, Nn as setTaskEnabled, Oa as parseInput, Oi as renameChatSession, On as createAgentInstructionTask, Or as reloadConfig, Ot as listKiloResultStates, Pi as subscribeChatSessionEvents, Pr as readHostMetrics, Pt as fixPrCiFailure, Qt as getGitHubPrFileDiff, Ri as listMemoryCandidates, Rr as localApiTokenQueryParam, Rt as readRepoCheckoutStatus, Sa as listNotifications, Si as archiveChatSession, Sn as setPrWatchPolling, Sr as updateProviderConfig, St as searchKiloSessions, T as approvePreparedDiffPushWithPolicy, Ta as formatNotificationServerSentEvent, Ti as linkChatSessionContext, Tr as updateExecutionPolicy, Ui as readNeonSessionState, Ut as writeRepoFile, Va as parseDashboardConfig, Vi as listMemoryEvents, Vt as replaceRepoFile, Wa as asJsonValue, Wi as formatConfigServerSentEvent, Wn as settleScheduledTaskWorkflowRun, Wr as readRuntimeStatus, Wt as listRepoEditEvents, Xa as __require, Xi as readRepoRegistrySnapshot, Xt as getGitHubPrBranchPermissions, Y as restoreSkillPatchCandidate, Yi as readRepoHealthSnapshot, Yt as deleteGitHubPrReviewDraftComment, Zi as repoFullName, Zn as getGitHubPullRequest, Zt as getGitHubPrEventState, _a as readApprovalRecord, _i as refreshChatSessionSummary, _n as addRefWatch, _t as readKiloSession, aa as releaseWorktreeLock, ai as readPublicMcpOAuthLogin, an as postGitHubPrComment, ba as setWorkflowSummaryRunId, bi as readChatSessionMessages, bn as listRefWatches, br as updateRepoAutopilotPolicy, bt as readKiloSessionMessages, c as abandonPreparedDiffWithRevisionAbort, ci as removeMcpServer, cn as postGitHubPrThreadReply, d as failAutopilotAdmission, di as listMcpApprovals, dn as refreshPrWatchEventState, dr as runApprovedExecution, dt as readKiloTaskDiff, ea as listWorktrees, ei as getMcpRegistry, en as getGitHubPrRequestedChanges, et as readWorkflowObservability, f as recordAutopilotAdmissionRun, fa as readPreparedDiffChangedFiles, fi as listMcpAudit, fr as listExecutionApprovals, ft as readKiloTaskEvents, ga as runPreparedDiffVerification, gi as referenceChatSession, gn as addPrWatch, h as settleAutopilotAdmissionTriage, ha as requestPreparedDiffRevision, hr as checkExecutionPolicy, ht as startKiloTask, i as runAutopilotRecoveryAction, ia as readWorktreeStatus, ii as logoutMcpOAuthServer, in as patchGitHubPrReviewDraftComment, it as listLearningReviews, j as readReportHtml, ja as readProviderConfigSync, ji as updateChatSessionCommandEvent, jn as readTaskRecord, jt as verifyKiloResult, k as listReports, ka as isRegisteredProvider, ki as restoreChatSession, kn as createBriefingTask, kr as triagePrEvent, kt as promoteKiloResult, l as runPreparedDiffRevision, la as listPreparedDiffs, li as setMcpServerEnabled, ln as postGitHubPrThreadResolution, lr as syncExeDevCheckout, lt as abortKiloTask, m as settleAutopilotAdmissionPrepare, ma as readPreparedDiffSummary, mr as resolveExecutionApproval, mt as readKiloTaskStatus, na as createWorktree, ni as installFlueExecutionContextTracker, nn as getGitHubPrReviewThreads, nt as loadAutomationLearningMemoryContext, o as readAutopilotState, oa as syncWorktree, oi as startMcpOAuthLogin, on as postGitHubPrReview, p as recordAutopilotAdmissionTerminalFact, pa as readPreparedDiffFileDiff, pi as resolveMcpApprovalWithPaths, pr as requestExecutionApproval, pt as readKiloTaskSessions, q as listSkillPatchCandidates, qa as okAction, qn as preparePrWorktree, qr as reloadRuntimeSkills, r as readAutopilotRecoveryOptions, ra as lockWorktree, ri as completeMcpOAuthCallback, rn as listPrWatchEventWatermarks, rt as attachLearningReviewRunId, s as autopilotStateSchema, si as addMcpServer, sn as postGitHubPrReviewDraftComment, ta as cleanupWorktrees, tn as getGitHubPrReviewDraft, tt as recordFlueObservation, u as beginAutopilotAdmissionPrepare, ua as openPreparedDiffWorktree, ui as updateMcpServer, un as putGitHubPrReviewDraft, ut as listKiloTasks, va as addWorkflowSummary, vi as listChatSessions, vr as readExecutionPolicy, vt as readKiloSessionChildren, wa as resolveNotification, wi as createChatSessionCommandEvent, wr as updateWorktreePolicy, xa as addNotification, xi as searchChatSessions, xn as removePrWatch, xr as readProviderConfig, xt as readUnavailableSessionAdapter, ya as listWorkflowSummaries, yi as readChatSession, yn as listPrWatches, yt as readKiloSessionDiff, za as ConfigValidationError, zi as archiveMemory, zr as readLocalApiToken, zt as readRepoDiff } from "./autopilot-CuVDqfcB.js";
2
- import { a as readBriefingState, c as settleBriefingObservation, i as readBriefingRunDetails, l as updateBriefingProfile, o as rotateBriefingSession, r as linkBriefingWorkflowObservation, s as runBriefingNow } from "./briefings-BnBRFYeL.js";
3
- import { a as runSchedulerTick, c as rollbackQuietly, d as supportedCommands, n as readSafetyPolicy, o as isSqliteBusy, s as readMetadataValue } from "./safety-D1Y07udx.js";
4
- import { a as review_conversation_for_learning_default, r as review_pr_batch_for_learning_default, s as curate_learning_store_default, t as scheduler_tick_default } from "./scheduler-tick-HqkOkEhU.js";
1
+ import { $ as readLearningOperatorState, $i as repoFullName, $n as runApprovedExecution, $r as listMcpAudit, $t as getGitHubPrFiles, A as readReport, Aa as parseInput, Ai as renameChatSession, An as createBriefingTask, At as reviewKiloResult, Ba as ensureRuntimeHomeSync, Bi as listMemoryCandidates, Bt as readRepoFile, Ca as addNotification, Ci as searchChatSessions, Cn as setPrWatchPolling, Cr as bearerToken, D as fixPrReviewFeedback, Da as formatNotificationServerSentEvent, Di as linkChatSessionContext, Dr as readLocalApiToken, E as commentPrAutofixResult, Ea as resolveNotification, Ei as createChatSessionCommandEvent, Er as localApiTokenQueryParam, Fa as readProviderConfigSync, Fr as reloadRuntimeSkills, Ga as parseDashboardConfig, Gi as readNeonSessionState, Gn as settleScheduledTaskWorkflowRun, Gr as logoutMcpOAuthServer, Gt as pushPrAutofix, Hi as listMemories, Hr as getMcpRegistry, Ht as searchRepoFiles, I as recordConversationTurnAndMaybeQueueLearning, Ia as loadNeondeckEnv, Ii as subscribeChatSessionEvents, J as rejectSkillPatchCandidate, Ja as asJsonValue, Ji as subscribeConfigEvents, Jn as preparePrWorktree, Jr as addMcpServer, Jt as deleteGitHubPrReviewDraft, K as applySkillPatchCandidate, Ka as runtimePaths, Ki as formatConfigServerSentEvent, Kr as readPublicMcpOAuthLogin, L as recordHandledPrFromWorkflowResult, Lt as patchRepoFiles, Ma as installFlueExecutionContextTracker, Mi as switchChatSession, Mn as readTaskRecord, Mr as readRuntimeStatus, Mt as recordDocsDriftFixTaskBoundary, Na as isRegisteredProvider, Ni as updateChatSessionCommandEvent, Nn as removeTask, Nr as listRuntimeSkills, Oa as subscribeNotificationEvents, Oi as listChatSessionCommandEvents, Ot as listKiloResultStates, Pa as providerRuntimeRegistrations, Pi as formatChatSessionServerSentEvent, Pn as setTaskEnabled, Pr as loadRuntimeSkill, Pt as fixPrCiFailure, Qa as __commonJSMin, Qi as readRepoRegistrySnapshot, Qr as listMcpApprovals, Qt as getGitHubPrFileDiff, Rt as readRepoCheckoutStatus, Sa as setWorkflowSummaryRunId, Si as readChatSessionMessages, Sn as removePrWatch, Sr as readHostMetrics, St as searchKiloSessions, T as approvePreparedDiffPushWithPolicy, Ta as markNotificationRead, Ti as createChatSession, Tr as localApiTokenMatches, Ua as ConfigValidationError, Ui as listMemoryEvents, Ut as writeRepoFile, Va as readRuntimeJson, Vi as archiveMemory, Vt as replaceRepoFile, Wa as parseAppConfig, Wi as upsertMemory, Wr as completeMcpOAuthCallback, Wt as listRepoEditEvents, Xa as invalidInputAction, Xr as setMcpServerEnabled, Xt as getGitHubPrBranchPermissions, Y as restoreSkillPatchCandidate, Ya as failedAction, Yn as verifyPrWorktree, Yr as removeMcpServer, Yt as deleteGitHubPrReviewDraftComment, Za as okAction, Zi as readRepoHealthSnapshot, Zn as syncExeDevCheckout, Zr as updateMcpServer, Zt as getGitHubPrEventState, _a as requestPreparedDiffRevision, _n as addPrWatch, _r as triagePrEvent, _t as readKiloSession, aa as lockWorktree, ai as listGitHubPrQueue, an as postGitHubPrComment, ba as addWorkflowSummary, bi as listChatSessions, bn as listPrWatches, bt as readKiloSessionMessages, c as abandonPreparedDiffWithRevisionAbort, ca as syncWorktree, cn as postGitHubPrThreadReply, cr as updateRepoAutopilotPolicy, d as failAutopilotAdmission, da as listPreparedDiffs, dn as refreshPrWatchEventState, dr as updateAgentModels, dt as readKiloTaskDiff, ei as resolveMcpApprovalWithPaths, en as getGitHubPrRequestedChanges, eo as __require, er as listExecutionApprovals, et as readWorkflowObservability, f as recordAutopilotAdmissionRun, fa as openPreparedDiffWorktree, fr as updateWorktreePolicy, ft as readKiloTaskEvents, ga as readPreparedDiffSummary, gi as listChatSessionActivity, gr as reloadConfig, h as settleAutopilotAdmissionTriage, ha as readPreparedDiffFileDiff, hr as updateDashboardLayout, ht as startKiloTask, i as runAutopilotRecoveryAction, ia as createWorktree, in as patchGitHubPrReviewDraftComment, it as listLearningReviews, j as readReportHtml, ji as restoreChatSession, jn as listTaskRecords, jt as verifyKiloResult, k as listReports, ka as nonEmptyStringSchema, ki as pinChatSession, kn as createAgentInstructionTask, kt as promoteKiloResult, l as runPreparedDiffRevision, ln as postGitHubPrThreadResolution, lr as readProviderConfig, lt as abortKiloTask, m as settleAutopilotAdmissionPrepare, ma as readPreparedDiffChangedFiles, mr as applyDashboardPreset, mt as readKiloTaskStatus, na as listWorktrees, nn as getGitHubPrReviewThreads, nr as resolveExecutionApproval, nt as loadAutomationLearningMemoryContext, o as readAutopilotState, oa as readWorktreeStatus, on as postGitHubPrReview, or as readExecutionPolicy, p as recordAutopilotAdmissionTerminalFact, pr as updateExecutionPolicy, pt as readKiloTaskSessions, q as listSkillPatchCandidates, qi as replayConfigEventsAfter, qr as startMcpOAuthLogin, r as readAutopilotRecoveryOptions, ra as cleanupWorktrees, ri as getGitHubPullRequest, rn as listPrWatchEventWatermarks, rr as checkExecutionPolicy, rt as attachLearningReviewRunId, s as autopilotStateSchema, sa as releaseWorktreeLock, sn as postGitHubPrReviewDraftComment, tn as getGitHubPrReviewDraft, tr as requestExecutionApproval, tt as recordFlueObservation, u as beginAutopilotAdmissionPrepare, un as putGitHubPrReviewDraft, ur as updateProviderConfig, ut as listKiloTasks, va as runPreparedDiffVerification, vi as referenceChatSession, vn as addRefWatch, vt as readKiloSessionChildren, wa as listNotifications, wi as archiveChatSession, wn as resolvePrReference, wr as localApiAuthHeader, xa as listWorkflowSummaries, xi as readChatSession, xn as listRefWatches, xt as readUnavailableSessionAdapter, ya as readApprovalRecord, yi as refreshChatSessionSummary, yt as readKiloSessionDiff, za as ensureRuntimeHome, zi as decideMemoryCandidate, zt as readRepoDiff } from "./autopilot-BB7mZq1T.js";
2
+ import { a as readBriefingState, c as settleBriefingObservation, i as readBriefingRunDetails, l as updateBriefingProfile, o as rotateBriefingSession, r as linkBriefingWorkflowObservation, s as runBriefingNow } from "./briefings-DNfGmgfx.js";
3
+ import { a as startPrReview, c as readPrReviewForTarget, i as recentPrReviews, l as formatPrReviewServerSentEvent, o as submitPrReview, r as failPrReview, s as readPrReview, t as attachPrReviewAttemptRun, u as subscribePrReviewEvents } from "./pr-reviews-D1kgrd3B.js";
4
+ import { a as runSchedulerTick, c as rollbackQuietly, d as supportedCommands, n as readSafetyPolicy, o as isSqliteBusy, s as readMetadataValue } from "./safety-Bjw5dbyq.js";
5
+ import { a as review_conversation_for_learning_default, r as review_pr_batch_for_learning_default, s as curate_learning_store_default, t as scheduler_tick_default } from "./scheduler-tick-CpUBkC78.js";
5
6
  import { getRun, invoke, listRuns, observe, registerProvider } from "@flue/runtime";
6
7
  import { createHash, randomUUID } from "node:crypto";
8
+ import * as v from "valibot";
7
9
  import { existsSync } from "node:fs";
8
10
  import { readFile } from "node:fs/promises";
9
11
  import "node:path";
10
12
  import { fileURLToPath } from "node:url";
11
13
  import { DatabaseSync } from "node:sqlite";
12
- import * as v from "valibot";
13
14
  import { flue } from "@flue/runtime/routing";
14
15
  import { Hono } from "hono";
15
16
  //#region node_modules/@hono/node-server/dist/utils/stream.cjs
@@ -379,6 +380,41 @@ function createNotificationEventRoutes() {
379
380
  return routes;
380
381
  }
381
382
  //#endregion
383
+ //#region src/server/events/review-stream.ts
384
+ function createReviewEventRoutes() {
385
+ const routes = new Hono();
386
+ routes.get("/reviews", () => {
387
+ const encoder = new TextEncoder();
388
+ let cleanup = () => {};
389
+ const stream = new ReadableStream({
390
+ start(controller) {
391
+ const send = (value) => controller.enqueue(encoder.encode(value));
392
+ send(": connected\n\n");
393
+ const unsubscribe = subscribePrReviewEvents((event) => {
394
+ send(formatPrReviewServerSentEvent(event));
395
+ });
396
+ const heartbeat = setInterval(() => {
397
+ send(`: heartbeat ${Date.now()}\n\n`);
398
+ }, 25e3);
399
+ cleanup = () => {
400
+ clearInterval(heartbeat);
401
+ unsubscribe();
402
+ };
403
+ },
404
+ cancel() {
405
+ cleanup();
406
+ }
407
+ });
408
+ return new Response(stream, { headers: {
409
+ "cache-control": "no-cache, no-transform",
410
+ connection: "keep-alive",
411
+ "content-type": "text/event-stream; charset=utf-8",
412
+ "x-accel-buffering": "no"
413
+ } });
414
+ });
415
+ return routes;
416
+ }
417
+ //#endregion
382
418
  //#region src/server/events/session-stream.ts
383
419
  function createSessionEventRoutes() {
384
420
  const routes = new Hono();
@@ -423,6 +459,11 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
423
459
  const unsubscribe = (dependencies.observe ?? observe)((event, context) => {
424
460
  const contextHome = flueContextRuntimeHome(context);
425
461
  if (contextHome && contextHome !== paths.home) return;
462
+ if (event.type === "run_start") try {
463
+ linkPrReviewRunObservation(event, paths);
464
+ } catch (error) {
465
+ console.error("[neondeck] failed to link PR review run", error);
466
+ }
426
467
  if (event.type === "run_end") {
427
468
  recordFlueObservation(event, paths).then(async () => {
428
469
  const terminalFact = autopilotTerminalFact(event);
@@ -454,6 +495,9 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
454
495
  linkBriefingWorkflowObservation(event, paths).catch((error) => {
455
496
  console.error("[neondeck] failed to link briefing workflow run", error);
456
497
  });
498
+ Promise.resolve().then(() => settlePrReviewObservation(event, paths)).catch((error) => {
499
+ console.error("[neondeck] failed to settle PR review run", error);
500
+ });
457
501
  const learningReviewId = learningReviewResultId(event);
458
502
  if (learningReviewId) Promise.resolve().then(() => attachLearningReviewRunId({
459
503
  reviewId: learningReviewId,
@@ -509,6 +553,22 @@ function installFlueObservationHandlers(paths, dependencies = {}) {
509
553
  });
510
554
  observationHandlerUnsubscribers.set(paths.home, unsubscribe);
511
555
  }
556
+ function settlePrReviewObservation(event, paths) {
557
+ if (!event.isError) return null;
558
+ return failPrReview({
559
+ runId: event.runId,
560
+ allowReady: true,
561
+ message: "The Flue review workflow failed. Inspect the guarded run for details."
562
+ }, paths);
563
+ }
564
+ function linkPrReviewRunObservation(event, paths) {
565
+ if (event.workflowName !== "review-pr-for-human") return null;
566
+ if (!event.input || typeof event.input !== "object") return null;
567
+ const reviewId = stringField(event.input, "reviewId");
568
+ const attemptId = stringField(event.input, "attemptId");
569
+ if (!reviewId || !attemptId) return null;
570
+ return attachPrReviewAttemptRun(reviewId, attemptId, event.runId, paths);
571
+ }
512
572
  function flueContextRuntimeHome(context) {
513
573
  const value = context?.env?.NEONDECK_HOME;
514
574
  return typeof value === "string" && value ? value : void 0;
@@ -518,7 +578,7 @@ async function startPrepareAfterTriage(event, paths) {
518
578
  const admission = await beginAutopilotAdmissionPrepare({ triageRunId: event.runId }, paths);
519
579
  if (!admission) return;
520
580
  try {
521
- const { runId } = await invoke((await import("./prepare-pr-worktree-CgSjjz_X.js")).default, { input: {
581
+ const { runId } = await invoke((await import("./prepare-pr-worktree-DDlVS5Ug.js")).default, { input: {
522
582
  repoId: admission.repoId,
523
583
  prNumber: admission.prNumber,
524
584
  eventId: admission.eventFingerprint,
@@ -721,7 +781,7 @@ async function dispatchApprovedPreparedDiffPush(approval, paths, dependencies) {
721
781
  try {
722
782
  receipt = await invokeWorkflowForRuntimeHome(paths, dispatch, invokeWorkflow);
723
783
  } catch (error) {
724
- const message = errorMessage$3(error);
784
+ const message = errorMessage$4(error);
725
785
  await recordDispatchFailure(preparedDiff, mode, dispatch, approvalId, message, paths);
726
786
  return {
727
787
  ...withDispatchData(approval, {
@@ -752,7 +812,7 @@ async function dispatchApprovedPreparedDiffPush(approval, paths, dependencies) {
752
812
  dispatchedAt: (/* @__PURE__ */ new Date()).toISOString()
753
813
  }
754
814
  }, paths).catch(async (error) => {
755
- const message = errorMessage$3(error);
815
+ const message = errorMessage$4(error);
756
816
  await recordDispatchSummaryFailure(preparedDiff, mode, dispatch, approvalId, receipt.runId, message, paths);
757
817
  return null;
758
818
  });
@@ -801,8 +861,8 @@ async function invokeWorkflowForRuntimeHome(paths, dispatch, invokeWorkflow) {
801
861
  return invokeWorkflow(dispatch.workflow, dispatch.input);
802
862
  }
803
863
  async function invokeAutopilotWorkflow(workflow, input) {
804
- if (workflow === "push-pr-autofix") return invokeWorkflow((await import("./push-pr-autofix-jUKVyyZZ.js")).default, { input });
805
- return invokeWorkflow((await import("./verify-then-push-pr-autofix-CKnTC8yC.js")).default, { input });
864
+ if (workflow === "push-pr-autofix") return invokeWorkflow((await import("./push-pr-autofix-D6c-v-4C.js")).default, { input });
865
+ return invokeWorkflow((await import("./verify-then-push-pr-autofix-CS4KZOs2.js")).default, { input });
806
866
  }
807
867
  async function recordDispatchFailure(preparedDiff, mode, dispatch, approvalId, error, paths) {
808
868
  await addWorkflowSummary({
@@ -859,7 +919,7 @@ async function recordDispatchSummaryFailure(preparedDiff, mode, dispatch, approv
859
919
  async function invokeWorkflow(workflow, request) {
860
920
  return invoke(workflow, request);
861
921
  }
862
- function errorMessage$3(error) {
922
+ function errorMessage$4(error) {
863
923
  return error instanceof Error ? error.message : String(error);
864
924
  }
865
925
  function withDispatchData(approval, dispatch, message) {
@@ -1359,7 +1419,40 @@ function createGitHubRoutes(paths) {
1359
1419
  routes.post("/prs/:owner/:repo/:number/reviews", async (c) => {
1360
1420
  const target = prTargetFromParams(c.req.param("owner"), c.req.param("repo"), c.req.param("number"));
1361
1421
  if (!target.ok) return c.json(target.result, 400);
1362
- const result = await postGitHubPrReview(target.input, await safeJsonBody(c), paths);
1422
+ const reviewInput = await safeJsonBody(c);
1423
+ const reviewInputObject = objectField$1(reviewInput);
1424
+ const requestedHeadSha = typeof reviewInputObject.headSha === "string" ? reviewInputObject.headSha : null;
1425
+ const durableReview = readPrReviewForTarget(target.input.repo, target.input.prNumber, paths);
1426
+ if (durableReview && (durableReview.status !== "ready" || !requestedHeadSha || durableReview.headSha !== requestedHeadSha)) return c.json({
1427
+ ok: false,
1428
+ action: "github_pr_review_post",
1429
+ changed: false,
1430
+ message: durableReview.status !== "ready" ? "The durable review must be ready before it can be submitted." : "The durable review does not match the pull request head being submitted.",
1431
+ data: { reviewId: durableReview.id }
1432
+ }, 409);
1433
+ const result = await postGitHubPrReview(target.input, reviewInput, paths);
1434
+ if (result.ok) {
1435
+ const data = objectField$1(result.data);
1436
+ const draft = objectField$1(data.draft);
1437
+ const review = objectField$1(data.review);
1438
+ const verdict = draft.verdict;
1439
+ if (verdict === "comment" || verdict === "approve" || verdict === "request-changes") {
1440
+ const submitted = submitPrReview({
1441
+ repoFullName: target.input.repo,
1442
+ prNumber: target.input.prNumber,
1443
+ verdict,
1444
+ githubReviewUrl: typeof review.url === "string" ? review.url : null,
1445
+ headSha: typeof draft.headSha === "string" ? draft.headSha : null
1446
+ }, paths);
1447
+ if (durableReview && !submitted) return c.json({
1448
+ ok: false,
1449
+ action: "github_pr_review_post",
1450
+ changed: true,
1451
+ message: "GitHub accepted the review, but Neondeck could not settle its durable review record.",
1452
+ data: result.data
1453
+ }, 409);
1454
+ }
1455
+ }
1363
1456
  return c.json(result, result.ok ? 200 : 400);
1364
1457
  });
1365
1458
  routes.post("/prs/:owner/:repo/:number/review-threads/:threadId/reply", async (c) => {
@@ -1402,6 +1495,9 @@ function createGitHubRoutes(paths) {
1402
1495
  });
1403
1496
  return routes;
1404
1497
  }
1498
+ function objectField$1(value) {
1499
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
1500
+ }
1405
1501
  function prTargetFromParams(owner, repo, numberText) {
1406
1502
  const number = Number(numberText);
1407
1503
  if (!Number.isInteger(number) || number <= 0) return {
@@ -1604,7 +1700,7 @@ async function registerHandoffPr(rawInput, paths = runtimePaths(), dependencies
1604
1700
  queued: true
1605
1701
  });
1606
1702
  } catch (error) {
1607
- const message = errorMessage$2(error);
1703
+ const message = errorMessage$3(error);
1608
1704
  const audit = await addHandoffAudit({
1609
1705
  event: "register-pr",
1610
1706
  source,
@@ -1698,7 +1794,7 @@ async function externalReviewQueueAllowed(paths) {
1698
1794
  }
1699
1795
  async function invokeReviewPrWorkflow(input) {
1700
1796
  const { invoke } = await import("@flue/runtime");
1701
- return invoke((await import("./review-pr-for-human-CUiMGwmG.js")).default, { input });
1797
+ return invoke((await import("./review-pr-for-human-BSlPTs2t.js")).default, { input });
1702
1798
  }
1703
1799
  async function addHandoffAudit(summary, paths, options = {}) {
1704
1800
  return addWorkflowSummary({
@@ -1743,7 +1839,7 @@ function failResult(action, message, data = {}) {
1743
1839
  function displaySource(source) {
1744
1840
  return source.replace(/^(?:external|ci):/, "");
1745
1841
  }
1746
- function errorMessage$2(error) {
1842
+ function errorMessage$3(error) {
1747
1843
  if (error instanceof Error) return error.message;
1748
1844
  return String(error);
1749
1845
  }
@@ -2599,9 +2695,9 @@ async function stageDocsDriftFix(rawInput, paths = runtimePaths(), dependencies
2599
2695
  allowedDocsPaths: docsFixAllowedDocsPaths(summary)
2600
2696
  }, paths);
2601
2697
  } catch (error) {
2602
- return failedAction("docs_drift_stage_fix", `Could not record docs drift fix boundary: ${errorMessage$1(error)}.`, {
2698
+ return failedAction("docs_drift_stage_fix", `Could not record docs drift fix boundary: ${errorMessage$2(error)}.`, {
2603
2699
  requires: ["docsDriftBoundary"],
2604
- errors: [errorMessage$1(error)]
2700
+ errors: [errorMessage$2(error)]
2605
2701
  });
2606
2702
  }
2607
2703
  const learningMemoryContext = await loadAutomationLearningMemoryContext(paths, {
@@ -2745,7 +2841,7 @@ function stringArrayConfig(value) {
2745
2841
  function objectConfig(value) {
2746
2842
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2747
2843
  }
2748
- function errorMessage$1(error) {
2844
+ function errorMessage$2(error) {
2749
2845
  return error instanceof Error ? error.message : String(error);
2750
2846
  }
2751
2847
  //#endregion
@@ -2754,6 +2850,7 @@ function createReportApiRoutes(paths) {
2754
2850
  const routes = new Hono();
2755
2851
  routes.get("/reports", async (c) => {
2756
2852
  const kind = c.req.query("kind")?.trim() || void 0;
2853
+ const excludeKind = c.req.query("excludeKind")?.trim() || void 0;
2757
2854
  const limitText = c.req.query("limit");
2758
2855
  const limit = limitText ? Number(limitText) : void 0;
2759
2856
  if (limitText && (limit === void 0 || !Number.isFinite(limit) || limit <= 0)) return c.json({
@@ -2768,6 +2865,7 @@ function createReportApiRoutes(paths) {
2768
2865
  action: "reports_list",
2769
2866
  items: await listReports(paths, {
2770
2867
  kind,
2868
+ excludeKind,
2771
2869
  limit
2772
2870
  }),
2773
2871
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -2840,6 +2938,139 @@ function createReportFileRoutes(paths) {
2840
2938
  return routes;
2841
2939
  }
2842
2940
  //#endregion
2941
+ //#region src/server/routes/reviews.ts
2942
+ function createReviewRoutes(paths) {
2943
+ const routes = new Hono();
2944
+ routes.get("/reviews", async (c) => {
2945
+ const repo = c.req.query("repo")?.trim();
2946
+ const prNumber = Number(c.req.query("prNumber"));
2947
+ if (repo && Number.isInteger(prNumber) && prNumber > 0) {
2948
+ const review = readPrReviewForTarget(repo, prNumber, paths);
2949
+ const items = review ? [review] : [];
2950
+ return c.json({
2951
+ ok: true,
2952
+ action: "pr_reviews_list",
2953
+ changed: false,
2954
+ items,
2955
+ groups: groupReviews(items, [])
2956
+ });
2957
+ }
2958
+ const reviews = recentPrReviews(paths);
2959
+ const queueResult = await listGitHubPrQueue(paths);
2960
+ const awaiting = (queueResult.ok ? queueFromResult(queueResult.data) : { items: [] }).items.filter((item) => item.relations.includes("review-requested")).map((pullRequest) => ({
2961
+ pullRequest,
2962
+ review: reviews.find((review) => review.repoFullName.toLowerCase() === pullRequest.repo.toLowerCase() && review.prNumber === pullRequest.number) ?? null
2963
+ }));
2964
+ return c.json({
2965
+ ok: true,
2966
+ action: "pr_reviews_list",
2967
+ changed: false,
2968
+ items: reviews,
2969
+ groups: groupReviews(reviews, awaiting),
2970
+ queueIssues: queueResult.ok ? [] : queueResult.errors ?? []
2971
+ });
2972
+ });
2973
+ routes.get("/reviews/:id", (c) => {
2974
+ const review = readPrReview(c.req.param("id"), paths);
2975
+ return review ? c.json({
2976
+ ok: true,
2977
+ action: "pr_review_read",
2978
+ changed: false,
2979
+ review
2980
+ }) : c.json({
2981
+ ok: false,
2982
+ action: "pr_review_read",
2983
+ changed: false,
2984
+ message: "PR review not found."
2985
+ }, 404);
2986
+ });
2987
+ routes.post("/reviews", async (c) => {
2988
+ const body = objectBody(await safeJsonBody(c));
2989
+ const ref = typeof body.ref === "string" ? body.ref.trim() : "";
2990
+ if (!ref) return c.json({
2991
+ ok: false,
2992
+ action: "pr_review_start",
2993
+ changed: false,
2994
+ message: "A pull request reference is required.",
2995
+ requires: ["ref"]
2996
+ }, 400);
2997
+ try {
2998
+ const result = await startPrReview({
2999
+ ref,
3000
+ origin: reviewOrigin(body.origin)
3001
+ }, paths);
3002
+ return c.json({
3003
+ ok: true,
3004
+ action: "pr_review_start",
3005
+ changed: true,
3006
+ message: `Started review for ${result.review.repoFullName}#${result.review.prNumber}.`,
3007
+ ...result
3008
+ }, 202);
3009
+ } catch (error) {
3010
+ return c.json({
3011
+ ok: false,
3012
+ action: "pr_review_start",
3013
+ changed: false,
3014
+ message: errorMessage$1(error)
3015
+ }, 400);
3016
+ }
3017
+ });
3018
+ routes.post("/reviews/:id/review", async (c) => {
3019
+ const existing = readPrReview(c.req.param("id"), paths);
3020
+ if (!existing) return c.json({
3021
+ ok: false,
3022
+ action: "pr_review_restart",
3023
+ changed: false,
3024
+ message: "PR review not found."
3025
+ }, 404);
3026
+ try {
3027
+ const result = await startPrReview({
3028
+ ref: existing.ref,
3029
+ origin: "panel"
3030
+ }, paths);
3031
+ return c.json({
3032
+ ok: true,
3033
+ action: "pr_review_restart",
3034
+ changed: true,
3035
+ message: `Re-reviewing ${existing.repoFullName}#${existing.prNumber}.`,
3036
+ ...result
3037
+ }, 202);
3038
+ } catch (error) {
3039
+ return c.json({
3040
+ ok: false,
3041
+ action: "pr_review_restart",
3042
+ changed: false,
3043
+ message: errorMessage$1(error)
3044
+ }, 400);
3045
+ }
3046
+ });
3047
+ return routes;
3048
+ }
3049
+ function groupReviews(reviews, awaiting) {
3050
+ return {
3051
+ awaiting,
3052
+ inProgress: reviews.filter((review) => review.status === "reviewing"),
3053
+ needsAction: reviews.filter((review) => review.status === "ready" || review.status === "failed"),
3054
+ submitted: reviews.filter((review) => review.status === "submitted")
3055
+ };
3056
+ }
3057
+ function queueFromResult(value) {
3058
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { items: [] };
3059
+ const queue = value.queue;
3060
+ if (!queue || typeof queue !== "object" || Array.isArray(queue)) return { items: [] };
3061
+ const items = queue.items;
3062
+ return { items: Array.isArray(items) ? items : [] };
3063
+ }
3064
+ function objectBody(value) {
3065
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3066
+ }
3067
+ function reviewOrigin(value) {
3068
+ return value === "chat" || value === "panel" || value === "api" ? value : "api";
3069
+ }
3070
+ function errorMessage$1(error) {
3071
+ return error instanceof Error ? error.message : String(error);
3072
+ }
3073
+ //#endregion
2843
3074
  //#region src/server/routes/repos.ts
2844
3075
  function createReposRoutes(paths) {
2845
3076
  const routes = new Hono();
@@ -3327,6 +3558,14 @@ function createSessionRoutes(paths) {
3327
3558
  }, paths);
3328
3559
  return c.json(result, result.ok ? 200 : 404);
3329
3560
  });
3561
+ routes.get("/sessions/:id/activity", async (c) => {
3562
+ const rawLimit = Number(c.req.query("limit"));
3563
+ const result = await listChatSessionActivity({
3564
+ sessionId: c.req.param("id"),
3565
+ limit: Number.isFinite(rawLimit) ? rawLimit : void 0
3566
+ }, paths);
3567
+ return c.json(result, result.ok ? 200 : 404);
3568
+ });
3330
3569
  routes.post("/sessions/:id/command-events", async (c) => {
3331
3570
  const result = await createChatSessionCommandEvent({
3332
3571
  ...await safeJsonObject(c),
@@ -3586,6 +3825,7 @@ async function createApp(options = {}) {
3586
3825
  app.route("/api", createRuntimeRoutes(paths));
3587
3826
  app.route("/api/events", createConfigEventRoutes());
3588
3827
  app.route("/api/events", createNotificationEventRoutes());
3828
+ app.route("/api/events", createReviewEventRoutes());
3589
3829
  app.route("/api/events", createSessionEventRoutes());
3590
3830
  app.route("/api/safety", createSafetyRoutes(paths));
3591
3831
  app.route("/api/execution", createExecutionRoutes(paths));
@@ -3609,6 +3849,7 @@ async function createApp(options = {}) {
3609
3849
  app.route("/api/skills", createSkillRoutes(paths));
3610
3850
  app.route("/api/commands", createCommandRoutes());
3611
3851
  app.route("/api", createReportApiRoutes(paths));
3852
+ app.route("/api", createReviewRoutes(paths));
3612
3853
  app.route("/api/workflows", createWorkflowRoutes(paths));
3613
3854
  app.route("/api/github", createGitHubRoutes(paths));
3614
3855
  app.use("/api/flue/agents/display-assistant/*", displayAssistantLearningMiddleware(paths));
@@ -3648,4 +3889,4 @@ var app_default = await createApp();
3648
3889
  //#endregion
3649
3890
  export { app_default as default };
3650
3891
 
3651
- //# sourceMappingURL=app-CYRclf6Z.js.map
3892
+ //# sourceMappingURL=app-kQMyZcgk.js.map