You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AttackGen can generate an impressively complete incident-response exercise, but the journey from setup to generation, refinement, and return navigation is fragile.
From a user's perspective:
Required provider, model, industry, company-size, and matrix settings are configured on the Welcome page, but those controls are not present on scenario pages. When a required value is missing, the scenario page tells the user to change it "in the sidebar" even though that sidebar contains only navigation on the current page.
The Threat Group Scenarios page automatically selects the alphabetically first group. For Enterprise ATT&CK this is currently APT-C-23, which has no associated techniques, so the default experience is a dead end.
Generate remains actionable before the workflow is ready. Validation happens only after the click and may report setup fields before reporting the missing page-specific selection.
Optional AI-enhanced and purple-team controls appear after or alongside the primary action, making them easy to miss before generation starts.
Generation is a multi-stage workflow, but the UI presents it as a single 30–50 second operation. In testing, an APT29 scenario using a reasoning model and the optional purple-team narrative took roughly five minutes. The stream paused for long periods without changing while the page continued to say it was streaming.
The base scenario can be complete while the optional purple-team narrative is still running, but the useful base result is not yet treated as safely available. A slow or failed optional phase therefore blocks access to the scenario, downloads, and Assistant handoff.
A generated scenario is available to the AttackGen Assistant, but returning to the originating Threat Group Scenarios page can reset the group selector and stop rendering the scenario and its download controls. The user has no reliable "return to my result" route.
Completed scenarios are very long. The tested APT29 result contained 16 major sections, 14 injects, ATT&CK coverage, metrics, artefacts, safety rules, and a separate Detection & Response walkthrough. This is valuable content, but it lacks a compact summary and fast navigation.
The Assistant's empty state reports that no scenario exists but does not offer a direct route to start one.
Browser diagnostics repeatedly report invalid empty sidebar theme colours. Accessibility inspection also exposes icon ligature names such as keyboard_double_arrow_left and unnamed top-bar controls instead of meaningful accessible labels.
The mobile layout itself is sound: at 390×844 there was no horizontal overflow and the core content remained readable. The generated scenario quality, download set, ATT&CK Navigator export, Detection & Response content, and scenario-aware Assistant all worked well once reached.
Solution
Provide a continuous, stateful scenario workflow that guides the user through setup, clearly communicates readiness and progress, persists usable results as soon as they exist, and makes it easy to move between a scenario and the Assistant without losing work.
The solution should:
Render one shared setup experience on every app page, backed by the existing non-secret state-persistence mechanism. API keys must remain session-only and must never enter URLs.
Present a visible setup/readiness summary and disable generation until all required global and page-specific inputs are valid.
Start threat-group and case-study selectors with no selection, or only offer entries that can produce a scenario. The first visible value must never be an unusable default.
Place all generation modifiers before the primary Generate action and explain when a modifier adds another model call, cost, or waiting phase.
Model generation as explicit phases: preparing inputs, generating the base scenario, preparing deterministic exports, optionally generating the purple-team narrative, and complete or partially complete.
Persist and render the base scenario immediately after the first model stream completes. Optional enrichment must never prevent the base result, base download, ATT&CK Navigator layer, or Assistant handoff from becoming available.
Treat optional enrichment failures as degraded success. Preserve the base result, explain what failed, and offer a focused retry for only the failed enrichment.
Preserve each scenario page's latest generated result and generation metadata across Streamlit reruns and page navigation for the lifetime of the session. The Assistant should link back to the originating result, and the originating page should reliably re-render it.
Add a compact result summary and navigation surface for long scenarios, while retaining the complete Markdown render and all existing downloads.
Give empty and error states direct recovery actions instead of instructions that refer to unavailable controls.
Remove repeated theme warnings and give icon-only controls meaningful accessible names wherever the application or supported Streamlit configuration can control them.
User Stories
As a new user, I want to see which setup values are required, so that I understand what must be completed before generating a scenario.
As a returning user, I want my non-secret provider, model, matrix, industry, and company-size choices restored, so that I do not repeat setup after navigation or refresh.
As a security-conscious user, I want API keys excluded from URLs and browser history, so that setup persistence does not expose credentials.
As a user on any scenario page, I want access to the same setup controls, so that an error never sends me to a sidebar that lacks the referenced setting.
As a user with an incomplete setup, I want a concise readiness summary listing every missing requirement, so that I can resolve all blockers in one pass.
As a user with an incomplete setup, I want Generate disabled, so that I do not spend a click discovering predictable validation errors.
As a user correcting setup, I want the readiness summary and Generate state to update immediately, so that I know when the workflow is ready.
As a user selecting a threat group, I want the selector to begin with a neutral prompt, so that I make an intentional choice rather than unknowingly accepting an arbitrary default.
As a user selecting a threat group, I want groups without associated techniques removed or clearly marked unavailable, so that every selectable group can progress to generation.
As an ATLAS user, I want case studies without usable procedures handled consistently with ATT&CK groups, so that I do not encounter a dead-end default.
As a user searching a large group list, I want search by group name and alias to remain available, so that the safer neutral default does not make selection cumbersome.
As a custom-scenario user, I want Generate disabled until at least one technique is selected, so that missing-technique validation is visible before submission.
As an AI Insider Threat user, I want required threat categories distinguished from optional STRIDE threats and capabilities, so that the form's minimum valid state is obvious.
As a user, I want AI-enhanced and purple-team options shown before Generate, so that I can make the choice before starting the request.
As a cost-conscious user, I want the purple-team option to state that it adds a second model call, so that I understand the additional time and provider usage.
As a user starting generation, I want confirmation of the selected matrix, organisation profile, threat group or techniques, and modifiers, so that I can catch an incorrect configuration before provider usage begins.
As a user waiting for generation, I want to see the current phase and elapsed time, so that I can distinguish active work from a stalled request.
As a user waiting for streamed output, I want the page to show content as it arrives and keep the active status near the visible result, so that long generations feel responsive.
As a user of a reasoning model, I want duration messaging that acknowledges multi-minute runs, so that the app does not set an expectation it routinely misses.
As a user generating a purple-team narrative, I want to see that the base scenario is complete before the optional enrichment begins, so that I understand what remains.
As a user whose base scenario has completed, I want the scenario and base downloads available immediately, so that optional enrichment cannot hold my work hostage.
As a user whose optional enrichment stalls, I want to skip or stop only that phase, so that the completed base scenario remains usable.
As a user whose optional enrichment fails, I want a clear degraded-success message and a Retry enrichment action, so that I do not regenerate the entire scenario.
As a user whose base generation fails before producing usable output, I want the error associated with the base phase and a retry action that preserves my inputs.
As a user who navigates to the Assistant, I want the originating scenario and its metadata preserved, so that the Assistant has the correct context.
As a user returning from the Assistant, I want a direct Back to scenario action, so that I can resume reading and downloading the same result.
As a user returning to a scenario page through the main navigation, I want the latest generated result to reappear, so that navigation never makes completed work seem lost.
As a user with results from more than one scenario type, I want each page to retain its own latest result, so that generating a custom scenario does not overwrite a threat-group result.
As a user viewing a previous result, I want the selected group, matrix, organisation profile, modifiers, technique set, and generation time shown with it, so that I can tell what produced the output.
As a user changing inputs after generation, I want the app to distinguish the displayed result's captured inputs from the currently edited form, so that old output is not misrepresented as matching new selections.
As a user who has changed inputs, I want the previous result to remain available until I explicitly regenerate or clear it, so that editing the form does not destroy work.
As a user reading a long scenario, I want an executive summary and section navigation, so that I can orient myself without scrolling through the entire document.
As an exercise facilitator, I want quick access to injects, success criteria, metrics, artefacts, and rules of engagement, so that I can use the output operationally.
As a SOC practitioner, I want the Scenario and Detection & Response outputs kept as distinct views, so that attack narrative and defensive guidance remain easy to navigate.
As a user, I want a persistent result action area with Assistant, scenario download, Navigator layer, Detection & Response download, regenerate, and clear actions, so that the main next steps are easy to find.
As a user opening the Assistant without a scenario, I want direct actions to create a threat-group, custom, or AI insider scenario, so that the empty state becomes a useful starting point.
As a user in the Assistant, I want the scenario identity visible, so that I know which result the chat is using.
As a keyboard or screen-reader user, I want icon-only controls to have meaningful names such as Expand sidebar, Collapse sidebar, Send message, and Open menu, so that their purpose is understandable.
As a keyboard user, I want every form control and action reachable in a logical order with a visible focus state, so that the workflow is operable without a pointer.
As a mobile user, I want setup, generation status, long results, tabs, and result actions to fit without horizontal scrolling, so that the complete workflow remains usable on a narrow screen.
As a developer diagnosing the app, I want a clean browser console during normal use, so that real warnings and failures are not buried by repeated theme messages.
As a user, I want feedback controls to remain attached to the scenario I am rating, so that navigating or regenerating cannot submit feedback for the wrong result.
As a user downloading artefacts, I want filenames and their captured content to remain stable across reruns and navigation, so that all files from one generation can be identified as a set.
As a user, I want clearing a scenario to require an explicit action and leave global setup intact, so that I can start a new scenario without reconfiguring the provider.
As a user refreshing a deep-linked scenario page, I want non-secret setup restored and a clear explanation if generated content was session-only and is no longer available, so that refresh behaviour is predictable.
Implementation Decisions
Use the existing shared scenario-page coordinator as the primary workflow seam. Scenario pages continue to own their domain-specific widgets, data selection, prompt construction, and readiness requirements; the coordinator owns lifecycle, persistence, progress, result rendering, retries, downloads, and cross-page handoff.
Add one shared setup-sidebar renderer used by Welcome and every functional page. It owns provider, model, credential input, matrix, industry, and company-size presentation while continuing to write the existing shadow state.
Keep the existing query-parameter persistence contract for non-secret setup values. API keys, generated scenario text, chat history, and generated artefacts remain excluded from query parameters.
Represent readiness as data rather than side effects. Each scenario page supplies its page-specific requirements to a shared readiness summary, and the coordinator derives the disabled state and visible list of blockers before any model call.
Use neutral selector defaults. Threat groups and ATLAS case studies must not use the first sorted item as an implicit choice. Entries that cannot produce techniques should be filtered out before presentation or explicitly disabled with a reason.
Capture a generation input snapshot when Generate is pressed. It includes scenario type, matrix, organisation profile, selected entity or techniques, modifiers, the sampled technique set, and human-readable identity metadata. Rendering and downloads use this captured snapshot rather than mutable current widgets.
Keep page-scoped result namespaces so threat-group, custom, and AI insider results can coexist. Maintain a separate latest-result pointer for the Assistant and global navigation.
Split the lifecycle into externally observable phases: ready, generating base scenario, base scenario available, building deterministic artefacts, generating optional defense narrative, complete, degraded complete, and failed.
Persist the cleaned base scenario, filename, Navigator layer, deterministic Detection & Response report, input snapshot, and Assistant handoff immediately after the base stream completes. Do not wait for the optional narrative call.
Run the optional narrative as an enrichment of an already persisted result. Store its status independently and merge it into the Detection & Response view and download when complete.
If optional enrichment fails or is stopped, retain the base scenario and deterministic defense reference. Expose Retry purple-team narrative without re-running the base scenario.
Keep the current deterministic ATT&CK/ATLAS joins authoritative. The model-generated purple-team narrative may explain supplied detections and mitigations, but it must not replace the deterministic reference.
Replace the single duration promise with phase-aware language. Show elapsed time during active phases and describe purple-team mode as a second model call that may make the full workflow take several minutes.
Preserve the existing Scenario and Detection & Response tabs. Add a compact summary and section-navigation surface above the full result rather than truncating or rewriting the generated Markdown.
Put result actions in one consistent location. The action area includes Open in Assistant, Back to this scenario when in the Assistant, downloads, regenerate, retry failed enrichment, and clear result.
The Assistant empty state links to all three generation entry points. When a result exists, the Assistant shows the scenario identity and originating page.
Remove or explicitly configure any sidebar theme values that resolve to empty strings, and verify the supported configuration against the pinned Streamlit version. If an upstream Streamlit bug causes the warnings, upgrade or pin to a version that does not emit them before adding application workarounds.
Add explicit accessible labels to application-owned icon controls. For Streamlit-owned chrome, prefer supported configuration or a Streamlit upgrade over brittle DOM/CSS patches.
Preserve the current responsive layout and use progressive disclosure for setup and long result navigation on narrow screens.
Testing Decisions
A good test asserts externally observable workflow behaviour: whether generation can start, what is persisted, which phase is visible, which result and downloads remain available, and what happens after navigation or failure. Tests should not assert private helper call order, CSS class names, or Streamlit's internal DOM structure.
Use the existing scenario-page coordinator test seam as the highest-level automated seam for generation behaviour. Continue stubbing Streamlit presentation and controlling the model stream, but assert the public coordinator contract and session-state/result outputs.
Extend the existing scenario coordinator tests to cover: disabled/not-ready behaviour; captured input metadata; base result persistence before optional enrichment; two-phase progress; optional narrative success; optional narrative error; optional narrative stop/skip; retry of enrichment without a second base call; and degraded-complete rendering.
Add a cross-navigation coordinator test that generates a threat-group scenario, simulates visiting the Assistant and returning, and verifies that the page-scoped result, captured inputs, stable filenames, Navigator layer, Detection & Response state, and result actions are still rendered.
Extend state-persistence tests around the existing query-parameter seam. Cover global setup restoration on a deep link, precedence of current session values, invalid provider or matrix values, and the invariant that API keys and generated content never reach the URL.
Test the shared setup renderer at its state contract: given persisted selections and environment-provided credentials, it exposes a complete setup; given missing required fields, it exposes all blockers without invoking a model.
Test threat-group option preparation against the shipped Enterprise and ICS group data. Every enabled option must resolve to at least one associated technique; the selector must have no implicit first selection.
Test ATLAS option preparation against the shipped case-study data. Every enabled case study must have a usable procedure and extracted technique set.
Parameterise readiness tests across threat-group, custom, and AI insider pages so global requirements behave consistently while page-specific requirements remain distinct.
Use controllable streaming fixtures that can yield chunks, pause, raise, or complete. Verify that partial text is visible during streaming, elapsed status remains phase-correct, and a stalled optional phase does not revoke the base result.
Retain existing tests for response cleaning, namespaced state, stable filenames, Navigator downloads, deterministic defense output, and Assistant handoff. Build on those tests rather than creating a parallel persistence mechanism.
Add an Assistant workflow test that verifies the empty-state generation links, scenario identity, scenario-context handoff, and Back to scenario route. Do not test model wording; assert only that the captured scenario and user message reach the Assistant model seam and that the streamed response is retained.
Add one end-to-end Streamlit smoke journey using a deterministic fake LLM: complete setup, select a usable group, enable purple-team mode, generate, observe both phases, open the Assistant, return, and download all available artefacts. This is the acceptance test for the navigation and persistence bug found during manual testing.
Add a narrow-viewport smoke check at approximately 390×844 that asserts no horizontal document overflow and that setup, Generate, phase status, result tabs, and result actions remain reachable.
Add an accessibility smoke check for application-owned controls: meaningful accessible names, unique form labels, logical keyboard order, and visible focus. Avoid assertions against generated Streamlit class names.
Add a browser-console smoke check that loads Welcome and one scenario page and fails on unexpected application warnings or errors. Allowlist only explicitly documented upstream messages; the repeated empty sidebar-colour warnings must not remain silently allowlisted.
Manual acceptance should repeat the tested representative journey: Enterprise, Finance/Banking, medium organisation, APT29, purple-team narrative, followed by a scenario-aware Assistant question and return navigation.
Out of Scope
Changing the substantive scenario-generation prompts or evaluating the cybersecurity quality of model output.
Redesigning the deterministic Detection & Response data model, MITRE ATT&CK/ATLAS datasets, or Navigator layer format.
Persisting generated scenarios across browser sessions, devices, server restarts, or multiple users. This specification covers the lifetime of the current Streamlit session.
Adding authentication, authorisation, shared workspaces, or organisation-level scenario history.
Replacing Streamlit or redesigning the entire visual identity.
Guaranteeing provider-side generation latency. The work improves progress, phase isolation, timeouts, retry, and recovery; it does not promise faster model inference.
Adding new LLM providers, models, MITRE matrices, scenario types, or export formats.
Automatically rating, scoring, or rewriting generated scenario content.
Creating a full document-management system for saved scenarios.
Further Notes
Manual testing was performed locally at localhost:8501 on desktop and a 390×844 viewport.
The representative end-to-end run used OpenAI API, gpt-5.6-sol, Enterprise ATT&CK, Finance/Banking, a medium organisation, APT29, and the optional purple-team narrative.
The base scenario was high quality and included 16 major sections, 14 injects, ATT&CK coverage, success criteria, metrics, artefacts, safety rules, post-exercise review, Markdown download, Navigator layer, and deterministic Detection & Response content.
The scenario-aware Assistant successfully retained the generated scenario and answered a targeted question. The failure appeared when returning to the originating page, where the selector reset and the result/download UI no longer rendered.
The current architecture already has useful persistence and testing foundations: non-secret query-parameter shadows, page-scoped result keys, a latest-scenario Assistant handoff, and a shared scenario lifecycle coordinator. This specification should strengthen those seams rather than replace them.
The requested ready-for-agent triage label does not currently exist in the repository's label vocabulary. The repository currently exposes the standard labels bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, and wontfix.
Problem Statement
AttackGen can generate an impressively complete incident-response exercise, but the journey from setup to generation, refinement, and return navigation is fragile.
From a user's perspective:
keyboard_double_arrow_leftand unnamed top-bar controls instead of meaningful accessible labels.The mobile layout itself is sound: at 390×844 there was no horizontal overflow and the core content remained readable. The generated scenario quality, download set, ATT&CK Navigator export, Detection & Response content, and scenario-aware Assistant all worked well once reached.
Solution
Provide a continuous, stateful scenario workflow that guides the user through setup, clearly communicates readiness and progress, persists usable results as soon as they exist, and makes it easy to move between a scenario and the Assistant without losing work.
The solution should:
User Stories
Implementation Decisions
Testing Decisions
Out of Scope
Further Notes
localhost:8501on desktop and a 390×844 viewport.gpt-5.6-sol, Enterprise ATT&CK, Finance/Banking, a medium organisation, APT29, and the optional purple-team narrative.ready-for-agenttriage label does not currently exist in the repository's label vocabulary. The repository currently exposes the standard labelsbug,documentation,duplicate,enhancement,good first issue,help wanted,invalid,question, andwontfix.