Repository privacy answer kept and renewed in steps (v1.37.11) #130

Merged
ai-reviewer merged 4 commits from mihoe/repository-privacy-tests into main 2026-10-09 13:10:47 +02:00
Owner

Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

The Problem

RepositoryPrivacy.isPrivate is above the Mutation-CRAP target of 15 in the nightly mutation build of 2026-10-07 and 2026-10-09:

Method Mutation-CRAP Complexity Killed / eligible
RepositoryPrivacy.isPrivate 16.40 10 9 / 15

One method decided whether the cached answer still stands, asked the forge, warned about a silent forge and stored the new answer.
The tests never touched the exact moment an answer expires, and nothing checked that a silent forge is reported once and not on every retry.

Non-Goals

  • No change of the behaviour: the same answers, the same expiry times, the same warning.

The Scenarios

Feature: The privacy answer of a repository

Scenario#130.01: A cached answer expires at exactly its validity

So that a repository that changed its visibility is followed within the stated time, and not one poll later or earlier.

  • Given the forge answered for a repository
  • When one second less than the answer's validity has passed
  • Then the cached answer is returned and the forge is not asked
  • When the full validity has passed
  • Then the forge is asked again
  • The validity is REFRESH_AFTER (15 minutes) for a confirmed answer and RETRY_UNKNOWN_AFTER (1 minute) for a guess.
Verified by

Scenario#130.02: A forge that stops answering is reported once

So that the log names the outage without repeating it every minute while the forge stays silent.

  • Given the forge answered for a repository
  • When the forge stops answering and is asked three times in a row
  • Then the warning "Cannot tell whether … is private" is logged once
Verified by

The Solution

  • Answer.standsAt(now) says whether a cached answer is still valid.
  • isPrivate returns the cached answer or calls ask.
  • ask reads the visibility, warns when a known answer turns unknown, and stores the new answer.

Measured locally with PIT on RepositoryPrivacy:

Method Mutation-CRAP before after
RepositoryPrivacy.isPrivate 16.40 6.04
RepositoryPrivacy.ask new 6.11
Answer.standsAt new 3.00

The gate stays at 15.

Prerequisite PRs

  • PR#129 — this branch is stacked on it, for the version and the release notes.

Follow-up PRs

  • PR#131 splits two more methods of ConfigLoader into smaller steps, so that their scores drop below 15.
    ConfigLoader.renameLegacySandbox is at 15.93.
    ConfigLoader.checkRestartsInstance is at exactly 15.00: one more surviving mutant would put it above the gate.

🤖 Generated with Claude Code

> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation. ## The Problem `RepositoryPrivacy.isPrivate` is above the Mutation-CRAP target of 15 in the nightly mutation build of 2026-10-07 and 2026-10-09: | Method | Mutation-CRAP | Complexity | Killed / eligible | |-------------------------------|--------------:|-----------:|------------------:| | `RepositoryPrivacy.isPrivate` | 16.40 | 10 | 9 / 15 | One method decided whether the cached answer still stands, asked the forge, warned about a silent forge and stored the new answer. The tests never touched the exact moment an answer expires, and nothing checked that a silent forge is reported once and not on every retry. ## Non-Goals - No change of the behaviour: the same answers, the same expiry times, the same warning. ## The Scenarios ### Feature: The privacy answer of a repository #### Scenario#130.01: A cached answer expires at exactly its validity So that a repository that changed its visibility is followed within the stated time, and not one poll later or earlier. - **Given** the forge answered for a repository - **When** one second less than the answer's validity has passed - **Then** the cached answer is returned and the forge is not asked - **When** the full validity has passed - **Then** the forge is asked again - The validity is `REFRESH_AFTER` (15 minutes) for a confirmed answer and `RETRY_UNKNOWN_AFTER` (1 minute) for a guess. ##### Verified by - [RepositoryPrivacyUnitTest: a confirmed answer stands for exactly REFRESH_AFTER](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) - [RepositoryPrivacyUnitTest: a guess stands for exactly RETRY_UNKNOWN_AFTER](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) #### Scenario#130.02: A forge that stops answering is reported once So that the log names the outage without repeating it every minute while the forge stays silent. - **Given** the forge answered for a repository - **When** the forge stops answering and is asked three times in a row - **Then** the warning "Cannot tell whether … is private" is logged once ##### Verified by - [RepositoryPrivacyUnitTest: a forge that stops answering is reported once](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) ## The Solution - `Answer.standsAt(now)` says whether a cached answer is still valid. - `isPrivate` returns the cached answer or calls `ask`. - `ask` reads the visibility, warns when a known answer turns unknown, and stores the new answer. Measured locally with PIT on `RepositoryPrivacy`: | Method | Mutation-CRAP before | after | |-------------------------------|---------------------:|------:| | `RepositoryPrivacy.isPrivate` | 16.40 | 6.04 | | `RepositoryPrivacy.ask` | new | 6.11 | | `Answer.standsAt` | new | 3.00 | The gate stays at 15. ## Prerequisite PRs - PR#129 — this branch is stacked on it, for the version and the release notes. ## Follow-up PRs - PR#131 splits two more methods of `ConfigLoader` into smaller steps, so that their scores drop below 15. `ConfigLoader.renameLegacySandbox` is at 15.93. `ConfigLoader.checkRestartsInstance` is at exactly 15.00: one more surviving mutant would put it above the gate. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mi added 2 commits 2026-10-09 12:50:43 +02:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Repository privacy answer kept and renewed in steps (v1.37.11)
werkator build succeeded after 02:01
ai-review/assessment human review required; a human approval unlocks the merge; review request failed: POST /repos/mi/werkator/pulls/130/requested_reviewers failed with HTTP 422
ai-review/gate build failed after 01:38
b39b215c30
isPrivate returns the cached answer while Answer.standsAt says it is
valid, and otherwise asks the forge through ask. Tests pin the exact
moments an answer expires and the single warning about a silent forge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi force-pushed mihoe/repository-privacy-tests from eb9470af0d to b39b215c30 2026-10-09 12:50:43 +02:00 Compare
claude-code changed title from WIP: Repository privacy answer kept and renewed in steps to Repository privacy answer kept and renewed in steps (v1.37.11) 2026-10-09 12:57:00 +02:00
Collaborator
🟡 werkrevisor YELLOW for b39b215, superseded by the result for 66badd0

🟡 werkrevisor: YELLOW / HUMAN_REVIEW

Change kind: mixed.

Reasons

  • YELLOW spec: docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md section 'Follow-up PRs' hard_to_understand (0.58 > yellow_above = 0.5)
  • hint 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01)
  • hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html
  • hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md:74
  • hint model recommends merge with caution

Findings

  1. Unclear follow-up wording at docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md:74, severity unknown, counted as medium, hint, as a line comment

Classifier

Unit Question Problem Confidence Verdict
docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md section 'Follow-up PRs' hard_to_understand 0.58 0.56 YELLOW

6 of 7 units passed all questions (1 PR document(s)).

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20370, calls 1, tokens in 19640 / out 10364 (reasoning included in out), duration 93.8 s, cost 0.0183 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5445, cost 0.0002 USD, finding judge `jev-1.13.0` calls 1, tokens in 1830, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 56, cost 0.0036 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.4 s, classifier 0.5 s, context 5.2 s, model_review 87.1 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).
Reviewed head `b39b215c300153a83d9fc05f8d841c01ae2b55c8` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1.
<!-- werkrevisor:b39b215c300153a83d9fc05f8d841c01ae2b55c8 --> <!-- werkrevisor-verdict:YELLOW --> <!-- werkrevisor-folded --> <details><summary>🟡 werkrevisor YELLOW for <code>b39b215</code>, superseded by <a href="http://git.javagil.de/mi/werkator/pulls/130#issuecomment-2438">the result for <code>66badd0</code></a></summary> ## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW Change kind: `mixed`. ### Reasons - **YELLOW** spec: docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md section 'Follow-up PRs' hard_to_understand (0.58 > yellow_above = 0.5) - **hint** 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01) - **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html - **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md:74 - **hint** model recommends merge with caution ### Findings 1. **Unclear follow-up wording** at `docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md:74`, severity unknown, counted as medium, hint, as a line comment ### Classifier | Unit | Question | Problem | Confidence | Verdict | |---|---|---|---|---| | docs/prs/2026-10-09-PR#130-repository-privacy-answer-steps.md section 'Follow-up PRs' | hard_to_understand | 0.58 | 0.56 | YELLOW | 6 of 7 units passed all questions (1 PR document(s)). <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20370, calls 1, tokens in 19640 / out 10364 (reasoning included in out), duration 93.8 s, cost 0.0183 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5445, cost 0.0002 USD, finding judge `jev-1.13.0` calls 1, tokens in 1830, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 56, cost 0.0036 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.4 s, classifier 0.5 s, context 5.2 s, model_review 87.1 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).<br> Reviewed head `b39b215c300153a83d9fc05f8d841c01ae2b55c8` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1. </sub> </details>
ai-reviewer left a comment
Collaborator

werkrevisor: YELLOW / HUMAN_REVIEW for b39b215c300153a83d9fc05f8d841c01ae2b55c8.
The result comment of werkrevisor holds the details.

werkrevisor: YELLOW / HUMAN_REVIEW for `b39b215c300153a83d9fc05f8d841c01ae2b55c8`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:b39b215c300153a83d9fc05f8d841c01ae2b55c8 -->
@@ -0,0 +71,4 @@
- PR#129 — this branch is stacked on it, for the version and the release notes.
## Follow-up PRs
Collaborator

Unclear follow-up wording, severity unknown, counted as medium (werkrevisor)

hint; Jev: real 0.67, severity 1.0 of 3

The follow-up item "ConfigLoader.checkRestartsInstance (exactly 15.00) gets room below the target" uses an imprecise metaphor ("gets room") for what the next PR will do to a method sitting at the Mutation-CRAP limit, and leaves the intended action (split? refactor? leave alone?) ambiguous. A reader cannot tell from this sentence alone whether the follow-up will actively reshape the method or merely rely on it staying where it is.

**Unclear follow-up wording**, severity unknown, counted as medium (werkrevisor) hint; Jev: real 0.67, severity 1.0 of 3 The follow-up item "ConfigLoader.checkRestartsInstance (exactly 15.00) gets room below the target" uses an imprecise metaphor ("gets room") for what the next PR will do to a method sitting at the Mutation-CRAP limit, and leaves the intended action (split? refactor? leave alone?) ambiguous. A reader cannot tell from this sentence alone whether the follow-up will actively reshape the method or merely rely on it staying where it is.
Collaborator

Fixed in the PR-doc: the follow-up now says that PR#131 splits both ConfigLoader methods into smaller steps so that their scores drop below 15, and why checkRestartsInstance at exactly 15.00 needs it.

Fixed in the PR-doc: the follow-up now says that PR#131 splits both ConfigLoader methods into smaller steps so that their scores drop below 15, and why checkRestartsInstance at exactly 15.00 needs it.
claude-code marked this conversation as resolved
ai-reviewer scheduled this pull request to auto merge when all checks succeed 2026-10-09 12:59:08 +02:00
mi added 1 commit 2026-10-09 13:00:16 +02:00
PR-doc of PR#130: follow-up section in plain sentences
ai-review/assessment AI review passed; approved by werkrevisor; merge waits for 1 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit
ai-review/gate build succeeded after 01:33
werkator build succeeded after 02:13
66badd0e9d
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
🟢 werkrevisor GREEN for 66badd0, superseded by the result for 9e3ec73

🟢 werkrevisor: GREEN / PASS

Gate: approved by werkrevisor; merge waits for 1 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit.

Change kind: mixed.

Reasons

  • hint 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01)
  • hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html

Classifier

7 of 7 units passed all questions (1 PR document(s)).

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20270, calls 1, tokens in 19548 / out 12750 (reasoning included in out), duration 90.5 s, cost 0.0211 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5472, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 135, cost 0.0004 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.3 s, classifier 0.6 s, context 3.6 s, model_review 85.6 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).
Reviewed head `66badd0e9d636aba254b5b78879e3da735060125` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1.
<!-- werkrevisor:66badd0e9d636aba254b5b78879e3da735060125 --> <!-- werkrevisor-verdict:GREEN --> <!-- werkrevisor-folded --> <details><summary>🟢 werkrevisor GREEN for <code>66badd0</code>, superseded by <a href="http://git.javagil.de/mi/werkator/pulls/130#issuecomment-2446">the result for <code>9e3ec73</code></a></summary> ## 🟢 werkrevisor: GREEN / PASS Gate: approved by werkrevisor; merge waits for 1 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit. Change kind: `mixed`. ### Reasons - **hint** 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01) - **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html ### Classifier 7 of 7 units passed all questions (1 PR document(s)). <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20270, calls 1, tokens in 19548 / out 12750 (reasoning included in out), duration 90.5 s, cost 0.0211 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5472, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 135, cost 0.0004 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.3 s, classifier 0.6 s, context 3.6 s, model_review 85.6 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).<br> Reviewed head `66badd0e9d636aba254b5b78879e3da735060125` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1. </sub> </details>
ai-reviewer approved these changes 2026-10-09 13:01:54 +02:00
Dismissed
ai-reviewer left a comment
Collaborator

werkrevisor: GREEN / PASS for 66badd0e9d636aba254b5b78879e3da735060125.
The result comment of werkrevisor holds the details.

werkrevisor: GREEN / PASS for `66badd0e9d636aba254b5b78879e3da735060125`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:66badd0e9d636aba254b5b78879e3da735060125 -->
ai-reviewer canceled auto merging this pull request when all checks succeed 2026-10-09 13:01:55 +02:00
mi added 1 commit 2026-10-09 13:06:13 +02:00
PR-doc of PR#130: the follow-up says what PR#131 does
ai-review/assessment AI review passed; approved by werkrevisor; merge scheduled for when the checks succeed
ai-review/gate build succeeded after 00:56
werkator build succeeded after 02:07
9e3ec73087
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi dismissed ai-reviewer's review 2026-10-09 13:06:13 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

Collaborator

🟢 werkrevisor: GREEN / PASS

Change kind: mixed.

Reasons

  • hint 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev
  • hint 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01)
  • hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html

Classifier

7 of 7 units passed all questions (1 PR document(s)).

Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20277, calls 1, tokens in 19555 / out 3966 (reasoning included in out), duration 50.5 s, cost 0.0088 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5479, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 125, cost 0.0003 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.4 s, classifier 0.5 s, context 5.9 s, model_review 43.4 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).
Reviewed head `9e3ec73087fd1759909c9d832b3146898e1fbdd3` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1.
<!-- werkrevisor:9e3ec73087fd1759909c9d832b3146898e1fbdd3 --> <!-- werkrevisor-verdict:GREEN --> ## 🟢 werkrevisor: GREEN / PASS Change kind: `mixed`. ### Reasons - **hint** 3 changed file(s) that neither weaken the checks, touch security nor show a risk category of jvm-spring-backend according to Jev - **hint** 1 build change(s) of low risk according to Jev: build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.01) - **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): src/main/resources/templates/releases.html ### Classifier 7 of 7 units passed all questions (1 PR document(s)). <sub> Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 20277, calls 1, tokens in 19555 / out 3966 (reasoning included in out), duration 50.5 s, cost 0.0088 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5479, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 28267 / out 125, cost 0.0003 USD (reported), build file judge `jev-1.13.0` calls 4, tokens in 5207, cost 0.0002 USD, phases: path_judge 0.4 s, classifier 0.5 s, context 5.9 s, model_review 43.4 s, config: defaults + host + repository (.werkrevisor.toml at main 01b5512).<br> Reviewed head `9e3ec73087fd1759909c9d832b3146898e1fbdd3` against base `01b55120d492279be6c8ca4f7f5a31d5113ce6d2`, werkrevisor 0.30.1. </sub>
ai-reviewer left a comment
Collaborator

werkrevisor: GREEN / PASS for 9e3ec73087fd1759909c9d832b3146898e1fbdd3.
The result comment of werkrevisor holds the details.

werkrevisor: GREEN / PASS for `9e3ec73087fd1759909c9d832b3146898e1fbdd3`. The result comment of werkrevisor holds the details. <!-- werkrevisor-review:9e3ec73087fd1759909c9d832b3146898e1fbdd3 -->
ai-reviewer scheduled this pull request to auto merge when all checks succeed 2026-10-09 13:07:10 +02:00
ai-reviewer merged commit 1943a593c0 into main 2026-10-09 13:10:47 +02:00
ai-reviewer deleted branch mihoe/repository-privacy-tests 2026-10-09 13:10:47 +02:00
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/werkator#130