alissa-tools-github-revloop 0.16.15__tar.gz → 0.16.16__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.16.15/src/main/alissa_tools_github_revloop.egg-info → alissa_tools_github_revloop-0.16.16}/PKG-INFO +1 -1
- alissa_tools_github_revloop-0.16.16/src/main/alissa/tools/github/revloop/version +1 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/__init__.py +7 -5
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/page.py +17 -2
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/sources.py +6 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/sysinfo.py +34 -6
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16/src/main/alissa_tools_github_revloop.egg-info}/PKG-INFO +1 -1
- alissa_tools_github_revloop-0.16.15/src/main/alissa/tools/github/revloop/version +0 -1
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/LICENSE +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/MANIFEST.in +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/NOTICE +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/README.md +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/requirements.txt +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/setup.cfg +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/setup.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/__init__.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/__main__.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/alissa.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/config.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/ghclient.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/loop.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/proc.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/prreview.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/state.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/version.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/__main__.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/auth.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa/tools/github/revloop/webui/server.py +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa_tools_github_revloop.egg-info/SOURCES.txt +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa_tools_github_revloop.egg-info/dependency_links.txt +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa_tools_github_revloop.egg-info/entry_points.txt +0 -0
- {alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/src/main/alissa_tools_github_revloop.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.16.16
|
|
@@ -15,14 +15,16 @@ pass writes one `poll_snapshots` row (UI-1, PR #35) carrying the pass timing,
|
|
|
15
15
|
the candidate count, the decision-summary counts, and the compact per-item
|
|
16
16
|
stage list. The sidecar reads that table through `State.read_snapshots`, plus
|
|
17
17
|
the spawn ledger, the escalation table and the ping ledger (the operator
|
|
18
|
-
inbox), all read-only. Its only live signals are local (`alissa tmux ls`,
|
|
19
|
-
`/proc` walk
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
inbox), all read-only. Its only live signals are local (`alissa tmux ls`, one
|
|
19
|
+
`/proc` walk serving both each session's pane-PID tree and the host-wide
|
|
20
|
+
top-by-RSS list, and the container's own cgroup v2 memory charge) or cached
|
|
21
|
+
(`gh api rate_limit`, 60s; the PyPI version JSON, 10m) -- so a fleet of
|
|
22
|
+
operators refreshing the dashboard never moves the daemon's rate budget.
|
|
22
23
|
|
|
23
24
|
Layout:
|
|
24
25
|
auth.py -- fail-closed passcode, HMAC-signed sessions, CSRF, login throttle
|
|
25
|
-
sysinfo.py -- /proc process-tree CPU%/RSS
|
|
26
|
+
sysinfo.py -- /proc process-tree CPU%/RSS + host-wide top-by-RSS and the
|
|
27
|
+
cgroup memory split (sample-free, vanished-PID tolerant)
|
|
26
28
|
sources.py -- the read-only data layer + the retry-now UPDATE, cached checks
|
|
27
29
|
page.py -- the single static HTML page (studio design system, both themes)
|
|
28
30
|
server.py -- ThreadingHTTPServer wiring, routing, auth/CSRF gating, actions
|
|
@@ -437,14 +437,29 @@ _JS = r"""
|
|
|
437
437
|
// The meter is the RESIDENT share of the charge, deliberately: it is the
|
|
438
438
|
// only part of a rising charge that a limit can actually kill for, so the
|
|
439
439
|
// shared warn/crit thresholds mean the same thing here as on the others.
|
|
440
|
+
// Gated on ANY of the three, not on `charged`: cgroup_memory reads
|
|
441
|
+
// memory.current and memory.stat through separate helpers so each degrades
|
|
442
|
+
// on its own, and a tile keyed to the headline alone would throw away a
|
|
443
|
+
// breakdown the reader deliberately preserved. The headline and the meter
|
|
444
|
+
// carry their own null handling, so a missing `charged` costs only itself.
|
|
440
445
|
var mem = t.memory;
|
|
441
|
-
if (mem && mem.charged != null) {
|
|
446
|
+
if (mem && (mem.charged != null || mem.resident != null || mem.reclaimable != null)) {
|
|
442
447
|
var msub = (mem.resident == null ? '--' : bytes(mem.resident)) + ' resident · ' +
|
|
443
448
|
(mem.reclaimable == null ? '--' : bytes(mem.reclaimable)) + ' reclaimable';
|
|
449
|
+
// shmem is charged, is NOT droppable (swap-backed), and is excluded from
|
|
450
|
+
// reclaimable -- so it has to be visible, or a tmpfs-heavy container
|
|
451
|
+
// shows a charge that neither of the other two numbers accounts for.
|
|
452
|
+
if (mem.shmem) msub += ' · ' + bytes(mem.shmem) + ' shmem';
|
|
444
453
|
var mpct = (mem.resident == null || !mem.charged) ? null :
|
|
445
454
|
Math.round(100 * mem.resident / mem.charged);
|
|
446
455
|
out += tile('Container Memory', bytes(mem.charged), msub, mpct);
|
|
447
|
-
|
|
456
|
+
// 'unavailable', not a cgroup-v2 verdict: this branch is also reached on a
|
|
457
|
+
// host-namespace deployment (the controller exists, its interface files
|
|
458
|
+
// are absent from the v2 root) and on a partial read. The console cannot
|
|
459
|
+
// tell those apart, and a wrong diagnosis sends an operator to check the
|
|
460
|
+
// wrong thing -- the neighbouring tiles say 'unavailable' for the same
|
|
461
|
+
// reason, and so does the origin task's acceptance detail.
|
|
462
|
+
} else { out += tile('Container Memory', '--', 'unavailable'); }
|
|
448
463
|
out += tile('Review Queue', t.queue_depth, 'PRs awaiting me, last poll');
|
|
449
464
|
el('tiles').innerHTML = out;
|
|
450
465
|
}
|
|
@@ -501,6 +501,12 @@ class Sources:
|
|
|
501
501
|
# trees out of it and the top-process list ranks the same snapshot, so
|
|
502
502
|
# the two panels can never disagree about a process that exited between
|
|
503
503
|
# them -- and the host pays for one walk per poll, not two.
|
|
504
|
+
#
|
|
505
|
+
# The cost on the other side of that trade, so nobody reorders this
|
|
506
|
+
# thinking it is free: the snapshot is now taken BEFORE `sessions()`
|
|
507
|
+
# shells out to tmux, so a pane that starts inside that window is
|
|
508
|
+
# missing from `stats` and its row shows "--" for CPU%/RSS for one
|
|
509
|
+
# poll. Self-healing in ~10s, and cheaper than walking /proc twice.
|
|
504
510
|
proc_index = sysinfo.build_index(self._proc_root)
|
|
505
511
|
sessions = self.sessions(index=proc_index)
|
|
506
512
|
rate = self.rate_limit()
|
|
@@ -276,6 +276,15 @@ def _sum_or_none(*values: "int | None") -> "int | None":
|
|
|
276
276
|
return sum(value for value in values if value is not None)
|
|
277
277
|
|
|
278
278
|
|
|
279
|
+
def _drop_shmem(file_bytes: "int | None", shmem: "int | None") -> "int | None":
|
|
280
|
+
"""The droppable part of `file`. `shmem` unknown means the droppable part
|
|
281
|
+
is unknown -- publishing `file` whole would be the reassuring-direction
|
|
282
|
+
error the split exists to prevent."""
|
|
283
|
+
if file_bytes is None or shmem is None:
|
|
284
|
+
return None
|
|
285
|
+
return max(0, file_bytes - shmem)
|
|
286
|
+
|
|
287
|
+
|
|
279
288
|
def cgroup_memory(
|
|
280
289
|
cgroup_root: "str | os.PathLike[str]" = "/sys/fs/cgroup",
|
|
281
290
|
) -> dict:
|
|
@@ -287,13 +296,25 @@ def cgroup_memory(
|
|
|
287
296
|
So we also report:
|
|
288
297
|
|
|
289
298
|
* `resident` -- `anon`, the process memory that is really in use.
|
|
290
|
-
* `reclaimable` -- `file
|
|
291
|
-
shrinkable kernel caches
|
|
299
|
+
* `reclaimable` -- `(file - shmem) + slab_reclaimable`: the page cache plus
|
|
300
|
+
the shrinkable kernel caches, the "not really in use" bucket.
|
|
301
|
+
* `shmem` -- broken out of `file` rather than left inside it, because it is
|
|
302
|
+
not droppable: tmpfs, shm segments and shared anonymous mmaps are
|
|
303
|
+
swap-backed, so with swap disabled or capped (the normal container case)
|
|
304
|
+
the kernel cannot reclaim them under pressure -- they are what the
|
|
305
|
+
container gets OOM-killed for. Counting them as reclaimable is the one
|
|
306
|
+
way this reader can be wrong in the REASSURING direction, telling an
|
|
307
|
+
operator "5.9 GB of cache, no leak" about pages nothing can free. Issue
|
|
308
|
+
#74's scope text prescribes `file + slab_reclaimable` verbatim; the same
|
|
309
|
+
sentence calls the result the "not really in use" bucket, and where the
|
|
310
|
+
formula and the words disagree the words are the requirement. Surfaced as
|
|
311
|
+
its own magnitude instead of folded into `resident`, because "5 GB of
|
|
312
|
+
tmpfs" and "5 GB of process heap" are different operator problems even
|
|
313
|
+
though neither is droppable.
|
|
292
314
|
|
|
293
315
|
The raw keys ride along for a spot check against an in-container
|
|
294
|
-
`memory.stat`. Note the
|
|
295
|
-
|
|
296
|
-
inside `file` while behaving like anon memory) -- they are the three
|
|
316
|
+
`memory.stat`. Note the summary numbers do NOT partition the charge --
|
|
317
|
+
kernel stacks, pagetables and sockets are charged too -- they are the
|
|
297
318
|
magnitudes an operator compares, not a balance sheet.
|
|
298
319
|
|
|
299
320
|
Never raises. On a host without cgroup v2 -- a dev laptop, macOS, a v1
|
|
@@ -306,7 +327,14 @@ def cgroup_memory(
|
|
|
306
327
|
out: "dict[str, int | None]" = {
|
|
307
328
|
"charged": charged,
|
|
308
329
|
"resident": stat["anon"],
|
|
309
|
-
|
|
330
|
+
# `shmem` is a SUBSET of `file` in cgroup v2, so it is subtracted, not
|
|
331
|
+
# added. Clamped at zero: the two keys are sampled from one read of one
|
|
332
|
+
# file and cannot legitimately cross, but a negative "cache" number
|
|
333
|
+
# would be a worse thing to render than a zero if a kernel ever
|
|
334
|
+
# disagreed with that.
|
|
335
|
+
"reclaimable": _sum_or_none(
|
|
336
|
+
_drop_shmem(stat["file"], stat["shmem"]), stat["slab_reclaimable"]
|
|
337
|
+
),
|
|
310
338
|
}
|
|
311
339
|
out.update(stat)
|
|
312
340
|
return out
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.16.15
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alissa_tools_github_revloop-0.16.15 → alissa_tools_github_revloop-0.16.16}/requirements.txt
RENAMED
|
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
|