alissa-tools-github-revloop 0.31.7__tar.gz → 0.31.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {alissa_tools_github_revloop-0.31.7/src/main/alissa_tools_github_revloop.egg-info → alissa_tools_github_revloop-0.31.9}/PKG-INFO +1 -1
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/alissa.py +78 -3
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/loop.py +40 -1
- alissa_tools_github_revloop-0.31.9/src/main/alissa/tools/github/revloop/version +1 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9/src/main/alissa_tools_github_revloop.egg-info}/PKG-INFO +1 -1
- alissa_tools_github_revloop-0.31.7/src/main/alissa/tools/github/revloop/version +0 -1
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/LICENSE +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/MANIFEST.in +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/NOTICE +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/README.md +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/requirements.txt +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/setup.cfg +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/setup.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/__init__.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/__main__.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/alissa_client.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/bows.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/config.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/fleet_vitals.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/ghclient.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/loop_events.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/proc.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/prompts.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/prreview.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/state.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/trust.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/version.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/__init__.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/__main__.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/auth.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/page.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/server.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/sources.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa/tools/github/revloop/webui/sysinfo.py +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa_tools_github_revloop.egg-info/SOURCES.txt +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa_tools_github_revloop.egg-info/dependency_links.txt +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa_tools_github_revloop.egg-info/entry_points.txt +0 -0
- {alissa_tools_github_revloop-0.31.7 → alissa_tools_github_revloop-0.31.9}/src/main/alissa_tools_github_revloop.egg-info/top_level.txt +0 -0
|
@@ -219,6 +219,30 @@ def _advertises(helptext: str, flag: str) -> bool:
|
|
|
219
219
|
) is not None
|
|
220
220
|
|
|
221
221
|
|
|
222
|
+
# The two spawn stamps of the Studio loop cost meter (studio.alissa.app
|
|
223
|
+
# docs/design/loop-cost-meter.md §2.3, §2.4, lane L4; issue #153, the port of
|
|
224
|
+
# devloop's issue #149): `--task` names the ORIGIN task the reviewer serves and
|
|
225
|
+
# `--repo` the canonical lowercase `owner/name`, so the session row carries
|
|
226
|
+
# `focusTaskId` and `repo` from its first second. The reviewer's skill then
|
|
227
|
+
# re-anchors `current_task` on its review task and that write wins the focus;
|
|
228
|
+
# the origin keeps its `code_session` evidence row and the meter resolves the
|
|
229
|
+
# rest at read time (§2.4).
|
|
230
|
+
QUEUE_ADD_TASK_FLAG = "--task"
|
|
231
|
+
QUEUE_ADD_REPO_FLAG = "--repo"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def queue_add_accepts_stamps(helptext: str) -> bool:
|
|
235
|
+
"""Whether `alissa tmux queue add --help` lists BOTH `--task` and `--repo`.
|
|
236
|
+
|
|
237
|
+
Both or neither: the CLI this daemon shipped against (0.3.0) already lists
|
|
238
|
+
`-t, --task <ref>`, but with the older meaning -- link a queue item for
|
|
239
|
+
shell write-back -- and has no `--repo`; that CLI is not the stamp-aware
|
|
240
|
+
one, so it gets neither flag.
|
|
241
|
+
"""
|
|
242
|
+
text = helptext or ""
|
|
243
|
+
return _advertises(text, QUEUE_ADD_TASK_FLAG) and _advertises(text, QUEUE_ADD_REPO_FLAG)
|
|
244
|
+
|
|
245
|
+
|
|
222
246
|
# CR6 verdict envelope outcomes.
|
|
223
247
|
VERDICT_APPROVE = "approve"
|
|
224
248
|
VERDICT_REQUEST_CHANGES = "request_changes"
|
|
@@ -879,6 +903,9 @@ class Alissa:
|
|
|
879
903
|
# One diagnostic per client for a status filter that could not be sent
|
|
880
904
|
# (see `_warn_status_filter_dropped`); this path runs every poll pass.
|
|
881
905
|
self._status_filter_warned = False
|
|
906
|
+
# The spawn-stamp probe's answer, memoized like `_task_list_flags`;
|
|
907
|
+
# None = not probed yet (or the last probe could not run).
|
|
908
|
+
self._spawn_stamps_accepted: "bool | None" = None
|
|
882
909
|
|
|
883
910
|
@property
|
|
884
911
|
def task_list_bow_id(self) -> "str | None":
|
|
@@ -1385,6 +1412,37 @@ class Alissa:
|
|
|
1385
1412
|
break
|
|
1386
1413
|
return count
|
|
1387
1414
|
|
|
1415
|
+
# -- the `alissa tmux queue add` spawn-stamp probe -----------------------
|
|
1416
|
+
|
|
1417
|
+
def accepts_spawn_stamps(self) -> bool:
|
|
1418
|
+
"""Whether the installed `queue add` takes `--task` AND `--repo`.
|
|
1419
|
+
|
|
1420
|
+
Read off the CLI's own `--help`, for the reasons `probe_task_list`
|
|
1421
|
+
gives. An answer, yes or no, is memoized for the process; a probe that
|
|
1422
|
+
cannot run at all reads as "no" for THIS spawn and is not memoized, so
|
|
1423
|
+
a transient failure never switches the stamps off until a restart.
|
|
1424
|
+
"""
|
|
1425
|
+
if self._spawn_stamps_accepted is not None:
|
|
1426
|
+
return self._spawn_stamps_accepted
|
|
1427
|
+
try:
|
|
1428
|
+
helptext = run(["alissa", "tmux", "queue", "add", "--help"], timeout=20)
|
|
1429
|
+
except CommandError as exc:
|
|
1430
|
+
log.warning(
|
|
1431
|
+
"could not probe `alissa tmux queue add --help` (%s) — this "
|
|
1432
|
+
"reviewer is enqueued without --task/--repo", exc,
|
|
1433
|
+
)
|
|
1434
|
+
return False
|
|
1435
|
+
except Exception: # pragma: no cover - defence in depth
|
|
1436
|
+
log.exception("unexpected failure probing `alissa tmux queue add --help`")
|
|
1437
|
+
return False
|
|
1438
|
+
self._spawn_stamps_accepted = queue_add_accepts_stamps(helptext)
|
|
1439
|
+
if not self._spawn_stamps_accepted:
|
|
1440
|
+
log.info(
|
|
1441
|
+
"the installed alissa CLI does not accept `queue add --task/--repo`; "
|
|
1442
|
+
"reviewer spawns go unstamped"
|
|
1443
|
+
)
|
|
1444
|
+
return self._spawn_stamps_accepted
|
|
1445
|
+
|
|
1388
1446
|
def enqueue_reviewer(
|
|
1389
1447
|
self,
|
|
1390
1448
|
*,
|
|
@@ -1393,8 +1451,18 @@ class Alissa:
|
|
|
1393
1451
|
cwd: Path,
|
|
1394
1452
|
agent: str,
|
|
1395
1453
|
task_ref: str | None,
|
|
1454
|
+
repo: str | None = None,
|
|
1396
1455
|
dry_run: bool = False,
|
|
1397
1456
|
) -> None:
|
|
1457
|
+
"""Enqueue one reviewer session.
|
|
1458
|
+
|
|
1459
|
+
`task_ref` is the ORIGIN task (`TASK-<n>`) the round serves -- not the
|
|
1460
|
+
review task, which the directive names and the ledger records -- and
|
|
1461
|
+
`repo` the PR's `owner/name`, lowercased here. They are passed as
|
|
1462
|
+
`--task` / `--repo` only when the installed CLI accepts both (see
|
|
1463
|
+
`accepts_spawn_stamps`); an older CLI gets neither, so the enqueue
|
|
1464
|
+
never fails for want of a stamp.
|
|
1465
|
+
"""
|
|
1398
1466
|
argv = [
|
|
1399
1467
|
"alissa",
|
|
1400
1468
|
"tmux",
|
|
@@ -1406,14 +1474,21 @@ class Alissa:
|
|
|
1406
1474
|
"--cwd",
|
|
1407
1475
|
str(cwd),
|
|
1408
1476
|
]
|
|
1477
|
+
stamps: "list[str]" = []
|
|
1409
1478
|
if task_ref:
|
|
1410
|
-
|
|
1411
|
-
|
|
1479
|
+
stamps += [QUEUE_ADD_TASK_FLAG, task_ref]
|
|
1480
|
+
if repo:
|
|
1481
|
+
stamps += [QUEUE_ADD_REPO_FLAG, repo.lower()]
|
|
1412
1482
|
|
|
1413
1483
|
if dry_run:
|
|
1414
|
-
|
|
1484
|
+
# Runs nothing, the probe included: the line shows the stamps a
|
|
1485
|
+
# stamp-aware CLI would receive.
|
|
1486
|
+
log.info("[dry-run] would enqueue: %s", " ".join(argv + stamps) + " <directive>")
|
|
1415
1487
|
return
|
|
1416
1488
|
|
|
1489
|
+
if stamps and self.accepts_spawn_stamps():
|
|
1490
|
+
argv += stamps
|
|
1491
|
+
argv.append(directive)
|
|
1417
1492
|
run(argv, timeout=60)
|
|
1418
1493
|
|
|
1419
1494
|
# Reviewers are one-shot per round (CR3): once the session finishes and is
|
|
@@ -1215,6 +1215,44 @@ def plan_id_of(pr: PullRequest) -> "str | None":
|
|
|
1215
1215
|
return match.group(1) if match else None
|
|
1216
1216
|
|
|
1217
1217
|
|
|
1218
|
+
# The ORIGIN task a reviewer spawn is stamped with (`--task`, issue #153; the
|
|
1219
|
+
# Studio cost meter's lane L4). First from the review task's CR2 title --
|
|
1220
|
+
# `Review PR <org>/<repo>#<n> (TASK-<origin>)` -- then from the PR body, the
|
|
1221
|
+
# way devloop's `pr_origin_task_ref` reads it (issue #149 there): the
|
|
1222
|
+
# `Alissa-Task:` trailer, then the worker's own `Origin task:` / `Origin Alissa
|
|
1223
|
+
# task:` line (both spellings are on live bodies). There is deliberately NO
|
|
1224
|
+
# `Implementation task:` fallback -- the stamp claims the session serves the
|
|
1225
|
+
# origin, and a downstream task is not one. A plan's review title carries a
|
|
1226
|
+
# plan id, not a task, so a plan PR normally resolves to None.
|
|
1227
|
+
_REVIEW_TITLE_ORIGIN_RE = re.compile(r"\(\s*TASK-(\d+)\s*\)", re.IGNORECASE)
|
|
1228
|
+
_BODY_ORIGIN_TASK_RES = tuple(
|
|
1229
|
+
re.compile(rf"{key}\**\s*:\**\s*`?TASK-(\d+)", re.IGNORECASE)
|
|
1230
|
+
for key in (r"Alissa-Task", r"Origin(?:\s+Alissa)?\s+task")
|
|
1231
|
+
)
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
def pr_origin_task_ref(body: str) -> "str | None":
|
|
1235
|
+
"""`TASK-<n>` for the origin task a PR body names, or None."""
|
|
1236
|
+
text = body or ""
|
|
1237
|
+
for pattern in _BODY_ORIGIN_TASK_RES:
|
|
1238
|
+
match = pattern.search(text)
|
|
1239
|
+
if match:
|
|
1240
|
+
return f"TASK-{match.group(1)}"
|
|
1241
|
+
return None
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
def review_origin_task_ref(task: "Task | None", pr: PullRequest) -> "str | None":
|
|
1245
|
+
"""The origin `TASK-<n>` a reviewer round serves, or None -- in which case
|
|
1246
|
+
the spawn is stamped with `--repo` alone. The review task's title wins
|
|
1247
|
+
over the PR body: it is the one the CR2 convention writes, and a round
|
|
1248
|
+
with no review task yet (spawn_anyway) still has the body to go on."""
|
|
1249
|
+
if task is not None:
|
|
1250
|
+
match = _REVIEW_TITLE_ORIGIN_RE.search(task.title or "")
|
|
1251
|
+
if match:
|
|
1252
|
+
return f"TASK-{match.group(1)}"
|
|
1253
|
+
return pr_origin_task_ref(pr.body)
|
|
1254
|
+
|
|
1255
|
+
|
|
1218
1256
|
def plan_review_task_title(pr: PullRequest) -> str:
|
|
1219
1257
|
"""The CR2 title of a plan PR's review task (design §6.1)."""
|
|
1220
1258
|
return f"Review plan {pr.slug} ({plan_id_of(pr) or '<plan id>'})"
|
|
@@ -5851,7 +5889,8 @@ class ReviewWatcher:
|
|
|
5851
5889
|
directive=directive,
|
|
5852
5890
|
cwd=hub,
|
|
5853
5891
|
agent=self.config.agent_profile,
|
|
5854
|
-
task_ref=task
|
|
5892
|
+
task_ref=review_origin_task_ref(task, pr),
|
|
5893
|
+
repo=pr.full_name,
|
|
5855
5894
|
dry_run=self.config.dry_run,
|
|
5856
5895
|
)
|
|
5857
5896
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.31.9
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.31.7
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|