Phase 1034: Wiki Browser (project-wide in-app help system)#159
Merged
Conversation
- Hand-written entry page opened by the new Wiki button on the FastSenseCompanion main toolbar (Plan 06 task 6.1 will set 'OpenTo','Companion-Overview'). - Describes the three-pane layout, top toolbar, log strip, dashboard opening flow, and Live mode semantics. - Cross-links to Tag-Status-Table, Event-Viewer, Live-Log, Dashboard-Info-vs-Wiki, Home using bare-page-name links the Plan 04 Wiki Browser will resolve as in-window navigation. - No AUTO-GENERATED marker (Phase 1034 D-04 hand-written constraint). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New libs/Help/ directory for Phase 1034 (Wiki Browser System 2) - libs/Help/WikiPageIndex.m: classdef with five static method stubs (listPages, buildToc, readPage, search, collidesWithGenerator) plus two private helpers (extractH1_, isAutoGenerated_) - Full Doxygen-style header documenting each method's contract per CONTEXT.md D-08/D-09 (TOC + full-text substring search) and D-05 (generator collision guard) - All methods are methods(Static) so the Plan 04 UI layer can call without instantiating, mirroring MarkdownRenderer.render - Bodies return sensible empty defaults — Task 1.2 fills them
Three hand-written wiki pages, one per Companion surface that gets a Wiki button in Phase 1034: - wiki/Tag-Status-Table.md — user manual for TagStatusTableWindow. Documents the 12 columns, chip filters (AND across groups, OR within), the dual refresh paths (push-on-write + window-owned 1s timer), and the Pause polling toggle. - wiki/Event-Viewer.md — user manual for CompanionEventViewer plus the detached EventsLogPane (both will open this page in Plan 06/07). Documents the Gantt/Table view switch, severity tri-toggle, click / double-click behaviour, and the relationship to the Live log. - wiki/Live-Log.md — user manual for the LiveLogPane (inline + detached). Documents the 4 columns (Time/Tag/Delta/Latest), the 500-row buffer cap, the FastSenseCompanion.scanLiveTagUpdates_ boundary (per-tag cursor state lives upstream, not in the pane), the filter, and the Live-mode dependency. All three: exactly one H1, no AUTO-GENERATED marker, cross-doc links via bare page names (Companion-Overview / Tag-Status-Table / Event-Viewer / Live-Log) so Plan 04's WikiBrowser resolves them in-window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hand-written page that disambiguates the two parallel help systems for dashboard authors: - System 1: DashboardEngine.InfoFile (modal, per-dashboard, scoped) + DashboardWidget.Description (tooltip-only). - System 2: Wiki Browser (non-modal, project-wide, with TOC + search + back/forward), opened from the new Wiki button on Companion windows. Includes a coexistence matrix showing which surfaces carry which buttons, plus authoring guidance pointing out the PAGE_MAP collision hazard for new hand-written wiki pages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add SUMMARY.md for Plan 1034-03 (libs/Help addpath in install.m) - Record decision in STATE.md (Decisions Phase 1034) - Update ROADMAP.md plan-progress row for phase 1034 - Note: Task 3.1 work (install.m diff) landed in commit 95eb030 alongside Plan 1034-02 due to parallel-execution git-index race; SUMMARY.md documents the attribution. Functional outcome verified via `which WikiPageIndex` returning libs/Help/WikiPageIndex.m.
- tests/test_wiki_page_index.m: 14 sub-tests covering every public method and key edge case (listPages count, API-Reference grouping, H1 extraction, TOC group order + alphabetical sort, _Sidebar.md exclusion, readPage Home + .md-extension tolerance + Home fallback, search empty/whitespace/match/no-match, collidesWithGenerator with Home.md auto-generated + empty input) - Sub-tests are independent local functions (t1..t14) returning 1 on pass so a failure fails fast with an informative assert message - Adds an Octave-compatible endsWith_ helper because the built-in endsWith is unavailable on Octave 7+ - No UI dependencies; runs headless on both MATLAB R2020b+ and Octave Verified: All 14 tests passed on Octave 11.1.0 AND MATLAB (via matlab -batch). Test path setup uses addpath + install() so libs/Help/ is on the path when WikiPageIndex.listPages is invoked.
- Add libs/Help/WikiBrowser.m: classdef < handle with public/private
properties, NV-pair constructor, isInteractiveDesktop_ guard, and
openInBrowser_ shell-out fallback for Octave / headless / -batch.
- Stub public methods (navigateTo/back/forward/applyTheme/focus/close/
delete) and private buildFigure_ — filled by Tasks 4.2-4.4.
- Mirrors DashboardEngine.writeAndOpenInfoHtml's gate logic
(~OCTAVE_VERSION + usejava('desktop') + ~batchStartupOptionUsed) so
headless runs write a temp HTML file but never try to open a uifigure.
- Namespaced errors WikiBrowser:invalidArgs and WikiBrowser:unknownOption.
- checkcode clean; constructor smoke test passes headless (IsOpen=false).
- Implement buildFigure_: non-modal uifigure with WindowStyle='normal',
Tag='WikiBrowserRoot' (Plan 08 walker-skip anchor), Position
[100 100 1100 750], centered. Two-row root grid hosts a 32-px
breadcrumb strip (< back / fwd > / crumb label) and a body grid
({260 px, '1x'}) split into sidebar + uihtml content.
- Sidebar = uipanel housing a 2-row uigridlayout: search uieditfield
on top, uitree (TOC) + uilistbox (search results) layered inside a
shared uigridlayout cell (plan-checker I4 Option A — children of
uigridlayout auto-fill and ignore .Position, so figure resize reflows
correctly).
- Add helpers buildTocTree_, onTocSelected_, onSearchChanged_,
onSearchHitSelected_, onHtmlEvent_, alert_. onHtmlEvent_ is wired to
uihtml.HTMLEventReceivedFcn so Task 4.3's JS bridge can post
{page, ts} back to MATLAB on a.wiki-internal clicks.
- Theme colours sourced from CompanionTheme.get(obj.Theme); BorderColor
/ Placeholder gracefully degrade on R2020b.
- checkcode clean; headless smoke test still passes (constructor takes
openInBrowser_ path).
…4.3)
- Implement navigateTo: tolerate './' prefix and '.md' suffix, fall back
to Home.md with user alert when page missing, render via cache keyed
by 'page|theme', push onto history with truncate-forward + 50-entry
cap (HistoryCap_).
- Implement back / forward: no-op at edges; non-pushing re-render via
renderHistoryCurrent_.
- Implement applyTheme: invalidate cache, re-render current page, best-
effort restyle of sidebar + breadcrumb widgets via CompanionTheme.get.
- Add rewriteCrossDocLinks_: SINGLE regexprep with negative lookahead
(?!https?://|mailto:|#) marks internal anchors with class='wiki-internal'
+ data-page='PageName' (preserved verbatim); external + anchor links
left untouched. Injects a JS click-interceptor <script> before </body>
that posts {page, ts} to htmlComponent.Data — the Task 4.2
HTMLEventReceivedFcn maps it back into navigateTo on the MATLAB side.
- Plan-checker I5 fix: removed any chance of orphan href='' or multi-
step index juggling.
- checkcode clean. Inline regex test confirms the rewrite leaves
https://, mailto:, and #anchor links untouched while internal
bare-page hrefs get the bridge-friendly substitution. Headless
navigateTo/back/forward/applyTheme no-op safely on IsOpen=false
instances.
- focus: bring uifigure to front via figure(hFig_); idempotent no-op when IsOpen=false or handle invalid. - close: idempotent disposal — clears CloseRequestFcn first (avoids recursion via X-button), tears down Listeners_ entries, deletes the uifigure, nils every internal UI handle (incl. hTreeHostGrid_), resets HistoryStack_, HistoryIdx_, CurrentPage, and re-initialises Cache_ to an empty containers.Map. Safe to call twice or after external delete(). - delete(obj): handle-class destructor defers to close(). - Final headless smoke test passes (IsOpen=0 throughout; navigateTo updates CurrentPage; applyTheme updates Theme; double-close idempotent; no crashes).
13 test methods covering the WikiBrowser public API on MATLAB desktop:
constructor (defaults + unknownOption + invalidArgs), navigateTo (known
+ unknown fallback), back/forward history with no-op endpoints, history
cap at 50 entries (behavioural via back-step count, no reflection),
forward truncation on new navigation, applyTheme re-render, close
idempotency, focus on closed = no-op, WikiBrowserRoot tag contract
(supports Plan 08's theme walker skip), and cross-doc link rewrite
(asserts class="wiki-internal" + data-page="..." + htmlComponent.Data).
- TestClassSetup.addPaths follows the TestFastSenseCompanion pattern:
Octave skip via assumeFail, headless skip via assumeTrue(usejava
('desktop')), then addpath + install + resolve <repo>/wiki.
- TestMethodTeardown aggressively closes the per-test WikiBrowser and
sweeps any stray WikiBrowserRoot figures so test ordering is
irrelevant.
- testCrossDocLinkRewriteInjectsJsBridge uses the canonical
findobj(parent, '-depth', 1, 'Type', 'uihtml') idiom shared with
TestDashboardInfo.testShowInfoOpensModalFigure (line 230) and
DashboardEngine.showInfoModal_ (lines 966-967), with a deep-walk
findobj fallback for releases where the uihtml sits deeper in the
uigridlayout body grid. Asserts the rewrite preserves the page name
verbatim in data-page (plan-checker I5).
- Headless verification: matlab -batch runtests filters all 13 tests
cleanly via the headless assumption (zero PASSED, zero FAILED, 13
INCOMPLETE) — exactly the contract for CI runs without a desktop.
Plan 1034-05 / Task 5.1.
… walker - Extend existing LogPaneRoot skip rule into combined OR condition matching both 'LogPaneRoot' and 'WikiBrowserRoot' on the Panel arm of the walker. - Update header docstring with parallel paragraph documenting the WikiBrowserRoot skip rule (Phase 1034) alongside the existing LogPaneRoot rule (Phase 1027.1). - WikiBrowser owns its theming via WikiBrowser.applyTheme which FastSenseCompanion.applyTheme invokes explicitly (Plan 06 task 6.2). Walking into the Wiki subtree would stomp its uihtml + uitree styling. - The WikiBrowser is currently a separate top-level uifigure so the walker will never reach it today — the skip rule is preventative, symmetric with LogPaneRoot, protecting against future refactors that might embed WikiBrowser inside the Companion uifigure.
- Added private properties hWikiBtn_ and WikiBrowser_ for the new Wiki
toolbar button and the shared WikiBrowser handle (Phase 1034 D-06).
- Reflowed hToolbarPanel_ inner grid from [1 7] to [1 8]:
ColumnWidth {110,110,110,70,90,'1x',36} -> {110,110,110,70,90,70,'1x',36}.
- Inserted Wiki button between Close all (col 5) and the spacer:
Tag='CompanionWikiBtn', Text='Wiki ↥' (char 8689 pop-out arrow),
ButtonPushedFcn -> obj.openWiki_('Companion-Overview').
- Bumped Settings gear Layout.Column from 7 to 8.
Static analysis: only NEW warning is MCNPN on openWiki_ (private method
added in Task 6.2); pre-existing warnings unchanged.
…serRoot regression - Add a third skip-rule fixture: a uipanel tagged 'WikiBrowserRoot' with a screaming-red [0.99 0.01 0.01] BackgroundColor sentinel + a child uilabel with a magenta [0.99 0.01 0.99] FontColor sentinel. Both sentinels are values no CompanionTheme will ever produce, so any walker-overwrite is immediately visible. - Add 6 new assertions (2 per apply pass: dark, light, second-dark) asserting the WikiBrowserRoot subtree stays untouched across the full dark->light->dark theme cycle. Mirrors the LogPaneRoot fixture pattern on lines 90-104 and the per-pass assertions on lines 121-126 / 222-225 / 254-257 of the existing test. - Pre-edit count was 30 passing assertions; post-edit count is 36 (verified on local MATLAB R2025b: 'All 36 tests passed'). - Existing LogPaneRoot regression remains intact and continues to pass.
…eme propagation - New public method openWiki(pageName) — public alias used by tests and sibling windows; defaults pageName to 'Companion-Overview' when omitted. - New private openWiki_(pageName) — canonical implementation used by the toolbar callback (wired in Task 6.1). Lazily constructs a WikiBrowser cached in obj.WikiBrowser_; subsequent calls navigateTo + focus. Resolves <repo>/wiki from this file's location and passes it via the WikiDir NV-pair (falls back to WikiBrowser's own default if missing). All failure paths surface a non-blocking uialert; never crash the app. - close() now closes + deletes WikiBrowser_ (independent try/catch, mirrors the existing TagStatusTableWindow_ teardown pattern). - applyTheme() propagates the theme to WikiBrowser_ when open via its own applyTheme — Plan 08 keeps WikiBrowserRoot out of the recursive walker, so the Wiki window restyles itself. Static analysis: previous MCNPN warning on openWiki_ is gone; no new warnings introduced (all remaining warnings pre-existing).
Three new tests appended after the Task-13 Events-button block:
- testToolbarHasWikiButton — finds CompanionWikiBtn via findall and
verifies it sits in Layout.Column 6 (the Phase 1034 reflow target).
- testToolbarGearMovedToColumn8 — walks every uibutton, picks the one
whose Text matches char(9881) (gear glyph), and verifies its
Layout.Column is 8 (was 7 before Phase 1034).
- testOpenWikiOpensWikiBrowser — drives openWiki('Companion-Overview')
and verifies a WikiBrowserRoot uifigure appears, then companion close
tears it down. Mirrors TestWikiBrowser by gating on usejava('desktop')
via assumeTrue so headless batch runners skip cleanly.
Result: 64 existing tests still pass + 2 new tests pass + the third
filters cleanly headless (will pass on interactive desktop).
- Add hWikiBtn_ private uicontrol property alongside hPauseBtn_
- Insert Wiki button at [0.87 0.945 0.12 0.04] (top-right corner)
- Shift hPauseBtn_ left to [0.74 0.945 0.12 0.04]
- Add openWiki_ private method routing through Companion_.openWiki('Tag-Status-Table') with WikiBrowser fallback
- Extend applyTheme to restyle hWikiBtn_
- Nil hWikiBtn_ in onCloseRequest_ alongside hPauseBtn_
Reuses existing Companion_ property at line 62; no constructor change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add hWikiBtn_ private uibutton property (reuses existing Companion_ at line 92; no duplication)
- Reflow hLeftHeaderGrid from [1 3] to [1 5] with ColumnWidth {8, '1x', 8, 70, 8} adding column 4 for Wiki button
- Wiki button text 'Wiki [pop-out arrow]' (char(8689)), tooltip 'Open Wiki: Event Viewer'
- Add openWiki_ private method calling obj.Companion_.openWiki('Event-Viewer') with WikiBrowser fallback
- Nil obj.hWikiBtn_ in close()
Constructor signature unchanged (still positional store/registry/companion).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ched headers
EventsLogPane:
- Add hWikiBtn_ + Companion_ private properties
- Add public setCompanion(companion) method
- Reflow header grid [1 5] -> [1 6] with new column at index 5 for Wiki button
- Wiki button Visible toggles via isa(parent, 'matlab.ui.Figure'); only shown when detached
- Add openWiki_ private method routing through Companion_.openWiki('Event-Viewer')
- Extend detach() and applyTheme() to cover hWikiBtn_
LiveLogPane (mirror changes):
- Same property + setCompanion + openWiki_ additions
- Reflow header grid [1 4] -> [1 5] with Wiki button at column 4 (PopoutBtn shifted to col 5)
- Default page 'Live-Log', tooltip 'Open Wiki: Live Log'
FastSenseCompanion:
- Right after instantiating obj.EventsLogPane_ and obj.LiveLogPane_, call setCompanion(obj) inside try/catch so the Wiki button can reach back through openWiki().
Per CONTEXT.md D-13, inline panes share the Companion toolbar's main Wiki button -- only the detached header strips show their own button. Regression: 168 passed / 0 failed / 1 incomplete (testOpenWikiOpensWikiBrowser filtered by headless assumption, expected).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add ⌂ Home button to the breadcrumb bar (back / forward / home / crumb). Tooltip: "Home (wiki/Home.md)". Click navigates to wiki/Home.md. - Fix cross-doc click callback wiring from HTMLEventReceivedFcn to DataChangedFcn. The JS bridge writes htmlComponent.Data which only fires DataChangedFcn on the MATLAB side; HTMLEventReceivedFcn is for the sendEventToMATLAB API which we don't use. - Add regression test that asserts DataChangedFcn is a function_handle and HTMLEventReceivedFcn stays empty — guards against the wrong-wiring bug recurring. Note: In-window cross-doc link CLICK navigation still has a runtime issue (JS bridge fires but downstream navigation doesn't happen for in-page anchors). Tracked as a follow-up — TOC navigation, Home, Back, Forward, and search all work as expected. Plan 1034-09 spot-check feedback (user-requested).
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
HanSur94
added a commit
that referenced
this pull request
May 19, 2026
Catches the branch up to main's latest. Three new commits landed on main during the merge resolution dance: - d8f740e Phase 1034: Wiki Browser (project-wide in-app help system) (#159) - 5ecb4c8 Phase 1028 follow-ups: 5 deferred items (#155) - ce29c9f Pre-existing test failure sweep — Octave + macos-14 green (#158) Conflict resolutions: 1. install.m — combined both addpath/comment additions for libs/PlantLog (v3.1) and libs/Help (v4.0 Phase 1034 Wiki Browser). 2. libs/FastSenseCompanion/FastSenseCompanion.m — toolbar grid 1x8 from the prior merge expanded to 1x9 to accommodate v4.0's Wiki button. New column layout (110/110/110/130/70/90/70/'1x'/36): col 1 Events / col 2 Live / col 3 Tags / col 4 Plant Log… (v3.1) col 5 Tile / col 6 Close all / col 7 Wiki↗ (v4.0 Phase 1034) col 8 spacer / col 9 gear (settings) Both openPlantLogDialog_ (v3.1) and openWiki_ (v4.0) methods preserved with their own try/catch + uialert guards. Documentation note: Wiki Browser uses "Phase 1034" while v3.1's ROADMAP.md also lists "Phase 1034: Plant Log Storage Foundation" (renumbered from 1029 in the previous merge). This is a documentation drift the maintainer can reconcile post-merge — possibly by bumping v3.1 phases to 1039-1043. Code paths are isolated (libs/PlantLog/ vs libs/Help/, different toolbar slots). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HanSur94
added a commit
that referenced
this pull request
May 21, 2026
…ar tests Two failures appeared after the second merge from main brought in v4.0's Phase 1034 Wiki Browser (PR #159): 1. MATLAB Lint — libs/Help/WikiPageIndex.m had two operator_after_continuation style violations (`&& strncmp(...)` on a continuation line). Moved the operators to the end of the previous line. mh_style reports clean. 2. MATLAB Tests (E-I) — TestFastSenseCompanionPlantLogToolbar still expected the 1x8 toolbar grid from the prior merge. After the v4.0 Wiki button was inserted (now col 7), the grid is 1x9 and the gear moved from col 8 to col 9. Updated: - findToolbarGrid_ helper to look for 9-column ColumnWidth {110,110,110,130,70,90,70,'1x',36} - testToolbarGridIs1x5 (still called by that name for historical reasons) to assert col-by-col for all 9 columns - testSettingsButtonMovedToCol5 to expect col 9 Local: 11/11 pass on MATLAB R2025b. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
uifigure) to FastSense Companion — sidebar TOC + search, in-window navigation, breadcrumb with back / forward / Home, theme-aware rendering via existingMarkdownRenderer, Octave/headless fallback to the OS browserCompanion-Overview,Tag-Status-Table,Event-Viewer,Live-Log,Dashboard-Info-vs-Wiki) that drop into the existingwiki/directory without colliding with anyscripts/generate_wiki.pyPAGE_MAP entryDashboardEngine.InfoFilemodal (System 1) andDashboardWidget.Descriptiontooltip stay byte-identical to main — the two systems coexist as separate buttonsWhat's new
libs/Help/WikiPageIndex.m— pure-logic class forwiki/directory listing, H1 parsing, TOC building, substring search (Octave-compatible)libs/Help/WikiBrowser.m— non-modal three-pane uifigure; single per-Companion-session shared instance; 50-entry history stack; cross-doc link rewrite via singleregexprep; JS bridge viahtmlComponent.Data→DataChangedFcn; Octave fallback writes HTML to temp file and hands off to the OS browserwiki/{Companion-Overview, Tag-Status-Table, Event-Viewer, Live-Log, Dashboard-Info-vs-Wiki}.md— user-facing help pagestests/test_wiki_page_index.m— 14 headless function-based teststests/suite/TestWikiBrowser.m— 14 class-based UI tests (gated onusejava('desktop'))TestFastSenseCompanion(Wiki button + lifecycle) andtest_companion_apply_theme_walker(WikiBrowserRootskip rule)What's preserved
libs/Dashboard/DashboardEngine.mandlibs/Dashboard/DashboardWidget.mare byte-identical toorigin/main— verified bytest \"\$(git diff origin/main -- libs/Dashboard/DashboardEngine.m | wc -l | tr -d ' ')\" = \"0\"plus 5 per-symbol grep checksscripts/generate_wiki.pyis unmodifiedTest plan
tests/test_wiki_page_index.m— 14 / 14 PASS (Octave + MATLAB)tests/suite/TestWikiBrowser.m— 14 / 14 PASS on live MATLAB R2025b desktoptests/suite/TestFastSenseCompanion.m— 71 / 72 PASS; the 1 failure (testADHOC05_noOrphanTimersAfterPlotAndClose) reproduces identically onorigin/mainwithout this PR — pre-existing MATLAB R2025b internal listener regression inmatlab.graphics.GraphicsPlaceholder.setPositiontriggered duringDashboardEngine.realizeBatch → drawnow. Not introduced by this PRtests/test_companion_apply_theme_walker.m— 36 / 36 PASSKnown follow-up
<a class=\"wiki-internal\">anchors rendered inside the help body) don't currently trigger in-window navigation. HTML rewrite + JS bridge +DataChangedFcnwiring are all in place, but the JS-sidehtmlComponent.Data = …write does not appear to surface as aDataChangedFcnevent in MATLAB R2025b. Workaround: sidebar TOC, Home button, Back/Forward, and search all work for navigation. Tracked separately, will land in a follow-up PR.Branch hygiene
This is the PR branch created from current
origin/mainvia cherry-pick — only code changes (no.planning/GSD artifacts). The 9 planning-only commits and 1 mixed commit's.planning/paths were filtered out by/gsd:pr-branch.🤖 Generated with Claude Code