@litfamily/litclaude 1.0.10 → 1.0.13
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/CHANGELOG.md +36 -0
- package/README.md +436 -45
- package/README_ko-KR.md +403 -17
- package/bin/install-ownership.mjs +155 -18
- package/bin/litclaude-ai.js +91 -9
- package/docs/ab/S11-baseline-desktop.webp +0 -0
- package/docs/ab/S11-baseline-phone.webp +0 -0
- package/docs/ab/S11-litclaude-desktop.webp +0 -0
- package/docs/ab/S11-litclaude-phone.webp +0 -0
- package/docs/ab/S3-baseline-desktop.webp +0 -0
- package/docs/ab/S3-baseline-phone.webp +0 -0
- package/docs/ab/S3-litclaude-desktop.webp +0 -0
- package/docs/ab/S3-litclaude-phone.webp +0 -0
- package/docs/ab/S4-baseline-desktop.webp +0 -0
- package/docs/ab/S4-baseline-phone.webp +0 -0
- package/docs/ab/S4-litclaude-desktop.webp +0 -0
- package/docs/ab/S4-litclaude-phone.webp +0 -0
- package/docs/ab/S5-baseline-pages.webp +0 -0
- package/docs/ab/S5-baseline-slides.webp +0 -0
- package/docs/ab/S5-litclaude-pages.webp +0 -0
- package/docs/ab/S5-litclaude-slides.webp +0 -0
- package/docs/ab/S7-litclaude-diagram.webp +0 -0
- package/docs/ab/S8-baseline-slides.webp +0 -0
- package/docs/ab/S8-litclaude-slides.webp +0 -0
- package/docs/ab/S9-litclaude-pages.webp +0 -0
- package/docs/agents.md +10 -7
- package/docs/assets/cover-motion-still.webp +0 -0
- package/docs/assets/cover-motion.webp +0 -0
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/skills/autoconference.webp +0 -0
- package/docs/assets/skills/automatic-checks.webp +0 -0
- package/docs/assets/skills/autoresearch.webp +0 -0
- package/docs/assets/skills/browser-drive.webp +0 -0
- package/docs/assets/skills/debugging.webp +0 -0
- package/docs/assets/skills/deep-interview.webp +0 -0
- package/docs/assets/skills/frontend-ui-ux.webp +0 -0
- package/docs/assets/skills/lit-burnoff-file.webp +0 -0
- package/docs/assets/skills/lit-burnoff.webp +0 -0
- package/docs/assets/skills/lit-code.webp +0 -0
- package/docs/assets/skills/lit-commit.webp +0 -0
- package/docs/assets/skills/lit-comprehend.webp +0 -0
- package/docs/assets/skills/lit-crucible.webp +0 -0
- package/docs/assets/skills/lit-diagram-drawer.webp +0 -0
- package/docs/assets/skills/lit-docx.webp +0 -0
- package/docs/assets/skills/lit-handoff.webp +0 -0
- package/docs/assets/skills/lit-humanizer.webp +0 -0
- package/docs/assets/skills/lit-init.webp +0 -0
- package/docs/assets/skills/lit-loop.webp +0 -0
- package/docs/assets/skills/lit-plan.webp +0 -0
- package/docs/assets/skills/lit-pptx.webp +0 -0
- package/docs/assets/skills/lit-recap.webp +0 -0
- package/docs/assets/skills/lit-scientific-visualization.webp +0 -0
- package/docs/assets/skills/lit-team.webp +0 -0
- package/docs/assets/skills/lit-typographic-motion.webp +0 -0
- package/docs/assets/skills/litgoal.webp +0 -0
- package/docs/assets/skills/litresearch.webp +0 -0
- package/docs/assets/skills/litwork.webp +0 -0
- package/docs/assets/skills/lsp-setup.webp +0 -0
- package/docs/assets/skills/readme-studio.webp +0 -0
- package/docs/assets/skills/refactor.webp +0 -0
- package/docs/assets/skills/review-work.webp +0 -0
- package/docs/assets/skills/start-work.webp +0 -0
- package/docs/assets/skills/structural-search.webp +0 -0
- package/docs/assets/skills/visual-qa.webp +0 -0
- package/docs/assets/skills/wikify.webp +0 -0
- package/docs/hooks.md +185 -41
- package/docs/migration.md +6 -3
- package/docs/privacy.md +6 -1
- package/package.json +4 -2
- package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
- package/plugins/litclaude/agents/korean-prose-editor.md +1 -0
- package/plugins/litclaude/agents/korean-style-analyzer.md +1 -0
- package/plugins/litclaude/agents/meaning-preservation-auditor.md +1 -0
- package/plugins/litclaude/agents/native-flow-reviewer.md +1 -0
- package/plugins/litclaude/agents/polish-orchestrator.md +1 -0
- package/plugins/litclaude/bin/litclaude-hook.js +347 -35
- package/plugins/litclaude/bin/litclaude-hud.js +29 -1
- package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
- package/plugins/litclaude/bundled-rules/lit-humanizer.md +14 -0
- package/plugins/litclaude/commands/korean-ai-slop-remover.md +2 -2
- package/plugins/litclaude/commands/lit-comprehend.md +11 -11
- package/plugins/litclaude/commands/lit-humanizer.md +75 -0
- package/plugins/litclaude/commands/lit-korean.md +4 -130
- package/plugins/litclaude/commands/litresearch.md +12 -10
- package/plugins/litclaude/hooks/hooks.json +1 -1
- package/plugins/litclaude/lib/canonical-runtime-commitments.mjs +2 -2
- package/plugins/litclaude/lib/canonical-skill-catalog.mjs +5 -1
- package/plugins/litclaude/lib/canonical-skill-resources.mjs +618 -13
- package/plugins/litclaude/lib/deliverable-hedge-guard.mjs +256 -350
- package/plugins/litclaude/lib/hud-accent-palette.mjs +33 -0
- package/plugins/litclaude/lib/interface-mode.mjs +33 -0
- package/plugins/litclaude/lib/interface-probe-gate.mjs +125 -0
- package/plugins/litclaude/lib/jev-skill-hint.mjs +445 -0
- package/plugins/litclaude/lib/motion-render-gate.mjs +164 -0
- package/plugins/litclaude/lib/mutated-file-paths.mjs +32 -1
- package/plugins/litclaude/lib/office-runtime-lock/package-lock.json +745 -0
- package/plugins/litclaude/lib/office-runtime-lock/package.json +12 -0
- package/plugins/litclaude/lib/office-runtime-lock/requirements.lock +15 -0
- package/plugins/litclaude/lib/office-runtime.mjs +255 -0
- package/plugins/litclaude/lib/office_data.py +493 -0
- package/plugins/litclaude/lib/office_runtime_bootstrap.py +61 -0
- package/plugins/litclaude/lib/ooxml_integrity.py +199 -0
- package/plugins/litclaude/lib/rename-aliases.mjs +3 -1
- package/plugins/litclaude/lib/render_pages.py +105 -0
- package/plugins/litclaude/skills/autoconference/SKILL.md +2 -0
- package/plugins/litclaude/skills/browser-drive/SKILL.md +19 -6
- package/plugins/litclaude/skills/browser-drive/scripts/capability-probe.mjs +44 -8
- package/plugins/litclaude/skills/frontend-ui-ux/ATTRIBUTION.md +26 -0
- package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +50 -16
- package/plugins/litclaude/skills/frontend-ui-ux/examples/phase-3-readme-ab/README.md +9 -0
- package/plugins/litclaude/skills/frontend-ui-ux/references/complete-contract.md +32 -6
- package/plugins/litclaude/skills/frontend-ui-ux/references/craft-floor.md +257 -0
- package/plugins/litclaude/skills/frontend-ui-ux/references/default-editorial-pixel.json +6 -0
- package/plugins/litclaude/skills/frontend-ui-ux/references/interaction-motion.md +34 -88
- package/plugins/litclaude/skills/frontend-ui-ux/references/motion-guide.md +130 -0
- package/plugins/litclaude/skills/frontend-ui-ux/references/slop-register.md +150 -0
- package/plugins/litclaude/skills/frontend-ui-ux/references/visual-reconstruction.md +39 -85
- package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +1534 -0
- package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +141 -0
- package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-server.mjs +57 -0
- package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +129 -0
- package/plugins/litclaude/skills/frontend-ui-ux/scripts/interface-probe.mjs +316 -0
- package/plugins/litclaude/skills/lit-comprehend/SKILL.md +34 -43
- package/plugins/litclaude/skills/lit-comprehend/references/artifact-template.md +5 -44
- package/plugins/litclaude/skills/lit-comprehend/scripts/verify-explainer.mjs +6 -16
- package/plugins/litclaude/skills/lit-diagram-drawer/NOTICE +33 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/SKILL.md +123 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-architecture-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bar-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-beeswarm-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bubble-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-bump-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-data-flow-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-datalake-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-db-schema-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dependency-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-deployment-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-integration-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-er-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-fishbone-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-flowchart-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-gantt-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-heatmap-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-drawio-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-it-state-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-journey-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-kanban-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-layers-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-line-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-marimekko-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-medallion-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-nested-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-org-chart-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-polar-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-process-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-pyramid-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-quadrant-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-queue-animated-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-radar-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-ridgeline-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sankey-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-scatter-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-slopegraph-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-state-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-story-map-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-streamgraph-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-swimlane-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-timeline-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-tree-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-treemap-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-uml-class-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-venn-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-wardley-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-dark.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-full.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/examples/type-waterfall-light.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/OFL.txt +94 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/PretendardVariable.woff2 +0 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/fonts/provenance.json +22 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/icons.html +231 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/index.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/devicon-MIT.txt +20 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/diagram-design-MIT.txt +21 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/log-z-MIT.txt +21 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/simple-icons-CC0.md +30 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/assets/licenses/tabler-MIT.txt +21 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/01-service-architecture/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/01-service-architecture/brief.md +33 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/02-release-decision/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/02-release-decision/brief.md +18 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/03-data-retention/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/03-data-retention/brief.md +19 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/04-oauth-sequence/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/04-oauth-sequence/brief.md +17 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/05-review-lanes/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/05-review-lanes/brief.md +17 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/06-rollout-gates/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/06-rollout-gates/brief.md +17 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/07-deployment-boundary/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/07-deployment-boundary/brief.md +19 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/08-policy-traces/after.html +1 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/examples/08-policy-traces/brief.md +20 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/accessibility.md +37 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/export.md +29 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/import-drawio.md +21 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/import-excalidraw.md +14 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/import-mermaid.md +18 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/import-schema.md +28 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/korean-typography.md +34 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/motion.md +29 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/office-pptx-docx.md +42 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/output-spec.md +48 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-annotation.md +12 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-icons.md +21 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-sketchy.md +11 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/primitive-terminal.md +11 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/profiles.md +24 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/semantic-patterns.md +27 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/style-guide.md +67 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-architecture.md +51 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bar.md +51 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-beeswarm.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bubble.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-bump.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-catalog.json +1433 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-data-flow.md +51 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-datalake.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-db-schema.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dependency.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-deployment.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dp-integration.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-dp-security-matrix.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-er.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-fishbone.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-flowchart.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-gantt.md +49 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-heatmap.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-high-level-vertical.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-high-level.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-drawio.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-excalidraw.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-import-mermaid.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-it-state.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-journey.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-kanban.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-layers.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-line.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-loop-terminal.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-loop.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-marimekko.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-medallion.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-nested.md +59 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-org-chart.md +58 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-paved-road-animated.md +72 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-polar.md +67 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-policy-trace-animated.md +69 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-process.md +58 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-pyramid.md +59 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-quadrant-consultant.md +60 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-quadrant.md +57 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-queue-animated.md +63 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-radar.md +57 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-ridgeline.md +63 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sankey.md +68 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-scatter.md +60 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sequence-oauth.md +66 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-sequence.md +63 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-slopegraph.md +65 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-state-lifecycle.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-state.md +59 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-story-map.md +52 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-streamgraph.md +53 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-swimlane.md +52 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-timeline.md +52 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-tree-block-decomposition.md +57 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-tree.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-treemap.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-uml-class.md +52 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-venn.md +51 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-wardley.md +52 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/type-waterfall.md +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/references/verifier-guide.md +66 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/block-registry.mjs +43 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/brief-contract.mjs +94 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/check-visible-text.mjs +15 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/diagram-metrics.mjs +223 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/doctor.mjs +35 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/drawio-extract.mjs +635 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/excalidraw-extract.mjs +319 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/export.mjs +116 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/mermaid-extract.mjs +438 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/office-safety.mjs +54 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/renderer.mjs +33 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-all.mjs +58 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-brief.mjs +22 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-coverage.mjs +56 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-diagram.mjs +27 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-motion.mjs +12 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/verify-type.mjs +48 -0
- package/plugins/litclaude/skills/lit-diagram-drawer/scripts/visual-quality.mjs +376 -0
- package/plugins/litclaude/skills/lit-docx/NOTICE +33 -0
- package/plugins/litclaude/skills/lit-docx/SKILL.md +170 -0
- package/plugins/litclaude/skills/lit-docx/references/frontmatter_schema.md +42 -0
- package/plugins/litclaude/skills/lit-docx/references/journal_style_spec.md +17 -0
- package/plugins/litclaude/skills/lit-docx/references/markdown_quality_checklist.md +37 -0
- package/plugins/litclaude/skills/lit-docx/references/slop_phrase_list.yaml +58 -0
- package/plugins/litclaude/skills/lit-docx/references/slop_rules.md +35 -0
- package/plugins/litclaude/skills/lit-docx/scripts/clean_markdown.py +95 -0
- package/plugins/litclaude/skills/lit-docx/scripts/convert_md_to_docx.py +1194 -0
- package/plugins/litclaude/skills/lit-docx/scripts/convert_md_to_pdf.py +290 -0
- package/plugins/litclaude/skills/lit-docx/scripts/convert_pdf.py +139 -0
- package/plugins/litclaude/skills/lit-docx/scripts/edit_docx.py +306 -0
- package/plugins/litclaude/skills/lit-docx/scripts/embed_images.py +78 -0
- package/plugins/litclaude/skills/lit-docx/scripts/generate_docx_templates.py +500 -0
- package/plugins/litclaude/skills/lit-docx/scripts/qa_docx.py +177 -0
- package/plugins/litclaude/skills/lit-docx/scripts/slop_lint.py +561 -0
- package/plugins/litclaude/skills/lit-docx/scripts/visual_audit.py +48 -0
- package/plugins/litclaude/skills/lit-docx/templates/docx/acs.docx +0 -0
- package/plugins/litclaude/skills/lit-docx/templates/docx/elsevier.docx +0 -0
- package/plugins/litclaude/skills/lit-docx/templates/docx/ieee.docx +0 -0
- package/plugins/litclaude/skills/lit-docx/templates/docx/korean-generic.docx +0 -0
- package/plugins/litclaude/skills/lit-docx/templates/docx/nature.docx +0 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/acs/README.md +5 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/acs/template.tex +37 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/elsevier/README.md +5 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/elsevier/template.tex +38 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/ieee/README.md +5 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/ieee/template.tex +37 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/korean-generic/README.md +5 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/korean-generic/template.tex +37 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/nature/README.md +5 -0
- package/plugins/litclaude/skills/lit-docx/templates/latex/nature/template.tex +37 -0
- package/plugins/litclaude/skills/lit-docx/templates/registry.yaml +1366 -0
- package/plugins/litclaude/skills/lit-humanizer/NOTICE +160 -0
- package/plugins/litclaude/skills/lit-humanizer/SKILL.md +164 -0
- package/plugins/litclaude/skills/lit-humanizer/assets/always-on-rule.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/assets/report-skeleton.md +25 -0
- package/plugins/litclaude/skills/lit-humanizer/assets/slide-text-skeleton.md +28 -0
- package/plugins/litclaude/skills/lit-humanizer/bench/prompts.md +73 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/accessibility-note/after.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/accessibility-note/before.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/api-reference/after.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/api-reference/before.md +15 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/changelog/after.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/changelog/before.md +12 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/code-comments/after.md +10 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/code-comments/before.md +19 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/commit/after.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/commit/before.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/data-release/after.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/data-release/before.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/english-essay/after.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/english-essay/before.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/incident-update/after.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/incident-update/before.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-essay/after.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-essay/before.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-report/after.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-report/before.md +13 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-slide/after.md +19 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/ko-slide/before.md +21 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/meeting-brief/after.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/meeting-brief/before.md +11 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/policy-faq/after.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/policy-faq/before.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/pr/after.md +15 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/pr/before.md +17 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/project-update/after.md +7 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/project-update/before.md +9 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/readme/after.md +12 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/readme/before.md +14 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/report/after.md +13 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/report/before.md +11 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/research-abstract/after.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/research-abstract/before.md +5 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/slides/after.md +19 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/slides/before.md +19 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/troubleshooting/after.md +11 -0
- package/plugins/litclaude/skills/lit-humanizer/examples/troubleshooting/before.md +11 -0
- package/plugins/litclaude/skills/lit-humanizer/motion-guide.md +123 -0
- package/plugins/litclaude/skills/lit-humanizer/references/code-patterns.md +468 -0
- package/plugins/litclaude/skills/lit-humanizer/references/deliverable-channels.md +111 -0
- package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-checklist.md +43 -0
- package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-content.md +243 -0
- package/plugins/litclaude/skills/lit-humanizer/references/en-patterns-structure.md +375 -0
- package/plugins/litclaude/skills/lit-humanizer/references/en-patterns.md +57 -0
- package/plugins/litclaude/skills/lit-humanizer/references/ko-metrics.md +33 -0
- package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns-a-d.md +659 -0
- package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns-e-j.md +387 -0
- package/plugins/litclaude/skills/lit-humanizer/references/ko-patterns.md +31 -0
- package/plugins/litclaude/skills/lit-humanizer/references/rewrite-playbook.md +54 -0
- package/plugins/litclaude/skills/lit-humanizer/references/taxonomy.md +153 -0
- package/plugins/litclaude/skills/lit-humanizer/rules.json +884 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/artifact-text.mjs +38 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/core.mjs +207 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/detect.mjs +64 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/extract_office_text.py +112 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/ko-metrics.mjs +124 -0
- package/plugins/litclaude/skills/lit-humanizer/scripts/scan-input.mjs +29 -0
- package/plugins/litclaude/skills/lit-loop/SKILL.md +30 -1
- package/plugins/litclaude/skills/lit-plan/SKILL.md +4 -1
- package/plugins/litclaude/skills/lit-pptx/NOTICE +38 -0
- package/plugins/litclaude/skills/lit-pptx/SKILL.md +207 -0
- package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-lg.png +0 -0
- package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-md.png +0 -0
- package/plugins/litclaude/skills/lit-pptx/assets/azure/circle-sm.png +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Black.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Bold.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Light.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Medium.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/A2Z-Regular.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/OFL.txt +94 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/a2z/SOURCE.md +29 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/OFL.txt +94 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/Pretendard-Bold.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/pretendard/Pretendard-Regular.otf +0 -0
- package/plugins/litclaude/skills/lit-pptx/fonts/provenance.json +78 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/analyst.md +49 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/antithesis.md +59 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/architect.md +44 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/critic.md +42 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/synthesizer.md +47 -0
- package/plugins/litclaude/skills/lit-pptx/references/agents/thesis.md +33 -0
- package/plugins/litclaude/skills/lit-pptx/references/anti-slop-checklist.md +81 -0
- package/plugins/litclaude/skills/lit-pptx/references/authoring-guide.md +173 -0
- package/plugins/litclaude/skills/lit-pptx/references/consensus-protocol.md +125 -0
- package/plugins/litclaude/skills/lit-pptx/references/data-display-cookbook.md +45 -0
- package/plugins/litclaude/skills/lit-pptx/references/design-system-azure.md +58 -0
- package/plugins/litclaude/skills/lit-pptx/references/interview-protocol.md +113 -0
- package/plugins/litclaude/skills/lit-pptx/references/stages/autopilot.md +48 -0
- package/plugins/litclaude/skills/lit-pptx/references/stages/interview.md +52 -0
- package/plugins/litclaude/skills/lit-pptx/references/stages/plan.md +42 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/compile-deck.js +414 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/craft_extras.py +373 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/deck_craft.py +321 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/embed_fonts.py +215 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/forbidden-terms.json +55 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/layout_inventory.py +418 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/learn_template.py +446 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/derive-palette.js +176 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/directive-parser.js +244 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/font-map.js +79 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/gen-bg.js +86 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/gen-gradient-assets.js +37 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/layout-resolver.js +768 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/markdown-loader.js +136 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/render-adapter-html.js +356 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/render-adapter-pptx.js +2094 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/runtime-require.js +28 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/slide-ast.js +561 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/spec-validator.js +94 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/lib/template-registry.js +394 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/package.json +4 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/qa_deck.py +766 -0
- package/plugins/litclaude/skills/lit-pptx/scripts/validate_pptx.py +215 -0
- package/plugins/litclaude/skills/lit-pptx/specs/markdown-slide-spec-v1.md +251 -0
- package/plugins/litclaude/skills/lit-pptx/specs/markdown-slide-spec-v2.md +214 -0
- package/plugins/litclaude/skills/lit-pptx/specs/slide-ast-v1.schema.json +229 -0
- package/plugins/litclaude/skills/lit-pptx/specs/slide-ast-v2.schema.json +144 -0
- package/plugins/litclaude/skills/lit-pptx/specs/template-enrollment-contract.md +382 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/capabilities.yaml +146 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/layout-mapping.yaml +454 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-A2Z/template.yaml +37 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/capabilities.yaml +154 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/layout-mapping.yaml +475 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/AZURE-PRO/template.yaml +37 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/capabilities.yaml +179 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/layout-mapping.yaml +299 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/template.yaml +45 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/capabilities.yaml +181 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/layout-mapping.yaml +299 -0
- package/plugins/litclaude/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/template.yaml +44 -0
- package/plugins/litclaude/skills/lit-scientific-visualization/SKILL.md +1 -0
- package/plugins/litclaude/skills/lit-typographic-motion/SKILL.md +131 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/NOTICE +23 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +56 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/audio/beat_grid.py +56 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/audio/requirements.lock +1084 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/constants.mjs +211 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/contrast.mjs +90 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/events.mjs +46 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/flash.mjs +211 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/gate-rules.mjs +550 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/presets.mjs +123 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/text.mjs +100 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/timeline.mjs +142 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/util.mjs +167 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/core/voices.mjs +19 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/models/word-timing.json +198 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/analysis.mjs +108 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/brief.mjs +158 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/chrome.mjs +330 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/coverage.mjs +83 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/done.mjs +104 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/encode.mjs +104 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/frame-worker.mjs +36 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/look.mjs +128 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/pipeline.mjs +592 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/png.mjs +112 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/report.mjs +66 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/runtime.mjs +330 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/session.mjs +145 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/sound-cli.mjs +60 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/sound.mjs +641 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-capture.mjs +178 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-gate.mjs +122 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-qa.mjs +295 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage-serve.mjs +278 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stage.mjs +503 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/stills.mjs +100 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/treatment.mjs +343 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/node/ws-server.mjs +132 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/package-lock.json +25 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/package.json +10 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/init.js +288 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/qa.js +157 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/stage/stage-kit.js +701 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/boot.mjs +123 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/engine.mjs +281 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/gl.mjs +319 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/glsl-common.mjs +78 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/index.html +6 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/lines.mjs +112 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/crt.mjs +98 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/dither.mjs +49 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/glitch.mjs +77 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/swiss-grid.mjs +61 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/terminal-ui.mjs +88 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/passes/tidal-gradient.mjs +86 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/post.mjs +165 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scale.mjs +15 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scene.mjs +82 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/end-card.mjs +30 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/index.mjs +16 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/karaoke-line.mjs +47 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/kinetic-list.mjs +45 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/number-counter.mjs +29 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/signature.mjs +73 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/scenes/title-slam.mjs +73 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/stroke.mjs +236 -0
- package/plugins/litclaude/skills/lit-typographic-motion/engine/web/type.mjs +180 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-400.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-700.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w100-900.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-400.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-700.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w125-900.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-400.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-700.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/Archivo-w75-900.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/archivo/OFL.txt +93 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/manifest.json +437 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/OFL.txt +93 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/Silkscreen-Bold.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/silkscreen/Silkscreen-Regular.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/CREDITS +42 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSAllure.svg +216 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSFelix.svg +216 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSOsmotron.svg +216 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSReadability.svg +216 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/EMSTech.svg +217 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/stroke/OFL.txt +91 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/vt323/OFL.txt +93 -0
- package/plugins/litclaude/skills/lit-typographic-motion/fonts/vt323/VT323-Regular.ttf +0 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/brief-schema.md +91 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/craft-loop.md +69 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/engine-contract.md +104 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/look.md +106 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/runtime.md +65 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/sound.md +83 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/stage.md +192 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/style-bibles.md +117 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/treatment.md +114 -0
- package/plugins/litclaude/skills/lit-typographic-motion/references/type-craft.md +79 -0
- package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion-doctor.mjs +78 -0
- package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion-runtime.mjs +67 -0
- package/plugins/litclaude/skills/lit-typographic-motion/scripts/motion.mjs +132 -0
- package/plugins/litclaude/skills/litresearch/SKILL.md +54 -18
- package/scripts/doctor.mjs +5 -0
- package/scripts/postinstall.mjs +1 -0
- package/plugins/litclaude/skills/lit-korean/SKILL.md +0 -327
- /package/plugins/litclaude/skills/{lit-korean/references/fidelity-checklist.md → lit-humanizer/references/litclaude-fidelity-checklist.md} +0 -0
- /package/plugins/litclaude/skills/{lit-korean/references/rewrite-rules.md → lit-humanizer/references/litclaude-rewrite-rules.md} +0 -0
- /package/plugins/litclaude/skills/{lit-korean/references/style-patterns.md → lit-humanizer/references/litclaude-style-patterns.md} +0 -0
|
@@ -113,3 +113,36 @@ export const litBrandPrefix = (version, { noColor = false, truecolor = false, de
|
|
|
113
113
|
out += `\x1b[38;2;${NEON_END[0]};${NEON_END[1]};${NEON_END[2]}m v${version}]\x1b[0m`;
|
|
114
114
|
return out;
|
|
115
115
|
};
|
|
116
|
+
|
|
117
|
+
// --- Rainbow text (Jev skill hint) ------------------------------------------
|
|
118
|
+
// Per-character hue sweep starting at `phase` degrees: truecolor paints exact hues, 256-color
|
|
119
|
+
// snaps each hue to the 6x6x6 cube, 16-color picks the nearest bright hue, plain returns the
|
|
120
|
+
// text untouched. Spaces get no escape, and stripping the escapes always gives back `text`.
|
|
121
|
+
const RAINBOW_ANSI16 = Object.freeze([91, 93, 92, 96, 94, 95]);
|
|
122
|
+
|
|
123
|
+
const hueToRgb = (hue) => {
|
|
124
|
+
// HSV with a softened saturation so every hue stays legible on a dark terminal.
|
|
125
|
+
const h = ((hue % 360) + 360) % 360 / 60;
|
|
126
|
+
const s = 0.65;
|
|
127
|
+
const x = 1 - Math.abs((h % 2) - 1);
|
|
128
|
+
const [r, g, b] = [[1, x, 0], [x, 1, 0], [0, 1, x], [0, x, 1], [x, 0, 1], [1, 0, x]][Math.floor(h) % 6];
|
|
129
|
+
return [r, g, b].map((channel) => Math.round(255 * (1 - s + s * channel)));
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const rainbowText = (text, { depth = "plain", phase = 0 } = {}) => {
|
|
133
|
+
if (!["truecolor", "256", "16"].includes(depth)) return text;
|
|
134
|
+
const chars = [...text];
|
|
135
|
+
const step = chars.length > 1 ? Math.min(60, 300 / (chars.length - 1)) : 0;
|
|
136
|
+
const painted = chars.map((char, index) => {
|
|
137
|
+
if (char === " ") return char;
|
|
138
|
+
const hue = (((phase + index * step) % 360) + 360) % 360;
|
|
139
|
+
if (depth === "16") return `\x1b[${RAINBOW_ANSI16[Math.floor(((hue + 30) % 360) / 60)]}m${char}`;
|
|
140
|
+
const [r, g, b] = hueToRgb(hue);
|
|
141
|
+
if (depth === "256") {
|
|
142
|
+
const cube = (value) => Math.round((value / 255) * 5);
|
|
143
|
+
return `\x1b[38;5;${16 + 36 * cube(r) + 6 * cube(g) + cube(b)}m${char}`;
|
|
144
|
+
}
|
|
145
|
+
return `\x1b[38;2;${r};${g};${b}m${char}`;
|
|
146
|
+
});
|
|
147
|
+
return `\x1b[1m${painted.join("")}\x1b[0m`;
|
|
148
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Interface-mode wording for frontend-ui-ux: build (the default), polish, audit and harden.
|
|
2
|
+
//
|
|
3
|
+
// Input is the hook's normalized prompt text (lower-cased, code removed, `-` and `_` turned into
|
|
4
|
+
// spaces), so "stress-test" arrives as "stress test" and "read-only" as "read only". Hangul terms
|
|
5
|
+
// are bare stems for the same agglutination reason the hook's UI route gives. Mode words say
|
|
6
|
+
// nothing about the object; the hook pairs them with its interface-noun check before routing, so
|
|
7
|
+
// "이 문단 다듬어줘" or "서버 상태 점검" never reach the skill. Video, 영상, 모션 and 발표 wording
|
|
8
|
+
// is deliberately absent: those belong to other skills.
|
|
9
|
+
|
|
10
|
+
// A fix requested in the same breath turns an audit back into an editing mode.
|
|
11
|
+
const FIX_REQUEST = /고쳐\s*줘|바로\s*고쳐|고치고|수정해\s*줘|\b(?:then|and) fix\b|\bfix (?:everything|it all|them all)\b/u;
|
|
12
|
+
const AUDIT = /\baudit\w*|\bread only\b|\bjust check\b|\btell me what['’]?s wrong\b|점검|검토만/u;
|
|
13
|
+
const HARDEN = /\bharden\w*|\bstress test\w*|\bholds? up (?:under|with)\b|\brobust to\b|튼튼하게|견고하게/u;
|
|
14
|
+
const NEGATED_HARDEN = /\b(?:don['’]?t|do not|no|without)\s+(?:stress test\w*|harden\w*)/gu;
|
|
15
|
+
const POLISH = /\bpolish\w*|\bclean up the styling\b|\btighten up\b|\bsame layout\b|\bwithout redesigning\b|\bdon['’]?t restructure\b|\bkeep every \w+ where\b|다듬|그대로\s*두고|구조는\s*(?:그대로|손대지)/u;
|
|
16
|
+
// Polish never restructures: wording that asks for a new layout or a rebuild is a build.
|
|
17
|
+
const REBUILD = /(?<!without )\bredesign\w*|\bcompletely new\b|\bbrand new\b|\bfrom scratch\b|전체를\s*다시|다시\s*짜|새로\s*(?:만들|짜)/u;
|
|
18
|
+
|
|
19
|
+
export const INTERFACE_MODES = Object.freeze(["build", "polish", "audit", "harden"]);
|
|
20
|
+
|
|
21
|
+
// True when the text carries a polish, audit or harden word (negated harden wording excluded).
|
|
22
|
+
export function hasInterfaceModeWord(normalized) {
|
|
23
|
+
const text = normalized.replace(NEGATED_HARDEN, " ");
|
|
24
|
+
return AUDIT.test(text) || HARDEN.test(text) || POLISH.test(text);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function interfaceMode(normalized) {
|
|
28
|
+
const text = normalized.replace(NEGATED_HARDEN, " ");
|
|
29
|
+
if (AUDIT.test(text) && !FIX_REQUEST.test(text)) return "audit";
|
|
30
|
+
if (HARDEN.test(text)) return "harden";
|
|
31
|
+
if (POLISH.test(text) && !REBUILD.test(text)) return "polish";
|
|
32
|
+
return "build";
|
|
33
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Interface-probe hand-off gate. A lit workflow turn (lit-loop, litwork, litgoal, a native
|
|
2
|
+
// workflow, or frontend-ui-ux itself) that writes a user-facing web interface must run
|
|
3
|
+
// frontend-ui-ux's interface probe before it ends: UserPromptSubmit arms the turn, PostToolUse
|
|
4
|
+
// records interface edits and probe runs, and the Stop hook refuses to end the turn until a clean
|
|
5
|
+
// probe run follows the last edit. Clean means the run completed: its output shows the Approve
|
|
6
|
+
// verdict and no BLOCKED line, or, when the output went elsewhere, its --out manifest (written after
|
|
7
|
+
// the edit) has exit code 0, every matrix row and no HIGH finding. Empty output, a BLOCKED run and
|
|
8
|
+
// anything the hook cannot read are not clean. The block
|
|
9
|
+
// counter is the loop brake: at most INTERFACE_PROBE_MAX_BLOCKS blocks per turn, then the stop
|
|
10
|
+
// passes with a warning. Any unreadable state fails SAFE (allow).
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { extname, isAbsolute, join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import { resolveProjectStateRoot } from "./project-state-root.mjs";
|
|
15
|
+
|
|
16
|
+
export const INTERFACE_PROBE_MAX_BLOCKS = 2;
|
|
17
|
+
// start-work is left out: its prompt turn must stay side-effect-free, and the plan rows it runs
|
|
18
|
+
// already name frontend-ui-ux in their Verification.
|
|
19
|
+
export const INTERFACE_PROBE_WORKFLOWS = Object.freeze(["lit-loop", "litwork", "litgoal", "native-workflow", "frontend-ui-ux"]);
|
|
20
|
+
// Files a browser renders as the interface itself. Path segments alone (an `app/` directory) are
|
|
21
|
+
// not enough here: a backend-only change must never be held for a browser probe.
|
|
22
|
+
export const INTERFACE_FILE_EXTENSIONS = Object.freeze([".html", ".htm", ".css", ".scss", ".sass", ".less", ".vue", ".svelte", ".astro", ".tsx", ".jsx"]);
|
|
23
|
+
|
|
24
|
+
const PROBE_COMMAND = /\bnode\b[^\n;&|]*interface-probe\.mjs/u;
|
|
25
|
+
const OUT_ARGUMENT = /interface-probe\.mjs[^\n;&|]*?--out[=\s]+(?:"([^"]+)"|'([^']+)'|([^\s;&|>]+))/u;
|
|
26
|
+
const MATRIX_ROWS = 7;
|
|
27
|
+
const MAX_PATHS = 5;
|
|
28
|
+
|
|
29
|
+
export const interfaceProbeTurnPath = (cwd = resolveProjectStateRoot()) => join(resolveProjectStateRoot(cwd), ".litclaude", "interface-probe", "turn.json");
|
|
30
|
+
|
|
31
|
+
const readTurn = (cwd) => {
|
|
32
|
+
const path = interfaceProbeTurnPath(cwd);
|
|
33
|
+
if (!existsSync(path)) return null;
|
|
34
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
35
|
+
if (!parsed || typeof parsed !== "object" || typeof parsed.sessionId !== "string" || !Number.isInteger(parsed.blockCount) || parsed.blockCount < 0) {
|
|
36
|
+
throw new Error("invalid interface-probe turn state");
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const writeTurn = (cwd, state) => {
|
|
42
|
+
const target = interfaceProbeTurnPath(cwd);
|
|
43
|
+
mkdirSync(join(target, ".."), { recursive: true });
|
|
44
|
+
const tmp = `${target}.tmp`;
|
|
45
|
+
writeFileSync(tmp, JSON.stringify(state));
|
|
46
|
+
renameSync(tmp, target);
|
|
47
|
+
return state;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Every prompt re-arms or clears the turn, so the gate never outlives the turn that armed it.
|
|
51
|
+
export const recordInterfaceProbeTurn = (cwd, { sessionId, discipline, now = Date.now() }) => {
|
|
52
|
+
if (!INTERFACE_PROBE_WORKFLOWS.includes(discipline)) {
|
|
53
|
+
rmSync(interfaceProbeTurnPath(cwd), { force: true });
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return writeTurn(cwd, { sessionId: typeof sessionId === "string" ? sessionId : "", discipline, promptAt: now, editAt: null, paths: [], probeAt: null, issue: null, issueAt: null, blockCount: 0, warned: false });
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const interfaceFilePaths = (filePaths) => filePaths.filter((path) => INTERFACE_FILE_EXTENSIONS.includes(extname(path).toLowerCase()));
|
|
60
|
+
|
|
61
|
+
const probeOutput = (input) => {
|
|
62
|
+
const response = input.tool_response;
|
|
63
|
+
if (!response || typeof response !== "object") return "";
|
|
64
|
+
return [response.stdout, response.stderr, response.output].filter((part) => typeof part === "string").join("\n");
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Why a probe run is not clean, or null when it is.
|
|
68
|
+
const probeIssue = ({ output, command, workdir, editAt }) => {
|
|
69
|
+
if (/BLOCKED:/u.test(output)) return (/BLOCKED:[^\n]*/u.exec(output)[0]).slice(0, 120);
|
|
70
|
+
if (/Verdict: Block \(/u.test(output)) return "a HIGH finding remains";
|
|
71
|
+
if (/Verdict: Approve \(0 HIGH\)/u.test(output)) return null;
|
|
72
|
+
const out = OUT_ARGUMENT.exec(command);
|
|
73
|
+
const dir = out && (out[1] ?? out[2] ?? out[3]);
|
|
74
|
+
if (!dir || dir.includes("$")) return output.trim() ? "no verdict in its output" : "empty output and no readable --out manifest";
|
|
75
|
+
try {
|
|
76
|
+
const file = join(isAbsolute(dir) ? dir : join(workdir, dir), "findings.json");
|
|
77
|
+
if (statSync(file).mtimeMs < (editAt ?? 0)) return "its --out manifest predates the last interface edit";
|
|
78
|
+
const { manifest, findings } = JSON.parse(readFileSync(file, "utf8"));
|
|
79
|
+
if (manifest?.exit_code !== 0 || (manifest.viewports_run ?? []).length < MATRIX_ROWS) return `its --out manifest shows exit ${manifest?.exit_code} with ${(manifest?.viewports_run ?? []).length} of ${MATRIX_ROWS} rows`;
|
|
80
|
+
if ((findings ?? []).some((finding) => finding.severity === "HIGH" && finding.tier !== "not_verified")) return "a HIGH finding remains";
|
|
81
|
+
return null;
|
|
82
|
+
} catch {
|
|
83
|
+
return "empty output and no readable --out manifest";
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const observeInterfaceProbeTool = (cwd, { input, filePaths, now = Date.now() }) => {
|
|
88
|
+
let turn;
|
|
89
|
+
try {
|
|
90
|
+
turn = readTurn(cwd);
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
if (!turn || turn.sessionId !== input.session_id) return null;
|
|
95
|
+
const edited = interfaceFilePaths(filePaths);
|
|
96
|
+
const command = input.tool_name === "Bash" && typeof input.tool_input?.command === "string" ? input.tool_input.command : "";
|
|
97
|
+
if (edited.length) {
|
|
98
|
+
return writeTurn(cwd, { ...turn, editAt: now, paths: [...new Set([...edited, ...turn.paths])].slice(0, MAX_PATHS) });
|
|
99
|
+
}
|
|
100
|
+
if (PROBE_COMMAND.test(command)) {
|
|
101
|
+
const workdir = typeof input.cwd === "string" ? input.cwd : cwd;
|
|
102
|
+
const issue = probeIssue({ output: probeOutput(input), command, workdir, editAt: turn.editAt });
|
|
103
|
+
return writeTurn(cwd, issue ? { ...turn, issue, issueAt: now } : { ...turn, probeAt: now, issue: null, issueAt: null });
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const evaluateInterfaceProbeStop = ({ cwd, sessionId, now = Date.now() }) => {
|
|
109
|
+
const turn = readTurn(cwd);
|
|
110
|
+
if (!turn || turn.sessionId !== sessionId || turn.editAt === null) return { action: "allow", why: "no-interface-edit" };
|
|
111
|
+
if (turn.probeAt !== null && turn.probeAt >= turn.editAt) return { action: "allow", why: "probed" };
|
|
112
|
+
const detail = turn.issue && turn.issueAt >= turn.editAt
|
|
113
|
+
? `the interface changed (${turn.paths.join(", ")}) and the last interface probe run after it was not clean: ${turn.issue}`
|
|
114
|
+
: `the interface changed (${turn.paths.join(", ")}) and no clean run of frontend-ui-ux's interface probe followed it`;
|
|
115
|
+
if (turn.blockCount >= INTERFACE_PROBE_MAX_BLOCKS) {
|
|
116
|
+
if (turn.warned) return { action: "allow", why: "capped" };
|
|
117
|
+
writeTurn(cwd, { ...turn, warned: true });
|
|
118
|
+
return { action: "warn", why: "capped", systemMessage: `LitClaude interface probe: ${detail}; allowing the stop after ${INTERFACE_PROBE_MAX_BLOCKS} reminders.` };
|
|
119
|
+
}
|
|
120
|
+
writeTurn(cwd, { ...turn, blockCount: turn.blockCount + 1, lastBlockAt: now });
|
|
121
|
+
return {
|
|
122
|
+
action: "block",
|
|
123
|
+
reason: `${detail}. Hand the interface part to Skill(frontend-ui-ux): run scripts/interface-probe.mjs from its skill directory on the built page across the full matrix, fix every HIGH finding, then run it again. If it cannot run, or a HIGH has to stay, say BLOCKED or state the limitation with its reason before finishing.`,
|
|
124
|
+
};
|
|
125
|
+
};
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
// Optional Jev skill hint for the UserPromptSubmit hook.
|
|
2
|
+
//
|
|
3
|
+
// Off unless LITCLAUDE_JEV=1 and TYPESAFE_API_KEY are both in the environment. On an eligible
|
|
4
|
+
// turn it asks TypeSafe's Jev model which one of this plugin's own skills fits the prompt, and
|
|
5
|
+
// returns at most one fixed advisory sentence naming a skill ID it validated against the catalog
|
|
6
|
+
// it sent. The response is untrusted data: no response text ever reaches the model context.
|
|
7
|
+
//
|
|
8
|
+
// The key is read from the environment only. It is never written, printed, traced, or placed in
|
|
9
|
+
// an error: every failure is reported as a fixed reason word from FALLBACK_REASONS.
|
|
10
|
+
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import { closeSync, constants, lstatSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync, writeSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
import { canonicalSkillIds } from "./canonical-skill-catalog.mjs";
|
|
16
|
+
import { SECRET_SHAPE_PATTERNS } from "./secret-shapes.mjs";
|
|
17
|
+
|
|
18
|
+
export const JEV_FLAG = "LITCLAUDE_JEV";
|
|
19
|
+
export const JEV_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
|
|
20
|
+
export const JEV_DEFAULT_MODEL = "jev-1.13.0";
|
|
21
|
+
export const JEV_DEFAULT_TIMEOUT_MS = 1500;
|
|
22
|
+
export const JEV_MAX_TIMEOUT_MS = 3000;
|
|
23
|
+
export const JEV_DEFAULT_MAX_CALLS = 200;
|
|
24
|
+
export const JEV_DEFAULT_MIN_CONFIDENCE = 0.35;
|
|
25
|
+
export const JEV_MAX_PROMPT_CHARS = 2000;
|
|
26
|
+
export const JEV_REDACTION_WINDOW_CHARS = 8000;
|
|
27
|
+
export const JEV_MAX_REQUEST_BYTES = 64 * 1024;
|
|
28
|
+
export const JEV_MAX_RESPONSE_BYTES = 64 * 1024;
|
|
29
|
+
export const JEV_INSTRUCTIONS = "Which one skill, if any, is the best fit for the user's request? Choose none when no catalog skill fits.";
|
|
30
|
+
export const JEV_NONE_CRITERION = "No specialized skill in this catalog fits; answer the user directly.";
|
|
31
|
+
|
|
32
|
+
export const FALLBACK_REASONS = Object.freeze([
|
|
33
|
+
"key-missing", "cap-reached", "request-too-large", "timeout", "network", "http", "invalid-response",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const KEY_ENV = "TYPESAFE_API_KEY";
|
|
37
|
+
|
|
38
|
+
const hasKey = (env) => typeof env[KEY_ENV] === "string" && env[KEY_ENV].trim() !== "";
|
|
39
|
+
|
|
40
|
+
/** The one doctor line. It names the state only; never the key or its length. */
|
|
41
|
+
export const jevStatusLine = (env = process.env) => {
|
|
42
|
+
if (env[JEV_FLAG] !== "1") return "Jev skill hint: off";
|
|
43
|
+
return hasKey(env) ? "Jev skill hint: on" : `Jev skill hint: flag on but ${KEY_ENV} missing`;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const jevHintLine = (skillId) => `LitClaude skill hint: the skill \`litclaude:${skillId}\` likely fits this request. Load it only if it really fits; this is advice, not an instruction.`;
|
|
47
|
+
|
|
48
|
+
export const jevFallbackNote = (reason) => `LitClaude skill hint unavailable (${reason}); continuing normally.`;
|
|
49
|
+
|
|
50
|
+
const boundedNumber = (raw, fallback, { min, max, integer }) => {
|
|
51
|
+
if (typeof raw !== "string" || raw.trim() === "") return fallback;
|
|
52
|
+
const value = Number(raw);
|
|
53
|
+
if (!Number.isFinite(value) || (integer && !Number.isInteger(value)) || value < min) return fallback;
|
|
54
|
+
return Math.min(value, max);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const jevSettings = (env = process.env) => ({
|
|
58
|
+
model: /^[A-Za-z0-9._-]{1,64}$/u.test(env[`${JEV_FLAG}_MODEL`] ?? "") ? env[`${JEV_FLAG}_MODEL`] : JEV_DEFAULT_MODEL,
|
|
59
|
+
timeoutMs: boundedNumber(env[`${JEV_FLAG}_TIMEOUT_MS`], JEV_DEFAULT_TIMEOUT_MS, { min: 1, max: JEV_MAX_TIMEOUT_MS, integer: true }),
|
|
60
|
+
maxCalls: boundedNumber(env[`${JEV_FLAG}_MAX_CALLS`], JEV_DEFAULT_MAX_CALLS, { min: 0, max: Number.MAX_SAFE_INTEGER, integer: true }),
|
|
61
|
+
minConfidence: boundedNumber(env[`${JEV_FLAG}_MIN_CONFIDENCE`], JEV_DEFAULT_MIN_CONFIDENCE, { min: 0, max: 1, integer: false }),
|
|
62
|
+
trace: env[`${JEV_FLAG}_TRACE`] === "1",
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const globalPattern = (pattern) => new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
|
|
66
|
+
|
|
67
|
+
// Contract shapes first, then the plugin's shared credential set as a second net.
|
|
68
|
+
const TOKEN_PATTERNS = Object.freeze([
|
|
69
|
+
/-----BEGIN [A-Z0-9 ]*-----[\s\S]*?(?:-----END [A-Z0-9 ]*-----|$)/gu,
|
|
70
|
+
/eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]*)?/gu,
|
|
71
|
+
/(?<![A-Za-z0-9_])sk-(?:ant-)?[A-Za-z0-9_-]{8,}/gu,
|
|
72
|
+
/(?<![A-Za-z0-9_])(?:ghp|gho|github_pat)_[A-Za-z0-9_]{8,}/gu,
|
|
73
|
+
/(?<![A-Za-z0-9_])npm_[A-Za-z0-9]{8,}/gu,
|
|
74
|
+
/(?<![A-Za-z0-9_])apikey_[A-Za-z0-9_-]{8,}/gu,
|
|
75
|
+
/(?<![A-Za-z0-9_])xox[abprs]-[A-Za-z0-9-]{8,}/gu,
|
|
76
|
+
/(?<![A-Za-z0-9])AKIA[A-Z0-9]{12,}/gu,
|
|
77
|
+
/(?<![A-Za-z0-9_])AIza[A-Za-z0-9_-]{16,}/gu,
|
|
78
|
+
/[A-Za-z0-9+/_-]{32,}={0,2}/gu,
|
|
79
|
+
...SECRET_SHAPE_PATTERNS.map(globalPattern),
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Redaction in the contract's order: an 8,000-character window, the literal key, home paths,
|
|
84
|
+
* e-mail addresses, token shapes, the 2,000-character cut, then any run of 8 or more token
|
|
85
|
+
* characters left at the cut, so a secret split by the cut never leaves a fragment behind.
|
|
86
|
+
*/
|
|
87
|
+
export const redactPromptForJev = (text, key) => {
|
|
88
|
+
let value = Array.from(typeof text === "string" ? text : "").slice(0, JEV_REDACTION_WINDOW_CHARS).join("");
|
|
89
|
+
// A key pasted into the prompt itself is removed first, even when its shape escapes the patterns.
|
|
90
|
+
if (typeof key === "string" && key !== "") value = value.split(key).join("[secret]");
|
|
91
|
+
// A home path ends at the next separator or punctuation; a trailing dot stays outside it.
|
|
92
|
+
value = value
|
|
93
|
+
.replace(/\/(?:Users|home)\/[^/\\\s,;:!?'"`()<>[\]{}]*[^/\\\s,;:!?'"`()<>[\]{}.]/gu, "~")
|
|
94
|
+
.replace(/[A-Za-z]:\\Users\\[^/\\\s,;:!?'"`()<>[\]{}]*[^/\\\s,;:!?'"`()<>[\]{}.]/gu, "~");
|
|
95
|
+
value = value.replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}/gu, "[email]");
|
|
96
|
+
for (const pattern of TOKEN_PATTERNS) value = value.replace(pattern, "[secret]");
|
|
97
|
+
const characters = Array.from(value);
|
|
98
|
+
if (characters.length <= JEV_MAX_PROMPT_CHARS) return value;
|
|
99
|
+
return characters.slice(0, JEV_MAX_PROMPT_CHARS).join("").replace(/[A-Za-z0-9+/_=-]{8,}$/u, "[secret]");
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const frontmatterField = (frontmatter, name) => {
|
|
103
|
+
const match = new RegExp(`^${name}:[ \\t]*(.*)$`, "mu").exec(frontmatter);
|
|
104
|
+
if (!match) return "";
|
|
105
|
+
const raw = match[1].trim();
|
|
106
|
+
if (raw.startsWith('"')) {
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(raw);
|
|
109
|
+
} catch {
|
|
110
|
+
return raw.slice(1, -1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return raw.startsWith("'") && raw.endsWith("'") ? raw.slice(1, -1) : raw;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The enrolled skills the model may load itself: every canonical skill except those marked
|
|
118
|
+
* `disable-model-invocation: true`, which only a user slash command can start.
|
|
119
|
+
*/
|
|
120
|
+
export const buildJevCatalog = (pluginRoot) => {
|
|
121
|
+
const catalog = [];
|
|
122
|
+
for (const skillId of canonicalSkillIds) {
|
|
123
|
+
let content;
|
|
124
|
+
try {
|
|
125
|
+
content = readFileSync(join(pluginRoot, "skills", skillId, "SKILL.md"), "utf8");
|
|
126
|
+
} catch {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content)?.[1] ?? "";
|
|
130
|
+
if (frontmatterField(frontmatter, "disable-model-invocation") === "true") continue;
|
|
131
|
+
const description = String(frontmatterField(frontmatter, "description")).slice(0, 300);
|
|
132
|
+
if (description) catalog.push({ id: skillId, description });
|
|
133
|
+
}
|
|
134
|
+
return catalog;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const buildJevRequestBody = ({ model, state, catalog }) => ({
|
|
138
|
+
model,
|
|
139
|
+
state,
|
|
140
|
+
questions: {
|
|
141
|
+
which: {
|
|
142
|
+
type: "choice",
|
|
143
|
+
instructions: JEV_INSTRUCTIONS,
|
|
144
|
+
criteria: {
|
|
145
|
+
...Object.fromEntries(catalog.map(({ id, description }) => [id, description])),
|
|
146
|
+
none: JEV_NONE_CRITERION,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/** Validates an untrusted response. Returns the accepted choice ID, "none", or a failure. */
|
|
153
|
+
export const parseJevResponse = ({ status, text, catalogIds, minConfidence }) => {
|
|
154
|
+
if (status !== 200) return { ok: false, reason: "http" };
|
|
155
|
+
let parsed;
|
|
156
|
+
try {
|
|
157
|
+
parsed = JSON.parse(text);
|
|
158
|
+
} catch {
|
|
159
|
+
return { ok: false, reason: "invalid-response" };
|
|
160
|
+
}
|
|
161
|
+
const answer = parsed?.answers?.which;
|
|
162
|
+
const choice = answer?.choice;
|
|
163
|
+
if (typeof choice !== "string" || (choice !== "none" && !catalogIds.includes(choice))) {
|
|
164
|
+
return { ok: false, reason: "invalid-response" };
|
|
165
|
+
}
|
|
166
|
+
const confidence = answer.confidence;
|
|
167
|
+
if (typeof confidence !== "number" || !Number.isFinite(confidence)) return { ok: false, reason: "invalid-response" };
|
|
168
|
+
return { ok: true, choice, confidence, accepted: choice !== "none" && confidence >= minConfidence };
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const readBounded = async (response) => {
|
|
172
|
+
const reader = response.body?.getReader?.();
|
|
173
|
+
if (!reader) {
|
|
174
|
+
const text = await response.text();
|
|
175
|
+
return Buffer.byteLength(text, "utf8") > JEV_MAX_RESPONSE_BYTES ? null : text;
|
|
176
|
+
}
|
|
177
|
+
const chunks = [];
|
|
178
|
+
let size = 0;
|
|
179
|
+
for (;;) {
|
|
180
|
+
const { done, value } = await reader.read();
|
|
181
|
+
if (done) break;
|
|
182
|
+
size += value.byteLength;
|
|
183
|
+
if (size > JEV_MAX_RESPONSE_BYTES) {
|
|
184
|
+
await reader.cancel().catch(() => {});
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
chunks.push(Buffer.from(value));
|
|
188
|
+
}
|
|
189
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/** One POST, no retry. Resolves to { status, text } or { reason }; never throws, never rejects. */
|
|
193
|
+
const postOnce = async ({ fetchImpl, key, body, timeoutMs }) => {
|
|
194
|
+
const controller = new AbortController();
|
|
195
|
+
let timer;
|
|
196
|
+
const timeout = new Promise((resolveTimeout) => {
|
|
197
|
+
timer = setTimeout(() => {
|
|
198
|
+
controller.abort();
|
|
199
|
+
resolveTimeout({ reason: "timeout" });
|
|
200
|
+
}, timeoutMs);
|
|
201
|
+
});
|
|
202
|
+
const request = (async () => {
|
|
203
|
+
try {
|
|
204
|
+
const response = await fetchImpl(JEV_ENDPOINT, {
|
|
205
|
+
method: "POST",
|
|
206
|
+
headers: { authorization: `Bearer ${key}`, "content-type": "application/json" },
|
|
207
|
+
body,
|
|
208
|
+
redirect: "error",
|
|
209
|
+
signal: controller.signal,
|
|
210
|
+
});
|
|
211
|
+
const status = response.status;
|
|
212
|
+
if (status !== 200) {
|
|
213
|
+
// An unread body would hold the connection open; release it before reporting.
|
|
214
|
+
await response.body?.cancel?.().catch(() => {});
|
|
215
|
+
return { status, text: "" };
|
|
216
|
+
}
|
|
217
|
+
const text = await readBounded(response);
|
|
218
|
+
return text === null ? { status, reason: "invalid-response" } : { status, text };
|
|
219
|
+
} catch {
|
|
220
|
+
return { reason: controller.signal.aborted ? "timeout" : "network" };
|
|
221
|
+
}
|
|
222
|
+
})();
|
|
223
|
+
try {
|
|
224
|
+
return await Promise.race([request, timeout]);
|
|
225
|
+
} finally {
|
|
226
|
+
clearTimeout(timer);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const safeSessionId = (sessionId) => {
|
|
231
|
+
const cleaned = typeof sessionId === "string" ? sessionId.replace(/[^A-Za-z0-9_-]/gu, "").slice(0, 64) : "";
|
|
232
|
+
return cleaned || "unknown";
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const jevStateDirectory = (stateRoot) => join(stateRoot, ".litclaude", "jev");
|
|
236
|
+
|
|
237
|
+
// Opening with O_NOFOLLOW refuses a symlink planted at a state or trace path, so a write never
|
|
238
|
+
// lands outside the state folder. Where the platform lacks the flag, lstat refuses it instead.
|
|
239
|
+
const NO_FOLLOW = constants.O_NOFOLLOW ?? 0;
|
|
240
|
+
const refuseSymlink = (path) => {
|
|
241
|
+
if (NO_FOLLOW) return;
|
|
242
|
+
try {
|
|
243
|
+
if (lstatSync(path).isSymbolicLink()) throw new Error("symlink");
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (error?.code !== "ENOENT") throw error;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// The last hinted skill and its latency, kept for the HUD. Only a catalog ID and a whole
|
|
250
|
+
// number of milliseconds survive a read, so the status line never echoes anything else.
|
|
251
|
+
const validLast = (value) => (
|
|
252
|
+
typeof value?.skill === "string" && canonicalSkillIds.includes(value.skill)
|
|
253
|
+
&& Number.isSafeInteger(value.latency_ms) && value.latency_ms >= 0
|
|
254
|
+
? { skill: value.skill, latency_ms: value.latency_ms }
|
|
255
|
+
: null
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const readSession = (stateRoot, sessionId) => {
|
|
259
|
+
const empty = { calls: 0, noted: false, banner: false, last: null };
|
|
260
|
+
try {
|
|
261
|
+
const path = join(jevStateDirectory(stateRoot), `session-${safeSessionId(sessionId)}.json`);
|
|
262
|
+
if (lstatSync(path).isSymbolicLink()) return empty;
|
|
263
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
264
|
+
return {
|
|
265
|
+
calls: Number.isSafeInteger(parsed?.calls) && parsed.calls >= 0 ? parsed.calls : 0,
|
|
266
|
+
noted: parsed?.noted === true,
|
|
267
|
+
banner: parsed?.banner === true,
|
|
268
|
+
last: validLast(parsed?.last),
|
|
269
|
+
};
|
|
270
|
+
} catch {
|
|
271
|
+
return empty;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const writeSession = (stateRoot, sessionId, session) => {
|
|
276
|
+
try {
|
|
277
|
+
const directory = jevStateDirectory(stateRoot);
|
|
278
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
279
|
+
const target = join(directory, `session-${safeSessionId(sessionId)}.json`);
|
|
280
|
+
const temporary = `${target}.${process.pid}.tmp`;
|
|
281
|
+
refuseSymlink(temporary);
|
|
282
|
+
writeFileSync(temporary, JSON.stringify(session), {
|
|
283
|
+
mode: 0o600,
|
|
284
|
+
flag: constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | NO_FOLLOW,
|
|
285
|
+
});
|
|
286
|
+
renameSync(temporary, target);
|
|
287
|
+
return true;
|
|
288
|
+
} catch {
|
|
289
|
+
// Session bookkeeping is best-effort; an unwritable state folder never alters the turn.
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const writeTrace = (stateRoot, record) => {
|
|
295
|
+
try {
|
|
296
|
+
const directory = jevStateDirectory(stateRoot);
|
|
297
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
298
|
+
const target = join(directory, "trace.jsonl");
|
|
299
|
+
refuseSymlink(target);
|
|
300
|
+
const fd = openSync(target, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | NO_FOLLOW, 0o600);
|
|
301
|
+
try {
|
|
302
|
+
writeSync(fd, `${JSON.stringify(record)}\n`);
|
|
303
|
+
} finally {
|
|
304
|
+
closeSync(fd);
|
|
305
|
+
}
|
|
306
|
+
} catch {
|
|
307
|
+
// The trace is an opt-in debug aid; failing to write it never alters the turn.
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Called by the prompt hook at the start of every turn while the flag is on, so the HUD shows a
|
|
313
|
+
* skill only for the turn that was hinted. Touches nothing when there is no hint to clear.
|
|
314
|
+
*/
|
|
315
|
+
export const clearJevTurn = (stateRoot, sessionId) => {
|
|
316
|
+
const session = readSession(stateRoot, sessionId);
|
|
317
|
+
if (session.last) writeSession(stateRoot, sessionId, { ...session, last: null });
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export const JEV_BANNER = "✦ Jev skill hint ON ✦";
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* True exactly once per session, on the first turn with both switches on. The "shown" mark is
|
|
324
|
+
* written before the caller emits the banner; when it cannot be written, no banner is shown,
|
|
325
|
+
* so an unwritable state folder never repeats it.
|
|
326
|
+
*/
|
|
327
|
+
export const claimJevBanner = ({ env = process.env, stateRoot, sessionId } = {}) => {
|
|
328
|
+
if (env[JEV_FLAG] !== "1" || !hasKey(env) || !stateRoot) return false;
|
|
329
|
+
const session = readSession(stateRoot, sessionId);
|
|
330
|
+
if (session.banner) return false;
|
|
331
|
+
return writeSession(stateRoot, sessionId, { ...session, banner: true });
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* What the HUD may show: null when the flag is off, otherwise the key's presence and this
|
|
336
|
+
* turn's hint. It reports whether a key exists, never the key or its length.
|
|
337
|
+
*/
|
|
338
|
+
export const jevHudState = ({ env = process.env, stateRoot, sessionId } = {}) => {
|
|
339
|
+
if (env[JEV_FLAG] !== "1") return null;
|
|
340
|
+
if (!hasKey(env)) return { keyMissing: true, last: null };
|
|
341
|
+
return { keyMissing: false, last: stateRoot ? readSession(stateRoot, sessionId).last : null };
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export const formatJevLatency = (latencyMs) => `${(latencyMs / 1000).toFixed(2)}s`;
|
|
345
|
+
|
|
346
|
+
/** Host-side eligibility that needs no router: a leading command character or too little text. */
|
|
347
|
+
export const isJevEligibleText = (text) => {
|
|
348
|
+
if (typeof text !== "string") return false;
|
|
349
|
+
const trimmed = text.trimStart();
|
|
350
|
+
if (/^[/!]/u.test(trimmed) || /<command-name>/u.test(text)) return false;
|
|
351
|
+
return text.replace(/\s/gu, "").length >= 4;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Runs the hint for one turn. `eligible` is the hook's own verdict (not routed, not a slash
|
|
356
|
+
* command). Returns { hint, note }: each is a fixed sentence or null, and neither ever carries
|
|
357
|
+
* response text. Never throws.
|
|
358
|
+
*/
|
|
359
|
+
export const suggestJevSkill = async ({
|
|
360
|
+
env = process.env,
|
|
361
|
+
prompt,
|
|
362
|
+
eligible = true,
|
|
363
|
+
sessionId,
|
|
364
|
+
stateRoot,
|
|
365
|
+
pluginRoot,
|
|
366
|
+
fetchImpl = globalThis.fetch,
|
|
367
|
+
now = () => Date.now(),
|
|
368
|
+
}) => {
|
|
369
|
+
const quiet = { hint: null, note: null };
|
|
370
|
+
if (env[JEV_FLAG] !== "1") return quiet;
|
|
371
|
+
if (!eligible || !isJevEligibleText(prompt)) return quiet;
|
|
372
|
+
const settings = jevSettings(env);
|
|
373
|
+
const session = readSession(stateRoot, sessionId);
|
|
374
|
+
const state = redactPromptForJev(prompt, hasKey(env) ? env[KEY_ENV] : undefined);
|
|
375
|
+
const started = now();
|
|
376
|
+
let result = { choice: null, confidence: null, status: null, reason: null };
|
|
377
|
+
const fail = (reason) => {
|
|
378
|
+
result = { ...result, reason };
|
|
379
|
+
return reason;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
let hint = null;
|
|
383
|
+
let hinted = null;
|
|
384
|
+
let failure = null;
|
|
385
|
+
if (!hasKey(env)) {
|
|
386
|
+
failure = fail("key-missing");
|
|
387
|
+
} else if (session.calls >= settings.maxCalls) {
|
|
388
|
+
failure = fail("cap-reached");
|
|
389
|
+
} else {
|
|
390
|
+
const catalog = buildJevCatalog(pluginRoot);
|
|
391
|
+
const body = JSON.stringify(buildJevRequestBody({ model: settings.model, state, catalog }));
|
|
392
|
+
if (Buffer.byteLength(body, "utf8") > JEV_MAX_REQUEST_BYTES) {
|
|
393
|
+
failure = fail("request-too-large");
|
|
394
|
+
} else {
|
|
395
|
+
// Fail closed: the call is counted on disk before it is made, and an uncountable call is
|
|
396
|
+
// never made, so an unwritable state folder cannot lift the per-session cap.
|
|
397
|
+
session.calls += 1;
|
|
398
|
+
if (!writeSession(stateRoot, sessionId, session)) return quiet;
|
|
399
|
+
const response = typeof fetchImpl === "function"
|
|
400
|
+
? await postOnce({ fetchImpl, key: env[KEY_ENV], body, timeoutMs: settings.timeoutMs })
|
|
401
|
+
: { reason: "network" };
|
|
402
|
+
result.status = response.status ?? null;
|
|
403
|
+
if (response.reason) {
|
|
404
|
+
failure = fail(response.reason);
|
|
405
|
+
} else {
|
|
406
|
+
const parsed = parseJevResponse({
|
|
407
|
+
status: response.status,
|
|
408
|
+
text: response.text,
|
|
409
|
+
catalogIds: catalog.map(({ id }) => id),
|
|
410
|
+
minConfidence: settings.minConfidence,
|
|
411
|
+
});
|
|
412
|
+
if (!parsed.ok) {
|
|
413
|
+
failure = fail(parsed.reason);
|
|
414
|
+
} else {
|
|
415
|
+
result = { ...result, choice: parsed.choice, confidence: parsed.confidence };
|
|
416
|
+
if (parsed.accepted) {
|
|
417
|
+
hint = jevHintLine(parsed.choice);
|
|
418
|
+
hinted = parsed.choice;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const latencyMs = Math.max(0, Math.round(now() - started));
|
|
426
|
+
let note = null;
|
|
427
|
+
if (failure && !session.noted) {
|
|
428
|
+
session.noted = true;
|
|
429
|
+
note = jevFallbackNote(failure);
|
|
430
|
+
}
|
|
431
|
+
session.last = hinted ? { skill: hinted, latency_ms: latencyMs } : null;
|
|
432
|
+
writeSession(stateRoot, sessionId, session);
|
|
433
|
+
if (settings.trace) {
|
|
434
|
+
writeTrace(stateRoot, {
|
|
435
|
+
ts: new Date(started).toISOString(),
|
|
436
|
+
prompt_sha256: createHash("sha256").update(state).digest("hex"),
|
|
437
|
+
choice: result.choice,
|
|
438
|
+
confidence: result.confidence,
|
|
439
|
+
latency_ms: latencyMs,
|
|
440
|
+
http_status: result.status,
|
|
441
|
+
fallback: result.reason,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
return { hint, note };
|
|
445
|
+
};
|