Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
6bbc2bb
Add posthog integration for error logging
kcarnold Nov 11, 2025
83a981e
staging a visual bug to check for CI workflow
Alina086 Nov 17, 2025
9478c67
draft backend and frontend error testing
kdh29 Nov 18, 2025
1b14a45
fix: update unused input parameter + comment cleanups
Alina086 Nov 25, 2025
47c920e
fix: unstage the intentional bug
Alina086 Nov 25, 2025
55efdd1
test: update baseline images
Alina086 Nov 25, 2025
a7e6dbf
chore: documenting instructions for running test
Alina086 Nov 25, 2025
bd98ce7
Merge branch 'main' of github.com:AIToolsLab/writing-tools into test/…
Alina086 Nov 25, 2025
90584ea
chore: add detailed instructions on running the test
Alina086 Nov 25, 2025
56d8e50
feat; posthog llm analytics
kdh29 Nov 25, 2025
a5e5a98
ideas from the summer
kcarnold Nov 25, 2025
d486ee1
Import experiment code that I'd prototyped in a different repo
kcarnold Dec 2, 2025
68f9974
test: set up mock backend for /api/get_suggestion endpoint
Alina086 Dec 2, 2025
de015ce
test: add playwright tests for the main flows in draft component of d…
Alina086 Dec 2, 2025
1624bc8
Initial full-experiment spike (from last night)
kcarnold Dec 2, 2025
d131067
Fix usage of ai-sdk
kcarnold Dec 2, 2025
a128514
minor tweaks
kcarnold Dec 2, 2025
96cf2a4
Merge pull request #308 from AIToolsLab/test/playwright-automation
Alina086 Dec 2, 2025
be3e596
Fix PR #316 review comments: Add TLX questions, improve logging, refa…
kcarnold Dec 2, 2025
31ff5da
backlog.md instructions for CLAUDE.md (but this takes a lot of tokens…
kcarnold Dec 2, 2025
2d8cb63
remove unused stuff in .gitignore (it was blocking adding `lib` folder)
kcarnold Dec 2, 2025
8427f40
Refactor study components: unify autoRefreshInterval handling, update…
kcarnold Dec 3, 2025
8491955
Fix typing
kcarnold Dec 3, 2025
7f10590
Bookkeeping
kcarnold Dec 3, 2025
f4cbc05
Avoid logging auto-refresh events
kcarnold Dec 3, 2025
acec051
new task
kcarnold Dec 3, 2025
ecdb7e7
Add chat message logging to ChatPanel component
kcarnold Dec 3, 2025
002c359
note that suggestions auto-update
kcarnold Dec 3, 2025
c179723
task-10 completed last night
kcarnold Dec 3, 2025
920db5d
WIP testing
kcarnold Dec 3, 2025
1474661
more WIP testing, still not quite right
kcarnold Dec 3, 2025
7fd6bf4
Add some tasks
kcarnold Dec 3, 2025
7d97646
fix testing utils
kcarnold Dec 3, 2025
1247403
add display bug task
kcarnold Dec 3, 2025
1545e63
factor out CLAUDE.md into frontend and backend.
kcarnold Dec 3, 2025
33bc1fb
Finished task 12.
kcarnold Dec 3, 2025
dbea464
Started work on task-7 but I'm not sure I really want to do this.
kcarnold Dec 3, 2025
12d6812
WIP: chat messages with timing delay
kcarnold Dec 3, 2025
3777b38
useless tests
kcarnold Dec 4, 2025
0e58939
Simplify logic, revert to streaming
kcarnold Dec 4, 2025
2806a80
update tests
kcarnold Dec 4, 2025
65b5ffc
Log the actual displayed messages
kcarnold Dec 4, 2025
3db65a3
Fix jotai nextjs Provider-less mode
kcarnold Dec 4, 2025
6e32b5d
update tasks
kcarnold Dec 4, 2025
5f9d40e
Log each message in a multi-part message, with the time it was actual…
kcarnold Dec 4, 2025
cf36ad1
Merge pull request #315 from AIToolsLab/test/update-mockbackend
Alina086 Dec 4, 2025
b6b58c7
css-fix: fix oversize sidebar (backlog task-13)
Alina086 Dec 5, 2025
2a9fc06
Fix scrolling to bottom on new messages
kcarnold Dec 5, 2025
2d64364
fix status in tests
kcarnold Dec 5, 2025
e7caebe
Make the complete_document mode visible in the UI
nghtctrl Dec 6, 2025
3e312d7
Add prompt for complete_document mode (prompt was copied over from nl…
nghtctrl Dec 6, 2025
22f6c56
Address a React Server Components vuln
kcarnold Dec 6, 2025
e89cf82
scroll-to-bottom tests
kcarnold Dec 6, 2025
b992015
Change task-14 status to Done
nghtctrl Dec 6, 2025
a386833
update system message for explicit delegation & add fake name
Alina086 Dec 8, 2025
433fa97
lowered Sarah's reading/typing speed to be more realistic, added more…
jooha-yoo Dec 8, 2025
fe99129
Merge branch 'main' into posthog
kdh29 Dec 10, 2025
b2e3dff
fix for failed lint build
kdh29 Dec 10, 2025
de1abd3
fix: address PR feedback - remove redundant PostHog init, fix package…
kdh29 Dec 16, 2025
9eb7e2f
Merge pull request #303 from AIToolsLab/posthog
kdh29 Dec 17, 2025
919583f
Revert "Merge pull request #303 from AIToolsLab/posthog"
kcarnold Dec 17, 2025
6a938f8
Build container for experiment
kcarnold Dec 19, 2025
9bb8979
need typescript (and other dev dependencies) to run build
kcarnold Dec 19, 2025
b6f250d
Simplify git commit gathering
kcarnold Dec 19, 2025
468103a
remove unused copilot instructions (copilot will find CLAUDE.md)
kcarnold Dec 19, 2025
73de977
Merge remote-tracking branch 'origin/main' into proj/measuring-thinki…
kcarnold Jan 5, 2026
561e58e
Remove Claude stuff
kcarnold Jan 5, 2026
e4ee0e1
Make security a bit more robust for using username in paths
kcarnold Jan 5, 2026
7b246d0
Try harder to avoid the security warning
kcarnold Jan 5, 2026
6f947e8
Standalone only in Docker
kcarnold Jan 5, 2026
45e0210
bump nodejs version
kcarnold Jan 5, 2026
f79c7e8
Use the same image as frontend
kcarnold Jan 5, 2026
556217b
Merge pull request #316 from AIToolsLab/proj/measuring-thinking-exper…
kcarnold Jan 5, 2026
c362d78
Vibe coded chat collapsable tab
nghtctrl Jan 6, 2026
af78feb
Remove some stuff from README
kcarnold Jan 8, 2026
7abafbb
Add auto-expand for chat after a delay
kcarnold Jan 8, 2026
384508c
Tweak the initial messages
kcarnold Jan 8, 2026
e042b98
Sarah sends a follow-up if no questions asked
kcarnold Jan 8, 2026
a9cf20c
Explain the situation a bit more
kcarnold Jan 8, 2026
be5b56b
document the purpose of the experiment for Claude
kcarnold Jan 8, 2026
a3fb85d
maybe a company tone doc
kcarnold Jan 8, 2026
640431c
Apply the edit to the correct page
kcarnold Jan 8, 2026
fa7eeba
Merge pull request #324 from AIToolsLab/separate-chat
kcarnold Jan 8, 2026
d58e95a
log to the right place
kcarnold Jan 8, 2026
2dc17d2
persist experiment logs
kcarnold Jan 8, 2026
2d1a8b4
Fix log mountpoint, since the experiment dockerfile runs everything i…
kcarnold Jan 9, 2026
32e08da
try looking up the correct GID.
kcarnold Jan 9, 2026
eec7c57
declare the GID arg in the correct stage
kcarnold Jan 9, 2026
f6c13fe
Add the nextjs user to the group
kcarnold Jan 9, 2026
c974049
Oops, syntax error
kcarnold Jan 9, 2026
b71e28a
Don't show an email address for the participant
kcarnold Jan 12, 2026
57e1dc4
Support multiple scenarios
kcarnold Jan 12, 2026
0fe5ee7
Fix some hardcoded Sarah
kcarnold Jan 12, 2026
b25154f
Update docs for configurable scenarios
kcarnold Jan 13, 2026
8d35af1
Don't need a field for From
kcarnold Jan 13, 2026
2a69ea1
bump nextjs version
kcarnold Jan 13, 2026
0dad319
Move Send button to the header
kcarnold Jan 13, 2026
4bc60d5
clarify the error message
kcarnold Jan 13, 2026
88cd598
bump model to gpt-5.2 (cheaper and better)
kcarnold Jan 13, 2026
a0c628d
remove done todos
kcarnold Jan 13, 2026
198b66a
Don't store duplicate results (usually "insufficient content" messages)
kcarnold Jan 13, 2026
cc7af8c
Bump the writing recommendation model to GPT 5.2 also
kcarnold Jan 13, 2026
239c3e0
Clarify the non-example suggestion types
kcarnold Jan 13, 2026
8cb25f0
add back a sender name
kcarnold Jan 13, 2026
ecef281
Add coverage module for vitest
kcarnold Jan 13, 2026
3b2aa35
Avoid double-logging messages by explicitly managing logging events
kcarnold Jan 13, 2026
06dea14
scroll to bottom when typing
kcarnold Jan 13, 2026
b4f50f3
simplify timer cleanup
kcarnold Jan 13, 2026
eec1af3
update tests
kcarnold Jan 13, 2026
819d6af
advanced too much
kcarnold Jan 13, 2026
45a5a81
silly linter stuff
kcarnold Jan 15, 2026
734595f
Tighten down types on study params
kcarnold Jan 15, 2026
545f52c
bump wave
kcarnold Jan 15, 2026
0ec8a1a
refactor page view to improve type safety; log the study params
kcarnold Jan 15, 2026
e53f3d9
try to flush out a logging bug, still haven't caught it
kcarnold Jan 15, 2026
599493b
Fix stale closure: we were using displayed part for the previous message
kcarnold Jan 15, 2026
917c636
buggy test
kcarnold Jan 15, 2026
b35678e
Log the AI data and response!
kcarnold Jan 15, 2026
3777a78
log the final text
kcarnold Jan 15, 2026
5313933
vibe-coded analysis scripts (based on previous analysis scripts and c…
kcarnold Jan 15, 2026
d54915f
Load scenarios from JSON for both the experiment and the log analysis
kcarnold Jan 15, 2026
7fcaf73
Fix consent form integration and details
kcarnold Jan 20, 2026
05a6185
fix up intro page
kcarnold Jan 20, 2026
4b50fdb
minor code fixups
kcarnold Jan 20, 2026
c73dc11
add a caveat about AI-generated colleague responses
kcarnold Jan 20, 2026
7b94d0d
Differentiate single-line vs multi-line text inputs in survey questions
kcarnold Jan 20, 2026
29ceecb
fix debrief questions
kcarnold Jan 20, 2026
5d84b69
fix final page
kcarnold Jan 20, 2026
f04a7ec
Emphasize "not" to use a suggestion.
kcarnold Jan 20, 2026
ede5bae
Don't bother showing suggestions if too little text
kcarnold Jan 20, 2026
c511204
Remove early prototype code
kcarnold Jan 20, 2026
91decd7
It's not a prototype anymore.
kcarnold Jan 20, 2026
29b3fa6
fill in completion code
kcarnold Jan 20, 2026
6f021fe
study URLs
kcarnold Jan 20, 2026
e4d5dcb
oops, wrong completion code
kcarnold Jan 20, 2026
11454b5
manual fixes to scenarios
kcarnold Jan 24, 2026
419b064
Update scenarios, describe why
kcarnold Jan 25, 2026
6609300
vibe-coded evals and outline
kcarnold Jan 25, 2026
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
25 changes: 4 additions & 21 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
name: Playwright Tests
name: Playwright Visual Regression Tests
on:
# push:
# branches: [ main ]
# pull_request:
# branches: [ main ]
workflow_dispatch: # Enables manual triggering only
inputs:
update-snapshots:
description: 'Update visual snapshots'
required: false
type: boolean
default: false
workflow_dispatch: # Manual trigger only

defaults:
run:
working-directory: frontend

jobs:
test:
timeout-minutes: 60
Expand All @@ -31,19 +23,10 @@ jobs:
run: npm run build
- name: Run Playwright tests
run: npx playwright test
# Playwright will automatically start the frontend via webServer config
# API calls are mocked in the test file with page.route()
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: frontend/playwright-report/
retention-days: 30
- name: Upload updated snapshots
if: github.event.inputs.update-snapshots == 'true'
uses: actions/upload-artifact@v4
with:
name: updated-snapshots
path: frontend/tests/**/*-snapshots/**
retention-days: 30

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ We follow specific GitHub conventions to keep our project organized and maintain
For detailed conventions on branch naming, commit messages, PR process, and issue management, see [CONTRIBUTING.md](CONTRIBUTING.md).

# Running visual regression tests
Run manually via Actions tab. To update baselines after UI changes, re-run with "Update visual snapshots" checked and commit the downloaded artifact as new baseline images.

The visual regression tests capture screenshots and ensure UI consistency of the application. See [VISUAL_REGRESSION.md](VISUAL_REGRESSION.md) for detailed instructions on running tests and updating baseline images.
50 changes: 50 additions & 0 deletions VISUAL_REGRESSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Visual Regression Testing Guide

This project uses Playwright to run visual regression tests that capture screenshots and compare them against baseline images. Currently, we have tests set up only for the demo page of the application.

## Running the tests

1. Navigate to the **Actions** tab in GitHub
2. Select **Playwright Visual Regression Tests** workflow
3. Click **Run workflow** button and choose the branch you wish to run tests on
4. The workflow will run tests against all browsers (Chromium, Firefox, WebKit)

## Understanding test results

- **✅ Pass**: No visual changes detected - your PR is ready for merge
- **❌ Fail**: Visual differences detected - review the changes

## Reviewing visual differences

When tests fail:

1. Go to the failed workflow run
2. Download the **playwright-report** artifact
3. Extract the artifact and open `index.html` in a browser
4. Review the visual comparison showing:
- Expected (baseline) image
- Actual (current) image
- Diff highlighting the changes

## Updating baseline images

If the UI changes are **intentional** and you want to update the baselines:

1. From the Playwright report, download the actual images for each browser
2. Replace the existing baseline images in `frontend/tests/demo-page-visual.spec.ts-snapshots/`
3. Rename downloaded images to match existing baseline names:
- `demo-page-chromium-linux.png`
- `demo-page-firefox-linux.png`
- `demo-page-webkit-linux.png`
4. Commit and push the updated baseline images
5. Re-run the visual regression test to verify it passes

## Baseline image locations

Current baseline images are stored in:
```
frontend/tests/demo-page-visual.spec.ts-snapshots/
├── demo-page-chromium-linux.png
├── demo-page-firefox-linux.png
└── demo-page-webkit-linux.png
```
2 changes: 1 addition & 1 deletion frontend/src/editor/editor.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Controls CSS for editor in all the pages (editor, demo, study) */
.editorContainer {
margin: 20px;
background: #fff;
background: #ffffff;
color: #000;
position: relative;
line-height: 20px;
Expand Down
10 changes: 3 additions & 7 deletions frontend/tests/demo-page-visual.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { test, expect } from '@playwright/test';
import { setupMockBackend } from './mockBackend';

test('demo page - visual regression', async ({ page }) => {
// Intercept API calls and return mocked responses
await page.route('/api/**', async route => {
await route.fulfill({
status: 200,
body: JSON.stringify({ message: 'mocked' })
});
});
// Setup mock backend with actual API structure
await setupMockBackend(page);

await page.goto('/');

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 145 additions & 0 deletions frontend/tests/draft-flows.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { test, expect } from '@playwright/test';
import { setupMockBackend } from './mockBackend';

test.describe('Draft component - Main flows', () => {
test.beforeEach(async ({ page }) => {
// Setup mock backend with actual API structure
await setupMockBackend(page);

// Navigate to the draft page
await page.goto('/');

// Wait for page to be ready
await expect(page.getByRole('banner')).toContainText('Thoughtful');
});

test('should display three generation option buttons', async ({ page }) => {
// Locate the draft iframe
const frame = page.frameLocator('#editor-frame');

// Verify all three generation buttons are present using title attribute
const exampleButton = frame.locator('button[title="Examples of what you could write next:"]');
const readerButton = frame.locator('button[title="Possible questions your reader might have:"]');
const adviceButton = frame.locator('button[title="Advice for your next words:"]');

await expect(exampleButton).toBeVisible();
await expect(readerButton).toBeVisible();
await expect(adviceButton).toBeVisible();
});

test('should generate and display example sentences when clicking example button', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');
const exampleButton = frame.locator('button[title="Examples of what you could write next:"]');

// Click the example sentences button
await exampleButton.click();

// Wait for and verify suggestions are displayed
await expect(frame.getByText('First example suggestion')).toBeVisible({ timeout: 5000 });
await expect(frame.getByText('Second example suggestion')).toBeVisible();
await expect(frame.getByText('Third example suggestion')).toBeVisible();
});

test('should generate and display reader perspective when clicking reader button', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');
const readerButton = frame.locator('button[title="Possible questions your reader might have:"]');

// Click the reader perspective button
await readerButton.click();

// Wait for and verify suggestions are displayed
await expect(frame.getByText('First reader perspective')).toBeVisible({ timeout: 5000 });
await expect(frame.getByText('Second reader perspective')).toBeVisible();
await expect(frame.getByText('Third reader perspective')).toBeVisible();
});

test('should generate and display advice when clicking advice button', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');
const adviceButton = frame.locator('button[title="Advice for your next words:"]');

// Click the advice button
await adviceButton.click();

// Wait for and verify suggestions are displayed
await expect(frame.getByText('First piece of advice')).toBeVisible({ timeout: 5000 });
await expect(frame.getByText('Second piece of advice')).toBeVisible();
await expect(frame.getByText('Third piece of advice')).toBeVisible();
});

test('should delete suggestion when clicking delete button', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');
const exampleButton = frame.locator('button[title="Examples of what you could write next:"]');
const readerButton = frame.locator('button[title="Possible questions your reader might have:"]');
const adviceButton = frame.locator('button[title="Advice for your next words:"]');

// Generate example suggestion
await exampleButton.click();
await expect(frame.getByText('First example suggestion')).toBeVisible({ timeout: 5000 });

// Delete example suggestion
const deleteButton1 = frame.locator('button[aria-label="Delete saved item"]').first();
await deleteButton1.click();
await expect(frame.getByText('First example suggestion')).not.toBeVisible({ timeout: 2000 });

// Generate reader perspective suggestion
await readerButton.click();
await expect(frame.getByText('First reader perspective')).toBeVisible({ timeout: 5000 });

// Delete reader perspective suggestion
const deleteButton2 = frame.locator('button[aria-label="Delete saved item"]').first();
await deleteButton2.click();
await expect(frame.getByText('First reader perspective')).not.toBeVisible({ timeout: 2000 });

// Generate advice suggestion
await adviceButton.click();
await expect(frame.getByText('First piece of advice')).toBeVisible({ timeout: 5000 });

// Delete advice suggestion
const deleteButton3 = frame.locator('button[aria-label="Delete saved item"]').first();
await deleteButton3.click();
await expect(frame.getByText('First piece of advice')).not.toBeVisible({ timeout: 2000 });
});

test('should disable buttons during loading', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');
const exampleButton = frame.locator('button[title="Examples of what you could write next:"]');
const readerButton = frame.locator('button[title="Possible questions your reader might have:"]');
const adviceButton = frame.locator('button[title="Advice for your next words:"]');

// Mock backend with delay and realistic response
await page.route('**/api/get_suggestion*', async (route) => {
await page.waitForTimeout(1000); // simulate network delay
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
result: '- First example suggestion\n\n- Second example suggestion\n\n- Third example suggestion'
}),
});
});

// Click the button to trigger request
await exampleButton.click();

// Immediately check that all buttons are disabled
await expect(exampleButton).toBeDisabled();
await expect(readerButton).toBeDisabled();
await expect(adviceButton).toBeDisabled();

// Wait for the UI to render the first suggestion
await expect(frame.locator('text=First example suggestion')).toBeVisible();

// Verify buttons are enabled again
await expect(exampleButton).toBeEnabled();
await expect(readerButton).toBeEnabled();
await expect(adviceButton).toBeEnabled();
});

test('should display empty state message when no suggestions generated', async ({ page }) => {
const frame = page.frameLocator('#editor-frame');

// Verify empty state message is shown
await expect(frame.getByText('Click the button above to generate a suggestion.')).toBeVisible();
});

});
50 changes: 50 additions & 0 deletions frontend/tests/mockBackend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Page } from '@playwright/test';

/**
* Mock backend API responses that match the actual FastAPI backend structure
*/

export interface GenerationResult {
generation_type: string;
result: string;
extra_data: Record<string, any>;
}

/**
* Setup mock backend for /api/get_suggestion endpoint
* Matches the actual backend API structure from server.py and nlp.py
*/
export async function setupMockBackend(page: Page) {
// Mock /api/get_suggestion
await page.route('**/api/get_suggestion', async (route) => {
const request = route.request();
const postData = request.postDataJSON();
const gtype = postData?.gtype;

let result = '';

switch(gtype) {
case 'example_sentences':
result = '- First example suggestion\n\n- Second example suggestion\n\n- Third example suggestion';
break;
case 'analysis_readerPerspective':
result = '- First reader perspective\n\n- Second reader perspective\n\n- Third reader perspective';
break;
case 'proposal_advice':
result = '- First piece of advice\n\n- Second piece of advice\n\n- Third piece of advice';
break;
}

const response: GenerationResult = {
generation_type: gtype || 'unknown',
result,
extra_data: {},
};

await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(response),
});
});
}
5 changes: 5 additions & 0 deletions sandbox/ideas/vis-spec.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Text editor with sidebar that has an AI conversation about the document. When the writer sends a message, the current state of the document (including what text is around the cursor) is also sent in the conversation (maybe the user chat message and the document text are given in separate XML-ish tags for the LLM). The AI is given tools to show visualizations in ASCII art, Mermaid, or plain Markdown (e.g., for a hierarchical outline or presentation slides). To start, the user presses a button to request that the AI suggest visualizations of the document content that could help them allocate their attention in their writing. The AI then responds with brief descriptions of 3 or more possible visualizations that it could make, and maybe some clarifying questions about the rhetorical situation if needed. Then the writer responds with a what visualization they desire (one of those or something different). The AI then generates that visualization.

The visualizations should include references to specific parts of the document. When the user clicks on that part of the visualization, the corresponding part of the document should highlight. When the user clicks in the document, the part of the visualization with a document reference closest to the text that's near the cursor should be highlighted, so the visualization is interactive and two way.

The AI should be very careful to ground its observations and visualizations in the specific content of the document, not generic things.
9 changes: 9 additions & 0 deletions sandbox/ideas/visualization-sys-msg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
We are powering a tool that is designed to help people write thoughtfully, with full cognitive engagement in their work, thinking about their complete rhetorical situation.

The user is currently in a "visualization" part of the tool, where the tool promises to help the writer visualize their document to help them understand what points they are making, what their current structure is, what are the concepts and relationships in their document, and many other possible visualizations. The appropriate visualization will depend on the document, the writer, and the context. The writer may not have provided us with all necessary context; we should ask for additional details as needed.

The user will provide a document that they're working on. For our initial response, we will list 3 or more possible visualizations that we could make for them, each with an example of a specific relationship or insight that they might observe if they request that visualization. We will wait for the user to request a visualization (which might be different yet from what we suggest). Then we will provide the requested visualization. We are allowed to generate Mermaid diagrams using ```mermaid fenced code blocks, ASCII art in ```pre code blocks (which will be displayed monospace), or plain Markdown (for outlines or whatever), no code block needed in that case.

We should reference specific parts of the document as much as possible. Within the body of the visualization or conversation, add a reference using Markdown numbered footnote syntax [^3]. Wait until the end of the response to include all of the footnote bodies. For each footnote body, include a verbatim quote from the document (without quotation marks) that is long enough to uniquely identify the referenced part of the document, but max of one line.

When generating a visualization, it is critical that we remain faithful to the document provided. If we ever realize that we've deviated from the document text, even slightly, we must include a remark to that effect in [square brackets] as soon as possible after the deviation.