alissa-tools-github-devloop 0.8.57__py3-none-any.whl → 0.8.59__py3-none-any.whl
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/devloop/loop.py +231 -8
- alissa/tools/github/devloop/loop_events.py +1 -1
- alissa/tools/github/devloop/state.py +17 -0
- alissa/tools/github/devloop/version +1 -1
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/METADATA +1 -1
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/RECORD +11 -11
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/WHEEL +1 -1
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/entry_points.txt +0 -0
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/licenses/LICENSE +0 -0
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/licenses/NOTICE +0 -0
- {alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/top_level.txt +0 -0
|
@@ -516,6 +516,44 @@ from .state import State
|
|
|
516
516
|
|
|
517
517
|
log = logging.getLogger(__name__)
|
|
518
518
|
|
|
519
|
+
# The criteria-typing rule (issue #194). orcloop ticks only `evidence`
|
|
520
|
+
# criteria when a PR merges, and the soft validator answers "needs a human"
|
|
521
|
+
# for every `human` one -- so a worker that types a FACT ("PR ready for
|
|
522
|
+
# review", "screenshots committed") as `human` parks its task at
|
|
523
|
+
# pending_validation forever (TASK-183426950, PR #2652: 103 fleet tasks piled
|
|
524
|
+
# up and the backlog brake paused every release). The worker picks the type,
|
|
525
|
+
# so the directive must say how: by who can close the criterion. The
|
|
526
|
+
# operator-gate list stays out of the criteria because orcloop already
|
|
527
|
+
# harvests it from the PR body into the origin task's "Needs a look"
|
|
528
|
+
# checklist; copied in, it would turn every unverifiable item into a human
|
|
529
|
+
# criterion again. The legacy type words are deliberately never written here
|
|
530
|
+
# (a test pins their absence from every directive): naming them, even to
|
|
531
|
+
# forbid them, is how they get copied.
|
|
532
|
+
_CRITERIA_RULE = (
|
|
533
|
+
"Type every validation criterion on your implementation task by WHO CAN "
|
|
534
|
+
"CLOSE IT, writing the type as exactly one of `evidence`, `check` or "
|
|
535
|
+
"`human`: `evidence` is the default — it closes from what the PR, the "
|
|
536
|
+
"delivery note, a merged commit, a test run or a committed file shows "
|
|
537
|
+
"(orcloop ticks these on merge); `check`, with a `source`, when "
|
|
538
|
+
"a machine signal names it (`ci:<owner>/<repo>[#<check>]` for \"CI "
|
|
539
|
+
"green\"); `human` ONLY for a person's judgment (taste, a live phone "
|
|
540
|
+
"check, a pilot user, a decision) — and then say so in the criterion's "
|
|
541
|
+
"text. Facts are never `human`: \"PR ready / review requested / approved "
|
|
542
|
+
"/ merged\", \"tests X pass\", \"screenshots at <path> committed\", "
|
|
543
|
+
"\"doc section added\", \"delivery note registered\" are all "
|
|
544
|
+
"`evidence`. Never copy the PR body's \"Not verified — operator's gate\" "
|
|
545
|
+
"list into task criteria: orcloop harvests it into a \"Needs a look\" "
|
|
546
|
+
"checklist on the origin task by itself."
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
# The adopt half: a resumed or fix-round session inherits a task some other
|
|
550
|
+
# session typed, possibly before this rule existed.
|
|
551
|
+
_CRITERIA_ADOPT = (
|
|
552
|
+
" On a task you ADOPT, retype any criterion that breaks this rule (a fact "
|
|
553
|
+
"typed `human` becomes `evidence`), and type any criterion you add the "
|
|
554
|
+
"same way."
|
|
555
|
+
)
|
|
556
|
+
|
|
519
557
|
# The origin-task instruction is split in two because the downstream rule is
|
|
520
558
|
# the same either way -- only the starting point differs: a present ref is
|
|
521
559
|
# authoritative; an absent one (spawn_anyway / warn_and_spawn) makes locating
|
|
@@ -525,6 +563,8 @@ _TASK_WITH_ORIGIN = (
|
|
|
525
563
|
"implementation task DOWNSTREAM of it (create_downstream_task), and keep "
|
|
526
564
|
"its status honest: in_progress while you work, pending_validation at "
|
|
527
565
|
"handoff."
|
|
566
|
+
+ " "
|
|
567
|
+
+ _CRITERIA_RULE
|
|
528
568
|
)
|
|
529
569
|
|
|
530
570
|
_TASK_WITHOUT_ORIGIN = (
|
|
@@ -532,6 +572,8 @@ _TASK_WITHOUT_ORIGIN = (
|
|
|
532
572
|
"behind this issue, or create one, then create your implementation task "
|
|
533
573
|
"DOWNSTREAM of it before writing code, and keep its status honest: "
|
|
534
574
|
"in_progress while you work, pending_validation at handoff."
|
|
575
|
+
+ " "
|
|
576
|
+
+ _CRITERIA_RULE
|
|
535
577
|
)
|
|
536
578
|
|
|
537
579
|
# The resume counterparts. A resumed attempt inherits a PR the dead session
|
|
@@ -547,6 +589,9 @@ _RESUME_TASK_WITH_ORIGIN = (
|
|
|
547
589
|
"in_progress while you work, pending_validation at handoff. Only if the "
|
|
548
590
|
"PR body names none, create your implementation task DOWNSTREAM of the "
|
|
549
591
|
"origin (create_downstream_task) before writing code."
|
|
592
|
+
+ " "
|
|
593
|
+
+ _CRITERIA_RULE
|
|
594
|
+
+ _CRITERIA_ADOPT
|
|
550
595
|
)
|
|
551
596
|
|
|
552
597
|
_RESUME_TASK_WITHOUT_ORIGIN = (
|
|
@@ -555,6 +600,9 @@ _RESUME_TASK_WITHOUT_ORIGIN = (
|
|
|
555
600
|
"in_progress while you work, pending_validation at handoff); otherwise "
|
|
556
601
|
"locate the origin task behind this issue, or create one, and create "
|
|
557
602
|
"your implementation task DOWNSTREAM of it before writing code."
|
|
603
|
+
+ " "
|
|
604
|
+
+ _CRITERIA_RULE
|
|
605
|
+
+ _CRITERIA_ADOPT
|
|
558
606
|
)
|
|
559
607
|
|
|
560
608
|
# The delivery note (issue #63). A worker's highest-value output is not the
|
|
@@ -1514,6 +1562,9 @@ FIX_DIRECTIVE = (
|
|
|
1514
1562
|
"keep its status honest — in_progress while you work, pending_validation "
|
|
1515
1563
|
"at handoff. If a ref is missing from the PR body, restoring both is part "
|
|
1516
1564
|
"of your job: the PR body is the canonical cross-actor record. "
|
|
1565
|
+
+ _CRITERIA_RULE
|
|
1566
|
+
+ _CRITERIA_ADOPT
|
|
1567
|
+
+ " "
|
|
1517
1568
|
"Golden path: your cwd is the repo's worktree hub ROOT and the PR's head "
|
|
1518
1569
|
"branch `{head_ref}` already exists — re-attach its worktree with `git "
|
|
1519
1570
|
"worktree add {worktree_dir} {head_ref}` if it is missing (the directory "
|
|
@@ -1567,6 +1618,9 @@ FIX_RESUME_DIRECTIVE = (
|
|
|
1567
1618
|
"in_progress while you work, pending_validation at handoff. If a ref is "
|
|
1568
1619
|
"missing from the PR body, restoring both is part of your job: the PR "
|
|
1569
1620
|
"body is the canonical cross-actor record. "
|
|
1621
|
+
+ _CRITERIA_RULE
|
|
1622
|
+
+ _CRITERIA_ADOPT
|
|
1623
|
+
+ " "
|
|
1570
1624
|
"FIRST hydrate the context you did not live through: read the PR (body, "
|
|
1571
1625
|
"commits, and every review thread) and the issue behind it, to see how "
|
|
1572
1626
|
"far the dead session got. Golden path: your cwd is the repo's worktree "
|
|
@@ -1835,6 +1889,16 @@ LIVE_STALLED_COMMENT = (
|
|
|
1835
1889
|
"`{classified}`."
|
|
1836
1890
|
)
|
|
1837
1891
|
|
|
1892
|
+
ASSIGNED_OUTSIDE_COMMENT = (
|
|
1893
|
+
"**Dev loop skipping this issue** — it has been assigned to `{login}` for "
|
|
1894
|
+
"at least {minutes} min, but this daemon has no spawn for it on its "
|
|
1895
|
+
"ledger and no spawn line of its own on the activity comment, so the "
|
|
1896
|
+
"assignment was made outside the loop (by hand, or under another "
|
|
1897
|
+
"workspace's ledger). The daemon will not spawn over it. Operator "
|
|
1898
|
+
"options: unassign `{login}` to let the loop take the issue, or leave it "
|
|
1899
|
+
"if someone is working it by hand. (One-time notice.)"
|
|
1900
|
+
)
|
|
1901
|
+
|
|
1838
1902
|
# The operator page for an account-level prompt kind (issue #127): an
|
|
1839
1903
|
# expired login, a hit usage limit, an empty credit balance. No keystroke
|
|
1840
1904
|
# answers these, so the page is the act -- one per kind per
|
|
@@ -2199,6 +2263,16 @@ ESCALATION_FIX_HANDOVER = "fix-handover"
|
|
|
2199
2263
|
# neither ping may silence the other.
|
|
2200
2264
|
ESCALATION_LIVE_STALLED = "live-stalled"
|
|
2201
2265
|
|
|
2266
|
+
# The assigned-outside skip's once-per-issue operator page (issue #200): the
|
|
2267
|
+
# issue is assigned to this login, the ledger has no row and its activity
|
|
2268
|
+
# comment no spawn line of ours, so nothing the daemon can see explains the
|
|
2269
|
+
# assignment. Once-ever like ESCALATION_ASSIGNMENT -- the remedy (unassign,
|
|
2270
|
+
# or leave it to whoever is working it by hand) does not change per poll.
|
|
2271
|
+
# ASSIGNED_OUTSIDE_SEEN is the episode's durable first-seen clock, kept in the
|
|
2272
|
+
# activity_log ledger so a daemon restart does not restart the wait.
|
|
2273
|
+
ESCALATION_ASSIGNED_OUTSIDE = "assigned-outside"
|
|
2274
|
+
ASSIGNED_OUTSIDE_SEEN = "assigned-outside-seen"
|
|
2275
|
+
|
|
2202
2276
|
# The wedge kill's once-per-episode marker (see wedge_kind). Not an operator
|
|
2203
2277
|
# page -- the daemon acted instead of asking -- but, like ESCALATION_REREQUEST,
|
|
2204
2278
|
# a once-per-key act the `escalations` table is the ledger of: it dedupes the
|
|
@@ -4778,14 +4852,21 @@ class DevWatcher:
|
|
|
4778
4852
|
return self._claim_deferral(claim, attempts)
|
|
4779
4853
|
|
|
4780
4854
|
if login in issue.assignees and age is None:
|
|
4781
|
-
# Self-assigned but the ledger never spawned:
|
|
4782
|
-
#
|
|
4783
|
-
#
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
)
|
|
4855
|
+
# Self-assigned but the ledger never spawned. Issue #200: when the
|
|
4856
|
+
# issue's own activity comment carries an EXPIRED spawn line by
|
|
4857
|
+
# this login on this lane (the claim above already let it age
|
|
4858
|
+
# out), the assignment is a dead attempt of ours whose ledger row
|
|
4859
|
+
# was lost (an overlapping deploy wrote it) -- adopt it into the
|
|
4860
|
+
# ledger and let the ordinary stale matrix below decide, exactly
|
|
4861
|
+
# as if the row had been there all along.
|
|
4862
|
+
orphans = self._orphaned_spawns(issue, session_name(issue, 1))
|
|
4863
|
+
if orphans:
|
|
4864
|
+
attempts, age = self._adopt_orphaned_spawns(issue, orphans)
|
|
4865
|
+
else:
|
|
4866
|
+
# No spawn line at all: assigned outside this daemon (by
|
|
4867
|
+
# hand, or under another workspace's ledger). Not ours to
|
|
4868
|
+
# double-book -- but not silent forever either.
|
|
4869
|
+
return self._assigned_outside(issue, login)
|
|
4789
4870
|
|
|
4790
4871
|
# Staleness needs THREE signals, not one: the ledger timer says the
|
|
4791
4872
|
# newest spawn is old, but elapsed time alone cannot tell a dead
|
|
@@ -10123,6 +10204,148 @@ class DevWatcher:
|
|
|
10123
10204
|
defer_token=loop_events_mod.DEFER_CLAIM,
|
|
10124
10205
|
)
|
|
10125
10206
|
|
|
10207
|
+
def _orphaned_spawns(
|
|
10208
|
+
self, issue: Issue, session: str
|
|
10209
|
+
) -> "list[ActivityClaim]":
|
|
10210
|
+
"""The EXPIRED spawn lines this login wrote on the issue's activity
|
|
10211
|
+
comment for `session`'s lane, oldest first and one per session name
|
|
10212
|
+
(issue #200). Called only when the issue is self-assigned and the
|
|
10213
|
+
ledger has no row for it, i.e. after `external_claim` has already
|
|
10214
|
+
turned down every line as not fresh: what is left is a dead attempt
|
|
10215
|
+
of ours whose ledger row was lost (written by an overlapping
|
|
10216
|
+
deployment, or before a ledger loss).
|
|
10217
|
+
|
|
10218
|
+
Own authorship comes from `marked_comment`, the lane from
|
|
10219
|
+
`activity_lane`. Same switch and fail-open rule as `external_claim`:
|
|
10220
|
+
with claims disabled, or on any read failure, the answer is "no
|
|
10221
|
+
lines", which keeps today's skip."""
|
|
10222
|
+
if not self.config.activity_claims_enabled:
|
|
10223
|
+
return []
|
|
10224
|
+
try:
|
|
10225
|
+
comment = self.github.marked_comment(
|
|
10226
|
+
issue.owner, issue.repo, issue.number, ACTIVITY_MARKER
|
|
10227
|
+
)
|
|
10228
|
+
except Exception as exc:
|
|
10229
|
+
log.warning(
|
|
10230
|
+
"could not read the activity comment on %s (%s) — no "
|
|
10231
|
+
"orphaned attempt to adopt this poll",
|
|
10232
|
+
issue.issue_slug,
|
|
10233
|
+
exc,
|
|
10234
|
+
)
|
|
10235
|
+
return []
|
|
10236
|
+
if comment is None:
|
|
10237
|
+
return []
|
|
10238
|
+
lane = activity_lane(session)
|
|
10239
|
+
window = self.config.stale_minutes * 60
|
|
10240
|
+
oldest: "dict[str, ActivityClaim]" = {}
|
|
10241
|
+
for claim in activity_claims(comment.body):
|
|
10242
|
+
if activity_lane(claim.session) != lane or claim.age < window:
|
|
10243
|
+
continue
|
|
10244
|
+
known = oldest.get(claim.session)
|
|
10245
|
+
if known is None or claim.at < known.at:
|
|
10246
|
+
oldest[claim.session] = claim
|
|
10247
|
+
return sorted(oldest.values(), key=lambda claim: claim.at)
|
|
10248
|
+
|
|
10249
|
+
def _adopt_orphaned_spawns(
|
|
10250
|
+
self, issue: Issue, orphans: "list[ActivityClaim]"
|
|
10251
|
+
) -> "tuple[int, float]":
|
|
10252
|
+
"""Record each orphaned spawn line as a ledger row stamped with the
|
|
10253
|
+
line's own time, so attempt_cap counts it and the ordinary stale
|
|
10254
|
+
matrix (linked-PR probe, tmux liveness, resume) judges it exactly as
|
|
10255
|
+
a row that was never lost. Returns the (attempts, age) the caller
|
|
10256
|
+
continues with.
|
|
10257
|
+
|
|
10258
|
+
Rows are numbered 1..k in line order (the ledger has none for this
|
|
10259
|
+
issue), keeping the session name the line carries; numbering by the
|
|
10260
|
+
name's own suffix could REPLACE a row when a line is missing. Not
|
|
10261
|
+
written on a dry run (no ledger write is), but the returned values
|
|
10262
|
+
let the dry pass reach the same decision."""
|
|
10263
|
+
for attempt, orphan in enumerate(orphans, start=1):
|
|
10264
|
+
log.warning(
|
|
10265
|
+
"%s: adopted orphaned attempt %d from activity log (`%s`, "
|
|
10266
|
+
"spawned %d min ago by this login, no local ledger row) — "
|
|
10267
|
+
"taking the stale path",
|
|
10268
|
+
issue.issue_slug,
|
|
10269
|
+
attempt,
|
|
10270
|
+
orphan.session,
|
|
10271
|
+
int(orphan.age / 60),
|
|
10272
|
+
)
|
|
10273
|
+
if self.config.dry_run:
|
|
10274
|
+
continue
|
|
10275
|
+
self.state.record_spawn(
|
|
10276
|
+
repo_slug=issue.full_name,
|
|
10277
|
+
issue=issue.number,
|
|
10278
|
+
attempt=attempt,
|
|
10279
|
+
session=orphan.session,
|
|
10280
|
+
)
|
|
10281
|
+
# The row just written is the newest; move its clock back to the
|
|
10282
|
+
# line's, so its age says what the line says.
|
|
10283
|
+
self.state.age_out_spawn(issue.full_name, issue.number, orphan.at)
|
|
10284
|
+
return len(orphans), orphans[-1].age
|
|
10285
|
+
|
|
10286
|
+
def _assigned_outside(self, issue: Issue, login: str) -> Decision:
|
|
10287
|
+
"""The skip for an issue assigned to this login with nothing on the
|
|
10288
|
+
ledger or the activity comment to explain it -- assigned by hand.
|
|
10289
|
+
Not silent forever (issue #200): once the skip has persisted for
|
|
10290
|
+
STALLED_DEFER_MULTIPLE stale windows (clock: the episode's durable
|
|
10291
|
+
first-seen row) it posts ONE operator comment, recorded only after
|
|
10292
|
+
it lands so a failed post retries next poll."""
|
|
10293
|
+
full_name, number = issue.full_name, issue.number
|
|
10294
|
+
reason = (
|
|
10295
|
+
f"assigned to {login} outside this daemon (no spawn on the "
|
|
10296
|
+
f"ledger) — unassign the issue to let the loop take it"
|
|
10297
|
+
)
|
|
10298
|
+
if self.state.escalated(full_name, number, ESCALATION_ASSIGNED_OUTSIDE):
|
|
10299
|
+
return Decision(Action.SKIPPED, reason)
|
|
10300
|
+
if self.config.dry_run:
|
|
10301
|
+
return Decision(Action.SKIPPED, reason)
|
|
10302
|
+
first_seen = self.state.activity_logged_at(
|
|
10303
|
+
full_name, number, ASSIGNED_OUTSIDE_SEEN
|
|
10304
|
+
)
|
|
10305
|
+
if first_seen is None:
|
|
10306
|
+
self.state.record_activity(full_name, number, ASSIGNED_OUTSIDE_SEEN)
|
|
10307
|
+
first_seen = int(time.time())
|
|
10308
|
+
stalled_after = STALLED_DEFER_MULTIPLE * self.config.stale_minutes * 60
|
|
10309
|
+
waited = time.time() - first_seen
|
|
10310
|
+
if waited < stalled_after:
|
|
10311
|
+
# The page's clock is the seat's: no parking across it, or it
|
|
10312
|
+
# would fire on the first pass after the wake (issue #153).
|
|
10313
|
+
return Decision(
|
|
10314
|
+
Action.SKIPPED,
|
|
10315
|
+
reason,
|
|
10316
|
+
owed=True,
|
|
10317
|
+
timer=(
|
|
10318
|
+
parking_mod.TIMER_STALE_WINDOW, first_seen + stalled_after
|
|
10319
|
+
),
|
|
10320
|
+
)
|
|
10321
|
+
body = ASSIGNED_OUTSIDE_COMMENT.format(
|
|
10322
|
+
login=login, minutes=int(waited / 60)
|
|
10323
|
+
)
|
|
10324
|
+
log.warning(
|
|
10325
|
+
"%s has been assigned to %s outside this daemon for %.0f min — "
|
|
10326
|
+
"escalating to operator (once)",
|
|
10327
|
+
issue.issue_slug,
|
|
10328
|
+
login,
|
|
10329
|
+
waited / 60,
|
|
10330
|
+
)
|
|
10331
|
+
try:
|
|
10332
|
+
self.github.comment(issue.owner, issue.repo, number, body)
|
|
10333
|
+
except CommandError as exc:
|
|
10334
|
+
log.error(
|
|
10335
|
+
"could not post the assigned-outside comment on %s: %s — "
|
|
10336
|
+
"the page retries next poll",
|
|
10337
|
+
issue.issue_slug,
|
|
10338
|
+
exc,
|
|
10339
|
+
)
|
|
10340
|
+
return Decision(Action.SKIPPED, reason, owed=True)
|
|
10341
|
+
self.state.record_escalation(
|
|
10342
|
+
full_name, number, ESCALATION_ASSIGNED_OUTSIDE
|
|
10343
|
+
)
|
|
10344
|
+
return Decision(
|
|
10345
|
+
Action.ESCALATED,
|
|
10346
|
+
f"{reason}; operator paged after {int(waited / 60)} min",
|
|
10347
|
+
)
|
|
10348
|
+
|
|
10126
10349
|
def _log_deferral(
|
|
10127
10350
|
self,
|
|
10128
10351
|
owner: str,
|
|
@@ -189,7 +189,7 @@ _LIMIT_LIFTED_RE = re.compile(r"^usage-limit-lifted:(?P<session>[^@]+)@(?P<since
|
|
|
189
189
|
# points the operator at an unrelated PR or at nothing.
|
|
190
190
|
_ISSUE_ANCHORED = (
|
|
191
191
|
"cap", "assignment", "stalled", "live-stalled", "wedged", "first-run-dialog",
|
|
192
|
-
"claude-exited",
|
|
192
|
+
"claude-exited", "assigned-outside",
|
|
193
193
|
)
|
|
194
194
|
|
|
195
195
|
|
|
@@ -1245,6 +1245,23 @@ class State:
|
|
|
1245
1245
|
).fetchone()
|
|
1246
1246
|
return row is not None
|
|
1247
1247
|
|
|
1248
|
+
def activity_logged_at(
|
|
1249
|
+
self, repo_slug: str, number: int, kind: str
|
|
1250
|
+
) -> "int | None":
|
|
1251
|
+
"""When this activity KIND was first recorded (unix seconds), or None.
|
|
1252
|
+
The durable first-seen clock of an episode that must outlive a daemon
|
|
1253
|
+
restart (issue #200: the assigned-outside skip escalates once it has
|
|
1254
|
+
persisted long enough). A row held in memory by a failed write answers
|
|
1255
|
+
with the timestamp it would have carried."""
|
|
1256
|
+
pending = self._pending_gates.get(("activity_log", repo_slug, number, kind))
|
|
1257
|
+
if pending is not None:
|
|
1258
|
+
return int(pending)
|
|
1259
|
+
row = self._db.execute(
|
|
1260
|
+
"SELECT logged_at FROM activity_log WHERE repo_slug=? AND number=? AND kind=?",
|
|
1261
|
+
(repo_slug, number, kind),
|
|
1262
|
+
).fetchone()
|
|
1263
|
+
return None if row is None else int(row["logged_at"])
|
|
1264
|
+
|
|
1248
1265
|
def record_activity(self, repo_slug: str, number: int, kind: str) -> None:
|
|
1249
1266
|
"""Idempotent per kind: OR IGNORE keeps the first line's timestamp.
|
|
1250
1267
|
Recorded by the caller only AFTER the append lands, so a transient
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.8.
|
|
1
|
+
0.8.59
|
{alissa_tools_github_devloop-0.8.57.dist-info → alissa_tools_github_devloop-0.8.59.dist-info}/RECORD
RENAMED
|
@@ -10,13 +10,13 @@ alissa/tools/github/devloop/hubs.py,sha256=yjnsnSHLG7GNNP8X2hILeAMV6P5n4JGc_IaAx
|
|
|
10
10
|
alissa/tools/github/devloop/hungtests.py,sha256=TozIDydUe_Kn1m5EtGeGtYt_BrLqGznrNjikLYhxH-Q,24621
|
|
11
11
|
alissa/tools/github/devloop/integration_check.py,sha256=JkFwz3JqOQBIvzszmiql-IMVGSH3lDers6mJUHh9zMM,17928
|
|
12
12
|
alissa/tools/github/devloop/janitor.py,sha256=R8REoHBeY2cfW7fYJVhKr-F5z9Mjlc-vmv-z4KtvBZc,27360
|
|
13
|
-
alissa/tools/github/devloop/loop.py,sha256=
|
|
14
|
-
alissa/tools/github/devloop/loop_events.py,sha256=
|
|
13
|
+
alissa/tools/github/devloop/loop.py,sha256=JxG-XCa3Ass2g2ZPqChTT6AwuTU__g8r3kL3o6IMDo4,704072
|
|
14
|
+
alissa/tools/github/devloop/loop_events.py,sha256=B8wq4_MMXbf1-od3pk9OHVo6F6W2lzzUZmU6GsKcCkM,38113
|
|
15
15
|
alissa/tools/github/devloop/parking.py,sha256=7h3Gg2XQ0eqlvn0M6K6NeEg9xbqnlUPrZNs9gRofzxc,12410
|
|
16
16
|
alissa/tools/github/devloop/proc.py,sha256=nzfsxJSHFWRQcrXmfv588KazFysv8dVQrhMPH1q5eRk,3134
|
|
17
17
|
alissa/tools/github/devloop/prompts.py,sha256=VzN6ec5eF2wwg7QSCRg52WLcxo-tGbGRgQbc4HSahUc,55169
|
|
18
|
-
alissa/tools/github/devloop/state.py,sha256=
|
|
19
|
-
alissa/tools/github/devloop/version,sha256=
|
|
18
|
+
alissa/tools/github/devloop/state.py,sha256=MIlE3siJjUs5YEv1-Xm-Gmur6B-Okq3M_Lu6d_zxtmA,89534
|
|
19
|
+
alissa/tools/github/devloop/version,sha256=RUiBcvvmDXs3StQliqk4xZ9OHwNcLZhYv6BP72Tgq48,7
|
|
20
20
|
alissa/tools/github/devloop/version.py,sha256=znuuOaitXGrBpbskNy78_rlVpFdtmKmk_3k1ACxZrl0,1418
|
|
21
21
|
alissa/tools/github/devloop/webui/__init__.py,sha256=vdXYoyGYzD7BrJ5lV6XdH8Bpw_pej8-RK0hjfxop7-8,1513
|
|
22
22
|
alissa/tools/github/devloop/webui/__main__.py,sha256=wORyW5AkgsniK0TZcrOrvm_P7Q4Mr-fH-4S6qj9XcgA,6137
|
|
@@ -25,10 +25,10 @@ alissa/tools/github/devloop/webui/page.py,sha256=4OD3e01ByvVM4Wo04AZyFuyOYTFEMT2
|
|
|
25
25
|
alissa/tools/github/devloop/webui/server.py,sha256=3aGYGesjUSrPrgcpfy-oYDefBNKnAj3lGfRzwsRkv_I,27031
|
|
26
26
|
alissa/tools/github/devloop/webui/sources.py,sha256=Uw_2B5QGSmW6f66WfVbQb6yLLYmSv6uuF7HNJ5OSr_I,39314
|
|
27
27
|
alissa/tools/github/devloop/webui/sysinfo.py,sha256=ptlogH9alFv0vZ-pQfyUaA3w-K7LQS3tQHGv0d8Tdlk,9649
|
|
28
|
-
alissa_tools_github_devloop-0.8.
|
|
29
|
-
alissa_tools_github_devloop-0.8.
|
|
30
|
-
alissa_tools_github_devloop-0.8.
|
|
31
|
-
alissa_tools_github_devloop-0.8.
|
|
32
|
-
alissa_tools_github_devloop-0.8.
|
|
33
|
-
alissa_tools_github_devloop-0.8.
|
|
34
|
-
alissa_tools_github_devloop-0.8.
|
|
28
|
+
alissa_tools_github_devloop-0.8.59.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
29
|
+
alissa_tools_github_devloop-0.8.59.dist-info/licenses/NOTICE,sha256=FKstNs3uw_tQod4_1XcFLD1FUTJQXf4FC0oXJAOA_HE,260
|
|
30
|
+
alissa_tools_github_devloop-0.8.59.dist-info/METADATA,sha256=DJWWCbT9oCvjlvPArIt3qbJuS-PjP9VKsue_c17-PYw,15973
|
|
31
|
+
alissa_tools_github_devloop-0.8.59.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
32
|
+
alissa_tools_github_devloop-0.8.59.dist-info/entry_points.txt,sha256=8aC7Ajzx4bu9ZRR37a40IDfuStacvZP5KsAxY1dbFKU,145
|
|
33
|
+
alissa_tools_github_devloop-0.8.59.dist-info/top_level.txt,sha256=DodjDg-l-TWQnlxG-Vuc3G5sB4O7cWGQwe6XrVx3u-A,7
|
|
34
|
+
alissa_tools_github_devloop-0.8.59.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|