fix(hub): delivered-Nachrichten bleiben im Check-in sichtbar
`delivered` heißt nur "einmal ausgeliefert", nicht "gelesen" — abgeschlossen ist eine Nachricht erst mit read/acked. Der Check-in filterte aber auf `unread` und ließ damit jede Nachricht fallen, die irgendwo schon einmal aufgetaucht war (etwa beim Session-Start), ohne dass der Agent sie je beantwortet hätte. Real aufgefallen an einer Architekten-Korrektur an kimi: Status `delivered`, im pending-Block unsichtbar — die Korrektur wäre still verlorengegangen. Genau der Fehlermodus, gegen den der Kanal gebaut wurde. Tests: 292 → 294. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a6f640242a
commit
4be0826a6f
@ -135,7 +135,15 @@ export function resolvePending(
|
||||
}
|
||||
}
|
||||
|
||||
const unread = listMessages(cwd).filter((m) => m.status === 'unread' && isMine(m.to));
|
||||
// `unread` UND `delivered`: `delivered` heißt nur "einmal ausgeliefert", nicht
|
||||
// "gelesen" — erst read/acked schließt eine Nachricht ab. Filterte man hier
|
||||
// auf `unread`, verschwände jede Nachricht aus dem Rückkanal, sobald sie
|
||||
// einmal irgendwo aufgetaucht ist (z. B. beim Session-Start), ohne dass der
|
||||
// Agent sie je beantwortet hat. Real passiert bei einer Architekten-Korrektur
|
||||
// an kimi: Status `delivered`, im Check-in unsichtbar.
|
||||
const unread = listMessages(cwd).filter(
|
||||
(m) => (m.status === 'unread' || m.status === 'delivered') && isMine(m.to),
|
||||
);
|
||||
pending.unreadCount = unread.length;
|
||||
pending.messages = unread.slice(-MAX_MESSAGE_PREVIEWS).map((m) => ({
|
||||
id: m.id,
|
||||
@ -145,7 +153,7 @@ export function resolvePending(
|
||||
|
||||
const parts: string[] = [];
|
||||
if (pending.interrupted) parts.push(pending.interrupted.action);
|
||||
if (pending.unreadCount > 0) parts.push(`${pending.unreadCount} ungelesene Nachricht(en) — agenthub_inbox lesen und antworten.`);
|
||||
if (pending.unreadCount > 0) parts.push(`${pending.unreadCount} unbeantwortete Nachricht(en) — agenthub_inbox lesen, beantworten und mit agenthub_message quittieren.`);
|
||||
if (pending.answeredAsks.length > 0) parts.push(`Deine Frage(n) ${pending.answeredAsks.map((a) => a.id).join(', ')} sind BEANTWORTET — lies die Antwort, bevor du weiterbaust.`);
|
||||
if (pending.waitingTasks.length > 0) parts.push(`Offen für dich: ${pending.waitingTasks.join(', ')}.`);
|
||||
if (parts.length > 0) pending.note = parts.join(' ');
|
||||
|
||||
@ -3,7 +3,7 @@ import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { createTask, claimTask, reviewTask, reopenTask, cancelTask, assignTask } from '../src/core/services/taskService.js';
|
||||
import { createMessage } from '../src/core/services/messageService.js';
|
||||
import { createMessage, markMessageDelivered } from '../src/core/services/messageService.js';
|
||||
import { resolvePending, hasPending } from '../src/core/services/checkinService.js';
|
||||
import { createAsk, answerAsk } from '../src/core/services/askService.js';
|
||||
|
||||
@ -98,7 +98,7 @@ describe('resolvePending — Nachrichten und Zuweisungen', () => {
|
||||
expect(pending.unreadCount).toBe(1);
|
||||
expect(pending.messages[0]?.from).toBe('claude');
|
||||
expect(pending.messages[0]?.preview).toContain('Reihenfolge');
|
||||
expect(pending.note).toMatch(/ungelesene/i);
|
||||
expect(pending.note).toMatch(/unbeantwortete/i);
|
||||
});
|
||||
|
||||
it('nennt offene, an den Agenten adressierte Tasks', () => {
|
||||
@ -156,3 +156,17 @@ describe('resolvePending — beantwortete Fragen (Ask-Timeout-Lücke)', () => {
|
||||
expect(resolvePending(cwd, 'kimi').answeredAsks).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolvePending — `delivered` zaehlt weiter', () => {
|
||||
it('zeigt eine bereits ausgelieferte, aber unbeantwortete Nachricht weiter an', () => {
|
||||
const msg = createMessage(cwd, { from: 'claude', to: 'kimi', text: 'Korrektur: nimm doch Variante A.' });
|
||||
markMessageDelivered(cwd, msg.id);
|
||||
|
||||
const pending = resolvePending(cwd, 'kimi');
|
||||
|
||||
// `delivered` heisst nur "einmal aufgetaucht". Filterte der Check-in auf
|
||||
// `unread`, ginge eine Architekten-Korrektur still verloren.
|
||||
expect(pending.unreadCount).toBe(1);
|
||||
expect(hasPending(pending)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user