Skip to content

LibreOffice Writer sidebar extension (extensions/vanamkarthiknetha) - #4

Open
vanamkarthiknetha wants to merge 6 commits into
superdocsapp:mainfrom
vanamkarthiknetha:extension/writer-sidebar
Open

LibreOffice Writer sidebar extension (extensions/vanamkarthiknetha)#4
vanamkarthiknetha wants to merge 6 commits into
superdocsapp:mainfrom
vanamkarthiknetha:extension/writer-sidebar

Conversation

@vanamkarthiknetha

Copy link
Copy Markdown

Name: Karthik Vanam

A native LibreOffice Writer sidebar extension (single .oxt, Python/UNO): select a passage, describe the edit in plain language, review the actual proposed text, and Apply — only the selected range changes, with its styles preserved and the rest of the document untouched. The full human-in-the-loop loop runs over the SuperDocs async chat API, validated in the GUI on Linux and Windows, and a headless style-respect test (heading + bullet list + table survive an edit: ALL PASS) ships in tests/.

Built for the SuperDocs hiring round. AI-assisted development (Claude Code), disclosed per CONTRIBUTING.

🤖 Generated with Claude Code

vanamkarthiknetha and others added 6 commits August 6, 2026 21:22
Native LibreOffice Writer sidebar panel (.oxt, Python/UNO): select a passage,
describe the edit, review the actual proposed text, Apply -> only the selected
range changes with its styles preserved. Full HITL loop over the SuperDocs
async chat API; validated in the GUI on Linux and Windows; includes a headless
style-respect test (heading/bullets/table survive an edit -> ALL PASS).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tick 'Whole document' in the sidebar: the doc is exported through the
host's own filter (storeToURL, MS Word 2007 XML) and uploaded as a file;
each approved change is located in the live document by its old_html
(plain-text paragraphs, matched as one consecutive run) and replaced with
a style-preserving setString. A change that is not found or matches more
than one place is skipped and named in the status line, never guessed at;
untouched text is never rewritten.

Tests: offline write-back invariants (0 ops, no key) and a live .docx
round-trip (1 op), both ALL PASS on headless Linux. The offline test
caught an inline-tag stripping bug (space vs empty replacement) before it
shipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gate

Creation-style instructions ('create a gym plan') complete with ZERO
pending changes: the content is already committed server-side in
result.document_changes, bypassing the ask_every_time approval gate
entirely (found via probe, logged as a bug report). The sidebar now
closes that gap on its side: the client surfaces the draft from the
completed job, the panel presents it as a reviewable proposal, Apply
inserts it at the view cursor (writeback.insert_paragraphs - existing
text is never modified), Reject discards it. No-op results still report
'nothing changed' honestly.

Tests: offline suite extended to 19 checks (write-back invariants +
draft insertion), ALL PASS; new plain-HTTP live test proves draft_html
extraction on a real completed job, and honestly reports SKIPPED when
the model nondeterministically chooses in-place edits instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rafts

Windows screenshots of the drafting flow working end to end (27-paragraph
draft inserted at the cursor with existing text untouched; a follow-up
whole-document edit returning 22 reviewable proposals), wired into the
README.

The draft screenshot exposed a flattening flaw: table cells in drafted
content concatenated ('MondayStrength Training...45 mins') because </td>
boundaries vanished during HTML-to-text reduction. Cell ends now become
spaces before the block split. Offline suite still 19/19 ALL PASS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… screen

panel.xdl is a bulletin board - fixed coordinates, no reflow - and the panel
claimed a fixed 360px height. In a small office window the bottom of the stack,
the status line (the one control that says what just happened), was placed
outside the visible panel and simply vanished.

- new src/pythonpath/panel_layout.py: floor/minimum/preferred tiers and grow
  weights per control, pure arithmetic, no UNO. Tall panel: instruction,
  preview and status share the slack. Short panel: the hint then the title
  drop out and the flexible boxes shrink, while the working controls,
  Apply/Reject and the status line stay on screen. An empty preview now takes
  no room at all.
- panel.py: an XWindowListener re-places every control on each resize, and
  getHeightForWidth reports the real minimum/preferred/maximum instead of a
  fixed 360, so the deck grows the panel when there is room and scrolls only
  below the floor layout. The pixel scale is measured from btnSend's authored
  height, so sizes follow the host's DPI/font scaling rather than a hardcoded
  factor (2.5 px/unit on the Windows box this was validated on). Status and
  preview also carry their full text as a tooltip.
- new tests/layout_test.py: offline, plain python3, no LibreOffice, no API
  key, 0 operations - 38,570 assertions over 2,231 panel sizes at three DPI
  scales. Ends with PANEL LAYOUT TEST: ALL PASS.

GUI-validated on Windows in a throwaway profile: at panel heights of 801, 510,
330 and 230px the status line stayed fully inside the panel and below the
decision buttons every time; screenshot at a 900x520 office window added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant