Conversations on the new loop (M2.5, PR A)
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 5m14s
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 5m14s
- A top-level message that isn't a command is a conversation: an item in the `general` scope (L1), threaded under the operator's message, with `reply`, `ask_human` and `propose_work` and no workspace or execution. `general` is reserved as a project name. - propose_work(project, title, summary) goes up as a revision for a go-ahead (or a plain yes). On go, under a file_issue intent (L8), the record issue is opened in that project, assigned to the agent and carrying the new item's ID; its item starts agreed, with the summary as its brief. Intake skips any issue carrying an ID (D1); boot adopts a filed issue or puts the proposal up again. - A conversation closes after tuning.loop.general_idle_s (default a day); a reply in its thread then starts a new conversation that continues it. Tests: conversation unit tests (threading, filing, the marker, an unknown project, changes, idle close and continuation, a plain yes, both crash cases, commands at top level); the walk with conversations, proposals and idle time, and records_have_one_item / conversations_do_no_work; an e2e conversation that becomes filed work. 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
d70d43a8cc
commit
3f54896f65
14 files changed
+811
-35
No files matched your search
@@ -68,6 +68,7 @@ PROJECT_OPTIONAL = (
|
||||
# never in a command the model chose.
|
||||
VISIBILITY = ("commands", "harness")
|
||||
_PROJECT_NAME = re.compile(r"[a-z0-9][a-z0-9-]*")
|
||||
GENERAL = "general" # the scope of conversation not about a project (L1)
|
||||
|
||||
_REFERENCE = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}")
|
||||
|
||||
@@ -116,6 +117,8 @@ class LoopTuning:
|
||||
# A restatement on a `bug` issue proceeds after this long without a
|
||||
# reply (D1).
|
||||
bug_grace_s: float = 600.0
|
||||
# A `general` conversation closes after this long without a message (L1).
|
||||
general_idle_s: float = 86400.0
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -247,6 +250,9 @@ def _parse_projects(
|
||||
if not isinstance(name, str) or not _PROJECT_NAME.fullmatch(name):
|
||||
errors.append(f"{where}: a project name is lowercase letters, digits, -")
|
||||
continue
|
||||
if name == GENERAL:
|
||||
errors.append(f"{where}: `{GENERAL}` is the scope of conversations (L1)")
|
||||
continue
|
||||
if not isinstance(entry, dict):
|
||||
errors.append(f"{where}: must be a mapping")
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user