Initial QQwrite skill
This commit is contained in:
commit
28e04853f1
|
|
@ -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.
|
||||
|
|
@ -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.
|
|
@ -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
|
||||
|
|
@ -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())
|
||||
Loading…
Reference in New Issue