mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* fix(chat): render cards inside execution records Render supported od-card payloads inside execution records with the existing card components, instance scopes, and browser-assistance callback. Preserve Markdown code examples and isolate card payloads from later Markdown parsing. * test(web): await writable scope before deleting a conversation * fix(web): buffer streamed card opener prefixes * fix(web): remove undesigned ChatPanel cards (OPEND-2971) Remove task-brief and rule-proposal presentation and their exclusive UI, styles, and translations following the explicit product decision. Preserve quoted card examples, neighboring prose, and the three retained card kinds, including browser-assist callbacks. * fix(chat): stop generating undesigned brief and rule cards * test(web): use supported role query options for removed cards * fix(chat): hide retired brand browser assistance cards * fix(web): hide undesigned assistant message panels * test(web): specify the brand project kind in hidden UI fixture * style(web): remove trailing blank line after panel styles * fix(web): hide verification scorecards in ChatPanel * test(chat): align retired UI expectations with approved hiding * fix(chat): keep card payloads opaque to question form parsing * fix(web): preserve card parsing across replay metadata Keep marker masking aligned with physical run boundaries, and replace repeated Markdown tail scans with a forward indexed walk. Preserve actual forms and raw code examples with replay and paragraph-boundary regression coverage. * fix(web): keep form field syntax inside its payload Recognize complete forms through the existing parser before scanning their fields for card or code markers. Preserve sibling form actions and keep outer card/code ownership with callback-based parsing that avoids an import cycle. * fix(chat): share question form protocol context with host detection --------- Co-authored-by: lefarcen <935902669@qq.com>
60 lines
2.8 KiB
TypeScript
60 lines
2.8 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { splitOnOdCards } from '../src/artifacts/od-card.js';
|
|
import { composeSystemPrompt } from '../src/prompts/system.js';
|
|
|
|
const memoryBody = '### Profile\n\nOperator audience.\n\n### Verified rules\n\nKeep spacing consistent.';
|
|
|
|
describe('OPEND-2971 contracts memory card instructions', () => {
|
|
for (const memoryHooks of [undefined, { rewrite: true, verify: true }]) {
|
|
describe(memoryHooks ? 'explicitly enabled hooks' : 'default hooks', () => {
|
|
it.each(['task-brief', 'rule-proposal'])('does not request a %s card', (kind) => {
|
|
const prompt = composeSystemPrompt({ memoryBody, memoryHooks });
|
|
|
|
expect(prompt).not.toContain(`<od-card type="${kind}">`);
|
|
});
|
|
});
|
|
}
|
|
|
|
it('retains personal memory, applied-memory chips, and rule verification', () => {
|
|
const prompt = composeSystemPrompt({ memoryBody });
|
|
|
|
expect(prompt).toContain(memoryBody);
|
|
expect(prompt).toContain('## Personal memory');
|
|
expect(prompt).toContain('<od-card type="memory-applied">');
|
|
expect(prompt).toContain('<od-card type="verify-scorecard">');
|
|
});
|
|
|
|
it('still honors the verification switch without dropping memory', () => {
|
|
const prompt = composeSystemPrompt({ memoryBody, memoryHooks: { verify: false } });
|
|
|
|
expect(prompt).toContain(memoryBody);
|
|
expect(prompt).toContain('<od-card type="memory-applied">');
|
|
expect(prompt).not.toContain('<od-card type="verify-scorecard">');
|
|
});
|
|
|
|
it('does not introduce memory cards when there is no memory', () => {
|
|
const prompt = composeSystemPrompt({ memoryBody: ' ' });
|
|
|
|
expect(prompt).not.toContain('<od-card type="task-brief">');
|
|
expect(prompt).not.toContain('<od-card type="rule-proposal">');
|
|
});
|
|
});
|
|
|
|
describe('historical od-card compatibility', () => {
|
|
it.each([
|
|
{ kind: 'task-brief', payload: { summary: 'Historic brief', fields: [{ label: 'Format', value: '16:9' }] } },
|
|
{ kind: 'rule-proposal', payload: { name: 'Historic rule', assertion: 'Keep spacing consistent', check: 'Inspect spacing' } },
|
|
{ kind: 'memory-applied', payload: { summary: 'Applied saved preferences', used: [] } },
|
|
{ kind: 'verify-scorecard', payload: { status: 'pass', rows: [{ rule: 'Spacing', status: 'pass' }] } },
|
|
{ kind: 'brand-browser-assist', payload: { brandId: 'brand-1', url: 'https://example.test' } },
|
|
])('still recognizes $kind without leaking its raw block into prose', ({ kind, payload }) => {
|
|
const raw = `<od-card type="${kind}">${JSON.stringify(payload)}</od-card>`;
|
|
const segments = splitOnOdCards(`Before.\n${raw}\nAfter.`);
|
|
|
|
expect(segments).toHaveLength(3);
|
|
expect(segments[0]).toEqual({ kind: 'text', text: 'Before.\n' });
|
|
expect(segments[1]).toMatchObject({ kind: 'card', card: { kind, ...payload }, raw });
|
|
expect(segments[2]).toEqual({ kind: 'text', text: '\nAfter.' });
|
|
});
|
|
});
|