Commit Graph
100 Commits
Author SHA1 Message Date
felixmandClaude Opus 4.8 b36964a427 fix(keeld): log the effective ambient cadence, not the raw setting
A settings.json predating the ambient fields deserializes cadence to 0;
the sentinel clamps that to its 5m default, so log the clamped value
instead of a misleading cadence=0s.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:59:42 -04:00
felixmandClaude Sonnet 4.6 6c81a0d4f8 feat(keeld): wire the ambient drift coach sentinel
Automated smoke test results:
- GET /: 200
- POST /ambient/snooze: 204
- GET /settings: includes ambient_mode and ambient_cadence_secs fields
- daemon log: "ambient: mode=notify cadence=0s" (cadence=0 because existing
  settings.json predates these fields; ambient.New defaults to 5 min when
  cadence is non-positive — correct degradation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:57:14 -04:00
felixm aaed1ad265 feat(web): ambient banner, snooze/focus actions, settings controls 2026-06-05 21:51:49 -04:00
felixmandClaude Opus 4.8 fa178a1fd2 feat(web): ambient line in state envelope + /ambient/snooze
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:46:45 -04:00
felixmandClaude Sonnet 4.6 ef845ce463 feat(settings): ambient_mode and ambient_cadence_secs fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:43:45 -04:00
felixmandClaude Sonnet 4.6 4b2cb4242f feat(statusfile): render the ambient drift line when idle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:41:24 -04:00
felixm 7507cc6d28 fix(ambient): re-check active mode after the judge call (coexistence TOCTOU) 2026-06-05 21:39:46 -04:00
felixm c963895599 feat(ambient): evaluate loop, two-stage surfacing, snooze, config 2026-06-05 21:35:56 -04:00
felixm af3a0e2ac8 feat(ambient): sentinel core — evidence ring, Line, deps 2026-06-05 21:33:59 -04:00
felixm b37ee40dd2 feat(ai): AmbientDrift — frame-grounded drift judge 2026-06-05 21:30:37 -04:00
felixm 2690fdd513 refactor(offscreen): assemble frame via shared internal/frame 2026-06-05 21:28:21 -04:00
felixmandClaude Sonnet 4.6 703218658b feat(frame): shared ~/owc frame assembler extracted for reuse
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 21:26:21 -04:00
felixm 607ad74def feat(notify): notify-send effector with nop fallback 2026-06-05 21:22:12 -04:00
felixmandClaude Opus 4.8 aac3173874 docs: implementation plan for the ambient drift coach
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:20:11 -04:00
felixmandClaude Opus 4.8 9d7786c3e6 docs: design the ambient drift coach (always-on sentinel)
The first Control loop / scheduler component (architecture §3): an
always-on sentinel beside the one-mode harness that judges activity
against the ~/owc frame when no session is declared, and surfaces drift
to the status bar, a notify-send toast, and a web-UI banner.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:03:10 -04:00
felixmandClaude Opus 4.8 682eb603fa fix(evidence): X11 sensor polls so tab/title changes are tracked
The X11 source only re-read the active window on _NET_ACTIVE_WINDOW
changes, so switching a browser tab — which changes the window title
but not the active window — was invisible. All the time on the new tab
was credited to the stale title (e.g. reading a Consume article showed
up as time on the Keel tab).

Mirror the Windows sensor: poll the active window every 750ms and emit
only when the window or its title changes. A shared, display-free
pollLoop carries the change-dedup and is unit-tested for the exact
regression (a title-only change must emit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:32:24 -04:00
felixm 6d296bf743 docs: mark off-screen AW memory as shipped in architecture §5 2026-06-05 20:08:20 -04:00
felixm c855731c39 fix(web): preserve aw_url when a settings POST omits it
A UI save was silently blanking the configured AW URL because
handlePostSettings bound the whole Settings from the request and saved
it as-is. Now reads s.settings.AWURL under the existing settingsMu lock
and carries it forward when req.AWURL is empty, so fields not exposed in
the form are never erased.
2026-06-05 20:05:59 -04:00
felixmandClaude Sonnet 4.6 bd2b8a41fd feat(offscreen): read recent proposals into the brief; prompt follows up
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:56:59 -04:00
felixmandClaude Sonnet 4.6 16b44c9e90 feat(offscreen): record proposal_made/action_taken/proposal_dismissed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:51:18 -04:00
felixm 5bdb98c1a7 feat(keeld): construct AW memory store, nop fallback when AW is down 2026-06-05 19:45:24 -04:00
felixmandClaude Opus 4.8 67f91442a4 feat(settings): KEEL_AW_URL with localhost default
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:39:49 -04:00
felixm 3a4f498f86 feat(memory): AW-backed Store with over-fetch kind filtering 2026-06-05 19:38:35 -04:00
felixm 7d4f9ca4a8 feat(memory): Store port with nop and fake adapters 2026-06-05 19:33:46 -04:00
felixm 582af0d68b feat(aw): Insert and Recent over the events endpoint 2026-06-05 19:32:43 -04:00
felixm b422b6deb6 feat(aw): AW REST client with idempotent EnsureBucket 2026-06-05 19:29:41 -04:00
felixmandClaude Opus 4.8 3386405c7c docs: implementation plan for off-screen AW-backed memory
Nine TDD tasks: internal/aw REST client (EnsureBucket/Insert/Recent),
internal/memory port (Store + awStore over-fetch filter + nop + fake),
KEEL_AW_URL setting, harness.Services.Memory wiring with nop fallback,
off-screen write path (proposal_made/action_taken/proposal_dismissed) and
read path (## Recently proposed + follow-up prompt rule), plus full and
live verification. Derived from the 2026-06-05 design spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:16:47 -04:00
felixmandClaude Opus 4.8 730ffe33ce docs: design off-screen AW-backed memory (first durable-memory slice)
Brainstormed design for Keel's first cross-run memory: a thin memory.Store
port backed by an internal/aw REST client writing to the keel.events bucket,
with off-screen as the single wired consumer (records proposal_made /
action_taken / proposal_dismissed and reads its recent history back into the
brief for fresher, follow-up-aware proposals). Brain-only, best-effort,
degrades to nop when AW is down. Realizes keel-architecture.md §5/§7 at the
smallest honest vertical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:08:41 -04:00
felixmandClaude Opus 4.8 7d69a1f320 Generalize the focus controller into a harness hosting swappable modes
Loosen AntiDrift's session controller into Keel's general collect→brain→act
loop. A new internal/harness runs at most one mode.Mode at a time, fanning
async completions out to the web SSE and status-bar surfaces.

- internal/mode: the Mode contract (Kind/Command/View/Active) plus optional
  EvidenceConsumer and Expirer ports, and the surfacing Envelope.
- internal/mode/focus: the former session/domain/statemachine packages moved
  under the mode, now satisfying the harness contracts unchanged.
- internal/mode/offscreen: a one-shot away-from-desk mode built on the new
  ai.Proposer, which turns a life-domain brief into one off-screen action.
- cmd/keeld replaces cmd/antidriftd; daemon wires focus + offscreen factories
  with per-mode persistence under ~/.keel/modes/<kind>.
- Finish the rename: KEEL_* env refs in the README, /keeld build artifact
  ignored, stale antidriftd binary removed.

Include the design + implementation plan this refactor was built from under
docs/superpowers/{specs,plans}/2026-06-04-controller-refactor*.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:00:49 -04:00
felixmandClaude Opus 4.8 258de2c14b docs: make Keel the repo front door + add agent context
- README: lead with Keel (the human-harness), frame AntiDrift as the focus
  mode, keep the milestone history. Fix the "rename deferred" wording (the
  dir/repo is already keel; only the code identity stays antidrift) and drop
  the dangling 2026-05-31 spec reference (that spec was intentionally removed).
- keel-architecture.md: update the rename status in the header and §8 — the
  directory is keel; the Go module / antidriftd binary / ANTIDRIFT_* env /
  ~/.antidrift -> ~/.keel migration land with the controller refactor.
- add AGENTS.md (agent orientation) + CLAUDE.md symlink so claude / codex /
  Hermes auto-load Keel context when launched in this repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 13:20:51 -04:00
felixmandClaude Opus 4.8 f9e580ff7e docs: name the cockpit Keel and add its architecture
Move the higher-goals cockpit architecture into this repo: AntiDrift is
Keel's seed, with its focus harness becoming one mode of a general
collect -> brain -> act loop. Records the locked decisions: the product
is the harness around a swappable brain (claude/codex/Hermes); storage is
ActivityWatch; two surfaces (web UI + status bar); gated -> autonomous
effectors. Code/repo rename to keel deferred until the controller-refactor
decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:57:14 -04:00
felixmandClaude Opus 4.8 13633ffabf Fix drift sync: per-window verdicts, forgiving class match, event-driven status bar
Three independent defects made the focus state feel flaky and let the OS
status bar disagree with the web UI:

- Status file lagged the web by up to a minute: it rendered only on a 60s
  ticker with no hook into state changes. notify() now fans out to multiple
  listeners (AddOnChange) and the writer has a coalesced Wake() so drift
  reaches the bar as promptly as the browser.

- A brief off-task visit could latch drift for the whole session. Sibling
  windows of one app (a browser's reading tab vs its chat tab) share a window
  class, but the judge verdict was cached by class alone, so one tab's verdict
  poisoned the rest and never re-judged. Cache is now keyed by class + scrubbed
  title (judgedWindows) so siblings are judged independently.

- Allowed-class matching was exact equality, so a short token ("brave") never
  matched the real WM_CLASS ("Brave-browser") and every window was routed to
  the LLM. Matching is now substring-based, and planning surfaces the live
  window class with a click-to-add chip so users pick a token that matches.

Also fix the planning checkbox alignment: the global full-width input rule was
stretching the "Enforce focus" checkbox; scope it out for checkboxes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 09:25:30 -04:00
felixmandClaude Opus 4.8 9012d5ddc6 Purge leftover Rust implementation
Remove the legacy/ Rust tree (Cargo manifests, .rs sources, desktop
entry), drop Rust-specific .gitignore blocks and README note, and strip
now-dangling "ported from Rust" comments from the Go sources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 09:06:14 -04:00
felixm 91a3fb29c2 Add Windows 11 support behind evidence.Source and enforce.Guard ports
Polling active-window sensor and window-minimize guard as //go:build windows
adapters over a shared internal/winapi Win32 binding. Pure logic (class
normalization, emit-on-change tracking) is TDD-tested on Linux; syscall code is
cross-compile verified. No consumer changes.
2026-06-02 12:41:25 -04:00
felixm 9546999acb Clarify null-HWND doc note in ForegroundWindow 2026-06-02 12:39:32 -04:00
felixm d45a01eca5 Verify Windows cross-compile and Linux regression for Windows support
- GOOS=windows GOARCH=amd64 go build ./...  (whole module links)
- GOOS=darwin  GOARCH=amd64 go build ./...  (!linux && !windows fallback intact)
- go build ./... && go test ./...           (Linux host green, incl. new winapi/evidence tests)
- go vet ./... on linux and windows         (clean)
- cmd/antidriftd cross-compiles to a real PE32+ x86-64 .exe
2026-06-02 12:37:24 -04:00
felixm b6c7933f16 Align Windows guard ctx param and doc with X11 guard 2026-06-02 12:36:12 -04:00
felixm f37e295166 Add Windows window-minimize guard 2026-06-02 12:34:14 -04:00
felixm d149736946 Share unavailable() so the Windows sensor logs unavailable transitions 2026-06-02 12:33:23 -04:00
felixm 0daf8c2849 Add Windows polling active-window sensor 2026-06-02 12:30:16 -04:00
felixm 0f47d2dbf0 Document title/path truncation behavior in Win32 binding 2026-06-02 12:29:07 -04:00
felixm 0ac1511aac Add Win32 binding for foreground window and minimize 2026-06-02 12:24:55 -04:00
felixmandClaude Sonnet 4.6 7d62af0750 Document foregroundTracker unavailable-state contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:23:54 -04:00
felixm e1194be3c2 Add emit-on-change tracker for the Windows polling sensor 2026-06-02 12:21:58 -04:00
felixm f79c149039 Clarify .exe suffix handling in class normalization 2026-06-02 12:21:12 -04:00
felixm 4ea8aed04b Add pure process-path to class normalization for Windows 2026-06-02 12:18:59 -04:00
felixmandClaude Opus 4.8 885b0f9224 Plan Windows 11 support implementation
Six TDD/cross-compile tasks: pure class normalization and emit-on-change
tracker (unit-tested on Linux), Win32 binding, the two windows-tagged port
adapters, build-tag narrowing, and a whole-module cross-compile gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:08:01 -04:00
felixmandClaude Opus 4.8 e0ea1eca83 Spec Windows 11 support via windows-tagged port adapters
Full-parity design: evidence.Source (polling) and enforce.Guard
(ShowWindow) behind the existing X11/no-op port boundaries, pure Go,
verified compile-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 11:35:39 -04:00
felixmandClaude Opus 4.8 14ec2b6ea8 Remove shipped specs and plans; history and code are the record
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 22:00:52 -04:00
felixmandClaude Opus 4.8 b447432df0 Track faithful-reflection implementation plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:56:48 -04:00
felixmandClaude Opus 4.8 ca5e76baf5 Test faithful on/off-task crediting through RecordWindow
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:05:07 -04:00
felixm e5c32563d0 Render on/off-task split in the reflection block 2026-06-01 21:02:23 -04:00
felixmandClaude Opus 4.8 7eb2b5dc58 Split session time into on/off/unclassified buckets
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:00:52 -04:00
felixmandClaude Opus 4.8 6b99804132 Add faithful-reflection on/off-task split design spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:49:19 -04:00
felixmandClaude Opus 4.8 38e1a175b6 Harden settings UI: robust parentDir, escape browse paths, surface load error
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:29:42 -04:00
felixmandClaude Opus 4.8 ce201c57bb Add settings gear, overlay, and file-browser modal to the UI
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:26:24 -04:00
felixmandClaude Opus 4.8 326990d69a Serialize settings applies; log fallback save error
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:24:17 -04:00
felixmandClaude Opus 4.8 324aa3ebce Drive daemon config from settings file via injected applier
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:21:07 -04:00
felixmandClaude Opus 4.8 86c85629c0 Remove /knowledge/path; folded into /settings
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:18:44 -04:00
felixmandClaude Opus 4.8 acf336c846 Strengthen /fs/browse test: assert dir and entry paths
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:16:36 -04:00
felixmandClaude Opus 4.8 a108964457 Add GET /fs/browse directory-listing endpoint
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:15:00 -04:00
felixmandClaude Opus 4.8 1a925b3a05 Clarify settings apply/save comment; strengthen settings tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:13:33 -04:00
felixmandClaude Opus 4.8 2a196bcdb2 Add GET/POST /settings handlers with injected applier
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:10:47 -04:00
felixmandClaude Opus 4.8 e3351b3d70 Add settings package: Settings file load/save/seed
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:07:42 -04:00
felixmandClaude Opus 4.8 ae5cec3dce Add settings page implementation plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:53:27 -04:00
felixmandClaude Opus 4.8 3fdbfd307b Add settings page + settings file design spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:47:42 -04:00
felixmandClaude Opus 4.8 4f6b26a220 Trust no proxies on the local server
antidriftd binds localhost only and sits behind no proxy, so trusting all
proxies (gin's default) is both wrong and a startup warning. Set an empty
trusted-proxy list to disable forwarded-IP header trust and silence it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:24:19 -04:00
felixmandClaude Opus 4.8 71b8c80c69 Scrub spinner glyphs from window-title bucket keys
Bucket keys are {Class, ScrubTitle(Title)}, so each animated progress frame a
terminal app cycles into its title (Claude Code's braille and dingbat-star
glyphs) became a distinct bucket — fragmenting one task into dozens of rows and
inflating the switch count, since applyEvent counts a switch per key change.

ScrubTitle now drops any non-ASCII symbol or control rune and collapses leftover
whitespace. This is category-based rather than range-based, so future spinner
sets are covered too, while letters and digits of every script survive and ASCII
symbols (e.g. "C++") are left intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:23:49 -04:00
felixmandClaude Opus 4.8 1c81eb1b50 Refresh the active evidence band live and drop its duplicate switch count
The active view's fast-path repainted only the status band, so the "now"
window, per-window buckets, and their times froze at the moment the active
screen first rendered — only the status-band switch count and the countdown
kept moving. Give the evidence band a stable id and repaint it every tick via
updateActiveEvidence, mirroring updateActiveDrift.

The evidence band's own "context switches" readout duplicated the live count
in the status band, so remove it (and its now-dead .switches CSS rule).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 19:23:49 -04:00
felixm d95aed0111 Add AntiDrift favicon 2026-06-01 19:09:37 -04:00
felixmandClaude Opus 4.8 895ad342c7 Migrate the reflection fetch onto runFetchAsync
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:12:10 -04:00
felixmandClaude Opus 4.8 59283be733 Migrate the coach fetch onto runFetchAsync
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:08:48 -04:00
felixmandClaude Opus 4.8 fbbff6966d Migrate the knowledge fetch onto runFetchAsync
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:06:09 -04:00
felixmandClaude Opus 4.8 db0d11ea2e Add runFetchAsync helper and migrate the tasks fetch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:05:08 -04:00
felixmandClaude Opus 4.8 d3f0526355 Split async AI roles into roles.go
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:57:26 -04:00
felixmandClaude Opus 4.8 0d3294b30d Split drift/nudge/enforcement into drift.go
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:50:53 -04:00
felixmandClaude Opus 4.8 d068e2f79c Split evidence-stats accounting into stats.go
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:46:15 -04:00
felixmandClaude Opus 4.8 a0f144968b Split session views into views.go
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:42:53 -04:00
felixmandClaude Opus 4.8 f13f33cf74 Add knowledge stale-discard characterization test
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:39:40 -04:00
felixmandClaude Opus 4.8 465938906e Add M9 tame-session refactor implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:31:57 -04:00
felixmandClaude Opus 4.8 79b3c0be95 Add M9 tame-session refactor design spec
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 17:24:36 -04:00
felixmandClaude Opus 4.8 5adab985a7 Add the enforce toggle and drift-band minimize note
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:49:31 -04:00
felixmandClaude Opus 4.8 4cc1edfc60 Wire the enforce guard into the daemon and assert it on the wire
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:46:59 -04:00
felixmandClaude Opus 4.8 47f1167247 Minimize the off-task window on confirmed drift at the block level
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:43:30 -04:00
felixmandClaude Opus 4.8 41c0a5fbbc Thread per-commitment enforcement level through to the snapshot
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:41:09 -04:00
felixmandClaude Opus 4.8 7fdcae5d14 Add enforce.Guard port with X11 and no-op adapters
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:35:54 -04:00
felixmandClaude Opus 4.8 d0e6893659 Add M8 Tier A window-minimize enforcement implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:22:59 -04:00
felixmandClaude Opus 4.8 76cdd4c857 Add M8 Tier A window-minimize enforcement design spec
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:11:56 -04:00
felixmandClaude Opus 4.8 e3cfe8c70c Assert the reviewer fires exactly once per session
Closes the one coverage gap from the final review: the spec's
'one async call per session' efficiency claim is now directly
verified via the reviewer call count, not just implied. Also drops a
stale CarryForward-preview mention from the Review projection in the
design spec to match the shipped (cleaner) behaviour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:47:27 -04:00
felixmandClaude Opus 4.8 95e14e6340 Show the recap on Review and the carry-forward on Planning
The Review screen renders the reviewer's one-line recap (quiet pending
line, then the recap); the Planning screen renders last session's
carry-forward as a 'Last time: …' one-liner, mirroring the knowledge
indicator. Updates the README Status section for M7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:42:21 -04:00
felixmandClaude Opus 4.8 ff100b2472 Wire the reviewer and assert reflection on the wire
main injects the AI service as the reviewer alongside the other roles.
A web test drives a session to Review and asserts the recap rides the
state payload, then to the next Planning and asserts the carry-forward
does too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:38:13 -04:00
felixmandClaude Opus 4.8 a4f0c00cac Reflect on entering Review and ground the next coach
The controller fetches a reflection asynchronously on enterReview
(generation-guarded, non-blocking, graceful) and caches a one-line
recap plus a latest-wins carry-forward. The recap projects onto Review,
the carry-forward onto the next Planning, and both ride the snapshot.
RequestCoach composes the carry-forward into the coach's existing
free-form grounding string, so ai.Coach is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:36:50 -04:00
felixmandClaude Opus 4.8 25f56b3c71 Add RecentSessions reader over the audit chain
Exposes the last n session summaries (oldest-first) for the reviewer to
read as recent-history context. Missing/empty chain or n<=0 yields nil.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:26:57 -04:00
felixmandClaude Opus 4.8 e4e34b092c Add reviewer role to the ai port
A fourth leaf role: Review(finished, history) returns a two-line
Reflection (recap + carry_forward) over the same CLI backend as the
coach. Primitive-only, with a JSON prompt and a tolerant parser that
rejects a blank recap but allows an empty carry_forward.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:24:04 -04:00
felixmandClaude Opus 4.8 82fd7d35a5 Add M7 reflection implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 09:20:55 -04:00
felixm f417faab9a Add M7 reflection design spec 2026-06-01 09:11:00 -04:00
felixmandClaude Opus 4.8 5342da2755 Show a profile-grounding indicator on the planning screen
The planning view renders a quiet line for the standing-profile state
(loading/grounded/absent/unreadable) with a "change" affordance to
repoint the file via POST /knowledge/path. The profile text never
reaches the browser — only status, path, and size. Also updates the
README Status section to describe the M6 knowledge port.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:08:55 -04:00
felixmandClaude Opus 4.8 b1b807590c Wire the knowledge file adapter and a runtime path selector
main constructs the FileSource (default via ANTIDRIFT_KNOWLEDGE_FILE)
and injects it. Adds POST /knowledge/path to repoint the profile file at
runtime, and web tests asserting the planning payload carries the
knowledge object (status + path, never the text) and that path selection
reloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:06:10 -04:00
felixmandClaude Opus 4.8 8bd37ed46d Load the knowledge profile on planning and ground the coach
The controller loads the profile asynchronously on entering planning,
mirroring the tasks fetch: generation-guarded goroutine, status enum
(idle/pending/ready/absent/error), projected into State only while
planning and only when a source is set. The loaded text is cached and
passed to the coach as grounding; SetKnowledgePath repoints the file at
runtime. nil source degrades to no view and an ungrounded coach.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:04:13 -04:00
felixmandClaude Opus 4.8 0f1790c8d5 Thread optional grounding into the coach prompt
The ai.Coach interface gains a grounding parameter carrying standing
context about the user (the knowledge port). buildPrompt injects an
"About the user" block only when grounding is non-empty, so an empty
grounding produces a byte-for-byte unchanged prompt. Drift judge and
nudge are untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 08:01:03 -04:00