Task 8 of the slice plan. Saves clipboard PNG/JPEG bytes under
{profileDir}/media/{noteId}/{uuid}.{ext} with mkdir -p semantics,
returns relPath/mime/bytes for the repository row, supports
deleteNoteDirectory (used by note delete + GC) and listNoteDirs
(used by media GC to find orphans).
Verification: `npx vitest run tests/unit/MediaStore.test.ts`
4 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 7 of the slice plan. Implements the full repository surface
backing every IPC inbox/capture path: create (UUID v7 + atomic
notes + pending_jobs insert), insertMedia, findById/list,
updateAiResult (CASE WHEN guard against title/summary
overwrite when *_edited_by_user flips), markAiFailed (truncates
ai_error to 500 chars + clears pending job), updateUserAiFields
(sets edited flags as a side effect, replaces user-source tags),
setIntent + dismissIntent (intent_prompted_at uses COALESCE so
the first stamp wins), delete, getPendingCount,
getAllPendingJobs, incrementJobAttempt, and a private hydrate
that joins notes with note_tags + media.
Plan deviation: list/list-with-cursor query gets a secondary
"id DESC" tiebreaker. Two notes created in the same millisecond
shared created_at and reordered nondeterministically; UUID v7
sorts monotonically with creation order, so id DESC restores
"newest first" within ties.
Verification: `npx vitest run tests/unit/NoteRepository.test.ts`
12 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 5 of the slice plan. resolveProfilePaths(profile='default')
returns { profileDir, dbFile, mediaDir } under
{userData}/Inkling/profiles/<profile>/ and ensures mediaDir exists
via recursive mkdirSync. Slice scope is single profile 'default'
(spec §1.1, §2.4).
Verification: `npm run typecheck` exits 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 4 of the slice plan. Adds initLogger() (rotates daily logs
under {userData}/Inkling/logs at 5MB cap, info level by default
and debug when INKLING_DEBUG=1), a hashPrefix() helper for
safely referencing note IDs in logs without exposing content,
and a typed logger facade with info/warn/error/debug methods.
Wires initLogger() + an app.start info entry into the
whenReady hook.
Verification: `npm run typecheck` exits 0. Runtime log file
creation deferred to live `npm run dev` once Tasks 3+19 land.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 3 of the slice plan. Replaces the minimum @shared/types
augmentation with the full domain model: Note (with v0.2
intent + edited-flag fields), NoteTag, NoteMedia, AiStatus,
WeeklyContinuity, CaptureApi, InboxApi, and the InklingApi
aggregate exposed on window.inkling. Adds the preload bridge
that wires every InklingApi method to its IPC channel via
contextBridge.exposeInMainWorld.
Verification: `npm run typecheck` exits 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 2 of the slice plan. Creates the minimal Electron main
process: app entry that opens an Inbox BrowserWindow on
whenReady, an inboxWindow module that handles show/hide/close-
to-tray semantics, an HTML placeholder renderer ("Inkling Inbox
(renderer pending)"), and the minimum @shared/types augmentation
for app.isQuitting (Task 3 expands this file).
Plan tsconfig template adjustment: TypeScript 6 deprecates
baseUrl. Dropped it and made paths entries explicitly relative
("./src/...") so they resolve from tsconfig.json's directory.
Updated both the in-repo tsconfig.json and Task 1 Step 3 in the
plan to match.
Verification: `npm run typecheck` exits 0. Full `npm run dev`
sanity check is deferred until Task 3 (preload) and Task 19
(quickcapture HTML) land — electron-vite.config.ts wires both
entries that don't yet exist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds package.json, tsconfig.json, tsconfig.node.json,
electron.vite.config.ts, vitest.config.ts, .gitignore, and
package-lock.json. Verified Node 24.15.0 + npm 11.12.1 via Volta.
better-sqlite3 12.9.0 native build succeeded against VS 2022 +
Python 3.12.
Plan v0.4 had two install pin issues; adjusted live and logged
in plan Task 1 Step 2:
- electron-vite@2.3.0 + vite@6.0.3 ERESOLVE (peer ^4||^5).
Promoted build-tool chain: electron-vite 5.0.0, vite 7.3.2,
@vitejs/plugin-react 5.1.4 (vite@7 is the compatible overlap;
vitest@4.1.5 also accepts vite@7).
- @types/uuid@11.0.0 deprecated stub (uuid@11 ships own types);
removed from devDependencies.
Other deps installed at the planned exact pins. Step 8 sanity:
TypeScript 6.0.3, Vitest 4.1.5, Electron 41.3.0 (npm ls).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User reassessed model needs: 26b is overkill for slice-scope tasks
(short Korean title + 3-line summary + ≤3 kebab-case tags). e4b
(8.0B Q4_K_M, efficiency variant) sits closest to the original
"표준 9b" tier in spec §6.5 and gives faster responses with
adequate margin for the slice's simple structuring work.
Spec changes:
- Header bumped to v0.4 with new revision line.
- §1.1 retiers AI 파이프라인 from "고품질 26B" to "표준 e4b".
- §2.1 diagram, §3.1 ai_provider example, §4.1 provider name,
§4.2 request body, §4.6 health check, §5.4 copy catalog: model
string swapped 26b → e4b.
- §6.4 perf target restored to <30s provisional (e4b is similar
scale to original 9b reference, 60s margin no longer needed).
- §8 open issue rewritten: e4b is the standard-tier substitute,
with 26b/e2b documented as quality-up / speed-up fallback paths
if dogfood reveals issues with Korean output or tag formatting.
Plan changes:
- Header bumped to v0.4 with restated Goal.
- Architecture summary, Task 12 unit test mocks/expectations,
LocalOllamaProvider default model, copy banner, Task 33 dogfood
prerequisite: 26b → e4b throughout.
Tier ladder for dogfood escalation (from §8):
e2b (5.1B, speed) ← e4b (8.0B, default) → 26b (25.8B, quality)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Model swap: gemma4:9b has no official checkpoint; LAN server
(192.168.0.47:11434) ships gemma4:26b (25.8B Q4_K_M), which fits the
§6.5 26B cap and the "high-quality" tier. Updates §1.1, §2.1 diagram,
§3.1 ai_provider example, §4.1 provider name, §4.2 request body, §4.6
health check, §5.4 copy catalog, plan Task 12 (mock + default model),
Task 30 main entry, Task 33 dogfood intro.
Endpoint: LocalOllamaProvider now configurable via constructor opts.
Task 30 main entry and integration test read INKLING_OLLAMA_ENDPOINT
from env; unset falls back to localhost. LAN Ollama moves from
out-of-scope to in-scope via endpoint injection; only a separate
LanOllamaProvider class remains deferred.
Perf target §6.4: RTX 3060-referenced <30s target no longer valid
under 26B Q4_K_M + LAN. Set to <60s provisional; §8 adds a new open
issue to measure real p95 during first dogfood week and confirm.
§7.4 adds INKLING_OLLAMA_ENDPOINT env setup and recommends Volta over
nvm-windows for Windows Node 24.15.0 install.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds to handoff: rationale for choosing native Windows over WSL2
(global hotkey, OS notifications, clipboard image, tray, data path,
performance measurements all break under WSLg). Pre-flight
checklist updated so Ollama runs on a LAN server, not on the
Windows machine. Notes the one-line env-var change needed in Plan
Task 30 to wire LocalOllamaProvider to a LAN endpoint, and clarifies
that this is configuration (not a new Provider class).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures decisions made across both /brainstorming rounds (initial
slice scope + Strategy integration), user profile, project state,
Windows-specific gotchas (build tools, hotkey conflicts, Ollama,
file paths), load-bearing invariants, and suggested first messages
for the new Claude Code session on the dogfood machine.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 5 new tasks and updates existing ones to cover:
- ContinuityService (was StreakService) for Weekly Continuity (7
notes/week, KST Mon-Sun, recovery detection >=7 day gap).
- NotificationService for OS native post-submit reward toast (4
rotating copies, deterministic by noteId hash).
- IntentService + IntentBanner component for "의미 한 줄" prompt
after AI done (4 rotating prompts).
- RecoveryToast component with localStorage dismissal.
- AI proposal labels (gray "AI" badges on un-edited fields), tag
source subscript, edited-by-user flags guarding AI overwrites.
- Updated copy throughout (recovery-friendly, no failure language).
- New schema columns: user_intent, intent_prompted_at,
title_edited_by_user, summary_edited_by_user.
- Updated IPC: setIntent/dismissIntent/getContinuity.
- Tray copy ("기억 구출하기" / "구출한 메모 보기").
- Updated dogfood checklist with all v0.2 features.
Plan now has 33 tasks (was 28). All tasks remain bite-sized with
TDD discipline (red → green → commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28-task TDD plan covering project bootstrap, data layer, AI pipeline,
Quick Capture + Inbox UI, tray, media GC, and E2E smoke test. Each
task is bite-sized with red/green/commit discipline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pin Node 24 LTS (Krypton) as runtime. Document latest-stable-major
policy for dependencies with initial pin candidates as of 2026-04-24,
and .nvmrc-based version synchronization for dev/CI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial design document covering the first end-to-end slice of Inkling:
Quick Capture, SQLite storage, Local Ollama AI pipeline (gemma4:9b),
and Inbox with inline editing. Scoped for dogfood on Windows/macOS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>