loki-mode 6.1.0 → 6.2.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 CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v6.1.0
6
+ # Loki Mode v6.2.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -263,4 +263,4 @@ The following features are documented in skill modules but not yet fully automat
263
263
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
264
264
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
265
265
 
266
- **v6.1.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
266
+ **v6.2.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.1.0
1
+ 6.2.0
package/autonomy/loki CHANGED
@@ -448,6 +448,12 @@ show_help() {
448
448
  echo " --parallel Enable parallel mode with git worktrees"
449
449
  echo " --budget USD Set cost budget limit"
450
450
  echo ""
451
+ echo "Progressive Isolation (for 'run'):"
452
+ echo " --worktree, -w Git worktree isolation (separate branch)"
453
+ echo " --pr Auto-create PR after completion (implies --worktree)"
454
+ echo " --ship Auto-merge after PR (implies --pr)"
455
+ echo " --detach, -d Run in background (implies --worktree)"
456
+ echo ""
451
457
  echo "Examples:"
452
458
  echo " loki run 123 # GitHub issue from current repo"
453
459
  echo " loki run PROJ-456 # Jira issue"
@@ -2519,6 +2525,10 @@ cmd_run() {
2519
2525
  local start_args=()
2520
2526
  local no_start=false
2521
2527
  local provider_override=""
2528
+ local use_worktree=false
2529
+ local create_pr=false
2530
+ local auto_merge=false
2531
+ local run_detached=false
2522
2532
 
2523
2533
  # Parse arguments
2524
2534
  while [[ $# -gt 0 ]]; do
@@ -2551,6 +2561,14 @@ cmd_run() {
2551
2561
  echo " --sandbox Run in Docker sandbox"
2552
2562
  echo " --budget USD Set cost budget limit"
2553
2563
  echo ""
2564
+ echo "Progressive Isolation:"
2565
+ echo " --worktree, -w Git worktree isolation (separate branch)"
2566
+ echo " --pr Worktree + auto-create PR (implies --worktree)"
2567
+ echo " --ship Worktree + PR + auto-merge (implies --pr)"
2568
+ echo " --detach, -d Run in background (implies --worktree)"
2569
+ echo ""
2570
+ echo " Cascade: --ship implies --pr implies --worktree"
2571
+ echo ""
2554
2572
  echo "Environment Variables:"
2555
2573
  echo " JIRA_API_TOKEN Jira API token (for Jira issues)"
2556
2574
  echo " JIRA_URL Jira base URL (for Jira issues)"
@@ -2563,6 +2581,10 @@ cmd_run() {
2563
2581
  echo " loki run https://gitlab.com/o/r/-/issues/42 # GitLab issue"
2564
2582
  echo " loki run 123 --dry-run # Preview PRD"
2565
2583
  echo " loki run 123 --parallel --provider codex # Parallel mode with Codex"
2584
+ echo " loki run 123 --worktree # Isolated branch"
2585
+ echo " loki run 123 --pr # Auto-create PR"
2586
+ echo " loki run 123 --ship # Full automation: PR + merge"
2587
+ echo " loki run 123 --ship -d # Background, full automation"
2566
2588
  exit 0
2567
2589
  ;;
2568
2590
  --dry-run)
@@ -2626,6 +2648,30 @@ cmd_run() {
2626
2648
  start_args+=("--budget" "${1#*=}")
2627
2649
  shift
2628
2650
  ;;
2651
+ --worktree|-w)
2652
+ start_args+=("--parallel")
2653
+ use_worktree=true
2654
+ shift
2655
+ ;;
2656
+ --pr)
2657
+ use_worktree=true
2658
+ create_pr=true
2659
+ start_args+=("--parallel")
2660
+ shift
2661
+ ;;
2662
+ --ship)
2663
+ use_worktree=true
2664
+ create_pr=true
2665
+ auto_merge=true
2666
+ start_args+=("--parallel")
2667
+ shift
2668
+ ;;
2669
+ --detach|-d)
2670
+ use_worktree=true
2671
+ run_detached=true
2672
+ start_args+=("--parallel")
2673
+ shift
2674
+ ;;
2629
2675
  -*)
2630
2676
  echo -e "${RED}Unknown option: $1${NC}"
2631
2677
  echo "Run 'loki run --help' for usage."
@@ -2687,10 +2733,46 @@ cmd_run() {
2687
2733
  fi
2688
2734
  echo ""
2689
2735
 
2736
+ # Progressive isolation: set up worktree branch naming
2737
+ if $use_worktree; then
2738
+ local branch_name="issue/${issue_provider}-${number:-$(date +%s)}"
2739
+ log_info "Progressive isolation: branch $branch_name"
2740
+ export LOKI_PARALLEL_MODE=true
2741
+ export LOKI_WORKTREE_BRANCH="$branch_name"
2742
+ fi
2743
+
2690
2744
  # Generate PRD
2691
2745
  local prd_content
2692
2746
  prd_content=$(echo "$issue_json" | generate_prd_from_issue)
2693
2747
 
2748
+ # Detached mode: fork to background
2749
+ if $run_detached; then
2750
+ local log_file="$LOKI_DIR/logs/run-${number:-$(date +%s)}.log"
2751
+ mkdir -p "$(dirname "$log_file")"
2752
+ echo -e "${GREEN}Running detached. Logs: $log_file${NC}"
2753
+ echo -e "Check status: ${CYAN}loki status${NC}"
2754
+
2755
+ # Write PRD first so background process can use it
2756
+ mkdir -p "$LOKI_DIR"
2757
+ local prd_content_detach
2758
+ prd_content_detach=$(echo "$issue_json" | generate_prd_from_issue)
2759
+ local detach_prd="$LOKI_DIR/prd-issue-${number}.md"
2760
+ echo "$prd_content_detach" > "$detach_prd"
2761
+
2762
+ nohup bash -c "
2763
+ cd $(pwd)
2764
+ export LOKI_DETACHED=true
2765
+ export LOKI_PARALLEL_MODE=true
2766
+ export LOKI_WORKTREE_BRANCH=\"$branch_name\"
2767
+ $(command -v loki || echo "$0") start \"$detach_prd\" --parallel ${start_args[*]+"${start_args[*]}"}
2768
+ " > "$log_file" 2>&1 &
2769
+
2770
+ local bg_pid=$!
2771
+ echo "$bg_pid" > "$LOKI_DIR/run-${number:-detached}.pid"
2772
+ echo "Background PID: $bg_pid"
2773
+ return 0
2774
+ fi
2775
+
2694
2776
  # Handle dry-run
2695
2777
  if [[ "$dry_run" == "true" ]]; then
2696
2778
  echo -e "${BOLD}Generated PRD Preview:${NC}"
@@ -2728,6 +2810,75 @@ cmd_run() {
2728
2810
  echo ""
2729
2811
  echo -e "${GREEN}Starting Loki Mode with generated PRD...${NC}"
2730
2812
  cmd_start "$output_file" ${start_args[@]+"${start_args[@]}"}
2813
+
2814
+ # Progressive isolation: create PR
2815
+ if $create_pr; then
2816
+ echo ""
2817
+ echo -e "${GREEN}Creating pull request...${NC}"
2818
+ local pr_title="${title:-Implementation for issue ${issue_ref}}"
2819
+ local pr_body="Implemented by Loki Mode (autonomous agent)
2820
+
2821
+ Issue: ${issue_ref}
2822
+ Provider: ${issue_provider}
2823
+
2824
+ ## Changes
2825
+ $(git log --oneline "main..HEAD" 2>/dev/null || echo "See diff")"
2826
+
2827
+ case "${issue_provider:-github}" in
2828
+ github)
2829
+ if command -v gh &>/dev/null; then
2830
+ local branch_current
2831
+ branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
2832
+ if [[ -n "$branch_current" && "$branch_current" != "main" && "$branch_current" != "master" ]]; then
2833
+ git push origin "$branch_current" 2>/dev/null || true
2834
+ gh pr create --title "$pr_title" --body "$pr_body" --head "$branch_current" 2>/dev/null && \
2835
+ echo -e "${GREEN}PR created${NC}" || \
2836
+ echo -e "${YELLOW}PR creation failed${NC}"
2837
+ fi
2838
+ fi
2839
+ ;;
2840
+ gitlab)
2841
+ if command -v glab &>/dev/null; then
2842
+ local branch_current
2843
+ branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
2844
+ if [[ -n "$branch_current" && "$branch_current" != "main" && "$branch_current" != "master" ]]; then
2845
+ git push origin "$branch_current" 2>/dev/null || true
2846
+ glab mr create --title "$pr_title" --description "$pr_body" --source-branch "$branch_current" 2>/dev/null && \
2847
+ echo -e "${GREEN}MR created${NC}" || \
2848
+ echo -e "${YELLOW}MR creation failed${NC}"
2849
+ fi
2850
+ fi
2851
+ ;;
2852
+ *)
2853
+ echo -e "${YELLOW}PR creation not supported for provider: $issue_provider${NC}"
2854
+ ;;
2855
+ esac
2856
+ fi
2857
+
2858
+ # Progressive isolation: auto-merge
2859
+ if $auto_merge; then
2860
+ echo -e "${GREEN}Auto-merging...${NC}"
2861
+ case "${issue_provider:-github}" in
2862
+ github)
2863
+ local branch_current
2864
+ branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
2865
+ gh pr merge "$branch_current" --squash --delete-branch 2>/dev/null && \
2866
+ echo -e "${GREEN}PR merged and branch deleted${NC}" || \
2867
+ echo -e "${YELLOW}Auto-merge failed. PR remains open.${NC}"
2868
+ if [[ -n "${number:-}" ]]; then
2869
+ gh issue close "$number" --comment "Resolved by Loki Mode" 2>/dev/null || true
2870
+ fi
2871
+ ;;
2872
+ gitlab)
2873
+ glab mr merge --squash --remove-source-branch 2>/dev/null && \
2874
+ echo -e "${GREEN}MR merged and branch deleted${NC}" || \
2875
+ echo -e "${YELLOW}Auto-merge failed. MR remains open.${NC}"
2876
+ ;;
2877
+ *)
2878
+ echo -e "${YELLOW}Auto-merge not supported for provider: $issue_provider${NC}"
2879
+ ;;
2880
+ esac
2881
+ fi
2731
2882
  fi
2732
2883
  }
2733
2884
 
@@ -6739,6 +6890,167 @@ cmd_migrate() {
6739
6890
  cmd_migrate_start "$codebase_path" "$target" "$plan_only" "$phase" "$parallel" "$compliance" "$dry_run" "$do_resume" "$multi_repo" "$export_report" "$no_dashboard" "$no_docs"
6740
6891
  }
6741
6892
 
6893
+ #===============================================================================
6894
+ # loki cluster - Custom workflow templates (v6.2.0)
6895
+ #===============================================================================
6896
+
6897
+ cmd_cluster() {
6898
+ local subcmd="${1:-list}"
6899
+ shift 2>/dev/null || true
6900
+
6901
+ case "$subcmd" in
6902
+ --help|-h|help)
6903
+ echo -e "${BOLD}loki cluster${NC} - Custom workflow templates (v6.2.0)"
6904
+ echo ""
6905
+ echo "Usage: loki cluster <command> [options]"
6906
+ echo ""
6907
+ echo "Commands:"
6908
+ echo " list List available workflow templates"
6909
+ echo " validate <name> Validate a cluster template"
6910
+ echo " run <name> [args] Execute a cluster workflow"
6911
+ echo " info <name> Show template details"
6912
+ echo ""
6913
+ echo "Examples:"
6914
+ echo " loki cluster list"
6915
+ echo " loki cluster validate security-review"
6916
+ echo " loki cluster info code-review"
6917
+ ;;
6918
+ list)
6919
+ echo -e "${BOLD}Available Cluster Templates${NC}"
6920
+ echo ""
6921
+ local template_dir="$SKILL_DIR/templates/clusters"
6922
+ if [[ ! -d "$template_dir" ]]; then
6923
+ echo "No templates found at $template_dir"
6924
+ return 1
6925
+ fi
6926
+ for f in "$template_dir"/*.json; do
6927
+ [[ ! -f "$f" ]] && continue
6928
+ local name
6929
+ name=$(basename "$f" .json)
6930
+ local desc
6931
+ desc=$(python3 -c "
6932
+ import json, sys
6933
+ try:
6934
+ with open(sys.argv[1]) as f:
6935
+ d = json.load(f)
6936
+ print(d.get('description', 'No description'))
6937
+ except: print('Error reading template')
6938
+ " "$f" 2>/dev/null || echo "")
6939
+ local agent_count
6940
+ agent_count=$(python3 -c "
6941
+ import json, sys
6942
+ try:
6943
+ with open(sys.argv[1]) as f:
6944
+ d = json.load(f)
6945
+ print(len(d.get('agents', [])))
6946
+ except: print('?')
6947
+ " "$f" 2>/dev/null || echo "?")
6948
+ printf " %-20s %s agents %s\n" "$name" "$agent_count" "$desc"
6949
+ done
6950
+ ;;
6951
+ validate)
6952
+ local template_name="${1:-}"
6953
+ if [[ -z "$template_name" ]]; then
6954
+ echo -e "${RED}Usage: loki cluster validate <template-name>${NC}"
6955
+ return 1
6956
+ fi
6957
+ local template_file="$SKILL_DIR/templates/clusters/${template_name}.json"
6958
+ if [[ ! -f "$template_file" ]]; then
6959
+ echo -e "${RED}Template not found: $template_name${NC}"
6960
+ echo "Run 'loki cluster list' to see available templates."
6961
+ return 1
6962
+ fi
6963
+ echo -e "${CYAN}Validating: $template_name${NC}"
6964
+ local errors
6965
+ errors=$(python3 -c "
6966
+ import json, sys
6967
+ sys.path.insert(0, '$(dirname "$SKILL_DIR/swarm/")')
6968
+ sys.path.insert(0, '$SKILL_DIR')
6969
+ from swarm.patterns import TopologyValidator
6970
+ errors = TopologyValidator.validate_file(sys.argv[1])
6971
+ if errors:
6972
+ for e in errors:
6973
+ print(f'ERROR: {e}')
6974
+ else:
6975
+ print('VALID')
6976
+ " "$template_file" 2>&1)
6977
+ if echo "$errors" | grep -q "^VALID$"; then
6978
+ echo -e "${GREEN}Template is valid${NC}"
6979
+ return 0
6980
+ else
6981
+ echo -e "${RED}Validation errors:${NC}"
6982
+ echo "$errors"
6983
+ return 1
6984
+ fi
6985
+ ;;
6986
+ info)
6987
+ local template_name="${1:-}"
6988
+ if [[ -z "$template_name" ]]; then
6989
+ echo -e "${RED}Usage: loki cluster info <template-name>${NC}"
6990
+ return 1
6991
+ fi
6992
+ local template_file="$SKILL_DIR/templates/clusters/${template_name}.json"
6993
+ if [[ ! -f "$template_file" ]]; then
6994
+ echo -e "${RED}Template not found: $template_name${NC}"
6995
+ return 1
6996
+ fi
6997
+ python3 -c "
6998
+ import json, sys
6999
+ with open(sys.argv[1]) as f:
7000
+ d = json.load(f)
7001
+ print(f\"Name: {d.get('name', 'unknown')}\")
7002
+ print(f\"Description: {d.get('description', 'none')}\")
7003
+ print(f\"Version: {d.get('version', 'unknown')}\")
7004
+ print(f\"Topology: {d.get('topology', 'unknown')}\")
7005
+ print(f\"Agents: {len(d.get('agents', []))}\")
7006
+ print()
7007
+ for a in d.get('agents', []):
7008
+ subs = ', '.join(a.get('subscribes', []))
7009
+ pubs = ', '.join(a.get('publishes', []))
7010
+ print(f\" [{a['id']}] ({a.get('type', '?')})\")
7011
+ print(f\" Role: {a.get('role', '?')}\")
7012
+ print(f\" Subscribes: {subs}\")
7013
+ print(f\" Publishes: {pubs}\")
7014
+ print()
7015
+ " "$template_file"
7016
+ ;;
7017
+ run)
7018
+ local template_name="${1:-}"
7019
+ if [[ -z "$template_name" ]]; then
7020
+ echo -e "${RED}Usage: loki cluster run <template-name> [args]${NC}"
7021
+ return 1
7022
+ fi
7023
+ local template_file="$SKILL_DIR/templates/clusters/${template_name}.json"
7024
+ if [[ ! -f "$template_file" ]]; then
7025
+ echo -e "${RED}Template not found: $template_name${NC}"
7026
+ return 1
7027
+ fi
7028
+ # Validate first
7029
+ local errors
7030
+ errors=$(python3 -c "
7031
+ import json, sys
7032
+ sys.path.insert(0, '$SKILL_DIR')
7033
+ from swarm.patterns import TopologyValidator
7034
+ errors = TopologyValidator.validate_file(sys.argv[1])
7035
+ for e in errors: print(e)
7036
+ " "$template_file" 2>&1)
7037
+ if [[ -n "$errors" ]]; then
7038
+ echo -e "${RED}Template validation failed:${NC}"
7039
+ echo "$errors"
7040
+ return 1
7041
+ fi
7042
+ echo -e "${GREEN}Cluster template: $template_name${NC}"
7043
+ echo -e "${YELLOW}Note: Cluster execution engine is planned for v6.3.0.${NC}"
7044
+ echo -e "Template validated successfully. Use 'loki cluster info $template_name' for details."
7045
+ ;;
7046
+ *)
7047
+ echo -e "${RED}Unknown cluster command: $subcmd${NC}"
7048
+ echo "Run 'loki cluster --help' for usage."
7049
+ return 1
7050
+ ;;
7051
+ esac
7052
+ }
7053
+
6742
7054
  # Main command dispatcher
6743
7055
  main() {
6744
7056
  if [ $# -eq 0 ]; then
@@ -6869,6 +7181,9 @@ main() {
6869
7181
  migrate)
6870
7182
  cmd_migrate "$@"
6871
7183
  ;;
7184
+ cluster)
7185
+ cmd_cluster "$@"
7186
+ ;;
6872
7187
  metrics)
6873
7188
  cmd_metrics "$@"
6874
7189
  ;;
@@ -62,6 +62,34 @@ DASHBOARD_PORT="${LOKI_DASHBOARD_PORT:-57374}"
62
62
  # Security: Prompt injection disabled by default for enterprise security
63
63
  PROMPT_INJECTION_ENABLED="${LOKI_PROMPT_INJECTION:-false}"
64
64
 
65
+ #===============================================================================
66
+ # Docker Credential Mount Presets
67
+ #===============================================================================
68
+
69
+ # Preset definitions: "host_path:container_path:mode"
70
+ # Container runs as user 'loki' (UID 1000), so mount to /home/loki/
71
+ declare -A DOCKER_MOUNT_PRESETS
72
+ DOCKER_MOUNT_PRESETS=(
73
+ [gh]="$HOME/.config/gh:/home/loki/.config/gh:ro"
74
+ [git]="$HOME/.gitconfig:/home/loki/.gitconfig:ro"
75
+ [ssh]="$HOME/.ssh:/home/loki/.ssh:ro"
76
+ [aws]="$HOME/.aws:/home/loki/.aws:ro"
77
+ [azure]="$HOME/.azure:/home/loki/.azure:ro"
78
+ [kube]="$HOME/.kube:/home/loki/.kube:ro"
79
+ [terraform]="$HOME/.terraform.d:/home/loki/.terraform.d:ro"
80
+ [gcloud]="$HOME/.config/gcloud:/home/loki/.config/gcloud:ro"
81
+ [npm]="$HOME/.npmrc:/home/loki/.npmrc:ro"
82
+ )
83
+
84
+ # Environment variables auto-passed per preset (comma-separated)
85
+ declare -A DOCKER_ENV_PRESETS
86
+ DOCKER_ENV_PRESETS=(
87
+ [aws]="AWS_REGION,AWS_PROFILE,AWS_DEFAULT_REGION"
88
+ [azure]="AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID"
89
+ [gcloud]="GOOGLE_PROJECT,GOOGLE_REGION,GCLOUD_PROJECT"
90
+ [terraform]="TF_VAR_*"
91
+ )
92
+
65
93
  #===============================================================================
66
94
  # Utility Functions
67
95
  #===============================================================================
@@ -767,9 +795,129 @@ docker_desktop_sandbox_run() {
767
795
  # Docker Container Sandbox (standard Docker - fallback from Docker Desktop)
768
796
  #===============================================================================
769
797
 
798
+ # Resolve Docker credential mount presets
799
+ # Reads from: .loki/config/settings.json dockerMounts, LOKI_DOCKER_MOUNTS env var
800
+ # Returns: string of -v and -e flags for docker run
801
+ resolve_docker_mounts() {
802
+ local mount_args=""
803
+
804
+ # Read configured presets (JSON array of strings)
805
+ local presets_json=""
806
+ if [[ -f "${PROJECT_DIR}/.loki/config/settings.json" ]]; then
807
+ presets_json=$(python3 -c "
808
+ import json, sys
809
+ try:
810
+ with open('${PROJECT_DIR}/.loki/config/settings.json') as f:
811
+ print(json.dumps(json.load(f).get('dockerMounts', [])))
812
+ except: print('[]')
813
+ " 2>/dev/null || echo "[]")
814
+ fi
815
+
816
+ # Override with env var if set
817
+ if [[ -n "${LOKI_DOCKER_MOUNTS:-}" ]]; then
818
+ presets_json="$LOKI_DOCKER_MOUNTS"
819
+ fi
820
+
821
+ # Parse and resolve
822
+ if [[ "$presets_json" != "[]" ]] && [[ "$presets_json" != "" ]]; then
823
+ local preset_names
824
+ preset_names=$(python3 -c "
825
+ import json, sys
826
+ try:
827
+ data = json.loads(sys.argv[1])
828
+ if isinstance(data, list):
829
+ for item in data:
830
+ print(item)
831
+ except: pass
832
+ " "$presets_json" 2>/dev/null || echo "")
833
+
834
+ local name
835
+ while IFS= read -r name; do
836
+ [[ -z "$name" ]] && continue
837
+
838
+ local preset_value="${DOCKER_MOUNT_PRESETS[$name]:-}"
839
+ if [[ -z "$preset_value" ]]; then
840
+ log_warn "Unknown Docker mount preset: $name"
841
+ continue
842
+ fi
843
+
844
+ IFS=':' read -ra parts <<< "$preset_value"
845
+ local host_path="${parts[0]}"
846
+ local container_path="${parts[1]}"
847
+ local mode="${parts[2]:-ro}"
848
+
849
+ # Expand ~ and $HOME
850
+ host_path=$(eval echo "$host_path" 2>/dev/null || echo "$host_path")
851
+
852
+ # Only mount if host path exists
853
+ if [[ -e "$host_path" ]]; then
854
+ mount_args="$mount_args -v ${host_path}:${container_path}:${mode}"
855
+ log_info " Mount preset [$name]: $host_path -> $container_path ($mode)"
856
+ fi
857
+
858
+ # Add associated env vars
859
+ local env_list="${DOCKER_ENV_PRESETS[$name]:-}"
860
+ if [[ -n "$env_list" ]]; then
861
+ IFS=',' read -ra env_names <<< "$env_list"
862
+ local env_name
863
+ for env_name in "${env_names[@]}"; do
864
+ if [[ "$env_name" == *"*" ]]; then
865
+ # Wildcard: pass all matching env vars
866
+ local prefix="${env_name%\*}"
867
+ while IFS='=' read -r key val; do
868
+ [[ "$key" == "$prefix"* ]] && [[ -n "$val" ]] && \
869
+ mount_args="$mount_args -e $key"
870
+ done < <(env)
871
+ elif [[ -n "${!env_name:-}" ]]; then
872
+ mount_args="$mount_args -e $env_name"
873
+ fi
874
+ done
875
+ fi
876
+ done <<< "$preset_names"
877
+ fi
878
+
879
+ echo "$mount_args"
880
+ }
881
+
770
882
  start_sandbox() {
771
- local prd_path="${1:-}"
883
+ # Parse arguments: extract flags before positional args
884
+ local prd_path=""
772
885
  local provider="${LOKI_PROVIDER:-claude}"
886
+ local no_mounts=false
887
+ local -a custom_mounts=()
888
+
889
+ while [[ $# -gt 0 ]]; do
890
+ case "$1" in
891
+ --mount)
892
+ if [[ -n "${2:-}" ]]; then
893
+ custom_mounts+=("$2")
894
+ shift 2
895
+ else
896
+ log_error "--mount requires HOST:CONTAINER:MODE argument"
897
+ return 1
898
+ fi
899
+ ;;
900
+ --no-mounts)
901
+ no_mounts=true
902
+ shift
903
+ ;;
904
+ --provider)
905
+ if [[ -n "${2:-}" ]]; then
906
+ provider="$2"
907
+ shift 2
908
+ else
909
+ shift
910
+ fi
911
+ ;;
912
+ *)
913
+ # First non-flag argument is the PRD path
914
+ if [[ -z "$prd_path" ]]; then
915
+ prd_path="$1"
916
+ fi
917
+ shift
918
+ ;;
919
+ esac
920
+ done
773
921
 
774
922
  # Set up signal handler to cleanup on Ctrl+C
775
923
  trap cleanup_container INT TERM
@@ -887,6 +1035,38 @@ start_sandbox() {
887
1035
  docker_args+=("--volume" "$HOME/.config/gh:/home/loki/.config/gh:ro")
888
1036
  fi
889
1037
 
1038
+ # Apply Docker credential mount presets (additive on top of defaults above)
1039
+ if [[ "$no_mounts" != "true" ]] && [[ "${LOKI_NO_DOCKER_MOUNTS:-}" != "true" ]]; then
1040
+ local preset_mounts
1041
+ preset_mounts=$(resolve_docker_mounts)
1042
+ if [[ -n "$preset_mounts" ]]; then
1043
+ # shellcheck disable=SC2206
1044
+ docker_args+=($preset_mounts)
1045
+ fi
1046
+ fi
1047
+
1048
+ # Apply custom --mount arguments
1049
+ local custom_mount
1050
+ for custom_mount in "${custom_mounts[@]+"${custom_mounts[@]}"}"; do
1051
+ if [[ -n "$custom_mount" ]]; then
1052
+ IFS=':' read -ra mount_parts <<< "$custom_mount"
1053
+ local c_host="${mount_parts[0]:-}"
1054
+ local c_container="${mount_parts[1]:-}"
1055
+ local c_mode="${mount_parts[2]:-ro}"
1056
+ if [[ -n "$c_host" ]] && [[ -n "$c_container" ]]; then
1057
+ c_host=$(eval echo "$c_host" 2>/dev/null || echo "$c_host")
1058
+ if [[ -e "$c_host" ]]; then
1059
+ docker_args+=("--volume" "${c_host}:${c_container}:${c_mode}")
1060
+ log_info " Custom mount: $c_host -> $c_container ($c_mode)"
1061
+ else
1062
+ log_warn "Custom mount source does not exist: $c_host"
1063
+ fi
1064
+ else
1065
+ log_warn "Invalid mount format: $custom_mount (expected HOST:CONTAINER[:MODE])"
1066
+ fi
1067
+ fi
1068
+ done
1069
+
890
1070
  # Pass API keys as environment variables (more secure than mounting files)
891
1071
  if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
892
1072
  docker_args+=("--env" "ANTHROPIC_API_KEY")
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.1.0"
10
+ __version__ = "6.2.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.1.0
5
+ **Version:** v6.2.0
6
6
 
7
7
  ---
8
8
 
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '6.1.0'
60
+ __version__ = '6.2.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",
@@ -0,0 +1,21 @@
1
+ # Cluster Templates
2
+
3
+ Pre-built workflow topologies for common development patterns.
4
+
5
+ ## Usage
6
+
7
+ loki cluster list # List available templates
8
+ loki cluster validate <template> # Validate topology
9
+ loki cluster run <template> [args] # Execute workflow
10
+
11
+ ## Template Format
12
+
13
+ Each template is a JSON file defining agents, their pub/sub topics,
14
+ and the workflow topology.
15
+
16
+ ## Available Templates
17
+
18
+ - security-review: Multi-agent security audit pipeline
19
+ - performance-audit: Performance analysis with profiling
20
+ - refactoring: Structured refactoring with test preservation
21
+ - code-review: Multi-reviewer code review process
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "Code Review",
3
+ "description": "Multi-reviewer code review with conflict resolution",
4
+ "version": "1.0.0",
5
+ "topology": "fan-out-fan-in",
6
+ "agents": [
7
+ {
8
+ "id": "reviewer-arch",
9
+ "type": "review-code",
10
+ "role": "Review architecture and design patterns",
11
+ "subscribes": ["task.start"],
12
+ "publishes": ["review.architecture"]
13
+ },
14
+ {
15
+ "id": "reviewer-security",
16
+ "type": "review-security",
17
+ "role": "Review security implications",
18
+ "subscribes": ["task.start"],
19
+ "publishes": ["review.security"]
20
+ },
21
+ {
22
+ "id": "reviewer-tests",
23
+ "type": "eng-qa",
24
+ "role": "Review test coverage and quality",
25
+ "subscribes": ["task.start"],
26
+ "publishes": ["review.tests"]
27
+ },
28
+ {
29
+ "id": "resolver",
30
+ "type": "review-code",
31
+ "role": "Synthesize all review findings and resolve conflicts",
32
+ "subscribes": ["review.architecture", "review.security", "review.tests"],
33
+ "publishes": ["task.complete"]
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "Performance Audit",
3
+ "description": "Performance analysis with profiling and optimization recommendations",
4
+ "version": "1.0.0",
5
+ "topology": "fan-out-fan-in",
6
+ "agents": [
7
+ {
8
+ "id": "profiler",
9
+ "type": "eng-perf",
10
+ "role": "Profile application and identify bottlenecks",
11
+ "subscribes": ["task.start"],
12
+ "publishes": ["profile.results"]
13
+ },
14
+ {
15
+ "id": "db-analyzer",
16
+ "type": "eng-database",
17
+ "role": "Analyze database queries and index usage",
18
+ "subscribes": ["task.start"],
19
+ "publishes": ["db.analysis"]
20
+ },
21
+ {
22
+ "id": "optimizer",
23
+ "type": "eng-perf",
24
+ "role": "Generate optimization recommendations from all analyses",
25
+ "subscribes": ["profile.results", "db.analysis"],
26
+ "publishes": ["task.complete"]
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "Refactoring",
3
+ "description": "Structured refactoring with test preservation and review",
4
+ "version": "1.0.0",
5
+ "topology": "pipeline",
6
+ "agents": [
7
+ {
8
+ "id": "analyzer",
9
+ "type": "review-code",
10
+ "role": "Analyze code for refactoring opportunities",
11
+ "subscribes": ["task.start"],
12
+ "publishes": ["analysis.complete"]
13
+ },
14
+ {
15
+ "id": "refactorer",
16
+ "type": "eng-backend",
17
+ "role": "Apply refactoring changes with test preservation",
18
+ "subscribes": ["analysis.complete"],
19
+ "publishes": ["refactor.complete"]
20
+ },
21
+ {
22
+ "id": "verifier",
23
+ "type": "eng-qa",
24
+ "role": "Verify all tests pass and behavior is preserved",
25
+ "subscribes": ["refactor.complete"],
26
+ "publishes": ["task.complete"]
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "Security Review",
3
+ "description": "Multi-agent security audit with adversarial testing",
4
+ "version": "1.0.0",
5
+ "topology": "pipeline",
6
+ "agents": [
7
+ {
8
+ "id": "scanner",
9
+ "type": "ops-security",
10
+ "role": "Run SAST/dependency scanning on codebase",
11
+ "subscribes": ["task.start"],
12
+ "publishes": ["scan.results"]
13
+ },
14
+ {
15
+ "id": "reviewer",
16
+ "type": "review-security",
17
+ "role": "Review findings from scanner, assess severity",
18
+ "subscribes": ["scan.results"],
19
+ "publishes": ["review.findings"]
20
+ },
21
+ {
22
+ "id": "adversarial",
23
+ "type": "review-security",
24
+ "role": "Attempt to exploit discovered vulnerabilities",
25
+ "subscribes": ["review.findings"],
26
+ "publishes": ["exploit.results"]
27
+ },
28
+ {
29
+ "id": "reporter",
30
+ "type": "prod-techwriter",
31
+ "role": "Compile security report from all findings",
32
+ "subscribes": ["scan.results", "review.findings", "exploit.results"],
33
+ "publishes": ["task.complete"]
34
+ }
35
+ ]
36
+ }