drift-analyzer 0.5.0__tar.gz

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.
Files changed (187) hide show
  1. drift_analyzer-0.5.0/.git +1 -0
  2. drift_analyzer-0.5.0/.githooks/commit-msg +28 -0
  3. drift_analyzer-0.5.0/.githooks/pre-commit +25 -0
  4. drift_analyzer-0.5.0/.githooks/pre-push +68 -0
  5. drift_analyzer-0.5.0/.github/ISSUE_TEMPLATE/bug_report.md +36 -0
  6. drift_analyzer-0.5.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
  7. drift_analyzer-0.5.0/.github/ISSUE_TEMPLATE/false_positive.md +39 -0
  8. drift_analyzer-0.5.0/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  9. drift_analyzer-0.5.0/.github/PULL_REQUEST_TEMPLATE.md +35 -0
  10. drift_analyzer-0.5.0/.github/copilot-instructions.md +163 -0
  11. drift_analyzer-0.5.0/.github/instructions/drift-policy.instructions.md +57 -0
  12. drift_analyzer-0.5.0/.github/workflows/ci.yml +79 -0
  13. drift_analyzer-0.5.0/.github/workflows/docs.yml +48 -0
  14. drift_analyzer-0.5.0/.github/workflows/publish.yml +88 -0
  15. drift_analyzer-0.5.0/.github/workflows/validate-release.yml +33 -0
  16. drift_analyzer-0.5.0/.gitignore +27 -0
  17. drift_analyzer-0.5.0/.pre-commit-hooks.yaml +12 -0
  18. drift_analyzer-0.5.0/CHANGELOG.md +91 -0
  19. drift_analyzer-0.5.0/CODE_OF_CONDUCT.md +125 -0
  20. drift_analyzer-0.5.0/CONTRIBUTING.md +166 -0
  21. drift_analyzer-0.5.0/DEVELOPER.md +144 -0
  22. drift_analyzer-0.5.0/LICENSE +21 -0
  23. drift_analyzer-0.5.0/Makefile +68 -0
  24. drift_analyzer-0.5.0/OUTREACH.md +396 -0
  25. drift_analyzer-0.5.0/PKG-INFO +284 -0
  26. drift_analyzer-0.5.0/POLICY.md +238 -0
  27. drift_analyzer-0.5.0/README.md +224 -0
  28. drift_analyzer-0.5.0/SECURITY.md +45 -0
  29. drift_analyzer-0.5.0/STUDY.md +735 -0
  30. drift_analyzer-0.5.0/action.yml +101 -0
  31. drift_analyzer-0.5.0/docs/PRODUCT_STRATEGY.md +294 -0
  32. drift_analyzer-0.5.0/docs/adr/001-deterministic-analysis-pipeline.md +73 -0
  33. drift_analyzer-0.5.0/docs/adr/002-ast-fingerprinting-for-patterns.md +114 -0
  34. drift_analyzer-0.5.0/docs/adr/003-composite-scoring-model.md +97 -0
  35. drift_analyzer-0.5.0/docs/adr/004-subprocess-git-parsing.md +91 -0
  36. drift_analyzer-0.5.0/docs/language-roadmap.md +8 -0
  37. drift_analyzer-0.5.0/docs/language-support-matrix.md +9 -0
  38. drift_analyzer-0.5.0/docs/python-baseline.md +15 -0
  39. drift_analyzer-0.5.0/docs/python-rule-inventory.md +50 -0
  40. drift_analyzer-0.5.0/docs/tsjs-mvp-scope.md +18 -0
  41. drift_analyzer-0.5.0/docs-site/algorithms/deep-dive.md +64 -0
  42. drift_analyzer-0.5.0/docs-site/algorithms/scoring.md +50 -0
  43. drift_analyzer-0.5.0/docs-site/algorithms/signals.md +55 -0
  44. drift_analyzer-0.5.0/docs-site/benchmarking.md +69 -0
  45. drift_analyzer-0.5.0/docs-site/case-studies/django.md +26 -0
  46. drift_analyzer-0.5.0/docs-site/case-studies/fastapi.md +23 -0
  47. drift_analyzer-0.5.0/docs-site/case-studies/index.md +13 -0
  48. drift_analyzer-0.5.0/docs-site/case-studies/pydantic.md +19 -0
  49. drift_analyzer-0.5.0/docs-site/changelog.md +3 -0
  50. drift_analyzer-0.5.0/docs-site/contributing.md +26 -0
  51. drift_analyzer-0.5.0/docs-site/getting-started/configuration.md +68 -0
  52. drift_analyzer-0.5.0/docs-site/getting-started/finding-triage.md +126 -0
  53. drift_analyzer-0.5.0/docs-site/getting-started/installation.md +33 -0
  54. drift_analyzer-0.5.0/docs-site/getting-started/quickstart.md +52 -0
  55. drift_analyzer-0.5.0/docs-site/getting-started/team-rollout.md +94 -0
  56. drift_analyzer-0.5.0/docs-site/index.md +50 -0
  57. drift_analyzer-0.5.0/docs-site/product-strategy.md +56 -0
  58. drift_analyzer-0.5.0/docs-site/study.md +5 -0
  59. drift_analyzer-0.5.0/drift.example.yaml +72 -0
  60. drift_analyzer-0.5.0/examples/demo-project/README.md +20 -0
  61. drift_analyzer-0.5.0/examples/demo-project/api/__init__.py +0 -0
  62. drift_analyzer-0.5.0/examples/demo-project/api/routes.py +22 -0
  63. drift_analyzer-0.5.0/examples/demo-project/db/__init__.py +0 -0
  64. drift_analyzer-0.5.0/examples/demo-project/db/models.py +26 -0
  65. drift_analyzer-0.5.0/examples/demo-project/services/__init__.py +0 -0
  66. drift_analyzer-0.5.0/examples/demo-project/services/email_service.py +22 -0
  67. drift_analyzer-0.5.0/examples/demo-project/services/order_service.py +32 -0
  68. drift_analyzer-0.5.0/examples/demo-project/services/user_service.py +28 -0
  69. drift_analyzer-0.5.0/examples/demo-project/utils/__init__.py +0 -0
  70. drift_analyzer-0.5.0/examples/demo-project/utils/validators.py +43 -0
  71. drift_analyzer-0.5.0/examples/demo_fastapi.md +100 -0
  72. drift_analyzer-0.5.0/examples/drift-check.yml +33 -0
  73. drift_analyzer-0.5.0/mkdocs.yml +71 -0
  74. drift_analyzer-0.5.0/outreach/awesome_python_entry.md +24 -0
  75. drift_analyzer-0.5.0/outreach/awesome_static_analysis_entry.md +28 -0
  76. drift_analyzer-0.5.0/outreach/devto_outline.md +70 -0
  77. drift_analyzer-0.5.0/outreach/hn_post.md +37 -0
  78. drift_analyzer-0.5.0/outreach/reddit_experienced.md +44 -0
  79. drift_analyzer-0.5.0/outreach/reddit_python.md +55 -0
  80. drift_analyzer-0.5.0/outreach/twitter_thread.md +64 -0
  81. drift_analyzer-0.5.0/pyproject.toml +137 -0
  82. drift_analyzer-0.5.0/src/drift/__init__.py +18 -0
  83. drift_analyzer-0.5.0/src/drift/__main__.py +6 -0
  84. drift_analyzer-0.5.0/src/drift/analyzer.py +370 -0
  85. drift_analyzer-0.5.0/src/drift/analyzers/typescript/alias_resolver.py +129 -0
  86. drift_analyzer-0.5.0/src/drift/analyzers/typescript/barrel_resolver.py +131 -0
  87. drift_analyzer-0.5.0/src/drift/analyzers/typescript/import_graph.py +172 -0
  88. drift_analyzer-0.5.0/src/drift/analyzers/typescript/workspace_boundaries.py +116 -0
  89. drift_analyzer-0.5.0/src/drift/cache.py +209 -0
  90. drift_analyzer-0.5.0/src/drift/cli.py +80 -0
  91. drift_analyzer-0.5.0/src/drift/commands/__init__.py +16 -0
  92. drift_analyzer-0.5.0/src/drift/commands/analyze.py +142 -0
  93. drift_analyzer-0.5.0/src/drift/commands/badge.py +75 -0
  94. drift_analyzer-0.5.0/src/drift/commands/check.py +100 -0
  95. drift_analyzer-0.5.0/src/drift/commands/patterns.py +70 -0
  96. drift_analyzer-0.5.0/src/drift/commands/self_analyze.py +61 -0
  97. drift_analyzer-0.5.0/src/drift/commands/timeline.py +42 -0
  98. drift_analyzer-0.5.0/src/drift/commands/trend.py +125 -0
  99. drift_analyzer-0.5.0/src/drift/config.py +127 -0
  100. drift_analyzer-0.5.0/src/drift/embeddings.py +294 -0
  101. drift_analyzer-0.5.0/src/drift/ingestion/__init__.py +12 -0
  102. drift_analyzer-0.5.0/src/drift/ingestion/ast_parser.py +509 -0
  103. drift_analyzer-0.5.0/src/drift/ingestion/file_discovery.py +156 -0
  104. drift_analyzer-0.5.0/src/drift/ingestion/git_history.py +281 -0
  105. drift_analyzer-0.5.0/src/drift/ingestion/ts_parser.py +452 -0
  106. drift_analyzer-0.5.0/src/drift/models.py +240 -0
  107. drift_analyzer-0.5.0/src/drift/output/__init__.py +18 -0
  108. drift_analyzer-0.5.0/src/drift/output/json_output.py +147 -0
  109. drift_analyzer-0.5.0/src/drift/output/rich_output.py +489 -0
  110. drift_analyzer-0.5.0/src/drift/py.typed +0 -0
  111. drift_analyzer-0.5.0/src/drift/recommendations.py +268 -0
  112. drift_analyzer-0.5.0/src/drift/rules/tsjs/cross_package_import_ban.py +93 -0
  113. drift_analyzer-0.5.0/src/drift/scoring/__init__.py +17 -0
  114. drift_analyzer-0.5.0/src/drift/scoring/engine.py +269 -0
  115. drift_analyzer-0.5.0/src/drift/signals/__init__.py +21 -0
  116. drift_analyzer-0.5.0/src/drift/signals/architecture_violation.py +454 -0
  117. drift_analyzer-0.5.0/src/drift/signals/base.py +108 -0
  118. drift_analyzer-0.5.0/src/drift/signals/doc_impl_drift.py +492 -0
  119. drift_analyzer-0.5.0/src/drift/signals/explainability_deficit.py +198 -0
  120. drift_analyzer-0.5.0/src/drift/signals/mutant_duplicates.py +484 -0
  121. drift_analyzer-0.5.0/src/drift/signals/pattern_fragmentation.py +175 -0
  122. drift_analyzer-0.5.0/src/drift/signals/system_misalignment.py +217 -0
  123. drift_analyzer-0.5.0/src/drift/signals/temporal_volatility.py +171 -0
  124. drift_analyzer-0.5.0/src/drift/suppression.py +93 -0
  125. drift_analyzer-0.5.0/src/drift/timeline.py +293 -0
  126. drift_analyzer-0.5.0/tests/__init__.py +0 -0
  127. drift_analyzer-0.5.0/tests/conftest.py +149 -0
  128. drift_analyzer-0.5.0/tests/fixtures/__init__.py +0 -0
  129. drift_analyzer-0.5.0/tests/fixtures/ground_truth.py +1106 -0
  130. drift_analyzer-0.5.0/tests/fixtures/tsjs_alias_resolution/src/app.ts +6 -0
  131. drift_analyzer-0.5.0/tests/fixtures/tsjs_alias_resolution/src/core/logger.ts +3 -0
  132. drift_analyzer-0.5.0/tests/fixtures/tsjs_alias_resolution/src/shared/config.ts +3 -0
  133. drift_analyzer-0.5.0/tests/fixtures/tsjs_alias_resolution/tsconfig.json +9 -0
  134. drift_analyzer-0.5.0/tests/fixtures/tsjs_barrel_resolution/src/app.ts +3 -0
  135. drift_analyzer-0.5.0/tests/fixtures/tsjs_barrel_resolution/src/button.tsx +1 -0
  136. drift_analyzer-0.5.0/tests/fixtures/tsjs_barrel_resolution/src/index.ts +2 -0
  137. drift_analyzer-0.5.0/tests/fixtures/tsjs_graph_relative/app.ts +6 -0
  138. drift_analyzer-0.5.0/tests/fixtures/tsjs_graph_relative/components/button.tsx +3 -0
  139. drift_analyzer-0.5.0/tests/fixtures/tsjs_graph_relative/components/index.ts +3 -0
  140. drift_analyzer-0.5.0/tests/fixtures/tsjs_graph_relative/lib/util.ts +3 -0
  141. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/negative/cross_package_import_ban.json +5 -0
  142. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/negative/package.json +7 -0
  143. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/negative/packages/app/src/main.ts +3 -0
  144. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/negative/packages/ui/src/button.ts +1 -0
  145. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/positive/cross_package_import_ban.json +3 -0
  146. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/positive/package.json +7 -0
  147. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/positive/packages/app/src/main.ts +3 -0
  148. drift_analyzer-0.5.0/tests/fixtures/tsjs_rule_cross_package/positive/packages/ui/src/button.ts +1 -0
  149. drift_analyzer-0.5.0/tests/fixtures/tsjs_workspace_boundaries/package.json +7 -0
  150. drift_analyzer-0.5.0/tests/fixtures/tsjs_workspace_boundaries/packages/app/src/main.ts +1 -0
  151. drift_analyzer-0.5.0/tests/fixtures/tsjs_workspace_boundaries/packages/ui/src/button.tsx +1 -0
  152. drift_analyzer-0.5.0/tests/test_ablation.py +237 -0
  153. drift_analyzer-0.5.0/tests/test_architecture_violation.py +110 -0
  154. drift_analyzer-0.5.0/tests/test_ast_parser.py +112 -0
  155. drift_analyzer-0.5.0/tests/test_avs_enhanced.py +133 -0
  156. drift_analyzer-0.5.0/tests/test_avs_mutations.py +351 -0
  157. drift_analyzer-0.5.0/tests/test_badge_command.py +47 -0
  158. drift_analyzer-0.5.0/tests/test_cache_resilience.py +38 -0
  159. drift_analyzer-0.5.0/tests/test_ci_reality.py +296 -0
  160. drift_analyzer-0.5.0/tests/test_config.py +43 -0
  161. drift_analyzer-0.5.0/tests/test_dia_enhanced.py +254 -0
  162. drift_analyzer-0.5.0/tests/test_embeddings.py +106 -0
  163. drift_analyzer-0.5.0/tests/test_file_discovery.py +180 -0
  164. drift_analyzer-0.5.0/tests/test_fix_actionability.py +382 -0
  165. drift_analyzer-0.5.0/tests/test_git_history_edge_cases.py +228 -0
  166. drift_analyzer-0.5.0/tests/test_git_history_safety.py +94 -0
  167. drift_analyzer-0.5.0/tests/test_integration.py +168 -0
  168. drift_analyzer-0.5.0/tests/test_json_output.py +94 -0
  169. drift_analyzer-0.5.0/tests/test_mutant_duplicates_edge_cases.py +201 -0
  170. drift_analyzer-0.5.0/tests/test_output_golden.py +242 -0
  171. drift_analyzer-0.5.0/tests/test_pattern_fragmentation.py +147 -0
  172. drift_analyzer-0.5.0/tests/test_precision_recall.py +286 -0
  173. drift_analyzer-0.5.0/tests/test_recommendations.py +214 -0
  174. drift_analyzer-0.5.0/tests/test_recommendations_edge_cases.py +254 -0
  175. drift_analyzer-0.5.0/tests/test_scoring.py +218 -0
  176. drift_analyzer-0.5.0/tests/test_scoring_edge_cases.py +259 -0
  177. drift_analyzer-0.5.0/tests/test_self_command.py +31 -0
  178. drift_analyzer-0.5.0/tests/test_smoke_real_repos.py +316 -0
  179. drift_analyzer-0.5.0/tests/test_suppression.py +162 -0
  180. drift_analyzer-0.5.0/tests/test_timeline.py +158 -0
  181. drift_analyzer-0.5.0/tests/test_trend_chart.py +42 -0
  182. drift_analyzer-0.5.0/tests/test_tsjs_alias_resolution.py +18 -0
  183. drift_analyzer-0.5.0/tests/test_tsjs_barrel_resolution.py +20 -0
  184. drift_analyzer-0.5.0/tests/test_tsjs_import_graph_relative.py +28 -0
  185. drift_analyzer-0.5.0/tests/test_tsjs_rule_cross_package_import_ban.py +41 -0
  186. drift_analyzer-0.5.0/tests/test_tsjs_workspace_boundaries.py +44 -0
  187. drift_analyzer-0.5.0/tests/test_typescript_parser.py +161 -0
@@ -0,0 +1 @@
1
+ gitdir: ../.git/modules/drift
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env sh
2
+ # commit-msg hook — enforce Conventional Commits format
3
+ # Install with: git config core.hooksPath .githooks
4
+ #
5
+ # Allowed prefixes: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
6
+ # Format: type(scope): description OR type: description
7
+
8
+ commit_msg_file="$1"
9
+ commit_msg=$(head -1 "$commit_msg_file")
10
+
11
+ # Allow merge commits and fixup/squash commits
12
+ if echo "$commit_msg" | grep -qE "^(Merge|fixup!|squash!) "; then
13
+ exit 0
14
+ fi
15
+
16
+ pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,}"
17
+
18
+ if ! echo "$commit_msg" | grep -qE "$pattern"; then
19
+ echo ">>> [commit-msg] ERROR: Commit message does not follow Conventional Commits."
20
+ echo ""
21
+ echo " Expected format: type(scope): description"
22
+ echo " Example: feat(scoring): add count dampening"
23
+ echo ""
24
+ echo " Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
25
+ echo ""
26
+ echo " Your message: $commit_msg"
27
+ exit 1
28
+ fi
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env sh
2
+ # pre-commit hook — block private paths + fast lint on staged files
3
+ # Install once with: git config core.hooksPath .githooks
4
+ set -e
5
+
6
+ blocked_pattern='^(tagesplanung/)'
7
+
8
+ staged_blocked=$(git diff --cached --name-only --diff-filter=ACMR | grep -E "$blocked_pattern" || true)
9
+
10
+ if [ -n "$staged_blocked" ]; then
11
+ echo ">>> [pre-commit] ERROR: Blocked paths detected in staged changes:"
12
+ echo "$staged_blocked"
13
+ echo ">>> [pre-commit] Remove these files from staging before commit."
14
+ exit 1
15
+ fi
16
+
17
+ # Fast lint on staged Python files (errors + import order only, <1s).
18
+ # Full lint + typecheck + tests run in pre-push.
19
+ staged_py=$(git diff --cached --name-only --diff-filter=ACMR -- '*.py' || true)
20
+ if [ -n "$staged_py" ]; then
21
+ if command -v ruff >/dev/null 2>&1; then
22
+ echo ">>> [pre-commit] Running ruff quick-check on staged files..."
23
+ echo "$staged_py" | xargs ruff check --select E,F,I --no-fix
24
+ fi
25
+ fi
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env sh
2
+ # pre-push hook — mirrors CI checks (version-check + lint + typecheck + test + self-analysis)
3
+ # Install once with: git config core.hooksPath .githooks
4
+ set -e
5
+
6
+ # Block private/non-tool paths from being pushed.
7
+ blocked_pattern='^(tagesplanung/)'
8
+
9
+ reject_push_for_blocked_paths() {
10
+ local_ref="$1"
11
+ local_sha="$2"
12
+ remote_ref="$3"
13
+ remote_sha="$4"
14
+
15
+ # Deletion push (local ref removed) can be ignored here.
16
+ if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
17
+ return 0
18
+ fi
19
+
20
+ if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
21
+ commit_list=$(git rev-list "$local_sha" --not --all)
22
+ else
23
+ commit_list=$(git rev-list "$remote_sha..$local_sha")
24
+ fi
25
+
26
+ for commit in $commit_list; do
27
+ blocked_hits=$(git diff-tree --no-commit-id --name-only --diff-filter=ACMR -r "$commit" | grep -E "$blocked_pattern" || true)
28
+ if [ -n "$blocked_hits" ]; then
29
+ echo ">>> [pre-push] ERROR: Blocked paths detected in commits for $local_ref -> $remote_ref"
30
+ echo "$blocked_hits"
31
+ echo ">>> [pre-push] Remove these files from the commit history before pushing."
32
+ exit 1
33
+ fi
34
+ done
35
+ }
36
+
37
+ while read local_ref local_sha remote_ref remote_sha; do
38
+ reject_push_for_blocked_paths "$local_ref" "$local_sha" "$remote_ref" "$remote_sha"
39
+ done
40
+
41
+ echo ">>> [pre-push] Starting local CI checks..."
42
+
43
+ # Unset git context variables that git injects when running hooks.
44
+ # Without this, tests that create git repos in tmp dirs inherit GIT_DIR
45
+ # from the parent repo and fail with exit 128 ("not a git repository").
46
+ unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_OBJECT_DIRECTORY GIT_COMMON_DIR
47
+
48
+ # 1. Version format (SemVer)
49
+ echo ">>> [1/5] Checking SemVer version..."
50
+ python scripts/check_version.py --check-semver
51
+
52
+ # 2. Lint
53
+ echo ">>> [2/5] Running ruff lint..."
54
+ ruff check src/ tests/
55
+
56
+ # 3. Type checking
57
+ echo ">>> [3/5] Running mypy..."
58
+ python -m mypy src/drift
59
+
60
+ # 4. Tests with coverage (exclude slow smoke tests that clone external repos)
61
+ echo ">>> [4/5] Running pytest + coverage (excl. smoke tests)..."
62
+ pytest -v --tb=short --cov --cov-report=term-missing --ignore=tests/test_smoke_real_repos.py
63
+
64
+ # 5. Self-analysis
65
+ echo ">>> [5/5] Running self-analysis..."
66
+ drift analyze --repo . --format json > /dev/null
67
+
68
+ echo ">>> [pre-push] All checks passed. Push continues."
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: "Bug Report"
3
+ about: "Something isn't working as expected"
4
+ title: "[Bug] "
5
+ labels: ["bug"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## Describe the bug
10
+
11
+ A clear description of what the bug is.
12
+
13
+ ## To reproduce
14
+
15
+ ```bash
16
+ # Command you ran
17
+ drift analyze --repo /path/to/project
18
+
19
+ # Or: paste the relevant config
20
+ ```
21
+
22
+ **Python version:** <!-- e.g. 3.12 -->
23
+ **drift-analyzer version:** <!-- drift --version -->
24
+ **OS:** <!-- e.g. Ubuntu 22.04, macOS 14, Windows 11 -->
25
+
26
+ ## Expected behaviour
27
+
28
+ What you expected to happen.
29
+
30
+ ## Actual behaviour
31
+
32
+ What actually happened. Include the full error output if applicable.
33
+
34
+ ## Additional context
35
+
36
+ <!-- Stack trace, drift.yaml contents, anything else relevant -->
@@ -0,0 +1,11 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Questions and usage help
4
+ url: https://github.com/sauremilk/drift/discussions
5
+ about: Please ask and answer general questions in Discussions.
6
+ - name: Documentation
7
+ url: https://sauremilk.github.io/drift/
8
+ about: Check the docs site for setup, configuration, and examples.
9
+ - name: Security report
10
+ url: https://github.com/sauremilk/drift/security/policy
11
+ about: Please report security vulnerabilities via the Security Policy page.
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: "False Positive / False Negative"
3
+ about: "Drift is flagging something incorrectly, or missing a real issue"
4
+ title: "[FP/FN] "
5
+ labels: ["signal-quality"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## Signal affected
10
+
11
+ <!-- Which signal produced the false result? -->
12
+
13
+ - [ ] Pattern Fragmentation (PFS)
14
+ - [ ] Architecture Violations (AVS)
15
+ - [ ] Mutant Duplicates (MDS)
16
+ - [ ] Explainability Deficit (EDS)
17
+ - [ ] Temporal Volatility (TVS)
18
+ - [ ] System Misalignment (SMS)
19
+
20
+ ## False positive or false negative?
21
+
22
+ - [ ] False positive — drift flagged something that isn't a real issue
23
+ - [ ] False negative — drift missed something that is a real issue
24
+
25
+ ## Code example
26
+
27
+ ```python
28
+ # Paste the relevant code snippet here
29
+ ```
30
+
31
+ ## Why this is incorrect
32
+
33
+ Explain why drift's assessment is wrong in this case.
34
+
35
+ ## drift.yaml config (if any)
36
+
37
+ ```yaml
38
+
39
+ ```
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: "Feature Request"
3
+ about: "Suggest a new signal, output format, or improvement"
4
+ title: "[Feature] "
5
+ labels: ["enhancement"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## Problem / motivation
10
+
11
+ What problem does this solve? What's the current limitation?
12
+
13
+ ## Proposed solution
14
+
15
+ Describe the feature you'd like. Be as specific as possible.
16
+
17
+ ## Alternatives considered
18
+
19
+ Any alternative approaches you've thought about?
20
+
21
+ ## Would you like to contribute?
22
+
23
+ - [ ] Yes, I'd like to open a PR for this
24
+ - [ ] No, just requesting it
@@ -0,0 +1,35 @@
1
+ ## Summary
2
+
3
+ <!-- What changed and why? -->
4
+
5
+ ## Related issue
6
+
7
+ <!-- Use: Closes #123 / Fixes #123 / Related #123 -->
8
+
9
+ ## Type of change
10
+
11
+ - [ ] Bug fix
12
+ - [ ] New feature
13
+ - [ ] Refactor
14
+ - [ ] Documentation
15
+ - [ ] Test-only change
16
+ - [ ] CI/Build change
17
+
18
+ ## Validation
19
+
20
+ - [ ] `pytest` passes locally
21
+ - [ ] `ruff check src/ tests/` passes locally
22
+ - [ ] `mypy src/drift` passes locally
23
+ - [ ] `drift self` delta checked (target: <= +0.010)
24
+ - [ ] Added/updated tests for behavioral changes
25
+
26
+ ## Checklist
27
+
28
+ - [ ] PR is focused on one concern
29
+ - [ ] Public docs updated (README/docs-site) if needed
30
+ - [ ] Changelog entry added if user-visible
31
+ - [ ] No unrelated files included
32
+
33
+ ## Notes for reviewers
34
+
35
+ <!-- Anything that needs special attention during review -->
@@ -0,0 +1,163 @@
1
+ # Drift — Verbindliche Arbeitsgrundlage für alle Agenten
2
+
3
+ **Diese Datei ist für alle Copilot-Agenten, Coding-Agenten und KI-Assistenten im Drift-Workspace bindend.**
4
+
5
+ Die vollständige Policy befindet sich in:
6
+ `POLICY.md` (Workspace-Root)
7
+
8
+ Lies diese Datei **vor jeder Arbeit** vollständig, sofern sie nicht bereits im Kontext ist.
9
+ Die Policy ist ein Vertrag — keine Empfehlung, kein Vorschlag.
10
+
11
+ ---
12
+
13
+ ## PFLICHT-GATE: Zulässigkeitsprüfung vor jeder Aufgabe
14
+
15
+ **Vor jeder Antwort, die eine Änderung, ein Feature, eine Analyse oder eine Umsetzung enthält, MUSS der Agent dieses Gate sichtbar ausgeben:**
16
+
17
+ ```
18
+ ### Drift Policy Gate
19
+ - Aufgabe: [Kurzbeschreibung der Aufgabe in einem Satz]
20
+ - Zulassungskriterium erfüllt: [JA / NEIN] → [welches Kriterium: Unsicherheit / Signal / Glaubwürdigkeit / Handlungsfähigkeit / Trend / Einführbarkeit]
21
+ - Ausschlusskriterium ausgelöst: [JA / NEIN] → [falls JA: welches]
22
+ - Roadmap-Phase: [Phase 1 / 2 / 3 / 4] — blockiert durch höhere Phase: [JA / NEIN]
23
+ - Entscheidung: [ZULÄSSIG / ABBRUCH]
24
+ - Begründung: [ein Satz]
25
+ ```
26
+
27
+ **Bei Entscheidung ABBRUCH:** Keine weitere Umsetzung. Stattdessen: kurze Erklärung, welches Kriterium verletzt wird und was stattdessen priorisiert werden sollte.
28
+
29
+ **Das Gate darf nicht übersprungen werden.** Auch nicht bei kleinen Änderungen, Refactorings oder scheinbar offensichtlichen Aufgaben.
30
+
31
+ ---
32
+
33
+ ## Nicht verhandelbare Grundregeln
34
+
35
+ ### Was Drift ist
36
+ Drift ist ein statischer Analyzer zur Erkennung architektonischer Kohärenzprobleme.
37
+ Zweck: strukturelle Erosion erkennen, benennen, priorisieren, über Zeit vergleichbar machen.
38
+
39
+ ### Was Drift nicht ist
40
+ - Drift ist kein Tool, das lediglich Probleme auflistet.
41
+ - Drift erzeugt keine dekorativen Ergebnisse.
42
+ - Drift priorisiert keine Ergebnisse ohne realen Zusammenhang mit struktureller Kohärenz.
43
+
44
+ ---
45
+
46
+ ## Absolute Ausschlusskriterien für neue Arbeit
47
+
48
+ **Keine Aufgabe darf begonnen werden**, die ausschließlich folgendes erzeugt:
49
+ - mehr Ausgabe ohne besseren Erkenntniswert
50
+ - mehr Komplexität ohne klaren Nutzen
51
+ - mehr Oberfläche ohne bessere Analyse
52
+ - mehr Analyse ohne Validierung des Ergebnisses
53
+ - mehr technische Ausarbeitung ohne Beitrag zur Produktwirkung
54
+ - einen Nutzen, der nicht eindeutig benennbar ist
55
+
56
+ ---
57
+
58
+ ## Priorisierungsformel (Policy §6)
59
+
60
+ ```
61
+ Priorität = (Unsicherheit × Schaden × Nutzbarkeit) / Aufwand
62
+ ```
63
+
64
+ Bei konkurrierenden Vorhaben gilt diese feste Reihenfolge:
65
+ 1. Glaubwürdigkeit erhalten
66
+ 2. Signalpräzision verbessern
67
+ 3. Verständlichkeit der Befunde verbessern
68
+ 4. False Positives / False Negatives reduzieren
69
+ 5. Einführbarkeit verbessern
70
+ 6. Trendanalyse verbessern
71
+ 7. Zusätzliche Features, Formate, Komfortmerkmale
72
+
73
+ **Eine niedrigere Stufe verdrängt niemals eine höhere.**
74
+
75
+ ---
76
+
77
+ ## Qualitätsanforderungen an jeden Befund (Policy §13)
78
+
79
+ Jeder Befund muss besitzen:
80
+ - technische Nachvollziehbarkeit
81
+ - Reproduzierbarkeit
82
+ - eindeutige Zuordnung zu einer Ursache
83
+ - klare Benennung der betroffenen Stelle
84
+ - nachvollziehbare Begründung
85
+ - erkennbare nächste Maßnahme
86
+
87
+ Ein Befund ohne klare Begründung ist **unzulässig**.
88
+ Ein Befund ohne mögliche nächste Maßnahme ist **unvollständig**.
89
+
90
+ ---
91
+
92
+ ## Zulassungskriterien für neue Arbeit (Policy §8)
93
+
94
+ Eine Aufgabe darf nur begonnen werden, wenn sie mindestens eines erfüllt:
95
+ - reduziert eine zentrale Unsicherheit
96
+ - verbessert die Signalqualität
97
+ - erhöht die Glaubwürdigkeit
98
+ - erhöht die Handlungsfähigkeit
99
+ - verbessert die Trendfähigkeit
100
+ - erleichtert die Einführbarkeit
101
+
102
+ ---
103
+
104
+ ## Roadmap-Phasen-Hierarchie (Policy §14)
105
+
106
+ **Phase 1 — Vertrauen** (Vorrang vor allem anderen):
107
+ Nachvollziehbarkeit → Reproduzierbarkeit → Fehlalarmreduktion → Erklärbarkeit
108
+
109
+ **Phase 2 — Relevanz** → **Phase 3 — Einführbarkeit** → **Phase 4 — Skalierung**
110
+
111
+ Phase 4 verdrängt niemals Phase 1.
112
+ Skalierungsmaßnahmen ohne gesichertes Vertrauen sind **nachrangig**.
113
+
114
+ ---
115
+
116
+ ## Entscheidungsregel bei Unklarheit (Policy §16)
117
+
118
+ > Wähle die Option, die die größte Unsicherheit reduziert.
119
+ > Sind mehrere gleich gut: höchsten Erkenntniswert pro Aufwandseinheit.
120
+ > Ist keine Option hinreichend begründet: **keine Umsetzung**.
121
+
122
+ ---
123
+
124
+ ## Schlussbestimmung
125
+
126
+ Diese Policy ist verbindlich (Policy §18).
127
+ Abweichungen sind nur zulässig wenn: dokumentiert, begründet, als Ausnahme gekennzeichnet.
128
+ Im Zweifel gilt: geringerer Interpretationsspielraum, höherer Erkenntniswert.
129
+
130
+ ---
131
+
132
+ ## Schnellreferenz für Agenten
133
+
134
+ Vollständiger Developer Guide: **[DEVELOPER.md](../DEVELOPER.md)**
135
+
136
+ ### Architektur (Datenfluss)
137
+
138
+ ```
139
+ ingestion/ → signals/ → scoring/ → output/
140
+ AST + Git 7 Detektoren Score+Severity Rich/JSON/SARIF
141
+ ```
142
+
143
+ ### Wichtigste Kommandos
144
+
145
+ | Aufgabe | Befehl |
146
+ |---------|--------|
147
+ | Dev-Setup | `make install` |
148
+ | Alle Checks | `make check` |
149
+ | Nur Tests (schnell) | `make test-fast` |
150
+ | Lint + Autofix | `make lint-fix` |
151
+ | CI lokal replizieren | `make ci` |
152
+ | Selbstanalyse | `make self` |
153
+
154
+ ### Verzeichnisstruktur
155
+
156
+ | Pfad | Inhalt |
157
+ |------|--------|
158
+ | `src/drift/signals/` | 7 Signale (PFS, AVS, MDS, EDS, TVS, SMS, DIA) |
159
+ | `src/drift/ingestion/` | AST-Parsing, Git-History, File-Discovery |
160
+ | `src/drift/scoring/` | Composite-Score, Module-Scores, Severity |
161
+ | `src/drift/output/` | Rich-Terminal, JSON, SARIF |
162
+ | `src/drift/commands/` | Click-CLI-Subcommands |
163
+ | `tests/` | 27+ Testdateien, conftest.py mit tmp_repo Fixture |
@@ -0,0 +1,57 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "Drift Policy — Bindende Arbeitsregeln für alle Dateien. MUSS gelesen werden bevor Änderungen an Drift-Code, Analyselogik, Ergebnisformaten oder Features vorgenommen werden."
4
+ ---
5
+
6
+ # Drift — Policy (bindend für alle Dateioperationen)
7
+
8
+ Vollständige Policy: `POLICY.md` im Workspace-Root.
9
+ Kurzfassung der Kern-Verbote und Anforderungen:
10
+
11
+ ## PFLICHT-GATE: Zulässigkeitsprüfung — immer zuerst ausführen und ausgeben
12
+
13
+ Vor jeder Umsetzung dieses Format sichtbar ausgeben:
14
+
15
+ ```
16
+ ### Drift Policy Gate
17
+ - Aufgabe: [Kurzbeschreibung in einem Satz]
18
+ - Zulassungskriterium erfüllt: [JA / NEIN] → [Unsicherheit / Signal / Glaubwürdigkeit / Handlungsfähigkeit / Trend / Einführbarkeit]
19
+ - Ausschlusskriterium ausgelöst: [JA / NEIN] → [falls JA: welches]
20
+ - Roadmap-Phase: [1 / 2 / 3 / 4] — blockiert durch höhere Phase: [JA / NEIN]
21
+ - Entscheidung: [ZULÄSSIG / ABBRUCH]
22
+ - Begründung: [ein Satz]
23
+ ```
24
+
25
+ Bei **ABBRUCH**: keine Umsetzung, stattdessen Erklärung + Gegenvorschlag.
26
+ Das Gate darf **niemals übersprungen** werden.
27
+
28
+ ---
29
+
30
+ ## Vor jeder Änderung prüfen
31
+
32
+ **Ist die Aufgabe zulässig?** Sie muss mindestens eines erfüllen:
33
+ - reduziert eine zentrale Unsicherheit
34
+ - verbessert die Signalqualität oder Glaubwürdigkeit
35
+ - erhöht die Handlungsfähigkeit
36
+ - verbessert Trendfähigkeit oder Einführbarkeit
37
+
38
+ **Ist die Aufgabe unzulässig?** Sofort abbrechen, wenn sie ausschließlich erzeugt:
39
+ - mehr Ausgabe ohne Erkenntniswert
40
+ - mehr Komplexität ohne klaren Nutzen
41
+ - ein Feature, dessen Beitrag nicht klar benennbar ist
42
+
43
+ ## Pflicht bei Code-Änderungen an Analyseergebnissen
44
+
45
+ Jedes Ergebnis/Befund benötigt zwingend:
46
+ 1. technische Nachvollziehbarkeit
47
+ 2. Reproduzierbarkeit
48
+ 3. eindeutige Ursachenzuordnung
49
+ 4. nachvollziehbare Begründung
50
+ 5. erkennbare nächste Maßnahme
51
+
52
+ Fehlt eines dieser fünf Elemente → Änderung ist **unzulässig**.
53
+
54
+ ## Prioritätsbindung
55
+
56
+ Reihenfolge ist nicht verhandelbar:
57
+ `Glaubwürdigkeit > Signalpräzision > Verständlichkeit > FP/FN-Reduktion > Einführbarkeit > Trend > Features`
@@ -0,0 +1,79 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ version-check:
12
+ name: Version format check
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Validate pyproject.toml version is SemVer
23
+ # Ensures the version in pyproject.toml is always MAJOR.MINOR.PATCH –
24
+ # a merge to master with an invalid or missing version is blocked.
25
+ run: python scripts/check_version.py --check-semver
26
+
27
+ test:
28
+ runs-on: ubuntu-latest
29
+ needs: version-check
30
+ strategy:
31
+ matrix:
32
+ python-version: ["3.11", "3.12", "3.13"]
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0 # Full history for git-based signals
38
+
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: ${{ matrix.python-version }}
42
+
43
+ - name: Install dependencies
44
+ run: pip install -e ".[dev]"
45
+
46
+ - name: Lint with ruff
47
+ run: ruff check src/ tests/
48
+
49
+ - name: Type-check with mypy
50
+ run: python -m mypy src/drift
51
+
52
+ - name: Run tests with coverage
53
+ run: pytest -v --tb=short --cov=drift --cov-report=xml --cov-report=term-missing -m "not slow"
54
+
55
+ - name: Upload coverage to Codecov
56
+ if: matrix.python-version == '3.12'
57
+ uses: codecov/codecov-action@v4
58
+ with:
59
+ files: coverage.xml
60
+ fail_ci_if_error: false
61
+ env:
62
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
63
+
64
+ - name: Self-analysis
65
+ run: drift analyze --repo . --format json > /dev/null
66
+
67
+ - name: Drift self-check (score gate)
68
+ if: matrix.python-version == '3.12'
69
+ run: |
70
+ drift self --format json > drift_score.json
71
+ python -c "
72
+ import json, sys
73
+ data = json.load(open('drift_score.json'))
74
+ score = data['drift_score']
75
+ if score > 0.47:
76
+ print(f'FAIL: drift self score {score:.3f} exceeds threshold 0.47')
77
+ sys.exit(1)
78
+ print(f'OK: drift self score {score:.3f} (threshold 0.47)')
79
+ "
@@ -0,0 +1,48 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ paths:
7
+ - "docs-site/**"
8
+ - "mkdocs.yml"
9
+ - ".github/workflows/docs.yml"
10
+
11
+ permissions:
12
+ contents: read
13
+ pages: write
14
+ id-token: write
15
+
16
+ concurrency:
17
+ group: pages
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+
30
+ - name: Install MkDocs
31
+ run: pip install mkdocs-material
32
+
33
+ - name: Build documentation
34
+ run: mkdocs build --strict
35
+
36
+ - uses: actions/upload-pages-artifact@v3
37
+ with:
38
+ path: site/
39
+
40
+ deploy:
41
+ needs: build
42
+ runs-on: ubuntu-latest
43
+ environment:
44
+ name: github-pages
45
+ url: ${{ steps.deployment.outputs.page_url }}
46
+ steps:
47
+ - id: deployment
48
+ uses: actions/deploy-pages@v4