@launchsecure/launch-kit 0.0.28 → 0.0.29

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.
Files changed (23) hide show
  1. package/dist/server/chart-serve.js +3 -1
  2. package/dist/server/cli.js +231 -221
  3. package/dist/server/council-entry.js +0 -0
  4. package/dist/server/course-entry.js +3 -3
  5. package/dist/server/fb-wizard.js +0 -0
  6. package/dist/server/graph-mcp-entry.js +35 -72
  7. package/dist/server/init-entry.js +794 -195
  8. package/package.json +22 -21
  9. package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +4 -4
  10. package/scaffolds/ls-marketplace/plugins/{ls → kit}/.claude-plugin/plugin.json +1 -10
  11. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/activate-beacon.md +2 -2
  12. package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
  13. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-array.md +3 -3
  14. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-clear.md +2 -2
  15. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-pulse.md +7 -7
  16. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/beacon-scan.md +7 -7
  17. package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
  18. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/show-mcp-status.md +6 -6
  19. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/standup.md +52 -38
  20. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
  21. package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
  22. package/scaffolds/statusline/statusline-mcp.sh +192 -0
  23. package/scaffolds/statusline/statusline-wrapper.sh +50 -0
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env bash
2
+ # launch-kit MCP chip generator.
3
+ # Emits a colored one-line summary of MCP daemon health, one chip per daemon.
4
+ # Composes into any existing statusline via the launch-kit wrapper.
5
+ #
6
+ # Usage:
7
+ # statusline-mcp.sh # all known chips (recall, chart, deck, council)
8
+ # statusline-mcp.sh --show=recall,chart # only the listed chips
9
+ # statusline-mcp.sh --compact # collapse to `mcp <up>/<total>`
10
+ # green when all up, red if any down
11
+ #
12
+ # Project root is inferred from $LK_STATUSLINE_CWD (set by the wrapper) or
13
+ # $PWD by walking up until a `.launchsecure` dir is found. Silent exit when
14
+ # the cwd is not inside a launchsecure project.
15
+ set -u
16
+
17
+ show=""
18
+ compact=0
19
+ for arg in "$@"; do
20
+ case "$arg" in
21
+ --show=*) show="${arg#--show=}" ;;
22
+ --compact) compact=1 ;;
23
+ esac
24
+ done
25
+ [ -z "$show" ] && show="recall,chart,deck,council"
26
+
27
+ GREEN=$'\033[32m'
28
+ ORANGE=$'\033[33m'
29
+ RED=$'\033[31m'
30
+ RESET=$'\033[0m'
31
+
32
+ find_project_root() {
33
+ # `.recall` only exists at the repo root (launch-recall init creates it
34
+ # there). `.launchsecure` can appear in subdirs too (e.g. packages/cli
35
+ # when graphs are generated for a sub-project), so we prefer .recall as
36
+ # the canonical root marker. Fallback: outermost `.launchsecure` ancestor
37
+ # (walk up and keep overwriting → keeps the highest match).
38
+ local d="${1:-$PWD}"
39
+ local recall_root=""
40
+ local outermost_launchsecure=""
41
+ while [ -n "$d" ] && [ "$d" != "/" ]; do
42
+ if [ -z "$recall_root" ] && [ -d "$d/.recall" ]; then
43
+ recall_root="$d"
44
+ fi
45
+ if [ -d "$d/.launchsecure" ]; then
46
+ outermost_launchsecure="$d"
47
+ fi
48
+ d=$(dirname "$d")
49
+ done
50
+ if [ -n "$recall_root" ]; then echo "$recall_root"; return 0; fi
51
+ if [ -n "$outermost_launchsecure" ]; then echo "$outermost_launchsecure"; return 0; fi
52
+ return 1
53
+ }
54
+
55
+ PROJECT_ROOT=$(find_project_root "${LK_STATUSLINE_CWD:-$PWD}") || exit 0
56
+
57
+ iso_to_epoch() {
58
+ # Input is always UTC (ISO timestamps from .freshness.json end in Z).
59
+ # macOS BSD `date` defaults to local TZ, so without TZ=UTC the timestamp
60
+ # gets misread as local time → wildly wrong age (e.g. 6h instead of 55m).
61
+ local ts="$1"
62
+ ts="${ts%%.*}"; ts="${ts%%Z*}"; ts="${ts%%+*}"
63
+ TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%S" "$ts" +%s 2>/dev/null
64
+ }
65
+
66
+ fmt_age() {
67
+ local then="$1"
68
+ local now diff
69
+ now=$(date +%s)
70
+ diff=$((now - then))
71
+ if [ "$diff" -lt 60 ]; then echo "${diff}s"
72
+ elif [ "$diff" -lt 3600 ]; then echo "$((diff/60))m"
73
+ elif [ "$diff" -lt 86400 ]; then echo "$((diff/3600))h"
74
+ else echo "$((diff/86400))d"
75
+ fi
76
+ }
77
+
78
+ pid_from_lockfile() {
79
+ grep -o '"pid"[^,}]*' "$1" 2>/dev/null | head -1 | sed 's/[^0-9]//g'
80
+ }
81
+
82
+ # Each chip_* function sets two globals so the caller can use both the
83
+ # colored display string (verbose mode) and the abstract state (compact mode)
84
+ # without re-running the underlying probe. Must be called as a bare command
85
+ # (no subshell) so the assignments survive.
86
+ _state=""
87
+ _display=""
88
+
89
+ chip_recall() {
90
+ local pidfile="$PROJECT_ROOT/.recall/watch.pid"
91
+ local repo="$PROJECT_ROOT/.recall/repo.git"
92
+ if [ ! -f "$pidfile" ]; then _state="red"; _display="${RED}recall${RESET}"; return; fi
93
+ local pid
94
+ pid=$(cat "$pidfile" 2>/dev/null) || pid=""
95
+ if [ -z "$pid" ] || ! kill -0 "$pid" 2>/dev/null; then
96
+ _state="red"; _display="${RED}recall${RESET}"
97
+ return
98
+ fi
99
+ if [ -d "$repo" ]; then
100
+ local last
101
+ last=$(git --git-dir="$repo" log -1 --format=%ct 2>/dev/null)
102
+ if [ -n "$last" ]; then
103
+ local now diff age
104
+ now=$(date +%s); diff=$((now - last)); age=$(fmt_age "$last")
105
+ if [ "$diff" -gt 21600 ]; then
106
+ _state="orange"; _display="${ORANGE}recall(${age})${RESET}"
107
+ else
108
+ _state="green"; _display="${GREEN}recall(${age})${RESET}"
109
+ fi
110
+ return
111
+ fi
112
+ fi
113
+ _state="green"; _display="${GREEN}recall${RESET}"
114
+ }
115
+
116
+ chip_chart() {
117
+ local freshness="$PROJECT_ROOT/.launchsecure/graphs/.freshness.json"
118
+ if [ ! -f "$freshness" ]; then _state="red"; _display="${RED}chart${RESET}"; return; fi
119
+ local last
120
+ last=$(grep -o '"lastFullRegenAt"[^,}]*' "$freshness" | head -1 | sed 's/.*"\([0-9TZ:.+-]*\)".*/\1/')
121
+ local lock="$PROJECT_ROOT/.launchsecure/launch-chart.lock"
122
+ local color="$ORANGE"; local state="orange"
123
+ if [ -f "$lock" ]; then
124
+ local pid
125
+ pid=$(pid_from_lockfile "$lock")
126
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
127
+ color="$GREEN"; state="green"
128
+ fi
129
+ fi
130
+ if [ -n "$last" ] && [ "$last" != "null" ]; then
131
+ local epoch age
132
+ epoch=$(iso_to_epoch "$last")
133
+ if [ -n "$epoch" ]; then
134
+ age=$(fmt_age "$epoch")
135
+ _state="$state"; _display="${color}chart(${age})${RESET}"
136
+ return
137
+ fi
138
+ fi
139
+ _state="$state"; _display="${color}chart${RESET}"
140
+ }
141
+
142
+ chip_deck() {
143
+ local lock="$PROJECT_ROOT/.launchsecure/launch-deck.lock"
144
+ if [ -f "$lock" ]; then
145
+ local pid; pid=$(pid_from_lockfile "$lock")
146
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
147
+ _state="green"; _display="${GREEN}deck${RESET}"; return
148
+ fi
149
+ fi
150
+ _state="orange"; _display="${ORANGE}deck${RESET}"
151
+ }
152
+
153
+ chip_council() {
154
+ local lock="$PROJECT_ROOT/.launchsecure/launch-council.lock"
155
+ if [ -f "$lock" ]; then
156
+ local pid; pid=$(pid_from_lockfile "$lock")
157
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
158
+ _state="green"; _display="${GREEN}council${RESET}"; return
159
+ fi
160
+ fi
161
+ _state="orange"; _display="${ORANGE}council${RESET}"
162
+ }
163
+
164
+ show_list=$(echo "$show" | tr ',' ' ')
165
+ total=0
166
+ up=0
167
+ out=""
168
+ for d in $show_list; do
169
+ case "$d" in
170
+ recall) chip_recall ;;
171
+ chart) chip_chart ;;
172
+ deck) chip_deck ;;
173
+ council) chip_council ;;
174
+ *) continue ;;
175
+ esac
176
+ total=$((total + 1))
177
+ [ "$_state" = "green" ] && up=$((up + 1))
178
+ if [ "$compact" = "0" ]; then
179
+ if [ -z "$out" ]; then out="$_display"; else out="${out} · ${_display}"; fi
180
+ fi
181
+ done
182
+
183
+ if [ "$compact" = "1" ]; then
184
+ if [ "$total" -eq 0 ]; then exit 0; fi
185
+ if [ "$up" -eq "$total" ]; then
186
+ printf '%smcp %d/%d%s' "$GREEN" "$up" "$total" "$RESET"
187
+ else
188
+ printf '%smcp %d/%d%s' "$RED" "$up" "$total" "$RESET"
189
+ fi
190
+ else
191
+ printf '%s' "$out"
192
+ fi
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # launch-kit statusline wrapper.
3
+ # Runs the user's original statusline command, then appends MCP chip output.
4
+ # Reads Claude Code's statusline JSON from stdin once, fans it out.
5
+ #
6
+ # The original command is stored under `_launchKitStatuslineOriginal.command`
7
+ # in ~/.claude/settings.json (written by `launch-kit statusline activate`).
8
+ # `launch-kit statusline deactivate` restores it to `statusLine.command`.
9
+ set -u
10
+
11
+ input=$(cat)
12
+ settings="$HOME/.claude/settings.json"
13
+
14
+ original_cmd=""
15
+ if [ -f "$settings" ] && command -v jq >/dev/null 2>&1; then
16
+ original_cmd=$(jq -r '._launchKitStatuslineOriginal.command // empty' "$settings" 2>/dev/null || true)
17
+ fi
18
+
19
+ original_output=""
20
+ if [ -n "$original_cmd" ]; then
21
+ original_output=$(printf '%s' "$input" | bash -c "$original_cmd" 2>/dev/null || true)
22
+ fi
23
+
24
+ cwd=""
25
+ if command -v jq >/dev/null 2>&1; then
26
+ cwd=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null || true)
27
+ fi
28
+
29
+ chips=""
30
+ if [ -x "$HOME/.launchsecure/statusline-mcp.sh" ]; then
31
+ # Build args array conditionally; `set -u` + empty `"${args[@]}"` would
32
+ # error on bash 4 (default macOS bash), so test length before expanding.
33
+ args=()
34
+ [ -n "${LK_STATUSLINE_SHOW:-}" ] && args+=("--show=$LK_STATUSLINE_SHOW")
35
+ [ "${LK_STATUSLINE_COMPACT:-0}" = "1" ] && args+=("--compact")
36
+ if [ "${#args[@]}" -eq 0 ]; then
37
+ chips=$(LK_STATUSLINE_CWD="$cwd" "$HOME/.launchsecure/statusline-mcp.sh" 2>/dev/null || true)
38
+ else
39
+ chips=$(LK_STATUSLINE_CWD="$cwd" "$HOME/.launchsecure/statusline-mcp.sh" "${args[@]}" 2>/dev/null || true)
40
+ fi
41
+ fi
42
+
43
+ sep=$'\033[2m | \033[0m'
44
+ if [ -n "$original_output" ] && [ -n "$chips" ]; then
45
+ printf '%s%s%s' "$original_output" "$sep" "$chips"
46
+ elif [ -n "$original_output" ]; then
47
+ printf '%s' "$original_output"
48
+ elif [ -n "$chips" ]; then
49
+ printf '%s' "$chips"
50
+ fi