JacobLinCool Codex commited on
Commit
caed1d4
·
verified ·
1 Parent(s): 7575503

fix: invalidate stale plans on context changes

Browse files

Co-authored-by: Codex <noreply@openai.com>

hackathon_advisor/agent.py CHANGED
@@ -355,6 +355,7 @@ class AdvisorEngine:
355
  field = str(call.arguments["field"])
356
  profile[field] = str(call.arguments["value"])
357
  state["profile"] = profile
 
358
  tool_events.append(ToolEvent("update_profile", f"Remembered {field}."))
359
  response = f"Profile updated: {field} = {profile[field]}."
360
  return self._result(normalized, corrections, response, state, tool_events, [], [], None, [], {})
@@ -369,6 +370,7 @@ class AdvisorEngine:
369
  ) -> TurnResult:
370
  goals = normalize_goals(call.arguments.get("goals"), default=[])
371
  state["goals"] = goals
 
372
  idea = self._current_idea(state)
373
  if idea is not None:
374
  idea.goals = goals
 
355
  field = str(call.arguments["field"])
356
  profile[field] = str(call.arguments["value"])
357
  state["profile"] = profile
358
+ state.pop("last_plan", None)
359
  tool_events.append(ToolEvent("update_profile", f"Remembered {field}."))
360
  response = f"Profile updated: {field} = {profile[field]}."
361
  return self._result(normalized, corrections, response, state, tool_events, [], [], None, [], {})
 
370
  ) -> TurnResult:
371
  goals = normalize_goals(call.arguments.get("goals"), default=[])
372
  state["goals"] = goals
373
+ state.pop("last_plan", None)
374
  idea = self._current_idea(state)
375
  if idea is not None:
376
  idea.goals = goals
static/app.js CHANGED
@@ -616,6 +616,10 @@ function handleEvent(event) {
616
  renderScore(event.score);
617
  ink.classList.toggle("bleed", event.score.verdict.startsWith("ECHO"));
618
  ink.classList.toggle("gold", event.score.verdict.startsWith("UNWRITTEN"));
 
 
 
 
619
  }
620
  if (event.artifact?.title) {
621
  currentArtifact = event.artifact;
 
616
  renderScore(event.score);
617
  ink.classList.toggle("bleed", event.score.verdict.startsWith("ECHO"));
618
  ink.classList.toggle("gold", event.score.verdict.startsWith("UNWRITTEN"));
619
+ } else if (!event.projects?.length) {
620
+ const idea = currentIdea();
621
+ renderSelectedIdeaSeal(idea);
622
+ renderSelectedIdeaArtifact(idea || {});
623
  }
624
  if (event.artifact?.title) {
625
  currentArtifact = event.artifact;
tests/test_agent.py CHANGED
@@ -181,11 +181,14 @@ def test_planner_get_project_drives_project_response() -> None:
181
 
182
  def test_planner_profile_and_goals_update_state() -> None:
183
  index = ProjectIndex.from_files(Path("data/projects.json"), Path("data/project_index.json"))
 
 
 
184
  profile_engine = AdvisorEngine(
185
  index,
186
  planner=StaticPlanner(ToolCall("update_profile", {"field": "skills", "value": "frontend"})),
187
  )
188
- profile = profile_engine.turn("remember this", {})
189
  target_engine = AdvisorEngine(
190
  index,
191
  planner=StaticPlanner(ToolCall("set_goals", {"goals": ["Off the Grid", "Field Notes"]})),
@@ -194,12 +197,16 @@ def test_planner_profile_and_goals_update_state() -> None:
194
 
195
  assert targeted.state["profile"]["skills"] == "frontend"
196
  assert targeted.state["goals"] == ["Off the Grid", "Field Notes"]
 
 
197
  assert "Local-first, Build notes" in targeted.response
198
 
199
 
200
  def test_goal_update_invalidates_current_idea_artifact() -> None:
201
  index = ProjectIndex.from_files(Path("data/projects.json"), Path("data/project_index.json"))
202
  first = AdvisorEngine(index).turn("A local-first archive cartographer for family photos", {})
 
 
203
  target_engine = AdvisorEngine(
204
  index,
205
  planner=StaticPlanner(ToolCall("set_goals", {"goals": ["Field Notes"]})),
@@ -211,6 +218,7 @@ def test_goal_update_invalidates_current_idea_artifact() -> None:
211
  assert idea["score"] is None
212
  assert idea["artifact"] is None
213
  assert "last_artifact" not in targeted.state
 
214
 
215
 
216
  def test_session_goals_apply_to_new_and_current_ideas() -> None:
 
181
 
182
  def test_planner_profile_and_goals_update_state() -> None:
183
  index = ProjectIndex.from_files(Path("data/projects.json"), Path("data/project_index.json"))
184
+ planned = AdvisorEngine(index).turn("A local-first archive cartographer for family photos", {})
185
+ planned = AdvisorEngine(index).turn("make a build plan", planned.state)
186
+ assert planned.state["last_plan"]
187
  profile_engine = AdvisorEngine(
188
  index,
189
  planner=StaticPlanner(ToolCall("update_profile", {"field": "skills", "value": "frontend"})),
190
  )
191
+ profile = profile_engine.turn("remember this", planned.state)
192
  target_engine = AdvisorEngine(
193
  index,
194
  planner=StaticPlanner(ToolCall("set_goals", {"goals": ["Off the Grid", "Field Notes"]})),
 
197
 
198
  assert targeted.state["profile"]["skills"] == "frontend"
199
  assert targeted.state["goals"] == ["Off the Grid", "Field Notes"]
200
+ assert "last_plan" not in profile.state
201
+ assert "last_plan" not in targeted.state
202
  assert "Local-first, Build notes" in targeted.response
203
 
204
 
205
  def test_goal_update_invalidates_current_idea_artifact() -> None:
206
  index = ProjectIndex.from_files(Path("data/projects.json"), Path("data/project_index.json"))
207
  first = AdvisorEngine(index).turn("A local-first archive cartographer for family photos", {})
208
+ first = AdvisorEngine(index).turn("make a build plan", first.state)
209
+ assert first.state["last_plan"]
210
  target_engine = AdvisorEngine(
211
  index,
212
  planner=StaticPlanner(ToolCall("set_goals", {"goals": ["Field Notes"]})),
 
218
  assert idea["score"] is None
219
  assert idea["artifact"] is None
220
  assert "last_artifact" not in targeted.state
221
+ assert "last_plan" not in targeted.state
222
 
223
 
224
  def test_session_goals_apply_to_new_and_current_ideas() -> None: