Skip to content

墨笔初成,入卷有门 · Add N1 CLI with subcommands, envelope, EXIF, ROI, and detect - #29

Merged
eric8810 merged 5 commits into
mainfrom
feat/n1-cli
Jul 22, 2026
Merged

墨笔初成,入卷有门 · Add N1 CLI with subcommands, envelope, EXIF, ROI, and detect#29
eric8810 merged 5 commits into
mainfrom
feat/n1-cli

Conversation

@eric8810

Copy link
Copy Markdown
Contributor

Summary

N1 CLI entry point implementation (roadmap §5, D106).

Changes

CLI bin (bindings/node/bin/light-ocr.cjs)

  • Subcommand structure:
    ecognize\ / \detect\ / \info, with implicit recognize default

  • ecognize: file/stdin → json/jsonl/text, --region, --provider, --no-exif, --schema-version\
  • \detect: detection-only output (always JSON, no --format), --crop\ flag (pending crop bytes)
  • \info: --model-info\ / --version\ (mutually exclusive)
  • stdout/stderr strict separation, stable exit codes (64-72)
  • Flag validation before input reading (parameter errors surface first)

C++ Core changes

  • \Engine::detect()\ virtual method + implementation in \src/core/engine.cpp\ (reuses detection stage, skips recognition)
  • \DetectionResult\ / \DetectionBox\ / \Rect\ types in \include/light_ocr/types.hpp\
  • EXIF orientation: C++ parser + pixel transform (\�indings/node/src/exif.cpp), integrated into decode path
  • ROI: \crop_decoded_image\ + box offset in \encoded_image.cpp, \�pplyExif/
    egion\ options in \�ddon.cpp\

  • ative_detect\ binding in \�ddon.cpp\

JS layer

  • \OcrEngine.detect()\ method, \DetectionResult\ / \Rect\ types in \index.d.ts\
  • JS EXIF orientation parser (\�indings/node/js/exif.cjs, zero-dependency)
  • \�pplyExif\ /
    egion\ options in \RecognizeOptions\

Design docs

  • \docs/cli-design.md: N1 CLI design (subcommands, flag review, exit codes, envelope schema, ROI/EXIF/detect semantics)
  • \docs/decisions.md: D106 decision (stable CLI surface, stdout/stderr, exit code table, envelope contract)

Agent Skill

  • .agents/skills/local-ocr/SKILL.md: when to use OCR, command reference, exit codes, failure handling

Tests (54 passing)

  • \ est/cli.test.cjs: 45 tests (argv, help, exit codes, envelope, schema snapshot, ROI, detect envelope, flag ordering)
  • \ est/exif.test.cjs: 9 tests (EXIF parse 1-8, pixel transform, round-trip)

What needs CI verification

C++ changes require native build (cmake + MSVC + node headers). Local environment lacks these. CI should verify:

  • Core \Engine::detect()\ compiles and produces correct detection boxes
  • EXIF C++ pixel transform produces correct orientation
  • ROI crop + box offset produces correct coordinates

  • ative_detect\ binding works end-to-end
  • Existing adapter tests still pass

Not in this PR

  • --crop\ PNG bytes (needs Core returning crop bytes or independent decode; D-N1-3 pending)
  • 20 Agent task eval (roadmap §5.7 acceptance, separate effort)
  • README/SKILL first-use validation (roadmap §5.7 acceptance, separate effort)

…I, and detect

N1 CLI entry point (roadmap §5, D106):

- light-ocr bin with recognize/detect/info subcommands
- recognize: file/stdin input, json/jsonl/text output, implicit default
- detect: detection-only output (Core Engine::detect(), no recognition)
- info: --model-info/--version (mutually exclusive)
- schemaVersion=1 DocumentResult envelope with stable line/detection IDs
- EXIF orientation: JS parser + C++ pixel transform, --no-exif flag
- ROI --region: pageSpace rectangle, adapter-layer crop, box offset
- stdout/stderr strict separation, stable exit codes (64-72)
- Flag validation before input reading (parameter errors surface first)
- Agent Skill at .agents/skills/local-ocr/SKILL.md
- D106 decision in decisions.md, cli-design.md design doc
- 54 unit tests (cli logic + exif parser), all passing
chenghan added 4 commits July 22, 2026 08:40
…tect()

CI failed on all platforms with -Werror=unused-variable:
detection_input_width and detection_input_height were copied from
recognize() but never read in detect() (no diagnostics collection).
- addon.cpp: move detect_mode from function param to Request struct
  (worker lambda can't capture native_recognize_impl params)
- addon.cpp: fix recognize ROI offset to use line.box.points (Quad has
  no begin/end, it has .points array)
- CMakeLists.txt: add exif.cpp to fuzz_encoded_image sources (linker
  error: undefined reference to exif::apply_orientation)
- exif.cpp: fix size_t to uint32_t narrowing warning (C4267)
Result::value() returns const T& for lvalues, so modifying boxes/lines
through it failed with 'assignment of member in read-only object'.

Fix: move the result out to a local variable before modifying, then
wrap in Result::success before returning.
Function was defined after EngineState::run() but called from the
worker lambda inside it. Non-core builds compile addon.cpp as one
translation unit and require declaration before use.
@eric8810
eric8810 merged commit a20a433 into main Jul 22, 2026
10 checks passed
birhantprkc pushed a commit to birhantprkc/light-ocr that referenced this pull request Jul 29, 2026
…ect (arcships#29)

* feat(n1): 墨笔初成,入卷有门 · add N1 CLI with subcommands, envelope, EXIF, ROI, and detect

N1 CLI entry point (roadmap §5, D106):

- light-ocr bin with recognize/detect/info subcommands
- recognize: file/stdin input, json/jsonl/text output, implicit default
- detect: detection-only output (Core Engine::detect(), no recognition)
- info: --model-info/--version (mutually exclusive)
- schemaVersion=1 DocumentResult envelope with stable line/detection IDs
- EXIF orientation: JS parser + C++ pixel transform, --no-exif flag
- ROI --region: pageSpace rectangle, adapter-layer crop, box offset
- stdout/stderr strict separation, stable exit codes (64-72)
- Flag validation before input reading (parameter errors surface first)
- Agent Skill at .agents/skills/local-ocr/SKILL.md
- D106 decision in decisions.md, cli-design.md design doc
- 54 unit tests (cli logic + exif parser), all passing

* fix(core): 删冗余变量,编译无碍 · remove unused detection_input variables in detect()

CI failed on all platforms with -Werror=unused-variable:
detection_input_width and detection_input_height were copied from
recognize() but never read in detect() (no diagnostics collection).

* fix(n1): 修补编译,链路通达 · fix contract/safety CI failures

- addon.cpp: move detect_mode from function param to Request struct
  (worker lambda can't capture native_recognize_impl params)
- addon.cpp: fix recognize ROI offset to use line.box.points (Quad has
  no begin/end, it has .points array)
- CMakeLists.txt: add exif.cpp to fuzz_encoded_image sources (linker
  error: undefined reference to exif::apply_orientation)
- exif.cpp: fix size_t to uint32_t narrowing warning (C4267)

* fix(n1): 去常量之限,变量可动 · fix const-correctness in ROI offset

Result::value() returns const T& for lvalues, so modifying boxes/lines
through it failed with 'assignment of member in read-only object'.

Fix: move the result out to a local variable before modifying, then
wrap in Result::success before returning.

* fix(n1): 前置定义,先后有序 · move detect_result_to_ocr_result before worker

Function was defined after EngineState::run() but called from the
worker lambda inside it. Non-core builds compile addon.cpp as one
translation unit and require declaration before use.

---------

Co-authored-by: chenghan <chenghan@fazhitech.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant