alissa-tools-github-devloop 0.8.34__tar.gz → 0.8.36__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.
Files changed (38) hide show
  1. {alissa_tools_github_devloop-0.8.34/src/main/alissa_tools_github_devloop.egg-info → alissa_tools_github_devloop-0.8.36}/PKG-INFO +1 -1
  2. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/alissa.py +57 -2
  3. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/loop.py +30 -0
  4. alissa_tools_github_devloop-0.8.36/src/main/alissa/tools/github/devloop/version +1 -0
  5. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36/src/main/alissa_tools_github_devloop.egg-info}/PKG-INFO +1 -1
  6. alissa_tools_github_devloop-0.8.34/src/main/alissa/tools/github/devloop/version +0 -1
  7. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/LICENSE +0 -0
  8. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/MANIFEST.in +0 -0
  9. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/NOTICE +0 -0
  10. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/README.md +0 -0
  11. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/requirements.txt +0 -0
  12. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/setup.cfg +0 -0
  13. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/setup.py +0 -0
  14. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/__init__.py +0 -0
  15. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/__main__.py +0 -0
  16. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/alissa_client.py +0 -0
  17. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/bows.py +0 -0
  18. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/config.py +0 -0
  19. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/fleet_vitals.py +0 -0
  20. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/ghclient.py +0 -0
  21. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/hubs.py +0 -0
  22. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/janitor.py +0 -0
  23. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/loop_events.py +0 -0
  24. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/proc.py +0 -0
  25. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/prompts.py +0 -0
  26. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/state.py +0 -0
  27. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/version.py +0 -0
  28. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/__init__.py +0 -0
  29. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/__main__.py +0 -0
  30. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/auth.py +0 -0
  31. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/page.py +0 -0
  32. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/server.py +0 -0
  33. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/sources.py +0 -0
  34. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa/tools/github/devloop/webui/sysinfo.py +0 -0
  35. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa_tools_github_devloop.egg-info/SOURCES.txt +0 -0
  36. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa_tools_github_devloop.egg-info/dependency_links.txt +0 -0
  37. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa_tools_github_devloop.egg-info/entry_points.txt +0 -0
  38. {alissa_tools_github_devloop-0.8.34 → alissa_tools_github_devloop-0.8.36}/src/main/alissa_tools_github_devloop.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alissa-tools-github-devloop
3
- Version: 0.8.34
3
+ Version: 0.8.36
4
4
  Summary: ALISSA-TOOLS-GITHUB-DEVLOOP
5
5
  Home-page: https://alissa.app
6
6
  Author: Fahera
@@ -116,7 +116,49 @@ def send_keys_argv(name: str, keys: "tuple[str, ...]") -> "list[str]":
116
116
  return ["tmux", "-S", tmux_socket(), "send-keys", "-t", tmux_target(name), *keys]
117
117
 
118
118
 
119
+ # The two spawn stamps of the Studio cost meter (loop-cost-meter.md §2.3,
120
+ # §2.4, issue #149): `--task` names the ORIGIN task the session serves and
121
+ # `--repo` the canonical lowercase `owner/name`, so the session row carries
122
+ # `focusTaskId` and `repo` from its first second. Each flag is matched as a
123
+ # whole option token in `alissa tmux queue add --help`.
124
+ _TASK_FLAG_RE = re.compile(r"(?<![\w-])--task(?![\w-])")
125
+ _REPO_FLAG_RE = re.compile(r"(?<![\w-])--repo(?![\w-])")
126
+
127
+
128
+ def queue_add_accepts_stamps(help_text: str) -> bool:
129
+ """True when `alissa tmux queue add --help` lists BOTH `--task` and
130
+ `--repo`. Both or neither: a CLI with `--task` alone predates the stamp
131
+ (its `--task` links a queue item for shell write-back, and the session
132
+ row has no `repo` to fill), so it gets neither flag."""
133
+ text = help_text or ""
134
+ return bool(_TASK_FLAG_RE.search(text) and _REPO_FLAG_RE.search(text))
135
+
136
+
119
137
  class Alissa:
138
+ def __init__(self) -> None:
139
+ # The stamp probe's verdict, read once per process (one Alissa per
140
+ # watcher, one watcher per daemon): None until a probe has answered.
141
+ self._stamps_accepted: "bool | None" = None
142
+
143
+ def accepts_spawn_stamps(self) -> bool:
144
+ """Whether the installed CLI's `queue add` takes `--task`/`--repo`.
145
+ Probed once and cached; a probe that cannot run at all (a timeout,
146
+ a missing binary) reads as "no" for THIS spawn and is not cached, so
147
+ a transient failure never switches the stamps off for good."""
148
+ if self._stamps_accepted is None:
149
+ try:
150
+ out = run(["alissa", "tmux", "queue", "add", "--help"],
151
+ timeout=30, check=False)
152
+ except (CommandError, OSError) as exc:
153
+ log.warning("could not probe `alissa tmux queue add --help` "
154
+ "(%s); enqueuing without --task/--repo", exc)
155
+ return False
156
+ self._stamps_accepted = queue_add_accepts_stamps(out)
157
+ if not self._stamps_accepted:
158
+ log.info("the installed alissa CLI does not accept "
159
+ "`queue add --task/--repo`; spawns go unstamped")
160
+ return self._stamps_accepted
161
+
120
162
  def enqueue_developer(
121
163
  self,
122
164
  *,
@@ -124,8 +166,14 @@ class Alissa:
124
166
  directive: str,
125
167
  cwd: Path,
126
168
  agent: str,
169
+ task_ref: "str | None" = None,
170
+ repo: "str | None" = None,
127
171
  dry_run: bool = False,
128
172
  ) -> None:
173
+ """Enqueue the session. `task_ref` (the ORIGIN task, `TASK-<n>`) and
174
+ `repo` (`owner/name`, lowercased here) are passed as `--task` /
175
+ `--repo` only when the installed CLI accepts both; an older CLI gets
176
+ neither, so the enqueue never fails for want of a stamp."""
129
177
  argv = [
130
178
  "alissa",
131
179
  "tmux",
@@ -136,13 +184,20 @@ class Alissa:
136
184
  agent,
137
185
  "--cwd",
138
186
  str(cwd),
139
- directive,
140
187
  ]
188
+ stamps: "list[str]" = []
189
+ if task_ref:
190
+ stamps += ["--task", task_ref]
191
+ if repo:
192
+ stamps += ["--repo", repo.lower()]
141
193
 
142
194
  if dry_run:
143
- log.info("[dry-run] would enqueue: %s", " ".join(argv[:-1]) + " <directive>")
195
+ log.info("[dry-run] would enqueue: %s", " ".join(argv + stamps) + " <directive>")
144
196
  return
145
197
 
198
+ if stamps and self.accepts_spawn_stamps():
199
+ argv += stamps
200
+ argv.append(directive)
146
201
  run(argv, timeout=60)
147
202
 
148
203
  # Developers are one-shot per attempt: a finished (or dead) session must
@@ -2366,6 +2366,28 @@ def revert_task_number(body: str) -> int:
2366
2366
  return 0
2367
2367
 
2368
2368
 
2369
+ # The ORIGIN task as a PR body names it, for the spawn stamp (issue #149):
2370
+ # the `Alissa-Task:` trailer first, then the worker's own `Origin task:` /
2371
+ # `Origin Alissa task:` line (both spellings are on live bodies). Unlike
2372
+ # REVERT_TASK_KEYS there is NO `Implementation task:` fallback -- the stamp
2373
+ # claims the session serves the origin, and a downstream task is not one.
2374
+ _ORIGIN_TASK_RES = tuple(
2375
+ re.compile(rf"{key}\**\s*:\**\s*`?TASK-(\d+)", re.IGNORECASE)
2376
+ for key in (r"Alissa-Task", r"Origin(?:\s+Alissa)?\s+task")
2377
+ )
2378
+
2379
+
2380
+ def pr_origin_task_ref(body: str) -> "str | None":
2381
+ """`TASK-<n>` for the origin task a PR body names, or None -- in which
2382
+ case the fix, maintain and revert edges spawn unstamped."""
2383
+ text = body or ""
2384
+ for pattern in _ORIGIN_TASK_RES:
2385
+ match = pattern.search(text)
2386
+ if match:
2387
+ return f"TASK-{match.group(1)}"
2388
+ return None
2389
+
2390
+
2369
2391
  def revert_branch(task_number: int, pr_number: int) -> str:
2370
2392
  """`TASK-<n>-REVERT-PR<k>`: the revert branch's name, a `TASK-<n>-<DESC>`
2371
2393
  shape by construction so the fix and maintain edges spawn on it."""
@@ -4065,6 +4087,8 @@ class DevWatcher:
4065
4087
  directive=directive,
4066
4088
  cwd=hub,
4067
4089
  agent=self.config.agent_profile,
4090
+ task_ref=task_ref,
4091
+ repo=issue.full_name,
4068
4092
  dry_run=self.config.dry_run,
4069
4093
  )
4070
4094
 
@@ -7330,6 +7354,8 @@ class DevWatcher:
7330
7354
  directive=directive,
7331
7355
  cwd=hub,
7332
7356
  agent=self.config.agent_profile,
7357
+ task_ref=pr_origin_task_ref(pr.body),
7358
+ repo=pr.full_name,
7333
7359
  dry_run=self.config.dry_run,
7334
7360
  )
7335
7361
 
@@ -7595,6 +7621,8 @@ class DevWatcher:
7595
7621
  directive=directive,
7596
7622
  cwd=hub,
7597
7623
  agent=self.config.agent_profile,
7624
+ task_ref=pr_origin_task_ref(pr.body),
7625
+ repo=pr.full_name,
7598
7626
  dry_run=self.config.dry_run,
7599
7627
  )
7600
7628
 
@@ -7985,6 +8013,8 @@ class DevWatcher:
7985
8013
  directive=directive,
7986
8014
  cwd=hub,
7987
8015
  agent=self.config.agent_profile,
8016
+ task_ref=pr_origin_task_ref(pr.body),
8017
+ repo=pr.full_name,
7988
8018
  dry_run=self.config.dry_run,
7989
8019
  )
7990
8020
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alissa-tools-github-devloop
3
- Version: 0.8.34
3
+ Version: 0.8.36
4
4
  Summary: ALISSA-TOOLS-GITHUB-DEVLOOP
5
5
  Home-page: https://alissa.app
6
6
  Author: Fahera