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>
This commit is contained in:
2026-06-01 09:42:21 -04:00
parent ff100b2472
commit 95e14e6340
3 changed files with 36 additions and 0 deletions
+10
View File
@@ -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,
+1
View File
@@ -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;
+25
View File
@@ -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 `<div class="band"><div class="reflectline meta">reflecting…</div></div>`;
if (refl.status === 'ready' && refl.recap) {
return `<div class="band"><div class="reflectline">${refl.recap}</div></div>`;
}
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 = `<span class="reflectline meta">Last time: ${refl.carry_forward}</span>`;
}
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) {
</div>
<div class="band" id="tasksBand"></div>
<div class="band" id="knowBand"></div>
<div class="band" id="reflectBand"></div>
<div class="band">
<label>Next action</label><input id="na" placeholder="What exactly will you do?">
<label>Success condition</label><input id="sc" placeholder="How do you know it's done?">
@@ -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) {
<p class="meta">${c.next_action || ''}</p>
<p class="meta">done when: ${c.success_condition || ''}</p>
</div>
${reflectionBlock(state.reflection)}
${reviewSummary(state.evidence)}
<div class="band"><button id="end" class="btn btn-primary">End</button></div>`;
document.getElementById('end').onclick = () => post('/end');