From 80c125a5720d2c90c7515e8c441b72d04c5ccefd Mon Sep 17 00:00:00 2001 From: tommy0103 Date: Thu, 9 Jul 2026 10:20:18 +0800 Subject: [PATCH] build(app): migrate to electron-vite (main/preload/renderer), keep electron-builder (Phase 5d-3a) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure app into src/{main,preload,renderer}; electron.vite.config.ts builds all three (each main module its own input so CJS requires + the indexer worker resolve; better-sqlite3 externalized; Vue plugin for renderer). main/index.js paths updated for the out/ layout + ELECTRON_RENDERER_URL. Still JS/CJS — TS+ESM and core consumption are the next stages. Verified: npm run dev launches clean; electron-vite build succeeds; root suite 119/119. --- .gitignore | 1 + app/electron.vite.config.ts | 31 ++ app/package-lock.json | 470 ++++++++++++++++++ app/package.json | 33 +- app/renderer/vite.config.js | 11 - app/{main.js => src/main/index.js} | 16 +- app/{ => src/main}/indexer-service.js | 0 app/{ => src/main}/indexer-worker-client.js | 0 app/{ => src/main}/indexer-worker.js | 0 app/{ => src/main}/indexer.js | 2 +- app/{ => src/main}/recap-capture-query.js | 0 app/{preload.js => src/preload/index.js} | 0 app/{ => src}/renderer/index.html | 0 app/{ => src}/renderer/js/app.js | 0 app/{ => src}/renderer/js/data.js | 0 app/{ => src}/renderer/js/keys.js | 0 app/{ => src}/renderer/js/memory-list.js | 0 app/{ => src}/renderer/js/registry.js | 0 app/{ => src}/renderer/js/render.js | 0 app/{ => src}/renderer/js/session-list.js | 0 app/{ => src}/renderer/js/sidebar.js | 0 app/{ => src}/renderer/js/state.js | 0 app/{ => src}/renderer/js/usage.js | 0 app/{ => src}/renderer/js/utils.js | 0 app/{ => src}/renderer/src/App.vue | 0 .../renderer/src/assets/recap-cards.html | 0 .../renderer/src/components/Sidebar.vue | 0 .../renderer/src/components/Toolbar.vue | 0 .../src/components/recap/ClosingCard.vue | 0 .../src/components/recap/CoverCard.vue | 0 .../src/components/recap/PathCard.vue | 0 .../src/components/recap/VibeCard.vue | 0 .../src/components/recap/WorkflowCard.vue | 0 .../src/components/recap/archetypes.js | 0 .../src/components/recap/card-base.css | 0 .../renderer/src/components/recap/seals.js | 0 app/{ => src}/renderer/src/data.js | 0 app/{ => src}/renderer/src/main.js | 0 .../renderer/src/mock/recap-2026-W24.json | 0 app/{ => src}/renderer/src/router.js | 0 app/{ => src}/renderer/src/session-live.mjs | 0 .../renderer/src/sidebar-projects.mjs | 0 app/{ => src}/renderer/src/store.js | 0 app/{ => src}/renderer/src/utils.js | 0 app/{ => src}/renderer/src/views/Activity.vue | 0 .../renderer/src/views/MemoryDetail.vue | 0 .../renderer/src/views/MemoryList.vue | 0 .../renderer/src/views/RecapDetail.vue | 0 .../renderer/src/views/RecapExport.vue | 0 .../renderer/src/views/RecapList.vue | 0 .../renderer/src/views/SessionDetail.vue | 0 .../renderer/src/views/SessionList.vue | 0 app/{ => src}/renderer/src/views/Settings.vue | 0 .../renderer/src/views/SubagentDetail.vue | 0 app/{ => src}/renderer/styles/base.css | 0 app/{ => src}/renderer/styles/detail.css | 0 app/{ => src}/renderer/styles/list.css | 0 app/{ => src}/renderer/styles/sidebar.css | 0 app/{ => src}/renderer/styles/statusbar.css | 0 app/{ => src}/renderer/styles/toolbar.css | 0 app/yarnball.md | 8 + tests/app-indexer-service.test.mjs | 2 +- tests/app-indexer-worker-client.test.mjs | 2 +- tests/app-indexer.test.mjs | 2 +- tests/app-main-settings.test.mjs | 32 +- tests/recap-capture-query.test.mjs | 2 +- tests/recap-patterns.test.mjs | 34 +- tests/session-live.test.mjs | 2 +- tests/sidebar-projects.test.mjs | 2 +- 69 files changed, 572 insertions(+), 78 deletions(-) create mode 100644 app/electron.vite.config.ts delete mode 100644 app/renderer/vite.config.js rename app/{main.js => src/main/index.js} (97%) rename app/{ => src/main}/indexer-service.js (100%) rename app/{ => src/main}/indexer-worker-client.js (100%) rename app/{ => src/main}/indexer-worker.js (100%) rename app/{ => src/main}/indexer.js (99%) rename app/{ => src/main}/recap-capture-query.js (100%) rename app/{preload.js => src/preload/index.js} (100%) rename app/{ => src}/renderer/index.html (100%) rename app/{ => src}/renderer/js/app.js (100%) rename app/{ => src}/renderer/js/data.js (100%) rename app/{ => src}/renderer/js/keys.js (100%) rename app/{ => src}/renderer/js/memory-list.js (100%) rename app/{ => src}/renderer/js/registry.js (100%) rename app/{ => src}/renderer/js/render.js (100%) rename app/{ => src}/renderer/js/session-list.js (100%) rename app/{ => src}/renderer/js/sidebar.js (100%) rename app/{ => src}/renderer/js/state.js (100%) rename app/{ => src}/renderer/js/usage.js (100%) rename app/{ => src}/renderer/js/utils.js (100%) rename app/{ => src}/renderer/src/App.vue (100%) rename app/{ => src}/renderer/src/assets/recap-cards.html (100%) rename app/{ => src}/renderer/src/components/Sidebar.vue (100%) rename app/{ => src}/renderer/src/components/Toolbar.vue (100%) rename app/{ => src}/renderer/src/components/recap/ClosingCard.vue (100%) rename app/{ => src}/renderer/src/components/recap/CoverCard.vue (100%) rename app/{ => src}/renderer/src/components/recap/PathCard.vue (100%) rename app/{ => src}/renderer/src/components/recap/VibeCard.vue (100%) rename app/{ => src}/renderer/src/components/recap/WorkflowCard.vue (100%) rename app/{ => src}/renderer/src/components/recap/archetypes.js (100%) rename app/{ => src}/renderer/src/components/recap/card-base.css (100%) rename app/{ => src}/renderer/src/components/recap/seals.js (100%) rename app/{ => src}/renderer/src/data.js (100%) rename app/{ => src}/renderer/src/main.js (100%) rename app/{ => src}/renderer/src/mock/recap-2026-W24.json (100%) rename app/{ => src}/renderer/src/router.js (100%) rename app/{ => src}/renderer/src/session-live.mjs (100%) rename app/{ => src}/renderer/src/sidebar-projects.mjs (100%) rename app/{ => src}/renderer/src/store.js (100%) rename app/{ => src}/renderer/src/utils.js (100%) rename app/{ => src}/renderer/src/views/Activity.vue (100%) rename app/{ => src}/renderer/src/views/MemoryDetail.vue (100%) rename app/{ => src}/renderer/src/views/MemoryList.vue (100%) rename app/{ => src}/renderer/src/views/RecapDetail.vue (100%) rename app/{ => src}/renderer/src/views/RecapExport.vue (100%) rename app/{ => src}/renderer/src/views/RecapList.vue (100%) rename app/{ => src}/renderer/src/views/SessionDetail.vue (100%) rename app/{ => src}/renderer/src/views/SessionList.vue (100%) rename app/{ => src}/renderer/src/views/Settings.vue (100%) rename app/{ => src}/renderer/src/views/SubagentDetail.vue (100%) rename app/{ => src}/renderer/styles/base.css (100%) rename app/{ => src}/renderer/styles/detail.css (100%) rename app/{ => src}/renderer/styles/list.css (100%) rename app/{ => src}/renderer/styles/sidebar.css (100%) rename app/{ => src}/renderer/styles/statusbar.css (100%) rename app/{ => src}/renderer/styles/toolbar.css (100%) create mode 100644 app/yarnball.md diff --git a/.gitignore b/.gitignore index 9025db8..21d2053 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ release/ .dev.docs .claude/ dist/ +app/out/ diff --git a/app/electron.vite.config.ts b/app/electron.vite.config.ts new file mode 100644 index 0000000..3de8ba4 --- /dev/null +++ b/app/electron.vite.config.ts @@ -0,0 +1,31 @@ +import { resolve } from 'node:path'; +import { defineConfig, externalizeDepsPlugin } from 'electron-vite'; +import vue from '@vitejs/plugin-vue'; + +// Kept CommonJS for the first electron-vite boot (no "type":"module" yet); the +// TS + ESM migration is a later stage. Each main-process module is its own input +// so it is emitted to out/main/.js and the CommonJS require("./x") calls +// between them (and `new Worker(__dirname/indexer-worker.js)`) resolve at runtime. +export default defineConfig({ + main: { + plugins: [externalizeDepsPlugin()], + build: { + rollupOptions: { + input: { + index: resolve('src/main/index.js'), + indexer: resolve('src/main/indexer.js'), + 'indexer-service': resolve('src/main/indexer-service.js'), + 'indexer-worker': resolve('src/main/indexer-worker.js'), + 'indexer-worker-client': resolve('src/main/indexer-worker-client.js'), + 'recap-capture-query': resolve('src/main/recap-capture-query.js'), + }, + }, + }, + }, + preload: { + plugins: [externalizeDepsPlugin()], + }, + renderer: { + plugins: [vue()], + }, +}); diff --git a/app/package-lock.json b/app/package-lock.json index 0a5fdb0..c297a04 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -15,11 +15,171 @@ "@vitejs/plugin-vue": "^5.0.0", "electron": "^33.0.0", "electron-builder": "^25.0.0", + "electron-vite": "^5.0.0", "vite": "^6.0.0", "vue": "^3.4.0", "vue-router": "^4.3.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", @@ -40,6 +200,30 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", @@ -56,6 +240,56 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/types": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", @@ -1008,6 +1242,38 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1015,6 +1281,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", @@ -2230,6 +2507,19 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.42", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz", + "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/better-sqlite3": { "version": "11.10.0", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", @@ -2300,6 +2590,40 @@ "node": "18 || 20 || >=22" } }, + "node_modules/browserslist": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.5.tgz", + "integrity": "sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001800", + "electron-to-chromium": "^1.5.387", + "node-releases": "^2.0.50", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2418,6 +2742,16 @@ "node": ">= 10.0.0" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", @@ -2562,6 +2896,27 @@ "node": ">= 0.4" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001803", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz", + "integrity": "sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2885,6 +3240,13 @@ "dev": true, "license": "ISC" }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -3487,6 +3849,43 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.389", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz", + "integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==", + "dev": true, + "license": "ISC" + }, + "node_modules/electron-vite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/electron-vite/-/electron-vite-5.0.0.tgz", + "integrity": "sha512-OHp/vjdlubNlhNkPkL/+3JD34ii5ov7M0GpuXEVdQeqdQ3ulvVR7Dg/rNBLfS5XPIFwgoBLDf9sjjrL+CuDyRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.4", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "cac": "^6.7.14", + "esbuild": "^0.25.11", + "magic-string": "^0.30.19", + "picocolors": "^1.1.1" + }, + "bin": { + "electron-vite": "bin/electron-vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@swc/core": "^1.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3944,6 +4343,16 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -4537,6 +4946,13 @@ "node": ">=10" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", @@ -4560,6 +4976,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -5206,6 +5635,16 @@ "node": ">=10" } }, + "node_modules/node-releases": { + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -6533,6 +6972,37 @@ "node": ">= 4.0.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/app/package.json b/app/package.json index 885761e..c80b054 100644 --- a/app/package.json +++ b/app/package.json @@ -2,18 +2,16 @@ "name": "obelisk", "version": "0.1.0", "description": "Memory management for Obelisk — let Claude Code search its own memory", - "main": "main.js", + "main": "out/main/index.js", "scripts": { - "start": "electron .", - "dev": "node scripts/dev.js", - "dev:renderer": "vite renderer", - "build:renderer": "vite build renderer", - "build": "npm run build:renderer && electron-builder", - "pack": "npm run build:renderer && electron-builder --dir", - "dist": "npm run build:renderer && electron-builder --mac --win --linux", - "dist:mac": "npm run build:renderer && electron-builder --mac", - "dist:win": "npm run build:renderer && electron-builder --win", - "dist:linux": "npm run build:renderer && electron-builder --linux" + "start": "electron-vite preview", + "dev": "electron-vite dev", + "build": "electron-vite build && electron-builder", + "pack": "electron-vite build && electron-builder --dir", + "dist": "electron-vite build && electron-builder --mac --win --linux", + "dist:mac": "electron-vite build && electron-builder --mac", + "dist:win": "electron-vite build && electron-builder --win", + "dist:linux": "electron-vite build && electron-builder --linux" }, "build": { "appId": "com.obelisk.app", @@ -45,14 +43,10 @@ "category": "Development" }, "files": [ - "main.js", - "preload.js", - "recap-capture-query.js", - "indexer.js", - "indexer-service.js", - "indexer-worker.js", - "indexer-worker-client.js", - "dist-renderer/**/*" + "out/**" + ], + "asarUnpack": [ + "**/node_modules/better-sqlite3/**" ], "extraResources": [ { @@ -72,6 +66,7 @@ "@vitejs/plugin-vue": "^5.0.0", "electron": "^33.0.0", "electron-builder": "^25.0.0", + "electron-vite": "^5.0.0", "vite": "^6.0.0", "vue": "^3.4.0", "vue-router": "^4.3.0" diff --git a/app/renderer/vite.config.js b/app/renderer/vite.config.js deleted file mode 100644 index 62c7a0a..0000000 --- a/app/renderer/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -export default defineConfig({ - plugins: [vue()], - base: './', - build: { - outDir: '../dist-renderer', - emptyOutDir: true, - }, -}) diff --git a/app/main.js b/app/src/main/index.js similarity index 97% rename from app/main.js rename to app/src/main/index.js index 2c38a51..55cc1c2 100644 --- a/app/main.js +++ b/app/src/main/index.js @@ -241,7 +241,7 @@ async function stopBackgroundResources({ stopWorker = false } = {}) { } function createWindow() { - const isDev = process.argv.includes('--dev'); + const isDev = process.argv.includes('--dev') || !!process.env.ELECTRON_RENDERER_URL; const shouldOpenDevTools = process.argv.includes('--devtools'); const win = new BrowserWindow({ @@ -253,7 +253,7 @@ function createWindow() { trafficLightPosition: { x: 14, y: 10 }, backgroundColor: '#0a0b14', webPreferences: { - preload: path.join(__dirname, 'preload.js'), + preload: path.join(__dirname, '..', 'preload', 'index.js'), contextIsolation: true, nodeIntegration: false, devTools: isDev || shouldOpenDevTools, @@ -268,12 +268,12 @@ function createWindow() { }); if (isDev) { - win.loadURL(process.env.OBELISK_DEV_SERVER_URL || 'http://localhost:5173'); + win.loadURL(process.env.ELECTRON_RENDERER_URL || process.env.OBELISK_DEV_SERVER_URL || 'http://localhost:5173'); if (shouldOpenDevTools) { win.webContents.openDevTools(); } } else { - win.loadFile(path.join(__dirname, 'dist-renderer', 'index.html')); + win.loadFile(path.join(__dirname, '..', 'renderer', 'index.html')); } } @@ -607,7 +607,7 @@ async function createExportCapture(parentWin, query) { height: EXPORT_HEIGHT, show: false, webPreferences: { - preload: path.join(__dirname, 'preload.js'), + preload: path.join(__dirname, '..', 'preload', 'index.js'), contextIsolation: true, nodeIntegration: false, offscreen: true, @@ -615,10 +615,10 @@ async function createExportCapture(parentWin, query) { }, }); - const isDev = process.argv.includes('--dev'); + const isDev = process.argv.includes('--dev') || !!process.env.ELECTRON_RENDERER_URL; const url = isDev - ? `http://localhost:5173/#/recap-export?${query}` - : `file://${path.join(__dirname, 'dist-renderer', 'index.html')}#/recap-export?${query}`; + ? `${process.env.ELECTRON_RENDERER_URL || 'http://localhost:5173'}/#/recap-export?${query}` + : `file://${path.join(__dirname, '..', 'renderer', 'index.html')}#/recap-export?${query}`; await exportWin.loadURL(url); await waitForExportReady(exportWin.webContents); diff --git a/app/indexer-service.js b/app/src/main/indexer-service.js similarity index 100% rename from app/indexer-service.js rename to app/src/main/indexer-service.js diff --git a/app/indexer-worker-client.js b/app/src/main/indexer-worker-client.js similarity index 100% rename from app/indexer-worker-client.js rename to app/src/main/indexer-worker-client.js diff --git a/app/indexer-worker.js b/app/src/main/indexer-worker.js similarity index 100% rename from app/indexer-worker.js rename to app/src/main/indexer-worker.js diff --git a/app/indexer.js b/app/src/main/indexer.js similarity index 99% rename from app/indexer.js rename to app/src/main/indexer.js index 925f381..51f25f0 100644 --- a/app/indexer.js +++ b/app/src/main/indexer.js @@ -14,7 +14,7 @@ const DEFAULT_HISTORY_PATH = path.join(DEFAULT_CLAUDE_DIR, 'history.jsonl'); function resolveSchemaPath() { const candidates = [ path.join(__dirname, 'schema.sql'), - path.join(__dirname, '..', 'scripts', 'schema.sql'), + path.join(__dirname, '..', '..', '..', 'scripts', 'schema.sql'), process.resourcesPath ? path.join(process.resourcesPath, 'scripts', 'schema.sql') : null, ].filter(Boolean); const found = candidates.find(p => fs.existsSync(p)); diff --git a/app/recap-capture-query.js b/app/src/main/recap-capture-query.js similarity index 100% rename from app/recap-capture-query.js rename to app/src/main/recap-capture-query.js diff --git a/app/preload.js b/app/src/preload/index.js similarity index 100% rename from app/preload.js rename to app/src/preload/index.js diff --git a/app/renderer/index.html b/app/src/renderer/index.html similarity index 100% rename from app/renderer/index.html rename to app/src/renderer/index.html diff --git a/app/renderer/js/app.js b/app/src/renderer/js/app.js similarity index 100% rename from app/renderer/js/app.js rename to app/src/renderer/js/app.js diff --git a/app/renderer/js/data.js b/app/src/renderer/js/data.js similarity index 100% rename from app/renderer/js/data.js rename to app/src/renderer/js/data.js diff --git a/app/renderer/js/keys.js b/app/src/renderer/js/keys.js similarity index 100% rename from app/renderer/js/keys.js rename to app/src/renderer/js/keys.js diff --git a/app/renderer/js/memory-list.js b/app/src/renderer/js/memory-list.js similarity index 100% rename from app/renderer/js/memory-list.js rename to app/src/renderer/js/memory-list.js diff --git a/app/renderer/js/registry.js b/app/src/renderer/js/registry.js similarity index 100% rename from app/renderer/js/registry.js rename to app/src/renderer/js/registry.js diff --git a/app/renderer/js/render.js b/app/src/renderer/js/render.js similarity index 100% rename from app/renderer/js/render.js rename to app/src/renderer/js/render.js diff --git a/app/renderer/js/session-list.js b/app/src/renderer/js/session-list.js similarity index 100% rename from app/renderer/js/session-list.js rename to app/src/renderer/js/session-list.js diff --git a/app/renderer/js/sidebar.js b/app/src/renderer/js/sidebar.js similarity index 100% rename from app/renderer/js/sidebar.js rename to app/src/renderer/js/sidebar.js diff --git a/app/renderer/js/state.js b/app/src/renderer/js/state.js similarity index 100% rename from app/renderer/js/state.js rename to app/src/renderer/js/state.js diff --git a/app/renderer/js/usage.js b/app/src/renderer/js/usage.js similarity index 100% rename from app/renderer/js/usage.js rename to app/src/renderer/js/usage.js diff --git a/app/renderer/js/utils.js b/app/src/renderer/js/utils.js similarity index 100% rename from app/renderer/js/utils.js rename to app/src/renderer/js/utils.js diff --git a/app/renderer/src/App.vue b/app/src/renderer/src/App.vue similarity index 100% rename from app/renderer/src/App.vue rename to app/src/renderer/src/App.vue diff --git a/app/renderer/src/assets/recap-cards.html b/app/src/renderer/src/assets/recap-cards.html similarity index 100% rename from app/renderer/src/assets/recap-cards.html rename to app/src/renderer/src/assets/recap-cards.html diff --git a/app/renderer/src/components/Sidebar.vue b/app/src/renderer/src/components/Sidebar.vue similarity index 100% rename from app/renderer/src/components/Sidebar.vue rename to app/src/renderer/src/components/Sidebar.vue diff --git a/app/renderer/src/components/Toolbar.vue b/app/src/renderer/src/components/Toolbar.vue similarity index 100% rename from app/renderer/src/components/Toolbar.vue rename to app/src/renderer/src/components/Toolbar.vue diff --git a/app/renderer/src/components/recap/ClosingCard.vue b/app/src/renderer/src/components/recap/ClosingCard.vue similarity index 100% rename from app/renderer/src/components/recap/ClosingCard.vue rename to app/src/renderer/src/components/recap/ClosingCard.vue diff --git a/app/renderer/src/components/recap/CoverCard.vue b/app/src/renderer/src/components/recap/CoverCard.vue similarity index 100% rename from app/renderer/src/components/recap/CoverCard.vue rename to app/src/renderer/src/components/recap/CoverCard.vue diff --git a/app/renderer/src/components/recap/PathCard.vue b/app/src/renderer/src/components/recap/PathCard.vue similarity index 100% rename from app/renderer/src/components/recap/PathCard.vue rename to app/src/renderer/src/components/recap/PathCard.vue diff --git a/app/renderer/src/components/recap/VibeCard.vue b/app/src/renderer/src/components/recap/VibeCard.vue similarity index 100% rename from app/renderer/src/components/recap/VibeCard.vue rename to app/src/renderer/src/components/recap/VibeCard.vue diff --git a/app/renderer/src/components/recap/WorkflowCard.vue b/app/src/renderer/src/components/recap/WorkflowCard.vue similarity index 100% rename from app/renderer/src/components/recap/WorkflowCard.vue rename to app/src/renderer/src/components/recap/WorkflowCard.vue diff --git a/app/renderer/src/components/recap/archetypes.js b/app/src/renderer/src/components/recap/archetypes.js similarity index 100% rename from app/renderer/src/components/recap/archetypes.js rename to app/src/renderer/src/components/recap/archetypes.js diff --git a/app/renderer/src/components/recap/card-base.css b/app/src/renderer/src/components/recap/card-base.css similarity index 100% rename from app/renderer/src/components/recap/card-base.css rename to app/src/renderer/src/components/recap/card-base.css diff --git a/app/renderer/src/components/recap/seals.js b/app/src/renderer/src/components/recap/seals.js similarity index 100% rename from app/renderer/src/components/recap/seals.js rename to app/src/renderer/src/components/recap/seals.js diff --git a/app/renderer/src/data.js b/app/src/renderer/src/data.js similarity index 100% rename from app/renderer/src/data.js rename to app/src/renderer/src/data.js diff --git a/app/renderer/src/main.js b/app/src/renderer/src/main.js similarity index 100% rename from app/renderer/src/main.js rename to app/src/renderer/src/main.js diff --git a/app/renderer/src/mock/recap-2026-W24.json b/app/src/renderer/src/mock/recap-2026-W24.json similarity index 100% rename from app/renderer/src/mock/recap-2026-W24.json rename to app/src/renderer/src/mock/recap-2026-W24.json diff --git a/app/renderer/src/router.js b/app/src/renderer/src/router.js similarity index 100% rename from app/renderer/src/router.js rename to app/src/renderer/src/router.js diff --git a/app/renderer/src/session-live.mjs b/app/src/renderer/src/session-live.mjs similarity index 100% rename from app/renderer/src/session-live.mjs rename to app/src/renderer/src/session-live.mjs diff --git a/app/renderer/src/sidebar-projects.mjs b/app/src/renderer/src/sidebar-projects.mjs similarity index 100% rename from app/renderer/src/sidebar-projects.mjs rename to app/src/renderer/src/sidebar-projects.mjs diff --git a/app/renderer/src/store.js b/app/src/renderer/src/store.js similarity index 100% rename from app/renderer/src/store.js rename to app/src/renderer/src/store.js diff --git a/app/renderer/src/utils.js b/app/src/renderer/src/utils.js similarity index 100% rename from app/renderer/src/utils.js rename to app/src/renderer/src/utils.js diff --git a/app/renderer/src/views/Activity.vue b/app/src/renderer/src/views/Activity.vue similarity index 100% rename from app/renderer/src/views/Activity.vue rename to app/src/renderer/src/views/Activity.vue diff --git a/app/renderer/src/views/MemoryDetail.vue b/app/src/renderer/src/views/MemoryDetail.vue similarity index 100% rename from app/renderer/src/views/MemoryDetail.vue rename to app/src/renderer/src/views/MemoryDetail.vue diff --git a/app/renderer/src/views/MemoryList.vue b/app/src/renderer/src/views/MemoryList.vue similarity index 100% rename from app/renderer/src/views/MemoryList.vue rename to app/src/renderer/src/views/MemoryList.vue diff --git a/app/renderer/src/views/RecapDetail.vue b/app/src/renderer/src/views/RecapDetail.vue similarity index 100% rename from app/renderer/src/views/RecapDetail.vue rename to app/src/renderer/src/views/RecapDetail.vue diff --git a/app/renderer/src/views/RecapExport.vue b/app/src/renderer/src/views/RecapExport.vue similarity index 100% rename from app/renderer/src/views/RecapExport.vue rename to app/src/renderer/src/views/RecapExport.vue diff --git a/app/renderer/src/views/RecapList.vue b/app/src/renderer/src/views/RecapList.vue similarity index 100% rename from app/renderer/src/views/RecapList.vue rename to app/src/renderer/src/views/RecapList.vue diff --git a/app/renderer/src/views/SessionDetail.vue b/app/src/renderer/src/views/SessionDetail.vue similarity index 100% rename from app/renderer/src/views/SessionDetail.vue rename to app/src/renderer/src/views/SessionDetail.vue diff --git a/app/renderer/src/views/SessionList.vue b/app/src/renderer/src/views/SessionList.vue similarity index 100% rename from app/renderer/src/views/SessionList.vue rename to app/src/renderer/src/views/SessionList.vue diff --git a/app/renderer/src/views/Settings.vue b/app/src/renderer/src/views/Settings.vue similarity index 100% rename from app/renderer/src/views/Settings.vue rename to app/src/renderer/src/views/Settings.vue diff --git a/app/renderer/src/views/SubagentDetail.vue b/app/src/renderer/src/views/SubagentDetail.vue similarity index 100% rename from app/renderer/src/views/SubagentDetail.vue rename to app/src/renderer/src/views/SubagentDetail.vue diff --git a/app/renderer/styles/base.css b/app/src/renderer/styles/base.css similarity index 100% rename from app/renderer/styles/base.css rename to app/src/renderer/styles/base.css diff --git a/app/renderer/styles/detail.css b/app/src/renderer/styles/detail.css similarity index 100% rename from app/renderer/styles/detail.css rename to app/src/renderer/styles/detail.css diff --git a/app/renderer/styles/list.css b/app/src/renderer/styles/list.css similarity index 100% rename from app/renderer/styles/list.css rename to app/src/renderer/styles/list.css diff --git a/app/renderer/styles/sidebar.css b/app/src/renderer/styles/sidebar.css similarity index 100% rename from app/renderer/styles/sidebar.css rename to app/src/renderer/styles/sidebar.css diff --git a/app/renderer/styles/statusbar.css b/app/src/renderer/styles/statusbar.css similarity index 100% rename from app/renderer/styles/statusbar.css rename to app/src/renderer/styles/statusbar.css diff --git a/app/renderer/styles/toolbar.css b/app/src/renderer/styles/toolbar.css similarity index 100% rename from app/renderer/styles/toolbar.css rename to app/src/renderer/styles/toolbar.css diff --git a/app/yarnball.md b/app/yarnball.md new file mode 100644 index 0000000..47a1b7c --- /dev/null +++ b/app/yarnball.md @@ -0,0 +1,8 @@ + +--- 2026-06-18 Activity noise folding phase --- +- Task: fold noise sessions/projects in Activity.vue (monthly + daily lists) +- Noise rules already used: NOISE_PROJECT_RE = /^(od-conn-test|[0-9a-f]{6,})/i in App.vue; SessionList: !s.title means noise +- Activity.vue has 3 group types per block: newWorkspaces / newSessions / continued +- Approach: per-block compute noise split, render normal first then single fold banner toggling all noise in that block +- Default collapsed; banner says 'N hidden — likely test/throwaway runs' + diff --git a/tests/app-indexer-service.test.mjs b/tests/app-indexer-service.test.mjs index 53d9020..1acde12 100644 --- a/tests/app-indexer-service.test.mjs +++ b/tests/app-indexer-service.test.mjs @@ -6,7 +6,7 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; const require = createRequire(import.meta.url); -const { createIndexerService } = require('../app/indexer-service.js'); +const { createIndexerService } = require('../app/src/main/indexer-service.js'); function manualTimers() { const timers = new Set(); diff --git a/tests/app-indexer-worker-client.test.mjs b/tests/app-indexer-worker-client.test.mjs index 9f12d02..1c559c5 100644 --- a/tests/app-indexer-worker-client.test.mjs +++ b/tests/app-indexer-worker-client.test.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); -const { createWorkerBuildIndex } = require('../app/indexer-worker-client.js'); +const { createWorkerBuildIndex } = require('../app/src/main/indexer-worker-client.js'); test('worker build client resolves build results from a worker thread', async () => { const instances = []; diff --git a/tests/app-indexer.test.mjs b/tests/app-indexer.test.mjs index 4e196e5..f17e82c 100644 --- a/tests/app-indexer.test.mjs +++ b/tests/app-indexer.test.mjs @@ -6,7 +6,7 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; const require = createRequire(import.meta.url); -const { buildIndex } = require('../app/indexer.js'); +const { buildIndex } = require('../app/src/main/indexer.js'); const { DatabaseSync } = require('node:sqlite'); class TestDatabase { diff --git a/tests/app-main-settings.test.mjs b/tests/app-main-settings.test.mjs index 3f329a3..72f681d 100644 --- a/tests/app-main-settings.test.mjs +++ b/tests/app-main-settings.test.mjs @@ -12,7 +12,7 @@ async function loadMainForWindowFlags(flags) { const originalArgv = process.argv; const originalHome = process.env.HOME; const originalLoad = Module._load; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); const home = join(tmpdir(), `obelisk-window-flags-${Date.now()}-${Math.random()}`); mkdirSync(join(home, '.obelisk'), { recursive: true }); writeFileSync(join(home, '.obelisk', 'obelisk.sqlite'), ''); @@ -93,7 +93,7 @@ async function loadMainForWindowFlags(flags) { }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); return windows; } finally { @@ -137,7 +137,7 @@ test('main process watches Codex sessions directory instead of Codex root', asyn process.env.HOME = home; const serviceOptions = []; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeDatabase { @@ -202,7 +202,7 @@ test('main process watches Codex sessions directory instead of Codex root', asyn }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); assert.equal(serviceOptions.length, 1); @@ -229,7 +229,7 @@ test('session IPC hides Codex rows by default and supports explicit source opt-i const ipcHandlers = new Map(); const queries = []; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeDatabase { @@ -305,7 +305,7 @@ test('session IPC hides Codex rows by default and supports explicit source opt-i }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); ipcHandlers.get('db:getSessions')(null, {}); @@ -373,7 +373,7 @@ test('main process migrates an existing app database before source-filtered IPC legacy.close(); const ipcHandlers = new Map(); - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeBrowserWindow { @@ -454,7 +454,7 @@ test('main process migrates an existing app database before source-filtered IPC }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); const sessions = ipcHandlers.get('db:getSessions')(null, {}); @@ -480,7 +480,7 @@ test('closing the last macOS window releases background resources until activati const home = join(tmpdir(), `obelisk-main-window-${Date.now()}`); mkdirSync(join(home, '.obelisk'), { recursive: true }); writeFileSync(join(home, '.obelisk', 'obelisk.sqlite'), ''); - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; process.env.HOME = home; Object.defineProperty(process, 'platform', { value: 'darwin' }); @@ -561,7 +561,7 @@ test('closing the last macOS window releases background resources until activati }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); assert.equal(windows.length, 1); @@ -618,7 +618,7 @@ test('settings rebuild reopens the database from the configured Claude path', as const buildCalls = []; const serviceEvents = []; const originalLoad = Module._load; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeDatabase { @@ -703,7 +703,7 @@ test('settings rebuild reopens the database from the configured Claude path', as }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); const rebuild = ipcHandlers.get('settings:rebuildIndex'); @@ -750,7 +750,7 @@ test('settings rebuild keeps the existing database after a worker failure', asyn const closedDbPaths = []; const serviceEvents = []; const originalLoad = Module._load; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeDatabase { @@ -834,7 +834,7 @@ test('settings rebuild keeps the existing database after a worker failure', asyn }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); const rebuild = ipcHandlers.get('settings:rebuildIndex'); @@ -878,7 +878,7 @@ test('settings rebuild cancels an in-flight background build instead of waiting const ipcHandlers = new Map(); const serviceEvents = []; const originalLoad = Module._load; - const mainPath = require.resolve('../app/main.js'); + const mainPath = require.resolve('../app/src/main/index.js'); delete require.cache[mainPath]; class FakeDatabase { @@ -963,7 +963,7 @@ test('settings rebuild cancels an in-flight background build instead of waiting }; try { - require('../app/main.js'); + require('../app/src/main/index.js'); await new Promise(resolve => setImmediate(resolve)); const rebuild = ipcHandlers.get('settings:rebuildIndex'); diff --git a/tests/recap-capture-query.test.mjs b/tests/recap-capture-query.test.mjs index c13821f..af0c750 100644 --- a/tests/recap-capture-query.test.mjs +++ b/tests/recap-capture-query.test.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); -const { buildRecapExportQuery, cleanRecapFilename } = require('../app/recap-capture-query.js'); +const { buildRecapExportQuery, cleanRecapFilename } = require('../app/src/main/recap-capture-query.js'); test('recap export query includes the selected recap filename', () => { const query = buildRecapExportQuery({ diff --git a/tests/recap-patterns.test.mjs b/tests/recap-patterns.test.mjs index a983839..5fb5a25 100644 --- a/tests/recap-patterns.test.mjs +++ b/tests/recap-patterns.test.mjs @@ -155,10 +155,10 @@ test('cover card retrieval and writing choose one dominant human claim', async ( test('cover card schema uses claim instead of subtitle', async () => { const pattern = await read('references/recap/pattern1-cover.md'); const writing = await read('references/recap/writing1-cover.md'); - const component = await read('app/renderer/src/components/recap/CoverCard.vue'); - const detail = await read('app/renderer/src/views/RecapDetail.vue'); - const list = await read('app/renderer/src/views/RecapList.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/CoverCard.vue'); + const detail = await read('app/src/renderer/src/views/RecapDetail.vue'); + const list = await read('app/src/renderer/src/views/RecapList.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(pattern, /claim that lists three topics/i); assert.doesNotMatch(pattern, /subtitle/); @@ -197,8 +197,8 @@ test('thinking card retrieval searches for turns instead of implementation timel test('thinking path schema uses turn instead of outcome', async () => { const pattern = await read('references/recap/pattern2-thinking.md'); const writing = await read('references/recap/writing2-thinking.md'); - const component = await read('app/renderer/src/components/recap/PathCard.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/PathCard.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(pattern, /prompt, turn, and an `evidence` anchor/i); assert.doesNotMatch(pattern, /outcome/); @@ -230,9 +230,9 @@ test('vibe card retrieval finds small user voice, not a correction audit', async test('vibe card schema uses voice_lines instead of observations', async () => { const writing = await read('references/recap/writing3-vibe.md'); - const component = await read('app/renderer/src/components/recap/VibeCard.vue'); - const detail = await read('app/renderer/src/views/RecapDetail.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/VibeCard.vue'); + const detail = await read('app/src/renderer/src/views/RecapDetail.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(writing, /voice_lines: Array/); assert.match(writing, /"voice_lines": \[/); @@ -273,8 +273,8 @@ test('workflow card retrieval scopes real workflow runs and user reactions', asy test('workflow card uses reaction instead of outcome for row copy', async () => { const pattern = await read('references/recap/pattern4-workflow.md'); const writing = await read('references/recap/writing4-workflow.md'); - const component = await read('app/renderer/src/components/recap/WorkflowCard.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/WorkflowCard.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(pattern, /items\[\]\.reaction/i); assert.match(writing, /reaction: string/); @@ -288,9 +288,9 @@ test('workflow card uses reaction instead of outcome for row copy', async () => test('workflow card schema uses deck instead of summary for the visible line', async () => { const writing = await read('references/recap/writing4-workflow.md'); - const component = await read('app/renderer/src/components/recap/WorkflowCard.vue'); - const detail = await read('app/renderer/src/views/RecapDetail.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/WorkflowCard.vue'); + const detail = await read('app/src/renderer/src/views/RecapDetail.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(writing, /deck\?: string/); assert.match(writing, /"deck": "你召唤了机器军团。结果各有不同。"/); @@ -323,9 +323,9 @@ test('closing card retrieval and writing keep a small personal receipt', async ( test('closing card schema uses receipts instead of stats', async () => { const pattern = await read('references/recap/pattern5-closing.md'); const writing = await read('references/recap/writing5-closing.md'); - const component = await read('app/renderer/src/components/recap/ClosingCard.vue'); - const detail = await read('app/renderer/src/views/RecapDetail.vue'); - const mock = await read('app/renderer/src/mock/recap-2026-W24.json'); + const component = await read('app/src/renderer/src/components/recap/ClosingCard.vue'); + const detail = await read('app/src/renderer/src/views/RecapDetail.vue'); + const mock = await read('app/src/renderer/src/mock/recap-2026-W24.json'); assert.match(pattern, /one or two compact receipts/i); assert.doesNotMatch(pattern, /receipt stats/); diff --git a/tests/session-live.test.mjs b/tests/session-live.test.mjs index 052468d..3f0dda4 100644 --- a/tests/session-live.test.mjs +++ b/tests/session-live.test.mjs @@ -5,7 +5,7 @@ import { createSessionLiveState, consumeSessionDirty, noteSessionUpdated, -} from '../app/renderer/src/session-live.mjs'; +} from '../app/src/renderer/src/session-live.mjs'; test('session live state marks non-visible updated sessions as dirty', () => { const live = createSessionLiveState(); diff --git a/tests/sidebar-projects.test.mjs b/tests/sidebar-projects.test.mjs index 69ab670..4ab2837 100644 --- a/tests/sidebar-projects.test.mjs +++ b/tests/sidebar-projects.test.mjs @@ -1,6 +1,6 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { buildSidebarProjects } from '../app/renderer/src/sidebar-projects.mjs'; +import { buildSidebarProjects } from '../app/src/renderer/src/sidebar-projects.mjs'; test('session sidebar projects follow database recency order instead of label order', () => { const sessions = [