Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/linear/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,23 @@ describe('linear/format', () => {
heading: 'Task complete',
date: new Date('2026-06-23T00:00:00Z'),
});
expect(body.startsWith('**Task complete**')).toBe(true);
expect(body.startsWith('馃Л **[OpenSwarm] Task complete**')).toBe(true);
expect(body).toContain('_via OpenSwarm 路 2026-06-23_');
});

it('always starts with the daemon signature regardless of optional content', () => {
const inputs = [
{ heading: 'Minimal' },
{ heading: 'With summary', summary: 'Done.' },
{ heading: 'With sections', sections: [{ label: 'Result', body: 'Done.' }] },
{ heading: 'With meta', meta: { Run: '42' } },
{ heading: 'With all', summary: 'Done.', sections: [{ label: 'Result', body: 'Done.' }], meta: { Run: '42' } },
];
for (const input of inputs) {
expect(formatAutomationComment(input)).toMatch(/^馃Л \*\*\[OpenSwarm\] /);
}
});

it('keeps short facts inline and renders lists as bullets', () => {
const body = formatAutomationComment({
heading: 'Revision requested',
Expand Down
2 changes: 1 addition & 1 deletion src/linear/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export interface AutomationCommentInput {
* carrying just enough trace to find the run later.
*/
export function formatAutomationComment(input: AutomationCommentInput): string {
const parts: string[] = [`**${input.heading}**`];
const parts: string[] = [`馃Л **[OpenSwarm] ${input.heading}**`];

if (input.summary?.trim()) parts.push(input.summary.trim());

Expand Down
22 changes: 21 additions & 1 deletion src/linear/linear.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest';
import { addComment, clearLinearCache, createSubIssue, drainLinearConnection, effectCommentId, fetchIssuesForStates, getInProgressIssues, getNextBacklogIssue, initLinear, LINEAR_ACTIVE_ENRICH_CAP, LINEAR_ACTIVE_MAX_PAGES, LINEAR_ACTIVE_PAGE_SIZE, LINEAR_BACKLOG_PAGE_SIZE, LINEAR_RELATED_PAGE_SIZE, parseBlockerIdentifiers, populateBlockedBy, type LinearIssueInfo, type RawIssueNode } from './linear.js';
import { addComment, clearLinearCache, createSubIssue, drainLinearConnection, effectCommentId, fetchIssuesForStates, getInProgressIssues, getNextBacklogIssue, initLinear, logBlocked, logWorkComplete, logWorkStart, LINEAR_ACTIVE_ENRICH_CAP, LINEAR_ACTIVE_MAX_PAGES, LINEAR_ACTIVE_PAGE_SIZE, LINEAR_BACKLOG_PAGE_SIZE, LINEAR_RELATED_PAGE_SIZE, parseBlockerIdentifiers, populateBlockedBy, type LinearIssueInfo, type RawIssueNode } from './linear.js';
import { LinearClient } from '@linear/sdk';

// createSubIssue reads the module-level client singleton (getClient()), set only
Expand Down Expand Up @@ -402,3 +402,23 @@ describe('populateBlockedBy', () => {
expect(result[0].blockedBy).toBeUndefined();
});
});

describe('state-change comment ordering', () => {
it.each([
['start', logWorkStart, ['issue-1', 'agent-1'], 'In Progress'],
['complete', logWorkComplete, ['issue-1', 'agent-1', 'done'], 'Done'],
['blocked', logBlocked, ['issue-1', 'agent-1', 'reason'], 'Todo'],
])('%s comments before changing state', async (_label, action, args, expectedState) => {
const events: string[] = [];
const fakeClient = {
createComment: vi.fn(async () => { events.push('comment'); return { success: true }; }),
issue: vi.fn(async () => ({ team: Promise.resolve({ id: 'team-1' }) })),
team: vi.fn(async () => ({ states: async () => ({ nodes: [{ id: 'state-1', name: expectedState }] }) })),
updateIssue: vi.fn(async () => { events.push('state'); return { success: true }; }),
};
vi.mocked(LinearClient).mockImplementation(function (this: unknown) { return fakeClient as never; } as never);
initLinear('fake-key', 'team-1');
await (action as (...values: string[]) => Promise<void>)(...(args as string[]));
expect(events).toEqual(['comment', 'state']);
});
});
Loading