@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/dist/types.d.ts
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
export type Severity = "error" | "warning" | "info";
|
|
2
|
+
export type AxisName = "tokens" | "a11y" | "components" | "stories" | "ai-surface";
|
|
3
|
+
export type BuiltInRuleId = "tokens/no-hardcoded-color" | "tokens/no-hardcoded-spacing" | "tokens/no-hardcoded-typography" | "tokens/no-hardcoded-radii" | "tokens/no-hardcoded-shadow" | "tokens/no-hardcoded-motion-duration" | "tokens/no-hardcoded-motion-easing" | "tokens/no-hardcoded-breakpoints" | "tokens/no-hardcoded-z-index" | "tokens/no-hardcoded-opacity" | "tokens/no-hardcoded-border-width" | "tokens/dtcg-conformance" | "tokens/description-coverage" | "components/no-native-shadows" | "naming/component-pascalcase" | "naming/hook-prefix" | "naming/prop-camelcase" | "a11y/essentials" | "stories/coverage" | "stories/variant-coverage" | "ai-surface/agents-md-quality" | "ai-surface/component-manifest-json" | "ai-surface/ds-index-exported";
|
|
4
|
+
export type RuleId = BuiltInRuleId | string;
|
|
5
|
+
export interface SourceLocation {
|
|
6
|
+
file: string;
|
|
7
|
+
line: number;
|
|
8
|
+
column: number;
|
|
9
|
+
}
|
|
10
|
+
export interface Finding {
|
|
11
|
+
ruleId: RuleId;
|
|
12
|
+
axis: AxisName;
|
|
13
|
+
severity: Severity;
|
|
14
|
+
location: SourceLocation;
|
|
15
|
+
message: string;
|
|
16
|
+
suggestion?: string;
|
|
17
|
+
context?: string;
|
|
18
|
+
confidence?: Confidence;
|
|
19
|
+
}
|
|
20
|
+
export interface RuleContext {
|
|
21
|
+
repoRoot: string;
|
|
22
|
+
tokens: TokenMap | null;
|
|
23
|
+
componentsModule: string | null;
|
|
24
|
+
componentInventory: ComponentInventoryEntry[];
|
|
25
|
+
storyIndex: StoryIndex | null;
|
|
26
|
+
excludePaths: string[];
|
|
27
|
+
/**
|
|
28
|
+
* True when the repo being audited IS the design system (workspace
|
|
29
|
+
* detection found a DS-export package in the same monorepo). Some rules
|
|
30
|
+
* (no-native-shadows, stories/coverage) skip in this mode because their
|
|
31
|
+
* semantics target consumer-of-DS audits, not DS-self audits. Full
|
|
32
|
+
* DS-self rule semantics planned for v0.2.
|
|
33
|
+
*/
|
|
34
|
+
dsSelfMode?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface TokenMap {
|
|
37
|
+
colors: Map<string, string[]>;
|
|
38
|
+
spacing: Map<string, string[]>;
|
|
39
|
+
typography: Map<string, string[]>;
|
|
40
|
+
radii: Map<string, string[]>;
|
|
41
|
+
shadows: Map<string, string[]>;
|
|
42
|
+
motion: Map<string, string[]>;
|
|
43
|
+
breakpoints: Map<string, string[]>;
|
|
44
|
+
zIndex: Map<string, string[]>;
|
|
45
|
+
opacity: Map<string, string[]>;
|
|
46
|
+
borderWidth: Map<string, string[]>;
|
|
47
|
+
source: "tailwind-v3" | "tailwind-v4" | "dtcg" | "css-vars" | "mixed";
|
|
48
|
+
}
|
|
49
|
+
/** A single prop extracted from a component's TypeScript type annotation. */
|
|
50
|
+
export interface ComponentPropEntry {
|
|
51
|
+
/** Prop identifier, e.g. "variant" */
|
|
52
|
+
name: string;
|
|
53
|
+
/**
|
|
54
|
+
* Raw TypeScript type text, e.g. '"primary" | "secondary" | "ghost"'.
|
|
55
|
+
* For props imported from another file, this will be the reference name
|
|
56
|
+
* (e.g. "ButtonProps") without cross-file resolution (v0.2 enhancement).
|
|
57
|
+
*/
|
|
58
|
+
typeText?: string;
|
|
59
|
+
/** True when the prop is optional (`?:`). */
|
|
60
|
+
isOptional?: boolean;
|
|
61
|
+
/** Default value extracted from destructuring, e.g. "primary" for `{ variant = "primary" }`. */
|
|
62
|
+
defaultValue?: string;
|
|
63
|
+
/**
|
|
64
|
+
* True when `typeText` is a string-literal union (all members are string literals),
|
|
65
|
+
* e.g. `'"primary" | "secondary"`.
|
|
66
|
+
*/
|
|
67
|
+
isVariantUnion?: boolean;
|
|
68
|
+
/** Extracted string-literal values when `isVariantUnion` is true. */
|
|
69
|
+
variants?: string[];
|
|
70
|
+
}
|
|
71
|
+
export interface ComponentInventoryEntry {
|
|
72
|
+
name: string;
|
|
73
|
+
module: string;
|
|
74
|
+
usageCount: number;
|
|
75
|
+
/**
|
|
76
|
+
* Props extracted from the component's TypeScript prop type definition.
|
|
77
|
+
* Populated by buildComponentInventory when the loader can parse the source files.
|
|
78
|
+
* Absent when the component source is not available for analysis.
|
|
79
|
+
*/
|
|
80
|
+
props?: ComponentPropEntry[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A single named export from a CSF v3 story file.
|
|
84
|
+
* Extracted from `export const Primary = { args: { variant: "primary" } }`.
|
|
85
|
+
*/
|
|
86
|
+
export interface StoryExport {
|
|
87
|
+
/** Export name, e.g. "Primary" */
|
|
88
|
+
name: string;
|
|
89
|
+
/**
|
|
90
|
+
* Simple literal args extracted from the story's `args` object.
|
|
91
|
+
* Only string/number/boolean literals are extracted; complex expressions are skipped.
|
|
92
|
+
* Example: { variant: "primary", size: "md", disabled: false }
|
|
93
|
+
*/
|
|
94
|
+
args?: Record<string, string | number | boolean>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Per-file story entry with CSF v3 export data.
|
|
98
|
+
* Extends the original minimal `{ id, importPath }` shape with parsed story exports.
|
|
99
|
+
*/
|
|
100
|
+
export interface StoryEntry {
|
|
101
|
+
id: string;
|
|
102
|
+
importPath: string;
|
|
103
|
+
/**
|
|
104
|
+
* Component name from the default export's `component` field (best-effort).
|
|
105
|
+
* e.g. `export default { component: Button }` → componentName = "Button"
|
|
106
|
+
* Absent when the default export is complex or uses a variable reference
|
|
107
|
+
* not visible as a direct identifier.
|
|
108
|
+
*/
|
|
109
|
+
componentName?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Named story exports from the file.
|
|
112
|
+
* e.g. `export const Primary = { args: { variant: "primary" } }` →
|
|
113
|
+
* stories = [{ name: "Primary", args: { variant: "primary" } }]
|
|
114
|
+
* Absent when no exports were extracted (complex factory patterns, parse errors).
|
|
115
|
+
*/
|
|
116
|
+
stories?: StoryExport[];
|
|
117
|
+
}
|
|
118
|
+
export interface StoryIndex {
|
|
119
|
+
byTitle: Map<string, StoryEntry>;
|
|
120
|
+
}
|
|
121
|
+
export interface Rule {
|
|
122
|
+
id: RuleId;
|
|
123
|
+
axis: AxisName;
|
|
124
|
+
evaluate(ctx: RuleContext, parsedFiles: ParsedFiles): Promise<RuleEvalResult>;
|
|
125
|
+
classifyConfidence?: (finding: Finding, ctx: ClassifyContext) => Confidence;
|
|
126
|
+
applyCodemod?: (finding: Finding, ctx: CodemodContext) => CodemodResult;
|
|
127
|
+
}
|
|
128
|
+
export interface ParsedFiles {
|
|
129
|
+
ts: ParsedTsFile[];
|
|
130
|
+
css: ParsedCssFile[];
|
|
131
|
+
cssInJs: ExtractedCssInJsBlock[];
|
|
132
|
+
}
|
|
133
|
+
export interface ParsedTsFile {
|
|
134
|
+
path: string;
|
|
135
|
+
ast: unknown;
|
|
136
|
+
source: string;
|
|
137
|
+
imports: ImportRecord[];
|
|
138
|
+
}
|
|
139
|
+
export interface ImportRecord {
|
|
140
|
+
module: string;
|
|
141
|
+
named: string[];
|
|
142
|
+
default: string | null;
|
|
143
|
+
line: number;
|
|
144
|
+
}
|
|
145
|
+
export interface ParsedCssFile {
|
|
146
|
+
path: string;
|
|
147
|
+
source: string;
|
|
148
|
+
/**
|
|
149
|
+
* Set to `true` for `.sass` (indented syntax) files which are still skipped
|
|
150
|
+
* in v0.1. `.scss` is fully parsed via `parsers/scss-transform.ts` and the
|
|
151
|
+
* transformed CSS-equivalent source is returned in `source`.
|
|
152
|
+
* Also set to `true` if the SCSS transform throws unexpectedly so the
|
|
153
|
+
* pipeline degrades gracefully instead of crashing the audit.
|
|
154
|
+
*/
|
|
155
|
+
skipped?: true;
|
|
156
|
+
}
|
|
157
|
+
export interface ExtractedCssInJsBlock {
|
|
158
|
+
path: string;
|
|
159
|
+
line: number;
|
|
160
|
+
content: string;
|
|
161
|
+
}
|
|
162
|
+
export interface ParseError {
|
|
163
|
+
file: string;
|
|
164
|
+
reason: string;
|
|
165
|
+
}
|
|
166
|
+
export interface RuleEvalResult {
|
|
167
|
+
findings: Finding[];
|
|
168
|
+
opportunities: number;
|
|
169
|
+
/**
|
|
170
|
+
* Files the rule attempted to analyze but had to skip because its parser
|
|
171
|
+
* could not understand them. Surfaced as `meta.parseErrors` in the audit
|
|
172
|
+
* output so users can see what was NOT analyzed (transparency over silent
|
|
173
|
+
* 100/100 scores). v0.1 limitation — see issue #155.
|
|
174
|
+
*/
|
|
175
|
+
parseErrors?: ParseError[];
|
|
176
|
+
}
|
|
177
|
+
export interface AxisScore {
|
|
178
|
+
axis: AxisName;
|
|
179
|
+
score: number | "N/A";
|
|
180
|
+
findings: number;
|
|
181
|
+
opportunities: number;
|
|
182
|
+
}
|
|
183
|
+
export interface Layer4Meta {
|
|
184
|
+
/** True when the LLM response was served from cache. */
|
|
185
|
+
cacheHit?: boolean;
|
|
186
|
+
/** USD spent on LLM calls (0 on cache hit). */
|
|
187
|
+
usdSpent?: number;
|
|
188
|
+
/** Model identifier as reported by the connector. */
|
|
189
|
+
modelUsed?: string;
|
|
190
|
+
/** "higher" for frontier models, "lower" for local/free-tier. */
|
|
191
|
+
llmQuality?: "higher" | "lower";
|
|
192
|
+
/** Number of LLM-proposed findings dropped by the validator. */
|
|
193
|
+
droppedHallucinations?: number;
|
|
194
|
+
/** Set to true when Layer 4 was intentionally skipped via --static-only. */
|
|
195
|
+
staticOnly?: boolean;
|
|
196
|
+
/** Non-fatal error that occurred during Layer 4 (audit continues with Layers 1+2 score). */
|
|
197
|
+
error?: {
|
|
198
|
+
kind: string;
|
|
199
|
+
message: string;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
export interface CoverageMeta {
|
|
203
|
+
/** Count of source files actually walked by the scanner (NOT a generic find of the repo). */
|
|
204
|
+
scannedFiles: number;
|
|
205
|
+
/** Audit pipeline duration in milliseconds (excludes Node boot and CLI argument parsing). */
|
|
206
|
+
durationMs: number;
|
|
207
|
+
/** Resolved path to the user's .lyse.yaml, or `null` when no config file was discovered. */
|
|
208
|
+
configPath: string | null;
|
|
209
|
+
/**
|
|
210
|
+
* Files a rule attempted to analyze but could not parse. Deterministic (same
|
|
211
|
+
* file → same reason), sorted by `file` ascending. Omitted when no rule reported
|
|
212
|
+
* a parse failure. Tracks #155.
|
|
213
|
+
*/
|
|
214
|
+
parseErrors?: ParseError[];
|
|
215
|
+
}
|
|
216
|
+
export interface AuditResult {
|
|
217
|
+
schemaVersion: 2;
|
|
218
|
+
rulesVersion: string;
|
|
219
|
+
toolVersion: string;
|
|
220
|
+
/**
|
|
221
|
+
* The pinned scoring-formula version stamped on every emitted audit artifact.
|
|
222
|
+
* Currently always `"scoring-v1"`. Bumping to `"scoring-v2"` is a semver-major
|
|
223
|
+
* event — same input may produce a different score.
|
|
224
|
+
* (ADR 0017 + spec §3 falsifiable claim 1.)
|
|
225
|
+
*/
|
|
226
|
+
scoringVersion: "scoring-v1";
|
|
227
|
+
repoRoot: string;
|
|
228
|
+
timestamp: string;
|
|
229
|
+
stack: string[];
|
|
230
|
+
finalScore: number | "N/A";
|
|
231
|
+
tier: string;
|
|
232
|
+
axes: AxisScore[];
|
|
233
|
+
findings: Finding[];
|
|
234
|
+
/** ADR-0015: Layer 4 LLM augmentation metadata + #156 audit-perimeter signals. */
|
|
235
|
+
meta?: {
|
|
236
|
+
layer4?: Layer4Meta;
|
|
237
|
+
/** Phase 1 of #156 — audit-perimeter signals so the score has a visible denominator. Includes `parseErrors` (#155) as a deterministic subfield. */
|
|
238
|
+
coverage?: CoverageMeta;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
export interface RuleMeta {
|
|
242
|
+
id: RuleId;
|
|
243
|
+
axis: AxisName;
|
|
244
|
+
defaultSeverity: Severity;
|
|
245
|
+
shortDescription: string;
|
|
246
|
+
fullDescription: string;
|
|
247
|
+
helpUri: string;
|
|
248
|
+
rationale: string;
|
|
249
|
+
examples: {
|
|
250
|
+
good: string;
|
|
251
|
+
bad: string;
|
|
252
|
+
}[];
|
|
253
|
+
allowlist: string[];
|
|
254
|
+
}
|
|
255
|
+
export interface RulesManifest {
|
|
256
|
+
schemaVersion: "1.0.0";
|
|
257
|
+
rulesVersion: string;
|
|
258
|
+
rules: RuleMeta[];
|
|
259
|
+
}
|
|
260
|
+
export type Confidence = "high" | "medium" | "low";
|
|
261
|
+
export declare function isValidConfidence(v: unknown): v is Confidence;
|
|
262
|
+
export interface LyseConfig {
|
|
263
|
+
designSystem?: {
|
|
264
|
+
componentsModule?: string;
|
|
265
|
+
elements?: Record<string, string>;
|
|
266
|
+
excludePaths?: string[];
|
|
267
|
+
};
|
|
268
|
+
llm?: {
|
|
269
|
+
provider?: 'anthropic' | 'openai' | 'openai-compatible' | 'mcp' | 'none' | 'auto';
|
|
270
|
+
model?: string;
|
|
271
|
+
endpoint?: string;
|
|
272
|
+
/** ADR-0015: ConnectorResolver fields (Task 2) */
|
|
273
|
+
connector?: 'auto' | 'mcp-host' | 'openrouter' | 'direct-api-key' | 'ollama';
|
|
274
|
+
costCapUsd?: number;
|
|
275
|
+
cacheMaxAgeDays?: number;
|
|
276
|
+
staticOnly?: boolean;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
export interface ClassifyContext {
|
|
280
|
+
tokens: TokenMap;
|
|
281
|
+
components: Set<string>;
|
|
282
|
+
config: LyseConfig;
|
|
283
|
+
/**
|
|
284
|
+
* Absolute path to the repository root being audited. Optional because
|
|
285
|
+
* historical callers built `ClassifyContext` without this field; rules
|
|
286
|
+
* that need on-demand semantic resolution (e.g. via ts-morph) should
|
|
287
|
+
* degrade gracefully when it is absent.
|
|
288
|
+
*/
|
|
289
|
+
repoRoot?: string;
|
|
290
|
+
}
|
|
291
|
+
export interface CodemodContext extends ClassifyContext {
|
|
292
|
+
fileContent: string;
|
|
293
|
+
parsedAst: unknown;
|
|
294
|
+
}
|
|
295
|
+
export interface CodemodResult {
|
|
296
|
+
diff: string;
|
|
297
|
+
importsAdded: string[];
|
|
298
|
+
confidence: Confidence;
|
|
299
|
+
warnings?: string[];
|
|
300
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAiTA,MAAM,UAAU,iBAAiB,CAAC,CAAU;IAC1C,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,KAAK,CAAC;AACvD,CAAC"}
|
package/dist/util/git.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// packages/core/src/util/git.ts
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { promises as fs } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
export async function gitHeadSha(repoRoot) {
|
|
9
|
+
try {
|
|
10
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "HEAD"], { cwd: repoRoot });
|
|
11
|
+
return stdout.trim();
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return "no-git";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export async function modifiedFilesWithHashes(repoRoot) {
|
|
18
|
+
try {
|
|
19
|
+
const { stdout } = await execFileAsync("git", ["diff", "--name-only", "HEAD"], { cwd: repoRoot });
|
|
20
|
+
const paths = stdout.split("\n").filter((p) => p.length > 0);
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const p of paths) {
|
|
23
|
+
try {
|
|
24
|
+
const content = await fs.readFile(join(repoRoot, p), "utf8");
|
|
25
|
+
out.push({
|
|
26
|
+
path: p,
|
|
27
|
+
contentHash: createHash("sha256").update(content).digest("hex").slice(0, 16),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// file deleted or unreadable — skip
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/util/git.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IAC5D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClG,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAmB,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;gBAC7D,GAAG,CAAC,IAAI,CAAC;oBACP,IAAI,EAAE,CAAC;oBACP,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;iBAC7E,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for util/git.ts — gitHeadSha + modifiedFilesWithHashes.
|
|
3
|
+
* These test the fallback paths (no git repo) so no real git state is required.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from "vitest";
|
|
6
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { gitHeadSha, modifiedFilesWithHashes } from "./git.js";
|
|
10
|
+
describe("gitHeadSha", () => {
|
|
11
|
+
it("returns 'no-git' for a directory that is not a git repo", async () => {
|
|
12
|
+
const dir = mkdtempSync(join(tmpdir(), "lyse-git-"));
|
|
13
|
+
try {
|
|
14
|
+
const sha = await gitHeadSha(dir);
|
|
15
|
+
expect(sha).toBe("no-git");
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
rmSync(dir, { recursive: true, force: true });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it("returns a non-empty string for a real git repo", async () => {
|
|
22
|
+
// Use the Lyse repo root itself as a real git repo
|
|
23
|
+
const sha = await gitHeadSha(process.cwd());
|
|
24
|
+
// Should be a 40-char hex SHA or "no-git"
|
|
25
|
+
expect(typeof sha).toBe("string");
|
|
26
|
+
expect(sha.length).toBeGreaterThan(0);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("modifiedFilesWithHashes", () => {
|
|
30
|
+
it("returns an empty array for a directory that is not a git repo", async () => {
|
|
31
|
+
const dir = mkdtempSync(join(tmpdir(), "lyse-git-mod-"));
|
|
32
|
+
try {
|
|
33
|
+
const result = await modifiedFilesWithHashes(dir);
|
|
34
|
+
expect(Array.isArray(result)).toBe(true);
|
|
35
|
+
expect(result).toHaveLength(0);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
rmSync(dir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=git.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.test.js","sourceRoot":"","sources":["../../src/util/git.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAE/D,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,mDAAmD;QACnD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5C,0CAA0C;QAC1C,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures that an entry exists in .gitignore at the given repository root.
|
|
3
|
+
* Idempotent: if the entry already exists, this is a no-op.
|
|
4
|
+
* If not in a git repo (no .git/ directory), this is also a no-op.
|
|
5
|
+
*
|
|
6
|
+
* @param cwd Repository root directory
|
|
7
|
+
* @param entry The .gitignore entry to ensure (e.g., ".lyse/")
|
|
8
|
+
*/
|
|
9
|
+
export declare function ensureGitignoreEntry(cwd: string, entry: string): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, appendFile, writeFile, access } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
/**
|
|
5
|
+
* Ensures that an entry exists in .gitignore at the given repository root.
|
|
6
|
+
* Idempotent: if the entry already exists, this is a no-op.
|
|
7
|
+
* If not in a git repo (no .git/ directory), this is also a no-op.
|
|
8
|
+
*
|
|
9
|
+
* @param cwd Repository root directory
|
|
10
|
+
* @param entry The .gitignore entry to ensure (e.g., ".lyse/")
|
|
11
|
+
*/
|
|
12
|
+
export async function ensureGitignoreEntry(cwd, entry) {
|
|
13
|
+
// No-op if not a git repo
|
|
14
|
+
try {
|
|
15
|
+
await access(join(cwd, ".git"), constants.F_OK);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const gPath = join(cwd, ".gitignore");
|
|
21
|
+
try {
|
|
22
|
+
const raw = await readFile(gPath, "utf8");
|
|
23
|
+
// Check if entry exists (exact match or with/without trailing slash)
|
|
24
|
+
const normalizedEntry = entry.replace(/\/$/, "");
|
|
25
|
+
const lines = raw.split("\n");
|
|
26
|
+
if (lines.some((line) => {
|
|
27
|
+
const normalized = line.trim().replace(/\/$/, "");
|
|
28
|
+
return normalized === normalizedEntry || normalized === entry.trim();
|
|
29
|
+
})) {
|
|
30
|
+
return; // Already exists
|
|
31
|
+
}
|
|
32
|
+
await appendFile(gPath, `\n# Lyse local cache\n${entry}\n`);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// File doesn't exist, create it
|
|
36
|
+
await writeFile(gPath, `# Lyse local cache\n${entry}\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=gitignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/util/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAW,EAAE,KAAa;IACnE,0BAA0B;IAC1B,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1C,qEAAqE;QACrE,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO,UAAU,KAAK,eAAe,IAAI,UAAU,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACvE,CAAC,CAAC,EAAE,CAAC;YACH,OAAO,CAAC,iBAAiB;QAC3B,CAAC;QACD,MAAM,UAAU,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;QAChC,MAAM,SAAS,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash selected dependencies from package.json.
|
|
3
|
+
* If `tracked` is provided, only those keys are hashed.
|
|
4
|
+
* If not provided, hashes the union of dependencies + devDependencies.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hashDeps(repoRoot: string, tracked?: string[]): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/**
|
|
5
|
+
* Hash selected dependencies from package.json.
|
|
6
|
+
* If `tracked` is provided, only those keys are hashed.
|
|
7
|
+
* If not provided, hashes the union of dependencies + devDependencies.
|
|
8
|
+
*/
|
|
9
|
+
export function hashDeps(repoRoot, tracked) {
|
|
10
|
+
const pkgPath = join(repoRoot, "package.json");
|
|
11
|
+
if (!existsSync(pkgPath))
|
|
12
|
+
return "";
|
|
13
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
14
|
+
const all = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
15
|
+
if (tracked) {
|
|
16
|
+
const selected = {};
|
|
17
|
+
for (const dep of tracked)
|
|
18
|
+
if (dep in all)
|
|
19
|
+
selected[dep] = all[dep];
|
|
20
|
+
return "sha256:" + createHash("sha256").update(JSON.stringify(selected)).digest("hex").slice(0, 16);
|
|
21
|
+
}
|
|
22
|
+
return "sha256:" + createHash("sha256").update(JSON.stringify(all)).digest("hex").slice(0, 16);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=hash-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-deps.js","sourceRoot":"","sources":["../../src/util/hash-deps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAgB,EAAE,OAAkB;IAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAGnD,CAAC;IACF,MAAM,GAAG,GAA2B,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;IACpF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAC5C,KAAK,MAAM,GAAG,IAAI,OAAO;YAAE,IAAI,GAAG,IAAI,GAAG;gBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAE,CAAC;QACrE,OAAO,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACjG,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal in-house spinner — issue #97.
|
|
3
|
+
*
|
|
4
|
+
* Why in-house? `ora` / `nanospinner` / `cli-spinners` would each pull a small
|
|
5
|
+
* dep tree we don't need. The full spec for an audit-time spinner is a redraw
|
|
6
|
+
* loop + ANSI cursor codes — well under 100 LOC. picocolors (already a dep)
|
|
7
|
+
* handles color.
|
|
8
|
+
*
|
|
9
|
+
* Design contract:
|
|
10
|
+
* - Always writes to stderr by default. stdout is reserved for the audit
|
|
11
|
+
* JSON / SARIF payload; the spinner must never contaminate it.
|
|
12
|
+
* - No-op when `enabled` is false OR `isTTY` is false. Callers can pass the
|
|
13
|
+
* spinner unconditionally; suppression logic lives here.
|
|
14
|
+
* - On `start()` we hide the cursor and install signal handlers so a
|
|
15
|
+
* ^C-killed audit doesn't leave the terminal in a cursor-hidden state.
|
|
16
|
+
* - On `succeed()` / `fail()` / `stop()` we clear the spinner line first,
|
|
17
|
+
* then optionally write the final state (succeed/fail). The final line
|
|
18
|
+
* persists; the in-progress frame does not.
|
|
19
|
+
*/
|
|
20
|
+
export interface SpinnerOptions {
|
|
21
|
+
/** Whether the destination stream is a TTY. */
|
|
22
|
+
isTTY: boolean;
|
|
23
|
+
/** Master switch — false means no-op (used for --quiet, JSON/SARIF, etc.). */
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
/** Destination stream (default: process.stderr). */
|
|
26
|
+
stream?: NodeJS.WriteStream;
|
|
27
|
+
/**
|
|
28
|
+
* Whether to emit ANSI color codes. Cursor + clear-line codes are emitted
|
|
29
|
+
* regardless because they're what makes the spinner visible. Default:
|
|
30
|
+
* `isTTY && NO_COLOR` is unset.
|
|
31
|
+
*/
|
|
32
|
+
color?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface Spinner {
|
|
35
|
+
start(label: string): void;
|
|
36
|
+
update(label: string): void;
|
|
37
|
+
succeed(label: string): void;
|
|
38
|
+
fail(label: string): void;
|
|
39
|
+
stop(): void;
|
|
40
|
+
}
|
|
41
|
+
export declare function createSpinner(opts: SpinnerOptions): Spinner;
|