loki-mode 6.83.1 → 7.0.1

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/autonomy/loki CHANGED
@@ -396,13 +396,13 @@ show_help() {
396
396
  echo "Usage: loki <command> [options]"
397
397
  echo ""
398
398
  echo "Commands:"
399
- echo " run <issue> Issue-driven engineering (v6.0.0) - GitHub/GitLab/Jira/Azure DevOps"
400
- echo " start [PRD] Start Loki Mode (optionally with PRD file)"
399
+ echo " start [PRD|ISSUE] Start Loki Mode (PRD file, issue ref, or no arg)"
400
+ echo " run <issue> (deprecated) Alias for 'loki start <issue-ref>'"
401
401
  echo " quick \"task\" Quick single-task mode (lightweight, 3 iterations max)"
402
402
  echo " monitor [path] Monitor Docker Compose services with auto-fix (v6.67.0)"
403
403
  echo " demo Run interactive demo (~60s simulated session)"
404
404
  echo " init [name] Project scaffolding with 21 PRD templates"
405
- echo " issue <url|num> [DEPRECATED] Use 'loki run' instead"
405
+ echo " issue <url|num> (deprecated) Use 'loki start <issue-ref>' instead"
406
406
  echo " watch [prd] Auto-rerun on PRD file changes (v6.33.0)"
407
407
  echo " export <format> Export session data: json|markdown|csv|timeline (v6.0.0)"
408
408
  echo " stop Stop execution immediately"
@@ -511,6 +511,96 @@ show_help() {
511
511
  echo " See: $RUN_SH (header comments)"
512
512
  }
513
513
 
514
+ # Detect argument type for unified `loki start` (v6.84.0)
515
+ # Returns one of: prd | issue | empty | unknown
516
+ # Logic:
517
+ # - empty arg -> "empty"
518
+ # - file path ending in .md/.json/.txt AND exists on disk -> "prd"
519
+ # - file path ending in .md/.json/.txt (doesn't exist) -> "prd" (let downstream handle)
520
+ # - URL matching github.com/gitlab.com/atlassian.net/dev.azure.com/visualstudio.com issues -> "issue"
521
+ # - PROJ-123 style Jira key -> "issue"
522
+ # - owner/repo#123 -> "issue"
523
+ # - #NUM or bare NUM -> "issue" (GitHub issue in current repo)
524
+ # - Anything else that looks like a filesystem path -> "prd"
525
+ # - Fallback -> "unknown" (caller treats as PRD path for back-compat)
526
+ detect_arg_type() {
527
+ local arg="${1:-}"
528
+
529
+ # Empty arg
530
+ if [ -z "$arg" ]; then
531
+ echo "empty"
532
+ return 0
533
+ fi
534
+
535
+ # Known PRD extensions - treat as PRD first (highest priority).
536
+ # This handles edge case where a file is literally named "123.md" or
537
+ # sits in a dir that matches another pattern.
538
+ case "$arg" in
539
+ *.md|*.json|*.txt|*.yaml|*.yml)
540
+ echo "prd"
541
+ return 0
542
+ ;;
543
+ esac
544
+
545
+ # Issue URLs -- order matters: check explicit tracker hosts first
546
+ if [[ "$arg" =~ github\.com/[^/]+/[^/]+/issues/[0-9]+ ]]; then
547
+ echo "issue"
548
+ return 0
549
+ fi
550
+ if [[ "$arg" =~ gitlab\.com/.+/-/issues/[0-9]+ ]] || [[ "$arg" =~ gitlab\..+/-/issues/[0-9]+ ]]; then
551
+ echo "issue"
552
+ return 0
553
+ fi
554
+ if [[ "$arg" =~ \.atlassian\.net/browse/[A-Z]+-[0-9]+ ]] || [[ "$arg" =~ jira\..+/browse/[A-Z]+-[0-9]+ ]]; then
555
+ echo "issue"
556
+ return 0
557
+ fi
558
+ if [[ "$arg" =~ dev\.azure\.com/.+/_workitems/edit/[0-9]+ ]] || [[ "$arg" =~ visualstudio\.com/.+/_workitems/edit/[0-9]+ ]]; then
559
+ echo "issue"
560
+ return 0
561
+ fi
562
+
563
+ # owner/repo#123
564
+ if [[ "$arg" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+#[0-9]+$ ]]; then
565
+ echo "issue"
566
+ return 0
567
+ fi
568
+
569
+ # Jira project key: PROJ-123
570
+ if [[ "$arg" =~ ^[A-Z][A-Z0-9]+-[0-9]+$ ]]; then
571
+ echo "issue"
572
+ return 0
573
+ fi
574
+
575
+ # #123 or bare number -- treat as GitHub issue in current repo,
576
+ # BUT only if a file with that literal name does NOT exist on disk
577
+ # (ambiguity resolution: files-on-disk win over issue-number heuristic).
578
+ if [[ "$arg" =~ ^#?[0-9]+$ ]]; then
579
+ if [ -e "$arg" ]; then
580
+ # File on disk wins -- treat as PRD
581
+ echo "prd"
582
+ else
583
+ echo "issue"
584
+ fi
585
+ return 0
586
+ fi
587
+
588
+ # Path-like (contains / or starts with . or /) -> treat as PRD
589
+ if [[ "$arg" == */* ]] || [[ "$arg" == .* ]] || [[ "$arg" == /* ]]; then
590
+ echo "prd"
591
+ return 0
592
+ fi
593
+
594
+ # Existing file on disk -> PRD
595
+ if [ -e "$arg" ]; then
596
+ echo "prd"
597
+ return 0
598
+ fi
599
+
600
+ # Fallback: unknown. Caller treats as PRD for backward compat.
601
+ echo "unknown"
602
+ }
603
+
514
604
  # Start Loki Mode
515
605
  cmd_start() {
516
606
  local args=()
@@ -524,15 +614,39 @@ cmd_start() {
524
614
  local mirofish_disabled=false
525
615
  local no_plan=false # v6.81.1: --no-plan opts out of auto-plan display
526
616
 
617
+ # v6.84.0: unified entry point -- explicit mode overrides + issue-mode args
618
+ local explicit_mode="" # "prd" | "issue" | "" (auto-detect)
619
+ local positional_arg="" # raw positional arg for mode detection
620
+ local issue_ref_explicit="" # --issue value (when explicit_mode=issue)
621
+ local issue_mode_args=() # captured issue-mode flags (--dry-run, --pr, etc.)
622
+ local issue_dry_run=false
623
+ local issue_no_start=false
624
+ local issue_output_file=""
625
+ local issue_use_worktree=false
626
+ local issue_create_pr=false
627
+ local issue_auto_merge=false
628
+ local issue_run_detached=false
629
+
527
630
  while [[ $# -gt 0 ]]; do
528
631
  case "$1" in
529
632
  --help|-h)
530
- echo -e "${BOLD}loki start${NC} - Start Loki Mode autonomous execution"
633
+ echo -e "${BOLD}loki start${NC} - Unified entry point for Loki Mode (v6.84.0)"
634
+ echo ""
635
+ echo "Usage: loki start [PRD|ISSUE-REF] [options]"
531
636
  echo ""
532
- echo "Usage: loki start [PRD] [options]"
637
+ echo "Modes (auto-detected from input):"
638
+ echo " PRD mode - path ending in .md/.json/.txt/.yaml -> build from PRD"
639
+ echo " ISSUE mode - GitHub/GitLab/Jira/Azure DevOps URL, owner/repo#N,"
640
+ echo " PROJ-123, #123, or bare number -> generate PRD from issue"
641
+ echo " no input - analyze current directory, auto-generate PRD"
533
642
  echo ""
534
643
  echo "Arguments:"
535
- echo " PRD Path to PRD file (optional)"
644
+ echo " PRD Path to PRD file (.md/.json/.txt/.yaml)"
645
+ echo " ISSUE-REF Issue URL, number, or tracker key (see above)"
646
+ echo ""
647
+ echo "Explicit mode flags (override auto-detection):"
648
+ echo " --prd FILE Force PRD mode with FILE"
649
+ echo " --issue URL|NUM Force issue mode with URL or number"
536
650
  echo ""
537
651
  echo "Options:"
538
652
  echo " --provider NAME AI provider: claude (default), codex, gemini, cline, aider"
@@ -558,6 +672,15 @@ cmd_start() {
558
672
  echo " --no-plan Skip auto-shown PRD analysis at startup"
559
673
  echo " --yes, -y Skip confirmation prompts (auto-confirm)"
560
674
  echo ""
675
+ echo "Issue-mode options (only used when input is an ISSUE-REF):"
676
+ echo " --dry-run Preview generated PRD without starting"
677
+ echo " --no-start Generate PRD but don't start execution"
678
+ echo " --output FILE Save generated PRD to custom path"
679
+ echo " --worktree, -w Git worktree isolation (separate branch)"
680
+ echo " --pr Worktree + auto-create PR"
681
+ echo " --ship Worktree + PR + auto-merge"
682
+ echo " --detach, -d Run in background"
683
+ echo ""
561
684
  echo "Environment Variables:"
562
685
  echo " LOKI_PRD_FILE Path to PRD file (alternative to positional arg)"
563
686
  echo " LOKI_AUTO_CONFIRM Set to 'true'/'false' to control prompts (takes precedence over CI)"
@@ -566,14 +689,21 @@ cmd_start() {
566
689
  echo " LOKI_BUDGET_LIMIT Cost budget limit in USD"
567
690
  echo ""
568
691
  echo "Examples:"
569
- echo " loki start # Interactive or resume existing"
570
- echo " loki start ./prd.md # Start with PRD file"
571
- echo " loki start ./prd.md --parallel # Parallel mode with worktrees"
572
- echo " loki start --provider codex # Use OpenAI Codex CLI"
692
+ echo " loki start # Interactive, analyze current dir"
693
+ echo " loki start ./prd.md # PRD mode"
694
+ echo " loki start https://github.com/o/r/issues/42 # ISSUE mode (GitHub)"
695
+ echo " loki start 123 # ISSUE mode (current repo GitHub issue)"
696
+ echo " loki start PROJ-456 # ISSUE mode (Jira)"
697
+ echo " loki start owner/repo#789 # ISSUE mode (GitHub specific repo)"
698
+ echo " loki start --prd ./prd.md --parallel # Explicit PRD, parallel mode"
699
+ echo " loki start --issue 123 --ship # Explicit issue, full automation"
700
+ echo " loki start --provider codex # Use OpenAI Codex CLI"
573
701
  echo " loki start --bmad-project ./my-project # Start from BMAD artifacts"
574
- echo " loki start --openspec ./openspec/changes/my-feature # Start from OpenSpec change"
575
- echo " loki start --yes # Skip confirmation prompt"
576
- echo " LOKI_PRD_FILE=./prd.md loki start # PRD via env var"
702
+ echo " loki start --openspec ./openspec/changes/my-feature # From OpenSpec change"
703
+ echo " loki start --yes # Skip confirmation prompt"
704
+ echo " LOKI_PRD_FILE=./prd.md loki start # PRD via env var"
705
+ echo ""
706
+ echo "Note: 'loki run' is a deprecated alias for 'loki start' with an issue ref."
577
707
  exit 0
578
708
  ;;
579
709
  --provider)
@@ -804,22 +934,196 @@ cmd_start() {
804
934
  export LOKI_BUDGET_LIMIT="$budget_val"
805
935
  shift
806
936
  ;;
937
+ # v6.84.0: explicit mode flags (override auto-detection)
938
+ --prd)
939
+ if [[ -n "${2:-}" ]] && [[ "${2:-}" != --* ]]; then
940
+ explicit_mode="prd"
941
+ prd_file="$2"
942
+ shift 2
943
+ else
944
+ echo -e "${RED}--prd requires a file path${NC}"
945
+ exit 1
946
+ fi
947
+ ;;
948
+ --prd=*)
949
+ explicit_mode="prd"
950
+ prd_file="${1#*=}"
951
+ shift
952
+ ;;
953
+ --issue)
954
+ if [[ -n "${2:-}" ]] && [[ "${2:-}" != --* ]]; then
955
+ explicit_mode="issue"
956
+ issue_ref_explicit="$2"
957
+ shift 2
958
+ else
959
+ echo -e "${RED}--issue requires a URL, number, or issue key${NC}"
960
+ exit 1
961
+ fi
962
+ ;;
963
+ --issue=*)
964
+ explicit_mode="issue"
965
+ issue_ref_explicit="${1#*=}"
966
+ shift
967
+ ;;
968
+ # v6.84.0: issue-mode flags (only meaningful when input is an issue)
969
+ --dry-run)
970
+ issue_dry_run=true
971
+ issue_mode_args+=("--dry-run")
972
+ shift
973
+ ;;
974
+ --no-start)
975
+ issue_no_start=true
976
+ issue_mode_args+=("--no-start")
977
+ shift
978
+ ;;
979
+ --output)
980
+ if [[ -n "${2:-}" ]]; then
981
+ issue_output_file="$2"
982
+ issue_mode_args+=("--output" "$2")
983
+ shift 2
984
+ else
985
+ echo -e "${RED}--output requires a file path${NC}"
986
+ exit 1
987
+ fi
988
+ ;;
989
+ --output=*)
990
+ issue_output_file="${1#*=}"
991
+ issue_mode_args+=("--output=${1#*=}")
992
+ shift
993
+ ;;
994
+ --worktree|-w)
995
+ issue_use_worktree=true
996
+ issue_mode_args+=("--worktree")
997
+ shift
998
+ ;;
999
+ --pr)
1000
+ issue_use_worktree=true
1001
+ issue_create_pr=true
1002
+ issue_mode_args+=("--pr")
1003
+ shift
1004
+ ;;
1005
+ --ship)
1006
+ issue_use_worktree=true
1007
+ issue_create_pr=true
1008
+ issue_auto_merge=true
1009
+ issue_mode_args+=("--ship")
1010
+ shift
1011
+ ;;
1012
+ --detach|-d)
1013
+ issue_use_worktree=true
1014
+ issue_run_detached=true
1015
+ issue_mode_args+=("--detach")
1016
+ shift
1017
+ ;;
807
1018
  -*)
808
1019
  echo -e "${RED}Unknown option: $1${NC}"
809
1020
  exit 1
810
1021
  ;;
811
1022
  *)
812
- prd_file="$1"
1023
+ # Capture first positional arg for unified mode detection.
1024
+ # Additional positional args are ignored (same as prior behavior).
1025
+ if [ -z "$positional_arg" ]; then
1026
+ positional_arg="$1"
1027
+ fi
813
1028
  shift
814
1029
  ;;
815
1030
  esac
816
1031
  done
817
1032
 
1033
+ # v6.84.0: Unified dispatch based on explicit flags or auto-detection
1034
+ # Precedence: --issue > --prd > positional auto-detect > LOKI_PRD_FILE env
1035
+ local detected_type=""
1036
+ if [ -n "$explicit_mode" ]; then
1037
+ detected_type="$explicit_mode"
1038
+ elif [ -n "$positional_arg" ]; then
1039
+ detected_type=$(detect_arg_type "$positional_arg")
1040
+ elif [ -n "${LOKI_PRD_FILE:-}" ]; then
1041
+ detected_type="prd"
1042
+ prd_file="$LOKI_PRD_FILE"
1043
+ else
1044
+ detected_type="empty"
1045
+ fi
1046
+
1047
+ # ISSUE mode: delegate to cmd_run's code path. To avoid duplicating ~450
1048
+ # lines of issue-fetching + PR-creation logic, we re-dispatch through
1049
+ # cmd_run with reconstructed args. cmd_run then calls cmd_start again
1050
+ # with the generated PRD file and --no-plan (see line ~4431).
1051
+ if [ "$detected_type" = "issue" ]; then
1052
+ local issue_ref
1053
+ if [ "$explicit_mode" = "issue" ]; then
1054
+ issue_ref="$issue_ref_explicit"
1055
+ else
1056
+ issue_ref="$positional_arg"
1057
+ fi
1058
+ # Reconstruct args for cmd_run: issue ref + all options we captured.
1059
+ # args[] already has --provider, --parallel, --bg, etc.
1060
+ local run_args=("$issue_ref")
1061
+ # Pass through issue-mode flags
1062
+ for a in "${issue_mode_args[@]+"${issue_mode_args[@]}"}"; do
1063
+ run_args+=("$a")
1064
+ done
1065
+ # Pass through generic options that cmd_run understands
1066
+ for a in "${args[@]+"${args[@]}"}"; do
1067
+ run_args+=("$a")
1068
+ done
1069
+ # Pass through --no-plan if set
1070
+ if [ "$no_plan" = "true" ]; then
1071
+ run_args+=("--no-plan")
1072
+ fi
1073
+ # Mark this invocation as unified (so cmd_run skips deprecation notice)
1074
+ export LOKI_UNIFIED_START=1
1075
+ cmd_run "${run_args[@]}"
1076
+ return $?
1077
+ fi
1078
+
1079
+ # PRD mode: positional arg is the PRD file (if not already set via --prd)
1080
+ if [ "$detected_type" = "prd" ] && [ -z "$prd_file" ]; then
1081
+ prd_file="$positional_arg"
1082
+ fi
1083
+ # Unknown type: fall back to PRD (legacy back-compat)
1084
+ if [ "$detected_type" = "unknown" ] && [ -z "$prd_file" ]; then
1085
+ prd_file="$positional_arg"
1086
+ fi
1087
+
1088
+ # R8 fix (v7.0.0): if a PRD path was specified (positional or --prd) and
1089
+ # the file does NOT exist, fail fast with a clear error. This prevents the
1090
+ # "silently accepted, then run as no-PRD" failure mode.
1091
+ if [ -n "$prd_file" ] && [ "$detected_type" != "empty" ]; then
1092
+ case "$prd_file" in
1093
+ *.md|*.json|*.txt|*.yaml|*.yml)
1094
+ if [ ! -f "$prd_file" ]; then
1095
+ echo "Error: PRD file not found: $prd_file" >&2
1096
+ echo "Hint: provide a path to an existing .md/.json/.txt/.yaml/.yml file, or run 'loki start' with no args to analyze the current directory." >&2
1097
+ exit 1
1098
+ fi
1099
+ ;;
1100
+ esac
1101
+ fi
1102
+
818
1103
  # Support LOKI_PRD_FILE environment variable as fallback
819
1104
  if [ -z "$prd_file" ] && [ -n "${LOKI_PRD_FILE:-}" ]; then
820
1105
  prd_file="$LOKI_PRD_FILE"
821
1106
  fi
822
1107
 
1108
+ # v6.84.1 (R8 Gap 1): fail fast if a PRD-like path was provided but the file
1109
+ # does not exist on disk. Previously we silently fell through and let the
1110
+ # "no PRD specified" branch take over, which misled users who typo'd a path.
1111
+ # Only applies when an explicit path was given (positional, --prd, or env);
1112
+ # the no-arg "generate from codebase" path is still supported below.
1113
+ # BMAD/OpenSpec adapters run later and may set prd_file to a normalized
1114
+ # output that doesn't exist yet -- they're guarded by bmad_project_path /
1115
+ # openspec_change_path, so skip this check when either is set.
1116
+ if [ -n "$prd_file" ] && [ -z "$bmad_project_path" ] && [ -z "$openspec_change_path" ]; then
1117
+ case "$prd_file" in
1118
+ *.md|*.json|*.txt|*.yaml|*.yml)
1119
+ if [ ! -f "$prd_file" ]; then
1120
+ echo -e "${RED}Error: PRD file not found: $prd_file${NC}" >&2
1121
+ exit 1
1122
+ fi
1123
+ ;;
1124
+ esac
1125
+ fi
1126
+
823
1127
  # Mutual exclusivity: --openspec and --bmad-project cannot be used together
824
1128
  if [[ -n "${openspec_change_path:-}" ]] && [[ -n "${bmad_project_path:-}" ]]; then
825
1129
  echo -e "${RED}Error: --openspec and --bmad-project are mutually exclusive. Use one or the other.${NC}"
@@ -4054,6 +4358,33 @@ cmd_issue_view() {
4054
4358
  #===============================================================================
4055
4359
 
4056
4360
  cmd_run() {
4361
+ # v6.84.0: `loki run` is now a deprecated alias for `loki start <issue-ref>`.
4362
+ # When invoked directly (not via the unified start dispatcher), emit a
4363
+ # deprecation notice and a telemetry event so we can track adoption of the
4364
+ # unified command. Skip when LOKI_UNIFIED_START=1 (cmd_start -> cmd_run).
4365
+ if [ "${LOKI_UNIFIED_START:-0}" != "1" ]; then
4366
+ # Only warn for real invocations, not --help (help is still useful)
4367
+ local _show_warn=true
4368
+ for _a in "$@"; do
4369
+ if [ "$_a" = "--help" ] || [ "$_a" = "-h" ]; then
4370
+ _show_warn=false
4371
+ break
4372
+ fi
4373
+ done
4374
+ if [ "$_show_warn" = "true" ]; then
4375
+ echo -e "${YELLOW}Notice: 'loki run' is deprecated. Use 'loki start <issue-ref>' instead.${NC}" >&2
4376
+ echo -e "${DIM} All features (--worktree, --pr, --ship, --dry-run) work on 'loki start'.${NC}" >&2
4377
+ echo "" >&2
4378
+ # Emit telemetry event so we can measure adoption of the unified command.
4379
+ # Signature: emit_event <type> <source> <action> [key=value ...]
4380
+ emit_event cli_command_deprecated cli run_to_start \
4381
+ "old_command=run" \
4382
+ "new_command=start" \
4383
+ "version=6.84.0" \
4384
+ "argv=${*:-}"
4385
+ fi
4386
+ fi
4387
+
4057
4388
  require_jq || return 1
4058
4389
 
4059
4390
  local issue_ref=""
@@ -4071,7 +4402,7 @@ cmd_run() {
4071
4402
  while [[ $# -gt 0 ]]; do
4072
4403
  case "$1" in
4073
4404
  --help|-h)
4074
- echo -e "${BOLD}loki run${NC} - Issue-driven engineering (v6.0.0)"
4405
+ echo -e "${BOLD}loki run${NC} - Issue-driven engineering (DEPRECATED: use 'loki start')"
4075
4406
  echo ""
4076
4407
  echo "Usage: loki run <issue-ref> [options]"
4077
4408
  echo " loki run <url-or-key> [options]"