folioqueue 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- folioqueue-0.1.0/.gitignore +13 -0
- folioqueue-0.1.0/CHANGELOG.md +14 -0
- folioqueue-0.1.0/CONTRIBUTING.md +32 -0
- folioqueue-0.1.0/LICENSE +21 -0
- folioqueue-0.1.0/PKG-INFO +171 -0
- folioqueue-0.1.0/README.md +141 -0
- folioqueue-0.1.0/README.zh-CN.md +70 -0
- folioqueue-0.1.0/SECURITY.md +24 -0
- folioqueue-0.1.0/docs/design.md +47 -0
- folioqueue-0.1.0/docs/evidence/synthetic-batch.json +48 -0
- folioqueue-0.1.0/docs/research.md +26 -0
- folioqueue-0.1.0/docs/validation.md +82 -0
- folioqueue-0.1.0/examples/documents/inventory.csv +3 -0
- folioqueue-0.1.0/examples/documents/nested/guide.md +8 -0
- folioqueue-0.1.0/examples/documents/unsupported.bin +1 -0
- folioqueue-0.1.0/examples/documents/welcome.txt +4 -0
- folioqueue-0.1.0/pyproject.toml +65 -0
- folioqueue-0.1.0/scripts/validate_release.py +91 -0
- folioqueue-0.1.0/src/folioqueue/__init__.py +3 -0
- folioqueue-0.1.0/src/folioqueue/__main__.py +3 -0
- folioqueue-0.1.0/src/folioqueue/cli.py +134 -0
- folioqueue-0.1.0/src/folioqueue/engine.py +310 -0
- folioqueue-0.1.0/src/folioqueue/paths.py +106 -0
- folioqueue-0.1.0/src/folioqueue/report.py +69 -0
- folioqueue-0.1.0/src/folioqueue/storage.py +124 -0
- folioqueue-0.1.0/src/folioqueue/worker.py +105 -0
- folioqueue-0.1.0/tests/conftest.py +68 -0
- folioqueue-0.1.0/tests/test_documents.py +29 -0
- folioqueue-0.1.0/tests/test_engine.py +272 -0
- folioqueue-0.1.0/tests/test_paths_cli_worker.py +194 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-09-08
|
|
4
|
+
|
|
5
|
+
Initial alpha release.
|
|
6
|
+
|
|
7
|
+
- Local recursive TXT/Markdown/CSV conversion with optional MarkItDown PDF/DOCX/HTML extraction.
|
|
8
|
+
- Bounded one-file worker processes and timeout/error isolation.
|
|
9
|
+
- Input snapshots, checksum-based incremental decisions and per-file write-ahead checkpoints.
|
|
10
|
+
- Conservative output ownership and source-extension-preserving names.
|
|
11
|
+
- Read-only plan command, JSON/HTML reports and stable exit codes.
|
|
12
|
+
- Synthetic regression fixtures, cross-platform CI and English/Chinese documentation.
|
|
13
|
+
|
|
14
|
+
Known limits: no OCR, no packaged desktop app, no hostile-document sandbox. See the README and validation record.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
FolioQueue welcomes reproducible bug reports, documentation corrections, compatibility tests and focused changes to the local conversion workflow.
|
|
4
|
+
|
|
5
|
+
## Before contributing
|
|
6
|
+
|
|
7
|
+
Read the README and `docs/design.md`. Discuss large features before implementation; the initial scope intentionally excludes OCR, cloud services, desktop UI, RAG chunking and an HTTP API.
|
|
8
|
+
|
|
9
|
+
For a bug report, include your OS, Python and FolioQueue/MarkItDown versions, command flags, expected behavior and the report's error code. Attach only synthetic or non-sensitive samples you are authorized to share. Filenames and reports can be sensitive. Do not attach your private ledger or real customer documents.
|
|
10
|
+
|
|
11
|
+
## Development checks
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python -m pip install -e ".[test,documents]"
|
|
15
|
+
python -m pytest --cov=folioqueue --cov-report=term-missing
|
|
16
|
+
python -m ruff check .
|
|
17
|
+
python -m ruff format --check .
|
|
18
|
+
python -m build
|
|
19
|
+
python -m twine check dist/*
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Tests should demonstrate an observable contract or failure recovery, not repeat the implementation. Parser fixes need a small redistributable fixture. Please identify which platforms you actually tested.
|
|
23
|
+
|
|
24
|
+
Keep changes focused, describe the problem and final behavior, and include validation. Preserve existing output-ownership guarantees. Contributions are accepted under the repository's MIT license; preserve third-party notices when appropriate.
|
|
25
|
+
|
|
26
|
+
## AI-assisted contributions
|
|
27
|
+
|
|
28
|
+
AI assistance is welcome. The contributor is responsible for understanding the change, verifying behavior and checking attribution.
|
|
29
|
+
|
|
30
|
+
## Maintenance
|
|
31
|
+
|
|
32
|
+
The repository owner, GokouRuri43, is the initial maintainer. Release review covers tests, package install smoke checks, documentation accuracy and known limitations. No response-time SLA is offered.
|
folioqueue-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GokouRuri43
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: folioqueue
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Restartable local document-to-Markdown batches with a checksum ledger and failure isolation
|
|
5
|
+
Project-URL: Homepage, https://github.com/GokouRuri43/folioqueue
|
|
6
|
+
Project-URL: Issues, https://github.com/GokouRuri43/folioqueue/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/GokouRuri43/folioqueue/blob/main/CHANGELOG.md
|
|
8
|
+
Author: GokouRuri43
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,document-conversion,incremental,markdown,markitdown
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Provides-Extra: documents
|
|
22
|
+
Requires-Dist: markitdown[docx,pdf]<0.2,>=0.1.7; extra == 'documents'
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: build<2,>=1; extra == 'test'
|
|
25
|
+
Requires-Dist: pytest-cov<8,>=6; extra == 'test'
|
|
26
|
+
Requires-Dist: pytest<10,>=8; extra == 'test'
|
|
27
|
+
Requires-Dist: ruff<1,>=0.11; extra == 'test'
|
|
28
|
+
Requires-Dist: twine<7,>=6; extra == 'test'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# FolioQueue
|
|
32
|
+
|
|
33
|
+
**Restartable local document-to-Markdown batches, with a checksum ledger and inspectable failures.**
|
|
34
|
+
|
|
35
|
+
[](https://github.com/GokouRuri43/folioqueue/actions/workflows/ci.yml)
|
|
36
|
+
[](https://www.python.org/downloads/)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
|
|
39
|
+
[简体中文](README.zh-CN.md) · [Design](docs/design.md) · [Validation](docs/validation.md) · [Contributing](CONTRIBUTING.md)
|
|
40
|
+
|
|
41
|
+
FolioQueue helps maintain a Markdown copy of a **local document collection**. It snapshots each input, converts files in separate processes, checkpoints completed work, and checks both source and output hashes before skipping an unchanged file. A broken document can fail while the rest of the batch finishes.
|
|
42
|
+
|
|
43
|
+
**Status: 0.1.0 alpha.** See the validation record for what has actually been tested.
|
|
44
|
+
|
|
45
|
+
## Who is this for?
|
|
46
|
+
|
|
47
|
+
- **Note / knowledge-base maintainers** folding PDFs, Word and HTML into a Markdown vault, and keeping it in sync as sources change.
|
|
48
|
+
- **Local RAG / LLM corpus builders** who need a reproducible, incremental Markdown mirror of a document folder to index.
|
|
49
|
+
- **Self-hosted archive keepers** who want failures isolated per file and edited output protected, instead of a one-shot bulk convert.
|
|
50
|
+
|
|
51
|
+
## Why use it?
|
|
52
|
+
|
|
53
|
+
- **Resume by rerunning.** Completed files are checkpointed individually; failed files are retried on the next run.
|
|
54
|
+
- **Detect real changes.** SHA-256 checksums, rather than timestamps alone, determine whether to convert. Converter dependency changes invalidate document caches.
|
|
55
|
+
- **Protect edits.** Untracked or manually changed output is a conflict, even with `--force`.
|
|
56
|
+
- **Keep names distinct.** `report.pdf` → `documents/report.pdf.md`; `report.docx` → `documents/report.docx.md`.
|
|
57
|
+
- **Contain ordinary failures.** Bounded parallel file processes, per-file timeouts, input/output size checks, and a DOCX expansion preflight.
|
|
58
|
+
- **Inspect every outcome.** Local HTML and JSON reports list converted, skipped, failed, ignored and stale files. Reports omit extracted text and raw converter exceptions.
|
|
59
|
+
- **Plan first.** `plan` shows per-file decisions without creating files.
|
|
60
|
+
|
|
61
|
+
This is an independently implemented workflow layer. PDF/DOCX/HTML extraction is delegated to [Microsoft MarkItDown](https://github.com/microsoft/markitdown); this project is not affiliated with Microsoft or OpenAI. It does not claim to improve PDF extraction fidelity. [Alternatives and research](docs/research.md).
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
Python 3.11 or later is required. Use a virtual environment. On Windows, the Python launcher may be `py` instead of `python`.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/GokouRuri43/folioqueue.git
|
|
69
|
+
cd folioqueue
|
|
70
|
+
python -m pip install ".[documents]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`python -m pip install .` installs the dependency-free TXT/Markdown/CSV core. The `documents` extra adds PDF, DOCX and HTML through MarkItDown. A wheel and source archive are also provided in GitHub Releases; the project is **not currently published to PyPI**.
|
|
74
|
+
|
|
75
|
+
## Try it on the included examples
|
|
76
|
+
|
|
77
|
+
Run these commands from the repository directory:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
folioqueue plan examples/documents -o demo-output --json
|
|
81
|
+
folioqueue convert examples/documents -o demo-output
|
|
82
|
+
folioqueue convert examples/documents -o demo-output
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The first conversion produces three Markdown files and ignores one unsupported fixture. The second skips all three unchanged files. Open `demo-output/report.html` to inspect the latest run.
|
|
86
|
+
|
|
87
|
+
For your own collection:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
folioqueue convert ./documents -o ./markdown-output --workers 2 --timeout 60
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
On Windows:
|
|
94
|
+
|
|
95
|
+
```powershell
|
|
96
|
+
folioqueue convert 'C:\My Documents' -o 'C:\Markdown Output' --workers 2
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Source and output directories must not overlap. Hidden-name files/directories, symlinks and Windows junctions are skipped. No URL inputs, cloud services, LLM API calls, third-party MarkItDown plugins, or shell commands are used by the conversion workflow. Dependencies must be installed beforehand.
|
|
100
|
+
|
|
101
|
+
## Supported formats
|
|
102
|
+
|
|
103
|
+
| Input | Backend | Boundaries |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| `.txt`, `.md` | Standard library | Strict UTF-8 with optional BOM by default; `--encoding` selects another encoding |
|
|
106
|
+
| `.csv` | Standard library | Comma-separated, first row as header; quoted commas/newlines supported; Markdown cell escaping |
|
|
107
|
+
| `.html`, `.htm` | MarkItDown | Text extraction; no browser, script execution or asset downloading is requested |
|
|
108
|
+
| `.docx` | MarkItDown | Extraction quality follows upstream; no visual layout preservation |
|
|
109
|
+
| `.pdf` | MarkItDown | Text-based PDFs; no OCR, no guarantee of correct reading order or tables |
|
|
110
|
+
|
|
111
|
+
Empty extracted text is a failure, including a scanned PDF with no text layer. Legacy `.doc`, spreadsheets, slides, images, media, archives and encrypted documents are outside the v0.1 support scope. Source documents remain the authoritative copy.
|
|
112
|
+
|
|
113
|
+
## Controls and exit codes
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
folioqueue convert ./documents -o ./markdown-output --types txt,csv,docx
|
|
117
|
+
folioqueue convert ./documents -o ./markdown-output --encoding gb18030
|
|
118
|
+
folioqueue convert ./documents -o ./markdown-output --max-input-mb 64 --max-output-mb 32
|
|
119
|
+
folioqueue convert ./documents -o ./markdown-output --force --json
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`--workers` is 1–16 (default 2). `--timeout` covers each converter subprocess, including imports, but not scanning, hashing, copying or committing. `--force` reconverts owned, unedited output; it never authorizes overwriting a conflict. Move conflicting output aside or use a new output directory.
|
|
123
|
+
|
|
124
|
+
| Exit | Meaning |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `0` | No failed files / no blocking plan decisions; ignored and stale entries are informational |
|
|
127
|
+
| `1` | At least one failed conversion or planned conflict/error |
|
|
128
|
+
| `2` | Invalid arguments, invalid ledger, overlapping roots, lock contention or a run-level filesystem error |
|
|
129
|
+
| `130` | Interrupted; rerun to continue from completed checkpoints |
|
|
130
|
+
|
|
131
|
+
Deleted source files are reported as **stale**; their output is retained. A failed updated source can leave the previous Markdown in place. Consumers must check `report.json` and must not assume every existing Markdown file is current. The report describes the most recent completed run, not a global corpus validity certificate.
|
|
132
|
+
|
|
133
|
+
## Output
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
markdown-output/
|
|
137
|
+
documents/
|
|
138
|
+
report.pdf.md
|
|
139
|
+
subfolder/notes.txt.md
|
|
140
|
+
report.html
|
|
141
|
+
report.json
|
|
142
|
+
.folioqueue/
|
|
143
|
+
state.json
|
|
144
|
+
writer.lock
|
|
145
|
+
work/
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The private ledger binds an output directory to one absolute source path. Do not edit it or share it as a public artifact. Moving the source requires a new output directory in v0.1. A kernel-managed exclusive writer lock is automatically released on process exit; the lock file may remain and should not be deleted while a run is active.
|
|
149
|
+
|
|
150
|
+
Interrupted conversions may leave temporary source snapshots in `.folioqueue/work`. Once no run is active, you may remove that directory to reclaim space. A subprocess is **failure isolation, not a security sandbox**; process only trusted documents or use an external sandbox for untrusted inputs. See [SECURITY.md](SECURITY.md).
|
|
151
|
+
|
|
152
|
+
## Development
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
python -m pip install -e ".[test,documents]"
|
|
156
|
+
python -m pytest --cov=folioqueue --cov-report=term-missing
|
|
157
|
+
python -m ruff check .
|
|
158
|
+
python -m ruff format --check .
|
|
159
|
+
python -m build
|
|
160
|
+
python -m twine check dist/*
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The test suite includes synthetic, redistributable PDF/DOCX/HTML fixtures and actual subprocess conversions. CI tests Windows, Linux and macOS. The workflow result, rather than this sentence, is the authority for current pass/fail status.
|
|
164
|
+
|
|
165
|
+
## Roadmap
|
|
166
|
+
|
|
167
|
+
1. Collect reproducible reports from document-collection maintainers and improve format diagnostics.
|
|
168
|
+
2. Publish larger, redistributable corpus results and measure overhead, failure behavior and memory use.
|
|
169
|
+
3. Consider an explicit stale-output review command and portable ledger migration after the core behavior is exercised.
|
|
170
|
+
|
|
171
|
+
Requests for unsupported features belong in issues with a concrete workflow and a minimal non-sensitive sample. No telemetry is collected by FolioQueue.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# FolioQueue
|
|
2
|
+
|
|
3
|
+
**Restartable local document-to-Markdown batches, with a checksum ledger and inspectable failures.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/GokouRuri43/folioqueue/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
[简体中文](README.zh-CN.md) · [Design](docs/design.md) · [Validation](docs/validation.md) · [Contributing](CONTRIBUTING.md)
|
|
10
|
+
|
|
11
|
+
FolioQueue helps maintain a Markdown copy of a **local document collection**. It snapshots each input, converts files in separate processes, checkpoints completed work, and checks both source and output hashes before skipping an unchanged file. A broken document can fail while the rest of the batch finishes.
|
|
12
|
+
|
|
13
|
+
**Status: 0.1.0 alpha.** See the validation record for what has actually been tested.
|
|
14
|
+
|
|
15
|
+
## Who is this for?
|
|
16
|
+
|
|
17
|
+
- **Note / knowledge-base maintainers** folding PDFs, Word and HTML into a Markdown vault, and keeping it in sync as sources change.
|
|
18
|
+
- **Local RAG / LLM corpus builders** who need a reproducible, incremental Markdown mirror of a document folder to index.
|
|
19
|
+
- **Self-hosted archive keepers** who want failures isolated per file and edited output protected, instead of a one-shot bulk convert.
|
|
20
|
+
|
|
21
|
+
## Why use it?
|
|
22
|
+
|
|
23
|
+
- **Resume by rerunning.** Completed files are checkpointed individually; failed files are retried on the next run.
|
|
24
|
+
- **Detect real changes.** SHA-256 checksums, rather than timestamps alone, determine whether to convert. Converter dependency changes invalidate document caches.
|
|
25
|
+
- **Protect edits.** Untracked or manually changed output is a conflict, even with `--force`.
|
|
26
|
+
- **Keep names distinct.** `report.pdf` → `documents/report.pdf.md`; `report.docx` → `documents/report.docx.md`.
|
|
27
|
+
- **Contain ordinary failures.** Bounded parallel file processes, per-file timeouts, input/output size checks, and a DOCX expansion preflight.
|
|
28
|
+
- **Inspect every outcome.** Local HTML and JSON reports list converted, skipped, failed, ignored and stale files. Reports omit extracted text and raw converter exceptions.
|
|
29
|
+
- **Plan first.** `plan` shows per-file decisions without creating files.
|
|
30
|
+
|
|
31
|
+
This is an independently implemented workflow layer. PDF/DOCX/HTML extraction is delegated to [Microsoft MarkItDown](https://github.com/microsoft/markitdown); this project is not affiliated with Microsoft or OpenAI. It does not claim to improve PDF extraction fidelity. [Alternatives and research](docs/research.md).
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
Python 3.11 or later is required. Use a virtual environment. On Windows, the Python launcher may be `py` instead of `python`.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/GokouRuri43/folioqueue.git
|
|
39
|
+
cd folioqueue
|
|
40
|
+
python -m pip install ".[documents]"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`python -m pip install .` installs the dependency-free TXT/Markdown/CSV core. The `documents` extra adds PDF, DOCX and HTML through MarkItDown. A wheel and source archive are also provided in GitHub Releases; the project is **not currently published to PyPI**.
|
|
44
|
+
|
|
45
|
+
## Try it on the included examples
|
|
46
|
+
|
|
47
|
+
Run these commands from the repository directory:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
folioqueue plan examples/documents -o demo-output --json
|
|
51
|
+
folioqueue convert examples/documents -o demo-output
|
|
52
|
+
folioqueue convert examples/documents -o demo-output
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The first conversion produces three Markdown files and ignores one unsupported fixture. The second skips all three unchanged files. Open `demo-output/report.html` to inspect the latest run.
|
|
56
|
+
|
|
57
|
+
For your own collection:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
folioqueue convert ./documents -o ./markdown-output --workers 2 --timeout 60
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
On Windows:
|
|
64
|
+
|
|
65
|
+
```powershell
|
|
66
|
+
folioqueue convert 'C:\My Documents' -o 'C:\Markdown Output' --workers 2
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Source and output directories must not overlap. Hidden-name files/directories, symlinks and Windows junctions are skipped. No URL inputs, cloud services, LLM API calls, third-party MarkItDown plugins, or shell commands are used by the conversion workflow. Dependencies must be installed beforehand.
|
|
70
|
+
|
|
71
|
+
## Supported formats
|
|
72
|
+
|
|
73
|
+
| Input | Backend | Boundaries |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `.txt`, `.md` | Standard library | Strict UTF-8 with optional BOM by default; `--encoding` selects another encoding |
|
|
76
|
+
| `.csv` | Standard library | Comma-separated, first row as header; quoted commas/newlines supported; Markdown cell escaping |
|
|
77
|
+
| `.html`, `.htm` | MarkItDown | Text extraction; no browser, script execution or asset downloading is requested |
|
|
78
|
+
| `.docx` | MarkItDown | Extraction quality follows upstream; no visual layout preservation |
|
|
79
|
+
| `.pdf` | MarkItDown | Text-based PDFs; no OCR, no guarantee of correct reading order or tables |
|
|
80
|
+
|
|
81
|
+
Empty extracted text is a failure, including a scanned PDF with no text layer. Legacy `.doc`, spreadsheets, slides, images, media, archives and encrypted documents are outside the v0.1 support scope. Source documents remain the authoritative copy.
|
|
82
|
+
|
|
83
|
+
## Controls and exit codes
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
folioqueue convert ./documents -o ./markdown-output --types txt,csv,docx
|
|
87
|
+
folioqueue convert ./documents -o ./markdown-output --encoding gb18030
|
|
88
|
+
folioqueue convert ./documents -o ./markdown-output --max-input-mb 64 --max-output-mb 32
|
|
89
|
+
folioqueue convert ./documents -o ./markdown-output --force --json
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`--workers` is 1–16 (default 2). `--timeout` covers each converter subprocess, including imports, but not scanning, hashing, copying or committing. `--force` reconverts owned, unedited output; it never authorizes overwriting a conflict. Move conflicting output aside or use a new output directory.
|
|
93
|
+
|
|
94
|
+
| Exit | Meaning |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| `0` | No failed files / no blocking plan decisions; ignored and stale entries are informational |
|
|
97
|
+
| `1` | At least one failed conversion or planned conflict/error |
|
|
98
|
+
| `2` | Invalid arguments, invalid ledger, overlapping roots, lock contention or a run-level filesystem error |
|
|
99
|
+
| `130` | Interrupted; rerun to continue from completed checkpoints |
|
|
100
|
+
|
|
101
|
+
Deleted source files are reported as **stale**; their output is retained. A failed updated source can leave the previous Markdown in place. Consumers must check `report.json` and must not assume every existing Markdown file is current. The report describes the most recent completed run, not a global corpus validity certificate.
|
|
102
|
+
|
|
103
|
+
## Output
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
markdown-output/
|
|
107
|
+
documents/
|
|
108
|
+
report.pdf.md
|
|
109
|
+
subfolder/notes.txt.md
|
|
110
|
+
report.html
|
|
111
|
+
report.json
|
|
112
|
+
.folioqueue/
|
|
113
|
+
state.json
|
|
114
|
+
writer.lock
|
|
115
|
+
work/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The private ledger binds an output directory to one absolute source path. Do not edit it or share it as a public artifact. Moving the source requires a new output directory in v0.1. A kernel-managed exclusive writer lock is automatically released on process exit; the lock file may remain and should not be deleted while a run is active.
|
|
119
|
+
|
|
120
|
+
Interrupted conversions may leave temporary source snapshots in `.folioqueue/work`. Once no run is active, you may remove that directory to reclaim space. A subprocess is **failure isolation, not a security sandbox**; process only trusted documents or use an external sandbox for untrusted inputs. See [SECURITY.md](SECURITY.md).
|
|
121
|
+
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
python -m pip install -e ".[test,documents]"
|
|
126
|
+
python -m pytest --cov=folioqueue --cov-report=term-missing
|
|
127
|
+
python -m ruff check .
|
|
128
|
+
python -m ruff format --check .
|
|
129
|
+
python -m build
|
|
130
|
+
python -m twine check dist/*
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The test suite includes synthetic, redistributable PDF/DOCX/HTML fixtures and actual subprocess conversions. CI tests Windows, Linux and macOS. The workflow result, rather than this sentence, is the authority for current pass/fail status.
|
|
134
|
+
|
|
135
|
+
## Roadmap
|
|
136
|
+
|
|
137
|
+
1. Collect reproducible reports from document-collection maintainers and improve format diagnostics.
|
|
138
|
+
2. Publish larger, redistributable corpus results and measure overhead, failure behavior and memory use.
|
|
139
|
+
3. Consider an explicit stale-output review command and portable ledger migration after the core behavior is exercised.
|
|
140
|
+
|
|
141
|
+
Requests for unsupported features belong in issues with a concrete workflow and a minimal non-sensitive sample. No telemetry is collected by FolioQueue.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# FolioQueue
|
|
2
|
+
|
|
3
|
+
**可重复执行、逐文件保存进度的本地文档转 Markdown 工具。**
|
|
4
|
+
|
|
5
|
+
[English](README.md) · [设计](docs/design.md) · [验证记录](docs/validation.md)
|
|
6
|
+
|
|
7
|
+
适合维护本地文档集合和知识库:文件变化后重新转换,未变化的文件跳过,失败文件下次重试。PDF、DOCX、HTML 的底层提取使用 Microsoft MarkItDown;TXT、Markdown、CSV 使用 Python 标准库。
|
|
8
|
+
|
|
9
|
+
**当前为 0.1.0 alpha。** 它是独立的工作流工具,与 Microsoft、OpenAI 没有隶属关系。
|
|
10
|
+
|
|
11
|
+
## 适用人群
|
|
12
|
+
|
|
13
|
+
- **笔记 / 知识库维护者**:把 PDF、Word、HTML 并入 Markdown 库,并在源文件变化后保持同步。
|
|
14
|
+
- **本地 RAG / LLM 语料构建者**:需要一个可复现、增量的 Markdown 镜像目录用于索引。
|
|
15
|
+
- **自托管资料整理者**:希望失败按文件隔离、已编辑输出不被覆盖,而不是一次性批量转换。
|
|
16
|
+
|
|
17
|
+
## 安装和使用
|
|
18
|
+
|
|
19
|
+
需要 Python 3.11 或以上,建议在虚拟环境安装。Windows 的 Python 命令可能是 `py`。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/GokouRuri43/folioqueue.git
|
|
23
|
+
cd folioqueue
|
|
24
|
+
python -m pip install ".[documents]"
|
|
25
|
+
folioqueue plan examples/documents -o demo-output --json
|
|
26
|
+
folioqueue convert examples/documents -o demo-output
|
|
27
|
+
folioqueue convert examples/documents -o demo-output
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
第一次转换三个示例文件并忽略一个不支持的文件;第二次应跳过三个未变化文件。打开 `demo-output/report.html` 查看结果。
|
|
31
|
+
|
|
32
|
+
仅需要 TXT、Markdown、CSV 时,执行 `python -m pip install .`,核心没有第三方运行依赖。GitHub Releases 提供 wheel 和源码包;**目前没有发布到 PyPI**。
|
|
33
|
+
|
|
34
|
+
转换自己的文件夹:
|
|
35
|
+
|
|
36
|
+
```powershell
|
|
37
|
+
folioqueue convert 'C:\My Documents' -o 'C:\Markdown Output' --workers 2 --timeout 60
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
输入和输出目录必须互不包含。默认递归扫描,跳过以点开头的文件/目录、符号链接和 Windows junction。支持 `.txt .md .csv .html .htm .docx .pdf`,不支持 OCR、旧版 `.doc`、表格文件、演示文稿、音视频、压缩包或 URL。
|
|
41
|
+
|
|
42
|
+
## 行为约定
|
|
43
|
+
|
|
44
|
+
- 每个文件在独立进程中转换,有超时与大小检查;一个文件失败不会让其他文件一起失败。
|
|
45
|
+
- 每完成一个文件保存一次检查点;中断后重新运行原命令即可继续。
|
|
46
|
+
- SHA-256 同时检查源文件和输出;修改时间不变也能检测到内容变化。
|
|
47
|
+
- 手动修改的输出或工具未记录的同名文件会报冲突,`--force` 也不会覆盖。请将冲突文件另存,或使用新输出目录。
|
|
48
|
+
- 保留原扩展名,例如 `报告.pdf` 输出为 `documents/报告.pdf.md`,避免与 `报告.docx` 冲突。
|
|
49
|
+
- 源文件被删除后,旧输出会保留并标记为 stale;更新失败也可能保留上次成功结果。导入知识库前需要检查报告。
|
|
50
|
+
- 报告包含相对文件名和状态,不包含提取正文或转换库的原始异常。文件名仍可能敏感。
|
|
51
|
+
- 转换流程不配置云服务或 LLM,不启用 MarkItDown 第三方插件。依赖需要预先安装。
|
|
52
|
+
|
|
53
|
+
## 常用选项
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
folioqueue convert ./documents -o ./out --types txt,csv,docx
|
|
57
|
+
folioqueue convert ./documents -o ./out --encoding gb18030
|
|
58
|
+
folioqueue convert ./documents -o ./out --max-input-mb 64 --max-output-mb 32
|
|
59
|
+
folioqueue convert ./documents -o ./out --force --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
并发默认 2,范围 1–16;转换子进程默认超时 60 秒。超时不包含扫描、校验和计算、复制和写入。CSV 为逗号分隔,第一行作为表头;文本默认严格按 UTF-8(兼容 BOM)解码。
|
|
63
|
+
|
|
64
|
+
退出码:`0` 无失败,`1` 有文件失败/计划冲突,`2` 参数或运行环境错误,`130` 被中断。`report.html` 和 `report.json` 是最近一次完成的运行报告,不代表目录中每个 Markdown 都一定是最新内容。
|
|
65
|
+
|
|
66
|
+
`.folioqueue/state.json` 包含绝对源目录和校验记录,不应手动修改或公开分享。源目录迁移时请使用新输出目录。强制终止后可能在 `.folioqueue/work` 留下源文件快照,确认没有运行中的任务后可手动删除该目录。
|
|
67
|
+
|
|
68
|
+
独立进程用于隔离普通故障,**不是安全沙箱**。处理不可信文件需要额外沙箱;大小检查也不是操作系统级内存限制。详见 [安全边界](SECURITY.md)。
|
|
69
|
+
|
|
70
|
+
欢迎提交可复现问题和脱敏样例。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Security policy and boundaries
|
|
2
|
+
|
|
3
|
+
The 0.1.x release line receives fixes as maintainers are able. This alpha has not undergone an independent security audit.
|
|
4
|
+
|
|
5
|
+
## Reporting
|
|
6
|
+
|
|
7
|
+
If private vulnerability reporting is enabled, use the repository's **Security → Report a vulnerability** flow. If unavailable, open a minimal issue requesting a private contact channel without posting exploit details, documents, tokens or private filesystem paths.
|
|
8
|
+
|
|
9
|
+
## Threat model
|
|
10
|
+
|
|
11
|
+
FolioQueue is for trusted local documents in a directory controlled by the user. It does not configure LLM/cloud clients, enable third-party MarkItDown plugins, call a shell or accept URL inputs. Optional parsers and their transitive dependencies are still part of the trusted computing base. Ordinary process isolation is not a security sandbox or a network firewall.
|
|
12
|
+
|
|
13
|
+
Input/output checksums, a cooperative writer lock, path checks, input snapshots, atomic output replacement, timeouts and admission limits reduce common operational failures. They do not protect against a compromised parser, malicious local process, filesystem race, resource exhaustion inside a parser, or a deliberately modified ledger.
|
|
14
|
+
|
|
15
|
+
The worker runs with the user's account permissions. Run untrusted documents only inside a separate sandbox with OS-enforced filesystem, network, CPU and memory limits. Markdown output can contain untrusted links or raw markup; review it before rendering in another application.
|
|
16
|
+
|
|
17
|
+
## Data retained locally
|
|
18
|
+
|
|
19
|
+
- Converted Markdown contains document text.
|
|
20
|
+
- The private ledger contains the absolute input root, relative paths and hashes.
|
|
21
|
+
- Reports contain relative filenames and error codes, but omit body text and raw parser exceptions.
|
|
22
|
+
- Temporary snapshots are normally removed after each job. Forced termination may leave copies in `.folioqueue/work`; remove that directory only after confirming no run is active.
|
|
23
|
+
|
|
24
|
+
Do not publish your output directory without reviewing it. The project itself has no telemetry or analytics code.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Design and invariants
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
FolioQueue is a workflow layer for repeated conversion of trusted local document collections. It implements scheduling, input snapshots, output ownership, incremental decisions and run reporting. MarkItDown performs the optional document extraction. There is no new PDF parser, OCR engine, browser service, LLM call, or public HTTP endpoint.
|
|
6
|
+
|
|
7
|
+
## Data flow
|
|
8
|
+
|
|
9
|
+
1. Validate separate roots and reject symlink/junction path components.
|
|
10
|
+
2. Acquire an OS-managed exclusive lock in the output directory.
|
|
11
|
+
3. Load a schema-versioned ledger bound to the source root; scan selected extensions.
|
|
12
|
+
4. Hash sources and check existing output ownership. A checksum mismatch is a conflict, including under `--force`.
|
|
13
|
+
5. Schedule at most `workers` jobs. Copy each input into a temporary snapshot, checking size and the planned checksum.
|
|
14
|
+
6. Spawn the same Python interpreter as a one-file worker. Discard converter stdout/stderr; accept a small structured status file and bounded Markdown output.
|
|
15
|
+
7. Recheck the live source and output, checkpoint pending ownership, atomically replace Markdown, and checkpoint success.
|
|
16
|
+
8. Write JSON and inert HTML reports for the completed run.
|
|
17
|
+
|
|
18
|
+
The report is relative-path-only. The private ledger contains an absolute source root to prevent accidental output reuse with an unrelated collection.
|
|
19
|
+
|
|
20
|
+
## Cache key
|
|
21
|
+
|
|
22
|
+
TXT/MD/CSV use the FolioQueue version, Python major/minor version and selected text encoding. Document formats additionally include the installed distribution names and versions, so a transitive converter dependency update invalidates document cache entries. This is deliberately conservative: installing an unrelated distribution can also cause reconversion.
|
|
23
|
+
|
|
24
|
+
Source and output SHA-256 hashes must both match. No timestamp-only fast path is used. Failed conversions are not cached as successful. Missing output is regenerated. `--force` bypasses only the unchanged-file shortcut.
|
|
25
|
+
|
|
26
|
+
## Commit interruption cases
|
|
27
|
+
|
|
28
|
+
| Interruption point | Next run |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Before pending checkpoint | Previous ledger/output remain authoritative |
|
|
31
|
+
| After pending checkpoint, before output replacement | Old owned hash is accepted, and the file is reconverted |
|
|
32
|
+
| After output replacement, before success checkpoint | Matching new output can be reused if source and fingerprint still match |
|
|
33
|
+
| After success checkpoint | Normal incremental skip |
|
|
34
|
+
|
|
35
|
+
Atomic replacement is per file. The whole batch is not a transaction, and the two report files are not a transactional pair. A forced stop can leave the previous completed report and temporary snapshots. Always inspect the command exit code. Power-loss durability depends on the filesystem; `fsync` of file contents is used, but this is not a database-grade power-failure guarantee.
|
|
36
|
+
|
|
37
|
+
## Output ownership
|
|
38
|
+
|
|
39
|
+
Only checksummed output tracked by the ledger is replaced. Names retain source extensions. Source names that collide under NFC normalization and case folding are rejected before conversion for portability. Output file/directory conflicts (for example, a source `a.txt` next to an `a.txt.md/` directory) are also rejected before conversion. Reports and the private metadata directory are reserved generated paths. Stale outputs are retained, never automatically deleted.
|
|
40
|
+
|
|
41
|
+
The output directory is an application-managed workspace; do not edit reports or the ledger. Source documents and handwritten Markdown should live elsewhere. An output file edited concurrently after the final ownership check is outside the cooperative-writer model; do not edit output during an active run.
|
|
42
|
+
|
|
43
|
+
## Resource and security limits
|
|
44
|
+
|
|
45
|
+
At most 16 worker processes can be requested (default 2). Defaults are 64 MiB input, 32 MiB output and 60 seconds per worker. DOCX archives are limited to 10,000 entries and 256 MiB declared uncompressed data. These are admission/output checks, not OS memory or disk quotas: an underlying parser can allocate substantial memory before returning output. Use an external sandbox and resource limits for hostile documents.
|
|
46
|
+
|
|
47
|
+
Time limits cover worker startup/imports and conversion. Scanning, hashing, snapshotting and commit I/O are not timed. Only direct child processes are managed; the supported conversion paths do not intentionally launch grandchildren. No protection against a compromised parser, hostile local process, filesystem race, or maliciously edited ledger is claimed.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"executed_at": "2026-09-08T06:39:31.915120+00:00",
|
|
3
|
+
"platform": "Windows",
|
|
4
|
+
"python": "3.12.14",
|
|
5
|
+
"folioqueue": "0.1.0",
|
|
6
|
+
"markitdown": "0.1.7",
|
|
7
|
+
"workers": 2,
|
|
8
|
+
"corpus": {
|
|
9
|
+
"txt": 40,
|
|
10
|
+
"csv": 10,
|
|
11
|
+
"docx": 2,
|
|
12
|
+
"pdf": 2,
|
|
13
|
+
"html": 2
|
|
14
|
+
},
|
|
15
|
+
"runs": [
|
|
16
|
+
{
|
|
17
|
+
"scenario": "initial",
|
|
18
|
+
"summary": {
|
|
19
|
+
"converted": 56
|
|
20
|
+
},
|
|
21
|
+
"duration_seconds": 4.031
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"scenario": "unchanged",
|
|
25
|
+
"summary": {
|
|
26
|
+
"skipped": 56
|
|
27
|
+
},
|
|
28
|
+
"duration_seconds": 0.219
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"scenario": "one_source_changed",
|
|
32
|
+
"summary": {
|
|
33
|
+
"converted": 1,
|
|
34
|
+
"skipped": 55
|
|
35
|
+
},
|
|
36
|
+
"duration_seconds": 0.25
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"scenario": "one_output_edited",
|
|
40
|
+
"summary": {
|
|
41
|
+
"failed": 1,
|
|
42
|
+
"skipped": 55
|
|
43
|
+
},
|
|
44
|
+
"duration_seconds": 0.203
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"limitations": "Small synthetic smoke corpus; not an extraction-quality or comparative throughput benchmark."
|
|
48
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Selection research — 2026-09-08
|
|
2
|
+
|
|
3
|
+
The following are public demand signals, not customer endorsements and not independently reproduced upstream bug findings.
|
|
4
|
+
|
|
5
|
+
## Upstream signals
|
|
6
|
+
|
|
7
|
+
- [MarkItDown #1371](https://github.com/microsoft/markitdown/issues/1371), “Feature Request: Add batch processing capability for directory conversion”: an open request to convert all supported files in a directory (recursively) in one operation, e.g. `markitdown --batch ./documents --output ./converted`. This is the direct scope FolioQueue implements, plus incremental and ownership behavior.
|
|
8
|
+
- [MarkItDown #1166](https://github.com/microsoft/markitdown/issues/1166), “Process multiple files”: an open request to batch-convert a list of files in one invocation. FolioQueue covers this through recursive collection scanning rather than a repeated flag list.
|
|
9
|
+
- [MarkItDown #135](https://github.com/microsoft/markitdown/issues/135), “Support for Parallel Processing of files”: a request and discussion around document-processing throughput. Some comments make unsupported general claims about Python parallelism; FolioQueue does not adopt those claims. A bounded one-file process model is used for failure isolation and scheduling.
|
|
10
|
+
- [MarkItDown #1234](https://github.com/microsoft/markitdown/issues/1234), “Magika Dependency Optional”: a browser/Pyodide use case affected by ONNX dependencies. FolioQueue does **not** solve that upstream browser issue; it keeps its own text/CSV core dependency-free and makes the complete document backend optional.
|
|
11
|
+
- The upstream single-file CLI was inspected at commit [`b6e8bbdce628d564c6af031b5f26cda6e818ea10`](https://github.com/microsoft/markitdown/tree/b6e8bbdce628d564c6af031b5f26cda6e818ea10). FolioQueue implements a separate collection workflow using the published Python package, without copying upstream implementation code.
|
|
12
|
+
|
|
13
|
+
## Related projects inspected
|
|
14
|
+
|
|
15
|
+
- [MarkItDown Plus](https://github.com/lamguo/markitdown-plus): folder conversion, workers, manifests, assets, RAG chunking and JSONL. Stronger choice when chunking and assets are central. Its README was reviewed; no claim is made that it lacks an unmentioned capability.
|
|
16
|
+
- [kuma90/markitdown-batch](https://github.com/kuma90/markitdown-batch): Windows GUI/CLI for folder conversion through a LAN API.
|
|
17
|
+
- [shubhankarreddy/markitdown-gui](https://github.com/shubhankarreddy/markitdown-gui): Windows desktop conversion workflow, discovered through repository metadata.
|
|
18
|
+
|
|
19
|
+
FolioQueue's v0.1 contract focuses on checksum-based resume, conservative output ownership, write-ahead recovery, per-file timeout isolation and read-only planning. These are concrete, testable behaviors.
|
|
20
|
+
|
|
21
|
+
## Next steps
|
|
22
|
+
|
|
23
|
+
- Gather external usage on representative, non-sensitive collections.
|
|
24
|
+
- Identify workflows where checkpointing and output-conflict detection materially help.
|
|
25
|
+
- Measure overhead against a simple sequential MarkItDown loop using the same corpus, backend version and hardware.
|
|
26
|
+
- Turn real failure reports into minimal fixtures and fixes.
|