use crate::brain::agent::service::AgentService;
use crate::brain::agent::service::context::parse_context_manifest;
use crate::brain::agent::service::request_budget::{
COMPACTION_SUMMARY_MAX_TOKENS, COMPACTION_SUMMARY_REASONING_HEADROOM_TOKENS,
compaction_summary_input_reserve, compaction_summary_output_tokens,
compaction_summary_request_allowance,
};
use tracing_subscriber::Layer;
use tracing_subscriber::layer::SubscriberExt;
#[test]
fn the_input_reserve_covers_the_output_allowance() {
let reserve = compaction_summary_input_reserve();
let allowance = compaction_summary_request_allowance() as usize;
assert!(
reserve > allowance,
"input reserve ({reserve}) must exceed the summariser's output allowance \
({allowance}): a reserve smaller than the allowance hands the summariser \
more input than the context window can hold (#1930)"
);
assert!(
allowance > compaction_summary_output_tokens() as usize,
"the request allowance ({allowance}) must exceed the document budget \
({}): equal values are exactly what cut the document at source (#1933)",
compaction_summary_output_tokens()
);
}
#[test]
fn the_reserve_is_derived_from_the_one_constant() {
assert_eq!(
compaction_summary_output_tokens(),
COMPACTION_SUMMARY_MAX_TOKENS,
"the DOCUMENT budget must BE the shared constant"
);
assert_eq!(
compaction_summary_request_allowance(),
COMPACTION_SUMMARY_MAX_TOKENS + COMPACTION_SUMMARY_REASONING_HEADROOM_TOKENS,
"the request allowance must be the document budget plus the reasoning headroom (#1933)"
);
let headroom =
compaction_summary_input_reserve() - compaction_summary_request_allowance() as usize;
assert_eq!(
headroom, 1_000,
"the reserve must be the request allowance plus the prompt headroom"
);
}
#[test]
fn both_call_sites_derive_from_the_constant() {
let context_src = include_str!("../brain/agent/service/context.rs");
let compaction_src = include_str!("../brain/agent/service/compaction.rs");
assert!(
context_src.contains("compaction_summary_input_reserve()"),
"context.rs must size the input budget from the shared reserve helper"
);
assert!(
!context_src.contains("8_000usize"),
"context.rs must not carry a hard-coded output reserve literal (#1930)"
);
assert!(
context_src.contains("compaction_summary_request_allowance()"),
"the manual /compact call site must pass the shared REQUEST allowance (#1933)"
);
assert!(
compaction_src.contains("compaction_summary_request_allowance()"),
"the background compaction call site must pass the shared REQUEST allowance (#1933)"
);
assert!(
context_src.contains("compaction_summary_output_tokens()"),
"the trim guard must keep trimming to the DOCUMENT budget (#1933)"
);
}
#[test]
fn the_rendered_directive_states_the_budget_and_the_retention_order() {
let directive = AgentService::compaction_budget_directive(COMPACTION_SUMMARY_MAX_TOKENS);
assert!(
directive.contains(&COMPACTION_SUMMARY_MAX_TOKENS.to_string()),
"the directive must state the token budget it enforces; got: {directive}"
);
assert!(
directive.contains("context-manifest"),
"the directive must name the mandatory context-manifest fence as a MUST-keep block"
);
assert!(
directive.contains("FIRST TO GO"),
"the directive must name what is dropped first when the budget is tight"
);
for block in ["section 0", "section 8", "section 7"] {
assert!(
directive.contains(block),
"the directive must name {block} among the MUST-keep blocks; got: {directive}"
);
}
}
#[test]
fn the_prompt_no_longer_orders_maximum_verbosity() {
let system_prompt = AgentService::compaction_system_prompt();
assert!(
!system_prompt.contains("verbose"),
"the summariser system prompt must not invite verbosity (#1930): {system_prompt}"
);
let context_src = include_str!("../brain/agent/service/context.rs");
assert!(
!context_src.contains("BE EXHAUSTIVE"),
"the continuation-document prompt must not order maximum size (#1930)"
);
}
const TIGHT_BUDGET: usize = 1_000;
fn oversized_summary() -> String {
let bulk = |label: &str| {
format!(
"## {label}\n{}",
"the summariser recorded this in great detail, at length, twice over, \
with file paths, line numbers and quoted code, because it was told to be \
exhaustive and nothing ever trimmed it. "
.repeat(30)
)
};
format!(
"CRITICAL: The context window is at 91% capacity.\n\
You are creating a COMPREHENSIVE CONTINUATION DOCUMENT.\n\n\
## 0. IMMEDIATE TASK (CRITICAL — MOST IMPORTANT SECTION)\n\
**Obligation status: OPEN**\n\
CONTINUE THIS TASK: finish the trim guard. Do NOT deviate.\n\n\
{}\n{}\n{}\n{}\n{}\n{}\n\n\
## 7. Recovery Playbook\n\
Run `git log --oneline -3` and read the plan file.\n\n\
## 8. Next Step\n\
Add the guard, then commit it.\n\n\
## 9. Continuation Message\n\
Picking the guard back up right now.\n\n\
## 10. Context Manifest (MANDATORY MACHINE-READABLE BLOCK)\n\
```context-manifest\n\
active_skills:\n - opencrabs-dev/editor.md\n\
discard_skills:\n - meta-factory\n\
required_tools:\n - plan\n\
```\n",
bulk("1. Chronological Analysis"),
bulk("2. Files Modified"),
bulk("3. User Preferences & Constraints"),
bulk("4. Errors & Corrections"),
bulk("5. All User Messages"),
bulk("6. Pending Tasks"),
)
}
#[test]
fn a_trimmed_document_keeps_its_obligation_status_and_manifest_fence() {
let oversized = oversized_summary();
let before = crate::brain::tokenizer::count_tokens(&oversized);
assert!(
before > TIGHT_BUDGET,
"the fixture must actually exceed the tight budget ({before} vs {TIGHT_BUDGET}), \
or the guard is never exercised and this test proves nothing"
);
let trimmed = AgentService::enforce_summary_budget(oversized.clone(), TIGHT_BUDGET, &[]);
let after = crate::brain::tokenizer::count_tokens(&trimmed);
assert!(
after < before,
"the guard must drop content when the document is over budget ({before} -> {after})"
);
assert!(
after <= TIGHT_BUDGET,
"the trimmed document must fit the budget it was given ({after} > {TIGHT_BUDGET}):\n{trimmed}"
);
assert!(
parse_context_manifest(&trimmed).is_some(),
"the trimmed document must still carry a parseable context-manifest fence:\n{trimmed}"
);
assert!(
trimmed.to_lowercase().contains("obligation status"),
"the trimmed document must still carry the §0 obligation-status line:\n{trimmed}"
);
assert!(
!trimmed.contains("## 1. Chronological Analysis\nthe summariser recorded"),
"a bulk section's body must be dropped whole, not left in place:\n{trimmed}"
);
}
#[test]
fn a_document_within_budget_is_returned_unchanged() {
let doc = "## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev\n```\n";
let out = AgentService::enforce_summary_budget(
doc.to_string(),
COMPACTION_SUMMARY_MAX_TOKENS as usize,
&[],
);
assert_eq!(
out, doc,
"an under-budget document must pass through untouched"
);
}
#[test]
fn the_guard_keeps_the_obligation_rather_than_trim_it() {
let doc = format!(
"## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n{}\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev\n```\n",
"CONTINUE THIS TASK: keep going. ".repeat(400)
);
let out = AgentService::enforce_summary_budget(doc, 100, &[]);
assert!(
out.to_lowercase().contains("obligation status"),
"the obligation status must survive even when it alone busts the budget"
);
assert!(
parse_context_manifest(&out).is_some(),
"the manifest fence must survive even when the budget cannot be met"
);
}
#[test]
fn the_guard_runs_before_the_artifact_correction() {
let src = include_str!("../brain/agent/service/context.rs");
let fn_start = src
.find("pub(super) async fn compute_compaction_summary(")
.expect("compute_compaction_summary must exist");
let guard = src
.find("Self::enforce_summary_budget(")
.expect("compute_compaction_summary must call the budget guard (#1930)");
let correction = src
.find("Self::flag_unbacked_artifacts(summary, &snapshot_messages)")
.expect("the #482 artifact correction must still run");
assert!(
fn_start < guard,
"the guard call must live inside compute_compaction_summary"
);
assert!(
guard < correction,
"the budget guard must run BEFORE the #482 artifact correction, so a \
correction is never trimmed away (#1930)"
);
}
#[test]
fn the_prompt_emits_the_must_keep_blocks_before_the_prose() {
let src = include_str!("../brain/agent/service/context.rs");
let start = src
.find("let base_prompt = format!(")
.expect("the summariser prompt must be built in one format string");
let end = start
+ src[start..]
.find("\n );")
.expect("the prompt format string must close");
let prompt = &src[start..end];
let pos = |needle: &str| {
prompt
.find(needle)
.unwrap_or_else(|| panic!("the summariser prompt must contain {needle:?}"))
};
let s0 = pos("## 0. IMMEDIATE TASK");
let manifest = pos("## 10. Context Manifest");
let s7 = pos("## 7. Recovery Playbook");
let s8 = pos("## 8. Next Step");
let s1 = pos("## 1. Chronological Analysis");
let s6 = pos("## 6. Pending Tasks");
let s9 = pos("## 9. Continuation Message");
assert!(s0 < manifest, "§0 (the obligation) must be emitted first");
assert!(
manifest < s7 && s7 < s8,
"the must-keep blocks must be emitted 0 -> manifest -> §7 -> §8 (#1933)"
);
assert!(
s8 < s1,
"§7/§8 must precede the prose (§1-§6), so a tail cut removes only prose (#1933)"
);
assert!(
manifest < s1,
"the `context-manifest` fence must be emitted AHEAD of the prose (§1-§6): \
a tail cut of any size must not be able to remove it (#1933)"
);
assert!(s6 < s9, "§9 (the continuation message) stays last");
assert!(
!prompt.contains("At the very end"),
"§10 must no longer send the manifest to the very end of the document: \
that is the placement the MaxTokens cut removed (#1933)"
);
}
fn summary_of_round(round: usize) -> String {
let repeats = 200 + round * 200;
let bulk = "the summariser recorded this in great detail, at length, twice over, \
with file paths, line numbers and quoted code. "
.repeat(repeats);
format!(
"## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\
CONTINUE THIS TASK: keep going.\n\n\
## 1. Chronological Analysis\n{bulk}\n\n\
## 2. Files Modified\n{bulk}\n\n\
## 7. Recovery Playbook\nRun `git log --oneline -3`.\n\n\
## 8. Next Step\nCommit the guard.\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev/editor.md\n```\n"
)
}
#[test]
fn five_forced_compactions_stay_bounded() {
let budget = COMPACTION_SUMMARY_MAX_TOKENS as usize;
let ceiling = budget + budget / 10;
let mut raw_sizes = Vec::new();
let mut out_sizes = Vec::new();
for round in 0..5 {
let raw = summary_of_round(round);
let raw_tokens = crate::brain::tokenizer::count_tokens(&raw);
assert!(
raw_tokens > budget,
"round {round}: the raw document must exceed the budget \
({raw_tokens} vs {budget}), or the guard is never exercised"
);
let out = AgentService::enforce_summary_budget(raw, budget, &[]);
let out_tokens = crate::brain::tokenizer::count_tokens(&out);
assert!(
out_tokens <= ceiling,
"round {round}: the guarded document must fit budget x1.1 \
({out_tokens} > {ceiling}) — this is the #474 spiral, uncapped"
);
raw_sizes.push(raw_tokens);
out_sizes.push(out_tokens);
}
for w in raw_sizes.windows(2) {
assert!(
w[1] > w[0],
"the fixture's raw rounds must grow round over round: {raw_sizes:?}"
);
}
assert!(
!out_sizes.windows(2).all(|w| w[1] > w[0]),
"the guarded series must not grow monotonically round over round \
(pre-fix it did: {out_sizes:?})"
);
assert!(
out_sizes.iter().all(|&s| s <= ceiling),
"every guarded round must be bounded ({out_sizes:?} vs ceiling {ceiling})"
);
}
#[derive(Clone, Default)]
struct EventCapture {
events: std::sync::Arc<std::sync::Mutex<Vec<(String, String)>>>,
}
impl EventCapture {
fn warns(&self) -> Vec<String> {
self.events
.lock()
.unwrap()
.iter()
.filter(|(level, _)| level == "WARN")
.map(|(_, message)| message.clone())
.collect()
}
}
impl<S: tracing::Subscriber> Layer<S> for EventCapture {
fn on_event(
&self,
event: &tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let mut visitor = MessageVisitor::default();
event.record(&mut visitor);
self.events.lock().unwrap().push((
event.metadata().level().to_string(),
visitor.message.unwrap_or_default(),
));
}
}
#[derive(Default)]
struct MessageVisitor {
message: Option<String>,
}
impl tracing::field::Visit for MessageVisitor {
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
if field.name() == "message" {
self.message = Some(format!("{value:?}"));
}
}
}
#[test]
fn an_under_budget_document_without_a_fence_warns() {
let doc = "## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\
CONTINUE THIS TASK: it was cut before the manifest was written.\n";
let tokens = crate::brain::tokenizer::count_tokens(doc);
assert!(
tokens <= COMPACTION_SUMMARY_MAX_TOKENS as usize,
"the fixture must fit the budget ({tokens} > {}), or it takes the trim \
path and proves nothing about the early return (#1933)",
COMPACTION_SUMMARY_MAX_TOKENS
);
let capture = EventCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
let out = tracing::subscriber::with_default(subscriber, || {
AgentService::enforce_summary_budget(
doc.to_string(),
COMPACTION_SUMMARY_MAX_TOKENS as usize,
&[],
)
});
assert_eq!(
out, doc,
"an under-budget document is still returned unchanged"
);
let warns = capture.warns();
assert!(
warns.iter().any(|m| m.contains("context-manifest")),
"a fence-less under-budget document must WARN (#1933); captured: {warns:?}"
);
}
#[test]
fn a_complete_under_budget_document_does_not_warn() {
let doc = "## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\
CONTINUE THIS TASK: keep going.\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev\n```\n";
let capture = EventCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
let _out = tracing::subscriber::with_default(subscriber, || {
AgentService::enforce_summary_budget(
doc.to_string(),
COMPACTION_SUMMARY_MAX_TOKENS as usize,
&[],
)
});
assert!(
capture.warns().is_empty(),
"a complete under-budget document must not warn; captured: {:?}",
capture.warns()
);
}
#[test]
fn a_maxtokens_stop_warns_that_the_document_is_truncated() {
let usage = crate::brain::provider::TokenUsage {
output_tokens: 3_000,
reasoning_tokens: 1_842,
..Default::default()
};
let capture = EventCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
tracing::subscriber::with_default(subscriber, || {
AgentService::warn_if_summary_truncated(
Some(crate::brain::provider::StopReason::MaxTokens),
&usage,
);
});
let warns = capture.warns();
assert!(
warns
.iter()
.any(|m| m.contains("MaxTokens") && m.contains("#1933")),
"a MaxTokens stop must WARN that the document is truncated (#1933); captured: {warns:?}"
);
}
#[test]
fn an_endturn_stop_does_not_warn() {
let usage = crate::brain::provider::TokenUsage::default();
let capture = EventCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
tracing::subscriber::with_default(subscriber, || {
AgentService::warn_if_summary_truncated(
Some(crate::brain::provider::StopReason::EndTurn),
&usage,
);
});
assert!(
capture.warns().is_empty(),
"an EndTurn stop is not a truncation; captured: {:?}",
capture.warns()
);
}
fn head_protected_document() -> String {
let prose = |label: &str| {
format!(
"## {label}\n{}\n\n",
"the summariser recorded this at length. ".repeat(200)
)
};
format!(
"## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\
CONTINUE THIS TASK: keep going.\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev\n```\n\n\
## 7. Recovery Playbook\nRun `git log --oneline -3`.\n\n\
## 8. Next Step\nCommit the guard.\n\n\
{}{}{}{}{}{}\
## 9. Continuation Message\nPicking it back up.\n",
prose("1. Chronological Analysis"),
prose("2. Files Modified"),
prose("3. User Preferences & Constraints"),
prose("4. Errors & Corrections"),
prose("5. All User Messages"),
prose("6. Pending Tasks"),
)
}
fn manifest_last_document() -> String {
let prose = |label: &str| {
format!(
"## {label}\n{}\n\n",
"the summariser recorded this at length. ".repeat(200)
)
};
format!(
"## 0. IMMEDIATE TASK\n**Obligation status: OPEN**\n\
CONTINUE THIS TASK: keep going.\n\n\
## 7. Recovery Playbook\nRun `git log --oneline -3`.\n\n\
## 8. Next Step\nCommit the guard.\n\n\
{}{}{}{}{}{}\
## 9. Continuation Message\nPicking it back up.\n\n\
## 10. Context Manifest\n```context-manifest\n\
active_skills:\n - opencrabs-dev\n```\n",
prose("1. Chronological Analysis"),
prose("2. Files Modified"),
prose("3. User Preferences & Constraints"),
prose("4. Errors & Corrections"),
prose("5. All User Messages"),
prose("6. Pending Tasks"),
)
}
#[test]
fn a_maxtokens_cut_keeps_the_manifest_only_when_the_head_is_protected() {
let head = head_protected_document();
let old = manifest_last_document();
let cut = |d: &str| d[..d.len() / 2].to_string();
let cut_head = cut(&head);
let cut_old = cut(&old);
assert!(
parse_context_manifest(&cut_head).is_some(),
"a tail cut of a head-protected document must still carry the \
context-manifest fence (#1933)"
);
assert!(
cut_head.to_lowercase().contains("obligation status"),
"§0 (the obligation) must survive the same cut (#1933)"
);
assert!(
parse_context_manifest(&cut_old).is_none(),
"the control arm (manifest last) must LOSE the fence to the same cut, \
or this test cannot distinguish the two orderings"
);
}
#[test]
fn a_cut_document_surfaces_the_truncation_warn_and_keeps_its_fence() {
let doc = head_protected_document();
let cut = doc[..doc.len() / 2].to_string();
let usage = crate::brain::provider::TokenUsage {
output_tokens: 5_500,
reasoning_tokens: 0,
..Default::default()
};
let capture = EventCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
let out = tracing::subscriber::with_default(subscriber, || {
AgentService::warn_if_summary_truncated(
Some(crate::brain::provider::StopReason::MaxTokens),
&usage,
);
AgentService::enforce_summary_budget(
cut.clone(),
COMPACTION_SUMMARY_MAX_TOKENS as usize,
&[],
)
});
let warns = capture.warns();
assert!(
warns
.iter()
.any(|m| m.contains("MaxTokens") && m.contains("#1933")),
"a document cut at source must surface the truncation WARN (#1933); \
captured: {warns:?}"
);
assert!(
parse_context_manifest(&out).is_some(),
"the head-protected fence must survive both the cut and the trim:\n{out}"
);
}