@lyse-labs/lyse 0.1.0-alpha.2
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 +45 -0
- package/PRIVACY.md +181 -0
- package/README.md +34 -0
- package/SECURITY.md +43 -0
- package/dist/bench/evidence-pack/anti-dummy.d.ts +11 -0
- package/dist/bench/evidence-pack/anti-dummy.js +20 -0
- package/dist/bench/evidence-pack/anti-dummy.js.map +1 -0
- package/dist/bench/evidence-pack/builder.d.ts +14 -0
- package/dist/bench/evidence-pack/builder.js +77 -0
- package/dist/bench/evidence-pack/builder.js.map +1 -0
- package/dist/bench/evidence-pack/histograms.d.ts +2 -0
- package/dist/bench/evidence-pack/histograms.js +131 -0
- package/dist/bench/evidence-pack/histograms.js.map +1 -0
- package/dist/bench/evidence-pack/manifest-detector.d.ts +2 -0
- package/dist/bench/evidence-pack/manifest-detector.js +65 -0
- package/dist/bench/evidence-pack/manifest-detector.js.map +1 -0
- package/dist/bench/evidence-pack/package-json-digest.d.ts +2 -0
- package/dist/bench/evidence-pack/package-json-digest.js +51 -0
- package/dist/bench/evidence-pack/package-json-digest.js.map +1 -0
- package/dist/bench/evidence-pack/sampler.d.ts +2 -0
- package/dist/bench/evidence-pack/sampler.js +140 -0
- package/dist/bench/evidence-pack/sampler.js.map +1 -0
- package/dist/bench/evidence-pack/types.d.ts +127 -0
- package/dist/bench/evidence-pack/types.js +2 -0
- package/dist/bench/evidence-pack/types.js.map +1 -0
- package/dist/bench/evidence-pack/verifier-corpus.d.ts +5 -0
- package/dist/bench/evidence-pack/verifier-corpus.js +13 -0
- package/dist/bench/evidence-pack/verifier-corpus.js.map +1 -0
- package/dist/bench/taxonomy-loader.d.ts +20 -0
- package/dist/bench/taxonomy-loader.js +28 -0
- package/dist/bench/taxonomy-loader.js.map +1 -0
- package/dist/bench/taxonomy.v3.json +20 -0
- package/dist/cli/__tests__/version-migration.test.d.ts +1 -0
- package/dist/cli/__tests__/version-migration.test.js +69 -0
- package/dist/cli/__tests__/version-migration.test.js.map +1 -0
- package/dist/cli/output/__tests__/eslint-style.test.d.ts +1 -0
- package/dist/cli/output/__tests__/eslint-style.test.js +205 -0
- package/dist/cli/output/__tests__/eslint-style.test.js.map +1 -0
- package/dist/cli/output/__tests__/limit.test.d.ts +1 -0
- package/dist/cli/output/__tests__/limit.test.js +65 -0
- package/dist/cli/output/__tests__/limit.test.js.map +1 -0
- package/dist/cli/output/eslint-style.d.ts +18 -0
- package/dist/cli/output/eslint-style.js +42 -0
- package/dist/cli/output/eslint-style.js.map +1 -0
- package/dist/cli/output/limit.d.ts +5 -0
- package/dist/cli/output/limit.js +32 -0
- package/dist/cli/output/limit.js.map +1 -0
- package/dist/cli/output/score-gauge.d.ts +4 -0
- package/dist/cli/output/score-gauge.js +15 -0
- package/dist/cli/output/score-gauge.js.map +1 -0
- package/dist/cli/version-migration.d.ts +18 -0
- package/dist/cli/version-migration.js +49 -0
- package/dist/cli/version-migration.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +856 -0
- package/dist/cli.js.map +1 -0
- package/dist/codemods/diff.d.ts +17 -0
- package/dist/codemods/diff.js +77 -0
- package/dist/codemods/diff.js.map +1 -0
- package/dist/codemods/git-helpers.d.ts +10 -0
- package/dist/codemods/git-helpers.js +75 -0
- package/dist/codemods/git-helpers.js.map +1 -0
- package/dist/codemods/index.d.ts +27 -0
- package/dist/codemods/index.js +40 -0
- package/dist/codemods/index.js.map +1 -0
- package/dist/codemods/naming-component-pascalcase.d.ts +13 -0
- package/dist/codemods/naming-component-pascalcase.js +106 -0
- package/dist/codemods/naming-component-pascalcase.js.map +1 -0
- package/dist/codemods/naming-hook-prefix.d.ts +13 -0
- package/dist/codemods/naming-hook-prefix.js +86 -0
- package/dist/codemods/naming-hook-prefix.js.map +1 -0
- package/dist/codemods/safety.d.ts +50 -0
- package/dist/codemods/safety.js +109 -0
- package/dist/codemods/safety.js.map +1 -0
- package/dist/codemods/safety.test.d.ts +1 -0
- package/dist/codemods/safety.test.js +154 -0
- package/dist/codemods/safety.test.js.map +1 -0
- package/dist/codemods/shadow-native.d.ts +2 -0
- package/dist/codemods/shadow-native.js +103 -0
- package/dist/codemods/shadow-native.js.map +1 -0
- package/dist/codemods/tokens-color.d.ts +2 -0
- package/dist/codemods/tokens-color.js +69 -0
- package/dist/codemods/tokens-color.js.map +1 -0
- package/dist/codemods/tokens-spacing.d.ts +2 -0
- package/dist/codemods/tokens-spacing.js +66 -0
- package/dist/codemods/tokens-spacing.js.map +1 -0
- package/dist/commands/__tests__/email-prompt.test.d.ts +1 -0
- package/dist/commands/__tests__/email-prompt.test.js +126 -0
- package/dist/commands/__tests__/email-prompt.test.js.map +1 -0
- package/dist/commands/__tests__/explain-score.test.d.ts +1 -0
- package/dist/commands/__tests__/explain-score.test.js +88 -0
- package/dist/commands/__tests__/explain-score.test.js.map +1 -0
- package/dist/commands/__tests__/feedback.test.d.ts +1 -0
- package/dist/commands/__tests__/feedback.test.js +186 -0
- package/dist/commands/__tests__/feedback.test.js.map +1 -0
- package/dist/commands/audit-flags.d.ts +49 -0
- package/dist/commands/audit-flags.js +17 -0
- package/dist/commands/audit-flags.js.map +1 -0
- package/dist/commands/audit-pipeline.d.ts +31 -0
- package/dist/commands/audit-pipeline.js +342 -0
- package/dist/commands/audit-pipeline.js.map +1 -0
- package/dist/commands/bench-pack.d.ts +5 -0
- package/dist/commands/bench-pack.js +61 -0
- package/dist/commands/bench-pack.js.map +1 -0
- package/dist/commands/ci-setup.d.ts +9 -0
- package/dist/commands/ci-setup.js +42 -0
- package/dist/commands/ci-setup.js.map +1 -0
- package/dist/commands/email-prompt.d.ts +36 -0
- package/dist/commands/email-prompt.js +160 -0
- package/dist/commands/email-prompt.js.map +1 -0
- package/dist/commands/explain-score.d.ts +35 -0
- package/dist/commands/explain-score.js +137 -0
- package/dist/commands/explain-score.js.map +1 -0
- package/dist/commands/explain.d.ts +6 -0
- package/dist/commands/explain.js +93 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/feedback.d.ts +31 -0
- package/dist/commands/feedback.js +155 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/fix.d.ts +48 -0
- package/dist/commands/fix.js +191 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/init-detect.d.ts +20 -0
- package/dist/commands/init-detect.js +124 -0
- package/dist/commands/init-detect.js.map +1 -0
- package/dist/commands/init-write-agents-md.d.ts +14 -0
- package/dist/commands/init-write-agents-md.js +71 -0
- package/dist/commands/init-write-agents-md.js.map +1 -0
- package/dist/commands/init-write-lyse-md.d.ts +14 -0
- package/dist/commands/init-write-lyse-md.js +253 -0
- package/dist/commands/init-write-lyse-md.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +147 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp-entry.d.ts +33 -0
- package/dist/commands/mcp-entry.js +47 -0
- package/dist/commands/mcp-entry.js.map +1 -0
- package/dist/commands/mcp-setup.d.ts +10 -0
- package/dist/commands/mcp-setup.js +74 -0
- package/dist/commands/mcp-setup.js.map +1 -0
- package/dist/commands/share.d.ts +4 -0
- package/dist/commands/share.js +60 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/telemetry.d.ts +4 -0
- package/dist/commands/telemetry.js +27 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/templates/lyse-workflow.yml.template +30 -0
- package/dist/config/schema.d.ts +158 -0
- package/dist/config/schema.js +136 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/credentials/keychain.d.ts +20 -0
- package/dist/credentials/keychain.js +35 -0
- package/dist/credentials/keychain.js.map +1 -0
- package/dist/credentials/keychain.test.d.ts +1 -0
- package/dist/credentials/keychain.test.js +32 -0
- package/dist/credentials/keychain.test.js.map +1 -0
- package/dist/credentials/paths.d.ts +1 -0
- package/dist/credentials/paths.js +6 -0
- package/dist/credentials/paths.js.map +1 -0
- package/dist/credentials/store.d.ts +17 -0
- package/dist/credentials/store.js +60 -0
- package/dist/credentials/store.js.map +1 -0
- package/dist/credentials/store.test.d.ts +1 -0
- package/dist/credentials/store.test.js +48 -0
- package/dist/credentials/store.test.js.map +1 -0
- package/dist/detection/from-filesystem.d.ts +2 -0
- package/dist/detection/from-filesystem.js +26 -0
- package/dist/detection/from-filesystem.js.map +1 -0
- package/dist/detection/from-git.d.ts +2 -0
- package/dist/detection/from-git.js +53 -0
- package/dist/detection/from-git.js.map +1 -0
- package/dist/detection/from-package-json.d.ts +2 -0
- package/dist/detection/from-package-json.js +194 -0
- package/dist/detection/from-package-json.js.map +1 -0
- package/dist/detection/pre-flight.d.ts +5 -0
- package/dist/detection/pre-flight.js +47 -0
- package/dist/detection/pre-flight.js.map +1 -0
- package/dist/detection/types.d.ts +27 -0
- package/dist/detection/types.js +2 -0
- package/dist/detection/types.js.map +1 -0
- package/dist/entitlement/check.d.ts +7 -0
- package/dist/entitlement/check.js +37 -0
- package/dist/entitlement/check.js.map +1 -0
- package/dist/entitlement/index.d.ts +1 -0
- package/dist/entitlement/index.js +2 -0
- package/dist/entitlement/index.js.map +1 -0
- package/dist/entitlement/keys.d.ts +10 -0
- package/dist/entitlement/keys.js +14 -0
- package/dist/entitlement/keys.js.map +1 -0
- package/dist/history/ndjson-store.d.ts +70 -0
- package/dist/history/ndjson-store.js +102 -0
- package/dist/history/ndjson-store.js.map +1 -0
- package/dist/identity/index.d.ts +1 -0
- package/dist/identity/index.js +2 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/repo-bucket.d.ts +22 -0
- package/dist/identity/repo-bucket.js +78 -0
- package/dist/identity/repo-bucket.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/layer4-stage.d.ts +18 -0
- package/dist/llm/layer4-stage.js +12 -0
- package/dist/llm/layer4-stage.js.map +1 -0
- package/dist/loaders/components.d.ts +26 -0
- package/dist/loaders/components.js +285 -0
- package/dist/loaders/components.js.map +1 -0
- package/dist/loaders/stories.d.ts +2 -0
- package/dist/loaders/stories.js +231 -0
- package/dist/loaders/stories.js.map +1 -0
- package/dist/loaders/token-graph.d.ts +39 -0
- package/dist/loaders/token-graph.js +146 -0
- package/dist/loaders/token-graph.js.map +1 -0
- package/dist/loaders/tokens.d.ts +2 -0
- package/dist/loaders/tokens.js +521 -0
- package/dist/loaders/tokens.js.map +1 -0
- package/dist/mcp/_find-root.d.ts +12 -0
- package/dist/mcp/_find-root.js +28 -0
- package/dist/mcp/_find-root.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +42 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/audit-file.d.ts +25 -0
- package/dist/mcp/tools/audit-file.js +147 -0
- package/dist/mcp/tools/audit-file.js.map +1 -0
- package/dist/mcp/tools/suggest-fix.d.ts +13 -0
- package/dist/mcp/tools/suggest-fix.js +100 -0
- package/dist/mcp/tools/suggest-fix.js.map +1 -0
- package/dist/menu/action-menu.d.ts +6 -0
- package/dist/menu/action-menu.js +15 -0
- package/dist/menu/action-menu.js.map +1 -0
- package/dist/menu/prompts.d.ts +7 -0
- package/dist/menu/prompts.js +30 -0
- package/dist/menu/prompts.js.map +1 -0
- package/dist/menu/repl.d.ts +17 -0
- package/dist/menu/repl.js +77 -0
- package/dist/menu/repl.js.map +1 -0
- package/dist/parsers/css-in-js.d.ts +2 -0
- package/dist/parsers/css-in-js.js +69 -0
- package/dist/parsers/css-in-js.js.map +1 -0
- package/dist/parsers/css.d.ts +2 -0
- package/dist/parsers/css.js +32 -0
- package/dist/parsers/css.js.map +1 -0
- package/dist/parsers/scss-transform.d.ts +25 -0
- package/dist/parsers/scss-transform.js +55 -0
- package/dist/parsers/scss-transform.js.map +1 -0
- package/dist/parsers/tailwind-v4.d.ts +8 -0
- package/dist/parsers/tailwind-v4.js +90 -0
- package/dist/parsers/tailwind-v4.js.map +1 -0
- package/dist/parsers/ts-morph-project.d.ts +16 -0
- package/dist/parsers/ts-morph-project.js +77 -0
- package/dist/parsers/ts-morph-project.js.map +1 -0
- package/dist/parsers/ts.d.ts +2 -0
- package/dist/parsers/ts.js +61 -0
- package/dist/parsers/ts.js.map +1 -0
- package/dist/reliability/__tests__/types.test.d.ts +1 -0
- package/dist/reliability/__tests__/types.test.js +14 -0
- package/dist/reliability/__tests__/types.test.js.map +1 -0
- package/dist/reliability/catalogue/__tests__/promotion.test.d.ts +1 -0
- package/dist/reliability/catalogue/__tests__/promotion.test.js +23 -0
- package/dist/reliability/catalogue/__tests__/promotion.test.js.map +1 -0
- package/dist/reliability/catalogue/__tests__/sub-axes.test.d.ts +1 -0
- package/dist/reliability/catalogue/__tests__/sub-axes.test.js +27 -0
- package/dist/reliability/catalogue/__tests__/sub-axes.test.js.map +1 -0
- package/dist/reliability/catalogue/promotion.d.ts +8 -0
- package/dist/reliability/catalogue/promotion.js +25 -0
- package/dist/reliability/catalogue/promotion.js.map +1 -0
- package/dist/reliability/catalogue/sub-axes.d.ts +3 -0
- package/dist/reliability/catalogue/sub-axes.js +18 -0
- package/dist/reliability/catalogue/sub-axes.js.map +1 -0
- package/dist/reliability/confidence/__tests__/manifest-loader.test.d.ts +1 -0
- package/dist/reliability/confidence/__tests__/manifest-loader.test.js +103 -0
- package/dist/reliability/confidence/__tests__/manifest-loader.test.js.map +1 -0
- package/dist/reliability/confidence/bundled-manifest.d.ts +2 -0
- package/dist/reliability/confidence/bundled-manifest.js +8 -0
- package/dist/reliability/confidence/bundled-manifest.js.map +1 -0
- package/dist/reliability/confidence/index.d.ts +3 -0
- package/dist/reliability/confidence/index.js +3 -0
- package/dist/reliability/confidence/index.js.map +1 -0
- package/dist/reliability/confidence/manifest-loader.d.ts +8 -0
- package/dist/reliability/confidence/manifest-loader.js +53 -0
- package/dist/reliability/confidence/manifest-loader.js.map +1 -0
- package/dist/reliability/feedback/__tests__/interactive.test.d.ts +1 -0
- package/dist/reliability/feedback/__tests__/interactive.test.js +85 -0
- package/dist/reliability/feedback/__tests__/interactive.test.js.map +1 -0
- package/dist/reliability/feedback/__tests__/repo-bucket.test.d.ts +1 -0
- package/dist/reliability/feedback/__tests__/repo-bucket.test.js +18 -0
- package/dist/reliability/feedback/__tests__/repo-bucket.test.js.map +1 -0
- package/dist/reliability/feedback/__tests__/sender.test.d.ts +1 -0
- package/dist/reliability/feedback/__tests__/sender.test.js +101 -0
- package/dist/reliability/feedback/__tests__/sender.test.js.map +1 -0
- package/dist/reliability/feedback/interactive.d.ts +20 -0
- package/dist/reliability/feedback/interactive.js +150 -0
- package/dist/reliability/feedback/interactive.js.map +1 -0
- package/dist/reliability/feedback/repo-bucket.d.ts +2 -0
- package/dist/reliability/feedback/repo-bucket.js +9 -0
- package/dist/reliability/feedback/repo-bucket.js.map +1 -0
- package/dist/reliability/feedback/sender.d.ts +16 -0
- package/dist/reliability/feedback/sender.js +28 -0
- package/dist/reliability/feedback/sender.js.map +1 -0
- package/dist/reliability/index.d.ts +1 -0
- package/dist/reliability/index.js +2 -0
- package/dist/reliability/index.js.map +1 -0
- package/dist/reliability/llm-eval/__tests__/budget.test.d.ts +1 -0
- package/dist/reliability/llm-eval/__tests__/budget.test.js +39 -0
- package/dist/reliability/llm-eval/__tests__/budget.test.js.map +1 -0
- package/dist/reliability/llm-eval/budget.d.ts +14 -0
- package/dist/reliability/llm-eval/budget.js +43 -0
- package/dist/reliability/llm-eval/budget.js.map +1 -0
- package/dist/reliability/score/__tests__/formula-v1.test.d.ts +1 -0
- package/dist/reliability/score/__tests__/formula-v1.test.js +29 -0
- package/dist/reliability/score/__tests__/formula-v1.test.js.map +1 -0
- package/dist/reliability/score/formula-v1.d.ts +13 -0
- package/dist/reliability/score/formula-v1.js +19 -0
- package/dist/reliability/score/formula-v1.js.map +1 -0
- package/dist/reliability/score/version-pin.d.ts +1 -0
- package/dist/reliability/score/version-pin.js +2 -0
- package/dist/reliability/score/version-pin.js.map +1 -0
- package/dist/reliability/score/weight.d.ts +1 -0
- package/dist/reliability/score/weight.js +5 -0
- package/dist/reliability/score/weight.js.map +1 -0
- package/dist/reliability/types.d.ts +39 -0
- package/dist/reliability/types.js +2 -0
- package/dist/reliability/types.js.map +1 -0
- package/dist/reporters/coverage-footer.d.ts +2 -0
- package/dist/reporters/coverage-footer.js +7 -0
- package/dist/reporters/coverage-footer.js.map +1 -0
- package/dist/reporters/json.d.ts +5 -0
- package/dist/reporters/json.js +51 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/markdown.d.ts +7 -0
- package/dist/reporters/markdown.js +35 -0
- package/dist/reporters/markdown.js.map +1 -0
- package/dist/reporters/sarif.d.ts +5 -0
- package/dist/reporters/sarif.js +109 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/terminal-format.d.ts +34 -0
- package/dist/reporters/terminal-format.js +97 -0
- package/dist/reporters/terminal-format.js.map +1 -0
- package/dist/reporters/terminal.d.ts +4 -0
- package/dist/reporters/terminal.js +201 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/rule-runner.d.ts +8 -0
- package/dist/rule-runner.js +22 -0
- package/dist/rule-runner.js.map +1 -0
- package/dist/rules/_codemod-adapter.d.ts +16 -0
- package/dist/rules/_codemod-adapter.js +49 -0
- package/dist/rules/_codemod-adapter.js.map +1 -0
- package/dist/rules/_exclude.d.ts +11 -0
- package/dist/rules/_exclude.js +17 -0
- package/dist/rules/_exclude.js.map +1 -0
- package/dist/rules/_function-body-analysis.d.ts +82 -0
- package/dist/rules/_function-body-analysis.js +379 -0
- package/dist/rules/_function-body-analysis.js.map +1 -0
- package/dist/rules/_rule-module.d.ts +31 -0
- package/dist/rules/_rule-module.js +32 -0
- package/dist/rules/_rule-module.js.map +1 -0
- package/dist/rules/_skip-context.d.ts +36 -0
- package/dist/rules/_skip-context.js +128 -0
- package/dist/rules/_skip-context.js.map +1 -0
- package/dist/rules/a11y-essentials.d.ts +1 -0
- package/dist/rules/a11y-essentials.js +140 -0
- package/dist/rules/a11y-essentials.js.map +1 -0
- package/dist/rules/ai-surface-agents-md-quality.d.ts +22 -0
- package/dist/rules/ai-surface-agents-md-quality.js +233 -0
- package/dist/rules/ai-surface-agents-md-quality.js.map +1 -0
- package/dist/rules/ai-surface-component-manifest-json.d.ts +19 -0
- package/dist/rules/ai-surface-component-manifest-json.js +232 -0
- package/dist/rules/ai-surface-component-manifest-json.js.map +1 -0
- package/dist/rules/ai-surface-ds-index-exported.d.ts +19 -0
- package/dist/rules/ai-surface-ds-index-exported.js +239 -0
- package/dist/rules/ai-surface-ds-index-exported.js.map +1 -0
- package/dist/rules/components-shadow-native.d.ts +2 -0
- package/dist/rules/components-shadow-native.js +118 -0
- package/dist/rules/components-shadow-native.js.map +1 -0
- package/dist/rules/manifest.d.ts +5 -0
- package/dist/rules/manifest.js +20 -0
- package/dist/rules/manifest.js.map +1 -0
- package/dist/rules/naming-component-pascalcase.d.ts +7 -0
- package/dist/rules/naming-component-pascalcase.js +197 -0
- package/dist/rules/naming-component-pascalcase.js.map +1 -0
- package/dist/rules/naming-hook-prefix.d.ts +6 -0
- package/dist/rules/naming-hook-prefix.js +185 -0
- package/dist/rules/naming-hook-prefix.js.map +1 -0
- package/dist/rules/pack-loader.d.ts +30 -0
- package/dist/rules/pack-loader.js +60 -0
- package/dist/rules/pack-loader.js.map +1 -0
- package/dist/rules/pack-validator.d.ts +8 -0
- package/dist/rules/pack-validator.js +97 -0
- package/dist/rules/pack-validator.js.map +1 -0
- package/dist/rules/registry.d.ts +3 -0
- package/dist/rules/registry.js +28 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/rules/storybook-coverage.d.ts +1 -0
- package/dist/rules/storybook-coverage.js +49 -0
- package/dist/rules/storybook-coverage.js.map +1 -0
- package/dist/rules/templates/_regex-utils.d.ts +5 -0
- package/dist/rules/templates/_regex-utils.js +8 -0
- package/dist/rules/templates/_regex-utils.js.map +1 -0
- package/dist/rules/templates/a11y-jsx-template.d.ts +15 -0
- package/dist/rules/templates/a11y-jsx-template.js +69 -0
- package/dist/rules/templates/a11y-jsx-template.js.map +1 -0
- package/dist/rules/templates/css-property-token-compliance.d.ts +18 -0
- package/dist/rules/templates/css-property-token-compliance.js +56 -0
- package/dist/rules/templates/css-property-token-compliance.js.map +1 -0
- package/dist/rules/templates/import-source-restriction.d.ts +18 -0
- package/dist/rules/templates/import-source-restriction.js +60 -0
- package/dist/rules/templates/import-source-restriction.js.map +1 -0
- package/dist/rules/templates/js-call-token-compliance.d.ts +18 -0
- package/dist/rules/templates/js-call-token-compliance.js +61 -0
- package/dist/rules/templates/js-call-token-compliance.js.map +1 -0
- package/dist/rules/templates/js-prop-token-compliance.d.ts +21 -0
- package/dist/rules/templates/js-prop-token-compliance.js +56 -0
- package/dist/rules/templates/js-prop-token-compliance.js.map +1 -0
- package/dist/rules/templates/naming-convention.d.ts +18 -0
- package/dist/rules/templates/naming-convention.js +76 -0
- package/dist/rules/templates/naming-convention.js.map +1 -0
- package/dist/rules/templates/registry.d.ts +5 -0
- package/dist/rules/templates/registry.js +30 -0
- package/dist/rules/templates/registry.js.map +1 -0
- package/dist/rules/templates/storybook-coverage-template.d.ts +15 -0
- package/dist/rules/templates/storybook-coverage-template.js +58 -0
- package/dist/rules/templates/storybook-coverage-template.js.map +1 -0
- package/dist/rules/templates/tailwind-utility-class-compliance.d.ts +15 -0
- package/dist/rules/templates/tailwind-utility-class-compliance.js +70 -0
- package/dist/rules/templates/tailwind-utility-class-compliance.js.map +1 -0
- package/dist/rules/templates/types.d.ts +16 -0
- package/dist/rules/templates/types.js +2 -0
- package/dist/rules/templates/types.js.map +1 -0
- package/dist/rules/tokens-description-coverage.d.ts +15 -0
- package/dist/rules/tokens-description-coverage.js +193 -0
- package/dist/rules/tokens-description-coverage.js.map +1 -0
- package/dist/rules/tokens-dtcg-conformance.d.ts +47 -0
- package/dist/rules/tokens-dtcg-conformance.js +363 -0
- package/dist/rules/tokens-dtcg-conformance.js.map +1 -0
- package/dist/rules/tokens-no-hardcoded-color.d.ts +18 -0
- package/dist/rules/tokens-no-hardcoded-color.js +436 -0
- package/dist/rules/tokens-no-hardcoded-color.js.map +1 -0
- package/dist/rules/tokens-no-hardcoded-spacing.d.ts +8 -0
- package/dist/rules/tokens-no-hardcoded-spacing.js +193 -0
- package/dist/rules/tokens-no-hardcoded-spacing.js.map +1 -0
- package/dist/scorer.d.ts +38 -0
- package/dist/scorer.js +126 -0
- package/dist/scorer.js.map +1 -0
- package/dist/share/clipboard.d.ts +26 -0
- package/dist/share/clipboard.js +76 -0
- package/dist/share/clipboard.js.map +1 -0
- package/dist/suppression/__tests__/inline.test.d.ts +1 -0
- package/dist/suppression/__tests__/inline.test.js +25 -0
- package/dist/suppression/__tests__/inline.test.js.map +1 -0
- package/dist/suppression/__tests__/lyseignore.test.d.ts +1 -0
- package/dist/suppression/__tests__/lyseignore.test.js +32 -0
- package/dist/suppression/__tests__/lyseignore.test.js.map +1 -0
- package/dist/suppression/defaults.d.ts +1 -0
- package/dist/suppression/defaults.js +14 -0
- package/dist/suppression/defaults.js.map +1 -0
- package/dist/suppression/inline.d.ts +7 -0
- package/dist/suppression/inline.js +32 -0
- package/dist/suppression/inline.js.map +1 -0
- package/dist/suppression/lyseignore.d.ts +2 -0
- package/dist/suppression/lyseignore.js +22 -0
- package/dist/suppression/lyseignore.js.map +1 -0
- package/dist/telemetry/consent.d.ts +48 -0
- package/dist/telemetry/consent.js +139 -0
- package/dist/telemetry/consent.js.map +1 -0
- package/dist/telemetry/index.d.ts +2 -0
- package/dist/telemetry/index.js +3 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/local-log.d.ts +64 -0
- package/dist/telemetry/local-log.js +123 -0
- package/dist/telemetry/local-log.js.map +1 -0
- package/dist/tokens/dtcg-model.d.ts +53 -0
- package/dist/tokens/dtcg-model.js +18 -0
- package/dist/tokens/dtcg-model.js.map +1 -0
- package/dist/tokens/normalizer.d.ts +17 -0
- package/dist/tokens/normalizer.js +360 -0
- package/dist/tokens/normalizer.js.map +1 -0
- package/dist/types.d.ts +300 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/util/git.d.ts +6 -0
- package/dist/util/git.js +40 -0
- package/dist/util/git.js.map +1 -0
- package/dist/util/git.test.d.ts +5 -0
- package/dist/util/git.test.js +42 -0
- package/dist/util/git.test.js.map +1 -0
- package/dist/util/gitignore.d.ts +9 -0
- package/dist/util/gitignore.js +39 -0
- package/dist/util/gitignore.js.map +1 -0
- package/dist/util/hash-deps.d.ts +6 -0
- package/dist/util/hash-deps.js +24 -0
- package/dist/util/hash-deps.js.map +1 -0
- package/dist/util/spinner.d.ts +41 -0
- package/dist/util/spinner.js +126 -0
- package/dist/util/spinner.js.map +1 -0
- package/dist/util/with-spinner.d.ts +11 -0
- package/dist/util/with-spinner.js +19 -0
- package/dist/util/with-spinner.js.map +1 -0
- package/dist/walker.d.ts +14 -0
- package/dist/walker.js +91 -0
- package/dist/walker.js.map +1 -0
- package/package.json +83 -0
- package/rules-manifest.json +289 -0
- package/schemas/v1/lyse-config.json +82 -0
- package/schemas/v1/lyse-event.json +68 -0
- package/schemas/v1/lyse-license.json +19 -0
- package/schemas/v1/lyse-llm-payload.json +53 -0
- package/schemas/v1/lyse-llm-response.json +45 -0
- package/schemas/v1/lyse-result.json +98 -0
- package/schemas/v1/lyse-rules.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Lyse — Dual License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Noé Chagué.
|
|
4
|
+
|
|
5
|
+
Lyse is dual-licensed. You may use, modify, and distribute it under
|
|
6
|
+
either:
|
|
7
|
+
|
|
8
|
+
1. **GNU Affero General Public License version 3** (AGPLv3) — see
|
|
9
|
+
[`LICENSE-AGPL-3.0.txt`](./LICENSE-AGPL-3.0.txt). Use this when you
|
|
10
|
+
accept the AGPLv3's network-copyleft requirements (notably: if you run
|
|
11
|
+
a modified version as a network service, you must offer your users the
|
|
12
|
+
modified source code).
|
|
13
|
+
|
|
14
|
+
2. **Commercial License** — see [`COMMERCIAL.md`](./COMMERCIAL.md). Use
|
|
15
|
+
this when you want to embed Lyse in a closed-source product,
|
|
16
|
+
re-host it as a SaaS without sharing source, or otherwise need terms
|
|
17
|
+
incompatible with AGPLv3.
|
|
18
|
+
|
|
19
|
+
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Lyse-Commercial
|
|
20
|
+
|
|
21
|
+
The official, complete AGPLv3 text is at <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
|
22
|
+
The copy committed alongside this file is verbatim from that URL.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED. Lyse outputs (scores, reports, AGENTS.md/DESIGN.md files)
|
|
26
|
+
are static-analysis artifacts and MUST NOT be used as the sole basis for
|
|
27
|
+
procurement, compliance, or accessibility-certification decisions.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Why dual?
|
|
32
|
+
|
|
33
|
+
The MVP is fully open-source under AGPLv3. AGPLv3's network clause prevents
|
|
34
|
+
larger vendors from rebundling Lyse as a closed-source SaaS without
|
|
35
|
+
contributing back. The Commercial License exists for users whose own
|
|
36
|
+
licensing or distribution model is incompatible with AGPLv3 (e.g. embedding
|
|
37
|
+
Lyse's engine in a proprietary product).
|
|
38
|
+
|
|
39
|
+
The **GitHub Action wrapper** (`lyse-labs/lyse-action`, separate
|
|
40
|
+
repository) is published under the **MIT License** to maximise compatibility
|
|
41
|
+
with the GitHub Actions / Marketplace ecosystem. Only the engine in this
|
|
42
|
+
repository is AGPLv3-dual-licensed.
|
|
43
|
+
|
|
44
|
+
For commercial licensing inquiries: noe@getlyse.com (TBD) /
|
|
45
|
+
contact@lyse-labs.com.
|
package/PRIVACY.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Privacy Notice — Lyse
|
|
2
|
+
|
|
3
|
+
**Controller:** Lyse Labs
|
|
4
|
+
**Contact:** contact@getlyse.com
|
|
5
|
+
|
|
6
|
+
This document fulfils the transparency obligations of **GDPR Articles 13–14** and the related French CNIL guidance. It describes what Lyse collects, when, why, and what your rights are.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Default audit: static-only, fully local
|
|
11
|
+
|
|
12
|
+
`lyse audit` is **static-only by default**: it parses your code on your machine, computes the Health Score, and returns. No network calls. Nothing leaves the runner.
|
|
13
|
+
|
|
14
|
+
### Optional LLM-assisted flows (BYOK)
|
|
15
|
+
|
|
16
|
+
A few entry points may call out to an LLM provider you configure (Anthropic, OpenAI, OpenRouter, your local Ollama, or your IDE's LLM via MCP). They are **off by default** and you choose the provider:
|
|
17
|
+
|
|
18
|
+
- `lyse init` (only if an LLM credential is detected or you explicitly opt in) — generates a tailored rule pack.
|
|
19
|
+
- MCP host LLMs (Cursor / Claude Code / Codex) when your agent calls Lyse's MCP tools — that traffic goes through the IDE's own provider, not through Lyse.
|
|
20
|
+
|
|
21
|
+
When an LLM-assisted flow does run, what Lyse sends:
|
|
22
|
+
|
|
23
|
+
- The static findings from the current audit (~5–15 KB).
|
|
24
|
+
- 8–15 representative source files, capped at 200 KB total, selected to cover the DS dimensions being analyzed.
|
|
25
|
+
- Your `package.json` (dependencies only — `scripts` and other fields are stripped).
|
|
26
|
+
|
|
27
|
+
What Lyse never sends:
|
|
28
|
+
|
|
29
|
+
- `.env*`, `*.pem`, `*.key`, `*.p12`, `id_rsa*`, or any file matching the secret-content regex set.
|
|
30
|
+
- Anything matched by your `.gitignore`.
|
|
31
|
+
- The full source tree at any time.
|
|
32
|
+
|
|
33
|
+
Every LLM call is logged at `.lyse/llm-calls.jsonl` (git-ignored). You can audit them after each run.
|
|
34
|
+
|
|
35
|
+
`lyse audit --static-only` and `llm: { provider: 'none' }` in `.lyse.yaml` are explicit escape hatches that turn every LLM path off.
|
|
36
|
+
|
|
37
|
+
**Lyse Labs never sees your code, your findings, your scores, or your API keys.** We do not run a proxy, do not host any LLM endpoint, and do not receive telemetry from your audits (telemetry remains opt-in only — see [Telemetry](#telemetry) below).
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 1a. Telemetry (opt-in only)
|
|
42
|
+
|
|
43
|
+
We collect data **only** when you explicitly opt in via the first-run consent prompt shown on your first `lyse audit`.
|
|
44
|
+
|
|
45
|
+
**Telemetry defaults to OFF.** It requires an explicit affirmative action — pressing `y` at the prompt.
|
|
46
|
+
|
|
47
|
+
### First-run consent prompt
|
|
48
|
+
|
|
49
|
+
On your first `lyse audit`, Lyse displays a one-time prompt describing exactly what data would be sent. Pressing `y` enables anonymous telemetry; pressing Enter, `n`, or interrupting the prompt declines. **The audit runs to completion in both cases — there is no functional difference between accepting and declining.** Your answer is saved to `~/.lyse/consent.json` and Lyse never prompts you again, except: if you decline on the first prompt, Lyse will ask one more time on your next audit (max two prompts in your lifetime). You can change your answer at any time (see §7).
|
|
50
|
+
|
|
51
|
+
In non-interactive environments (CI, scripts, piped output), no prompt is shown and telemetry remains OFF unless explicitly enabled.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. What data we receive when telemetry is enabled
|
|
56
|
+
|
|
57
|
+
If — and only if — you opt in (by answering `y` at the first-run prompt, or by running `lyse telemetry on`): events are written to `.lyse/events.ndjson` in your repo.
|
|
58
|
+
|
|
59
|
+
The full event schema is published at [`schemas/v1/lyse-event.json`](./packages/core/schemas/v1/lyse-event.json) and contains:
|
|
60
|
+
|
|
61
|
+
| Field | Type | Example |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `schema_version` | int | `1` |
|
|
64
|
+
| `event_id` | string (hex) | `"01HXYZ0123456789ABCDEFGHIJ"` |
|
|
65
|
+
| `event_type` | enum | `"audit.completed"` |
|
|
66
|
+
| `ts` | ISO date | `"<iso-timestamp>"` |
|
|
67
|
+
| `session_id` | string (hex) | `"01HXYZ0123456789ABCDEFGHIJ"` |
|
|
68
|
+
| `repo_bucket` | string (hex, 16 char) | server-derived hash of the repo identifier with a server-side salt rotated daily |
|
|
69
|
+
| `sdk_version` | string | `"0.1.0"` |
|
|
70
|
+
| `audit.score` | int 0-100 or `null` | `43` |
|
|
71
|
+
| `audit.axes` | object | `{ tokens: 30, a11y: 60, components: 38, stories: 47 }` |
|
|
72
|
+
| `audit.violations` | object | `{ error: 0, warning: 433, info: 0 }` |
|
|
73
|
+
| `audit.duration_ms` | int | `8341` |
|
|
74
|
+
| `stack` | object | `{ framework: "react", ds_detected: "tailwind-v4" }` |
|
|
75
|
+
| `finding.file_hash` | hex(8) | `"abcd1234"` — `SHA-256(filepath + salt)` truncated; **not reversible** |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. What we explicitly DO NOT collect
|
|
80
|
+
|
|
81
|
+
- **No source code, file paths, or file content.** The `file_hash` field is an 8-character SHA-256 prefix of the file path with a server-side salt — the original path cannot be recovered.
|
|
82
|
+
- **No IP address.** The Cloudflare Worker handling `/v1/events` drops the `CF-Connecting-IP` header before any storage operation.
|
|
83
|
+
- **No User-Agent.** Same — dropped at the edge.
|
|
84
|
+
- **No GitHub username or actor identifier in stored data.** The OIDC `repository_id` is used transiently for rate-limiting and then discarded; only the salted hash is retained.
|
|
85
|
+
- **No personal data of any kind** (email, name, organisation name in cleartext).
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 4. Legal basis
|
|
90
|
+
|
|
91
|
+
**Article 6(1)(a) — explicit consent.** Consent is given by pressing `y` at the first-run prompt. Telemetry defaults to OFF and requires an affirmative action — pressing Enter or declining at the prompt leaves telemetry OFF, and the audit runs identically in both cases (no service is conditioned on consent, per Art. 7(4)).
|
|
92
|
+
|
|
93
|
+
We do not rely on legitimate interest (Art. 6(1)(f)) because the explicit-consent path is clean, machine-checkable, and survives a CNIL audit without an LIA balancing test.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 5. Retention
|
|
98
|
+
|
|
99
|
+
- **Events (local):** written to `.lyse/events.ndjson` in your own repo. Retention is at your discretion as the data controller.
|
|
100
|
+
- **Aggregated counts** (used for the public `/v1/bench/summary` endpoint): retained indefinitely as pure statistical aggregates — no individual event is recoverable.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## LLM provider data flow (when you opt in)
|
|
105
|
+
|
|
106
|
+
If you enable an LLM-assisted flow (see §1), the provider you configure receives only the payload described in §1. You control the provider entirely:
|
|
107
|
+
|
|
108
|
+
| Provider mode | Where data goes | Cost to user |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| Anthropic (`ANTHROPIC_API_KEY`) | `api.anthropic.com` | per token, your bill |
|
|
111
|
+
| OpenAI (`OPENAI_API_KEY`) | `api.openai.com` | per token, your bill |
|
|
112
|
+
| OpenAI-compatible (`LYSE_LLM_ENDPOINT`) | user-configured endpoint (Ollama local, Together, Groq, etc.) | depends |
|
|
113
|
+
| OpenRouter (OAuth) | `openrouter.ai` → underlying provider | ~10% mark-up, your bill |
|
|
114
|
+
| MCP host (Cursor, Claude Code) | the IDE's LLM provider | covered by IDE subscription |
|
|
115
|
+
| `none` / `--static-only` | nowhere | n/a |
|
|
116
|
+
|
|
117
|
+
Files excluded from the data flow:
|
|
118
|
+
|
|
119
|
+
- `node_modules`, `dist`, `build`, `.git`, `.next`, `coverage`, `.lyse`
|
|
120
|
+
- Everything in `.gitignore`
|
|
121
|
+
- Files containing common secret patterns (`.env*`, `*.pem`, `*.key`, content
|
|
122
|
+
starting with `-----BEGIN PRIVATE KEY-----` etc.)
|
|
123
|
+
|
|
124
|
+
Audit trail: every LLM call is appended to `.lyse/llm-calls.jsonl` (per-repo, git-ignored). Inspect via `cat .lyse/llm-calls.jsonl | jq`.
|
|
125
|
+
|
|
126
|
+
Permanent opt-out: set `llm: { provider: 'none' }` in `.lyse.yaml`.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 5b. Optional email capture (`lyse init`)
|
|
131
|
+
|
|
132
|
+
At the **end** of the `lyse init` wizard, Lyse asks once whether you'd like
|
|
133
|
+
to be notified of major releases and security disclosures. The prompt is:
|
|
134
|
+
|
|
135
|
+
- Strictly opt-in. Pressing Enter (no input) skips it and stores nothing.
|
|
136
|
+
- Suppressed entirely in CI, non-TTY contexts, `--yes` mode, or when
|
|
137
|
+
`LYSE_NO_EMAIL_PROMPT=1` is set.
|
|
138
|
+
- If you type an address, it is validated against an RFC-5322-lite regex,
|
|
139
|
+
then stored locally in `~/.lyse/profile.json` as
|
|
140
|
+
`{ email, createdAt, lyseVersion }`. The file is never read by `lyse audit`
|
|
141
|
+
and never transmitted in the same network call as your audit results.
|
|
142
|
+
|
|
143
|
+
Delete `~/.lyse/profile.json` to revoke. We will honor a deletion request
|
|
144
|
+
emailed to contact@getlyse.com within 30 days of receipt.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 6. Sub-processors
|
|
149
|
+
|
|
150
|
+
The telemetry pipeline relies on:
|
|
151
|
+
|
|
152
|
+
| Sub-processor | Role | Legal mechanism |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| Cloudflare (Workers + KV + DNS) | Receives `/v1/events` POSTs, stores aggregates, serves `/v1/bench/summary` | EU SCCs in place; EU data residency configured |
|
|
155
|
+
|
|
156
|
+
The Lyse site (`getlyse.com`) is **a redirect to the GitHub repo** — no analytics, no cookies, no tracking pixels.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 7. Your rights (GDPR Arts. 15-22)
|
|
161
|
+
|
|
162
|
+
You may, at any time:
|
|
163
|
+
|
|
164
|
+
- **Access (Art. 15)** — request a copy of any data we hold tied to your `repo_bucket`. Email contact@getlyse.com with the bucket (visible in `.lyse/events.ndjson` after a local audit).
|
|
165
|
+
- **Rectification (Art. 16)** — correct inaccurate data (unlikely to apply given the data we hold).
|
|
166
|
+
- **Erasure (Art. 17)** — request deletion. Will be completed within 30 days.
|
|
167
|
+
- **Restriction (Art. 18)** — pause processing while disputes are resolved.
|
|
168
|
+
- **Data portability (Art. 20)** — receive your data in machine-readable JSON.
|
|
169
|
+
- **Object (Art. 21)** — withdraw consent. Run `lyse telemetry off`. Withdrawal is effective immediately and takes the same single action as giving consent (one keystroke at the prompt, or one command).
|
|
170
|
+
|
|
171
|
+
You also have the right to lodge a complaint with the **CNIL** (https://www.cnil.fr/) or your national data-protection authority.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 8. Changes to this notice
|
|
176
|
+
|
|
177
|
+
We post a notice in the [GitHub releases](https://github.com/lyse-labs/lyse/releases) when this notice changes materially. Continued use after a material change constitutes acceptance.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
*Hosted at `github.com/lyse-labs/lyse/blob/main/PRIVACY.md` and bundled in every npm release of `lyse`.*
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# lyse
|
|
2
|
+
|
|
3
|
+
> Audit your design system: Health Score, AGENTS.md, AI-ready contract.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @lyse-labs/lyse audit
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
CLI output (terminal-friendly) — or `--format=json` / `--format=sarif` for machines.
|
|
10
|
+
|
|
11
|
+
**Full docs and examples:** https://github.com/lyse-labs/lyse
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **12 deterministic rules** across 5 axes: tokens, a11y, components, stories, ai-surface
|
|
16
|
+
- **Deterministic, schema-versioned JSON output** (`schemas/v1/lyse-result.json`)
|
|
17
|
+
- **SARIF 2.1.0 output** — wire it into any SARIF-aware viewer (e.g. GitHub's Security tab via `github/codeql-action/upload-sarif`).
|
|
18
|
+
- **CLI commands:** `lyse audit`, `lyse fix`, `lyse explain`, `lyse agents`, `lyse share`, `lyse init`, `lyse mcp [setup|serve]`, `lyse feedback`, `lyse telemetry [on|off|status]`, `lyse bench-pack`, `lyse version`
|
|
19
|
+
- **Global flags:** `--yes`, `--no-prompt`, `--no-color`, `--quiet`, `--config=<path>`
|
|
20
|
+
- **Identity:** anonymous `repo_bucket` fingerprint
|
|
21
|
+
- **Telemetry:** opt-in only (first-run prompt, default OFF — see [PRIVACY.md](../../PRIVACY.md))
|
|
22
|
+
|
|
23
|
+
## Companion infrastructure
|
|
24
|
+
|
|
25
|
+
- **Cloudflare Worker** (`api.getlyse.com`) — serves the public anonymized bench summary and accepts opt-in telemetry events.
|
|
26
|
+
- Benchmark corpus (70 OSS design systems) maintained in the separate public repo [`lyse-labs/lyse-bench`](https://github.com/lyse-labs/lyse-bench) (CC BY 4.0).
|
|
27
|
+
|
|
28
|
+
## License
|
|
29
|
+
|
|
30
|
+
© 2026 Lyse Labs. Dual-licensed: AGPL-3.0-only OR Commercial. See https://github.com/lyse-labs/lyse.
|
|
31
|
+
|
|
32
|
+
## Privacy
|
|
33
|
+
|
|
34
|
+
Telemetry is opt-in only. See [PRIVACY.md](https://github.com/lyse-labs/lyse/blob/main/PRIVACY.md) for the full GDPR Arts. 13–14 notice.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Security Policy — Lyse
|
|
2
|
+
|
|
3
|
+
## Reporting vulnerabilities
|
|
4
|
+
|
|
5
|
+
If you discover a security vulnerability in Lyse, please report it **privately** before disclosing publicly:
|
|
6
|
+
|
|
7
|
+
- **GitHub Security Advisories:** https://github.com/lyse-labs/lyse/security/advisories/new (preferred)
|
|
8
|
+
- **Email:** contact@getlyse.com. For PGP-encrypted reports, please request the key by email.
|
|
9
|
+
|
|
10
|
+
We aim to respond within **5 business days**. Critical issues (RCE, data exfiltration, auth bypass) get a same-day acknowledgment.
|
|
11
|
+
|
|
12
|
+
## Supported versions
|
|
13
|
+
|
|
14
|
+
The **latest minor** receives security fixes. Older minors get fixes only for critical (CVSS >= 9.0) issues.
|
|
15
|
+
|
|
16
|
+
## Security model
|
|
17
|
+
|
|
18
|
+
Lyse is designed to **minimise the attack surface** by handling everything client-side:
|
|
19
|
+
|
|
20
|
+
| Component | Trust boundary | Notes |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `lyse` (npm CLI) | User's machine / CI runner | Runs entirely locally. No source code leaves the runner. No outbound network calls when `LYSE_TELEMETRY` is unset (default). Verified by [no-leak tests](./tests/security/no-leak.test.ts). |
|
|
23
|
+
| `api.getlyse.com` (Cloudflare Worker) | Our infrastructure | Receives ONLY the JSON event payload (see [PRIVACY.md](./PRIVACY.md)). IP/User-Agent dropped at the edge before any storage operation. Rate-limited per anonymous bucket. |
|
|
24
|
+
|
|
25
|
+
## Cryptographic posture
|
|
26
|
+
|
|
27
|
+
| Concern | Mechanism |
|
|
28
|
+
|---|---|
|
|
29
|
+
| npm release integrity | `npm publish --provenance` (Sigstore attestation) |
|
|
30
|
+
| Release tag integrity | GPG-signed git tags |
|
|
31
|
+
| License JWT | Ed25519 (EdDSA), public key embedded in the package, private key offline. Rotated on major-version bumps. |
|
|
32
|
+
| `repo_bucket` anonymisation | SHA-256 with a server-side salt rotated daily |
|
|
33
|
+
|
|
34
|
+
## Out of scope
|
|
35
|
+
|
|
36
|
+
- Vulnerabilities in dependencies upstream from Lyse (report to those projects). We monitor advisories and ship `dependabot` patches.
|
|
37
|
+
- Issues that require the user to have already compromised their own machine.
|
|
38
|
+
- Theoretical timing attacks against the rule engine (the engine produces public output by design).
|
|
39
|
+
- Anything related to the user's own design system content — Lyse does not introspect runtime data.
|
|
40
|
+
|
|
41
|
+
## Hall of fame
|
|
42
|
+
|
|
43
|
+
Credits for responsibly disclosed issues will be listed here.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface DummyInput {
|
|
2
|
+
size: number;
|
|
3
|
+
lineCount: number;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
export interface DummyInputFull extends DummyInput {
|
|
7
|
+
sha256: string;
|
|
8
|
+
knownDummyHashes: ReadonlySet<string>;
|
|
9
|
+
}
|
|
10
|
+
export declare function isLikelyDummy(input: DummyInput): boolean;
|
|
11
|
+
export declare function computeIsLikelyDummy(input: DummyInputFull): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const PLACEHOLDER_RE = /\b(todo|placeholder|coming soon|wip|fixme|tbd)\b/i;
|
|
2
|
+
export function isLikelyDummy(input) {
|
|
3
|
+
if (input.size < 100)
|
|
4
|
+
return true;
|
|
5
|
+
if (input.lineCount < 5)
|
|
6
|
+
return true;
|
|
7
|
+
const nonBlankLines = input.content.split("\n").filter((l) => l.trim().length > 0);
|
|
8
|
+
if (nonBlankLines.length < 3)
|
|
9
|
+
return true;
|
|
10
|
+
const placeholderRatio = nonBlankLines.filter((l) => PLACEHOLDER_RE.test(l)).length / nonBlankLines.length;
|
|
11
|
+
if (placeholderRatio > 0.5)
|
|
12
|
+
return true;
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
export function computeIsLikelyDummy(input) {
|
|
16
|
+
if (input.knownDummyHashes.has(input.sha256))
|
|
17
|
+
return true;
|
|
18
|
+
return isLikelyDummy(input);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=anti-dummy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anti-dummy.js","sourceRoot":"","sources":["../../../src/bench/evidence-pack/anti-dummy.ts"],"names":[],"mappings":"AAWA,MAAM,cAAc,GAAG,mDAAmD,CAAC;AAE3E,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,IAAI,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,CAAC,SAAS,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,gBAAgB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;IAC3G,IAAI,gBAAgB,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAqB;IACxD,IAAI,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EvidencePack, RepoMeta } from "./types.js";
|
|
2
|
+
export interface BuildEvidencePackInput {
|
|
3
|
+
repoRoot: string;
|
|
4
|
+
owner: string;
|
|
5
|
+
name: string;
|
|
6
|
+
headSha: string;
|
|
7
|
+
lyseCliVersion: string;
|
|
8
|
+
extractedAt: string;
|
|
9
|
+
primaryLanguage?: string;
|
|
10
|
+
frameworks?: ReadonlyArray<string>;
|
|
11
|
+
monorepoLayout?: RepoMeta["monorepoLayout"];
|
|
12
|
+
knownDummyHashes?: ReadonlySet<string>;
|
|
13
|
+
}
|
|
14
|
+
export declare function buildEvidencePack(input: BuildEvidencePackInput): Promise<EvidencePack>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { detectManifests } from "./manifest-detector.js";
|
|
2
|
+
import { computeIsLikelyDummy } from "./anti-dummy.js";
|
|
3
|
+
import { buildPackageJsonDigest } from "./package-json-digest.js";
|
|
4
|
+
import { computeHistograms } from "./histograms.js";
|
|
5
|
+
import { collectCanonicalSamples } from "./sampler.js";
|
|
6
|
+
import { buildVerifierCorpus } from "./verifier-corpus.js";
|
|
7
|
+
export async function buildEvidencePack(input) {
|
|
8
|
+
const manifests = await detectManifests(input.repoRoot);
|
|
9
|
+
const knownDummyHashes = input.knownDummyHashes ?? new Set();
|
|
10
|
+
const enrichDummy = async (meta) => {
|
|
11
|
+
if (!meta.present || !meta.path || !meta.sha256)
|
|
12
|
+
return meta;
|
|
13
|
+
try {
|
|
14
|
+
const { readFile } = await import("node:fs/promises");
|
|
15
|
+
const { join } = await import("node:path");
|
|
16
|
+
const content = await readFile(join(input.repoRoot, meta.path), "utf8");
|
|
17
|
+
const isLikelyDummy = computeIsLikelyDummy({
|
|
18
|
+
size: meta.size ?? 0,
|
|
19
|
+
lineCount: meta.lineCount ?? 0,
|
|
20
|
+
content,
|
|
21
|
+
sha256: meta.sha256,
|
|
22
|
+
knownDummyHashes,
|
|
23
|
+
});
|
|
24
|
+
return { ...meta, isLikelyDummy };
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return meta;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const enrichedManifests = {
|
|
31
|
+
...manifests,
|
|
32
|
+
agentsMd: await enrichDummy(manifests.agentsMd),
|
|
33
|
+
claudeMd: await enrichDummy(manifests.claudeMd),
|
|
34
|
+
designMd: await enrichDummy(manifests.designMd),
|
|
35
|
+
skillMd: await enrichDummy(manifests.skillMd),
|
|
36
|
+
componentsJson: await enrichDummy(manifests.componentsJson),
|
|
37
|
+
llmsTxt: await enrichDummy(manifests.llmsTxt),
|
|
38
|
+
llmsFullTxt: await enrichDummy(manifests.llmsFullTxt),
|
|
39
|
+
tokensJsonDtcg: await enrichDummy(manifests.tokensJsonDtcg),
|
|
40
|
+
};
|
|
41
|
+
const packageJsonDigest = await buildPackageJsonDigest(input.repoRoot);
|
|
42
|
+
const histograms = await computeHistograms(input.repoRoot);
|
|
43
|
+
const canonicalSamples = await collectCanonicalSamples(input.repoRoot);
|
|
44
|
+
const allSamples = [
|
|
45
|
+
...canonicalSamples.primitiveComponents,
|
|
46
|
+
...canonicalSamples.compoundComponents,
|
|
47
|
+
...canonicalSamples.layoutComponents,
|
|
48
|
+
...canonicalSamples.formComponents,
|
|
49
|
+
...canonicalSamples.stories,
|
|
50
|
+
...canonicalSamples.tests,
|
|
51
|
+
...canonicalSamples.tokenFiles,
|
|
52
|
+
...canonicalSamples.configFiles,
|
|
53
|
+
];
|
|
54
|
+
const verifierCorpus = buildVerifierCorpus({ files: allSamples });
|
|
55
|
+
const repo = {
|
|
56
|
+
owner: input.owner,
|
|
57
|
+
name: input.name,
|
|
58
|
+
headSha: input.headSha,
|
|
59
|
+
primaryLanguage: input.primaryLanguage ?? "TypeScript",
|
|
60
|
+
frameworks: input.frameworks ?? [],
|
|
61
|
+
monorepoLayout: input.monorepoLayout ?? "unknown",
|
|
62
|
+
subpackages: packageJsonDigest.subpackages.map((p) => p.path).sort(),
|
|
63
|
+
};
|
|
64
|
+
const pack = {
|
|
65
|
+
canonicalSamples,
|
|
66
|
+
extractedAt: input.extractedAt,
|
|
67
|
+
histograms,
|
|
68
|
+
lyseCliVersion: input.lyseCliVersion,
|
|
69
|
+
manifests: enrichedManifests,
|
|
70
|
+
packageJsonDigest,
|
|
71
|
+
repo,
|
|
72
|
+
schemaVersion: "bench-pack/1.0",
|
|
73
|
+
verifierCorpus,
|
|
74
|
+
};
|
|
75
|
+
return pack;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/bench/evidence-pack/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import fg from "fast-glob";
|
|
4
|
+
const HEX_RE = /#[0-9a-fA-F]{3,8}\b/g;
|
|
5
|
+
const RGBA_RE = /\brgba?\(/g;
|
|
6
|
+
const PX_RE = /\b\d+(\.\d+)?px\b/g;
|
|
7
|
+
const ARIA_RE = /\baria-[a-z]+\s*=/g;
|
|
8
|
+
const ALT_RE = /\balt\s*=/g;
|
|
9
|
+
const ROLE_RE = /\brole\s*=/g;
|
|
10
|
+
const TABINDEX_RE = /\btabIndex\s*=/g;
|
|
11
|
+
const FOCUS_HOOK_RE = /\b(useFocusable|useFocusTrap|use[A-Z]\w*Focus\w*)\b/g;
|
|
12
|
+
const SEMANTIC_TOKEN_RE = /\b(theme|tokens?)\.[a-zA-Z][\w.]+/g;
|
|
13
|
+
function percentiles(values) {
|
|
14
|
+
if (values.length === 0)
|
|
15
|
+
return { p50: 0, p90: 0, p99: 0 };
|
|
16
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
17
|
+
const at = (q) => sorted[Math.min(sorted.length - 1, Math.floor(q * sorted.length))];
|
|
18
|
+
return { p50: at(0.5), p90: at(0.9), p99: at(0.99) };
|
|
19
|
+
}
|
|
20
|
+
function countMatches(re, content) {
|
|
21
|
+
return (content.match(re) ?? []).length;
|
|
22
|
+
}
|
|
23
|
+
async function* iterateSourceFiles(repoRoot) {
|
|
24
|
+
const files = await fg(["**/*.{ts,tsx,js,jsx,css,scss}"], {
|
|
25
|
+
cwd: repoRoot,
|
|
26
|
+
ignore: [
|
|
27
|
+
"**/node_modules/**",
|
|
28
|
+
"**/dist/**",
|
|
29
|
+
"**/build/**",
|
|
30
|
+
"**/.next/**",
|
|
31
|
+
"**/.recall-suite-cache/**",
|
|
32
|
+
"**/benchmarks/fixtures/**",
|
|
33
|
+
"**/fixtures/**",
|
|
34
|
+
"**/.tmp/**",
|
|
35
|
+
"**/coverage/**",
|
|
36
|
+
],
|
|
37
|
+
onlyFiles: true,
|
|
38
|
+
});
|
|
39
|
+
files.sort();
|
|
40
|
+
for (const rel of files) {
|
|
41
|
+
try {
|
|
42
|
+
const content = await readFile(join(repoRoot, rel), "utf8");
|
|
43
|
+
yield { path: rel, content };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// skip unreadable
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function detectTestFramework(testFiles) {
|
|
51
|
+
for (const f of testFiles) {
|
|
52
|
+
if (/from\s+["']vitest["']/.test(f.content))
|
|
53
|
+
return "vitest";
|
|
54
|
+
if (/from\s+["']@jest\/globals["']|require\(["']jest["']\)/.test(f.content))
|
|
55
|
+
return "jest";
|
|
56
|
+
if (/from\s+["']mocha["']/.test(f.content))
|
|
57
|
+
return "mocha";
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
export async function computeHistograms(repoRoot) {
|
|
62
|
+
const td = {
|
|
63
|
+
filesScanned: 0, inline: [], semantic: 0, hex: 0, rgba: 0, px: 0,
|
|
64
|
+
};
|
|
65
|
+
const a11y = { aria: 0, alt: 0, role: 0, tabIndex: 0, focusHook: 0 };
|
|
66
|
+
const storyContent = [];
|
|
67
|
+
const testFiles = [];
|
|
68
|
+
for await (const { path: rel, content } of iterateSourceFiles(repoRoot)) {
|
|
69
|
+
if (rel.endsWith(".stories.tsx") || rel.endsWith(".stories.ts") || rel.endsWith(".stories.jsx") || rel.endsWith(".stories.js")) {
|
|
70
|
+
const ext = rel.slice(rel.indexOf(".stories"));
|
|
71
|
+
storyContent.push({ ext, len: content.length });
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (rel.endsWith(".test.tsx") || rel.endsWith(".test.ts") || rel.endsWith(".spec.tsx") || rel.endsWith(".spec.ts")) {
|
|
75
|
+
const ext = rel.slice(rel.lastIndexOf("."));
|
|
76
|
+
testFiles.push({ ext, content });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
td.filesScanned += 1;
|
|
80
|
+
const hex = countMatches(HEX_RE, content);
|
|
81
|
+
const rgba = countMatches(RGBA_RE, content);
|
|
82
|
+
const px = countMatches(PX_RE, content);
|
|
83
|
+
const inline = hex + rgba + px;
|
|
84
|
+
td.inline.push(inline);
|
|
85
|
+
td.hex += hex;
|
|
86
|
+
td.rgba += rgba;
|
|
87
|
+
td.px += px;
|
|
88
|
+
td.semantic += countMatches(SEMANTIC_TOKEN_RE, content);
|
|
89
|
+
a11y.aria += countMatches(ARIA_RE, content);
|
|
90
|
+
a11y.alt += countMatches(ALT_RE, content);
|
|
91
|
+
a11y.role += countMatches(ROLE_RE, content);
|
|
92
|
+
a11y.tabIndex += countMatches(TABINDEX_RE, content);
|
|
93
|
+
a11y.focusHook += countMatches(FOCUS_HOOK_RE, content);
|
|
94
|
+
}
|
|
95
|
+
const tokenDiscipline = {
|
|
96
|
+
filesScanned: td.filesScanned,
|
|
97
|
+
inlineLiteralsPerFile: percentiles(td.inline),
|
|
98
|
+
semanticTokenReferences: td.semantic,
|
|
99
|
+
rawHexCount: td.hex,
|
|
100
|
+
rawRgbaCount: td.rgba,
|
|
101
|
+
rawPxCount: td.px,
|
|
102
|
+
};
|
|
103
|
+
const a11yAttributes = {
|
|
104
|
+
ariaAttrCount: a11y.aria,
|
|
105
|
+
altAttrCount: a11y.alt,
|
|
106
|
+
roleAttrCount: a11y.role,
|
|
107
|
+
tabIndexCount: a11y.tabIndex,
|
|
108
|
+
focusManagementHookCount: a11y.focusHook,
|
|
109
|
+
};
|
|
110
|
+
const storyExtensions = {};
|
|
111
|
+
let storyTotalChars = 0;
|
|
112
|
+
for (const s of storyContent) {
|
|
113
|
+
storyExtensions[s.ext] = (storyExtensions[s.ext] ?? 0) + 1;
|
|
114
|
+
storyTotalChars += s.len;
|
|
115
|
+
}
|
|
116
|
+
const storyFiles = {
|
|
117
|
+
count: storyContent.length,
|
|
118
|
+
extensions: storyExtensions,
|
|
119
|
+
totalCharCount: storyTotalChars,
|
|
120
|
+
};
|
|
121
|
+
const testExtensions = {};
|
|
122
|
+
for (const t of testFiles)
|
|
123
|
+
testExtensions[t.ext] = (testExtensions[t.ext] ?? 0) + 1;
|
|
124
|
+
const testFilesBlock = {
|
|
125
|
+
count: testFiles.length,
|
|
126
|
+
extensions: testExtensions,
|
|
127
|
+
framework: detectTestFramework(testFiles),
|
|
128
|
+
};
|
|
129
|
+
return { tokenDiscipline, a11yAttributes, storyFiles, testFiles: testFilesBlock };
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=histograms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"histograms.js","sourceRoot":"","sources":["../../../src/bench/evidence-pack/histograms.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
async function fileMeta(root, relPath) {
|
|
5
|
+
const absolute = join(root, relPath);
|
|
6
|
+
try {
|
|
7
|
+
const buf = await readFile(absolute);
|
|
8
|
+
const sha = createHash("sha256").update(buf).digest("hex");
|
|
9
|
+
const content = buf.toString("utf8");
|
|
10
|
+
const lineCount = content.length === 0 ? 0 : content.split("\n").length;
|
|
11
|
+
return { present: true, path: relPath, size: buf.byteLength, sha256: sha, lineCount };
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return { present: false };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function dirMeta(root, relDir) {
|
|
18
|
+
const absolute = join(root, relDir);
|
|
19
|
+
try {
|
|
20
|
+
const entries = await readdir(absolute, { withFileTypes: true });
|
|
21
|
+
const files = [];
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
if (!entry.isFile())
|
|
24
|
+
continue;
|
|
25
|
+
const relPath = `${relDir}/${entry.name}`;
|
|
26
|
+
const buf = await readFile(join(root, relPath));
|
|
27
|
+
files.push({
|
|
28
|
+
path: relPath,
|
|
29
|
+
size: buf.byteLength,
|
|
30
|
+
sha256: createHash("sha256").update(buf).digest("hex"),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
34
|
+
if (files.length === 0)
|
|
35
|
+
return { present: false };
|
|
36
|
+
return { present: true, directory: relDir, fileCount: files.length, files };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { present: false };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function detectMcp(root) {
|
|
43
|
+
for (const candidate of ["apps/mcp/package.json", "mcp.json", ".mcp/config.json"]) {
|
|
44
|
+
const meta = await fileMeta(root, candidate);
|
|
45
|
+
if (meta.present) {
|
|
46
|
+
return { ...meta, transport: "unknown" };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { present: false };
|
|
50
|
+
}
|
|
51
|
+
export async function detectManifests(repoRoot) {
|
|
52
|
+
return {
|
|
53
|
+
agentsMd: await fileMeta(repoRoot, "AGENTS.md"),
|
|
54
|
+
claudeMd: await fileMeta(repoRoot, "CLAUDE.md"),
|
|
55
|
+
designMd: await fileMeta(repoRoot, "DESIGN.md"),
|
|
56
|
+
skillMd: await fileMeta(repoRoot, "SKILL.md"),
|
|
57
|
+
componentsJson: await fileMeta(repoRoot, "components.json"),
|
|
58
|
+
cursorRules: await dirMeta(repoRoot, ".cursor/rules"),
|
|
59
|
+
llmsTxt: await fileMeta(repoRoot, "llms.txt"),
|
|
60
|
+
llmsFullTxt: await fileMeta(repoRoot, "llms-full.txt"),
|
|
61
|
+
mcpConfig: await detectMcp(repoRoot),
|
|
62
|
+
tokensJsonDtcg: await fileMeta(repoRoot, "tokens.json"),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=manifest-detector.js.map
|