matrix send and matrix read #100

Open
claude-code wants to merge 8 commits from claude-code/matrix-send-read into main
Collaborator

Two commands for agents: matrix send writes a plain-text message into a room, matrix read prints its decrypted messages; both through the running relay or a client of their own.

See doc/prs/2026-10-23-PR#100-matrix-send-read.md.

🤖 Generated with Claude Code

Two commands for agents: `matrix send` writes a plain-text message into a room, `matrix read` prints its decrypted messages; both through the running relay or a client of their own. See `doc/prs/2026-10-23-PR#100-matrix-send-read.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-code added 1 commit 2026-10-23 18:38:22 +02:00
PR document: matrix send and matrix read
werkator build succeeded after 01:07
werkator/dependencies build succeeded after 00:19
b8b7f2390a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi added 1 commit 2026-10-23 18:43:03 +02:00
matrix send and matrix read, also through control.sock
werkator build failed after 04:32
werkator/dependencies build succeeded after 00:16
81a94c1fd2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi added 1 commit 2026-10-23 18:43:38 +02:00
PR document, README, risk analysis and plan for matrix send and read
werkator build failed after 04:36
werkator/dependencies build succeeded after 00:18
2351ecb21e
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi added 1 commit 2026-10-23 18:52:36 +02:00
matrix read: the reading of the timeline without a client, under the Mutation-CRAP limit
werkator build succeeded after 05:00
werkator/dependencies build succeeded after 00:23
ab304ca349
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi added 1 commit 2026-10-23 19:05:13 +02:00
PR document: the test against the real rooms
werkator build succeeded after 05:55
werkator/dependencies build succeeded after 00:30
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; review requested from mi; merge scheduled for when the checks succeed
ai-review/gate build succeeded after 09:17
254fdc9321
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude-code marked the pull request as ready for review 2026-10-23 19:11:58 +02:00
Collaborator
🟠 werkrevisor ORANGE for 254fdc9, superseded by the result for f54ad51

🟠 werkrevisor: ORANGE / FINDINGS

Change kind: feature_with_modified_tests.

Reasons

  • ORANGE changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.81)
  • ORANGE 3 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReading.kt:23, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:48-50, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/Main.kt:317-318
  • YELLOW tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement
  • YELLOW change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes
  • YELLOW spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 hard_to_read (0.53 > yellow_above = 0.5)
  • YELLOW spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 more_than_one_aspect (0.68 > yellow_above = 0.6)
  • YELLOW spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 implementation_details (0.64 > yellow_above = 0.6)
  • YELLOW spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 given_when_then_misused (0.79 > yellow_above = 0.6)
  • hint 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint model recommends changes before merge
  • hint model rates the risk as high (advisory: Jev judged every changed file)

Findings

  1. [high] Build Failure at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReading.kt:23, ORANGE, as a line comment

  2. [high] Stale Cursor at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:48-50, ORANGE, as a line comment

  3. [medium] Extra Arguments at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/Main.kt:317-318, ORANGE, as a line comment

Classifier

Unit Question Problem Confidence Verdict
doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 hard_to_read 0.53 0.52 YELLOW
doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 more_than_one_aspect 0.68 – YELLOW
doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 implementation_details 0.64 – YELLOW
doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 given_when_then_misused 0.79 – YELLOW

11 of 12 units passed all questions (1 PR document(s)).
3 answers ignored because of a confidence below [classifier] min_confidence.

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 61592, calls 1, tokens in 59990 / out 37479 (reasoning included in out), duration 554.4 s, cost 0.0629 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10330, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 6813, cost 0.0003 USD, build file judge `jev-1.14.0` calls 16, tokens in 28300, cost 0.0012 USD, phases: path_judge 0.7 s, classifier 0.5 s, context 0.8 s, model_review 551.6 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).
Reviewed head `254fdc93212ef11ed416a878a7ac89832b133e07` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2.
<!-- werkrevisor:254fdc93212ef11ed416a878a7ac89832b133e07 --> <!-- werkrevisor-verdict:ORANGE --> <!-- werkrevisor-blocks:bcf7660a2d227efef94b870c8d874da9,90753c6412c0ff8198b0a8ca14d88292,6194907bf7f7a67de7fc1b36797bf92f,4e95c24b86e0e9c3dd0aacbd6f7a96d3,05a2f6ef6ec9e967d5d1b2eac8c7cb45,ecee0f663c4fce1f60b0afb5b07278b0,0e9f13d59704543605a912c3283b4e41,f50c020cc567c80fc7e89a1fc8ecf277,bad20a8d008888776cb9e61c074e0017,4f3d57dcc7de387fcf6ef51bca9505dd,2b71fae8113e6d5ca77ba1e6490c1f50,3c5c5970bc2c20a9a3596516487151ae,8065fcf2e8fa75a0e23bf6f8c441513b,5dd085ff1471653a9ae1af312e62696c,cc437211086f304c244b7cd843d463d6,52bf7eb7f90f4c51a1a4d3df516c0597,d8ee706b85d2b93b402edb06d79a46e5,24d75064fe90e2bcfb2647c8cd741e6c,1b1a23a5ea1e59ef43fe2e5666215384,253f89ea481a9c1d4dcc33bb4a9a0c79,e48974b700759e6876bc4554915f5703,6fb2246a143cc074aecbf6445e048f74,83d01d3fc8ff665883d8be0f100b5ca5,8886449a39476ab90246c4a80ea66496,12c8ca81c1bebbd7965bb9eb618d58a7,a7939e3b20c1d962c9bfac626eaac445,0bdd7a6b3a3a36f822323c8127047e05,c3bee07eab2d43bad35397dda3126a2f,a6bf5f93a14add230e3675e6ea38d5f5,4065b773bf1fb988087b16ff49a851ba,6bda92971b9c0c4527927db3ad3a62a0,e24d89a08e3edc6566978e6a468f8452,c19dd8cdfc8a7c0edbda6a5b7a1fa9d2,286f7cae870f46be0414504f5edf6ce9,540a7d7d5e46a636bfb77c3f48a0a295,822f156a0c9f820d8d199165b78c0812,935c9b34278f3735e2fabeab72a15fd6,72bb3a0a35e5f8cde077571ac59efb23,cea550f3d1cccd347fa3b3db996fb874,0499287720e2b901062ecd215c06e24a,00c4dfdce7cac4429363974fb6fd89ec,a239074999066d29d97d815fde3c2e07,6cfa62f9c968417d938aab637479121b,17e69f3adb49c5b79f5746ff66cc9791,eb022560002c138ae77bd98c1f2e0be4,cdb647cd74997d341b8bf02b9dbff1fb,7912f2f388dfa08508eb5fabc30056dd,f89d0edf491d27be9b68f2c287fbf7eb,7ec03a764a28a0bc5156f87abbce4a82,b84370c3f1b8e91bb7061e8163302a2f,11495aa92fe55d4a605d0a14a1d30c2a,b2422a4248efd9e1173736a52c9c5e65,e367ba16f266660d5fc47368fa998d55,eb04647909410d239c7049b1d1eeba6f,fe0da9d6ec333b641d6cdda448d03dec,a6dcdaa660385019285fe2bac28de69d,3f8d2ab32e5c34e0cfad96a7da7d5e73,02267513e38604ec8f3e60f4143d81ae,ac8086e5faec789cdabe63bd3a754ce8,d2bc7a09a3026c987c242889051e8755,2affc77b864cc8bf3adcf38008675d03,7ed00eda0f32c80d79f09343ef8d1c1f --> <!-- werkrevisor-folded --> <details><summary>🟠 werkrevisor ORANGE for <code>254fdc9</code>, superseded by <a href="http://git.javagil.de/mi/werkregie/pulls/100#issuecomment-7510">the result for <code>f54ad51</code></a></summary> ## 🟠 werkrevisor: ORANGE / FINDINGS Change kind: `feature_with_modified_tests`. ### Reasons - **ORANGE** changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.81) - **ORANGE** 3 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReading.kt:23, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:48-50, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/Main.kt:317-318 - **YELLOW** tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement - **YELLOW** change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes - **YELLOW** spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 hard_to_read (0.53 > yellow_above = 0.5) - **YELLOW** spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 more_than_one_aspect (0.68 > yellow_above = 0.6) - **YELLOW** spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 implementation_details (0.64 > yellow_above = 0.6) - **YELLOW** spec: doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 given_when_then_misused (0.79 > yellow_above = 0.6) - **hint** 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** model recommends changes before merge - **hint** model rates the risk as high (advisory: Jev judged every changed file) ### Findings 1. **[high] Build Failure** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReading.kt:23`, ORANGE, as a line comment 2. **[high] Stale Cursor** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:48-50`, ORANGE, as a line comment 3. **[medium] Extra Arguments** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/Main.kt:317-318`, ORANGE, as a line comment ### Classifier | Unit | Question | Problem | Confidence | Verdict | |---|---|---|---|---| | doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 | hard_to_read | 0.53 | 0.52 | YELLOW | | doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 | more_than_one_aspect | 0.68 | – | YELLOW | | doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 | implementation_details | 0.64 | – | YELLOW | | doc/prs/2026-10-23-PR#100-matrix-send-read.md Scenario#100.05 | given_when_then_misused | 0.79 | – | YELLOW | 11 of 12 units passed all questions (1 PR document(s)). 3 answers ignored because of a confidence below [classifier] min_confidence. <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 61592, calls 1, tokens in 59990 / out 37479 (reasoning included in out), duration 554.4 s, cost 0.0629 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10330, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 6813, cost 0.0003 USD, build file judge `jev-1.14.0` calls 16, tokens in 28300, cost 0.0012 USD, phases: path_judge 0.7 s, classifier 0.5 s, context 0.8 s, model_review 551.6 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).<br> Reviewed head `254fdc93212ef11ed416a878a7ac89832b133e07` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2. </sub> </details>
ai-reviewer left a comment
Collaborator

werkrevisor: ORANGE / FINDINGS for 254fdc93212ef11ed416a878a7ac89832b133e07.
The result comment of werkrevisor holds the details.

werkrevisor: ORANGE / FINDINGS for `254fdc93212ef11ed416a878a7ac89832b133e07`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:254fdc93212ef11ed416a878a7ac89832b133e07 -->
@@ -286,0 +314,4 @@
val usage = "matrix send --room RAUM TEXT|-"
fun given(value: String?) = value?.takeIf { it.isNotBlank() } ?: throw UsageError(usage)
val room = given(invocation.option("--room", usage))
val text = given(invocation.arguments.removeFirstOrNull())
Collaborator

[medium] Extra Arguments (werkrevisor)

ORANGE; Jev: real 0.82, severity 2.9 of 3

Only the first positional argument is consumed, and remaining arguments are never validated. An unquoted message such as Build is green therefore sends only Build and reports success instead of rejecting the wrong call. Reject leftover arguments before sending so the command exits with its usage error rather than delivering a partial message.

**[medium] Extra Arguments** (werkrevisor) ORANGE; Jev: real 0.82, severity 2.9 of 3 Only the first positional argument is consumed, and remaining arguments are never validated. An unquoted message such as `Build is green` therefore sends only `Build` and reports success instead of rejecting the wrong call. Reject leftover arguments before sending so the command exits with its usage error rather than delivering a partial message.
Author
Collaborator

Fixed in f54ad51: matrix send refuses more than one text argument with its usage, exit code 2. Test: MainTest "matrix send needs room and text, none of them blank".

Fixed in `f54ad51`: `matrix send` refuses more than one text argument with its usage, exit code 2. Test: MainTest "matrix send needs room and text, none of them blank".
claude-code marked this conversation as resolved
@@ -0,0 +45,4 @@
reached = MatrixReading.reached(event.event.id.full, Instant.ofEpochMilli(event.event.originTimestamp), request)
if (!reached && candidate(event)) found += flow
}
check(reached || request.afterEvent == null || found.size == request.limit) {
Collaborator

[high] Stale Cursor (werkrevisor)

ORANGE; Jev: real 0.71, severity 3.0 of 3

The found.size == request.limit branch succeeds without confirming that afterEvent was reached. In an active room, matrix read --since $typo --limit 20 therefore returns the newest 20 messages successfully, silently skipping the interval for an incremental reader. This also contradicts the PR document's guarantee that an event ID outside the last 500 events fails; keep scanning to locate the cursor and fail if it is absent.

**[high] Stale Cursor** (werkrevisor) ORANGE; Jev: real 0.71, severity 3.0 of 3 The `found.size == request.limit` branch succeeds without confirming that `afterEvent` was reached. In an active room, `matrix read --since $typo --limit 20` therefore returns the newest 20 messages successfully, silently skipping the interval for an incremental reader. This also contradicts the PR document's guarantee that an event ID outside the last 500 events fails; keep scanning to locate the cursor and fail if it is absent.
Author
Collaborator

Fixed in f54ad51: with --since EVENT_ID the reading looks for the event beyond the limit and fails if it is not among the last 500 events; it keeps the newest limit messages after it. Test: MatrixReaderTest "an event to start after that the room does not show ends the command, also beyond the limit".

Fixed in `f54ad51`: with `--since EVENT_ID` the reading looks for the event beyond the limit and fails if it is not among the last 500 events; it keeps the newest `limit` messages after it. Test: MatrixReaderTest "an event to start after that the room does not show ends the command, also beyond the limit".
claude-code marked this conversation as resolved
@@ -0,0 +20,4 @@
/** The reading of [room]; [since] is an event ID or a time, and with it the limit is as far as a reading goes back. */
fun request(room: String, since: String?, limit: Int?, zone: ZoneId): ReadRequest {
val afterEvent = since?.takeIf { it.startsWith("$") }
Collaborator

[high] Build Failure (werkrevisor)

ORANGE; Jev: real 0.91, severity 2.7 of 3

startsWith("$") is invalid Kotlin syntax because the dollar sign starts a string template. This prevents the project and the new tests from compiling. Use startsWith('$') or escape the literal dollar sign.

**[high] Build Failure** (werkrevisor) ORANGE; Jev: real 0.91, severity 2.7 of 3 `startsWith("$")` is invalid Kotlin syntax because the dollar sign starts a string template. This prevents the project and the new tests from compiling. Use `startsWith('$')` or escape the literal dollar sign.
Author
Collaborator

Not a finding: in Kotlin a $ that no identifier or { follows is a literal, so "$" compiles. The build of 254fdc9 is green, with MatrixReadingTest and MainTest using --since $e. No change.

Not a finding: in Kotlin a `$` that no identifier or `{` follows is a literal, so `"$"` compiles. The build of `254fdc9` is green, with `MatrixReadingTest` and `MainTest` using `--since $e`. No change.
claude-code marked this conversation as resolved
ai-reviewer scheduled this pull request to auto merge when all checks succeed 2026-10-23 19:21:28 +02:00
ai-reviewer requested review from mi 2026-10-23 19:21:28 +02:00
mi added 1 commit 2026-10-23 19:27:42 +02:00
matrix read looks for --since beyond the limit, matrix send refuses an unquoted text, Scenario#100.05 of one aspect
werkator build succeeded after 07:33
werkator/dependencies build succeeded after 00:34
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ai-review/gate build succeeded after 10:04
f54ad51ef2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
🟠 werkrevisor ORANGE for f54ad51, superseded by the result for 751fdd5

🟠 werkrevisor: ORANGE / FINDINGS

Change kind: feature_with_modified_tests.

Reasons

  • ORANGE changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.83)
  • ORANGE 3 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-54, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:61-64, doc/prs/2026-10-23-PR#100-matrix-send-read.md:37
  • YELLOW tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement
  • YELLOW change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes
  • hint 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint model recommends changes before merge
  • hint model rates the risk as high (advisory: Jev judged every changed file)

Findings

  1. [high] Encrypted reaction at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-54, ORANGE, as a line comment

  2. [medium] Legacy Olm at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:61-64, ORANGE, as a line comment

  3. [medium] Event ID at doc/prs/2026-10-23-PR#100-matrix-send-read.md:37, ORANGE, as a line comment

Classifier

12 of 12 units passed all questions (1 PR document(s)).
2 answers ignored because of a confidence below [classifier] min_confidence.

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 61721, calls 1, tokens in 60119 / out 43536 (reasoning included in out), duration 599.6 s, cost 0.0702 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10452, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 6471, cost 0.0003 USD, build file judge `jev-1.14.0` calls 16, tokens in 28413, cost 0.0012 USD, phases: path_judge 0.8 s, classifier 0.7 s, context 0.9 s, model_review 595.6 s, finding_judge 0.4 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).
Reviewed head `f54ad51ef28e05b8b34d62bedcb3ab73247ba142` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2.
<!-- werkrevisor:f54ad51ef28e05b8b34d62bedcb3ab73247ba142 --> <!-- werkrevisor-verdict:ORANGE --> <!-- werkrevisor-blocks:bcf7660a2d227efef94b870c8d874da9,90753c6412c0ff8198b0a8ca14d88292,6194907bf7f7a67de7fc1b36797bf92f,4e95c24b86e0e9c3dd0aacbd6f7a96d3,05a2f6ef6ec9e967d5d1b2eac8c7cb45,ecee0f663c4fce1f60b0afb5b07278b0,0e9f13d59704543605a912c3283b4e41,f50c020cc567c80fc7e89a1fc8ecf277,bbc20050497d7ae157cbc5e9e8caf638,4f3d57dcc7de387fcf6ef51bca9505dd,2b71fae8113e6d5ca77ba1e6490c1f50,3c5c5970bc2c20a9a3596516487151ae,8065fcf2e8fa75a0e23bf6f8c441513b,5dd085ff1471653a9ae1af312e62696c,cc437211086f304c244b7cd843d463d6,52bf7eb7f90f4c51a1a4d3df516c0597,d8ee706b85d2b93b402edb06d79a46e5,24d75064fe90e2bcfb2647c8cd741e6c,1b1a23a5ea1e59ef43fe2e5666215384,253f89ea481a9c1d4dcc33bb4a9a0c79,e48974b700759e6876bc4554915f5703,6fb2246a143cc074aecbf6445e048f74,83d01d3fc8ff665883d8be0f100b5ca5,8886449a39476ab90246c4a80ea66496,12c8ca81c1bebbd7965bb9eb618d58a7,a7939e3b20c1d962c9bfac626eaac445,0bdd7a6b3a3a36f822323c8127047e05,c3bee07eab2d43bad35397dda3126a2f,a6bf5f93a14add230e3675e6ea38d5f5,4065b773bf1fb988087b16ff49a851ba,6bda92971b9c0c4527927db3ad3a62a0,e24d89a08e3edc6566978e6a468f8452,c19dd8cdfc8a7c0edbda6a5b7a1fa9d2,286f7cae870f46be0414504f5edf6ce9,540a7d7d5e46a636bfb77c3f48a0a295,0bc2f4ab1766daacd711d373d1f6b702,935c9b34278f3735e2fabeab72a15fd6,72bb3a0a35e5f8cde077571ac59efb23,cea550f3d1cccd347fa3b3db996fb874,0499287720e2b901062ecd215c06e24a,00c4dfdce7cac4429363974fb6fd89ec,a239074999066d29d97d815fde3c2e07,a7f7f5e758543d732fb2140841deae1a,17e69f3adb49c5b79f5746ff66cc9791,eb022560002c138ae77bd98c1f2e0be4,cdb647cd74997d341b8bf02b9dbff1fb,7912f2f388dfa08508eb5fabc30056dd,f89d0edf491d27be9b68f2c287fbf7eb,7ec03a764a28a0bc5156f87abbce4a82,b84370c3f1b8e91bb7061e8163302a2f,11495aa92fe55d4a605d0a14a1d30c2a,b2422a4248efd9e1173736a52c9c5e65,e367ba16f266660d5fc47368fa998d55,eb04647909410d239c7049b1d1eeba6f,20035056a4fb8d96fa04e25e7bc5f871,a6dcdaa660385019285fe2bac28de69d,3f8d2ab32e5c34e0cfad96a7da7d5e73,6290b9f7df6749c922f622f9d6789a7a,ac8086e5faec789cdabe63bd3a754ce8,d2bc7a09a3026c987c242889051e8755,2affc77b864cc8bf3adcf38008675d03,7ed00eda0f32c80d79f09343ef8d1c1f --> <!-- werkrevisor-folded --> <details><summary>🟠 werkrevisor ORANGE for <code>f54ad51</code>, superseded by <a href="http://git.javagil.de/mi/werkregie/pulls/100#issuecomment-7519">the result for <code>751fdd5</code></a></summary> ## 🟠 werkrevisor: ORANGE / FINDINGS Change kind: `feature_with_modified_tests`. ### Reasons - **ORANGE** changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.83) - **ORANGE** 3 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-54, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:61-64, doc/prs/2026-10-23-PR#100-matrix-send-read.md:37 - **YELLOW** tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement - **YELLOW** change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes - **hint** 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** model recommends changes before merge - **hint** model rates the risk as high (advisory: Jev judged every changed file) ### Findings 1. **[high] Encrypted reaction** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-54`, ORANGE, as a line comment 2. **[medium] Legacy Olm** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:61-64`, ORANGE, as a line comment 3. **[medium] Event ID** at `doc/prs/2026-10-23-PR#100-matrix-send-read.md:37`, ORANGE, as a line comment ### Classifier 12 of 12 units passed all questions (1 PR document(s)). 2 answers ignored because of a confidence below [classifier] min_confidence. <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 61721, calls 1, tokens in 60119 / out 43536 (reasoning included in out), duration 599.6 s, cost 0.0702 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10452, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 6471, cost 0.0003 USD, build file judge `jev-1.14.0` calls 16, tokens in 28413, cost 0.0012 USD, phases: path_judge 0.8 s, classifier 0.7 s, context 0.9 s, model_review 595.6 s, finding_judge 0.4 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).<br> Reviewed head `f54ad51ef28e05b8b34d62bedcb3ab73247ba142` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2. </sub> </details>
ai-reviewer left a comment
Collaborator

werkrevisor: ORANGE / FINDINGS for f54ad51ef28e05b8b34d62bedcb3ab73247ba142.
The result comment of werkrevisor holds the details.

werkrevisor: ORANGE / FINDINGS for `f54ad51ef28e05b8b34d62bedcb3ab73247ba142`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:f54ad51ef28e05b8b34d62bedcb3ab73247ba142 -->
@@ -0,0 +43,4 @@
internal suspend fun candidates(events: Flow<Flow<TimelineEvent>>, request: ReadRequest): List<Flow<TimelineEvent>> {
val found = mutableListOf<Flow<TimelineEvent>>()
var reached = false
events.takeWhile { !reached && (request.afterEvent != null || found.size < request.limit) }.collect { flow ->
Collaborator

[high] Encrypted reaction (werkrevisor)

ORANGE; Jev: real 0.69, severity 2.9 of 3

The limit is applied while selecting encrypted events, before entry later decrypts and discards reactions. Reactions in encrypted rooms are commonly stored as encrypted events, so the newest encrypted reaction consumes a slot and is then removed. With the default limit the command can print only 19 of 20 messages; with --limit 1, it can print nothing although the next event is a message. Decrypt and filter candidates before applying the limit, or continue scanning until the limit is filled, and add a regression test.

**[high] Encrypted reaction** (werkrevisor) ORANGE; Jev: real 0.69, severity 2.9 of 3 The limit is applied while selecting encrypted events, before `entry` later decrypts and discards reactions. Reactions in encrypted rooms are commonly stored as encrypted events, so the newest encrypted reaction consumes a slot and is then removed. With the default limit the command can print only 19 of 20 messages; with `--limit 1`, it can print nothing although the next event is a message. Decrypt and filter candidates before applying the limit, or continue scanning until the limit is filled, and add a regression test.
Author
Collaborator

Not a finding: m.relates_to stays cleartext in an encrypted event (Matrix spec, end-to-end encryption and relations), so an encrypted reaction carries its RelatesTo.Annotation outside the ciphertext, and candidate drops it before the limit. Test: MatrixReaderTest "a message or an encrypted event of any algorithm may be a message, a reaction is none", with an encrypted event that annotates. Only another encrypted non-message, e.g. a poll, can take a slot; the PR document states that. No change.

Not a finding: `m.relates_to` stays cleartext in an encrypted event (Matrix spec, end-to-end encryption and relations), so an encrypted reaction carries its `RelatesTo.Annotation` outside the ciphertext, and `candidate` drops it before the limit. Test: MatrixReaderTest "a message or an encrypted event of any algorithm may be a message, a reaction is none", with an encrypted event that annotates. Only another encrypted non-message, e.g. a poll, can take a slot; the PR document states that. No change.
claude-code marked this conversation as resolved
@@ -0,0 +58,4 @@
withTimeoutOrNull(30.seconds) { event.first { it.content != null } } ?: event.first()
/** Whether [event] may be a message: a text, a notice, a file and the like, or an encrypted event other than a reaction. */
internal fun candidate(event: TimelineEvent): Boolean {
Collaborator

[medium] Legacy Olm (werkrevisor)

ORANGE; Jev: real 0.80, severity 3.0 of 3

candidate accepts only MegolmEncryptedMessageEventContent, so standard m.room.encrypted events using the legacy Olm algorithm never enter the candidate list and are silently omitted from matrix read. Historical rooms can contain such messages, which should at least appear as (nicht entschlüsselt) when no key is available. Accept the common encrypted-event type, including Olm, and cover it with a test.

**[medium] Legacy Olm** (werkrevisor) ORANGE; Jev: real 0.80, severity 3.0 of 3 `candidate` accepts only `MegolmEncryptedMessageEventContent`, so standard `m.room.encrypted` events using the legacy Olm algorithm never enter the candidate list and are silently omitted from `matrix read`. Historical rooms can contain such messages, which should at least appear as `(nicht entschlüsselt)` when no key is available. Accept the common encrypted-event type, including Olm, and cover it with a test.
Author
Collaborator

Olm encrypts only to-device events; Trixnity has no Olm content for room events (OlmEncryptedToDeviceEventContent only). Still, candidate now takes EncryptedMessageEventContent of any algorithm, so an unknown one shows as (nicht entschlüsselt): fixed in 751fdd5, with a test of an Unknown with algorithm m.olm.v1.curve25519-aes-sha2.

Olm encrypts only to-device events; Trixnity has no Olm content for room events (`OlmEncryptedToDeviceEventContent` only). Still, `candidate` now takes `EncryptedMessageEventContent` of any algorithm, so an unknown one shows as `(nicht entschlüsselt)`: fixed in `751fdd5`, with a test of an `Unknown` with algorithm `m.olm.v1.curve25519-aes-sha2`.
claude-code marked this conversation as resolved
@@ -0,0 +34,4 @@
- **Given** the device of `matrix login` is verified and member of the room "HSAdmin NG"
- **When** an agent runs `werkregie-dashboard matrix send --room "HSAdmin NG" "Build ist grün"`
- **Then** the message is in the room, encrypted like the room, and the command prints `SENT` and its event ID
Collaborator

[medium] Event ID (werkrevisor)

ORANGE; Jev: real 0.70, severity 3.0 of 3

The scenario and Solution promise SENT plus the event ID, but MatrixSender.line deliberately returns only SENT when the outbox entry disappears before its ID is observed, as the new test also codifies. This race is realistic, so an agent using the returned ID as its next --since cursor can receive an incomplete result. Either guarantee the ID or amend the PR contract and CLI help to state that it is optional.

**[medium] Event ID** (werkrevisor) ORANGE; Jev: real 0.70, severity 3.0 of 3 The scenario and Solution promise `SENT` plus the event ID, but `MatrixSender.line` deliberately returns only `SENT` when the outbox entry disappears before its ID is observed, as the new test also codifies. This race is realistic, so an agent using the returned ID as its next `--since` cursor can receive an incomplete result. Either guarantee the ID or amend the PR contract and CLI help to state that it is optional.
Author
Collaborator

Fixed in 751fdd5: Scenario#100.01, the Solution and the help text say that SENT comes without the event ID when the outbox gave the message up before the client saw it; the README said so already. An agent that gets no ID reads with --since a time.

Fixed in `751fdd5`: Scenario#100.01, the Solution and the help text say that `SENT` comes without the event ID when the outbox gave the message up before the client saw it; the README said so already. An agent that gets no ID reads with `--since` a time.
claude-code marked this conversation as resolved
mi added 1 commit 2026-10-23 19:44:40 +02:00
matrix read counts encrypted events of any algorithm; SENT without event ID in help and PR document
werkator build succeeded after 05:00
werkator/dependencies build succeeded after 00:14
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ai-review/gate build succeeded after 10:22
751fdd5fd2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
🟠 werkrevisor ORANGE for 751fdd5, superseded by the result for 9ef234b

🟠 werkrevisor: ORANGE / FINDINGS

Change kind: feature_with_modified_tests.

Reasons

  • ORANGE changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.80)
  • ORANGE 1 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-50
  • YELLOW tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement
  • YELLOW change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes
  • hint 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint 2 finding(s) of low severity or rated minor by Jev: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:30, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:29-30
  • hint model recommends merge with caution

Findings

  1. [medium] Time filter stops at first older event at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-50, ORANGE, as a line comment

  2. [medium] Output order untested at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:29-30, hint, as a line comment

  3. [low] Output times use another zone at dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:30, hint, as a line comment

Classifier

12 of 12 units passed all questions (1 PR document(s)).
5 answers ignored because of a confidence below [classifier] min_confidence.

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 62206, calls 1, tokens in 60562 / out 53526 (reasoning included in out), duration 617.1 s, cost 0.0824 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10542, cost 0.0004 USD, finding judge `jev-1.14.0` calls 2, tokens in 4602, cost 0.0002 USD, build file judge `jev-1.14.0` calls 16, tokens in 28549, cost 0.0012 USD, phases: path_judge 0.7 s, classifier 0.5 s, context 1.6 s, model_review 613.3 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).
Reviewed head `751fdd5fd29ed763c3121c1a924e529aa701cc3f` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2.
<!-- werkrevisor:751fdd5fd29ed763c3121c1a924e529aa701cc3f --> <!-- werkrevisor-verdict:ORANGE --> <!-- werkrevisor-blocks:bcf7660a2d227efef94b870c8d874da9,90753c6412c0ff8198b0a8ca14d88292,6194907bf7f7a67de7fc1b36797bf92f,3db7a25e3e4fdff9d609759b9907b47f,05a2f6ef6ec9e967d5d1b2eac8c7cb45,ecee0f663c4fce1f60b0afb5b07278b0,0e9f13d59704543605a912c3283b4e41,f50c020cc567c80fc7e89a1fc8ecf277,bbc20050497d7ae157cbc5e9e8caf638,4f3d57dcc7de387fcf6ef51bca9505dd,2b71fae8113e6d5ca77ba1e6490c1f50,3c5c5970bc2c20a9a3596516487151ae,8065fcf2e8fa75a0e23bf6f8c441513b,5dd085ff1471653a9ae1af312e62696c,cc437211086f304c244b7cd843d463d6,52bf7eb7f90f4c51a1a4d3df516c0597,d8ee706b85d2b93b402edb06d79a46e5,24d75064fe90e2bcfb2647c8cd741e6c,1b1a23a5ea1e59ef43fe2e5666215384,253f89ea481a9c1d4dcc33bb4a9a0c79,e48974b700759e6876bc4554915f5703,6fb2246a143cc074aecbf6445e048f74,83d01d3fc8ff665883d8be0f100b5ca5,8886449a39476ab90246c4a80ea66496,12c8ca81c1bebbd7965bb9eb618d58a7,a7939e3b20c1d962c9bfac626eaac445,0bdd7a6b3a3a36f822323c8127047e05,c3bee07eab2d43bad35397dda3126a2f,a6bf5f93a14add230e3675e6ea38d5f5,4065b773bf1fb988087b16ff49a851ba,6bda92971b9c0c4527927db3ad3a62a0,e24d89a08e3edc6566978e6a468f8452,c19dd8cdfc8a7c0edbda6a5b7a1fa9d2,286f7cae870f46be0414504f5edf6ce9,540a7d7d5e46a636bfb77c3f48a0a295,880444bbb207e5228eaafac253b356ea,935c9b34278f3735e2fabeab72a15fd6,72bb3a0a35e5f8cde077571ac59efb23,cea550f3d1cccd347fa3b3db996fb874,0499287720e2b901062ecd215c06e24a,00c4dfdce7cac4429363974fb6fd89ec,a239074999066d29d97d815fde3c2e07,a7f7f5e758543d732fb2140841deae1a,17e69f3adb49c5b79f5746ff66cc9791,eb022560002c138ae77bd98c1f2e0be4,cdb647cd74997d341b8bf02b9dbff1fb,7912f2f388dfa08508eb5fabc30056dd,f89d0edf491d27be9b68f2c287fbf7eb,7ec03a764a28a0bc5156f87abbce4a82,b84370c3f1b8e91bb7061e8163302a2f,11495aa92fe55d4a605d0a14a1d30c2a,b2422a4248efd9e1173736a52c9c5e65,e367ba16f266660d5fc47368fa998d55,eb04647909410d239c7049b1d1eeba6f,518d03c567bc55cafd2cb2010e8e2ce6,a6dcdaa660385019285fe2bac28de69d,3f8d2ab32e5c34e0cfad96a7da7d5e73,508f3141fa39960f5bb3bee38b5bd2ca,ac8086e5faec789cdabe63bd3a754ce8,d2bc7a09a3026c987c242889051e8755,2affc77b864cc8bf3adcf38008675d03,7ed00eda0f32c80d79f09343ef8d1c1f --> <!-- werkrevisor-folded --> <details><summary>🟠 werkrevisor ORANGE for <code>751fdd5</code>, superseded by <a href="http://git.javagil.de/mi/werkregie/pulls/100#issuecomment-7531">the result for <code>9ef234b</code></a></summary> ## 🟠 werkrevisor: ORANGE / FINDINGS Change kind: `feature_with_modified_tests`. ### Reasons - **ORANGE** changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.80) - **ORANGE** 1 finding(s) that Jev rates as probably real and severe: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-50 - **YELLOW** tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement - **YELLOW** change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes - **hint** 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** 2 finding(s) of low severity or rated minor by Jev: dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:30, dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:29-30 - **hint** model recommends merge with caution ### Findings 1. **[medium] Time filter stops at first older event** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:46-50`, ORANGE, as a line comment 2. **[medium] Output order untested** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:29-30`, hint, as a line comment 3. **[low] Output times use another zone** at `dashboard/src/main/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReader.kt:30`, hint, as a line comment ### Classifier 12 of 12 units passed all questions (1 PR document(s)). 5 answers ignored because of a confidence below [classifier] min_confidence. <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 62206, calls 1, tokens in 60562 / out 53526 (reasoning included in out), duration 617.1 s, cost 0.0824 USD (reported), classifier `jev-1.14.0` calls 12, tokens in 10542, cost 0.0004 USD, finding judge `jev-1.14.0` calls 2, tokens in 4602, cost 0.0002 USD, build file judge `jev-1.14.0` calls 16, tokens in 28549, cost 0.0012 USD, phases: path_judge 0.7 s, classifier 0.5 s, context 1.6 s, model_review 613.3 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).<br> Reviewed head `751fdd5fd29ed763c3121c1a924e529aa701cc3f` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2. </sub> </details>
ai-reviewer left a comment
Collaborator

werkrevisor: ORANGE / FINDINGS for 751fdd5fd29ed763c3121c1a924e529aa701cc3f.
The result comment of werkrevisor holds the details.

werkrevisor: ORANGE / FINDINGS for `751fdd5fd29ed763c3121c1a924e529aa701cc3f`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:751fdd5fd29ed763c3121c1a924e529aa701cc3f -->
@@ -0,0 +26,4 @@
object MatrixReader {
/** Reads with [client], which has synced once since it started; the text the command prints. */
internal suspend fun read(client: MatrixClient, roomId: RoomId, request: ReadRequest): String = withTimeout(5.minutes) {
val events = coroutineScope { candidates(client, roomId, request).map { async { decrypted(it) } }.awaitAll() }
Collaborator

[medium] Output order untested (werkrevisor)

hint; Jev: real 0.60, severity 2.3 of 3

The oldest-first order of the matrix read output exists only in the .reversed() here; no test covers it, because MatrixReader.candidates is tested newest-first and MatrixReading.text keeps the order it is given. Removing or inverting .reversed() would keep every test green while breaking the documented order of the blocks. Extract the ordering into a testable function and assert it.

**[medium] Output order untested** (werkrevisor) hint; Jev: real 0.60, severity 2.3 of 3 The oldest-first order of the `matrix read` output exists only in the `.reversed()` here; no test covers it, because `MatrixReader.candidates` is tested newest-first and `MatrixReading.text` keeps the order it is given. Removing or inverting `.reversed()` would keep every test green while breaking the documented order of the blocks. Extract the ordering into a testable function and assert it.
Author
Collaborator

Fixed in 9ef234b: MatrixReading.text takes the messages newest first, as the room gives them, and prints them oldest first; MatrixReadingTest "each message is a block of time, sender, event ID and its indented text, the oldest first" checks the order.

Fixed in `9ef234b`: `MatrixReading.text` takes the messages newest first, as the room gives them, and prints them oldest first; MatrixReadingTest "each message is a block of time, sender, event ID and its indented text, the oldest first" checks the order.
claude-code marked this conversation as resolved
@@ -0,0 +27,4 @@
/** Reads with [client], which has synced once since it started; the text the command prints. */
internal suspend fun read(client: MatrixClient, roomId: RoomId, request: ReadRequest): String = withTimeout(5.minutes) {
val events = coroutineScope { candidates(client, roomId, request).map { async { decrypted(it) } }.awaitAll() }
MatrixReading.text(events.mapNotNull(::entry).reversed(), ZoneId.systemDefault())
Collaborator

[low] Output times use another zone (werkrevisor)

hint

The printed timestamps are formatted with ZoneId.systemDefault() of the process that renders the text (the relay), while --since without an offset is parsed in the zone of the CLI process. When the read is served by the relay on another machine, the agent interprets the cutoff in its own zone but sees the times in the relay's zone, so the output does not show the "local time" that README and the PR document promise. Carry the caller's zone in the request and format the times with it.

**[low] Output times use another zone** (werkrevisor) hint The printed timestamps are formatted with `ZoneId.systemDefault()` of the process that renders the text (the relay), while `--since` without an offset is parsed in the zone of the CLI process. When the read is served by the relay on another machine, the agent interprets the cutoff in its own zone but sees the times in the relay's zone, so the output does not show the "local time" that README and the PR document promise. Carry the caller's zone in the request and format the times with it.
Author
Collaborator

Fixed in 9ef234b: ReadRequest carries the caller's zone through control.sock, and the times print in it. The socket is a local Unix socket, so the relay runs on the same machine, but its unit may have another TZ.

Fixed in `9ef234b`: `ReadRequest` carries the caller's zone through `control.sock`, and the times print in it. The socket is a local Unix socket, so the relay runs on the same machine, but its unit may have another `TZ`.
claude-code marked this conversation as resolved
@@ -0,0 +43,4 @@
internal suspend fun candidates(events: Flow<Flow<TimelineEvent>>, request: ReadRequest): List<Flow<TimelineEvent>> {
val found = mutableListOf<Flow<TimelineEvent>>()
var reached = false
events.takeWhile { !reached && (request.afterEvent != null || found.size < request.limit) }.collect { flow ->
Collaborator

[medium] Time filter stops at first older event (werkrevisor)

ORANGE; Jev: real 0.78, severity 3.0 of 3

The scan for --since <time> walks the timeline newest first and stops at the first event whose origin_server_ts is older than the cutoff (MatrixReading.reached). Matrix orders a room by stream order, not by timestamp, so with a federated homeserver or delayed events an event with an old timestamp can precede events with newer ones. In that case the scan stops immediately and matrix read --since 2026-10-23T14:00 prints nothing although messages sent after 14:00 exist. Filter the fetched window by timestamp instead of ending the scan at the first older event.

**[medium] Time filter stops at first older event** (werkrevisor) ORANGE; Jev: real 0.78, severity 3.0 of 3 The scan for `--since <time>` walks the timeline newest first and stops at the first event whose `origin_server_ts` is older than the cutoff (`MatrixReading.reached`). Matrix orders a room by stream order, not by timestamp, so with a federated homeserver or delayed events an event with an old timestamp can precede events with newer ones. In that case the scan stops immediately and `matrix read --since 2026-10-23T14:00` prints nothing although messages sent after 14:00 exist. Filter the fetched window by timestamp instead of ending the scan at the first older event.
Author
Collaborator

Fixed in 9ef234b: an event before --since TIME is skipped, and only 20 such events in a row end the reading, so an older time stamp among newer ones no longer stops it. Test: MatrixReaderTest "an event before the time to start from is skipped, and enough of them in a row end the reading".

Fixed in `9ef234b`: an event before `--since` TIME is skipped, and only 20 such events in a row end the reading, so an older time stamp among newer ones no longer stops it. Test: MatrixReaderTest "an event before the time to start from is skipped, and enough of them in a row end the reading".
claude-code marked this conversation as resolved
mi added 1 commit 2026-10-23 20:01:45 +02:00
matrix read: skip events before --since TIME rather than stop at the first, times in the caller's zone, order tested
werkator build succeeded after 05:03
werkator/dependencies build succeeded after 00:16
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ai-review/gate build succeeded after 12:08
9ef234b447
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator

🟠 werkrevisor: ORANGE / FINDINGS

Change kind: feature_with_modified_tests.

Reasons

  • ORANGE changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.82)
  • YELLOW tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement
  • YELLOW change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes
  • hint 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file)

Classifier

12 of 12 units passed all questions (1 PR document(s)).
4 answers ignored because of a confidence below [classifier] min_confidence.

Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 63184, duration 725.2 s, cost unknown, classifier `jev-1.14.0` calls 12, tokens in 10618, cost 0.0004 USD, build file judge `jev-1.14.0` calls 16, tokens in 29002, cost 0.0012 USD, phases: path_judge 0.8 s, classifier 0.6 s, context 0.6 s, model_review 722.7 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).
Reviewed head `9ef234b447070dc365d8844cd69b6d39912ec23e` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2.
<!-- werkrevisor:9ef234b447070dc365d8844cd69b6d39912ec23e --> <!-- werkrevisor-verdict:ORANGE --> <!-- werkrevisor-blocks:bcf7660a2d227efef94b870c8d874da9,90753c6412c0ff8198b0a8ca14d88292,6194907bf7f7a67de7fc1b36797bf92f,3db7a25e3e4fdff9d609759b9907b47f,05a2f6ef6ec9e967d5d1b2eac8c7cb45,ecee0f663c4fce1f60b0afb5b07278b0,0e9f13d59704543605a912c3283b4e41,f50c020cc567c80fc7e89a1fc8ecf277,bbc20050497d7ae157cbc5e9e8caf638,f793c23dd7139cfc8acd9f5961e20c84,f2e3bf6d799a8e5b2d9567de3ee324cb,3c5c5970bc2c20a9a3596516487151ae,8065fcf2e8fa75a0e23bf6f8c441513b,5dd085ff1471653a9ae1af312e62696c,cc437211086f304c244b7cd843d463d6,52bf7eb7f90f4c51a1a4d3df516c0597,d8ee706b85d2b93b402edb06d79a46e5,24d75064fe90e2bcfb2647c8cd741e6c,1b1a23a5ea1e59ef43fe2e5666215384,60cf017ec1bd22b2b7fb27b6f70cf262,e48974b700759e6876bc4554915f5703,0a5291caeb929265c2a3291178c40020,83d01d3fc8ff665883d8be0f100b5ca5,8886449a39476ab90246c4a80ea66496,12c8ca81c1bebbd7965bb9eb618d58a7,a7939e3b20c1d962c9bfac626eaac445,0bdd7a6b3a3a36f822323c8127047e05,c3bee07eab2d43bad35397dda3126a2f,a6bf5f93a14add230e3675e6ea38d5f5,4065b773bf1fb988087b16ff49a851ba,6bda92971b9c0c4527927db3ad3a62a0,e24d89a08e3edc6566978e6a468f8452,c19dd8cdfc8a7c0edbda6a5b7a1fa9d2,286f7cae870f46be0414504f5edf6ce9,540a7d7d5e46a636bfb77c3f48a0a295,f422a7c5001f3b8ba18e5590bd659c3f,c27fe08d1fba440534e7cb8a188bc278,72bb3a0a35e5f8cde077571ac59efb23,cea550f3d1cccd347fa3b3db996fb874,0499287720e2b901062ecd215c06e24a,00c4dfdce7cac4429363974fb6fd89ec,a239074999066d29d97d815fde3c2e07,565b57cd59db59c9bea5f3834691d6c6,17e69f3adb49c5b79f5746ff66cc9791,93b39b53790118c8c55edb2d0ddbf97f,cdb647cd74997d341b8bf02b9dbff1fb,7912f2f388dfa08508eb5fabc30056dd,f89d0edf491d27be9b68f2c287fbf7eb,7ec03a764a28a0bc5156f87abbce4a82,b84370c3f1b8e91bb7061e8163302a2f,57cb4733dcfbe199abcd4a3fdca467c7,b2422a4248efd9e1173736a52c9c5e65,e367ba16f266660d5fc47368fa998d55,eb04647909410d239c7049b1d1eeba6f,51c0b6c1bb71bb1818ec3bb584c6b97d,5cfe6f15b042cde145b96beb06944547,3f8d2ab32e5c34e0cfad96a7da7d5e73,056f36b66337a60a976e38538a2cc6b5,ac8086e5faec789cdabe63bd3a754ce8,d2bc7a09a3026c987c242889051e8755,2affc77b864cc8bf3adcf38008675d03,7ed00eda0f32c80d79f09343ef8d1c1f --> ## 🟠 werkrevisor: ORANGE / FINDINGS Change kind: `feature_with_modified_tests`. ### Reasons - **ORANGE** changes that weaken the checks according to Jev: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt (weakens checks 0.82) - **YELLOW** tests lost or disabled: dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt:64 removes 8 test(s) or assertion(s) without a replacement - **YELLOW** change kind 'feature_with_modified_tests' (main code, tests, docs); AI-approvable are only: docs only, tests only added, docs and tests, refactoring with unchanged tests, feature with purely additive tests, harmless files only, mechanical changes only, mixed changes - **hint** 15 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file) ### Classifier 12 of 12 units passed all questions (1 PR document(s)). 4 answers ignored because of a confidence below [classifier] min_confidence. <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 63184, duration 725.2 s, cost unknown, classifier `jev-1.14.0` calls 12, tokens in 10618, cost 0.0004 USD, build file judge `jev-1.14.0` calls 16, tokens in 29002, cost 0.0012 USD, phases: path_judge 0.8 s, classifier 0.6 s, context 0.6 s, model_review 722.7 s, config: defaults + host + repository (.werkrevisor.toml at main 367947a).<br> Reviewed head `9ef234b447070dc365d8844cd69b6d39912ec23e` against base `367947a4816effc84a1428bc387976cc64995367`, werkrevisor 0.65.2. </sub>
Some optional checks failed
werkator build succeeded after 05:03
Required
Details
werkator/dependencies build succeeded after 00:16
Required
Details
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ai-review/gate build succeeded after 12:08
Required
Details
This pull request doesn't have enough required approvals yet. 0 of 1 approvals granted from users or teams on the allowlist.
This pull request has official review requests.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin claude-code/matrix-send-read:claude-code/matrix-send-read
git checkout claude-code/matrix-send-read
Sign in to join this conversation.
No Reviewers
No labels
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mi/werkregie#100