Three independently ugly bugs that all fed the same log flood:
* Electron's `WebFrameMain.send` writes every "Render frame was disposed"
to stderr via `console.error`. When the worker fans a second
agent-event past a reloading renderer, we produced thousands of
identical lines and stalled the main loop on stderr I/O. Added a
`mainFrame.detached` guard so the send is short-circuited before
Electron's own catch block fires, and installed a targeted filter in
`suppress-warnings.ts` (now actually imported from the entry point)
so the specific `console.error("Error sending from webFrameMain:"…)`
noise never reaches the terminal. Any other payload still surfaces.
* `dispatchAgentMessage` accepted the human-reader sentinel as a wake
target when an agent replied to `__board__` — `wakeAgentIfPossible`
then called `db.getAgent("__board__")`, threw, and the dispatcher
kept repeating on every send. Strip `HUMAN_SENDER_ID` at
`resolveMessageWakeTargets`, and keep a defense-in-depth guard in the
heartbeat so a stray caller (future automation fan-out) cannot
reintroduce the crash.
* Pi's skills loader rejects any SKILL.md whose frontmatter `name`
diverges from its parent directory. The four bundled `my-writing-style`
copies declared `name: writing-style-skill`, so every install emitted
a warning and dropped the skill. They also lived as orphan gitlinks
(mode 160000 without .gitmodules), and the global `*.md` gitignore
hid every other SKILL.md from version control. Fixed the frontmatter
to match the dir, converted the dangling submodules to plain trees,
and allowlisted `builtin-skills/**/*.md` so a fresh clone carries the
catalogue instead of silently losing it.
5.2 KiB
Track Changes Guide
Overview
Track Changes in OpenXML uses revision markup elements to record insertions, deletions, and formatting changes. Each revision has a unique ID, author, and timestamp.
Insertion: <w:ins>
Wraps runs that were inserted during tracking:
<w:ins w:id="1" w:author="John Smith" w:date="2026-03-21T10:30:00Z">
<w:r>
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" />
<w:sz w:val="22" />
</w:rPr>
<w:t>This text was inserted.</w:t>
</w:r>
</w:ins>
w:id— unique revision ID (integer, must be unique across document)w:author— free text string identifying the authorw:date— ISO 8601 format with timezone:YYYY-MM-DDTHH:MM:SSZ- Content inside is normal runs (
w:r) with optional formatting
Deletion: <w:del>
Wraps runs that were deleted during tracking:
<w:del w:id="2" w:author="John Smith" w:date="2026-03-21T10:31:00Z">
<w:r>
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" />
<w:sz w:val="22" />
</w:rPr>
<w:delText xml:space="preserve">This text was deleted.</w:delText>
</w:r>
</w:del>
CRITICAL: Inside <w:del>, text MUST use <w:delText>, NOT <w:t>. Using <w:t> inside a deletion is invalid and will cause corruption or unexpected behavior. Word may silently repair it, but other consumers will fail.
Formatting Change: <w:rPrChange>
Records that a run's formatting was changed. Placed inside w:rPr, it stores the previous formatting:
<w:r>
<w:rPr>
<w:b /> <!-- Current: bold -->
<w:rPrChange w:id="3" w:author="Jane Doe" w:date="2026-03-21T11:00:00Z">
<w:rPr>
<!-- Previous: not bold (empty rPr means no formatting) -->
</w:rPr>
</w:rPrChange>
</w:rPr>
<w:t>This text was made bold.</w:t>
</w:r>
The outer w:rPr holds the new (current) formatting. The w:rPrChange child holds the old (previous) formatting.
Paragraph Property Change: <w:pPrChange>
Records paragraph-level formatting changes (alignment, spacing, style):
<w:pPr>
<w:jc w:val="center" /> <!-- Current: centered -->
<w:pPrChange w:id="4" w:author="Jane Doe" w:date="2026-03-21T11:05:00Z">
<w:pPr>
<w:jc w:val="left" /> <!-- Previous: left-aligned -->
</w:pPr>
</w:pPrChange>
</w:pPr>
Revision ID Management
- Every revision element (
w:ins,w:del,w:rPrChange,w:pPrChange,w:tblPrChange, etc.) requires aw:idattribute - IDs must be unique integers across the entire document
- IDs should be monotonically increasing (not strictly required, but expected by Word)
- When adding revisions, scan for the current maximum
w:idand increment from there
Existing max ID: 47
New insertion: w:id="48"
New deletion: w:id="49"
Author and Date
- Author: Free text. Use consistent strings (e.g.,
"MiniMaxAI"for all automated edits) - Date: ISO 8601 with UTC timezone marker:
2026-03-21T10:30:00Z- Must include the
Tseparator andZsuffix (or+HH:MMoffset) - Omitting the date is allowed but not recommended
- Must include the
Operations
Propose Insertion
Add <w:ins> wrapper around new content at the target location:
<w:p>
<w:r><w:t>Existing text. </w:t></w:r>
<w:ins w:id="5" w:author="MiniMaxAI" w:date="2026-03-21T12:00:00Z">
<w:r><w:t>Proposed new text. </w:t></w:r>
</w:ins>
<w:r><w:t>More existing text.</w:t></w:r>
</w:p>
Propose Deletion
Wrap existing content in <w:del> and change <w:t> to <w:delText>:
<w:p>
<w:r><w:t>Keep this. </w:t></w:r>
<w:del w:id="6" w:author="MiniMaxAI" w:date="2026-03-21T12:01:00Z">
<w:r>
<w:rPr><w:b /></w:rPr>
<w:delText>Remove this.</w:delText>
</w:r>
</w:del>
<w:r><w:t> Keep this too.</w:t></w:r>
</w:p>
Accept a Tracked Change
- Accept insertion: Remove the
<w:ins>wrapper, keep the inner runs as normal content - Accept deletion: Remove the entire
<w:del>element and its content
Reject a Tracked Change
- Reject insertion: Remove the entire
<w:ins>element and its content - Reject deletion: Remove the
<w:del>wrapper, change<w:delText>back to<w:t>
Cross-Paragraph Operations
Deleting a Paragraph Break (Merging Paragraphs)
When tracked deletion spans a paragraph boundary, use <w:pPrChange> on the merged paragraph:
<w:p>
<w:pPr>
<w:pPrChange w:id="7" w:author="MiniMaxAI" w:date="2026-03-21T12:05:00Z">
<w:pPr>
<w:pStyle w:val="Normal" />
</w:pPr>
</w:pPrChange>
</w:pPr>
<w:r><w:t>First paragraph text. </w:t></w:r>
<w:del w:id="8" w:author="MiniMaxAI" w:date="2026-03-21T12:05:00Z">
<w:r><w:delText> </w:delText></w:r>
</w:del>
<w:r><w:t>Second paragraph text (now merged).</w:t></w:r>
</w:p>
Inserting a New Paragraph
The entire new paragraph is wrapped in <w:ins>:
<w:p>
<w:pPr>
<w:rPr>
<w:ins w:id="9" w:author="MiniMaxAI" w:date="2026-03-21T12:10:00Z" />
</w:rPr>
</w:pPr>
<w:ins w:id="10" w:author="MiniMaxAI" w:date="2026-03-21T12:10:00Z">
<w:r><w:t>Entirely new paragraph.</w:t></w:r>
</w:ins>
</w:p>
The paragraph mark itself is marked as inserted via w:ins inside w:pPr > w:rPr.