Compare commits

..

6 Commits

Author SHA1 Message Date
b3b8dc98af docs: record presence timezone fallback
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 8s
Build / test-and-image (pull_request) Successful in 26s
2026-07-05 23:05:53 +02:00
f0a8162202 Merge pull request 'fix: fall back from invalid DAVE presence timezone' (#74) from codex/issue-73-presence-timezone-fallback into codex/production-intelligence-terminal
All checks were successful
Codex Template Compliance / template-compliance (push) Successful in 6s
Release Dry Run / release-dry-run (push) Successful in 16s
Build / test-and-image (push) Successful in 28s
2026-07-05 21:03:33 +00:00
09ee1d9006 fix: fall back from invalid presence timezone
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 6s
Build / test-and-image (pull_request) Successful in 45s
2026-07-05 23:01:37 +02:00
20243d159f Merge pull request 'docs: record dynamic DAVE presence release' (#72) from codex/handoff-dave-presence into codex/production-intelligence-terminal
All checks were successful
Release Dry Run / release-dry-run (push) Successful in 19s
Codex Template Compliance / template-compliance (push) Successful in 7s
Build / test-and-image (push) Successful in 32s
2026-07-05 20:59:42 +00:00
8413f5b7f1 docs: record dynamic DAVE presence release
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 7s
Build / test-and-image (pull_request) Successful in 25s
2026-07-05 22:58:19 +02:00
ca68541adf Merge pull request 'feat: add dynamic autonomous DAVE presence' (#71) from codex/issue-70-dave-presence into codex/production-intelligence-terminal
All checks were successful
Codex Template Compliance / template-compliance (push) Successful in 6s
Release Dry Run / release-dry-run (push) Successful in 16s
Build / test-and-image (push) Successful in 34s
2026-07-05 20:55:59 +00:00
3 changed files with 23 additions and 9 deletions

View File

@@ -2,18 +2,20 @@
Last updated: 2026-07-05 Last updated: 2026-07-05
## Active WIP: Dynamic DAVE Presence ## Dynamic DAVE Presence
- Gitea issue #70 tracks dynamic autonomous Telegram presence for DAVE. - Gitea issue #70 was closed by merged PR #71. Production merge commit: `ca68541adf9931e311f1a79a09cb87b3cae85928`.
- Local branch: `codex/issue-70-dave-presence`. - Implementation commit: `08b6016 feat: add dynamic autonomous DAVE presence`; handoff commit: `f2d8e89`.
- Local implementation commit: `08b6016 feat: add dynamic autonomous DAVE presence`.
- The implementation deliberately uses no fixed daily schedule. It evaluates at randomized intervals, is pulled forward by material/critical sweep deltas, delays itself after operator chat activity, and lengthens quiet periods. - The implementation deliberately uses no fixed daily schedule. It evaluates at randomized intervals, is pulled forward by material/critical sweep deltas, delays itself after operator chat activity, and lengthens quiet periods.
- Hard controls: profile quiet hours, daily cap, minimum message gap, bounded evaluation interval, persisted state in `runs/dave-presence-state.json`, and agent-core rejection of mutating tools outside operator-initiated chat. - Hard controls: profile quiet hours, daily cap, minimum message gap, bounded evaluation interval, persisted state in `runs/dave-presence-state.json`, and agent-core rejection of mutating tools outside operator-initiated chat.
- Presence can produce a grounded warning, update, all-clear, practical suggestion, or one useful question; it stays silent when another message would add noise. It never claims consciousness or continuous observation. - Presence can produce a grounded warning, update, all-clear, practical suggestion, or one useful question; it stays silent when another message would add noise. It never claims consciousness or continuous observation.
- New env keys start with `DAVE_PRESENCE_`; the feature defaults off and must be enabled explicitly in the Dockge `.env`. - New env keys start with `DAVE_PRESENCE_`; the repository default remains opt-in.
- Local lightweight verification passed: Node syntax checks, `package.json` parse, Compose config, and `git diff --check`. Heavy tests/build were not run locally per kit policy. - Local lightweight verification passed: Node syntax checks, `package.json` parse, Compose config, and `git diff --check`. Heavy tests/build were not run locally per kit policy.
- Push was blocked by the Codex usage-limit approval service until 2026-07-06 02:28 local time. The branch and commit currently exist only in this workspace. - PR runs 915-916 and production runs 917-919 passed, including unit tests, Compose validation, Docker build/publish, release dry-run, and template compliance.
- Required continuation: push the branch, create a PR closing #70, poll Gitea runners, fix failures if any, merge, poll production publish workflows, add `DAVE_PRESENCE_ENABLED=true` to the Dockge environment, redeploy `latest`, verify `/api/health.davePresence`, then update this handoff with final commits/run IDs/live state. - Dockge was updated from the Gitea Registry and explicitly configured with `DAVE_PRESENCE_ENABLED=true`, max 4 messages/day, 75-minute minimum gap, randomized 45-180 minute evaluation bounds, 60-minute post-interaction idle delay, and a 5-minute timer resolution.
- Live `/api/health` reported `davePresence.enabled=true`, `running=true`, `dynamic=true`, `sentToday=0`, a variable `nextEvaluationAt`, the existing encrypted profile preserved, and no sweep error. The container reported `running/healthy`.
- Live verification then exposed issue #73: an invalid optional profile timezone caused `lastReason=invalid_timezone`. PR #74 fixed runtime resolution to fall back to `DAVE_PRESENCE_TIMEZONE` without logging or modifying encrypted profile data. Merge commit: `f0a8162202bfe0a0a8ed2a00dc4f0f7092677eea`.
- PR runs 925-926 and production runs 927-929 passed. After redeployment and the startup timer, live health reported `lastReason=not_due` instead of `invalid_timezone`, with dynamic presence running, the profile preserved, the container healthy, and no sweep error.
## Latest Completed Work ## Latest Completed Work

View File

@@ -78,8 +78,12 @@ export class DavePresence {
const profile = this.profileStore?.getAgentProfile(); const profile = this.profileStore?.getAgentProfile();
if (!profile) return this._result(false, 'profile_missing'); if (!profile) return this._result(false, 'profile_missing');
const timezone = profile.timezone || this.fallbackTimezone; let timezone = profile.timezone || this.fallbackTimezone;
const clock = localClock(now, timezone); let clock = localClock(now, timezone);
if (!clock && timezone !== this.fallbackTimezone) {
timezone = this.fallbackTimezone;
clock = localClock(now, timezone);
}
if (!clock) return this._result(false, 'invalid_timezone'); if (!clock) return this._result(false, 'invalid_timezone');
this._rollDay(clock.day); this._rollDay(clock.day);
if (this.state.sentCount >= this.maxPerDay) return this._result(false, 'daily_limit'); if (this.state.sentCount >= this.maxPerDay) return this._result(false, 'daily_limit');

View File

@@ -89,3 +89,11 @@ test('local clock uses the profile timezone', () => {
assert.deepEqual(localClock(new Date('2026-07-06T12:30:00Z'), 'Europe/Berlin'), { day: '2026-07-06', time: '14:30' }); assert.deepEqual(localClock(new Date('2026-07-06T12:30:00Z'), 'Europe/Berlin'), { day: '2026-07-06', time: '14:30' });
assert.equal(localClock(new Date(), 'Invalid/Timezone'), null); assert.equal(localClock(new Date(), 'Invalid/Timezone'), null);
}); });
test('invalid profile timezone falls back to configured operational timezone', async () => {
const { presence, messages, calls } = setup({ profile: { timezone: 'not-a-timezone' } });
const outcome = await presence.tick(new Date('2026-07-06T12:00:00Z'));
assert.equal(outcome.reason, 'sent');
assert.equal(messages.length, 1);
assert.match(calls[0].prompt, /timezone: UTC/);
});