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/src/analytics-app/layout/analyticsLayoutCore.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
export type AnalyticsLayoutWidth = "full" | "half";
|
|
2
|
-
|
|
3
|
-
export type AnalyticsLayoutItemState = {
|
|
4
|
-
id: string;
|
|
5
|
-
layout: AnalyticsLayoutWidth;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export type AnalyticsLayoutBlockSource = {
|
|
9
|
-
id: string;
|
|
10
|
-
defaultLayout?: AnalyticsLayoutWidth;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type AnalyticsLayoutPlacementIntent =
|
|
14
|
-
| "after"
|
|
15
|
-
| "before"
|
|
16
|
-
| "end"
|
|
17
|
-
| "hold"
|
|
18
|
-
| "pair-after"
|
|
19
|
-
| "pair-before";
|
|
20
|
-
|
|
21
|
-
export type AnalyticsLayoutPlacement = {
|
|
22
|
-
draggedId: string;
|
|
23
|
-
intent: AnalyticsLayoutPlacementIntent;
|
|
24
|
-
targetId?: string | null;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function isLayoutWidth(value: unknown): value is AnalyticsLayoutWidth {
|
|
28
|
-
return value === "full" || value === "half";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function uniqueKnownBlocks(blocks: AnalyticsLayoutBlockSource[]): AnalyticsLayoutBlockSource[] {
|
|
32
|
-
const seen = new Set<string>();
|
|
33
|
-
return blocks.filter((block) => {
|
|
34
|
-
if (!block.id || seen.has(block.id)) return false;
|
|
35
|
-
seen.add(block.id);
|
|
36
|
-
return true;
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function expandToFull(item: AnalyticsLayoutItemState): AnalyticsLayoutItemState {
|
|
41
|
-
return { ...item, layout: "full" };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function collapseToHalf(item: AnalyticsLayoutItemState): AnalyticsLayoutItemState {
|
|
45
|
-
return { ...item, layout: "half" };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function packRows(items: AnalyticsLayoutItemState[]): AnalyticsLayoutItemState[][] {
|
|
49
|
-
const rows: AnalyticsLayoutItemState[][] = [];
|
|
50
|
-
for (let index = 0; index < items.length; index += 1) {
|
|
51
|
-
const item = items[index];
|
|
52
|
-
const nextItem = items[index + 1];
|
|
53
|
-
if (item.layout === "half" && nextItem?.layout === "half") {
|
|
54
|
-
rows.push([item, nextItem]);
|
|
55
|
-
index += 1;
|
|
56
|
-
} else {
|
|
57
|
-
rows.push([expandToFull(item)]);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return rows;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function flattenPackedRows(rows: AnalyticsLayoutItemState[][]): AnalyticsLayoutItemState[] {
|
|
64
|
-
return rows.flatMap((row) => {
|
|
65
|
-
if (row.length === 2) {
|
|
66
|
-
return row.map(collapseToHalf);
|
|
67
|
-
}
|
|
68
|
-
return row.map(expandToFull);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function normalize(
|
|
73
|
-
blocks: AnalyticsLayoutBlockSource[],
|
|
74
|
-
storedLayout?: unknown
|
|
75
|
-
): AnalyticsLayoutItemState[] {
|
|
76
|
-
const knownBlocks = uniqueKnownBlocks(blocks);
|
|
77
|
-
const blockById = new Map(knownBlocks.map((block) => [block.id, block]));
|
|
78
|
-
const storedItems = Array.isArray(storedLayout)
|
|
79
|
-
? storedLayout
|
|
80
|
-
.map((item): AnalyticsLayoutItemState | null => {
|
|
81
|
-
if (!item || typeof item !== "object") return null;
|
|
82
|
-
const candidate = item as Partial<AnalyticsLayoutItemState>;
|
|
83
|
-
if (typeof candidate.id !== "string" || !blockById.has(candidate.id)) return null;
|
|
84
|
-
return {
|
|
85
|
-
id: candidate.id,
|
|
86
|
-
layout: isLayoutWidth(candidate.layout) ? candidate.layout : blockById.get(candidate.id)?.defaultLayout ?? "full"
|
|
87
|
-
};
|
|
88
|
-
})
|
|
89
|
-
.filter((item): item is AnalyticsLayoutItemState => Boolean(item))
|
|
90
|
-
: [];
|
|
91
|
-
const storedIds = new Set(storedItems.map((item) => item.id));
|
|
92
|
-
const missingItems = knownBlocks
|
|
93
|
-
.filter((block) => !storedIds.has(block.id))
|
|
94
|
-
.map((block) => ({
|
|
95
|
-
id: block.id,
|
|
96
|
-
layout: block.defaultLayout ?? "full"
|
|
97
|
-
}));
|
|
98
|
-
return flattenPackedRows(packRows([...storedItems, ...missingItems]));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function moveBlock(
|
|
102
|
-
items: AnalyticsLayoutItemState[],
|
|
103
|
-
draggedId: string,
|
|
104
|
-
targetId: string | null | undefined,
|
|
105
|
-
position: "after" | "before" | "end"
|
|
106
|
-
): AnalyticsLayoutItemState[] {
|
|
107
|
-
const dragged = items.find((item) => item.id === draggedId);
|
|
108
|
-
if (!dragged) return items;
|
|
109
|
-
const remaining = items
|
|
110
|
-
.filter((item) => item.id !== draggedId)
|
|
111
|
-
.map((item) => ({ ...item }));
|
|
112
|
-
const nextDragged = expandToFull(dragged);
|
|
113
|
-
if (position === "end" || !targetId) {
|
|
114
|
-
return flattenPackedRows(packRows([...remaining, nextDragged]));
|
|
115
|
-
}
|
|
116
|
-
const targetIndex = remaining.findIndex((item) => item.id === targetId);
|
|
117
|
-
if (targetIndex === -1) return flattenPackedRows(packRows([...remaining, nextDragged]));
|
|
118
|
-
const insertionIndex = position === "after" ? targetIndex + 1 : targetIndex;
|
|
119
|
-
const next = [...remaining];
|
|
120
|
-
next.splice(insertionIndex, 0, nextDragged);
|
|
121
|
-
return flattenPackedRows(packRows(next));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function pairWithTarget(
|
|
125
|
-
items: AnalyticsLayoutItemState[],
|
|
126
|
-
draggedId: string,
|
|
127
|
-
targetId: string,
|
|
128
|
-
side: "after" | "before"
|
|
129
|
-
): AnalyticsLayoutItemState[] {
|
|
130
|
-
if (draggedId === targetId) return items;
|
|
131
|
-
const dragged = items.find((item) => item.id === draggedId);
|
|
132
|
-
if (!dragged || !items.some((item) => item.id === targetId)) return items;
|
|
133
|
-
const remaining = items
|
|
134
|
-
.filter((item) => item.id !== draggedId)
|
|
135
|
-
.map((item) => (item.id === targetId ? collapseToHalf(item) : { ...item }));
|
|
136
|
-
const targetIndex = remaining.findIndex((item) => item.id === targetId);
|
|
137
|
-
const nextDragged = collapseToHalf(dragged);
|
|
138
|
-
const insertionIndex = side === "after" ? targetIndex + 1 : targetIndex;
|
|
139
|
-
const next = [...remaining];
|
|
140
|
-
next.splice(insertionIndex, 0, nextDragged);
|
|
141
|
-
return flattenPackedRows(packRows(next));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function predictPlacement(
|
|
145
|
-
items: AnalyticsLayoutItemState[],
|
|
146
|
-
placement: AnalyticsLayoutPlacement
|
|
147
|
-
): AnalyticsLayoutItemState[] {
|
|
148
|
-
if (placement.intent === "hold") {
|
|
149
|
-
return items;
|
|
150
|
-
}
|
|
151
|
-
if (placement.intent === "pair-before" && placement.targetId) {
|
|
152
|
-
return pairWithTarget(items, placement.draggedId, placement.targetId, "before");
|
|
153
|
-
}
|
|
154
|
-
if (placement.intent === "pair-after" && placement.targetId) {
|
|
155
|
-
return pairWithTarget(items, placement.draggedId, placement.targetId, "after");
|
|
156
|
-
}
|
|
157
|
-
if (placement.intent === "before") {
|
|
158
|
-
return moveBlock(items, placement.draggedId, placement.targetId, "before");
|
|
159
|
-
}
|
|
160
|
-
if (placement.intent === "after") {
|
|
161
|
-
return moveBlock(items, placement.draggedId, placement.targetId, "after");
|
|
162
|
-
}
|
|
163
|
-
return moveBlock(items, placement.draggedId, null, "end");
|
|
164
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { StrictMode } from "react";
|
|
2
|
-
import { createRoot } from "react-dom/client";
|
|
3
|
-
|
|
4
|
-
import App from "./App";
|
|
5
|
-
import "../styles/codex-theme.css";
|
|
6
|
-
import "./tokens.css";
|
|
7
|
-
import "./charting/chart-tokens.css";
|
|
8
|
-
import "./styles.css";
|
|
9
|
-
import "./tables/data-table.css";
|
|
10
|
-
|
|
11
|
-
const root = document.getElementById("root");
|
|
12
|
-
|
|
13
|
-
if (!root) {
|
|
14
|
-
throw new Error("Missing root element");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
createRoot(root).render(
|
|
18
|
-
<StrictMode>
|
|
19
|
-
<App />
|
|
20
|
-
</StrictMode>
|
|
21
|
-
);
|
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Shared chart contract for generated analytics app packages."""
|
|
3
|
-
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
from typing import Any
|
|
7
|
-
|
|
8
|
-
from package_utils import ContractError
|
|
9
|
-
|
|
10
|
-
SUPPORTED_CHART_TYPES = {
|
|
11
|
-
"area",
|
|
12
|
-
"bar",
|
|
13
|
-
"boxPlot",
|
|
14
|
-
"funnel",
|
|
15
|
-
"heatmap",
|
|
16
|
-
"histogram",
|
|
17
|
-
"horizontalBar",
|
|
18
|
-
"horizontalStackedBar",
|
|
19
|
-
"horizontalStackedBar100",
|
|
20
|
-
"leaderboard",
|
|
21
|
-
"line",
|
|
22
|
-
"pie",
|
|
23
|
-
"scatter",
|
|
24
|
-
"sparkline",
|
|
25
|
-
"stackedArea",
|
|
26
|
-
"stackedBar",
|
|
27
|
-
"stackedBar100",
|
|
28
|
-
"waterfall",
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
ALLOWED_CHART_INTENTS = {
|
|
32
|
-
"comparison",
|
|
33
|
-
"composition",
|
|
34
|
-
"custom",
|
|
35
|
-
"decomposition",
|
|
36
|
-
"distribution",
|
|
37
|
-
"funnel",
|
|
38
|
-
"lookup",
|
|
39
|
-
"relationship",
|
|
40
|
-
"status",
|
|
41
|
-
"trend",
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
INTENT_COMPATIBLE_CHART_TYPES = {
|
|
45
|
-
"comparison": {"bar", "horizontalBar", "leaderboard", "scatter"},
|
|
46
|
-
"composition": {
|
|
47
|
-
"horizontalStackedBar",
|
|
48
|
-
"horizontalStackedBar100",
|
|
49
|
-
"pie",
|
|
50
|
-
"stackedArea",
|
|
51
|
-
"stackedBar",
|
|
52
|
-
"stackedBar100",
|
|
53
|
-
},
|
|
54
|
-
"decomposition": {"bar", "horizontalBar", "waterfall"},
|
|
55
|
-
"distribution": {"boxPlot", "histogram"},
|
|
56
|
-
"funnel": {"bar", "funnel", "horizontalBar"},
|
|
57
|
-
"lookup": {"leaderboard"},
|
|
58
|
-
"relationship": {"heatmap", "scatter"},
|
|
59
|
-
"status": {"bar", "horizontalBar", "sparkline"},
|
|
60
|
-
"trend": {"area", "bar", "line", "sparkline", "stackedArea"},
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
ALLOWED_COMPARISON_CONTEXT_FIELDS = {
|
|
64
|
-
"baseline",
|
|
65
|
-
"denominator",
|
|
66
|
-
"grain",
|
|
67
|
-
"normalization",
|
|
68
|
-
"semanticFamily",
|
|
69
|
-
"unit",
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
SINGLE_SERIES_CHART_TYPES = {
|
|
73
|
-
"funnel",
|
|
74
|
-
"histogram",
|
|
75
|
-
"leaderboard",
|
|
76
|
-
"pie",
|
|
77
|
-
"sparkline",
|
|
78
|
-
"waterfall",
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
INTRINSIC_MULTI_SERIES_CHART_TYPES = {
|
|
82
|
-
"boxPlot",
|
|
83
|
-
"heatmap",
|
|
84
|
-
"horizontalStackedBar",
|
|
85
|
-
"horizontalStackedBar100",
|
|
86
|
-
"stackedArea",
|
|
87
|
-
"stackedBar",
|
|
88
|
-
"stackedBar100",
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
ALLOWED_SERIES_COLORS = {"blue", "purple", "green", "neutral", "orange", "yellow", "pink", "red"}
|
|
92
|
-
ALLOWED_SERIES_LINE_STYLES = {"solid", "dashed", "dotted"}
|
|
93
|
-
ALLOWED_SERIES_ROLES = {"actual", "baseline", "target", "forecast", "plan", "comparison"}
|
|
94
|
-
ALLOWED_PALETTE_KINDS = {"categorical", "sequential", "diverging", "semantic", "identity"}
|
|
95
|
-
ALLOWED_LEGEND_POSITIONS = {"bottom", "right"}
|
|
96
|
-
ALLOWED_LEGEND_SORTS = {"spec", "labelAsc", "labelDesc"}
|
|
97
|
-
ALLOWED_VALUE_LABEL_MODES = {"none", "auto", "all", "endpoints"}
|
|
98
|
-
LEADERBOARD_MAX_ROWS = 8
|
|
99
|
-
MIXED_SCALE_SERIES_RATIO = 25
|
|
100
|
-
MIXED_METRIC_AXIS_FIELDS = {"kpi", "measure", "metric"}
|
|
101
|
-
MIXED_METRIC_AXIS_MARKERS = ("kpi", "measure", "metric")
|
|
102
|
-
MIXED_METRIC_CHANGE_FIELD_MARKERS = (
|
|
103
|
-
"change_pct",
|
|
104
|
-
"delta_pct",
|
|
105
|
-
"movement_pct",
|
|
106
|
-
"wow_change",
|
|
107
|
-
"wow_pct",
|
|
108
|
-
"week_over_week",
|
|
109
|
-
"week_over_week_change",
|
|
110
|
-
"week_over_week_pct",
|
|
111
|
-
"w_w_change",
|
|
112
|
-
)
|
|
113
|
-
DECOMPOSITION_FIELD_MARKERS = (
|
|
114
|
-
"component",
|
|
115
|
-
"decomp",
|
|
116
|
-
"decomposition",
|
|
117
|
-
"factor",
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def validate_chart_type(chart_type: Any, path: str) -> str:
|
|
122
|
-
if chart_type not in SUPPORTED_CHART_TYPES:
|
|
123
|
-
raise ContractError(f"{path}.type must be one of {sorted(SUPPORTED_CHART_TYPES)}")
|
|
124
|
-
return chart_type
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def validate_chart_intent(intent: Any, path: str) -> str:
|
|
128
|
-
if intent not in ALLOWED_CHART_INTENTS:
|
|
129
|
-
raise ContractError(f"{path}.intent must be one of {sorted(ALLOWED_CHART_INTENTS)}")
|
|
130
|
-
return intent
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def require_object(value: Any, path: str) -> dict[str, Any]:
|
|
134
|
-
if not isinstance(value, dict):
|
|
135
|
-
raise ContractError(f"{path} must be an object")
|
|
136
|
-
return value
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def optional_string(value: Any, path: str) -> None:
|
|
140
|
-
if value is not None and not isinstance(value, str):
|
|
141
|
-
raise ContractError(f"{path} must be a string when present")
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def optional_bool(value: Any, path: str) -> None:
|
|
145
|
-
if value is not None and not isinstance(value, bool):
|
|
146
|
-
raise ContractError(f"{path} must be a boolean when present")
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def chart_intent(chart: dict[str, Any] | None) -> str | None:
|
|
150
|
-
intent = chart.get("intent") if isinstance(chart, dict) else None
|
|
151
|
-
return intent if isinstance(intent, str) and intent in ALLOWED_CHART_INTENTS else None
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def field_looks_like_metric_definition(field: str) -> bool:
|
|
155
|
-
normalized = field.lower().replace("-", "_")
|
|
156
|
-
tokens = [token for token in normalized.split("_") if token]
|
|
157
|
-
return any(
|
|
158
|
-
marker in tokens or normalized.endswith(f"{marker}_name")
|
|
159
|
-
for marker in MIXED_METRIC_AXIS_MARKERS
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def validate_comparison_context(context: Any, path: str) -> None:
|
|
164
|
-
if context is None:
|
|
165
|
-
return
|
|
166
|
-
context_obj = require_object(context, path)
|
|
167
|
-
for key, value in context_obj.items():
|
|
168
|
-
if key not in ALLOWED_COMPARISON_CONTEXT_FIELDS:
|
|
169
|
-
raise ContractError(
|
|
170
|
-
f"{path}.{key} is not supported; use one of {sorted(ALLOWED_COMPARISON_CONTEXT_FIELDS)}"
|
|
171
|
-
)
|
|
172
|
-
optional_string(value, f"{path}.{key}")
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def validate_chart_intent_metadata(
|
|
176
|
-
chart: dict[str, Any],
|
|
177
|
-
path: str,
|
|
178
|
-
*,
|
|
179
|
-
require: bool = False,
|
|
180
|
-
) -> str | None:
|
|
181
|
-
intent_value = chart.get("intent")
|
|
182
|
-
if intent_value is None:
|
|
183
|
-
if require:
|
|
184
|
-
raise ContractError(f"{path}.intent is required")
|
|
185
|
-
return None
|
|
186
|
-
|
|
187
|
-
intent = validate_chart_intent(intent_value, path)
|
|
188
|
-
question = chart.get("question")
|
|
189
|
-
rationale = chart.get("rationale")
|
|
190
|
-
if require and (not isinstance(question, str) or not question.strip()):
|
|
191
|
-
raise ContractError(f"{path}.question is required")
|
|
192
|
-
if (require or intent == "custom") and (
|
|
193
|
-
not isinstance(rationale, str) or not rationale.strip()
|
|
194
|
-
):
|
|
195
|
-
raise ContractError(f"{path}.rationale is required")
|
|
196
|
-
optional_string(question, f"{path}.question")
|
|
197
|
-
optional_string(rationale, f"{path}.rationale")
|
|
198
|
-
validate_comparison_context(chart.get("comparisonContext"), f"{path}.comparisonContext")
|
|
199
|
-
chart_type = chart.get("type")
|
|
200
|
-
if isinstance(chart_type, str):
|
|
201
|
-
validate_chart_intent_compatibility(chart_type, chart, path)
|
|
202
|
-
return intent
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
def validate_chart_intent_compatibility(chart_type: str, chart: dict[str, Any], path: str) -> None:
|
|
206
|
-
intent = chart_intent(chart)
|
|
207
|
-
if intent is None or intent == "custom":
|
|
208
|
-
return
|
|
209
|
-
compatible_types = INTENT_COMPATIBLE_CHART_TYPES.get(intent, set())
|
|
210
|
-
if chart_type not in compatible_types:
|
|
211
|
-
raise ContractError(
|
|
212
|
-
f"{path}.type {chart_type!r} is not compatible with intent {intent!r}; "
|
|
213
|
-
"choose a compatible chart family or use intent custom with a clear rationale"
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def chart_encoding(chart: dict[str, Any] | None, role: str) -> dict[str, Any]:
|
|
218
|
-
encodings = chart.get("encodings") if isinstance(chart, dict) else None
|
|
219
|
-
if not isinstance(encodings, dict):
|
|
220
|
-
return {}
|
|
221
|
-
encoding = encodings.get(role)
|
|
222
|
-
return encoding if isinstance(encoding, dict) else {}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
def chart_encoding_field(chart: dict[str, Any] | None, role: str) -> str:
|
|
226
|
-
field = chart_encoding(chart, role).get("field")
|
|
227
|
-
return field if isinstance(field, str) else ""
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def chart_encoding_fields(chart: dict[str, Any] | None, role: str) -> list[str]:
|
|
231
|
-
fields = chart_encoding(chart, role).get("fields")
|
|
232
|
-
if not isinstance(fields, list):
|
|
233
|
-
return []
|
|
234
|
-
return [field for field in fields if isinstance(field, str) and field]
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def chart_y_fields(chart: dict[str, Any]) -> list[str]:
|
|
238
|
-
return chart_encoding_fields(chart, "y") or [chart_encoding_field(chart, "y")]
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def chart_quality_warnings(
|
|
242
|
-
chart: dict[str, Any],
|
|
243
|
-
rows: list[Any] | None = None,
|
|
244
|
-
*,
|
|
245
|
-
sibling_charts: list[dict[str, Any]] | None = None,
|
|
246
|
-
) -> list[str]:
|
|
247
|
-
warnings: list[str] = []
|
|
248
|
-
intent = chart_intent(chart)
|
|
249
|
-
if intent is None:
|
|
250
|
-
warnings.append("Chart is missing intent metadata.")
|
|
251
|
-
if not isinstance(chart.get("question"), str) or not chart.get("question", "").strip():
|
|
252
|
-
warnings.append("Chart is missing the question it answers.")
|
|
253
|
-
if not isinstance(chart.get("rationale"), str) or len(chart.get("rationale", "").strip()) < 24:
|
|
254
|
-
warnings.append("Chart rationale is missing or too terse.")
|
|
255
|
-
if intent in {"lookup", "status"}:
|
|
256
|
-
warnings.append(f"Intent {intent} may be clearer as a table or KPI card than a chart.")
|
|
257
|
-
if sibling_charts:
|
|
258
|
-
question = str(chart.get("question", "")).strip().lower()
|
|
259
|
-
signature = (
|
|
260
|
-
intent,
|
|
261
|
-
chart.get("dataset"),
|
|
262
|
-
chart_encoding_field(chart, "x"),
|
|
263
|
-
tuple(chart_y_fields(chart)),
|
|
264
|
-
)
|
|
265
|
-
for sibling in sibling_charts:
|
|
266
|
-
if sibling is chart:
|
|
267
|
-
continue
|
|
268
|
-
sibling_question = str(sibling.get("question", "")).strip().lower()
|
|
269
|
-
sibling_signature = (
|
|
270
|
-
chart_intent(sibling),
|
|
271
|
-
sibling.get("dataset"),
|
|
272
|
-
chart_encoding_field(sibling, "x"),
|
|
273
|
-
tuple(chart_y_fields(sibling)),
|
|
274
|
-
)
|
|
275
|
-
if question and question == sibling_question:
|
|
276
|
-
warnings.append("Chart repeats another chart question.")
|
|
277
|
-
break
|
|
278
|
-
if signature == sibling_signature:
|
|
279
|
-
warnings.append(
|
|
280
|
-
"Chart repeats another chart's intent, dataset, axis, and measures."
|
|
281
|
-
)
|
|
282
|
-
break
|
|
283
|
-
if rows is not None and chart.get("type") == "leaderboard" and len(rows) > LEADERBOARD_MAX_ROWS:
|
|
284
|
-
warnings.append(
|
|
285
|
-
"Leaderboard uses a larger backing row set; verify omitted rows are not material."
|
|
286
|
-
)
|
|
287
|
-
return warnings
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def validate_chart_presentation_options(chart: dict[str, Any], path: str) -> None:
|
|
291
|
-
palette = chart.get("palette")
|
|
292
|
-
if palette is not None:
|
|
293
|
-
palette_obj = require_object(palette, f"{path}.palette")
|
|
294
|
-
kind = palette_obj.get("kind")
|
|
295
|
-
if kind not in ALLOWED_PALETTE_KINDS:
|
|
296
|
-
raise ContractError(
|
|
297
|
-
f"{path}.palette.kind must be one of {sorted(ALLOWED_PALETTE_KINDS)}"
|
|
298
|
-
)
|
|
299
|
-
optional_string(palette_obj.get("name"), f"{path}.palette.name")
|
|
300
|
-
midpoint = palette_obj.get("midpoint")
|
|
301
|
-
if midpoint is not None and as_number(midpoint) is None:
|
|
302
|
-
raise ContractError(f"{path}.palette.midpoint must be a number when present")
|
|
303
|
-
|
|
304
|
-
legend = chart.get("legend")
|
|
305
|
-
if legend is not None:
|
|
306
|
-
legend_obj = require_object(legend, f"{path}.legend")
|
|
307
|
-
optional_bool(legend_obj.get("interactive"), f"{path}.legend.interactive")
|
|
308
|
-
position = legend_obj.get("position")
|
|
309
|
-
if position is not None and position not in ALLOWED_LEGEND_POSITIONS:
|
|
310
|
-
raise ContractError(
|
|
311
|
-
f"{path}.legend.position must be one of {sorted(ALLOWED_LEGEND_POSITIONS)}"
|
|
312
|
-
)
|
|
313
|
-
sort = legend_obj.get("sort")
|
|
314
|
-
if sort is not None and sort not in ALLOWED_LEGEND_SORTS:
|
|
315
|
-
raise ContractError(f"{path}.legend.sort must be one of {sorted(ALLOWED_LEGEND_SORTS)}")
|
|
316
|
-
optional_string(legend_obj.get("title"), f"{path}.legend.title")
|
|
317
|
-
|
|
318
|
-
labels = chart.get("labels")
|
|
319
|
-
if labels is not None:
|
|
320
|
-
labels_obj = require_object(labels, f"{path}.labels")
|
|
321
|
-
values = labels_obj.get("values")
|
|
322
|
-
if values is not None and values not in ALLOWED_VALUE_LABEL_MODES:
|
|
323
|
-
raise ContractError(
|
|
324
|
-
f"{path}.labels.values must be one of {sorted(ALLOWED_VALUE_LABEL_MODES)}"
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
reference_lines = chart.get("referenceLines")
|
|
328
|
-
if reference_lines is not None:
|
|
329
|
-
if not isinstance(reference_lines, list):
|
|
330
|
-
raise ContractError(f"{path}.referenceLines must be a list when present")
|
|
331
|
-
for idx, line in enumerate(reference_lines):
|
|
332
|
-
line_obj = require_object(line, f"{path}.referenceLines[{idx}]")
|
|
333
|
-
value = line_obj.get("value")
|
|
334
|
-
if not isinstance(value, (int, float, str)) or isinstance(value, bool):
|
|
335
|
-
raise ContractError(
|
|
336
|
-
f"{path}.referenceLines[{idx}].value must be a string or number"
|
|
337
|
-
)
|
|
338
|
-
axis = line_obj.get("axis")
|
|
339
|
-
if axis is not None and axis not in {"x", "y"}:
|
|
340
|
-
raise ContractError(f"{path}.referenceLines[{idx}].axis must be x or y")
|
|
341
|
-
color = line_obj.get("color")
|
|
342
|
-
if color is not None and color not in ALLOWED_SERIES_COLORS:
|
|
343
|
-
raise ContractError(
|
|
344
|
-
f"{path}.referenceLines[{idx}].color must be one of "
|
|
345
|
-
f"{sorted(ALLOWED_SERIES_COLORS)}"
|
|
346
|
-
)
|
|
347
|
-
line_style = line_obj.get("lineStyle")
|
|
348
|
-
if line_style is not None and line_style not in ALLOWED_SERIES_LINE_STYLES:
|
|
349
|
-
raise ContractError(
|
|
350
|
-
f"{path}.referenceLines[{idx}].lineStyle must be one of "
|
|
351
|
-
f"{sorted(ALLOWED_SERIES_LINE_STYLES)}"
|
|
352
|
-
)
|
|
353
|
-
optional_string(line_obj.get("label"), f"{path}.referenceLines[{idx}].label")
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
def as_number(value: Any) -> float | None:
|
|
357
|
-
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
|
358
|
-
return None
|
|
359
|
-
return float(value)
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
def chart_palette_kind(chart: dict[str, Any] | None) -> str | None:
|
|
363
|
-
palette = chart.get("palette") if isinstance(chart, dict) else None
|
|
364
|
-
if not isinstance(palette, dict):
|
|
365
|
-
return None
|
|
366
|
-
kind = palette.get("kind")
|
|
367
|
-
return kind if isinstance(kind, str) else None
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
def chart_has_fixed_measure_color(chart: dict[str, Any] | None) -> bool:
|
|
371
|
-
color = chart_encoding(chart, "color")
|
|
372
|
-
return isinstance(color.get("scale"), str) and bool(color.get("scale"))
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
def validate_chart_field_compatibility(
|
|
376
|
-
chart_type: str,
|
|
377
|
-
x_field: str,
|
|
378
|
-
fields: list[str],
|
|
379
|
-
path: str,
|
|
380
|
-
chart: dict[str, Any] | None = None,
|
|
381
|
-
) -> None:
|
|
382
|
-
if not field_looks_like_metric_definition(x_field):
|
|
383
|
-
return
|
|
384
|
-
|
|
385
|
-
if chart_type == "leaderboard":
|
|
386
|
-
raise ContractError(
|
|
387
|
-
f"{path} ranks metric definitions against each other; use KPI cards, "
|
|
388
|
-
"a compact table, or a trend/share chart instead"
|
|
389
|
-
)
|
|
390
|
-
|
|
391
|
-
if chart_type not in {"bar", "horizontalBar"}:
|
|
392
|
-
return
|
|
393
|
-
|
|
394
|
-
if any(
|
|
395
|
-
marker in field.lower() for field in fields for marker in MIXED_METRIC_CHANGE_FIELD_MARKERS
|
|
396
|
-
):
|
|
397
|
-
if chart_palette_kind(chart) != "categorical" or chart_has_fixed_measure_color(chart):
|
|
398
|
-
raise ContractError(
|
|
399
|
-
f"{path} compares movement across different metric names; use "
|
|
400
|
-
'palette.kind "categorical" and omit fixed measure colors so each metric '
|
|
401
|
-
"bar is encoded as a distinct category"
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
def validate_chart_data_compatibility(chart: dict[str, Any], rows: list[Any], path: str) -> None:
|
|
406
|
-
chart_type = chart.get("type")
|
|
407
|
-
validate_chart_intent_compatibility(chart_type, chart, path)
|
|
408
|
-
fields = [field for field in chart_y_fields(chart) if field]
|
|
409
|
-
if not rows:
|
|
410
|
-
return
|
|
411
|
-
|
|
412
|
-
for field in fields:
|
|
413
|
-
has_numeric_value = any(
|
|
414
|
-
isinstance(row, dict) and as_number(row.get(field)) is not None for row in rows
|
|
415
|
-
)
|
|
416
|
-
if not has_numeric_value:
|
|
417
|
-
raise ContractError(
|
|
418
|
-
f"{path}.encodings.y field {field!r} must reference a numeric "
|
|
419
|
-
"dataset field with at least one numeric value"
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
if (
|
|
423
|
-
chart_type not in SINGLE_SERIES_CHART_TYPES | INTRINSIC_MULTI_SERIES_CHART_TYPES
|
|
424
|
-
and len(fields) > 1
|
|
425
|
-
):
|
|
426
|
-
maxima = []
|
|
427
|
-
for field in fields:
|
|
428
|
-
max_abs = max(
|
|
429
|
-
[
|
|
430
|
-
abs(value)
|
|
431
|
-
for row in rows
|
|
432
|
-
if isinstance(row, dict)
|
|
433
|
-
if (value := as_number(row.get(field))) is not None
|
|
434
|
-
],
|
|
435
|
-
default=0,
|
|
436
|
-
)
|
|
437
|
-
if max_abs > 0:
|
|
438
|
-
maxima.append(max_abs)
|
|
439
|
-
if len(maxima) > 1 and max(maxima) / min(maxima) >= MIXED_SCALE_SERIES_RATIO:
|
|
440
|
-
raise ContractError(
|
|
441
|
-
f"{path} combines measures with materially different scales; "
|
|
442
|
-
"split them into separate chart cards"
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
if chart_type not in {"bar", "horizontalBar", "leaderboard", "waterfall"} or len(fields) != 1:
|
|
446
|
-
return
|
|
447
|
-
|
|
448
|
-
chart_markers = " ".join(
|
|
449
|
-
str(value).lower()
|
|
450
|
-
for value in (
|
|
451
|
-
chart.get("id", ""),
|
|
452
|
-
chart.get("title", ""),
|
|
453
|
-
chart.get("dataset", ""),
|
|
454
|
-
chart_encoding_field(chart, "x"),
|
|
455
|
-
fields[0],
|
|
456
|
-
)
|
|
457
|
-
)
|
|
458
|
-
if not any(marker in chart_markers for marker in DECOMPOSITION_FIELD_MARKERS):
|
|
459
|
-
return
|
|
460
|
-
|
|
461
|
-
field = fields[0]
|
|
462
|
-
values = [
|
|
463
|
-
abs(value)
|
|
464
|
-
for row in rows
|
|
465
|
-
if isinstance(row, dict)
|
|
466
|
-
if (value := as_number(row.get(field))) is not None and abs(value) > 0
|
|
467
|
-
]
|
|
468
|
-
if len(values) > 1 and max(values) / min(values) >= MIXED_SCALE_SERIES_RATIO:
|
|
469
|
-
raise ContractError(
|
|
470
|
-
f"{path} renders decomposition components with materially different scales; "
|
|
471
|
-
"split dominant and small factors into separate chart cards or use a compact table"
|
|
472
|
-
)
|