Compare commits
10 commits
8b174976e6
...
66423cf66b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66423cf66b | ||
|
|
ec18f30f6d | ||
|
|
f1db2f3b2d | ||
|
|
4be80803d4 | ||
|
|
cc5baa712b | ||
|
|
10a4c1227b | ||
|
|
e26f7e141b | ||
|
|
516d6a1b34 | ||
|
|
0352f8d04b | ||
|
|
3509d29882 |
15 changed files with 950 additions and 360 deletions
20
AGENTS.md
20
AGENTS.md
|
|
@ -48,6 +48,26 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
|
|||
- `trash` > `rm` (recoverable beats gone forever)
|
||||
- When in doubt, ask.
|
||||
|
||||
### 🔑 Credentials
|
||||
- **Never read credential files.** Not even to "verify" or "check" them.
|
||||
- When setting up a new integration, create `.credentials/service.env` with **placeholder values** and let the human fill them in.
|
||||
- Scripts source credentials at runtime — you don't need to see them.
|
||||
- Example placeholder file:
|
||||
```
|
||||
SERVICE_URL=https://example.com
|
||||
SERVICE_API_KEY=FILL_IN
|
||||
SERVICE_USER=FILL_IN
|
||||
```
|
||||
|
||||
## Evening Wind-Down (19:00-23:00 Vienna)
|
||||
|
||||
After 19:00 Vienna time, you're in wind-down mode. This applies in **all conversations**, not just heartbeats:
|
||||
|
||||
- **If chatting about work/tinkering**: Actively look for stopping points. When a subtask completes or there's a natural pause, suggest wrapping up. Don't just passively help them keep going.
|
||||
- **If they want to start something new after 20:00**: Gently suggest postponing to tomorrow.
|
||||
- **Concrete suggestions**: Use `bin/jellyfin` and `bin/audiobooks` to suggest specific shows/audiobooks instead of vague "maybe wind down."
|
||||
- **Evening reminders**: When they're transitioning to wind-down, remind about evening recurring tasks (e.g., nose shower) before they get too comfortable.
|
||||
|
||||
## External vs Internal
|
||||
|
||||
**Safe to do freely:**
|
||||
|
|
|
|||
32
HEARTBEAT.md
32
HEARTBEAT.md
|
|
@ -8,19 +8,17 @@ Check the following and notify only once per event (track in `memory/heartbeat-s
|
|||
|
||||
3. **Evening wind-down guidance (19:00-22:00 Vienna)**:
|
||||
|
||||
**Active work detection**: If user is chatting with me about work tasks, I KNOW they're working. Don't just passively help — actively look for stopping points.
|
||||
|
||||
**During work conversations after 19:00**:
|
||||
- Track how long the current task has been going
|
||||
- When a subtask completes or there's a natural pause, suggest: "This might be a good stopping point for tonight"
|
||||
- If a task is dragging on (30+ min with no end in sight), gently note: "This is getting complex — want to pick it up tomorrow with fresh eyes?"
|
||||
- Don't wait for them to ask — proactively identify when a task can be paused
|
||||
**First nudge at 19:00**: On the first heartbeat at/after 19:00 Vienna, always check in — ask what they're doing if not in active conversation, or nudge toward winding down if already chatting about work/tinkering.
|
||||
|
||||
**If NOT in active conversation**: Send a brief WhatsApp asking what they're doing (working? winding down? about to start something new?). Log responses in `memory/wind-down-log.json`.
|
||||
|
||||
**If they're about to start something new after 20:00**: Gently suggest postponing to tomorrow.
|
||||
**Concrete wind-down suggestions**: Don't just say "maybe wind down" — use real data:
|
||||
- `bin/jellyfin resume` → suggest continuing what they're watching
|
||||
- `bin/jellyfin recent` → suggest something newly added
|
||||
- `bin/audiobooks current` → suggest picking up their audiobook
|
||||
- Make it specific: "You're 44% through Die zweite Legion" or "New movie added: The Rip (2026)"
|
||||
|
||||
**Work-end reminders**: When they indicate they're wrapping up or transitioning to wind-down, check `memory/brain-dump.json` for `recurring` items with `when: "evening"` and remind them (e.g., nose shower) before they get too deep into relaxation mode.
|
||||
**Work-end reminders**: When they indicate they're wrapping up or transitioning to wind-down, check `memory/tasks.json` for `recurring` items with `when: "evening"` and remind them (e.g., nose shower) before they get too deep into relaxation mode.
|
||||
|
||||
**📝 AUTO-LOG EVERYTHING 19:00→SLEEP** — Log to `memory/wind-down-log.json` as events happen:
|
||||
- What they're doing (working, watching TV, chatting, browsing, etc.)
|
||||
|
|
@ -44,10 +42,18 @@ Check the following and notify only once per event (track in `memory/heartbeat-s
|
|||
|
||||
5. **Steam Machine / Steam Frame**: Check for **official Valve news only** about pricing or release date. Notify once when official price or specific release date is announced. Baseline: "early 2026" window, no price yet.
|
||||
|
||||
6. **Brain dump nudging**: During daytime hours (10:00-18:00 Vienna), occasionally check `memory/brain-dump.json` for:
|
||||
- Items with `remindOn` date matching today
|
||||
- Items older than 2 days that haven't been addressed (weekdays only — Mon-Fri)
|
||||
On weekends: only surface items with `remindOn` = today.
|
||||
6. **OpenClaw + Claude Code updates**: Check once daily (daytime) for:
|
||||
- OpenClaw releases (especially for Opus 4.6 support via PR #9863)
|
||||
- Claude Code new versions
|
||||
Track in `memory/heartbeat-state.json` watchlist. Notify when new versions ship.
|
||||
|
||||
7. **Task nudging**: During daytime hours (10:00-18:00 Vienna), occasionally check `memory/tasks.json` for:
|
||||
- `now` priority tasks — nudge daily
|
||||
- `soon` priority tasks — nudge every 2-3 days (weekdays only)
|
||||
- `someday` tasks — only mention during weekly reviews or when contextually relevant
|
||||
On weekends: only nudge `now` priority items.
|
||||
Surface 1-2 items max, conversationally. NOT in evening — that's wind-down time.
|
||||
**Auto-capture:** When user mentions tasks naturally in chat ("I should...", "I need to...", "Don't forget..."), add to tasks.json and confirm with a short acknowledgment.
|
||||
**Done = delete.** Remove completed tasks immediately. History lives in daily memory logs.
|
||||
|
||||
If nothing new to report, reply HEARTBEAT_OK.
|
||||
|
|
|
|||
67
TOOLS.md
67
TOOLS.md
|
|
@ -67,6 +67,47 @@ derstandard raw [max] # Full RSS XML
|
|||
2. Pick interesting ones, optionally fetch full content with `articles`
|
||||
3. Next briefing: only shows articles published since last check
|
||||
|
||||
## Audiobookshelf
|
||||
|
||||
Helper script: `~/clawd/bin/audiobooks`
|
||||
|
||||
```bash
|
||||
audiobooks current # Currently listening / in-progress books
|
||||
audiobooks recent [limit] # Recently active books (default: 5)
|
||||
audiobooks finished [limit] # Finished books (default: 10)
|
||||
audiobooks stats # Listening stats overview
|
||||
audiobooks libraries # List libraries
|
||||
```
|
||||
|
||||
- Credentials: `.credentials/audiobookshelf.env`
|
||||
- URL: `https://audiobooks.cloonar.com`
|
||||
- Output is tab-separated for minimal tokens
|
||||
- Use during wind-down to suggest continuing audiobook
|
||||
|
||||
---
|
||||
|
||||
## Jellyfin
|
||||
|
||||
Helper script: `~/clawd/bin/jellyfin`
|
||||
|
||||
```bash
|
||||
jellyfin resume [limit] # Continue watching (in-progress items)
|
||||
jellyfin recent [limit] # Recently added to library
|
||||
jellyfin watched [limit] # Watch history (last played)
|
||||
jellyfin shows # All series with watch status
|
||||
jellyfin movies # All movies with watch status
|
||||
jellyfin search <query> # Search library
|
||||
jellyfin stats # Watch statistics overview
|
||||
jellyfin libraries # List libraries
|
||||
```
|
||||
|
||||
- Credentials: `.credentials/jellyfin.env` (user-scoped token for `tv`)
|
||||
- URL: `https://jellyfin.cloonar.com`
|
||||
- Output is tab-separated for minimal tokens
|
||||
- Use during wind-down to suggest specific shows/movies
|
||||
|
||||
---
|
||||
|
||||
## Forgejo Git Access
|
||||
|
||||
Helper script: `~/bin/forgejo`
|
||||
|
|
@ -137,28 +178,30 @@ ainews reset # Clear seen history
|
|||
|
||||
## Brain Dump CLI
|
||||
|
||||
Helper script: `~/clawd/bin/brain-dump`
|
||||
Helper script: `~/clawd/bin/tasks`
|
||||
|
||||
```bash
|
||||
brain-dump list [--priority now,soon] [--due] [--limit N]
|
||||
brain-dump add --text "..." --priority soon [--context "..."]
|
||||
brain-dump edit <id> [--text "..."] [--priority ...] [--context "..."]
|
||||
brain-dump done <id>
|
||||
brain-dump show <id>
|
||||
brain-dump nudged <id1>,<id2>,...
|
||||
brain-dump recurring [--when evening]
|
||||
tasks list [--priority now,soon] [--due] [--limit N]
|
||||
tasks add --text "..." --priority soon [--context "..."]
|
||||
tasks add --recurring --text "..." --frequency daily [--when evening] [--context "..."]
|
||||
tasks edit <id> [--text "..."] [--priority|--frequency|--when|--context "..."]
|
||||
tasks done <id>
|
||||
tasks show <id>
|
||||
tasks nudged <id1>,<id2>,...
|
||||
tasks recurring
|
||||
```
|
||||
|
||||
- Data: `memory/brain-dump.json`
|
||||
- Data: `memory/tasks.json`
|
||||
- `--due` filters by nudge interval: now=1d, soon=3d, someday=7d
|
||||
- `nudged` marks tasks as just-nudged (resets due timer)
|
||||
- `recurring` lists recurring reminders (nose shower etc.)
|
||||
- `recurring` lists all recurring items with full context (note, when, frequency)
|
||||
- `add --recurring` / `edit` / `done` work for both tasks and recurring items
|
||||
- Output is tab-separated for minimal tokens
|
||||
|
||||
**Heartbeat workflow:**
|
||||
1. `brain-dump list --due --limit 2` → get tasks needing a nudge
|
||||
1. `tasks list --due --limit 2` → get tasks needing a nudge
|
||||
2. Mention them conversationally
|
||||
3. `brain-dump nudged <id1>,<id2>` → mark as nudged
|
||||
3. `tasks nudged <id1>,<id2>` → mark as nudged
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
169
bin/audiobooks
Executable file
169
bin/audiobooks
Executable file
|
|
@ -0,0 +1,169 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
|
||||
const CRED_PATH = path.join(__dirname, '..', '.credentials', 'audiobookshelf.env');
|
||||
|
||||
function loadCreds() {
|
||||
const raw = fs.readFileSync(CRED_PATH, 'utf8');
|
||||
const env = {};
|
||||
for (const line of raw.split('\n')) {
|
||||
const m = line.match(/^(\w+)=(.+)$/);
|
||||
if (m) env[m[1]] = m[2];
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
function api(endpoint) {
|
||||
const { AUDIOBOOKSHELF_URL, AUDIOBOOKSHELF_TOKEN } = loadCreds();
|
||||
const url = `${AUDIOBOOKSHELF_URL}${endpoint}`;
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = https.get(url, { headers: { 'Authorization': `Bearer ${AUDIOBOOKSHELF_TOKEN}` } }, (res) => {
|
||||
let data = '';
|
||||
res.on('data', c => data += c);
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(data)); }
|
||||
catch { reject(new Error(`Invalid JSON from ${endpoint}`)); }
|
||||
});
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.setTimeout(10000, () => { req.destroy(); reject(new Error('Timeout')); });
|
||||
});
|
||||
}
|
||||
|
||||
function formatDuration(secs) {
|
||||
const h = Math.floor(secs / 3600);
|
||||
const m = Math.floor((secs % 3600) / 60);
|
||||
if (h > 0) return `${h}h ${m}m`;
|
||||
return `${m}m`;
|
||||
}
|
||||
|
||||
function formatProgress(progress) {
|
||||
return `${Math.round(progress * 100)}%`;
|
||||
}
|
||||
|
||||
async function cmdCurrent() {
|
||||
const data = await api('/api/me/items-in-progress');
|
||||
const items = data.libraryItems || [];
|
||||
if (items.length === 0) {
|
||||
console.log('Nothing in progress.');
|
||||
return;
|
||||
}
|
||||
for (const item of items) {
|
||||
const meta = item.media?.metadata || {};
|
||||
const title = meta.title || 'Unknown';
|
||||
const author = meta.authorName || 'Unknown';
|
||||
const narrator = meta.narratorName || '-';
|
||||
const series = meta.seriesName || '-';
|
||||
const duration = formatDuration(item.media?.duration || 0);
|
||||
|
||||
// Get progress from user's mediaProgress
|
||||
const me = await api('/api/me');
|
||||
const prog = (me.mediaProgress || []).find(p => p.libraryItemId === item.id);
|
||||
const progress = prog ? formatProgress(prog.progress) : '?';
|
||||
const currentTime = prog ? formatDuration(prog.currentTime) : '?';
|
||||
const remaining = prog ? formatDuration((item.media?.duration || 0) - (prog.currentTime || 0)) : '?';
|
||||
|
||||
console.log(`${title}\t${author}\t${series}\t${progress}\t${currentTime}/${duration}\tremaining:${remaining}\tnarrator:${narrator}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdLibraries() {
|
||||
const data = await api('/api/libraries');
|
||||
for (const lib of (data.libraries || [])) {
|
||||
console.log(`${lib.id}\t${lib.name}\t${lib.mediaType}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdRecent(args) {
|
||||
const limit = args[0] || '5';
|
||||
const me = await api('/api/me');
|
||||
const progress = (me.mediaProgress || [])
|
||||
.filter(p => !p.isFinished)
|
||||
.sort((a, b) => (b.lastUpdate || 0) - (a.lastUpdate || 0))
|
||||
.slice(0, parseInt(limit, 10));
|
||||
|
||||
if (progress.length === 0) {
|
||||
console.log('No recent listening activity.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (const p of progress) {
|
||||
try {
|
||||
const item = await api(`/api/items/${p.libraryItemId}?expanded=1`);
|
||||
const meta = item.media?.metadata || {};
|
||||
const title = meta.title || 'Unknown';
|
||||
const author = meta.authorName || 'Unknown';
|
||||
const series = meta.seriesName || '-';
|
||||
const pct = formatProgress(p.progress);
|
||||
const lastUpdate = new Date(p.lastUpdate).toISOString().slice(0, 10);
|
||||
console.log(`${title}\t${author}\t${series}\t${pct}\tlast:${lastUpdate}`);
|
||||
} catch {
|
||||
// Item might have been removed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdFinished(args) {
|
||||
const limit = args[0] || '10';
|
||||
const me = await api('/api/me');
|
||||
const finished = (me.mediaProgress || [])
|
||||
.filter(p => p.isFinished)
|
||||
.sort((a, b) => (b.finishedAt || 0) - (a.finishedAt || 0))
|
||||
.slice(0, parseInt(limit, 10));
|
||||
|
||||
if (finished.length === 0) {
|
||||
console.log('No finished books.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (const p of finished) {
|
||||
try {
|
||||
const item = await api(`/api/items/${p.libraryItemId}?expanded=1`);
|
||||
const meta = item.media?.metadata || {};
|
||||
const title = meta.title || 'Unknown';
|
||||
const author = meta.authorName || 'Unknown';
|
||||
const finishedDate = p.finishedAt ? new Date(p.finishedAt).toISOString().slice(0, 10) : '?';
|
||||
console.log(`${title}\t${author}\tfinished:${finishedDate}`);
|
||||
} catch {
|
||||
// Item might have been removed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdStats() {
|
||||
const me = await api('/api/me');
|
||||
const progress = me.mediaProgress || [];
|
||||
const inProgress = progress.filter(p => !p.isFinished && !p.hideFromContinueListening).length;
|
||||
const finished = progress.filter(p => p.isFinished).length;
|
||||
const totalListened = progress.reduce((sum, p) => sum + (p.currentTime || 0), 0);
|
||||
|
||||
console.log(`in-progress:${inProgress}\tfinished:${finished}\ttotal-listened:${formatDuration(totalListened)}`);
|
||||
}
|
||||
|
||||
// --- Main ---
|
||||
|
||||
const [cmd, ...args] = process.argv.slice(2);
|
||||
|
||||
const run = async () => {
|
||||
switch (cmd) {
|
||||
case 'current': await cmdCurrent(); break;
|
||||
case 'recent': await cmdRecent(args); break;
|
||||
case 'finished': await cmdFinished(args); break;
|
||||
case 'stats': await cmdStats(); break;
|
||||
case 'libraries': await cmdLibraries(); break;
|
||||
default:
|
||||
console.log(`Usage: audiobooks <command>
|
||||
|
||||
Commands:
|
||||
current Currently listening / in-progress books
|
||||
recent [limit] Recently active books (default: 5)
|
||||
finished [limit] Finished books (default: 10)
|
||||
stats Listening stats overview
|
||||
libraries List libraries`);
|
||||
}
|
||||
};
|
||||
|
||||
run().catch(err => { console.error(`Error: ${err.message}`); process.exit(1); });
|
||||
150
bin/jellyfin
Executable file
150
bin/jellyfin
Executable file
|
|
@ -0,0 +1,150 @@
|
|||
#!/usr/bin/env node
|
||||
// Jellyfin CLI — token-efficient output for assistant use
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Load credentials
|
||||
const envFile = fs.readFileSync(path.join(__dirname, '..', '.credentials', 'jellyfin.env'), 'utf8');
|
||||
const env = {};
|
||||
envFile.split('\n').forEach(l => { const [k, ...v] = l.split('='); if (k && v.length) env[k.trim()] = v.join('=').trim(); });
|
||||
|
||||
const BASE = env.JELLYFIN_URL;
|
||||
const API_KEY = env.JELLYFIN_API_KEY;
|
||||
const USER_ID = env.JELLYFIN_USER_ID;
|
||||
|
||||
function api(endpoint) {
|
||||
const sep = endpoint.includes('?') ? '&' : '?';
|
||||
const url = `${BASE}${endpoint}${sep}api_key=${API_KEY}`;
|
||||
return new Promise((resolve, reject) => {
|
||||
https.get(url, res => {
|
||||
let data = '';
|
||||
res.on('data', c => data += c);
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(data)); } catch { resolve(data); }
|
||||
});
|
||||
}).on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
function getUserId() { return USER_ID; }
|
||||
|
||||
function dur(ticks) {
|
||||
if (!ticks) return '';
|
||||
const min = Math.round(ticks / 600000000);
|
||||
if (min < 60) return `${min}m`;
|
||||
return `${Math.floor(min/60)}h${min%60 ? ' '+min%60+'m' : ''}`;
|
||||
}
|
||||
|
||||
function pct(userData, runTimeTicks) {
|
||||
if (!userData) return '';
|
||||
if (userData.Played) return '✓';
|
||||
if (userData.PlayedPercentage) return Math.round(userData.PlayedPercentage) + '%';
|
||||
if (userData.PlaybackPositionTicks && runTimeTicks) return Math.round(userData.PlaybackPositionTicks / runTimeTicks * 100) + '%';
|
||||
return '';
|
||||
}
|
||||
|
||||
const commands = {
|
||||
async resume(limit = 10) {
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items/Resume?Limit=${limit}&Fields=Overview,RunTimeTicks&MediaTypes=Video`);
|
||||
if (!r.Items.length) return console.log('Nothing in progress');
|
||||
console.log('TITLE\tEPISODE\tPROGRESS\tDURATION');
|
||||
r.Items.forEach(i => {
|
||||
const show = i.SeriesName || '';
|
||||
const name = show ? `${i.Name}` : i.Name;
|
||||
console.log([show || i.Name, show ? i.Name : '', pct(i.UserData, i.RunTimeTicks), dur(i.RunTimeTicks)].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async recent(limit = 10) {
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items/Latest?Limit=${limit}&Fields=RunTimeTicks`);
|
||||
if (!r.length) return console.log('No recent items');
|
||||
console.log('TYPE\tTITLE\tNAME\tYEAR\tDURATION');
|
||||
r.forEach(i => {
|
||||
console.log([i.Type === 'Episode' ? 'EP' : 'MOV', i.SeriesName || i.Name, i.SeriesName ? i.Name : '', i.ProductionYear || '', dur(i.RunTimeTicks)].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async watched(limit = 20) {
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items?Limit=${limit}&SortBy=DatePlayed&SortOrder=Descending&Filters=IsPlayed&Recursive=true&IncludeItemTypes=Movie,Episode&Fields=RunTimeTicks,DateLastMediaAdded`);
|
||||
if (!r.Items.length) return console.log('No watched items');
|
||||
console.log('TYPE\tTITLE\tEPISODE\tYEAR');
|
||||
r.Items.forEach(i => {
|
||||
console.log([i.Type === 'Episode' ? 'EP' : 'MOV', i.SeriesName || i.Name, i.SeriesName ? i.Name : '', i.ProductionYear || ''].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async shows() {
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items?IncludeItemTypes=Series&Recursive=true&SortBy=SortName&Fields=RunTimeTicks`);
|
||||
if (!r.Items.length) return console.log('No shows');
|
||||
console.log('TITLE\tYEAR\tSTATUS');
|
||||
r.Items.forEach(i => {
|
||||
console.log([i.Name, i.ProductionYear || '', pct(i.UserData, i.RunTimeTicks) || 'unwatched'].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async movies() {
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items?IncludeItemTypes=Movie&Recursive=true&SortBy=SortName&Fields=RunTimeTicks`);
|
||||
if (!r.Items.length) return console.log('No movies');
|
||||
console.log('TITLE\tYEAR\tDURATION\tSTATUS');
|
||||
r.Items.forEach(i => {
|
||||
console.log([i.Name, i.ProductionYear || '', dur(i.RunTimeTicks), pct(i.UserData, i.RunTimeTicks) || '-'].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async search(query) {
|
||||
if (!query) { console.error('Usage: jellyfin search <query>'); process.exit(1); }
|
||||
const uid = await getUserId();
|
||||
const r = await api(`/Users/${uid}/Items?SearchTerm=${encodeURIComponent(query)}&Recursive=true&IncludeItemTypes=Movie,Series,Episode&Limit=10&Fields=RunTimeTicks`);
|
||||
if (!r.Items.length) return console.log('No results');
|
||||
console.log('TYPE\tTITLE\tNAME\tYEAR');
|
||||
r.Items.forEach(i => {
|
||||
console.log([i.Type, i.SeriesName || i.Name, i.SeriesName ? i.Name : '', i.ProductionYear || ''].join('\t'));
|
||||
});
|
||||
},
|
||||
|
||||
async stats() {
|
||||
const uid = await getUserId();
|
||||
const [movies, shows, episodes] = await Promise.all([
|
||||
api(`/Users/${uid}/Items?IncludeItemTypes=Movie&Recursive=true&Filters=IsPlayed`),
|
||||
api(`/Users/${uid}/Items?IncludeItemTypes=Series&Recursive=true`),
|
||||
api(`/Users/${uid}/Items?IncludeItemTypes=Episode&Recursive=true&Filters=IsPlayed`),
|
||||
]);
|
||||
console.log(`Movies watched:\t${movies.TotalRecordCount}`);
|
||||
console.log(`Shows in library:\t${shows.TotalRecordCount}`);
|
||||
console.log(`Episodes watched:\t${episodes.TotalRecordCount}`);
|
||||
},
|
||||
|
||||
async libraries() {
|
||||
const uid = getUserId();
|
||||
const r = await api(`/Users/${uid}/Views`);
|
||||
console.log('NAME\tTYPE\tID');
|
||||
(r.Items || []).forEach(l => {
|
||||
console.log([l.Name, l.CollectionType || 'mixed', l.Id].join('\t'));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const cmd = process.argv[2];
|
||||
const args = process.argv.slice(3);
|
||||
|
||||
if (!cmd || !commands[cmd]) {
|
||||
console.log('Usage: jellyfin <command> [args]\n');
|
||||
console.log('Commands:');
|
||||
console.log(' resume [limit] Continue watching');
|
||||
console.log(' recent [limit] Recently added');
|
||||
console.log(' watched [limit] Watch history');
|
||||
console.log(' shows All series');
|
||||
console.log(' movies All movies');
|
||||
console.log(' search <query> Search library');
|
||||
console.log(' stats Watch statistics');
|
||||
console.log(' libraries List libraries');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
commands[cmd](...args).catch(e => { console.error(e.message); process.exit(1); });
|
||||
|
|
@ -4,7 +4,7 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const DUMP_PATH = path.join(__dirname, '..', 'memory', 'brain-dump.json');
|
||||
const DUMP_PATH = path.join(__dirname, '..', 'memory', 'tasks.json');
|
||||
|
||||
const NUDGE_INTERVALS = {
|
||||
now: 24 * 60 * 60 * 1000, // 1 day
|
||||
|
|
@ -41,29 +41,31 @@ function formatTask(t) {
|
|||
return line;
|
||||
}
|
||||
|
||||
function formatRecurring(r) {
|
||||
let line = `${r.id}\t${r.frequency}\t${r.when || '-'}\t${r.text}`;
|
||||
if (r.context) line += `\t${r.context}`;
|
||||
return line;
|
||||
}
|
||||
|
||||
// --- Commands ---
|
||||
|
||||
function cmdList(args) {
|
||||
const data = load();
|
||||
let tasks = data.tasks || [];
|
||||
|
||||
// Filter by priority
|
||||
const prioArg = getFlag(args, '--priority');
|
||||
if (prioArg) {
|
||||
const prios = prioArg.split(',').map(s => s.trim());
|
||||
tasks = tasks.filter(t => prios.includes(t.priority));
|
||||
}
|
||||
|
||||
// Filter by due
|
||||
if (args.includes('--due')) {
|
||||
tasks = tasks.filter(isDue);
|
||||
}
|
||||
|
||||
// Sort: now > soon > someday
|
||||
const prioOrder = { now: 0, soon: 1, someday: 2 };
|
||||
tasks.sort((a, b) => (prioOrder[a.priority] ?? 3) - (prioOrder[b.priority] ?? 3));
|
||||
|
||||
// Limit
|
||||
const limitArg = getFlag(args, '--limit');
|
||||
if (limitArg) {
|
||||
tasks = tasks.slice(0, parseInt(limitArg, 10));
|
||||
|
|
@ -80,72 +82,112 @@ function cmdList(args) {
|
|||
}
|
||||
|
||||
function cmdAdd(args) {
|
||||
const isRecurring = args.includes('--recurring');
|
||||
const text = getFlag(args, '--text');
|
||||
if (!text) { console.error('--text required'); process.exit(1); }
|
||||
const priority = getFlag(args, '--priority') || 'soon';
|
||||
const context = getFlag(args, '--context') || undefined;
|
||||
|
||||
const data = load();
|
||||
const task = {
|
||||
id: shortId(),
|
||||
added: new Date().toISOString().slice(0, 10),
|
||||
text,
|
||||
priority,
|
||||
};
|
||||
if (context) task.context = context;
|
||||
data.tasks = data.tasks || [];
|
||||
data.tasks.push(task);
|
||||
save(data);
|
||||
console.log(`Added: ${task.id}\t${priority}\t${text}`);
|
||||
|
||||
if (isRecurring) {
|
||||
const frequency = getFlag(args, '--frequency') || 'daily';
|
||||
const when = getFlag(args, '--when') || undefined;
|
||||
const item = { id: shortId(), text, frequency };
|
||||
if (when) item.when = when;
|
||||
if (context) item.context = context;
|
||||
data.recurring = data.recurring || [];
|
||||
data.recurring.push(item);
|
||||
save(data);
|
||||
console.log(`Added recurring: ${formatRecurring(item)}`);
|
||||
} else {
|
||||
const priority = getFlag(args, '--priority') || 'soon';
|
||||
const task = { id: shortId(), added: new Date().toISOString().slice(0, 10), text, priority };
|
||||
if (context) task.context = context;
|
||||
data.tasks = data.tasks || [];
|
||||
data.tasks.push(task);
|
||||
save(data);
|
||||
console.log(`Added: ${task.id}\t${priority}\t${text}`);
|
||||
}
|
||||
}
|
||||
|
||||
function cmdEdit(args) {
|
||||
const id = args[0];
|
||||
if (!id) { console.error('Usage: brain-dump edit <id> [--text ...] [--priority ...] [--context ...]'); process.exit(1); }
|
||||
if (!id) { console.error('Usage: tasks edit <id> [--text ...] [--priority ...] [--context ...] [--frequency ...] [--when ...]'); process.exit(1); }
|
||||
|
||||
const data = load();
|
||||
const task = (data.tasks || []).find(t => t.id === id);
|
||||
if (!task) { console.error(`Task ${id} not found.`); process.exit(1); }
|
||||
|
||||
// Check tasks first, then recurring
|
||||
let item = (data.tasks || []).find(t => t.id === id);
|
||||
let isRecurring = false;
|
||||
if (!item) {
|
||||
item = (data.recurring || []).find(r => r.id === id);
|
||||
isRecurring = true;
|
||||
}
|
||||
if (!item) { console.error(`Item ${id} not found.`); process.exit(1); }
|
||||
|
||||
const text = getFlag(args, '--text');
|
||||
const priority = getFlag(args, '--priority');
|
||||
const context = getFlag(args, '--context');
|
||||
if (text) item.text = text;
|
||||
if (context !== null && context !== undefined) item.context = context;
|
||||
|
||||
if (text) task.text = text;
|
||||
if (priority) task.priority = priority;
|
||||
if (context !== null && context !== undefined) task.context = context;
|
||||
|
||||
save(data);
|
||||
console.log(`Updated: ${formatTask(task)}`);
|
||||
if (isRecurring) {
|
||||
const frequency = getFlag(args, '--frequency');
|
||||
const when = getFlag(args, '--when');
|
||||
if (frequency) item.frequency = frequency;
|
||||
if (when) item.when = when;
|
||||
save(data);
|
||||
console.log(`Updated recurring: ${formatRecurring(item)}`);
|
||||
} else {
|
||||
const priority = getFlag(args, '--priority');
|
||||
if (priority) item.priority = priority;
|
||||
save(data);
|
||||
console.log(`Updated: ${formatTask(item)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function cmdDone(args) {
|
||||
const id = args[0];
|
||||
if (!id) { console.error('Usage: brain-dump done <id>'); process.exit(1); }
|
||||
if (!id) { console.error('Usage: tasks done <id>'); process.exit(1); }
|
||||
|
||||
const data = load();
|
||||
const idx = (data.tasks || []).findIndex(t => t.id === id);
|
||||
if (idx === -1) { console.error(`Task ${id} not found.`); process.exit(1); }
|
||||
|
||||
const removed = data.tasks.splice(idx, 1)[0];
|
||||
save(data);
|
||||
console.log(`Done: ${removed.text}`);
|
||||
// Check tasks
|
||||
let idx = (data.tasks || []).findIndex(t => t.id === id);
|
||||
if (idx !== -1) {
|
||||
const removed = data.tasks.splice(idx, 1)[0];
|
||||
save(data);
|
||||
console.log(`Done: ${removed.text}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check recurring
|
||||
idx = (data.recurring || []).findIndex(r => r.id === id);
|
||||
if (idx !== -1) {
|
||||
const removed = data.recurring.splice(idx, 1)[0];
|
||||
save(data);
|
||||
console.log(`Removed recurring: ${removed.text}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(`Item ${id} not found.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function cmdShow(args) {
|
||||
const id = args[0];
|
||||
if (!id) { console.error('Usage: brain-dump show <id>'); process.exit(1); }
|
||||
if (!id) { console.error('Usage: tasks show <id>'); process.exit(1); }
|
||||
|
||||
const data = load();
|
||||
const task = (data.tasks || []).find(t => t.id === id);
|
||||
if (!task) { console.error(`Task ${id} not found.`); process.exit(1); }
|
||||
const item = (data.tasks || []).find(t => t.id === id)
|
||||
|| (data.recurring || []).find(r => r.id === id);
|
||||
if (!item) { console.error(`Item ${id} not found.`); process.exit(1); }
|
||||
|
||||
console.log(JSON.stringify(task, null, 2));
|
||||
console.log(JSON.stringify(item, null, 2));
|
||||
}
|
||||
|
||||
function cmdNudged(args) {
|
||||
const ids = (args[0] || '').split(',').map(s => s.trim()).filter(Boolean);
|
||||
if (ids.length === 0) { console.error('Usage: brain-dump nudged <id1>,<id2>,...'); process.exit(1); }
|
||||
if (ids.length === 0) { console.error('Usage: tasks nudged <id1>,<id2>,...'); process.exit(1); }
|
||||
|
||||
const data = load();
|
||||
const now = new Date().toISOString();
|
||||
|
|
@ -161,19 +203,15 @@ function cmdNudged(args) {
|
|||
console.log(`Marked ${count} task(s) as nudged.`);
|
||||
}
|
||||
|
||||
function cmdRecurring(args) {
|
||||
function cmdRecurring() {
|
||||
const data = load();
|
||||
const when = getFlag(args, '--when');
|
||||
let items = data.recurring || [];
|
||||
if (when) {
|
||||
items = items.filter(r => r.when === when);
|
||||
}
|
||||
const items = data.recurring || [];
|
||||
if (items.length === 0) {
|
||||
console.log('No recurring items.');
|
||||
return;
|
||||
}
|
||||
for (const r of items) {
|
||||
console.log(`${r.id}\t${r.frequency}\t${r.when || '-'}\t${r.text}`);
|
||||
console.log(formatRecurring(r));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,16 +234,17 @@ switch (cmd) {
|
|||
case 'done': cmdDone(args); break;
|
||||
case 'show': cmdShow(args); break;
|
||||
case 'nudged': cmdNudged(args); break;
|
||||
case 'recurring': cmdRecurring(args); break;
|
||||
case 'recurring': cmdRecurring(); break;
|
||||
default:
|
||||
console.log(`Usage: brain-dump <command>
|
||||
console.log(`Usage: tasks <command>
|
||||
|
||||
Commands:
|
||||
list [--priority now,soon] [--due] [--limit N]
|
||||
add --text "..." --priority soon [--context "..."]
|
||||
edit <id> [--text "..."] [--priority ...] [--context "..."]
|
||||
add --recurring --text "..." --frequency daily [--when evening] [--context "..."]
|
||||
edit <id> [--text "..."] [--priority|--frequency|--when|--context "..."]
|
||||
done <id>
|
||||
show <id>
|
||||
nudged <id1>,<id2>,...
|
||||
recurring [--when evening]`);
|
||||
recurring`);
|
||||
}
|
||||
23
memory/2026-02-06.md
Normal file
23
memory/2026-02-06.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# 2026-02-06 (Friday)
|
||||
|
||||
## Key Events
|
||||
- **Opus 4.6 upgrade**: User pointed out OpenClaw update included Opus 4.6 support. Config was still on 4.5 — patched config to set Opus 4.6 as primary with 4.5 fallback. Updated TOOLS.md.
|
||||
- **Cron jobs fixed**: News cron jobs were broken all day — root cause was `wakeMode: "next-heartbeat"` causing jobs to be skipped when heartbeat timing didn't align. Fixed by switching all 8 news jobs to `wakeMode: "now"`. Tested successfully at 21:35 and 21:39 UTC.
|
||||
- **Cron delivery note**: What appears truncated in system logs is actually the full message on WhatsApp — I only see a summary of cron agent output.
|
||||
- **Task system revamp**: Restructured brain-dump.json — removed status field (done = delete), added priority system (now/soon/someday), updated HEARTBEAT.md with auto-capture and smarter nudging rules.
|
||||
- **AirPods listed on Willhaben**: Helped write title/description for AirPods Pro 2 USB-C listing. Task completed and removed from brain-dump.
|
||||
- **Bazzite 42→43 upgrade**: Helped user rebase GPD Win 4 from Bazzite 42 to 43. Used `ostree-unverified-registry` to bypass stuck ref. Upgrade successful.
|
||||
- **FSR4 setup**: Guided user through FSR4 emulated RDNA3 on GPD Win 4 HX 370. ProtonPlus → Proton GE → `DXIL_SPIRV_CONFIG=wmma_rdna3_workaround FSR4_UPGRADE=1`. Set up global env vars.
|
||||
- **GPD Win 4 notes**: HX 370 processor, BIOS 0.10 (latest for this model), 1080p display. 15W TDP = ~28W total system draw (normal). Clair Obscur needs ~20W TDP for 30fps at 1080p FSR performance.
|
||||
- **SVS + Watzek Petschinka reminders**: Set for Monday 9 AM Vienna.
|
||||
- **Codex CLI**: Explained plan mode (Shift+Tab to cycle modes: Ask/Plan/Auto).
|
||||
|
||||
## Wind-down
|
||||
- 19:00-22:00 window: Failed to check in at 19:00 — user called me out. Must proactively reach out when wind-down window starts.
|
||||
- User worked until ~23:00 on Friday (hook issue → NixOS config → cron testing). Classic scope creep pattern.
|
||||
- Nose shower done at 23:01.
|
||||
|
||||
## Lessons
|
||||
- **Always check in at 19:00 Vienna** when wind-down window starts, even if user seems quiet.
|
||||
- **Cron jobs**: Use `wakeMode: "now"` for isolated jobs that need precise timing. `next-heartbeat` is unreliable for scheduled tasks.
|
||||
- **Cron delivery**: I only see summaries of cron agent output, not the full message. Don't assume truncation on WhatsApp.
|
||||
71
memory/2026-02-07.md
Normal file
71
memory/2026-02-07.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# 2026-02-07 (Saturday)
|
||||
|
||||
## Cron Bug Fix 🐛
|
||||
- **Root cause**: `recomputeNextRuns()` in `/app/src/cron/service/store.ts` (line ~409 in ensureLoaded) recomputes `nextRunAtMs` for ALL jobs before `runDueJobs()` runs. For recurring schedules (cron/every), `computeNextRunAtMs()` always returns the NEXT occurrence after `now`, advancing the schedule past the current time. `runDueJobs()` then finds no due jobs.
|
||||
- One-shot `at` jobs were unaffected because `computeJobNextRunAtMs` returns the original timestamp for them.
|
||||
- **Fix**: Patched `/app/dist/gateway-cli-D6nsc3s0.js` — in `recomputeNextRuns`, added check to skip recomputing if `nextRunAtMs <= now` (job is due, let it execute first).
|
||||
- **Impact**: All 8 news cron jobs (Der Standard + AI News × 4 times/day) had NEVER fired since creation on Feb 6.
|
||||
- Hard-killed gateway (PID 2) to force container restart and load patched JS bundle.
|
||||
- Verified: recurring `every` job fired correctly after patch. Real news jobs scheduled for 14:00 Vienna.
|
||||
- **TODO**: File upstream bug report on OpenClaw GitHub (issue in `recomputeNextRuns` race condition).
|
||||
|
||||
## GPD Win 4 Optimization
|
||||
- User working on improving performance/watt on GPD Win 4 2025 (HX 370, Bazzite 43, FSR 4 enabled)
|
||||
- Discussed: TDP tuning (15-20W sweet spot), core parking via PowerTools Decky plugin, resolution/FSR upscaling, fan curves, frame limiting
|
||||
- Core parking: disable SMT, reduce threads to 4 for GPU-bound games
|
||||
- BIOS: UMA frame buffer option not available on HX 370 model (others report same)
|
||||
- Recommended removing ReShade since FSR 4 handles upscaling
|
||||
- ProtonGE: update every 2-4 weeks or when a game has issues
|
||||
|
||||
## Android → Snapcast Streaming (Reference)
|
||||
- No native AirPlay-like solution for Android → Snapcast
|
||||
- **Best option:** DLNA/UPnP — gmrender-resurrect piped into Snapcast server + BubbleUPnP app on phone
|
||||
- **Alternatives:** Bluetooth A2DP sink (range limited), TCP source (no good Android app yet), AirPlay via Android app (hacky)
|
||||
- User interested but not urgent — revisit when asked
|
||||
|
||||
## Cron Bug — Already Fixed Upstream
|
||||
- Bug fixed in OpenClaw **2026.2.6** (we're on 2026.2.4)
|
||||
- Changelog: "prevent recomputeNextRuns from skipping due jobs when timer fires late by reordering onTimer flow"
|
||||
- PR #10776 by @tyler6204
|
||||
- User wants to update OpenClaw (asked, not done yet)
|
||||
|
||||
## Cron Jobs Consolidated
|
||||
- 8 news jobs → 2 jobs using multi-time cron expressions: `0 10,14,18,22 * * *`
|
||||
- Der Standard: job ID `917a96d5-14e7-4057-96e5-d83f2729ed9b`
|
||||
- AI News: job ID `a8991f6b-a31a-4997-bc92-b286573241d4`
|
||||
- Both confirmed working after fix (14:00 Vienna delivery successful)
|
||||
|
||||
## Tasks CLI (`bin/tasks`)
|
||||
- Renamed from `brain-dump` to `tasks`
|
||||
- Data file: `memory/tasks.json` (was `memory/brain-dump.json`)
|
||||
- Commands: list, add, edit, done, show, nudged, recurring
|
||||
- Supports both regular tasks and recurring items
|
||||
- `--due` flag with nudge intervals: now=1d, soon=3d, someday=7d
|
||||
- Merged `--note` and `--context` into single `--context` field
|
||||
- Design decision: tasks tool is for actionable items ONLY, not knowledge storage. Reference info goes in memory files where `memory_search` finds it.
|
||||
|
||||
## Audiobookshelf Integration
|
||||
- Built `bin/audiobooks` CLI tool
|
||||
- URL: https://audiobooks.cloonar.com
|
||||
- Credentials stored in `.credentials/audiobookshelf.env`
|
||||
- Commands: current, recent, finished, stats, libraries
|
||||
- Currently listening: "Die zweite Legion" (Askir Band 2) by Richard Schwartz — 44% done, 8h 46m remaining
|
||||
- Purpose: wind-down suggestions ("pick up your audiobook")
|
||||
|
||||
## Infuse + Jellyfin
|
||||
- User uses Infuse app on Apple TV with Jellyfin server
|
||||
- Asked about syncing watch state from Infuse → Jellyfin
|
||||
- Infuse has native Jellyfin integration that auto-syncs watch state
|
||||
- InfuseSync plugin also available (github.com/firecore/InfuseSync)
|
||||
- Need to confirm: is user using Jellyfin connection or direct file share?
|
||||
- Task added: `47eaa129` — look into Jellyfin playing stats with Intune app on iOS
|
||||
|
||||
## Improvement Ideas Discussed
|
||||
- Better wind-down: concrete suggestions using audiobook/TV data instead of vague nagging
|
||||
- Proactive calendar prep: weather, travel time, context from previous visits
|
||||
- Email triage: decided not worth it (user still uses mail client)
|
||||
- Workout: not needed (has working app already)
|
||||
- Decided: keep wind-down in main session (not separate agent) for better context
|
||||
|
||||
## Calendar
|
||||
- Marie besuchen 13:00-17:00 (reminder sent at 11:30 Vienna)
|
||||
|
|
@ -1,15 +1,83 @@
|
|||
https://simonwillison.net/2026/Feb/6/an-update-on-heroku/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/6/karel-doosterlinck/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/5/ai-adoption-journey/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/5/two-new-models/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/5/the-world-factbook/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/4/voxtral-2/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/4/distributing-go-binaries/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/3/introducing-deno-sandbox/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/3/january/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/3/brandon-sanderson/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/2/introducing-the-codex-app/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/2/no-humans-allowed/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/1/openclaw-in-docker/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/31/andrej-karpathy/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/31/collective-efficacy/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/30/steve-yegge/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/30/moltbook/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/30/a-programming-tool-for-the-arts/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/29/datasette-10a24/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/28/dynamic-features-static-site/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/28/the-five-levels/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/27/one-human-one-agent-one-browser/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/27/kimi-k25/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/26/tests/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/26/chatgpt-containers/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/25/the-browser-is-the-sandbox/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/25/kakapo-cam/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/24/dont-trust-the-process/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/24/jasmine-sun/#atom-everything
|
||||
https://simonwillison.net/2026/Jan/23/fastrender/#atom-everything
|
||||
https://openai.com/policies/kr-privacy-policy
|
||||
https://openai.com/index/our-approach-to-localization
|
||||
https://openai.com/index/gpt-5-lowers-protein-synthesis-cost
|
||||
https://openai.com/index/trusted-access-for-cyber
|
||||
https://openai.com/index/introducing-openai-frontier
|
||||
https://openai.com/index/navigating-health-questions
|
||||
https://openai.com/index/introducing-gpt-5-3-codex
|
||||
https://openai.com/index/gpt-5-3-codex-system-card
|
||||
https://openai.com/index/unlocking-the-codex-harness
|
||||
https://openai.com/index/vfl-wolfsburg
|
||||
https://openai.com/index/sora-feed-philosophy
|
||||
https://openai.com/index/snowflake-partnership
|
||||
https://openai.com/index/introducing-the-codex-app
|
||||
https://openai.com/index/inside-our-in-house-data-agent
|
||||
https://openai.com/index/retiring-gpt-4o-and-older-models
|
||||
https://openai.com/index/taisei
|
||||
https://openai.com/index/emea-youth-and-wellbeing-grant
|
||||
https://openai.com/index/the-next-chapter-for-ai-in-the-eu
|
||||
https://openai.com/index/ai-agent-link-safety
|
||||
https://openai.com/index/pvh-future-of-fashion
|
||||
https://openai.com/index/trustbank
|
||||
https://openai.com/index/introducing-prism
|
||||
https://openai.com/index/indeed-maggie-hulce
|
||||
https://openai.com/index/unrolling-the-codex-agent-loop
|
||||
https://openai.com/index/scaling-postgresql
|
||||
https://openai.com/index/praktika
|
||||
https://openai.com/business/guides-and-resources/chatgpt-usage-and-adoption-patterns-at-work
|
||||
https://openai.com/index/higgsfield
|
||||
https://openai.com/index/edu-for-countries
|
||||
https://openai.com/index/how-countries-can-end-the-capability-overhang
|
||||
https://magazine.sebastianraschka.com/p/categories-of-inference-time-scaling
|
||||
https://magazine.sebastianraschka.com/p/state-of-llms-2025
|
||||
https://magazine.sebastianraschka.com/p/llm-research-papers-2025-part2
|
||||
https://magazine.sebastianraschka.com/p/technical-deepseek
|
||||
https://magazine.sebastianraschka.com/p/beyond-standard-llms
|
||||
https://magazine.sebastianraschka.com/p/llm-evaluation-4-approaches
|
||||
https://magazine.sebastianraschka.com/p/qwen3-from-scratch
|
||||
https://magazine.sebastianraschka.com/p/from-gpt-2-to-gpt-oss-analyzing-the
|
||||
https://magazine.sebastianraschka.com/p/the-big-llm-architecture-comparison
|
||||
https://magazine.sebastianraschka.com/p/llm-research-papers-2025-list-one
|
||||
https://magazine.sebastianraschka.com/p/coding-the-kv-cache-in-llms
|
||||
https://magazine.sebastianraschka.com/p/coding-llms-from-the-ground-up
|
||||
https://magazine.sebastianraschka.com/p/the-state-of-llm-reasoning-model-training
|
||||
https://magazine.sebastianraschka.com/p/first-look-at-reasoning-from-scratch
|
||||
https://magazine.sebastianraschka.com/p/state-of-llm-reasoning-and-inference-scaling
|
||||
https://magazine.sebastianraschka.com/p/understanding-reasoning-llms
|
||||
https://magazine.sebastianraschka.com/p/ai-research-papers-2024-part-2
|
||||
https://magazine.sebastianraschka.com/p/ai-research-papers-2024-part-1
|
||||
https://magazine.sebastianraschka.com/p/llm-research-papers-the-2024-list
|
||||
https://magazine.sebastianraschka.com/p/understanding-multimodal-llms
|
||||
https://simonwillison.net/2026/Feb/6/tom-dale/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/6/pydantic-monty/#atom-everything
|
||||
https://simonwillison.net/2026/Feb/7/software-factory/#atom-everything
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
{
|
||||
"sent": []
|
||||
"sent": [
|
||||
{"event": "Marie besuchen", "date": "2026-02-07", "remindedAt": "2026-02-07T09:31:00Z"}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +1,87 @@
|
|||
https://www.derstandard.at/story/3000000306979/trump-always-chickens-out-macht-taco-tatsaechlich-immer-einen-rueckzieher?ref=rss
|
||||
https://www.derstandard.at/story/3000000307063/usa-schiessen-iranische-drohne-nahe-flugzeugtraeger-im-arabischen-meer-ab?ref=rss
|
||||
https://www.derstandard.at/story/3000000306672/neue-epstein-files-werfen-fragen-an-adelige-diplomaten-und-eva-dichand-auf?ref=rss
|
||||
https://www.derstandard.at/story/3000000306965/wodurch-fast-vier-von-zehn-krebsfaellen-vermeidbar-waeren?ref=rss
|
||||
https://www.derstandard.at/story/3000000306903/etappensieg-fuer-saudischen-staatsfonds-mubadala-im-streit-mit-signa?ref=rss
|
||||
https://www.derstandard.at/story/3000000307018/das-gehalt-ueberzeugt-beschaeftigte-nicht-dafuer-die-kollegen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307007/waymo-will-robotaxis-global-anbieten-und-sammelt-dafuer-neue-milliarden-ein?ref=rss
|
||||
https://www.derstandard.at/story/3000000307041/babys-erkennen-objekte-schon-im-alter-von-zwei-monaten?ref=rss
|
||||
https://www.derstandard.at/story/3000000306987/welche-bedrohung-durch-russland-ist-realistisch?ref=rss
|
||||
https://www.derstandard.at/story/3000000306974/minister-wiederkehr-warum-weniger-latein-im-gymnasium-mehr-humanismus-bedeutet?ref=rss
|
||||
https://www.derstandard.at/story/3000000306758/olympia-2026-zerstueckelte-winterspiele-sind-die-letzte-chance?ref=rss
|
||||
https://www.derstandard.at/story/3000000303908/warum-online-bewerbungsgespraeche-so-schwierig-sind-und-wie-man-dennoch-punktet?ref=rss
|
||||
https://www.derstandard.at/story/3000000306921/psychiaterin-kastner-ueber-kindstoetung-das-groesste-risiko-ist-eine-unbehandelte-depression?ref=rss
|
||||
https://www.derstandard.at/story/3000000307052/trotz-kreuzbandrisses-vonn-haelt-an-olympia-start-fest?ref=rss
|
||||
https://www.derstandard.at/story/3000000306703/vermoegen-sinnvoll-anlegen-eigentum-miete-oder-alternative-geldanlage?ref=rss
|
||||
https://www.derstandard.at/story/3000000306735/krankenstand-wegen-skiunfalls-wann-darf-der-arbeitgeber-das-gehalt-verweigern?ref=rss
|
||||
https://www.derstandard.at/story/3000000306990/maja-t-droht-in-budapester-antifa-prozess-ein-hartes-urteil?ref=rss
|
||||
https://www.derstandard.at/story/3000000306855/kunstsammler-leon-black-war-jeffrey-epsteins-haupteinnahmequelle?ref=rss
|
||||
https://www.derstandard.at/story/3000000306890/epstein-aff228re-ehepaar-clinton-zu-aussage-vor-dem-kongress-bereit?ref=rss
|
||||
https://www.derstandard.at/story/3000000306960/konflikt-bei-den-salzburger-festspielen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307071/burgenlands-ex-landeshauptmann-niessl-will-f252r-hofburg-kandidieren?ref=rss
|
||||
https://www.derstandard.at/story/3000000307072/gaddafi-sohn-seif-al-islam-gestorben?ref=rss
|
||||
https://www.derstandard.at/story/3000000306899/prozess-wegen-sexuellen-missbrauchs-gegen-ex-politiker-stronach-beginnt-in-kanada?ref=rss
|
||||
https://www.derstandard.at/story/3000000307067/anklage-will-wahlausschluss-f252r-le-pen-aber-nicht-sofort?ref=rss
|
||||
https://www.derstandard.at/story/3000000307066/auf-kuba-hat-es-null-grad?ref=rss
|
||||
https://www.derstandard.at/story/3000000307006/trump-fordert-von-elite-uni-harvard-eine-milliarde-dollar-schadenersatz?ref=rss
|
||||
https://www.derstandard.at/story/3000000306975/beschuss-bei-17-grad-menschen-suchen-schutz-in-kyjiws-u-bahn-stationen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306996/tod-eines-haeftlings-expertenkommission-soll-strafvollzug-verbessern?ref=rss
|
||||
https://www.derstandard.at/story/3000000306831/skelettierte-frauenleiche-in-wien-favoriten-entdeckt?ref=rss
|
||||
https://www.derstandard.at/story/3000000306971/von-grammys-bis-kennedy-center-der-maga-kulturkampf-folgt-einer-strategie?ref=rss
|
||||
https://www.derstandard.at/story/3000000306968/nicht-die-ki-ist-ausser-kontrolle-sondern-der-mensch?ref=rss
|
||||
https://www.derstandard.at/story/3000000306772/latein-kuerzen-lieber-eine-bildungsreform-die-wir-brauchen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306775/weniger-latein-humanistische-bildung-ist-kein-ballast?ref=rss
|
||||
https://www.derstandard.at/story/3000000305513/wunderheilung-im-winter?ref=rss
|
||||
https://www.derstandard.at/story/3000000306811/machtkampf-in-china-mit-unberechenbaren-folgen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306670/eine-regierung-die-gestalten-will-sollte-mehr-ideen-haben-als-eine-volksbefragung?ref=rss
|
||||
https://www.derstandard.at/story/3000000306839/sex-geld-macht-was-war-das-geheimnis-des-jeffrey-epstein?ref=rss
|
||||
https://www.derstandard.at/story/3000000306835/stocker-europa-wird-aus-vielen-richtungen-bedroht?ref=rss
|
||||
https://www.derstandard.at/story/3000000307558/kritik-an-rassistischem-trump-post-ueber-barack-und-michelle-obama?ref=rss
|
||||
https://www.derstandard.at/story/3000000307468/der-bitcoin-crasht-die-szene-laechelt-muede?ref=rss
|
||||
https://www.derstandard.at/story/3000000307239/batterie-ohne-lithium-warum-china-jetzt-auf-druckluftspeicher-setzt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307485/so-gross-wie-ein-schulbus-phantomqualle-in-atlantik-gefilmt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307236/jetzt-weiss-jeder-wo-nuuk-ist-wie-sich-trump-auf-den-groenland-tourismus-auswirkt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307471/die-babler-demontage-ist-verrueckt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307488/die-epstein-files-sind-eine-gewollte-ueberforderung-der-gesellschaft?ref=rss
|
||||
https://www.derstandard.at/story/3000000307363/latein-und-ein-aufstand-der-eliten?ref=rss
|
||||
https://www.derstandard.at/story/3000000306982/darin-gleicht-donald-trump-fast-allen-diktatoren?ref=rss
|
||||
https://www.derstandard.at/story/3000000307480/nervoes-sam-altman-zuckt-wegen-spott-von-anthropic-aus?ref=rss
|
||||
https://www.derstandard.at/story/3000000307472/der-herr-der-kameras-orf-regisseur-koegler-inszeniert-die-olympia-abfahrt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307321/quiz-zehn-fragen-um-die-welt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307578/polens-parlamentspraesident-gegen-nobelpreis-fuer-trump-us-botschafter-empoert?ref=rss
|
||||
https://www.derstandard.at/story/3000000307466/die-eu-kommission-testet-alternativen-zu-microsoft-teams?ref=rss
|
||||
https://www.derstandard.at/story/3000000300279/oesterreichs-fussball-bundesliga-ist-so-schlecht-wie-seit-jahrzehnten-nicht?ref=rss
|
||||
https://www.derstandard.at/story/3000000305885/als-ai-weiwei-seinen-mittelfinger-dem-tiananmen-platz-entgegenstreckte?ref=rss
|
||||
https://www.derstandard.at/story/3000000307479/baeume-in-den-dolomiten-haben-wohl-doch-keine-sonnenfinsternis-vorhergesehen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306805/der-standard-preismonitor-diese-produkte-wurden-am-teuersten?ref=rss
|
||||
https://www.derstandard.at/story/3000000307527/attentat-in-moskau-auf-stellvertretenden-leiter-des-militaergeheimdienstes?ref=rss
|
||||
https://www.derstandard.at/story/3000000307544/abfahrt-mit-kreuzbandriss-trainer-svindal-glaubt-an-lindsey-vonns-medaillenchance?ref=rss
|
||||
https://www.derstandard.at/story/3000000307177/worauf-wir-uns-bei-olympia-am-meisten-freuen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307391/zweite-runde-mit-dichtem-programm-woeginger-muss-ab-mittwoch-zurueck-auf-die-anklagebank?ref=rss
|
||||
https://www.derstandard.at/story/3000000307505/-frau-in-wien-nach-mutma223lichem-sexualdelikt-in-lebensgefahr?ref=rss
|
||||
https://www.derstandard.at/story/3000000307556/abermals-kritik-vor-erster-phase-des-kopftuchverbots-an-schulen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307559/viele-tote-bei-anschlag-auf-moschee-in-islamabad?ref=rss
|
||||
https://www.derstandard.at/story/3000000307557/ermittlungen-gegen-norwegischen-ex-regierungschef-wegen-epstein-affaere?ref=rss
|
||||
https://www.derstandard.at/story/3000000307515/washington-post-redaktion-protestiert-gegen-kahlschlag?ref=rss
|
||||
https://www.derstandard.at/story/3000000307486/stocker-fuehrt-politisches-armdruecken-in-der-koalition-ein-zu-seinem-schaden?ref=rss
|
||||
https://www.derstandard.at/story/3000000307554/schon-zu-viel-trump?ref=rss
|
||||
https://www.derstandard.at/story/3000000307489/der-wert-von-lebensmitteln-sollte-nicht-am-preis-haengen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307357/schriftsteller-thomas-raab-latein-als-humanistische-eintrittskarte?ref=rss
|
||||
https://www.derstandard.at/story/3000000307333/die-russische-epstein-connection?ref=rss
|
||||
https://www.derstandard.at/story/3000000307336/am-niedergang-der-washington-post-ist-nicht-nur-jeff-bezos-schuld?ref=rss
|
||||
https://www.derstandard.at/story/3000000307138/wie-lange-noch-bleiben-sozialunternehmen-die-unsichtbaren-optimisten?ref=rss
|
||||
https://www.derstandard.at/story/3000000253356/finde-den-fehler?ref=rss
|
||||
https://www.derstandard.at/story/3000000306814/cartoons-februar?ref=rss
|
||||
https://www.derstandard.at/story/3000000306730/was-ist-euer-lieblings-club-wiens?ref=rss
|
||||
https://www.derstandard.at/story/3000000306462/wenn-der-letzte-wille-nicht-dem-zufall-ueberlassen-werden-soll?ref=rss
|
||||
https://www.derstandard.at/story/3000000306728/seid-ihr-auch-von-gestiegenen-svs-beitraegen-betroffen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306902/teilauszahlung-des-gehalts-in-bitcoin-eure-erfahrungen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306593/ki-statt-latein-7-kritische-fragen-zur-reform?ref=rss
|
||||
https://www.derstandard.at/story/3000000306299/neuigkeiten-im-gluecksspielrecht-lootboxen-und-geschaeftsfuehrerhaftung?ref=rss
|
||||
https://www.derstandard.at/story/3000000306729/sollten-geschaefte-regulaer-sonntags-oeffnen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306767/wie-oft-schreibt-ihr-noch-mit-der-hand?ref=rss
|
||||
https://www.derstandard.at/story/3000000306139/was-kostet-ein-verlorenes-tier-rechtlich-gesehen?ref=rss
|
||||
https://www.derstandard.at/story/3000000305258/das-virtuelle-labor-im-weltraum?ref=rss
|
||||
https://www.derstandard.at/story/3000000306940/befreiungsschlag-als-bumerang-stockers-volksabstimmung-verstimmt-auch-in-der-oevp?ref=rss
|
||||
https://www.derstandard.at/story/3000000307458/nutzt-ihr-amazon-fuer-die-taeglichen-verbrauchsartikel?ref=rss
|
||||
https://www.derstandard.at/story/3000000307065/profitieren-wirklich-alle-aktive-fonds-und-lebensversicherungen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306520/kurzzeitvermietung-in-wien-das-ende-von-airbnb-als-geschaeftsmodell?ref=rss
|
||||
https://www.derstandard.at/story/3000000307531/ist-latein-mehr-als-nur-ein-unterrichtsfach?ref=rss
|
||||
https://www.derstandard.at/story/3000000307305/was-sind-ihre-erfahrungen-als-zugbegleiterinnen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306657/lueger-ehrenmal-ein-monument-der-gescheiterten-entnazifizierung?ref=rss
|
||||
https://www.derstandard.at/story/3000000307296/thema-grundwehrdienstverlaengerung-was-sind-eure-erfahrungen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306485/doppelte-botanik-pflanzen-mit-geschichten-und-zum-geniessen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307370/was-sind-eure-erinnerungen-an-die-olympischen-winterspiele?ref=rss
|
||||
https://www.derstandard.at/story/3000000303147/zwischen-information-und-image-was-aerztliche-werbung-darf?ref=rss
|
||||
https://www.derstandard.at/story/3000000307416/usa-und-eu-kooperieren-bei-seltenen-erden-warum-sie-keine-andere-wahl-haben?ref=rss
|
||||
https://www.derstandard.at/story/3000000307497/schwaerzungen-und-kontrollverlust-warum-epsteins-opfer-die-veroeffentlichungen-kritisieren?ref=rss
|
||||
https://www.derstandard.at/story/3000000307598/wehrpflicht-neos-gegen-volksbefragung?ref=rss
|
||||
https://www.derstandard.at/story/3000000307127/cora-liess-sich-mit-23-sterilisieren-so-krassen-hate-habe-ich-nie-bekommen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307156/fuer-die-eiserne-reserve-der-benkos-wird-es-eng-was-steckt-in-der-laura-privatstiftung?ref=rss
|
||||
https://www.derstandard.at/story/3000000307588/grossvater-schoss-in-oberoesterreich-auf-30-jaehrige-enkelin?ref=rss
|
||||
https://www.derstandard.at/story/3000000307564/epsteins-prominente-verstrickungen-in-die-kunstwelt-haben-ein-nachspiel?ref=rss
|
||||
https://www.derstandard.at/story/3000000307568/minnesotas-ice-watchers-how-tactics-of-1960s-radicals-went-mainstream?ref=rss
|
||||
https://www.derstandard.at/story/3000000307500/fleisch-die-empoerung-im-schnitzel-land?ref=rss
|
||||
https://www.derstandard.at/story/3000000307322/haeppchenweise-tuerkisch-im-neuen-kuebey?ref=rss
|
||||
https://www.derstandard.at/story/3000000307110/goldverkauf-leicht-gemacht?ref=rss
|
||||
https://www.derstandard.at/story/3000000307561/geeetech-m1s-im-test-kompetenter-3d-drucker-fuer-kids?ref=rss
|
||||
https://www.derstandard.at/story/3000000306765/abschied-vom-schlechten-kaffee-in-wien?ref=rss
|
||||
https://www.derstandard.at/story/3000000307596/zwischen-finger-am-abzug-und-gutem-start-gemischte-reaktionen-im-iran-auf-verhandlungen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307331/nasa-astronaut-bowen-in-wien-der-mond-ist-nur-der-anfang?ref=rss
|
||||
https://www.derstandard.at/story/3000000307225/neue-ausstellung-belegt-kunst-braucht-kommerz?ref=rss
|
||||
https://www.derstandard.at/story/3000000307539/bitcoin-crash-wie-es-dazu-kam-und-wie-weit-es-noch-abwaerts-gehen-kann?ref=rss
|
||||
https://www.derstandard.at/story/3000000307584/ich-habe-keinen-fehler-gemacht-trump-distanziert-sich-von-rassistische-posting-ueber-die-obamas?ref=rss
|
||||
https://www.derstandard.at/story/3000000307604/nach-ofarims-aussagen-zum-davidstern-verfahren-reagiert-sein-anwalt?ref=rss
|
||||
https://www.derstandard.at/story/3000000307605/bundestag-verweigerte-afd-personal-laut-parteiangaben-ausstellung-von-hausausweisen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307533/sahel-usa-ruecken-wieder-naeher-europa-ringt-derweil-um-einen-kurs?ref=rss
|
||||
https://www.derstandard.at/story/3000000307601/von-allmen-holt-olympiagold-in-der-abfahrt-oesterreicher-verpassen-medaille?ref=rss
|
||||
https://www.derstandard.at/story/3000000307595/-zur-prostitution-gezwungen-und-entf252hrt-junge-frau-in-n214-befreit?ref=rss
|
||||
https://www.derstandard.at/story/3000000307120/braucht-es-2026-ueberhaupt-noch-feminismus?ref=rss
|
||||
https://www.derstandard.at/story/3000000307420/wie-gross-sollte-ein-kinderzimmer-sein?ref=rss
|
||||
https://www.derstandard.at/story/3000000307605/usa-wollen-laut-selenskyj-kriegsende-noch-vor-dem-sommer?ref=rss
|
||||
https://www.derstandard.at/story/3000000306765/profitieren-wirklich-alle-aktive-fonds-und-lebensversicherungen?ref=rss
|
||||
https://www.derstandard.at/story/3000000306828/in-den-usa-haben-nazi-vergleiche-hochkonjunktur?ref=rss
|
||||
https://www.derstandard.at/story/3000000306837/moltbook-apokalypse-und-shitposting?ref=rss
|
||||
https://www.derstandard.at/story/3000000306928/vom-ich-zum-du-100-tage-als-personenbetreuer-beduerftiger-menschen?ref=rss
|
||||
https://www.derstandard.at/story/3000000307507/warum-thailand-bei-der-cannabis-legalisierung-zurueckgerudert-ist?ref=rss
|
||||
https://www.derstandard.at/story/3000000306092/zukunftsforscher-gen-z-boomer-millennials-sind-keine-guten-kategorien?ref=rss
|
||||
https://www.derstandard.at/story/3000000307298/lady-gaga-adrien-brody-friends-hoehepunkte-der-super-bowl-spots?ref=rss
|
||||
https://www.derstandard.at/story/3000000306983/gesuender-essen-im-alltag-11-expertentipps-die-zeigen-wie-es-gelingen-kann?ref=rss
|
||||
https://www.derstandard.at/story/3000000307609/buhrufe-fuer-vance-bei-olympia-eroeffnung-waren-im-us-tv-nicht-zu-hoeren?ref=rss
|
||||
https://www.derstandard.at/story/3000000306833/olympia-biathletin-slettemark-niemand-in-groenland-will-zum-amerikaner-werden?ref=rss
|
||||
https://www.derstandard.at/story/3000000303500/kunstduenger-ruiniert-millionen-alte-prozesse-im-boden?ref=rss
|
||||
https://www.derstandard.at/story/3000000307033/wo-sind-die-games-fuer-einen-einzelnen-abend?ref=rss
|
||||
https://www.derstandard.at/story/3000000307298/warum-thailand-bei-der-cannabis-legalisierung-zurueckgerudert-ist?ref=rss
|
||||
|
|
|
|||
|
|
@ -3,14 +3,45 @@
|
|||
"usa_iran_attack": true,
|
||||
"rheinmetall_above_1950": false,
|
||||
"steam_hardware_price": false,
|
||||
"steam_hardware_release_date": false
|
||||
"steam_hardware_release_date": false,
|
||||
"hamr_40tb_release": false
|
||||
},
|
||||
"lastChecks": {
|
||||
"news": "2026-01-30T08:17:00Z",
|
||||
"rheinmetall": "2026-02-03T22:00:00Z",
|
||||
"rheinmetall_price": 1773.50,
|
||||
"calendar": "2026-02-03T22:00:00Z",
|
||||
"rheinmetall": "2026-02-07T08:41:00Z",
|
||||
"rheinmetall_price": 1587.00,
|
||||
"calendar": "2026-02-04T04:25:00Z",
|
||||
"steam_hardware": "2026-02-03T22:00:00Z",
|
||||
"notes": "RHM: €1,773.50, below threshold. Calendar Feb 4: 'nyc' meeting at 12:00 (video call, no action). Steam hardware: still 'early 2026', no official price/date."
|
||||
"hamr_40tb": "2026-02-04T21:10:00Z",
|
||||
"notes": "RHM: €1,902.00, below €1,950 threshold. Steam hardware: still 'early 2026', no official price/date. HAMR 40TB: expected mid-2026, no release date yet."
|
||||
},
|
||||
"watchlist": {
|
||||
"hamr_40tb": {
|
||||
"description": "Seagate 40TB HAMR drives (IronWolf Pro / Exos)",
|
||||
"expectedRelease": "mid-2026",
|
||||
"notifyOn": "release with price",
|
||||
"lastCheck": "2026-02-04",
|
||||
"status": "not yet released"
|
||||
},
|
||||
"steam_hardware": {
|
||||
"description": "Steam Machine / Steam Frame",
|
||||
"expectedRelease": "early 2026",
|
||||
"notifyOn": "official price or release date",
|
||||
"status": "announced, no price/date"
|
||||
},
|
||||
"openclaw_opus46": {
|
||||
"description": "OpenClaw support for Claude Opus 4.6",
|
||||
"pr": "#9863",
|
||||
"notifyOn": "PR merged or new release with opus-4-6 support",
|
||||
"lastCheck": "2026-02-05",
|
||||
"status": "PR open, not merged"
|
||||
},
|
||||
"claude_code_update": {
|
||||
"description": "Claude Code updates",
|
||||
"notifyOn": "new version released",
|
||||
"lastCheck": "2026-02-05",
|
||||
"lastKnownVersion": null,
|
||||
"status": "watching"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,35 +2,35 @@
|
|||
"description": "Task tracking — auto-captured from chat or manually added. Done tasks get deleted.",
|
||||
"recurring": [
|
||||
{
|
||||
"id": "nose-shower",
|
||||
"id": "843efabf",
|
||||
"text": "Nose shower 👃🚿",
|
||||
"frequency": "daily",
|
||||
"when": "evening",
|
||||
"note": "Remind in evening, whether work just wrapped up or already relaxing"
|
||||
"context": "Remind in evening, whether work just wrapped up or already relaxing"
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "forgejo-script",
|
||||
"added": "2026-01-31",
|
||||
"id": "b9d1d89e",
|
||||
"added": "2026-02-07",
|
||||
"text": "Create script to auto-update workflows to Forgejo monorepo actions",
|
||||
"context": "Monorepo is done, using GitHub actions as fallback for now",
|
||||
"priority": "someday"
|
||||
"priority": "someday",
|
||||
"context": "Monorepo is done, using GitHub actions as fallback for now"
|
||||
},
|
||||
{
|
||||
"id": "forgejo-mcp-server",
|
||||
"added": "2026-01-31",
|
||||
"id": "af198211",
|
||||
"added": "2026-02-07",
|
||||
"text": "Set up MCP server for Forgejo instance",
|
||||
"context": "Phase 1: MCP server for interactive Claude web sessions (fork + PR workflow). Phase 2: Automated issue-solving pipeline with clarification comments.",
|
||||
"priority": "soon",
|
||||
"lastNudged": "2026-02-07T13:59:36.313Z"
|
||||
"context": "Phase 1: MCP server for interactive Claude web sessions (fork + PR workflow). Phase 2: Automated issue-solving pipeline with clarification comments.",
|
||||
"lastNudged": "2026-02-07T14:11:07.284Z"
|
||||
},
|
||||
{
|
||||
"id": "typo3-v13-gbv",
|
||||
"added": "2026-02-01",
|
||||
"id": "0902aaba",
|
||||
"added": "2026-02-07",
|
||||
"text": "TYPO3 v13 upgrade for GBV",
|
||||
"priority": "soon",
|
||||
"lastNudged": "2026-02-07T13:59:36.313Z"
|
||||
"lastNudged": "2026-02-07T14:11:07.284Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
145
memory/tv-shows.json
Normal file
145
memory/tv-shows.json
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
{
|
||||
"description": "TV shows tracking for recommendations",
|
||||
"shows": [
|
||||
{
|
||||
"title": "Monarch: Legacy of Monsters",
|
||||
"status": "watching",
|
||||
"startedWatching": "2026-02-04",
|
||||
"currentEpisode": 2,
|
||||
"platform": "Apple TV+",
|
||||
"genre": ["Sci-Fi", "Fantasy", "Drama", "Action & Adventure"],
|
||||
"universe": "MonsterVerse (Godzilla)",
|
||||
"rating": null,
|
||||
"notes": "Features Kurt Russell & Wyatt Russell. Ask when finished."
|
||||
},
|
||||
{
|
||||
"title": "Fallout",
|
||||
"status": "watching",
|
||||
"season": 2,
|
||||
"platform": "Prime Video",
|
||||
"genre": ["Sci-Fi", "Post-apocalyptic", "Drama"],
|
||||
"notes": "Season 2 finale ready to watch as of Feb 4"
|
||||
},
|
||||
{
|
||||
"title": "Prodigal Son",
|
||||
"status": "watched",
|
||||
"genre": ["Crime", "Drama", "Thriller"],
|
||||
"notes": "Was watching Feb 3"
|
||||
},
|
||||
{
|
||||
"title": "Hijack",
|
||||
"status": "watching",
|
||||
"season": 2,
|
||||
"platform": "Apple TV+",
|
||||
"genre": ["Thriller", "Drama"],
|
||||
"notes": "S2 finale drops March 4, 2026"
|
||||
}
|
||||
],
|
||||
"history": [
|
||||
{
|
||||
"title": "Wheel of Time",
|
||||
"rating": "liked",
|
||||
"genre": ["Fantasy", "Adventure"]
|
||||
},
|
||||
{
|
||||
"title": "Stargate SG-1",
|
||||
"rating": "liked",
|
||||
"genre": ["Sci-Fi", "Adventure", "Military"]
|
||||
},
|
||||
{
|
||||
"title": "Stargate Atlantis",
|
||||
"rating": "liked",
|
||||
"genre": ["Sci-Fi", "Adventure", "Military"]
|
||||
},
|
||||
{
|
||||
"title": "Doctor Who",
|
||||
"rating": "liked",
|
||||
"genre": ["Sci-Fi", "Adventure", "Time travel"]
|
||||
},
|
||||
{
|
||||
"title": "Chuck",
|
||||
"rating": "liked",
|
||||
"genre": ["Action", "Comedy", "Spy"],
|
||||
"notes": "Light-hearted spy action"
|
||||
},
|
||||
{
|
||||
"title": "Sherlock",
|
||||
"rating": "liked",
|
||||
"genre": ["Crime", "Mystery", "Drama"]
|
||||
},
|
||||
{
|
||||
"title": "Psych",
|
||||
"rating": "liked",
|
||||
"genre": ["Comedy", "Crime", "Mystery"],
|
||||
"notes": "Light-hearted crime procedural"
|
||||
},
|
||||
{
|
||||
"title": "Big Bang Theory",
|
||||
"rating": "liked",
|
||||
"genre": ["Sitcom", "Comedy"]
|
||||
},
|
||||
{
|
||||
"title": "King of Queens",
|
||||
"rating": "liked",
|
||||
"genre": ["Sitcom", "Comedy"]
|
||||
},
|
||||
{
|
||||
"title": "Stranger Things",
|
||||
"rating": "liked early seasons",
|
||||
"genre": ["Sci-Fi", "Fantasy", "Horror"],
|
||||
"notes": "First seasons good, later seasons declined"
|
||||
},
|
||||
{
|
||||
"title": "Breaking Bad",
|
||||
"rating": "liked",
|
||||
"genre": ["Drama", "Crime", "Thriller"]
|
||||
},
|
||||
{
|
||||
"title": "Ted Lasso",
|
||||
"rating": "liked",
|
||||
"genre": ["Comedy", "Feel-good"]
|
||||
},
|
||||
{
|
||||
"title": "The Boys",
|
||||
"rating": "liked",
|
||||
"genre": ["Action", "Superhero", "Dark comedy"]
|
||||
},
|
||||
{
|
||||
"title": "Jack Ryan",
|
||||
"rating": "liked",
|
||||
"genre": ["Action", "Thriller", "Spy"]
|
||||
},
|
||||
{
|
||||
"title": "Reacher",
|
||||
"rating": "liked",
|
||||
"genre": ["Action", "Crime", "Thriller"]
|
||||
},
|
||||
{
|
||||
"title": "Game of Thrones",
|
||||
"rating": "no",
|
||||
"genre": ["Fantasy", "Drama"],
|
||||
"notes": "Didn't enjoy - but likes other fantasy (Wheel of Time)"
|
||||
},
|
||||
{
|
||||
"title": "The Office (US)",
|
||||
"rating": "meh",
|
||||
"genre": ["Comedy", "Mockumentary"]
|
||||
}
|
||||
],
|
||||
"notSeen": ["The Expanse", "Succession", "The Bear", "True Detective", "Mindhunter", "Ozark", "What We Do in the Shadows"],
|
||||
"preferences": {
|
||||
"likedGenres": ["Sci-Fi", "Action", "Thriller", "Spy", "Crime/Mystery", "Sitcom", "Feel-good comedy", "Fantasy/Adventure"],
|
||||
"patterns": [
|
||||
"Big sci-fi fan (Stargate, Doctor Who, Fallout)",
|
||||
"Enjoys fantasy adventure (Wheel of Time) - GoT was exception not rule",
|
||||
"Loves action thrillers (Reacher, Jack Ryan, The Boys)",
|
||||
"Appreciates light-hearted comedy-action blends (Chuck, Psych)",
|
||||
"Classic sitcom fan (Big Bang Theory, King of Queens)",
|
||||
"Likes clever mysteries (Sherlock)",
|
||||
"Quality drama with tight storytelling (Breaking Bad)",
|
||||
"Prefers shows that stay focused - lost interest when Stranger Things dragged"
|
||||
],
|
||||
"notLiked": ["Game of Thrones specifically", "Mockumentary style (Office was meh)"],
|
||||
"notes": ["Broad taste but leans toward fun/adventurous over grimdark"]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,223 +1,8 @@
|
|||
{
|
||||
"goal": {
|
||||
"lastTaskDone": "22:00",
|
||||
"windDownPeriod": "22:00-00:00",
|
||||
"bedtime": "00:00",
|
||||
"windDownNeeded": "~2 hours"
|
||||
},
|
||||
"timezone": "Europe/Vienna",
|
||||
"learningPhase": true,
|
||||
"date": "2026-02-07",
|
||||
"entries": [
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:14",
|
||||
"activity": "nose shower (evening routine)",
|
||||
"note": "does this every evening"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:20",
|
||||
"activity": "tinkering with HA automation",
|
||||
"note": "setting up morning briefing hook"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:28",
|
||||
"activity": "setting up CalDAV access for me",
|
||||
"note": "still working on integrations"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:37",
|
||||
"activity": "still working on HA morning hook",
|
||||
"note": "acknowledged wants to finish, 23 min to midnight"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:44",
|
||||
"activity": "testing morning briefing hook",
|
||||
"note": "first test - CalDAV didn't work"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:46",
|
||||
"activity": "testing morning briefing hook",
|
||||
"note": "second test - CalDAV worked!"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-30",
|
||||
"time": "23:49",
|
||||
"activity": "starting wind-down",
|
||||
"note": "watching something, hot beverage"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "01:10",
|
||||
"activity": "bedtime routine",
|
||||
"note": "brushing teeth, putting cats out"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "02:15",
|
||||
"activity": "going to sleep",
|
||||
"note": "watched in bed, surfed internet"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "19:04",
|
||||
"activity": "Gitea → Forgejo migration",
|
||||
"note": "been working for hours already, now on workflow migration to new actions monorepo",
|
||||
"taskType": "infrastructure/devops tinkering"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "19:13",
|
||||
"activity": "decided to defer script to tomorrow",
|
||||
"note": "nudge worked! chose pragmatic stopping point: point to GitHub actions, test workflow, script tomorrow",
|
||||
"nudgeResult": "accepted"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "19:56",
|
||||
"activity": "finished testing workflows",
|
||||
"note": "tested 2 workflows, both worked. Final switch to Forgejo planned for tomorrow morning. Task wrapped up successfully before 20:00!"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "20:13",
|
||||
"activity": "starting semi wind-down (watching something)",
|
||||
"note": "usually finishes before 22:00 - on track for goal!"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "22:05",
|
||||
"activity": "bedtime routine starting (brushing teeth)",
|
||||
"note": "right on schedule! brain-dumped MCP/automation ideas first, then wind-down"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "22:32",
|
||||
"activity": "in bed winding down",
|
||||
"note": "cat, tea, audiobook - proper relaxation mode"
|
||||
},
|
||||
{
|
||||
"date": "2026-01-31",
|
||||
"time": "23:27",
|
||||
"activity": "going to sleep",
|
||||
"note": "33 minutes BEFORE midnight goal!"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-01",
|
||||
"time": "19:16",
|
||||
"activity": "relaxing, watching a series",
|
||||
"note": "already winding down by 19:16 on Sunday - great start!"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-01",
|
||||
"time": "20:36",
|
||||
"activity": "nose shower done",
|
||||
"note": "completed after episode ended, reminder at 20:10 worked"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-01",
|
||||
"time": "23:45",
|
||||
"activity": "going to sleep",
|
||||
"note": "15 minutes before midnight goal - on track!"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "01:01",
|
||||
"activity": "couldn't fall asleep, ate a bit, trying again",
|
||||
"note": "trouble sleeping despite good wind-down timing"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "19:22",
|
||||
"activity": "setting up ci-templates and testing with gbv-aktuell",
|
||||
"note": "working on workflow optimization from earlier discussion"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "22:10",
|
||||
"activity": "stopped working",
|
||||
"note": "fixed Deployer issue, called it a day. I failed to suggest stopping points earlier (19:00-22:00)"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "22:33",
|
||||
"activity": "nose shower reminder",
|
||||
"note": "requested 23 min delay after first reminder"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "22:39",
|
||||
"activity": "nose shower done",
|
||||
"note": "completed"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "22:46",
|
||||
"activity": "identity setup chat",
|
||||
"note": "chose Hoid as my identity - relaxed conversation while winding down"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-02",
|
||||
"time": "23:51",
|
||||
"activity": "in bed winding down",
|
||||
"note": "watching/relaxing more"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-03",
|
||||
"time": "00:05",
|
||||
"activity": "trying to sleep",
|
||||
"note": "5 min past midnight goal"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-03",
|
||||
"time": "19:15",
|
||||
"activity": "watching Prodigal Son (TV)",
|
||||
"note": "visited Marie earlier (16:00), now relaxing with a series - good wind-down activity"
|
||||
},
|
||||
{
|
||||
"date": "2026-02-03",
|
||||
"time": "21:40",
|
||||
"activity": "arrived home",
|
||||
"note": "HomeArrival hook fired, sent nose shower reminder"
|
||||
}
|
||||
],
|
||||
"patterns": {
|
||||
"2026-01-30": {
|
||||
"stoppedWork": "23:49",
|
||||
"startedBedRoutine": "01:10",
|
||||
"actualBedtime": "02:15",
|
||||
"windDownDuration": "~2.5 hours",
|
||||
"goalMissedBy": "~2h 15min",
|
||||
"notes": "was tinkering with tools until late, then watched TV + internet in bed"
|
||||
},
|
||||
"2026-01-31": {
|
||||
"stoppedWork": "19:56",
|
||||
"startedBedRoutine": "22:05",
|
||||
"actualBedtime": "23:27",
|
||||
"windDownDuration": "~1.5 hours",
|
||||
"goalMetBy": "33 minutes early!",
|
||||
"notes": "nudge at 19:13 helped defer script task. Proper wind-down: TV, then bed with cat/tea/audiobook. Huge improvement from previous night.",
|
||||
"sleepOutcome": {
|
||||
"fellAsleepIn": "~30 min",
|
||||
"briefWake": "5-6am",
|
||||
"wokeUp": "08:00",
|
||||
"totalSleep": "~8 hours",
|
||||
"quality": "good",
|
||||
"morningFeeling": "better than last 2 days"
|
||||
}
|
||||
},
|
||||
"2026-02-02": {
|
||||
"stoppedWork": "22:10",
|
||||
"noseShower": "22:39",
|
||||
"inBed": "23:51",
|
||||
"tryingSleep": "00:05",
|
||||
"windDownDuration": "~2 hours",
|
||||
"goalMissedBy": "~5 min (work ended late at 22:10 instead of 22:00)",
|
||||
"notes": "I failed at wind-down guidance - helped with work from 19:00 to 22:10 without suggesting stopping points. User called me out, updated HEARTBEAT.md. Bedtime itself was close to goal."
|
||||
}
|
||||
}
|
||||
{"time": "19:14", "activity": "Tinkering — troubleshooting Bazzite suspend/resume + VRAM on GPD Win 4", "note": "Saturday evening, tech tinkering not deep work. Active conversation."},
|
||||
{"time": "19:44", "activity": "Still GPD tinkering — fixed VRAM (8GB via UMAF), narrowed suspend crash to CPU hotplug (PowerTools core parking + SMT)", "note": "Making progress, having fun with it. Not work."},
|
||||
{"time": "20:10", "activity": "Done tinkering — nosmt kernel param fixed suspend. Switching to YouTube then TV/audiobook", "note": "Good wind-down transition. Reminded about nose shower."}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue