Skip to content

Commit 0ba6de5

Browse files
committed
Add topic-change boundary detection with context-aware nudge
1 parent ac420f2 commit 0ba6de5

2 files changed

Lines changed: 39 additions & 20 deletions

File tree

index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,18 +204,23 @@ export default function (pi: ExtensionAPI): void {
204204
// ── context: inject primacy-zone nudge before each LLM call ────
205205
pi.on("context", async (event, ctx: ExtensionContext) => {
206206
const usage = ctx.getContextUsage();
207-
if (!usage || usage.percent === null || usage.percent < 30) {
207+
const percent = usage?.percent ?? null;
208+
if (usage && usage.percent !== null) {
209+
state.lastContextPercent = usage.percent;
210+
}
211+
if (!state.pendingTopicBoundaryHint && (percent === null || percent < 30)) {
208212
return;
209213
}
210214

211-
state.lastContextPercent = usage.percent;
215+
const nudge = buildNudge(state, percent);
216+
state.pendingTopicBoundaryHint = null;
212217
return {
213218
messages: [
214219
...event.messages,
215220
{
216221
role: "custom",
217222
customType: "agenticoding-watchdog",
218-
content: buildNudge(usage.percent),
223+
content: nudge,
219224
display: false,
220225
timestamp: Date.now(),
221226
},

watchdog.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,42 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
1212
import type { AgenticodingState } from "./state.js";
1313
import { STATUS_KEY_HANDOFF } from "./tui.js";
1414

15-
/** Build a nudge string with the exact percent interpolated. */
16-
export function buildNudge(percent: number): string {
17-
const pct = Math.round(percent);
15+
export function buildNudge(state: Pick<AgenticodingState, "activeNotebookTopic" | "pendingTopicBoundaryHint">, percent: number | null): string {
16+
const pct = percent === null ? null : Math.round(percent);
17+
const topic = state.activeNotebookTopic;
18+
const boundary = state.pendingTopicBoundaryHint;
1819

19-
if (pct >= 70) {
20-
return `Context at ${pct}% — deep in the degraded zone. Compaction may trigger soon
21-
(emergency summarization at ~90%). Prefer a deliberate handoff now: save
22-
reusable state to the ledger, draft a clear next-task brief, and call handoff.`;
20+
if (boundary) {
21+
return `Notebook topic changed from ${boundary.from ?? "(unset)"} to ${boundary.to}.
22+
Treat this as a strong task-boundary signal. Prefer a deliberate handoff before
23+
continuing under the new topic: save durable findings to the notebook, draft a
24+
concise situational brief, and call handoff. Only continue inline if this was
25+
merely a rename rather than a real pivot.`;
2326
}
2427

25-
if (pct >= 50) {
26-
return `Context at ${pct}% — well past the primacy-zone heuristic. If the current job is
27-
done or the context is noisy, consider a handoff soon. Save reusable state to
28-
the ledger and draft a concise but sufficiently detailed brief for what comes
29-
next.`;
28+
const contextLead = pct === null
29+
? "Topic-aware context reminder."
30+
: pct >= 70
31+
? `Context at ${pct}% — topic discipline is urgent.`
32+
: pct >= 50
33+
? `Context at ${pct}% — topic discipline matters now.`
34+
: `Context at ${pct}% — choose your next step by topic fit.`;
35+
36+
if (topic) {
37+
const urgency = pct !== null && pct >= 70
38+
? "If the work no longer fits this topic, prefer a deliberate handoff now. If it still fits and only a focused noisy branch is needed, spawn it instead of polluting the parent context."
39+
: "If the current work still fits this topic, prefer spawn for isolated noisy subtasks. If it no longer fits, prefer handoff instead of dragging stale context forward.";
40+
return `${contextLead}
41+
Active notebook topic: ${topic}.
42+
Use the topic as the current semantic frame. ${urgency}
43+
Save durable findings to the notebook before handoff.`;
3044
}
3145

32-
// 30-50%
33-
return `Context at ${pct}% — past the primacy-zone heuristic. One context, one job.
34-
If you're mid-job and still clear, continue. If the current phase is complete
35-
or the context is noisy, consider a handoff and draft a clear brief for what
36-
comes next.`;
46+
const noTopicUrgency = pct !== null && pct >= 70
47+
? "Assign a fresh topic in the next clean context after handoff."
48+
: "Assign a short stable topic soon. If the work stays within that topic, prefer spawn for noisy subtasks. If the work shifts beyond it, prefer handoff.";
49+
return `${contextLead}
50+
No active notebook topic is set. ${noTopicUrgency}`;
3751
}
3852

3953
/**

0 commit comments

Comments
 (0)