Skip to content

Commit 62d23ff

Browse files
joshwilhelmiclaude
andcommitted
[gobby-cli-#467] feat: echo all five research budget limits in JSON
gwiki research --format json echoed only max_steps/max_tokens/max_sources; the spec requires every enforced budget to be visible. Promote the hardcoded 900s wall-time / 24000-byte note budgets to named constants (RESEARCH_MAX_WALL_TIME_SECONDS, RESEARCH_MAX_NOTE_BYTES), add max_wall_time_seconds and max_note_bytes to ResearchOutcome and the ResearchOutput JSON struct, and add both keys to contract.rs json_output_keys. Regenerated the pinned crates/gwiki/contract/gwiki.contract.json. cargo fmt --check, clippy -D warnings, and cargo test -p gobby-wiki (contract_builder_matches_pinned_json + contract_command_emits_pinned_json) pass. Companion to gobby epic #15586 / M6 #15592. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent da9bcd8 commit 62d23ff

4 files changed

Lines changed: 20 additions & 2 deletions

File tree

crates/gwiki/contract/gwiki.contract.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@
483483
"max_steps",
484484
"max_tokens",
485485
"max_sources",
486+
"max_wall_time_seconds",
487+
"max_note_bytes",
486488
"write_conflict",
487489
"sources_added",
488490
"accepted_notes",

crates/gwiki/src/commands/research.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct ResearchOutput {
1414
max_steps: usize,
1515
max_tokens: usize,
1616
max_sources: usize,
17+
max_wall_time_seconds: u64,
18+
max_note_bytes: usize,
1719
write_conflict: bool,
1820
sources_added: Vec<String>,
1921
accepted_notes: Vec<crate::session::AcceptedResearchNote>,
@@ -40,6 +42,8 @@ pub(crate) fn execute(options: research::ResearchOptions) -> Result<CommandOutco
4042
max_steps: outcome.max_steps,
4143
max_tokens: outcome.max_tokens,
4244
max_sources: outcome.max_sources,
45+
max_wall_time_seconds: outcome.max_wall_time_seconds,
46+
max_note_bytes: outcome.max_note_bytes,
4347
write_conflict: outcome.write_conflict,
4448
sources_added: outcome.sources_added,
4549
accepted_notes: outcome.session.accepted_notes,

crates/gwiki/src/contract.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ pub fn contract() -> CliContract {
175175
"max_steps",
176176
"max_tokens",
177177
"max_sources",
178+
"max_wall_time_seconds",
179+
"max_note_bytes",
178180
"write_conflict",
179181
"sources_added",
180182
"accepted_notes",

crates/gwiki/src/research.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ use crate::session::{AcceptedResearchNote, ResearchScope, ResearchSession, resea
2424
use crate::{CommandOutcome, IngestFileOptions, ReadTarget, ScopeSelection, WikiError};
2525

2626
const MAX_RESEARCH_NOTE_SUFFIX_ATTEMPTS: usize = 1000;
27+
/// Enforced research-loop budgets, echoed in JSON output so callers see every
28+
/// limit that can stop a run.
29+
const RESEARCH_MAX_WALL_TIME_SECONDS: u64 = 900;
30+
const RESEARCH_MAX_NOTE_BYTES: usize = 24_000;
2731
const RESEARCH_NOTE_MARKER_STALE_AFTER: Duration = Duration::from_secs(15 * 60);
2832
const RESEARCH_NOTE_MATERIALIZE_TIMEOUT: Duration = Duration::from_secs(10);
2933
const RESEARCH_NOTE_MATERIALIZE_INITIAL_DELAY: Duration = Duration::from_millis(25);
@@ -90,6 +94,8 @@ pub struct ResearchOutcome {
9094
pub max_steps: usize,
9195
pub max_tokens: usize,
9296
pub max_sources: usize,
97+
pub max_wall_time_seconds: u64,
98+
pub max_note_bytes: usize,
9399
pub write_conflict: bool,
94100
pub sources_added: Vec<String>,
95101
pub findings: Vec<AuditFinding>,
@@ -210,6 +216,8 @@ pub fn run(options: ResearchOptions) -> Result<ResearchOutcome, WikiError> {
210216
max_steps: options.max_steps,
211217
max_tokens: options.max_tokens,
212218
max_sources: options.max_sources,
219+
max_wall_time_seconds: RESEARCH_MAX_WALL_TIME_SECONDS,
220+
max_note_bytes: RESEARCH_MAX_NOTE_BYTES,
213221
write_conflict: loop_result.write_conflict,
214222
sources_added: loop_result.sources_added,
215223
findings: Vec::new(),
@@ -247,6 +255,8 @@ pub fn run(options: ResearchOptions) -> Result<ResearchOutcome, WikiError> {
247255
max_steps: options.max_steps,
248256
max_tokens: options.max_tokens,
249257
max_sources: options.max_sources,
258+
max_wall_time_seconds: RESEARCH_MAX_WALL_TIME_SECONDS,
259+
max_note_bytes: RESEARCH_MAX_NOTE_BYTES,
250260
write_conflict: false,
251261
sources_added: Vec::new(),
252262
findings,
@@ -290,8 +300,8 @@ fn run_enrichment_loop(
290300
max_steps: options.max_steps,
291301
max_tokens: options.max_tokens,
292302
max_sources: options.max_sources,
293-
max_wall_time: Duration::from_secs(900),
294-
max_note_bytes: 24_000,
303+
max_wall_time: Duration::from_secs(RESEARCH_MAX_WALL_TIME_SECONDS),
304+
max_note_bytes: RESEARCH_MAX_NOTE_BYTES,
295305
},
296306
ResearchLoopDeps {
297307
model: &mut model,

0 commit comments

Comments
 (0)