dsh-finalize
Manifest valid★ 1Pre-delivery finalize pass for DSH: strips docx/pptx/xlsx/odf tool fingerprints, recomputes real statistics, and reports what it will not fabricate.
dsh-finalize
English | 简体中文
A DeepSeek Harness plugin that runs one finalize pass the moment a file is delivered — and nowhere else. It strips the fingerprints document libraries leave behind, recomputes the statistics that are actually derivable, and puts everything it will not fabricate into a side panel instead of writing it into the file.
Design rule: fix what is provably wrong, never invent evidence. Edit time, revision history, comments and "was written by a human" claims are reported, not written.
Applicationis removed rather than replaced with a fakeMicrosoft Office Word 16.0string — absence is unremarkable, a lie contradicts the rest of the package.
Why this exists
Documents produced by python-docx, python-pptx, openpyxl or LibreOffice carry their own birth certificate: a creator field naming the library, a 2013 template date, Words=0 on a forty-page report, a leftover template thumbnail. Those are bugs, not style choices, and anyone who unzips the file can see them.
The usual advice — forge the edit time, invent a revision count — makes things worse. It contradicts the fields you cannot change (the rsid trail, the real save history) and collapses the moment someone looks. This plugin takes the honest half: normalize what is wrong, report what only a human can supply.
What it does
| Format | Automatic fixes | Reported, never fixed |
|---|---|---|
docx | creator and description, template date, Application/AppVersion, word/character/paragraph/line counts, template thumbnail | TotalTime=0, missing comments, missing tracked changes, page count |
pptx | same core properties, slide/notes/hidden-slide counts, word counts | no speaker notes, cropped images still in ppt/media, hidden slides |
xlsx | core properties, TitlesOfParts aligned to sheet names | zero formulas, pivot cache retaining deleted rows, external links, hidden sheets |
odt ods odp | meta:generator, creator, dates, meta:document-statistic, thumbnail and its manifest entry | meta:editing-duration=PT0S, single save cycle, no annotations, no tracked changes |
pdf | nothing — read-only by design | Producer/Creator/XMP, incremental updates, missing bookmarks, signatures |
Several files in one delivery are processed independently. Several deliveries in one session merge into a single report for 30 minutes instead of overwriting each other.
Install
The plugin is a DSH bundle — a plain package with a dsh.bundle.patch; there is no build step and no runtime dependency.
git clone https://github.com/hengyun721/dsh-finalize.git
dsh plugin --profile desktop add /absolute/path/to/dsh-finalize
Or from inside the Harness, install the checkout directory with the plugin manager (install_bundle, target = the absolute path above). Restart once if it reports restart-required.
Usage
Nothing to call. Deliver a file with present (or a configured transport) and the pass runs before the tool executes, so the file on disk is already normalized when it reaches the recipient.
A shield icon appears in the message action row next to copy / like / dislike / branch:
| State | Meaning |
|---|---|
| grey | no delivery in this session yet |
| amber with a count | that many items need a human |
| click | panel with fixed / open / read-only rows per file |
The panel also offers Scan recent files, which runs the pass on the newest Office files in the working directory without a delivery — handy when a document was produced by a script rather than through present.
Configuration
- id: dsh-finalize
name: 'dsh-finalize'
config:
author: ''
triggerTools: [present, qqbot_send_file]
formats: [docx, pptx, xlsx, pdf, odt, ods, odp]
scanLimit: 5
autoFix:
stripGeneratorFields: true
dropApplicationField: true
recomputeStats: true
report:
surface: panel
| Key | Type | Default | Description |
|---|---|---|---|
author | string | '' | Written into dc:creator, lastModifiedBy and meta:initial-creator. Empty clears generator names without inventing a person. |
triggerTools | string[] | present, qqbot_send_file | Delivery tools that trigger the pass. |
formats | string[] | all seven | Adapter whitelist; anything else is reported as skipped. |
scanLimit | number | 5 | How many recent files Scan recent files processes. |
autoFix.stripGeneratorFields | boolean | true | Remove library names and generated by … descriptions. |
autoFix.dropApplicationField | boolean | true | Remove Application/AppVersion instead of faking an Office version. |
autoFix.recomputeStats | boolean | true | Recompute word/character/paragraph counters from the body. |
report.surface | panel | silent | panel | Whether the action-row button renders. |
Repository layout
| Path | Responsibility |
|---|---|
index.js | Host half. Registers the tools/pre-execute hook on the delivery tools, routes each file to an adapter, merges per-session reports, and serves /api/finalize.report and /api/finalize.scan. Registers no tool and no prompt section. |
client.js | Browser half. Registers the shield button into conversation.chat.assistant-actions and renders the report panel (fixed overlay, theme tokens, no DOM writes outside its own tree). |
lib/office.js | Format engine, dependency-free. ZIP reader/writer (node:zlib), OOXML adapters (docx/pptx/xlsx), ODF adapter (odt/ods/odp), read-only PDF inspector. |
cordis.patch.yml | Bundle patch: inserts the dsh-finalize row and the default config. This is what install_bundle applies to the profile. |
package.json | Package manifest: dsh.bundle.patch, the dsh.client web half (platform, immediately, inject), the export map, and the check / test scripts. |
locale/en.json, locale/zh.json | Display metadata read by the Plugin Manager and Settings without activating the plugin: meta.title, meta.description. |
icon.svg | Original plugin icon (document + check), used in the plugin inventory and bundle details. |
test/smoke.test.mjs | Four node:test cases: ODF rewrite, docx rewrite, PDF inspector, non-ZIP rejection. Fixtures are built in memory; nothing on disk. |
.github/workflows/ci.yml | CI on push and pull request: Node 20, npm run check, then npm test. |
CHANGELOG.md | Version history in Keep-a-Changelog format. |
LICENSE | MIT. |
README.md | This document. |
README.zh.md | Chinese translation. |
Engine map
lib/office.js is deliberately one file with a flat API:
| Symbol | Role |
|---|---|
readZip(buffer) | Parse the central directory into { name, data, time, date } entries. No ZIP64. |
writeZip(entries) | Rebuild the archive with deflateRaw. Entries named mimetype are stored uncompressed and keep their position, as ODF requires. |
finalizeDocx / finalizePptx / finalizeXlsx | OOXML adapters; they share fixCore, stripApplication, dropThumbnail and commonUnresolved. |
finalizeOdf | ODF adapter over meta.xml and META-INF/manifest.xml. |
inspectPdf | Regex-level PDF inspector; returns observations only and never rewrites bytes. |
finalizeOffice(bytes, kind, options) | Dispatcher used by the Host half. |
Compatibility
Built to sit beside other plugins without changing their behaviour.
- No tool, no prompt section. Nothing is added to the model's tool list or system prompt, so token accounting and tool selection are untouched.
- One passive listener.
tools/pre-executeruns only for the configured delivery tools, always returnsnext(), and swallows its own failures, so it can neither block nor rewrite another tool's call. - No transport coupling. It hooks the delivery tool, not a transport, so QQ, Web and CLI transports keep working.
- Namespaced surface. Routes are
/api/finalize.reportand/api/finalize.scan; the slot id isdsh-finalize. Neither collides with the shippeddeliverables,changes.*orpresentedroutes. - Opt-in debug only. Nothing is written outside the delivered files unless
DSH_FINALIZE_DEBUG=1.
Limits
- Page counts need a layout engine; the plugin reports rather than guesses.
- ODF support rewrites
meta.xmland the manifest thumbnail entry, nothing else. Verified structurally; opening in LibreOffice is not covered by CI. - Legacy binary formats (
doc,xls,ppt),rtfandipynbare not implemented.docstores a real accumulated edit time inPIDSI_EDITTIME— worth adding before reaching for anything cosmetic. - This is not an authorship detector and does not claim a file "looks human". It removes noise and reports contradictions.
Debugging
Set DSH_FINALIZE_DEBUG=1 before starting the Harness to write dsh-finalize.log and dsh-finalize-last.json into the OS temp directory. Off by default; nothing is written to your workspace.
Development
npm run check # node --check on the three runtime files
npm test # four unit tests, no dependencies
npm test runs the test file in-process so it also works inside sandboxed terminals where the test runner cannot spawn children.
License
MIT — see LICENSE.
Comments
Loading…
From the same category
DeepSeek Harness plugin for Reactive Resume: bridges your resumes and job applications into a Harness session over MCP.
★ 41.7k
↓ 146/wk
MIT
Aug 24, 2026
dsh plugin --profile web add dsh-plugin-reactive-resumeby dsh-market
The plugin market inside DeepSeek Harness — browse, search, one-click install · DSH 可视化插件市场
★ 10.3k
↓ 136.6k/wk
MIT
TypeScript
Nov 2, 2026
dsh plugin --profile web add dshmarketby Tencent
Let AI agents use your real, logged-in browser without interrupting your work. CLI + extension for browser automation across any shell-capable AI agent.
★ 9.9k
↓ 7.4k/wk
MIT
TypeScript
Nov 2, 2026
dsh plugin --profile terminal add @wxg-prc-cpg/browser-skill-dsh-pluginby superdesigndev
OpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn
★ 7.1k
NOASSERTION
Python
Nov 3, 2026
dsh plugin --profile web add treg-dshby yjh051108
dsh-routing-suite — injector + router-standard kit: install the runtime injector first, then the task-aware reasoning-mode router preset (measured P1-P23).
★ 7k
MIT
JavaScript
Sep 18, 2026
dsh plugin --profile web add @dsh-external/dsh-super-injectorby Q00
Agent OS: the agent gets smarter on its own. We just hold the line: Interview-gated, staged evaluation, budgeted evolution loop. MCP server, 14 runtimes: Claude Code, Codex CLI, Gemini CLI, OpenCode,
★ 6.3k
MIT
Python
Nov 1, 2026