@ouro.bot/cli 0.1.0-alpha.100 → 0.1.0-alpha.102

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.
package/changelog.json CHANGED
@@ -1,6 +1,20 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.102",
6
+ "changes": [
7
+ "Live obligations now persist a concrete current artifact and next action, so status answers can anchor on the actual active lane, artifact, and immediate step instead of drifting into broad mission statements.",
8
+ "Obligation-bound coding feedback now turns PR milestones into structured report-backs and lifecycle updates, which keeps the originating live conversation informed when child work opens a PR, waits for merge, or needs a runtime update."
9
+ ]
10
+ },
11
+ {
12
+ "version": "0.1.0-alpha.101",
13
+ "changes": [
14
+ "Live coding-session status now prefers active work from the current thread instead of resurfacing stale global history, so agents stop anchoring on ancient sessions like `coding-001` when newer coding lanes are already in flight.",
15
+ "Active-work rendering and prompt steering now surface same-thread live coding lanes explicitly, giving the agent a clearer center of gravity before it answers questions about ongoing work."
16
+ ]
17
+ },
4
18
  {
5
19
  "version": "0.1.0-alpha.100",
6
20
  "changes": [
@@ -32,6 +32,20 @@ function hasSharedObligationPressure(input) {
32
32
  && input.currentObligation.trim().length > 0) || input.mustResolveBeforeHandoff
33
33
  || summarizeLiveTasks(input.taskBoard).length > 0;
34
34
  }
35
+ function formatCodingLaneLabel(session) {
36
+ return `${session.runner} ${session.id}`;
37
+ }
38
+ function describeCodingSessionScope(session, currentSession) {
39
+ if (!session.originSession)
40
+ return "";
41
+ if (currentSession
42
+ && session.originSession.friendId === currentSession.friendId
43
+ && session.originSession.channel === currentSession.channel
44
+ && session.originSession.key === currentSession.key) {
45
+ return " for this thread";
46
+ }
47
+ return ` for ${session.originSession.channel}/${session.originSession.key}`;
48
+ }
35
49
  function activeObligationCount(obligations) {
36
50
  return (obligations ?? []).filter((ob) => (0, obligations_1.isOpenObligationStatus)(ob.status)).length;
37
51
  }
@@ -49,6 +63,62 @@ function formatObligationSurface(obligation) {
49
63
  return ` (${obligation.currentSurface.label})`;
50
64
  }
51
65
  }
66
+ function findPrimaryOpenObligation(frame) {
67
+ return (frame.pendingObligations ?? []).find((ob) => ob.status !== "pending" && ob.status !== "fulfilled")
68
+ ?? (frame.pendingObligations ?? []).find(obligations_1.isOpenObligation)
69
+ ?? null;
70
+ }
71
+ function formatActiveLane(frame, obligation) {
72
+ const liveCodingSession = frame.codingSessions?.[0];
73
+ if (liveCodingSession) {
74
+ return `${formatCodingLaneLabel(liveCodingSession)}${describeCodingSessionScope(liveCodingSession, frame.currentSession)}`;
75
+ }
76
+ if (obligation?.currentSurface?.label) {
77
+ return obligation.currentSurface.label;
78
+ }
79
+ if (frame.inner?.job?.status === "running") {
80
+ return "inner dialog";
81
+ }
82
+ return null;
83
+ }
84
+ function formatCurrentArtifact(frame, obligation) {
85
+ if (obligation?.currentArtifact?.trim()) {
86
+ return obligation.currentArtifact.trim();
87
+ }
88
+ if (obligation?.currentSurface?.kind === "merge" && obligation.currentSurface.label.trim()) {
89
+ return obligation.currentSurface.label.trim();
90
+ }
91
+ if ((frame.codingSessions ?? []).length > 0) {
92
+ return "no PR or merge artifact yet";
93
+ }
94
+ return null;
95
+ }
96
+ function formatNextAction(frame, obligation) {
97
+ if (obligation?.nextAction?.trim()) {
98
+ return obligation.nextAction.trim();
99
+ }
100
+ const liveCodingSession = frame.codingSessions?.[0];
101
+ if (liveCodingSession?.status === "waiting_input") {
102
+ return `answer ${formatCodingLaneLabel(liveCodingSession)} and continue`;
103
+ }
104
+ if (liveCodingSession?.status === "stalled") {
105
+ return `unstick ${formatCodingLaneLabel(liveCodingSession)} and continue`;
106
+ }
107
+ if (liveCodingSession) {
108
+ return "finish the coding pass and bring the result back here";
109
+ }
110
+ if (obligation?.status === "waiting_for_merge") {
111
+ const artifact = formatCurrentArtifact(frame, obligation) ?? "the fix";
112
+ return `wait for checks, merge ${artifact}, then update runtime`;
113
+ }
114
+ if (obligation?.status === "updating_runtime") {
115
+ return "update runtime, verify version/changelog, then re-observe";
116
+ }
117
+ if (obligation) {
118
+ return "continue the active loop and bring the result back here";
119
+ }
120
+ return null;
121
+ }
52
122
  function suggestBridgeForActiveWork(input) {
53
123
  const targetCandidates = (input.targetCandidates ?? [])
54
124
  .filter((candidate) => {
@@ -106,9 +176,10 @@ function buildActiveWorkFrame(input) {
106
176
  const liveTaskNames = summarizeLiveTasks(input.taskBoard);
107
177
  const activeBridgePresent = input.bridges.some(isActiveBridge);
108
178
  const openObligations = activeObligationCount(input.pendingObligations);
179
+ const liveCodingSessions = input.codingSessions ?? [];
109
180
  const centerOfGravity = activeBridgePresent
110
181
  ? "shared-work"
111
- : (input.inner.status === "running" || input.inner.hasPending || input.mustResolveBeforeHandoff || openObligations > 0)
182
+ : (input.inner.status === "running" || input.inner.hasPending || input.mustResolveBeforeHandoff || openObligations > 0 || liveCodingSessions.length > 0)
112
183
  ? "inward-work"
113
184
  : "local-turn";
114
185
  const frame = {
@@ -127,6 +198,7 @@ function buildActiveWorkFrame(input) {
127
198
  freshestForCurrentFriend: friendSessions[0] ?? null,
128
199
  otherLiveSessionsForCurrentFriend: friendSessions,
129
200
  },
201
+ codingSessions: liveCodingSessions,
130
202
  pendingObligations: input.pendingObligations ?? [],
131
203
  targetCandidates: input.targetCandidates ?? [],
132
204
  bridgeSuggestion: suggestBridgeForActiveWork({
@@ -148,6 +220,7 @@ function buildActiveWorkFrame(input) {
148
220
  bridges: frame.bridges.length,
149
221
  liveTasks: frame.taskPressure.liveTaskNames.length,
150
222
  liveSessions: frame.friendActivity.otherLiveSessionsForCurrentFriend.length,
223
+ codingSessions: frame.codingSessions.length,
151
224
  pendingObligations: openObligations,
152
225
  hasBridgeSuggestion: frame.bridgeSuggestion !== null,
153
226
  },
@@ -156,6 +229,10 @@ function buildActiveWorkFrame(input) {
156
229
  }
157
230
  function formatActiveWorkFrame(frame) {
158
231
  const lines = ["## what i'm holding"];
232
+ const primaryObligation = findPrimaryOpenObligation(frame);
233
+ const activeLane = formatActiveLane(frame, primaryObligation);
234
+ const currentArtifact = formatCurrentArtifact(frame, primaryObligation);
235
+ const nextAction = formatNextAction(frame, primaryObligation);
159
236
  // Session line
160
237
  if (frame.currentSession) {
161
238
  let sessionLine = `i'm in a conversation on ${formatSessionLabel(frame.currentSession)}.`;
@@ -172,6 +249,22 @@ function formatActiveWorkFrame(frame) {
172
249
  lines.push("");
173
250
  lines.push("i'm not in a conversation right now.");
174
251
  }
252
+ if (activeLane || currentArtifact || nextAction) {
253
+ lines.push("");
254
+ lines.push("## current concrete state");
255
+ if (frame.currentSession) {
256
+ lines.push(`- live conversation: ${formatSessionLabel(frame.currentSession)}`);
257
+ }
258
+ if (activeLane) {
259
+ lines.push(`- active lane: ${activeLane}`);
260
+ }
261
+ if (currentArtifact) {
262
+ lines.push(`- current artifact: ${currentArtifact}`);
263
+ }
264
+ if (nextAction) {
265
+ lines.push(`- next action: ${nextAction}`);
266
+ }
267
+ }
175
268
  // Inner status block
176
269
  const job = frame.inner?.job;
177
270
  if (job) {
@@ -205,6 +298,13 @@ function formatActiveWorkFrame(frame) {
205
298
  }
206
299
  // idle, returned, abandoned: omitted
207
300
  }
301
+ if ((frame.codingSessions ?? []).length > 0) {
302
+ lines.push("");
303
+ lines.push("## live coding work");
304
+ for (const session of frame.codingSessions) {
305
+ lines.push(`- [${session.status}] ${formatCodingLaneLabel(session)}${describeCodingSessionScope(session, frame.currentSession)}`);
306
+ }
307
+ }
208
308
  // Task pressure
209
309
  if ((frame.taskPressure?.liveTaskNames ?? []).length > 0) {
210
310
  lines.push("");
@@ -140,6 +140,12 @@ function advanceObligation(agentRoot, obligationId, update) {
140
140
  if (update.currentSurface) {
141
141
  obligation.currentSurface = update.currentSurface;
142
142
  }
143
+ if (typeof update.currentArtifact === "string") {
144
+ obligation.currentArtifact = update.currentArtifact;
145
+ }
146
+ if (typeof update.nextAction === "string") {
147
+ obligation.nextAction = update.nextAction;
148
+ }
143
149
  if (typeof update.latestNote === "string") {
144
150
  obligation.latestNote = update.latestNote;
145
151
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findActivePersistentObligation = findActivePersistentObligation;
4
4
  exports.renderActiveObligationSteering = renderActiveObligationSteering;
5
+ exports.renderConcreteStatusGuidance = renderConcreteStatusGuidance;
5
6
  const runtime_1 = require("../nerves/runtime");
6
7
  function findActivePersistentObligation(frame) {
7
8
  if (!frame)
@@ -29,3 +30,58 @@ i'm already working on something i owe ${name}.${surfaceLine}
29
30
 
30
31
  i should close that loop before i act like this is a fresh blank turn.`;
31
32
  }
33
+ function formatActiveLane(frame, obligation) {
34
+ const liveCodingSession = frame.codingSessions?.[0];
35
+ if (liveCodingSession) {
36
+ const sameThread = frame.currentSession
37
+ && liveCodingSession.originSession
38
+ && liveCodingSession.originSession.friendId === frame.currentSession.friendId
39
+ && liveCodingSession.originSession.channel === frame.currentSession.channel
40
+ && liveCodingSession.originSession.key === frame.currentSession.key;
41
+ return sameThread
42
+ ? `${liveCodingSession.runner} ${liveCodingSession.id} for this same thread`
43
+ : liveCodingSession.originSession
44
+ ? `${liveCodingSession.runner} ${liveCodingSession.id} for ${liveCodingSession.originSession.channel}/${liveCodingSession.originSession.key}`
45
+ : `${liveCodingSession.runner} ${liveCodingSession.id}`;
46
+ }
47
+ return obligation.currentSurface?.label || "this live loop";
48
+ }
49
+ function formatCurrentArtifact(frame, obligation) {
50
+ return obligation.currentArtifact
51
+ || (obligation.currentSurface?.kind === "merge" ? obligation.currentSurface.label : "")
52
+ || ((frame.codingSessions ?? []).length > 0 ? "no PR or merge artifact yet" : "no explicit artifact yet");
53
+ }
54
+ function formatNextAction(frame, obligation) {
55
+ if (obligation.nextAction)
56
+ return obligation.nextAction;
57
+ const liveCodingSession = frame.codingSessions?.[0];
58
+ if (liveCodingSession?.status === "waiting_input") {
59
+ return `answer ${liveCodingSession.runner} ${liveCodingSession.id} and continue`;
60
+ }
61
+ if (liveCodingSession?.status === "stalled") {
62
+ return `unstick ${liveCodingSession.runner} ${liveCodingSession.id} and continue`;
63
+ }
64
+ if (liveCodingSession) {
65
+ return "finish the coding pass and bring the result back here";
66
+ }
67
+ if (obligation.status === "waiting_for_merge") {
68
+ return `wait for checks, merge ${formatCurrentArtifact(frame, obligation)}, then update runtime`;
69
+ }
70
+ if (obligation.status === "updating_runtime") {
71
+ return "update runtime, verify version/changelog, then re-observe";
72
+ }
73
+ return "continue the active loop and bring the result back here";
74
+ }
75
+ function renderConcreteStatusGuidance(frame, obligation) {
76
+ if (!obligation)
77
+ return "";
78
+ const activeLane = formatActiveLane(frame, obligation);
79
+ const currentArtifact = formatCurrentArtifact(frame, obligation);
80
+ const nextAction = formatNextAction(frame, obligation);
81
+ return `if someone asks what i'm doing or for status, i answer from the concrete state:
82
+ - active lane: ${activeLane}
83
+ - current artifact: ${currentArtifact}
84
+ - next action: ${nextAction}
85
+
86
+ i don't replace that with a broad mission statement if this concrete state is available.`;
87
+ }
@@ -470,7 +470,9 @@ function centerOfGravitySteeringSection(channel, options) {
470
470
  const activeObligation = (0, obligation_steering_1.findActivePersistentObligation)(frame);
471
471
  if (cog === "inward-work") {
472
472
  if (activeObligation) {
473
- return (0, obligation_steering_1.renderActiveObligationSteering)(activeObligation);
473
+ return `${(0, obligation_steering_1.renderActiveObligationSteering)(activeObligation)}
474
+
475
+ ${(0, obligation_steering_1.renderConcreteStatusGuidance)(frame, activeObligation)}`;
474
476
  }
475
477
  if (job?.status === "queued" || job?.status === "running") {
476
478
  const originClause = job.origin
@@ -494,6 +496,23 @@ if it's separate, i can be fully present here -- my inner work will wait.`;
494
496
  i've been thinking privately and reached something.${originClause}
495
497
 
496
498
  i should bring my answer back to the conversation it came from.`;
499
+ }
500
+ const liveCodingSession = frame.codingSessions?.[0];
501
+ if (liveCodingSession) {
502
+ const sameThread = frame.currentSession
503
+ && liveCodingSession.originSession
504
+ && liveCodingSession.originSession.friendId === frame.currentSession.friendId
505
+ && liveCodingSession.originSession.channel === frame.currentSession.channel
506
+ && liveCodingSession.originSession.key === frame.currentSession.key;
507
+ const scopeClause = sameThread
508
+ ? " for this same thread"
509
+ : liveCodingSession.originSession
510
+ ? ` for ${liveCodingSession.originSession.channel}/${liveCodingSession.originSession.key}`
511
+ : "";
512
+ return `## where my attention is
513
+ i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}.
514
+
515
+ i should orient around that live lane first, then decide what still needs to come back here.`;
497
516
  }
498
517
  return `## where my attention is
499
518
  i have unfinished work that needs attention before i move on.
@@ -14,6 +14,8 @@ const OBLIGATION_WAKE_UPDATE_KINDS = new Set([
14
14
  "failed",
15
15
  "killed",
16
16
  ]);
17
+ const PULL_REQUEST_NUMBER_PATTERN = /\bPR\s*#(\d+)\b/i;
18
+ const PULL_REQUEST_URL_PATTERN = /\/pull\/(\d+)(?:\b|\/)?/i;
17
19
  function clip(text, maxLength = 280) {
18
20
  const trimmed = text.trim();
19
21
  if (trimmed.length <= maxLength)
@@ -57,6 +59,61 @@ function formatSessionLabel(session) {
57
59
  : "";
58
60
  return `${session.runner} ${session.id}${origin}`;
59
61
  }
62
+ function extractPullRequestLabel(snippet) {
63
+ if (!snippet)
64
+ return null;
65
+ const numberMatch = snippet.match(PULL_REQUEST_NUMBER_PATTERN);
66
+ if (numberMatch)
67
+ return `PR #${numberMatch[1]}`;
68
+ const urlMatch = snippet.match(PULL_REQUEST_URL_PATTERN);
69
+ if (urlMatch)
70
+ return `PR #${urlMatch[1]}`;
71
+ return null;
72
+ }
73
+ function isMergedPullRequestSnippet(snippet) {
74
+ return /\bmerged\b/i.test(snippet) || /\blanded\b/i.test(snippet);
75
+ }
76
+ function deriveObligationMilestone(update) {
77
+ const snippet = pickUpdateSnippet(update);
78
+ const pullRequest = extractPullRequestLabel(snippet);
79
+ if (update.kind === "completed" && snippet && pullRequest && isMergedPullRequestSnippet(snippet)) {
80
+ return {
81
+ status: "updating_runtime",
82
+ currentSurface: { kind: "runtime", label: "ouro up" },
83
+ currentArtifact: pullRequest,
84
+ nextAction: "update runtime, verify version/changelog, then re-observe",
85
+ };
86
+ }
87
+ if (update.kind === "completed" && pullRequest) {
88
+ return {
89
+ status: "waiting_for_merge",
90
+ currentSurface: { kind: "merge", label: pullRequest },
91
+ currentArtifact: pullRequest,
92
+ nextAction: `wait for checks, merge ${pullRequest}, then update runtime`,
93
+ };
94
+ }
95
+ if (update.kind === "waiting_input") {
96
+ return {
97
+ status: "investigating",
98
+ currentSurface: { kind: "coding", label: `${update.session.runner} ${update.session.id}` },
99
+ nextAction: `answer ${update.session.runner} ${update.session.id} and continue`,
100
+ };
101
+ }
102
+ if (update.kind === "stalled") {
103
+ return {
104
+ status: "investigating",
105
+ currentSurface: { kind: "coding", label: `${update.session.runner} ${update.session.id}` },
106
+ nextAction: `unstick ${update.session.runner} ${update.session.id} and continue`,
107
+ };
108
+ }
109
+ if (update.kind === "progress" || update.kind === "spawned" || update.kind === "failed" || update.kind === "killed" || update.kind === "completed") {
110
+ return {
111
+ status: "investigating",
112
+ currentSurface: { kind: "coding", label: `${update.session.runner} ${update.session.id}` },
113
+ };
114
+ }
115
+ return null;
116
+ }
60
117
  function isSafeProgressSnippet(snippet) {
61
118
  const wordCount = snippet.split(/\s+/).filter(Boolean).length;
62
119
  return (snippet.length <= 80
@@ -94,6 +151,22 @@ function formatUpdateMessage(update) {
94
151
  return `${label} started`;
95
152
  }
96
153
  }
154
+ function formatReportBackMessage(update, baseMessage) {
155
+ if (!baseMessage)
156
+ return null;
157
+ if (!update.session.obligationId || !update.session.originSession) {
158
+ return baseMessage;
159
+ }
160
+ const milestone = deriveObligationMilestone(update);
161
+ const extraLines = [];
162
+ if (milestone?.currentArtifact) {
163
+ extraLines.push(`current artifact: ${milestone.currentArtifact}`);
164
+ }
165
+ if (milestone?.nextAction) {
166
+ extraLines.push(`next: ${milestone.nextAction}`);
167
+ }
168
+ return extraLines.length > 0 ? `${baseMessage}\n${extraLines.join("\n")}` : baseMessage;
169
+ }
97
170
  function obligationNoteFromUpdate(update) {
98
171
  const snippet = pickUpdateSnippet(update);
99
172
  switch (update.kind) {
@@ -121,10 +194,13 @@ function syncObligationFromUpdate(update) {
121
194
  const obligationId = update.session.obligationId;
122
195
  if (!obligationId)
123
196
  return;
197
+ const milestone = deriveObligationMilestone(update);
124
198
  try {
125
199
  (0, obligations_1.advanceObligation)((0, identity_1.getAgentRoot)(), obligationId, {
126
- status: "investigating",
127
- currentSurface: { kind: "coding", label: `${update.session.runner} ${update.session.id}` },
200
+ status: milestone?.status ?? "investigating",
201
+ currentSurface: milestone?.currentSurface ?? { kind: "coding", label: `${update.session.runner} ${update.session.id}` },
202
+ currentArtifact: milestone?.currentArtifact,
203
+ nextAction: milestone?.nextAction,
128
204
  latestNote: obligationNoteFromUpdate(update) ?? undefined,
129
205
  });
130
206
  }
@@ -193,10 +269,10 @@ function attachCodingSessionFeedback(manager, session, target) {
193
269
  };
194
270
  const spawnedUpdate = { kind: "spawned", session };
195
271
  syncObligationFromUpdate(spawnedUpdate);
196
- sendMessage(formatUpdateMessage(spawnedUpdate));
272
+ sendMessage(formatReportBackMessage(spawnedUpdate, formatUpdateMessage(spawnedUpdate)));
197
273
  unsubscribe = manager.subscribe(session.id, async (update) => {
198
274
  syncObligationFromUpdate(update);
199
- sendMessage(formatUpdateMessage(update));
275
+ sendMessage(formatReportBackMessage(update, formatUpdateMessage(update)));
200
276
  await wakeInnerDialogForObligation(update);
201
277
  if (TERMINAL_UPDATE_KINDS.has(update.kind)) {
202
278
  closed = true;
@@ -60,6 +60,45 @@ function findReusableCodingSession(sessions, request) {
60
60
  const matches = sessions.filter((session) => matchesReusableCodingSession(session, request)).sort(latestSessionFirst);
61
61
  return matches[0] ?? null;
62
62
  }
63
+ function isLiveCodingStatus(status) {
64
+ return status === "spawning" || status === "running" || status === "waiting_input" || status === "stalled";
65
+ }
66
+ function rankCodingStatusSession(session, currentSession) {
67
+ return sameOriginSession({
68
+ friendId: currentSession.friendId,
69
+ channel: currentSession.channel,
70
+ key: currentSession.key,
71
+ }, session.originSession)
72
+ ? 0
73
+ : 1;
74
+ }
75
+ function selectCodingStatusSessions(sessions, currentSession) {
76
+ if (sessions.length === 0)
77
+ return [];
78
+ if (!currentSession) {
79
+ return sessions;
80
+ }
81
+ const activeSessions = sessions.filter((session) => isLiveCodingStatus(session.status)).sort(latestSessionFirst);
82
+ if (activeSessions.length > 0) {
83
+ return activeSessions.sort((left, right) => {
84
+ const rankDelta = rankCodingStatusSession(left, currentSession) - rankCodingStatusSession(right, currentSession);
85
+ if (rankDelta !== 0)
86
+ return rankDelta;
87
+ return latestSessionFirst(left, right);
88
+ });
89
+ }
90
+ const matchingClosedSessions = sessions
91
+ .filter((session) => sameOriginSession({
92
+ friendId: currentSession.friendId,
93
+ channel: currentSession.channel,
94
+ key: currentSession.key,
95
+ }, session.originSession))
96
+ .sort(latestSessionFirst);
97
+ if (matchingClosedSessions.length > 0) {
98
+ return matchingClosedSessions;
99
+ }
100
+ return [...sessions].sort(latestSessionFirst);
101
+ }
63
102
  const codingSpawnTool = {
64
103
  type: "function",
65
104
  function: {
@@ -218,12 +257,12 @@ exports.codingToolDefinitions = [
218
257
  },
219
258
  {
220
259
  tool: codingStatusTool,
221
- handler: (args) => {
260
+ handler: (args, ctx) => {
222
261
  emitCodingToolEvent("coding_status");
223
262
  const manager = (0, index_1.getCodingSessionManager)();
224
263
  const sessionId = requireArg(args, "sessionId");
225
264
  if (!sessionId) {
226
- return JSON.stringify(manager.listSessions());
265
+ return JSON.stringify(selectCodingStatusSessions(manager.listSessions(), ctx?.currentSession));
227
266
  }
228
267
  const session = manager.getSession(sessionId);
229
268
  if (!session)
@@ -11,6 +11,7 @@ const continuity_1 = require("./continuity");
11
11
  const manager_1 = require("../heart/bridges/manager");
12
12
  const identity_1 = require("../heart/identity");
13
13
  const tasks_1 = require("../repertoire/tasks");
14
+ const coding_1 = require("../repertoire/coding");
14
15
  const session_activity_1 = require("../heart/session-activity");
15
16
  const active_work_1 = require("../heart/active-work");
16
17
  const delegation_1 = require("../heart/delegation");
@@ -186,12 +187,32 @@ async function handleInboundTurn(input) {
186
187
  catch {
187
188
  pendingObligations = [];
188
189
  }
190
+ let codingSessions = [];
191
+ try {
192
+ codingSessions = (0, coding_1.getCodingSessionManager)()
193
+ .listSessions()
194
+ .filter((session) => {
195
+ if (session.status !== "spawning" && session.status !== "running" && session.status !== "waiting_input" && session.status !== "stalled") {
196
+ return false;
197
+ }
198
+ if (!session.originSession) {
199
+ return false;
200
+ }
201
+ return session.originSession.friendId === currentSession.friendId
202
+ && session.originSession.channel === currentSession.channel
203
+ && session.originSession.key === currentSession.key;
204
+ });
205
+ }
206
+ catch {
207
+ codingSessions = [];
208
+ }
189
209
  const activeWorkFrame = (0, active_work_1.buildActiveWorkFrame)({
190
210
  currentSession,
191
211
  currentObligation,
192
212
  mustResolveBeforeHandoff,
193
213
  inner: readInnerWorkState(),
194
214
  bridges: activeBridges,
215
+ codingSessions,
195
216
  pendingObligations,
196
217
  taskBoard: (() => {
197
218
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.100",
3
+ "version": "0.1.0-alpha.102",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",