@a-t-h-i/bot-lobby 0.6.18 → 0.6.19

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 (52) hide show
  1. package/package.json +1 -1
  2. package/src/ask/relay.ts +3 -1
  3. package/src/ask/tool.ts +18 -3
  4. package/src/ask/types.ts +12 -0
  5. package/src/ask/web.ts +2 -1
  6. package/src/delivery/checks.ts +37 -0
  7. package/src/delivery/lock.ts +78 -0
  8. package/src/delivery/merge.ts +44 -0
  9. package/src/delivery/operations.ts +134 -0
  10. package/src/delivery/pr.ts +40 -0
  11. package/src/delivery/review.ts +90 -0
  12. package/src/delivery/rules.ts +46 -0
  13. package/src/delivery/source.ts +39 -0
  14. package/src/delivery/transport.ts +36 -0
  15. package/src/delivery/types.ts +60 -0
  16. package/src/execution/agent-runner.ts +1 -23
  17. package/src/index.ts +1 -1
  18. package/src/lobby/feed.ts +0 -6
  19. package/src/lobby/host.ts +3 -0
  20. package/src/lobby/planner.ts +1 -7
  21. package/src/lobby/pr-review.ts +1 -7
  22. package/src/lobby/prompt-hub.ts +7 -1
  23. package/src/lobby/quickfix.ts +3 -16
  24. package/src/lobby/service.ts +73 -3
  25. package/src/lobby/sessions.ts +12 -0
  26. package/src/lobby/task-rows.ts +5 -0
  27. package/src/master/master.ts +1 -1
  28. package/src/master/research.ts +0 -1
  29. package/src/pi/events.ts +0 -2
  30. package/src/pi/model-settings.ts +7 -26
  31. package/src/pi/model-support.ts +4 -19
  32. package/src/schemas/configuration.ts +8 -38
  33. package/src/schemas/findings.ts +0 -2
  34. package/src/schemas/task.ts +14 -0
  35. package/src/state/blocking-requests.ts +23 -0
  36. package/src/state/persistence.ts +12 -1
  37. package/src/state/phase-timing.ts +53 -0
  38. package/src/state/task-state.ts +2 -0
  39. package/src/state/timing-merge.ts +25 -0
  40. package/src/webui/api/index.ts +17 -1
  41. package/src/webui/api/tasks.ts +52 -0
  42. package/src/webui/protocol.ts +8 -0
  43. package/src/workflow/approvals.ts +3 -0
  44. package/src/workflow/workflow.ts +14 -33
  45. package/webui/dist/assets/index-BJI9lE5R.js +98 -0
  46. package/webui/dist/assets/index-Dg0tvkeY.css +2 -0
  47. package/webui/dist/build.json +83 -43
  48. package/webui/dist/index.html +2 -2
  49. package/src/execution/fallback.ts +0 -75
  50. package/src/pi/master-fallback.ts +0 -61
  51. package/webui/dist/assets/index-CHLNxlA1.js +0 -98
  52. package/webui/dist/assets/index-m9XcQvH8.css +0 -2
@@ -52,6 +52,7 @@ import { tail, truncate } from "../text.ts";
52
52
  import { isAutoMode } from "../state/auto.ts";
53
53
  import { briefRejection } from "./brief.ts";
54
54
  import { assertNoPendingApprovals, pendingApprovals, requestApproval, resolveApproval } from "./approvals.ts";
55
+ import { withBlockingRequest } from "../state/blocking-requests.ts";
55
56
  import { pingApproval } from "../pi/notify.ts";
56
57
  import { describeRun, runLogEntry } from "../pi/run-summary.ts";
57
58
  import { nextStates } from "./transitions.ts";
@@ -64,8 +65,8 @@ import { appendMetrics, metricFromRun } from "../state/metrics.ts";
64
65
  import { markCommentsAddressed, pendingComments, readPlanComments } from "../state/comments.ts";
65
66
  import { fastNext, onFastTrack, parseRoster, qaRequired, qaStillDue, qaTookPart, rosterWords, trackSummary } from "./track.ts";
66
67
  import { missingWorktree, taskCwd } from "../execution/workspace.ts";
67
- import { createPullRequest } from "../lobby/pulls.ts";
68
- import type { Exec } from "../lobby/issues.ts";
68
+ import { completionReview } from "../delivery/review.ts";
69
+ import { execCommand, type Exec } from "../lobby/issues.ts";
69
70
 
70
71
  export const ORCHESTRATE_ACTIONS = [
71
72
  "clarify",
@@ -1309,38 +1310,10 @@ async function handleComplete(task: Task, params: OrchestrateParams, deps: Workf
1309
1310
  task.blockers = [];
1310
1311
  if (task.state === "implementing") transition(task, "reviewing");
1311
1312
  transition(task, "completed");
1312
- const opened = await openPullRequest(task, deps);
1313
+ task.delivery = await completionReview(task, deps.root, { cwd: deps.root, exec: deps.exec ?? execCommand });
1314
+ deps.notify(`Task ${task.id} is completed. Delivery review is available; publishing requires your approval.`, "info");
1313
1315
  flushDecisions(deps, task);
1314
- return `Task ${task.id} completed. History recorded and temporary scratchpads removed.${opened}`;
1315
- }
1316
-
1317
- /** Longest pull request body `gh` takes without complaint. */
1318
- const PR_BODY_CHARS = 60_000;
1319
-
1320
- /**
1321
- * Open the task's pull request once it completes, so its branch lands in
1322
- * review by itself. Every reason it cannot (no isolation, no remote, `gh` not
1323
- * signed in) is recorded as a note and the completion stands either way.
1324
- */
1325
- async function openPullRequest(task: Task, deps: WorkflowDeps): Promise<string> {
1326
- const git = task.git;
1327
- if (!git || (git.mode !== "branch" && git.mode !== "worktree")) return pullNote(task, "No pull request opened — task has no git isolation");
1328
- const base = git.from?.trim();
1329
- if (!base || /^detached at /i.test(base) || /^[a-f0-9]{40,64}$/i.test(base)) return pullNote(task, "No pull request opened — task has no valid base branch");
1330
- const body = [task.proposal?.trim() || task.plan?.trim() || task.title, task.qaVerdict ? `QA verdict: ${task.qaVerdict}` : ""].filter(Boolean).join("\n\n").slice(0, PR_BODY_CHARS);
1331
- try {
1332
- const pull = await createPullRequest({ exec: deps.exec, cwd: taskCwd(task, deps.cwd), branch: git.branch, base, title: task.title, body });
1333
- recordDecision(task, `Opened pull request #${pull.number} for ${git.branch}: ${pull.url}`);
1334
- deps.notify(`Pull request #${pull.number} is open: ${pull.url}`, "info");
1335
- return ` Pull request #${pull.number} is open: ${pull.url}.`;
1336
- } catch (error) {
1337
- return pullNote(task, `No pull request opened for ${git.branch} — ${(error as Error).message}`);
1338
- }
1339
- }
1340
-
1341
- function pullNote(task: Task, note: string): string {
1342
- recordDecision(task, note);
1343
- return ` ${note}.`;
1316
+ return `Task ${task.id} completed. History recorded and temporary scratchpads removed. Delivery review is available; nothing was published.`;
1344
1317
  }
1345
1318
 
1346
1319
  /** Asked when the oracle completes a task QA has not passed (the user told it to finish, say). */
@@ -1740,8 +1713,16 @@ export async function runWorkflowAction(params: OrchestrateParams, deps: Workflo
1740
1713
  const gone = missingWorktree(task);
1741
1714
  if (gone && params.action !== "status") return { ok: false, taskId: task.id, state: task.state, message: `Rejected: ${gone}` };
1742
1715
  const finished = new Map<string, AgentRun>();
1716
+ const identity = { root: deps.root, configDir: deps.configDir, taskId: task.id, sessionId: task.ownerSessionId };
1717
+ const wait = <T>(run: () => Promise<T>) => {
1718
+ saveTask(deps.root, deps.configDir, task);
1719
+ return withBlockingRequest(identity, run);
1720
+ };
1743
1721
  const tracked: WorkflowDeps = {
1744
1722
  ...deps,
1723
+ choose: (...args) => wait(() => deps.choose(...args)),
1724
+ ask: (...args) => wait(() => deps.ask(...args)),
1725
+ ...(deps.askQuestions ? { askQuestions: (...args: Parameters<NonNullable<WorkflowDeps["askQuestions"]>>) => wait(() => deps.askQuestions!(...args)) } : {}),
1745
1726
  // Every agent, diff and desk of a task with its own worktree works there.
1746
1727
  cwd: taskCwd(task, deps.cwd),
1747
1728
  onUpdate: (run) => {