loki-mode 7.11.0 → 7.12.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/loki +152 -12
- package/autonomy/run.sh +72 -0
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/R7-ZERO-CONFIG-FIRST-RUN-PLAN.md +137 -0
- 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-to-product system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product via the RARV-C closure loop, with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v7.
|
|
6
|
+
# Loki Mode v7.12.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -381,4 +381,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
381
381
|
|
|
382
382
|
---
|
|
383
383
|
|
|
384
|
-
**v7.
|
|
384
|
+
**v7.12.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.12.0
|
package/autonomy/loki
CHANGED
|
@@ -739,6 +739,17 @@ detect_arg_type() {
|
|
|
739
739
|
return 0
|
|
740
740
|
fi
|
|
741
741
|
|
|
742
|
+
# R7 (zero-config first run): a one-line brief. An arg that contains
|
|
743
|
+
# whitespace and matched none of the file/issue/path patterns above is a
|
|
744
|
+
# natural-language brief (e.g. "build a todo app"), NOT a PRD path. This is
|
|
745
|
+
# additive: a single-token arg with no whitespace still falls through to
|
|
746
|
+
# "unknown" (PRD-path back-compat) below. The `--brief` flag is the
|
|
747
|
+
# deterministic escape hatch for the rare single-word brief.
|
|
748
|
+
if [[ "$arg" == *[[:space:]]* ]]; then
|
|
749
|
+
echo "brief"
|
|
750
|
+
return 0
|
|
751
|
+
fi
|
|
752
|
+
|
|
742
753
|
# Fallback: unknown. Caller treats as PRD for backward compat.
|
|
743
754
|
echo "unknown"
|
|
744
755
|
}
|
|
@@ -752,6 +763,7 @@ cmd_start() {
|
|
|
752
763
|
local args=()
|
|
753
764
|
local prd_file=""
|
|
754
765
|
local provider=""
|
|
766
|
+
local brief_text="" # R7: explicit one-line brief (--brief "...")
|
|
755
767
|
local bmad_project_path=""
|
|
756
768
|
local openspec_change_path=""
|
|
757
769
|
local mirofish_url=""
|
|
@@ -784,6 +796,8 @@ cmd_start() {
|
|
|
784
796
|
echo " PRD mode - path ending in .md/.json/.txt/.yaml -> build from PRD"
|
|
785
797
|
echo " ISSUE mode - GitHub/GitLab/Jira/Azure DevOps URL, owner/repo#N,"
|
|
786
798
|
echo " PROJ-123, #123, or bare number -> generate PRD from issue"
|
|
799
|
+
echo " BRIEF mode - a quoted one-line description (with spaces) -> fast"
|
|
800
|
+
echo " zero-config first run; visible artifact + proof quickly"
|
|
787
801
|
echo " no input - analyze current directory, auto-generate PRD"
|
|
788
802
|
echo ""
|
|
789
803
|
echo "Arguments:"
|
|
@@ -793,6 +807,7 @@ cmd_start() {
|
|
|
793
807
|
echo "Explicit mode flags (override auto-detection):"
|
|
794
808
|
echo " --prd FILE Force PRD mode with FILE"
|
|
795
809
|
echo " --issue URL|NUM Force issue mode with URL or number"
|
|
810
|
+
echo " --brief \"TEXT\" Force zero-config brief mode (fast first run)"
|
|
796
811
|
echo ""
|
|
797
812
|
echo "Options:"
|
|
798
813
|
echo " --provider NAME AI provider: claude (default), codex, cline, aider"
|
|
@@ -816,6 +831,7 @@ cmd_start() {
|
|
|
816
831
|
echo " --mirofish-bg Run MiroFish pipeline in background"
|
|
817
832
|
echo " --no-mirofish Disable MiroFish even if env var is set"
|
|
818
833
|
echo " --no-plan Skip auto-shown PRD analysis at startup"
|
|
834
|
+
echo " --brief \"TEXT\" Zero-config fast first run from a one-line brief"
|
|
819
835
|
echo " --yes, -y Skip confirmation prompts (auto-confirm)"
|
|
820
836
|
echo ""
|
|
821
837
|
echo "Issue-mode options (only used when input is an ISSUE-REF):"
|
|
@@ -836,6 +852,8 @@ cmd_start() {
|
|
|
836
852
|
echo ""
|
|
837
853
|
echo "Examples:"
|
|
838
854
|
echo " loki start # Interactive, analyze current dir"
|
|
855
|
+
echo " loki start \"build a todo app\" # BRIEF mode (zero-config fast run)"
|
|
856
|
+
echo " loki start --brief \"snake\" # BRIEF mode (single-word escape hatch)"
|
|
839
857
|
echo " loki start ./prd.md # PRD mode"
|
|
840
858
|
echo " loki start https://github.com/o/r/issues/42 # ISSUE mode (GitHub)"
|
|
841
859
|
echo " loki start 123 # ISSUE mode (current repo GitHub issue)"
|
|
@@ -1065,6 +1083,22 @@ cmd_start() {
|
|
|
1065
1083
|
no_plan=true
|
|
1066
1084
|
shift
|
|
1067
1085
|
;;
|
|
1086
|
+
--brief)
|
|
1087
|
+
# R7: explicit one-line brief (escape hatch for single-word
|
|
1088
|
+
# briefs that detect_arg_type would otherwise treat as a PRD
|
|
1089
|
+
# path). Forces the zero-config first-run brief sub-path.
|
|
1090
|
+
if [[ -n "${2:-}" ]] && [[ "${2:-}" != --* ]]; then
|
|
1091
|
+
brief_text="$2"
|
|
1092
|
+
shift 2
|
|
1093
|
+
else
|
|
1094
|
+
echo -e "${RED}--brief requires a one-line description (e.g., --brief \"build a todo app\")${NC}"
|
|
1095
|
+
exit 1
|
|
1096
|
+
fi
|
|
1097
|
+
;;
|
|
1098
|
+
--brief=*)
|
|
1099
|
+
brief_text="${1#*=}"
|
|
1100
|
+
shift
|
|
1101
|
+
;;
|
|
1068
1102
|
--budget)
|
|
1069
1103
|
if [[ -n "${2:-}" ]]; then
|
|
1070
1104
|
if ! echo "$2" | grep -qE '^[0-9]+(\.[0-9]+)?$'; then
|
|
@@ -1184,12 +1218,21 @@ cmd_start() {
|
|
|
1184
1218
|
done
|
|
1185
1219
|
|
|
1186
1220
|
# v6.84.0: Unified dispatch based on explicit flags or auto-detection
|
|
1187
|
-
# Precedence: --issue > --prd > positional auto-detect >
|
|
1221
|
+
# Precedence: --brief > --issue > --prd > positional auto-detect >
|
|
1222
|
+
# LOKI_PRD_FILE env
|
|
1188
1223
|
local detected_type=""
|
|
1189
|
-
if [ -n "$
|
|
1224
|
+
if [ -n "$brief_text" ]; then
|
|
1225
|
+
# R7: explicit --brief always forces the zero-config brief sub-path.
|
|
1226
|
+
detected_type="brief"
|
|
1227
|
+
elif [ -n "$explicit_mode" ]; then
|
|
1190
1228
|
detected_type="$explicit_mode"
|
|
1191
1229
|
elif [ -n "$positional_arg" ]; then
|
|
1192
1230
|
detected_type=$(detect_arg_type "$positional_arg")
|
|
1231
|
+
# R7: a positional one-line brief (whitespace, not a file/issue) maps to
|
|
1232
|
+
# the brief sub-path; capture the text from the positional arg.
|
|
1233
|
+
if [ "$detected_type" = "brief" ]; then
|
|
1234
|
+
brief_text="$positional_arg"
|
|
1235
|
+
fi
|
|
1193
1236
|
elif [ -n "${LOKI_PRD_FILE:-}" ]; then
|
|
1194
1237
|
detected_type="prd"
|
|
1195
1238
|
prd_file="$LOKI_PRD_FILE"
|
|
@@ -1229,6 +1272,51 @@ cmd_start() {
|
|
|
1229
1272
|
return $?
|
|
1230
1273
|
fi
|
|
1231
1274
|
|
|
1275
|
+
# R7 (zero-config first run): BRIEF mode. The user gave a one-line brief
|
|
1276
|
+
# (`loki start "build a todo app"` or `loki start --brief "..."`). Synthesize
|
|
1277
|
+
# a forward-looking PRD, switch to the lightweight TTFV profile (honest fast:
|
|
1278
|
+
# capped iterations, council off, simple tier, heavy phases off), and mark
|
|
1279
|
+
# LOKI_TTFV=1 so run.sh prints the "what next / go deeper" framing at the
|
|
1280
|
+
# end. Then fall through to the normal flow, which appends prd_file to args
|
|
1281
|
+
# and execs run.sh. This is additive -- nothing here changes the PRD/issue
|
|
1282
|
+
# paths above.
|
|
1283
|
+
if [ "$detected_type" = "brief" ]; then
|
|
1284
|
+
local version
|
|
1285
|
+
version=$(get_version)
|
|
1286
|
+
local _ttfv_max_iter="${LOKI_MAX_ITERATIONS:-3}"
|
|
1287
|
+
mkdir -p "$LOKI_DIR" 2>/dev/null || true
|
|
1288
|
+
local brief_prd="$LOKI_DIR/brief-prd-$$.md"
|
|
1289
|
+
synthesize_brief_prd "$brief_prd" "$brief_text"
|
|
1290
|
+
prd_file="$brief_prd"
|
|
1291
|
+
|
|
1292
|
+
# Apply the shared lightweight profile and flag the TTFV first-run path.
|
|
1293
|
+
# The signal value ("brief") drives the end-of-run wording in run.sh so
|
|
1294
|
+
# the message matches what actually ran (lightweight, council off).
|
|
1295
|
+
set_ttfv_lightweight_profile "$_ttfv_max_iter"
|
|
1296
|
+
export LOKI_TTFV=brief
|
|
1297
|
+
# Skip the heavy auto-plan analysis -- the brief path is the fast path,
|
|
1298
|
+
# and we already printed the upfront framing below.
|
|
1299
|
+
no_plan=true
|
|
1300
|
+
|
|
1301
|
+
echo -e "${BOLD}Loki Mode v$version - Zero-config first run${NC}"
|
|
1302
|
+
echo ""
|
|
1303
|
+
echo -e "${CYAN}Brief:${NC} $brief_text"
|
|
1304
|
+
echo -e "${DIM}Fast first pass: $_ttfv_max_iter iterations max, council off, simple tier.${NC}"
|
|
1305
|
+
echo -e "${DIM}You will get a runnable artifact and a proof-of-run quickly.${NC}"
|
|
1306
|
+
echo -e "${DIM}Go deeper later with: loki start (full RARV-C depth).${NC}"
|
|
1307
|
+
echo -e "${GREEN}Brief PRD written${NC} to $brief_prd"
|
|
1308
|
+
echo ""
|
|
1309
|
+
fi
|
|
1310
|
+
|
|
1311
|
+
# R7: existing-repo no-arg path also gets the TTFV "what next" framing at the
|
|
1312
|
+
# end of the run. Execution here is UNCHANGED (full-depth no-PRD codebase
|
|
1313
|
+
# analysis + generated-PRD-reuse); we only add accurate end-of-run framing.
|
|
1314
|
+
# The signal value ("repo") drives the full-depth wording in run.sh so the
|
|
1315
|
+
# message does not falsely claim a lightweight pass.
|
|
1316
|
+
if [ "$detected_type" = "empty" ] && [ -z "${LOKI_TTFV:-}" ]; then
|
|
1317
|
+
export LOKI_TTFV=repo
|
|
1318
|
+
fi
|
|
1319
|
+
|
|
1232
1320
|
# PRD mode: positional arg is the PRD file (if not already set via --prd)
|
|
1233
1321
|
if [ "$detected_type" = "prd" ] && [ -z "$prd_file" ]; then
|
|
1234
1322
|
prd_file="$positional_arg"
|
|
@@ -8847,6 +8935,65 @@ cmd_demo() {
|
|
|
8847
8935
|
return $start_exit
|
|
8848
8936
|
}
|
|
8849
8937
|
|
|
8938
|
+
# R7 (zero-config first run): set the lightweight TTFV execution profile.
|
|
8939
|
+
# Shared by `cmd_quick` and the `loki start "<brief>"` brief sub-path so the
|
|
8940
|
+
# fast first pass means the same thing in both: capped iterations, completion
|
|
8941
|
+
# council off, simple complexity tier, heavy phases off. This is HONEST fast --
|
|
8942
|
+
# it genuinely shortens the path to first visible value; it does not fake
|
|
8943
|
+
# progress. Depth is opt-in via a plain `loki start` re-run.
|
|
8944
|
+
# Usage: set_ttfv_lightweight_profile [max_iter]
|
|
8945
|
+
set_ttfv_lightweight_profile() {
|
|
8946
|
+
local max_iter="${1:-${LOKI_MAX_ITERATIONS:-3}}"
|
|
8947
|
+
export LOKI_MAX_ITERATIONS="$max_iter"
|
|
8948
|
+
export LOKI_COMPLEXITY=simple
|
|
8949
|
+
export LOKI_COUNCIL_ENABLED=false
|
|
8950
|
+
export LOKI_PHASE_CODE_REVIEW=false
|
|
8951
|
+
export LOKI_PHASE_PERFORMANCE=false
|
|
8952
|
+
export LOKI_PHASE_ACCESSIBILITY=false
|
|
8953
|
+
export LOKI_PHASE_REGRESSION=false
|
|
8954
|
+
export LOKI_PHASE_UAT=false
|
|
8955
|
+
export LOKI_PHASE_WEB_RESEARCH=false
|
|
8956
|
+
}
|
|
8957
|
+
|
|
8958
|
+
# R7: synthesize a forward-looking PRD from a one-line brief. Writes to a
|
|
8959
|
+
# unique path (caller-provided) and echoes nothing -- the file is the output.
|
|
8960
|
+
# Kept DISTINCT from .loki/generated-prd.md (codebase-analysis artifact) so it
|
|
8961
|
+
# never pollutes the v7.8.1 generated-PRD-reuse signature logic. The brief text
|
|
8962
|
+
# is the project intent; the rest is a minimal scaffold the agent fills in.
|
|
8963
|
+
# Usage: synthesize_brief_prd <output_file> <brief_text>
|
|
8964
|
+
synthesize_brief_prd() {
|
|
8965
|
+
local out_file="$1"
|
|
8966
|
+
local brief_text="$2"
|
|
8967
|
+
local out_dir
|
|
8968
|
+
out_dir="$(dirname "$out_file")"
|
|
8969
|
+
mkdir -p "$out_dir" 2>/dev/null || true
|
|
8970
|
+
cat > "$out_file" << BRIEFEOF
|
|
8971
|
+
# Project Brief
|
|
8972
|
+
|
|
8973
|
+
## Overview
|
|
8974
|
+
$brief_text
|
|
8975
|
+
|
|
8976
|
+
## Requirements
|
|
8977
|
+
- Build the smallest working version of the above that a user can see and run.
|
|
8978
|
+
- Prefer a runnable artifact (a page, a CLI, an API endpoint) over scaffolding.
|
|
8979
|
+
- Follow conventional structure for the chosen stack; keep dependencies minimal.
|
|
8980
|
+
- Write a short README describing how to run it.
|
|
8981
|
+
|
|
8982
|
+
## Success Criteria
|
|
8983
|
+
- A user can run the result and observe the core behavior described above.
|
|
8984
|
+
- No errors on a clean start; the happy path works end to end.
|
|
8985
|
+
|
|
8986
|
+
## Constraints
|
|
8987
|
+
- This is a fast first pass (zero-config first run). Keep scope tight.
|
|
8988
|
+
- Do not over-engineer; depth and hardening come on a later full run.
|
|
8989
|
+
- No emojis, no em dashes in code, comments, or docs.
|
|
8990
|
+
|
|
8991
|
+
---
|
|
8992
|
+
|
|
8993
|
+
**Mode:** Brief (zero-config first run, lightweight first pass)
|
|
8994
|
+
BRIEFEOF
|
|
8995
|
+
}
|
|
8996
|
+
|
|
8850
8997
|
# Quick mode - lightweight single-task execution
|
|
8851
8998
|
cmd_quick() {
|
|
8852
8999
|
# v7.6.3 B-11 fix: --help previously fell through to provider invocation
|
|
@@ -8934,16 +9081,9 @@ QPRDEOF
|
|
|
8934
9081
|
echo -e "${GREEN}Quick PRD generated${NC} at $quick_prd"
|
|
8935
9082
|
echo ""
|
|
8936
9083
|
|
|
8937
|
-
# Set lightweight execution environment
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
export LOKI_COUNCIL_ENABLED=false
|
|
8941
|
-
export LOKI_PHASE_CODE_REVIEW=false
|
|
8942
|
-
export LOKI_PHASE_PERFORMANCE=false
|
|
8943
|
-
export LOKI_PHASE_ACCESSIBILITY=false
|
|
8944
|
-
export LOKI_PHASE_REGRESSION=false
|
|
8945
|
-
export LOKI_PHASE_UAT=false
|
|
8946
|
-
export LOKI_PHASE_WEB_RESEARCH=false
|
|
9084
|
+
# Set lightweight execution environment (shared TTFV profile -- see
|
|
9085
|
+
# set_ttfv_lightweight_profile; same profile the R7 brief sub-path uses).
|
|
9086
|
+
set_ttfv_lightweight_profile "$max_iter"
|
|
8947
9087
|
|
|
8948
9088
|
# Record start for efficiency tracking
|
|
8949
9089
|
record_session_start
|
package/autonomy/run.sh
CHANGED
|
@@ -4121,6 +4121,69 @@ generate_proof_of_run() {
|
|
|
4121
4121
|
return 0
|
|
4122
4122
|
}
|
|
4123
4123
|
|
|
4124
|
+
# print_ttfv_next_steps: R7 zero-config first-run "what next / go deeper"
|
|
4125
|
+
# message. The wording MUST match what actually ran, so it branches on the mode:
|
|
4126
|
+
# - brief: a one-line brief ran on the lightweight profile (council off,
|
|
4127
|
+
# simple tier, capped iterations). Proof contains diffs, cost, time
|
|
4128
|
+
# (council verdicts are absent because the council was disabled).
|
|
4129
|
+
# - repo: a no-arg in-repo run analyzed the codebase and ran at full depth
|
|
4130
|
+
# (council on). Proof contains diffs, cost, time, and council
|
|
4131
|
+
# verdicts.
|
|
4132
|
+
# This function only prints; the caller owns the TTY gate. Never fails the run.
|
|
4133
|
+
# Usage: print_ttfv_next_steps <mode> <result>
|
|
4134
|
+
print_ttfv_next_steps() {
|
|
4135
|
+
local mode="${1:-}"
|
|
4136
|
+
local result="${2:-0}"
|
|
4137
|
+
local loki_dir="${TARGET_DIR:-.}/.loki"
|
|
4138
|
+
local proofs_dir="$loki_dir/proofs"
|
|
4139
|
+
|
|
4140
|
+
echo ""
|
|
4141
|
+
echo "============================================================"
|
|
4142
|
+
if [ "$result" = "0" ]; then
|
|
4143
|
+
echo " First pass complete. Here is what you have:"
|
|
4144
|
+
else
|
|
4145
|
+
echo " First pass ended early. Here is what was produced:"
|
|
4146
|
+
fi
|
|
4147
|
+
echo "============================================================"
|
|
4148
|
+
echo ""
|
|
4149
|
+
echo " What I did:"
|
|
4150
|
+
if [ "$mode" = "brief" ]; then
|
|
4151
|
+
echo " - Worked from your one-line brief on a fast, lightweight first"
|
|
4152
|
+
echo " pass (council off, simple tier, capped iterations)."
|
|
4153
|
+
echo " - Generated a proof-of-run (diffs, cost, time)."
|
|
4154
|
+
else
|
|
4155
|
+
echo " - Analyzed your codebase and generated a PRD, then ran a full"
|
|
4156
|
+
echo " first pass (council on, full RARV-C depth)."
|
|
4157
|
+
echo " - Generated a proof-of-run (diffs, cost, time, council verdicts)."
|
|
4158
|
+
fi
|
|
4159
|
+
echo ""
|
|
4160
|
+
echo " See the visible artifact (proof-of-run):"
|
|
4161
|
+
if [ -d "$proofs_dir" ]; then
|
|
4162
|
+
local latest
|
|
4163
|
+
latest=$(ls -1t "$proofs_dir" 2>/dev/null | head -1)
|
|
4164
|
+
if [ -n "$latest" ]; then
|
|
4165
|
+
echo " loki proof open $latest"
|
|
4166
|
+
echo " (or open $proofs_dir/$latest/index.html)"
|
|
4167
|
+
else
|
|
4168
|
+
echo " loki proof list"
|
|
4169
|
+
fi
|
|
4170
|
+
else
|
|
4171
|
+
echo " loki proof list"
|
|
4172
|
+
fi
|
|
4173
|
+
echo ""
|
|
4174
|
+
if [ "$mode" = "brief" ]; then
|
|
4175
|
+
echo " Go deeper (full RARV-C depth, council-gated):"
|
|
4176
|
+
echo " loki start # continue / harden this project"
|
|
4177
|
+
echo " loki start ./prd.md # build from a full PRD"
|
|
4178
|
+
else
|
|
4179
|
+
echo " Next steps:"
|
|
4180
|
+
echo " loki start ./prd.md # build from a full PRD"
|
|
4181
|
+
echo " loki start \"<one line>\" # fast first pass from a brief"
|
|
4182
|
+
fi
|
|
4183
|
+
echo ""
|
|
4184
|
+
return 0
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4124
4187
|
track_iteration_complete() {
|
|
4125
4188
|
local iteration="$1"
|
|
4126
4189
|
local exit_code="${2:-0}"
|
|
@@ -13335,6 +13398,15 @@ main() {
|
|
|
13335
13398
|
generate_proof_of_run "$result" || true
|
|
13336
13399
|
fi
|
|
13337
13400
|
|
|
13401
|
+
# R7 (zero-config first run): "what next / go deeper" framing. Only when the
|
|
13402
|
+
# CLI flagged this as a TTFV first run and stdout is a TTY, so it stays
|
|
13403
|
+
# silent in CI / pipes and never fires for normal PRD runs. The wording
|
|
13404
|
+
# branches on the mode (brief = lightweight first pass; repo = full-depth
|
|
13405
|
+
# codebase analysis) so the message always matches what actually ran.
|
|
13406
|
+
if [ -n "${LOKI_TTFV:-}" ] && [ -t 1 ]; then
|
|
13407
|
+
print_ttfv_next_steps "${LOKI_TTFV}" "$result" || true
|
|
13408
|
+
fi
|
|
13409
|
+
|
|
13338
13410
|
# Create PR from agent branch if branch protection was enabled
|
|
13339
13411
|
create_session_pr
|
|
13340
13412
|
audit_agent_action "session_stop" "Session ended" "result=$result,iterations=$ITERATION_COUNT"
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# R7: Zero-config killer first run (time-to-first-value)
|
|
2
|
+
|
|
3
|
+
Design note for the R7 release in the competitive-stickiness arc. Worktree
|
|
4
|
+
deliverable for the integrator to cherry-pick. NO version bumps here.
|
|
5
|
+
|
|
6
|
+
## Goal
|
|
7
|
+
|
|
8
|
+
Convert trials to habits. The #1 acquisition-to-retention gate is the first
|
|
9
|
+
run. Today a blank first run is mediocre and Loki's deep RARV-C / council can
|
|
10
|
+
feel heavy on run 1. R7 = a frictionless first run: a user types
|
|
11
|
+
`loki start "<one line>"` (or `loki start` in an existing repo) and sees a
|
|
12
|
+
VISIBLE valuable artifact in minutes, with depth opt-in later.
|
|
13
|
+
|
|
14
|
+
Honest "fast": we do NOT fake progress. We actually shorten the path by running
|
|
15
|
+
a lightweight execution profile first (capped iterations, completion council
|
|
16
|
+
off, simple complexity tier, heavy phases off) so the first visible artifact
|
|
17
|
+
plus a proof-of-run land quickly. "Go deeper" = re-run plain `loki start` for
|
|
18
|
+
the full RARV-C depth.
|
|
19
|
+
|
|
20
|
+
## Verified current behavior (real code, traced 2026-06-03)
|
|
21
|
+
|
|
22
|
+
- `cmd_start()` (`autonomy/loki:746`) is the unified entry. It parses args,
|
|
23
|
+
calls `detect_arg_type()` (`autonomy/loki:667`), then dispatches:
|
|
24
|
+
issue -> `cmd_run`; prd -> sets `prd_file`; empty -> no-PRD path; unknown
|
|
25
|
+
-> treated as a PRD path for back-compat.
|
|
26
|
+
- `cmd_start` ends in `_loki_new_session_exec "$RUN_SH" ...` (`autonomy/loki:1678`).
|
|
27
|
+
Every branch of `_loki_new_session_exec` (`autonomy/loki:167-186`) uses
|
|
28
|
+
`exec`, so NOTHING after that line in `cmd_start` runs. Any end-of-run
|
|
29
|
+
message must live in `run.sh`, not after the exec in `cmd_start`.
|
|
30
|
+
- `cmd_quick()` (`autonomy/loki:8849`) already synthesizes a PRD from a
|
|
31
|
+
one-line task and sets the lightweight profile
|
|
32
|
+
(`LOKI_MAX_ITERATIONS=3`, `LOKI_COMPLEXITY=simple`,
|
|
33
|
+
`LOKI_COUNCIL_ENABLED=false`, heavy phases off), then execs `run.sh`.
|
|
34
|
+
- No-PRD + generated-PRD-reuse (v7.8.1): in `run.sh` around line 11102,
|
|
35
|
+
`decide_generated_prd_action()` (`run.sh:4032`) returns reuse|update|generate
|
|
36
|
+
for the no-arg in-repo path; signature persisted by
|
|
37
|
+
`persist_prd_signature_if_present()` (`run.sh:4064`).
|
|
38
|
+
- Proof-of-run (R1): `generate_proof_of_run()` (`run.sh:4101`) wraps
|
|
39
|
+
`autonomy/lib/proof-generator.py`. It runs at session end (`run.sh:13312`)
|
|
40
|
+
on both success and failure, gated only by `LOKI_PROOF` (NOT by council
|
|
41
|
+
state), writing `.loki/proofs/<run_id>/{proof.json,index.html}`. Viewable
|
|
42
|
+
via `loki proof list` / `loki proof open <id>` (Bun-routed, `bin/loki:119`).
|
|
43
|
+
|
|
44
|
+
### The exact gap R7 closes (traced, not assumed)
|
|
45
|
+
|
|
46
|
+
`loki start "build a todo app"` TODAY:
|
|
47
|
+
1. `detect_arg_type("build a todo app")` returns `unknown` (has spaces, no
|
|
48
|
+
extension, not a file, not an issue ref).
|
|
49
|
+
2. The PRD-not-found guard at `autonomy/loki:1243` and `:1268` only fires for
|
|
50
|
+
`*.md|*.json|*.txt|*.yaml|*.yml`, so a brief with spaces slips past.
|
|
51
|
+
3. `prd_file="build a todo app"` is passed to `run.sh`, which fails:
|
|
52
|
+
`[ERROR] PRD file not found: build a todo app`.
|
|
53
|
+
|
|
54
|
+
So the one-line-brief path is broken today. R7 makes it work. This is ADDITIVE:
|
|
55
|
+
no existing valid input (`.md` PRD, issue ref, single-token name) changes
|
|
56
|
+
behavior.
|
|
57
|
+
|
|
58
|
+
## Design (additive, no behavior change to existing inputs)
|
|
59
|
+
|
|
60
|
+
1. `detect_arg_type`: add a `brief` return ONLY for args that contain
|
|
61
|
+
whitespace and match none of the file/issue/path patterns. A single-token
|
|
62
|
+
`unknown` arg still falls back to PRD path (back-compat preserved).
|
|
63
|
+
2. `--brief "<text>"` explicit flag: deterministic escape hatch for the rare
|
|
64
|
+
single-word brief (e.g. `loki start --brief "snake"`).
|
|
65
|
+
3. Shared helper `synthesize_brief_prd <file> <text>`: factored so `cmd_quick`
|
|
66
|
+
and the new brief path write the same forward-looking PRD. The brief PRD is
|
|
67
|
+
written to `.loki/brief-prd-$$.md` -- DISTINCT from `.loki/generated-prd.md`
|
|
68
|
+
so it never pollutes the v7.8.1 generated-PRD-reuse signature logic
|
|
69
|
+
(generated-prd is for codebase analysis of an existing repo; brief is a
|
|
70
|
+
forward spec).
|
|
71
|
+
4. `cmd_start` brief sub-path: set the lightweight TTFV profile (same env as
|
|
72
|
+
quick), synthesize the brief PRD, set `LOKI_TTFV=brief`, then continue
|
|
73
|
+
through the normal exec path. Upfront framing ("fast first pass") is printed
|
|
74
|
+
BEFORE the exec.
|
|
75
|
+
5. `cmd_start` no-arg in-repo path: UNCHANGED execution (existing no-PRD +
|
|
76
|
+
reuse, full RARV-C depth), but set `LOKI_TTFV=repo` so the end-of-run
|
|
77
|
+
what-next framing appears.
|
|
78
|
+
6. `run.sh` end-of-session: after proof generation, when `LOKI_TTFV` is set and
|
|
79
|
+
stdout is a TTY, call `print_ttfv_next_steps <mode> <result>`. The wording
|
|
80
|
+
BRANCHES on mode so the message always matches what actually ran:
|
|
81
|
+
- `brief`: lightweight first pass, council off; proof has diffs/cost/time
|
|
82
|
+
(NO council verdicts, because the council was disabled).
|
|
83
|
+
- `repo`: full-depth codebase analysis, council on; proof has
|
|
84
|
+
diffs/cost/time/council verdicts.
|
|
85
|
+
Both point at `loki proof list` / `loki proof open` (the visible artifact)
|
|
86
|
+
and the depth opt-in. Gated so it is silent in CI / pipes and never fires
|
|
87
|
+
for normal PRD runs. Factored into `print_ttfv_next_steps` so it is
|
|
88
|
+
unit-testable.
|
|
89
|
+
|
|
90
|
+
Honesty note: the `brief` message intentionally does NOT advertise "council
|
|
91
|
+
verdicts" because brief mode runs with the council off (`_collect_council` in
|
|
92
|
+
proof-generator.py finds no council state, so that proof section is blank on the
|
|
93
|
+
brief path). The `repo` message claims verdicts because the full-depth path runs
|
|
94
|
+
the council. This keeps the end-of-run summary truthful per the no-fabrication
|
|
95
|
+
rule.
|
|
96
|
+
|
|
97
|
+
### Why fast is honest
|
|
98
|
+
|
|
99
|
+
The brief path uses the same lightweight profile `cmd_quick` already ships:
|
|
100
|
+
3 iterations max, council off, simple tier, heavy phases (perf, a11y,
|
|
101
|
+
regression, UAT, web-research) off. That genuinely shortens the path to first
|
|
102
|
+
visible value. We do not print fake progress or claim work that did not happen;
|
|
103
|
+
the proof-of-run is generated from real `.loki/` state. Depth is opt-in: the
|
|
104
|
+
end-of-run message tells the user to re-run plain `loki start` (or
|
|
105
|
+
`loki start <prd.md>`) for the full council-gated build.
|
|
106
|
+
|
|
107
|
+
## Parity (bash + Bun)
|
|
108
|
+
|
|
109
|
+
`loki start` and `loki quick` are NOT in the Bun shim allowlist
|
|
110
|
+
(`bin/loki:119`), so dispatch is bash-only by design; this change is bash-only
|
|
111
|
+
for the CLI surface. The runtime pieces it reuses are already shared across
|
|
112
|
+
routes: `proof-generator.py` (one implementation, both routes) and the no-PRD /
|
|
113
|
+
generated-PRD-reuse path in `run.sh` (both routes source run.sh). No Bun CLI
|
|
114
|
+
change is required for parity.
|
|
115
|
+
|
|
116
|
+
## Files
|
|
117
|
+
|
|
118
|
+
- `autonomy/loki`: `detect_arg_type` brief return; `--brief` flag;
|
|
119
|
+
`synthesize_brief_prd` helper; `cmd_quick` refactor to use it; `cmd_start`
|
|
120
|
+
brief sub-path + `LOKI_TTFV` wiring; help text.
|
|
121
|
+
- `autonomy/run.sh`: end-of-session TTFV what-next block.
|
|
122
|
+
- `tests/cli/test_zero_config_first_run.sh`: new test suite.
|
|
123
|
+
|
|
124
|
+
## Tests (no paid runs; mock via early exit)
|
|
125
|
+
|
|
126
|
+
Following `tests/cli/test_start_run_unified.sh`: extract `detect_arg_type` and
|
|
127
|
+
`synthesize_brief_prd` in a subshell and assert on them; force `cmd_start` to
|
|
128
|
+
exit before `run.sh` boots via `--provider nonexistent-provider`.
|
|
129
|
+
|
|
130
|
+
- `detect_arg_type("build a todo app")` = `brief`; single tokens still `unknown`;
|
|
131
|
+
`.md` still `prd`; issue refs still `issue`; empty still `empty`.
|
|
132
|
+
- `synthesize_brief_prd` writes a PRD containing the brief text and TTFV markers.
|
|
133
|
+
- `loki start "<brief>"` enters the brief path (lightweight env, not
|
|
134
|
+
"PRD file not found").
|
|
135
|
+
- `loki start --brief "<one word>"` works.
|
|
136
|
+
- existing-repo no-arg path still routes to no-PRD (unchanged).
|
|
137
|
+
- `loki start <prd.md>` (real PRD) still routes to PRD mode (no regression).
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var N7=Object.defineProperty;var k7=(K)=>K;function D7(K,$){this[K]=k7.bind(null,$)}var v=(K,$)=>{for(var Q in $)N7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:D7.bind($,Q)})};var E=(K,$)=>()=>(K&&($=K(K=0)),$);var $1=import.meta.require;var z0={};v(z0,{lokiDir:()=>w,homeLokiDir:()=>v1,findRepoRootForVersion:()=>y1,REPO_ROOT:()=>c});import{resolve as p,dirname as b1}from"path";import{fileURLToPath as C7}from"url";import{existsSync as O1}from"fs";import{homedir as h7}from"os";function b7(){let K=Z0;for(let $=0;$<6;$++){if(O1(p(K,"VERSION"))&&O1(p(K,"autonomy/run.sh")))return K;let Q=b1(K);if(Q===K)break;K=Q}return p(Z0,"..","..","..")}function y1(K){let $=K;for(let Q=0;Q<6;Q++){if(O1(p($,"VERSION"))&&O1(p($,"autonomy/run.sh")))return $;let X=b1($);if(X===$)break;$=X}return p(K,"..","..","..")}function w(){return process.env.LOKI_DIR??p(process.cwd(),".loki")}function v1(){return p(h7(),".loki")}var Z0,c;var g=E(()=>{Z0=b1(C7(import.meta.url));c=b7()});import{readFileSync as y7}from"fs";import{resolve as v7,dirname as g7}from"path";import{fileURLToPath as m7}from"url";function T1(){if(r!==null)return r;let K="7.
|
|
2
|
+
var N7=Object.defineProperty;var k7=(K)=>K;function D7(K,$){this[K]=k7.bind(null,$)}var v=(K,$)=>{for(var Q in $)N7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:D7.bind($,Q)})};var E=(K,$)=>()=>(K&&($=K(K=0)),$);var $1=import.meta.require;var z0={};v(z0,{lokiDir:()=>w,homeLokiDir:()=>v1,findRepoRootForVersion:()=>y1,REPO_ROOT:()=>c});import{resolve as p,dirname as b1}from"path";import{fileURLToPath as C7}from"url";import{existsSync as O1}from"fs";import{homedir as h7}from"os";function b7(){let K=Z0;for(let $=0;$<6;$++){if(O1(p(K,"VERSION"))&&O1(p(K,"autonomy/run.sh")))return K;let Q=b1(K);if(Q===K)break;K=Q}return p(Z0,"..","..","..")}function y1(K){let $=K;for(let Q=0;Q<6;Q++){if(O1(p($,"VERSION"))&&O1(p($,"autonomy/run.sh")))return $;let X=b1($);if(X===$)break;$=X}return p(K,"..","..","..")}function w(){return process.env.LOKI_DIR??p(process.cwd(),".loki")}function v1(){return p(h7(),".loki")}var Z0,c;var g=E(()=>{Z0=b1(C7(import.meta.url));c=b7()});import{readFileSync as y7}from"fs";import{resolve as v7,dirname as g7}from"path";import{fileURLToPath as m7}from"url";function T1(){if(r!==null)return r;let K="7.12.0";if(typeof K==="string"&&K.length>0)return r=K,r;try{let $=g7(m7(import.meta.url)),Q=y1($);r=y7(v7(Q,"VERSION"),"utf-8").trim()}catch{r="unknown"}return r}var r=null;var g1=E(()=>{g()});var V0={};v(V0,{runOrThrow:()=>f7,run:()=>N,commandVersion:()=>p7,commandExists:()=>y,ShellError:()=>m1});async function N(K,$={}){let Q=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),X,Z;if($.timeoutMs&&$.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[z,H,U]=await Promise.all([new Response(Q.stdout).text(),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:H,exitCode:U}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function f7(K,$={}){let Q=await N(K,$);if(Q.exitCode!==0)throw new m1(`command failed (${Q.exitCode}): ${K.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function y(K){let $=u7(K),Q=await N(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function u7(K){if(!/^[A-Za-z0-9._/-]+$/.test(K))throw Error(`refused to shell-escape suspect token: ${K}`);return K}async function p7(K,$="--version"){if(!await y(K))return null;let X=await N([K,$],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var m1;var l=E(()=>{m1=class m1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,Q,X){super(K);this.message=K;this.exitCode=$;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function d(K){return c7?"":K}var c7,A,h,x,u6,_,k,D,V;var o=E(()=>{c7=(process.env.NO_COLOR??"").length>0;A=d("\x1B[0;31m"),h=d("\x1B[0;32m"),x=d("\x1B[1;33m"),u6=d("\x1B[0;34m"),_=d("\x1B[0;36m"),k=d("\x1B[1m"),D=d("\x1B[2m"),V=d("\x1B[0m")});import{existsSync as e7}from"fs";async function Q1(){if(U1!==void 0)return U1;let K="/opt/homebrew/bin/python3.12";if(e7(K))return U1=K,K;let $=await y("python3.12");if($)return U1=$,$;let Q=await y("python3");return U1=Q,Q}async function t(K,$={}){let Q=await Q1();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return N([Q,"-c",K],$)}var U1;var q1=E(()=>{l()});var A0={};v(A0,{runStatus:()=>B5});import{existsSync as C,readFileSync as Z1,readdirSync as G0,statSync as B0}from"fs";import{resolve as S,basename as Z5}from"path";import{homedir as z5}from"os";async function V5(){if(await y("jq"))return!0;return process.stdout.write(`${A}Error: jq is required but not installed.${V}
|
|
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)
|
|
@@ -667,4 +667,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
667
667
|
`),2}default:return process.stderr.write(`Unknown command: ${$}
|
|
668
668
|
`),process.stderr.write(S7),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var R6=await x6(Bun.argv.slice(2));process.exit(R6);
|
|
669
669
|
|
|
670
|
-
//# debugId=
|
|
670
|
+
//# debugId=255812AF20A1A7F564756E2164756E21
|
package/mcp/__init__.py
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.12.0",
|
|
4
4
|
"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).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|