create-yss-spec 3.5.2 → 3.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/template/asset-runtime.js +3 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/codebase-design/SKILL.md +4 -0
- package/template/{.codex/skills/improve-codebase-architecture/SKILL.md → .agents/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.agents/skills/frontend-commit/SKILL.md +4 -93
- package/template/.agents/skills/git-commit-core/SKILL.md +18 -0
- package/template/.agents/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.agents/skills/llm-wiki/SKILL.md +12 -13
- package/template/.agents/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.agents/skills/llm-wiki/references/compile.md +21 -114
- package/template/.agents/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.agents/skills/llm-wiki/references/lint.md +9 -46
- package/template/.agents/skills/llm-wiki/references/query.md +9 -18
- package/template/.agents/skills/llm-wiki/references/schema.md +56 -29
- package/template/.agents/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.agents/skills/llm-wiki/references/writing.md +4 -4
- package/template/.agents/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.agents/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.agents/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.agents/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.agents/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.agents/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.agents/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.agents/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.agents/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.agents/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.agents/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.agents/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.agents/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.agents/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.agents/skills/prototype/LOGIC.md +1 -1
- package/template/.agents/skills/prototype/SKILL.md +5 -19
- package/template/.agents/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.agents/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.agents/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.agents/skills/yss-research/SKILL.md +4 -0
- package/template/.codex/skills/codebase-design/SKILL.md +4 -0
- package/template/{.pi/skills/improve-codebase-architecture/SKILL.md → .codex/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.codex/skills/frontend-commit/SKILL.md +4 -93
- package/template/.codex/skills/git-commit-core/SKILL.md +18 -0
- package/template/.codex/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.codex/skills/llm-wiki/SKILL.md +12 -13
- package/template/.codex/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.codex/skills/llm-wiki/references/compile.md +21 -114
- package/template/.codex/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.codex/skills/llm-wiki/references/lint.md +9 -46
- package/template/.codex/skills/llm-wiki/references/query.md +9 -18
- package/template/.codex/skills/llm-wiki/references/schema.md +56 -29
- package/template/.codex/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.codex/skills/llm-wiki/references/writing.md +4 -4
- package/template/.codex/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.codex/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.codex/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.codex/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.codex/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.codex/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.codex/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.codex/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.codex/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.codex/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.codex/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.codex/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.codex/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.codex/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.codex/skills/prototype/LOGIC.md +1 -1
- package/template/.codex/skills/prototype/SKILL.md +5 -19
- package/template/.codex/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.codex/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.codex/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.codex/skills/yss-research/SKILL.md +4 -0
- package/template/.cursor/skills/codebase-design/SKILL.md +4 -0
- package/template/.cursor/skills/{improve-codebase-architecture/SKILL.md → codebase-design/references/architecture-audit.md} +3 -9
- package/template/.cursor/skills/frontend-commit/SKILL.md +4 -93
- package/template/.cursor/skills/git-commit-core/SKILL.md +18 -0
- package/template/.cursor/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.cursor/skills/llm-wiki/SKILL.md +12 -13
- package/template/.cursor/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.cursor/skills/llm-wiki/references/compile.md +21 -114
- package/template/.cursor/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.cursor/skills/llm-wiki/references/lint.md +9 -46
- package/template/.cursor/skills/llm-wiki/references/query.md +9 -18
- package/template/.cursor/skills/llm-wiki/references/schema.md +56 -29
- package/template/.cursor/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.cursor/skills/llm-wiki/references/writing.md +4 -4
- package/template/.cursor/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.cursor/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.cursor/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.cursor/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.cursor/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.cursor/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.cursor/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.cursor/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.cursor/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.cursor/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.cursor/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.cursor/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.cursor/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.cursor/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.cursor/skills/prototype/LOGIC.md +1 -1
- package/template/.cursor/skills/prototype/SKILL.md +5 -19
- package/template/.cursor/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.cursor/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.cursor/skills/yss-research/SKILL.md +4 -0
- package/template/.pi/skills/codebase-design/SKILL.md +4 -0
- package/template/{.agents/skills/improve-codebase-architecture/SKILL.md → .pi/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.pi/skills/frontend-commit/SKILL.md +4 -93
- package/template/.pi/skills/git-commit-core/SKILL.md +18 -0
- package/template/.pi/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.pi/skills/llm-wiki/SKILL.md +12 -13
- package/template/.pi/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.pi/skills/llm-wiki/references/compile.md +21 -114
- package/template/.pi/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.pi/skills/llm-wiki/references/lint.md +9 -46
- package/template/.pi/skills/llm-wiki/references/query.md +9 -18
- package/template/.pi/skills/llm-wiki/references/schema.md +56 -29
- package/template/.pi/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.pi/skills/llm-wiki/references/writing.md +4 -4
- package/template/.pi/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.pi/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.pi/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.pi/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.pi/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.pi/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.pi/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.pi/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.pi/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.pi/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.pi/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.pi/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.pi/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.pi/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.pi/skills/prototype/LOGIC.md +1 -1
- package/template/.pi/skills/prototype/SKILL.md +5 -19
- package/template/.pi/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.pi/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.pi/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.pi/skills/yss-research/SKILL.md +4 -0
- package/template/.template-spec/agents/README.md +1 -1
- package/template/.template-spec/agents/digital-human-roles.yaml +1 -1
- package/template/.template-spec/agents/skill-migrations.md +15 -0
- package/template/.template-spec/agents/yss-skill-registry.yaml +10 -29
- package/template/.template-spec/architecture/README.md +3 -34
- package/template/.template-spec/plan/templates/competitive-analysis-template.md +2 -2
- package/template/.template-spec/process/contract-reading.md +24 -0
- package/template/.template-spec/process/lifecycle-registry-baseline.json +3 -1
- package/template/.template-spec/process/lifecycle-registry.yaml +6 -0
- package/template/.template-spec/process/research-completion.md +23 -0
- package/template/.template-spec/process/schemas/digital-human-task-package.schema.json +202 -12
- package/template/.template-spec/process/schemas/frontend-implementation-evidence.schema.json +7 -15
- package/template/.template-spec/process/subagent-collaboration.md +8 -0
- package/template/.template-spec/process/templates/frontend-implementation-verification-template.yaml +15 -1
- package/template/AGENTS.md +1 -1
- package/template/CONTEXT.md +5 -1
- package/template/README.md +12 -24
- package/template/scripts/contract +5 -5
- package/template/scripts/lib/contract-views.mjs +57 -2
- package/template/scripts/lib/execution-evidence.mjs +51 -0
- package/template/scripts/lib/harness-execution-scope.mjs +1 -1
- package/template/scripts/lib/implementation-contract-compiler.mjs +2 -0
- package/template/scripts/lib/lifecycle-context-query.mjs +15 -3
- package/template/scripts/lib/lifecycle-status.mjs +32 -6
- package/template/scripts/lib/lifecycle-transition.mjs +19 -1
- package/template/scripts/lib/maintenance-research.mjs +63 -0
- package/template/scripts/lib/read-only-intake.mjs +132 -0
- package/template/scripts/lib/skill-registry.mjs +2 -1
- package/template/scripts/lib/skill-supply-chain.mjs +4 -0
- package/template/scripts/lib/slice-task-package.mjs +1 -1
- package/template/scripts/lib/task-package.mjs +9 -2
- package/template/scripts/lifecycle-status +2 -2
- package/template/scripts/prepare-read-only-intake +16 -0
- package/template/scripts/run-read-only-intake +14 -0
- package/template/scripts/verify-digital-human-task-package +2 -2
- package/template/scripts/verify-frontend-implementation-evidence +24 -1
- package/template/scripts/verify-maintenance-research +13 -0
- package/template/skills-lock.json +19 -76
- package/template.manifest.json +118 -29
- package/template.snapshot.json +5 -6
- package/template/.agents/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.agents/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.agents/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.agents/skills/prototype/UI.md +0 -112
- package/template/.agents/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.agents/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.agents/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.agents/skills/wait-what/SKILL.md +0 -7
- package/template/.agents/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.codex/skills/data-analytics/.app.json +0 -84
- package/template/.codex/skills/data-analytics/.codex-plugin/plugin.json +0 -66
- package/template/.codex/skills/data-analytics/.mcp.json +0 -30
- package/template/.codex/skills/data-analytics/AGENTS.md +0 -20
- package/template/.codex/skills/data-analytics/DEPENDENCIES.MD +0 -27
- package/template/.codex/skills/data-analytics/README.md +0 -60
- package/template/.codex/skills/data-analytics/__yss_dotfile__.gitignore +0 -2
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part005 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part006 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part005 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part006 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part007 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-small.svg +0 -5
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience.png +0 -0
- package/template/.codex/skills/data-analytics/assets/datascience.svg +0 -10
- package/template/.codex/skills/data-analytics/mcp/server.cjs +0 -2964
- package/template/.codex/skills/data-analytics/package-lock.json +0 -3048
- package/template/.codex/skills/data-analytics/package.json +0 -43
- package/template/.codex/skills/data-analytics/scripts/normalize-widget-assets.mjs +0 -75
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +0 -137
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/references/quality-checks.md +0 -29
- package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +0 -148
- package/template/.codex/skills/data-analytics/skills/build-dashboard/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/bi-platform-dashboard.md +0 -18
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/html-dashboard.md +0 -24
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/mcp-artifact-dashboard.md +0 -71
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/streamlit-dashboard.md +0 -85
- package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +0 -207
- package/template/.codex/skills/data-analytics/skills/build-report/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/assets/executive-report-shell.html +0 -70
- package/template/.codex/skills/data-analytics/skills/build-report/assets/technical-report-shell.html +0 -66
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/SKILL.md +0 -108
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/__init__.py +0 -1
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/cli.py +0 -52
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/constants.py +0 -61
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/docx_writer.py +0 -362
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/html_parser.py +0 -829
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/model.py +0 -30
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/plan.py +0 -127
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/quality.py +0 -374
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/rendering.py +0 -613
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/table_utils.py +0 -54
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/utils.py +0 -16
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc_plan.py +0 -9
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/tests/test_delivery_plan.py +0 -45
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/SKILL.md +0 -77
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/scripts/report_to_google_slides.py +0 -2379
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/SKILL.md +0 -88
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/executive-report.md +0 -97
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/mcp-app-report.md +0 -59
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/technical-report.md +0 -75
- package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +0 -103
- package/template/.codex/skills/data-analytics/skills/design-kpis/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +0 -68
- package/template/.codex/skills/data-analytics/skills/gather-business-context/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/index/SKILL.md +0 -251
- package/template/.codex/skills/data-analytics/skills/index/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +0 -131
- package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +0 -141
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/references/report-templates.md +0 -32
- package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +0 -106
- package/template/.codex/skills/data-analytics/skills/market-sizing/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +0 -130
- package/template/.codex/skills/data-analytics/skills/metric-diagnostics/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +0 -141
- package/template/.codex/skills/data-analytics/skills/product-business-analysis/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +0 -178
- package/template/.codex/skills/data-analytics/skills/spreadsheets/agents/openai.yaml +0 -9
- package/template/.codex/skills/data-analytics/skills/spreadsheets/assets/file-spreadsheet.png +0 -0
- package/template/.codex/skills/data-analytics/skills/spreadsheets/charts.md +0 -31
- package/template/.codex/skills/data-analytics/skills/spreadsheets/references/artifact_tool_api.md +0 -466
- package/template/.codex/skills/data-analytics/skills/spreadsheets/style_guidelines.md +0 -99
- package/template/.codex/skills/data-analytics/skills/user-context/SKILL.md +0 -197
- package/template/.codex/skills/data-analytics/skills/user-context/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/automation-config.md +0 -26
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/source-category-config.json +0 -51
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/user-context-config.md +0 -66
- package/template/.codex/skills/data-analytics/skills/user-context/references/automation.md +0 -69
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-examples.md +0 -204
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-state-template.json +0 -87
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding.md +0 -497
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/connector-playbook.md +0 -74
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/setup.md +0 -65
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/skill-template.md +0 -160
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/source-intake.md +0 -75
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/weekly-polling-automation.md +0 -96
- package/template/.codex/skills/data-analytics/skills/user-context/references/source-category-runtime.md +0 -263
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/data_analytics_preflight.py +0 -1462
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/init_user_context_state.py +0 -128
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/reset_user_context_state.py +0 -101
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/validate_user_context_preflight.py +0 -499
- package/template/.codex/skills/data-analytics/skills/user-context/tests/test_state_helpers.py +0 -978
- package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +0 -126
- package/template/.codex/skills/data-analytics/skills/validate-data/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/validate-data/references/validation-methods.md +0 -70
- package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +0 -157
- package/template/.codex/skills/data-analytics/skills/visualize-data/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md +0 -774
- package/template/.codex/skills/data-analytics/src/DESIGN.md +0 -222
- package/template/.codex/skills/data-analytics/src/analytics-app/App.tsx +0 -3666
- package/template/.codex/skills/data-analytics/src/analytics-app/analytics-layout.test.mjs +0 -136
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartFrame.tsx +0 -54
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartLegend.tsx +0 -96
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartRenderer.tsx +0 -1647
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartTooltip.tsx +0 -245
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-app-helpers.tsx +0 -462
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-capabilities.ts +0 -107
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-compatibility.ts +0 -164
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-contract.ts +0 -192
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-theme.ts +0 -203
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-tokens.css +0 -619
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-transforms.ts +0 -402
- package/template/.codex/skills/data-analytics/src/analytics-app/fonts/SystemSansVariableVF.woff2 +0 -0
- package/template/.codex/skills/data-analytics/src/analytics-app/imageExport.ts +0 -370
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/AnalyticsLayoutCanvas.tsx +0 -536
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/RichMarkdown.tsx +0 -681
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/analyticsLayoutCore.ts +0 -164
- package/template/.codex/skills/data-analytics/src/analytics-app/main.tsx +0 -21
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/chart_contract.py +0 -472
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/check_analytics_app_runtime_links.py +0 -75
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/design_contract.py +0 -142
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/package_utils.py +0 -142
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/tests/test_package_utils.py +0 -377
- package/template/.codex/skills/data-analytics/src/analytics-app/styles.css +0 -3468
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.d.ts +0 -44
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.jsx +0 -639
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/data-table.css +0 -327
- package/template/.codex/skills/data-analytics/src/analytics-app/tokens.css +0 -225
- package/template/.codex/skills/data-analytics/src/analytics-app/types.ts +0 -204
- package/template/.codex/skills/data-analytics/src/analytics-app-core.md +0 -85
- package/template/.codex/skills/data-analytics/src/codex-style-contract.md +0 -30
- package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.html +0 -12
- package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.jsx +0 -1008
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.css +0 -2117
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.html +0 -122
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.js +0 -3588
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.css +0 -483
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.html +0 -32
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.js +0 -333
- package/template/.codex/skills/data-analytics/src/mcp-host.js +0 -153
- package/template/.codex/skills/data-analytics/src/recharts-config.js +0 -315
- package/template/.codex/skills/data-analytics/src/recharts-renderer.jsx +0 -294
- package/template/.codex/skills/data-analytics/src/sql-source-view.css +0 -33
- package/template/.codex/skills/data-analytics/src/sql-source-view.js +0 -157
- package/template/.codex/skills/data-analytics/src/styles/codex-theme.css +0 -121
- package/template/.codex/skills/data-analytics/src/table-renderer.jsx +0 -28
- package/template/.codex/skills/data-analytics/tests/chart-transforms.test.mjs +0 -87
- package/template/.codex/skills/data-analytics/tests/funnel-smoke.html +0 -105
- package/template/.codex/skills/data-analytics/tests/inline-widget-compare.html +0 -233
- package/template/.codex/skills/data-analytics/tests/mcp-server.test.mjs +0 -1500
- package/template/.codex/skills/data-analytics/tests/native-style-contract.test.mjs +0 -219
- package/template/.codex/skills/data-analytics/tests/recharts-config.test.mjs +0 -144
- package/template/.codex/skills/data-analytics/tests/recharts-renderer.test.mjs +0 -11
- package/template/.codex/skills/data-analytics/tests/rich-markdown.test.mjs +0 -54
- package/template/.codex/skills/data-analytics/tests/widget-render-harness.html +0 -321
- package/template/.codex/skills/data-analytics/tsconfig.json +0 -19
- package/template/.codex/skills/data-analytics/vite.config.ts +0 -46
- package/template/.codex/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.codex/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.codex/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.codex/skills/prototype/UI.md +0 -112
- package/template/.codex/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.codex/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.codex/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.codex/skills/wait-what/SKILL.md +0 -7
- package/template/.codex/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.cursor/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.cursor/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.cursor/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.cursor/skills/prototype/UI.md +0 -112
- package/template/.cursor/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.cursor/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.cursor/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.cursor/skills/wait-what/SKILL.md +0 -7
- package/template/.cursor/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.pi/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.pi/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.pi/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.pi/skills/prototype/UI.md +0 -112
- package/template/.pi/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.pi/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.pi/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.pi/skills/wait-what/SKILL.md +0 -7
- package/template/.pi/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.template-spec/agents/domain.md +0 -31
- /package/template/.agents/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.codex/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.cursor/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.pi/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md
DELETED
|
@@ -1,774 +0,0 @@
|
|
|
1
|
-
# Seaborn Templates
|
|
2
|
-
|
|
3
|
-
Use this when implementing static charts in Python. Seaborn owns marks;
|
|
4
|
-
Matplotlib owns layout, axes, annotations, and export.
|
|
5
|
-
|
|
6
|
-
## How To Use This File
|
|
7
|
-
|
|
8
|
-
1. Choose the family from `../SKILL.md` `Chart Selection`.
|
|
9
|
-
2. Pick the lightest variant below that answers the question.
|
|
10
|
-
3. Apply shared style before chart-specific tweaks.
|
|
11
|
-
4. Export SVG and PNG.
|
|
12
|
-
5. Inspect in the final notebook, report, dashboard, or slide.
|
|
13
|
-
|
|
14
|
-
## Canonical Family Map
|
|
15
|
-
|
|
16
|
-
- `Tables & Scorecards`: HTML layer, not Seaborn.
|
|
17
|
-
- `Trend`: Trend Line, Highlighted Multi-Series Trend, Stacked Area,
|
|
18
|
-
Overlapping Area, Small Multiples.
|
|
19
|
-
- `Comparison & Ranking`: Grouped Column Bars, Ranked Horizontal Bars,
|
|
20
|
-
Diverging Horizontal Bars, Dot Reference Comparison, Concentration / Pareto.
|
|
21
|
-
- `Composition`: Stacked Horizontal Bars, Pie Chart.
|
|
22
|
-
- `Distribution`: Histogram / KDE, Grouped Distribution Comparison.
|
|
23
|
-
- `Relationship`: Scatter, Bubble Chart, Scatter / Density.
|
|
24
|
-
- `Uncertainty & Benchmark`: Ordered Line & Dot, Faceted Dot & Interval,
|
|
25
|
-
Experiment Lift With Confidence Intervals.
|
|
26
|
-
- `Matrix & Cohort`: Heatmap.
|
|
27
|
-
- `Decomposition & Progression`: Funnel Stage Bars, Waterfall Bridge.
|
|
28
|
-
|
|
29
|
-
## Shared Style Guidance
|
|
30
|
-
|
|
31
|
-
Use this section for every chart. The recipes name form; this section owns visual decisions.
|
|
32
|
-
|
|
33
|
-
### Build Sequence
|
|
34
|
-
|
|
35
|
-
Use this order:
|
|
36
|
-
|
|
37
|
-
1. `Format`: family and delivery surface.
|
|
38
|
-
2. `Structure`: title, subtitle, axes, labels, annotations, removals.
|
|
39
|
-
3. `Colors`: smallest readable set of palette roots.
|
|
40
|
-
|
|
41
|
-
If the chart feels busy, revisit `Format` or `Structure`; do not add colors,
|
|
42
|
-
heavier strokes, or extra decoration.
|
|
43
|
-
|
|
44
|
-
### Palette
|
|
45
|
-
|
|
46
|
-
Choose a palette policy before plotting. Use only approved roots, explicit maps, neutrals, and shades. Never use default categorical colors for shipped charts.
|
|
47
|
-
|
|
48
|
-
Policy classes:
|
|
49
|
-
|
|
50
|
-
- `Single-root preferred`: one non-neutral root plus shades and neutrals. Use for simple trends, ranks, distributions, relationships,
|
|
51
|
-
heatmaps, intervals, experiment lift, and comparable small multiples.
|
|
52
|
-
- `Hard two-root cap`: at most two non-neutral roots plus neutrals. Use for binary, signed, focal-vs-context, benchmark, Pareto, overlapping area,
|
|
53
|
-
highlighted trend, ordered line-dot, and waterfall charts.
|
|
54
|
-
- `Relaxed multi-category`: up to five approved roots when category identity matters. Use for pie, stacked bars/area, grouped bars, and stage bars.
|
|
55
|
-
With more than five categories, group to top-N plus Other or change form.
|
|
56
|
-
|
|
57
|
-
Shades and neutral comparator fills do not count as roots. Separate series with tone, open fill, marker fill, line style, direct labels, ordering, or faceting.
|
|
58
|
-
Do not ship visually identical fills for adjacent or overlapping marks.
|
|
59
|
-
Use each selected root's `base` tone, the middle swatch of the five-color row,
|
|
60
|
-
as the default non-neutral mark color for shipped charts. Use `dark` for keylines, outlines, labels, or reference strokes; use `light`, `xlight`, or `open` for supporting fills.
|
|
61
|
-
|
|
62
|
-
| Family | XLight | Light | Base | Mid | Dark |
|
|
63
|
-
|---|---|---|---|---|---|
|
|
64
|
-
| Blue | `#EAF1FE` | `#CEDFFE` | `#A3BEFA` | `#5477C4` | `#2E4780` |
|
|
65
|
-
| Gold | `#FFF4C2` | `#FFEA8F` | `#FFE15B` | `#B8A037` | `#736422` |
|
|
66
|
-
| Orange | `#FFEDDE` | `#FFBDA1` | `#F0986E` | `#CC6F47` | `#804126` |
|
|
67
|
-
| Olive | `#D8ECBD` | `#BEEB96` | `#A3D576` | `#71B436` | `#386411` |
|
|
68
|
-
| Pink | `#FCDAD6` | `#F5BACC` | `#F390CA` | `#BD569B` | `#8A3A6F` |
|
|
69
|
-
|
|
70
|
-
- Use `Blue` for general product or KPI charts.
|
|
71
|
-
- Use `Gold` for model/eval examples with no subject color.
|
|
72
|
-
- Use `Orange`, `Olive`, or `Pink` when the subject or report points there.
|
|
73
|
-
- Calls with `hue`, grouped marks, multiple lines, `stackplot`, `pie`, grouped distributions, or colormaps must pass explicit palette/color maps.
|
|
74
|
-
- Prefer `base` for primary fills, lines, dots, and legend swatches. Treat `mid` as an exception for cases that need extra contrast.
|
|
75
|
-
- For positive/negative states, use dark vs open/light fills, signed labels,
|
|
76
|
-
and zero-line context; use green/red only for documented domain semantics.
|
|
77
|
-
|
|
78
|
-
### Semantic Tokens
|
|
79
|
-
|
|
80
|
-
| Token | Value | Use |
|
|
81
|
-
|---|---:|---|
|
|
82
|
-
| `surface` | `#FCFCFD` | page or figure background |
|
|
83
|
-
| `panel` | `#FFFFFF` | chart panel and axes background |
|
|
84
|
-
| `ink` | `#1F2430` | titles, primary labels, reference lines |
|
|
85
|
-
| `muted` | `#6F768A` | subtitles, notes, secondary ticks |
|
|
86
|
-
| `grid` | `#E6E8F0` | quiet grid lines and dotted plot areas |
|
|
87
|
-
| `axis` | `#D7DBE7` | visible left/bottom axis bars |
|
|
88
|
-
|
|
89
|
-
Use dark-neutral calibration, benchmark, reference, and ideal lines.
|
|
90
|
-
|
|
91
|
-
Neutral comparator fills:
|
|
92
|
-
|
|
93
|
-
| Token | Value | Use |
|
|
94
|
-
|---|---:|---|
|
|
95
|
-
| `neutral_xlight` | `#F4F5F7` | open comparator fills |
|
|
96
|
-
| `neutral_light` | `#E2E5EA` | secondary comparator fills |
|
|
97
|
-
| `neutral_base` | `#C5CAD3` | dense comparator fills or disabled states |
|
|
98
|
-
| `neutral_mid` | `#7A828F` | comparator outlines and labels |
|
|
99
|
-
| `neutral_dark` | `#464C55` | high-contrast comparator keylines |
|
|
100
|
-
|
|
101
|
-
### Typography And Naming
|
|
102
|
-
|
|
103
|
-
- Use a sans stack for titles, subtitles, axis titles, legends, and notes.
|
|
104
|
-
- Use a mono stack for numeric tick labels, direct value labels, benchmark labels, and compact callouts.
|
|
105
|
-
- Every shipped chart must have a visible title and subtitle.
|
|
106
|
-
- Use sentence case for short takeaway titles.
|
|
107
|
-
- Put metric scope in subtitles: unit, denominator, date range, cohort, filters,
|
|
108
|
-
confidence level, or benchmark.
|
|
109
|
-
- Use title case for short axis labels.
|
|
110
|
-
- Use sentence case for subtitles, notes, and analytical questions.
|
|
111
|
-
- Preserve model names exactly: `GPT-4o`, `o3-mini`, `o1`, `o1-mini`, `Sora`.
|
|
112
|
-
- Do not shrink type to fix layout. Widen, wrap, facet, or split.
|
|
113
|
-
|
|
114
|
-
### Labels, Legends, And Callouts
|
|
115
|
-
|
|
116
|
-
- Align title, subtitle, and top legend to the same left edge.
|
|
117
|
-
- Prefer direct labels when they reduce lookup.
|
|
118
|
-
- Use a compact top legend when direct labels collide.
|
|
119
|
-
- Keep value labels near marks with a clear gutter.
|
|
120
|
-
- Put pie labels outside. If labels collide, use a right-side list.
|
|
121
|
-
- Use callouts sparingly; anchor them to data points.
|
|
122
|
-
|
|
123
|
-
### Axes, Grids, And Plot Area
|
|
124
|
-
|
|
125
|
-
- Use one stroke width per chart; do not encode emphasis with thickness.
|
|
126
|
-
- Web/static chart default: `1px` visual stroke.
|
|
127
|
-
- Deck export default: `1.5px` visual stroke.
|
|
128
|
-
- Keep keylines on filled marks and shapes.
|
|
129
|
-
- Do not use gradients inside chart marks.
|
|
130
|
-
- Use white or near-white backgrounds unless the whole artifact is dark.
|
|
131
|
-
- For line, area, and line-dot charts, keep left and bottom axis bars visible.
|
|
132
|
-
- Use dotted plot areas only for line, area, or line-dot charts.
|
|
133
|
-
- For bar charts, keep grid lines quiet and only on the value axis.
|
|
134
|
-
- For datetime x-axes, use `format_date_axis(ax)` after plotting so tick labels stay concise and do not overlap.
|
|
135
|
-
|
|
136
|
-
### Mark Styling
|
|
137
|
-
|
|
138
|
-
- Bars: filled marks with keylines; sort unless order matters; use horizontal bars for long labels.
|
|
139
|
-
- Use the root `base` tone for primary fills and line marks. Use `dark` as the keyline or high-contrast reference stroke, not as the default fill.
|
|
140
|
-
- Diverging bars: reserve separate zones for category labels, negative value labels, zero line, positive bars, and positive value labels.
|
|
141
|
-
- Lines: use declared roots, line style, tone, or labels; remove extra guides.
|
|
142
|
-
- Line-dot and interval charts: make dots and whiskers primary; keep connector lines quiet; use dark-neutral benchmark lines.
|
|
143
|
-
- Bubbles: area-encode size only when the third metric materially changes the interpretation; include a compact size legend.
|
|
144
|
-
- Areas: keep boundary lines above fills, but do not outline the sides or bottom of filled area polygons.
|
|
145
|
-
- Pie charts: sort slices, use outside labels, avoid tiny inside labels, and keep labels readable.
|
|
146
|
-
- Heatmaps: use a declared sequential scale; annotate only readable cells.
|
|
147
|
-
|
|
148
|
-
### Layout And Export
|
|
149
|
-
|
|
150
|
-
- Reserve header space for title and subtitle plus label gutters before plotting.
|
|
151
|
-
- Use `add_chart_header(fig, ax, title, subtitle)` for every shipped static chart. Do not mix `ax.set_title(...)` with separate subtitle text.
|
|
152
|
-
- Use an 8-column footprint for most standalone HTML charts; widen to 10 or 12 for long labels, dense series, or annotations. Treat 6 columns as the minimum.
|
|
153
|
-
- Stack side-by-side charts on mobile; do not invent off-grid widths.
|
|
154
|
-
- For shipped branded web outputs, inspect light and dark variants.
|
|
155
|
-
- Never compress a chart into a narrow card if labels clip.
|
|
156
|
-
- Inspect the exported PNG and final embedded context, not only the raw SVG.
|
|
157
|
-
|
|
158
|
-
## Minimal Implementation Skeleton
|
|
159
|
-
|
|
160
|
-
Adapt this skeleton.
|
|
161
|
-
|
|
162
|
-
```python
|
|
163
|
-
import matplotlib.pyplot as plt
|
|
164
|
-
import matplotlib.dates as mdates
|
|
165
|
-
import matplotlib.ticker as mticker
|
|
166
|
-
import numpy as np
|
|
167
|
-
import seaborn as sns
|
|
168
|
-
import textwrap
|
|
169
|
-
from matplotlib.patches import Patch
|
|
170
|
-
|
|
171
|
-
FONT_FAMILY = ["Aptos", "Inter", "Segoe UI", "DejaVu Sans", "Arial", "sans-serif"]
|
|
172
|
-
MONO_FONT_FAMILY = ["SF Mono", "Menlo", "Consolas", "DejaVu Sans Mono", "monospace"]
|
|
173
|
-
|
|
174
|
-
TOKENS = {
|
|
175
|
-
"surface": "#FCFCFD",
|
|
176
|
-
"panel": "#FFFFFF",
|
|
177
|
-
"ink": "#1F2430",
|
|
178
|
-
"muted": "#6F768A",
|
|
179
|
-
"grid": "#E6E8F0",
|
|
180
|
-
"axis": "#D7DBE7",
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
NEUTRAL_MARKS = {
|
|
184
|
-
"open": TOKENS["panel"],
|
|
185
|
-
"xlight": "#F4F5F7",
|
|
186
|
-
"light": "#E2E5EA",
|
|
187
|
-
"base": "#C5CAD3",
|
|
188
|
-
"mid": "#7A828F",
|
|
189
|
-
"dark": "#464C55",
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
COLOR_FAMILIES = {
|
|
193
|
-
"blue": {
|
|
194
|
-
"open": TOKENS["panel"],
|
|
195
|
-
"xlight": "#EAF1FE",
|
|
196
|
-
"light": "#CEDFFE",
|
|
197
|
-
"base": "#A3BEFA",
|
|
198
|
-
"mid": "#5477C4",
|
|
199
|
-
"dark": "#2E4780",
|
|
200
|
-
},
|
|
201
|
-
"gold": {
|
|
202
|
-
"open": TOKENS["panel"],
|
|
203
|
-
"xlight": "#FFF4C2",
|
|
204
|
-
"light": "#FFEA8F",
|
|
205
|
-
"base": "#FFE15B",
|
|
206
|
-
"mid": "#B8A037",
|
|
207
|
-
"dark": "#736422",
|
|
208
|
-
},
|
|
209
|
-
"orange": {
|
|
210
|
-
"open": TOKENS["panel"],
|
|
211
|
-
"xlight": "#FFEDDE",
|
|
212
|
-
"light": "#FFBDA1",
|
|
213
|
-
"base": "#F0986E",
|
|
214
|
-
"mid": "#CC6F47",
|
|
215
|
-
"dark": "#804126",
|
|
216
|
-
},
|
|
217
|
-
"olive": {
|
|
218
|
-
"open": TOKENS["panel"],
|
|
219
|
-
"xlight": "#D8ECBD",
|
|
220
|
-
"light": "#BEEB96",
|
|
221
|
-
"base": "#A3D576",
|
|
222
|
-
"mid": "#71B436",
|
|
223
|
-
"dark": "#386411",
|
|
224
|
-
},
|
|
225
|
-
"pink": {
|
|
226
|
-
"open": TOKENS["panel"],
|
|
227
|
-
"xlight": "#FCDAD6",
|
|
228
|
-
"light": "#F5BACC",
|
|
229
|
-
"base": "#F390CA",
|
|
230
|
-
"mid": "#BD569B",
|
|
231
|
-
"dark": "#8A3A6F",
|
|
232
|
-
},
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
def palette_from_family(labels, family, tones=("base", "light", "xlight", "open", "base")):
|
|
236
|
-
"""Return an explicit palette map from one declared palette root."""
|
|
237
|
-
labels = list(labels)
|
|
238
|
-
tone_list = list(tones)
|
|
239
|
-
return {
|
|
240
|
-
label: family[tone_list[i % len(tone_list)]]
|
|
241
|
-
for i, label in enumerate(labels)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
def add_chart_header(fig, ax, title, subtitle, *, title_width=78, subtitle_width=112) -> None:
|
|
246
|
-
"""Add a wrapped figure-level title/subtitle and reserve plot space."""
|
|
247
|
-
title = str(title).strip()
|
|
248
|
-
subtitle = str(subtitle).strip()
|
|
249
|
-
if not title or not subtitle:
|
|
250
|
-
raise ValueError("Every shipped chart needs a non-empty title and subtitle.")
|
|
251
|
-
|
|
252
|
-
title = textwrap.fill(title, width=title_width, break_long_words=False)
|
|
253
|
-
subtitle = textwrap.fill(subtitle, width=subtitle_width, break_long_words=False)
|
|
254
|
-
title_lines = title.count("\n") + 1
|
|
255
|
-
subtitle_lines = subtitle.count("\n") + 1
|
|
256
|
-
|
|
257
|
-
ax.set_title("")
|
|
258
|
-
fig.subplots_adjust(top=max(0.62, 0.86 - 0.045 * (title_lines - 1) - 0.032 * (subtitle_lines - 1)))
|
|
259
|
-
|
|
260
|
-
left = ax.get_position().x0
|
|
261
|
-
fig.text(left, 0.985, title, ha="left", va="top", fontsize=13, fontweight="semibold", color=TOKENS["ink"], linespacing=1.08)
|
|
262
|
-
fig.text(left, 0.93 - 0.045 * (title_lines - 1), subtitle, ha="left", va="top", fontsize=9, color=TOKENS["muted"], linespacing=1.18)
|
|
263
|
-
sns.despine(ax=ax)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def format_date_axis(ax, *, max_ticks=6) -> None:
|
|
267
|
-
"""Keep time axes readable by limiting ticks and using concise labels."""
|
|
268
|
-
locator = mdates.AutoDateLocator(minticks=3, maxticks=max_ticks)
|
|
269
|
-
ax.xaxis.set_major_locator(locator)
|
|
270
|
-
ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator))
|
|
271
|
-
ax.tick_params(axis="x", labelrotation=0)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
def use_chart_theme() -> None:
|
|
275
|
-
sns.set_theme(
|
|
276
|
-
style="whitegrid",
|
|
277
|
-
rc={
|
|
278
|
-
"figure.facecolor": TOKENS["surface"],
|
|
279
|
-
"figure.edgecolor": "none",
|
|
280
|
-
"savefig.facecolor": "none",
|
|
281
|
-
"savefig.edgecolor": "none",
|
|
282
|
-
"axes.facecolor": TOKENS["panel"],
|
|
283
|
-
"axes.edgecolor": TOKENS["axis"],
|
|
284
|
-
"axes.labelcolor": TOKENS["ink"],
|
|
285
|
-
"axes.grid": True,
|
|
286
|
-
"axes.spines.top": False,
|
|
287
|
-
"axes.spines.right": False,
|
|
288
|
-
"grid.color": TOKENS["grid"],
|
|
289
|
-
"grid.linewidth": 0.8,
|
|
290
|
-
"font.family": "sans-serif",
|
|
291
|
-
"font.sans-serif": FONT_FAMILY,
|
|
292
|
-
"font.monospace": MONO_FONT_FAMILY,
|
|
293
|
-
"patch.linewidth": 1.0,
|
|
294
|
-
},
|
|
295
|
-
)
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
## Visualization Templates
|
|
299
|
-
|
|
300
|
-
Each template inherits shared style. Snippets assume `fig`, `ax`, `family`,
|
|
301
|
-
`title`, `subtitle`, and labels exist; adapt names and sizing. Finish every shipped chart with `add_chart_header(fig, ax, title, subtitle)`. For FacetGrid or multi-axis charts, pass the figure and first primary axis.
|
|
302
|
-
|
|
303
|
-
### Trend Line
|
|
304
|
-
|
|
305
|
-
- Use: continuous metric over ordered x.
|
|
306
|
-
- Data: sorted x, y.
|
|
307
|
-
- Snippet:
|
|
308
|
-
```python
|
|
309
|
-
plot_df = df.sort_values(x_col)
|
|
310
|
-
sns.lineplot(data=plot_df, x=x_col, y=y_col, ax=ax, color=family["base"], linewidth=1.0)
|
|
311
|
-
if np.issubdtype(plot_df[x_col].dtype, np.datetime64):
|
|
312
|
-
format_date_axis(ax)
|
|
313
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### Highlighted Multi-Series Trend
|
|
317
|
-
|
|
318
|
-
- Use: focal series with peer context.
|
|
319
|
-
- Data: x, y, series, focal flag.
|
|
320
|
-
- Snippet:
|
|
321
|
-
```python
|
|
322
|
-
peer_families = [NEUTRAL_MARKS, COLOR_FAMILIES["gold"], NEUTRAL_MARKS]
|
|
323
|
-
for i, (series, part) in enumerate(df.loc[~df[focal_col]].groupby(series_col)):
|
|
324
|
-
peer_family = peer_families[i % len(peer_families)]
|
|
325
|
-
sns.lineplot(data=part, x=x_col, y=y_col, ax=ax, color=peer_family["base"], linewidth=1.0, linestyle=["--", ":", "-."][i % 3], label=series)
|
|
326
|
-
focal_label = str(df.loc[df[focal_col], series_col].drop_duplicates().iloc[0])
|
|
327
|
-
sns.lineplot(data=df.loc[df[focal_col]], x=x_col, y=y_col, ax=ax, color=family["base"], linewidth=1.0, label=focal_label)
|
|
328
|
-
if np.issubdtype(df[x_col].dtype, np.datetime64):
|
|
329
|
-
format_date_axis(ax)
|
|
330
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=min(df[series_col].nunique(), 4), borderaxespad=0)
|
|
331
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Stacked Area
|
|
335
|
-
|
|
336
|
-
- Use: additive composition over time.
|
|
337
|
-
- Data: x plus additive components, or long data pivoted wide.
|
|
338
|
-
- Snippet:
|
|
339
|
-
```python
|
|
340
|
-
wide = df.pivot(index=x_col, columns=segment_col, values=value_col).fillna(0).sort_index()
|
|
341
|
-
family_cycle = [COLOR_FAMILIES[name] for name in ["blue", "gold", "olive", "pink", "orange"]]
|
|
342
|
-
area_families = [family_cycle[i % len(family_cycle)] for i in range(wide.shape[1])]
|
|
343
|
-
fills = [area_families[i]["base"] for i in range(wide.shape[1])]
|
|
344
|
-
areas = ax.stackplot(wide.index, wide.T.to_numpy(), labels=list(wide.columns), colors=fills, linewidth=0)
|
|
345
|
-
lower = np.zeros(len(wide), dtype=float)
|
|
346
|
-
for area, values, area_family in zip(areas, wide.T.to_numpy(), area_families):
|
|
347
|
-
area.set_edgecolor("none")
|
|
348
|
-
area.set_linewidth(0)
|
|
349
|
-
upper = lower + values
|
|
350
|
-
lower = upper
|
|
351
|
-
cumulative = wide.T.to_numpy().cumsum(axis=0)
|
|
352
|
-
for boundary, area_family in zip(cumulative, area_families):
|
|
353
|
-
ax.plot(wide.index, boundary, color=area_family["dark"], linewidth=1.0, zorder=3.2)
|
|
354
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=min(wide.shape[1], 4), borderaxespad=0)
|
|
355
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### Overlapping Area
|
|
359
|
-
|
|
360
|
-
- Use: overlapping continuous envelopes.
|
|
361
|
-
- Data: x plus 2-3 y series.
|
|
362
|
-
- Snippet:
|
|
363
|
-
```python
|
|
364
|
-
if not 2 <= len(y_cols) <= 3:
|
|
365
|
-
raise ValueError("Overlapping area expects two or three y series.")
|
|
366
|
-
area_styles = [
|
|
367
|
-
# Draw rear envelopes first and the low/base envelope last.
|
|
368
|
-
(str(y_cols[1]), y_cols[1], COLOR_FAMILIES["olive"]["base"], COLOR_FAMILIES["olive"]["dark"], COLOR_FAMILIES["olive"]["base"], "-", 0.36, 1.1),
|
|
369
|
-
]
|
|
370
|
-
if len(y_cols) == 3:
|
|
371
|
-
area_styles.append(
|
|
372
|
-
(str(y_cols[2]), y_cols[2], COLOR_FAMILIES["blue"]["base"], COLOR_FAMILIES["blue"]["dark"], COLOR_FAMILIES["blue"]["base"], "-", 0.66, 1.8)
|
|
373
|
-
)
|
|
374
|
-
area_styles.append(
|
|
375
|
-
(str(y_cols[0]), y_cols[0], COLOR_FAMILIES["olive"]["base"], COLOR_FAMILIES["olive"]["dark"], COLOR_FAMILIES["olive"]["base"], "-", 0.72, 3.0)
|
|
376
|
-
)
|
|
377
|
-
for name, y, fill_color, edge_color, line_color, line_style, fill_alpha, zorder in area_styles:
|
|
378
|
-
area = ax.fill_between(
|
|
379
|
-
df[x_col], 0, df[y],
|
|
380
|
-
color=fill_color, alpha=fill_alpha,
|
|
381
|
-
edgecolor="none",
|
|
382
|
-
linewidth=0,
|
|
383
|
-
zorder=zorder,
|
|
384
|
-
)
|
|
385
|
-
for name, y, _, _, line_color, line_style, _, _ in area_styles:
|
|
386
|
-
ax.plot(df[x_col], df[y], color=line_color, linestyle=line_style, linewidth=1.05, label=name, zorder=5.2)
|
|
387
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=min(len(area_styles), 4), borderaxespad=0)
|
|
388
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### Small Multiples
|
|
392
|
-
|
|
393
|
-
- Use: many trend lines.
|
|
394
|
-
- Data: x, y, facet.
|
|
395
|
-
- Snippet:
|
|
396
|
-
```python
|
|
397
|
-
g = sns.FacetGrid(df, col=facet_col, col_wrap=3, sharex=True, sharey=True)
|
|
398
|
-
facet_order = list(df[facet_col].drop_duplicates())
|
|
399
|
-
facet_palette = {facet: COLOR_FAMILIES["blue"]["base"] for facet in facet_order}
|
|
400
|
-
g.map_dataframe(sns.lineplot, x=x_col, y=y_col, hue=facet_col, palette=facet_palette, legend=False, linewidth=1.0)
|
|
401
|
-
g.set_titles("{col_name}", size=8.5)
|
|
402
|
-
add_chart_header(g.figure, g.axes.flat[0], title, subtitle)
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
### Grouped Column Bars
|
|
406
|
-
|
|
407
|
-
- Use: side-by-side category comparison.
|
|
408
|
-
- Data: category, series, value; few categories.
|
|
409
|
-
- Snippet:
|
|
410
|
-
```python
|
|
411
|
-
series_order = list(df[series_col].drop_duplicates())
|
|
412
|
-
category_order = list(df[category_col].drop_duplicates())
|
|
413
|
-
x = np.arange(len(category_order))
|
|
414
|
-
width = min(0.24, 0.72 / max(len(series_order), 1))
|
|
415
|
-
series_families = [COLOR_FAMILIES[name] for name in ["orange", "blue", "olive", "gold", "pink"]]
|
|
416
|
-
for i, series in enumerate(series_order):
|
|
417
|
-
series_family = series_families[i % len(series_families)]
|
|
418
|
-
values = df.loc[df[series_col] == series].set_index(category_col).loc[category_order, value_col].to_numpy()
|
|
419
|
-
offset = (i - (len(series_order) - 1) / 2) * width
|
|
420
|
-
bars = ax.bar(
|
|
421
|
-
x + offset,
|
|
422
|
-
values,
|
|
423
|
-
width=width,
|
|
424
|
-
label=series,
|
|
425
|
-
color=series_family["base"],
|
|
426
|
-
edgecolor=series_family["dark"],
|
|
427
|
-
linewidth=1.0,
|
|
428
|
-
)
|
|
429
|
-
ax.set_xticks(x, category_order)
|
|
430
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=min(len(series_order), 4), borderaxespad=0)
|
|
431
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
### Ranked Horizontal Bars
|
|
435
|
-
|
|
436
|
-
- Use: rank, top-N, long labels.
|
|
437
|
-
- Data: category, value; sort unless order matters.
|
|
438
|
-
- Snippet:
|
|
439
|
-
```python
|
|
440
|
-
plot_df = df.sort_values(value_col, ascending=True)
|
|
441
|
-
bar_family = COLOR_FAMILIES["orange"]
|
|
442
|
-
palette = palette_from_family(plot_df[category_col], bar_family, tones=("base", "light", "xlight", "open", "base"))
|
|
443
|
-
edge_colors = {category: bar_family["dark"] for category in plot_df[category_col]}
|
|
444
|
-
sns.barplot(data=plot_df, x=value_col, y=category_col, hue=category_col, palette=palette, legend=False, dodge=False, ax=ax, edgecolor=TOKENS["ink"], linewidth=1.0)
|
|
445
|
-
for patch, category in zip(ax.patches, plot_df[category_col]):
|
|
446
|
-
patch.set_edgecolor(edge_colors[category])
|
|
447
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Diverging Horizontal Bars
|
|
451
|
-
|
|
452
|
-
- Use: signed deltas or drivers around zero.
|
|
453
|
-
- Data: category, signed value.
|
|
454
|
-
- Snippet:
|
|
455
|
-
```python
|
|
456
|
-
plot_df = df.sort_values(value_col)
|
|
457
|
-
positive_family = COLOR_FAMILIES["olive"]
|
|
458
|
-
negative_family = COLOR_FAMILIES["orange"]
|
|
459
|
-
colors = np.where(plot_df[value_col] >= 0, positive_family["base"], negative_family["base"])
|
|
460
|
-
edge_colors = np.where(plot_df[value_col] >= 0, positive_family["dark"], negative_family["dark"])
|
|
461
|
-
bars = ax.barh(plot_df[category_col], plot_df[value_col], color=colors, edgecolor=edge_colors, linewidth=1.0)
|
|
462
|
-
neg_min = plot_df.loc[plot_df[value_col] < 0, value_col].min()
|
|
463
|
-
pos_max = plot_df.loc[plot_df[value_col] > 0, value_col].max()
|
|
464
|
-
neg_label_x = neg_min * 0.74
|
|
465
|
-
ax.set_xlim(neg_min * 1.36, pos_max * 1.12)
|
|
466
|
-
for bar, value in zip(bars, plot_df[value_col]):
|
|
467
|
-
bar.set_edgecolor(positive_family["dark"] if value >= 0 else negative_family["dark"])
|
|
468
|
-
label_x = value + 0.25 if value >= 0 else neg_label_x
|
|
469
|
-
ax.text(label_x, bar.get_y() + bar.get_height() / 2, f"{value:+.1f}", ha="left", va="center", fontsize=8, color=TOKENS["ink"])
|
|
470
|
-
ax.axvline(0, color=TOKENS["ink"], linewidth=1.0)
|
|
471
|
-
ax.legend(
|
|
472
|
-
handles=[
|
|
473
|
-
Patch(facecolor=positive_family["base"], edgecolor=positive_family["dark"], label="Positive"),
|
|
474
|
-
Patch(facecolor=negative_family["base"], edgecolor=negative_family["dark"], label="Negative"),
|
|
475
|
-
],
|
|
476
|
-
loc="lower left",
|
|
477
|
-
bbox_to_anchor=(0, 1.02),
|
|
478
|
-
frameon=False,
|
|
479
|
-
ncol=2,
|
|
480
|
-
borderaxespad=0,
|
|
481
|
-
)
|
|
482
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
### Dot Reference Comparison
|
|
486
|
-
|
|
487
|
-
- Use: compact target, before/after, or benchmark comparison.
|
|
488
|
-
- Data: category, value, optional reference.
|
|
489
|
-
- Snippet:
|
|
490
|
-
```python
|
|
491
|
-
value_family = COLOR_FAMILIES["orange"]
|
|
492
|
-
ax.hlines(df[category_col], df[reference_col], df[value_col], color=NEUTRAL_MARKS["base"], linewidth=1.0, label="Reference gap")
|
|
493
|
-
ax.scatter(df[value_col], df[category_col], facecolors=value_family["base"], edgecolors=value_family["dark"], linewidths=1.0, label="Actual")
|
|
494
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=2, borderaxespad=0)
|
|
495
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
### Concentration / Pareto
|
|
499
|
-
|
|
500
|
-
- Use: concentration of volume or impact.
|
|
501
|
-
- Data: entity, value; derive cumulative share.
|
|
502
|
-
- Snippet:
|
|
503
|
-
```python
|
|
504
|
-
plot_df = df.sort_values(value_col, ascending=False).head(top_n).assign(cum_share=lambda d: d[value_col].cumsum() / d[value_col].sum())
|
|
505
|
-
bar_family = COLOR_FAMILIES["orange"]
|
|
506
|
-
line_family = COLOR_FAMILIES["blue"]
|
|
507
|
-
sns.barplot(data=plot_df, x=category_col, y=value_col, ax=ax, color=bar_family["base"], edgecolor=bar_family["dark"], linewidth=1.0)
|
|
508
|
-
ax2 = ax.twinx()
|
|
509
|
-
ax2.grid(False)
|
|
510
|
-
ax2.plot(plot_df[category_col], plot_df["cum_share"], color=line_family["base"], linewidth=1.0, marker="o", label="Cumulative share")
|
|
511
|
-
ax2.set_ylim(0, 1.05)
|
|
512
|
-
ax2.yaxis.set_major_formatter(mticker.PercentFormatter(1.0))
|
|
513
|
-
ax2.tick_params(axis="y", colors=TOKENS["muted"], labelsize=8, length=0)
|
|
514
|
-
ax2.spines["right"].set_visible(False)
|
|
515
|
-
ax.legend(
|
|
516
|
-
handles=[
|
|
517
|
-
Patch(facecolor=bar_family["base"], edgecolor=bar_family["dark"], label=str(value_col).replace("_", " ").title()),
|
|
518
|
-
ax2.lines[0],
|
|
519
|
-
],
|
|
520
|
-
loc="lower left",
|
|
521
|
-
bbox_to_anchor=(0, 1.02),
|
|
522
|
-
frameon=False,
|
|
523
|
-
ncol=2,
|
|
524
|
-
borderaxespad=0,
|
|
525
|
-
)
|
|
526
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
### Stacked Horizontal Bars
|
|
530
|
-
|
|
531
|
-
- Use: share-of-total, survey, or Likert buckets.
|
|
532
|
-
- Data: group, ordered segment, value or percent.
|
|
533
|
-
- Snippet:
|
|
534
|
-
```python
|
|
535
|
-
wide = df.pivot_table(index=group_col, columns=segment_col, values=value_col, fill_value=0).reindex(index=group_order, columns=segment_order)
|
|
536
|
-
left = np.zeros(len(wide))
|
|
537
|
-
segment_families = [COLOR_FAMILIES[name] for name in ["blue", "gold", "olive", "pink", "orange"]]
|
|
538
|
-
for i, segment in enumerate(segment_order):
|
|
539
|
-
segment_family = segment_families[i % len(segment_families)]
|
|
540
|
-
bars = ax.barh(wide.index, wide[segment], left=left, label=segment, color=segment_family["base"], edgecolor=segment_family["dark"], linewidth=1.0)
|
|
541
|
-
left += wide[segment].to_numpy()
|
|
542
|
-
ax.xaxis.set_major_formatter(mticker.PercentFormatter(100))
|
|
543
|
-
ax.legend(loc="lower left", bbox_to_anchor=(0, 1.04), frameon=False, ncol=min(len(segment_order), 4), borderaxespad=0)
|
|
544
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
### Pie Chart
|
|
548
|
-
|
|
549
|
-
- Use: rough part-to-whole with few slices.
|
|
550
|
-
- Data: category, value.
|
|
551
|
-
- Snippet:
|
|
552
|
-
```python
|
|
553
|
-
plot_df = df.sort_values(value_col, ascending=False)
|
|
554
|
-
slice_families = [COLOR_FAMILIES[name] for name in ["olive", "gold", "blue", "pink", "orange"]]
|
|
555
|
-
colors = [slice_families[i % len(slice_families)]["base"] for i in range(len(plot_df))]
|
|
556
|
-
wedges, _ = ax.pie(plot_df[value_col], startangle=90, counterclock=False, colors=colors, wedgeprops={"edgecolor": TOKENS["ink"], "linewidth": 1.0})
|
|
557
|
-
for i, (wedge, label, value) in enumerate(zip(wedges, plot_df[category_col], plot_df[value_col])):
|
|
558
|
-
slice_family = slice_families[i % len(slice_families)]
|
|
559
|
-
wedge.set_edgecolor(slice_family["dark"])
|
|
560
|
-
angle = np.deg2rad((wedge.theta1 + wedge.theta2) / 2)
|
|
561
|
-
ax.text(1.08 * np.cos(angle), 1.08 * np.sin(angle), f"{label}: {value:,.0f}", ha="left" if np.cos(angle) > 0 else "right", va="center")
|
|
562
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
### Histogram / KDE
|
|
566
|
-
|
|
567
|
-
- Use: spread, skew, tail, or threshold.
|
|
568
|
-
- Data: one numeric value.
|
|
569
|
-
- Snippet:
|
|
570
|
-
```python
|
|
571
|
-
sns.histplot(data=df, x=value_col, bins=bins, ax=ax, color=family["base"], edgecolor=family["dark"], linewidth=1.0)
|
|
572
|
-
ax.axvline(df[value_col].median(), color=TOKENS["ink"], linestyle=":", linewidth=1.0)
|
|
573
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
### Grouped Distribution Comparison
|
|
577
|
-
|
|
578
|
-
- Use: spread, skew, or outliers across cohorts.
|
|
579
|
-
- Data: group, numeric value.
|
|
580
|
-
- Snippet:
|
|
581
|
-
```python
|
|
582
|
-
group_order = list(df[group_col].drop_duplicates())
|
|
583
|
-
group_family = COLOR_FAMILIES["pink"]
|
|
584
|
-
box_tones = ["base", "light", "xlight"]
|
|
585
|
-
point_tones = ["base", "base", "base"]
|
|
586
|
-
box_palette = {group: group_family[box_tones[i % len(box_tones)]] for i, group in enumerate(group_order)}
|
|
587
|
-
point_palette = {group: group_family[point_tones[i % len(point_tones)]] for i, group in enumerate(group_order)}
|
|
588
|
-
edge_colors = {group: group_family["dark"] for group in group_order}
|
|
589
|
-
sns.boxplot(data=df, x=group_col, y=value_col, hue=group_col, palette=box_palette, legend=False, linewidth=1.0)
|
|
590
|
-
for patch, group in zip(ax.patches, group_order):
|
|
591
|
-
patch.set_edgecolor(edge_colors[group])
|
|
592
|
-
sns.stripplot(data=df.sample(min(len(df), 500)), x=group_col, y=value_col, hue=group_col, palette=point_palette, legend=False, alpha=0.25, size=2)
|
|
593
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
### Scatter
|
|
597
|
-
|
|
598
|
-
- Use: two-variable relationship.
|
|
599
|
-
- Data: numeric x/y, optional small group.
|
|
600
|
-
- Snippet:
|
|
601
|
-
```python
|
|
602
|
-
sns.scatterplot(data=df, x=x_col, y=y_col, ax=ax, color=family["base"], edgecolor=family["dark"], linewidth=0.6, alpha=0.65)
|
|
603
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
### Bubble Chart
|
|
607
|
-
|
|
608
|
-
- Use: two-variable relationship where a third numeric metric materially changes interpretation.
|
|
609
|
-
- Data: numeric x/y, numeric size.
|
|
610
|
-
- Snippet:
|
|
611
|
-
```python
|
|
612
|
-
size_min = df[size_col].min()
|
|
613
|
-
size_max = df[size_col].max()
|
|
614
|
-
size_values = np.quantile(df[size_col], [0.25, 0.5, 0.75])
|
|
615
|
-
|
|
616
|
-
def marker_size(value):
|
|
617
|
-
if size_max == size_min:
|
|
618
|
-
return 240
|
|
619
|
-
return 80 + (value - size_min) / (size_max - size_min) * 420
|
|
620
|
-
|
|
621
|
-
sns.scatterplot(
|
|
622
|
-
data=df,
|
|
623
|
-
x=x_col,
|
|
624
|
-
y=y_col,
|
|
625
|
-
size=size_col,
|
|
626
|
-
sizes=(80, 500),
|
|
627
|
-
legend=False,
|
|
628
|
-
ax=ax,
|
|
629
|
-
color=family["base"],
|
|
630
|
-
edgecolor=family["dark"],
|
|
631
|
-
linewidth=0.8,
|
|
632
|
-
alpha=0.55,
|
|
633
|
-
)
|
|
634
|
-
handles = [
|
|
635
|
-
ax.scatter([], [], s=marker_size(value), facecolors=family["base"], edgecolors=family["dark"], linewidths=0.8, alpha=0.55, label=f"{value:,.0f}")
|
|
636
|
-
for value in size_values
|
|
637
|
-
]
|
|
638
|
-
ax.legend(handles=handles, title=str(size_col).replace("_", " ").title(), loc="lower left", bbox_to_anchor=(0, 1.02), frameon=False, ncol=len(handles), borderaxespad=0)
|
|
639
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
### Scatter / Density
|
|
643
|
-
|
|
644
|
-
- Use: dense point cloud.
|
|
645
|
-
- Data: numeric x/y.
|
|
646
|
-
- Snippet:
|
|
647
|
-
```python
|
|
648
|
-
ax.hexbin(df[x_col], df[y_col], gridsize=28, mincnt=1, cmap=sns.blend_palette([TOKENS["panel"], family["light"], family["base"]], as_cmap=True))
|
|
649
|
-
fit = np.polyfit(df[x_col], df[y_col], deg=1)
|
|
650
|
-
x_fit = np.linspace(df[x_col].min(), df[x_col].max(), 100)
|
|
651
|
-
sns.lineplot(x=x_fit, y=fit[0] * x_fit + fit[1], ax=ax, color=family["base"], linewidth=1.0)
|
|
652
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
### Ordered Line & Dot
|
|
656
|
-
|
|
657
|
-
- Use: ordered bins, calibration, or uncertainty comparisons.
|
|
658
|
-
- Data: ordered x/bin, estimate, optional bounds/series.
|
|
659
|
-
- Snippet:
|
|
660
|
-
```python
|
|
661
|
-
ax.errorbar(
|
|
662
|
-
df[x_col], df[estimate_col],
|
|
663
|
-
yerr=[df[estimate_col] - df[lower_col], df[upper_col] - df[estimate_col]],
|
|
664
|
-
fmt="o", color=family["base"], linewidth=1.0, capsize=3,
|
|
665
|
-
)
|
|
666
|
-
ax.plot(df[x_col], df[estimate_col], color=family["light"], linewidth=1.0)
|
|
667
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
### Faceted Dot & Interval
|
|
671
|
-
|
|
672
|
-
- Use: subgroup estimates against benchmark.
|
|
673
|
-
- Data: facet, estimate, lower, upper, label.
|
|
674
|
-
- Snippet:
|
|
675
|
-
```python
|
|
676
|
-
for ax, (facet, part) in zip(axes, df.groupby(facet_col)):
|
|
677
|
-
facet_order = list(df[facet_col].drop_duplicates())
|
|
678
|
-
facet_tones = ["base", "light", "base"]
|
|
679
|
-
facet_color = COLOR_FAMILIES["gold"][facet_tones[facet_order.index(facet) % len(facet_tones)]]
|
|
680
|
-
ax.errorbar(
|
|
681
|
-
part[estimate_col], part[label_col],
|
|
682
|
-
xerr=[part[estimate_col] - part[lower_col], part[upper_col] - part[estimate_col]],
|
|
683
|
-
fmt="o", color=facet_color, linewidth=1.0,
|
|
684
|
-
)
|
|
685
|
-
ax.axvline(benchmark, color=TOKENS["ink"], linestyle=":", linewidth=1.0)
|
|
686
|
-
add_chart_header(fig, axes[0], title, subtitle)
|
|
687
|
-
```
|
|
688
|
-
|
|
689
|
-
### Experiment Lift With Confidence Intervals
|
|
690
|
-
|
|
691
|
-
- Use: lift, treatment effects, or model intervals.
|
|
692
|
-
- Data: label, estimate, lower, upper.
|
|
693
|
-
- Snippet:
|
|
694
|
-
```python
|
|
695
|
-
ax.axvline(0, color=TOKENS["ink"], linestyle=":", linewidth=1.0)
|
|
696
|
-
metric_family = COLOR_FAMILIES["gold"]
|
|
697
|
-
for _, row in df.iterrows():
|
|
698
|
-
marker_face = TOKENS["panel"] if row[estimate_col] < 0 else metric_family["base"]
|
|
699
|
-
ax.errorbar(
|
|
700
|
-
row[estimate_col], row[label_col],
|
|
701
|
-
xerr=np.array([[row[estimate_col] - row[lower_col]], [row[upper_col] - row[estimate_col]]]),
|
|
702
|
-
fmt="o", color=metric_family["base"], markerfacecolor=marker_face, markeredgecolor=metric_family["dark"], linewidth=1.0, capsize=3,
|
|
703
|
-
)
|
|
704
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
### Heatmap
|
|
708
|
-
|
|
709
|
-
- Use: two-dimensional structure or cohort matrix.
|
|
710
|
-
- Data: ordered pivot matrix.
|
|
711
|
-
- Snippet:
|
|
712
|
-
```python
|
|
713
|
-
cmap = sns.blend_palette([TOKENS["panel"], family["xlight"], family["light"], family["base"]], as_cmap=True)
|
|
714
|
-
sns.heatmap(matrix, ax=ax, cmap=cmap, linewidths=1.0, linecolor=TOKENS["panel"], annot=annot, fmt=value_format)
|
|
715
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
### Funnel Stage Bars
|
|
719
|
-
|
|
720
|
-
- Use: ordered stages, counts, conversion.
|
|
721
|
-
- Data: stage order, count, optional rate.
|
|
722
|
-
- Snippet:
|
|
723
|
-
```python
|
|
724
|
-
plot_df = df.set_index(stage_col).loc[stage_order].reset_index()
|
|
725
|
-
stage_families = [COLOR_FAMILIES[name] for name in ["olive", "gold", "blue", "pink", "orange"]]
|
|
726
|
-
palette = {stage: stage_families[i % len(stage_families)]["base"] for i, stage in enumerate(stage_order)}
|
|
727
|
-
edge_colors = {stage: stage_families[i % len(stage_families)]["dark"] for i, stage in enumerate(stage_order)}
|
|
728
|
-
sns.barplot(data=plot_df, x=stage_col, y=count_col, hue=stage_col, palette=palette, legend=False, dodge=False, ax=ax, edgecolor=TOKENS["ink"], linewidth=1.0)
|
|
729
|
-
for patch, stage in zip(ax.patches, plot_df[stage_col]):
|
|
730
|
-
patch.set_edgecolor(edge_colors[stage])
|
|
731
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
### Waterfall Bridge
|
|
735
|
-
|
|
736
|
-
- Use: additive bridge from start to end.
|
|
737
|
-
- Data: ordered drivers, signed deltas, start/end.
|
|
738
|
-
- Snippet:
|
|
739
|
-
```python
|
|
740
|
-
positive_family = COLOR_FAMILIES["olive"]
|
|
741
|
-
negative_family = COLOR_FAMILIES["orange"]
|
|
742
|
-
positive_fill = positive_family["base"]
|
|
743
|
-
negative_fill = negative_family["base"]
|
|
744
|
-
total_fill = NEUTRAL_MARKS["light"]
|
|
745
|
-
total_edge = NEUTRAL_MARKS["dark"]
|
|
746
|
-
x = np.arange(len(df) + 2)
|
|
747
|
-
driver_labels = ["Start", *df[label_col], "End"]
|
|
748
|
-
running = start_value + df[delta_col].cumsum().shift(fill_value=0)
|
|
749
|
-
ending = start_value + df[delta_col].cumsum()
|
|
750
|
-
end_value = ending.iloc[-1]
|
|
751
|
-
bottom = np.minimum(running, ending)
|
|
752
|
-
colors = np.where(df[delta_col] >= 0, positive_fill, negative_fill)
|
|
753
|
-
edge_colors = np.where(df[delta_col] >= 0, positive_family["dark"], negative_family["dark"])
|
|
754
|
-
ax.bar(x[0], start_value, color=total_fill, edgecolor=total_edge, linewidth=1.0)
|
|
755
|
-
bars = ax.bar(x[1:-1], df[delta_col].abs(), bottom=bottom, color=colors, edgecolor=edge_colors, linewidth=1.0)
|
|
756
|
-
for bar, delta in zip(bars, df[delta_col]):
|
|
757
|
-
bar.set_edgecolor(positive_family["dark"] if delta >= 0 else negative_family["dark"])
|
|
758
|
-
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_y() + bar.get_height() + 2, f"{delta:+.0f}", ha="center", fontsize=8, color=TOKENS["ink"])
|
|
759
|
-
ax.bar(x[-1], end_value, color=total_fill, edgecolor=total_edge, linewidth=1.0)
|
|
760
|
-
ax.set_xticks(x, driver_labels)
|
|
761
|
-
ax.legend(
|
|
762
|
-
handles=[
|
|
763
|
-
Patch(facecolor=total_fill, edgecolor=total_edge, label="Start/end"),
|
|
764
|
-
Patch(facecolor=positive_fill, edgecolor=positive_family["dark"], label="Positive delta"),
|
|
765
|
-
Patch(facecolor=negative_fill, edgecolor=negative_family["dark"], label="Negative delta"),
|
|
766
|
-
],
|
|
767
|
-
loc="lower left",
|
|
768
|
-
bbox_to_anchor=(0, 1.02),
|
|
769
|
-
frameon=False,
|
|
770
|
-
ncol=3,
|
|
771
|
-
borderaxespad=0,
|
|
772
|
-
)
|
|
773
|
-
add_chart_header(fig, ax, title, subtitle)
|
|
774
|
-
```
|