diff --git a/README.md b/README.md index 9b5688f..ef66101 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,16 @@ go test ./... ## Status +M7 (reflection): when a session ends, a fourth AI role — the reviewer — +reflects on it, read against your recent sessions, and produces two short +lines: a recap shown on the Review screen, and a carry-forward takeaway that +grounds the coach the next time you plan. It runs once asynchronously on +entering Review, never blocks the End button, and degrades gracefully — with +no backend (or a slow/failed call) Review and Planning behave exactly as +before. The carry-forward is snapshot-persisted (latest-wins) and composes +into the coach's grounding; the reflection lines are short and cross the wire +by design, while the knowledge profile still does not. + M6 (knowledge port): the planning coach now sharpens intents against who you actually are. A single profile file (`~/.antidrift/knowledge.md`, overridable via `ANTIDRIFT_KNOWLEDGE_FILE`) holds your standing context — priorities, diff --git a/internal/web/static/app.css b/internal/web/static/app.css index d46e41f..8be65b2 100644 --- a/internal/web/static/app.css +++ b/internal/web/static/app.css @@ -119,6 +119,7 @@ input:focus { outline: 0; border-color: var(--accent); } /* Planning: standing-profile grounding indicator */ .knowline { opacity: 0.85; } +.reflectline { opacity: 0.85; } .link { background: none; border: none; padding: 0; font: inherit; font-size: 12px; color: var(--accent); cursor: pointer; text-decoration: underline; diff --git a/internal/web/static/app.js b/internal/web/static/app.js index 42376f3..8117ab2 100644 --- a/internal/web/static/app.js +++ b/internal/web/static/app.js @@ -179,6 +179,27 @@ function updatePlanningKnowledge(k) { }; } +// reflectionBlock renders the reviewer's recap on the Review screen. idle/nil or +// an empty recap renders nothing; pending shows a quiet line; ready shows the +// one-line recap. +function reflectionBlock(refl) { + if (!refl) return ''; + if (refl.status === 'pending') return `
reflecting…
`; + if (refl.status === 'ready' && refl.recap) { + return `
${refl.recap}
`; + } + return ''; +} + +// updatePlanningReflection renders last session's carry-forward takeaway as a +// quiet one-liner on the planning screen. Nothing renders without one. +function updatePlanningReflection(refl) { + const el = document.getElementById('reflectBand'); + if (!el) return; + if (!refl || !refl.carry_forward) { el.innerHTML = ''; return; } + el.innerHTML = `Last time: ${refl.carry_forward}`; +} + function render(state) { setStateAttr(state); const rs = state.runtime_state; @@ -186,6 +207,7 @@ function render(state) { updatePlanningCoach(state.coach); updatePlanningTasks(state.tasks); updatePlanningKnowledge(state.knowledge); + updatePlanningReflection(state.reflection); return; } if (rs === 'active' && renderedState === 'active') { @@ -213,6 +235,7 @@ function render(state) {
+
@@ -239,6 +262,7 @@ function render(state) { updatePlanningCoach(state.coach); updatePlanningTasks(state.tasks); updatePlanningKnowledge(state.knowledge); + updatePlanningReflection(state.reflection); } else if (rs === 'active') { const c = state.commitment || {}; @@ -265,6 +289,7 @@ function render(state) {

${c.next_action || ''}

done when: ${c.success_condition || ''}

+ ${reflectionBlock(state.reflection)} ${reviewSummary(state.evidence)}
`; document.getElementById('end').onclick = () => post('/end');