quill: add issue-to-draft brief and retry_decorator sample
This commit is contained in:
1 parent
cdf6828fe0
commit
ef9f0380da
2 files changed
+91
No files matched your search
@@ -0,0 +1,56 @@
|
|||||||
|
# Issue-to-Draft Brief
|
||||||
|
|
||||||
|
A reusable template that converts a structured issue spec into a ready-to-run task brief for a Draft-lane agent.
|
||||||
|
|
||||||
|
## Input Contract
|
||||||
|
- **issue_id**: str
|
||||||
|
- **title**: str
|
||||||
|
- **acceptance_criteria**: list[str]
|
||||||
|
- **constraints**: list[str] (optional)
|
||||||
|
- **context**: str (optional)
|
||||||
|
|
||||||
|
## Output Contract
|
||||||
|
A single markdown file containing:
|
||||||
|
1. Goal (1 sentence)
|
||||||
|
2. Scope (bullets from acceptance criteria)
|
||||||
|
3. Constraints (bullets, or "none")
|
||||||
|
4. Artifact path (where the deliverable lives)
|
||||||
|
5. Verdict template (one-line + CHECK command)
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
- No filler, no hedging.
|
||||||
|
- Plain claims over adjectives.
|
||||||
|
- If a claim is unmeasured, mark it `[CLAIMED]`.
|
||||||
|
- End with `VERDICT:` line and `CHECK:` line (exit code 0 = correct).
|
||||||
|
|
||||||
|
## Sample Filled Brief
|
||||||
|
|
||||||
|
**Input:**
|
||||||
|
- issue_id: DRAFT-7
|
||||||
|
- title: Add retry decorator to http client
|
||||||
|
- acceptance_criteria:
|
||||||
|
- decorator retries 3x on 5xx
|
||||||
|
- exponential backoff capped at 5s
|
||||||
|
- type hints present
|
||||||
|
- constraints: stdlib only, <80 LOC
|
||||||
|
- context: replaces ad-hoc retry loop in main.py
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
GOAL: Add a stdlib-only retry decorator for 5xx errors with 3 attempts and exponential backoff capped at 5 seconds.
|
||||||
|
|
||||||
|
SCOPE:
|
||||||
|
- Decorator with 3-attempt retry on 5xx
|
||||||
|
- Exponential backoff (1s, 2s, 5s cap)
|
||||||
|
- Type hints on all public callables
|
||||||
|
- Remove ad-hoc retry loop from main.py
|
||||||
|
|
||||||
|
CONSTRAINTS:
|
||||||
|
- stdlib only
|
||||||
|
- <80 LOC
|
||||||
|
|
||||||
|
ARTIFACT: /root/.hermes/wizard-outputs/quill/retry_decorator.py
|
||||||
|
|
||||||
|
VERDICT: Decorator implemented, tested, and under 80 LOC.
|
||||||
|
|
||||||
|
CHECK: python /root/.hermes/wizard-outputs/quill/verify.py
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""Stdlib-only retry decorator for 5xx errors.
|
||||||
|
|
||||||
|
Exponential backoff: 1s, 2s, 5s cap. 3 attempts max.
|
||||||
|
Type hints on all public callables. <80 LOC.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
import functools
|
||||||
|
from typing import TypeVar, Callable, ParamSpec
|
||||||
|
|
||||||
|
P = ParamSpec("P")
|
||||||
|
R = TypeVar("R")
|
||||||
|
|
||||||
|
|
||||||
|
def retry_on_5xx(max_attempts: int = 3, base_delay: float = 1.0, cap: float = 5.0) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
||||||
|
"""Decorator: retry wrapped callable on 5xx up to max_attempts times."""
|
||||||
|
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
||||||
|
delay = base_delay
|
||||||
|
last_exc: BaseException | None = None
|
||||||
|
for attempt in range(1, max_attempts + 1):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except Exception as exc:
|
||||||
|
last_exc = exc
|
||||||
|
status = getattr(exc, "status", None)
|
||||||
|
if not (isinstance(status, int) and 500 <= status < 600):
|
||||||
|
raise
|
||||||
|
if attempt == max_attempts:
|
||||||
|
break
|
||||||
|
time.sleep(delay)
|
||||||
|
delay = min(delay * 2, cap)
|
||||||
|
raise last_exc # type: ignore[misc]
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
Reference in new issue
Block a user