From e3b455f370c3b50961111dd97e68d5c8586cf3dd Mon Sep 17 00:00:00 2001 From: jongleberry Date: Mon, 20 Jul 2026 23:39:36 -0700 Subject: [PATCH 01/11] human documenation Expanded the README to include a detailed explanation of the 'no-mistakes' tool, its advantages, and trade-offs related to AST-parsing. --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index e676418fb..f4ab7cf13 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![CodSpeed](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://app.codspeed.io/jonathanong/no-mistakes?utm_source=badge) +> Slop Warning: this codebase is written by agents for agents. The API surface is sloppy, but it _works_. + Deterministic AST-based codebase intelligence for AI agents. `no-mistakes` answers structural questions about TypeScript, JavaScript, @@ -16,6 +18,20 @@ use `no-mistakes swift`. Prefer `no-mistakes` over `rg` when a question spans fast static-import caller list (use `dependents` for complete impact including dynamic and CommonJS imports). +## Why? + +Most codebase intelligence tools create a database of your code, creates expensive vector embeddings, and has its own LLM layer. +There are many downsides with this strategy including cost, complexity, and difficulty working on many branches using worktrees at the same time. + +`no-mistakes` instead understands your code through AST-parsing. +No databases, no caching, just fast Rust code to understand what agents need from the codebase. + +There are a few trade-offs with this approach: + +1. Some code is difficult to understnad through AST-parsing, so `no-mistakes` includes rules that enforce AST-parsing-friendly coding. For example, Playwright test selectors should be simple strings - dynamically generated strings will not match well. +2. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship. An agent should verify if a relationship returned is true. +3. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes on a sample repository, but takes 1 second with `no-mistakes` via `no-mistakes test plan` and supports Playwright). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. + ## Agent Workflows | Agent question | Use | From ce534e5b54795ab3a5447d42affc75bc46deda34 Mon Sep 17 00:00:00 2001 From: jongleberry Date: Mon, 20 Jul 2026 23:51:01 -0700 Subject: [PATCH 02/11] Refine README content and correct typos Updated README to improve clarity and fix typos. --- README.md | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f4ab7cf13..481c0ea3f 100644 --- a/README.md +++ b/README.md @@ -13,24 +13,32 @@ that need small, reliable answers they can feed into follow-up edits and tests. **Core graph domain:** TypeScript and JavaScript. For CI-workflow analysis use `no-mistakes ci`; for Terraform/OpenTofu use `no-mistakes infra`; for Swift -use `no-mistakes swift`. Prefer `no-mistakes` over `rg` when a question spans ->2 workspace directories or >5 import hops; use `no-mistakes importers` for a +use `no-mistakes swift`. Prefer `no-mistakes` over `rg` when a question spans >2 +workspace directories or >5 import hops; use `no-mistakes importers` for a fast static-import caller list (use `dependents` for complete impact including dynamic and CommonJS imports). +The primary use-cases of `no-mistakes` is: + +1. Discovering impacted files and tests during planning +2. Running selected tests in PR CI to minimize CI costs +3. AST-based guardrails for your coding agents to minimize entropy and power the above use-cases + ## Why? -Most codebase intelligence tools create a database of your code, creates expensive vector embeddings, and has its own LLM layer. +Most codebase intelligence tools create a database of your code, creates expensive vector embeddings, and/or has its own LLM layer. There are many downsides with this strategy including cost, complexity, and difficulty working on many branches using worktrees at the same time. `no-mistakes` instead understands your code through AST-parsing. -No databases, no caching, just fast Rust code to understand what agents need from the codebase. +No databases, no caching, just fast Rust code to understand the codebase. +Yes, this is quite a huge undertaking to handle all cases, which is why this codebase is large with a lot of test fixtures. There are a few trade-offs with this approach: -1. Some code is difficult to understnad through AST-parsing, so `no-mistakes` includes rules that enforce AST-parsing-friendly coding. For example, Playwright test selectors should be simple strings - dynamically generated strings will not match well. -2. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship. An agent should verify if a relationship returned is true. -3. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes on a sample repository, but takes 1 second with `no-mistakes` via `no-mistakes test plan` and supports Playwright). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. +1. Some code is difficult to understnad through AST-parsing, so `no-mistakes` includes rules that enforce AST-parsing-friendly coding. For example, Playwright test selectors should be simple strings - dynamically generated strings will not match well, especially if you enable the "all Playwright test hooks must be covered by a Playwright test" rule. +1. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship. An agent should verify if a relationship returned is true. + 1. As such, some of the code is based on heuristics and may need fine-tuning. For example, there is some hardcoding to distinguish between an HTTP client vs. HTTP server, e.g. (`axios.get()` vs. `app = express(); app.get()`). +1. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes, but takes 1 second with `no-mistakes` via `no-mistakes test plan` and supports Playwright). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. ## Agent Workflows @@ -75,17 +83,13 @@ Local development from this repository: cargo run -p no-mistakes -- dependents src/utils.mts --format paths ``` -## Documentation +## Contributing -- [Documentation index](docs/README.md) -- [CLI commands](docs/cli/README.md) -- [Node/N-API guide](docs/node-api.md) -- [Configuration](docs/configuration/README.md) -- [Graph edge types](docs/graph-edges.md) -- [no-mistakes rules](docs/rules/README.md) -- [ESLint rules](docs/eslint-rules/README.md) -- [Agent guide](docs/agent-guide.md) -- [AST analysis behavior](docs/ast-analysis.md) +This repository is a huge token sink. Thus, contributions are welcomed. + +1. Please add test cases in `test-cases/` +2. Annotate which AI harness + model was used, Co-Authored-By is preferred +3. Maintain 99% project and patch test coverage ## Design Constraints @@ -99,8 +103,14 @@ cargo run -p no-mistakes -- dependents src/utils.mts --format paths - Explicit configuration: route roots, queue factories, test projects, and global fallback behavior are opt-in configuration, not inferred conventions. -## Link Lint +## Documentation -```sh -lychee --no-progress --exclude-path '^fixtures/' README.md 'docs/**/*.md' 'skills/**/*.md' 'packages/*/README.md' 'crates/*/README.md' CLAUDE.md -``` +- [Documentation index](docs/README.md) +- [CLI commands](docs/cli/README.md) +- [Node/N-API guide](docs/node-api.md) +- [Configuration](docs/configuration/README.md) +- [Graph edge types](docs/graph-edges.md) +- [no-mistakes rules](docs/rules/README.md) +- [ESLint rules](docs/eslint-rules/README.md) +- [Agent guide](docs/agent-guide.md) +- [AST analysis behavior](docs/ast-analysis.md) From d59447c26e207f22a91d9ca1446c7369f954e624 Mon Sep 17 00:00:00 2001 From: jongleberry Date: Mon, 20 Jul 2026 23:57:50 -0700 Subject: [PATCH 03/11] Update documentation section in README.md --- README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 481c0ea3f..412aa7b70 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,18 @@ Local development from this repository: cargo run -p no-mistakes -- dependents src/utils.mts --format paths ``` +## Documentation + +- [Documentation index](docs/README.md) +- [CLI commands](docs/cli/README.md) +- [Node/N-API guide](docs/node-api.md) +- [Configuration](docs/configuration/README.md) +- [Graph edge types](docs/graph-edges.md) +- [no-mistakes rules](docs/rules/README.md) +- [ESLint rules](docs/eslint-rules/README.md) +- [Agent guide](docs/agent-guide.md) +- [AST analysis behavior](docs/ast-analysis.md) + ## Contributing This repository is a huge token sink. Thus, contributions are welcomed. @@ -103,14 +115,3 @@ This repository is a huge token sink. Thus, contributions are welcomed. - Explicit configuration: route roots, queue factories, test projects, and global fallback behavior are opt-in configuration, not inferred conventions. -## Documentation - -- [Documentation index](docs/README.md) -- [CLI commands](docs/cli/README.md) -- [Node/N-API guide](docs/node-api.md) -- [Configuration](docs/configuration/README.md) -- [Graph edge types](docs/graph-edges.md) -- [no-mistakes rules](docs/rules/README.md) -- [ESLint rules](docs/eslint-rules/README.md) -- [Agent guide](docs/agent-guide.md) -- [AST analysis behavior](docs/ast-analysis.md) From b3f9f5a648f11ecc76fa0d2833dc8a377f5ebaac Mon Sep 17 00:00:00 2001 From: jongleberry Date: Tue, 21 Jul 2026 00:08:41 -0700 Subject: [PATCH 04/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 412aa7b70..dd3c9ad6a 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Yes, this is quite a huge undertaking to handle all cases, which is why this cod There are a few trade-offs with this approach: 1. Some code is difficult to understnad through AST-parsing, so `no-mistakes` includes rules that enforce AST-parsing-friendly coding. For example, Playwright test selectors should be simple strings - dynamically generated strings will not match well, especially if you enable the "all Playwright test hooks must be covered by a Playwright test" rule. -1. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship. An agent should verify if a relationship returned is true. +1. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship (unless it cannot be inferred through AST-parsing such as `import('./${someRandomFile}')`). An agent should verify if a relationship returned is true. 1. As such, some of the code is based on heuristics and may need fine-tuning. For example, there is some hardcoding to distinguish between an HTTP client vs. HTTP server, e.g. (`axios.get()` vs. `app = express(); app.get()`). 1. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes, but takes 1 second with `no-mistakes` via `no-mistakes test plan` and supports Playwright). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. From c7e4b8139ceb66dedcd8da0a26a15a4fa2a7ae4b Mon Sep 17 00:00:00 2001 From: jongleberry Date: Tue, 21 Jul 2026 00:12:42 -0700 Subject: [PATCH 05/11] Update README with support status for languages/tools Added support status for various languages and tools. --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index dd3c9ad6a..9bc71e79c 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,22 @@ This repository is a huge token sink. Thus, contributions are welcomed. 2. Annotate which AI harness + model was used, Co-Authored-By is preferred 3. Maintain 99% project and patch test coverage +## Support + +| Language/Framework/Tool | Status | +| -- | -- | +| TypeScript | Mature | +| `pnpm`, `npm`, `yarn`, `bun` | Supported, primarily tested using `pnpm` | +| `bullmq`, `glide-mq` | Mature, primarily tested for `glide-mq` | +| `vitest` | `vitest` is mature, `jest` has not been tested | +| .NET | Nascent | +| Swift | Nascent | +| Rust | Minimal | +| GitHub Actions | Minimal, planned | +| Terraform | Minimal | +| Go | Unsupported | +| Python | Unsupported | + ## Design Constraints - Local and deterministic: no services, databases, remote AI calls, or From d037b8332fd3ae71480c4e97ced1e2ae6e41dd29 Mon Sep 17 00:00:00 2001 From: jongleberry Date: Tue, 21 Jul 2026 00:13:15 -0700 Subject: [PATCH 06/11] Add Playwright support status to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9bc71e79c..b6f7d09ff 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ This repository is a huge token sink. Thus, contributions are welcomed. | `pnpm`, `npm`, `yarn`, `bun` | Supported, primarily tested using `pnpm` | | `bullmq`, `glide-mq` | Mature, primarily tested for `glide-mq` | | `vitest` | `vitest` is mature, `jest` has not been tested | +| `playwright` | Mature | | .NET | Nascent | | Swift | Nascent | | Rust | Minimal | From b1af00dc3b9c6f9df6fe7a09c9f4646e63d296ad Mon Sep 17 00:00:00 2001 From: jongleberry Date: Tue, 21 Jul 2026 00:13:48 -0700 Subject: [PATCH 07/11] Update README with Next framework status --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b6f7d09ff..e7927314b 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ This repository is a huge token sink. Thus, contributions are welcomed. | Language/Framework/Tool | Status | | -- | -- | | TypeScript | Mature | +| Next | Mature, other frameworks should work but are untested | | `pnpm`, `npm`, `yarn`, `bun` | Supported, primarily tested using `pnpm` | | `bullmq`, `glide-mq` | Mature, primarily tested for `glide-mq` | | `vitest` | `vitest` is mature, `jest` has not been tested | From dcd4029c5baaf77c164953e1a8aef7925998d377 Mon Sep 17 00:00:00 2001 From: jongleberry Date: Tue, 21 Jul 2026 03:04:37 -0700 Subject: [PATCH 08/11] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index e7927314b..ab6ddae60 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,14 @@ The primary use-cases of `no-mistakes` is: 2. Running selected tests in PR CI to minimize CI costs 3. AST-based guardrails for your coding agents to minimize entropy and power the above use-cases +Suppose you have the following dependency chain: + +> Backend `getPost(id)` -> Backend GET `/posts/:id` -> Next.js Fetch GET `/posts/:id` -> Next.js Page `/post/[id]` -> Playwright Test on `/post/[id]` + +During planning, `no-mistakes` will provide the full dependency chain to the agent in a single, fast, CLI command. +During CI testing, a `getPost()` change will select the relevant Playwright tests to run. +No embeddings, all determinstically. + ## Why? Most codebase intelligence tools create a database of your code, creates expensive vector embeddings, and/or has its own LLM layer. From 01deacfddc5ef12a822801b7c7a80392d6aaa9bf Mon Sep 17 00:00:00 2001 From: jongleberry Date: Sun, 26 Jul 2026 20:23:28 -0700 Subject: [PATCH 09/11] Update README.md --- README.md | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ab6ddae60..4c8ee9385 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,7 @@ > Slop Warning: this codebase is written by agents for agents. The API surface is sloppy, but it _works_. -Deterministic AST-based codebase intelligence for AI agents. - -`no-mistakes` answers structural questions about TypeScript, JavaScript, -React, Next.js, Playwright, queue, server-route, and Rust repository code -without running the application or calling an AI model. It is built for agents -that need small, reliable answers they can feed into follow-up edits and tests. - -**Core graph domain:** TypeScript and JavaScript. For CI-workflow analysis use -`no-mistakes ci`; for Terraform/OpenTofu use `no-mistakes infra`; for Swift -use `no-mistakes swift`. Prefer `no-mistakes` over `rg` when a question spans >2 -workspace directories or >5 import hops; use `no-mistakes importers` for a -fast static-import caller list (use `dependents` for complete impact including -dynamic and CommonJS imports). +Deterministic AST-based codebase intelligence and opinionated linting for AI agents. The primary use-cases of `no-mistakes` is: @@ -29,17 +17,38 @@ Suppose you have the following dependency chain: > Backend `getPost(id)` -> Backend GET `/posts/:id` -> Next.js Fetch GET `/posts/:id` -> Next.js Page `/post/[id]` -> Playwright Test on `/post/[id]` During planning, `no-mistakes` will provide the full dependency chain to the agent in a single, fast, CLI command. -During CI testing, a `getPost()` change will select the relevant Playwright tests to run. +During CI, a `getPost()` change will select the relevant Playwright tests to run. No embeddings, all determinstically. +To ensure that AST-parsing is reliable, many opinionated linting rules are included to avoid false positives. + +Additionally, since it already parses the entire AST tree, it includes opinionated linting rules based on anti-patterns written by agents. +Unlike tools like eslint/oxlint that only allow lint rules on a per-file basis, `no-mistakes` parses your entire codebase in memory and applies rules globally. +This is the origination of the name. + +Two biggest examples are the duplication of function names. + +```ts +// backend/controllers/users.mts +export function getCurrentUser (ctx) { + return UserService.getUserById(ctx.params.id) +} + +// backend/controllers/getCurrentUser.mts +export function getCurrentUser (ctx) { + return UserService.getUserById(ctx.params.id) +} +``` + +`no-mistakes` will throw if there are multiple definitions of `getCurrentUser` in a workspace. ## Why? -Most codebase intelligence tools create a database of your code, creates expensive vector embeddings, and/or has its own LLM layer. +Most codebase intelligence tools create a database of your code, slowly create vector embeddings, and/or has its own LLM layer. There are many downsides with this strategy including cost, complexity, and difficulty working on many branches using worktrees at the same time. `no-mistakes` instead understands your code through AST-parsing. No databases, no caching, just fast Rust code to understand the codebase. -Yes, this is quite a huge undertaking to handle all cases, which is why this codebase is large with a lot of test fixtures. +Yes, this is quite a huge undertaking to handle all cases, which is why this codebase is large. There are a few trade-offs with this approach: From b6de1b91b64d20944e896202a6536686d579a7e4 Mon Sep 17 00:00:00 2001 From: jongleberry Date: Sat, 1 Aug 2026 03:06:58 -0700 Subject: [PATCH 10/11] Update README.md --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4c8ee9385..ccf1e44dd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Deterministic AST-based codebase intelligence and opinionated linting for AI agents. -The primary use-cases of `no-mistakes` is: +The primary use-cases of `no-mistakes` are: 1. Discovering impacted files and tests during planning 2. Running selected tests in PR CI to minimize CI costs @@ -23,7 +23,7 @@ To ensure that AST-parsing is reliable, many opinionated linting rules are inclu Additionally, since it already parses the entire AST tree, it includes opinionated linting rules based on anti-patterns written by agents. Unlike tools like eslint/oxlint that only allow lint rules on a per-file basis, `no-mistakes` parses your entire codebase in memory and applies rules globally. -This is the origination of the name. +This is the origination of the name as it begun as a large number of custom cross-file linting rules. Two biggest examples are the duplication of function names. @@ -39,9 +39,10 @@ export function getCurrentUser (ctx) { } ``` -`no-mistakes` will throw if there are multiple definitions of `getCurrentUser` in a workspace. +`no-mistakes` will throw if there are multiple definitions of `getCurrentUser` in a workspace, +a common mistakes agents commonly make when an existing function did not show up in search. -## Why? +## Why AST-based? Most codebase intelligence tools create a database of your code, slowly create vector embeddings, and/or has its own LLM layer. There are many downsides with this strategy including cost, complexity, and difficulty working on many branches using worktrees at the same time. @@ -53,9 +54,10 @@ Yes, this is quite a huge undertaking to handle all cases, which is why this cod There are a few trade-offs with this approach: 1. Some code is difficult to understnad through AST-parsing, so `no-mistakes` includes rules that enforce AST-parsing-friendly coding. For example, Playwright test selectors should be simple strings - dynamically generated strings will not match well, especially if you enable the "all Playwright test hooks must be covered by a Playwright test" rule. -1. `no-mistakes` is best effort, with high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship (unless it cannot be inferred through AST-parsing such as `import('./${someRandomFile}')`). An agent should verify if a relationship returned is true. - 1. As such, some of the code is based on heuristics and may need fine-tuning. For example, there is some hardcoding to distinguish between an HTTP client vs. HTTP server, e.g. (`axios.get()` vs. `app = express(); app.get()`). -1. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes, but takes 1 second with `no-mistakes` via `no-mistakes test plan` and supports Playwright). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. +1. `no-mistakes` is best effort a goal of high recall and low precision, meaning it may return wrong information/relationships, but should never miss a relationship (unless it cannot be inferred through AST-parsing such as `import('./${someRandomFile}')`). An agent should verify if a relationship returned is true. + 1. As such, some of the code is based on heuristics and may need fine-tuning. For example, there is some hardcoding to distinguish between an HTTP client vs. HTTP server, e.g. (`axios.get()` vs. `app = express(); app.get()`), (though with a well written codebase, this should not be an issue because they should be written in completely separate files and you should specify which files your services/routes are defined to narrow the search). +1. High CPU usage - parsing your repository on-demand may cause high-CPU usage, but may be significantly faster than other methods (e.g. `vitest related` takes 2 minutes, but takes 1 second with `no-mistakes` via `no-mistakes test plan`, supports Playwright, and only using 10/28 cores on an Apple Mac Studio M3 Ultra). This may become a bottleneck when working on multiple worktrees at once, but `no-mistakes` includes a locking mechanism to not run concurrently. +1. Your code must be written in such a way to make it AST-friendly such as preferring many small files over large ones (since many relations are file-based) and having little abstractions and interdependencies as this blows up your dependency graph. ## Agent Workflows @@ -117,7 +119,7 @@ cargo run -p no-mistakes -- dependents src/utils.mts --format paths This repository is a huge token sink. Thus, contributions are welcomed. 1. Please add test cases in `test-cases/` -2. Annotate which AI harness + model was used, Co-Authored-By is preferred +2. Annotate which AI harness + model was used, `Co-Authored-By` is preferred 3. Maintain 99% project and patch test coverage ## Support From ad0a446d82b31a7bccab5bc4708e3ffed1b7f021 Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Sat, 22 Aug 2026 19:45:16 -0700 Subject: [PATCH 11/11] fix: allow README words worktrees and bullmq in cspell The human README uses both spellings, and cspell only had the singular worktree. Co-authored-by: Cursor --- cspell.config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cspell.config.yaml b/cspell.config.yaml index bd4734519..26ac1c8f2 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -18,6 +18,7 @@ words: - aspnet - asynq - Basenames + - bullmq - callees - callsite - callsites @@ -102,4 +103,5 @@ words: - vitest - walkdir - worktree + - worktrees - zeitwerk