showpane 0.4.13 → 0.4.15
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/README.md +2 -1
- package/bundle/meta/scaffold-manifest.json +10 -10
- package/bundle/scaffold/VERSION +1 -1
- package/bundle/scaffold/prisma/seed.ts +40 -35
- package/bundle/scaffold/src/__tests__/portal-contracts.test.ts +7 -0
- package/bundle/scaffold/src/app/(portal)/client/example/example-client.tsx +1 -2
- package/bundle/scaffold/src/app/(portal)/client/page.tsx +5 -4
- package/bundle/scaffold/src/app/page.tsx +43 -6
- package/bundle/scaffold/src/components/portal-shell.tsx +23 -0
- package/bundle/scaffold/src/lib/portal-contracts.ts +33 -0
- package/bundle/toolchain/CLI_VERSION +1 -0
- package/bundle/toolchain/TELEMETRY_CONFIG.json +4 -0
- package/bundle/toolchain/VERSION +1 -1
- package/bundle/toolchain/bin/ensure-cloud-project-link.ts +34 -1
- package/bundle/toolchain/bin/showpane-config +108 -29
- package/bundle/toolchain/bin/showpane-telemetry-log +84 -0
- package/bundle/toolchain/bin/showpane-telemetry-sync +212 -0
- package/bundle/toolchain/bin/showpane-update-check +130 -0
- package/bundle/toolchain/skills/SKILL.md.tmpl +13 -0
- package/bundle/toolchain/skills/VERSION +1 -1
- package/bundle/toolchain/skills/portal-analytics/SKILL.md +60 -38
- package/bundle/toolchain/skills/portal-analytics/SKILL.md.tmpl +192 -0
- package/bundle/toolchain/skills/portal-create/SKILL.md +65 -67
- package/bundle/toolchain/skills/portal-create/SKILL.md.tmpl +264 -0
- package/bundle/toolchain/skills/portal-credentials/SKILL.md +66 -49
- package/bundle/toolchain/skills/portal-credentials/SKILL.md.tmpl +198 -0
- package/bundle/toolchain/skills/portal-delete/SKILL.md +63 -41
- package/bundle/toolchain/skills/portal-delete/SKILL.md.tmpl +194 -0
- package/bundle/toolchain/skills/portal-deploy/SKILL.md +57 -47
- package/bundle/toolchain/skills/portal-deploy/SKILL.md.tmpl +452 -0
- package/bundle/toolchain/skills/portal-dev/SKILL.md +65 -47
- package/bundle/toolchain/skills/portal-dev/SKILL.md.tmpl +228 -0
- package/bundle/toolchain/skills/portal-list/SKILL.md +64 -43
- package/bundle/toolchain/skills/portal-list/SKILL.md.tmpl +181 -0
- package/bundle/toolchain/skills/portal-onboard/SKILL.md +331 -162
- package/bundle/toolchain/skills/portal-onboard/SKILL.md.tmpl +340 -0
- package/bundle/toolchain/skills/portal-preview/SKILL.md +65 -44
- package/bundle/toolchain/skills/portal-preview/SKILL.md.tmpl +171 -0
- package/bundle/toolchain/skills/portal-setup/SKILL.md +79 -60
- package/bundle/toolchain/skills/portal-setup/SKILL.md.tmpl +227 -0
- package/bundle/toolchain/skills/portal-share/SKILL.md +69 -47
- package/bundle/toolchain/skills/portal-share/SKILL.md.tmpl +162 -0
- package/bundle/toolchain/skills/portal-status/SKILL.md +58 -37
- package/bundle/toolchain/skills/portal-status/SKILL.md.tmpl +196 -0
- package/bundle/toolchain/skills/portal-update/SKILL.md +60 -46
- package/bundle/toolchain/skills/portal-update/SKILL.md.tmpl +269 -0
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md +55 -33
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md.tmpl +164 -0
- package/bundle/toolchain/skills/portal-verify/SKILL.md +69 -14
- package/bundle/toolchain/skills/portal-verify/SKILL.md.tmpl +224 -0
- package/bundle/toolchain/skills/shared/preamble.md +30 -126
- package/bundle/toolchain/skills/shared/runtime-principles.md +25 -0
- package/bundle/toolchain/templates/sales-followup/sales-followup-client.tsx +1 -1
- package/dist/index.js +79 -14
- package/package.json +5 -2
|
@@ -11,14 +11,17 @@ allowed-tools: [Bash, Read, Write, Edit, Glob, Grep]
|
|
|
11
11
|
Before doing anything else, execute this block in a Bash tool call:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
14
|
+
SHOWPANE_HOME="$HOME/.showpane"
|
|
15
|
+
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
16
|
+
CONFIG="$SHOWPANE_HOME/config.json"
|
|
15
17
|
if [ ! -f "$CONFIG" ]; then
|
|
16
|
-
echo "Showpane not configured. Run /portal
|
|
18
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
17
19
|
exit 1
|
|
18
20
|
fi
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
APP_PATH=$("$SHOWPANE_BIN/showpane-config" get app_path 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('app_path',''))" 2>/dev/null)
|
|
23
|
+
DEPLOY_MODE=$("$SHOWPANE_BIN/showpane-config" get deploy_mode 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('deploy_mode','local'))" 2>/dev/null || echo "local")
|
|
24
|
+
ORG_SLUG=$("$SHOWPANE_BIN/showpane-config" get orgSlug 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('orgSlug','') or d.get('org_slug',''))" 2>/dev/null || true)
|
|
22
25
|
APP_PATH="${SHOWPANE_APP_PATH:-$APP_PATH}"
|
|
23
26
|
if [ -f "$APP_PATH/.env" ]; then set -a && source "$APP_PATH/.env" && set +a; fi
|
|
24
27
|
DATABASE_URL="${DATABASE_URL:-}"
|
|
@@ -26,20 +29,26 @@ if [ ! -d "$APP_PATH/node_modules/.prisma" ]; then
|
|
|
26
29
|
echo "App dependencies not installed. Run: cd $APP_PATH && npm install"
|
|
27
30
|
exit 1
|
|
28
31
|
fi
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
SKILL_DIR="${SHOWPANE_TOOLCHAIN_DIR:-$SHOWPANE_HOME/current}"
|
|
30
34
|
SKILL_VERSION=$(cat "$SKILL_DIR/VERSION" 2>/dev/null || echo "unknown")
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
_UPD=$("$SHOWPANE_BIN/showpane-update-check" 2>/dev/null || true)
|
|
36
|
+
[ -n "$_UPD" ] && echo "$_UPD" || true
|
|
37
|
+
mkdir -p "$SHOWPANE_HOME/sessions" "$SHOWPANE_HOME/analytics" "$SHOWPANE_HOME/checkpoints"
|
|
38
|
+
touch "$SHOWPANE_HOME/sessions/$PPID"
|
|
39
|
+
find "$SHOWPANE_HOME/sessions" -mmin +120 -type f -delete 2>/dev/null || true
|
|
40
|
+
TEL=$("$SHOWPANE_BIN/showpane-config" get telemetry 2>/dev/null || echo "anonymous")
|
|
41
|
+
TEL_PROMPTED=$([ -f "$SHOWPANE_HOME/.telemetry-prompted" ] && echo "yes" || echo "no")
|
|
42
|
+
_TEL_START=$(date +%s)
|
|
43
|
+
_SESSION_ID="${PPID:-0}-$(date +%s)"
|
|
44
|
+
|
|
45
|
+
LEARN_FILE="$SHOWPANE_HOME/learnings.jsonl"
|
|
33
46
|
[ -f "$LEARN_FILE" ] && echo "LEARNINGS: $(wc -l < "$LEARN_FILE" | tr -d ' ') loaded" || echo "LEARNINGS: 0"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
_RECENT=$(grep '"event":"completed"' "$HOME/.showpane/timeline.jsonl" 2>/dev/null | tail -3 | grep -o '"skill":"[^"]*"' | sed 's/"skill":"//;s/"//' | tr '\n' ',' | sed 's/,$//' || true)
|
|
47
|
+
if [ -f "$SHOWPANE_HOME/timeline.jsonl" ]; then
|
|
48
|
+
_RECENT=$(grep '"event":"completed"' "$SHOWPANE_HOME/timeline.jsonl" 2>/dev/null | tail -3 | grep -o '"skill":"[^"]*"' | sed 's/"skill":"//;s/"//' | tr '
|
|
49
|
+
' ',' | sed 's/,$//' || true)
|
|
38
50
|
[ -n "$_RECENT" ] && echo "RECENT_SKILLS: $_RECENT"
|
|
39
51
|
fi
|
|
40
|
-
|
|
41
|
-
# Search relevant learnings
|
|
42
|
-
LEARN_FILE="$HOME/.showpane/learnings.jsonl"
|
|
43
52
|
if [ -f "$LEARN_FILE" ]; then
|
|
44
53
|
_LEARN_COUNT=$(wc -l < "$LEARN_FILE" 2>/dev/null | tr -d ' ')
|
|
45
54
|
echo "LEARNINGS: $_LEARN_COUNT entries"
|
|
@@ -49,23 +58,39 @@ if [ -f "$LEARN_FILE" ]; then
|
|
|
49
58
|
fi
|
|
50
59
|
fi
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
SHOWPANE_TIMELINE="$HOME/.showpane/timeline.jsonl"
|
|
61
|
+
SHOWPANE_TIMELINE="$SHOWPANE_HOME/timeline.jsonl"
|
|
54
62
|
mkdir -p "$(dirname "$SHOWPANE_TIMELINE")"
|
|
55
63
|
echo '{"skill":"portal-upgrade","event":"started","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> "$SHOWPANE_TIMELINE" 2>/dev/null
|
|
64
|
+
echo "SHOWPANE: v$SKILL_VERSION | MODE: $DEPLOY_MODE | APP: $APP_PATH"
|
|
65
|
+
echo "TELEMETRY: $TEL"
|
|
66
|
+
echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
56
67
|
```
|
|
57
68
|
|
|
58
|
-
If
|
|
69
|
+
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
70
|
+
|
|
71
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
72
|
+
|
|
73
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
74
|
+
|
|
75
|
+
Run:
|
|
76
|
+
```bash
|
|
77
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
78
|
+
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If `RECENT_SKILLS` is shown, suggest the likely next skill:
|
|
59
82
|
- After portal-create → suggest /portal-preview
|
|
60
|
-
- After portal-preview → suggest /portal-deploy
|
|
83
|
+
- After portal-preview → suggest /portal-deploy
|
|
61
84
|
- After portal-deploy → suggest /portal-status or /portal-verify
|
|
62
|
-
- After portal-setup → suggest /portal-create
|
|
63
|
-
- After portal-credentials → suggest /portal-
|
|
64
|
-
- After portal-update → suggest /portal-deploy
|
|
85
|
+
- After portal-setup → suggest /portal-onboard for a first run, or /portal-create for the fast path
|
|
86
|
+
- After portal-credentials → suggest /portal-deploy before external sharing
|
|
87
|
+
- After portal-update → suggest /portal-preview or /portal-deploy
|
|
65
88
|
|
|
66
|
-
If RECENT_LEARNINGS is shown, review them before proceeding.
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
If `RECENT_LEARNINGS` is shown, review them before proceeding. Apply them where relevant but do not mention them unless they materially affect the current task.
|
|
90
|
+
|
|
91
|
+
Read `skills/shared/runtime-principles.md` once near the start of the skill and apply the relevant product defaults.
|
|
92
|
+
|
|
93
|
+
If `skills/shared/platform-constraints.md` exists, read it once near the start of the skill and apply only the relevant limits.
|
|
69
94
|
|
|
70
95
|
## Overview
|
|
71
96
|
|
|
@@ -210,7 +235,7 @@ If no changelog exists, the CLI dry-run summary serves as the change summary.
|
|
|
210
235
|
|
|
211
236
|
## Upgrade Frequency
|
|
212
237
|
|
|
213
|
-
There is no auto-upgrade mechanism. The user must explicitly run `/portal
|
|
238
|
+
There is no auto-upgrade mechanism. The user must explicitly run `/portal-upgrade` to check for and apply updates.
|
|
214
239
|
|
|
215
240
|
Suggested upgrade frequency: monthly, or when the user encounters an issue that may have been fixed upstream. The skill does not nag or remind.
|
|
216
241
|
|
|
@@ -222,14 +247,11 @@ If a new version introduces changes to the learnings format, the changelog or se
|
|
|
222
247
|
|
|
223
248
|
## Completion
|
|
224
249
|
|
|
225
|
-
As a final step, log skill completion:
|
|
250
|
+
As a final step, log skill completion and telemetry:
|
|
226
251
|
|
|
227
252
|
```bash
|
|
228
253
|
echo '{"skill":"portal-upgrade","event":"completed","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> "$HOME/.showpane/timeline.jsonl" 2>/dev/null
|
|
254
|
+
_TEL_END=$(date +%s)
|
|
255
|
+
_TEL_DUR=$(( _TEL_END - ${_TEL_START:-_TEL_END} ))
|
|
256
|
+
"$HOME/.showpane/bin/showpane-telemetry-log" --skill "portal-upgrade" --duration "$_TEL_DUR" --outcome success --session-id "${_SESSION_ID:-}" 2>/dev/null || true
|
|
229
257
|
```
|
|
230
|
-
|
|
231
|
-
## Related Skills
|
|
232
|
-
|
|
233
|
-
- `/portal setup` -- re-run setup independently if the upgraded project needs reconfiguration
|
|
234
|
-
- `/portal status` -- check that all portals are healthy after an upgrade
|
|
235
|
-
- `/portal dev` -- restart the dev server to pick up any app changes
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: portal-upgrade
|
|
3
|
+
description: |
|
|
4
|
+
Self-update the Showpane skill pack to the latest version. Use when asked to "upgrade",
|
|
5
|
+
"update showpane", "update skills", "get latest version", or "check for updates". (showpane)
|
|
6
|
+
allowed-tools: [Bash, Read, Write, Edit, Glob, Grep]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
{{PREAMBLE}}
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
This skill updates both the global Showpane toolchain and the current project using the packaged Showpane CLI. The upgrade is versioned -- it does not depend on the user's project being a git clone of the upstream Showpane repository.
|
|
14
|
+
|
|
15
|
+
The flow is:
|
|
16
|
+
1. Check the current installed Showpane/toolchain version
|
|
17
|
+
2. Check the latest published CLI version on npm
|
|
18
|
+
3. Run a dry-run project upgrade to detect conflicts
|
|
19
|
+
4. Sync the matching global toolchain
|
|
20
|
+
5. Apply the project upgrade
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### Step 1: Check current version
|
|
25
|
+
|
|
26
|
+
Read the current skill pack version from the VERSION file:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cat $SKILL_DIR/VERSION
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This was already captured by the preamble, but read it explicitly here so you have the full version string (e.g., "1.0.0 (requires app >= 0.1.0)").
|
|
33
|
+
|
|
34
|
+
Display the current version:
|
|
35
|
+
|
|
36
|
+
"Current version: 1.0.0"
|
|
37
|
+
|
|
38
|
+
### Step 2: Check the latest published Showpane version
|
|
39
|
+
|
|
40
|
+
Run:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm view showpane version
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If the command fails, report:
|
|
47
|
+
|
|
48
|
+
"Could not reach the npm registry. Check your network connection and try again."
|
|
49
|
+
|
|
50
|
+
If the returned version matches the current Showpane version, inform the user that no published upgrade is available and stop.
|
|
51
|
+
|
|
52
|
+
### Step 3: Dry-run the project upgrade
|
|
53
|
+
|
|
54
|
+
Run a dry-run against the user's project before changing anything:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx showpane@latest upgrade --project "$APP_PATH" --dry-run
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If the dry-run reports conflicts, stop and show the conflicted managed files. Explain:
|
|
61
|
+
|
|
62
|
+
"Showpane found local edits in framework-managed files. Review or revert those files before running the upgrade."
|
|
63
|
+
|
|
64
|
+
### Step 4: Sync the latest toolchain
|
|
65
|
+
|
|
66
|
+
Install the matching global Showpane toolchain and Claude Code skill links:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx showpane@latest sync
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If sync fails, stop and report the error. Do not continue to the project upgrade.
|
|
73
|
+
|
|
74
|
+
### Step 5: Apply the project upgrade
|
|
75
|
+
|
|
76
|
+
Run:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx showpane@latest upgrade --project "$APP_PATH"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This applies packaged scaffold updates to managed files only. It does not rely on upstream git history.
|
|
83
|
+
|
|
84
|
+
### Step 6: Display the resulting version
|
|
85
|
+
|
|
86
|
+
Read the project version file:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cat "$APP_PATH/VERSION"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Display a short confirmation:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
════════════════════════════════════════
|
|
96
|
+
Showpane upgraded!
|
|
97
|
+
|
|
98
|
+
Toolchain: latest published version
|
|
99
|
+
App: <APP_PATH/VERSION>
|
|
100
|
+
════════════════════════════════════════
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Version Compatibility
|
|
104
|
+
|
|
105
|
+
The VERSION file format remains: `<skill_version> (requires app >= <min_app_version>)`
|
|
106
|
+
|
|
107
|
+
After syncing the toolchain, compare:
|
|
108
|
+
- Read the new minimum app version from `"$SKILL_DIR/skills/VERSION"`
|
|
109
|
+
- Read the current app version from `"$APP_PATH/VERSION"`
|
|
110
|
+
- If the app version is below the minimum, warn the user
|
|
111
|
+
|
|
112
|
+
## Conventions
|
|
113
|
+
|
|
114
|
+
- Always show the current version before checking for updates. This gives the user a reference point.
|
|
115
|
+
- Always run the dry-run first. No silent updates.
|
|
116
|
+
- Use double-line box drawing (`═`) for the version display boxes.
|
|
117
|
+
- If the user runs upgrade frequently (check learnings), keep output minimal: just the version change and commit count.
|
|
118
|
+
- Do not auto-upgrade on other skill invocations. The upgrade is only triggered explicitly by this skill.
|
|
119
|
+
|
|
120
|
+
## Edge Cases
|
|
121
|
+
|
|
122
|
+
- **Dry-run conflicts**: Stop and surface the file list. Do not attempt a force-upgrade.
|
|
123
|
+
- **Registry/network failure**: If `npm view` or `npx showpane@latest ...` fails due to connectivity, report it and stop.
|
|
124
|
+
- **Toolchain sync fails**: Do not continue to the project upgrade.
|
|
125
|
+
|
|
126
|
+
## Error Handling
|
|
127
|
+
|
|
128
|
+
- If the preamble fails, stop and display the error.
|
|
129
|
+
- If the dry-run fails, report the error and stop.
|
|
130
|
+
- If the real upgrade fails after the dry-run succeeded, show the CLI error output and stop.
|
|
131
|
+
- Do not attempt to recover with git commands.
|
|
132
|
+
|
|
133
|
+
## Changelog Awareness
|
|
134
|
+
|
|
135
|
+
After a successful upgrade, check if a CHANGELOG.md exists in the project root:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
cat "$APP_PATH/CHANGELOG.md" 2>/dev/null | head -50
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If a changelog exists, extract the entries between the previous and current version and display them as a "What's new" section:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
What's new in 1.1.0:
|
|
145
|
+
- Portal analytics now shows trend comparisons
|
|
146
|
+
- Fixed credential rotation not bumping version number
|
|
147
|
+
- Preamble now includes telemetry opt-in status
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
If no changelog exists, the CLI dry-run summary serves as the change summary.
|
|
151
|
+
|
|
152
|
+
## Upgrade Frequency
|
|
153
|
+
|
|
154
|
+
There is no auto-upgrade mechanism. The user must explicitly run `/portal-upgrade` to check for and apply updates.
|
|
155
|
+
|
|
156
|
+
Suggested upgrade frequency: monthly, or when the user encounters an issue that may have been fixed upstream. The skill does not nag or remind.
|
|
157
|
+
|
|
158
|
+
## Learnings Preservation
|
|
159
|
+
|
|
160
|
+
Upgrading does not affect the user's learnings file (`~/.showpane/learnings.jsonl`). Learnings are stored outside the project and persist across upgrades. Similarly, the config file (`~/.showpane/config.json`) and telemetry data (`~/.showpane/telemetry.jsonl`) are not touched by the upgrade.
|
|
161
|
+
|
|
162
|
+
If a new version introduces changes to the learnings format, the changelog or setup script should handle migration transparently.
|
|
163
|
+
|
|
164
|
+
{{COMPLETION}}
|
|
@@ -8,21 +8,20 @@ allowed-tools: [Bash, Read, Glob, Grep]
|
|
|
8
8
|
|
|
9
9
|
## Preamble (run first)
|
|
10
10
|
|
|
11
|
+
Before doing anything else, execute this block in a Bash tool call:
|
|
12
|
+
|
|
11
13
|
```bash
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
SHOWPANE_HOME="$HOME/.showpane"
|
|
15
|
+
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
16
|
+
CONFIG="$SHOWPANE_HOME/config.json"
|
|
14
17
|
if [ ! -f "$CONFIG" ]; then
|
|
15
18
|
echo "Showpane not configured. Run /portal-setup first."
|
|
16
19
|
exit 1
|
|
17
20
|
fi
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
CLOUD_ORG_SLUG=$(python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('cloud',d).get('org_slug', d.get('orgSlug','')))" 2>/dev/null)
|
|
23
|
-
CLOUD_PORTAL_URL=$(python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('cloud',d).get('portal_url', d.get('portalUrl','')))" 2>/dev/null)
|
|
24
|
-
CLOUD_API_BASE="${SHOWPANE_CLOUD_URL:-https://app.showpane.com}"
|
|
25
|
-
CLOUD_EVENTS_URL="${CLOUD_EVENTS_URL:-$CLOUD_API_BASE}"
|
|
21
|
+
|
|
22
|
+
APP_PATH=$("$SHOWPANE_BIN/showpane-config" get app_path 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('app_path',''))" 2>/dev/null)
|
|
23
|
+
DEPLOY_MODE=$("$SHOWPANE_BIN/showpane-config" get deploy_mode 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('deploy_mode','local'))" 2>/dev/null || echo "local")
|
|
24
|
+
ORG_SLUG=$("$SHOWPANE_BIN/showpane-config" get orgSlug 2>/dev/null || python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('orgSlug','') or d.get('org_slug',''))" 2>/dev/null || true)
|
|
26
25
|
APP_PATH="${SHOWPANE_APP_PATH:-$APP_PATH}"
|
|
27
26
|
if [ -f "$APP_PATH/.env" ]; then set -a && source "$APP_PATH/.env" && set +a; fi
|
|
28
27
|
DATABASE_URL="${DATABASE_URL:-}"
|
|
@@ -30,13 +29,69 @@ if [ ! -d "$APP_PATH/node_modules/.prisma" ]; then
|
|
|
30
29
|
echo "App dependencies not installed. Run: cd $APP_PATH && npm install"
|
|
31
30
|
exit 1
|
|
32
31
|
fi
|
|
33
|
-
|
|
32
|
+
|
|
33
|
+
SKILL_DIR="${SHOWPANE_TOOLCHAIN_DIR:-$SHOWPANE_HOME/current}"
|
|
34
34
|
SKILL_VERSION=$(cat "$SKILL_DIR/VERSION" 2>/dev/null || echo "unknown")
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
_UPD=$("$SHOWPANE_BIN/showpane-update-check" 2>/dev/null || true)
|
|
36
|
+
[ -n "$_UPD" ] && echo "$_UPD" || true
|
|
37
|
+
mkdir -p "$SHOWPANE_HOME/sessions" "$SHOWPANE_HOME/analytics" "$SHOWPANE_HOME/checkpoints"
|
|
38
|
+
touch "$SHOWPANE_HOME/sessions/$PPID"
|
|
39
|
+
find "$SHOWPANE_HOME/sessions" -mmin +120 -type f -delete 2>/dev/null || true
|
|
40
|
+
TEL=$("$SHOWPANE_BIN/showpane-config" get telemetry 2>/dev/null || echo "anonymous")
|
|
41
|
+
TEL_PROMPTED=$([ -f "$SHOWPANE_HOME/.telemetry-prompted" ] && echo "yes" || echo "no")
|
|
42
|
+
_TEL_START=$(date +%s)
|
|
43
|
+
_SESSION_ID="${PPID:-0}-$(date +%s)"
|
|
44
|
+
|
|
45
|
+
LEARN_FILE="$SHOWPANE_HOME/learnings.jsonl"
|
|
37
46
|
[ -f "$LEARN_FILE" ] && echo "LEARNINGS: $(wc -l < "$LEARN_FILE" | tr -d ' ') loaded" || echo "LEARNINGS: 0"
|
|
47
|
+
if [ -f "$SHOWPANE_HOME/timeline.jsonl" ]; then
|
|
48
|
+
_RECENT=$(grep '"event":"completed"' "$SHOWPANE_HOME/timeline.jsonl" 2>/dev/null | tail -3 | grep -o '"skill":"[^"]*"' | sed 's/"skill":"//;s/"//' | tr '
|
|
49
|
+
' ',' | sed 's/,$//' || true)
|
|
50
|
+
[ -n "$_RECENT" ] && echo "RECENT_SKILLS: $_RECENT"
|
|
51
|
+
fi
|
|
52
|
+
if [ -f "$LEARN_FILE" ]; then
|
|
53
|
+
_LEARN_COUNT=$(wc -l < "$LEARN_FILE" 2>/dev/null | tr -d ' ')
|
|
54
|
+
echo "LEARNINGS: $_LEARN_COUNT entries"
|
|
55
|
+
if [ "$_LEARN_COUNT" -gt 0 ] 2>/dev/null; then
|
|
56
|
+
echo "RECENT_LEARNINGS:"
|
|
57
|
+
tail -5 "$LEARN_FILE" 2>/dev/null
|
|
58
|
+
fi
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
SHOWPANE_TIMELINE="$SHOWPANE_HOME/timeline.jsonl"
|
|
62
|
+
mkdir -p "$(dirname "$SHOWPANE_TIMELINE")"
|
|
63
|
+
echo '{"skill":"portal-verify","event":"started","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> "$SHOWPANE_TIMELINE" 2>/dev/null
|
|
64
|
+
echo "SHOWPANE: v$SKILL_VERSION | MODE: $DEPLOY_MODE | APP: $APP_PATH"
|
|
65
|
+
echo "TELEMETRY: $TEL"
|
|
66
|
+
echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
38
67
|
```
|
|
39
68
|
|
|
69
|
+
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
70
|
+
|
|
71
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
72
|
+
|
|
73
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
74
|
+
|
|
75
|
+
Run:
|
|
76
|
+
```bash
|
|
77
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
78
|
+
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If `RECENT_SKILLS` is shown, suggest the likely next skill:
|
|
82
|
+
- After portal-create → suggest /portal-preview
|
|
83
|
+
- After portal-preview → suggest /portal-deploy
|
|
84
|
+
- After portal-deploy → suggest /portal-status or /portal-verify
|
|
85
|
+
- After portal-setup → suggest /portal-onboard for a first run, or /portal-create for the fast path
|
|
86
|
+
- After portal-credentials → suggest /portal-deploy before external sharing
|
|
87
|
+
- After portal-update → suggest /portal-preview or /portal-deploy
|
|
88
|
+
|
|
89
|
+
If `RECENT_LEARNINGS` is shown, review them before proceeding. Apply them where relevant but do not mention them unless they materially affect the current task.
|
|
90
|
+
|
|
91
|
+
Read `skills/shared/runtime-principles.md` once near the start of the skill and apply the relevant product defaults.
|
|
92
|
+
|
|
93
|
+
If `skills/shared/platform-constraints.md` exists, read it once near the start of the skill and apply only the relevant limits.
|
|
94
|
+
|
|
40
95
|
## Steps
|
|
41
96
|
|
|
42
97
|
### Step 1: URL Reachability
|
|
@@ -45,7 +100,7 @@ Determine the portal URL and check that it responds.
|
|
|
45
100
|
|
|
46
101
|
```bash
|
|
47
102
|
if [ -z "$CLOUD_PORTAL_URL" ] && [ -z "$CLOUD_ORG_SLUG" ]; then
|
|
48
|
-
echo "No hosted portal URL configured. Run /portal
|
|
103
|
+
echo "No hosted portal URL configured. Run /portal-deploy first."
|
|
49
104
|
exit 1
|
|
50
105
|
fi
|
|
51
106
|
PORTAL_URL="${CLOUD_PORTAL_URL:-https://$CLOUD_ORG_SLUG.showpane.com}"
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: portal-verify
|
|
3
|
+
description: |
|
|
4
|
+
Verify a Showpane Cloud portal after publish: DNS, SSL, login page, content rendering, engagement tracking.
|
|
5
|
+
Trigger phrases: "verify portal", "check deployment", "is my portal working", "portal health". (showpane)
|
|
6
|
+
allowed-tools: [Bash, Read, Glob, Grep]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
{{PREAMBLE}}
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
### Step 1: URL Reachability
|
|
14
|
+
|
|
15
|
+
Determine the portal URL and check that it responds.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
if [ -z "$CLOUD_PORTAL_URL" ] && [ -z "$CLOUD_ORG_SLUG" ]; then
|
|
19
|
+
echo "No hosted portal URL configured. Run /portal-deploy first."
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
PORTAL_URL="${CLOUD_PORTAL_URL:-https://$CLOUD_ORG_SLUG.showpane.com}"
|
|
23
|
+
echo "Checking app URL: $CLOUD_API_BASE"
|
|
24
|
+
APP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$CLOUD_API_BASE/api/health" 2>/dev/null)
|
|
25
|
+
echo "App health: $APP_CODE"
|
|
26
|
+
|
|
27
|
+
echo "Checking org URL: $PORTAL_URL"
|
|
28
|
+
ORG_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$PORTAL_URL" 2>/dev/null)
|
|
29
|
+
echo "Org portal: $ORG_CODE"
|
|
30
|
+
|
|
31
|
+
if [ "$ORG_CODE" = "200" ]; then
|
|
32
|
+
URL_STATUS="ok"
|
|
33
|
+
else
|
|
34
|
+
URL_STATUS="unreachable ($ORG_CODE)"
|
|
35
|
+
fi
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If the URL is unreachable, warn the user but continue with remaining checks. DNS propagation or cold starts can cause brief unavailability.
|
|
39
|
+
|
|
40
|
+
### Step 2: SSL Verification (cloud only)
|
|
41
|
+
|
|
42
|
+
For cloud deploys, verify the SSL certificate is valid and HTTPS redirect works.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
if [ "$DEPLOY_MODE" = "cloud" ] && [ -n "$CLOUD_ORG_SLUG" ]; then
|
|
46
|
+
HTTPS_URL="https://${CLOUD_ORG_SLUG}.showpane.com"
|
|
47
|
+
echo "Checking SSL for $HTTPS_URL..."
|
|
48
|
+
|
|
49
|
+
# Check certificate validity and expiry
|
|
50
|
+
SSL_INFO=$(echo | openssl s_client -servername "${CLOUD_ORG_SLUG}.showpane.com" \
|
|
51
|
+
-connect "${CLOUD_ORG_SLUG}.showpane.com:443" 2>/dev/null \
|
|
52
|
+
| openssl x509 -noout -dates 2>/dev/null)
|
|
53
|
+
|
|
54
|
+
if [ -n "$SSL_INFO" ]; then
|
|
55
|
+
SSL_EXPIRY=$(echo "$SSL_INFO" | grep 'notAfter' | cut -d= -f2)
|
|
56
|
+
echo "SSL valid, expires: $SSL_EXPIRY"
|
|
57
|
+
SSL_STATUS="valid, expires $SSL_EXPIRY"
|
|
58
|
+
else
|
|
59
|
+
echo "SSL certificate not found or invalid"
|
|
60
|
+
SSL_STATUS="not found"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Check HTTPS redirect from HTTP
|
|
64
|
+
HTTP_URL="http://${CLOUD_ORG_SLUG}.showpane.com"
|
|
65
|
+
REDIRECT_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$HTTP_URL" 2>/dev/null)
|
|
66
|
+
if [ "$REDIRECT_CODE" = "301" ] || [ "$REDIRECT_CODE" = "308" ]; then
|
|
67
|
+
echo "HTTP->HTTPS redirect: OK ($REDIRECT_CODE)"
|
|
68
|
+
else
|
|
69
|
+
echo "HTTP->HTTPS redirect: $REDIRECT_CODE (expected 301 or 308)"
|
|
70
|
+
fi
|
|
71
|
+
else
|
|
72
|
+
SSL_STATUS="n/a (no cloud org configured)"
|
|
73
|
+
fi
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Step 3: Portal Login Pages
|
|
77
|
+
|
|
78
|
+
List all active portals from the database and verify each login page loads.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd "$APP_PATH" && PORTAL_LIST=$(npx tsx -e "
|
|
82
|
+
const { prisma } = require('./src/lib/db');
|
|
83
|
+
prisma.clientPortal.findMany({ where: { isActive: true }, select: { slug: true, clientName: true } })
|
|
84
|
+
.then(portals => console.log(JSON.stringify(portals)))
|
|
85
|
+
.finally(() => prisma.\$disconnect());
|
|
86
|
+
" 2>/dev/null)
|
|
87
|
+
|
|
88
|
+
echo "Active portals: $PORTAL_LIST"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For each portal, verify the login page returns a response and contains auth-related content:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
PORTAL_URL="${CLOUD_PORTAL_URL:-https://$CLOUD_ORG_SLUG.showpane.com}"
|
|
95
|
+
echo "$PORTAL_LIST" | python3 -c "
|
|
96
|
+
import sys, json
|
|
97
|
+
portals = json.load(sys.stdin)
|
|
98
|
+
for p in portals:
|
|
99
|
+
slug = p['slug']
|
|
100
|
+
name = p.get('clientName', slug)
|
|
101
|
+
print(f' {name} ({slug})')
|
|
102
|
+
print(f'{len(portals)} active portals')
|
|
103
|
+
" 2>/dev/null
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then for each portal slug, check the login page:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
for SLUG in $(echo "$PORTAL_LIST" | python3 -c "
|
|
110
|
+
import sys, json
|
|
111
|
+
for p in json.load(sys.stdin): print(p['slug'])
|
|
112
|
+
" 2>/dev/null); do
|
|
113
|
+
PAGE_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$PORTAL_URL/client/$SLUG" 2>/dev/null)
|
|
114
|
+
PAGE_BODY=$(curl -s "$PORTAL_URL/client/$SLUG" 2>/dev/null | head -c 5000)
|
|
115
|
+
HAS_AUTH=$(echo "$PAGE_BODY" | grep -ci 'password\|login\|sign.in\|auth' 2>/dev/null || echo "0")
|
|
116
|
+
if [ "$PAGE_CODE" = "200" ] && [ "$HAS_AUTH" -gt 0 ]; then
|
|
117
|
+
echo " $SLUG: Login page OK"
|
|
118
|
+
elif [ "$PAGE_CODE" = "200" ]; then
|
|
119
|
+
echo " $SLUG: Page loads ($PAGE_CODE) but no auth content detected"
|
|
120
|
+
else
|
|
121
|
+
echo " $SLUG: FAILED ($PAGE_CODE)"
|
|
122
|
+
fi
|
|
123
|
+
done
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Step 4: Engagement Tracking
|
|
127
|
+
|
|
128
|
+
Verify the client events API endpoint responds.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
PORTAL_URL="${CLOUD_PORTAL_URL:-http://localhost:3000}"
|
|
132
|
+
EVENTS_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X OPTIONS "$PORTAL_URL/api/client-events" 2>/dev/null)
|
|
133
|
+
echo "Events endpoint: $EVENTS_CODE"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
For cloud deploys, also verify the cloud events URL is reachable:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
if [ "$DEPLOY_MODE" = "cloud" ] && [ -n "$CLOUD_EVENTS_URL" ]; then
|
|
140
|
+
CLOUD_EVENTS_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X OPTIONS "$CLOUD_EVENTS_URL/api/client-events" 2>/dev/null)
|
|
141
|
+
echo "Cloud events endpoint: $CLOUD_EVENTS_CODE"
|
|
142
|
+
fi
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The events endpoint should return 200 or 204 for OPTIONS requests. A 404 means the route is not deployed. A 405 (Method Not Allowed) is also acceptable — it means the route exists but only accepts POST.
|
|
146
|
+
|
|
147
|
+
### Step 5: File Downloads
|
|
148
|
+
|
|
149
|
+
Check if any PortalFile records exist and verify file download endpoints work.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
cd "$APP_PATH" && FILE_INFO=$(npx tsx -e "
|
|
153
|
+
const { prisma } = require('./src/lib/db');
|
|
154
|
+
prisma.portalFile.findMany({ select: { id: true, filename: true, portalId: true } })
|
|
155
|
+
.then(files => console.log(JSON.stringify({ count: files.length, files: files.slice(0, 5) })))
|
|
156
|
+
.catch(() => console.log(JSON.stringify({ count: 0, files: [] })))
|
|
157
|
+
.finally(() => prisma.\$disconnect());
|
|
158
|
+
" 2>/dev/null)
|
|
159
|
+
|
|
160
|
+
FILE_COUNT=$(echo "$FILE_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin).get('count',0))" 2>/dev/null)
|
|
161
|
+
echo "Hosted files: $FILE_COUNT"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
If files exist, verify a sample file download endpoint responds:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
if [ "$FILE_COUNT" -gt 0 ]; then
|
|
168
|
+
SAMPLE_FILE_ID=$(echo "$FILE_INFO" | python3 -c "
|
|
169
|
+
import sys, json
|
|
170
|
+
files = json.load(sys.stdin).get('files', [])
|
|
171
|
+
if files: print(files[0]['id'])
|
|
172
|
+
" 2>/dev/null)
|
|
173
|
+
if [ -n "$SAMPLE_FILE_ID" ]; then
|
|
174
|
+
PORTAL_URL="${CLOUD_PORTAL_URL:-http://localhost:3000}"
|
|
175
|
+
DL_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$PORTAL_URL/api/files/$SAMPLE_FILE_ID" 2>/dev/null)
|
|
176
|
+
echo "File download endpoint: $DL_CODE"
|
|
177
|
+
if [ "$DL_CODE" = "200" ] || [ "$DL_CODE" = "302" ]; then
|
|
178
|
+
FILE_STATUS="accessible"
|
|
179
|
+
else
|
|
180
|
+
FILE_STATUS="endpoint returned $DL_CODE"
|
|
181
|
+
fi
|
|
182
|
+
fi
|
|
183
|
+
else
|
|
184
|
+
FILE_STATUS="none hosted"
|
|
185
|
+
fi
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Step 6: Report
|
|
189
|
+
|
|
190
|
+
Compile all check results into a health report. Print it in this format:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
Portal Health Report
|
|
194
|
+
====================
|
|
195
|
+
URL: https://orgslug.showpane.com [ok/unreachable]
|
|
196
|
+
SSL: Valid, expires 2027-01-15 [ok/not found/n/a]
|
|
197
|
+
Portals: 3 active
|
|
198
|
+
acme: Login page [ok/failed], Events [ok/failed]
|
|
199
|
+
betacorp: Login page [ok/failed], Events [ok/failed]
|
|
200
|
+
demo: Login page [ok/failed], Events [ok/failed]
|
|
201
|
+
Files: 5 hosted, all accessible [ok/issues]
|
|
202
|
+
|
|
203
|
+
Overall: HEALTHY / DEGRADED / UNHEALTHY
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Rules for the overall status:
|
|
207
|
+
- **HEALTHY**: All checks pass (URL reachable, SSL valid for cloud, all portals load, events endpoint responds)
|
|
208
|
+
- **DEGRADED**: URL reachable but some portals fail, or SSL is pending, or events endpoint is down
|
|
209
|
+
- **UNHEALTHY**: URL is unreachable, or no portals load
|
|
210
|
+
|
|
211
|
+
After the report, suggest next steps:
|
|
212
|
+
- If UNHEALTHY: "Run /portal-deploy to redeploy, or /investigate to debug."
|
|
213
|
+
- If DEGRADED: "Check individual portal issues above. Run /portal-status for ongoing monitoring."
|
|
214
|
+
- If HEALTHY: "All systems operational. Run /portal-status for ongoing monitoring."
|
|
215
|
+
|
|
216
|
+
## Conventions
|
|
217
|
+
|
|
218
|
+
- This skill is read-only — it never modifies the deployment or database
|
|
219
|
+
- All checks use curl with short timeouts to avoid hanging on unreachable endpoints
|
|
220
|
+
- Cloud checks verify both the control plane (app.showpane.com) and the org portal (orgslug.showpane.com)
|
|
221
|
+
- The PortalFile model may not exist in all schema versions — catch errors gracefully
|
|
222
|
+
- If the database is unreachable, skip DB-dependent checks (Steps 3, 5) and note it in the report
|
|
223
|
+
- SSL checks only apply when a cloud portal URL is configured
|
|
224
|
+
- The events endpoint check uses OPTIONS to avoid creating spurious event records
|