loki-mode 7.46.0 → 7.48.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/README.md +1 -1
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +113 -0
- package/autonomy/crash.sh +47 -21
- package/autonomy/loki +50 -27
- package/autonomy/run.sh +468 -5
- package/autonomy/spec-interrogation.sh +550 -0
- package/autonomy/telemetry.sh +28 -8
- package/bin/postinstall.js +22 -10
- package/dashboard/__init__.py +1 -1
- package/dashboard/auth.py +117 -2
- package/dashboard/telemetry.py +34 -6
- package/docs/ACKNOWLEDGEMENTS.md +1 -1
- package/docs/COMPETITIVE-ANALYSIS.md +1 -1
- package/docs/INSTALLATION.md +10 -3
- package/docs/OPEN-CORE-BOUNDARY.md +6 -5
- package/docs/P2-SPEC-ROBUSTNESS-PLAN.md +192 -0
- package/docs/PRIVACY.md +82 -24
- package/docs/R9-OPEN-CORE-HOOKS-PLAN.md +2 -2
- package/docs/auto-claude-comparison.md +2 -2
- package/docs/certification/README.md +1 -1
- package/docs/competitive/bolt-new-analysis.md +1 -1
- package/docs/competitive/emergence-others-analysis.md +6 -6
- package/docs/competitive/replit-lovable-analysis.md +4 -4
- package/docs/enterprise/security.md +43 -3
- package/docs/show-hn-post.md +1 -1
- 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/web-app/dist/assets/{AdminPage-CKUOsWZW.js → AdminPage-CcCJ0Sjt.js} +1 -1
- package/web-app/dist/assets/{Avatar-CL9Id9Hi.js → Avatar-DK8kmayw.js} +1 -1
- package/web-app/dist/assets/{Badge-B12zwlD7.js → Badge-4uAWnemi.js} +1 -1
- package/web-app/dist/assets/{Button-CFLVoduT.js → Button-BBMk33tk.js} +1 -1
- package/web-app/dist/assets/ComparePage-bt9rwvST.js +1 -0
- package/web-app/dist/assets/{GitHubIssuesPanel-CSitxtAX.js → GitHubIssuesPanel-WDbH47UM.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-BIT06FRo.js → GitHubPRsPanel-C2CiYtTx.js} +1 -1
- package/web-app/dist/assets/{HomePage-pU_0fGny.js → HomePage-BQk-MUjn.js} +4 -4
- package/web-app/dist/assets/{LoginPage-DTZtt2Yb.js → LoginPage-DMOZVGGL.js} +1 -1
- package/web-app/dist/assets/{MagicPage-10zfra8o.js → MagicPage-Bzp2Nt1z.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-C-wiKUkv.js → MetricsPage-C39JVdsw.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BDkcmhYe.js → NotFoundPage-6vT_U9UL.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CiCavQ8n.js → ProjectPage-BfFcZp-E.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BLCXQwwC.js → ProjectsPage-CPMBf8Wt.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-PkxtaMyg.js → SettingsPage-BnNN6ETl.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-iECp8Tha.js → ShowcasePage-WDrMf-cx.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-DS6Anno1.js → SystemSettingsPage-DX4jb2e8.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-ls6h6bNL.js → TeamsPage-BCfqcXzu.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Bk0QzlPt.js → TemplatesPage-CZvmimDj.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-4-1hWCtZ.js → TerminalOutput-BlRqFwWV.js} +1 -1
- package/web-app/dist/assets/{activity-DH3ih2nS.js → activity-CacZsUyr.js} +1 -1
- package/web-app/dist/assets/{bell-Gn17S6uv.js → bell-DK2qtHnk.js} +1 -1
- package/web-app/dist/assets/{bot-Cbycc3VE.js → bot-CkcUtHad.js} +1 -1
- package/web-app/dist/assets/{check-nIAqa-kf.js → check-CbCPjX3M.js} +1 -1
- package/web-app/dist/assets/{chevron-left-D2jcWDll.js → chevron-left-5NUKWw3i.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CpL4Bhvt.js → circle-alert-S7uFoxC2.js} +1 -1
- package/web-app/dist/assets/{clock-IW4Wq86N.js → clock-CaQRrIrs.js} +1 -1
- package/web-app/dist/assets/{cloud-Cn8nNuH2.js → cloud-DBAX6c0r.js} +1 -1
- package/web-app/dist/assets/{code-xml-BiJBteXf.js → code-xml-De5-EXv3.js} +1 -1
- package/web-app/dist/assets/{copy-CnqkyNsi.js → copy-CUkT6k1v.js} +1 -1
- package/web-app/dist/assets/{database-CKSReqa5.js → database-BAWf1Gwt.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-CDzDY64R.js → dollar-sign-Ji8zk86R.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-Box4IwG1.js → file-code-corner-ChtXoBwS.js} +1 -1
- package/web-app/dist/assets/{file-plus-DpGqlXF8.js → file-plus-bFa37P76.js} +1 -1
- package/web-app/dist/assets/{folder-open-B57dAoBv.js → folder-open-DhXpXscO.js} +1 -1
- package/web-app/dist/assets/{git-commit-horizontal-BVbucmO5.js → git-commit-horizontal-DVPeDQ3j.js} +1 -1
- package/web-app/dist/assets/{globe-BkOnKl4x.js → globe-BPZgPeeu.js} +1 -1
- package/web-app/dist/assets/{hammer-DRbIQ4QU.js → hammer-jLCaujYH.js} +1 -1
- package/web-app/dist/assets/{index-CM_b_EhP.js → index-B-0iHBPO.js} +2 -2
- package/web-app/dist/assets/{layers-B78BiFiU.js → layers-B1vsrsFW.js} +1 -1
- package/web-app/dist/assets/{lightbulb-B-Itbm9g.js → lightbulb-C-uLoq9Y.js} +1 -1
- package/web-app/dist/assets/{loader-circle-Oq6NQhW2.js → loader-circle-JTfD-ZuM.js} +1 -1
- package/web-app/dist/assets/{lock-DbJ9zxbw.js → lock-G9rxD4gZ.js} +1 -1
- package/web-app/dist/assets/{mail-CzMRod6m.js → mail-BJ0PTN_V.js} +1 -1
- package/web-app/dist/assets/{package-WZ5osvej.js → package-CXClfLOO.js} +1 -1
- package/web-app/dist/assets/{plus-j08lFR-K.js → plus-EoL5OCB7.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CIr7E-g2.js → refresh-cw-BjREUnVq.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-gwoXxDeE.js → rotate-ccw-DahWX07H.js} +1 -1
- package/web-app/dist/assets/{save-B8fV_ZpE.js → save-Dek3gCn1.js} +1 -1
- package/web-app/dist/assets/{server-D5dO1paz.js → server-D6V1BAia.js} +1 -1
- package/web-app/dist/assets/{shield-alert-Du08zhdg.js → shield-alert-BtTK5Sxb.js} +1 -1
- package/web-app/dist/assets/{trash-2-DEKSVae5.js → trash-2-BT5o_g0r.js} +1 -1
- package/web-app/dist/assets/{trending-down-DBiXUtxJ.js → trending-down-D4Jk7KF3.js} +1 -1
- package/web-app/dist/assets/{trending-up-BgmK_tHq.js → trending-up-EQFTzhEo.js} +1 -1
- package/web-app/dist/assets/{upload-IaViyeVD.js → upload-JfI5lCSE.js} +1 -1
- package/web-app/dist/assets/{usePolling-PiRLqNu6.js → usePolling-BnhPUuGd.js} +1 -1
- package/web-app/dist/assets/{user-BB5J8wAF.js → user-DSUiUYtj.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/web-app/dist/assets/ComparePage-Dg0UdZAk.js +0 -1
package/README.md
CHANGED
|
@@ -502,4 +502,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
|
502
502
|
|
|
503
503
|
## Star History
|
|
504
504
|
|
|
505
|
-
[](https://www.star-history.com/?repos=asklokesh%2Floki-mode&type=timeline&legend=bottom-right)
|
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.48.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.48.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.48.0
|
|
@@ -1721,6 +1721,111 @@ EVIDENCE_EOF
|
|
|
1721
1721
|
return 1
|
|
1722
1722
|
}
|
|
1723
1723
|
|
|
1724
|
+
#===============================================================================
|
|
1725
|
+
# P2-2 Assumption ledger gate (spec-robustness).
|
|
1726
|
+
#
|
|
1727
|
+
# Blocks completion while any high-severity assumption is unresolved, where
|
|
1728
|
+
# unresolved means: severity=high AND confirmed=false AND acknowledged=false.
|
|
1729
|
+
# This is the completion-side teeth for the spec-interrogation feature: when the
|
|
1730
|
+
# spec was ambiguous and Loki had to assume something high-impact, "done" cannot
|
|
1731
|
+
# be declared until that assumption has at least been acknowledged (auto-ack
|
|
1732
|
+
# lifecycle in run.sh, default-on) or human-confirmed
|
|
1733
|
+
# (LOKI_ASSUMPTIONS_REQUIRE_CONFIRM=1).
|
|
1734
|
+
#
|
|
1735
|
+
# By-design timing: in DEFAULT autonomous mode run.sh auto-acknowledges entries
|
|
1736
|
+
# every iteration right after injecting them into the build prompt, so by the
|
|
1737
|
+
# time the council reaches this gate (>= COUNCIL_MIN_ITERATIONS) they are already
|
|
1738
|
+
# acknowledged and the gate passes. That is intentional: a permanent block on
|
|
1739
|
+
# "unconfirmed" in a non-TTY run would just die at max-iterations and never reach
|
|
1740
|
+
# the proof-of-done. The PERSISTENT block lives in the
|
|
1741
|
+
# LOKI_ASSUMPTIONS_REQUIRE_CONFIRM=1 path (auto-ack disabled, only human
|
|
1742
|
+
# confirmed=true clears it). In BOTH modes the assumptions are unconditionally
|
|
1743
|
+
# SURFACED in proof-of-done (build_completion_summary reads counts ignoring
|
|
1744
|
+
# ack/confirm state), so "done" always means "done, plus here is what I assumed."
|
|
1745
|
+
#
|
|
1746
|
+
# The block COUNT comes from spec_ledger_high_unresolved_count() in
|
|
1747
|
+
# autonomy/spec-interrogation.sh. The gate sources that module if it is not
|
|
1748
|
+
# already loaded, so it works both inside run.sh (already sourced) and in
|
|
1749
|
+
# standalone tests (sources it here). When the module / ledger is absent the
|
|
1750
|
+
# count is 0 and the gate passes -- a project with no recorded assumptions is
|
|
1751
|
+
# never blocked (no spurious block on clean specs).
|
|
1752
|
+
#
|
|
1753
|
+
# Mirrors council_evidence_gate: opt-out knob first, defensive COUNCIL_STATE_DIR
|
|
1754
|
+
# default, writes .loki/council/assumption-block.json on block (removed on pass).
|
|
1755
|
+
#
|
|
1756
|
+
# Returns 0 (pass / OK to complete) or 1 (block / CONTINUE).
|
|
1757
|
+
#===============================================================================
|
|
1758
|
+
council_assumption_ledger_gate() {
|
|
1759
|
+
# Knob first: opt-out is exact-as-today, before any file read or write.
|
|
1760
|
+
[ "${LOKI_ASSUMPTION_GATE:-1}" = "0" ] && return 0
|
|
1761
|
+
|
|
1762
|
+
if [ -z "${COUNCIL_STATE_DIR:-}" ]; then
|
|
1763
|
+
COUNCIL_STATE_DIR="${TARGET_DIR:-.}/.loki/council"
|
|
1764
|
+
fi
|
|
1765
|
+
|
|
1766
|
+
# Source the spec-interrogation module if its counter is not already defined
|
|
1767
|
+
# (standalone tests / completion-promise route). Best-effort.
|
|
1768
|
+
if ! type spec_ledger_high_unresolved_count >/dev/null 2>&1; then
|
|
1769
|
+
local _si_helper
|
|
1770
|
+
_si_helper="$(dirname "${BASH_SOURCE[0]}")/spec-interrogation.sh"
|
|
1771
|
+
if [ -f "$_si_helper" ]; then
|
|
1772
|
+
# shellcheck disable=SC1090
|
|
1773
|
+
. "$_si_helper" 2>/dev/null || true
|
|
1774
|
+
fi
|
|
1775
|
+
fi
|
|
1776
|
+
|
|
1777
|
+
# No module => no ledger => nothing to block on (pass-through).
|
|
1778
|
+
if ! type spec_ledger_high_unresolved_count >/dev/null 2>&1; then
|
|
1779
|
+
if [ -f "$COUNCIL_STATE_DIR/assumption-block.json" ]; then
|
|
1780
|
+
rm -f "$COUNCIL_STATE_DIR/assumption-block.json"
|
|
1781
|
+
fi
|
|
1782
|
+
return 0
|
|
1783
|
+
fi
|
|
1784
|
+
|
|
1785
|
+
local unresolved
|
|
1786
|
+
unresolved="$(spec_ledger_high_unresolved_count 2>/dev/null || echo 0)"
|
|
1787
|
+
# Defensive: coerce to an integer.
|
|
1788
|
+
case "$unresolved" in
|
|
1789
|
+
''|*[!0-9]*) unresolved=0 ;;
|
|
1790
|
+
esac
|
|
1791
|
+
|
|
1792
|
+
if [ "$unresolved" -eq 0 ]; then
|
|
1793
|
+
# Gate passes: remove any stale block report.
|
|
1794
|
+
if [ -f "$COUNCIL_STATE_DIR/assumption-block.json" ]; then
|
|
1795
|
+
rm -f "$COUNCIL_STATE_DIR/assumption-block.json"
|
|
1796
|
+
fi
|
|
1797
|
+
return 0
|
|
1798
|
+
fi
|
|
1799
|
+
|
|
1800
|
+
log_warn "[Council] Assumption ledger gate BLOCKED: ${unresolved} high-severity spec assumption(s) unresolved (the spec was ambiguous in ${unresolved} high-impact place(s))."
|
|
1801
|
+
log_warn "[Council] Resolve by confirming them in .loki/assumptions/ (set confirmed=true), or opt out with LOKI_ASSUMPTION_GATE=0."
|
|
1802
|
+
|
|
1803
|
+
mkdir -p "$COUNCIL_STATE_DIR" 2>/dev/null || true
|
|
1804
|
+
local ab_file="$COUNCIL_STATE_DIR/assumption-block.json"
|
|
1805
|
+
local ab_tmp="${ab_file}.tmp"
|
|
1806
|
+
local timestamp
|
|
1807
|
+
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
1808
|
+
cat > "$ab_tmp" << ASSUMPTION_EOF
|
|
1809
|
+
{
|
|
1810
|
+
"status": "blocked",
|
|
1811
|
+
"blocked": true,
|
|
1812
|
+
"blocked_at": "$timestamp",
|
|
1813
|
+
"iteration": ${ITERATION_COUNT:-0},
|
|
1814
|
+
"reason": "high_severity_assumptions_unresolved",
|
|
1815
|
+
"high_unresolved": $unresolved
|
|
1816
|
+
}
|
|
1817
|
+
ASSUMPTION_EOF
|
|
1818
|
+
mv "$ab_tmp" "$ab_file" 2>/dev/null || rm -f "$ab_tmp" 2>/dev/null || true
|
|
1819
|
+
|
|
1820
|
+
if type record_trust_event_bash &>/dev/null; then
|
|
1821
|
+
record_trust_event_bash "assumption_block" \
|
|
1822
|
+
"high_unresolved=$unresolved" \
|
|
1823
|
+
>/dev/null 2>&1 || true
|
|
1824
|
+
fi
|
|
1825
|
+
|
|
1826
|
+
return 1
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1724
1829
|
#===============================================================================
|
|
1725
1830
|
# Council Member Review - Individual member evaluation
|
|
1726
1831
|
#===============================================================================
|
|
@@ -2512,6 +2617,14 @@ council_evaluate() {
|
|
|
2512
2617
|
return 1 # CONTINUE - cannot complete without real evidence
|
|
2513
2618
|
fi
|
|
2514
2619
|
|
|
2620
|
+
# P2-2: assumption ledger gate - block completion while high-severity spec
|
|
2621
|
+
# assumptions are unresolved (the spec was ambiguous in a high-impact place
|
|
2622
|
+
# and Loki had to assume something that has not been acknowledged/confirmed).
|
|
2623
|
+
if ! council_assumption_ledger_gate; then
|
|
2624
|
+
log_info "[Council] Completion blocked by assumption ledger gate"
|
|
2625
|
+
return 1 # CONTINUE - cannot complete with unresolved high-sev assumptions
|
|
2626
|
+
fi
|
|
2627
|
+
|
|
2515
2628
|
# Compute threshold using the same ceiling(2/3) formula as council_vote and council_aggregate_votes
|
|
2516
2629
|
local _eval_threshold=$(( (COUNCIL_SIZE * 2 + 2) / 3 ))
|
|
2517
2630
|
|
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
|
*)
|