Compare commits
15 Commits
ecd4447c46
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9112d9524f | |||
| 18a76b0350 | |||
| 55e5cbeb0f | |||
| 01fa52a1fc | |||
| 18570dec1c | |||
| 9244d49d75 | |||
| 80ad7e837c | |||
| 37606bf304 | |||
| d10efd5beb | |||
| b44f8363ea | |||
| 802a916b92 | |||
| 0ab786b24a | |||
| ab9f73ba22 | |||
| 27f38718b1 | |||
| 2e6be68aaa |
@@ -2,6 +2,7 @@
|
|||||||
name: next-issue
|
name: next-issue
|
||||||
description: Wählt das nächste zu bearbeitende Gitea-Issue und gibt nur die Kerndaten zurück.
|
description: Wählt das nächste zu bearbeitende Gitea-Issue und gibt nur die Kerndaten zurück.
|
||||||
tools: mcp__gitea__list_issues, mcp__gitea__issue_read
|
tools: mcp__gitea__list_issues, mcp__gitea__issue_read
|
||||||
|
model: haiku
|
||||||
---
|
---
|
||||||
Finde das nächste offene Issue im Repo <owner>/<repo> mit Label `ai-ready`
|
Finde das nächste offene Issue im Repo <owner>/<repo> mit Label `ai-ready`
|
||||||
und NICHT mit Label `ai-wip` oder `ai-blocked`.
|
und NICHT mit Label `ai-wip` oder `ai-blocked`.
|
||||||
|
|||||||
@@ -4,12 +4,24 @@ argument-hint: <issue-nummer>
|
|||||||
allowed-tools: >
|
allowed-tools: >
|
||||||
Bash, Edit, Read, Write, Grep, Glob,
|
Bash, Edit, Read, Write, Grep, Glob,
|
||||||
mcp__gitea__issue_read, mcp__gitea__issue_write,
|
mcp__gitea__issue_read, mcp__gitea__issue_write,
|
||||||
|
mcp__gitea__label_read,
|
||||||
mcp__gitea__pull_request_write
|
mcp__gitea__pull_request_write
|
||||||
|
model: opus
|
||||||
---
|
---
|
||||||
Bearbeite Gitea-Issue #$1 im aktuellen Repo. Schritt für Schritt:
|
Bearbeite Gitea-Issue #$1 im aktuellen Repo. Schritt für Schritt:
|
||||||
|
|
||||||
|
**Label-Regeln (wichtig):** Die Gitea-Label-API arbeitet mit numerischen
|
||||||
|
Label-IDs, nicht mit Namen. Hole daher ZUERST einmalig die Label-Liste über
|
||||||
|
`label_read` (`method: list_repo_labels`) und merke dir die Zuordnung
|
||||||
|
Name → ID für die gesamte Bearbeitung. Verwende ausschließlich `add_labels`
|
||||||
|
(mit `labels: [<id>]`) und `remove_label` (mit `label_id: <id>`).
|
||||||
|
Niemals `replace_labels` oder `clear_labels` benutzen — das löscht alle
|
||||||
|
übrigen Labels des Issues (z.B. `prio/*`).
|
||||||
|
|
||||||
1. Lies Issue #$1 (Titel, Beschreibung, Kommentare) über `issue_read`.
|
1. Lies Issue #$1 (Titel, Beschreibung, Kommentare) über `issue_read`.
|
||||||
2. Setze Label `ai-wip` via `issue_write`, entferne `ai-ready`.
|
Notiere die aktuell gesetzten Labels, damit du sie nicht verlierst.
|
||||||
|
2. Hole die Label-Liste via `label_read`. Setze Label `ai-wip`
|
||||||
|
(`add_labels`), entferne `ai-ready` (`remove_label`).
|
||||||
3. Analysiere das Repo und finde die Ursache. Wenn der Scope zu groß/unklar
|
3. Analysiere das Repo und finde die Ursache. Wenn der Scope zu groß/unklar
|
||||||
ist (siehe CLAUDE.md), brich ab: kommentiere das Issue mit einer kurzen
|
ist (siehe CLAUDE.md), brich ab: kommentiere das Issue mit einer kurzen
|
||||||
Begründung, setze `ai-blocked`, und beende ohne Codeänderung.
|
Begründung, setze `ai-blocked`, und beende ohne Codeänderung.
|
||||||
@@ -20,4 +32,9 @@ Bearbeite Gitea-Issue #$1 im aktuellen Repo. Schritt für Schritt:
|
|||||||
7. Push den aktuellen Branch zum Remote.
|
7. Push den aktuellen Branch zum Remote.
|
||||||
8. Öffne via `pull_request_write` einen PR gegen `main` (bzw. `develop`).
|
8. Öffne via `pull_request_write` einen PR gegen `main` (bzw. `develop`).
|
||||||
Die PR-Beschreibung MUSS `Closes #$1` enthalten.
|
Die PR-Beschreibung MUSS `Closes #$1` enthalten.
|
||||||
9. Kommentiere am Issue mit dem PR-Link, setze Label `ai-review`.
|
9. Kommentiere am Issue mit dem PR-Link, setze Label `ai-review`
|
||||||
|
(`add_labels`) und entferne `ai-wip` (`remove_label`).
|
||||||
|
|
||||||
|
Wenn du in einem Schritt `ai-blocked` setzt, entferne ebenfalls `ai-wip`.
|
||||||
|
Existiert ein benötigtes Label nicht im Repo, kommentiere das am Issue statt
|
||||||
|
zu raten — erfinde keine Label-IDs.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Normalize line endings independent of core.autocrlf.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Maven wrapper: POSIX shell script must stay LF, even on Windows checkouts.
|
||||||
|
mvnw text eol=lf
|
||||||
|
*.sh text eol=lf
|
||||||
|
|
||||||
|
# Windows batch wrapper needs CRLF.
|
||||||
|
mvnw.cmd text eol=crlf
|
||||||
|
|
||||||
|
# Binaries: never convert.
|
||||||
|
*.jar binary
|
||||||
@@ -3,11 +3,11 @@ set -euo pipefail
|
|||||||
|
|
||||||
source .env
|
source .env
|
||||||
|
|
||||||
REPO_DIR="$HOME/code/dein-repo" # Haupt-Klon
|
REPO_DIR="$HOME/codebase/looptest" # Haupt-Klon
|
||||||
BASE_BRANCH="main"
|
BASE_BRANCH="main"
|
||||||
TEST_CMD="<dein Testkommando>" # z.B. ./gradlew test
|
TEST_CMD="./mvnw test" # z.B. ./gradlew test
|
||||||
MAX_ISSUES=5 # pro Durchlauf, damit du nicht davonläufst
|
MAX_ISSUES=5 # pro Durchlauf, damit du nicht davonläufst
|
||||||
POLL_INTERVAL=300 # Sekunden zwischen Polls (0 = einmal laufen)
|
POLL_INTERVAL=120 # Sekunden zwischen Polls (0 = einmal laufen)
|
||||||
|
|
||||||
cd "$REPO_DIR"
|
cd "$REPO_DIR"
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ process_next() {
|
|||||||
|
|
||||||
# 1) Nächstes Issue holen (Sub-Agent, minimaler Output)
|
# 1) Nächstes Issue holen (Sub-Agent, minimaler Output)
|
||||||
local out
|
local out
|
||||||
out=$(claude -p "Nutze den Sub-Agent 'next-issue'." \
|
out=$(claude -p "Nutze den Sub-Agent 'next-issue'. Gib NUR dessen Rueckgabezeile aus (ISSUE=<nr> oder ISSUE=NONE), keinen weiteren Text." \
|
||||||
--allowedTools "mcp__gitea__list_issues,mcp__gitea__issue_read" \
|
--allowedTools "Agent,mcp__gitea__list_issues,mcp__gitea__issue_read" \
|
||||||
--output-format text)
|
--output-format text)
|
||||||
local nr
|
local nr
|
||||||
nr=$(echo "$out" | grep -oE 'ISSUE=[0-9NONE]+' | cut -d= -f2)
|
nr=$(echo "$out" | grep -oE 'ISSUE=[0-9NONE]+' | cut -d= -f2)
|
||||||
@@ -40,7 +40,7 @@ process_next() {
|
|||||||
(
|
(
|
||||||
cd "$wt"
|
cd "$wt"
|
||||||
claude -p "/fix-issue $nr" \
|
claude -p "/fix-issue $nr" \
|
||||||
--allowedTools "Bash($TEST_CMD),Bash(git *),Edit,Read,Write,Grep,Glob,mcp__gitea__issue_read,mcp__gitea__issue_write,mcp__gitea__pull_request_write" \
|
--allowedTools "Bash($TEST_CMD),Bash(git *),Edit,Read,Write,Grep,Glob,mcp__gitea__issue_read,mcp__gitea__issue_write,mcp__gitea__label_read,mcp__gitea__pull_request_write" \
|
||||||
--output-format text
|
--output-format text
|
||||||
) || echo "!!! Worker für #$nr mit Fehler beendet"
|
) || echo "!!! Worker für #$nr mit Fehler beendet"
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
package com.example;
|
package com.example;
|
||||||
|
|
||||||
import com.example.util.AddFunction;
|
|
||||||
import com.example.util.CalcFunction;
|
import com.example.util.CalcFunction;
|
||||||
import com.example.util.MultiplyFunction;
|
import com.example.util.CalcFunctionFactory;
|
||||||
import com.example.util.SubtractFunction;
|
import com.example.util.CalcOperation;
|
||||||
|
|
||||||
public class LoopTestApplication {
|
public class LoopTestApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
static void main() {
|
||||||
System.out.println("============== Calculator =============");
|
System.out.println("============== Calculator =============");
|
||||||
CalcFunction add = new AddFunction();
|
for (CalcOperation operation : CalcOperation.values()) {
|
||||||
System.out.println("ADDITION: " + add.calc(2, 5, 6));
|
CalcFunction function = CalcFunctionFactory.create(operation);
|
||||||
CalcFunction subtract = new SubtractFunction();
|
System.out.println(operation + ": " + function.calc(2, 5, 6));
|
||||||
System.out.println("SUBTRACTION: " + subtract.calc(2, 5, 6));
|
}
|
||||||
CalcFunction multiply = new MultiplyFunction();
|
|
||||||
System.out.println("MULTIPLICATION: " + multiply.calc(2, 5, 6));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
public final class CalcFunctionFactory {
|
||||||
|
|
||||||
|
private CalcFunctionFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CalcFunction create(CalcOperation operation) {
|
||||||
|
if (operation == null) {
|
||||||
|
throw new IllegalArgumentException("Operation must not be null");
|
||||||
|
}
|
||||||
|
return switch (operation) {
|
||||||
|
case ADD -> new AddFunction();
|
||||||
|
case SUBTRACT -> new SubtractFunction();
|
||||||
|
case MULTIPLY -> new MultiplyFunction();
|
||||||
|
case DIVIDE -> new DivideFunction();
|
||||||
|
case POWER -> new PowerFunction();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
public enum CalcOperation {
|
||||||
|
|
||||||
|
ADD,
|
||||||
|
SUBTRACT,
|
||||||
|
MULTIPLY,
|
||||||
|
DIVIDE,
|
||||||
|
POWER
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
public class DivideFunction implements CalcFunction {
|
||||||
|
|
||||||
|
public double calc(double... input) {
|
||||||
|
if (input.length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
double result = input[0];
|
||||||
|
for (int i = 1; i < input.length; i++) {
|
||||||
|
if (input[i] == 0) {
|
||||||
|
throw new ArithmeticException("Division by zero");
|
||||||
|
}
|
||||||
|
result /= input[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
public class PowerFunction implements CalcFunction {
|
||||||
|
|
||||||
|
public double calc(double... input) {
|
||||||
|
if (input.length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
double result = input[0];
|
||||||
|
for (int i = 1; i < input.length; i++) {
|
||||||
|
result = Math.pow(result, input[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
class CalcFunctionFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsAddFunction() {
|
||||||
|
assertInstanceOf(AddFunction.class, CalcFunctionFactory.create(CalcOperation.ADD));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsSubtractFunction() {
|
||||||
|
assertInstanceOf(SubtractFunction.class, CalcFunctionFactory.create(CalcOperation.SUBTRACT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsMultiplyFunction() {
|
||||||
|
assertInstanceOf(MultiplyFunction.class, CalcFunctionFactory.create(CalcOperation.MULTIPLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsDivideFunction() {
|
||||||
|
assertInstanceOf(DivideFunction.class, CalcFunctionFactory.create(CalcOperation.DIVIDE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsPowerFunction() {
|
||||||
|
assertInstanceOf(PowerFunction.class, CalcFunctionFactory.create(CalcOperation.POWER));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsFunctionForEveryOperation() {
|
||||||
|
for (CalcOperation operation : CalcOperation.values()) {
|
||||||
|
assertNotNull(CalcFunctionFactory.create(operation), "No function for " + operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createdFunctionCalculates() {
|
||||||
|
assertEquals(13.0, CalcFunctionFactory.create(CalcOperation.ADD).calc(2.0, 5.0, 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsNullOperation() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> CalcFunctionFactory.create(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
class DivideFunctionTest {
|
||||||
|
|
||||||
|
private final DivideFunction divideFunction = new DivideFunction();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void dividesMultipleValues() {
|
||||||
|
assertEquals(2.0, divideFunction.calc(20.0, 5.0, 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returnsSingleValue() {
|
||||||
|
assertEquals(5.0, divideFunction.calc(5.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returnsZeroForNoInput() {
|
||||||
|
assertEquals(0.0, divideFunction.calc());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void dividesNegativeValues() {
|
||||||
|
assertEquals(-2.0, divideFunction.calc(4.0, -2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void throwsOnDivideByZero() {
|
||||||
|
assertThrows(ArithmeticException.class, () -> divideFunction.calc(5.0, 0.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.example.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class PowerFunctionTest {
|
||||||
|
|
||||||
|
private final PowerFunction powerFunction = new PowerFunction();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void raisesMultipleValuesLeftToRight() {
|
||||||
|
assertEquals(1073741824.0, powerFunction.calc(2.0, 5.0, 6.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returnsSingleValue() {
|
||||||
|
assertEquals(5.0, powerFunction.calc(5.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returnsZeroForNoInput() {
|
||||||
|
assertEquals(0.0, powerFunction.calc());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void raisesToNegativeExponent() {
|
||||||
|
assertEquals(0.25, powerFunction.calc(2.0, -2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void raisesToZeroExponent() {
|
||||||
|
assertEquals(1.0, powerFunction.calc(7.0, 0.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user