mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 10:50:38 +09:00
[codex] Add runtime lifecycle recovery and live issue visibility (#4419)
This commit is contained in:
parent
9a8d219949
commit
5a0c1979cf
121 changed files with 9625 additions and 2044 deletions
|
|
@ -318,6 +318,50 @@ describe("IssueChatThread", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("shows explicit follow-up badges and event copy", () => {
|
||||
const root = createRoot(container);
|
||||
|
||||
act(() => {
|
||||
root.render(
|
||||
<MemoryRouter>
|
||||
<IssueChatThread
|
||||
comments={[{
|
||||
id: "comment-1",
|
||||
companyId: "company-1",
|
||||
issueId: "issue-1",
|
||||
authorAgentId: null,
|
||||
authorUserId: "local-board",
|
||||
body: "Please continue validation.",
|
||||
followUpRequested: true,
|
||||
createdAt: new Date("2026-03-11T10:00:00.000Z"),
|
||||
updatedAt: new Date("2026-03-11T10:00:00.000Z"),
|
||||
}]}
|
||||
linkedRuns={[]}
|
||||
timelineEvents={[{
|
||||
id: "event-1",
|
||||
actorType: "agent",
|
||||
actorId: "agent-1",
|
||||
createdAt: new Date("2026-03-11T10:00:00.000Z"),
|
||||
commentId: "comment-1",
|
||||
followUpRequested: true,
|
||||
}]}
|
||||
liveRuns={[]}
|
||||
onAdd={async () => {}}
|
||||
showComposer={false}
|
||||
enableLiveTranscriptPolling={false}
|
||||
/>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(container.textContent).toContain("Follow-up");
|
||||
expect(container.textContent).toContain("requested follow-up");
|
||||
|
||||
act(() => {
|
||||
root.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it("shows unresolved blocker context above the composer", () => {
|
||||
const root = createRoot(container);
|
||||
|
||||
|
|
@ -359,6 +403,59 @@ describe("IssueChatThread", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("shows terminal blocker context when an immediate blocker is transitively blocked", () => {
|
||||
const root = createRoot(container);
|
||||
|
||||
act(() => {
|
||||
root.render(
|
||||
<MemoryRouter>
|
||||
<IssueChatThread
|
||||
comments={[]}
|
||||
linkedRuns={[]}
|
||||
timelineEvents={[]}
|
||||
liveRuns={[]}
|
||||
issueStatus="blocked"
|
||||
blockedBy={[
|
||||
{
|
||||
id: "blocker-1",
|
||||
identifier: "PAP-2167",
|
||||
title: "Phase 7 review",
|
||||
status: "blocked",
|
||||
priority: "medium",
|
||||
assigneeAgentId: "agent-1",
|
||||
assigneeUserId: null,
|
||||
terminalBlockers: [
|
||||
{
|
||||
id: "terminal-1",
|
||||
identifier: "PAP-2201",
|
||||
title: "Security sign-off",
|
||||
status: "todo",
|
||||
priority: "high",
|
||||
assigneeAgentId: "agent-2",
|
||||
assigneeUserId: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
onAdd={async () => {}}
|
||||
enableLiveTranscriptPolling={false}
|
||||
/>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(container.textContent).toContain("PAP-2167");
|
||||
expect(container.textContent).toContain("Phase 7 review");
|
||||
expect(container.textContent).toContain("Ultimately waiting on");
|
||||
expect(container.textContent).toContain("PAP-2201");
|
||||
expect(container.textContent).toContain("Security sign-off");
|
||||
expect(container.querySelector('[data-issue-path-id="PAP-2201"]')).not.toBeNull();
|
||||
|
||||
act(() => {
|
||||
root.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it("shows paused assigned agent context above the composer", () => {
|
||||
const root = createRoot(container);
|
||||
const pausedAgent = {
|
||||
|
|
@ -1363,6 +1460,66 @@ describe("IssueChatThread", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("keeps a running chain-of-thought in the Working state between commands", () => {
|
||||
const root = createRoot(container);
|
||||
|
||||
act(() => {
|
||||
root.render(
|
||||
<MemoryRouter>
|
||||
<IssueChatThread
|
||||
comments={[]}
|
||||
linkedRuns={[]}
|
||||
timelineEvents={[]}
|
||||
liveRuns={[{
|
||||
id: "run-1",
|
||||
issueId: "issue-1",
|
||||
status: "running",
|
||||
invocationSource: "comment",
|
||||
triggerDetail: null,
|
||||
startedAt: "2026-04-06T12:00:00.000Z",
|
||||
finishedAt: null,
|
||||
createdAt: "2026-04-06T12:00:00.000Z",
|
||||
agentId: "agent-1",
|
||||
agentName: "Agent 1",
|
||||
adapterType: "codex_local",
|
||||
}]}
|
||||
transcriptsByRunId={new Map([
|
||||
[
|
||||
"run-1",
|
||||
[
|
||||
{
|
||||
kind: "tool_call",
|
||||
ts: "2026-04-06T12:00:10.000Z",
|
||||
name: "command_execution",
|
||||
toolUseId: "tool-1",
|
||||
input: { command: "pnpm test" },
|
||||
},
|
||||
{
|
||||
kind: "tool_result",
|
||||
ts: "2026-04-06T12:00:20.000Z",
|
||||
toolUseId: "tool-1",
|
||||
toolName: "command_execution",
|
||||
content: "Tests passed",
|
||||
isError: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
])}
|
||||
onAdd={async () => {}}
|
||||
enableLiveTranscriptPolling={false}
|
||||
/>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(container.textContent).toContain("Working");
|
||||
expect(container.textContent).not.toContain("Worked");
|
||||
|
||||
act(() => {
|
||||
root.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it("folds chain-of-thought when the same message transitions from running to complete", () => {
|
||||
expect(resolveAssistantMessageFoldedState({
|
||||
messageId: "message-1",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue