oh-my-agent-commandcode 0.0.0-stage → 20.38.3
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/README.md +35 -2
- package/filter-test-output.sh +52 -0
- package/mods/oma.ts +347 -0
- package/package.json +30 -4
- package/skills/_shared/conditional/experiment-ledger.md +28 -0
- package/skills/_shared/conditional/exploration-loop.md +22 -0
- package/skills/_shared/conditional/quality-score.md +33 -0
- package/skills/_shared/core/anti-ai-prose.md +191 -0
- package/skills/_shared/core/api-contracts/README.md +28 -0
- package/skills/_shared/core/api-contracts/template.md +90 -0
- package/skills/_shared/core/clarification-protocol.md +23 -0
- package/skills/_shared/core/code-intelligence.md +46 -0
- package/skills/_shared/core/collaboration-policy.md +28 -0
- package/skills/_shared/core/common-checklist.md +28 -0
- package/skills/_shared/core/context-budget.md +22 -0
- package/skills/_shared/core/context-loading.md +34 -0
- package/skills/_shared/core/difficulty-guide.md +26 -0
- package/skills/_shared/core/execution-policy.md +31 -0
- package/skills/_shared/core/lessons-learned.md +33 -0
- package/skills/_shared/core/prompt-structure.md +18 -0
- package/skills/_shared/core/quality-principles.md +11 -0
- package/skills/_shared/core/session-metrics.md +35 -0
- package/skills/_shared/core/skill-routing.md +39 -0
- package/skills/_shared/core/test-approach.md +54 -0
- package/skills/_shared/core/vendor-detection.md +52 -0
- package/skills/_shared/runtime/memory-protocol.md +118 -0
- package/skills/_shared/runtime/result-contract.md +64 -0
- package/skills/_shared/ui-interaction-quality.md +133 -0
- package/skills/oma-academic-writing/SKILL.md +181 -0
- package/skills/oma-academic-writing/resources/abstract-guide.md +51 -0
- package/skills/oma-academic-writing/resources/academic-verb-tiers.md +42 -0
- package/skills/oma-academic-writing/resources/anti-ai-checklist.md +52 -0
- package/skills/oma-academic-writing/resources/hedging-guide.md +132 -0
- package/skills/oma-academic-writing/resources/sentence-structure-reference.md +151 -0
- package/skills/oma-architecture/SKILL.md +203 -0
- package/skills/oma-architecture/resources/api-evolution.md +41 -0
- package/skills/oma-architecture/resources/checklist.md +42 -0
- package/skills/oma-architecture/resources/execution-protocol.md +115 -0
- package/skills/oma-architecture/resources/methodology-selection.md +92 -0
- package/skills/oma-architecture/resources/migration-patterns.md +28 -0
- package/skills/oma-architecture/resources/output-templates.md +111 -0
- package/skills/oma-architecture/resources/stakeholder-synthesis.md +80 -0
- package/skills/oma-backend/SKILL.md +202 -0
- package/skills/oma-backend/resources/checklist.md +45 -0
- package/skills/oma-backend/resources/error-playbook.md +97 -0
- package/skills/oma-backend/resources/execution-protocol.md +39 -0
- package/skills/oma-backend/resources/orm-reference.md +61 -0
- package/skills/oma-backend/variants/node/api-template.ts +315 -0
- package/skills/oma-backend/variants/node/snippets.md +475 -0
- package/skills/oma-backend/variants/node/stack.yaml +21 -0
- package/skills/oma-backend/variants/node/tech-stack.md +33 -0
- package/skills/oma-backend/variants/python/api-template.py +378 -0
- package/skills/oma-backend/variants/python/snippets.md +199 -0
- package/skills/oma-backend/variants/python/stack.yaml +18 -0
- package/skills/oma-backend/variants/python/tech-stack.md +45 -0
- package/skills/oma-backend/variants/rust/api-template.rs +635 -0
- package/skills/oma-backend/variants/rust/snippets.md +471 -0
- package/skills/oma-backend/variants/rust/stack.yaml +20 -0
- package/skills/oma-backend/variants/rust/tech-stack.md +36 -0
- package/skills/oma-backend/variants/stack.schema.json +73 -0
- package/skills/oma-brainstorm/SKILL.md +166 -0
- package/skills/oma-brainstorm/resources/triz-lite.md +117 -0
- package/skills/oma-coordination/SKILL.md +171 -0
- package/skills/oma-db/SKILL.md +201 -0
- package/skills/oma-db/resources/anti-patterns.md +177 -0
- package/skills/oma-db/resources/checklist.md +67 -0
- package/skills/oma-db/resources/document-templates.md +107 -0
- package/skills/oma-db/resources/error-playbook.md +50 -0
- package/skills/oma-db/resources/examples.md +170 -0
- package/skills/oma-db/resources/execution-protocol.md +127 -0
- package/skills/oma-db/resources/iso-controls.md +98 -0
- package/skills/oma-db/resources/migration-playbook.md +93 -0
- package/skills/oma-db/resources/query-tuning.md +57 -0
- package/skills/oma-db/resources/vector-db.md +159 -0
- package/skills/oma-debug/SKILL.md +146 -0
- package/skills/oma-debug/resources/bug-report-template.md +327 -0
- package/skills/oma-debug/resources/checklist.md +31 -0
- package/skills/oma-debug/resources/common-patterns.md +734 -0
- package/skills/oma-debug/resources/debugging-checklist.md +364 -0
- package/skills/oma-debug/resources/error-playbook.md +94 -0
- package/skills/oma-debug/resources/execution-protocol.md +40 -0
- package/skills/oma-design/SKILL.md +135 -0
- package/skills/oma-design/resources/asset-strategy.md +34 -0
- package/skills/oma-design/resources/checklist.md +63 -0
- package/skills/oma-design/resources/data-grid.md +48 -0
- package/skills/oma-design/resources/design-md-spec.md +107 -0
- package/skills/oma-design/resources/design-tokens.md +53 -0
- package/skills/oma-design/resources/error-playbook.md +18 -0
- package/skills/oma-design/resources/execution-protocol.md +95 -0
- package/skills/oma-design/resources/external-design-skills.md +130 -0
- package/skills/oma-design/resources/getdesign-fetcher.md +104 -0
- package/skills/oma-design/resources/product-interface-review.md +59 -0
- package/skills/oma-design/resources/redesign-protocol.md +52 -0
- package/skills/oma-design/resources/stitch-integration.md +244 -0
- package/skills/oma-dev-workflow/SKILL.md +375 -0
- package/skills/oma-dev-workflow/resources/affected-checks.py +58 -0
- package/skills/oma-dev-workflow/resources/api-workflows.md +58 -0
- package/skills/oma-dev-workflow/resources/database-patterns.md +107 -0
- package/skills/oma-dev-workflow/resources/i18n-patterns.md +63 -0
- package/skills/oma-dev-workflow/resources/release-coordination.md +240 -0
- package/skills/oma-dev-workflow/resources/tooling-profiles.md +217 -0
- package/skills/oma-dev-workflow/resources/troubleshooting.md +78 -0
- package/skills/oma-dev-workflow/resources/validation-pipeline.md +246 -0
- package/skills/oma-docs/SKILL.md +77 -0
- package/skills/oma-docs/resources/commands.md +76 -0
- package/skills/oma-explanation/SKILL.md +212 -0
- package/skills/oma-explanation/resources/document-structure.md +115 -0
- package/skills/oma-explanation/resources/draft-format.md +199 -0
- package/skills/oma-explanation/resources/html-contract.md +102 -0
- package/skills/oma-frontend/SKILL.md +227 -0
- package/skills/oma-frontend/resources/angular-rules.md +110 -0
- package/skills/oma-frontend/resources/checklist.md +76 -0
- package/skills/oma-frontend/resources/error-playbook.md +125 -0
- package/skills/oma-frontend/resources/execution-protocol.md +46 -0
- package/skills/oma-frontend/resources/snippets.md +354 -0
- package/skills/oma-frontend/resources/specialized-visual-implementation.md +193 -0
- package/skills/oma-frontend/resources/tailwind-rules.md +83 -0
- package/skills/oma-frontend/resources/tech-stack.md +156 -0
- package/skills/oma-hwp/SKILL.md +166 -0
- package/skills/oma-hwp/config/hwp-config.yaml +35 -0
- package/skills/oma-hwp/resources/balanced-tables.ts +39 -0
- package/skills/oma-hwp/resources/execution-protocol.md +145 -0
- package/skills/oma-hwp/resources/flatten-tables.ts +101 -0
- package/skills/oma-hwp/resources/package.json +13 -0
- package/skills/oma-hwp/resources/troubleshooting.md +70 -0
- package/skills/oma-hwp/resources/tsconfig.json +10 -0
- package/skills/oma-hwp/resources/turndown-plugin-gfm.d.ts +9 -0
- package/skills/oma-image/SKILL.md +142 -0
- package/skills/oma-image/config/image-config.yaml +70 -0
- package/skills/oma-image/resources/checklist.md +18 -0
- package/skills/oma-image/resources/execution-protocol.md +117 -0
- package/skills/oma-image/resources/invocation.md +105 -0
- package/skills/oma-image/resources/prompt-tips.md +71 -0
- package/skills/oma-image/resources/vendor-matrix.md +90 -0
- package/skills/oma-market/SKILL.md +142 -0
- package/skills/oma-market/resources/checklist.md +12 -0
- package/skills/oma-market/resources/error-playbook.md +12 -0
- package/skills/oma-market/resources/execution-protocol.md +60 -0
- package/skills/oma-market/resources/frameworks/pestel.md +101 -0
- package/skills/oma-market/resources/frameworks/porters-5f.md +90 -0
- package/skills/oma-market/resources/frameworks/swot.md +61 -0
- package/skills/oma-market/resources/intent-rules.md +35 -0
- package/skills/oma-market/resources/output-laws.md +53 -0
- package/skills/oma-mobile/SKILL.md +168 -0
- package/skills/oma-mobile/resources/checklist.md +77 -0
- package/skills/oma-mobile/resources/error-playbook.md +198 -0
- package/skills/oma-mobile/resources/execution-protocol.md +47 -0
- package/skills/oma-mobile/resources/screen-template.dart +331 -0
- package/skills/oma-mobile/resources/screen-template.swift +239 -0
- package/skills/oma-mobile/resources/screen-template.tsx +179 -0
- package/skills/oma-mobile/resources/tech-stack.md +69 -0
- package/skills/oma-mobile/variants/README.md +45 -0
- package/skills/oma-mobile/variants/flutter/api-template.dart +461 -0
- package/skills/oma-mobile/variants/flutter/snippets.md +1353 -0
- package/skills/oma-mobile/variants/flutter/stack.yaml +21 -0
- package/skills/oma-mobile/variants/flutter/tech-stack.md +201 -0
- package/skills/oma-mobile/variants/kotlin-android/api-template.kt +182 -0
- package/skills/oma-mobile/variants/kotlin-android/snippets.md +871 -0
- package/skills/oma-mobile/variants/kotlin-android/stack.yaml +32 -0
- package/skills/oma-mobile/variants/kotlin-android/tech-stack.md +159 -0
- package/skills/oma-mobile/variants/react-native/api-template.ts +531 -0
- package/skills/oma-mobile/variants/react-native/snippets.md +1014 -0
- package/skills/oma-mobile/variants/react-native/stack.yaml +22 -0
- package/skills/oma-mobile/variants/react-native/tech-stack.md +192 -0
- package/skills/oma-mobile/variants/stack.schema.json +68 -0
- package/skills/oma-mobile/variants/swift-ios/api-template.swift +165 -0
- package/skills/oma-mobile/variants/swift-ios/snippets.md +1028 -0
- package/skills/oma-mobile/variants/swift-ios/stack.yaml +25 -0
- package/skills/oma-mobile/variants/swift-ios/tech-stack.md +174 -0
- package/skills/oma-observability/SKILL.md +225 -0
- package/skills/oma-observability/resources/anti-patterns.md +555 -0
- package/skills/oma-observability/resources/boundaries/cross-application.md +348 -0
- package/skills/oma-observability/resources/boundaries/multi-tenant.md +290 -0
- package/skills/oma-observability/resources/boundaries/release.md +372 -0
- package/skills/oma-observability/resources/boundaries/slo.md +225 -0
- package/skills/oma-observability/resources/checklist.md +123 -0
- package/skills/oma-observability/resources/examples.md +448 -0
- package/skills/oma-observability/resources/execution-protocol.md +166 -0
- package/skills/oma-observability/resources/incident-forensics.md +348 -0
- package/skills/oma-observability/resources/intent-rules.md +307 -0
- package/skills/oma-observability/resources/layers/L3-network.md +281 -0
- package/skills/oma-observability/resources/layers/L4-transport.md +299 -0
- package/skills/oma-observability/resources/layers/L7-application/crash-analytics.md +359 -0
- package/skills/oma-observability/resources/layers/L7-application/mobile-rum.md +278 -0
- package/skills/oma-observability/resources/layers/L7-application/waf.md +246 -0
- package/skills/oma-observability/resources/layers/L7-application/web-rum.md +350 -0
- package/skills/oma-observability/resources/layers/mesh.md +368 -0
- package/skills/oma-observability/resources/matrix.md +177 -0
- package/skills/oma-observability/resources/meta-observability.md +605 -0
- package/skills/oma-observability/resources/observability-as-code.md +666 -0
- package/skills/oma-observability/resources/signals/audit.md +310 -0
- package/skills/oma-observability/resources/signals/cost.md +303 -0
- package/skills/oma-observability/resources/signals/logs.md +263 -0
- package/skills/oma-observability/resources/signals/metrics.md +478 -0
- package/skills/oma-observability/resources/signals/privacy.md +351 -0
- package/skills/oma-observability/resources/signals/profiles.md +245 -0
- package/skills/oma-observability/resources/signals/traces.md +360 -0
- package/skills/oma-observability/resources/standards.md +214 -0
- package/skills/oma-observability/resources/transport/collector-topology.md +308 -0
- package/skills/oma-observability/resources/transport/otlp-grpc-vs-http.md +256 -0
- package/skills/oma-observability/resources/transport/sampling-recipes.md +297 -0
- package/skills/oma-observability/resources/transport/udp-statsd-mtu.md +167 -0
- package/skills/oma-observability/resources/vendor-categories.md +352 -0
- package/skills/oma-orchestration/SKILL.md +302 -0
- package/skills/oma-orchestration/config/cli-config.yaml +92 -0
- package/skills/oma-orchestration/resources/memory-schema.md +232 -0
- package/skills/oma-orchestration/resources/subagent-prompt-template.md +30 -0
- package/skills/oma-orchestration/scripts/parallel-run.sh +6 -0
- package/skills/oma-orchestration/scripts/spawn-agent.sh +5 -0
- package/skills/oma-orchestration/scripts/verify.sh +20 -0
- package/skills/oma-orchestration/templates/backend-task.md +19 -0
- package/skills/oma-orchestration/templates/debug-task.md +16 -0
- package/skills/oma-orchestration/templates/frontend-task.md +18 -0
- package/skills/oma-orchestration/templates/mobile-task.md +18 -0
- package/skills/oma-orchestration/templates/qa-task.md +16 -0
- package/skills/oma-orchestration/templates/tasks-example.yaml +15 -0
- package/skills/oma-pdf/SKILL.md +162 -0
- package/skills/oma-pdf/config/pdf-config.yaml +27 -0
- package/skills/oma-pdf/resources/execution-protocol.md +127 -0
- package/skills/oma-pm/SKILL.md +157 -0
- package/skills/oma-pm/resources/error-playbook.md +75 -0
- package/skills/oma-pm/resources/examples.md +439 -0
- package/skills/oma-pm/resources/execution-protocol.md +62 -0
- package/skills/oma-pm/resources/iso-planning.md +110 -0
- package/skills/oma-pm/resources/plan-phase-protocol.md +66 -0
- package/skills/oma-pm/resources/task-template.json +86 -0
- package/skills/oma-qa/SKILL.md +141 -0
- package/skills/oma-qa/resources/checklist.md +339 -0
- package/skills/oma-qa/resources/error-playbook.md +98 -0
- package/skills/oma-qa/resources/execution-protocol.md +169 -0
- package/skills/oma-qa/resources/iso-quality.md +82 -0
- package/skills/oma-qa/resources/verify-ship-protocol.md +116 -0
- package/skills/oma-recap/SKILL.md +245 -0
- package/skills/oma-recap/resources/output-formats.md +83 -0
- package/skills/oma-refactor/SKILL.md +184 -0
- package/skills/oma-refactor/resources/definition.md +108 -0
- package/skills/oma-refactor/resources/governance.md +33 -0
- package/skills/oma-refactor/resources/hotspots.py +44 -0
- package/skills/oma-refactor/resources/measurement.md +93 -0
- package/skills/oma-scholar/SKILL.md +276 -0
- package/skills/oma-scholar/config/scholar-config.yaml +79 -0
- package/skills/oma-scholar/resources/api-endpoints.md +174 -0
- package/skills/oma-scholar/resources/checklist.md +92 -0
- package/skills/oma-scholar/resources/execution-protocol.md +224 -0
- package/skills/oma-scholar/resources/fallback-providers.md +143 -0
- package/skills/oma-scholar/resources/setup-openalex.md +85 -0
- package/skills/oma-scholar/resources/sidecar-spec.md +341 -0
- package/skills/oma-scholar/resources/upstream-spec-cache.md +972 -0
- package/skills/oma-scm/SKILL.md +103 -0
- package/skills/oma-scm/resources/cm-operations.md +56 -0
- package/skills/oma-scm/resources/codeowners-playbook.md +45 -0
- package/skills/oma-scm/resources/conventional-commits.md +108 -0
- package/skills/oma-scm/resources/merge-risk.md +76 -0
- package/skills/oma-scm/resources/onboarding-risk-signals.md +71 -0
- package/skills/oma-search/SKILL.md +125 -0
- package/skills/oma-search/resources/checklist.md +36 -0
- package/skills/oma-search/resources/error-playbook.md +66 -0
- package/skills/oma-search/resources/examples.md +80 -0
- package/skills/oma-search/resources/execution-protocol.md +86 -0
- package/skills/oma-search/resources/intent-rules.md +47 -0
- package/skills/oma-search/resources/trust-registry.md +53 -0
- package/skills/oma-security/SKILL.md +172 -0
- package/skills/oma-security/resources/artex.md +108 -0
- package/skills/oma-security/resources/ci.md +134 -0
- package/skills/oma-security/resources/cisco-source.md +108 -0
- package/skills/oma-security/resources/deepsec-config.md +45 -0
- package/skills/oma-security/resources/deepsec-matchers.md +35 -0
- package/skills/oma-security/resources/deepsec-scanning.md +45 -0
- package/skills/oma-security/resources/deepsec-setup.md +41 -0
- package/skills/oma-security/resources/findings-contract.md +408 -0
- package/skills/oma-security/resources/mcp-scanning.md +122 -0
- package/skills/oma-security/resources/skill-scanning.md +106 -0
- package/skills/oma-security/resources/validation.md +71 -0
- package/skills/oma-skill-creation/SKILL.md +84 -0
- package/skills/oma-skill-creation/resources/prompt-evaluation.md +36 -0
- package/skills/oma-skill-creation/resources/ssl-lite-template.md +108 -0
- package/skills/oma-skill-creation/resources/validation-checklist.md +101 -0
- package/skills/oma-slide/SKILL.md +277 -0
- package/skills/oma-slide/resources/animation-patterns.md +245 -0
- package/skills/oma-slide/resources/assets/deck-stage.js +514 -0
- package/skills/oma-slide/resources/assets/viewport-base.css +257 -0
- package/skills/oma-slide/resources/canva-integration.md +203 -0
- package/skills/oma-slide/resources/checklist.md +46 -0
- package/skills/oma-slide/resources/design-doctrine.md +260 -0
- package/skills/oma-slide/resources/fixed-stage.md +232 -0
- package/skills/oma-slide/resources/generation-protocol.md +393 -0
- package/skills/oma-slide/resources/native-pptx.md +84 -0
- package/skills/oma-slide/resources/selection-index.json +461 -0
- package/skills/oma-slide/resources/style-presets.LICENSE +10 -0
- package/skills/oma-slide/resources/style-presets.md +520 -0
- package/skills/oma-tf-infra/SKILL.md +201 -0
- package/skills/oma-tf-infra/resources/checklist.md +53 -0
- package/skills/oma-tf-infra/resources/cost-optimization.md +574 -0
- package/skills/oma-tf-infra/resources/error-playbook.md +68 -0
- package/skills/oma-tf-infra/resources/examples.md +38 -0
- package/skills/oma-tf-infra/resources/execution-protocol.md +129 -0
- package/skills/oma-tf-infra/resources/iso-42001-infra.md +229 -0
- package/skills/oma-tf-infra/resources/multi-cloud-examples.md +241 -0
- package/skills/oma-tf-infra/resources/policy-testing-examples.md +332 -0
- package/skills/oma-translation/SKILL.md +229 -0
- package/skills/oma-translation/resources/anti-ai-patterns.md +104 -0
- package/skills/oma-translation/resources/lang/_template.md +73 -0
- package/skills/oma-translation/resources/lang/en.md +123 -0
- package/skills/oma-translation/resources/lang/ja.md +274 -0
- package/skills/oma-translation/resources/lang/ko.md +228 -0
- package/skills/oma-translation/resources/lang/zh.md +285 -0
- package/skills/oma-translation/resources/style-skills.md +104 -0
- package/skills/oma-translation/resources/translation-rubric.md +126 -0
- package/skills/oma-video/SKILL.md +229 -0
- package/skills/oma-video/config/video-config.yaml +60 -0
- package/skills/oma-video/resources/checklist.md +26 -0
- package/skills/oma-video/resources/execution-protocol.md +122 -0
- package/skills/oma-video/resources/existing-media.md +185 -0
- package/skills/oma-video/resources/hyperframes-authoring/README.md +44 -0
- package/skills/oma-video/resources/hyperframes-authoring/demo.md +31 -0
- package/skills/oma-video/resources/hyperframes-authoring/explainer.md +10 -0
- package/skills/oma-video/resources/hyperframes-authoring/shorts.md +10 -0
- package/skills/oma-video/resources/motion-principles.md +81 -0
- package/skills/oma-video/resources/mpt/driver.py +301 -0
- package/skills/oma-video/resources/prompt-tips.md +75 -0
- package/skills/oma-video/resources/script-schema.md +81 -0
- package/skills/oma-video/resources/sound-design.md +127 -0
- package/skills/oma-video/resources/strudel/package.json +11 -0
- package/skills/oma-video/resources/strudel/page.html +87 -0
- package/skills/oma-video/resources/strudel/render.mjs +295 -0
- package/skills/oma-video/resources/vendor-matrix.md +124 -0
- package/skills/oma-voice/SKILL.md +249 -0
- package/skills/oma-voice/config/voice-config.yaml +30 -0
- package/skills/oma-voice/resources/audio-processing.md +119 -0
- package/skills/oma-voice/resources/checklist.md +47 -0
- package/skills/oma-voice/resources/execution-protocol.md +215 -0
- package/skills/oma-voice/resources/prompt-tips.md +43 -0
- package/skills/oma-voice/resources/voice-matrix.md +51 -0
- package/skills/oma-voice/resources/voicestudio.md +87 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Frontend Agent - Tech Stack Reference
|
|
2
|
+
|
|
3
|
+
These are defaults for new projects without an established stack. Preserve the target project's installed versions and conventions; a scoped feature or fix does not authorize a stack migration.
|
|
4
|
+
|
|
5
|
+
## Core Framework
|
|
6
|
+
- **Framework**: Next.js 16+ (App Router), React 19+
|
|
7
|
+
- **Language**: TypeScript (strict mode)
|
|
8
|
+
- **Testing**: Vitest, React Testing Library
|
|
9
|
+
- **Browser verification**: Browser verification uses the installed MCPs selected in `mcp.devtools_browsers`: Aside (`aside`, default), Chrome DevTools MCP (`chrome`), and Firefox DevTools MCP (`firefox`). Multiple selections are supported; use `oma update mcp` to change them. Discover the selected server’s actual tools before use; tool names and capabilities differ between servers. An empty selection disables browser MCP verification; report any unverified UI checks.
|
|
10
|
+
- **UI**: `shadcn/ui` on the **Base UI** engine (see below)
|
|
11
|
+
|
|
12
|
+
## shadcn/ui Primitive Engine — Base UI vs Radix
|
|
13
|
+
|
|
14
|
+
shadcn/ui ships on two interchangeable headless engines: **Radix UI** and **Base UI**
|
|
15
|
+
(by the MUI team). They provide similar component categories, but primitive and
|
|
16
|
+
wrapper APIs differ. Verify composition, props and accessibility before migration.
|
|
17
|
+
|
|
18
|
+
### How the engine is selected
|
|
19
|
+
|
|
20
|
+
The engine is **not** a standalone `components.json` field. It is encoded in the **`style`**
|
|
21
|
+
prefix:
|
|
22
|
+
|
|
23
|
+
| `style` value | Engine |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `base-*` (e.g. `base-vega`) | **Base UI** |
|
|
26
|
+
| `radix-*` (e.g. `radix-nova`) | Radix UI |
|
|
27
|
+
|
|
28
|
+
```jsonc
|
|
29
|
+
// components.json
|
|
30
|
+
{
|
|
31
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
32
|
+
"style": "base-vega", // <- engine + style; base-* = Base UI
|
|
33
|
+
"rsc": true,
|
|
34
|
+
"tsx": true,
|
|
35
|
+
"tailwind": { "css": "src/styles/globals.css", "baseColor": "neutral", "cssVariables": true },
|
|
36
|
+
"iconLibrary": "lucide",
|
|
37
|
+
"aliases": { /* ... */ }
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Bootstrap with `npx shadcn create` (prompts for the engine) or `npx shadcn init`.
|
|
42
|
+
|
|
43
|
+
### Project default: **Base UI**
|
|
44
|
+
|
|
45
|
+
1. For a new project without an engine choice, Base UI is an available default. Verify the components and integration required by the project.
|
|
46
|
+
2. **Radix is an allowed fallback** — keep `radix-*` for an existing Radix codebase, or when a
|
|
47
|
+
needed component is only stable on Radix. State the reason when choosing Radix.
|
|
48
|
+
3. **Do NOT big-bang migrate** an existing project to Base UI just because it is the default.
|
|
49
|
+
Migrate component-by-component, with reason; due to API differences a global swap is risky.
|
|
50
|
+
4. To switch engines: change the `style` prefix, then re-add base components with
|
|
51
|
+
`npx shadcn add button card dialog … --overwrite`. Treat `components/ui/*` as read-only
|
|
52
|
+
otherwise (customize via wrappers / `cva`).
|
|
53
|
+
|
|
54
|
+
## Next.js 16 Conventions
|
|
55
|
+
|
|
56
|
+
### Proxy replaces Middleware
|
|
57
|
+
|
|
58
|
+
For projects using the Next.js 16+ proxy convention, preserve `proxy.ts`. Check the installed framework version and existing routing before proposing a migration.
|
|
59
|
+
|
|
60
|
+
- File: `middleware.ts` → `proxy.ts` (root or `src/`)
|
|
61
|
+
- Exported function: `middleware` → `proxy`
|
|
62
|
+
- Config flags: `skipMiddlewareUrlNormalize` → `skipProxyUrlNormalize`, etc.
|
|
63
|
+
<!-- oma-docs:ignore-start -->
|
|
64
|
+
- `src/proxy.ts` is the canonical request-proxy / auth-gate location
|
|
65
|
+
<!-- oma-docs:ignore-end -->
|
|
66
|
+
|
|
67
|
+
Do not infer that a framework entry point is unused from missing imports alone. Verify its location, exports, configuration, and relevant tests before reporting a wiring defect.
|
|
68
|
+
|
|
69
|
+
Reference: https://nextjs.org/docs/messages/middleware-to-proxy
|
|
70
|
+
|
|
71
|
+
### React Compiler (stable in Next.js 16)
|
|
72
|
+
|
|
73
|
+
Next.js 16 supports the React Compiler as a **stable, opt-in** top-level option (disabled by
|
|
74
|
+
default). It auto-memoizes components, replacing most manual memoization.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// next.config.ts (requires `babel-plugin-react-compiler` as a devDependency)
|
|
78
|
+
const nextConfig: NextConfig = {
|
|
79
|
+
reactCompiler: true, // or { compilationMode: 'annotation' } for opt-in per component
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Rules:
|
|
84
|
+
|
|
85
|
+
1. **Check whether the project has it enabled before tuning renders.** Look for
|
|
86
|
+
`reactCompiler` in `next.config.*`.
|
|
87
|
+
2. **Compiler ON**: do NOT hand-write `useMemo` / `useCallback` / `React.memo` in new code;
|
|
88
|
+
the compiler owns memoization. Correct `useEffect` deps still matter (the compiler does
|
|
89
|
+
not fix dependency bugs).
|
|
90
|
+
3. **Compiler OFF**: memoize manually as usual; suggest enabling the compiler only as a
|
|
91
|
+
separate, explicit change (it adds Babel to the build and increases compile times).
|
|
92
|
+
4. Do not mix modes ad hoc: `'annotation'` mode means only `"use memo"`-annotated components
|
|
93
|
+
compile; don't assume whole-app coverage.
|
|
94
|
+
|
|
95
|
+
## Server State — orval-generated TanStack Query hooks
|
|
96
|
+
|
|
97
|
+
When the project has an OpenAPI spec (most oma projects do), **TanStack Query hooks are
|
|
98
|
+
generated by `orval`, not hand-written**. The pipeline lives in oma-dev-workflow
|
|
99
|
+
(`resources/api-workflows.md`): backend emits `openapi.json` → `bunx orval` (usually via
|
|
100
|
+
`mise run gen:api`) emits typed `useQuery`/`useMutation` hooks (`client: react-query`).
|
|
101
|
+
|
|
102
|
+
1. **Generated output is read-only**, same rule as `components/ui/*`. Never edit generated
|
|
103
|
+
hooks/models; fix the OpenAPI spec (or orval config) and regenerate.
|
|
104
|
+
2. **Contract change flow**: backend schema change → regenerate spec → `bunx orval` →
|
|
105
|
+
fix resulting type errors in consuming code. Don't patch types by hand to "match later".
|
|
106
|
+
3. **Cross-cutting concerns go in the orval `mutator`** (custom axios/fetch instance):
|
|
107
|
+
auth headers, base URL, error normalization; never per-hook.
|
|
108
|
+
4. **Hand-written TanStack Query hooks are the exception**: third-party APIs or endpoints
|
|
109
|
+
outside the spec. Follow the fallback pattern in `snippets.md` §TanStack Query Hook.
|
|
110
|
+
|
|
111
|
+
## Mutations — Server Actions vs TanStack Query
|
|
112
|
+
|
|
113
|
+
Both are legitimate write paths in Next.js 16; pick per mutation, and don't route the same
|
|
114
|
+
mutation through both.
|
|
115
|
+
|
|
116
|
+
| Pick | When |
|
|
117
|
+
|---|---|
|
|
118
|
+
| **Server Action** (`'use server'` + `useActionState`) | Form-shaped, page-scoped writes where progressive enhancement or zero client JS matters; simple submit → revalidate flows (`revalidatePath` / `revalidateTag`); no shared client cache to update. |
|
|
119
|
+
| **TanStack Query mutation** | The write must update client-cached reads (`invalidateQueries`, optimistic updates, rollback); fires outside a form (drag-drop, toggles, autosave); needs retry/queue/offline semantics or fine-grained pending UI across components. |
|
|
120
|
+
|
|
121
|
+
Guidance:
|
|
122
|
+
|
|
123
|
+
1. If the data is already read through TanStack Query, mutate through TanStack Query; a
|
|
124
|
+
Server Action won't invalidate the client cache by itself.
|
|
125
|
+
2. Server Actions are still server endpoints: validate input with zod on the server side and
|
|
126
|
+
enforce auth inside the action, never only in the UI.
|
|
127
|
+
3. Don't call Server Actions from TanStack Query's `mutationFn` as a default pattern; that
|
|
128
|
+
stacks two mutation layers. Choose one owner per mutation.
|
|
129
|
+
|
|
130
|
+
## Client State — Jotai vs Zustand
|
|
131
|
+
|
|
132
|
+
Client state has **no project default**; pick per intent. Both are allowed, but **only one
|
|
133
|
+
per project** unless there is a strong reason to mix. The overriding rule is to *minimize
|
|
134
|
+
client state* in the first place: server state belongs in **TanStack Query**, URL state in
|
|
135
|
+
**nuqs**. Reach for a client-state library only for genuine client-owned state.
|
|
136
|
+
|
|
137
|
+
| Pick | When |
|
|
138
|
+
|---|---|
|
|
139
|
+
| **Jotai** | Atomic / bottom-up. Fine-grained, derived, or near-local shared state; many small independent atoms; state that maps onto React's render graph and RSC-split boundaries. |
|
|
140
|
+
| **Zustand** | Store / top-down. A single cohesive global store with action methods; needs non-React access (`store.getState()` / `subscribe` outside render); simpler mental model for app-wide state. |
|
|
141
|
+
|
|
142
|
+
Guidance:
|
|
143
|
+
|
|
144
|
+
1. **State the choice** in the project (e.g. a short note in the app README or DESIGN.md) so
|
|
145
|
+
contributors don't introduce the other library ad hoc.
|
|
146
|
+
2. **Don't mix** Jotai and Zustand in one app without justification — two client-state models
|
|
147
|
+
fragment the codebase.
|
|
148
|
+
3. **Default-free does not mean optional analysis**: if neither atomic nor single-store clearly
|
|
149
|
+
fits, the state probably belongs in TanStack Query (server) or nuqs (URL), not here.
|
|
150
|
+
|
|
151
|
+
## Optional Serena examples
|
|
152
|
+
|
|
153
|
+
These examples apply only when Serena is the configured provider and its tools are available. Otherwise use the project-selected provider or native search under the shared code-intelligence contract.
|
|
154
|
+
- `find_symbol("ComponentName")`: locate existing component
|
|
155
|
+
- `get_symbols_overview("src/components")`: list all components
|
|
156
|
+
- `find_referencing_symbols("Button")`: find usages before changes
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oma-hwp
|
|
3
|
+
description: Convert Hangul HWP, HWPX, or HWPML documents to Markdown with
|
|
4
|
+
kordoc. Use for text, table, and image extraction from these formats.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# HWP Skill - HWP / HWPX / HWPML to Markdown Conversion
|
|
8
|
+
|
|
9
|
+
## Scheduling
|
|
10
|
+
|
|
11
|
+
### Goal
|
|
12
|
+
Convert Korean HWP-family documents into readable Markdown or structured JSON while preserving document structure for LLM context, RAG, government-document review, or enterprise document processing.
|
|
13
|
+
|
|
14
|
+
### Intent signature
|
|
15
|
+
- User asks to convert, parse, read, extract, or transform `.hwp`, `.hwpx`, or `.hwpml`.
|
|
16
|
+
- User mentions Korean word processor files, Hangul documents, government forms, or "한글 파일".
|
|
17
|
+
- User needs headings, tables, nested tables, lists, images, footnotes, or hyperlinks extracted from HWP-family files.
|
|
18
|
+
|
|
19
|
+
### When to use
|
|
20
|
+
- Converting Korean HWP documents (`.hwp`, `.hwpx`, `.hwpml`) to Markdown
|
|
21
|
+
- Preparing Korean government/enterprise documents for LLM context or RAG
|
|
22
|
+
- Extracting structured content (tables, headings, lists, images) from HWP
|
|
23
|
+
- User says "convert this HWP", "parse hwpx", "HWP to markdown", "한글 파일"
|
|
24
|
+
|
|
25
|
+
### When NOT to use
|
|
26
|
+
- PDF files -> use `oma-pdf` (OCR + Tagged PDF specialization)
|
|
27
|
+
- XLSX / DOCX files -> out of scope; run `bunx kordoc` directly if needed (note: `oma-docs` is the documentation-drift skill, not a converter)
|
|
28
|
+
- Generating or editing HWP documents -> out of scope (kordoc itself supports `generate` / `fill` / `seal` / `patch` / `redact` / `lint` / `validate` / `render` subcommands; run `bunx kordoc@latest <subcommand>` directly if needed)
|
|
29
|
+
- Already-text files -> use Read tool directly
|
|
30
|
+
|
|
31
|
+
### Expected inputs
|
|
32
|
+
- `input_path`: `.hwp`, `.hwpx`, or `.hwpml` file path
|
|
33
|
+
- `output_path` or `output_dir`: optional explicit output target
|
|
34
|
+
- `format`: optional output format — `markdown` (default), `json` (structured AST), or `chunks` (RAG-oriented structural chunk JSON with heading breadcrumbs and standalone table chunks)
|
|
35
|
+
- `page_range`: optional page or section range
|
|
36
|
+
- `kordoc_version`: optional pinned kordoc version
|
|
37
|
+
|
|
38
|
+
### Expected outputs
|
|
39
|
+
- Markdown output next to the input file or in the requested directory
|
|
40
|
+
- Optional JSON or RAG-chunks output when requested
|
|
41
|
+
- Post-processed Markdown with flattened GFM tables and stripped Private Use Area glyphs by default
|
|
42
|
+
- A short report with output path, detected source format, and conversion issues
|
|
43
|
+
|
|
44
|
+
### Dependencies
|
|
45
|
+
- `bun` and `bunx`
|
|
46
|
+
- `bunx kordoc@latest` or configured pinned kordoc version
|
|
47
|
+
- `resources/flatten-tables.ts` for Markdown cleanup
|
|
48
|
+
- Local filesystem access to input and output paths
|
|
49
|
+
|
|
50
|
+
### Control-flow features
|
|
51
|
+
- Branches by file extension, output target, format, page range, encryption/DRM state, and post-processing requirements
|
|
52
|
+
- Calls external CLI tools through `bunx` and `bun run`
|
|
53
|
+
- Reads local HWP-family files and writes local Markdown or JSON output
|
|
54
|
+
- Routes non-HWP inputs to other skills instead of stretching this skill's scope
|
|
55
|
+
|
|
56
|
+
## Structural Flow
|
|
57
|
+
|
|
58
|
+
### Entry
|
|
59
|
+
1. Confirm the input path exists.
|
|
60
|
+
2. Confirm the extension is `.hwp`, `.hwpx`, or `.hwpml`.
|
|
61
|
+
3. Resolve output path or directory and default filename.
|
|
62
|
+
4. Check that `bun` is available.
|
|
63
|
+
|
|
64
|
+
### Scenes
|
|
65
|
+
1. **PREPARE**: Validate path, extension, size, output target, and requested format.
|
|
66
|
+
2. **ACQUIRE**: Detect source format and runtime availability.
|
|
67
|
+
3. **ACT**: Run `kordoc` with explicit output target and requested options.
|
|
68
|
+
4. **VERIFY**: Post-process Markdown and inspect structure for headings, tables, lists, images, and footnotes.
|
|
69
|
+
5. **FINALIZE**: Report output path, source format, and any conversion limitations.
|
|
70
|
+
|
|
71
|
+
### Transitions
|
|
72
|
+
- If the input is `.pdf`, stop and route to `oma-pdf`.
|
|
73
|
+
- If the input is `.xlsx` or `.docx`, explain that this skill does not advertise those formats.
|
|
74
|
+
- If `bun` is unavailable, stop and ask the user to install Bun.
|
|
75
|
+
- If Markdown is produced, run `resources/flatten-tables.ts` unless the caller explicitly needs HTML tables or PUA glyphs preserved.
|
|
76
|
+
- If output is empty or garbled, consult `resources/troubleshooting.md`.
|
|
77
|
+
|
|
78
|
+
### Failure and recovery
|
|
79
|
+
| Failure | Recovery |
|
|
80
|
+
|---------|----------|
|
|
81
|
+
| `bun` or `bunx` unavailable | Ask user to install Bun |
|
|
82
|
+
| Unsupported or mismatched format | Check extension and magic bytes, then route or stop |
|
|
83
|
+
| Encrypted or DRM-locked document | Report limitation and request an accessible copy when needed |
|
|
84
|
+
| Empty Markdown output | Treat as possible scanned-image content and recommend OCR outside this skill |
|
|
85
|
+
| Complex merged tables | Accept flattened Markdown or HTML fallback as best effort |
|
|
86
|
+
| Stale kordoc cache | Use `bunx kordoc@latest` or configured pinned version |
|
|
87
|
+
| `Cannot find module "turndown"` from `flatten-tables.ts` | Run `bun install` in this skill's `resources/` directory (its `node_modules` is gitignored and absent on fresh clones) |
|
|
88
|
+
|
|
89
|
+
### Exit
|
|
90
|
+
- Success: output file exists and structure is readable after post-processing.
|
|
91
|
+
- Partial success: output exists with explicitly reported table, glyph, encryption, or fidelity limitations.
|
|
92
|
+
- Failure: no reliable output is produced and the blocking cause is reported.
|
|
93
|
+
|
|
94
|
+
## Logical Operations
|
|
95
|
+
|
|
96
|
+
### Actions
|
|
97
|
+
| Action | SSL primitive | Evidence |
|
|
98
|
+
|--------|---------------|----------|
|
|
99
|
+
| Validate file path and extension | `VALIDATE` | Input preflight in execution protocol |
|
|
100
|
+
| Check runtime availability | `VALIDATE` | `bun --version` |
|
|
101
|
+
| Select output target and format | `SELECT` | Output behavior and config |
|
|
102
|
+
| Run converter | `CALL_TOOL` | `bunx kordoc@latest` |
|
|
103
|
+
| Write output artifact | `WRITE` | Markdown or JSON output |
|
|
104
|
+
| Flatten tables and strip PUA glyphs | `CALL_TOOL` | `resources/flatten-tables.ts` |
|
|
105
|
+
| Inspect extraction quality | `VALIDATE` | Verification step |
|
|
106
|
+
| Report result | `NOTIFY` | Final user-facing summary |
|
|
107
|
+
|
|
108
|
+
### Tools and instruments
|
|
109
|
+
- `kordoc`: primary HWP-family conversion CLI
|
|
110
|
+
- `flatten-tables.ts`: post-processing for GFM tables and Hancom PUA cleanup
|
|
111
|
+
- `bun` / `bunx`: runtime and CLI executor
|
|
112
|
+
|
|
113
|
+
### Canonical command path
|
|
114
|
+
```bash
|
|
115
|
+
bunx kordoc@latest "{input_path}" -o "{output_path}"
|
|
116
|
+
# fresh clone: run `bun install` in {skill_dir}/resources/ first (node_modules is gitignored)
|
|
117
|
+
bun "{skill_dir}/resources/flatten-tables.ts" "{output_path}"
|
|
118
|
+
# {skill_dir} = this skill's directory: .agents/skills/oma-hwp (project mode) or ~/.agents/skills/oma-hwp (global mode)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For batch conversion, use an explicit output directory:
|
|
122
|
+
```bash
|
|
123
|
+
bunx kordoc@latest "{input_pattern}" -d "{output_dir}"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Resource scope
|
|
127
|
+
| Scope | Resource target |
|
|
128
|
+
|-------|-----------------|
|
|
129
|
+
| `LOCAL_FS` | Input HWP-family files and generated outputs |
|
|
130
|
+
| `PROCESS` | `bunx kordoc` and `bun run` subprocesses |
|
|
131
|
+
| `MEMORY` | Format decisions, validation notes, and final report |
|
|
132
|
+
|
|
133
|
+
### Preconditions
|
|
134
|
+
- Input file exists and is readable.
|
|
135
|
+
- Output location is writable or can be created.
|
|
136
|
+
- `bun` is installed.
|
|
137
|
+
- `kordoc` can parse the document or fail with a reportable error.
|
|
138
|
+
|
|
139
|
+
### Effects and side effects
|
|
140
|
+
- Creates Markdown or JSON output files.
|
|
141
|
+
- May flatten merged-cell tables, trading cell fidelity for Markdown compatibility.
|
|
142
|
+
- Strips Private Use Area characters by default because they render as blanks without Hancom fonts.
|
|
143
|
+
- Does not intentionally modify the source HWP-family document.
|
|
144
|
+
|
|
145
|
+
### Guardrails
|
|
146
|
+
1. Always pass `@latest` or an explicit pinned version to avoid stale `bunx` cache.
|
|
147
|
+
2. Always pass an explicit output target when the user expects a file.
|
|
148
|
+
3. Do not add custom security defenses around kordoc's ZIP, XML, SSRF, or XSS defenses.
|
|
149
|
+
4. Report missing tables, garbled text, empty output, encrypted segments, and best-effort DRM extraction.
|
|
150
|
+
5. Keep full CLI details in `resources/execution-protocol.md` and troubleshooting branches in `resources/troubleshooting.md`.
|
|
151
|
+
|
|
152
|
+
### Supported Formats
|
|
153
|
+
| Format | Extension | Notes |
|
|
154
|
+
|--------|-----------|-------|
|
|
155
|
+
| HWP 5.x binary | `.hwp` | Full support (incl. DRM-locked via kordoc's rhwp-algorithm port) |
|
|
156
|
+
| HWPX | `.hwpx` | Full support incl. nested tables, merged cells |
|
|
157
|
+
| HWPML | `.hwp` (XML variant) | Auto-detected by signature |
|
|
158
|
+
|
|
159
|
+
> kordoc also parses PDF / XLSX / DOCX and offers document-authoring subcommands (`generate`, `fill`, `seal`, `patch`, `redact`, `lint`, `validate`, `render`). All of those are intentionally outside this skill's scope; see "When NOT to use". Conversion-quality flags (`--dedupe-headers`, `--keep-empty-cols`, `--inline-images`) and the `chunks` format are documented in `resources/execution-protocol.md`.
|
|
160
|
+
|
|
161
|
+
## References
|
|
162
|
+
- Execution protocol: `resources/execution-protocol.md`
|
|
163
|
+
- Troubleshooting: `resources/troubleshooting.md`
|
|
164
|
+
- Configuration: read the `hwp:` section of `.agents/oma-config.yaml` first, then fall back to `config/hwp-config.yaml` for any key it does not set (`supported_formats` lives only in the skill config). User overrides belong in `.agents/oma-config.yaml`, since `oma update` overwrites the skill config.
|
|
165
|
+
- Upstream: https://github.com/chrisryugj/kordoc
|
|
166
|
+
- Related: `../oma-pdf/SKILL.md` (use for `.pdf` inputs)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# oma-hwp configuration
|
|
2
|
+
# HWP / HWPX / HWPML to Markdown conversion settings
|
|
3
|
+
#
|
|
4
|
+
# NOT the place to put your settings: `oma update` overwrites this file. Put
|
|
5
|
+
# overrides under `hwp:` in .agents/oma-config.yaml, which is preserved —
|
|
6
|
+
# that section wins, and this file supplies only the shipped defaults the skill
|
|
7
|
+
# falls back to. Migration 022 moves anything you changed here for you.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
format: markdown # "markdown" (default), "json", or "chunks" (RAG structural chunks)
|
|
11
|
+
|
|
12
|
+
# kordoc version policy
|
|
13
|
+
# - "latest": always use latest (recommended for active kordoc development)
|
|
14
|
+
# - "pinned": use the version in `version.pinned`
|
|
15
|
+
# (verify with `npm view kordoc version` before pinning; the example below may be stale)
|
|
16
|
+
version:
|
|
17
|
+
channel: latest
|
|
18
|
+
pinned: "4.7.3"
|
|
19
|
+
|
|
20
|
+
# Output behavior
|
|
21
|
+
output:
|
|
22
|
+
# When no output directory is specified:
|
|
23
|
+
# "same_dir" = output next to the input file
|
|
24
|
+
# "cwd" = output in current working directory
|
|
25
|
+
default_location: same_dir
|
|
26
|
+
|
|
27
|
+
# Officially supported formats (advertised scope).
|
|
28
|
+
# kordoc supports more formats, but this skill only covers the Korean word
|
|
29
|
+
# processor family. Route other inputs to the appropriate skill:
|
|
30
|
+
# - .pdf -> oma-pdf
|
|
31
|
+
# - .xlsx / .docx -> out of scope (run `bunx kordoc ...` manually; oma-docs is the doc-drift skill, not a converter)
|
|
32
|
+
supported_formats:
|
|
33
|
+
- hwp
|
|
34
|
+
- hwpx
|
|
35
|
+
- hwpml
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replace balanced outermost table blocks. Nested tables are passed to the
|
|
3
|
+
* callback as part of their parent instead of being truncated at the first
|
|
4
|
+
* closing tag.
|
|
5
|
+
*/
|
|
6
|
+
export function replaceBalancedTables(
|
|
7
|
+
source: string,
|
|
8
|
+
replace: (tableHtml: string) => string,
|
|
9
|
+
): string {
|
|
10
|
+
const tag = /<\/?table\b[^>]*>/gi;
|
|
11
|
+
let depth = 0;
|
|
12
|
+
let blockStart = -1;
|
|
13
|
+
let cursor = 0;
|
|
14
|
+
let output = "";
|
|
15
|
+
|
|
16
|
+
for (let match = tag.exec(source); match; match = tag.exec(source)) {
|
|
17
|
+
const closing = /^<\/table/i.test(match[0]);
|
|
18
|
+
if (!closing) {
|
|
19
|
+
if (depth === 0) {
|
|
20
|
+
blockStart = match.index;
|
|
21
|
+
output += source.slice(cursor, blockStart);
|
|
22
|
+
}
|
|
23
|
+
depth += 1;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (depth === 0) continue;
|
|
28
|
+
depth -= 1;
|
|
29
|
+
if (depth === 0 && blockStart >= 0) {
|
|
30
|
+
const blockEnd = tag.lastIndex;
|
|
31
|
+
output += replace(source.slice(blockStart, blockEnd));
|
|
32
|
+
cursor = blockEnd;
|
|
33
|
+
blockStart = -1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Preserve malformed/unclosed input verbatim rather than dropping content.
|
|
38
|
+
return output + source.slice(blockStart >= 0 ? blockStart : cursor);
|
|
39
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# HWP Conversion - Execution Protocol
|
|
2
|
+
|
|
3
|
+
## Step 0: Validate Input
|
|
4
|
+
|
|
5
|
+
1. Confirm the input file path exists
|
|
6
|
+
2. Check extension is one of `.hwp`, `.hwpx`, `.hwpml`
|
|
7
|
+
- If `.pdf` -> hand off to `oma-pdf`
|
|
8
|
+
- If `.xlsx` / `.docx` -> not in scope; advise user to run `bunx kordoc@latest <file>` directly
|
|
9
|
+
3. Check file size (`wc -c` or `ls -lh`); warn if >100MB
|
|
10
|
+
4. Determine output location:
|
|
11
|
+
- If user specified output path (`-o` or `-d`) → use it
|
|
12
|
+
- Otherwise → same directory as the input file
|
|
13
|
+
5. Determine output filename: `{input_basename}.md`
|
|
14
|
+
|
|
15
|
+
## Step 1: Check Runtime
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun --version
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If `bun` is not available, ask the user to install Bun (https://bun.sh). `bunx` is required.
|
|
22
|
+
|
|
23
|
+
## Step 2: Convert
|
|
24
|
+
|
|
25
|
+
> **Important**: Without `-o` or `-d`, kordoc prints the Markdown to **stdout** and does not create a file. Always pass an explicit output path to match this skill's "same directory as input" convention.
|
|
26
|
+
|
|
27
|
+
### Standard conversion (single file, write next to input)
|
|
28
|
+
```bash
|
|
29
|
+
bunx kordoc@latest "{input_path}" -o "{output_path}"
|
|
30
|
+
# {output_path} = "{dirname(input_path)}/{basename_without_ext(input_path)}.md"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Output directory (multiple files)
|
|
34
|
+
```bash
|
|
35
|
+
bunx kordoc@latest "{input_pattern}" -d "{output_dir}"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Print to stdout (piping / preview)
|
|
39
|
+
```bash
|
|
40
|
+
bunx kordoc@latest "{input_path}"
|
|
41
|
+
# No file written; useful when piping to another tool
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Page / section range
|
|
45
|
+
```bash
|
|
46
|
+
bunx kordoc@latest "{input_path}" -p "{range}"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### JSON output (structured intermediate form)
|
|
50
|
+
```bash
|
|
51
|
+
bunx kordoc@latest "{input_path}" --format json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### RAG chunks output (structural chunk JSON)
|
|
55
|
+
```bash
|
|
56
|
+
bunx kordoc@latest "{input_path}" --format chunks
|
|
57
|
+
```
|
|
58
|
+
Emits RAG-oriented structural chunks: each chunk carries a heading / outline-hierarchy breadcrumb, and tables become standalone chunks. Prefer this over plain Markdown when the user is preparing HWP content for RAG ingestion or embedding pipelines.
|
|
59
|
+
|
|
60
|
+
### Conversion-quality flags (HWP-family relevant)
|
|
61
|
+
| Flag | Effect | When to use |
|
|
62
|
+
|------|--------|-------------|
|
|
63
|
+
| `--dedupe-headers` | Removes running headers repeated per page in HWP5 layout tables (default off) | Paginated forms where the same header row repeats; beware: may over-remove per-attachment renumbering |
|
|
64
|
+
| `--keep-empty-cols` | Preserves trailing empty table columns (form input fields); default trims them | Government form templates where blank fill-in columns are meaningful |
|
|
65
|
+
| `--inline-images` | Inlines images as base64 data URIs (BMP→PNG compression, HWP5 only) | Single self-contained Markdown file needed; skips writing an assets directory for inlined images |
|
|
66
|
+
|
|
67
|
+
Notes:
|
|
68
|
+
- Default format is `markdown`. Pass `--format json` for the structured AST, `--format chunks` for RAG chunks.
|
|
69
|
+
- `--silent` suppresses progress output, useful in automation / piping contexts.
|
|
70
|
+
|
|
71
|
+
## Step 2.5: Post-process kordoc output (default)
|
|
72
|
+
|
|
73
|
+
`resources/flatten-tables.ts` cleans up two kordoc artifacts that hurt downstream use:
|
|
74
|
+
|
|
75
|
+
1. **HTML `<table>` blocks**: kordoc emits these when a table has `colspan` / `rowspan` because GFM cannot represent merged cells. Converted to GFM pipe tables via `turndown-plugin-gfm`.
|
|
76
|
+
2. **Private Use Area characters**: HWP references Hancom-font-specific glyphs via U+E000-U+F8FF / U+F0000-U+FFFFD / U+100000-U+10FFFD code points. Without the Hancom font these render as blanks or tofu squares. Silently stripped.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bun "{skill_resources}/flatten-tables.ts" "{output_path}"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- `{skill_resources}` = this skill's `resources/` directory (`.agents/skills/oma-hwp/resources` in project mode, `~/.agents/skills/oma-hwp/resources` in global mode)
|
|
83
|
+
- Ensure `bun install` has been run once inside that directory (it installs `turndown` + `turndown-plugin-gfm` locally)
|
|
84
|
+
- Merged cells get flattened during the conversion (accepted trade-off)
|
|
85
|
+
- Skip this step only if the caller explicitly needs HTML tables or PUA characters preserved (rare)
|
|
86
|
+
|
|
87
|
+
## Step 3: Verify
|
|
88
|
+
|
|
89
|
+
1. Read the generated Markdown file
|
|
90
|
+
2. Verify structure:
|
|
91
|
+
- Headings preserved (`#`, `##`, etc.)
|
|
92
|
+
- Tables rendered (GFM pipe syntax, or HTML `<table>` fallback for merged cells)
|
|
93
|
+
- Lists maintained (bullets, numbered)
|
|
94
|
+
- Images referenced (relative paths or inline)
|
|
95
|
+
- Footnotes linked via `[^id]`
|
|
96
|
+
3. If the file is empty or clearly garbled, consult `troubleshooting.md`
|
|
97
|
+
4. If output directory is temporary, move the file to the target location
|
|
98
|
+
5. If the user needs the content in-conversation, read and present it
|
|
99
|
+
|
|
100
|
+
## Step 4: Report
|
|
101
|
+
|
|
102
|
+
Tell the user:
|
|
103
|
+
- Output file path
|
|
104
|
+
- Source format detected (HWP5 / HWPX / HWPML)
|
|
105
|
+
- Any issues encountered (encrypted segments, missing tables, best-effort DRM extraction)
|
|
106
|
+
- Page/section count if available
|
|
107
|
+
|
|
108
|
+
## Error Recovery
|
|
109
|
+
|
|
110
|
+
| Error | Recovery |
|
|
111
|
+
|-------|----------|
|
|
112
|
+
| `bunx` / `bun` not found | Ask user to install Bun: `curl -fsSL https://bun.sh/install \| bash` |
|
|
113
|
+
| `지원하지 않는 파일 형식` / `unsupported file format` | Confirm extension matches actual content; check magic bytes |
|
|
114
|
+
| `암호화된 문서` / `encrypted document` | Ask user for password; current kordoc CLI may not accept it inline (document as limitation) |
|
|
115
|
+
| Empty Markdown output | Likely a scanned-image-only HWP; suggest OCR pipeline (out of this skill's scope) |
|
|
116
|
+
| Broken / missing tables | Complex merged-cell tables fall back to HTML `<table>`; accept as best-effort |
|
|
117
|
+
| kordoc crash or stack trace | Ensure `@latest` is passed (bunx cache can be stale); if persistent, capture fixture and file issue upstream at https://github.com/chrisryugj/kordoc/issues |
|
|
118
|
+
| Slow conversion on large files | Use `-p` to narrow the page range; process sections separately |
|
|
119
|
+
|
|
120
|
+
## Pin vs Latest
|
|
121
|
+
|
|
122
|
+
- **Default**: `bunx kordoc@latest` (always latest). Gets upstream fixes automatically. `@latest` is required because a bare `bunx kordoc` can reuse a stale cached version indefinitely.
|
|
123
|
+
- **Reproducibility**: pin with `bunx kordoc@4.7.3 ...` or similar. Record the pinned version under `hwp.version` in `.agents/oma-config.yaml` (`channel: pinned`, `pinned: "4.7.3"`). Do not edit `config/hwp-config.yaml` — `oma update` overwrites it.
|
|
124
|
+
|
|
125
|
+
## Scope Reminder
|
|
126
|
+
|
|
127
|
+
If the user hands you a `.pdf` / `.xlsx` / `.docx` with this skill activated, **do not proceed**. Redirect:
|
|
128
|
+
|
|
129
|
+
- `.pdf` → switch to `oma-pdf`
|
|
130
|
+
- `.xlsx` / `.docx` → ask the user to run `bunx kordoc@latest <file>` directly; this skill does not advertise those formats
|
|
131
|
+
|
|
132
|
+
Likewise, document **authoring / editing** requests are out of this skill's scope even though kordoc supports them. Point the user at the subcommand directly:
|
|
133
|
+
|
|
134
|
+
| Request | kordoc subcommand |
|
|
135
|
+
|---------|-------------------|
|
|
136
|
+
| Generate HWPX from Markdown | `bunx kordoc@latest generate <md> -o <hwpx>` |
|
|
137
|
+
| Fill form blanks | `bunx kordoc@latest fill <template> -f 'k=v,...' -o <out>` |
|
|
138
|
+
| Place stamp/signature image | `bunx kordoc@latest seal <file> --image <png> --anchor "(인)" -o <out>` |
|
|
139
|
+
| Apply edited Markdown back to original | `bunx kordoc@latest patch <original> <edited-md> -o <out>` |
|
|
140
|
+
| Mask personal data (주민번호 etc.) | `bunx kordoc@latest redact <files...>` |
|
|
141
|
+
| Check official-document notation | `bunx kordoc@latest lint <file>` |
|
|
142
|
+
| Validate HWPX structure | `bunx kordoc@latest validate <file>` |
|
|
143
|
+
| Layout-preserving SVG render | `bunx kordoc@latest render <file> -o <svg>` |
|
|
144
|
+
|
|
145
|
+
kordoc technically supports all of the above, but routing keeps skill scopes clean.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/// <reference path="./turndown-plugin-gfm.d.ts" />
|
|
3
|
+
/**
|
|
4
|
+
* flatten-tables.ts: post-process kordoc output:
|
|
5
|
+
* 1. convert HTML <table> blocks to GFM pipe tables
|
|
6
|
+
* 2. strip Private Use Area characters (Hancom font-specific glyphs)
|
|
7
|
+
*
|
|
8
|
+
* (1) kordoc emits HTML <table> when a table has colspan/rowspan because GFM
|
|
9
|
+
* cannot represent merged cells. This script trades merge-cell fidelity
|
|
10
|
+
* for a pure-Markdown output.
|
|
11
|
+
* (2) HWP references Hancom-font-specific glyphs via Private Use Area code
|
|
12
|
+
* points (U+E000-U+F8FF, U+F0000-U+FFFFD, U+100000-U+10FFFD). Without
|
|
13
|
+
* the Hancom font these render as blanks or tofu squares; stripping is
|
|
14
|
+
* the pragmatic default for AI / plain-MD consumption.
|
|
15
|
+
*
|
|
16
|
+
* Usage: bun flatten-tables.ts <file.md> [<file.md>...]
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { constants } from "node:fs";
|
|
20
|
+
import { access, readFile, writeFile } from "node:fs/promises";
|
|
21
|
+
import TurndownService from "turndown";
|
|
22
|
+
import { tables } from "turndown-plugin-gfm";
|
|
23
|
+
import { replaceBalancedTables } from "./balanced-tables.js";
|
|
24
|
+
|
|
25
|
+
export { replaceBalancedTables } from "./balanced-tables.js";
|
|
26
|
+
|
|
27
|
+
const td = new TurndownService({
|
|
28
|
+
headingStyle: "atx",
|
|
29
|
+
codeBlockStyle: "fenced",
|
|
30
|
+
emDelimiter: "*",
|
|
31
|
+
bulletListMarker: "-",
|
|
32
|
+
});
|
|
33
|
+
td.use(tables);
|
|
34
|
+
|
|
35
|
+
const files = process.argv.slice(2);
|
|
36
|
+
if (import.meta.main && files.length === 0) {
|
|
37
|
+
console.error("Usage: bun flatten-tables.ts <file.md> [<file.md>...]");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const PUA = /[\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]/gu;
|
|
42
|
+
|
|
43
|
+
async function main(): Promise<void> {
|
|
44
|
+
for (const path of files) {
|
|
45
|
+
try {
|
|
46
|
+
await access(path, constants.F_OK);
|
|
47
|
+
} catch {
|
|
48
|
+
console.error(`[flatten-tables] not found: ${path}`);
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const src = await readFile(path, "utf8");
|
|
54
|
+
|
|
55
|
+
let tableCount = 0;
|
|
56
|
+
let keptCount = 0;
|
|
57
|
+
let out = replaceBalancedTables(src, (match: string) => {
|
|
58
|
+
const nestedTableCount = (match.match(/<table\b/gi) ?? []).length;
|
|
59
|
+
if (nestedTableCount > 1) {
|
|
60
|
+
keptCount += 1;
|
|
61
|
+
return match;
|
|
62
|
+
}
|
|
63
|
+
const converted = td.turndown(match).trim();
|
|
64
|
+
// turndown-plugin-gfm only converts tables whose first row is <th>
|
|
65
|
+
// (kordoc always emits one); anything else is kept as HTML — do not
|
|
66
|
+
// count it as flattened.
|
|
67
|
+
if (converted.startsWith("<table")) {
|
|
68
|
+
keptCount += 1;
|
|
69
|
+
return match;
|
|
70
|
+
}
|
|
71
|
+
tableCount += 1;
|
|
72
|
+
return `\n\n${converted}\n\n`;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
let puaCount = 0;
|
|
76
|
+
out = out.replace(PUA, () => {
|
|
77
|
+
puaCount += 1;
|
|
78
|
+
return "";
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (tableCount === 0 && puaCount === 0) {
|
|
82
|
+
const kept = keptCount ? ` (${keptCount} table(s) kept as HTML: no <th> heading row)` : "";
|
|
83
|
+
console.log(`[flatten-tables] ${path}: nothing to change${kept}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await writeFile(path, out, "utf8");
|
|
88
|
+
const parts: string[] = [];
|
|
89
|
+
if (tableCount) parts.push(`${tableCount} table(s) flattened`);
|
|
90
|
+
if (keptCount) parts.push(`${keptCount} table(s) kept as HTML (no <th> heading row)`);
|
|
91
|
+
if (puaCount) parts.push(`${puaCount} PUA char(s) stripped`);
|
|
92
|
+
console.log(`[flatten-tables] ${path}: ${parts.join(", ")}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (import.meta.main) {
|
|
97
|
+
main().catch((err: unknown) => {
|
|
98
|
+
console.error("[flatten-tables]", err);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
});
|
|
101
|
+
}
|