DeepSeek Harness Remote
DeepSeek Harness Remote 可将手机或另一台电脑与你运行 DeepSeek Harness 的电脑安全连接,随时随地继续你的工作,方便随时查看进度并继续工作。
AI 翻译
尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Kave Compass ("Compass" in the code, the cache names and the repo) is the household planner: events, what they cost, trips, and the loose ends attached to them. Replaces Google Calendar and the yearly planning sheet.
This branch is v2.0, Kave Compass on Material 3 (the version is VERSION
in service-worker.js). Two tabs: Calendar (a week or month strip over the
agenda, with one sheet for a day, an event or a ticket, and the event form)
and Insights (the next trip, the year in numbers, the ticket wall and the
clean-up cards). Settings, the Roadmap and the Archive are pages reached from
the menu drawer, and a magnifier in the top bar searches the whole app. Trips
and Radar are not built: they are lines on the Roadmap page. The data model,
the sync engine and the three imported years are sub-project A, unchanged.
The design is a set of documents in the private kave-hub repo, starting with
docs/superpowers/specs/2026-09-24-compass-a-core-design.md; what is next is
calendar/data/roadmap.md there, and the product brainstorm for the later
sub-projects is calendar/data/compass-planning-app-brainstorm.md.
This repo is the static app shell only. No data, no secrets. It is public so GitHub Pages can serve it for free.
The repo is the data store. Events, cost lines, checklists, travel data,
the insights queue and voice-note transcripts all live in the private
DarkpizzAi/kave-hub repo under calendar/data/, reached with
a personal token pasted in Settings. That is the pattern this shell was built
on and it stands. The finance facts log Compass writes to is not Compass
data: it lives with the finance plugin, finance/data/ in kave-hub.
An always-on mini PC runs what the app cannot. Arriving early October 2026, on 24/7, also a media server. It runs two separable scheduled jobs: a nightly pass that scans both inboxes, reads new bank extracts, transcribes voice notes and matches them against existing events; and a morning pass that sends each person's recap email. Two jobs, so a failure in one does not kill the other.
It beats a scheduled GitHub Action or a small VPS for one specific reason: Gmail and the bank extracts never leave the house.
Standing principle: repo first, box second. Only genuinely sensitive things live on the mini PC, and as little as possible - Gmail OAuth tokens, any bank credentials, raw audio pending transcription, and the scheduled jobs themselves. Everything else is in the repo, because anything on the box is invisible, unversioned and lost if the box dies.
Known risk: the box is a single point of failure - asleep, rebooting, Windows updating. Survivable only because a last-scanned timestamp makes it visible in the app.
Nothing personal is ever committed to this repo, which is the public shell.
Interpretation, never amounts. The bank extracts are the source of truth for money. Compass enriches them: whose a line is, how it splits, which trip it belongs to. A cost typed into Compass is a claim until a sweep matches it to a bank line and someone locks it; on a mismatch the bank's figure wins. The finance side reads the extracts and consults Compass, one way.
What Compass is the source of truth for is everything the bank cannot know: events, trips and their phases, checklists, ideas on the Radar, and the decisions people made on insights.
python dev_server.py
Then open http://localhost:8778/. Port 8778 so it runs alongside Spoon
(8777) and the kave-hub page (8642). The server sends no-store, so a plain
reload always shows your latest edit. The service worker does not run on
localhost, and tears itself down if it ever finds itself there.
Kave Compass is on Material 3. The kit lives in m3/ (kave-m3-tokens.css,
kave-m3.css, kave-m3.js) and is generated: copied from brand/ in
kave-hub by that repo's brand/tools/sync-household-tokens.py, together with
the icons at the repo root. Never hand-edit m3/. Edit the hub and
re-sync. To check this copy has not drifted, from the kave-hub repo:
python brand/tools/sync-household-tokens.py --check
The palette is one of five seeds (blue, teal, yellow, periwinkle,
terracotta), set as <html data-seed> by #theme-preload and
js/theme.js; a stored cobalt, amber or chartreuse maps to blue,
yellow, blue. js/boot.js sets <html data-size> (compact, medium or
expanded) from the kit's sizeClass. styles.css uses the kit's tokens and
defines no colour of its own. tokens.css (pre-Material) is still synced by
the script and still sits in the repo, but index.html no longer links it and
SHELL no longer caches it.
The icons are generated too: icon-512.png, icon-192.png,
icon-512-maskable.png, icon-512-monochrome.png, apple-touch-icon.png,
favicon-32.png and favicon.svg are copied to the repo root from
brand/icons/compass/ in kave-hub by the same sync-household-tokens.py. Never
hand-edit them: change the artwork in the hub, re-sync, and bump VERSION in
service-worker.js. manifest.json lists 192 and 512 as any, 512 as
maskable and 512 as monochrome.
Pushed to main, served by GitHub Pages. Relative fetch paths, so a subpath
is fine.
Bump VERSION in service-worker.js on every deploy. A token change is a
deploy too: a stale service worker will happily keep serving the old look.
Never rename this repo, its Pages URL, or the service-worker cache name. They are the deployment's identity. Renaming moves the live URL and orphans every installed copy on every phone.
The GitHub token lives in localStorage, under compass.settings, in plain
text. There is nowhere better: this is a static page with no server of its
own, so a token that survives a reload has to sit somewhere any script on the
origin can read. github.js never touches storage - the app pushes the token
in with setToken() - but that is layering, not protection. The input is
type="password" with autocomplete="off", and the token is never logged,
never put in a URL, and never rendered into markup: it goes into an
Authorization header, to api.github.com and nowhere else.
That means XSS is the whole threat model. Anything that can run script on
this origin can read the token and write to the hub repo. So: no synced string
reaches the DOM as markup, every interpolation goes through escapeHtml,
every URL through safeUrl, and there is no eval, no new Function, no
document.write and no insertAdjacentHTML.
There is a Content-Security-Policy as a <meta http-equiv> in
index.html, because Pages serves static files and cannot set headers. The
load-bearing part is script-src 'self' plus a single hash, with no
'unsafe-inline' and no 'unsafe-eval'. connect-src is 'self' and
api.github.com only. A meta CSP silently ignores frame-ancestors,
report-uri and sandbox, so they are absent rather than written down doing
nothing: clickjacking is not covered.
If a token is ever exposed, revoke it on GitHub. Clearing it in Settings only removes this device's copy.
script-src carries a sha256 of #theme-preload, the anti-flash palette
script inlined in index.html. Edit that script - one character of whitespace
is enough - and the hash stops matching and the script is blocked. Recompute
it with:
python -c "import re,hashlib,base64;b=re.search(rb'<script id=\"theme-preload\">(.*?)</script>',open('index.html','rb').read(),re.S).group(1);print('sha256-'+base64.b64encode(hashlib.sha256(b).digest()).decode())"
It matches on the id rather than on the first <script> in the file, and it
lives here rather than in index.html for the reason that cost Spoon an
iteration: a command containing the text <script></script> is itself the
first thing a regex hunting for the script finds, so documenting it in the
file it parses made it hash its own documentation.
A blocked script would otherwise be silent - the symptom is the colour flash
it exists to prevent, not an error. So it announces itself: the script stamps
data-theme-boot on <html> before doing anything else, and Settings shows a
red Theme preload BLOCKED line when that stamp is missing.
.gitattributes pins eol=lf, so the bytes hashed locally are the bytes
Pages serves - a CRLF working tree would hash to something production rejects.
Native ES modules, no bundler, no build step.
| Module | Does |
|---|---|
js/util.js | escapeHtml, safeUrl, uid, own |
js/store.js | persisted state, localStorage under compass.* |
js/theme.js | palette selection, colour-scheme, CSP-boot diagnostic |
js/sync.js | sync status (what each sync announces, never what it does) and the token check |
js/local.js, js/merge.js | local cache/queue, per-event merge |
js/model.js, js/dates.js, js/money.js | the event record, dates, costs |
js/data.js | the app's data instance over sync + local |
js/cal-model.js | pure Calendar logic (weeks, filters, trip/away rules) |
js/views.js | loadRange: how far the calendar reaches (a year back to two years ahead) |
js/holidays.js, js/filter.js | Barcelona bank holidays (shipped with the app); the Full and Minimal detail levels |
js/icons.js, js/chrome-icons.js | the category catalogue, app-chrome SVGs |
js/calendar.js | the Calendar tab: drawing and its handlers |
js/sheet.js | the sheet system: the bottom or side sheet and its levels, the form container, and the layers over them (menus, dialogs, pickers), one history entry each |
js/view-event.js, js/event-form.js | the event page and form; the pure form logic (drafts, cost rules, the save-time cost merge) |
js/ticket-view.js, js/tickets.js | the ticket viewer level; tickets kept on the phone in Cache Storage (compass-tickets) |
js/insights-data.js, js/view-insights.js, js/cleanup.js | the Insights tab: pure data, drawing and its sheets, and the clean-up queue and answers outbox |
This table names the modules, not their exact count - SHELL in
service-worker.js is the ground truth for what must load offline. A
module must be listed there in the same commit it's added; that list is
what to diff against js/*.js, not this table.
Every module must be listed in SHELL in service-worker.js. A module
missing there is a module the app cannot load offline, and nothing will say so
until someone opens Compass with no signal.
State lives in three places by lifetime: persisted store.state mirrored to
localStorage; module-level transient UI state that calls its own render
directly; and derived locals. Rendering is a full re-render on every
interaction, which is fine at this size and is the thing to know before adding
features.
v2.0, Kave Compass on Material 3, is built on a branch and not deployed yet.
Calendar (strip, month and agenda; the day, event and ticket sheet; the event
form with its date and time pickers), Insights, whole-app search, and the pages
Settings (palette, Calendar defaults, Grid emoji order, Archive, sync status,
who-am-I, app link, token, check for updates), Roadmap and Archive. The browser
tests live in tests/ (open http://localhost:8778/tests/).
Next: Trips and Radar, which are Roadmap lines until they are built.
Sub-project A (the data model and sync engine, the Calendar tab with Grid and
Agenda in one sheet with levels, the event page and form, Settings with free
time, and three years imported from the sheet) shipped first and was live on
main. Insights, Trips and Radar were dashed stubs then, and sub-project B
(Trips and Radar) was next. Superseded by v2.0 (Kave Compass on Material 3):
Insights is built, free-time highlighting is gone, and Trips and Radar left
the navigation for the Roadmap page.
js/prefs.js |
| Calendar defaults (view, detail level) and the Grid emoji order |
js/updates.js | check-for-updates and the sticky "A new version is ready" snackbar |
js/search.js | the whole-app search page: events, tickets, categories |
js/pickers.js | the Material date picker and the 24-hour time dial the event form opens |
js/view-roadmap.js | the Roadmap page: what each part is for, and what is coming |
m3/kave-m3.js | the Material 3 kit's behaviour (motion, layers, snackbars, size class); generated |
js/gate.js | the first-run gate: token, who, theme (the hub site's screen) |
js/render.js | the frame (navigation, top bar, drawer, pages) and Settings |
js/wire.js | one-time listeners, sync snackbars, pull to refresh, the banner |
js/boot.js | entry point, service-worker registration |
github.js | Contents API client, carried over from Spoon |