loki-mode 7.32.1 → 7.32.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/loki +27 -4
- package/autonomy/run.sh +150 -12
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.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, 11 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.32.
|
|
6
|
+
# Loki Mode v7.32.3
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -398,4 +398,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
398
398
|
|
|
399
399
|
---
|
|
400
400
|
|
|
401
|
-
**v7.32.
|
|
401
|
+
**v7.32.3 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.32.
|
|
1
|
+
7.32.3
|
package/autonomy/loki
CHANGED
|
@@ -711,6 +711,7 @@ show_help() {
|
|
|
711
711
|
echo " --no-dashboard Disable web dashboard"
|
|
712
712
|
echo " --sandbox Run in Docker sandbox for isolation"
|
|
713
713
|
echo " --skip-memory Skip loading memory context at startup"
|
|
714
|
+
echo " --fresh-prd Regenerate the PRD from the codebase (no-PRD runs; ignores the reusable generated PRD)"
|
|
714
715
|
echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
|
|
715
716
|
echo " --budget USD Set cost budget limit (display in dashboard/status)"
|
|
716
717
|
echo " --bmad-project PATH Use BMAD Method project artifacts as input"
|
|
@@ -1030,6 +1031,9 @@ cmd_start() {
|
|
|
1030
1031
|
echo " --api Start dashboard API server alongside the build"
|
|
1031
1032
|
echo " --sandbox Run in Docker sandbox"
|
|
1032
1033
|
echo " --skip-memory Skip loading memory context at startup"
|
|
1034
|
+
echo " --fresh-prd Regenerate the PRD from the codebase on a no-PRD run"
|
|
1035
|
+
echo " (ignores the reusable generated PRD; aliases: --regen-prd,"
|
|
1036
|
+
echo " --regenerate-prd, --regen, or LOKI_PRD_REGEN=1)"
|
|
1033
1037
|
echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
|
|
1034
1038
|
echo " --budget USD Cost budget limit (auto-pause when exceeded)"
|
|
1035
1039
|
echo " --bmad-project PATH Use BMAD Method project artifacts as input"
|
|
@@ -1142,10 +1146,12 @@ cmd_start() {
|
|
|
1142
1146
|
args+=("--parallel")
|
|
1143
1147
|
shift
|
|
1144
1148
|
;;
|
|
1145
|
-
--regen-prd|--regenerate-prd|--regen)
|
|
1149
|
+
--regen-prd|--regenerate-prd|--regen|--fresh-prd)
|
|
1146
1150
|
# v7.8.1: force a fresh generated PRD on a no-PRD run, overriding
|
|
1147
1151
|
# the staleness-aware reuse (decide_generated_prd_action in
|
|
1148
1152
|
# run.sh reads LOKI_PRD_REGEN). Exported so the runner sees it.
|
|
1153
|
+
# --fresh-prd is the documented alias surfaced in the reuse
|
|
1154
|
+
# disclosure line ("pass --fresh-prd to regenerate").
|
|
1149
1155
|
export LOKI_PRD_REGEN=1
|
|
1150
1156
|
shift
|
|
1151
1157
|
;;
|
|
@@ -1820,13 +1826,30 @@ cmd_start() {
|
|
|
1820
1826
|
echo -e "${YELLOW}Warning: No PRD file specified. Auto-confirming (CI mode).${NC}"
|
|
1821
1827
|
else
|
|
1822
1828
|
echo -e "${YELLOW}No PRD file specified.${NC}"
|
|
1823
|
-
|
|
1824
|
-
|
|
1829
|
+
# v7.8.1+: the runner (run_autonomous -> decide_generated_prd_action)
|
|
1830
|
+
# makes the real reuse|update|generate decision. Here we only adjust
|
|
1831
|
+
# the TTY prompt wording so it does not falsely claim "generate" when
|
|
1832
|
+
# a previously generated PRD already exists. --regen-prd / --fresh-prd
|
|
1833
|
+
# (LOKI_PRD_REGEN=1) always forces a fresh generation.
|
|
1834
|
+
local _prompt_q="Generate PRD from codebase and start? [Y/n] "
|
|
1835
|
+
if [ "${LOKI_PRD_REGEN:-}" = "1" ]; then
|
|
1836
|
+
echo "Loki Mode will regenerate the PRD from the codebase (forced)."
|
|
1837
|
+
_prompt_q="Regenerate PRD from codebase (forced) and start? [Y/n] "
|
|
1838
|
+
elif [ -f ".loki/generated-prd.md" ] || [ -f ".loki/generated-prd.json" ]; then
|
|
1839
|
+
echo "A previously generated PRD exists. Loki Mode will reuse it"
|
|
1840
|
+
echo "if the codebase is unchanged, update it incrementally if it"
|
|
1841
|
+
echo "changed, or use it as-is if you hand-edited it. Pass"
|
|
1842
|
+
echo "--fresh-prd to regenerate from scratch."
|
|
1843
|
+
_prompt_q="Continue with the existing generated PRD and start? [Y/n] "
|
|
1844
|
+
else
|
|
1845
|
+
echo "Loki Mode will analyze the existing codebase and generate"
|
|
1846
|
+
echo "a PRD automatically. No requirements document needed."
|
|
1847
|
+
fi
|
|
1825
1848
|
echo ""
|
|
1826
1849
|
# v7.5.3 UX: rephrased + default flipped from N to Y. The pre-v7.5.3
|
|
1827
1850
|
# "Continue? [y/N]" with default-N caused users to accidentally
|
|
1828
1851
|
# cancel by hitting Enter after reading the explanation.
|
|
1829
|
-
echo -e "
|
|
1852
|
+
echo -e "$_prompt_q\c"
|
|
1830
1853
|
read -r confirm
|
|
1831
1854
|
if [[ "$confirm" =~ ^[Nn] ]]; then
|
|
1832
1855
|
echo "Aborted. Usage: loki start <path-to-prd.md>"
|
package/autonomy/run.sh
CHANGED
|
@@ -4543,7 +4543,14 @@ _loki_hash_stdin() {
|
|
|
4543
4543
|
# Compute a cheap, clone-stable signature of the codebase so we can tell whether
|
|
4544
4544
|
# it changed since the generated PRD was last written. Git repos: HEAD sha +
|
|
4545
4545
|
# dirty flag (.loki/.git churn filtered out). Non-git: a hash of sorted
|
|
4546
|
-
# path+size pairs
|
|
4546
|
+
# path+size pairs PLUS file content (v7.32.3, #569: path+size alone was blind to
|
|
4547
|
+
# a same-size content edit, so a stale PRD could be silently reused with a
|
|
4548
|
+
# false "codebase unchanged" disclosure). Content hashing is clone-stable
|
|
4549
|
+
# (mtime is not, which is why mtime was never used). Trees larger than
|
|
4550
|
+
# LOKI_PRD_SIG_CONTENT_BUDGET bytes (default 50MB) skip the content pass and
|
|
4551
|
+
# emit a "files-shallow:" signature so startup stays fast; the safe failure
|
|
4552
|
+
# mode there is unchanged-from-before (size-blind), never a false "changed".
|
|
4553
|
+
# Echoes the signature.
|
|
4547
4554
|
compute_codebase_signature() {
|
|
4548
4555
|
local dir="${1:-.}"
|
|
4549
4556
|
( cd "$dir" 2>/dev/null || exit 0
|
|
@@ -4558,7 +4565,7 @@ compute_codebase_signature() {
|
|
|
4558
4565
|
fi
|
|
4559
4566
|
echo "git:${head}:${dirty}"
|
|
4560
4567
|
else
|
|
4561
|
-
local listing count
|
|
4568
|
+
local listing count total_sz budget
|
|
4562
4569
|
listing=$(find . \
|
|
4563
4570
|
-type d \( -name .loki -o -name .git -o -name node_modules -o -name dist \
|
|
4564
4571
|
-o -name build -o -name .next -o -name target -o -name vendor \
|
|
@@ -4569,16 +4576,54 @@ compute_codebase_signature() {
|
|
|
4569
4576
|
sz=$(stat -f%z "$f" 2>/dev/null || stat -c%s "$f" 2>/dev/null || echo 0)
|
|
4570
4577
|
printf '%s\t%s\n' "$f" "$sz"
|
|
4571
4578
|
done | LC_ALL=C sort)
|
|
4572
|
-
|
|
4573
|
-
|
|
4579
|
+
# grep -c prints 0 itself on no match (exit 1); '|| true' avoids the
|
|
4580
|
+
# old '|| echo 0' double-zero that embedded a newline on empty trees
|
|
4581
|
+
count=$(printf '%s\n' "$listing" | grep -c . || true)
|
|
4582
|
+
total_sz=$(printf '%s\n' "$listing" | awk -F'\t' '{s+=$2} END {printf "%d", s}')
|
|
4583
|
+
budget="${LOKI_PRD_SIG_CONTENT_BUDGET:-52428800}"
|
|
4584
|
+
if [ "${total_sz:-0}" -le "$budget" ] 2>/dev/null; then
|
|
4585
|
+
# Content pass: stream all file contents through one hash in the
|
|
4586
|
+
# same sorted order as the listing. Detects same-size edits.
|
|
4587
|
+
# xargs -0 batches the reads into a handful of cat invocations,
|
|
4588
|
+
# so cost scales with BYTES (which the budget above bounds), not
|
|
4589
|
+
# file count: a fork-per-file loop here measured ~38s of added
|
|
4590
|
+
# startup on a 30k-small-file tree. Renames and content swaps
|
|
4591
|
+
# are still caught by the listing hash (paths+sizes) below.
|
|
4592
|
+
local content_hash
|
|
4593
|
+
content_hash=$(printf '%s\n' "$listing" | cut -f1 | tr '\n' '\0' \
|
|
4594
|
+
| xargs -0 cat 2>/dev/null | _loki_hash_stdin)
|
|
4595
|
+
echo "files:$(printf '%s' "$listing" | _loki_hash_stdin):${count}:${content_hash}"
|
|
4596
|
+
else
|
|
4597
|
+
echo "files-shallow:$(printf '%s' "$listing" | _loki_hash_stdin):${count}"
|
|
4598
|
+
fi
|
|
4574
4599
|
fi
|
|
4575
4600
|
)
|
|
4576
4601
|
}
|
|
4577
4602
|
|
|
4603
|
+
# Content hash of the generated PRD file itself (NOT the codebase). Used to
|
|
4604
|
+
# detect that a user hand-edited the generated PRD: when the file no longer
|
|
4605
|
+
# matches the prd_sha Loki recorded after it last wrote the file, the PRD is
|
|
4606
|
+
# user-owned and must be used as-is, never silently overwritten. Echoes "" when
|
|
4607
|
+
# no generated PRD file is present.
|
|
4608
|
+
_loki_prd_file_hash() {
|
|
4609
|
+
local loki_dir="${1:-.}/.loki"
|
|
4610
|
+
local f=""
|
|
4611
|
+
if [ -f "$loki_dir/generated-prd.md" ]; then
|
|
4612
|
+
f="$loki_dir/generated-prd.md"
|
|
4613
|
+
elif [ -f "$loki_dir/generated-prd.json" ]; then
|
|
4614
|
+
f="$loki_dir/generated-prd.json"
|
|
4615
|
+
fi
|
|
4616
|
+
[ -n "$f" ] || { echo ""; return 0; }
|
|
4617
|
+
_loki_hash_stdin < "$f"
|
|
4618
|
+
}
|
|
4619
|
+
|
|
4578
4620
|
# Decide what to do with a previously generated PRD on a no-PRD run.
|
|
4579
|
-
# Echoes one of: reuse | update | generate. Never fails the run.
|
|
4580
|
-
#
|
|
4621
|
+
# Echoes one of: reuse | update | generate | user_owned. Never fails the run.
|
|
4622
|
+
# Precedence: force-regen > user_owned (hand-edited) > reuse/update > generate.
|
|
4623
|
+
# - LOKI_PRD_REGEN=1 (or --regen-prd/--fresh-prd, which set it) -> generate.
|
|
4581
4624
|
# - no generated PRD present -> generate (first run).
|
|
4625
|
+
# - generated PRD present but its content hash differs from the recorded
|
|
4626
|
+
# prd_sha -> user_owned (the user hand-edited it; use as-is, do not rewrite).
|
|
4582
4627
|
# - generated PRD present, no recorded signature -> update (have a PRD but no
|
|
4583
4628
|
# provenance: reconcile incrementally rather than trust-blindly or discard).
|
|
4584
4629
|
# - signature matches current codebase -> reuse (unchanged).
|
|
@@ -4595,19 +4640,54 @@ decide_generated_prd_action() {
|
|
|
4595
4640
|
if [ ! -f "$sig_file" ]; then
|
|
4596
4641
|
echo "update"; return 0
|
|
4597
4642
|
fi
|
|
4598
|
-
local stored current
|
|
4643
|
+
local stored stored_prd_sha current cur_prd_sha
|
|
4599
4644
|
stored=$(LOKI_SIG_FILE="$sig_file" python3 -c "
|
|
4600
4645
|
import json, os
|
|
4601
4646
|
try:
|
|
4602
4647
|
print(json.load(open(os.environ['LOKI_SIG_FILE'])).get('signature',''))
|
|
4603
4648
|
except Exception:
|
|
4604
4649
|
print('')
|
|
4650
|
+
" 2>/dev/null)
|
|
4651
|
+
stored_prd_sha=$(LOKI_SIG_FILE="$sig_file" python3 -c "
|
|
4652
|
+
import json, os
|
|
4653
|
+
try:
|
|
4654
|
+
print(json.load(open(os.environ['LOKI_SIG_FILE'])).get('prd_sha',''))
|
|
4655
|
+
except Exception:
|
|
4656
|
+
print('')
|
|
4605
4657
|
" 2>/dev/null)
|
|
4606
4658
|
[ -z "$stored" ] && { echo "update"; return 0; }
|
|
4659
|
+
# Hand-edit detection (precedence above reuse/update): if we recorded a
|
|
4660
|
+
# prd_sha and the file no longer matches it, the user edited it themselves.
|
|
4661
|
+
# Treat as user-owned: use as-is, never regenerate over their changes.
|
|
4662
|
+
if [ -n "$stored_prd_sha" ]; then
|
|
4663
|
+
cur_prd_sha=$(_loki_prd_file_hash "${TARGET_DIR:-.}")
|
|
4664
|
+
if [ -n "$cur_prd_sha" ] && [ "$cur_prd_sha" != "$stored_prd_sha" ]; then
|
|
4665
|
+
echo "user_owned"; return 0
|
|
4666
|
+
fi
|
|
4667
|
+
fi
|
|
4607
4668
|
current=$(compute_codebase_signature "${TARGET_DIR:-.}")
|
|
4608
4669
|
if [ "$stored" = "$current" ]; then
|
|
4609
4670
|
echo "reuse"
|
|
4610
4671
|
else
|
|
4672
|
+
# v7.32.3 format transition (#569): a stored pre-content-hash signature
|
|
4673
|
+
# ("files:<listing>:<count>", 3 fields) compared against the new 4-field
|
|
4674
|
+
# format would falsely claim "codebase changed" on the first post-upgrade
|
|
4675
|
+
# run. When the new signature extends the stored one (same listing
|
|
4676
|
+
# fields), the tree is unchanged at the old format's trust level: reuse,
|
|
4677
|
+
# honestly. The next persist upgrades the stored format. A same-size edit
|
|
4678
|
+
# made BEFORE the upgrade stays invisible for this one run, exactly as it
|
|
4679
|
+
# was on the old version (no regression, no false disclosure).
|
|
4680
|
+
case "$stored" in
|
|
4681
|
+
files:*:*)
|
|
4682
|
+
# Require the legitimate old 3-field format (files:HASH:COUNT,
|
|
4683
|
+
# exactly 2 colons), not a truncated/corrupted 2-field value
|
|
4684
|
+
# (council hardening: corruption must fall to update, as before).
|
|
4685
|
+
if [ "$(printf '%s' "$stored" | tr -dc ':' | wc -c | tr -d ' ')" = "2" ] \
|
|
4686
|
+
&& [ "${current#"${stored}":}" != "$current" ]; then
|
|
4687
|
+
echo "reuse"; return 0
|
|
4688
|
+
fi
|
|
4689
|
+
;;
|
|
4690
|
+
esac
|
|
4611
4691
|
echo "update"
|
|
4612
4692
|
fi
|
|
4613
4693
|
}
|
|
@@ -4618,6 +4698,12 @@ except Exception:
|
|
|
4618
4698
|
persist_prd_signature_if_present() {
|
|
4619
4699
|
local exit_code="${1:-0}"
|
|
4620
4700
|
[ "$exit_code" = "0" ] || return 0
|
|
4701
|
+
# Hand-edited (user-owned) PRD: do NOT rewrite the signature. Re-hashing the
|
|
4702
|
+
# user's edited file would re-baseline its content as the new prd_sha, so the
|
|
4703
|
+
# next run would fall through to plain reuse with the wrong (non-user-owned)
|
|
4704
|
+
# disclosure. Preserve the prior Loki-authored prd_sha/generated_at so every
|
|
4705
|
+
# subsequent run keeps detecting user_owned until --fresh-prd forces a regen.
|
|
4706
|
+
[ "${GENERATED_PRD_ACTION:-}" = "user_owned" ] && return 0
|
|
4621
4707
|
# only for no-PRD runs whose generated PRD exists
|
|
4622
4708
|
case "${prd_path:-}" in
|
|
4623
4709
|
""|*.loki/generated-prd.md|*.loki/generated-prd.json) ;;
|
|
@@ -4630,17 +4716,47 @@ persist_prd_signature_if_present() {
|
|
|
4630
4716
|
[ -n "$sig" ] || return 0
|
|
4631
4717
|
mkdir -p "$loki_dir/state" 2>/dev/null || return 0
|
|
4632
4718
|
local mode="files"; case "$sig" in git:*) mode="git" ;; esac
|
|
4719
|
+
# Record the content hash of the PRD file Loki just wrote so a later
|
|
4720
|
+
# hand-edit by the user is detectable (decide_generated_prd_action). This
|
|
4721
|
+
# runs AFTER the agent's own PRD writes, so Loki's updates are not mistaken
|
|
4722
|
+
# for user edits.
|
|
4723
|
+
local prd_sha; prd_sha=$(_loki_prd_file_hash "${TARGET_DIR:-.}")
|
|
4633
4724
|
local tmp="$loki_dir/state/.prd-signature.json.tmp.$$"
|
|
4725
|
+
# Preserve generated_at when the codebase signature is unchanged so the
|
|
4726
|
+
# reuse disclosure ("generated on <date>") stays honest across reuse runs;
|
|
4727
|
+
# only stamp a new date when the PRD content actually changed (sig differs).
|
|
4634
4728
|
LOKI_SIG="$sig" LOKI_SIG_MODE="$mode" LOKI_SIG_VER="$(get_version 2>/dev/null || echo unknown)" \
|
|
4729
|
+
LOKI_PRD_SHA="$prd_sha" LOKI_SIG_FILE="$loki_dir/state/prd-signature.json" \
|
|
4635
4730
|
python3 -c "
|
|
4636
4731
|
import json, os, datetime
|
|
4732
|
+
sig = os.environ['LOKI_SIG']
|
|
4733
|
+
prev = {}
|
|
4734
|
+
try:
|
|
4735
|
+
prev = json.load(open(os.environ['LOKI_SIG_FILE']))
|
|
4736
|
+
except Exception:
|
|
4737
|
+
prev = {}
|
|
4738
|
+
prev_at = prev.get('generated_at') if isinstance(prev, dict) else None
|
|
4739
|
+
prev_sig = prev.get('signature') if isinstance(prev, dict) else None
|
|
4740
|
+
# Unchanged, OR the v7.32.3 files-signature format upgrade (#569): the new
|
|
4741
|
+
# 4-field signature extends an old 3-field one whose listing fields match.
|
|
4742
|
+
# Preserve the date in both cases; the PRD content did not change.
|
|
4743
|
+
_legacy_upgrade = (
|
|
4744
|
+
isinstance(prev_sig, str) and prev_sig.startswith('files:')
|
|
4745
|
+
and prev_sig.count(':') == 2
|
|
4746
|
+
and sig.startswith(prev_sig + ':')
|
|
4747
|
+
)
|
|
4748
|
+
if prev_at and (prev_sig == sig or _legacy_upgrade):
|
|
4749
|
+
generated_at = prev_at
|
|
4750
|
+
else:
|
|
4751
|
+
generated_at = datetime.datetime.now(datetime.timezone.utc).isoformat().replace('+00:00','Z')
|
|
4637
4752
|
rec = {
|
|
4638
|
-
'signature':
|
|
4639
|
-
'generated_at':
|
|
4753
|
+
'signature': sig,
|
|
4754
|
+
'generated_at': generated_at,
|
|
4640
4755
|
'prd_path': '.loki/generated-prd.md',
|
|
4756
|
+
'prd_sha': os.environ.get('LOKI_PRD_SHA',''),
|
|
4641
4757
|
'mode': os.environ['LOKI_SIG_MODE'],
|
|
4642
4758
|
'loki_version': os.environ['LOKI_SIG_VER'],
|
|
4643
|
-
}
|
|
4759
|
+
}
|
|
4644
4760
|
print(json.dumps(rec))
|
|
4645
4761
|
" > "$tmp" 2>/dev/null && mv -f "$tmp" "$loki_dir/state/prd-signature.json" 2>/dev/null || rm -f "$tmp" 2>/dev/null
|
|
4646
4762
|
}
|
|
@@ -12014,13 +12130,35 @@ run_autonomous() {
|
|
|
12014
12130
|
export GENERATED_PRD_ACTION
|
|
12015
12131
|
local _gen_prd=".loki/generated-prd.md"
|
|
12016
12132
|
[ -f ".loki/generated-prd.md" ] || _gen_prd=".loki/generated-prd.json"
|
|
12133
|
+
# Date the generated PRD was last written (for an honest disclosure).
|
|
12134
|
+
local _prd_date=""
|
|
12135
|
+
if [ -f ".loki/state/prd-signature.json" ]; then
|
|
12136
|
+
_prd_date=$(LOKI_SIG_FILE=".loki/state/prd-signature.json" python3 -c "
|
|
12137
|
+
import json, os
|
|
12138
|
+
try:
|
|
12139
|
+
d = json.load(open(os.environ['LOKI_SIG_FILE'])).get('generated_at','')
|
|
12140
|
+
print((d or '')[:10])
|
|
12141
|
+
except Exception:
|
|
12142
|
+
print('')
|
|
12143
|
+
" 2>/dev/null)
|
|
12144
|
+
fi
|
|
12017
12145
|
case "$GENERATED_PRD_ACTION" in
|
|
12018
12146
|
reuse)
|
|
12019
|
-
|
|
12147
|
+
if [ -n "$_prd_date" ]; then
|
|
12148
|
+
log_info "Reusing the PRD last generated or updated on $_prd_date; pass --fresh-prd to regenerate ($_gen_prd)"
|
|
12149
|
+
else
|
|
12150
|
+
log_info "Reusing the generated PRD (codebase unchanged); pass --fresh-prd to regenerate ($_gen_prd)"
|
|
12151
|
+
fi
|
|
12152
|
+
prd_path="$_gen_prd"
|
|
12153
|
+
;;
|
|
12154
|
+
user_owned)
|
|
12155
|
+
# The user hand-edited the generated PRD. Use it as-is (never
|
|
12156
|
+
# overwrite their edits); distinct disclosure from a clean reuse.
|
|
12157
|
+
log_info "Using your hand-edited PRD as-is ($_gen_prd); pass --fresh-prd to regenerate from the codebase"
|
|
12020
12158
|
prd_path="$_gen_prd"
|
|
12021
12159
|
;;
|
|
12022
12160
|
update)
|
|
12023
|
-
log_info "No user PRD found. Codebase changed since the generated PRD; will update it incrementally
|
|
12161
|
+
log_info "No user PRD found. Codebase changed since the generated PRD; will update it incrementally ($_gen_prd); pass --fresh-prd to regenerate from scratch"
|
|
12024
12162
|
prd_path="$_gen_prd"
|
|
12025
12163
|
;;
|
|
12026
12164
|
*)
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v7.32.
|
|
5
|
+
**Version:** v7.32.3
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.32.
|
|
2
|
+
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.32.3";if(typeof $==="string"&&$.length>0)return $$=$,$$;try{let Q=QQ(ZQ(import.meta.url)),Z=d$(Q);$$=e6($Q(Z,"VERSION"),"utf-8").trim()}catch{$$="unknown"}return $$}var $$=null;var n$=L(()=>{C()});var C1={};h(C1,{runOrThrow:()=>zQ,run:()=>j,commandVersion:()=>KQ,commandExists:()=>f,ShellError:()=>a$});async function j($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[W,K,U]=await Promise.all([new Response(Z.stdout).text(),new Response(Z.stderr).text(),Z.exited]);return{stdout:W,stderr:K,exitCode:U}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function zQ($,Q={}){let Z=await j($,Q);if(Z.exitCode!==0)throw new a$(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=XQ($),Z=await j(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function XQ($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function KQ($,Q="--version"){if(!await f($))return null;let z=await j([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var a$;var d=L(()=>{a$=class a$ extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function a($){return WQ?"":$}var WQ,T,S,I,TZ,w,R,y,q;var c=L(()=>{WQ=(process.env.NO_COLOR??"").length>0;T=a("\x1B[0;31m"),S=a("\x1B[0;32m"),I=a("\x1B[1;33m"),TZ=a("\x1B[0;34m"),w=a("\x1B[0;36m"),R=a("\x1B[1m"),y=a("\x1B[2m"),q=a("\x1B[0m")});import{existsSync as TQ}from"fs";async function Q$(){if(B$!==void 0)return B$;let $="/opt/homebrew/bin/python3.12";if(TQ($))return B$=$,$;let Q=await f("python3.12");if(Q)return B$=Q,Q;let Z=await f("python3");return B$=Z,Z}async function Z$($,Q={}){let Z=await Q$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return j([Z,"-c",$],Q)}var B$;var W$=L(()=>{d()});var t1={};h(t1,{runStatus:()=>gQ});import{existsSync as v,readFileSync as U$,readdirSync as l1,statSync as d1}from"fs";import{resolve as D,basename as xQ}from"path";import{homedir as NQ}from"os";async function DQ(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${q}
|
|
3
3
|
`),process.stdout.write(`Install with:
|
|
4
4
|
`),process.stdout.write(` brew install jq (macOS)
|
|
5
5
|
`),process.stdout.write(` apt install jq (Debian/Ubuntu)
|
|
@@ -789,4 +789,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
789
789
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
790
790
|
`),process.stderr.write(o6),2}}p1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var ZZ=await QZ(Bun.argv.slice(2));process.exit(ZZ);
|
|
791
791
|
|
|
792
|
-
//# debugId=
|
|
792
|
+
//# debugId=E69BF9B144A89A3864756E2164756E21
|
package/mcp/__init__.py
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
3
|
"mcpName": "io.github.asklokesh/loki-mode",
|
|
4
|
-
"version": "7.32.
|
|
4
|
+
"version": "7.32.3",
|
|
5
5
|
"description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 11 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent",
|