loki-mode 9.50.1 → 9.50.3
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.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-generator.py +7 -5
- package/autonomy/run.sh +228 -5
- package/dashboard/__init__.py +1 -1
- package/docs/COMPETITIVE-INTEL-2026-09.md +444 -0
- package/docs/INSTALLATION.md +1 -1
- package/docs/ONE-RUN-AUDIT.md +277 -0
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/skills/00-index.md +15 -0
- package/skills/factory-operations.md +508 -0
- package/skills/release-cadence.md +382 -0
- package/web-app/auth.py +27 -0
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v9.50.
|
|
6
|
+
# Loki Mode v9.50.3
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
470
470
|
|
|
471
471
|
---
|
|
472
472
|
|
|
473
|
-
**v9.50.
|
|
473
|
+
**v9.50.3 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
9.50.
|
|
1
|
+
9.50.3
|
|
@@ -1536,11 +1536,13 @@ def _build_proof(args, loki_dir, target_dir, repo_root):
|
|
|
1536
1536
|
"honesty": honesty,
|
|
1537
1537
|
}
|
|
1538
1538
|
|
|
1539
|
-
# Top-level mirror for the intervention axis.
|
|
1540
|
-
# reads proof["interventions"]
|
|
1541
|
-
#
|
|
1542
|
-
#
|
|
1543
|
-
#
|
|
1539
|
+
# Top-level mirror for the intervention axis. _interventions_value in
|
|
1540
|
+
# trust_trajectory.py reads proof["interventions"]; the counter itself is
|
|
1541
|
+
# written by handle_pause in autonomy/run.sh, which increments
|
|
1542
|
+
# .loki/state/interventions.json once per blocking pause. Mirrored (not
|
|
1543
|
+
# moved) for the same back-compat reason the other flat keys are mirrored.
|
|
1544
|
+
# Only ever set when actually measured, so the axis stays honestly
|
|
1545
|
+
# "unavailable" rather than showing a fabricated zero.
|
|
1544
1546
|
if isinstance(journey, dict) and isinstance(journey.get("interventions"), int):
|
|
1545
1547
|
proof["interventions"] = journey["interventions"]
|
|
1546
1548
|
|
package/autonomy/run.sh
CHANGED
|
@@ -4332,6 +4332,63 @@ else:
|
|
|
4332
4332
|
' 2>/dev/null || true
|
|
4333
4333
|
}
|
|
4334
4334
|
|
|
4335
|
+
# _loki_receipt_facts <loki_dir>
|
|
4336
|
+
#
|
|
4337
|
+
# Echo three tab-separated facts about THIS run's Evidence Receipt, or nothing
|
|
4338
|
+
# at all: "<run_id>\t<proof_dir>\t<headline>".
|
|
4339
|
+
#
|
|
4340
|
+
# WHY THIS EXISTS (#209). The receipt is generated automatically and opt-OUT
|
|
4341
|
+
# (LOKI_PROOF defaults to 1), but the only place its location ever reached a
|
|
4342
|
+
# user was the TTFV first-run block, which fires solely on a zero-config first
|
|
4343
|
+
# run. A user who does not already know `loki proof` exists could therefore
|
|
4344
|
+
# finish a successful run without ever learning a checkable receipt was written.
|
|
4345
|
+
#
|
|
4346
|
+
# HONESTY RULES, deliberately fail-silent:
|
|
4347
|
+
# - Resolved from the PERSISTED pointer (.loki/state/last-proof-id.txt),
|
|
4348
|
+
# never newest-by-mtime, so it names the run the generator actually wrote.
|
|
4349
|
+
# - Emits NOTHING unless the pointer, the proof dir, and proof.json all exist.
|
|
4350
|
+
# the summary builder (build_completion_summary) is itself invoked mid-pause
|
|
4351
|
+
# before the teardown receipt on the success path, where no receipt exists
|
|
4352
|
+
# yet -- printing a path there would be a promise, not a fact.
|
|
4353
|
+
# - The headline is honesty.headline, which the generator computes
|
|
4354
|
+
# DETERMINISTICALLY from recorded facts (VERIFIED / VERIFIED WITH GAPS /
|
|
4355
|
+
# NOT VERIFIED). It is never the council verdict, which the generator
|
|
4356
|
+
# itself labels "AI judgment, not deterministic proof". A missing or
|
|
4357
|
+
# unreadable headline yields an empty third field, and the callers then
|
|
4358
|
+
# print the path without a verdict rather than inventing one.
|
|
4359
|
+
# Best-effort: never fails a run.
|
|
4360
|
+
_loki_receipt_facts() {
|
|
4361
|
+
local loki_dir="${1:-}"
|
|
4362
|
+
[ -n "$loki_dir" ] || return 0
|
|
4363
|
+
local id_file="$loki_dir/state/last-proof-id.txt"
|
|
4364
|
+
[ -s "$id_file" ] || return 0
|
|
4365
|
+
local rid=""
|
|
4366
|
+
rid="$(cat "$id_file" 2>/dev/null || true)"
|
|
4367
|
+
# Confine the run id to the alphabet the generator actually mints. The
|
|
4368
|
+
# headline is sanitized below; the id was not, so an interior newline or a
|
|
4369
|
+
# tab in the pointer split the tab-separated record and handed the consumers
|
|
4370
|
+
# a field boundary that is not there. Reject rather than repair: a pointer
|
|
4371
|
+
# outside this alphabet is corrupt, and a repaired id would name a directory
|
|
4372
|
+
# that does not exist.
|
|
4373
|
+
case "$rid" in
|
|
4374
|
+
''|*[!A-Za-z0-9._-]*) return 0 ;;
|
|
4375
|
+
esac
|
|
4376
|
+
[ -n "$rid" ] || return 0
|
|
4377
|
+
local pj="$loki_dir/proofs/$rid/proof.json"
|
|
4378
|
+
[ -f "$pj" ] || return 0
|
|
4379
|
+
local headline=""
|
|
4380
|
+
headline="$(python3 -c "
|
|
4381
|
+
import json, sys
|
|
4382
|
+
try:
|
|
4383
|
+
d = json.load(open(sys.argv[1]))
|
|
4384
|
+
h = (d.get('honesty') or {}).get('headline') or ''
|
|
4385
|
+
print(str(h).replace('\t', ' ').replace('\n', ' ').strip())
|
|
4386
|
+
except Exception:
|
|
4387
|
+
print('')" "$pj" 2>/dev/null || true)"
|
|
4388
|
+
printf '%s\t%s\t%s\n' "$rid" "$loki_dir/proofs/$rid" "$headline"
|
|
4389
|
+
return 0
|
|
4390
|
+
}
|
|
4391
|
+
|
|
4335
4392
|
build_completion_summary() {
|
|
4336
4393
|
local outcome="${1:-complete}"
|
|
4337
4394
|
local loki_dir="${TARGET_DIR:-.}/.loki"
|
|
@@ -4867,6 +4924,49 @@ except Exception:
|
|
|
4867
4924
|
echo "Resolve those in the spec, then re-run."
|
|
4868
4925
|
;;
|
|
4869
4926
|
esac
|
|
4927
|
+
|
|
4928
|
+
# Evidence Receipt (#209). The receipt is written automatically on every
|
|
4929
|
+
# run, success or failure, but its location only ever reached the user
|
|
4930
|
+
# through the zero-config first-run block. State it here, where every
|
|
4931
|
+
# terminal outcome passes, so a user who has never heard of `loki proof`
|
|
4932
|
+
# still learns a checkable receipt exists and how to re-check it.
|
|
4933
|
+
# Prints NOTHING when no receipt has been written yet (mid-pause, or the
|
|
4934
|
+
# first summary on the success path): a path that does not exist is a
|
|
4935
|
+
# promise, not a fact. The verdict line is the generator's deterministic
|
|
4936
|
+
# headline, omitted entirely when unreadable rather than invented.
|
|
4937
|
+
_cs_receipt="$(_loki_receipt_facts "$loki_dir" 2>/dev/null || true)"
|
|
4938
|
+
if [ -n "$_cs_receipt" ]; then
|
|
4939
|
+
_cs_rid="${_cs_receipt%% *}"
|
|
4940
|
+
_cs_rest="${_cs_receipt#* }"
|
|
4941
|
+
_cs_dir="${_cs_rest%% *}"
|
|
4942
|
+
_cs_headline="${_cs_rest#* }"
|
|
4943
|
+
echo ""
|
|
4944
|
+
echo "Evidence Receipt (this run):"
|
|
4945
|
+
if [ -n "$_cs_headline" ]; then
|
|
4946
|
+
echo " Verdict: $_cs_headline"
|
|
4947
|
+
fi
|
|
4948
|
+
# Gated on the PAGE, not the receipt. The helper gates on
|
|
4949
|
+
# proof.json, but the generator writes proof.json and THEN renders
|
|
4950
|
+
# index.html unwrapped (proof-generator.py), so a render failure
|
|
4951
|
+
# leaves the data present and the page absent. Naming a page that
|
|
4952
|
+
# is not there is the same class proof.ts:118 refuses ("worse than
|
|
4953
|
+
# an absent one") and `loki proof open` refuses with "Proof page
|
|
4954
|
+
# not found". Gate only this line: proof verify reads proof.json,
|
|
4955
|
+
# so the id and the re-check below still work without the page.
|
|
4956
|
+
if [ -f "$_cs_dir/index.html" ]; then
|
|
4957
|
+
echo " Receipt: $_cs_dir/index.html"
|
|
4958
|
+
fi
|
|
4959
|
+
echo " Re-check it yourself, do not take our word for it:"
|
|
4960
|
+
# Cwd-independent: the receipt is resolved from the run's target
|
|
4961
|
+
# dir, which need not be where the user is standing. A bare
|
|
4962
|
+
# `loki proof verify <id>` then fails for exactly the user we just
|
|
4963
|
+
# told to check our work.
|
|
4964
|
+
if [ "$(cd "$loki_dir/.." 2>/dev/null && pwd -P)" = "$(pwd -P)" ]; then
|
|
4965
|
+
echo " loki proof verify $_cs_rid"
|
|
4966
|
+
else
|
|
4967
|
+
echo " (cd $(cd "$loki_dir/.." 2>/dev/null && pwd -P) && loki proof verify $_cs_rid)"
|
|
4968
|
+
fi
|
|
4969
|
+
fi
|
|
4870
4970
|
} > "$loki_dir/COMPLETION.txt" 2>/dev/null || true
|
|
4871
4971
|
|
|
4872
4972
|
# ---- Durable machine-readable file: .loki/state/completion.json -----------
|
|
@@ -5199,6 +5299,20 @@ except Exception:
|
|
|
5199
5299
|
echo -e "${GREEN}|${NC}"
|
|
5200
5300
|
echo -e "${GREEN}|${NC} ${DIM}Review the work:${NC}"
|
|
5201
5301
|
echo -e "${GREEN}|${NC} ${_review}"
|
|
5302
|
+
# NO Evidence Receipt line here, deliberately. The card renders from inside
|
|
5303
|
+
# emit_completion_summary, which is reached only from within run_autonomous
|
|
5304
|
+
# -- thousands of lines BEFORE the teardown that generates this run's
|
|
5305
|
+
# receipt. Announcing here would therefore be silent on a normal success
|
|
5306
|
+
# run (no proof exists yet), and on a SECOND run in the same directory it
|
|
5307
|
+
# would have been actively wrong before #211: .loki/state/last-proof-id.txt
|
|
5308
|
+
# was never cleared at run start, so the card would read the PREVIOUS run's
|
|
5309
|
+
# pointer and print that receipt, with that run's verdict, as though it
|
|
5310
|
+
# described this run. The pointer is now cleared during run init (search
|
|
5311
|
+
# "Same reasoning for the proof pointer"), which closes the cross-run leak,
|
|
5312
|
+
# but this site stays silent anyway: it renders thousands of lines before
|
|
5313
|
+
# THIS run's receipt exists, so it would print nothing on a normal success
|
|
5314
|
+
# run. The announcement lives at the teardown instead, after the final
|
|
5315
|
+
# generate_proof_of_run, where the pointer is guaranteed current.
|
|
5202
5316
|
echo -e "${GREEN}+================================================================+${NC}"
|
|
5203
5317
|
echo ""
|
|
5204
5318
|
return 0
|
|
@@ -6529,6 +6643,15 @@ init_loki_dir() {
|
|
|
6529
6643
|
mkdir -p .loki/metrics/efficiency
|
|
6530
6644
|
# Clear stale metrics from previous sessions so loki metrics shows current run data (#75)
|
|
6531
6645
|
rm -f .loki/metrics/efficiency/iteration-*.json 2>/dev/null || true
|
|
6646
|
+
# Same reasoning for the proof pointer (#211). .loki/state/last-proof-id.txt
|
|
6647
|
+
# is written by generate_proof_of_run and was never cleared, so a run that
|
|
6648
|
+
# died before generating a proof left the PREVIOUS run's id behind. Every
|
|
6649
|
+
# reader then resolved a receipt describing different work, and
|
|
6650
|
+
# the summary builder (build_completion_summary) would print it under the
|
|
6651
|
+
# literal heading "Evidence
|
|
6652
|
+
# Receipt (this run):". A receipt naming the wrong run is worse than no
|
|
6653
|
+
# receipt: absence reads as "no data", a stale one reads as evidence.
|
|
6654
|
+
rm -f .loki/state/last-proof-id.txt 2>/dev/null || true
|
|
6532
6655
|
mkdir -p .loki/rules
|
|
6533
6656
|
mkdir -p .loki/signals
|
|
6534
6657
|
|
|
@@ -25728,18 +25851,45 @@ except Exception:
|
|
|
25728
25851
|
|
|
25729
25852
|
log_header "Execution Paused"
|
|
25730
25853
|
echo ""
|
|
25731
|
-
|
|
25854
|
+
# The keypress half of this line is only true on an interactive terminal.
|
|
25855
|
+
# Off a TTY (--bg, a container, a CI job) no key can be read, so advertising
|
|
25856
|
+
# it there tells the operator to do something that cannot work.
|
|
25857
|
+
if [ -t 0 ]; then
|
|
25858
|
+
log_info "To resume: Remove .loki/PAUSE or press Enter"
|
|
25859
|
+
else
|
|
25860
|
+
log_info "To resume: Remove .loki/PAUSE (no TTY: keypress resume unavailable)"
|
|
25861
|
+
fi
|
|
25732
25862
|
log_info "To add instructions: echo 'your instructions' > .loki/HUMAN_INPUT.md"
|
|
25733
25863
|
log_info "To stop completely: touch .loki/STOP"
|
|
25734
25864
|
echo ""
|
|
25735
25865
|
|
|
25736
|
-
# Create resume instructions file
|
|
25866
|
+
# Create resume instructions file.
|
|
25867
|
+
#
|
|
25868
|
+
# The resume line is built OUTSIDE the heredoc because the heredoc is quoted
|
|
25869
|
+
# (<< 'EOF') and must stay that way: its body contains `rm .loki/PAUSE` and
|
|
25870
|
+
# `touch .loki/STOP` in backticks, so unquoting to interpolate a variable
|
|
25871
|
+
# would execute them and delete the PAUSE file this function just wrote.
|
|
25872
|
+
#
|
|
25873
|
+
# This file is the surface a NON-INTERACTIVE operator actually reads (--bg,
|
|
25874
|
+
# a container, a CI job), and it was the last place still promising a
|
|
25875
|
+
# keypress that cannot arrive there -- the same defect the console banner
|
|
25876
|
+
# above already fixed. The no-TTY wording is byte-identical to that banner's
|
|
25877
|
+
# so one grep spans both surfaces and any future divergence is visible.
|
|
25878
|
+
local _resume_line
|
|
25879
|
+
if [ -t 0 ]; then
|
|
25880
|
+
_resume_line='1. **Resume**: Press Enter in terminal or `rm .loki/PAUSE`'
|
|
25881
|
+
else
|
|
25882
|
+
_resume_line='1. **Resume**: `rm .loki/PAUSE` (no TTY: keypress resume unavailable)'
|
|
25883
|
+
fi
|
|
25884
|
+
|
|
25737
25885
|
cat > "$loki_dir/PAUSED.md" << 'EOF'
|
|
25738
25886
|
# Loki Mode - Paused
|
|
25739
25887
|
|
|
25740
25888
|
Execution is currently paused. Options:
|
|
25741
25889
|
|
|
25742
|
-
|
|
25890
|
+
EOF
|
|
25891
|
+
printf '%s\n' "$_resume_line" >> "$loki_dir/PAUSED.md"
|
|
25892
|
+
cat >> "$loki_dir/PAUSED.md" << 'EOF'
|
|
25743
25893
|
2. **Add Instructions**: `echo "Focus on fixing the login bug" > .loki/HUMAN_INPUT.md`
|
|
25744
25894
|
3. **Stop**: `touch .loki/STOP`
|
|
25745
25895
|
|
|
@@ -25805,8 +25955,31 @@ except Exception:
|
|
|
25805
25955
|
break
|
|
25806
25956
|
fi
|
|
25807
25957
|
|
|
25808
|
-
# Check for any key press (non-blocking)
|
|
25809
|
-
|
|
25958
|
+
# Check for any key press (non-blocking). GATED ON AN INTERACTIVE STDIN
|
|
25959
|
+
# ([ -t 0 ], the established idiom in this file) because off a TTY this
|
|
25960
|
+
# arm is not merely useless, it is wrong in BOTH directions:
|
|
25961
|
+
#
|
|
25962
|
+
# 1. stdin is /dev/null (--bg, a container, a CI job): the read can
|
|
25963
|
+
# never succeed, so the loop spins on `sleep 1` forever with nobody
|
|
25964
|
+
# able to press anything. That is the reported hang.
|
|
25965
|
+
# 2. stdin is a PIPE OR FILE THAT HAS BYTES (stdin inherited from a
|
|
25966
|
+
# parent, a heredoc, `< somefile`): the read SUCCEEDS on the first
|
|
25967
|
+
# stray byte and the next line deletes .loki/PAUSE. A gate
|
|
25968
|
+
# escalation that paused at GATE_PAUSE_LIMIT is then silently
|
|
25969
|
+
# resumed by data nobody typed -- a false resume, which is worse
|
|
25970
|
+
# than the hang because the run continues past a blocking gate.
|
|
25971
|
+
#
|
|
25972
|
+
# Both were reproduced directly: with bytes on stdin `read -t 1 -n 1`
|
|
25973
|
+
# returns 0, with /dev/null it returns non-zero.
|
|
25974
|
+
#
|
|
25975
|
+
# The human escape path is UNCHANGED. The STOP and PAUSE-removal checks
|
|
25976
|
+
# above are file-based, run every second, and are what the dashboard,
|
|
25977
|
+
# the CLI, and `rm .loki/PAUSE` already use -- so a non-interactive
|
|
25978
|
+
# operator keeps every way out they had. Only the keypress, which that
|
|
25979
|
+
# operator never had, is skipped. On a real TTY this is byte-identical.
|
|
25980
|
+
# No timeout is imposed: a bounded wait would invent a new terminal
|
|
25981
|
+
# outcome and could fail a legitimate long human pause.
|
|
25982
|
+
if [ -t 0 ] && read -t 1 -n 1 2>/dev/null; then
|
|
25810
25983
|
rm -f "$loki_dir/PAUSE"
|
|
25811
25984
|
PAUSED=false
|
|
25812
25985
|
break
|
|
@@ -26980,6 +27153,56 @@ except Exception:
|
|
|
26980
27153
|
generate_proof_of_run "$result" || true
|
|
26981
27154
|
fi
|
|
26982
27155
|
|
|
27156
|
+
# Evidence Receipt (#209): tell the user, on screen, that a checkable
|
|
27157
|
+
# receipt exists and how to re-check it.
|
|
27158
|
+
#
|
|
27159
|
+
# POSITION IS LOAD-BEARING. This sits immediately after the FINAL
|
|
27160
|
+
# generate_proof_of_run, which is the only point where the receipt for THIS
|
|
27161
|
+
# run is guaranteed written and .loki/state/last-proof-id.txt is guaranteed
|
|
27162
|
+
# to point at it. Every earlier surface is either too early (the completion
|
|
27163
|
+
# card renders from inside run_autonomous, long before any proof exists) or
|
|
27164
|
+
# unreachable to a foreground user (COMPLETION.txt self-heals here, but only
|
|
27165
|
+
# a --bg launch is ever told to read it). Before #211 the pointer was never
|
|
27166
|
+
# cleared at run start, so announcing from an earlier site printed the
|
|
27167
|
+
# PREVIOUS run's receipt and verdict on a second run in the same directory.
|
|
27168
|
+
# Run init now clears it (search "Same reasoning for the proof pointer"), so
|
|
27169
|
+
# a stale pointer no longer survives into a new run; the position still
|
|
27170
|
+
# matters because an earlier site is simply too early for THIS run's proof.
|
|
27171
|
+
#
|
|
27172
|
+
# TTY-gated the same way print_ttfv_next_steps is above: machine output and
|
|
27173
|
+
# --bg stay byte-identical, and those readers already get the same facts
|
|
27174
|
+
# from COMPLETION.txt. Fail-silent and best-effort: prints nothing at all
|
|
27175
|
+
# when no receipt was written (LOKI_PROOF=0, or generation failed), and
|
|
27176
|
+
# never fails the run.
|
|
27177
|
+
if [ -t 1 ] && [ "${BACKGROUND_MODE:-false}" != "true" ]; then
|
|
27178
|
+
_rcpt="$(_loki_receipt_facts "${TARGET_DIR:-.}/.loki" 2>/dev/null || true)"
|
|
27179
|
+
if [ -n "${_rcpt:-}" ]; then
|
|
27180
|
+
_rcpt_id="${_rcpt%% *}"
|
|
27181
|
+
_rcpt_rest="${_rcpt#* }"
|
|
27182
|
+
_rcpt_dir="${_rcpt_rest%% *}"
|
|
27183
|
+
_rcpt_headline="${_rcpt_rest#* }"
|
|
27184
|
+
echo ""
|
|
27185
|
+
if [ -n "$_rcpt_headline" ]; then
|
|
27186
|
+
echo "Evidence Receipt for this run: $_rcpt_headline"
|
|
27187
|
+
else
|
|
27188
|
+
echo "Evidence Receipt for this run:"
|
|
27189
|
+
fi
|
|
27190
|
+
# Gated on the PAGE existing -- see the COMPLETION.txt site above.
|
|
27191
|
+
if [ -f "$_rcpt_dir/index.html" ]; then
|
|
27192
|
+
echo " $_rcpt_dir/index.html"
|
|
27193
|
+
fi
|
|
27194
|
+
echo " Re-check it yourself, do not take our word for it:"
|
|
27195
|
+
# Cwd-independent, same reasoning as the COMPLETION.txt site.
|
|
27196
|
+
_rcpt_root="$(cd "${TARGET_DIR:-.}" 2>/dev/null && pwd -P)"
|
|
27197
|
+
if [ "$_rcpt_root" = "$(pwd -P)" ]; then
|
|
27198
|
+
echo " loki proof verify $_rcpt_id"
|
|
27199
|
+
else
|
|
27200
|
+
echo " (cd $_rcpt_root && loki proof verify $_rcpt_id)"
|
|
27201
|
+
fi
|
|
27202
|
+
echo ""
|
|
27203
|
+
fi
|
|
27204
|
+
fi
|
|
27205
|
+
|
|
26983
27206
|
# Close the teardown window here rather than after cleanup: everything below
|
|
26984
27207
|
# is process reaping and file removal, while everything above is the work a
|
|
26985
27208
|
# user waits on (commit, PR, summary, proof). Emitting before cleanup also
|