- Long pastes into Observe/Interpret/Apply are tagged as pasted; notes show Mine / N pasted and an own-words share. Pastes follow text through merges. - The "-> Claude" buttons on the Script stage ask first when a chunk lacks enough of the user's own (non-pasted) words. - Weekly recall card on Home: write a passage from memory, compare with notes, self-rate; recalls are saved on the chunk and synced. - Recall history on Home with an eight-week strip and the full list. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
59 lines
2.7 KiB
JavaScript
59 lines
2.7 KiB
JavaScript
import { test, expect } from 'vitest';
|
|
import { thinFields, chunksNeedingWork } from './ownWork.js';
|
|
|
|
const text = (n) => Array.from({ length: n }, (_, i) => `w${i}`).join(' ');
|
|
|
|
test('a field counts as done once it reaches its minimum word count', () => {
|
|
const chunk = { observation: text(20), interpretation: text(19), application: text(10) };
|
|
expect(thinFields(chunk).map((f) => f.field)).toEqual(['interpretation']);
|
|
});
|
|
|
|
test('empty or missing notes are all flagged', () => {
|
|
expect(thinFields({}).map((f) => f.label)).toEqual(['Observe', 'Interpret', 'Apply']);
|
|
expect(thinFields(null)).toHaveLength(3);
|
|
});
|
|
|
|
test('only chunks with something missing are returned', () => {
|
|
const done = { id: 'a', observation: text(25), interpretation: text(25), application: text(12) };
|
|
const thin = { id: 'b', observation: text(25), interpretation: '', application: text(12) };
|
|
const result = chunksNeedingWork([done, thin]);
|
|
expect(result.map((r) => r.chunk.id)).toEqual(['b']);
|
|
expect(result[0].missing[0]).toMatchObject({ label: 'Interpret', have: 0, need: 20 });
|
|
});
|
|
|
|
import { withPaste, pastedWords, ownWords, ownShare, clearPastes } from './ownWork.js';
|
|
import { mergeChunk } from './mergeStudies.js';
|
|
|
|
test('only long pastes are remembered', () => {
|
|
expect(withPaste({}, 'observation', text(5))).toBeNull();
|
|
expect(withPaste({}, 'observation', text(15))).toEqual({ observation: [text(15)] });
|
|
});
|
|
|
|
test('pasted text stops counting once it is removed from the note', () => {
|
|
const pasted = text(30);
|
|
const chunk = { observation: `my own thought ${pasted}`, aiPastes: { observation: [pasted] } };
|
|
expect(pastedWords(chunk, 'observation')).toBe(30);
|
|
expect(ownWords(chunk, 'observation')).toBe(3);
|
|
expect(ownWords({ ...chunk, observation: 'now I wrote this myself' }, 'observation')).toBe(5);
|
|
});
|
|
|
|
test('pasted words do not satisfy the own-work minimum', () => {
|
|
const pasted = text(40);
|
|
const chunk = { observation: pasted, interpretation: text(25), application: text(12), aiPastes: { observation: [pasted] } };
|
|
expect(thinFields(chunk).map((f) => f.field)).toEqual(['observation']);
|
|
});
|
|
|
|
test('the own-words share and "That\'s mine"', () => {
|
|
const pasted = text(30);
|
|
const chunk = { observation: `${text(10)} ${pasted}`, aiPastes: { observation: [pasted] } };
|
|
expect(ownShare(chunk)).toBe(25);
|
|
expect(ownShare({})).toBeNull();
|
|
expect(ownShare({ ...chunk, aiPastes: clearPastes(chunk, 'observation') })).toBe(100);
|
|
});
|
|
|
|
test('merging two copies keeps the pastes from both', () => {
|
|
const a = { id: 'x', observation: 'a', editedAt: 2, aiPastes: { observation: ['p1'] } };
|
|
const b = { id: 'x', observation: 'b', editedAt: 1, aiPastes: { observation: ['p2'] } };
|
|
expect(mergeChunk(a, b).chunk.aiPastes.observation).toEqual(['p1', 'p2']);
|
|
});
|