chore: prepare docfill project for gitea
This commit is contained in:
@@ -8,11 +8,14 @@ Each run needs:
|
||||
|
||||
- A `task.json` config file.
|
||||
- A data source: `.xlsx` or SQLite `.db`.
|
||||
- Optional business filters in `filter.equals`.
|
||||
- A template: `.docx` or `.xlsx`.
|
||||
- An output path pattern in `task.json`.
|
||||
|
||||
Paths inside `task.json` are resolved from the config file directory.
|
||||
|
||||
Use one `task.json` per business task. Use `--var` for values that change per run, such as date, ticket number, person, or batch.
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
@@ -22,10 +25,42 @@ docfill run -c /path/to/task.json --var date=2026-06-18
|
||||
Use repeated `--var key=value` arguments for runtime values:
|
||||
|
||||
```bash
|
||||
docfill run -c task.json --var date=2026-06-18 --var batch=早班
|
||||
docfill run -c task.json --var date=2026-06-18 --var ticket_no=GD-002
|
||||
```
|
||||
|
||||
CLI variables override `vars` in `task.json`. Row data overrides both.
|
||||
Priority:
|
||||
|
||||
```text
|
||||
row data > CLI --var > task.json vars
|
||||
```
|
||||
|
||||
CLI variables override `vars` in `task.json`. The selected row data overrides both when rendering templates and output paths.
|
||||
|
||||
If `task.json` has a filter:
|
||||
|
||||
```json
|
||||
"filter": {
|
||||
"equals": {
|
||||
"日期": "{{date}}",
|
||||
"工单编号": "{{ticket_no}}"
|
||||
},
|
||||
"expect": "one"
|
||||
}
|
||||
```
|
||||
|
||||
then the command:
|
||||
|
||||
```bash
|
||||
docfill run -c task.json --var date=2026-06-18 --var ticket_no=GD-002
|
||||
```
|
||||
|
||||
selects the row where `日期 = 2026-06-18` and `工单编号 = GD-002`.
|
||||
|
||||
Use `--verbose` only when diagnosing a failed or suspicious run:
|
||||
|
||||
```bash
|
||||
docfill run -c task.json --var date=2026-06-18 --var ticket_no=GD-002 --verbose
|
||||
```
|
||||
|
||||
## Success
|
||||
|
||||
@@ -48,9 +83,91 @@ Exit code `2` means the command line was invalid.
|
||||
Errors are written to stderr with the `docfill:` prefix:
|
||||
|
||||
```text
|
||||
docfill: render row 1: missing template field "done"
|
||||
docfill: [TEMPLATE_FIELD_MISSING] render row 1: missing template field "done"
|
||||
hint: Add column "done" to the data source or pass --var done=...
|
||||
context: field=done template=/path/template.docx
|
||||
```
|
||||
|
||||
Verbose logs are also written to stderr:
|
||||
|
||||
```text
|
||||
log: load config path=/path/task.json
|
||||
log: read data type=excel path=/path/data.xlsx
|
||||
log: read data type=excel path=/path/data.xlsx rows=3
|
||||
log: filter rows=3 matched=1 expect=one
|
||||
log: render row=1 output=/path/out/work_order_2026-06-18_GD-002.docx
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
`CLI_USAGE`
|
||||
|
||||
The command line is invalid.
|
||||
|
||||
`CONFIG_READ`
|
||||
|
||||
The config file cannot be read.
|
||||
|
||||
`CONFIG_PARSE`
|
||||
|
||||
The config file is not valid JSON.
|
||||
|
||||
`CONFIG_VALIDATE`
|
||||
|
||||
The config is missing required fields or uses unsupported values.
|
||||
|
||||
`DATA_EXCEL`
|
||||
|
||||
Excel data cannot be opened or read.
|
||||
|
||||
`DATA_SQLITE`
|
||||
|
||||
SQLite data cannot be opened, queried, or parameterized.
|
||||
|
||||
`DATA_EMPTY`
|
||||
|
||||
The data source returned no rows.
|
||||
|
||||
`DATA_FILTER_FIELD`
|
||||
|
||||
The filter references a field that is not in the data.
|
||||
|
||||
`DATA_FILTER_VALUE`
|
||||
|
||||
The filter references a variable that was not provided.
|
||||
|
||||
`DATA_FILTER_NO_MATCH`
|
||||
|
||||
The filter matched no rows.
|
||||
|
||||
`DATA_FILTER_MULTI_MATCH`
|
||||
|
||||
The filter expected one row but matched multiple rows.
|
||||
|
||||
`TEMPLATE_OPEN`
|
||||
|
||||
The template file cannot be opened or inspected.
|
||||
|
||||
`TEMPLATE_FIELD_MISSING`
|
||||
|
||||
The template references a field that is not available.
|
||||
|
||||
`TEMPLATE_UNRESOLVED`
|
||||
|
||||
The rendered file would still contain a `{{field}}` placeholder.
|
||||
|
||||
`OUTPUT_EXISTS`
|
||||
|
||||
The output file exists and overwrite is not enabled.
|
||||
|
||||
`OUTPUT_WRITE`
|
||||
|
||||
The output directory or file cannot be written.
|
||||
|
||||
`INTERNAL`
|
||||
|
||||
An unexpected unclassified error occurred.
|
||||
|
||||
## Common Errors
|
||||
|
||||
`missing template field`
|
||||
@@ -65,6 +182,18 @@ The output file exists and `output.overwrite` is not `true`.
|
||||
|
||||
A SQLite query parameter such as `{{date}}` was not provided.
|
||||
|
||||
`filter matched no rows`
|
||||
|
||||
Check `filter.equals`, `--var` values, or the source table contents.
|
||||
|
||||
`filter matched N rows but expected one`
|
||||
|
||||
Add another filter condition or clean duplicate rows in the source table.
|
||||
|
||||
`filter field is not in data`
|
||||
|
||||
Check Excel headers or SQLite query column names.
|
||||
|
||||
`unresolved placeholder`
|
||||
|
||||
The rendered document still contains `{{field}}`. Check the source data value and the template.
|
||||
@@ -87,4 +216,4 @@ dist/docfill-darwin-arm64
|
||||
bash scripts/smoke.sh
|
||||
```
|
||||
|
||||
Smoke test builds a temporary binary, generates temporary example files, runs both example configs, and checks generated outputs.
|
||||
Smoke test builds a temporary binary, generates temporary example files, runs example configs including the filter case, and checks generated outputs.
|
||||
|
||||
186
docs/evaluations/2026-06-19-full-evaluation.md
Normal file
186
docs/evaluations/2026-06-19-full-evaluation.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# docfill 全方位评测报告
|
||||
|
||||
评测日期:2026-06-19
|
||||
|
||||
评测对象:`docfill` 当前工作区版本,包含错误码、日志、业务筛选 `filter.equals`、手工测试素材和用户文档更新。
|
||||
|
||||
## 结论
|
||||
|
||||
本轮评测结论:通过当前 MVP 质量门槛。
|
||||
|
||||
适用范围:
|
||||
|
||||
- 本地 macOS arm64 构建。
|
||||
- Excel / SQLite 数据源读取。
|
||||
- Word / Excel 模板填充。
|
||||
- `filter.equals` 多条件等值筛选。
|
||||
- `filter.expect` 的 `one` / `many` 行数约束。
|
||||
- CLI 成功输出、错误码、提示和上下文。
|
||||
- 用户文档、示例配置和手工测试素材一致性。
|
||||
|
||||
未宣称覆盖:
|
||||
|
||||
- Windows / Linux 二进制构建。
|
||||
- 大体量数据性能测试。
|
||||
- Excel 公式重算、透视表刷新。
|
||||
- 复杂 Word 模板语法。
|
||||
- 业务系统直连、权限、审批或调度系统。
|
||||
|
||||
## 工作区状态
|
||||
|
||||
当前工作区包含未提交变更,评测没有执行提交、回滚或清理。
|
||||
|
||||
基线提交:
|
||||
|
||||
```text
|
||||
ca444bd feat: add docfill mvp cli
|
||||
```
|
||||
|
||||
评测时存在的主要变更类型:
|
||||
|
||||
- CLI 错误码和日志。
|
||||
- `filter.equals` / `filter.expect` 筛选能力。
|
||||
- 新增 `HOWTO.md`。
|
||||
- 新增 `manual_tests/` 真实测试素材。
|
||||
- 新增 `examples/excel-filter-to-word/` smoke 示例。
|
||||
- 更新 README、runbook 和示例文档。
|
||||
|
||||
## 自动化评测
|
||||
|
||||
| 项目 | 命令 | 结果 |
|
||||
| --- | --- | --- |
|
||||
| Git diff 格式检查 | `git diff --check` | 通过,无输出 |
|
||||
| Go 单元测试 | `go test -count=1 ./...` | 通过 |
|
||||
| Go race 测试 | `go test -race -count=1 ./...` | 通过 |
|
||||
| Go 静态检查 | `go vet ./...` | 通过,无输出 |
|
||||
| 本机构建 | `bash scripts/build.sh` | 通过,输出 `dist/docfill-darwin-arm64` |
|
||||
| 冒烟测试 | `bash scripts/smoke.sh` | 通过,包含无筛选、筛选、SQLite 示例 |
|
||||
|
||||
`bash scripts/smoke.sh` 覆盖:
|
||||
|
||||
- Excel 到 Word:生成 2 个日报 Word 文件。
|
||||
- Excel 筛选到 Word:按 `date + ticket_no` 生成 1 个工单 Word 文件。
|
||||
- SQLite 到 Excel:生成 2 个部门汇总 Excel 文件。
|
||||
|
||||
## 真实素材成功路径
|
||||
|
||||
| 案例 | 命令 | 结果 |
|
||||
| --- | --- | --- |
|
||||
| Excel 筛选到 Word | `dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002 --verbose` | 生成 1 个 Word 文件 |
|
||||
| Excel 到 Word | `dist/docfill-darwin-arm64 run -c manual_tests/01_excel_to_word/task.json --var batch=早班 --verbose` | 生成 2 个 Word 文件 |
|
||||
| SQLite 到 Excel | `dist/docfill-darwin-arm64 run -c manual_tests/02_sqlite_to_excel/task.json --var date=2026-06-18 --verbose` | 生成 2 个 Excel 文件 |
|
||||
| Excel 到 Excel | `dist/docfill-darwin-arm64 run -c manual_tests/03_excel_to_excel/task.json --var date=2026-06-18 --verbose` | 生成 2 个 Excel 文件 |
|
||||
|
||||
关键输出:
|
||||
|
||||
```text
|
||||
manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx
|
||||
manual_tests/01_excel_to_word/out/daily_2026-06-18_张三_测试_1.docx
|
||||
manual_tests/01_excel_to_word/out/daily_2026-06-18_李四_2.docx
|
||||
manual_tests/02_sqlite_to_excel/out/summary_客服部_1.xlsx
|
||||
manual_tests/02_sqlite_to_excel/out/summary_营销部_2.xlsx
|
||||
manual_tests/03_excel_to_excel/out/audit_2026-06-18_王五_1.xlsx
|
||||
manual_tests/03_excel_to_excel/out/audit_2026-06-18_赵六_2.xlsx
|
||||
```
|
||||
|
||||
## 真实素材内容核验
|
||||
|
||||
使用 bundled Python 读取生成的 Word / Excel 文件并断言关键字段。
|
||||
|
||||
核验结果:
|
||||
|
||||
- 筛选工单 Word 包含 `GD-002`、`B 公司`、`D5000`、`已完成`。
|
||||
- 筛选工单 Word 不包含非目标行 `GD-001`、`A 公司`。
|
||||
- 日报 Word 包含 `张三/测试`、`早班`、`营销部`。
|
||||
- SQLite 汇总 Excel 中 `summary_营销部_2.xlsx` 的 B2:B6 为 `营销部 / 2026-06-18 / 张三 / 128 / 3`。
|
||||
- Excel 质检输出中 `audit_2026-06-18_赵六_2.xlsx` 的 B2:B6 为 `2026-06-18 / 赵六 / 系统截图一致性 / 87 / 缺少 1 张截图,需要补充`。
|
||||
- SQLite 源表包含 3 行测试数据。
|
||||
|
||||
## DOCX 渲染核验
|
||||
|
||||
使用 `documents` skill 的 `render_docx.py` 渲染两个 Word 输出:
|
||||
|
||||
```text
|
||||
manual_tests/_evaluation_rendered/filter/page-1.png
|
||||
manual_tests/_evaluation_rendered/daily/page-1.png
|
||||
```
|
||||
|
||||
视觉核验结果:
|
||||
|
||||
- 筛选工单页可读,字段位置正常,关键值为 `2026-06-18 / GD-002 / B 公司 / D5000 / 已完成 / 归档并同步日报`。
|
||||
- 日报页可读,字段位置正常,关键值为 `张三/测试 / 营销部 / 早班`。
|
||||
- 未观察到明显空白页、文本重叠、缺字或表格错位。
|
||||
|
||||
## CLI 失败路径
|
||||
|
||||
| 场景 | 命令或配置 | 预期错误码 | 结果 |
|
||||
| --- | --- | --- | --- |
|
||||
| 筛选无匹配 | `ticket_no=GD-999` | `DATA_FILTER_NO_MATCH` | 通过 |
|
||||
| 筛选变量缺失 | 不传 `ticket_no` | `DATA_FILTER_VALUE` | 通过 |
|
||||
| 筛选匹配多行 | 临时配置只按 `日期` 筛选且 `expect=one` | `DATA_FILTER_MULTI_MATCH` | 通过 |
|
||||
| 非法 `filter.expect` | 临时配置 `expect=single` | `CONFIG_VALIDATE` | 通过 |
|
||||
| 配置不存在 | `-c manual_tests/not-exist.json` | `CONFIG_READ` | 通过 |
|
||||
| CLI 参数错误 | `--var date` | `CLI_USAGE`,退出码 2 | 通过 |
|
||||
|
||||
典型错误输出:
|
||||
|
||||
```text
|
||||
docfill: [DATA_FILTER_NO_MATCH] filter matched no rows
|
||||
hint: Check filter.equals, --var values, or source table contents.
|
||||
context: expect=one filter=工单编号=GD-999,日期=2026-06-18
|
||||
```
|
||||
|
||||
```text
|
||||
docfill: [DATA_FILTER_MULTI_MATCH] filter matched 2 rows but expected one
|
||||
hint: Add another filter condition or clean duplicate rows in the source table.
|
||||
context: filter=日期=2026-06-18 matches=2
|
||||
```
|
||||
|
||||
## 结构与文档一致性
|
||||
|
||||
| 检查 | 结果 |
|
||||
| --- | --- |
|
||||
| 所有 `task.json` 可被 JSON 解析 | 通过 |
|
||||
| `manual_tests/**/out/*.{docx,xlsx}` 内部 XML 无残留 `{{` / `}}` 占位符 | 通过 |
|
||||
| README / HOWTO / runbook 均说明 `filter.equals`、`filter.expect`、`--var` 优先级 | 通过 |
|
||||
| 用户文档未出现不合适措辞 `小白`、`大白话` | 通过 |
|
||||
| 用户文档无 `TODO` / `TBD` / `FIXME` | 通过 |
|
||||
|
||||
## 能力覆盖评估
|
||||
|
||||
已验证:
|
||||
|
||||
- Excel 数据源读取。
|
||||
- SQLite 数据源读取。
|
||||
- Word 模板填充。
|
||||
- Excel 模板填充。
|
||||
- Word 同段落拆分占位符替换。
|
||||
- 输出文件名非法字符清理。
|
||||
- `vars` 默认变量。
|
||||
- CLI `--var` 覆盖 `vars`。
|
||||
- 数据行字段优先于 `--var` / `vars`。
|
||||
- 多条件业务筛选。
|
||||
- `expect=one` 和 `expect=many`。
|
||||
- 筛选错误、配置错误、CLI 错误。
|
||||
- stdout 输出生成文件清单。
|
||||
- stderr 输出日志、错误码、hint、context。
|
||||
|
||||
未覆盖或仅部分覆盖:
|
||||
|
||||
- 大文件性能。
|
||||
- 多 sheet 大范围模板扫描性能。
|
||||
- Windows / Linux 路径与构建。
|
||||
- Excel 公式、图表、透视表类模板。
|
||||
- Word 跨段落拆分占位符。
|
||||
- 真实业务系统导出的复杂脏数据。
|
||||
|
||||
## 风险与建议
|
||||
|
||||
P0 无阻塞问题。
|
||||
|
||||
建议进入下一轮前只做小范围补强:
|
||||
|
||||
1. 增加一条大约 500 到 1000 行 Excel 的筛选性能测试,确认小工具在常见业务表规模下响应稳定。
|
||||
2. 增加文档中的“字段命名建议”,例如日期列、工单编号列、辅助列的命名方式。
|
||||
3. 保持筛选语法只支持等值 AND,不增加模糊匹配、范围查询或表达式。
|
||||
4. 发布前在目标机器上补一次 `bash scripts/build.sh && bash scripts/smoke.sh`。
|
||||
@@ -0,0 +1,52 @@
|
||||
# Docfill P0.7 Errors And Logs Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make failures easier for digital employees and humans to classify without turning `docfill` into a logging platform.
|
||||
|
||||
**Architecture:** Add a small `AppError` type in the internal package with code, hint, and context. Keep CLI formatting in `cmd/docfill`; add only one runtime logging switch, `--verbose`, which writes step logs to stderr.
|
||||
|
||||
**Tech Stack:** Go standard errors, existing CLI flag parsing, existing tests.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Error Contract
|
||||
|
||||
**Files:**
|
||||
- Create: `internal/docfill/errors.go`
|
||||
- Modify: `internal/docfill/p0_test.go`
|
||||
- Modify: `cmd/docfill/main_test.go`
|
||||
|
||||
- [ ] Add tests for coded missing-field and output-exists failures.
|
||||
- [ ] Add tests for CLI stderr formatting with `[CODE]`, `hint:`, and `context:`.
|
||||
|
||||
### Task 2: Error Classification
|
||||
|
||||
**Files:**
|
||||
- Modify: `internal/docfill/docfill.go`
|
||||
- Create: `internal/docfill/errors.go`
|
||||
|
||||
- [ ] Classify config read, config parse, config validate, data Excel, data SQLite, template, output, and unresolved-placeholder failures where they already occur.
|
||||
- [ ] Keep existing return signatures.
|
||||
|
||||
### Task 3: Verbose Logs
|
||||
|
||||
**Files:**
|
||||
- Modify: `internal/docfill/docfill.go`
|
||||
- Modify: `cmd/docfill/main.go`
|
||||
- Modify: `cmd/docfill/main_test.go`
|
||||
|
||||
- [ ] Add `RunOptions.Logf`.
|
||||
- [ ] Add `--verbose` to `docfill run`.
|
||||
- [ ] Log only config load, data read summary, and per-row output path.
|
||||
|
||||
### Task 4: Docs And Verification
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/digital-employee-runbook.md`
|
||||
|
||||
- [ ] Document error shape and `--verbose`.
|
||||
- [ ] Run `go test -count=1 ./...`.
|
||||
- [ ] Run `bash scripts/smoke.sh`.
|
||||
- [ ] Run `bash scripts/build.sh`.
|
||||
Reference in New Issue
Block a user