Threads, commands and labels on the new loop (M2.3)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 3m45s
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 3m45s
- Commands that name their item ("go #14", "abandon #14", "stop #14")
apply to it wherever they're said; go, approve and abandon alone at top
level are asked about (L5). stop is never taken as an answer.
- A plain-language reply to a restatement is read by GoAheadReader, one
model call that agrees only on a clear yes; questions never reach it. The
agent says "taking that as a go-ahead on rev-N" first, bound to the
revision on screen at arrival (L3, L5, D1).
- Labels steer (D1): `bug` goes ahead after tuning.loop.bug_grace_s
(default 600 s) unless the operator replies; `discuss` isn't offered
restate until the operator has spoken; `bug`, `discuss` and `design` add
to the driver's instructions. A restatement asks no questions.
Tests: label and command unit tests, the property walk with labelled
issues, plain yeses, named gos and time passing (grace_only_unanswered,
discuss_talks_first), and e2e tests for a bug proceeding after its grace
period and a plain-language go-ahead.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
1 parent
a504526da2
commit
4d9c1d7529
13 files changed
+793
-35
No files matched your search
@@ -72,12 +72,18 @@ def issue(number: int = 14, author: str = "don", **kw: Any) -> Issue:
|
||||
title=kw.get("title", "Add count_words"),
|
||||
body=kw.get("body", "count words in a string"),
|
||||
author=author,
|
||||
labels=(),
|
||||
labels=kw.get("labels", ()),
|
||||
)
|
||||
|
||||
|
||||
class Harness:
|
||||
def __init__(self, tmp_path: Path, model: ScriptedModel, gitea: FakeGitea) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
tmp_path: Path,
|
||||
model: ScriptedModel,
|
||||
gitea: FakeGitea,
|
||||
**agent: Any, # more LoopAgent arguments: reader, clock, ...
|
||||
) -> None:
|
||||
tmp_path.mkdir(parents=True, exist_ok=True)
|
||||
self.store = StateStore(
|
||||
tmp_path / "state.db", oplog=OpLog("nisse-dev", io.StringIO())
|
||||
@@ -100,6 +106,7 @@ class Harness:
|
||||
worker=InlineWorker(),
|
||||
cancel=self.cancel,
|
||||
oplog=OpLog("nisse-dev", io.StringIO()),
|
||||
**agent,
|
||||
)
|
||||
self.transport.on_message(self.agent.on_message)
|
||||
|
||||
@@ -215,7 +222,8 @@ def test_a_go_at_top_level_is_not_a_go_ahead(h: Harness) -> None:
|
||||
h.agent.intake()
|
||||
h.say("go", thread=None)
|
||||
assert not loop_of(h.item()).started
|
||||
assert "assign one and I'll pick it up" in h.posted()[-1]
|
||||
# L5: an unnamed command at top level is ambiguous, so it asks.
|
||||
assert "Which item?" in h.posted()[-1] and "#14" in h.posted()[-1]
|
||||
|
||||
|
||||
# --- waiting points (L2) -------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user