loki-mode 7.47.0 → 7.49.0
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/completion-council.sh +85 -2
- package/autonomy/crash.sh +47 -21
- package/autonomy/loki +50 -27
- package/autonomy/run.sh +378 -1
- package/autonomy/spec-interrogation.sh +1 -0
- package/autonomy/telemetry.sh +28 -8
- package/bin/postinstall.js +22 -10
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_v2.py +258 -12
- package/dashboard/server.py +64 -10
- package/dashboard/telemetry.py +34 -6
- package/docs/INSTALLATION.md +10 -3
- package/docs/PRIVACY.md +82 -24
- package/loki-ts/dist/loki.js +30 -30
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
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 v7.
|
|
6
|
+
# Loki Mode v7.49.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -407,4 +407,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
407
407
|
|
|
408
408
|
---
|
|
409
409
|
|
|
410
|
-
**v7.
|
|
410
|
+
**v7.49.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.49.0
|
|
@@ -1569,6 +1569,19 @@ council_evidence_gate() {
|
|
|
1569
1569
|
local test_fails="false"
|
|
1570
1570
|
local test_runner="none"
|
|
1571
1571
|
local test_pass="true"
|
|
1572
|
+
# P1-1 (evidence-gate loophole): track WHY the test signal is not conclusive
|
|
1573
|
+
# positive evidence, mirroring diff_inconclusive. A project that ran NO test
|
|
1574
|
+
# suite (runner=="none") must NOT count as affirmative "tests are green"
|
|
1575
|
+
# evidence -- absence of tests is not proof of correctness. We classify it as
|
|
1576
|
+
# INCONCLUSIVE (not FAIL: a no-tests project is still allowed to complete, it
|
|
1577
|
+
# just may not lean on tests as positive proof), so the no-tests "done" routes
|
|
1578
|
+
# to the completion council's affirmative vote instead of silently passing on
|
|
1579
|
+
# diff-alone. test_inconclusive is pass-through by construction: it never sets
|
|
1580
|
+
# test_fails and never writes evidence-block.json, exactly like
|
|
1581
|
+
# diff_inconclusive. Opt-out (LOKI_EVIDENCE_NO_TESTS_AFFIRMATIVE=1) reverts to
|
|
1582
|
+
# the historical behavior where runner=="none" was an affirmative PASS.
|
|
1583
|
+
local test_inconclusive="false"
|
|
1584
|
+
local test_inconclusive_reason=""
|
|
1572
1585
|
if [ -f "$tr_file" ]; then
|
|
1573
1586
|
local test_status
|
|
1574
1587
|
test_status=$(_TR_FILE="$tr_file" python3 -c "
|
|
@@ -1597,9 +1610,25 @@ else:
|
|
|
1597
1610
|
test_fails="true"
|
|
1598
1611
|
fi
|
|
1599
1612
|
# INCONCLUSIVE => test_fails stays "false" => pass-through.
|
|
1613
|
+
# No test suite ran: a present results file that records runner=="none"
|
|
1614
|
+
# is not affirmative evidence. Route to council (inconclusive), not a
|
|
1615
|
+
# silent diff-alone pass. Default-on; LOKI_EVIDENCE_NO_TESTS_AFFIRMATIVE=1
|
|
1616
|
+
# restores the old affirmative-PASS behavior.
|
|
1617
|
+
if [ "$test_runner" = "none" ] && [ "${LOKI_EVIDENCE_NO_TESTS_AFFIRMATIVE:-0}" != "1" ]; then
|
|
1618
|
+
test_inconclusive="true"
|
|
1619
|
+
test_inconclusive_reason="no_test_runner"
|
|
1620
|
+
fi
|
|
1621
|
+
else
|
|
1622
|
+
# Missing test-results.json: no suite was recorded at all. Like the
|
|
1623
|
+
# runner=="none" case this is not affirmative evidence, so classify it
|
|
1624
|
+
# inconclusive (still pass-through: test_fails stays "false"). Preserves
|
|
1625
|
+
# the historical "no file = no gate" non-blocking behavior while making
|
|
1626
|
+
# the absence auditable instead of silently affirmative.
|
|
1627
|
+
if [ "${LOKI_EVIDENCE_NO_TESTS_AFFIRMATIVE:-0}" != "1" ]; then
|
|
1628
|
+
test_inconclusive="true"
|
|
1629
|
+
test_inconclusive_reason="no_test_results"
|
|
1630
|
+
fi
|
|
1600
1631
|
fi
|
|
1601
|
-
# Missing test-results.json (the else of the -f check) likewise leaves
|
|
1602
|
-
# test_fails="false" => inconclusive => pass-through (no file = no gate).
|
|
1603
1632
|
|
|
1604
1633
|
# --- v7.28.0: inconclusive-baseline lifecycle -------------------------------
|
|
1605
1634
|
# When the gate cannot establish a diff baseline (no git repo, or no run-start
|
|
@@ -1635,12 +1664,63 @@ INCONCLUSIVE_EOF
|
|
|
1635
1664
|
fi
|
|
1636
1665
|
fi
|
|
1637
1666
|
|
|
1667
|
+
# --- P1-1: durable, auditable evidence-gate details -------------------------
|
|
1668
|
+
# Persist the full evidence picture on EVERY gate run (pass and block) so any
|
|
1669
|
+
# completion claim is auditable after the fact: diff status, test runner +
|
|
1670
|
+
# status, both inconclusive reasons, and the final verdict. Atomic temp+mv,
|
|
1671
|
+
# under .loki/council/ (already excluded from the diff union by the gate's own
|
|
1672
|
+
# ^\.loki/ filter, so it never makes the gate toothless). Best-effort: a write
|
|
1673
|
+
# failure never changes the gate's decision. _write_evidence_details <verdict>
|
|
1674
|
+
# where verdict is one of pass|block (the caller passes the decided verdict).
|
|
1675
|
+
_write_evidence_details() {
|
|
1676
|
+
local _verdict="$1"
|
|
1677
|
+
mkdir -p "$COUNCIL_STATE_DIR" 2>/dev/null || true
|
|
1678
|
+
local _det_file="$COUNCIL_STATE_DIR/evidence-gate-details.json"
|
|
1679
|
+
local _det_tmp="${_det_file}.tmp"
|
|
1680
|
+
local _det_ts
|
|
1681
|
+
_det_ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
1682
|
+
local _diff_ok _tests_ok
|
|
1683
|
+
if [ "$diff_fails" = "true" ]; then _diff_ok="false"; else _diff_ok="true"; fi
|
|
1684
|
+
if [ "$test_fails" = "true" ]; then _tests_ok="false"; else _tests_ok="true"; fi
|
|
1685
|
+
cat > "$_det_tmp" << DETAILS_EOF
|
|
1686
|
+
{
|
|
1687
|
+
"recorded_at": "$_det_ts",
|
|
1688
|
+
"iteration": ${ITERATION_COUNT:-0},
|
|
1689
|
+
"verdict": "$_verdict",
|
|
1690
|
+
"diff": {
|
|
1691
|
+
"ok": $_diff_ok,
|
|
1692
|
+
"base_sha": "${base_sha:-}",
|
|
1693
|
+
"files_changed": $diff_files,
|
|
1694
|
+
"inconclusive": $diff_inconclusive,
|
|
1695
|
+
"inconclusive_reason": "$diff_inconclusive_reason"
|
|
1696
|
+
},
|
|
1697
|
+
"tests": {
|
|
1698
|
+
"ok": $_tests_ok,
|
|
1699
|
+
"runner": "$test_runner",
|
|
1700
|
+
"pass": $test_pass,
|
|
1701
|
+
"inconclusive": $test_inconclusive,
|
|
1702
|
+
"inconclusive_reason": "$test_inconclusive_reason"
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
DETAILS_EOF
|
|
1706
|
+
mv "$_det_tmp" "$_det_file" 2>/dev/null || rm -f "$_det_tmp" 2>/dev/null || true
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1638
1709
|
# --- Block decision: block iff DIFF FAILS or TEST FAILS ---
|
|
1639
1710
|
if [ "$diff_fails" != "true" ] && [ "$test_fails" != "true" ]; then
|
|
1640
1711
|
# Gate passes: remove any stale block report.
|
|
1641
1712
|
if [ -f "$COUNCIL_STATE_DIR/evidence-block.json" ]; then
|
|
1642
1713
|
rm -f "$COUNCIL_STATE_DIR/evidence-block.json"
|
|
1643
1714
|
fi
|
|
1715
|
+
# P1-1: when the gate passes ONLY because no test suite ran, say so out
|
|
1716
|
+
# loud. The pass is pass-through (no-tests must not deadlock), but a
|
|
1717
|
+
# completion that is not backed by any test evidence should never slip by
|
|
1718
|
+
# silently. The durable detail is in evidence-gate-details.json; this is
|
|
1719
|
+
# the human-visible honesty at the pass site.
|
|
1720
|
+
if [ "$test_inconclusive" = "true" ]; then
|
|
1721
|
+
log_warn "[Council] Evidence gate: completion not backed by test evidence (${test_inconclusive_reason}). Pass-through; set LOKI_EVIDENCE_NO_TESTS_AFFIRMATIVE=1 to treat no-tests as affirmative."
|
|
1722
|
+
fi
|
|
1723
|
+
_write_evidence_details "pass"
|
|
1644
1724
|
return 0
|
|
1645
1725
|
fi
|
|
1646
1726
|
|
|
@@ -1718,6 +1798,9 @@ EVIDENCE_EOF
|
|
|
1718
1798
|
>/dev/null 2>&1 || true
|
|
1719
1799
|
fi
|
|
1720
1800
|
|
|
1801
|
+
# P1-1: durable audit record for the block path too (see _write_evidence_details).
|
|
1802
|
+
_write_evidence_details "block"
|
|
1803
|
+
|
|
1721
1804
|
return 1
|
|
1722
1805
|
}
|
|
1723
1806
|
|
package/autonomy/crash.sh
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Loki Mode crash-reporting bash helpers (Phase 0: local-only, zero egress).
|
|
3
3
|
#
|
|
4
|
-
# This module is the single source of truth for the unified
|
|
5
|
-
# BOTH PostHog usage telemetry and local crash capture. It is
|
|
6
|
-
# helpers only; it executes nothing on source.
|
|
4
|
+
# This module is the single source of truth for the unified OPT-IN gate that
|
|
5
|
+
# controls BOTH PostHog usage telemetry and local crash capture. It is
|
|
6
|
+
# sourceable for helpers only; it executes nothing on source.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# Collection is OPT-IN and OFF by default. Nothing is collected, written, or
|
|
9
|
+
# sent unless the user explicitly opts in. A default install cannot phone home,
|
|
10
|
+
# which makes air-gapped, GDPR, and FedRAMP deployments safe out of the box.
|
|
11
|
+
#
|
|
12
|
+
# Opt-in (collection is enabled ONLY when one of these is present):
|
|
13
|
+
# - LOKI_TELEMETRY=on (case-insensitive, exact word "on")
|
|
14
|
+
# - ~/.loki/config line: TELEMETRY_ENABLED=true (written by: loki telemetry on)
|
|
15
|
+
#
|
|
16
|
+
# Opt-out always wins over opt-in (belt and suspenders for users who set both):
|
|
9
17
|
# - LOKI_TELEMETRY=off (case-insensitive)
|
|
10
18
|
# - LOKI_TELEMETRY_DISABLED=true
|
|
11
19
|
# - DO_NOT_TRACK=1
|
|
12
20
|
# - ~/.loki/config line: TELEMETRY_DISABLED=true
|
|
13
21
|
#
|
|
14
22
|
# All capture is best-effort: it never blocks the parent and always returns 0.
|
|
15
|
-
# Phase 0 has zero network egress
|
|
16
|
-
#
|
|
23
|
+
# Phase 0 has zero network egress; local capture is also gated by opt-in so a
|
|
24
|
+
# default install writes nothing at all.
|
|
17
25
|
|
|
18
26
|
# Double-source guard.
|
|
19
27
|
if [ -n "${_LOKI_CRASH_SH_SOURCED:-}" ]; then
|
|
@@ -25,26 +33,42 @@ _LOKI_CRASH_SH_SOURCED=1
|
|
|
25
33
|
_LOKI_CRASH_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
34
|
_LOKI_CRASH_CAPTURE_PY="${_LOKI_CRASH_DIR}/lib/crash_capture.py"
|
|
27
35
|
|
|
28
|
-
# loki_collection_enabled: returns 0 (enabled)
|
|
29
|
-
#
|
|
36
|
+
# loki_collection_enabled: returns 0 (enabled) ONLY when the user has opted in
|
|
37
|
+
# and has not also opted out. Opt-out always wins. Default is OFF (return 1).
|
|
38
|
+
# This is the SINGLE source of truth for telemetry + crash collection state, and
|
|
39
|
+
# its precedence MUST be mirrored by _is_enabled in dashboard/telemetry.py and
|
|
40
|
+
# _loki_telemetry_enabled in autonomy/telemetry.sh.
|
|
41
|
+
#
|
|
42
|
+
# Precedence:
|
|
43
|
+
# 1. Any opt-out flag present -> OFF (hard kill, always wins)
|
|
44
|
+
# 2. Else any opt-in flag present -> ON
|
|
45
|
+
# 3. Else (default) -> OFF (no egress, no local capture)
|
|
30
46
|
loki_collection_enabled() {
|
|
31
|
-
# Env: LOKI_TELEMETRY=off (case-insensitive)
|
|
32
47
|
local telem_lower
|
|
33
48
|
telem_lower="$(printf '%s' "${LOKI_TELEMETRY:-}" | tr '[:upper:]' '[:lower:]')"
|
|
34
|
-
[ "$telem_lower" = "off" ] && return 1
|
|
35
49
|
|
|
50
|
+
# --- 1. Opt-out always wins ---
|
|
51
|
+
# Env: LOKI_TELEMETRY=off (case-insensitive)
|
|
52
|
+
[ "$telem_lower" = "off" ] && return 1
|
|
36
53
|
# Env: LOKI_TELEMETRY_DISABLED=true
|
|
37
54
|
[ "${LOKI_TELEMETRY_DISABLED:-}" = "true" ] && return 1
|
|
38
|
-
|
|
39
55
|
# Env: DO_NOT_TRACK=1 (community standard)
|
|
40
56
|
[ "${DO_NOT_TRACK:-}" = "1" ] && return 1
|
|
41
|
-
|
|
42
|
-
# Persistent opt-out in ~/.loki/config (matches autonomy/run.sh:643 format).
|
|
57
|
+
# Persistent opt-out in ~/.loki/config.
|
|
43
58
|
if [ -f "${HOME}/.loki/config" ] && grep -q "^TELEMETRY_DISABLED=true" "${HOME}/.loki/config" 2>/dev/null; then
|
|
44
59
|
return 1
|
|
45
60
|
fi
|
|
46
61
|
|
|
47
|
-
|
|
62
|
+
# --- 2. Opt-in required to enable ---
|
|
63
|
+
# Env: LOKI_TELEMETRY=on (case-insensitive, exact word "on").
|
|
64
|
+
[ "$telem_lower" = "on" ] && return 0
|
|
65
|
+
# Persistent opt-in in ~/.loki/config (written by: loki telemetry on).
|
|
66
|
+
if [ -f "${HOME}/.loki/config" ] && grep -q "^TELEMETRY_ENABLED=true" "${HOME}/.loki/config" 2>/dev/null; then
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# --- 3. Default: OFF ---
|
|
71
|
+
return 1
|
|
48
72
|
}
|
|
49
73
|
|
|
50
74
|
# _loki_crash_python: resolve a python3 interpreter, or return 1 if absent.
|
|
@@ -144,15 +168,17 @@ loki_show_disclosure_once() {
|
|
|
144
168
|
return 0
|
|
145
169
|
fi
|
|
146
170
|
|
|
147
|
-
# Disclosure copy (
|
|
171
|
+
# Disclosure copy (opt-in framing; no emojis, no em dashes).
|
|
148
172
|
{
|
|
149
173
|
echo ""
|
|
150
|
-
echo "Loki Mode
|
|
151
|
-
echo "
|
|
152
|
-
echo "
|
|
153
|
-
echo "
|
|
154
|
-
echo "
|
|
155
|
-
echo "
|
|
174
|
+
echo "Loki Mode anonymous diagnostics are OFF by default. Nothing is collected"
|
|
175
|
+
echo "or sent unless you opt in, so a default install sends us no telemetry"
|
|
176
|
+
echo "or diagnostics. Air-gapped and enterprise deployments are safe out of"
|
|
177
|
+
echo "the box."
|
|
178
|
+
echo "If you opt in, we send anonymous diagnostics only (os, arch, version,"
|
|
179
|
+
echo "error type, sanitized stack signatures). Never your code, prompts, paths,"
|
|
180
|
+
echo "keys, or repo names."
|
|
181
|
+
echo "See docs/PRIVACY.md. Opt in anytime with: loki telemetry on"
|
|
156
182
|
echo ""
|
|
157
183
|
} >&2
|
|
158
184
|
|
package/autonomy/loki
CHANGED
|
@@ -4494,14 +4494,19 @@ cmd_dashboard_open() {
|
|
|
4494
4494
|
|
|
4495
4495
|
# Welcome opener (the "magic opener"). Shows a branded welcome page in the
|
|
4496
4496
|
# browser, or a terminal welcome when no browser is available (headless,
|
|
4497
|
-
# Docker, CI).
|
|
4498
|
-
#
|
|
4499
|
-
#
|
|
4497
|
+
# Docker, CI). Analytics are OPT-IN and OFF by default: unless the user has
|
|
4498
|
+
# opted in via the unified gate (loki_collection_enabled), the page is loaded
|
|
4499
|
+
# with ?telemetry=off so its form is inert and no analytics are ever sent.
|
|
4500
4500
|
WELCOME_MARKER="${HOME}/.loki/.welcomed"
|
|
4501
4501
|
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4502
|
+
# _loki_welcome_analytics_on: true only when the unified opt-in gate is on.
|
|
4503
|
+
# Falls back to "off" (no analytics) if the gate function is unavailable, which
|
|
4504
|
+
# keeps a default install from ever phoning home.
|
|
4505
|
+
_loki_welcome_analytics_on() {
|
|
4506
|
+
if type loki_collection_enabled &>/dev/null; then
|
|
4507
|
+
loki_collection_enabled && return 0
|
|
4508
|
+
return 1
|
|
4509
|
+
fi
|
|
4505
4510
|
return 1
|
|
4506
4511
|
}
|
|
4507
4512
|
|
|
@@ -4522,11 +4527,12 @@ cmd_welcome_terminal() {
|
|
|
4522
4527
|
echo -e " Quick start: ${BOLD}loki start ./prd.md${NC}"
|
|
4523
4528
|
echo -e " Docs: ${BOLD}https://www.autonomi.dev/docs${NC}"
|
|
4524
4529
|
echo ""
|
|
4525
|
-
if
|
|
4526
|
-
echo -e " ${DIM}
|
|
4530
|
+
if _loki_welcome_analytics_on; then
|
|
4531
|
+
echo -e " ${DIM}Anonymous usage analytics are ON (you opted in). We never collect${NC}"
|
|
4532
|
+
echo -e " ${DIM}prompts, PRDs, or code. Opt out: loki telemetry off${NC}"
|
|
4527
4533
|
else
|
|
4528
|
-
echo -e " ${DIM}Anonymous
|
|
4529
|
-
echo -e " ${DIM}
|
|
4534
|
+
echo -e " ${DIM}Anonymous analytics are off by default. Nothing is sent unless you${NC}"
|
|
4535
|
+
echo -e " ${DIM}opt in with: loki telemetry on${NC}"
|
|
4530
4536
|
fi
|
|
4531
4537
|
echo ""
|
|
4532
4538
|
}
|
|
@@ -4537,14 +4543,16 @@ cmd_welcome() {
|
|
|
4537
4543
|
|
|
4538
4544
|
local welcome_file="${SKILL_DIR}/assets/welcome/welcome.html"
|
|
4539
4545
|
|
|
4540
|
-
# Build the file URL with params: version, opt-
|
|
4546
|
+
# Build the file URL with params: version, opt-in state, and the existing
|
|
4541
4547
|
# anonymous telemetry distinct-id (so browser + install share one id).
|
|
4548
|
+
# Analytics are OFF by default: pass telemetry=off (inert form) UNLESS the
|
|
4549
|
+
# user has opted in via the unified gate.
|
|
4542
4550
|
local q="v=${ver}"
|
|
4543
|
-
if
|
|
4544
|
-
q="${q}&telemetry=off"
|
|
4545
|
-
else
|
|
4551
|
+
if _loki_welcome_analytics_on; then
|
|
4546
4552
|
local idfile="${HOME}/.loki-telemetry-id"
|
|
4547
4553
|
[ -f "$idfile" ] && q="${q}&did=$(cat "$idfile" 2>/dev/null | tr -d '[:space:]')"
|
|
4554
|
+
else
|
|
4555
|
+
q="${q}&telemetry=off"
|
|
4548
4556
|
fi
|
|
4549
4557
|
|
|
4550
4558
|
# Headless / Docker / CI / no-browser: print the terminal welcome only.
|
|
@@ -19742,12 +19750,13 @@ try {
|
|
|
19742
19750
|
|
|
19743
19751
|
# Unified collection state (PostHog usage telemetry + crash reporting).
|
|
19744
19752
|
# loki_collection_enabled is the single source of truth (crash.sh).
|
|
19753
|
+
# Collection is OPT-IN: OFF by default, enabled only after opt-in.
|
|
19745
19754
|
echo ""
|
|
19746
19755
|
if type loki_collection_enabled &>/dev/null; then
|
|
19747
19756
|
if loki_collection_enabled; then
|
|
19748
|
-
echo -e " Collection: ${GREEN}enabled${NC} (anonymous diagnostics;
|
|
19757
|
+
echo -e " Collection: ${GREEN}enabled${NC} (you opted in; anonymous diagnostics; opt out with: loki telemetry off)"
|
|
19749
19758
|
else
|
|
19750
|
-
echo -e " Collection: ${YELLOW}
|
|
19759
|
+
echo -e " Collection: ${YELLOW}off by default${NC} (nothing sent; opt in with: loki telemetry on)"
|
|
19751
19760
|
fi
|
|
19752
19761
|
fi
|
|
19753
19762
|
|
|
@@ -19828,13 +19837,17 @@ TELEM_DISABLE_PY
|
|
|
19828
19837
|
stop|off)
|
|
19829
19838
|
# Persistent opt-out across all sessions. This is the unified
|
|
19830
19839
|
# opt-out: it gates BOTH PostHog usage telemetry AND crash reporting.
|
|
19840
|
+
# Collection is opt-in (off by default), so this is mainly belt and
|
|
19841
|
+
# suspenders for users who previously opted in: it removes the
|
|
19842
|
+
# positive consent marker AND writes a hard opt-out that always wins.
|
|
19831
19843
|
local global_config="${HOME}/.loki/config"
|
|
19832
19844
|
mkdir -p "${HOME}/.loki"
|
|
19833
19845
|
|
|
19834
|
-
# Remove existing
|
|
19835
|
-
# (idempotent).
|
|
19846
|
+
# Remove existing TELEMETRY_ENABLED and TELEMETRY_DISABLED lines so we
|
|
19847
|
+
# never end up with both, then add the opt-out (idempotent).
|
|
19836
19848
|
if [ -f "$global_config" ]; then
|
|
19837
|
-
grep -v "^
|
|
19849
|
+
grep -v "^TELEMETRY_ENABLED=" "$global_config" \
|
|
19850
|
+
| grep -v "^TELEMETRY_DISABLED=" > "${global_config}.tmp" 2>/dev/null || true
|
|
19838
19851
|
mv "${global_config}.tmp" "$global_config"
|
|
19839
19852
|
fi
|
|
19840
19853
|
echo "TELEMETRY_DISABLED=true" >> "$global_config"
|
|
@@ -19843,20 +19856,27 @@ TELEM_DISABLE_PY
|
|
|
19843
19856
|
echo ""
|
|
19844
19857
|
echo " Opt-out saved to: $global_config"
|
|
19845
19858
|
echo " This persists across all sessions and new runs."
|
|
19846
|
-
echo " Run 'loki telemetry on' to
|
|
19859
|
+
echo " Run 'loki telemetry on' to opt back in."
|
|
19847
19860
|
;;
|
|
19848
19861
|
|
|
19849
19862
|
start|on)
|
|
19850
|
-
#
|
|
19863
|
+
# Persistent OPT-IN across all sessions. Collection is off by default;
|
|
19864
|
+
# this records explicit consent that the unified gate reads. Remove any
|
|
19865
|
+
# prior opt-out and the old marker, then write the positive consent.
|
|
19851
19866
|
local global_config="${HOME}/.loki/config"
|
|
19867
|
+
mkdir -p "${HOME}/.loki"
|
|
19852
19868
|
if [ -f "$global_config" ]; then
|
|
19853
|
-
grep -v "^
|
|
19869
|
+
grep -v "^TELEMETRY_ENABLED=" "$global_config" \
|
|
19870
|
+
| grep -v "^TELEMETRY_DISABLED=" > "${global_config}.tmp" 2>/dev/null || true
|
|
19854
19871
|
mv "${global_config}.tmp" "$global_config"
|
|
19855
19872
|
fi
|
|
19873
|
+
echo "TELEMETRY_ENABLED=true" >> "$global_config"
|
|
19856
19874
|
|
|
19857
|
-
echo -e "${BOLD}Telemetry and crash reporting
|
|
19875
|
+
echo -e "${BOLD}Telemetry and crash reporting enabled${NC}"
|
|
19858
19876
|
echo ""
|
|
19859
|
-
echo "
|
|
19877
|
+
echo " Opt-in saved to: $global_config"
|
|
19878
|
+
echo " Anonymous diagnostics collection is now ON for this user."
|
|
19879
|
+
echo " Run 'loki telemetry off' to opt back out at any time."
|
|
19860
19880
|
echo " OTEL tracing can be configured with 'loki telemetry enable [endpoint]'."
|
|
19861
19881
|
;;
|
|
19862
19882
|
|
|
@@ -19869,10 +19889,13 @@ TELEM_DISABLE_PY
|
|
|
19869
19889
|
echo " status Show OTEL config + collection state + pending crash reports"
|
|
19870
19890
|
echo " enable [endpoint] Enable OTEL (default: http://localhost:4318)"
|
|
19871
19891
|
echo " disable Disable OTEL for current project"
|
|
19892
|
+
echo " on Opt in to anonymous diagnostics (off by default)"
|
|
19872
19893
|
echo " off Opt out of all anonymous diagnostics (telemetry + crash)"
|
|
19873
|
-
echo " on
|
|
19874
|
-
echo " stop Alias for 'off' (
|
|
19875
|
-
echo "
|
|
19894
|
+
echo " start Alias for 'on' (persistent opt-in across all sessions)"
|
|
19895
|
+
echo " stop Alias for 'off' (persistent opt-out across all sessions)"
|
|
19896
|
+
echo ""
|
|
19897
|
+
echo "Anonymous diagnostics are OFF by default. Nothing is collected or"
|
|
19898
|
+
echo "sent unless you opt in. See docs/PRIVACY.md for the full disclosure."
|
|
19876
19899
|
echo ""
|
|
19877
19900
|
;;
|
|
19878
19901
|
*)
|