@ztothez/design-engineering 2.0.0
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/LICENSE +15 -0
- package/README.md +448 -0
- package/ROADMAP.md +127 -0
- package/SKILL.md +698 -0
- package/V2-ROADMAP.md +431 -0
- package/V3-ROADMAP.md +605 -0
- package/V4-ROADMAP.md +283 -0
- package/clean-room-ux-design-spec.md +1431 -0
- package/dist/cli/aggregate-gates.d.ts +2 -0
- package/dist/cli/aggregate-gates.js +86 -0
- package/dist/cli/aggregate-gates.js.map +1 -0
- package/dist/cli/assess-maintainer-review.d.ts +2 -0
- package/dist/cli/assess-maintainer-review.js +72 -0
- package/dist/cli/assess-maintainer-review.js.map +1 -0
- package/dist/cli/audit.d.ts +2 -0
- package/dist/cli/audit.js +71 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/compile-comparison-review.d.ts +2 -0
- package/dist/cli/compile-comparison-review.js +154 -0
- package/dist/cli/compile-comparison-review.js.map +1 -0
- package/dist/cli/compile-plan.d.ts +2 -0
- package/dist/cli/compile-plan.js +66 -0
- package/dist/cli/compile-plan.js.map +1 -0
- package/dist/cli/evaluate-corpus.d.ts +2 -0
- package/dist/cli/evaluate-corpus.js +65 -0
- package/dist/cli/evaluate-corpus.js.map +1 -0
- package/dist/cli/generate-react.d.ts +2 -0
- package/dist/cli/generate-react.js +83 -0
- package/dist/cli/generate-react.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +58 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/portfolio.d.ts +2 -0
- package/dist/cli/portfolio.js +316 -0
- package/dist/cli/portfolio.js.map +1 -0
- package/dist/cli/quality-gate.d.ts +2 -0
- package/dist/cli/quality-gate.js +131 -0
- package/dist/cli/quality-gate.js.map +1 -0
- package/dist/cli/repair-react.d.ts +2 -0
- package/dist/cli/repair-react.js +163 -0
- package/dist/cli/repair-react.js.map +1 -0
- package/dist/cli/review-heuristics.d.ts +2 -0
- package/dist/cli/review-heuristics.js +68 -0
- package/dist/cli/review-heuristics.js.map +1 -0
- package/dist/cli/validate-brief.d.ts +2 -0
- package/dist/cli/validate-brief.js +58 -0
- package/dist/cli/validate-brief.js.map +1 -0
- package/dist/cli/validate-comparison.d.ts +2 -0
- package/dist/cli/validate-comparison.js +68 -0
- package/dist/cli/validate-comparison.js.map +1 -0
- package/dist/cli/validate-contract.d.ts +2 -0
- package/dist/cli/validate-contract.js +54 -0
- package/dist/cli/validate-contract.js.map +1 -0
- package/dist/cli/validate-design.d.ts +2 -0
- package/dist/cli/validate-design.js +53 -0
- package/dist/cli/validate-design.js.map +1 -0
- package/dist/cli/validate-information.d.ts +2 -0
- package/dist/cli/validate-information.js +53 -0
- package/dist/cli/validate-information.js.map +1 -0
- package/dist/cli/validate-trust.d.ts +2 -0
- package/dist/cli/validate-trust.js +53 -0
- package/dist/cli/validate-trust.js.map +1 -0
- package/dist/cli/verify-ui.d.ts +2 -0
- package/dist/cli/verify-ui.js +181 -0
- package/dist/cli/verify-ui.js.map +1 -0
- package/dist/src/acceptance/evaluator.d.ts +13 -0
- package/dist/src/acceptance/evaluator.js +201 -0
- package/dist/src/acceptance/evaluator.js.map +1 -0
- package/dist/src/acceptance/loader.d.ts +2 -0
- package/dist/src/acceptance/loader.js +18 -0
- package/dist/src/acceptance/loader.js.map +1 -0
- package/dist/src/acceptance/report.d.ts +2 -0
- package/dist/src/acceptance/report.js +18 -0
- package/dist/src/acceptance/report.js.map +1 -0
- package/dist/src/acceptance/schema.d.ts +64 -0
- package/dist/src/acceptance/schema.js +57 -0
- package/dist/src/acceptance/schema.js.map +1 -0
- package/dist/src/acceptance/types.d.ts +47 -0
- package/dist/src/acceptance/types.js +2 -0
- package/dist/src/acceptance/types.js.map +1 -0
- package/dist/src/aggregate/report.d.ts +2 -0
- package/dist/src/aggregate/report.js +33 -0
- package/dist/src/aggregate/report.js.map +1 -0
- package/dist/src/aggregate/runner.d.ts +2 -0
- package/dist/src/aggregate/runner.js +165 -0
- package/dist/src/aggregate/runner.js.map +1 -0
- package/dist/src/aggregate/schema.d.ts +182 -0
- package/dist/src/aggregate/schema.js +54 -0
- package/dist/src/aggregate/schema.js.map +1 -0
- package/dist/src/aggregate/types.d.ts +57 -0
- package/dist/src/aggregate/types.js +2 -0
- package/dist/src/aggregate/types.js.map +1 -0
- package/dist/src/audit/policy.d.ts +3 -0
- package/dist/src/audit/policy.js +45 -0
- package/dist/src/audit/policy.js.map +1 -0
- package/dist/src/audit/report.d.ts +2 -0
- package/dist/src/audit/report.js +32 -0
- package/dist/src/audit/report.js.map +1 -0
- package/dist/src/audit/rules/accessibility-name.d.ts +2 -0
- package/dist/src/audit/rules/accessibility-name.js +64 -0
- package/dist/src/audit/rules/accessibility-name.js.map +1 -0
- package/dist/src/audit/rules/component-size.d.ts +2 -0
- package/dist/src/audit/rules/component-size.js +27 -0
- package/dist/src/audit/rules/component-size.js.map +1 -0
- package/dist/src/audit/rules/credential-placeholder.d.ts +2 -0
- package/dist/src/audit/rules/credential-placeholder.js +83 -0
- package/dist/src/audit/rules/credential-placeholder.js.map +1 -0
- package/dist/src/audit/rules/helpers.d.ts +16 -0
- package/dist/src/audit/rules/helpers.js +64 -0
- package/dist/src/audit/rules/helpers.js.map +1 -0
- package/dist/src/audit/rules/index.d.ts +2 -0
- package/dist/src/audit/rules/index.js +23 -0
- package/dist/src/audit/rules/index.js.map +1 -0
- package/dist/src/audit/rules/interactive-integrity.d.ts +2 -0
- package/dist/src/audit/rules/interactive-integrity.js +111 -0
- package/dist/src/audit/rules/interactive-integrity.js.map +1 -0
- package/dist/src/audit/rules/mixed-responsibilities.d.ts +2 -0
- package/dist/src/audit/rules/mixed-responsibilities.js +39 -0
- package/dist/src/audit/rules/mixed-responsibilities.js.map +1 -0
- package/dist/src/audit/rules/mock-production-path.d.ts +2 -0
- package/dist/src/audit/rules/mock-production-path.js +39 -0
- package/dist/src/audit/rules/mock-production-path.js.map +1 -0
- package/dist/src/audit/rules/network-state.d.ts +2 -0
- package/dist/src/audit/rules/network-state.js +39 -0
- package/dist/src/audit/rules/network-state.js.map +1 -0
- package/dist/src/audit/rules/operational-claim.d.ts +2 -0
- package/dist/src/audit/rules/operational-claim.js +94 -0
- package/dist/src/audit/rules/operational-claim.js.map +1 -0
- package/dist/src/audit/rules/placeholder-interaction.d.ts +2 -0
- package/dist/src/audit/rules/placeholder-interaction.js +46 -0
- package/dist/src/audit/rules/placeholder-interaction.js.map +1 -0
- package/dist/src/audit/rules/raw-design-values.d.ts +2 -0
- package/dist/src/audit/rules/raw-design-values.js +97 -0
- package/dist/src/audit/rules/raw-design-values.js.map +1 -0
- package/dist/src/audit/scanner.d.ts +2 -0
- package/dist/src/audit/scanner.js +215 -0
- package/dist/src/audit/scanner.js.map +1 -0
- package/dist/src/audit/types.d.ts +62 -0
- package/dist/src/audit/types.js +2 -0
- package/dist/src/audit/types.js.map +1 -0
- package/dist/src/comparison/evaluator.d.ts +2 -0
- package/dist/src/comparison/evaluator.js +478 -0
- package/dist/src/comparison/evaluator.js.map +1 -0
- package/dist/src/comparison/loader.d.ts +3 -0
- package/dist/src/comparison/loader.js +26 -0
- package/dist/src/comparison/loader.js.map +1 -0
- package/dist/src/comparison/maintainer.d.ts +47 -0
- package/dist/src/comparison/maintainer.js +218 -0
- package/dist/src/comparison/maintainer.js.map +1 -0
- package/dist/src/comparison/report.d.ts +2 -0
- package/dist/src/comparison/report.js +48 -0
- package/dist/src/comparison/report.js.map +1 -0
- package/dist/src/comparison/schema.d.ts +464 -0
- package/dist/src/comparison/schema.js +502 -0
- package/dist/src/comparison/schema.js.map +1 -0
- package/dist/src/contracts/archetypes.d.ts +21 -0
- package/dist/src/contracts/archetypes.js +102 -0
- package/dist/src/contracts/archetypes.js.map +1 -0
- package/dist/src/contracts/journeys.d.ts +7 -0
- package/dist/src/contracts/journeys.js +32 -0
- package/dist/src/contracts/journeys.js.map +1 -0
- package/dist/src/contracts/report.d.ts +2 -0
- package/dist/src/contracts/report.js +33 -0
- package/dist/src/contracts/report.js.map +1 -0
- package/dist/src/contracts/schema.d.ts +1038 -0
- package/dist/src/contracts/schema.js +385 -0
- package/dist/src/contracts/schema.js.map +1 -0
- package/dist/src/contracts/validator.d.ts +12 -0
- package/dist/src/contracts/validator.js +303 -0
- package/dist/src/contracts/validator.js.map +1 -0
- package/dist/src/corpus/evaluator.d.ts +2 -0
- package/dist/src/corpus/evaluator.js +203 -0
- package/dist/src/corpus/evaluator.js.map +1 -0
- package/dist/src/corpus/loader.d.ts +2 -0
- package/dist/src/corpus/loader.js +20 -0
- package/dist/src/corpus/loader.js.map +1 -0
- package/dist/src/corpus/report.d.ts +2 -0
- package/dist/src/corpus/report.js +33 -0
- package/dist/src/corpus/report.js.map +1 -0
- package/dist/src/corpus/schema.d.ts +316 -0
- package/dist/src/corpus/schema.js +269 -0
- package/dist/src/corpus/schema.js.map +1 -0
- package/dist/src/design-intelligence/loader.d.ts +2 -0
- package/dist/src/design-intelligence/loader.js +21 -0
- package/dist/src/design-intelligence/loader.js.map +1 -0
- package/dist/src/design-intelligence/report.d.ts +2 -0
- package/dist/src/design-intelligence/report.js +36 -0
- package/dist/src/design-intelligence/report.js.map +1 -0
- package/dist/src/design-intelligence/schema.d.ts +838 -0
- package/dist/src/design-intelligence/schema.js +854 -0
- package/dist/src/design-intelligence/schema.js.map +1 -0
- package/dist/src/design-intelligence/validator.d.ts +2 -0
- package/dist/src/design-intelligence/validator.js +1371 -0
- package/dist/src/design-intelligence/validator.js.map +1 -0
- package/dist/src/design-plan/compiler.d.ts +8 -0
- package/dist/src/design-plan/compiler.js +288 -0
- package/dist/src/design-plan/compiler.js.map +1 -0
- package/dist/src/design-plan/report.d.ts +2 -0
- package/dist/src/design-plan/report.js +28 -0
- package/dist/src/design-plan/report.js.map +1 -0
- package/dist/src/design-plan/schema.d.ts +202 -0
- package/dist/src/design-plan/schema.js +76 -0
- package/dist/src/design-plan/schema.js.map +1 -0
- package/dist/src/generation/loader.d.ts +2 -0
- package/dist/src/generation/loader.js +21 -0
- package/dist/src/generation/loader.js.map +1 -0
- package/dist/src/generation/policy.d.ts +12 -0
- package/dist/src/generation/policy.js +62 -0
- package/dist/src/generation/policy.js.map +1 -0
- package/dist/src/generation/react-typescript.d.ts +6 -0
- package/dist/src/generation/react-typescript.js +538 -0
- package/dist/src/generation/react-typescript.js.map +1 -0
- package/dist/src/generation/report.d.ts +2 -0
- package/dist/src/generation/report.js +21 -0
- package/dist/src/generation/report.js.map +1 -0
- package/dist/src/generation/schema.d.ts +44 -0
- package/dist/src/generation/schema.js +50 -0
- package/dist/src/generation/schema.js.map +1 -0
- package/dist/src/generation/templates/tokens.d.ts +1 -0
- package/dist/src/generation/templates/tokens.js +59 -0
- package/dist/src/generation/templates/tokens.js.map +1 -0
- package/dist/src/heuristics/evaluator.d.ts +2 -0
- package/dist/src/heuristics/evaluator.js +65 -0
- package/dist/src/heuristics/evaluator.js.map +1 -0
- package/dist/src/heuristics/loader.d.ts +2 -0
- package/dist/src/heuristics/loader.js +21 -0
- package/dist/src/heuristics/loader.js.map +1 -0
- package/dist/src/heuristics/report.d.ts +3 -0
- package/dist/src/heuristics/report.js +31 -0
- package/dist/src/heuristics/report.js.map +1 -0
- package/dist/src/heuristics/schema.d.ts +198 -0
- package/dist/src/heuristics/schema.js +197 -0
- package/dist/src/heuristics/schema.js.map +1 -0
- package/dist/src/information-design/loader.d.ts +2 -0
- package/dist/src/information-design/loader.js +21 -0
- package/dist/src/information-design/loader.js.map +1 -0
- package/dist/src/information-design/report.d.ts +2 -0
- package/dist/src/information-design/report.js +27 -0
- package/dist/src/information-design/report.js.map +1 -0
- package/dist/src/information-design/schema.d.ts +370 -0
- package/dist/src/information-design/schema.js +329 -0
- package/dist/src/information-design/schema.js.map +1 -0
- package/dist/src/information-design/validator.d.ts +2 -0
- package/dist/src/information-design/validator.js +242 -0
- package/dist/src/information-design/validator.js.map +1 -0
- package/dist/src/interface-trust/loader.d.ts +2 -0
- package/dist/src/interface-trust/loader.js +21 -0
- package/dist/src/interface-trust/loader.js.map +1 -0
- package/dist/src/interface-trust/report.d.ts +2 -0
- package/dist/src/interface-trust/report.js +26 -0
- package/dist/src/interface-trust/report.js.map +1 -0
- package/dist/src/interface-trust/schema.d.ts +299 -0
- package/dist/src/interface-trust/schema.js +238 -0
- package/dist/src/interface-trust/schema.js.map +1 -0
- package/dist/src/interface-trust/validator.d.ts +2 -0
- package/dist/src/interface-trust/validator.js +283 -0
- package/dist/src/interface-trust/validator.js.map +1 -0
- package/dist/src/portfolio/adapter-report.d.ts +3 -0
- package/dist/src/portfolio/adapter-report.js +38 -0
- package/dist/src/portfolio/adapter-report.js.map +1 -0
- package/dist/src/portfolio/adapters.d.ts +37 -0
- package/dist/src/portfolio/adapters.js +325 -0
- package/dist/src/portfolio/adapters.js.map +1 -0
- package/dist/src/portfolio/evidence.d.ts +9 -0
- package/dist/src/portfolio/evidence.js +233 -0
- package/dist/src/portfolio/evidence.js.map +1 -0
- package/dist/src/portfolio/files.d.ts +8 -0
- package/dist/src/portfolio/files.js +77 -0
- package/dist/src/portfolio/files.js.map +1 -0
- package/dist/src/portfolio/fixture-server.d.ts +11 -0
- package/dist/src/portfolio/fixture-server.js +131 -0
- package/dist/src/portfolio/fixture-server.js.map +1 -0
- package/dist/src/portfolio/loader.d.ts +2 -0
- package/dist/src/portfolio/loader.js +21 -0
- package/dist/src/portfolio/loader.js.map +1 -0
- package/dist/src/portfolio/mcp.d.ts +186 -0
- package/dist/src/portfolio/mcp.js +117 -0
- package/dist/src/portfolio/mcp.js.map +1 -0
- package/dist/src/portfolio/promotion-schema.d.ts +220 -0
- package/dist/src/portfolio/promotion-schema.js +148 -0
- package/dist/src/portfolio/promotion-schema.js.map +1 -0
- package/dist/src/portfolio/promotion.d.ts +4 -0
- package/dist/src/portfolio/promotion.js +160 -0
- package/dist/src/portfolio/promotion.js.map +1 -0
- package/dist/src/portfolio/qualification-schema.d.ts +268 -0
- package/dist/src/portfolio/qualification-schema.js +112 -0
- package/dist/src/portfolio/qualification-schema.js.map +1 -0
- package/dist/src/portfolio/qualification.d.ts +4 -0
- package/dist/src/portfolio/qualification.js +157 -0
- package/dist/src/portfolio/qualification.js.map +1 -0
- package/dist/src/portfolio/registry.d.ts +34 -0
- package/dist/src/portfolio/registry.js +240 -0
- package/dist/src/portfolio/registry.js.map +1 -0
- package/dist/src/portfolio/report.d.ts +4 -0
- package/dist/src/portfolio/report.js +47 -0
- package/dist/src/portfolio/report.js.map +1 -0
- package/dist/src/portfolio/run-schema.d.ts +135 -0
- package/dist/src/portfolio/run-schema.js +81 -0
- package/dist/src/portfolio/run-schema.js.map +1 -0
- package/dist/src/portfolio/runner.d.ts +118 -0
- package/dist/src/portfolio/runner.js +423 -0
- package/dist/src/portfolio/runner.js.map +1 -0
- package/dist/src/portfolio/schema.d.ts +251 -0
- package/dist/src/portfolio/schema.js +317 -0
- package/dist/src/portfolio/schema.js.map +1 -0
- package/dist/src/portfolio/snapshot.d.ts +89 -0
- package/dist/src/portfolio/snapshot.js +548 -0
- package/dist/src/portfolio/snapshot.js.map +1 -0
- package/dist/src/portfolio/taxonomy-schema.d.ts +215 -0
- package/dist/src/portfolio/taxonomy-schema.js +74 -0
- package/dist/src/portfolio/taxonomy-schema.js.map +1 -0
- package/dist/src/portfolio/taxonomy.d.ts +5 -0
- package/dist/src/portfolio/taxonomy.js +236 -0
- package/dist/src/portfolio/taxonomy.js.map +1 -0
- package/dist/src/portfolio/vault.d.ts +53 -0
- package/dist/src/portfolio/vault.js +176 -0
- package/dist/src/portfolio/vault.js.map +1 -0
- package/dist/src/product-brief/loader.d.ts +2 -0
- package/dist/src/product-brief/loader.js +21 -0
- package/dist/src/product-brief/loader.js.map +1 -0
- package/dist/src/product-brief/report.d.ts +2 -0
- package/dist/src/product-brief/report.js +22 -0
- package/dist/src/product-brief/report.js.map +1 -0
- package/dist/src/product-brief/schema.d.ts +367 -0
- package/dist/src/product-brief/schema.js +272 -0
- package/dist/src/product-brief/schema.js.map +1 -0
- package/dist/src/product-brief/validator.d.ts +2 -0
- package/dist/src/product-brief/validator.js +251 -0
- package/dist/src/product-brief/validator.js.map +1 -0
- package/dist/src/product.d.ts +7 -0
- package/dist/src/product.js +28 -0
- package/dist/src/product.js.map +1 -0
- package/dist/src/quality-gate/report.d.ts +2 -0
- package/dist/src/quality-gate/report.js +46 -0
- package/dist/src/quality-gate/report.js.map +1 -0
- package/dist/src/quality-gate/runner.d.ts +2 -0
- package/dist/src/quality-gate/runner.js +175 -0
- package/dist/src/quality-gate/runner.js.map +1 -0
- package/dist/src/quality-gate/schema.d.ts +75 -0
- package/dist/src/quality-gate/schema.js +37 -0
- package/dist/src/quality-gate/schema.js.map +1 -0
- package/dist/src/quality-gate/types.d.ts +49 -0
- package/dist/src/quality-gate/types.js +2 -0
- package/dist/src/quality-gate/types.js.map +1 -0
- package/dist/src/repair/loader.d.ts +2 -0
- package/dist/src/repair/loader.js +11 -0
- package/dist/src/repair/loader.js.map +1 -0
- package/dist/src/repair/policy.d.ts +16 -0
- package/dist/src/repair/policy.js +65 -0
- package/dist/src/repair/policy.js.map +1 -0
- package/dist/src/repair/report.d.ts +2 -0
- package/dist/src/repair/report.js +32 -0
- package/dist/src/repair/report.js.map +1 -0
- package/dist/src/repair/runner.d.ts +17 -0
- package/dist/src/repair/runner.js +511 -0
- package/dist/src/repair/runner.js.map +1 -0
- package/dist/src/repair/schema.d.ts +264 -0
- package/dist/src/repair/schema.js +202 -0
- package/dist/src/repair/schema.js.map +1 -0
- package/dist/src/retrieval/report.d.ts +2 -0
- package/dist/src/retrieval/report.js +21 -0
- package/dist/src/retrieval/report.js.map +1 -0
- package/dist/src/retrieval/schema.d.ts +123 -0
- package/dist/src/retrieval/schema.js +77 -0
- package/dist/src/retrieval/schema.js.map +1 -0
- package/dist/src/retrieval/search.d.ts +26 -0
- package/dist/src/retrieval/search.js +415 -0
- package/dist/src/retrieval/search.js.map +1 -0
- package/dist/src/runtime/advanced-checks.d.ts +6 -0
- package/dist/src/runtime/advanced-checks.js +487 -0
- package/dist/src/runtime/advanced-checks.js.map +1 -0
- package/dist/src/runtime/composition-checks.d.ts +5 -0
- package/dist/src/runtime/composition-checks.js +307 -0
- package/dist/src/runtime/composition-checks.js.map +1 -0
- package/dist/src/runtime/interface-checks.d.ts +12 -0
- package/dist/src/runtime/interface-checks.js +224 -0
- package/dist/src/runtime/interface-checks.js.map +1 -0
- package/dist/src/runtime/policy.d.ts +13 -0
- package/dist/src/runtime/policy.js +97 -0
- package/dist/src/runtime/policy.js.map +1 -0
- package/dist/src/runtime/report.d.ts +2 -0
- package/dist/src/runtime/report.js +48 -0
- package/dist/src/runtime/report.js.map +1 -0
- package/dist/src/runtime/schema.d.ts +406 -0
- package/dist/src/runtime/schema.js +308 -0
- package/dist/src/runtime/schema.js.map +1 -0
- package/dist/src/runtime/types.d.ts +177 -0
- package/dist/src/runtime/types.js +2 -0
- package/dist/src/runtime/types.js.map +1 -0
- package/dist/src/runtime/verifier.d.ts +2 -0
- package/dist/src/runtime/verifier.js +1201 -0
- package/dist/src/runtime/verifier.js.map +1 -0
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.js +1352 -0
- package/dist/src/server.js.map +1 -0
- package/docs/installation.md +337 -0
- package/knowledge-base/INDEX.md +285 -0
- package/knowledge-base/benchmarks/aegisops/CALIBRATION.md +52 -0
- package/knowledge-base/benchmarks/aegisops/MANIFEST.md +56 -0
- package/knowledge-base/benchmarks/aegisops/SOURCE-EVIDENCE.md +45 -0
- package/knowledge-base/benchmarks/aegisops/acceptance-criteria.md +42 -0
- package/knowledge-base/benchmarks/aegisops/anti-patterns.md +19 -0
- package/knowledge-base/benchmarks/aegisops/attestations.template.yaml +3 -0
- package/knowledge-base/benchmarks/aegisops/attestations.yaml +115 -0
- package/knowledge-base/benchmarks/aegisops/journeys.json +91 -0
- package/knowledge-base/benchmarks/aegisops/product-contract.yaml +328 -0
- package/knowledge-base/benchmarks/azure-optimizer/SOURCE-EVIDENCE.md +26 -0
- package/knowledge-base/benchmarks/azure-optimizer/V2-IMPLEMENTATION.md +39 -0
- package/knowledge-base/benchmarks/azure-optimizer/acceptance-criteria.md +23 -0
- package/knowledge-base/benchmarks/azure-optimizer/anti-patterns.md +13 -0
- package/knowledge-base/benchmarks/azure-optimizer/journeys.json +88 -0
- package/knowledge-base/benchmarks/azure-optimizer/product-contract.yaml +216 -0
- package/knowledge-base/benchmarks/azure-optimizer/v2-human-review-methodology.yaml +171 -0
- package/knowledge-base/benchmarks/azure-optimizer/v2-journeys.json +139 -0
- package/knowledge-base/benchmarks/corpus/PROVENANCE.md +21 -0
- package/knowledge-base/benchmarks/corpus/README.md +30 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-negative/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-negative/src/FakeDashboard.tsx +10 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-positive/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-positive/src/Progress.tsx +15 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-negative/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-negative/src/OperationsPanel.tsx +40 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/src/Dashboard.tsx +17 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/src/theme.css +15 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/SOURCE-EVIDENCE.md +3 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/journeys.json +20 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/product-contract.yaml +78 -0
- package/knowledge-base/benchmarks/corpus/corpus.schema.yaml +159 -0
- package/knowledge-base/benchmarks/corpus/corpus.yaml +209 -0
- package/knowledge-base/benchmarks/interface-quality/README.md +26 -0
- package/knowledge-base/benchmarks/interface-quality/SOLO-MAINTAINER-TRACK.md +35 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology-v1.1.schema.yaml +288 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology.schema.yaml +235 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology.template.yaml +181 -0
- package/knowledge-base/benchmarks/interface-quality/evidence/example-runtime-report.json +11 -0
- package/knowledge-base/benchmarks/interface-quality/review-session.schema.yaml +14 -0
- package/knowledge-base/benchmarks/interface-quality/review.schema.yaml +296 -0
- package/knowledge-base/benchmarks/interface-quality/review.template.yaml +43 -0
- package/knowledge-base/benchmarks/portfolio-corpus/ADAPTERS.md +68 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PORTFOLIO-RUNNER.md +131 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PRODUCT-TASK-CONTRACTS.md +29 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PROMOTED-RULES.md +31 -0
- package/knowledge-base/benchmarks/portfolio-corpus/archetype-profiles.yaml +26 -0
- package/knowledge-base/benchmarks/portfolio-corpus/product-task-profile.schema.yaml +105 -0
- package/knowledge-base/benchmarks/portfolio-corpus/registry.schema.yaml +188 -0
- package/knowledge-base/benchmarks/portfolio-corpus/registry.template.yaml +63 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-holdout-evaluation.template.json +14 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-promotion-evidence.template.json +24 -0
- package/knowledge-base/benchmarks/portfolio-corpus/v3-command-evidence.template.json +17 -0
- package/knowledge-base/benchmarks/portfolio-corpus/v3-qualification-evidence.template.json +29 -0
- package/knowledge-base/benchmarks/scenestart/CALIBRATION.md +95 -0
- package/knowledge-base/benchmarks/scenestart/MANIFEST.md +53 -0
- package/knowledge-base/benchmarks/scenestart/SOURCE-EVIDENCE.md +43 -0
- package/knowledge-base/benchmarks/scenestart/acceptance-criteria.md +59 -0
- package/knowledge-base/benchmarks/scenestart/anti-patterns.md +26 -0
- package/knowledge-base/benchmarks/scenestart/attestations.template.yaml +3 -0
- package/knowledge-base/benchmarks/scenestart/attestations.yaml +21 -0
- package/knowledge-base/benchmarks/scenestart/human-review.md +99 -0
- package/knowledge-base/benchmarks/scenestart/human-review.template.md +105 -0
- package/knowledge-base/benchmarks/scenestart/journeys.json +141 -0
- package/knowledge-base/benchmarks/scenestart/product-contract.yaml +427 -0
- package/knowledge-base/dependencies.yaml +69 -0
- package/knowledge-base/design-intelligence/MASTER.md +87 -0
- package/knowledge-base/design-intelligence/asset-generation.md +66 -0
- package/knowledge-base/design-intelligence/brand-systems.md +69 -0
- package/knowledge-base/design-intelligence/closed-loop-repair.md +95 -0
- package/knowledge-base/design-intelligence/design-deliverable.schema.yaml +1194 -0
- package/knowledge-base/design-intelligence/design-deliverable.template.yaml +591 -0
- package/knowledge-base/design-intelligence/design-plan.md +78 -0
- package/knowledge-base/design-intelligence/design-plan.schema.yaml +621 -0
- package/knowledge-base/design-intelligence/figma-production.md +63 -0
- package/knowledge-base/design-intelligence/generation-adapter.md +72 -0
- package/knowledge-base/design-intelligence/generation-adapter.schema.yaml +47 -0
- package/knowledge-base/design-intelligence/iconography.md +46 -0
- package/knowledge-base/design-intelligence/information-design.md +104 -0
- package/knowledge-base/design-intelligence/information-design.schema.yaml +390 -0
- package/knowledge-base/design-intelligence/information-design.template.yaml +281 -0
- package/knowledge-base/design-intelligence/interaction-recovery-verification.md +72 -0
- package/knowledge-base/design-intelligence/interface-trust.md +103 -0
- package/knowledge-base/design-intelligence/interface-trust.schema.yaml +263 -0
- package/knowledge-base/design-intelligence/interface-trust.template.yaml +173 -0
- package/knowledge-base/design-intelligence/licensing-and-provenance.md +59 -0
- package/knowledge-base/design-intelligence/presentation-design.md +56 -0
- package/knowledge-base/design-intelligence/product-design-brief.md +67 -0
- package/knowledge-base/design-intelligence/product-design-brief.schema.yaml +279 -0
- package/knowledge-base/design-intelligence/product-design-brief.template.yaml +225 -0
- package/knowledge-base/design-intelligence/repair-request.schema.yaml +95 -0
- package/knowledge-base/design-intelligence/repair-request.template.yaml +39 -0
- package/knowledge-base/design-intelligence/visual-accessibility.md +56 -0
- package/knowledge-base/design-intelligence/visual-polish.md +172 -0
- package/knowledge-base/maintained/architecture/MASTER.md +22 -0
- package/knowledge-base/maintained/architecture/component-boundaries.md +30 -0
- package/knowledge-base/maintained/architecture/product-platforms.md +25 -0
- package/knowledge-base/maintained/architecture/quality-attributes-and-evaluation.md +35 -0
- package/knowledge-base/maintained/product-patterns/MASTER.md +10 -0
- package/knowledge-base/maintained/product-patterns/ai-workspaces.md +26 -0
- package/knowledge-base/maintained/product-patterns/operational-dashboards.md +22 -0
- package/knowledge-base/provenance.yaml +196 -0
- package/knowledge-base/retrieval-scope.yaml +43 -0
- package/knowledge-base/usability-evaluation/HEURISTIC_EVALUATION.md +115 -0
- package/knowledge-base/usability-evaluation/heuristic-review.schema.yaml +210 -0
- package/knowledge-base/usability-evaluation/heuristic-review.template.yaml +37 -0
- package/package.json +133 -0
|
@@ -0,0 +1,1352 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readdir, readFile, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import { delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep, } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { formatAuditReport } from "./audit/report.js";
|
|
8
|
+
import { auditRepository } from "./audit/scanner.js";
|
|
9
|
+
import { formatAggregateReport } from "./aggregate/report.js";
|
|
10
|
+
import { aggregateQualityGates } from "./aggregate/runner.js";
|
|
11
|
+
import { aggregateReportSchema } from "./aggregate/schema.js";
|
|
12
|
+
import { formatContractValidationReport } from "./contracts/report.js";
|
|
13
|
+
import { contractValidationReportSchema } from "./contracts/schema.js";
|
|
14
|
+
import { validateProductContract } from "./contracts/validator.js";
|
|
15
|
+
import { evaluateInterfaceComparison } from "./comparison/evaluator.js";
|
|
16
|
+
import { loadComparisonMethodology, loadComparisonReview, } from "./comparison/loader.js";
|
|
17
|
+
import { formatComparisonReport } from "./comparison/report.js";
|
|
18
|
+
import { comparisonReportSchema } from "./comparison/schema.js";
|
|
19
|
+
import { evaluateCorpusBenchmark } from "./corpus/evaluator.js";
|
|
20
|
+
import { formatCorpusReport } from "./corpus/report.js";
|
|
21
|
+
import { corpusReportSchema } from "./corpus/schema.js";
|
|
22
|
+
import { loadDesignDeliverable } from "./design-intelligence/loader.js";
|
|
23
|
+
import { formatDesignDeliverableReport } from "./design-intelligence/report.js";
|
|
24
|
+
import { designDeliverableReportSchema } from "./design-intelligence/schema.js";
|
|
25
|
+
import { validateDesignDeliverable } from "./design-intelligence/validator.js";
|
|
26
|
+
import { compileDesignPlan } from "./design-plan/compiler.js";
|
|
27
|
+
import { formatDesignPlan } from "./design-plan/report.js";
|
|
28
|
+
import { designPlanSchema } from "./design-plan/schema.js";
|
|
29
|
+
import { formatQualityGateReport } from "./quality-gate/report.js";
|
|
30
|
+
import { runQualityGate } from "./quality-gate/runner.js";
|
|
31
|
+
import { qualityGateReportSchema } from "./quality-gate/schema.js";
|
|
32
|
+
import { PRODUCT_ID, VERSION } from "./product.js";
|
|
33
|
+
import { loadProductDesignBrief } from "./product-brief/loader.js";
|
|
34
|
+
import { formatProductBriefReport } from "./product-brief/report.js";
|
|
35
|
+
import { productBriefReportSchema } from "./product-brief/schema.js";
|
|
36
|
+
import { validateProductDesignBrief } from "./product-brief/validator.js";
|
|
37
|
+
import { listPortfolioProjectsForMcp, readPortfolioReportForMcp } from "./portfolio/mcp.js";
|
|
38
|
+
import { formatKnowledgeSearchReport } from "./retrieval/report.js";
|
|
39
|
+
import { knowledgeSearchInputSchema, knowledgeSearchReportSchema, } from "./retrieval/schema.js";
|
|
40
|
+
import { buildKnowledgeIndex, searchKnowledge, } from "./retrieval/search.js";
|
|
41
|
+
import { evaluateHeuristicReview } from "./heuristics/evaluator.js";
|
|
42
|
+
import { loadHeuristicReview } from "./heuristics/loader.js";
|
|
43
|
+
import { formatHeuristicReviewReport } from "./heuristics/report.js";
|
|
44
|
+
import { heuristicReviewReportSchema } from "./heuristics/schema.js";
|
|
45
|
+
import { loadInformationDesignContract } from "./information-design/loader.js";
|
|
46
|
+
import { formatInformationDesignReport } from "./information-design/report.js";
|
|
47
|
+
import { informationDesignReportSchema } from "./information-design/schema.js";
|
|
48
|
+
import { validateInformationDesignContract } from "./information-design/validator.js";
|
|
49
|
+
import { loadInterfaceTrustContract } from "./interface-trust/loader.js";
|
|
50
|
+
import { formatInterfaceTrustReport } from "./interface-trust/report.js";
|
|
51
|
+
import { interfaceTrustReportSchema } from "./interface-trust/schema.js";
|
|
52
|
+
import { validateInterfaceTrustContract } from "./interface-trust/validator.js";
|
|
53
|
+
import { runtimeJourneySchema, runtimeExpectedNetworkSchema, runtimeReportSchema, runtimeViewportSchema, } from "./runtime/schema.js";
|
|
54
|
+
import { formatRuntimeReport } from "./runtime/report.js";
|
|
55
|
+
import { validateRuntimeUrl } from "./runtime/policy.js";
|
|
56
|
+
import { verifyUiRuntime } from "./runtime/verifier.js";
|
|
57
|
+
const MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
58
|
+
const MODULE_DIRECTORY = dirname(fileURLToPath(import.meta.url));
|
|
59
|
+
function findProjectRoot(startDirectory) {
|
|
60
|
+
let currentDirectory = resolve(startDirectory);
|
|
61
|
+
while (true) {
|
|
62
|
+
if (existsSync(join(currentDirectory, "package.json")) &&
|
|
63
|
+
existsSync(join(currentDirectory, "knowledge-base"))) {
|
|
64
|
+
return currentDirectory;
|
|
65
|
+
}
|
|
66
|
+
const parentDirectory = dirname(currentDirectory);
|
|
67
|
+
if (parentDirectory === currentDirectory) {
|
|
68
|
+
throw new Error("Could not locate the ZtotheZ Design Engineering project root");
|
|
69
|
+
}
|
|
70
|
+
currentDirectory = parentDirectory;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function resolveProjectRoot() {
|
|
74
|
+
const configuredRoot = process.env.ZTOTHEZ_DESIGN_ENGINEERING_ROOT?.trim();
|
|
75
|
+
return findProjectRoot(configuredRoot ? resolve(configuredRoot) : MODULE_DIRECTORY);
|
|
76
|
+
}
|
|
77
|
+
const PROJECT_ROOT = resolveProjectRoot();
|
|
78
|
+
const KNOWLEDGE_BASE_ROOT = join(PROJECT_ROOT, "knowledge-base");
|
|
79
|
+
const BENCHMARK_ROOT = join(KNOWLEDGE_BASE_ROOT, "benchmarks");
|
|
80
|
+
const CORPUS_ROOT = join(BENCHMARK_ROOT, "corpus");
|
|
81
|
+
const DESIGN_INTELLIGENCE_ROOT = join(KNOWLEDGE_BASE_ROOT, "design-intelligence");
|
|
82
|
+
const RETRIEVAL_SCOPE_PATH = join(KNOWLEDGE_BASE_ROOT, "retrieval-scope.yaml");
|
|
83
|
+
let knowledgeIndexPromise;
|
|
84
|
+
function getKnowledgeIndex() {
|
|
85
|
+
knowledgeIndexPromise ??= buildKnowledgeIndex(PROJECT_ROOT, RETRIEVAL_SCOPE_PATH).catch((error) => {
|
|
86
|
+
knowledgeIndexPromise = undefined;
|
|
87
|
+
throw error;
|
|
88
|
+
});
|
|
89
|
+
return knowledgeIndexPromise;
|
|
90
|
+
}
|
|
91
|
+
const knowledgeAreas = {
|
|
92
|
+
architecture: {
|
|
93
|
+
directory: join(KNOWLEDGE_BASE_ROOT, "maintained", "architecture"),
|
|
94
|
+
label: "architecture",
|
|
95
|
+
},
|
|
96
|
+
designIntelligence: {
|
|
97
|
+
directory: DESIGN_INTELLIGENCE_ROOT,
|
|
98
|
+
label: "design intelligence",
|
|
99
|
+
},
|
|
100
|
+
figmaAndSystems: {
|
|
101
|
+
directory: DESIGN_INTELLIGENCE_ROOT,
|
|
102
|
+
label: "Figma and design systems",
|
|
103
|
+
},
|
|
104
|
+
uxPatterns: {
|
|
105
|
+
directory: join(KNOWLEDGE_BASE_ROOT, "maintained", "product-patterns"),
|
|
106
|
+
label: "dashboard and UX patterns",
|
|
107
|
+
},
|
|
108
|
+
usabilityEvaluation: {
|
|
109
|
+
directory: join(KNOWLEDGE_BASE_ROOT, "usability-evaluation"),
|
|
110
|
+
label: "usability evaluation",
|
|
111
|
+
excludedDirectories: ["sources"],
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const fileInputSchema = {
|
|
115
|
+
file: z
|
|
116
|
+
.string()
|
|
117
|
+
.trim()
|
|
118
|
+
.min(1)
|
|
119
|
+
.max(512)
|
|
120
|
+
.optional()
|
|
121
|
+
.describe("Repository-relative Markdown filename within this knowledge area. Omit to list available files."),
|
|
122
|
+
};
|
|
123
|
+
function isPathContained(baseDirectory, candidatePath) {
|
|
124
|
+
const relation = relative(baseDirectory, candidatePath);
|
|
125
|
+
return (relation === "" ||
|
|
126
|
+
(!relation.startsWith(`..${sep}`) && relation !== ".." && !isAbsolute(relation)));
|
|
127
|
+
}
|
|
128
|
+
function isExcludedKnowledgePath(area, baseDirectory, candidatePath) {
|
|
129
|
+
const firstSegment = relative(baseDirectory, candidatePath).split(sep)[0] ?? "";
|
|
130
|
+
return area.excludedDirectories?.includes(firstSegment) ?? false;
|
|
131
|
+
}
|
|
132
|
+
async function listMarkdownFiles(area, currentDirectory = area.directory) {
|
|
133
|
+
const entries = await readdir(currentDirectory, { withFileTypes: true });
|
|
134
|
+
const files = [];
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
const entryPath = join(currentDirectory, entry.name);
|
|
137
|
+
if (entry.isDirectory()) {
|
|
138
|
+
const relativeDirectory = relative(area.directory, entryPath).split(sep);
|
|
139
|
+
if (area.excludedDirectories?.includes(relativeDirectory[0] ?? ""))
|
|
140
|
+
continue;
|
|
141
|
+
files.push(...(await listMarkdownFiles(area, entryPath)));
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (entry.isFile() && extname(entry.name).toLowerCase() === ".md") {
|
|
145
|
+
files.push(relative(area.directory, entryPath).split(sep).join("/"));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return files.sort((left, right) => left.localeCompare(right));
|
|
149
|
+
}
|
|
150
|
+
async function readKnowledgeArea(area, requestedFile) {
|
|
151
|
+
const baseDirectory = await realpath(area.directory);
|
|
152
|
+
if (requestedFile === undefined) {
|
|
153
|
+
const files = await listMarkdownFiles({ ...area, directory: baseDirectory });
|
|
154
|
+
const listing = files.length > 0 ? files.map((file) => `- ${file}`).join("\n") : "- No Markdown files found.";
|
|
155
|
+
return `Available files in ${area.label}:\n${listing}`;
|
|
156
|
+
}
|
|
157
|
+
if (requestedFile.includes("\0")) {
|
|
158
|
+
throw new Error("The requested filename contains an invalid null byte");
|
|
159
|
+
}
|
|
160
|
+
if (isAbsolute(requestedFile) || extname(requestedFile).toLowerCase() !== ".md") {
|
|
161
|
+
throw new Error("Provide a relative Markdown filename ending in .md");
|
|
162
|
+
}
|
|
163
|
+
const candidatePath = resolve(baseDirectory, requestedFile);
|
|
164
|
+
if (!isPathContained(baseDirectory, candidatePath)) {
|
|
165
|
+
throw new Error("The requested file is outside the permitted knowledge area");
|
|
166
|
+
}
|
|
167
|
+
if (isExcludedKnowledgePath(area, baseDirectory, candidatePath)) {
|
|
168
|
+
throw new Error("The requested file is excluded from the distributable knowledge area");
|
|
169
|
+
}
|
|
170
|
+
let resolvedFile;
|
|
171
|
+
try {
|
|
172
|
+
resolvedFile = await realpath(candidatePath);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
176
|
+
throw new Error(`Knowledge file not found: ${requestedFile}`);
|
|
177
|
+
}
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
if (!isPathContained(baseDirectory, resolvedFile)) {
|
|
181
|
+
throw new Error("The requested file resolves outside the permitted knowledge area");
|
|
182
|
+
}
|
|
183
|
+
if (isExcludedKnowledgePath(area, baseDirectory, resolvedFile)) {
|
|
184
|
+
throw new Error("The requested file resolves inside an excluded knowledge area");
|
|
185
|
+
}
|
|
186
|
+
const fileStats = await stat(resolvedFile);
|
|
187
|
+
if (!fileStats.isFile()) {
|
|
188
|
+
throw new Error("The requested path is not a regular file");
|
|
189
|
+
}
|
|
190
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
191
|
+
throw new Error(`Knowledge file exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
192
|
+
}
|
|
193
|
+
const content = await readFile(resolvedFile, "utf8");
|
|
194
|
+
const sourcePath = relative(PROJECT_ROOT, resolvedFile).split(sep).join("/");
|
|
195
|
+
return `Source: ${sourcePath}\n\n${content}`;
|
|
196
|
+
}
|
|
197
|
+
async function resolveBenchmarkContract(requestedFile) {
|
|
198
|
+
if (requestedFile.includes("\0") || isAbsolute(requestedFile)) {
|
|
199
|
+
throw new Error("Provide a repository-relative benchmark contract path");
|
|
200
|
+
}
|
|
201
|
+
if (!/\.ya?ml$/i.test(requestedFile)) {
|
|
202
|
+
throw new Error("Benchmark contracts must end in .yaml or .yml");
|
|
203
|
+
}
|
|
204
|
+
const benchmarkRoot = await realpath(BENCHMARK_ROOT);
|
|
205
|
+
const candidate = resolve(benchmarkRoot, requestedFile);
|
|
206
|
+
if (!isPathContained(benchmarkRoot, candidate)) {
|
|
207
|
+
throw new Error("The requested contract is outside the benchmark directory");
|
|
208
|
+
}
|
|
209
|
+
const resolvedFile = await realpath(candidate);
|
|
210
|
+
if (!isPathContained(benchmarkRoot, resolvedFile)) {
|
|
211
|
+
throw new Error("The requested contract resolves outside the benchmark directory");
|
|
212
|
+
}
|
|
213
|
+
const fileStats = await stat(resolvedFile);
|
|
214
|
+
if (!fileStats.isFile() || fileStats.size > MAX_FILE_BYTES) {
|
|
215
|
+
throw new Error("The requested contract is unavailable or exceeds the file-size limit");
|
|
216
|
+
}
|
|
217
|
+
return resolvedFile;
|
|
218
|
+
}
|
|
219
|
+
async function resolveCorpusManifest(requestedFile) {
|
|
220
|
+
if (requestedFile.includes("\0") || isAbsolute(requestedFile)) {
|
|
221
|
+
throw new Error("Provide a path relative to the maintained corpus directory");
|
|
222
|
+
}
|
|
223
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
224
|
+
throw new Error("Corpus manifests must end in .json, .yaml, or .yml");
|
|
225
|
+
}
|
|
226
|
+
const corpusRoot = await realpath(CORPUS_ROOT);
|
|
227
|
+
const candidate = resolve(corpusRoot, requestedFile);
|
|
228
|
+
if (!isPathContained(corpusRoot, candidate)) {
|
|
229
|
+
throw new Error("The requested corpus manifest is outside the maintained corpus directory");
|
|
230
|
+
}
|
|
231
|
+
const resolvedFile = await realpath(candidate);
|
|
232
|
+
if (!isPathContained(corpusRoot, resolvedFile)) {
|
|
233
|
+
throw new Error("The requested corpus manifest resolves outside the maintained corpus directory");
|
|
234
|
+
}
|
|
235
|
+
const fileStats = await stat(resolvedFile);
|
|
236
|
+
if (!fileStats.isFile() || fileStats.size > MAX_FILE_BYTES) {
|
|
237
|
+
throw new Error("The requested corpus manifest is unavailable or exceeds the file-size limit");
|
|
238
|
+
}
|
|
239
|
+
return resolvedFile;
|
|
240
|
+
}
|
|
241
|
+
async function resolveBenchmarkAttestations(requestedFile) {
|
|
242
|
+
if (requestedFile.includes("\0") || isAbsolute(requestedFile)) {
|
|
243
|
+
throw new Error("Provide a repository-relative benchmark attestation path");
|
|
244
|
+
}
|
|
245
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
246
|
+
throw new Error("Attestations must end in .json, .yaml, or .yml");
|
|
247
|
+
}
|
|
248
|
+
const benchmarkRoot = await realpath(BENCHMARK_ROOT);
|
|
249
|
+
const candidate = resolve(benchmarkRoot, requestedFile);
|
|
250
|
+
if (!isPathContained(benchmarkRoot, candidate)) {
|
|
251
|
+
throw new Error("The requested attestations are outside the benchmark directory");
|
|
252
|
+
}
|
|
253
|
+
const resolvedFile = await realpath(candidate);
|
|
254
|
+
if (!isPathContained(benchmarkRoot, resolvedFile)) {
|
|
255
|
+
throw new Error("The requested attestations resolve outside the benchmark directory");
|
|
256
|
+
}
|
|
257
|
+
const fileStats = await stat(resolvedFile);
|
|
258
|
+
if (!fileStats.isFile() || fileStats.size > MAX_FILE_BYTES) {
|
|
259
|
+
throw new Error("The requested attestations are unavailable or exceed the file-size limit");
|
|
260
|
+
}
|
|
261
|
+
return resolvedFile;
|
|
262
|
+
}
|
|
263
|
+
function errorMessage(error) {
|
|
264
|
+
return error instanceof Error ? error.message : "An unknown file-reading error occurred";
|
|
265
|
+
}
|
|
266
|
+
async function configuredAuditRoots() {
|
|
267
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_AUDIT_ROOTS?.split(delimiter)
|
|
268
|
+
.map((entry) => entry.trim())
|
|
269
|
+
.filter((entry) => entry.length > 0);
|
|
270
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
271
|
+
const resolvedRoots = [];
|
|
272
|
+
for (const root of roots) {
|
|
273
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
274
|
+
const rootStats = await stat(resolvedRoot);
|
|
275
|
+
if (!rootStats.isDirectory()) {
|
|
276
|
+
throw new Error(`Configured audit root is not a directory: ${root}`);
|
|
277
|
+
}
|
|
278
|
+
resolvedRoots.push(resolvedRoot);
|
|
279
|
+
}
|
|
280
|
+
return resolvedRoots;
|
|
281
|
+
}
|
|
282
|
+
async function resolveAllowedAuditTarget(requestedTarget) {
|
|
283
|
+
if (requestedTarget.includes("\0")) {
|
|
284
|
+
throw new Error("The audit target contains an invalid null byte");
|
|
285
|
+
}
|
|
286
|
+
const roots = await configuredAuditRoots();
|
|
287
|
+
const candidates = isAbsolute(requestedTarget)
|
|
288
|
+
? [requestedTarget]
|
|
289
|
+
: roots.map((root) => resolve(root, requestedTarget));
|
|
290
|
+
for (const candidate of candidates) {
|
|
291
|
+
let resolvedCandidate;
|
|
292
|
+
try {
|
|
293
|
+
resolvedCandidate = await realpath(candidate);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
throw error;
|
|
300
|
+
}
|
|
301
|
+
if (roots.some((root) => isPathContained(root, resolvedCandidate))) {
|
|
302
|
+
const candidateStats = await stat(resolvedCandidate);
|
|
303
|
+
if (!candidateStats.isDirectory()) {
|
|
304
|
+
throw new Error("Audit target must be a directory");
|
|
305
|
+
}
|
|
306
|
+
return resolvedCandidate;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
throw new Error("Audit target is unavailable or outside ZTOTHEZ_DESIGN_AUDIT_ROOTS. Configure explicit allowed roots before scanning external repositories.");
|
|
310
|
+
}
|
|
311
|
+
async function configuredHeuristicReviewRoots() {
|
|
312
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_HEURISTIC_REVIEW_ROOTS?.split(delimiter)
|
|
313
|
+
.map((entry) => entry.trim())
|
|
314
|
+
.filter((entry) => entry.length > 0);
|
|
315
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
316
|
+
const resolvedRoots = [];
|
|
317
|
+
for (const root of roots) {
|
|
318
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
319
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
320
|
+
throw new Error(`Configured heuristic review root is not a directory: ${root}`);
|
|
321
|
+
}
|
|
322
|
+
resolvedRoots.push(resolvedRoot);
|
|
323
|
+
}
|
|
324
|
+
return resolvedRoots;
|
|
325
|
+
}
|
|
326
|
+
async function configuredComparisonRoots() {
|
|
327
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_COMPARISON_ROOTS?.split(delimiter)
|
|
328
|
+
.map((entry) => entry.trim())
|
|
329
|
+
.filter((entry) => entry.length > 0);
|
|
330
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
331
|
+
const resolvedRoots = [];
|
|
332
|
+
for (const root of roots) {
|
|
333
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
334
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
335
|
+
throw new Error(`Configured comparison root is not a directory: ${root}`);
|
|
336
|
+
}
|
|
337
|
+
resolvedRoots.push(resolvedRoot);
|
|
338
|
+
}
|
|
339
|
+
return resolvedRoots;
|
|
340
|
+
}
|
|
341
|
+
async function resolveAllowedComparisonFile(requestedFile) {
|
|
342
|
+
if (requestedFile.includes("\0")) {
|
|
343
|
+
throw new Error("The comparison path contains an invalid null byte");
|
|
344
|
+
}
|
|
345
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
346
|
+
throw new Error("Comparison files must end in .json, .yaml, or .yml");
|
|
347
|
+
}
|
|
348
|
+
const roots = await configuredComparisonRoots();
|
|
349
|
+
const candidates = isAbsolute(requestedFile)
|
|
350
|
+
? [requestedFile]
|
|
351
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
352
|
+
for (const candidate of candidates) {
|
|
353
|
+
let resolvedCandidate;
|
|
354
|
+
try {
|
|
355
|
+
resolvedCandidate = await realpath(candidate);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
359
|
+
continue;
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
363
|
+
continue;
|
|
364
|
+
const fileStats = await stat(resolvedCandidate);
|
|
365
|
+
if (!fileStats.isFile())
|
|
366
|
+
throw new Error("Comparison path must be a regular file");
|
|
367
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
368
|
+
throw new Error(`Comparison file exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
369
|
+
}
|
|
370
|
+
return resolvedCandidate;
|
|
371
|
+
}
|
|
372
|
+
throw new Error("Comparison file is unavailable or outside ZTOTHEZ_DESIGN_COMPARISON_ROOTS. Configure explicit allowed roots before reading external comparison artifacts.");
|
|
373
|
+
}
|
|
374
|
+
async function configuredDesignDeliverableRoots() {
|
|
375
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_DELIVERABLE_ROOTS?.split(delimiter)
|
|
376
|
+
.map((entry) => entry.trim())
|
|
377
|
+
.filter((entry) => entry.length > 0);
|
|
378
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
379
|
+
const resolvedRoots = [];
|
|
380
|
+
for (const root of roots) {
|
|
381
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
382
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
383
|
+
throw new Error(`Configured design deliverable root is not a directory: ${root}`);
|
|
384
|
+
}
|
|
385
|
+
resolvedRoots.push(resolvedRoot);
|
|
386
|
+
}
|
|
387
|
+
return resolvedRoots;
|
|
388
|
+
}
|
|
389
|
+
async function configuredInterfaceTrustRoots() {
|
|
390
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_TRUST_ROOTS?.split(delimiter)
|
|
391
|
+
.map((entry) => entry.trim())
|
|
392
|
+
.filter((entry) => entry.length > 0);
|
|
393
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
394
|
+
const resolvedRoots = [];
|
|
395
|
+
for (const root of roots) {
|
|
396
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
397
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
398
|
+
throw new Error(`Configured interface trust root is not a directory: ${root}`);
|
|
399
|
+
}
|
|
400
|
+
resolvedRoots.push(resolvedRoot);
|
|
401
|
+
}
|
|
402
|
+
return resolvedRoots;
|
|
403
|
+
}
|
|
404
|
+
async function configuredInformationDesignRoots() {
|
|
405
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_INFORMATION_ROOTS?.split(delimiter)
|
|
406
|
+
.map((entry) => entry.trim())
|
|
407
|
+
.filter((entry) => entry.length > 0);
|
|
408
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
409
|
+
const resolvedRoots = [];
|
|
410
|
+
for (const root of roots) {
|
|
411
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
412
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
413
|
+
throw new Error(`Configured information-design root is not a directory: ${root}`);
|
|
414
|
+
}
|
|
415
|
+
resolvedRoots.push(resolvedRoot);
|
|
416
|
+
}
|
|
417
|
+
return resolvedRoots;
|
|
418
|
+
}
|
|
419
|
+
async function configuredProductBriefRoots() {
|
|
420
|
+
const configuredRoots = process.env.ZTOTHEZ_DESIGN_BRIEF_ROOTS?.split(delimiter)
|
|
421
|
+
.map((entry) => entry.trim())
|
|
422
|
+
.filter((entry) => entry.length > 0);
|
|
423
|
+
const roots = configuredRoots?.length ? configuredRoots : [PROJECT_ROOT];
|
|
424
|
+
const resolvedRoots = [];
|
|
425
|
+
for (const root of roots) {
|
|
426
|
+
const resolvedRoot = await realpath(resolve(root));
|
|
427
|
+
if (!(await stat(resolvedRoot)).isDirectory()) {
|
|
428
|
+
throw new Error(`Configured product design brief root is not a directory: ${root}`);
|
|
429
|
+
}
|
|
430
|
+
resolvedRoots.push(resolvedRoot);
|
|
431
|
+
}
|
|
432
|
+
return resolvedRoots;
|
|
433
|
+
}
|
|
434
|
+
async function resolveAllowedProductDesignBrief(requestedFile) {
|
|
435
|
+
if (requestedFile.includes("\0")) {
|
|
436
|
+
throw new Error("The product design brief path contains an invalid null byte");
|
|
437
|
+
}
|
|
438
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
439
|
+
throw new Error("Product design briefs must end in .json, .yaml, or .yml");
|
|
440
|
+
}
|
|
441
|
+
const roots = await configuredProductBriefRoots();
|
|
442
|
+
const candidates = isAbsolute(requestedFile)
|
|
443
|
+
? [requestedFile]
|
|
444
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
445
|
+
for (const candidate of candidates) {
|
|
446
|
+
let resolvedCandidate;
|
|
447
|
+
try {
|
|
448
|
+
resolvedCandidate = await realpath(candidate);
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
452
|
+
continue;
|
|
453
|
+
throw error;
|
|
454
|
+
}
|
|
455
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
456
|
+
continue;
|
|
457
|
+
const fileStats = await stat(resolvedCandidate);
|
|
458
|
+
if (!fileStats.isFile())
|
|
459
|
+
throw new Error("Product design brief path must be a regular file");
|
|
460
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
461
|
+
throw new Error(`Product design brief exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
462
|
+
}
|
|
463
|
+
return resolvedCandidate;
|
|
464
|
+
}
|
|
465
|
+
throw new Error("Product design brief is unavailable or outside ZTOTHEZ_DESIGN_BRIEF_ROOTS. Configure explicit allowed roots before reading external briefs.");
|
|
466
|
+
}
|
|
467
|
+
async function resolveAllowedInformationDesignContract(requestedFile) {
|
|
468
|
+
if (requestedFile.includes("\0")) {
|
|
469
|
+
throw new Error("The information-design path contains an invalid null byte");
|
|
470
|
+
}
|
|
471
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
472
|
+
throw new Error("Information-design contracts must end in .json, .yaml, or .yml");
|
|
473
|
+
}
|
|
474
|
+
const roots = await configuredInformationDesignRoots();
|
|
475
|
+
const candidates = isAbsolute(requestedFile)
|
|
476
|
+
? [requestedFile]
|
|
477
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
478
|
+
for (const candidate of candidates) {
|
|
479
|
+
let resolvedCandidate;
|
|
480
|
+
try {
|
|
481
|
+
resolvedCandidate = await realpath(candidate);
|
|
482
|
+
}
|
|
483
|
+
catch (error) {
|
|
484
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
485
|
+
continue;
|
|
486
|
+
throw error;
|
|
487
|
+
}
|
|
488
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
489
|
+
continue;
|
|
490
|
+
const fileStats = await stat(resolvedCandidate);
|
|
491
|
+
if (!fileStats.isFile())
|
|
492
|
+
throw new Error("Information-design path must be a regular file");
|
|
493
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
494
|
+
throw new Error(`Information-design contract exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
495
|
+
}
|
|
496
|
+
return resolvedCandidate;
|
|
497
|
+
}
|
|
498
|
+
throw new Error("Information-design contract is unavailable or outside ZTOTHEZ_DESIGN_INFORMATION_ROOTS. Configure explicit allowed roots before reading external contracts.");
|
|
499
|
+
}
|
|
500
|
+
async function resolveAllowedInterfaceTrustContract(requestedFile) {
|
|
501
|
+
if (requestedFile.includes("\0")) {
|
|
502
|
+
throw new Error("The interface trust path contains an invalid null byte");
|
|
503
|
+
}
|
|
504
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
505
|
+
throw new Error("Interface trust contracts must end in .json, .yaml, or .yml");
|
|
506
|
+
}
|
|
507
|
+
const roots = await configuredInterfaceTrustRoots();
|
|
508
|
+
const candidates = isAbsolute(requestedFile)
|
|
509
|
+
? [requestedFile]
|
|
510
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
511
|
+
for (const candidate of candidates) {
|
|
512
|
+
let resolvedCandidate;
|
|
513
|
+
try {
|
|
514
|
+
resolvedCandidate = await realpath(candidate);
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
518
|
+
continue;
|
|
519
|
+
throw error;
|
|
520
|
+
}
|
|
521
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
522
|
+
continue;
|
|
523
|
+
const fileStats = await stat(resolvedCandidate);
|
|
524
|
+
if (!fileStats.isFile())
|
|
525
|
+
throw new Error("Interface trust path must be a regular file");
|
|
526
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
527
|
+
throw new Error(`Interface trust contract exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
528
|
+
}
|
|
529
|
+
return resolvedCandidate;
|
|
530
|
+
}
|
|
531
|
+
throw new Error("Interface trust contract is unavailable or outside ZTOTHEZ_DESIGN_TRUST_ROOTS. Configure explicit allowed roots before reading external contracts.");
|
|
532
|
+
}
|
|
533
|
+
async function resolveAllowedDesignDeliverable(requestedFile) {
|
|
534
|
+
if (requestedFile.includes("\0")) {
|
|
535
|
+
throw new Error("The design deliverable path contains an invalid null byte");
|
|
536
|
+
}
|
|
537
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
538
|
+
throw new Error("Design deliverable manifests must end in .json, .yaml, or .yml");
|
|
539
|
+
}
|
|
540
|
+
const roots = await configuredDesignDeliverableRoots();
|
|
541
|
+
const candidates = isAbsolute(requestedFile)
|
|
542
|
+
? [requestedFile]
|
|
543
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
544
|
+
for (const candidate of candidates) {
|
|
545
|
+
let resolvedCandidate;
|
|
546
|
+
try {
|
|
547
|
+
resolvedCandidate = await realpath(candidate);
|
|
548
|
+
}
|
|
549
|
+
catch (error) {
|
|
550
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
551
|
+
continue;
|
|
552
|
+
throw error;
|
|
553
|
+
}
|
|
554
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
555
|
+
continue;
|
|
556
|
+
const fileStats = await stat(resolvedCandidate);
|
|
557
|
+
if (!fileStats.isFile())
|
|
558
|
+
throw new Error("Design deliverable path must be a regular file");
|
|
559
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
560
|
+
throw new Error(`Design deliverable exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
561
|
+
}
|
|
562
|
+
return resolvedCandidate;
|
|
563
|
+
}
|
|
564
|
+
throw new Error("Design deliverable is unavailable or outside ZTOTHEZ_DESIGN_DELIVERABLE_ROOTS. Configure explicit allowed roots before reading external manifests.");
|
|
565
|
+
}
|
|
566
|
+
async function resolveAllowedHeuristicReview(requestedFile) {
|
|
567
|
+
if (requestedFile.includes("\0")) {
|
|
568
|
+
throw new Error("The heuristic review path contains an invalid null byte");
|
|
569
|
+
}
|
|
570
|
+
if (!/\.(?:json|ya?ml)$/i.test(requestedFile)) {
|
|
571
|
+
throw new Error("Heuristic reviews must end in .json, .yaml, or .yml");
|
|
572
|
+
}
|
|
573
|
+
const roots = await configuredHeuristicReviewRoots();
|
|
574
|
+
const candidates = isAbsolute(requestedFile)
|
|
575
|
+
? [requestedFile]
|
|
576
|
+
: roots.map((root) => resolve(root, requestedFile));
|
|
577
|
+
for (const candidate of candidates) {
|
|
578
|
+
let resolvedCandidate;
|
|
579
|
+
try {
|
|
580
|
+
resolvedCandidate = await realpath(candidate);
|
|
581
|
+
}
|
|
582
|
+
catch (error) {
|
|
583
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
584
|
+
continue;
|
|
585
|
+
throw error;
|
|
586
|
+
}
|
|
587
|
+
if (!roots.some((root) => isPathContained(root, resolvedCandidate)))
|
|
588
|
+
continue;
|
|
589
|
+
const fileStats = await stat(resolvedCandidate);
|
|
590
|
+
if (!fileStats.isFile())
|
|
591
|
+
throw new Error("Heuristic review path must be a regular file");
|
|
592
|
+
if (fileStats.size > MAX_FILE_BYTES) {
|
|
593
|
+
throw new Error(`Heuristic review exceeds the ${MAX_FILE_BYTES}-byte read limit`);
|
|
594
|
+
}
|
|
595
|
+
return resolvedCandidate;
|
|
596
|
+
}
|
|
597
|
+
throw new Error("Heuristic review is unavailable or outside ZTOTHEZ_DESIGN_HEURISTIC_REVIEW_ROOTS. Configure explicit allowed roots before reading external review artifacts.");
|
|
598
|
+
}
|
|
599
|
+
function isAllowedRuntimeUrl(value) {
|
|
600
|
+
const url = validateRuntimeUrl(value);
|
|
601
|
+
const configuredOrigins = process.env.ZTOTHEZ_DESIGN_RUNTIME_ORIGINS?.split(",")
|
|
602
|
+
.map((entry) => entry.trim())
|
|
603
|
+
.filter((entry) => entry.length > 0)
|
|
604
|
+
.map((entry) => validateRuntimeUrl(entry).origin);
|
|
605
|
+
if (configuredOrigins?.length) {
|
|
606
|
+
return configuredOrigins.includes(url.origin);
|
|
607
|
+
}
|
|
608
|
+
return ["localhost", "127.0.0.1", "0.0.0.0", "[::1]"].includes(url.hostname);
|
|
609
|
+
}
|
|
610
|
+
function runtimeOutputName(reportName) {
|
|
611
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
612
|
+
const suffix = reportName
|
|
613
|
+
?.toLowerCase()
|
|
614
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
615
|
+
.replace(/^-|-$/g, "")
|
|
616
|
+
.slice(0, 64);
|
|
617
|
+
return suffix ? `${timestamp}-${suffix}` : timestamp;
|
|
618
|
+
}
|
|
619
|
+
async function createRuntimeOutputDirectory(reportName) {
|
|
620
|
+
const root = resolve(process.env.ZTOTHEZ_DESIGN_RUNTIME_OUTPUT_ROOT?.trim() || join(PROJECT_ROOT, ".ztothez-design-runtime"));
|
|
621
|
+
await mkdir(root, { recursive: true });
|
|
622
|
+
const resolvedRoot = await realpath(root);
|
|
623
|
+
const outputDirectory = join(resolvedRoot, runtimeOutputName(reportName));
|
|
624
|
+
await mkdir(outputDirectory, { recursive: false });
|
|
625
|
+
return outputDirectory;
|
|
626
|
+
}
|
|
627
|
+
async function createQualityGateOutputDirectory(reportName) {
|
|
628
|
+
const root = await qualityGateOutputRoot();
|
|
629
|
+
const outputDirectory = join(root, runtimeOutputName(reportName));
|
|
630
|
+
await mkdir(outputDirectory, { recursive: false });
|
|
631
|
+
return outputDirectory;
|
|
632
|
+
}
|
|
633
|
+
async function qualityGateOutputRoot() {
|
|
634
|
+
const root = resolve(process.env.ZTOTHEZ_DESIGN_QUALITY_GATE_OUTPUT_ROOT?.trim() || join(PROJECT_ROOT, ".ztothez-design-quality-gate"));
|
|
635
|
+
await mkdir(root, { recursive: true });
|
|
636
|
+
return realpath(root);
|
|
637
|
+
}
|
|
638
|
+
async function resolveQualityGateReportDirectory(name) {
|
|
639
|
+
if (!/^[a-z0-9][a-z0-9._-]{0,127}$/i.test(name)) {
|
|
640
|
+
throw new Error("Report directory names may contain only letters, numbers, dots, underscores, and hyphens");
|
|
641
|
+
}
|
|
642
|
+
const root = await qualityGateOutputRoot();
|
|
643
|
+
const directory = await realpath(join(root, name));
|
|
644
|
+
if (!isPathContained(root, directory) || !(await stat(directory)).isDirectory()) {
|
|
645
|
+
throw new Error(`Quality gate report directory is unavailable: ${name}`);
|
|
646
|
+
}
|
|
647
|
+
return directory;
|
|
648
|
+
}
|
|
649
|
+
function registerKnowledgeTool(name, description, area) {
|
|
650
|
+
server.registerTool(name, {
|
|
651
|
+
title: name,
|
|
652
|
+
description,
|
|
653
|
+
inputSchema: fileInputSchema,
|
|
654
|
+
annotations: {
|
|
655
|
+
readOnlyHint: true,
|
|
656
|
+
destructiveHint: false,
|
|
657
|
+
idempotentHint: true,
|
|
658
|
+
openWorldHint: false,
|
|
659
|
+
},
|
|
660
|
+
}, async ({ file }) => {
|
|
661
|
+
try {
|
|
662
|
+
const text = await readKnowledgeArea(area, file);
|
|
663
|
+
return {
|
|
664
|
+
content: [{ type: "text", text }],
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
const message = errorMessage(error);
|
|
669
|
+
console.error(`[${name}] ${message}`);
|
|
670
|
+
return {
|
|
671
|
+
isError: true,
|
|
672
|
+
content: [{ type: "text", text: message }],
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
export const server = new McpServer({
|
|
678
|
+
name: PRODUCT_ID,
|
|
679
|
+
version: VERSION,
|
|
680
|
+
});
|
|
681
|
+
server.registerTool("search_design_knowledge", {
|
|
682
|
+
title: "Search approved design knowledge",
|
|
683
|
+
description: "Runs deterministic BM25 retrieval over the explicit approved knowledge scope. Returns ranked source paths, section excerpts, confidence, and an explicit no-match result. SKILL.md is marked authoritative, and legacy archives or local raw research are never indexed.",
|
|
684
|
+
inputSchema: knowledgeSearchInputSchema.shape,
|
|
685
|
+
outputSchema: knowledgeSearchReportSchema.shape,
|
|
686
|
+
annotations: {
|
|
687
|
+
readOnlyHint: true,
|
|
688
|
+
destructiveHint: false,
|
|
689
|
+
idempotentHint: true,
|
|
690
|
+
openWorldHint: false,
|
|
691
|
+
},
|
|
692
|
+
}, async (input) => {
|
|
693
|
+
try {
|
|
694
|
+
const index = await getKnowledgeIndex();
|
|
695
|
+
const report = searchKnowledge(index, input);
|
|
696
|
+
return {
|
|
697
|
+
content: [{ type: "text", text: formatKnowledgeSearchReport(report) }],
|
|
698
|
+
structuredContent: report,
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
catch (error) {
|
|
702
|
+
const message = errorMessage(error);
|
|
703
|
+
console.error(`[search_design_knowledge] ${message}`);
|
|
704
|
+
return {
|
|
705
|
+
isError: true,
|
|
706
|
+
content: [{ type: "text", text: message }],
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
server.registerTool("evaluate_corpus_benchmark", {
|
|
711
|
+
title: "Evaluate corpus benchmark",
|
|
712
|
+
description: "Runs the maintained positive and negative corpus for recommendation relevance, abstention, architectural integrity, task completeness, and anti-slop rejection. Returns case evidence, per-dimension scores, mean reciprocal rank, thresholds, and one deterministic pass or fail decision.",
|
|
713
|
+
inputSchema: {
|
|
714
|
+
manifest: z
|
|
715
|
+
.string()
|
|
716
|
+
.trim()
|
|
717
|
+
.min(1)
|
|
718
|
+
.max(512)
|
|
719
|
+
.optional()
|
|
720
|
+
.describe("Path relative to knowledge-base/benchmarks/corpus. Defaults to corpus.yaml."),
|
|
721
|
+
},
|
|
722
|
+
outputSchema: corpusReportSchema.shape,
|
|
723
|
+
annotations: {
|
|
724
|
+
readOnlyHint: true,
|
|
725
|
+
destructiveHint: false,
|
|
726
|
+
idempotentHint: true,
|
|
727
|
+
openWorldHint: false,
|
|
728
|
+
},
|
|
729
|
+
}, async ({ manifest }) => {
|
|
730
|
+
try {
|
|
731
|
+
const manifestPath = await resolveCorpusManifest(manifest ?? "corpus.yaml");
|
|
732
|
+
const report = await evaluateCorpusBenchmark(manifestPath, PROJECT_ROOT);
|
|
733
|
+
return {
|
|
734
|
+
content: [{ type: "text", text: formatCorpusReport(report) }],
|
|
735
|
+
structuredContent: report,
|
|
736
|
+
...(report.passed ? {} : { isError: true }),
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
const message = errorMessage(error);
|
|
741
|
+
console.error(`[evaluate_corpus_benchmark] ${message}`);
|
|
742
|
+
return {
|
|
743
|
+
isError: true,
|
|
744
|
+
content: [{ type: "text", text: message }],
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
registerKnowledgeTool("get_architecture_spec", "List or read maintained project-owned architecture specifications, evaluations, component boundaries, and product-platform guidance.", knowledgeAreas.architecture);
|
|
749
|
+
server.registerTool("validate_product_contract", {
|
|
750
|
+
title: "Validate product contract",
|
|
751
|
+
description: "Validates a benchmark product-contract YAML file, its source files, journey profiles, state transitions, and cross-references before design or implementation work begins.",
|
|
752
|
+
inputSchema: {
|
|
753
|
+
contract: z
|
|
754
|
+
.string()
|
|
755
|
+
.trim()
|
|
756
|
+
.min(1)
|
|
757
|
+
.max(512)
|
|
758
|
+
.describe("Path relative to knowledge-base/benchmarks, such as aegisops/product-contract.yaml"),
|
|
759
|
+
},
|
|
760
|
+
outputSchema: contractValidationReportSchema,
|
|
761
|
+
annotations: {
|
|
762
|
+
readOnlyHint: true,
|
|
763
|
+
destructiveHint: false,
|
|
764
|
+
idempotentHint: true,
|
|
765
|
+
openWorldHint: false,
|
|
766
|
+
},
|
|
767
|
+
}, async ({ contract }) => {
|
|
768
|
+
try {
|
|
769
|
+
const contractPath = await resolveBenchmarkContract(contract);
|
|
770
|
+
const report = await validateProductContract(contractPath, { projectRoot: PROJECT_ROOT });
|
|
771
|
+
return {
|
|
772
|
+
content: [{ type: "text", text: formatContractValidationReport(report) }],
|
|
773
|
+
structuredContent: report,
|
|
774
|
+
...(report.passed ? {} : { isError: true }),
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
const message = errorMessage(error);
|
|
779
|
+
console.error(`[validate_product_contract] ${message}`);
|
|
780
|
+
return {
|
|
781
|
+
isError: true,
|
|
782
|
+
content: [{ type: "text", text: message }],
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
registerKnowledgeTool("get_figma_system_rules", "List or read maintained project-owned Figma production, visual design, and design-system guidance.", knowledgeAreas.figmaAndSystems);
|
|
787
|
+
registerKnowledgeTool("get_design_intelligence", "List or read maintained visual polish, brand, Figma production, asset generation, iconography, presentation, licensing, and visual-accessibility modules.", knowledgeAreas.designIntelligence);
|
|
788
|
+
server.registerTool("validate_design_deliverable", {
|
|
789
|
+
title: "Validate design deliverable",
|
|
790
|
+
description: "Validates a versioned design-deliverable YAML or JSON manifest for semantic visual bindings, typography, composition, density, states, motion, charts, rendered-evidence and human-review declarations, three-level tokens, Figma structure, brand marks, asset provenance, icon semantics, presentation masters, contrast, and non-color cues. Structural pass and visual release readiness remain separate.",
|
|
791
|
+
inputSchema: {
|
|
792
|
+
manifestFile: z
|
|
793
|
+
.string()
|
|
794
|
+
.trim()
|
|
795
|
+
.min(1)
|
|
796
|
+
.max(4_096)
|
|
797
|
+
.describe("Absolute path or configured-root-relative manifest. External roots must be listed in ZTOTHEZ_DESIGN_DELIVERABLE_ROOTS."),
|
|
798
|
+
},
|
|
799
|
+
outputSchema: designDeliverableReportSchema.shape,
|
|
800
|
+
annotations: {
|
|
801
|
+
readOnlyHint: true,
|
|
802
|
+
destructiveHint: false,
|
|
803
|
+
idempotentHint: true,
|
|
804
|
+
openWorldHint: false,
|
|
805
|
+
},
|
|
806
|
+
}, async ({ manifestFile }) => {
|
|
807
|
+
try {
|
|
808
|
+
const resolvedFile = await resolveAllowedDesignDeliverable(manifestFile);
|
|
809
|
+
const manifest = await loadDesignDeliverable(resolvedFile);
|
|
810
|
+
const report = validateDesignDeliverable(manifest, resolvedFile);
|
|
811
|
+
return {
|
|
812
|
+
content: [{ type: "text", text: formatDesignDeliverableReport(report) }],
|
|
813
|
+
structuredContent: report,
|
|
814
|
+
...(report.passed ? {} : { isError: true }),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
catch (error) {
|
|
818
|
+
const message = errorMessage(error);
|
|
819
|
+
console.error(`[validate_design_deliverable] ${message}`);
|
|
820
|
+
return {
|
|
821
|
+
isError: true,
|
|
822
|
+
content: [{ type: "text", text: message }],
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
server.registerTool("validate_product_design_brief", {
|
|
827
|
+
title: "Validate product design brief",
|
|
828
|
+
description: "Validates a versioned product design brief for evidence-backed problems, primary audiences, measurable outcomes, critical tasks, truthful data and fallback behavior, applicable interface states, responsive platforms, unresolved assumptions, requirements, and acceptance coverage. A generation-ready result authorizes design planning only.",
|
|
829
|
+
inputSchema: {
|
|
830
|
+
briefFile: z
|
|
831
|
+
.string()
|
|
832
|
+
.trim()
|
|
833
|
+
.min(1)
|
|
834
|
+
.max(4_096)
|
|
835
|
+
.describe("Absolute path or configured-root-relative brief. External roots must be listed in ZTOTHEZ_DESIGN_BRIEF_ROOTS."),
|
|
836
|
+
},
|
|
837
|
+
outputSchema: productBriefReportSchema.shape,
|
|
838
|
+
annotations: {
|
|
839
|
+
readOnlyHint: true,
|
|
840
|
+
destructiveHint: false,
|
|
841
|
+
idempotentHint: true,
|
|
842
|
+
openWorldHint: false,
|
|
843
|
+
},
|
|
844
|
+
}, async ({ briefFile }) => {
|
|
845
|
+
try {
|
|
846
|
+
const resolvedFile = await resolveAllowedProductDesignBrief(briefFile);
|
|
847
|
+
const brief = await loadProductDesignBrief(resolvedFile);
|
|
848
|
+
const report = validateProductDesignBrief(brief, resolvedFile);
|
|
849
|
+
return {
|
|
850
|
+
content: [{ type: "text", text: formatProductBriefReport(report) }],
|
|
851
|
+
structuredContent: report,
|
|
852
|
+
...(report.generationReady ? {} : { isError: true }),
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
catch (error) {
|
|
856
|
+
const message = errorMessage(error);
|
|
857
|
+
console.error(`[validate_product_design_brief] ${message}`);
|
|
858
|
+
return {
|
|
859
|
+
isError: true,
|
|
860
|
+
content: [{ type: "text", text: message }],
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
server.registerTool("compile_design_plan", {
|
|
865
|
+
title: "Compile design plan",
|
|
866
|
+
description: "Compiles a version 1.0 product design brief into a deterministic and fully traceable information architecture, route proposal, component and state boundaries, downstream contract status, semantic token requirements, responsive behavior, asset policy, implementation stages, and verification obligations. Planned or invalid evidence remains provisional or blocked.",
|
|
867
|
+
inputSchema: {
|
|
868
|
+
briefFile: z
|
|
869
|
+
.string()
|
|
870
|
+
.trim()
|
|
871
|
+
.min(1)
|
|
872
|
+
.max(4_096)
|
|
873
|
+
.describe("Absolute path or configured-root-relative brief. The brief and existing downstream contracts must remain within a root listed in ZTOTHEZ_DESIGN_BRIEF_ROOTS."),
|
|
874
|
+
},
|
|
875
|
+
outputSchema: designPlanSchema.shape,
|
|
876
|
+
annotations: {
|
|
877
|
+
readOnlyHint: true,
|
|
878
|
+
destructiveHint: false,
|
|
879
|
+
idempotentHint: true,
|
|
880
|
+
openWorldHint: false,
|
|
881
|
+
},
|
|
882
|
+
}, async ({ briefFile }) => {
|
|
883
|
+
try {
|
|
884
|
+
const resolvedFile = await resolveAllowedProductDesignBrief(briefFile);
|
|
885
|
+
const roots = await configuredProductBriefRoots();
|
|
886
|
+
const projectRoot = roots.find((root) => isPathContained(root, resolvedFile));
|
|
887
|
+
if (!projectRoot)
|
|
888
|
+
throw new Error("The product design brief has no configured compilation root");
|
|
889
|
+
const brief = await loadProductDesignBrief(resolvedFile);
|
|
890
|
+
const plan = await compileDesignPlan(brief, { briefSourcePath: resolvedFile, projectRoot });
|
|
891
|
+
return {
|
|
892
|
+
content: [{ type: "text", text: formatDesignPlan(plan) }],
|
|
893
|
+
structuredContent: plan,
|
|
894
|
+
...(plan.status === "blocked" ? { isError: true } : {}),
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
catch (error) {
|
|
898
|
+
const message = errorMessage(error);
|
|
899
|
+
console.error(`[compile_design_plan] ${message}`);
|
|
900
|
+
return {
|
|
901
|
+
isError: true,
|
|
902
|
+
content: [{ type: "text", text: message }],
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
server.registerTool("validate_interface_trust", {
|
|
907
|
+
title: "Validate interface trust contract",
|
|
908
|
+
description: "Validates a versioned interface-trust YAML or JSON contract for data mode, connection, result origin, freshness, state-source traceability, pre-action disclosure, fallback and stale behavior, disconnected recovery, history and export provenance, and credential-like values. This checks declarations and cannot prove rendered or backend behavior.",
|
|
909
|
+
inputSchema: {
|
|
910
|
+
contractFile: z
|
|
911
|
+
.string()
|
|
912
|
+
.trim()
|
|
913
|
+
.min(1)
|
|
914
|
+
.max(4_096)
|
|
915
|
+
.describe("Absolute path or configured-root-relative contract. External roots must be listed in ZTOTHEZ_DESIGN_TRUST_ROOTS."),
|
|
916
|
+
},
|
|
917
|
+
outputSchema: interfaceTrustReportSchema.shape,
|
|
918
|
+
annotations: {
|
|
919
|
+
readOnlyHint: true,
|
|
920
|
+
destructiveHint: false,
|
|
921
|
+
idempotentHint: true,
|
|
922
|
+
openWorldHint: false,
|
|
923
|
+
},
|
|
924
|
+
}, async ({ contractFile }) => {
|
|
925
|
+
try {
|
|
926
|
+
const resolvedFile = await resolveAllowedInterfaceTrustContract(contractFile);
|
|
927
|
+
const contract = await loadInterfaceTrustContract(resolvedFile);
|
|
928
|
+
const report = validateInterfaceTrustContract(contract, resolvedFile);
|
|
929
|
+
return {
|
|
930
|
+
content: [{ type: "text", text: formatInterfaceTrustReport(report) }],
|
|
931
|
+
structuredContent: report,
|
|
932
|
+
...(report.passed ? {} : { isError: true }),
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
catch (error) {
|
|
936
|
+
const message = errorMessage(error);
|
|
937
|
+
console.error(`[validate_interface_trust] ${message}`);
|
|
938
|
+
return {
|
|
939
|
+
isError: true,
|
|
940
|
+
content: [{ type: "text", text: message }],
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
server.registerTool("validate_information_design", {
|
|
945
|
+
title: "Validate operational information design",
|
|
946
|
+
description: "Validates a versioned operational information-design YAML or JSON contract for source and context traceability, metric decisions, findings, chart purpose, exceptional value states, long labels, large collections, the eight-level hierarchy, non-color cues, and six answer-flow task declarations. This checks declarations and cannot prove rendered behavior or representative-user comprehension.",
|
|
947
|
+
inputSchema: {
|
|
948
|
+
contractFile: z
|
|
949
|
+
.string()
|
|
950
|
+
.trim()
|
|
951
|
+
.min(1)
|
|
952
|
+
.max(4_096)
|
|
953
|
+
.describe("Absolute path or configured-root-relative contract. External roots must be listed in ZTOTHEZ_DESIGN_INFORMATION_ROOTS."),
|
|
954
|
+
},
|
|
955
|
+
outputSchema: informationDesignReportSchema.shape,
|
|
956
|
+
annotations: {
|
|
957
|
+
readOnlyHint: true,
|
|
958
|
+
destructiveHint: false,
|
|
959
|
+
idempotentHint: true,
|
|
960
|
+
openWorldHint: false,
|
|
961
|
+
},
|
|
962
|
+
}, async ({ contractFile }) => {
|
|
963
|
+
try {
|
|
964
|
+
const resolvedFile = await resolveAllowedInformationDesignContract(contractFile);
|
|
965
|
+
const contract = await loadInformationDesignContract(resolvedFile);
|
|
966
|
+
const report = validateInformationDesignContract(contract, resolvedFile);
|
|
967
|
+
return {
|
|
968
|
+
content: [{ type: "text", text: formatInformationDesignReport(report) }],
|
|
969
|
+
structuredContent: report,
|
|
970
|
+
...(report.passed ? {} : { isError: true }),
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
catch (error) {
|
|
974
|
+
const message = errorMessage(error);
|
|
975
|
+
console.error(`[validate_information_design] ${message}`);
|
|
976
|
+
return {
|
|
977
|
+
isError: true,
|
|
978
|
+
content: [{ type: "text", text: message }],
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
server.registerTool("evaluate_interface_comparison", {
|
|
983
|
+
title: "Evaluate interface comparison",
|
|
984
|
+
description: "Validates a versioned anonymous interface-comparison methodology and review. It checks required stages, retained artifacts, claim scope, evidence-level separation, complete human matrices, counterbalancing, category scores, task metrics, and target-versus-comparator decisions. A valid review remains not release-ready until every configured human and benchmark threshold passes.",
|
|
985
|
+
inputSchema: {
|
|
986
|
+
methodologyFile: z
|
|
987
|
+
.string()
|
|
988
|
+
.trim()
|
|
989
|
+
.min(1)
|
|
990
|
+
.max(4_096)
|
|
991
|
+
.describe("Absolute path or configured-root-relative comparison methodology. External roots must be listed in ZTOTHEZ_DESIGN_COMPARISON_ROOTS."),
|
|
992
|
+
reviewFile: z
|
|
993
|
+
.string()
|
|
994
|
+
.trim()
|
|
995
|
+
.min(1)
|
|
996
|
+
.max(4_096)
|
|
997
|
+
.describe("Absolute path or configured-root-relative comparison review. External roots must be listed in ZTOTHEZ_DESIGN_COMPARISON_ROOTS."),
|
|
998
|
+
},
|
|
999
|
+
outputSchema: comparisonReportSchema.shape,
|
|
1000
|
+
annotations: {
|
|
1001
|
+
readOnlyHint: true,
|
|
1002
|
+
destructiveHint: false,
|
|
1003
|
+
idempotentHint: true,
|
|
1004
|
+
openWorldHint: false,
|
|
1005
|
+
},
|
|
1006
|
+
}, async ({ methodologyFile, reviewFile }) => {
|
|
1007
|
+
try {
|
|
1008
|
+
const [resolvedMethodology, resolvedReview] = await Promise.all([
|
|
1009
|
+
resolveAllowedComparisonFile(methodologyFile),
|
|
1010
|
+
resolveAllowedComparisonFile(reviewFile),
|
|
1011
|
+
]);
|
|
1012
|
+
const [methodology, review] = await Promise.all([
|
|
1013
|
+
loadComparisonMethodology(resolvedMethodology),
|
|
1014
|
+
loadComparisonReview(resolvedReview),
|
|
1015
|
+
]);
|
|
1016
|
+
const report = await evaluateInterfaceComparison(methodology, review, resolvedMethodology, resolvedReview);
|
|
1017
|
+
return {
|
|
1018
|
+
content: [{ type: "text", text: formatComparisonReport(report) }],
|
|
1019
|
+
structuredContent: report,
|
|
1020
|
+
...(report.passed ? {} : { isError: true }),
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
catch (error) {
|
|
1024
|
+
const message = errorMessage(error);
|
|
1025
|
+
console.error(`[evaluate_interface_comparison] ${message}`);
|
|
1026
|
+
return {
|
|
1027
|
+
isError: true,
|
|
1028
|
+
content: [{ type: "text", text: message }],
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
registerKnowledgeTool("get_dashboard_pattern", "List or read maintained project-owned AI-workspace and operational-dashboard patterns.", knowledgeAreas.uxPatterns);
|
|
1033
|
+
registerKnowledgeTool("get_usability_evaluation", "List or read maintained project-owned heuristic-evaluation guidance.", knowledgeAreas.usabilityEvaluation);
|
|
1034
|
+
server.registerTool("evaluate_heuristic_review", {
|
|
1035
|
+
title: "Evaluate heuristic review",
|
|
1036
|
+
description: "Validates a reviewer-provided heuristic-review YAML or JSON artifact, preserves automated, AI-assisted expert, human expert, and representative-user evidence as distinct levels, and derives unapplied acceptance-criterion candidates from open severity 3-4 findings. It never creates human attestations or modifies product contracts.",
|
|
1037
|
+
inputSchema: {
|
|
1038
|
+
reviewFile: z
|
|
1039
|
+
.string()
|
|
1040
|
+
.trim()
|
|
1041
|
+
.min(1)
|
|
1042
|
+
.max(4_096)
|
|
1043
|
+
.describe("Absolute path or configured-root-relative review file. External roots must be listed in ZTOTHEZ_DESIGN_HEURISTIC_REVIEW_ROOTS."),
|
|
1044
|
+
},
|
|
1045
|
+
outputSchema: heuristicReviewReportSchema.shape,
|
|
1046
|
+
annotations: {
|
|
1047
|
+
readOnlyHint: true,
|
|
1048
|
+
destructiveHint: false,
|
|
1049
|
+
idempotentHint: true,
|
|
1050
|
+
openWorldHint: false,
|
|
1051
|
+
},
|
|
1052
|
+
}, async ({ reviewFile }) => {
|
|
1053
|
+
try {
|
|
1054
|
+
const resolvedFile = await resolveAllowedHeuristicReview(reviewFile);
|
|
1055
|
+
const review = await loadHeuristicReview(resolvedFile);
|
|
1056
|
+
const report = evaluateHeuristicReview(review, resolvedFile);
|
|
1057
|
+
return {
|
|
1058
|
+
content: [{ type: "text", text: formatHeuristicReviewReport(report) }],
|
|
1059
|
+
structuredContent: report,
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
catch (error) {
|
|
1063
|
+
const message = errorMessage(error);
|
|
1064
|
+
console.error(`[evaluate_heuristic_review] ${message}`);
|
|
1065
|
+
return {
|
|
1066
|
+
isError: true,
|
|
1067
|
+
content: [{ type: "text", text: message }],
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
const auditFindingSchema = z.object({
|
|
1072
|
+
ruleId: z.string(),
|
|
1073
|
+
severity: z.enum(["error", "warning", "info"]),
|
|
1074
|
+
confidence: z.enum(["high", "medium", "low"]),
|
|
1075
|
+
file: z.string(),
|
|
1076
|
+
line: z.number().int().positive().optional(),
|
|
1077
|
+
column: z.number().int().positive().optional(),
|
|
1078
|
+
message: z.string(),
|
|
1079
|
+
evidence: z.array(z.string()),
|
|
1080
|
+
remediation: z.string(),
|
|
1081
|
+
});
|
|
1082
|
+
const auditReportSchema = {
|
|
1083
|
+
version: z.string(),
|
|
1084
|
+
target: z.string(),
|
|
1085
|
+
generatedAt: z.string(),
|
|
1086
|
+
filesScanned: z.number().int().nonnegative(),
|
|
1087
|
+
bytesScanned: z.number().int().nonnegative(),
|
|
1088
|
+
skippedFiles: z.array(z.object({ file: z.string(), reason: z.string() })),
|
|
1089
|
+
findings: z.array(auditFindingSchema),
|
|
1090
|
+
summary: z.object({
|
|
1091
|
+
errors: z.number().int().nonnegative(),
|
|
1092
|
+
warnings: z.number().int().nonnegative(),
|
|
1093
|
+
info: z.number().int().nonnegative(),
|
|
1094
|
+
}),
|
|
1095
|
+
passed: z.boolean(),
|
|
1096
|
+
evidenceBoundary: z.object({
|
|
1097
|
+
verifierLimitations: z.array(z.string()),
|
|
1098
|
+
humanReviewRequired: z.array(z.string()),
|
|
1099
|
+
}),
|
|
1100
|
+
};
|
|
1101
|
+
server.registerTool("list_portfolio_projects", {
|
|
1102
|
+
title: "List locally enabled portfolio projects",
|
|
1103
|
+
description: "Lists project IDs, cohorts, archetypes, adapters, and declared benchmark capabilities from an explicitly enabled local registry. It never exposes source roots or executes project commands.",
|
|
1104
|
+
inputSchema: {},
|
|
1105
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1106
|
+
}, async () => {
|
|
1107
|
+
try {
|
|
1108
|
+
const report = await listPortfolioProjectsForMcp();
|
|
1109
|
+
return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }], structuredContent: report };
|
|
1110
|
+
}
|
|
1111
|
+
catch (error) {
|
|
1112
|
+
const message = errorMessage(error);
|
|
1113
|
+
console.error(`[list_portfolio_projects] ${message}`);
|
|
1114
|
+
return { isError: true, content: [{ type: "text", text: message }] };
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
server.registerTool("get_portfolio_benchmark_report", {
|
|
1118
|
+
title: "Read a completed local portfolio benchmark",
|
|
1119
|
+
description: "Reads a completed structured benchmark summary from an explicitly enabled private report root. It returns no absolute source paths, cannot start benchmarks, and optionally scopes the result to one project ID.",
|
|
1120
|
+
inputSchema: {
|
|
1121
|
+
runId: z.string().regex(/^[a-z0-9][a-z0-9._-]{0,127}$/i),
|
|
1122
|
+
projectId: z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/).optional(),
|
|
1123
|
+
},
|
|
1124
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
1125
|
+
}, async ({ runId, projectId }) => {
|
|
1126
|
+
try {
|
|
1127
|
+
const report = await readPortfolioReportForMcp(runId, projectId);
|
|
1128
|
+
return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }], structuredContent: report };
|
|
1129
|
+
}
|
|
1130
|
+
catch (error) {
|
|
1131
|
+
const message = errorMessage(error);
|
|
1132
|
+
console.error(`[get_portfolio_benchmark_report] ${message}`);
|
|
1133
|
+
return { isError: true, content: [{ type: "text", text: message }] };
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
server.registerTool("audit_repository_architecture", {
|
|
1137
|
+
title: "Audit repository architecture",
|
|
1138
|
+
description: "Read-only static audit for UI source architecture, hard-coded credential literals, undisclosed mock paths, inert or incomplete interactions, unbound operational claims, raw design values, network state handling, accessibility names, and repository verification scripts. This does not prove runtime or visual correctness.",
|
|
1139
|
+
inputSchema: {
|
|
1140
|
+
targetDirectory: z
|
|
1141
|
+
.string()
|
|
1142
|
+
.trim()
|
|
1143
|
+
.min(1)
|
|
1144
|
+
.max(4096)
|
|
1145
|
+
.describe("Absolute path or configured-root-relative repository directory. External roots must be listed in ZTOTHEZ_DESIGN_AUDIT_ROOTS."),
|
|
1146
|
+
componentLineWarning: z.number().int().min(100).max(2_000).optional(),
|
|
1147
|
+
mixedResponsibilitiesMinLines: z.number().int().min(50).max(2_000).optional(),
|
|
1148
|
+
},
|
|
1149
|
+
outputSchema: auditReportSchema,
|
|
1150
|
+
annotations: {
|
|
1151
|
+
readOnlyHint: true,
|
|
1152
|
+
destructiveHint: false,
|
|
1153
|
+
idempotentHint: true,
|
|
1154
|
+
openWorldHint: false,
|
|
1155
|
+
},
|
|
1156
|
+
}, async ({ targetDirectory, componentLineWarning, mixedResponsibilitiesMinLines }) => {
|
|
1157
|
+
try {
|
|
1158
|
+
const target = await resolveAllowedAuditTarget(targetDirectory);
|
|
1159
|
+
const report = await auditRepository(target, {
|
|
1160
|
+
...(componentLineWarning === undefined ? {} : { componentLineWarning }),
|
|
1161
|
+
...(mixedResponsibilitiesMinLines === undefined
|
|
1162
|
+
? {}
|
|
1163
|
+
: { mixedResponsibilitiesMinLines }),
|
|
1164
|
+
});
|
|
1165
|
+
return {
|
|
1166
|
+
content: [{ type: "text", text: formatAuditReport(report) }],
|
|
1167
|
+
structuredContent: report,
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
catch (error) {
|
|
1171
|
+
const message = errorMessage(error);
|
|
1172
|
+
console.error(`[audit_repository_architecture] ${message}`);
|
|
1173
|
+
return {
|
|
1174
|
+
isError: true,
|
|
1175
|
+
content: [{ type: "text", text: message }],
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
server.registerTool("verify_ui_runtime", {
|
|
1180
|
+
title: "Verify UI runtime",
|
|
1181
|
+
description: "Launches headless Chromium against an already-running UI, captures checksummed base and post-journey responsive screenshots, and checks overflow, clipping, collisions, text and opt-in visual contrast, touch targets, focus visibility and occlusion, keyboard traps and ordering, 200% reflow and text resizing, reduced motion, media, console and network failures, interface trust, chart alternatives, decision hierarchy, clutter, visual claims, and asset metadata. Optional light and dark modes and declarative journeys are rechecked at every configured viewport. It does not start applications or execute repository commands.",
|
|
1182
|
+
inputSchema: {
|
|
1183
|
+
url: z.string().trim().min(1).max(4_096),
|
|
1184
|
+
reportName: z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/i).optional(),
|
|
1185
|
+
viewports: z.array(runtimeViewportSchema).min(1).max(8).optional(),
|
|
1186
|
+
colorSchemes: z.array(z.enum(["light", "dark"])).min(1).max(2).optional(),
|
|
1187
|
+
journeys: z.array(runtimeJourneySchema).max(10).optional(),
|
|
1188
|
+
expectedNetwork: z.array(runtimeExpectedNetworkSchema).max(20).optional(),
|
|
1189
|
+
settleMs: z.number().int().min(0).max(30_000).optional(),
|
|
1190
|
+
dynamicSelectors: z.array(z.string().min(1).max(1_024)).max(20).optional(),
|
|
1191
|
+
},
|
|
1192
|
+
outputSchema: runtimeReportSchema,
|
|
1193
|
+
annotations: {
|
|
1194
|
+
readOnlyHint: false,
|
|
1195
|
+
destructiveHint: false,
|
|
1196
|
+
idempotentHint: false,
|
|
1197
|
+
openWorldHint: true,
|
|
1198
|
+
},
|
|
1199
|
+
}, async ({ url, reportName, viewports, colorSchemes, journeys, expectedNetwork, settleMs, dynamicSelectors }) => {
|
|
1200
|
+
try {
|
|
1201
|
+
if (!isAllowedRuntimeUrl(url)) {
|
|
1202
|
+
throw new Error("Runtime URL is not allowed. Loopback origins are enabled by default; configure exact external origins with ZTOTHEZ_DESIGN_RUNTIME_ORIGINS.");
|
|
1203
|
+
}
|
|
1204
|
+
const outputDirectory = await createRuntimeOutputDirectory(reportName);
|
|
1205
|
+
const report = await verifyUiRuntime({
|
|
1206
|
+
url,
|
|
1207
|
+
outputDirectory,
|
|
1208
|
+
...(viewports ? { viewports } : {}),
|
|
1209
|
+
...(colorSchemes ? { colorSchemes } : {}),
|
|
1210
|
+
...(journeys ? { journeys } : {}),
|
|
1211
|
+
...(expectedNetwork ? { expectedNetwork } : {}),
|
|
1212
|
+
...(settleMs === undefined ? {} : { settleMs }),
|
|
1213
|
+
...(dynamicSelectors ? { dynamicSelectors } : {}),
|
|
1214
|
+
});
|
|
1215
|
+
return {
|
|
1216
|
+
content: [{ type: "text", text: formatRuntimeReport(report) }],
|
|
1217
|
+
structuredContent: report,
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
catch (error) {
|
|
1221
|
+
const message = errorMessage(error);
|
|
1222
|
+
console.error(`[verify_ui_runtime] ${message}`);
|
|
1223
|
+
return {
|
|
1224
|
+
isError: true,
|
|
1225
|
+
content: [{ type: "text", text: message }],
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
server.registerTool("run_design_quality_gate", {
|
|
1230
|
+
title: "Run ZtotheZ Design Engineering quality gate",
|
|
1231
|
+
description: "Runs product-contract validation, static architecture auditing, and a selected browser journey profile against an already-running UI, then writes one consolidated pass/fail evidence report. It does not start applications or execute repository commands.",
|
|
1232
|
+
inputSchema: {
|
|
1233
|
+
contract: z
|
|
1234
|
+
.string()
|
|
1235
|
+
.trim()
|
|
1236
|
+
.min(1)
|
|
1237
|
+
.max(512)
|
|
1238
|
+
.describe("Path relative to knowledge-base/benchmarks, such as aegisops/product-contract.yaml"),
|
|
1239
|
+
targetDirectory: z
|
|
1240
|
+
.string()
|
|
1241
|
+
.trim()
|
|
1242
|
+
.min(1)
|
|
1243
|
+
.max(4_096)
|
|
1244
|
+
.describe("Repository path allowed by ZTOTHEZ_DESIGN_AUDIT_ROOTS"),
|
|
1245
|
+
url: z.string().trim().min(1).max(4_096),
|
|
1246
|
+
profile: z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/),
|
|
1247
|
+
reportName: z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/i).optional(),
|
|
1248
|
+
failOn: z.enum(["error", "warning"]).optional(),
|
|
1249
|
+
settleMs: z.number().int().min(0).max(30_000).optional(),
|
|
1250
|
+
attestations: z
|
|
1251
|
+
.string()
|
|
1252
|
+
.trim()
|
|
1253
|
+
.min(1)
|
|
1254
|
+
.max(512)
|
|
1255
|
+
.optional()
|
|
1256
|
+
.describe("Optional path relative to knowledge-base/benchmarks"),
|
|
1257
|
+
},
|
|
1258
|
+
outputSchema: qualityGateReportSchema,
|
|
1259
|
+
annotations: {
|
|
1260
|
+
readOnlyHint: false,
|
|
1261
|
+
destructiveHint: false,
|
|
1262
|
+
idempotentHint: false,
|
|
1263
|
+
openWorldHint: true,
|
|
1264
|
+
},
|
|
1265
|
+
}, async ({ contract, targetDirectory, url, profile, reportName, failOn, settleMs, attestations }) => {
|
|
1266
|
+
try {
|
|
1267
|
+
if (!isAllowedRuntimeUrl(url)) {
|
|
1268
|
+
throw new Error("Runtime URL is not allowed. Loopback origins are enabled by default; configure exact external origins with ZTOTHEZ_DESIGN_RUNTIME_ORIGINS.");
|
|
1269
|
+
}
|
|
1270
|
+
const contractPath = await resolveBenchmarkContract(contract);
|
|
1271
|
+
const repository = await resolveAllowedAuditTarget(targetDirectory);
|
|
1272
|
+
const attestationsPath = attestations
|
|
1273
|
+
? await resolveBenchmarkAttestations(attestations)
|
|
1274
|
+
: undefined;
|
|
1275
|
+
const outputDirectory = await createQualityGateOutputDirectory(reportName);
|
|
1276
|
+
const report = await runQualityGate({
|
|
1277
|
+
contractPath,
|
|
1278
|
+
projectRoot: PROJECT_ROOT,
|
|
1279
|
+
repository,
|
|
1280
|
+
outputDirectory,
|
|
1281
|
+
url,
|
|
1282
|
+
profile,
|
|
1283
|
+
...(failOn ? { failOn } : {}),
|
|
1284
|
+
...(settleMs === undefined ? {} : { settleMs }),
|
|
1285
|
+
...(attestationsPath ? { attestationsPath } : {}),
|
|
1286
|
+
});
|
|
1287
|
+
return {
|
|
1288
|
+
content: [{ type: "text", text: formatQualityGateReport(report) }],
|
|
1289
|
+
structuredContent: report,
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
catch (error) {
|
|
1293
|
+
const message = errorMessage(error);
|
|
1294
|
+
console.error(`[run_design_quality_gate] ${message}`);
|
|
1295
|
+
return {
|
|
1296
|
+
isError: true,
|
|
1297
|
+
content: [{ type: "text", text: message }],
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
server.registerTool("aggregate_design_quality_gates", {
|
|
1302
|
+
title: "Aggregate ZtotheZ Design Engineering quality gates",
|
|
1303
|
+
description: "Combines previously generated profile quality-gate and acceptance reports into one contract-derived release decision. Every required profile must be present exactly once, complete, and evaluated with the same failure policy.",
|
|
1304
|
+
inputSchema: {
|
|
1305
|
+
contract: z
|
|
1306
|
+
.string()
|
|
1307
|
+
.trim()
|
|
1308
|
+
.min(1)
|
|
1309
|
+
.max(512)
|
|
1310
|
+
.describe("Path relative to knowledge-base/benchmarks, such as aegisops/product-contract.yaml"),
|
|
1311
|
+
reportDirectories: z
|
|
1312
|
+
.array(z.string().regex(/^[a-z0-9][a-z0-9._-]{0,127}$/i))
|
|
1313
|
+
.min(1)
|
|
1314
|
+
.max(20)
|
|
1315
|
+
.describe("Directory names within ZTOTHEZ_DESIGN_QUALITY_GATE_OUTPUT_ROOT"),
|
|
1316
|
+
reportName: z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/i).optional(),
|
|
1317
|
+
failOn: z.enum(["error", "warning"]).optional(),
|
|
1318
|
+
},
|
|
1319
|
+
outputSchema: aggregateReportSchema.shape,
|
|
1320
|
+
annotations: {
|
|
1321
|
+
readOnlyHint: false,
|
|
1322
|
+
destructiveHint: false,
|
|
1323
|
+
idempotentHint: false,
|
|
1324
|
+
openWorldHint: false,
|
|
1325
|
+
},
|
|
1326
|
+
}, async ({ contract, reportDirectories, reportName, failOn }) => {
|
|
1327
|
+
try {
|
|
1328
|
+
const contractPath = await resolveBenchmarkContract(contract);
|
|
1329
|
+
const directories = await Promise.all(reportDirectories.map((name) => resolveQualityGateReportDirectory(name)));
|
|
1330
|
+
const outputDirectory = await createQualityGateOutputDirectory(reportName ? `${reportName}-release` : "release");
|
|
1331
|
+
const report = await aggregateQualityGates({
|
|
1332
|
+
contractPath,
|
|
1333
|
+
projectRoot: PROJECT_ROOT,
|
|
1334
|
+
reportDirectories: directories,
|
|
1335
|
+
outputDirectory,
|
|
1336
|
+
...(failOn ? { failOn } : {}),
|
|
1337
|
+
});
|
|
1338
|
+
return {
|
|
1339
|
+
content: [{ type: "text", text: formatAggregateReport(report) }],
|
|
1340
|
+
structuredContent: report,
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
catch (error) {
|
|
1344
|
+
const message = errorMessage(error);
|
|
1345
|
+
console.error(`[aggregate_design_quality_gates] ${message}`);
|
|
1346
|
+
return {
|
|
1347
|
+
isError: true,
|
|
1348
|
+
content: [{ type: "text", text: message }],
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
//# sourceMappingURL=server.js.map
|