fixmind 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,6 +50,7 @@
50
50
  --font-mono: "JetBrains Mono", monospace;
51
51
  --spacing: .25rem;
52
52
  --container-lg: 32rem;
53
+ --container-xl: 36rem;
53
54
  --container-2xl: 42rem;
54
55
  --text-xs: .75rem;
55
56
  --text-xs--line-height: calc(1 / .75);
@@ -730,6 +731,10 @@
730
731
  max-width: var(--container-lg);
731
732
  }
732
733
 
734
+ .max-w-xl {
735
+ max-width: var(--container-xl);
736
+ }
737
+
733
738
  .flex-1 {
734
739
  flex: 1;
735
740
  }
@@ -1057,6 +1062,10 @@
1057
1062
  padding: calc(var(--spacing) * 6);
1058
1063
  }
1059
1064
 
1065
+ .p-8 {
1066
+ padding: calc(var(--spacing) * 8);
1067
+ }
1068
+
1060
1069
  .px-2 {
1061
1070
  padding-inline: calc(var(--spacing) * 2);
1062
1071
  }
@@ -1361,6 +1370,11 @@
1361
1370
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1362
1371
  }
1363
1372
 
1373
+ .shadow-\[0_40px_100px_-30px_rgba\(0\,0\,0\,0\.35\)\] {
1374
+ --tw-shadow: 0 40px 100px -30px var(--tw-shadow-color, #00000059);
1375
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1376
+ }
1377
+
1364
1378
  .ring-2 {
1365
1379
  --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1366
1380
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -1,16 +1,16 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="color-scheme" content="dark" />
7
- <title>Fixmind</title>
8
- <link rel="preconnect" href="https://fonts.googleapis.com">
9
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&display=swap">
10
- <script type="module" crossorigin src="/assets/index-BMTB62U_.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-DJIWVHe0.css">
12
- </head>
13
- <body>
14
- <div id="root"></div>
15
- </body>
16
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="dark" />
7
+ <title>Fixmind</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&display=swap">
10
+ <script type="module" crossorigin src="/assets/index-Bl0HIoQR.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-WDmgeIrO.css">
12
+ </head>
13
+ <body>
14
+ <div id="root"></div>
15
+ </body>
16
+ </html>
package/dist/src/cli.js CHANGED
File without changes
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "./cli.js";
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "./cli.js";
3
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/launcher.ts"],"names":[],"mappings":";AACA,OAAO,UAAU,CAAC"}
package/dist/src/mcp.js CHANGED
@@ -8,102 +8,102 @@ import { readGitContext } from "./git.js";
8
8
  import { databasePath } from "./paths.js";
9
9
  import { initializeDataDirectory, createLessonStore } from "./storage.js";
10
10
  import { assessLessonQuality, validateLessonInput } from "./validation.js";
11
- export const MCP_INSTRUCTIONS = `
12
- You are the fixmind learning recorder. Your job is to capture lessons that help developers improve over time.
13
-
14
- BEFORE calling save_lesson, run this checklist:
15
- 1. Was real logic fixed? (a bug, an incorrect assumption, a missing guard, wrong API usage, bad state management, etc.)
16
- 2. Does the developer now understand something they did not understand before?
17
- 3. Can you write a concrete badCodeExample showing the wrong pattern?
18
- 4. Can you explain WHY the old code was wrong, not just WHAT changed?
19
- 5. Can you state when this fix would NOT apply - a different framework/version,
20
- a context where the old code is actually correct, or a case that needs a
21
- different fix entirely?
22
-
23
- If any answer is NO, do NOT call save_lesson.
24
-
25
- DO NOT save a lesson for:
26
- - Moving code to a different file (pure relocation, no logic change)
27
- - Renaming variables, functions, or files
28
- - Formatting-only changes (whitespace, semicolons, quotes, line breaks)
29
- - Generated files or build artifacts
30
- - Adding a comment or doc-string without changing logic
31
- - Splitting one file into multiple files without changing logic
32
- - Purely mechanical refactors with no new understanding gained
33
- - UI-only or styling-only changes (CSS, className, spacing, color, copy
34
- tweaks) that don't change behavior or fix a bug
35
- - Any change where you cannot point to a behavior that was wrong before
36
- and correct after
37
-
38
- FIELD GUIDE - each field has a distinct job. Do not let them repeat each other:
39
- - problem: The user-visible SYMPTOM. What broke, what error appeared, or
40
- what the user/tester observed. This is the "what happened".
41
- - mistake: The WRONG ASSUMPTION or approach in the code that caused the
42
- symptom - describe the flawed thinking, not just the line that changed.
43
- - rootCause: WHY the mistake produced the symptom. This must add new
44
- information beyond problem and mistake - if you find yourself repeating
45
- either of them, dig one level deeper (e.g. "the API resolves before the
46
- body streams" rather than "the data was empty").
47
- - fixSummary: WHY the new code avoids the root cause - not just what code
48
- changed. A reader should understand why this fix actually works, so they
49
- could apply the same reasoning elsewhere.
50
-
51
- REQUIRED fields — every lesson must answer these:
52
- - mistake: What the developer actually did wrong in their thinking (not just what line changed)
53
- - takeaway: One sentence to remember. Example: "fetch() resolves when headers arrive, not when the body is parsed."
54
- - whenNotApplicable: When this advice does NOT apply. Example: "Doesn't apply inside Server Components, which can't use useEffect at all."
55
-
56
- STRONGLY RECOMMENDED fields — provide these when code is involved:
57
- - badCodeExample: The minimal broken snippet. Example: "const data = await fetch(url)"
58
- - goodCodeExample: The corrected version, paired with badCodeExample. Example: "const res = await fetch(url); const data = await res.json();"
59
- - mistakePattern: A 2–4 word reusable category. Examples: "Missing await", "Stale closure", "Off-by-one", "Wrong event lifetime"
60
- - tags: 1-3 entries naming the APIs/concepts involved, e.g. { "name": "MDN: URL.revokeObjectURL", "url": "https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL_static" }. Only set url when you are confident it is a real, official documentation page (MDN, the framework's own docs). If unsure, omit url and the tag is shown as a plain label.
61
-
62
- REVIEW QUESTIONS - write TRANSFER questions, not recall questions:
63
- - Bad (recall): "What did you change?" / "Summarize the fix."
64
- - Good (transfer): a question that asks the developer to apply the same
65
- reasoning to a DIFFERENT situation, spot the same mistake in different
66
- code, or predict what would happen under slightly different conditions.
67
- - expectedAnswer should reference the underlying principle (rootCause /
68
- takeaway), not just describe the diff.
69
-
70
- THE SAVE CAN BE REJECTED. If save_lesson returns an error, it means
71
- the lesson didn't clear the quality bar. Common reasons, with the fix for each:
72
- - rootCause or fixSummary just repeated another field word-for-word - rewrite
73
- it to add the missing WHY (the mechanism, not a restatement).
74
- - mistake and fixSummary both read as a pure refactor with no code comparison
75
- - add badCodeExample/goodCodeExample, or don't save this as a lesson.
76
- - problem/mistake/fixSummary read as a UI-only or styling-only change (colors,
77
- spacing, className, fonts, etc.) with no described behavior change - say
78
- what BROKE (an element became unclickable, content overflowed and hid other
79
- content, etc.), not just what looked different.
80
- - mistake, rootCause, or fixSummary is a generic placeholder like "fixed the
81
- bug" or "the code was wrong" - name the actual function, condition, or
82
- value involved.
83
- - every reviewQuestion is a recall question ("what did you change") - rewrite
84
- or add one TRANSFER question per the REVIEW QUESTIONS section above.
85
- Re-read the FIELD GUIDE above, rewrite the offending field with real new
86
- information, and try again. If you genuinely cannot explain a root cause beyond
87
- the symptom, this was probably not a learning-worthy fix - do not save it.
88
-
89
- For codeExample, badCodeExample, and goodCodeExample: write multi-line snippets
90
- with real line breaks and normal indentation, the same way you'd write the code
91
- in a file. Do not flatten the snippet onto one line using the two characters
92
- "\" + "n" as a stand-in for a newline - the dashboard renders these fields
93
- verbatim, so literal "\n" text shows up as "\n" instead of a line break.
94
-
95
- SUPERSEDING A PREVIOUS LESSON:
96
- If you previously called save_lesson for a fix that turned out NOT to
97
- work, and you are now saving a lesson for the CORRECT fix, set:
98
- - supersedesLessonId: the id of the earlier (wrong) lesson, from its
99
- "Saved learning lesson <id>" response in this conversation.
100
- - supersedeReason: one sentence on what was wrong with the earlier fix and
101
- why this one replaces it.
102
- The old lesson stops appearing in search and spaced-repetition review, but
103
- stays in history with a link to this corrected lesson. Only use this for
104
- fixes that turned out to be incorrect or incomplete — not for pure rewording.
105
-
106
- Write as a teacher, not as an agent log. Keep lessons short and human-readable.
11
+ export const MCP_INSTRUCTIONS = `
12
+ You are the fixmind learning recorder. Your job is to capture lessons that help developers improve over time.
13
+
14
+ BEFORE calling save_lesson, run this checklist:
15
+ 1. Was real logic fixed? (a bug, an incorrect assumption, a missing guard, wrong API usage, bad state management, etc.)
16
+ 2. Does the developer now understand something they did not understand before?
17
+ 3. Can you write a concrete badCodeExample showing the wrong pattern?
18
+ 4. Can you explain WHY the old code was wrong, not just WHAT changed?
19
+ 5. Can you state when this fix would NOT apply - a different framework/version,
20
+ a context where the old code is actually correct, or a case that needs a
21
+ different fix entirely?
22
+
23
+ If any answer is NO, do NOT call save_lesson.
24
+
25
+ DO NOT save a lesson for:
26
+ - Moving code to a different file (pure relocation, no logic change)
27
+ - Renaming variables, functions, or files
28
+ - Formatting-only changes (whitespace, semicolons, quotes, line breaks)
29
+ - Generated files or build artifacts
30
+ - Adding a comment or doc-string without changing logic
31
+ - Splitting one file into multiple files without changing logic
32
+ - Purely mechanical refactors with no new understanding gained
33
+ - UI-only or styling-only changes (CSS, className, spacing, color, copy
34
+ tweaks) that don't change behavior or fix a bug
35
+ - Any change where you cannot point to a behavior that was wrong before
36
+ and correct after
37
+
38
+ FIELD GUIDE - each field has a distinct job. Do not let them repeat each other:
39
+ - problem: The user-visible SYMPTOM. What broke, what error appeared, or
40
+ what the user/tester observed. This is the "what happened".
41
+ - mistake: The WRONG ASSUMPTION or approach in the code that caused the
42
+ symptom - describe the flawed thinking, not just the line that changed.
43
+ - rootCause: WHY the mistake produced the symptom. This must add new
44
+ information beyond problem and mistake - if you find yourself repeating
45
+ either of them, dig one level deeper (e.g. "the API resolves before the
46
+ body streams" rather than "the data was empty").
47
+ - fixSummary: WHY the new code avoids the root cause - not just what code
48
+ changed. A reader should understand why this fix actually works, so they
49
+ could apply the same reasoning elsewhere.
50
+
51
+ REQUIRED fields — every lesson must answer these:
52
+ - mistake: What the developer actually did wrong in their thinking (not just what line changed)
53
+ - takeaway: One sentence to remember. Example: "fetch() resolves when headers arrive, not when the body is parsed."
54
+ - whenNotApplicable: When this advice does NOT apply. Example: "Doesn't apply inside Server Components, which can't use useEffect at all."
55
+
56
+ STRONGLY RECOMMENDED fields — provide these when code is involved:
57
+ - badCodeExample: The minimal broken snippet. Example: "const data = await fetch(url)"
58
+ - goodCodeExample: The corrected version, paired with badCodeExample. Example: "const res = await fetch(url); const data = await res.json();"
59
+ - mistakePattern: A 2–4 word reusable category. Examples: "Missing await", "Stale closure", "Off-by-one", "Wrong event lifetime"
60
+ - tags: 1-3 entries naming the APIs/concepts involved, e.g. { "name": "MDN: URL.revokeObjectURL", "url": "https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL_static" }. Only set url when you are confident it is a real, official documentation page (MDN, the framework's own docs). If unsure, omit url and the tag is shown as a plain label.
61
+
62
+ REVIEW QUESTIONS - write TRANSFER questions, not recall questions:
63
+ - Bad (recall): "What did you change?" / "Summarize the fix."
64
+ - Good (transfer): a question that asks the developer to apply the same
65
+ reasoning to a DIFFERENT situation, spot the same mistake in different
66
+ code, or predict what would happen under slightly different conditions.
67
+ - expectedAnswer should reference the underlying principle (rootCause /
68
+ takeaway), not just describe the diff.
69
+
70
+ THE SAVE CAN BE REJECTED. If save_lesson returns an error, it means
71
+ the lesson didn't clear the quality bar. Common reasons, with the fix for each:
72
+ - rootCause or fixSummary just repeated another field word-for-word - rewrite
73
+ it to add the missing WHY (the mechanism, not a restatement).
74
+ - mistake and fixSummary both read as a pure refactor with no code comparison
75
+ - add badCodeExample/goodCodeExample, or don't save this as a lesson.
76
+ - problem/mistake/fixSummary read as a UI-only or styling-only change (colors,
77
+ spacing, className, fonts, etc.) with no described behavior change - say
78
+ what BROKE (an element became unclickable, content overflowed and hid other
79
+ content, etc.), not just what looked different.
80
+ - mistake, rootCause, or fixSummary is a generic placeholder like "fixed the
81
+ bug" or "the code was wrong" - name the actual function, condition, or
82
+ value involved.
83
+ - every reviewQuestion is a recall question ("what did you change") - rewrite
84
+ or add one TRANSFER question per the REVIEW QUESTIONS section above.
85
+ Re-read the FIELD GUIDE above, rewrite the offending field with real new
86
+ information, and try again. If you genuinely cannot explain a root cause beyond
87
+ the symptom, this was probably not a learning-worthy fix - do not save it.
88
+
89
+ For codeExample, badCodeExample, and goodCodeExample: write multi-line snippets
90
+ with real line breaks and normal indentation, the same way you'd write the code
91
+ in a file. Do not flatten the snippet onto one line using the two characters
92
+ "\" + "n" as a stand-in for a newline - the dashboard renders these fields
93
+ verbatim, so literal "\n" text shows up as "\n" instead of a line break.
94
+
95
+ SUPERSEDING A PREVIOUS LESSON:
96
+ If you previously called save_lesson for a fix that turned out NOT to
97
+ work, and you are now saving a lesson for the CORRECT fix, set:
98
+ - supersedesLessonId: the id of the earlier (wrong) lesson, from its
99
+ "Saved learning lesson <id>" response in this conversation.
100
+ - supersedeReason: one sentence on what was wrong with the earlier fix and
101
+ why this one replaces it.
102
+ The old lesson stops appearing in search and spaced-repetition review, but
103
+ stays in history with a link to this corrected lesson. Only use this for
104
+ fixes that turned out to be incorrect or incomplete — not for pure rewording.
105
+
106
+ Write as a teacher, not as an agent log. Keep lessons short and human-readable.
107
107
  `.trim();
108
108
  const reviewQuestionSchema = z.object({
109
109
  question: z.string().trim().min(1).describe("A TRANSFER question - apply the lesson to a different situation, spot the same mistake elsewhere, or predict an outcome. Do not ask 'what did you change' or 'summarize the fix'."),
package/dist/src/setup.js CHANGED
@@ -127,21 +127,21 @@ function configureCursor(homeDirectory, projectDirectory, scope, server, dryRun)
127
127
  };
128
128
  }
129
129
  const INSTRUCTION_MARKER = "fixmind:instructions";
130
- const INSTRUCTION_BODY = `\
131
- After fixing any meaningful bug or resolving a real coding mistake, always call \
132
- the fixmind save_lesson MCP tool before finishing your response.
133
-
134
- Call it for: bugs, incorrect API usage, wrong assumptions, bad state management, \
135
- logic errors, missing cleanup, security issues.
136
-
137
- Skip it for: renaming files or variables, formatting changes, moving code between \
138
- files, generated files, or adding comments without logic changes.
139
-
140
- When code is involved, always provide badCodeExample and goodCodeExample.
141
-
142
- When the mistake involves a documented API or concept, add tags: [{ name, url }] \
143
- linking to the official docs (MDN, the framework's docs, etc.). Only set url when \
144
- you're confident it's a real page — otherwise omit it and the tag still shows as a \
130
+ const INSTRUCTION_BODY = `\
131
+ After fixing any meaningful bug or resolving a real coding mistake, always call \
132
+ the fixmind save_lesson MCP tool before finishing your response.
133
+
134
+ Call it for: bugs, incorrect API usage, wrong assumptions, bad state management, \
135
+ logic errors, missing cleanup, security issues.
136
+
137
+ Skip it for: renaming files or variables, formatting changes, moving code between \
138
+ files, generated files, or adding comments without logic changes.
139
+
140
+ When code is involved, always provide badCodeExample and goodCodeExample.
141
+
142
+ When the mistake involves a documented API or concept, add tags: [{ name, url }] \
143
+ linking to the official docs (MDN, the framework's docs, etc.). Only set url when \
144
+ you're confident it's a real page — otherwise omit it and the tag still shows as a \
145
145
  label.`;
146
146
  function instructionBlock(client) {
147
147
  if (client === "cursor") {
@@ -16,42 +16,42 @@ export function initializeDataDirectory() {
16
16
  export function createLessonStore(filePath = databasePath()) {
17
17
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
18
18
  const db = new DatabaseSync(filePath);
19
- db.exec(`
20
- CREATE TABLE IF NOT EXISTS lessons (
21
- id TEXT PRIMARY KEY,
22
- created_at TEXT NOT NULL,
23
- updated_at TEXT NOT NULL,
24
- tool TEXT NOT NULL,
25
- project_path TEXT NOT NULL,
26
- title TEXT NOT NULL,
27
- original_prompt TEXT NOT NULL,
28
- problem TEXT NOT NULL,
29
- mistake TEXT NOT NULL,
30
- root_cause TEXT NOT NULL,
31
- fix_summary TEXT NOT NULL,
32
- takeaway TEXT,
33
- mistake_pattern TEXT,
34
- when_not_applicable TEXT,
35
- concepts TEXT NOT NULL,
36
- files_changed TEXT NOT NULL,
37
- code_example TEXT,
38
- bad_code_example TEXT,
39
- good_code_example TEXT,
40
- code_explanation TEXT,
41
- practice_task TEXT,
42
- review_questions TEXT NOT NULL,
43
- understanding TEXT NOT NULL,
44
- next_review_at TEXT NOT NULL,
45
- review_count INTEGER NOT NULL DEFAULT 0,
46
- source_diff TEXT,
47
- tags TEXT NOT NULL,
48
- status TEXT NOT NULL DEFAULT 'active',
49
- superseded_by TEXT,
50
- supersedes TEXT,
51
- supersede_reason TEXT
52
- );
53
- CREATE INDEX IF NOT EXISTS idx_lessons_created_at ON lessons(created_at DESC);
54
- CREATE INDEX IF NOT EXISTS idx_lessons_next_review_at ON lessons(next_review_at);
19
+ db.exec(`
20
+ CREATE TABLE IF NOT EXISTS lessons (
21
+ id TEXT PRIMARY KEY,
22
+ created_at TEXT NOT NULL,
23
+ updated_at TEXT NOT NULL,
24
+ tool TEXT NOT NULL,
25
+ project_path TEXT NOT NULL,
26
+ title TEXT NOT NULL,
27
+ original_prompt TEXT NOT NULL,
28
+ problem TEXT NOT NULL,
29
+ mistake TEXT NOT NULL,
30
+ root_cause TEXT NOT NULL,
31
+ fix_summary TEXT NOT NULL,
32
+ takeaway TEXT,
33
+ mistake_pattern TEXT,
34
+ when_not_applicable TEXT,
35
+ concepts TEXT NOT NULL,
36
+ files_changed TEXT NOT NULL,
37
+ code_example TEXT,
38
+ bad_code_example TEXT,
39
+ good_code_example TEXT,
40
+ code_explanation TEXT,
41
+ practice_task TEXT,
42
+ review_questions TEXT NOT NULL,
43
+ understanding TEXT NOT NULL,
44
+ next_review_at TEXT NOT NULL,
45
+ review_count INTEGER NOT NULL DEFAULT 0,
46
+ source_diff TEXT,
47
+ tags TEXT NOT NULL,
48
+ status TEXT NOT NULL DEFAULT 'active',
49
+ superseded_by TEXT,
50
+ supersedes TEXT,
51
+ supersede_reason TEXT
52
+ );
53
+ CREATE INDEX IF NOT EXISTS idx_lessons_created_at ON lessons(created_at DESC);
54
+ CREATE INDEX IF NOT EXISTS idx_lessons_next_review_at ON lessons(next_review_at);
55
55
  `);
56
56
  return {
57
57
  save(input) {
@@ -90,17 +90,17 @@ export function createLessonStore(filePath = databasePath()) {
90
90
  tags: input.tags ?? [],
91
91
  status: "active",
92
92
  };
93
- db.prepare(`
94
- INSERT INTO lessons (
95
- id, created_at, updated_at, tool, project_path, title, original_prompt,
96
- problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
97
- when_not_applicable, concepts, files_changed, code_example, bad_code_example,
98
- good_code_example, code_explanation, practice_task, review_questions,
99
- understanding, next_review_at, review_count, source_diff, tags,
100
- status, superseded_by, supersedes, supersede_reason
101
- ) VALUES (
102
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL
103
- )
93
+ db.prepare(`
94
+ INSERT INTO lessons (
95
+ id, created_at, updated_at, tool, project_path, title, original_prompt,
96
+ problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
97
+ when_not_applicable, concepts, files_changed, code_example, bad_code_example,
98
+ good_code_example, code_explanation, practice_task, review_questions,
99
+ understanding, next_review_at, review_count, source_diff, tags,
100
+ status, superseded_by, supersedes, supersede_reason
101
+ ) VALUES (
102
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL
103
+ )
104
104
  `).run(lesson.id, lesson.createdAt, lesson.updatedAt, lesson.tool, lesson.projectPath, lesson.title, lesson.originalPrompt, lesson.problem, lesson.mistake, lesson.rootCause, lesson.fixSummary, lesson.takeaway ?? null, lesson.mistakePattern ?? null, lesson.whenNotApplicable ?? null, JSON.stringify(lesson.concepts), JSON.stringify(lesson.filesChanged), lesson.codeExample ?? null, lesson.badCodeExample ?? null, lesson.goodCodeExample ?? null, lesson.codeExplanation ?? null, lesson.practiceTask ?? null, JSON.stringify(lesson.reviewQuestions), lesson.understanding, lesson.nextReviewAt, lesson.reviewCount, lesson.sourceDiff ?? null, JSON.stringify(lesson.tags), lesson.status);
105
105
  if (input.supersedesLessonId && this.get(input.supersedesLessonId)) {
106
106
  this.supersede(input.supersedesLessonId, lesson.id, input.supersedeReason);
@@ -120,31 +120,31 @@ export function createLessonStore(filePath = databasePath()) {
120
120
  return db.prepare("SELECT * FROM lessons WHERE updated_at > ? ORDER BY updated_at ASC").all(timestamp).map(fromDb);
121
121
  },
122
122
  upsertFromRemote(lesson) {
123
- db.prepare(`
124
- INSERT INTO lessons (
125
- id, created_at, updated_at, tool, project_path, title, original_prompt,
126
- problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
127
- when_not_applicable, concepts, files_changed, code_example, bad_code_example,
128
- good_code_example, code_explanation, practice_task, review_questions,
129
- understanding, next_review_at, review_count, source_diff, tags,
130
- status, superseded_by, supersedes, supersede_reason
131
- ) VALUES (
132
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
133
- )
134
- ON CONFLICT(id) DO UPDATE SET
135
- created_at=excluded.created_at, updated_at=excluded.updated_at, tool=excluded.tool,
136
- project_path=excluded.project_path, title=excluded.title, original_prompt=excluded.original_prompt,
137
- problem=excluded.problem, mistake=excluded.mistake, root_cause=excluded.root_cause,
138
- fix_summary=excluded.fix_summary, takeaway=excluded.takeaway, mistake_pattern=excluded.mistake_pattern,
139
- when_not_applicable=excluded.when_not_applicable, concepts=excluded.concepts,
140
- files_changed=excluded.files_changed, code_example=excluded.code_example,
141
- bad_code_example=excluded.bad_code_example, good_code_example=excluded.good_code_example,
142
- code_explanation=excluded.code_explanation, practice_task=excluded.practice_task,
143
- review_questions=excluded.review_questions, understanding=excluded.understanding,
144
- next_review_at=excluded.next_review_at, review_count=excluded.review_count,
145
- source_diff=excluded.source_diff, tags=excluded.tags, status=excluded.status,
146
- superseded_by=excluded.superseded_by, supersedes=excluded.supersedes,
147
- supersede_reason=excluded.supersede_reason
123
+ db.prepare(`
124
+ INSERT INTO lessons (
125
+ id, created_at, updated_at, tool, project_path, title, original_prompt,
126
+ problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
127
+ when_not_applicable, concepts, files_changed, code_example, bad_code_example,
128
+ good_code_example, code_explanation, practice_task, review_questions,
129
+ understanding, next_review_at, review_count, source_diff, tags,
130
+ status, superseded_by, supersedes, supersede_reason
131
+ ) VALUES (
132
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
133
+ )
134
+ ON CONFLICT(id) DO UPDATE SET
135
+ created_at=excluded.created_at, updated_at=excluded.updated_at, tool=excluded.tool,
136
+ project_path=excluded.project_path, title=excluded.title, original_prompt=excluded.original_prompt,
137
+ problem=excluded.problem, mistake=excluded.mistake, root_cause=excluded.root_cause,
138
+ fix_summary=excluded.fix_summary, takeaway=excluded.takeaway, mistake_pattern=excluded.mistake_pattern,
139
+ when_not_applicable=excluded.when_not_applicable, concepts=excluded.concepts,
140
+ files_changed=excluded.files_changed, code_example=excluded.code_example,
141
+ bad_code_example=excluded.bad_code_example, good_code_example=excluded.good_code_example,
142
+ code_explanation=excluded.code_explanation, practice_task=excluded.practice_task,
143
+ review_questions=excluded.review_questions, understanding=excluded.understanding,
144
+ next_review_at=excluded.next_review_at, review_count=excluded.review_count,
145
+ source_diff=excluded.source_diff, tags=excluded.tags, status=excluded.status,
146
+ superseded_by=excluded.superseded_by, supersedes=excluded.supersedes,
147
+ supersede_reason=excluded.supersede_reason
148
148
  `).run(lesson.id, lesson.createdAt, lesson.updatedAt, lesson.tool, lesson.projectPath, lesson.title, lesson.originalPrompt, lesson.problem, lesson.mistake, lesson.rootCause, lesson.fixSummary, lesson.takeaway ?? null, lesson.mistakePattern ?? null, lesson.whenNotApplicable ?? null, JSON.stringify(lesson.concepts), JSON.stringify(lesson.filesChanged), lesson.codeExample ?? null, lesson.badCodeExample ?? null, lesson.goodCodeExample ?? null, lesson.codeExplanation ?? null, lesson.practiceTask ?? null, JSON.stringify(lesson.reviewQuestions), lesson.understanding, lesson.nextReviewAt, lesson.reviewCount, lesson.sourceDiff ?? null, JSON.stringify(lesson.tags), lesson.status, lesson.supersededBy ?? null, lesson.supersedes ?? null, lesson.supersedeReason ?? null);
149
149
  },
150
150
  search(query, options = {}) {
package/dist/src/sync.js CHANGED
@@ -46,67 +46,67 @@ function escapeHtml(value) {
46
46
  }
47
47
  function oauthCallbackPage(options) {
48
48
  const tint = options.ok ? "124,92,255" : "255,92,114";
49
- return `<!doctype html>
50
- <html lang="en">
51
- <head>
52
- <meta charset="utf-8">
53
- <title>Fixmind</title>
54
- <style>
55
- :root { color-scheme: dark; }
56
- body {
57
- margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
58
- position: relative; overflow: hidden;
59
- background-color: #08090d; color: #e9ecf4;
60
- font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
61
- }
62
- body::before {
63
- content: ""; position: absolute; inset: 0; pointer-events: none;
64
- background-image:
65
- linear-gradient(to right, rgba(35,40,56,0.6) 1px, transparent 1px),
66
- linear-gradient(to bottom, rgba(35,40,56,0.6) 1px, transparent 1px);
67
- background-size: 48px 48px;
68
- mask-image: radial-gradient(circle at 50% 35%, black, transparent 75%);
69
- }
70
- body::after {
71
- content: ""; position: absolute; left: 50%; top: 0; width: 760px; height: 420px;
72
- transform: translateX(-50%); pointer-events: none; border-radius: 9999px;
73
- background: rgba(${tint},0.15); filter: blur(130px);
74
- }
75
- .card {
76
- position: relative; z-index: 1; text-align: center; padding: 2.5rem 3rem; border-radius: 16px;
77
- border: 1px solid #232838; background: rgba(17,20,27,0.92);
78
- }
79
- .icon {
80
- width: 48px; height: 48px; margin: 0 auto 1.25rem; border-radius: 50%;
81
- display: flex; align-items: center; justify-content: center; font-size: 22px;
82
- background: rgba(${tint},0.15);
83
- color: ${options.ok ? "#7c5cff" : "#ff5c72"};
84
- }
85
- h1 {
86
- font-family: "Space Grotesk", "Inter", sans-serif; font-size: 1.25rem; font-weight: 600;
87
- margin: 0 0 0.5rem;
88
- }
89
- p { margin: 0; color: #828a9c; font-size: 0.95rem; line-height: 1.5; }
90
- .redirect {
91
- display: inline-block; margin-top: 1.5rem; padding: 0.6rem 1.5rem; border-radius: 8px;
92
- background: #7c5cff; color: #08090d; font-weight: 600; font-size: 0.9rem;
93
- text-decoration: none;
94
- }
95
- .brand {
96
- margin-top: 2rem; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
97
- color: #4b3aae;
98
- }
99
- </style>
100
- </head>
101
- <body>
102
- <div class="card">
103
- <div class="icon">${options.ok ? "&#10003;" : "&#33;"}</div>
104
- <h1>${options.ok ? "You're signed in" : "Sign in failed"}</h1>
105
- <p>${escapeHtml(options.message)}</p>
106
- ${options.redirectUrl ? `<a class="redirect" href="${escapeHtml(options.redirectUrl)}">Try again</a>` : ""}
107
- <div class="brand">Fixmind</div>
108
- </div>
109
- </body>
49
+ return `<!doctype html>
50
+ <html lang="en">
51
+ <head>
52
+ <meta charset="utf-8">
53
+ <title>Fixmind</title>
54
+ <style>
55
+ :root { color-scheme: dark; }
56
+ body {
57
+ margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
58
+ position: relative; overflow: hidden;
59
+ background-color: #08090d; color: #e9ecf4;
60
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
61
+ }
62
+ body::before {
63
+ content: ""; position: absolute; inset: 0; pointer-events: none;
64
+ background-image:
65
+ linear-gradient(to right, rgba(35,40,56,0.6) 1px, transparent 1px),
66
+ linear-gradient(to bottom, rgba(35,40,56,0.6) 1px, transparent 1px);
67
+ background-size: 48px 48px;
68
+ mask-image: radial-gradient(circle at 50% 35%, black, transparent 75%);
69
+ }
70
+ body::after {
71
+ content: ""; position: absolute; left: 50%; top: 0; width: 760px; height: 420px;
72
+ transform: translateX(-50%); pointer-events: none; border-radius: 9999px;
73
+ background: rgba(${tint},0.15); filter: blur(130px);
74
+ }
75
+ .card {
76
+ position: relative; z-index: 1; text-align: center; padding: 2.5rem 3rem; border-radius: 16px;
77
+ border: 1px solid #232838; background: rgba(17,20,27,0.92);
78
+ }
79
+ .icon {
80
+ width: 48px; height: 48px; margin: 0 auto 1.25rem; border-radius: 50%;
81
+ display: flex; align-items: center; justify-content: center; font-size: 22px;
82
+ background: rgba(${tint},0.15);
83
+ color: ${options.ok ? "#7c5cff" : "#ff5c72"};
84
+ }
85
+ h1 {
86
+ font-family: "Space Grotesk", "Inter", sans-serif; font-size: 1.25rem; font-weight: 600;
87
+ margin: 0 0 0.5rem;
88
+ }
89
+ p { margin: 0; color: #828a9c; font-size: 0.95rem; line-height: 1.5; }
90
+ .redirect {
91
+ display: inline-block; margin-top: 1.5rem; padding: 0.6rem 1.5rem; border-radius: 8px;
92
+ background: #7c5cff; color: #08090d; font-weight: 600; font-size: 0.9rem;
93
+ text-decoration: none;
94
+ }
95
+ .brand {
96
+ margin-top: 2rem; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
97
+ color: #4b3aae;
98
+ }
99
+ </style>
100
+ </head>
101
+ <body>
102
+ <div class="card">
103
+ <div class="icon">${options.ok ? "&#10003;" : "&#33;"}</div>
104
+ <h1>${options.ok ? "You're signed in" : "Sign in failed"}</h1>
105
+ <p>${escapeHtml(options.message)}</p>
106
+ ${options.redirectUrl ? `<a class="redirect" href="${escapeHtml(options.redirectUrl)}">Try again</a>` : ""}
107
+ <div class="brand">Fixmind</div>
108
+ </div>
109
+ </body>
110
110
  </html>`;
111
111
  }
112
112
  function waitForOAuthCode(port, authUrl) {