LLM 기반 국책과제계획서·제안서·보고서(HWP/HWPX/DOCX/PDF/Markdown/HTML) CLI 자동 작성 파이프라인
Project description
ReportGen
A CLI pipeline for AI-assisted drafting of Korean national R&D project plans, proposals, and technical reports (HWP/HWPX) — from form analysis to a finished document, in partnership with an external LLM agent.
Overview
ReportGen is a command-line tool, not a hosted service or a model. You give it a form — a national R&D project plan, a proposal, a technical report, an IRB protocol, any similarly structured institutional document — plus reference material, and it does two things:
- Analyzes the form's structure and emits a mapping-request artifact that any external LLM agent can read.
- Applies the agent-authored mapping back onto the form to produce a finished document.
The pipeline itself never calls an LLM API. Content generation is delegated entirely to whichever external agent drives the CLI — Claude Code, OpenCode, Codex, or any other coding agent/harness. This means no API-key management and no lock-in to a single model provider inside the tool, and it's why the same pipeline works unmodified whether you're filling out a dementia-research R&D plan, a public-works proposal, or a mid-term technical report.
HWP/HWPX is ReportGen's native engine — reportgen parses and edits HWPX XML directly (StructureAnalyzer/SmartFillEngine, no external converter in the loop). For .docx, .pdf, .md, and .html templates, the same analyze → design → apply → verify methodology applies, routed through the right specialized tool for that format instead of a from-scratch HWPX-only parser — see Supported Template Formats. Reference material (the source facts you feed the design step) is supported natively across all of these formats regardless of what the template itself is in. ReportGen ships through three channels — PyPI, standalone binaries, and a Claude Code plugin — so it installs cleanly in any environment.
Features
- 🔍 Automatic HWPX structure analysis — TOC detection, 5-way table classification (DATA/INSTR/SKIP/SCHED/IDENT), and paragraph placeholder detection in one pass.
- 🤝 Mapping-request artifact generation — emits
request.json+prompt.mdfor any external LLM agent to read. Zero internal LLM calls. - ✍️ FieldMapping apply engine — takes the agent-authored JSON mapping and writes it into the HWPX XML via three precise actions:
replace/fill_cell/insert_after. - 🎯 Adaptive fill — no per-form hardcoding — table cells can be targeted by structural intent instead of raw coordinates: a
labelfield resolves to whatever cell sits next to that label text, and aschedulefield expands a Gantt-chart task into the right monthly cells — both computed fresh from each document's own structure, so the same code works on any form of that shape. - 🔤 Font consistency & line-wrap safety — automatically applies a 12pt non-bold Malgun Gothic
charPr, and strips stale<hp:linesegarray>caches so Hangul Word doesn't render overlapping text after reflow. - 📎 Reference-material ingestion, format-agnostic — TXT/MD/PDF/HWPX/DOCX/HTML reference files are all parsed automatically and folded into the mapping-request payload, regardless of what format the template itself is in.
- 🧭 Multi-format template routing —
.hwp/.hwpxtemplates are filled by ReportGen's native engine;.docx/.pdf/.md/.htmltemplates are filled by routing the same 4-step methodology through the matching specialized tool (see Supported Template Formats). - 🛡️ Structural verification gate — checks for table loss, coordinate anomalies, and paragraph fill rate right after the pipeline runs, and measures accurate fill rate excluding SKIP/SCHED tables.
- 🔁 HWP → HWPX conversion — converts binary HWP to ZIP-based HWPX via a Java fat JAR.
- 📦 Three distribution channels — PyPI (update-notification), standalone binary (true self-update), and the Claude Code plugin marketplace. See Installation for details on each.
Quick Start
pip install reportgen-pipeline
# Phase 1 — analyze the form & emit a mapping request (no LLM call)
reportgen \
--template input/project-plan-form.hwpx \
--reference input/project-summary.txt input/rfp.pdf \
--emit-mapping-request request.json
# (an external LLM agent reads request.json and writes mappings.json)
# Phase 2 — apply the mapping & produce the finished HWPX
reportgen \
--template input/project-plan-form.hwpx \
--mappings mappings.json \
--output output/result.hwpx \
--measure
How It Works
- Form analysis (Phase 1) —
StructureAnalyzerparses the HWPX form's table/paragraph structure, auto-classifies every table into one of 5 types (DATA/INSTR/SKIP/SCHED/IDENT), detects fill targets, and emitsrequest.json(full detail) plus a compact digest fromdigest.py(a few dozen KB, via--emit-digest) and an optionalprompt.md. This phase never calls an LLM API. - An external LLM agent fills it in — Claude Code, OpenCode, or any other agent designs the fill plan from the compact digest (not the full
request.json, especially for large forms), targets only the specific elements it needs fromrequest.json, and writesmappings.jsonfollowing theFieldMapping[]contract. Swapping models or providers never requires touching the pipeline code. - Mapping apply (Phase 2) —
SmartFillEnginewritesmappings.jsoninto the HWPX XML:replace(paragraphs, with stale linesegarray cleared),fill_cell(table cells, coordinates verified against the real document — or resolved dynamically from alabel/scheduleintent),insert_after(new paragraphs, 12pt Malgun Gothic applied). - Verify + measure —
verify_outputgates on table loss and paragraph fill rate, andmeasure_fill_ratecomputes an accurate fill rate against the original template, excluding SKIP/SCHED tables. The finishedoutput.hwpxopens directly in Hangul Word Processor.
Core design principles
| Principle | What it means |
|---|---|
| Form-invariant | Instruction tables ("delete before submission"), diagram-like tables, and identity tables are preserved as-is; only genuine data tables get filled |
| Line-wrap safety | Stale <hp:linesegarray> caches are stripped so Hangul Word reflows cleanly, with no overlapping text |
| Dynamic classification, never hardcoded | Gantt charts, org charts, and empty grids are identified by structural pattern, not by memorizing any one form's layout |
| Content stays external | Content generation is delegated to an external agent — model and provider stay fully swappable |
| Accurate measurement | Fill rate is computed against the original template, excluding SKIP/SCHED tables |
| Digest-first analysis | The design phase reads a compact digest instead of the full request.json — measured example: a 29-table form went from a 1.5MB request.json to a 45KB digest |
Supported Template Formats
The file format of the template you're filling out determines which engine actually does the work. Every format below follows the same four-step methodology — ① analyze structure, ② have an external agent design the fill plan, ③ apply it, ④ verify — but only HWP/HWPX runs through ReportGen's own purpose-built parser. The rest are routed to the right specialized tool so the same methodology applies without ReportGen pretending to have a native engine it doesn't:
| Template format | ① Analyze | ③ Apply | ④ Verify |
|---|---|---|---|
.hwp |
Convert to .hwpx first (hwp2hwpx), then use the row below |
(same) | (same) |
.hwpx |
reportgen --emit-mapping-request --emit-digest — native StructureAnalyzer |
reportgen --mappings — native SmartFillEngine |
reportgen --measure — deterministic script |
.docx |
The docx skill: an existing file is unzipped and read with python-docx (or pandoc -t markdown for a quick read); a new file is built with docx-js |
Same skill: cells/paragraphs are edited directly with python-docx, then rezipped (or generated fresh with docx-js) |
Render to PDF (LibreOffice soffice --headless --convert-to pdf, or Word via COM automation) and inspect the page images directly |
.pdf |
The pdf skill: check whether the PDF has real form fields |
Fill the form fields if present, otherwise overlay text at the right coordinates | Render pages to images and inspect directly |
.md / .html |
Read directly — both are plain text, so no separate structural parser is needed | Edit/Write directly | Read back and check |
Reference material is unaffected by this table — --reference accepts .txt/.md/.pdf/.hwpx/.docx/.html(.htm) in any combination no matter what format the template is in, because reference_reader.py parses each one directly (via pypdf, python-hwpx's TextExtractor, python-docx, or a tag-stripping HTML reader). Legacy binary .hwp/.doc reference files need a one-time conversion first (hwp2hwpx/soffice --convert-to docx) — the error message tells you the exact command.
LLM Allocation — how model tiers are assigned
ReportGen's own code contains no LLM calls anywhere. It is a deterministic CLI: Phase 1 and Phase 2 are pure structural analysis and XML editing, and --measure is a pure scoring script. Every piece of authored content comes from whatever external agent invokes the CLI — which means you (or your coding agent) decide which model tier does which job. The tool is designed around a specific 3-stage division of labor so that model spend tracks task difficulty instead of being uniform:
| Stage | Tier required | Input it should read | Why |
|---|---|---|---|
| ① Form analysis & fill design | High-tier (e.g. Opus-class, GPT-5.6-class "high"/"solve" reasoning, or an equivalent top-tier reasoning mode) | The compact digest (--emit-digest), not the full request.json |
This is the step that decides what goes in each field, how much content each section needs, and where a large table should be preserved vs. filled — the single highest-leverage decision in the whole run, so it deserves the strongest available model. Reading the full request.json here (which can be hundreds of KB to >1MB on large forms) burns tokens without improving the decision, since the digest already carries everything structural: element indices, previews, table classifications, and fill coordinates. |
| ② Field content generation | Mid-tier (e.g. Sonnet-class, GPT-5.6 standard, or a comparable general-purpose coding-agent model) | The Phase ① design plan, plus targeted lookups into request.json by element_index only when exact source text or merge structure is needed |
Once the design is set, writing the actual sentence/number for each target is comparatively mechanical — a mid-tier model handles it reliably and far more cheaply. |
| ③ Verification & fill-rate measurement | None — deterministic code | --measure output |
This is fully computed by measure_fill_rate.py; no model judgment is involved. Only re-invoke a mid-tier model here if the measured fill rate looks abnormally low or the output content looks suspicious — a high-tier model is never needed for this step. |
A few corollaries that follow directly from this design:
- Never use a lightweight/mini-tier model at any stage. The whole pipeline is calibrated around "one strong analysis pass, one competent fill pass" — a cheap model at either stage tends to produce sparse content or mis-scoped table decisions, which is exactly the failure mode the digest/design split is meant to prevent.
- Simple forms don't need the two-stage split. A form with a handful of tables and under ~20 paragraph targets is fine end-to-end in a single mid-tier session — reserve the high-tier design pass for large forms (10+ tables, multi-year tables, complex row/merge structures), where it earns its cost.
- Cache your research. If you're filling out many proposals in the same domain, save web-research findings (e.g.
input/research_facts.md) and reuse them — re-searching the same domain facts on every run is wasted spend, independent of which model tier you're using. - Prefer intent over coordinates when authoring
mappings.json. AFieldMappingentry can carry alabelfield (resolved to whatever cell sits next to that label text) or aschedulefield ({task_row, start_month, end_month, mark}, expanded into the right Gantt-chart cells) instead of hand-countedtable_row/table_col— this is what makes the same mapping-authoring approach transfer across different forms without new per-form logic. See the skill'sSKILL.md(.claude/skills/reportgen/SKILL.md) for the fullFieldMappingschema and worked examples.
CLI
--template <HWPX form path> (required)
--output <output HWPX path> (required for Phase 2)
--reference <file1> <file2> ... TXT/MD/PDF/HWPX/DOCX/HTML reference files
--data <user_data.json> additional structured data (optional)
--instructions "extra instructions" additional instructions for the agent (optional)
--emit-mapping-request <request.json> Phase 1: emit the mapping request
--emit-digest <digest.json> Phase 1: emit the compact structural digest (recommended primary input for the design stage)
--prompt-output <prompt.md> Phase 1: emit a Markdown prompt (optional)
--mappings <mappings.json> Phase 2: apply the mapping
--analysis-output <analysis.json> save the structure analysis result (optional)
--measure print the fill rate on completion
--version show version
--upgrade standalone-binary channel: self-upgrade immediately
--no-update-check skip the startup update check
--verbose
After converting HWP → HWPX
java -jar java/hwp2hwpx-fat.jar input/form.hwp input/form.hwpx
reportgen --template input/form.hwpx --emit-mapping-request request.json
Measuring fill rate separately
python scripts/measure_fill_rate.py --file output/result.hwpx --template input/form.hwpx
=======================================================
Fill Rate Report: result.hwpx [template]
=======================================================
TABLE CELLS (DATA tables only, SKIP/SCHED excluded):
Total data cells : 86
Filled cells : 86
Fill rate : 100.0% [##################################################]
PARAGRAPH TARGETS (from template):
Total targets : 66
Filled : 60
Fill rate : 90.9% [#############################################-----]
=======================================================
Installation
| Channel | Command | Notes |
|---|---|---|
| PyPI (recommended) | pip install reportgen-pipeline |
Public distribution; checks for a new version once a day at runtime and prints a pip install -U notice |
| Standalone binary | Download reportgen-<os>-<arch> from Releases |
For internal/collaborator use (private repo, requires auth); true self-update in the OpenCode style |
| Source (for development) | git clone then pip install -e . |
Includes the reportgen CLI, editable install |
Prerequisites
- Python 3.10+
- Java 11+ / Maven (only needed for HWP → HWPX conversion)
- Filling a
.docxor.pdftemplate pulls in the Claude Codedocx/pdfskills for the apply/verify steps (see Supported Template Formats); no extra setup is needed to use--referencewith those formats, sincepython-docxis a core dependency
PyPI channel details
pip install reportgen-pipeline
pip install -U reportgen-pipeline # upgrade
reportgen --version
pip deliberately never reinstalls itself automatically (this is correct, safe behavior). The CLI only prints a "a new version is available — run pip install -U" notice, the same way gh or npm do (disable with REPORTGEN_NO_UPDATE_CHECK=1). This repository is private, but PyPI is a separate public registry, so this channel is reachable by anyone.
Standalone binary channel details
gh release download v0.3.0 --repo kaismin82/ReportGen-pipeline \
--pattern "reportgen-<os>-<arch>*"
./reportgen-windows-x86_64.exe --template ... --emit-mapping-request request.json
⚠️ Because this repository is private, this channel only works for people with repo access (anonymous requests get a 404 from the GitHub API). Authentication comes from
gh auth tokenor theGITHUB_TOKEN/GH_TOKENenvironment variable. Use the PyPI channel if you need public distribution.
Unlike the pip package, a standalone binary owns nothing but itself (no shared venv or pinned-version environment to break), so on every run, if it detects a newer version it replaces itself and immediately re-executes the same command — the same mechanism OpenCode uses for opencode upgrade. Force it immediately with reportgen --upgrade, or disable it with REPORTGEN_NO_AUTOUPDATE=1.
Source install & conda caveat
git clone https://github.com/kaismin82/ReportGen-pipeline.git
cd ReportGen-pipeline
pip install -r requirements.txt # dependencies only
pip install -e . # or an editable install (includes the reportgen CLI)
bash setup.sh --java # (optional) build the HWP→HWPX converter
conda environments may already have a different package also named hwpx installed (pip install hwpx ❌ ≠ pip install python-hwpx ✅):
pip install python-hwpx --force-reinstall
Architecture
| Module | Role |
|---|---|
universal_pipeline.py |
📌 Main CLI entry point (the reportgen command) |
document_model.py |
Data classes (DocumentElement, TableInfo, FieldMapping) |
structure_analyzer.py |
HWPX structure analysis · table/paragraph classification |
dynamic_template_analyzer.py |
Analysis orchestrator (no LLM calls) |
smart_fill_engine.py |
HWPX XML edit engine (replace/fill_cell/insert_after) |
mapping_resolve.py |
Resolves label/schedule intent mappings into concrete fill_cell mappings |
schedule_resolve.py |
Expands a Gantt-chart task intent into the right monthly cells, from the table's own structure |
label_resolve.py |
Resolves a label intent to its value cell by text match + spatial rule |
identity_fill.py |
Auto-fills IDENT (identity/institution) tables from user_data, with zero fabrication |
table_resolve.py |
Nested-table resolver (passes through layout frames) |
toc_detection.py |
TOC detection · table-classification helpers · blank-detection regex |
reference_reader.py |
Reference-file parser: TXT/MD/PDF/HWPX/DOCX/HTML |
schedule_handler.py |
Gantt-chart metadata extraction |
verify_output.py |
Output structural verification gate |
measure_fill_rate.py |
Fill-rate measurement (accurate, computed against the template) |
digest.py |
Compact structural digest generation (computed from elements alone; primary input for the design stage) |
hwpx_compat.py / hwpx_utils.py |
HWPX-package compatibility layer · shared utilities |
update_check.py |
PyPI latest-version check/notice (pip channel) |
self_update.py |
Standalone-binary self-update (private repo, requires auth) |
bump_version.py |
Bulk version bump · release · CI consistency check |
ReportGen-pipeline/
├── scripts/ # all modules listed above + archive/ (legacy scripts)
├── tests/ # pytest suite (103+ passing)
├── java/ # HWP→HWPX converter (Convert.java, hwp2hwpx-fat.jar)
├── .claude-plugin/ # Claude Code marketplace catalog
├── reportgen/ # Claude Code plugin (distribution copy: plugin.json + SKILL.md)
├── .claude/skills/ # project-scoped skill (plugin mirror)
├── .github/workflows/ # ci.yml · publish.yml (PyPI) · build-binaries.yml
├── docs/ # design proposals
├── pyproject.toml # package metadata · build config
└── requirements.txt
Table classification scheme
| Class | Criteria | Handling |
|---|---|---|
DATA |
Ordinary data table | Filled by the agent (fill_cell) |
INSTR |
Contains authoring instructions ("delete before submission") | Preserved (never touched) |
SKIP |
Org chart, WBS, empty grid | Preserved as-is |
SCHED |
Gantt chart (task rows + monthly columns) | Filled via a schedule intent mapping |
IDENT |
PI/institution identity table | Auto-filled from user_data if present, otherwise preserved |
Claude Code Skill
ReportGen ships as a CLI-driven Claude Code skill — invoking /reportgen doesn't run a hosted service; it drives the same reportgen CLI described above from your local shell, with an external agent (Claude Code itself, in this case) doing the analysis and fill-content authoring per the LLM Allocation model. You can use it two ways:
Option 1 — Plugin marketplace (recommended, auto-upgrading)
/plugin marketplace add kaismin82/ReportGen-pipeline
/plugin install reportgen@reportgen-marketplace
New releases are detected and downloaded automatically in the background, and activate automatically the next session (restart) with no command needed (run /reload-plugins once to pick it up immediately in the current session). ⚠️ Since this repository is private, this channel is also collaborator-only.
Option 2 — Directly from the repository
Cloning the repository makes .claude/skills/reportgen/SKILL.md recognized immediately as a project-scoped skill. Update with git pull.
Use the /reportgen skill to draft a project plan matching this form.
- template: input/project-plan-form.hwpx
- reference files: input/project-summary.txt input/rfp.pdf
- output file: output/result.hwpx
The skill runs Phase 1 automatically → drafts mappings.json from reference material and web search → runs Phase 2 → confirms fill rate with --measure.
Why Not Just Ask Codex / Claude Code / OpenCode Directly?
You can always just type "please fill out this template" at any coding agent, without this skill. Here's concretely what that gives up, and what invoking /reportgen (or driving the CLI directly) changes instead:
| Asking the agent directly | Using /reportgen |
|
|---|---|---|
| Structure discovery | The agent reads the file once, informally, and guesses which paragraphs/cells are blanks vs. instructions to leave alone | Every table is explicitly classified (DATA/INSTR/SKIP/SCHED/IDENT) and every paragraph placeholder is detected before any content is written — instruction tables and diagram-like tables are never touched by accident |
| Table cell targeting | The agent typically hand-counts rows/columns from what it just read, which breaks silently the next time the form's layout differs slightly | label/schedule intent fields resolve coordinates dynamically from the document's own structure — the same mapping-authoring approach transfers to a differently-shaped form of the same kind, with no new code |
| Token cost on large forms | The agent re-reads the entire document — and often re-reads it again mid-edit — so cost scales with full document size every time | The design step reads a compact digest (tens of KB) instead of the full structure dump — measured example: a 29-table form went from a 1.5MB dump to a 45KB digest |
| Model tier | One model does everything at whatever tier you happened to invoke — overpaying for mechanical fill-ins, or underpaying for the one decision (what goes where, how much) that actually determines quality | Explicit 3-stage tiering: high-tier for the structural design decision, mid-tier for writing the actual content, no model at all for verification — see LLM Allocation |
| Verification | "Looks right" by skimming the output, if it's checked at all | A deterministic fill-rate gate reports exactly which targets are still empty or under length, measured against the original template — not a self-assessment by the same model that wrote the content |
| Identity/PI fields | An agent under a blanket "fill in everything" instruction will sometimes invent a plausible-looking name, phone number, or ID rather than leave a field blank | Zero-fabrication by design: unmatched or ambiguous identity fields are left blank with a bracketed "needs input" marker instead of guessed |
| Repeatability across forms | Every new template is a fresh, unstructured task — nothing from the last run transfers | The same analyze → design → apply → verify contract applies to every form of a given file type; only the content changes |
None of this makes ReportGen "smarter" than the agent — the agent still writes every sentence. What it adds is the scaffolding around that: a structural contract the agent fills in a repeatable way, and a deterministic check afterward that doesn't depend on the same agent grading its own homework.
Prompting examples
Without the skill (works, but gives up everything in the table above):
Please fill out input/irb-protocol-template.docx as a research plan for
an AI model that classifies 5 subtypes of intracranial hemorrhage on
non-contrast CT, and save it as output/protocol.docx.
With the skill — same request, routed through the methodology (template is .docx, so this routes to the docx skill per Supported Template Formats):
/reportgen
Use the reportgen skill to fill out the attached template.
- template: input/irb-protocol-template.docx
- reference: none — use web search for the clinical/technical background
- topic: AI model for 5-subtype classification of intracranial hemorrhage on
non-contrast CT, with automated structured report generation
- output: output/protocol.docx
For an HWPX national R&D plan with reference material already on hand (runs through ReportGen's native engine):
/reportgen
Use the reportgen skill to draft a project plan matching this form.
- template: input/project-plan-form.hwpx
- reference files: input/project-summary.txt input/rfp.pdf
- output file: output/result.hwpx
You don't need to spell out the phase mechanics (digest-first analysis, model tiering, verification) in the prompt itself — that's what SKILL.md already encodes. What you supply is the template, whatever reference material exists (or an explicit note that there is none and web search should fill the gap), and where the output should go.
Versioning & Release Automation
Version strings (pyproject.toml, universal_pipeline.py, plugin.json) are managed as a single source of truth by scripts/bump_version.py:
python scripts/bump_version.py 0.3.0 # bump the version everywhere (incl. SKILL.md mirror sync)
python scripts/bump_version.py 0.3.0 --release # + commit · tag (v & reportgen--v) · push · GitHub release
python scripts/bump_version.py --check # CI consistency check (run automatically by ci.yml)
Once a GitHub Release is published, two workflows follow automatically:
publish.yml→ publishes sdist/wheel to PyPI via Trusted Publishing (OIDC) — no token needed (requires a one-time PyPI pending-publisher + GitHubpypienvironment setup)build-binaries.yml→ builds, verifies, and attaches standalone binaries for the Linux/macOS/Windows matrix as release assets
FAQ
Q: I get ImportError: cannot import name 'HwpxPackage' from 'hwpx'.
A conflicting, unrelated package also named hwpx is installed in your conda environment. Run pip install python-hwpx --force-reinstall.
Q: After Phase 1, which files do I hand to the external agent?
Hand it request.json (from --emit-mapping-request), the compact digest (from --emit-digest), and prompt.md (from --prompt-output) if you generated one. The agent should design the fill plan from the digest, target only the specific elements it needs from request.json, and write a FieldMapping[] JSON array to mappings.json.
Q: The analysis stage burns too many tokens on a large, table-heavy form.
Generate the compact digest with --emit-digest and feed that to the design-stage model instead of request.json. The digest doesn't repeat each element's full text — it carries only indices, previews, table classifications, and fill coordinates, compressing a 29-table form's request.json from 1.5MB down to 45KB in one measured case. Only look up request.json by element_index when you need a specific element's exact source text.
Q: My paragraph fill rate comes out low.
Always pass --template alongside --measure. Fill quality itself depends on the external agent's model and prompt quality — see LLM Allocation.
Q: An instruction table got filled in.
structure_analyzer.py's _is_instruction_table() treats a "delete before submission" marker as a strong signal. If your form doesn't carry that marker, add another instruction signal to _DELETE_RE.
Q: The Gantt chart / schedule table gets filled oddly.
Prefer a schedule intent mapping over hand-picked coordinates — it lets schedule_resolve.py detect the month-header row and task blocks from the table's own structure. Structural metadata is also exposed via schedule_handler.detect_schedule_meta() in request.json if you need to inspect it directly.
Q: My template is a .docx or .pdf, not .hwpx — can I still use this?
Yes. reportgen itself only parses HWPX, but the skill routes .docx templates to the docx skill and .pdf templates to the pdf skill, applying the same analyze → design → apply → verify methodology through each tool's native editing approach. See Supported Template Formats. Reference material, separately, works natively in --reference for all of TXT/MD/PDF/HWPX/DOCX/HTML regardless of the template's own format.
Q: Why do the pip channel and the standalone-binary channel self-update differently? A pip package lives inside a shared venv / pinned-version environment, so silently bumping its own version could break a user's lockfile — hence "notify only." A standalone binary owns nothing but itself, so a true self-replace is safe.
Development
pip install -e ".[test]"
pytest tests/ -v # full suite
pytest tests/test_output_qa.py tests/test_smart_fill_engine_p0.py -v # core invariants only
python scripts/bump_version.py --check # version consistency check
| Test file | Verifies |
|---|---|
test_output_qa.py |
Absence of stale linesegarray · cell placement · resolver invariants |
test_smart_fill_engine_p0.py |
replace/fill_cell/linesegarray stripping |
test_structure_analyzer_p1.py |
TOC detection · header extraction · instruction tables |
test_mapping_artifact_handoff.py |
Phase 1/2 CLI round-trip |
test_self_update.py |
Platform → asset-name mapping, version comparison, asset-selection logic |
test_digest.py |
Table-classification precedence, fill-target extraction, large-table coordinate-omission threshold |
test_e2e_pipeline.py |
Full flow from structure analysis through SmartFillEngine |
test_korean_edge_cases.py |
Full-width brackets, ZWSP, full-width-space blank detection |
test_schedule_table.py |
Gantt-table detection · metadata extraction |
test_mapping_resolve.py |
label/schedule intent dispatch and fail-soft skipping |
test_schedule_resolve.py |
Dynamic month/task-block detection across varied Gantt shapes |
test_label_resolve.py |
Label text matching + spatial value-cell resolution |
test_identity_fill.py |
Zero-fabrication identity auto-fill, duplicate-label safety |
test_quality_gates.py |
Section-tier classification and content-length quality gates |
test_reference_p2.py |
Reference-file reading across TXT/PDF/HWPX/DOCX/HTML, format dispatch, clear errors on legacy .doc/.hwp |
License & Credits
MIT — see LICENSE. Free to use, modify, and distribute.
| Project | Role | License |
|---|---|---|
| python-hwpx | HWPX file parsing/packaging (HwpxPackage) |
MIT |
| hwp2hwpx by neolord0 | HWP → HWPX binary conversion (Java) | Apache 2.0 |
| @ohah/hwpjs by ohah | HWP → JSON/Markdown/HTML (Node.js) | MIT |
| lxml | HWPX XML parsing and manipulation | BSD |
| python-dotenv | .env environment-variable loading |
BSD |
| pypdf | PDF text extraction | BSD |
Reference & inspiration: hwp-pipeline (Yoojin-nam) — the Claude Code skill whose early design informed this project · the HWP/HWPX format specification (Hancom HWPML 2011/2016) · Claude Code by Anthropic
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reportgen_pipeline-0.3.1.tar.gz.
File metadata
- Download URL: reportgen_pipeline-0.3.1.tar.gz
- Upload date:
- Size: 162.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d338adef14efc5616521714510ea20312229d47ccb0b44a00bd51c21283b5565
|
|
| MD5 |
ec3839c70fb24f444469a214b3dd7e15
|
|
| BLAKE2b-256 |
001ef31e6994af316ba579715923843addd45184ef273983784256f885ec5288
|
Provenance
The following attestation bundles were made for reportgen_pipeline-0.3.1.tar.gz:
Publisher:
publish.yml on kaismin82/ReportGen-pipeline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reportgen_pipeline-0.3.1.tar.gz -
Subject digest:
d338adef14efc5616521714510ea20312229d47ccb0b44a00bd51c21283b5565 - Sigstore transparency entry: 2191214587
- Sigstore integration time:
-
Permalink:
kaismin82/ReportGen-pipeline@c0dbf1663e83ca54a73358600ed0be18721dbd65 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/kaismin82
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c0dbf1663e83ca54a73358600ed0be18721dbd65 -
Trigger Event:
release
-
Statement type:
File details
Details for the file reportgen_pipeline-0.3.1-py3-none-any.whl.
File metadata
- Download URL: reportgen_pipeline-0.3.1-py3-none-any.whl
- Upload date:
- Size: 101.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df05bc219ad49d17dd00889ce7aa10e00d2f22492a12d7afce2b5cf58fdf9d38
|
|
| MD5 |
fd3dbc2d81e04f67ce96b6c1dd39742a
|
|
| BLAKE2b-256 |
fe153da9c4ff4a061b537396bf68a72b928bc89c8c40cb2151f3e043566b2f2f
|
Provenance
The following attestation bundles were made for reportgen_pipeline-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on kaismin82/ReportGen-pipeline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reportgen_pipeline-0.3.1-py3-none-any.whl -
Subject digest:
df05bc219ad49d17dd00889ce7aa10e00d2f22492a12d7afce2b5cf58fdf9d38 - Sigstore transparency entry: 2191214970
- Sigstore integration time:
-
Permalink:
kaismin82/ReportGen-pipeline@c0dbf1663e83ca54a73358600ed0be18721dbd65 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/kaismin82
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c0dbf1663e83ca54a73358600ed0be18721dbd65 -
Trigger Event:
release
-
Statement type: