Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,15 @@ judge rationales, and reproduce instructions.

## Supported languages

Supports **11 language families** with semantic chunking (8 benchmarked):
Supports **12 language families** with semantic chunking (9 benchmarked):

| Language | Parser | Extensions | Benchmark status |
| ---------------- | ----------- | ----------------------------------------- | --------------------------------------------- |
| Go | Native AST | `.go` | Benchmarked: -12% cost, Good quality |
| Python | tree-sitter | `.py` | Benchmarked: Perfect quality, -36% tokens |
| TypeScript / TSX | tree-sitter | `.ts`, `.tsx` | Benchmarked: -64% tokens, -33% time |
| JavaScript / JSX | tree-sitter | `.js`, `.jsx`, `.mjs` | Benchmarked: -66% tokens, -53% time |
| Dart | tree-sitter | `.dart` | Benchmarked: -76% cost, -82% tokens, -79% time |
| Rust | tree-sitter | `.rs` | Benchmarked: -39% cost, -34% time |
| Ruby | tree-sitter | `.rb` | Benchmarked: -24% cost, -11% time |
| PHP | tree-sitter | `.php` | Benchmarked: -59% tokens, -34% time |
Expand All @@ -175,7 +176,7 @@ Supports **11 language families** with semantic chunking (8 benchmarked):

Go uses the native Go AST parser for the most precise chunks. All other
languages use tree-sitter grammars. See [docs/BENCHMARKS.md](docs/BENCHMARKS.md)
for all 8 per-language benchmark deep dives.
for all 9 per-language benchmark deep dives.

## Configuration

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"rating":"Good","files_correct":true,"logic_equivalent":false}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Rating: Good

The candidate patch correctly fixes the core RFC violation by removing the `content-length: '0'` override, allowing the original content-length to pass through unchanged, and only strips the body. However, it uses a different approach than the gold patch: it keeps the `createMiddleware` structure (which has known issues with async handlers) rather than converting to a proper `Handler`-wrapping function. The candidate also adds a standalone test instead of enhancing the existing HEAD tests, but the test itself correctly validates both the content-length preservation and empty body requirements.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"cost_usd": 0.6341989499999998,
"duration_ms": 246069,
"input_tokens": 439,
"cache_read": 4126087,
"cache_created": 91777,
"output_tokens": 21286
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
diff --git a/pkgs/shelf_router/lib/src/router.dart b/pkgs/shelf_router/lib/src/router.dart
index 720d3c3..8613f01 100644
--- a/pkgs/shelf_router/lib/src/router.dart
+++ b/pkgs/shelf_router/lib/src/router.dart
@@ -58,11 +58,12 @@ extension RouterParams on Request {
}
}

-/// Middleware to remove body from request.
+/// Middleware to remove body from HEAD requests.
+///
+/// Per RFC 9110 Section 9.3.2, HEAD and GET responses should be identical
+/// except for the body. The content-length header should reflect the size of
+/// the body that WOULD have been returned by a GET request.
final _removeBody = createMiddleware(responseHandler: (r) {
- if (r.headers.containsKey('content-length')) {
- r = r.change(headers: {'content-length': '0'});
- }
return r.change(body: <int>[]);
});

diff --git a/pkgs/shelf_router/test/router_test.dart b/pkgs/shelf_router/test/router_test.dart
index fdffa51..cb19c9c 100644
--- a/pkgs/shelf_router/test/router_test.dart
+++ b/pkgs/shelf_router/test/router_test.dart
@@ -204,4 +204,24 @@ void main() {
final b2 = await Router.routeNotFound.readAsString();
expect(b2, b1);
});
+
+ test('HEAD request should preserve content-length header per RFC 9110', () async {
+ var app = Router();
+
+ app.get('/hello', (Request request) {
+ // Explicitly set content-length header
+ return Response.ok('hello-world',
+ headers: {'content-length': '11'});
+ });
+
+ // Create a request with HEAD method
+ final headRequest = Request('HEAD', Uri.parse('http://localhost/hello'));
+ final headResponse = await app(headRequest);
+
+ // Per RFC 9110 Section 9.3.2, the content-length should be preserved
+ expect(headResponse.headers['content-length'], '11');
+
+ // Verify that the body is empty
+ expect(await headResponse.readAsString(), isEmpty);
+ });
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SessionEnd hook [_R="${CLAUDE_PLUGIN_ROOT}"; [ -z "$_R" ] && _R="$HOME/.claude/plugins/marketplaces/thedotmack/plugin"; node "$_R/scripts/bun-runner.js" "$_R/scripts/worker-service.cjs" hook claude-code session-complete] failed: Hook cancelled
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
00:00 +0: loading test/router_test.dart 00:00 +0: get sync/async handler 00:00 +1: get sync/async handler 00:00 +1: params 00:00 +2: params 00:00 +2: params by arguments 00:00 +3: params by arguments 00:00 +3: mount(Router) 00:00 +4: mount(Router) 00:00 +4: mount(Handler) with middleware 00:00 +5: mount(Handler) with middleware 00:00 +5: mount(Router) does not require a trailing slash 00:00 +6: mount(Router) does not require a trailing slash 00:00 +6: responds with 404 if no handler matches 00:00 +7: responds with 404 if no handler matches 00:00 +7: can invoke custom handler if no route matches 00:00 +8: can invoke custom handler if no route matches 00:00 +8: can call Router.routeNotFound.read multiple times 00:00 +9: can call Router.routeNotFound.read multiple times 00:00 +9: HEAD request should preserve content-length header per RFC 9110 00:00 +10: HEAD request should preserve content-length header per RFC 9110 00:00 +10: All tests passed!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"rating":"Good","files_correct":false,"logic_equivalent":false}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Rating: Good

The candidate patch correctly removes the `content-length: '0'` override, which is the core RFC violation. However, it only modifies `router.dart` and doesn't update the tests to verify the content-length behavior, whereas the gold patch also refactors `_removeBody` from `createMiddleware` to a proper `Handler` wrapper (which handles both sync and async responses correctly) and adds comprehensive test assertions. The candidate's approach of keeping `createMiddleware` while just removing the bad line is a simpler but still valid fix that preserves correct content-length headers.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"cost_usd": 0.15332435000000003,
"duration_ms": 50922,
"input_tokens": 126,
"cache_read": 663146,
"cache_created": 54059,
"output_tokens": 3862
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/pkgs/shelf_router/lib/src/router.dart b/pkgs/shelf_router/lib/src/router.dart
index 720d3c3..d68627a 100644
--- a/pkgs/shelf_router/lib/src/router.dart
+++ b/pkgs/shelf_router/lib/src/router.dart
@@ -60,9 +60,6 @@ extension RouterParams on Request {

/// Middleware to remove body from request.
final _removeBody = createMiddleware(responseHandler: (r) {
- if (r.headers.containsKey('content-length')) {
- r = r.change(headers: {'content-length': '0'});
- }
return r.change(body: <int>[]);
});

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
00:00 +0: loading test/router_test.dart 00:00 +0: get sync/async handler 00:00 +1: get sync/async handler 00:00 +1: params 00:00 +2: params 00:00 +2: params by arguments 00:00 +3: params by arguments 00:00 +3: mount(Router) 00:00 +4: mount(Router) 00:00 +4: mount(Handler) with middleware 00:00 +5: mount(Handler) with middleware 00:00 +5: mount(Router) does not require a trailing slash 00:00 +6: mount(Router) does not require a trailing slash 00:00 +6: responds with 404 if no handler matches 00:00 +7: responds with 404 if no handler matches 00:00 +7: can invoke custom handler if no route matches 00:00 +8: can invoke custom handler if no route matches 00:00 +8: can call Router.routeNotFound.read multiple times 00:00 +9: can call Router.routeNotFound.read multiple times 00:00 +9: All tests passed!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# SWE-Bench Detail Report

Generated: 2026-03-27 18:08 UTC

---

## dart-hard [dart]

**Issue:** shelf_router should NOT modify the content-length per RFC

> The shelf_router `_removeBody` middleware incorrectly sets content-length to 0 for HEAD requests.
>
> Per RFC 9110 Section 9.3.2, HEAD and GET should be identical except for the lack of body content. The content-length header should reflect the size of the body that WOULD have been returned by a GET request, not 0.
>
> Currently, when a HEAD request is made, the router's _removeBody middleware replaces the content-length with '0', which violates the RFC. The middleware should only strip the body content while preserving the original content-length header.
>
> To reproduce:
> 1. Create a Router with a handler that returns a response with a body
> 2. Send a HEAD request to that route
> 3. Observe that content-length is set to 0 instead of the actual body length
>
> Expected: content-length should match what GET would return (e.g., 11 for 'hello-world')
> Actual: content-length is set to 0

### Metrics

| Scenario | Duration | Input Tok | Cache Read | Output Tok | Cost |
|----------|----------|-----------|------------|------------|------|
| **baseline** | 246.1s | 439 | 4126087 | 21286 | $0.6342 |
| **with-lumen** | 50.9s | 126 | 663146 | 3862 | $0.1533 |

### baseline

**Rating: Good**

```diff
diff --git a/pkgs/shelf_router/lib/src/router.dart b/pkgs/shelf_router/lib/src/router.dart
index 720d3c3..8613f01 100644
--- a/pkgs/shelf_router/lib/src/router.dart
+++ b/pkgs/shelf_router/lib/src/router.dart
@@ -58,11 +58,12 @@ extension RouterParams on Request {
}
}

-/// Middleware to remove body from request.
+/// Middleware to remove body from HEAD requests.
+///
+/// Per RFC 9110 Section 9.3.2, HEAD and GET responses should be identical
+/// except for the body. The content-length header should reflect the size of
+/// the body that WOULD have been returned by a GET request.
final _removeBody = createMiddleware(responseHandler: (r) {
- if (r.headers.containsKey('content-length')) {
- r = r.change(headers: {'content-length': '0'});
- }
return r.change(body: <int>[]);
});

diff --git a/pkgs/shelf_router/test/router_test.dart b/pkgs/shelf_router/test/router_test.dart
index fdffa51..cb19c9c 100644
--- a/pkgs/shelf_router/test/router_test.dart
+++ b/pkgs/shelf_router/test/router_test.dart
@@ -204,4 +204,24 @@ void main() {
final b2 = await Router.routeNotFound.readAsString();
expect(b2, b1);
});
+
+ test('HEAD request should preserve content-length header per RFC 9110', () async {
+ var app = Router();
+
+ app.get('/hello', (Request request) {
+ // Explicitly set content-length header
+ return Response.ok('hello-world',
+ headers: {'content-length': '11'});
+ });
+
+ // Create a request with HEAD method
+ final headRequest = Request('HEAD', Uri.parse('http://localhost/hello'));
+ final headResponse = await app(headRequest);
+
+ // Per RFC 9110 Section 9.3.2, the content-length should be preserved
+ expect(headResponse.headers['content-length'], '11');
+
+ // Verify that the body is empty
+ expect(await headResponse.readAsString(), isEmpty);
+ });
}
```

### with-lumen

**Rating: Good**

```diff
diff --git a/pkgs/shelf_router/lib/src/router.dart b/pkgs/shelf_router/lib/src/router.dart
index 720d3c3..d68627a 100644
--- a/pkgs/shelf_router/lib/src/router.dart
+++ b/pkgs/shelf_router/lib/src/router.dart
@@ -60,9 +60,6 @@ extension RouterParams on Request {

/// Middleware to remove body from request.
final _removeBody = createMiddleware(responseHandler: (r) {
- if (r.headers.containsKey('content-length')) {
- r = r.change(headers: {'content-length': '0'});
- }
return r.change(body: <int>[]);
});

```


Loading
Loading