Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/generate-guidance.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ describe("canonical guidance generation", () => {
}
expect(GUIDANCE_CUES.rebaseCheck).toContain("Active summarized history is present");
expect(GUIDANCE_CUES.rebaseCheck).toContain("structural reset and cold start");
expect(GUIDANCE_CUES.rebaseCheck).toContain("cold-start test passes");
expect(GUIDANCE_CUES.timelineActive).toContain("`active`");
expect(GUIDANCE_CUES.timelineCheckpoints).toContain("`checkpoints`");
expect(GUIDANCE_CUES.timelineSearch).toContain("`search`");
Expand Down
84 changes: 58 additions & 26 deletions skills/context-management/CORE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion skills/context-management/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Resolve advanced ACM cases: ambiguous earliest-safe-base selection

# Advanced Context Management

The always-on **CORE owns the normal path**: ordinary checkpointing, clear phase folds, clear burst folds, pressure checks, task-end handling, and an obvious rebase all stay there. This Skill resolves one advanced condition at a time.
The always-on **CORE owns the normal path**: the working-set invariant, judgment layers, decision smells, recognizable moments, fold and rebase criteria, ordinary checkpointing, clear phase folds, clear burst folds, rebase checks under pressure, task-end handling, and an obvious rebase all stay there. This Skill resolves one advanced condition at a time when CORE's criteria pass but the decision remains ambiguous or a result reports an exceptional outcome.

Select the reference whose observable condition is active:

Expand Down
2 changes: 1 addition & 1 deletion src/checkpoint-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function registerCheckpointTool(pi: ExtensionAPI): void {
description: TOOL_DESCRIPTIONS.checkpoint,
promptSnippet: "Label a recoverable session boundary without changing context",
promptGuidelines: [
"Use acm_checkpoint to preflight each distinct user goal before managed work and to label later phase, burst, pause, milestone, or completion boundaries.",
"Use acm_checkpoint to preflight each distinct user goal before managed work makes rewind expensive, and to label later phase, burst, pause, milestone, or completion boundaries.",
],
parameters: schema,
renderShell: "self",
Expand Down
12 changes: 6 additions & 6 deletions src/context-usage-nudge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,17 @@ export function buildContextUsageNudgeMessage(nudge: PendingContextUsageNudge):

const guidance = nudge.level === 30
? [
"Continue the current work normally. At the next natural semantic boundary, consider whether current task requirements permit a safe fold or rebase travel.",
"Travel is optional, but keeping the active context small is preferred when it can be done without losing needed working state.",
"Continue the current work normally. At the next natural semantic boundary, check decision smells and whether fold criteria can pass against the working-set invariant.",
"Prefer a smaller active working set when a complete handoff can preserve needed state and make NEXT executable; otherwise keep required detail live.",
]
: nudge.level === 50
? [
"Context pressure is becoming material. Based on the current task requirements, actively look for the next safe opportunity for a fold or rebase travel.",
"Travel is recommended when a complete handoff can preserve the required working state and make NEXT executable. Do not travel if important context is still needed, but prefer returning to a smaller active context when safely possible.",
"Context pressure is becoming material. Raise the priority of a rebase check, and look for the next recognizable moment where fold criteria and cold start can pass.",
"Travel earns its place only when the handoff preserves required working state and makes NEXT executable. Prefer restoring a smaller working set when those criteria hold.",
]
: [
"Context pressure is high. At the earliest safe semantic boundary, strongly consider a fold or rebase travel if current task requirements allow a complete and recoverable handoff.",
"Keeping the active context small is strongly preferred, but correctness, task continuity, and recoverability take priority. If no safe travel is available, continue normally; native compaction is acceptable for a genuinely long task.",
"Context pressure is high. At the earliest safe semantic boundary, prefer a fold or rebase when fold criteria and cold start pass.",
"Correctness, task continuity, recoverability, and cold start outrank pressure. If no safe transition is available, continue with required detail live; native compaction is acceptable for a genuinely long task.",
];

return {
Expand Down
20 changes: 10 additions & 10 deletions src/generated-guidance.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/travel-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ export function registerTravelTool(pi: ExtensionAPI, runtime: AcmSessionRuntime)
description: TOOL_DESCRIPTIONS.travel,
promptSnippet: "Fold a named boundary or rebase summaries into a recoverable handoff",
promptGuidelines: [
"Use acm_travel only when the boundary is named, NEXT is executable from the handoff, and omitted raw history remains recoverable through a direct pointer.",
"Call acm_travel alone in its assistant tool batch; never combine this context mutation with sibling tool calls.",
"Use acm_travel when fold criteria hold: the boundary is named, NEXT is executable from the handoff, and omitted raw history remains recoverable through a direct pointer.",
"Call acm_travel alone in its assistant tool batch; mixed batches are rejected before mutation.",
],
parameters: schema,
executionMode: "sequential",
Expand Down
9 changes: 6 additions & 3 deletions test/context-nudge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ describe("ACM context usage reminders", () => {
});
expect(fixture.sentMessages[0]?.message.content).toContain("[ACM Context Reminder · 30% tier]");
expect(fixture.sentMessages[0]?.message.content).toContain("next natural semantic boundary");
expect(fixture.sentMessages[0]?.message.content).toContain("Travel is optional");
expect(fixture.sentMessages[0]?.message.content).toContain("decision smells");
expect(fixture.sentMessages[0]?.message.content).toContain("fold criteria");
expect(fixture.sentMessages[0]?.message.content).toContain("working-set invariant");

fixture.setUsagePercent(35);
await fixture.emit("context", { messages: [] });
Expand Down Expand Up @@ -248,8 +250,9 @@ describe("ACM context usage reminders", () => {
},
options: { deliverAs: "followUp" },
});
expect(fixture.sentMessages[0]?.message.content).toContain("actively look for the next safe opportunity");
expect(fixture.sentMessages[0]?.message.content).toContain("Travel is recommended");
expect(fixture.sentMessages[0]?.message.content).toContain("Raise the priority of a rebase check");
expect(fixture.sentMessages[0]?.message.content).toContain("Travel earns its place only when");
expect(fixture.sentMessages[0]?.message.content).toContain("recognizable moment");
});

test("a successful travel starts a new baseline-only reminder cycle", async () => {
Expand Down
85 changes: 70 additions & 15 deletions test/guidance-quality.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,102 @@ import { ACM_CORE, GUIDANCE_CUES, TOOL_DESCRIPTIONS } from "../src/generated-gui
const skillFile = (path: string) => Bun.file(new URL(`../skills/context-management/${path}`, import.meta.url)).text();

describe("ACM guidance quality", () => {
test("preserves the base workflow while bounding semantic rebase", () => {
for (const baseBehavior of [
test("anchors normal workflow on invariant, smells, moments, and criteria", () => {
for (const situation of [
"Phase, attempt, or batch item starts",
"Unbounded burst or risky step is next",
"Findings are distilled",
"Direction is rejected or superseded",
"Final answer is next",
]) {
expect(ACM_CORE).toContain(baseBehavior);
expect(ACM_CORE).toContain(situation);
}
expect(ACM_CORE).toContain("### Working-set invariant");
expect(ACM_CORE).toContain("### How judgment layers fit together");
expect(ACM_CORE).toContain("keep live what NEXT needs");
expect(ACM_CORE).toContain("ACM keeps that growth recoverable");
expect(ACM_CORE).toContain("earns its place against this invariant");
expect(ACM_CORE).toContain("**Decision smells** prompt a pause");
expect(ACM_CORE).toContain("**Failure shapes** name what went wrong and the lightest correction");
expect(ACM_CORE).toContain("### Decision smells");
expect(ACM_CORE).toContain("### Recognizable moments");
expect(ACM_CORE).toContain("When one of these situations arises");
expect(ACM_CORE).toContain("lightest transition that does");
expect(ACM_CORE).toContain("| What you can observe | What becomes reasonable |");
expect(ACM_CORE).not.toContain("| Event | Required transition |");
expect(ACM_CORE).not.toContain("| Situation | Judgment |");
expect(ACM_CORE).not.toContain("### Judgment triggers");
expect(ACM_CORE).toContain("### Fold criteria");
expect(ACM_CORE).toContain("### Rebase criteria");
expect(ACM_CORE).not.toContain("### Fold gate");
expect(ACM_CORE).toContain("### Failure shapes");
expect(ACM_CORE).toContain("Before `acm_travel`, answer in one line");
expect(ACM_CORE).toContain("candidates against that boundary");
expect(ACM_CORE).toContain("compare candidates against boundary placement and cold start");
expect(ACM_CORE).toContain("Ambiguous base selection, interleaved fronts, or raw-node fallback → load the context-management skill");
expect(ACM_CORE).toContain("For archive round trips, checkpoint-name collisions, travel failure, indeterminate mutation, or exhausted context refresh → load the context-management skill");
expect(ACM_CORE).not.toContain("ambiguous bases → load");
expect(ACM_CORE).toContain("Local fold example");
expect(ACM_CORE).toContain("Finished-chain rebase example");
expect(ACM_CORE).toContain("Why: findings are distilled");
expect(ACM_CORE).toContain("Why: prior chain is stable");
expect(ACM_CORE).not.toContain("Failed-direction example");
expect(ACM_CORE).not.toContain("**NEXT stalls**");
expect(ACM_CORE).toContain("Folded too early");
expect(ACM_CORE).toContain("recover the needed detail");
expect(ACM_CORE).toContain("without rereading archived summaries");
expect(ACM_CORE).toContain("Structural reset passes only when");
expect(ACM_CORE).toContain("projected summary depth does not grow");
expect(ACM_CORE).toContain("Cold start passes only when");
expect(ACM_CORE.length).toBeLessThan(7500);
expect(ACM_CORE.length).toBeLessThan(10000);
const invariantIndex = ACM_CORE.indexOf("### Working-set invariant");
const layersIndex = ACM_CORE.indexOf("### How judgment layers fit together");
const vocabularyIndex = ACM_CORE.indexOf("### Vocabulary");
expect(invariantIndex).toBeGreaterThan(-1);
expect(layersIndex).toBeGreaterThan(invariantIndex);
expect(layersIndex).toBeLessThan(vocabularyIndex);
expect(GUIDANCE_CUES.rebaseCheck).toContain("Active summarized history is present");
expect(ACM_CORE).toContain("Call `acm_travel` alone in its assistant tool batch");
expect(TOOL_DESCRIPTIONS.travel).toContain("must run alone in its assistant tool batch");
expect(ACM_CORE).toContain("rejects mixed tool batches");
expect(TOOL_DESCRIPTIONS.travel).toContain("Mixed tool batches are rejected");
});

test("front-loads a checkable checkpoint preflight", () => {
test("front-loads recoverability preflight as a cost judgment", () => {
const invariantIndex = ACM_CORE.indexOf("### Working-set invariant");
const preflightIndex = ACM_CORE.indexOf("### ACM preflight");
const vocabularyIndex = ACM_CORE.indexOf("### Vocabulary");

expect(preflightIndex).toBeGreaterThan(-1);
expect(preflightIndex).toBeLessThan(vocabularyIndex);
expect(ACM_CORE).toContain("A distinct user goal begins with an **ACM preflight** on the branch that will carry it");
expect(ACM_CORE).toContain("First complete any required `New request arrives over finished work` transition");
expect(ACM_CORE).toContain("then call `acm_checkpoint` with a semantic `<chain>-start` name before managed work");
expect(ACM_CORE).toContain("When no finished-chain transition is required, the checkpoint call is the first action");
expect(ACM_CORE).toContain("Managed work includes investigation, planning, delegation, any non-ACM tool call");
expect(invariantIndex).toBeGreaterThan(-1);
expect(invariantIndex).toBeLessThan(vocabularyIndex);
expect(preflightIndex).toBeGreaterThan(vocabularyIndex);
expect(ACM_CORE).toContain("Tools enforce structure; you judge when a transition earns its place");
expect(ACM_CORE).toContain("Recoverability has a cost curve");
expect(ACM_CORE).toContain("begins with an **ACM preflight** on the branch that will carry it");
expect(ACM_CORE).toContain("opening a **managed chain**");
expect(ACM_CORE).toContain("call `acm_checkpoint` with a semantic `<chain>-start` name before managed work");
expect(ACM_CORE).not.toContain("the checkpoint call is the first action");
expect(ACM_CORE).toContain("investigation, planning, delegation, any non-ACM tool call");
expect(ACM_CORE).toContain("the checkpoint was created or reused");
expect(ACM_CORE).toContain("follow the recovery guidance in its result before proceeding");
expect(ACM_CORE).toContain("A text-only direct reply requiring no managed work stays outside");
expect(ACM_CORE).toContain("**lightweight reply**");
expect(ACM_CORE).toContain("live detail the next action will reason over");
expect(ACM_CORE).toContain("Name the boundary before choosing a target");
expect(ACM_CORE).toContain("without archived summaries");
expect(ACM_CORE).toContain("checkpoint its `-start` boundary before acting");
expect(ACM_CORE).toContain("checkpoint before output or side effects arrive");
expect(ACM_CORE).not.toContain("| New chain starts |");
expect(TOOL_DESCRIPTIONS.checkpoint.startsWith("Preflight a distinct user goal")).toBe(true);
expect(TOOL_DESCRIPTIONS.checkpoint).toContain("before managed work makes rewind expensive");
expect(TOOL_DESCRIPTIONS.checkpoint.length).toBeLessThan(800);
});

test("routes one advanced condition at a time and reroutes on state change", async () => {
const skill = await skillFile("SKILL.md");
expect(skill).toContain("CORE owns the normal path");
expect(skill).toContain("working-set invariant");
expect(skill).toContain("judgment layers");
expect(skill).toContain("decision smells");
expect(skill).toContain("recognizable moments");
expect(skill).toContain("criteria pass but the decision remains ambiguous");
expect(skill).toContain("ordinary checkpointing");
expect(skill).toContain("clear phase folds");
expect(skill).toContain("clear burst folds");
Expand All @@ -79,4 +126,12 @@ describe("ACM guidance quality", () => {
expect(exceptional).toContain("Indeterminate branch mutation");
expect(exceptional).toContain("mutation may have landed");
});

test("re-anchors tool cues with observables and positive targets", () => {
expect(GUIDANCE_CUES.checkpointStart).toContain("Recoverability confirmed");
expect(GUIDANCE_CUES.checkpointStart).toContain("boundary");
expect(GUIDANCE_CUES.travelTask).toContain("handoff working set");
expect(GUIDANCE_CUES.travelTask).not.toContain("do not reintroduce");
expect(GUIDANCE_CUES.rebaseCheck).toContain("cold-start test passes");
});
});
1 change: 1 addition & 0 deletions test/tool-descriptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe("ACM tool description contract", () => {
expect(timelineTool).toContain("description: TOOL_DESCRIPTIONS.timeline");
expect(travelTool).toContain("description: TOOL_DESCRIPTIONS.travel");
expect(generatedGuidance).toContain("Preflight a distinct user goal on the branch that will carry it");
expect(generatedGuidance).toContain("before managed work makes rewind expensive");
expect(generatedGuidance).toContain("Names are unique across the session tree and case-sensitive");
expect(generatedGuidance).toContain("Omitting target labels the nearest meaningful USER/AI turn");
expect(generatedGuidance).toContain("without branching or folding the active context");
Expand Down