{"id":51302356,"url":"https://github.com/zer0contextlost/drift-scan","last_synced_at":"2026-06-30T21:01:59.149Z","repository":{"id":359703562,"uuid":"1247181620","full_name":"zer0contextlost/drift-scan","owner":"zer0contextlost","description":"Detect architectural drift in multi-language codebases (TypeScript, Python, Go)","archived":false,"fork":false,"pushed_at":"2026-05-23T02:39:40.000Z","size":92,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-23T04:14:55.777Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zer0contextlost.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-23T01:58:46.000Z","updated_at":"2026-05-23T02:39:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zer0contextlost/drift-scan","commit_stats":null,"previous_names":["zer0contextlost/drift-scan"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/zer0contextlost/drift-scan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zer0contextlost%2Fdrift-scan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zer0contextlost%2Fdrift-scan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zer0contextlost%2Fdrift-scan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zer0contextlost%2Fdrift-scan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zer0contextlost","download_url":"https://codeload.github.com/zer0contextlost/drift-scan/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zer0contextlost%2Fdrift-scan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34983171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T21:01:56.864Z","updated_at":"2026-06-30T21:01:59.139Z","avatar_url":"https://github.com/zer0contextlost.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# drift-scan\n\nDetect architectural drift in multi-language codebases. Declare layer rules once in `.driftrc.json`; drift-scan parses TypeScript, Python, and Go imports and flags every violation.\n\n```\nnpm install -g drift-scan\ndrift scan ./my-project\n```\n\n---\n\n## How it works\n\n1. You define **zones** (domain, service, infrastructure, etc.) and which zones each one is allowed to import.\n2. drift-scan crawls every `.ts`, `.py`, and `.go` file, extracts their imports, and builds a dependency graph.\n3. Any import that crosses a zone boundary in the wrong direction is a violation.\n\nViolations are ranked by blast radius: fanout (how many files in the same zone import the offending file) multiplied by how central the zone is. Scores map to `critical / high / medium / low`.\n\n---\n\n## Config\n\n`.driftrc.json` in the project root:\n\n```json\n{\n  \"layers\": [\"domain\", \"application\", \"infrastructure\"],\n  \"zones\": {\n    \"domain\": {\n      \"paths\": [\"src/domain/**\"],\n      \"canImport\": []\n    },\n    \"application\": {\n      \"paths\": [\"src/application/**\"],\n      \"canImport\": [\"domain\"]\n    },\n    \"infrastructure\": {\n      \"paths\": [\"src/infrastructure/**\"],\n      \"canImport\": [\"domain\", \"application\"]\n    }\n  },\n  \"ignore\": [\"**/*.test.ts\", \"**/*.spec.ts\"]\n}\n```\n\n`drift init [dir]` scaffolds a config by inspecting directory names.\n\n---\n\n## Commands\n\n```\ndrift scan [dir]          scan for violations (default: current directory)\ndrift explain \u003cfile\u003e      show all violations involving a specific file\ndrift graph [dir]         print the inter-zone dependency graph\ndrift stats [dir]         architecture health overview\ndrift init [dir]          scaffold a .driftrc.json\n```\n\n### scan options\n\n| Flag | Description |\n|------|-------------|\n| `--json` | Output JSON |\n| `--sarif` | Output SARIF 2.1 (GitHub code scanning) |\n| `--since \u003cref\u003e` | Only scan files changed since a git ref (e.g. `main`) |\n| `--fail-on \u003cseverity\u003e` | Exit 1 if violations at this severity or above exist |\n| `--min-severity \u003cseverity\u003e` | Only show violations at or above this severity |\n| `--output \u003cfile\u003e` | Write report to file instead of stdout |\n| `--watch` | Watch for file changes and re-scan automatically |\n| `--save-baseline \u003cfile\u003e` | Save current violations as a baseline |\n| `--from-baseline \u003cfile\u003e` | Only report violations not present in the baseline |\n\n### graph options\n\n| Flag | Description |\n|------|-------------|\n| `--dot` | Output Graphviz DOT instead of Mermaid |\n| `--output \u003cfile\u003e` | Write graph to file |\n\n---\n\n## Suppressing violations\n\n**Inline** — add a `drift-ignore` comment on the import line or the line above:\n\n```typescript\n// drift-ignore\nimport { db } from '../infra/Database';\n\nimport { db } from '../infra/Database'; // drift-ignore\n```\n\nWorks in TypeScript (`// drift-ignore`), Python (`# drift-ignore`), and Go (`// drift-ignore`).\n\n**Config exceptions** — whitelist specific file paths in `.driftrc.json` without touching source:\n\n```json\n{\n  \"exceptions\": [\n    {\n      \"from\": \"src/domain/legacy/**\",\n      \"to\": \"src/infra/**\",\n      \"reason\": \"migration in progress\"\n    }\n  ]\n}\n```\n\nBoth `from` and `to` are glob patterns (same syntax as zone `paths`). `to` is optional.\n\n---\n\n## Baseline mode\n\nUseful when adopting drift-scan on an existing codebase with pre-existing violations:\n\n```bash\n# Snapshot current state\ndrift scan --save-baseline baseline.drift.json\n\n# CI: only fail on new violations introduced after the baseline\ndrift scan --from-baseline baseline.drift.json --fail-on high\n```\n\nThe baseline stores stable fingerprints (violation type + relative file paths + line number). Violations that move to a different line will still match as long as they're the same import.\n\n---\n\n## Violation types\n\n| Type | Description |\n|------|-------------|\n| `layer` | A zone imports from a zone it is not permitted to depend on |\n| `circular` | A cross-zone dependency cycle exists |\n| `undeclared` | A file outside any zone imports from a declared zone |\n\n`import type` violations are flagged with `[type-only]` and scored lower — they carry no runtime risk.\n\n---\n\n## Severity\n\n| Score | Severity |\n|-------|----------|\n| ≥ 12 | critical |\n| ≥ 8 | high |\n| ≥ 4 | medium |\n| \u003c 4 | low |\n\nScore = `fanout × 2 + zone_centrality` (circular: `cycle_length + zone_centrality`).\n\n---\n\n## CI integration\n\n### GitHub Actions — SARIF upload\n\n```yaml\n- name: Scan architecture\n  run: drift scan --sarif --output drift.sarif\n\n- name: Upload to code scanning\n  uses: github/codeql-action/upload-sarif@v3\n  with:\n    sarif_file: drift.sarif\n```\n\n### Exit code\n\n`drift scan --fail-on high` exits 1 when any `high` or `critical` violation is found.\n\n---\n\n## TypeScript path aliases\n\ndrift-scan reads `tsconfig.json` `compilerOptions.paths` and `baseUrl` automatically. Imports like `@domain/User` are resolved to their real paths before zone matching — no extra config needed.\n\n```json\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@domain/*\": [\"src/domain/*\"],\n      \"@infra/*\": [\"src/infra/*\"]\n    }\n  }\n}\n```\n\n---\n\n## Language support\n\n| Language | Import styles |\n|----------|--------------|\n| TypeScript / JavaScript | `import`, `require()`, `import()`, `export … from`, `import type` |\n| Python | `import x`, `from x import y`, relative imports |\n| Go | `import \"github.com/org/repo/internal/pkg\"` (module-relative) |\n\n---\n\n## Requirements\n\n- Node.js ≥ 18\n\n---\n\n## License\n\nMIT — [zer0contextlost](https://github.com/zer0contextlost)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzer0contextlost%2Fdrift-scan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzer0contextlost%2Fdrift-scan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzer0contextlost%2Fdrift-scan/lists"}