@simplysm/sd-claude 14.0.65 → 14.0.68
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.
- package/claude/references/sd-requirement-source-handling.md +64 -0
- package/claude/references/sd-simplysm14/README.md +44 -40
- package/claude/references/sd-simplysm14/apis/angular/README.md +95 -0
- package/claude/references/sd-simplysm14/apis/angular/app-structure.md +49 -0
- package/claude/references/sd-simplysm14/apis/angular/buttons.md +42 -0
- package/claude/references/sd-simplysm14/apis/angular/crud.md +35 -0
- package/claude/references/sd-simplysm14/apis/angular/forms.md +63 -0
- package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +80 -0
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +33 -0
- package/claude/references/sd-simplysm14/apis/angular/layout.md +41 -0
- package/claude/references/sd-simplysm14/apis/angular/modal.md +63 -0
- package/claude/references/sd-simplysm14/apis/angular/routing.md +45 -0
- package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +35 -0
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +50 -0
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +42 -0
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +52 -0
- package/claude/references/sd-simplysm14/apis/angular/toast.md +46 -0
- package/claude/references/sd-simplysm14/apis/angular/visual.md +41 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +76 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +83 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +80 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +39 -0
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +112 -0
- package/claude/references/sd-simplysm14/apis/core-common/README.md +53 -0
- package/claude/references/sd-simplysm14/apis/core-common/extensions.md +123 -0
- package/claude/references/sd-simplysm14/apis/core-common/features.md +46 -0
- package/claude/references/sd-simplysm14/apis/core-common/types.md +114 -0
- package/claude/references/sd-simplysm14/apis/core-common/utils.md +158 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +12 -0
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +64 -0
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +52 -0
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +53 -0
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +81 -0
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +111 -0
- package/claude/references/sd-simplysm14/apis/excel/README.md +81 -0
- package/claude/references/sd-simplysm14/apis/lint/README.md +80 -0
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +33 -0
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +77 -0
- package/claude/references/sd-simplysm14/apis/orm-common/executable.md +20 -0
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +92 -0
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +98 -0
- package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +128 -0
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +59 -0
- package/claude/references/sd-simplysm14/apis/sd-claude/README.md +9 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +50 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +155 -0
- package/claude/references/sd-simplysm14/apis/service-client/README.md +92 -0
- package/claude/references/sd-simplysm14/apis/service-common/README.md +29 -0
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +63 -0
- package/claude/references/sd-simplysm14/apis/service-common/messages.md +56 -0
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +64 -0
- package/claude/references/sd-simplysm14/apis/service-common/service-types.md +43 -0
- package/claude/references/sd-simplysm14/apis/service-server/README.md +20 -0
- package/claude/references/sd-simplysm14/apis/service-server/auth.md +31 -0
- package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +47 -0
- package/claude/references/sd-simplysm14/apis/service-server/define-service.md +71 -0
- package/claude/references/sd-simplysm14/apis/service-server/internals.md +41 -0
- package/claude/references/sd-simplysm14/apis/service-server/server.md +66 -0
- package/claude/references/sd-simplysm14/apis/storage/README.md +69 -0
- package/claude/references/sd-simplysm14/{client-component.md → manuals/client-component.md} +134 -128
- package/claude/references/sd-simplysm14/manuals/client-crud.md +102 -0
- package/claude/references/sd-simplysm14/manuals/client-demo.md +128 -0
- package/claude/references/sd-simplysm14/manuals/client-rules.md +7 -0
- package/claude/references/sd-simplysm14/{client-setup.md → manuals/client-setup.md} +2 -2
- package/claude/references/sd-simplysm14/{client-tab.md → manuals/client-tab.md} +13 -11
- package/claude/references/sd-simplysm14/{orm-union.md → manuals/orm-union.md} +1 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +75 -0
- package/claude/rules/sd-base-rules.md +191 -79
- package/claude/scripts/sd_paths.py +22 -0
- package/claude/sd-check-bash.py +19 -0
- package/claude/sd-statusline.py +7 -12
- package/claude/skills/sd-commit/SKILL.md +8 -3
- package/claude/skills/sd-demo/SKILL.md +103 -62
- package/claude/skills/sd-demo/evals/fixtures/empty/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/.specs/260513120000_warehouse/spec.md +42 -0
- package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-master-screen/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-master-screen/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-modal/.specs/260513120000_warehouse/spec.md +75 -0
- package/claude/skills/sd-demo/evals/fixtures/with-modal/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-screens/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-screens/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/golden.jsonl +5 -3
- package/claude/skills/sd-dev/SKILL.md +33 -63
- package/claude/skills/sd-dev/evals/fixtures/case-add/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/golden.jsonl +3 -3
- package/claude/skills/sd-docs/SKILL.md +53 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +7 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +3 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +6 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +1 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +8 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +7 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +3 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +3 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +6 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +1 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +8 -0
- package/claude/skills/sd-docs/evals/golden.jsonl +2 -0
- package/claude/skills/sd-docs/references/subagent-prompt.md +100 -0
- package/claude/skills/sd-impl/SKILL.md +149 -46
- package/claude/skills/sd-impl/evals/fixtures/case-001-new-screen/spec.md +55 -0
- package/claude/skills/sd-impl/evals/fixtures/case-002-auto-process/spec.md +55 -0
- package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/packages/client/src/pages/book-list.ts +22 -0
- package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/spec.md +57 -0
- package/claude/skills/sd-impl/evals/fixtures/case-004-ambiguous-spec/spec.md +58 -0
- package/claude/skills/sd-impl/evals/fixtures/case-005-id-mismatch/spec.md +52 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.test.ts +10 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.ts +11 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/data-access//352/261/260/353/236/230/354/262/230-/354/240/221/352/267/274.ts +12 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/models//352/261/260/353/236/230/354/262/230.ts +8 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/spec.md +77 -0
- package/claude/skills/sd-impl/evals/fixtures/case-new/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +101 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +101 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/250/353/215/270.txt +1 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.txt +1 -0
- package/claude/skills/sd-impl/evals/golden.jsonl +6 -3
- package/claude/skills/sd-impl/references/spec-cross-check.md +82 -0
- package/claude/skills/sd-skill/SKILL.md +4 -4
- package/claude/skills/sd-skill/evals/golden.jsonl +1 -2
- package/claude/skills/sd-skill/references/eval-authoring.md +31 -0
- package/claude/skills/sd-skill/references/eval-run.md +1 -1
- package/claude/skills/sd-skill/references/skill-authoring.md +8 -5
- package/claude/skills/sd-skill/scripts/run_eval.py +39 -60
- package/claude/skills/sd-spec/SKILL.md +163 -105
- package/claude/skills/sd-spec/references/example-spec.md +585 -0
- package/claude/skills/sd-spec/references/spec-authoring.md +287 -0
- package/claude/skills/sd-spec/references/spec-md-template.md +15 -93
- package/claude/skills/sd-unpack/SKILL.md +7 -1
- package/claude/skills/sd-unpack/scripts/handlers/_common.py +10 -0
- package/claude/skills/sd-unpack/scripts/handlers/eml_handler.py +5 -13
- package/claude/skills/sd-unpack/scripts/handlers/msg_handler.py +3 -12
- package/claude/skills/sd-unpack/scripts/handlers/office_com.py +23 -37
- package/claude/skills/sd-unpack/scripts/handlers/office_worker.py +1 -4
- package/claude/skills/sd-unpack/scripts/handlers/pdf_handler.py +4 -13
- package/claude/skills/sd-unpack/scripts/unpack.py +4 -4
- package/claude/skills/sd-use/SKILL.md +1 -0
- package/claude/skills/sd-wip/SKILL.md +38 -0
- package/claude/skills/sd-wip/evals/fixtures/with-artifact/projects/acct/_wip.md +3 -0
- package/claude/skills/sd-wip/evals/fixtures/with-artifact/projects/acct/spec.md +15 -0
- package/claude/skills/sd-wip/evals/fixtures/with-existing-wip/.wips/260101120000_acct.md +6 -0
- package/claude/skills/sd-wip/evals/fixtures/with-existing-wip-for-compact/.wips/260101120000_acct.md +14 -0
- package/claude/skills/sd-wip/evals/golden.jsonl +4 -0
- package/claude/skills/sd-wip/references/compact.md +79 -0
- package/package.json +1 -1
- package/scripts/sd-entries.mjs +2 -2
- package/claude/references/sd-simplysm14/orm.md +0 -11
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -27
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/.specs/260503143025/overview.md +0 -12
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/src/components/Button.tsx +0 -12
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/src/components/Input.tsx +0 -27
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/355/231/224/353/251/264/spec.md +0 -25
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/.specs/260503143025/overview.md +0 -12
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/src/components/Input.tsx +0 -25
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/REQ-001-RTP/354/236/205/353/240/245/355/231/224/353/251/264/spec.md +0 -19
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/REQ-002-RTP/354/266/234/353/240/245/355/231/224/353/251/264/spec.md +0 -20
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/overview.md +0 -16
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/components/Button.tsx +0 -6
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/components/Input.tsx +0 -15
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-demo/references/demo-md-template.md +0 -92
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260301_/352/263/240/352/260/235/354/202/254_/354/236/205/352/263/240/354/232/224/354/262/255.eml +0 -5
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260305_/352/263/240/352/260/235/354/202/254_/354/266/234/352/263/240/354/232/224/354/262/255.eml +0 -6
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260310_/352/263/240/352/260/235/354/202/254_/352/266/214/355/225/234.eml +0 -6
- package/claude/skills/sd-dev/evals/fixtures/single-req-auto-chain/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/start-from-plan/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-dev/evals/fixtures/start-from-plan/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/plan.md +0 -28
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -14
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/src/components/Input.tsx +0 -6
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/multi-r/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/plan.md +0 -40
- package/claude/skills/sd-impl/evals/fixtures/multi-r/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/spec.md +0 -13
- package/claude/skills/sd-impl/evals/fixtures/multi-r/src/components/Input.tsx +0 -25
- package/claude/skills/sd-impl/evals/fixtures/multi-r/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/plan.md +0 -26
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-impl/references/impl-md-template.md +0 -87
- package/claude/skills/sd-impl/references/modes-and-failure.md +0 -65
- package/claude/skills/sd-plan/SKILL.md +0 -130
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/spec.md +0 -14
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/api/user.ts +0 -13
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/components/Input.tsx +0 -15
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/pages/UserList.tsx +0 -29
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -17
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/src/components/Input.tsx +0 -6
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-plan/evals/fixtures/demo-built/.specs/260503143025/DEMO-001-/352/261/260/353/236/230/354/262/230/demo.md +0 -26
- package/claude/skills/sd-plan/evals/fixtures/demo-built/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/355/231/224/353/251/264/spec.md +0 -15
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/components/Input.tsx +0 -25
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/data/mock-customer.ts +0 -16
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/pages/CustomerList.tsx +0 -25
- package/claude/skills/sd-plan/evals/golden.jsonl +0 -3
- package/claude/skills/sd-plan/references/plan-md-template.md +0 -138
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260122_/352/263/240/352/260/235/354/202/254_/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/260/234/354/204/240/354/232/224/354/262/255.eml +0 -20
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260205_/352/263/240/352/260/235/354/202/254_/354/266/234/352/263/240/355/231/224/353/251/264/352/264/200/353/240/250.eml +0 -17
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260301_/352/263/240/352/260/235/354/202/254_/352/266/214/355/225/234/354/262/264/352/263/204.eml +0 -18
- package/claude/skills/sd-spec/evals/fixtures/conflict-detection/.docs/20260317_/352/263/240/352/260/235/354/202/254_/352/270/264/352/270/211/354/262/230/353/246/254/353/260/251/354/271/250.eml +0 -17
- package/claude/skills/sd-spec/evals/fixtures/conflict-detection/.docs//355/232/214/354/235/230/353/214/200/353/263/270_20260320.txt +0 -13
- package/claude/skills/sd-spec/evals/fixtures/direct-simple/.gitkeep +0 -0
- package/claude/skills/sd-spec/evals/fixtures/spec-md-input/.specs/260101120000/REQ-001-test/spec.md +0 -19
- package/claude/skills/sd-spec/evals/fixtures/spec-md-input/.specs/260101120000/overview.md +0 -18
- package/claude/skills/sd-spec/evals/golden.jsonl +0 -4
- package/claude/skills/sd-spec/references/overview-md-template.md +0 -89
- package/claude/skills/sd-spec/references/raw-input-handling.md +0 -96
- package/claude/skills/sd-verify/SKILL.md +0 -96
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/impl.md +0 -20
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/plan.md +0 -14
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/src/lib/discount.test.ts +0 -11
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/src/lib/discount.ts +0 -7
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/impl.md +0 -21
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/plan.md +0 -21
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/src/pages/UserList.tsx +0 -19
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/impl.md +0 -19
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/plan.md +0 -14
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/src/lib/validate-amount.test.ts +0 -10
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/src/lib/validate-amount.ts +0 -7
- package/claude/skills/sd-verify/evals/golden.jsonl +0 -3
- package/claude/skills/sd-verify/references/verify-md-template.md +0 -99
- /package/claude/skills/{sd-demo/evals/fixtures/basic-single-req/src/pages → sd-wip/evals/fixtures/empty}/.gitkeep +0 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# spec.md 작성 규약
|
|
2
|
+
|
|
3
|
+
워크플로(언제 무엇을 묻는지)는 [SKILL.md](../SKILL.md) 참조.
|
|
4
|
+
|
|
5
|
+
## 섹션 구조
|
|
6
|
+
|
|
7
|
+
| § | 섹션 | 분류 |
|
|
8
|
+
| --- | ---------------- | -------------- |
|
|
9
|
+
| §1 | 개요 | 워크플로 |
|
|
10
|
+
| §2 | 업무 프로세스 | 워크플로 |
|
|
11
|
+
| §3 | 기타 요구사항 | 워크플로 |
|
|
12
|
+
| §4 | 화면 | 워크플로 |
|
|
13
|
+
| §5 | 자동 처리 | 워크플로 |
|
|
14
|
+
| §6 | 공통 정의 | 공통/자연 도출 |
|
|
15
|
+
| §7 | 도메인 모델 | 공통/자연 도출 |
|
|
16
|
+
| §8 | 외부 인터페이스 | 공통/자연 도출 |
|
|
17
|
+
| §9 | 본문 외 결정사항 | 메타 |
|
|
18
|
+
| §10 | 변경 이력 | 메타 |
|
|
19
|
+
|
|
20
|
+
§6/§7/§8/§9/§10 은 작성 워크플로 중 자연 도출됨 (별도 워크플로 단계 없음).
|
|
21
|
+
|
|
22
|
+
## 마커
|
|
23
|
+
|
|
24
|
+
### 헤더 마커 (섹션 상태)
|
|
25
|
+
|
|
26
|
+
| 마커 | 의미 |
|
|
27
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `[확정: YYYY-MM-DD]` | 섹션 확정. 본문에 인라인 `[OPEN]` 있어도 무방. |
|
|
29
|
+
| `[OPEN: YYYY-MM-DD]` | 섹션 자체 보류. 본문 = 재분석용 참조 포인터만. 임의안(BPMN/와이어프레임/항목 등) 채우지 X. |
|
|
30
|
+
| `[확정: YYYY-MM-DD, 구현: YYYY-MM-DD]` | §4 화면 / §5 자동 처리 한정. `[확정]` 마커에 `구현: 날짜` 를 콤마로 이어붙인 확장형. sd-impl 이 시연 검증까지 통과한 시점에 부착. 본문이 변경되면 `[확정]` 날짜 갱신 여부와 무관하게 `구현: …` 부분을 제거 (구버전 구현 무효화). |
|
|
31
|
+
|
|
32
|
+
대괄호 쌍을 연달아 두면(`[확정: …][구현: …]`) 마크다운이 reference-style 링크로 해석해 렌더링이 깨지므로, **단일 대괄호 안 콤마 결합** 형식을 사용한다.
|
|
33
|
+
|
|
34
|
+
### 본문 인라인 마커
|
|
35
|
+
|
|
36
|
+
| 마커 | 의미 |
|
|
37
|
+
| -------- | ----------------------------------------- |
|
|
38
|
+
| `[OPEN]` | 정보 부족·근거 없는 항목. 향후 확정 필요. |
|
|
39
|
+
|
|
40
|
+
- 임의 채우거나 누락하지 말고 `[OPEN]` 인라인 표기.
|
|
41
|
+
- 근거 부족 판정 = sd-base-rules "결정 근거" 적용. As-Is 만 근거인 항목·답변 범위 흡수 등 안티패턴 자료는 근거 없음으로 보고 `[OPEN]`.
|
|
42
|
+
- 헤더 `[확정]` + 본문 인라인 `[OPEN]` = OPEN 항목 인정한 상태로 섹션 확정. 향후 OPEN 만 처리.
|
|
43
|
+
- 묻기 시 선택지: `맞나요? [OPEN 상태로 확정 / 섹션 전체 보류 / OPEN 하나씩 해결]`
|
|
44
|
+
|
|
45
|
+
### 헤더 `[OPEN]` 본문 — 재분석용 참조 포인터
|
|
46
|
+
|
|
47
|
+
섹션 보류 시 본문에 담을 항목 (임의안 X):
|
|
48
|
+
|
|
49
|
+
- **자료 위치**: Requirement Source 파일·범위 (예: `회의록.md L12-30`, `첨부A.pdf p.3`).
|
|
50
|
+
- **LLM 과의 대화 발췌**: 분석 세션 중 사용자가 보류 즈음 준 부분 의견·근거·미결 코멘트 1~2줄 직접 인용 (Requirement Source 발화 X — 그건 "자료 위치" 로 처리).
|
|
51
|
+
- **자료 연결 메모**: 한 섹션이 여러 자료에 걸칠 때 연결 추정 한 줄.
|
|
52
|
+
- **다른 § 확정 영향 메모**: OPEN 유지 중 다른 § 확정이 본 OPEN 의 재분석에 영향을 줄 때 누적되는 한 줄 메모. 형식: `§X.Y <섹션명> 확정 — <결정 한 줄>` (운용 규칙은 SKILL.md "OPEN 섹션 영향 푸시").
|
|
53
|
+
|
|
54
|
+
재개 시 이 포인터로 LLM 이 자료 재독 → 임의안 재도출 → 확정되면 본문 전체를 임의안으로 교체하고 헤더 마커 `[OPEN]` → `[확정: 날짜]`.
|
|
55
|
+
|
|
56
|
+
## 본문 내 참조 (이름 기반)
|
|
57
|
+
|
|
58
|
+
본문 내 다른 섹션 참조 시 § 번호 대신 `[카테고리.이름]` 형식 사용. 다단 표기 가능.
|
|
59
|
+
|
|
60
|
+
- `[모델.재고]`, `[모델.박스.수량]`, `[모델.박스.품목.코드]`, `[화면.재고 확인]`, `[프로세스.입고]`, `[기타.과거 재고 조회]`, `[자동 처리.재고 스냅샷]`, `[외부인터페이스.ERP 입고 통보]`, `[공통 정의.Location 라벨]`
|
|
61
|
+
|
|
62
|
+
§ 번호는 분석 진행 중 자주 바뀌므로 이름 기반이 안정적.
|
|
63
|
+
|
|
64
|
+
## §1 개요
|
|
65
|
+
|
|
66
|
+
### §1.1 핵심 목적
|
|
67
|
+
|
|
68
|
+
- 한줄 동사형 큰 단위 표현.
|
|
69
|
+
- 0단계 도메인 관계도 기반 사이클·관계 표현. §2.x 동사구 항목 나열은 §1.2 의 역할이므로 X.
|
|
70
|
+
|
|
71
|
+
### §1.2 주요 목표
|
|
72
|
+
|
|
73
|
+
- 단위: 화면·기능 단위가 아니라 최종 사용자가 수행하는 업무 흐름 1건.
|
|
74
|
+
- 표현: 한 줄 동사구. 최종 사용자 도메인 어휘.
|
|
75
|
+
- §2 업무 프로세스 헤더와 1:1 매핑이 일반적.
|
|
76
|
+
- §2.x 본문에 명시된 핵심 항목은 한 줄에 모두 담아 임의 축약·누락 X.
|
|
77
|
+
|
|
78
|
+
### §1.3 최종 사용자/이해관계자
|
|
79
|
+
|
|
80
|
+
- 실제 담당자 이름은 넣지 않음.
|
|
81
|
+
- 설명은 일반화하여 작성.
|
|
82
|
+
|
|
83
|
+
### §1.4 환경/장치
|
|
84
|
+
|
|
85
|
+
구성도와 장치 목록은 목적이 별개. 각각 독립 작성.
|
|
86
|
+
|
|
87
|
+
- ASCII 구성도: 현장이 어떻게 생겼는지 시각화 — 이해당사자 간 현장 그림 맞추기용.
|
|
88
|
+
- 포함: 솔루션 측 노드(서버·데이터베이스·클라이언트 장치) + 노드 간 연결선 + 물리 위치 그룹(IDC·사무실·창고 등) + 자동 연동 외부 시스템.
|
|
89
|
+
- 제외: Actor, 외부 관계자(인적·조직), 수동 채널(메일·종이 등), 구체 제품명(MySQL 등)·통신 프로토콜(HTTPS 등), 장치 상세 사양(OS·해상도 등).
|
|
90
|
+
- 장치 목록: 솔루션이 대상으로 하는 장치/환경 스펙 — 서버·DB·클라이언트 장치 등. OS·버전·제품명·모델·해상도·하드웨어 등. 명시 스펙에 맞게 개발하며, 다른 스펙 환경에서의 동작은 책임 범위 외.
|
|
91
|
+
|
|
92
|
+
## §2 업무 프로세스
|
|
93
|
+
|
|
94
|
+
§2.x 분할 판별은 [SKILL.md 1단계](../SKILL.md). §1.2 주요 목표 1건 ≈ §2.x 1건 매핑이 일반적.
|
|
95
|
+
|
|
96
|
+
### 헤더 명칭
|
|
97
|
+
|
|
98
|
+
- 시스템·문서·메뉴·양식 명칭 그대로 X (예: 발주서·송장 등 문서명을 동사구에 쓰지 X).
|
|
99
|
+
- 도메인 업무 동사구 + 외부 관계자 관계가 드러나도록 (예: `구매처 발주 변경 요청`).
|
|
100
|
+
- 외부 관계자 식별은 [SKILL.md 0단계](../SKILL.md) 관계도 참조.
|
|
101
|
+
|
|
102
|
+
### BPMN
|
|
103
|
+
|
|
104
|
+
- 사용자에겐 ASCII 로 보여주고, 확정 후 mermaid 로 문서 저장.
|
|
105
|
+
- 흐름 단위 = 외부 비즈니스 이벤트 트리거부터 결과·후속까지 풀 흐름. 단일 화면 입력 절차 X.
|
|
106
|
+
- 노드 = 최종 사용자 액션·시스템 핵심 트랜잭션 (1행 동사구). 줄바꿈(`<br/>`) X.
|
|
107
|
+
- Actor·장치·매체(PDA·PC·종이 등)는 액션 컨텍스트로 노드에 명시 OK (예: `창고 작업자: PDA 박스 바코드 스캔`). OS·해상도·API·DB 등 시스템 내부 디테일은 X.
|
|
108
|
+
- 외부 채널 송신(메일·파일 다운로드 등)·외부 응답 수신(다음 사이클 자료 도착 등) 도 노드로 명시. 처리 노드는 사각(`T[...]`), 이벤트 노드는 둥근 노드(`E([...])`).
|
|
109
|
+
- 분기 = 사용자 의사결정 분기만.
|
|
110
|
+
- BPMN 아래·관련 섹션 위에 흐름 설명을 bullet 로 자유 나열 (별도 헤더 X). 노드 동사구만으로 안 잡히는 룰·조건·계산식·외부와의 약속·자료 출처 인용 등을 1줄씩. §4 화면·§5 자동 처리 본문 작성 시 이 bullet 들을 근거로 매핑하여 누락 방지. 단, §4 자체 디테일(필드·UI·파일 확장자) / §6·§7·§8 정형 명세는 여기 X — 각 §, 본문에선 이름 참조.
|
|
111
|
+
|
|
112
|
+
### 관련 섹션
|
|
113
|
+
|
|
114
|
+
BPMN 아래에 `관련 섹션:` 한 줄 — 본 섹션이 참조/의존하는 다른 섹션을 `[카테고리.이름]` 콤마 나열 (카테고리 제한 없음).
|
|
115
|
+
|
|
116
|
+
## §3 기타 요구사항
|
|
117
|
+
|
|
118
|
+
- 프로세스 단위는 아니지만 정형 분해(화면/자동 처리) 동반하는 사용자 직접 요구.
|
|
119
|
+
- 본문에는 요구 의도(한 줄~한 문단) + `관련 섹션:` 한 줄 (참조/의존 섹션을 `[카테고리.이름]` 콤마 나열, 카테고리 제한 없음) 만.
|
|
120
|
+
- 구현 디테일은 §4 화면 / §5 자동 처리 본문에서 다룸.
|
|
121
|
+
|
|
122
|
+
## §4 화면
|
|
123
|
+
|
|
124
|
+
### 화면 목록 표
|
|
125
|
+
|
|
126
|
+
§4 첫머리에 5컬럼 표:
|
|
127
|
+
|
|
128
|
+
| § | 분류 | 화면 | 유형 | 장치 |
|
|
129
|
+
|
|
130
|
+
- 분류: 도메인 묶음/메뉴 그룹 자유 명칭 (예: `기준정보`, `입고`, `재고`). LLM 임의안 → 확정.
|
|
131
|
+
- 유형: 마스터 / 트랜잭션 / 조회
|
|
132
|
+
- 장치: PC / PDA / 기타
|
|
133
|
+
- 화면 추가/제거 시 표도 갱신. 같은 분류끼리 인접 배치.
|
|
134
|
+
|
|
135
|
+
### 화면 정의
|
|
136
|
+
|
|
137
|
+
§4.x 표준 구조 (위→아래 순서):
|
|
138
|
+
|
|
139
|
+
- 헤더 인덱스 (한 줄씩):
|
|
140
|
+
- `Actor: <역할>`
|
|
141
|
+
- `관련 섹션: [카테고리.이름], ...` — 본 화면이 참조/의존하는 다른 섹션 콤마 나열 (카테고리 제한 없음. 모달 호출·시트 영역 재활용 등 화면 간 의존도 포함)
|
|
142
|
+
- 기능 개요: 불릿으로 화면 기능 설명
|
|
143
|
+
- 와이어프레임
|
|
144
|
+
- 항목: 데이터 항목만 (필터·시트 컬럼·입력/상세 폼). 액션 버튼은 "동작" 에.
|
|
145
|
+
- **표 제목은 와이어의 영역 라벨과 동일 명칭**으로 굵게 표기. 와이어 `<필터>` → `**필터**`, `<품목 목록 시트>` → `**품목 목록 시트**`, `<스캔 입력 폼>` → `**스캔 입력 폼**`.
|
|
146
|
+
- 한 영역에 종류가 다른 표가 여러 개 필요하면 (좌·우 분할의 양쪽 시트 등) 종류 부기: `**<영역 라벨> — <필터|시트 컬럼|입력 폼>**` (예: `**헤더 목록 — 필터**`, `**BOA 시트 — 시트 컬럼**`).
|
|
147
|
+
- 시트 화면 기본 구성: 상단 command 바의 `<필터>` + 시트 영역 (시트 컬럼) 2 그룹.
|
|
148
|
+
- 표 형식 — 도메인 매핑은 별도 컬럼으로 (필터는 시트 컬럼과 중복이라 도메인 매핑 컬럼 X):
|
|
149
|
+
- 입력 폼: `항목 | 종류 | 필수 | 도메인 매핑 | 비고`
|
|
150
|
+
- 시트 컬럼: `컬럼 | 종류 | 필수 | 도메인 매핑 | 비고`
|
|
151
|
+
- 필터: `항목 | 종류 | 필수 | 비고` (시트 컬럼이 매핑 정보 보유)
|
|
152
|
+
- 필수 컬럼: 필수 여부가 무의미한 경우(조회 시트 컬럼 등) `-`.
|
|
153
|
+
- 도메인 매핑 컬럼: `[모델.X.Y]` 표기 (양식 매핑과 일관). 매핑 없는 항목(선택 체크박스 등) 은 `-`.
|
|
154
|
+
- 비고 컬럼: 표시 내용 (이름과 도메인으로 자명하지 않을 때 어떤 값이 표시되는지) / 편집 방법 (편집 가능 항목의 동작 — 예: 클릭 시 모달, 인라인 편집) / 기타 자유 설명.
|
|
155
|
+
- 시트 컬럼 그룹핑 (해당 시): 시트 컬럼이 도메인적으로 묶일 때 표 안에 그룹 표시. 그룹 헤더 행 1줄 (`**그룹명**`, 다른 셀 빈 칸) + 자식 컬럼은 `└ ` 들여쓰기 prefix. 표 컬럼 수 유지.
|
|
156
|
+
- 동작: 액션 버튼·이벤트 별 처리.
|
|
157
|
+
- 시각 규칙 (해당 시): 행 단위·조건부 시각 표현(비활성 행 취소선·상태별 강조 색·아이콘 등). 컬럼 단위 표현은 항목 표 비고에 작성하므로 여기 X.
|
|
158
|
+
- 도메인 규칙·로직 (해당 시): 표준 절(항목/동작/양식 매핑)로 안 담기는 화면 고유 도메인 요구는 자유 명칭의 절을 필요한 만큼 추가. 누락 없이 적는 것이 핵심.
|
|
159
|
+
- 양식 매핑 (해당 시): 외부 양식 파일을 다루는 동작(업로드·다운로드) 별로 매핑 표. 표 컬럼: `파일 컬럼` + `도메인 모델 ([모델.X.Y])` + `변환·규칙 (해당 시)`. 양식별 별도 표 + 방향 명시 (예: `업로드 양식`, `다운로드 양식`). §6.x 에 명세된 양식이면 컬럼명 일치, 일회성이면 화면 안에서 직접 명세.
|
|
160
|
+
|
|
161
|
+
- 화면 헤더에 (장치) 표기 유지: `### N.N 화면명 (PC) [확정: 날짜]` 또는 `(PDA)` 등.
|
|
162
|
+
- 모달 화면은 별도 §4.x 로 분리 (부르는 쪽 동작에 "→ [화면.X] 을 모달로 띄움" 명시). 화면명에 "(모달)" 등 사용 맥락 표기 X — 같은 화면이 다른 곳에서 다르게 호출될 수 있음.
|
|
163
|
+
- 화면 일부 영역(시트·탭)이 다른 화면에서 모달로 재활용되면 별도 §4.x 분리 X. 대신 그 화면 동작 절 끝에 영역별 모달 호출 시 제약(편집 가능 여부 / 선택 전용 / multiselect 등) 한 줄씩 명시. 호출하는 쪽 동작은 "→ [화면.X] 의 <영역> 을 모달로 띄움" 으로 표기.
|
|
164
|
+
|
|
165
|
+
### 마스터 화면 표준
|
|
166
|
+
|
|
167
|
+
- ID 컬럼이 편집 버튼 역할(`[E N]`).
|
|
168
|
+
- 첫 컬럼은 선택 체크박스(`[ ]`).
|
|
169
|
+
- 시트 상단 버튼바: `[등록] [선택 삭제] [선택 복구] [엑셀 업로드] [엑셀 다운로드]`.
|
|
170
|
+
- ID 정렬 역방향.
|
|
171
|
+
|
|
172
|
+
### 상단 command 바
|
|
173
|
+
|
|
174
|
+
페이지 제목 바로 아래, 시트/폼 영역 위. 페이지 전체 또는 현재 레코드 단위 액션 바.
|
|
175
|
+
|
|
176
|
+
- 좌측: 필터 입력 + 조회 (list) / 진입 컨텍스트 표시 (detail)
|
|
177
|
+
- 우측: 페이지·레코드 단위 액션 (있을 때만)
|
|
178
|
+
- 좌/우 사이 ` │ ` 세로 구분선
|
|
179
|
+
|
|
180
|
+
우측 버튼 그룹 순서 (좌→우):
|
|
181
|
+
|
|
182
|
+
1. 기본 CRUD (저장 / 삭제 / 복구 등)
|
|
183
|
+
2. 워크플로 상태 전환 (확정 / 취소 / 승인 / 반려 등)
|
|
184
|
+
3. 유틸리티 (원본 다운로드 / 프린트 / PDF 등)
|
|
185
|
+
|
|
186
|
+
list·detail 동일. 새 버튼은 해당 그룹 끝에 추가.
|
|
187
|
+
시트 상단 버튼바도 동일 그룹 순서 적용 (마스터 화면 표준은 구체 인스턴스).
|
|
188
|
+
|
|
189
|
+
### 와이어프레임 (텍스트)
|
|
190
|
+
|
|
191
|
+
ASCII 그림 공통 규칙은 `sd-base-rules.md` 의 "ASCII 그림" 절 참조.
|
|
192
|
+
|
|
193
|
+
**원칙**: 영역 배치·구획만 잡는다. 디테일(필드·시트 컬럼·실제 값·아이콘 placeholder·fixed 경계·비활성 행 등 시각 표현)은 와이어에 X — 항목 표·동작 절·도메인 규칙 절이 단일 출처.
|
|
194
|
+
|
|
195
|
+
- 데이터 영역은 영역 타입 + 짧은 라벨로 추상화: `<필터>`, `<폼>`, `<시트>`, `<목록>`, `<PO 목록>`, `<라인 시트 - 작성영역>` 등. 영역 종류가 한눈에 안 잡히면 라벨 보강.
|
|
196
|
+
- 액션 버튼은 텍스트 유지 (`[조회]`, `[저장]`, `[등록]` 등) — 버튼 위치가 와이어의 정보. 아이콘만 있는 버튼도 텍스트로 표기.
|
|
197
|
+
- 화면이 영역(좌/우 분할·탭·상단 command 바·시트 상단 버튼바 등)으로 나뉘면 박스 라인으로 구획 표시.
|
|
198
|
+
- 상태(작성중/확정 등)에 따라 영역 구획이 크게 달라지면 상태별로 와이어프레임 분리. 제목은 `와이어프레임 (<상태명>):` (예: `와이어프레임 (확정 전):`, `와이어프레임 (확정 후):`).
|
|
199
|
+
|
|
200
|
+
## §5 자동 처리
|
|
201
|
+
|
|
202
|
+
스케줄러/이벤트 트리거로 도는 시스템 백그라운드 처리. 표준 프로토콜·채널을 통한 외부 자료 수집·적재(메일 폴링 + 첨부 적재, FTP 자료 흡수 등) 도 §5 — 시스템별 협상 없는 표준 인터페이싱은 §8 X.
|
|
203
|
+
|
|
204
|
+
서브섹션: Flowchart / 목적 / 트리거 / 처리 / 예외 처리 / 양식 매핑 (해당 시) / 관련 섹션.
|
|
205
|
+
|
|
206
|
+
- 양식 매핑 (해당 시): 외부 양식 파일을 다루는 처리(읽기·쓰기) 별로 매핑 표. 표 컬럼: `파일 컬럼` + `도메인 모델 ([모델.X.Y])` + `변환·규칙 (해당 시)`. 양식별 별도 표 + 방향 명시 (예: `읽기 양식`, `쓰기 양식`). §6.x 에 명세된 양식이면 컬럼명 일치, 일회성이면 처리 본문에서 직접 명세.
|
|
207
|
+
- 마지막 `관련 섹션:` 한 줄에 참조/의존 섹션을 `[카테고리.이름]` 콤마 나열 (카테고리 제한 없음).
|
|
208
|
+
|
|
209
|
+
### Flowchart
|
|
210
|
+
|
|
211
|
+
- 사용자에겐 ASCII 로 보여주고, 확정 후 mermaid 로 문서 저장.
|
|
212
|
+
- 노드 = 시스템 처리 단계 (1행 동사구).
|
|
213
|
+
- 분기 = 시스템 조건 분기·예외.
|
|
214
|
+
- 시작 = 트리거 (시간·이벤트). 종결 = 결과.
|
|
215
|
+
- 특수 케이스(상태 머신 / 호출 시퀀스 등)는 mermaid 의 다른 다이어그램 type(stateDiagram-v2 / sequenceDiagram 등) 사용 가능.
|
|
216
|
+
|
|
217
|
+
## §6 공통 정의
|
|
218
|
+
|
|
219
|
+
- §6.1 용어 사전 고정. 도메인 어휘·약어·시스템 내 의미 정의.
|
|
220
|
+
- 그 외 시스템 전반 규격(바코드 형식, 라벨, 공통 정책 등)은 §6.2~ 로 추가.
|
|
221
|
+
- 특정 §2/§3 본문 단계에서 자연 흡수되는 규칙(업로드 자료 컬럼 매핑·자료 해석 규칙 등)은 §6 X → 사용처 본문에 둠.
|
|
222
|
+
|
|
223
|
+
### 외부 자료 명세
|
|
224
|
+
|
|
225
|
+
§6 외부 자료 = **시스템 외부에서 정의되어 도메인 모델로 자명하지 않은** 자료 (예: 외부 시스템이 송신하는 파일, 거래처가 보내는 표준 양식, 정해진 외부 규격). 도메인 모델의 자체 엑셀 업로드/다운로드 양식은 §6 X — §7 도메인 모델 + §4/§5 양식 매핑으로 자명.
|
|
226
|
+
|
|
227
|
+
위 정의를 만족하는 §6.x 는 자료별 표 필수. 외부 자료의 모든 컬럼/필드를 1행 1정의로 나열 (자료 자체 객관 명세).
|
|
228
|
+
|
|
229
|
+
자료-레벨 메타(송신 측·자료 라이프사이클·갱신 주기·식별 키 구조 등 자료 *전체* 에 적용되는 객관 명세)는 근거 있을 때 컬럼 표 위에 자유롭게 작성 (불릿/단락/`라벨: 값` 모두 허용, 자료 성격에 맞게). 컬럼 표 안에 욱여넣지 X.
|
|
230
|
+
|
|
231
|
+
- 외부 자료가 여러 개 (예: `SAP.XML`, `D1.CSV`) 면 자료별 별도 표.
|
|
232
|
+
- 표 컬럼: 자료 성격에 따라 LLM 임의안 → 확정. 예: `컬럼명/식별자` + `필수/선택` + `설명/규칙`.
|
|
233
|
+
- 모든 컬럼 행 유지.
|
|
234
|
+
- "설명/규칙" 류 컬럼은 **그 컬럼이 무엇인지(데이터 정의: 형식·값 범위·의미·제약)** 만 기재. **용도(어디에 어떻게 쓰이는지)** X — 용도·매핑은 사용처(§4 양식 매핑 / §5 양식 매핑) 에서 다룸.
|
|
235
|
+
- 각 셀 값은 근거 채택 가능 자료(원본 자료 명시 정의·사용자 발언 등) 있을 때만 채움. 추정·임의 작성 X.
|
|
236
|
+
- "원본 따름"·"전체 명세는 X.xlsx 참조" 등 외부 참조로 본문 정의 대체 X.
|
|
237
|
+
- 원본 자료가 LLM 접근 불가/누락/모호 → 임의 처리 X. 사용자에게 자료 또는 명세 정보 요청.
|
|
238
|
+
|
|
239
|
+
## §7 도메인 모델
|
|
240
|
+
|
|
241
|
+
- 식별 키: 모든 엔티티에 `ID` 필드 (숫자, 자동 부여) 명시.
|
|
242
|
+
- 비즈니스 키 (코드 등): 별도 명시. 수정 가능 (PK 가 아니므로).
|
|
243
|
+
- 활성/비활성 boolean = 소프트 삭제 플래그. 마스터에는 완전 삭제 없음. UI 의 "삭제/복구" 액션과 매핑 → §6.1 용어 사전에 한 줄 명문화.
|
|
244
|
+
- 섹션 구조: `필드:` 표 + `키/제약:` 불릿.
|
|
245
|
+
- 필드 표 컬럼: `필드 | 타입 | 필수 | 비고`.
|
|
246
|
+
- 비고 컬럼: **그 필드가 무엇인지(데이터 정의: 형식·값 범위·의미·제약·예시)** 만 기재. **용도·출처·외부 양식/외부 시스템과의 매핑** X — 그건 §4 양식 매핑 / §5 양식 매핑 / §8 자료 매핑 에서 다룸.
|
|
247
|
+
|
|
248
|
+
## §8 외부 인터페이스
|
|
249
|
+
|
|
250
|
+
§8 = 상대 시스템 고유 인터페이스 약속 (시스템마다 자료 매핑·방식이 달라 협상이 필요한 것).
|
|
251
|
+
|
|
252
|
+
- 포함 예: 상대 ERP/거래처가 자체 정의한 API·EDI 규격, 외부 시스템 webhook 페이로드.
|
|
253
|
+
- 제외 예: 표준 프로토콜·채널 (메일 SMTP/IMAP/Exchange/Graph, FTP, 표준 OAuth 등). 시스템별 협상 없음 → §5 자동 처리에서 트리거·처리·양식 매핑으로 흡수.
|
|
254
|
+
|
|
255
|
+
본문은 도메인 약속 레벨까지만. 구체 endpoint URL·HTTP method·query 파라미터·인증 흐름 단계(grant_type·scope·token endpoint)·SDK 메소드명 등 구현 디테일은 X — 구현이 알아서. (§2 BPMN·§4 와이어·§7 도메인 모델과 동일 원칙)
|
|
256
|
+
|
|
257
|
+
§8.x 표준 구조 (위→아래 순서):
|
|
258
|
+
|
|
259
|
+
- 기본 정보 (헤더 없이 불릿 3개):
|
|
260
|
+
- `상대 시스템: <시스템명>`
|
|
261
|
+
- `방향: <방향 표기>`
|
|
262
|
+
- `전송 방식: <방식>`
|
|
263
|
+
- `자료 매핑:` 헤더 + 표 (상대 시스템 필드 ↔ 본 시스템 출처)
|
|
264
|
+
- `예외 처리:` 헤더 + 본문 (실패 케이스별 위험/대처/재시도 한계)
|
|
265
|
+
- `관련 섹션:` 한 줄 — 호출자 등 참조/의존 섹션을 `[카테고리.이름]` 콤마 나열 (카테고리 제한 없음)
|
|
266
|
+
|
|
267
|
+
한 §8.x 당 묻기 단위:
|
|
268
|
+
|
|
269
|
+
1. 기본 정보 + 자료 매핑 → "맞나요?"
|
|
270
|
+
2. 예외 처리 → "맞나요?"
|
|
271
|
+
|
|
272
|
+
## §9 본문 외 결정사항
|
|
273
|
+
|
|
274
|
+
§1~§8 어디에도 자연스럽게 들어가지 않는 결정·메모만. §1~§8 의 적절한 자리에 박을 수 있는 결정은 §9 X (누락 도피처로 사용 금지).
|
|
275
|
+
|
|
276
|
+
### 분석 제외 항목
|
|
277
|
+
|
|
278
|
+
1단계 헤더 분류 + 이후 본문 작성 중 식별된 "제외" 결정을 1줄씩 누적. 형식:
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
- <요구 한 줄> — <사유 한 마디 (운영 잔손 / 범위 밖 / 보류 등)>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## §10 변경 이력
|
|
285
|
+
|
|
286
|
+
- 본문 수정·추가 사항을 날짜순으로 누적 기록.
|
|
287
|
+
- 형식: `- YYYY-MM-DD: <변경 내용>` (간결하고 명확하게 작성)
|
|
@@ -1,107 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# {name} 요구 분석서
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## 1. 개요
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### 1.1 핵심 목적
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
# REQ-001-입고지시서수정
|
|
7
|
+
### 1.2 주요 목표
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
- 상태: draft | specifying | specified | planning | planned | implementing | implemented | verifying | done | dropped
|
|
12
|
-
- 생성일: YYYY-MM-DD
|
|
13
|
-
- 마지막 갱신: YYYY-MM-DD
|
|
14
|
-
- 관련 영역: <도메인 / 세부영역>
|
|
15
|
-
- 의존: REQ-XXX (있을 때만)
|
|
9
|
+
### 1.3 최종 사용자/이해관계자
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
<!-- 분리/병합/폐기/재분류 발생 시 기록. 평소엔 섹션 자체 생략 가능 -->
|
|
19
|
-
- YYYY-MM-DD: REQ-XXX에서 분리됨
|
|
11
|
+
### 1.4 환경/장치
|
|
20
12
|
|
|
21
|
-
##
|
|
22
|
-
<1줄 요약>
|
|
13
|
+
## 2. 업무 프로세스
|
|
23
14
|
|
|
24
|
-
##
|
|
25
|
-
<!-- 이 REQ 분석/Q 처리 중 발견된 약어·도메인 고유어·모호 용어. 일반 명사 X. 없으면 섹션 생략 가능 -->
|
|
26
|
-
- [ ] T1: <용어>
|
|
27
|
-
- **A**: <합의된 정의> (YYYY-MM-DD 확정)
|
|
28
|
-
- 출처: R<번호> 또는 <파일경로>:L<범위>
|
|
29
|
-
- [ ] T2: <용어>
|
|
30
|
-
- [ ] **Q**: <정의/동의어/범위 등 확인 필요 사항>
|
|
31
|
-
- 출처: ...
|
|
15
|
+
## 3. 기타 요구사항
|
|
32
16
|
|
|
33
|
-
##
|
|
34
|
-
- [ ] R1: <요구 제목>
|
|
35
|
-
> [YYYY-MM-DD, 초안] "원문 인용"
|
|
36
|
-
> 출처: <파일경로>:L<범위> 또는 채팅 paste 인용 + 일자
|
|
37
|
-
>
|
|
38
|
-
> [YYYY-MM-DD, **최종**] "최종 인용"
|
|
39
|
-
> 출처: ...
|
|
17
|
+
## 4. 화면
|
|
40
18
|
|
|
41
|
-
|
|
42
|
-
- 근거: <항상 명시. 사용자 답변 (YYYY-MM-DD) / 코드경로:L범위 / 공식문서 URL / 표준명 등>
|
|
43
|
-
- [ ] **Q**: <사용자에게 확인 필요한 사항>
|
|
19
|
+
## 5. 자동 처리
|
|
44
20
|
|
|
45
|
-
|
|
46
|
-
```
|
|
21
|
+
## 6. 공통 정의
|
|
47
22
|
|
|
48
|
-
##
|
|
23
|
+
## 7. 도메인 모델
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
|---|---|
|
|
52
|
-
| `## 메타` | 상태/일시/영역/의존 |
|
|
53
|
-
| `## 이력` | 메타 수준 변경 (분리/병합/폐기/재분류). 발생 시만 |
|
|
54
|
-
| `## 요약` | 1줄 요약 |
|
|
55
|
-
| `## 용어` | 이 REQ 분석/Q 처리 중 발견된 용어. T 체크리스트 안에 A/Q 인라인. 없으면 생략 |
|
|
56
|
-
| `## 세부 요구` | R 체크리스트. 각 R 안에 인용/A/Q 인라인 |
|
|
25
|
+
## 8. 외부 인터페이스
|
|
57
26
|
|
|
58
|
-
##
|
|
27
|
+
## 9. 본문 외 결정사항
|
|
59
28
|
|
|
60
|
-
|
|
61
|
-
- **출처**: 파일경로 + 라인 범위 (예: `.docs/...eml:L42-L48`) 또는 채팅 paste 인용 + 일자. Direct 모드(사용자 직접 요청)는 "사용자 직접 요청 + 일자".
|
|
62
|
-
- **보정 시**: `[원문] "..."` 같이 보존, 화자 추정 시 `[추정: B 차장]`
|
|
63
|
-
- **A (가정)**: 사용자와 합의된 결정 또는 결정 근거 기반 자동 판단. 원본에 없는 것. 영구 보존. 결정 출처는 항상 `근거:` 줄로 명시.
|
|
64
|
-
- **Q (미결)**: 사용자에게 확인 필요. 0개 되어야 specified 전환 가능
|
|
65
|
-
|
|
66
|
-
## 예시
|
|
67
|
-
|
|
68
|
-
```markdown
|
|
69
|
-
## 용어
|
|
70
|
-
- [x] T1: 긴급
|
|
71
|
-
- **A**: 당일 입고 처리가 필요한 건 (2026-05-03 확정)
|
|
72
|
-
- 근거: 사용자 답변 (2026-05-03)
|
|
73
|
-
- 출처: R1
|
|
74
|
-
- [ ] T2: PDF 강조
|
|
75
|
-
- [ ] **Q**: 색상 단독인가, 굵기/배경도 포함인가?
|
|
76
|
-
- 출처: R2
|
|
77
|
-
|
|
78
|
-
## 세부 요구
|
|
79
|
-
- [ ] R1: 입고지시서 화면에 "긴급" 체크박스 추가
|
|
80
|
-
> [2026-01-22, 초안] "긴급 표시 기능이 필요합니다"
|
|
81
|
-
> 출처: .docs/20260122_Ethan_Reporting기능개발요청.eml:L80-L82
|
|
82
|
-
>
|
|
83
|
-
> [2026-03-25, **최종**] "체크박스 형태로 화면 우상단에 배치"
|
|
84
|
-
> 출처: .docs/20260325_Ethan_입고지시서수정요청건.eml:L42-L48
|
|
85
|
-
|
|
86
|
-
- **A**: 체크박스는 헤더 영역 우측 (2026-05-03 확정)
|
|
87
|
-
- 근거: 사용자 답변 (2026-05-03)
|
|
88
|
-
- **A**: 디폴트 unchecked (2026-05-06 확정)
|
|
89
|
-
- 근거: packages/angular/src/.../sd-checkbox.control.ts:L23 동일 패턴
|
|
90
|
-
|
|
91
|
-
- [ ] R2: 긴급 표시된 PDF 출력 시 빨간색 강조
|
|
92
|
-
> [2026-03-17 회의, 추정: B 차장] "PDF에 빨간색으로 강조"
|
|
93
|
-
> [원문] "PDF에 빨간색으루 강조"
|
|
94
|
-
> 출처: .docs/회의대본_3.txt:L120
|
|
95
|
-
|
|
96
|
-
- **A**: PDF는 #D32F2F (2026-05-03 확정)
|
|
97
|
-
- 근거: 사용자 답변 (2026-05-03)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Direct 모드 출처 표기 예시
|
|
101
|
-
|
|
102
|
-
Direct 모드(사용자 직접 요청)는 파일/라인 대신:
|
|
103
|
-
|
|
104
|
-
```markdown
|
|
105
|
-
> [2026-05-03, 사용자 요청] "상차 상태 추가"
|
|
106
|
-
> 출처: 사용자 직접 요청 (2026-05-03)
|
|
107
|
-
```
|
|
29
|
+
## 10. 변경 이력
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-unpack
|
|
3
|
-
description:
|
|
3
|
+
description: 메일·문서(eml/msg/pdf/docx/pptx/xlsx/xlsb, 레거시 doc/ppt/xls)를 첨부 포함 재귀적으로 풀어 평문 트리로 펼친다. Use when 위 형식 파일의 본문·첨부 전반을 훑어야 할 때 (분석·요약·정리·검토 등). 단순 단답 조회(특정 값/셀 확인)나 옆에 이미 펼친 `<basename>_<ext>/` 폴더가 있으면 호출 X.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -16,10 +16,16 @@ python .claude/skills/sd-unpack/scripts/unpack.py <입력파일 절대경로>
|
|
|
16
16
|
|
|
17
17
|
여러 파일을 풀어달라는 요청이 오면 단일 파일 단위로 반복 호출한다.
|
|
18
18
|
|
|
19
|
+
## 환경
|
|
20
|
+
|
|
21
|
+
Windows + MS Office 필요 (docx/pptx/xlsx 변환). Python 패키지 의존은 `ensure_pip` 가 자동 처리. COM 의존 미충족 시 해당 형식 핸들러는 throw.
|
|
22
|
+
|
|
19
23
|
## 결과 폴더
|
|
20
24
|
|
|
21
25
|
입력 파일 옆에 `<basename>_<ext>/` 가 생긴다. 컨테이너 첨부는 같은 패턴으로 재귀적으로 풀린다. 폴더 안 `_source.<ext>` + `README.md` 가 풀린 폴더의 식별 마커.
|
|
22
26
|
|
|
27
|
+
동일 입력 재호출 시 기존 결과 폴더는 사전 삭제 후 재생성 (이전 산출 잔존물 섞이지 않게).
|
|
28
|
+
|
|
23
29
|
시각은 PNG, 텍스트/구조는 MD/JSON 으로 분리해 출력한다.
|
|
24
30
|
|
|
25
31
|
```
|
|
@@ -29,6 +29,16 @@ def ensure_pip(import_name: str, pip_name: Optional[str] = None) -> None:
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def decode_bytes(payload: bytes) -> str:
|
|
33
|
+
"""바이트 → 문자열. charset-normalizer 로 인코딩 자동 감지. 실패 시 throw."""
|
|
34
|
+
ensure_pip("charset_normalizer", "charset-normalizer")
|
|
35
|
+
from charset_normalizer import from_bytes
|
|
36
|
+
result = from_bytes(payload).best()
|
|
37
|
+
if result is None:
|
|
38
|
+
raise RuntimeError(f"encoding detection failed (payload size={len(payload)})")
|
|
39
|
+
return str(result)
|
|
40
|
+
|
|
41
|
+
|
|
32
42
|
CONTAINER_EXTS = {".eml", ".msg", ".pdf", ".docx", ".pptx", ".xlsx", ".xlsb", ".doc", ".ppt", ".xls"}
|
|
33
43
|
|
|
34
44
|
OS_FORBIDDEN_CHARS = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
|
|
@@ -15,19 +15,14 @@ from .dispatch import maybe_recurse_attachment
|
|
|
15
15
|
def _decode_header(raw: str | None) -> str:
|
|
16
16
|
if not raw:
|
|
17
17
|
return ""
|
|
18
|
-
|
|
19
|
-
return str(make_header(decode_header(raw)))
|
|
20
|
-
except Exception:
|
|
21
|
-
return raw
|
|
18
|
+
return str(make_header(decode_header(raw)))
|
|
22
19
|
|
|
23
20
|
|
|
24
21
|
def _decode_payload(part) -> str:
|
|
25
22
|
payload = part.get_payload(decode=True) or b""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
except LookupError:
|
|
30
|
-
return payload.decode("utf-8", errors="replace")
|
|
23
|
+
if not payload:
|
|
24
|
+
return ""
|
|
25
|
+
return _common.decode_bytes(payload)
|
|
31
26
|
|
|
32
27
|
|
|
33
28
|
def run(input_path: Path, out_dir: Path) -> None:
|
|
@@ -97,10 +92,7 @@ def run(input_path: Path, out_dir: Path) -> None:
|
|
|
97
92
|
for ap in saved_attachments:
|
|
98
93
|
recursed = maybe_recurse_attachment(ap, attachments_dir)
|
|
99
94
|
if recursed is not None:
|
|
100
|
-
|
|
101
|
-
os.unlink(_common.long_str(ap))
|
|
102
|
-
except OSError:
|
|
103
|
-
pass
|
|
95
|
+
os.unlink(_common.long_str(ap))
|
|
104
96
|
attachment_links.append(f"attachments/{recursed.name}/")
|
|
105
97
|
else:
|
|
106
98
|
attachment_links.append(f"attachments/{ap.name}")
|
|
@@ -32,10 +32,7 @@ def run(input_path: Path, out_dir: Path) -> None:
|
|
|
32
32
|
body_html: str | None = None
|
|
33
33
|
if body_html_raw:
|
|
34
34
|
if isinstance(body_html_raw, bytes):
|
|
35
|
-
|
|
36
|
-
body_html = body_html_raw.decode("utf-8", errors="replace")
|
|
37
|
-
except Exception:
|
|
38
|
-
body_html = body_html_raw.decode("latin-1", errors="replace")
|
|
35
|
+
body_html = _common.decode_bytes(body_html_raw)
|
|
39
36
|
else:
|
|
40
37
|
body_html = body_html_raw
|
|
41
38
|
|
|
@@ -70,10 +67,7 @@ def run(input_path: Path, out_dir: Path) -> None:
|
|
|
70
67
|
_common.write_bytes(dst, data)
|
|
71
68
|
recursed = maybe_recurse_attachment(dst, attachments_dir)
|
|
72
69
|
if recursed is not None:
|
|
73
|
-
|
|
74
|
-
os.unlink(_common.long_str(dst))
|
|
75
|
-
except OSError:
|
|
76
|
-
pass
|
|
70
|
+
os.unlink(_common.long_str(dst))
|
|
77
71
|
attachment_links.append(f"attachments/{recursed.name}/")
|
|
78
72
|
else:
|
|
79
73
|
attachment_links.append(f"attachments/{dst.name}")
|
|
@@ -91,7 +85,4 @@ def run(input_path: Path, out_dir: Path) -> None:
|
|
|
91
85
|
attachments=attachment_links,
|
|
92
86
|
)
|
|
93
87
|
finally:
|
|
94
|
-
|
|
95
|
-
msg.close()
|
|
96
|
-
except Exception:
|
|
97
|
-
pass
|
|
88
|
+
msg.close()
|
|
@@ -160,18 +160,14 @@ def _run_pptx(
|
|
|
160
160
|
|
|
161
161
|
for shape_idx, shape in enumerate(slide.shapes, start=1):
|
|
162
162
|
if shape.has_chart:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
slide_charts.setdefault(idx, []).append(chart_filename)
|
|
173
|
-
except Exception:
|
|
174
|
-
pass
|
|
163
|
+
data = _extract_pptx_chart_data(shape.chart)
|
|
164
|
+
_common.mkdir(charts_dir)
|
|
165
|
+
chart_filename = f"slide{i:02d}_chart{shape_idx:02d}.data.json"
|
|
166
|
+
_common.write_text(
|
|
167
|
+
charts_dir / chart_filename,
|
|
168
|
+
json.dumps(data, ensure_ascii=False, indent=2),
|
|
169
|
+
)
|
|
170
|
+
slide_charts.setdefault(idx, []).append(chart_filename)
|
|
175
171
|
|
|
176
172
|
# 슬라이드별 산출물 풀목록
|
|
177
173
|
parts = [f"`slides/{idx}_{safe_title}.png`", "`.md`"]
|
|
@@ -290,18 +286,14 @@ def _run_xlsx(
|
|
|
290
286
|
sheet_formula_count[idx] = len(formulas)
|
|
291
287
|
|
|
292
288
|
for chart_idx, chart in enumerate(getattr(ws_f, "_charts", []), start=1):
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
)
|
|
302
|
-
sheet_charts.setdefault(idx, []).append(chart_filename)
|
|
303
|
-
except Exception:
|
|
304
|
-
pass
|
|
289
|
+
data = _extract_openpyxl_chart_data(chart)
|
|
290
|
+
_common.mkdir(charts_dir)
|
|
291
|
+
chart_filename = f"sheet{idx}_chart{chart_idx:02d}.data.json"
|
|
292
|
+
_common.write_text(
|
|
293
|
+
charts_dir / chart_filename,
|
|
294
|
+
json.dumps(data, ensure_ascii=False, indent=2),
|
|
295
|
+
)
|
|
296
|
+
sheet_charts.setdefault(idx, []).append(chart_filename)
|
|
305
297
|
finally:
|
|
306
298
|
wb_values.close()
|
|
307
299
|
wb_formulas.close()
|
|
@@ -554,21 +546,15 @@ def _extract_xlsx_images_with_position(
|
|
|
554
546
|
for img in getattr(ws, "_images", []):
|
|
555
547
|
# anchor 위치 추출 (OneCellAnchor / TwoCellAnchor 둘 다 _from 갖음)
|
|
556
548
|
cell_addr = "anchor_unknown"
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
cell_addr = f"{get_column_letter(col)}{row}"
|
|
564
|
-
except Exception:
|
|
565
|
-
pass
|
|
549
|
+
anchor = img.anchor
|
|
550
|
+
marker = getattr(anchor, "_from", None) or getattr(anchor, "from", None)
|
|
551
|
+
if marker is not None:
|
|
552
|
+
col = marker.col + 1 # 0-based → 1-based
|
|
553
|
+
row = marker.row + 1
|
|
554
|
+
cell_addr = f"{get_column_letter(col)}{row}"
|
|
566
555
|
|
|
567
556
|
# 이미지 raw 데이터 추출 (openpyxl 내부 API).
|
|
568
|
-
|
|
569
|
-
data = img._data()
|
|
570
|
-
except Exception:
|
|
571
|
-
continue
|
|
557
|
+
data = img._data()
|
|
572
558
|
if not data:
|
|
573
559
|
continue
|
|
574
560
|
|
|
@@ -235,10 +235,7 @@ def _export_one_sheet(wb, tmp: Path, sheets_dir: Path,
|
|
|
235
235
|
) from e
|
|
236
236
|
finally:
|
|
237
237
|
if original_visible != -1:
|
|
238
|
-
|
|
239
|
-
ws.Visible = original_visible
|
|
240
|
-
except Exception:
|
|
241
|
-
pass
|
|
238
|
+
ws.Visible = original_visible
|
|
242
239
|
|
|
243
240
|
|
|
244
241
|
# ====================================================================
|