@@ -227,6 +227,51 @@ let updatePaneN = (model: model, msg: paneNMsg): model => {
227227 | SetInferenceActive (active ) => {... paneN , inferenceActive : active }
228228 | UpdateMonologue (text ) => {... paneN , monologue : text }
229229 | UpdateAgency (agency ) => {... paneN , agency }
230+ | ToggleSourceFilter (source ) => {
231+ let current = paneN .filters .sources
232+ let has = current -> Array .some (s => s === source )
233+ let newSources = if has {
234+ current -> Array .filter (s => s !== source )
235+ } else {
236+ Array .concat (current , [source ])
237+ }
238+ {... paneN , filters : {... paneN .filters , sources : newSources }}
239+ }
240+ | ToggleCategoryFilter (cat ) => {
241+ let current = paneN .filters .categories
242+ let has = current -> Array .some (c => c === cat )
243+ let newCats = if has {
244+ current -> Array .filter (c => c !== cat )
245+ } else {
246+ Array .concat (current , [cat ])
247+ }
248+ {... paneN , filters : {... paneN .filters , categories : newCats }}
249+ }
250+ | TogglePhaseFilter (phase ) => {
251+ let current = paneN .filters .phases
252+ let has = current -> Array .some (p => p === phase )
253+ let newPhases = if has {
254+ current -> Array .filter (p => p !== phase )
255+ } else {
256+ Array .concat (current , [phase ])
257+ }
258+ {... paneN , filters : {... paneN .filters , phases : newPhases }}
259+ }
260+ | SetConfidenceThreshold (threshold ) =>
261+ {... paneN , filters : {... paneN .filters , confidenceThreshold : threshold }}
262+ | ToggleValidatedOnly =>
263+ {... paneN , filters : {... paneN .filters , validatedOnly : ! paneN .filters .validatedOnly }}
264+ | ToggleProofOnly =>
265+ {... paneN , filters : {... paneN .filters , proofOnly : ! paneN .filters .proofOnly }}
266+ | ClearFilters =>
267+ {... paneN , filters : {
268+ sources : [],
269+ categories : [],
270+ phases : [],
271+ confidenceThreshold : 0.0 ,
272+ validatedOnly : false ,
273+ proofOnly : false ,
274+ }}
230275 }
231276 {... model , paneN : newPaneN }
232277}
@@ -11103,15 +11148,77 @@ let updateMenuBar = (model: model, msg: menuBarMsg): (model, Tea_Cmd.t<msg>) =>
1110311148 // File actions
1110411149 | "file:save-state" => (model , Tea_Cmd .none ) // Routed to SaveState in main update
1110511150 | "file:open-repo" => (model , Tea_Cmd .none ) // Would open RepoLoader panel
11106- | "file:export-ensaid" => (model , Tea_Cmd .none )
11107- | "file:import-chain" => (model , Tea_Cmd .none )
11108- | "file:import-panic" => (model , Tea_Cmd .none )
11109- | "file:preferences" => (model , Tea_Cmd .none )
11151+ | "file:new-workspace" => {
11152+ // Reset to initial state but keep viewMode as Standard (not DarkStart).
11153+ let fresh = Model .init ()
11154+ ({... fresh , viewMode : Standard }, Tea_Cmd .none )
11155+ }
11156+ | "file:export-ensaid" => {
11157+ // No backend export yet — route to Help panel with status message.
11158+ ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelHelp )}}, Tea_Cmd .none )
11159+ }
11160+ | "file:export-chain" => {
11161+ // No backend export yet — route to Help panel with status message.
11162+ ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelHelp )}}, Tea_Cmd .none )
11163+ }
11164+ | "file:import-chain" => (
11165+ // Open file dialog to import an event chain JSON file (same as PaneW import button).
11166+ model ,
11167+ TauriCmd .openEventChainFile (result => PaneW (EventChainFileLoaded (result ))),
11168+ )
11169+ | "file:import-panic" => (
11170+ // Open file dialog to import a panic-attacker report file (same as PaneW import button).
11171+ model ,
11172+ TauriCmd .openPanicAttackerReportFile (result =>
11173+ PaneW (PanicAttackerReportPathLoaded (result ))
11174+ ),
11175+ )
11176+ | "file:preferences" => (
11177+ // Open the Workspace panel — that's where preferences live.
11178+ {... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelWorkspace )}},
11179+ Tea_Cmd .none ,
11180+ )
11181+ | "file:print" => (model , Tea_Cmd .none ) // No print backend — intentional no-op
1111011182 // Edit actions
11111- | "edit:undo" => (model , Tea_Cmd .none ) // Routed to Undo
11112- | "edit:redo" => (model , Tea_Cmd .none ) // Routed to Redo
11183+ | "edit:undo" => (model , Tea_Cmd .none ) // Handled by main update loop — MenuAction routes through parent
11184+ | "edit:redo" => (model , Tea_Cmd .none ) // Handled by main update loop — MenuAction routes through parent
1111311185 | "edit:clear-chain" => ({... model , paneW : {... model .paneW , eventChain : [], eventChainSummary : None , eventChainTimeline : None , eventChainInput : "" , eventChainError : None }}, Tea_Cmd .none )
11114- | "edit:reset-panel" => (model , Tea_Cmd .none )
11186+ | "edit:find" => (model , Tea_Cmd .none ) // No find UI yet — awaiting search panel implementation
11187+ | "edit:replace" => (model , Tea_Cmd .none ) // No find/replace UI yet — awaiting search panel implementation
11188+ | "edit:reset-panel" => {
11189+ // Reset all panels to defaults via the Workspace handler's logic.
11190+ // Inline the same reset as Workspace(ResetAllPanels) since we can't recurse.
11191+ let m = {
11192+ ... model ,
11193+ coprocessors : CoprocessorsEngine .defaultState ,
11194+ buildDashboard : BuildDashboardEngine .defaultState ,
11195+ releaseManager : ReleaseManagerEngine .defaultState ,
11196+ automationRouter : AutomationRouterEngine .defaultState ,
11197+ scriptGist : ScriptGistEngine .defaultState ,
11198+ security : SecurityEngine .defaultState ,
11199+ voiceTag : VoiceTagEngine .defaultState ,
11200+ massPanic : MassPanicModel .init ,
11201+ panicAttack : PanicAttackModel .init ,
11202+ tsdm : TsdmModel .init ,
11203+ levelArchitect : LevelArchitectEngine .defaultState ,
11204+ networkTopology : NetworkTopologyEngine .defaultState ,
11205+ typell : TypeLLEngine .defaultState ,
11206+ boj : BojEngine .defaultState ,
11207+ vmInspector : VmInspectorEngine .defaultState ,
11208+ gamePreview : GamePreviewEngine .defaultState ,
11209+ provenance : ProvenanceEngine .defaultState ,
11210+ myLang : MyLangEngine .defaultState ,
11211+ valenceShell : ValenceShellEngine .defaultState ,
11212+ migration : MigrationEngine .defaultState ,
11213+ repoLoader : RepoLoaderEngine .defaultState ,
11214+ ai : AiEngine .defaultState ,
11215+ statusBar : StatusBarEngine .defaultState ,
11216+ cladeBrowser : CladeBrowserModel .defaultState ,
11217+ protocolSquisher : ProtocolSquisherEngine .defaultState ,
11218+ aerie : AerieEngine .defaultState ,
11219+ }
11220+ (m , Tea_Cmd .none )
11221+ }
1111511222 // View actions
1111611223 | "view:toggle-pane-l" => ({... model , paneLVisible : ! model .paneLVisible }, Tea_Cmd .none )
1111711224 | "view:toggle-pane-n" => ({... model , paneNVisible : ! model .paneNVisible }, Tea_Cmd .none )
@@ -11137,7 +11244,7 @@ let updateMenuBar = (model: model, msg: menuBarMsg): (model, Tea_Cmd.t<msg>) =>
1113711244 | "panel:security" => ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelSecurity )}}, Tea_Cmd .none )
1113811245 | "panel:boj" => ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelBoj )}}, Tea_Cmd .none )
1113911246 | "panel:typell" => ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelTypeLL )}}, Tea_Cmd .none )
11140- | "panel:provenance" => (model , Tea_Cmd .none ) // Provenance is core infrastructure — will become a panel
11247+ | "panel:provenance" => ({ ... model , panelSwitcher : { ... model . panelSwitcher , activePanel : Some ( PanelHelp )}}, Tea_Cmd .none ) // Provenance panel slot needed — routes to Help for now
1114111248 // Tools actions — open tool panels
1114211249 | "tools:panic-attack" => ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelPanicAttack )}}, Tea_Cmd .none )
1114311250 | "tools:mass-panic" => ({... model , panelSwitcher : {... model .panelSwitcher , activePanel : Some (PanelMassPanic )}}, Tea_Cmd .none )
0 commit comments