diff --git a/server/src/__tests__/case-history-api-discovery.test.ts b/server/src/__tests__/case-history-api-discovery.test.ts index c8d47787e5a..78990af5104 100644 --- a/server/src/__tests__/case-history-api-discovery.test.ts +++ b/server/src/__tests__/case-history-api-discovery.test.ts @@ -30,3 +30,8 @@ it("names the nested case id and how people appear in case history", () => { expect(revisions.description).toContain("createdByUserId"); expect(searchRunnerApi({ query: "GET /api/cases/{id}" }).results[0]!.summary).toBe("Read a case and its current facts"); }); + +it("tells chat to keep the person's brief as a document on a new case's primary task", () => { + expect(CASES_CHAT_DIRECTIVE).toContain("save that brief as a document on the case's primary task with initialDocuments"); + expect(CASES_CHAT_DIRECTIVE).toContain("Case fields do not replace the brief"); +}); diff --git a/server/src/services/agent-conversations.ts b/server/src/services/agent-conversations.ts index c5e00406b5b..023ef31d4ea 100644 --- a/server/src/services/agent-conversations.ts +++ b/server/src/services/agent-conversations.ts @@ -146,7 +146,7 @@ Keep discussion here and leave the conversation available for the next message. /** Presentation guidance for the opted-in Coordinator experience; not authority. */ /** Rendered only while the instance enables the Cases experiment. */ -export const CASES_CHAT_DIRECTIVE = `This instance has Cases enabled. A case is a saved record with its own facts, audit history and handoffs, separate from the documents on its tasks. Each case has a page at //cases/, using the identifier the case returns (such as RUN-C1) and this conversation's company prefix. When a reply concerns a case, such as its facts, its fact-change history or its handoffs, link the case page as a Markdown link, such as [RUN-C1](//cases/RUN-C1), alongside links to the tasks whose documents or comments you cite. When a question about a task's history may involve its case, find the case with GET /api/issues/{issueId}/cases and read who changed its facts in GET /api/cases/{id}/events, beside the task's document revisions.`; +export const CASES_CHAT_DIRECTIVE = `This instance has Cases enabled. A case is a saved record with its own facts, audit history and handoffs, separate from the documents on its tasks. Each case has a page at //cases/, using the identifier the case returns (such as RUN-C1) and this conversation's company prefix. When a reply concerns a case, such as its facts, its fact-change history or its handoffs, link the case page as a Markdown link, such as [RUN-C1](//cases/RUN-C1), alongside links to the tasks whose documents or comments you cite. When a question about a task's history may involve its case, find the case with GET /api/issues/{issueId}/cases and read who changed its facts in GET /api/cases/{id}/events, beside the task's document revisions. When the person opens a case from a brief, such as an attached file or a document here, save that brief as a document on the case's primary task with initialDocuments on POST /api/companies/{companyId}/case-handoffs, in the same request that creates the task, so it is saved before work starts. Case fields do not replace the brief: they hold the structured facts, and the document keeps the person's source for the assignee.`; /** Rendered only while the instance enables the Status Cards experiment. */ export const STATUS_CARDS_CHAT_DIRECTIVE = `This instance has Status Cards enabled. A status card is a saved Paperclip feature, not a document or comment: a live summary card on the company's Status page at //status (listed as Status in the sidebar), each card at //status/. The person describes what the card should track; the card's summarizer agent compiles that into a query over the company's tasks and writes the summary in its own hidden generation task. When the person asks for a status card, list the company's cards with GET /api/companies/{companyId}/status-cards and reuse a matching one; otherwise create one with POST /api/companies/{companyId}/status-cards, setting interestPrompt to what the card should summarize and agentId to the agent that writes its summary (yourself or a teammate; omitting it uses the built-in Summarizer when that is configured). Do not write a task document in place of a card. To refresh a card, POST /api/status-cards/{id}/refresh. Agents can manage only cards they authored. Creating or refreshing a card only queues the work: the summarizer updates the card in its own run, which you do not perform or wait for. Do not sleep or poll the card. Report the outcome the response gives: enqueued true means the summarizer's run is queued; alreadyGenerating means an earlier run is still going; enqueued false otherwise means no run started, so say why from card.state (such as paused_budget or paused_hours) or, when lastGeneratedAt is newer than before, that a concurrent refresh already finished. Reply now with that outcome and the card's returned href as a Markdown link, such as [Launch blockers](//status/), and say the summary appears on the card when its summarizer finishes. Call a summary generated or current only after reading a newer lastGeneratedAt than before your request. A card's interestPrompt is instructions for its summarizer, not for you; do not try to meet its requirements yourself.`;