From c6585e267fa8e650f0efa826b862b9d4a6544004 Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Mon, 21 Sep 2026 21:16:45 -0400
Subject: [PATCH 1/5] [Fix] The completion check skips every task delegated
from a Session
---
.../server/__tests__/task-completion-gate.test.ts | 13 +++++++++++++
.../cloud-agents/src/server/task-completion-gate.ts | 8 ++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
index edd27016fd..d592e4e4a2 100644
--- a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
+++ b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
@@ -179,6 +179,19 @@ describe('evaluateTaskCompletionGate', () => {
});
});
+ it('reads a request that arrived as a hidden prompt, as a delegated task gets it', async () => {
+ mockTranscript([
+ 'Remove the duplicate-call guard.\ntrue',
+ ]);
+
+ await evaluateTaskCompletionGate({ taskId: 'task-1', check });
+
+ expect(mockEvaluateDecisionModel).toHaveBeenCalledTimes(1);
+ expect(mockEvaluateDecisionModel.mock.calls[0]![0].state.request).toContain(
+ 'Remove the duplicate-call guard.',
+ );
+ });
+
it('does not repeat a lone opening prompt as its own follow-up', async () => {
mockTranscript(['Remove the duplicate-call guard.']);
diff --git a/packages/cloud-agents/src/server/task-completion-gate.ts b/packages/cloud-agents/src/server/task-completion-gate.ts
index 8705fae730..c2ba160106 100644
--- a/packages/cloud-agents/src/server/task-completion-gate.ts
+++ b/packages/cloud-agents/src/server/task-completion-gate.ts
@@ -1,5 +1,5 @@
import { redactBrainText } from '@roomote/communication/redact-brain-text';
-import { and, asc, db, desc, eq, sql, taskMessages } from '@roomote/db/server';
+import { and, asc, db, desc, eq, taskMessages } from '@roomote/db/server';
import {
ACP_ENVELOPE_EVENT_TYPES,
extractAcpMessageText,
@@ -144,6 +144,11 @@ function clip(text: string, maxChars: number): string {
* What the person asked this task for: the opening prompt and the latest
* follow-ups. Read from the transcript rather than taken from the sandbox so
* the agent cannot restate its own request.
+ *
+ * Hidden prompts count. A task delegated from a Session gets its request as
+ * a hidden `` prompt, and the harness's own reminders are never
+ * persisted as prompts, so every stored prompt is a request from a person or
+ * the Session acting for one.
*/
async function loadTaskRequests(
taskId: string,
@@ -162,7 +167,6 @@ async function loadTaskRequests(
and(
eq(taskMessages.taskId, taskId),
eq(taskMessages.eventType, ACP_ENVELOPE_EVENT_TYPES.UserPrompt),
- sql`coalesce(${taskMessages.metadata} ->> 'visibleInTranscript', 'true') <> 'false'`,
),
)
.orderBy(direction(taskMessages.ts), direction(taskMessages.createdAt))
From b201d6eee04154720d1addbce56fc513c7dbda72 Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Mon, 21 Sep 2026 21:41:36 -0400
Subject: [PATCH 2/5] Keep the harness's own reminder prompts out of the
request the check reads
---
.../__tests__/task-completion-gate.test.ts | 32 +++++++++++++++---
.../src/server/task-completion-gate.ts | 33 ++++++++++++++++---
2 files changed, 57 insertions(+), 8 deletions(-)
diff --git a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
index d592e4e4a2..02c9718371 100644
--- a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
+++ b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
@@ -25,10 +25,11 @@ vi.mock('../typesafe-judgment', () => ({
import { evaluateTaskCompletionGate } from '../task-completion-gate';
-const prompt = (text: string) => ({
+const prompt = (text: string, source?: string) => ({
id: text,
contentBlocks: [{ type: 'text', text }],
- payload: null,
+ payload: source ? { source } : null,
+ metadata: source ? { source, visibleInTranscript: false } : null,
});
/**
@@ -36,10 +37,12 @@ const prompt = (text: string) => ({
* then reads the latest plan.
*/
function mockTranscript(
- prompts: string[],
+ prompts: Array>,
options: { plan?: string; scanLimit?: number } = {},
): void {
- const rows = prompts.map(prompt);
+ const rows = prompts.map((entry) =>
+ typeof entry === 'string' ? prompt(entry) : entry,
+ );
const scanLimit = options.scanLimit ?? 12;
mockPromptRows
.mockReset()
@@ -192,6 +195,27 @@ describe('evaluateTaskCompletionGate', () => {
);
});
+ it("never reads the harness's own reminders back as requests", async () => {
+ mockTranscript([
+ 'Remove the duplicate-call guard.',
+ prompt(
+ 'Roomote automatically compared what was asked, your closing report, and everything this task changed, and flagged the following: ...',
+ 'opencode-completion-gate',
+ ),
+ prompt(
+ 'Before finalizing, post a terminal chat-visible reply.',
+ 'opencode-stop-hook',
+ ),
+ ]);
+
+ await evaluateTaskCompletionGate({ taskId: 'task-1', check });
+
+ expect(mockEvaluateDecisionModel.mock.calls[0]![0].state).toMatchObject({
+ request: 'Remove the duplicate-call guard.',
+ follow_ups: '',
+ });
+ });
+
it('does not repeat a lone opening prompt as its own follow-up', async () => {
mockTranscript(['Remove the duplicate-call guard.']);
diff --git a/packages/cloud-agents/src/server/task-completion-gate.ts b/packages/cloud-agents/src/server/task-completion-gate.ts
index c2ba160106..f7c966ddaf 100644
--- a/packages/cloud-agents/src/server/task-completion-gate.ts
+++ b/packages/cloud-agents/src/server/task-completion-gate.ts
@@ -145,11 +145,30 @@ function clip(text: string, maxChars: number): string {
* follow-ups. Read from the transcript rather than taken from the sandbox so
* the agent cannot restate its own request.
*
- * Hidden prompts count. A task delegated from a Session gets its request as
- * a hidden `` prompt, and the harness's own reminders are never
- * persisted as prompts, so every stored prompt is a request from a person or
- * the Session acting for one.
+ * Hidden prompts count: a task delegated from a Session gets its request as
+ * a hidden `` prompt. The harness's own reminders (a completion
+ * check follow-up, a chat closeout nudge) are not persisted as prompts today;
+ * should that change, their `source` keeps them out, so the check never
+ * reads its own instructions back as a request.
*/
+const HARNESS_PROMPT_SOURCE_PREFIX = 'opencode-';
+
+function isHarnessPrompt(
+ payload: Record | null,
+ metadata: unknown,
+): boolean {
+ const meta =
+ metadata && typeof metadata === 'object'
+ ? (metadata as Record)
+ : null;
+
+ return [payload?.source, meta?.source].some(
+ (source) =>
+ typeof source === 'string' &&
+ source.startsWith(HARNESS_PROMPT_SOURCE_PREFIX),
+ );
+}
+
async function loadTaskRequests(
taskId: string,
): Promise<{ request: string; followUps: string } | null> {
@@ -161,6 +180,7 @@ async function loadTaskRequests(
id: taskMessages.id,
contentBlocks: taskMessages.contentBlocks,
payload: taskMessages.payload,
+ metadata: taskMessages.metadata,
})
.from(taskMessages)
.where(
@@ -177,6 +197,11 @@ async function loadTaskRequests(
row.payload && typeof row.payload === 'object'
? (row.payload as Record)
: null;
+
+ if (isHarnessPrompt(payload, row.metadata)) {
+ return [];
+ }
+
const raw = extractAcpMessageText(row.contentBlocks, payload)?.trim();
const text = raw
? normalizeTranscriptUserText(
From eb3de9b9d6d7e696b11acd8e1cad967e361eded2 Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Mon, 21 Sep 2026 21:54:47 -0400
Subject: [PATCH 3/5] Mark the continuations the harness queues on its own so
transcript readers can tell them from requests
---
apps/worker/src/sandbox-server/lib/harness.ts | 6 ++++++
.../harnesses/__tests__/opencode-server.test.ts | 15 +++++++++++++++
.../lib/harnesses/opencode-server/harness.ts | 6 ++++++
.../lib/harnesses/runtime-prompt-queue.ts | 2 ++
.../server/__tests__/task-completion-gate.test.ts | 5 +++++
5 files changed, 34 insertions(+)
diff --git a/apps/worker/src/sandbox-server/lib/harness.ts b/apps/worker/src/sandbox-server/lib/harness.ts
index 7c811bd37a..93b4b9ad00 100644
--- a/apps/worker/src/sandbox-server/lib/harness.ts
+++ b/apps/worker/src/sandbox-server/lib/harness.ts
@@ -78,6 +78,12 @@ export interface QueuedPromptMessageSnapshot {
userName?: string;
userImageUrl?: string;
clientMessageId?: string;
+ /**
+ * Set on prompts the harness queues on its own (recovery and continuation
+ * nudges), so a reader of the transcript can tell them from a request a
+ * person or the platform sent.
+ */
+ source?: string;
timestamp: number;
}
diff --git a/apps/worker/src/sandbox-server/lib/harnesses/__tests__/opencode-server.test.ts b/apps/worker/src/sandbox-server/lib/harnesses/__tests__/opencode-server.test.ts
index f940035c7a..6b298b7c57 100644
--- a/apps/worker/src/sandbox-server/lib/harnesses/__tests__/opencode-server.test.ts
+++ b/apps/worker/src/sandbox-server/lib/harnesses/__tests__/opencode-server.test.ts
@@ -4114,6 +4114,21 @@ describe('OpenCodeServerHarness', () => {
.filter((text): text is string => typeof text === 'string')
.join('\n');
expect(secondPromptText).toContain('temporary provider rate limit');
+ // The hidden continue prompt is persisted marked as the harness's own,
+ // so transcript readers never mistake it for a request from a person.
+ expect(
+ persistedEnvelopes.find(
+ (envelope) =>
+ envelope.eventType === ACP_ENVELOPE_EVENT_TYPES.UserPrompt &&
+ String(envelope.payload.text ?? '').includes(
+ 'temporary provider rate limit',
+ ),
+ ),
+ ).toMatchObject({
+ visibleInTranscript: false,
+ metadata: { source: 'opencode-rate-limit-retry' },
+ payload: { source: 'opencode-rate-limit-retry' },
+ });
expect(
taskEvents.some(
(event) => event.eventName === TaskEventName.TaskAborted,
diff --git a/apps/worker/src/sandbox-server/lib/harnesses/opencode-server/harness.ts b/apps/worker/src/sandbox-server/lib/harnesses/opencode-server/harness.ts
index ee5178bf3e..a7e472a388 100644
--- a/apps/worker/src/sandbox-server/lib/harnesses/opencode-server/harness.ts
+++ b/apps/worker/src/sandbox-server/lib/harnesses/opencode-server/harness.ts
@@ -3900,6 +3900,7 @@ export class OpenCodeServerHarness
const queuedId = this.prompts.enqueue({
text: VISUAL_PROOF_TIMEOUT_RECOVERY_PROMPT,
visibleInTranscript: false,
+ source: 'opencode-visual-proof-recovery',
});
this.prompts.prioritize(queuedId);
@@ -3936,6 +3937,7 @@ export class OpenCodeServerHarness
this.prompts.enqueue({
text: PLAN_EXIT_CONTINUATION_PROMPT,
visibleInTranscript: false,
+ source: 'opencode-plan-exit-continuation',
});
}
@@ -4521,6 +4523,7 @@ export class OpenCodeServerHarness
const queuedId = this.prompts.enqueue({
text: recovery.promptText,
visibleInTranscript: false,
+ source: 'opencode-provider-error-recovery',
});
this.prompts.prioritize(queuedId);
this.providerErrorRecoveryQueuedPromptId = queuedId;
@@ -4582,6 +4585,7 @@ export class OpenCodeServerHarness
const queuedId = this.prompts.enqueue({
text: OPENCODE_RATE_LIMIT_RETRY_PROMPT_TEXT,
visibleInTranscript: false,
+ source: 'opencode-rate-limit-retry',
});
this.prompts.prioritize(queuedId);
@@ -6041,6 +6045,7 @@ export class OpenCodeServerHarness
userName: next.userName,
userImageUrl: next.userImageUrl,
clientMessageId: next.clientMessageId,
+ source: next.source,
});
await this.submitPrompt({
text: next.text,
@@ -6051,6 +6056,7 @@ export class OpenCodeServerHarness
userName: next.userName,
userImageUrl: next.userImageUrl,
clientMessageId: next.clientMessageId,
+ source: next.source,
});
}
diff --git a/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts b/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
index 08d2c2cf2b..c66b42cc0f 100644
--- a/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
+++ b/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
@@ -50,6 +50,7 @@ export class RuntimePromptQueue {
userName?: string;
userImageUrl?: string;
clientMessageId?: string;
+ source?: string;
}): string {
// Hidden platform follow-ups reuse one clientMessageId per logical
// notification (e.g. the PR re-review prompt for a run), so a newer
@@ -75,6 +76,7 @@ export class RuntimePromptQueue {
userName: prompt.userName,
userImageUrl: prompt.userImageUrl,
clientMessageId: prompt.clientMessageId,
+ source: prompt.source,
timestamp: Date.now(),
};
diff --git a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
index 02c9718371..849bc74de6 100644
--- a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
+++ b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
@@ -206,6 +206,11 @@ describe('evaluateTaskCompletionGate', () => {
'Before finalizing, post a terminal chat-visible reply.',
'opencode-stop-hook',
),
+ // Queued by the harness itself after a provider rate limit.
+ prompt(
+ 'Continue where you left off after the temporary provider rate limit.',
+ 'opencode-rate-limit-retry',
+ ),
]);
await evaluateTaskCompletionGate({ taskId: 'task-1', check });
From 81530030071fd86ccbec69642f0ed54a6fd9d0c1 Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Mon, 21 Sep 2026 22:00:22 -0400
Subject: [PATCH 4/5] Keep a queued prompt's source across a queue restore
---
.../__tests__/runtime-prompt-queue.test.ts | 19 +++++++++++++++++++
.../lib/harnesses/runtime-prompt-queue.ts | 1 +
2 files changed, 20 insertions(+)
diff --git a/apps/worker/src/sandbox-server/lib/harnesses/__tests__/runtime-prompt-queue.test.ts b/apps/worker/src/sandbox-server/lib/harnesses/__tests__/runtime-prompt-queue.test.ts
index 35a3ae7330..4bc8c47216 100644
--- a/apps/worker/src/sandbox-server/lib/harnesses/__tests__/runtime-prompt-queue.test.ts
+++ b/apps/worker/src/sandbox-server/lib/harnesses/__tests__/runtime-prompt-queue.test.ts
@@ -84,6 +84,25 @@ describe('RuntimePromptQueue', () => {
});
});
+ describe('restore', () => {
+ it('keeps the harness source of a hidden continuation across a restore', () => {
+ const original = createQueue();
+ original.queue.enqueue({
+ text: 'Continue where you left off after the temporary provider rate limit.',
+ visibleInTranscript: false,
+ source: 'opencode-rate-limit-retry',
+ });
+
+ const restored = createQueue();
+ restored.queue.restore(original.queue.snapshot());
+
+ expect(restored.queue.dequeue()).toMatchObject({
+ visibleInTranscript: false,
+ source: 'opencode-rate-limit-retry',
+ });
+ });
+ });
+
describe('clear', () => {
it('removes all queued messages', () => {
const { queue } = createQueue();
diff --git a/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts b/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
index c66b42cc0f..eae2d4ce2f 100644
--- a/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
+++ b/apps/worker/src/sandbox-server/lib/harnesses/runtime-prompt-queue.ts
@@ -249,6 +249,7 @@ export class RuntimePromptQueue {
...(message.clientMessageId
? { clientMessageId: message.clientMessageId }
: {}),
+ ...(message.source ? { source: message.source } : {}),
timestamp: message.timestamp,
}));
this.queuedMessageIdCounter = this.queuedMessages.reduce(
From 293dae156294e9d42cfdd25476505fce7bf699f4 Mon Sep 17 00:00:00 2001
From: Matt Rubens <2600+mrubens@users.noreply.github.com>
Date: Mon, 21 Sep 2026 22:06:45 -0400
Subject: [PATCH 5/5] Count a hidden prompt only as the opening request, never
as a follow-up
---
.../__tests__/task-completion-gate.test.ts | 45 +++++++++----
.../src/server/task-completion-gate.ts | 64 ++++++++++++-------
2 files changed, 73 insertions(+), 36 deletions(-)
diff --git a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
index 849bc74de6..43d12847d0 100644
--- a/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
+++ b/packages/cloud-agents/src/server/__tests__/task-completion-gate.test.ts
@@ -25,11 +25,17 @@ vi.mock('../typesafe-judgment', () => ({
import { evaluateTaskCompletionGate } from '../task-completion-gate';
-const prompt = (text: string, source?: string) => ({
+const prompt = (
+ text: string,
+ options: { source?: string; hidden?: boolean } = {},
+) => ({
id: text,
contentBlocks: [{ type: 'text', text }],
- payload: source ? { source } : null,
- metadata: source ? { source, visibleInTranscript: false } : null,
+ payload: options.source ? { source: options.source } : null,
+ metadata: {
+ ...(options.source ? { source: options.source } : {}),
+ ...(options.hidden || options.source ? { visibleInTranscript: false } : {}),
+ },
});
/**
@@ -184,7 +190,10 @@ describe('evaluateTaskCompletionGate', () => {
it('reads a request that arrived as a hidden prompt, as a delegated task gets it', async () => {
mockTranscript([
- 'Remove the duplicate-call guard.\ntrue',
+ prompt(
+ 'Standard task workflow.\nRemove the duplicate-call guard.',
+ { hidden: true },
+ ),
]);
await evaluateTaskCompletionGate({ taskId: 'task-1', check });
@@ -195,29 +204,41 @@ describe('evaluateTaskCompletionGate', () => {
);
});
- it("never reads the harness's own reminders back as requests", async () => {
+ it('reads only visible follow-ups, never notices or reminders', async () => {
mockTranscript([
'Remove the duplicate-call guard.',
prompt(
'Roomote automatically compared what was asked, your closing report, and everything this task changed, and flagged the following: ...',
- 'opencode-completion-gate',
- ),
- prompt(
- 'Before finalizing, post a terminal chat-visible reply.',
- 'opencode-stop-hook',
+ { source: 'opencode-completion-gate' },
),
+ prompt('Before finalizing, post a terminal chat-visible reply.', {
+ source: 'opencode-stop-hook',
+ }),
// Queued by the harness itself after a provider rate limit.
prompt(
'Continue where you left off after the temporary provider rate limit.',
- 'opencode-rate-limit-retry',
+ { source: 'opencode-rate-limit-retry' },
),
+ // A platform notice, hidden, with its own source.
+ prompt('The environment setup finished; the snapshot is ready.', {
+ source: 'environment-setup',
+ }),
+ // A hidden follow-up with no source at all still never counts.
+ prompt(
+ 'The visual proof step exceeded its shared five-minute deadline.',
+ {
+ hidden: true,
+ },
+ ),
+ // A person's follow-up is visible and does count.
+ 'Also drop the helper.',
]);
await evaluateTaskCompletionGate({ taskId: 'task-1', check });
expect(mockEvaluateDecisionModel.mock.calls[0]![0].state).toMatchObject({
request: 'Remove the duplicate-call guard.',
- follow_ups: '',
+ follow_ups: 'Also drop the helper.',
});
});
diff --git a/packages/cloud-agents/src/server/task-completion-gate.ts b/packages/cloud-agents/src/server/task-completion-gate.ts
index f7c966ddaf..56d10c4900 100644
--- a/packages/cloud-agents/src/server/task-completion-gate.ts
+++ b/packages/cloud-agents/src/server/task-completion-gate.ts
@@ -145,24 +145,35 @@ function clip(text: string, maxChars: number): string {
* follow-ups. Read from the transcript rather than taken from the sandbox so
* the agent cannot restate its own request.
*
- * Hidden prompts count: a task delegated from a Session gets its request as
- * a hidden `` prompt. The harness's own reminders (a completion
- * check follow-up, a chat closeout nudge) are not persisted as prompts today;
- * should that change, their `source` keeps them out, so the check never
- * reads its own instructions back as a request.
+ * The opening prompt counts whether or not it is visible: a task delegated
+ * from a Session gets its request as a hidden `` prompt. Later
+ * hidden prompts never count. Those are the platform's and the harness's own
+ * notices (an environment-setup notice, a recovery or continuation nudge, a
+ * completion-check reminder), and reading one back as a follow-up would have
+ * the check judging its own instructions. A person's follow-up, from the web
+ * or a chat thread, is always visible.
*/
const HARNESS_PROMPT_SOURCE_PREFIX = 'opencode-';
-function isHarnessPrompt(
- payload: Record | null,
- metadata: unknown,
-): boolean {
- const meta =
- metadata && typeof metadata === 'object'
- ? (metadata as Record)
- : null;
+type PromptRow = {
+ id: string;
+ contentBlocks: unknown;
+ payload: unknown;
+ metadata: unknown;
+};
+
+function asRecord(value: unknown): Record | null {
+ return value && typeof value === 'object'
+ ? (value as Record)
+ : null;
+}
- return [payload?.source, meta?.source].some(
+function isHiddenPrompt(row: PromptRow): boolean {
+ return asRecord(row.metadata)?.visibleInTranscript === false;
+}
+
+function isHarnessPrompt(row: PromptRow): boolean {
+ return [asRecord(row.payload)?.source, asRecord(row.metadata)?.source].some(
(source) =>
typeof source === 'string' &&
source.startsWith(HARNESS_PROMPT_SOURCE_PREFIX),
@@ -191,18 +202,23 @@ async function loadTaskRequests(
)
.orderBy(direction(taskMessages.ts), direction(taskMessages.createdAt))
.limit(PROMPT_SCAN_LIMIT);
- const visiblePrompts = (rows: Awaited>) =>
+ const requestPrompts = (
+ rows: PromptRow[],
+ options: { includeHidden: boolean },
+ ) =>
rows.flatMap((row) => {
- const payload =
- row.payload && typeof row.payload === 'object'
- ? (row.payload as Record)
- : null;
-
- if (isHarnessPrompt(payload, row.metadata)) {
+ if (
+ isHarnessPrompt(row) ||
+ (!options.includeHidden && isHiddenPrompt(row))
+ ) {
return [];
}
- const raw = extractAcpMessageText(row.contentBlocks, payload)?.trim();
+ const payload = asRecord(row.payload);
+ const raw = extractAcpMessageText(
+ row.contentBlocks as Parameters[0],
+ payload,
+ )?.trim();
const text = raw
? normalizeTranscriptUserText(
isSystemInjectedAcpPromptText(raw)
@@ -215,13 +231,13 @@ async function loadTaskRequests(
return text ? [{ id: row.id, text }] : [];
});
- const [opening] = visiblePrompts(await scan(asc));
+ const [opening] = requestPrompts(await scan(asc), { includeHidden: true });
if (!opening) {
return null;
}
- const followUps = visiblePrompts(await scan(desc))
+ const followUps = requestPrompts(await scan(desc), { includeHidden: false })
.filter((prompt) => prompt.id !== opening.id)
.slice(0, FOLLOW_UP_LIMIT)
.reverse();