Problem
The AttackGen Assistant (pages/4_π¬_AttackGen_Assistant.py) refines the scenario and β since #44 / #57 β the Detection & Response narrative, but its edits live only in the chat history. The downloadable files offered on the scenario pages (the scenario .md, the Detection & Response .md) always reflect the originally generated content, so a user who refines an output in the Assistant can't download the refined version β they'd have to copy text out of the chat by hand.
This is the "flow-back" nice-to-have explicitly deferred in #44:
Consider letting edits flow back so the updated narrative can be re-downloaded (nice-to-have; the current Assistant doesn't persist edits back to the source page either).
Why (current behaviour)
Downloads are built on the scenario pages from persisted session state (core/scenario_page.py):
- Scenario markdown β
st.download_button(..., data=cleaned, ...) (~scenario_page.py:362)
- Detection & Response
.md β data=defense_state["download_md"] (~scenario_page.py:454), where download_md = assemble_defense_document(deterministic_md, narrative_md, title=...) (scenario_page.py:286).
The Assistant only reads the cross-page handoff keys (last_scenario_text, last_defense_narrative) and appends model replies to assistant_messages_<target>. Nothing is ever written back to last_scenario_text, the narrative_md / download_md in f"{page_id}_scenario_defense", or the per-page text_key the download button reads.
Desired behaviour
After refining in the Assistant, the user can download the refined scenario and/or Detection & Response narrative. Covers all three Assistant modes: Scenario, Detection & Response, and Scenario + Detection & Response (the combined mode β one "apply" should update both consistently).
Sketch of the work
Two viable shapes:
- Self-contained (recommended, most contained): add download buttons on the Assistant page itself for the current, refined artifact(s). No changes needed on the scenario pages.
- Write-back: propagate the refined text into the session-state keys the scenario pages read, so returning to the scenario page shows updated downloads. Heavier β the Assistant holds the cross-page
last_* keys but not the page-scoped text_key / f"{page_id}_scenario_defense" dict, so those would need threading through the handoff.
Either way, an explicit "Apply changes" step is needed: the chat is conversational prose, not a clean document replacement, so blindly writing the last reply back won't work. A dedicated model call that returns the full revised artifact (or a fenced block the UI captures) is the reliable approach.
Constraints / considerations
- Never LLM-edit the deterministic STIX reference. The Detection & Response download is
deterministic_md + narrative_md. Only narrative_md may change; on apply, rebuild download_md = assemble_defense_document(deterministic_md, edited_narrative_md, title=...) so the deterministic join stays byte-for-byte intact.
- Signal edited vs. original (e.g. button label / filename suffix), and consider keeping the original available or confirming before overwrite.
- Combined "Both" mode should apply consistent edits to both artifacts in one action.
Context
Follow-up to #44 / #57 (Assistant editing the Detection & Response narrative) and the purple-team companion in v0.13 (#42). Builds naturally on the in-progress "Scenario + Detection & Response" combined Assistant mode.
Problem
The AttackGen Assistant (
pages/4_π¬_AttackGen_Assistant.py) refines the scenario and β since #44 / #57 β the Detection & Response narrative, but its edits live only in the chat history. The downloadable files offered on the scenario pages (the scenario.md, the Detection & Response.md) always reflect the originally generated content, so a user who refines an output in the Assistant can't download the refined version β they'd have to copy text out of the chat by hand.This is the "flow-back" nice-to-have explicitly deferred in #44:
Why (current behaviour)
Downloads are built on the scenario pages from persisted session state (
core/scenario_page.py):st.download_button(..., data=cleaned, ...)(~scenario_page.py:362).mdβdata=defense_state["download_md"](~scenario_page.py:454), wheredownload_md = assemble_defense_document(deterministic_md, narrative_md, title=...)(scenario_page.py:286).The Assistant only reads the cross-page handoff keys (
last_scenario_text,last_defense_narrative) and appends model replies toassistant_messages_<target>. Nothing is ever written back tolast_scenario_text, thenarrative_md/download_mdinf"{page_id}_scenario_defense", or the per-pagetext_keythe download button reads.Desired behaviour
After refining in the Assistant, the user can download the refined scenario and/or Detection & Response narrative. Covers all three Assistant modes: Scenario, Detection & Response, and Scenario + Detection & Response (the combined mode β one "apply" should update both consistently).
Sketch of the work
Two viable shapes:
last_*keys but not the page-scopedtext_key/f"{page_id}_scenario_defense"dict, so those would need threading through the handoff.Either way, an explicit "Apply changes" step is needed: the chat is conversational prose, not a clean document replacement, so blindly writing the last reply back won't work. A dedicated model call that returns the full revised artifact (or a fenced block the UI captures) is the reliable approach.
Constraints / considerations
deterministic_md+narrative_md. Onlynarrative_mdmay change; on apply, rebuilddownload_md = assemble_defense_document(deterministic_md, edited_narrative_md, title=...)so the deterministic join stays byte-for-byte intact.Context
Follow-up to #44 / #57 (Assistant editing the Detection & Response narrative) and the purple-team companion in v0.13 (#42). Builds naturally on the in-progress "Scenario + Detection & Response" combined Assistant mode.