Initial QQwrite skill

This commit is contained in:
qyh15 2026-05-27 21:14:31 +08:00
commit 28e04853f1
5 changed files with 268 additions and 0 deletions

75
SKILL.md Normal file
View File

@ -0,0 +1,75 @@
---
name: qqwrite
description: Adjust manuscript Word documents to match journal or group writing templates. Use when the user asks QQwrite to format, restructure, clean, or align a .docx manuscript according to a Word template from the local template library, especially for scientific manuscripts, AFM-style templates, section order, title page metadata, abstract/keywords placement, headings, captions, references, SI pointers, and submission-ready Word formatting.
---
# QQwrite
QQwrite is the Word-template execution skill for manuscript writing workflows. Its current scope is intentionally narrow: use a template from the local template library to adjust a user's manuscript Word file while preserving scientific meaning.
## Core Rule
Do not overwrite the source manuscript. Always create a revised copy and a short Markdown report.
Default outputs:
- `*_qqwrite_adjusted.docx`
- `*_qqwrite_report.md`
## Template Library
Use bundled templates first:
- `assets/templates/afm/article-template.docx` for Advanced Functional Materials-style manuscript formatting.
If the user provides another template path, use the user-provided template instead.
For template handling details, read `references/template-adjustment.md`.
## Workflow
1. Identify inputs:
- source manuscript `.docx`
- template `.docx`
- target journal or template name if provided
- output directory
2. Preflight both documents:
- inspect section order and heading hierarchy
- compare title page fields, abstract, keywords, main text, methods, references, captions, acknowledgements, and supporting information pointers
- inspect paragraph styles, table count, figure-caption patterns, references section, and obvious empty or duplicated sections
- run `scripts/docx_template_audit.py` when a quick structural report is useful
3. Adjust only formatting and template structure unless the user explicitly asks for rewriting:
- move or relabel sections to match the template
- normalize heading levels
- normalize title, author, affiliation, abstract, keywords, captions, references, and acknowledgements placement
- preserve scientific claims, numbers, units, equations, citations, and figure/table labels
- flag unclear template conflicts in the report instead of guessing silently
4. Produce the revised Word file:
- copy the original manuscript first
- apply template-compatible styles and section order
- keep original content recoverable
- avoid converting citations to plain text unless unavoidable and reported
5. Produce the report:
- list template used
- list changed sections and formatting changes
- list unresolved issues requiring author decision
- list any content that appears missing relative to the template
## Boundaries
- QQwrite does not decide manuscript novelty, literature strength, or reviewer risk. Route those tasks to QQsci.
- QQwrite does not generate Zotero/DeepSeek literature notes. Route those tasks to QQnote.
- QQwrite may lightly fix obvious Word-format inconsistencies, but substantial scientific rewriting belongs in QQsci or a future writing module expansion.
- For citation suggestions inside Word, follow QQsci's DOI-only comment convention if the task explicitly involves citation comments.
## Current Capability
Only one capability is active now:
`template-adjust-docx`: adjust a manuscript `.docx` according to a `.docx` template from the local library.
Future capabilities can be added later, but keep this skill focused on Word-template execution.

4
agents/openai.yaml Normal file
View File

@ -0,0 +1,4 @@
interface:
display_name: "QQwrite"
short_description: "Adjust manuscript Word documents to match writing templates."
default_prompt: "Help me adjust this manuscript Word document using a template from the template library. Preserve scientific meaning, compare structure and formatting with the template, and produce a revised .docx plus a short Markdown report."

Binary file not shown.

View File

@ -0,0 +1,62 @@
# Word Template Adjustment
## Goal
Make the user's manuscript follow the selected Word template without changing the scientific meaning.
## What To Compare
Compare these elements before editing:
- title page fields: title, authors, affiliations, corresponding author, abstract, keywords
- section order: introduction, results/discussion, conclusion, experimental/methods, acknowledgements, conflict of interest, data availability, references
- heading hierarchy and visible heading text
- figure and table caption style and numbering
- references section placement and numbering style
- SI references, graphical abstract/TOC notes, highlights, and cover letter cross-references when present
- page setup, margins, columns, headers/footers, and line spacing when detectable
## Editing Rules
- Work on a copied `.docx`; never overwrite the source.
- Prefer Word-native styles when available.
- Preserve all numbers, units, chemical formulas, gene/protein names, sample names, equations, citation markers, figure labels, and table labels.
- Do not silently delete content that has no obvious template location. Move it to the closest suitable section or flag it in the report.
- If the template contains placeholder text, replace only with matching manuscript content; remove unused placeholders in the revised copy.
- Keep references and citations intact. If field codes are lost by tooling, report that explicitly.
## Report Format
Use this Markdown shape:
```markdown
# QQwrite Template Adjustment Report
## Inputs
- Manuscript:
- Template:
- Output:
## Changes Made
- ...
## Missing Or Unclear Items
- ...
## Checks
- Section order:
- Heading hierarchy:
- Captions:
- References:
- Citation fields:
```
## When To Stop And Ask
Ask the user before continuing if:
- the manuscript and template are for clearly different article types
- the manuscript has no recognizable title/abstract/main sections
- a template-required section is missing and cannot be inferred
- editing would require scientific rewriting rather than formatting/structure adjustment
- citation fields, equations, or embedded objects are at risk of being flattened

View File

@ -0,0 +1,127 @@
#!/usr/bin/env python3
"""Create a lightweight structural audit for a manuscript/template DOCX pair.
This script intentionally uses only the Python standard library. It inspects the
OOXML package directly and reports headings, paragraph-style usage, section-like
paragraphs, table count, and image count. It does not modify documents.
"""
from __future__ import annotations
import argparse
import collections
import json
import re
import sys
import zipfile
from pathlib import Path
from xml.etree import ElementTree as ET
NS = {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
"a": "http://schemas.openxmlformats.org/drawingml/2006/main",
}
SECTION_PATTERNS = [
"abstract",
"keywords",
"introduction",
"results",
"discussion",
"conclusion",
"experimental",
"methods",
"acknowledgements",
"acknowledgments",
"conflict of interest",
"data availability",
"references",
]
def read_xml(zf: zipfile.ZipFile, name: str) -> ET.Element | None:
try:
return ET.fromstring(zf.read(name))
except KeyError:
return None
def text_from_paragraph(p: ET.Element) -> str:
parts = []
for t in p.findall(".//w:t", NS):
if t.text:
parts.append(t.text)
return "".join(parts).strip()
def style_from_paragraph(p: ET.Element) -> str:
style = p.find("./w:pPr/w:pStyle", NS)
if style is None:
return "(none)"
return style.attrib.get(f"{{{NS['w']}}}val", "(unknown)")
def inspect_docx(path: Path) -> dict:
with zipfile.ZipFile(path) as zf:
document = read_xml(zf, "word/document.xml")
if document is None:
raise ValueError(f"{path} does not contain word/document.xml")
paragraphs = document.findall(".//w:p", NS)
tables = document.findall(".//w:tbl", NS)
drawings = document.findall(".//w:drawing", NS)
style_counts: collections.Counter[str] = collections.Counter()
headings = []
section_hits = []
nonempty_count = 0
for index, p in enumerate(paragraphs, start=1):
text = text_from_paragraph(p)
style = style_from_paragraph(p)
style_counts[style] += 1
if not text:
continue
nonempty_count += 1
normalized = re.sub(r"\s+", " ", text).strip().lower()
if style.lower().startswith("heading") or style.lower().startswith("title"):
headings.append({"index": index, "style": style, "text": text[:160]})
if any(pattern == normalized or normalized.startswith(pattern + ":") for pattern in SECTION_PATTERNS):
section_hits.append({"index": index, "style": style, "text": text[:160]})
return {
"path": str(path),
"paragraphs": len(paragraphs),
"nonempty_paragraphs": nonempty_count,
"tables": len(tables),
"drawings": len(drawings),
"top_styles": style_counts.most_common(20),
"headings": headings[:80],
"section_hits": section_hits[:80],
}
def main() -> int:
parser = argparse.ArgumentParser(description="Audit a manuscript DOCX against a template DOCX.")
parser.add_argument("--manuscript", required=True, type=Path)
parser.add_argument("--template", required=True, type=Path)
parser.add_argument("--out", type=Path, help="Optional JSON output path.")
args = parser.parse_args()
report = {
"manuscript": inspect_docx(args.manuscript),
"template": inspect_docx(args.template),
}
payload = json.dumps(report, ensure_ascii=False, indent=2)
if args.out:
args.out.write_text(payload, encoding="utf-8")
else:
print(payload)
return 0
if __name__ == "__main__":
sys.exit(main())