mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-18 18:32:28 +08:00
fix: make telemetry binary calls conditional on _TEL and binary existence
Addresses Socket's 14 MEDIUM findings for opaque telemetry binary. Adds local JSONL fallback (always available, inspectable). Remote binary only runs if _TEL != "off" and binary exists.
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
import type { TemplateContext } from './types';
|
import type { TemplateContext } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preamble architecture — why every skill needs this
|
||||||
|
*
|
||||||
|
* Each skill runs independently via `claude -p`. There is no shared loader.
|
||||||
|
* The preamble provides: update checks, session tracking, user preferences,
|
||||||
|
* repo mode detection, and telemetry.
|
||||||
|
*
|
||||||
|
* Telemetry data flow:
|
||||||
|
* 1. Always: local JSONL append to ~/.gstack/analytics/ (inline, inspectable)
|
||||||
|
* 2. If _TEL != "off" AND binary exists: gstack-telemetry-log for remote reporting
|
||||||
|
*/
|
||||||
|
|
||||||
function generatePreambleBash(ctx: TemplateContext): string {
|
function generatePreambleBash(ctx: TemplateContext): string {
|
||||||
const runtimeRoot = ctx.host === 'codex'
|
const runtimeRoot = ctx.host === 'codex'
|
||||||
? `_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
? `_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||||
@@ -40,7 +52,15 @@ echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
|||||||
mkdir -p ~/.gstack/analytics
|
mkdir -p ~/.gstack/analytics
|
||||||
echo '{"skill":"${ctx.skillName}","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
|
echo '{"skill":"${ctx.skillName}","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
|
||||||
# zsh-compatible: use find instead of glob to avoid NOMATCH error
|
# zsh-compatible: use find instead of glob to avoid NOMATCH error
|
||||||
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do [ -f "$_PF" ] && ${ctx.paths.binDir}/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true; break; done
|
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do
|
||||||
|
if [ -f "$_PF" ]; then
|
||||||
|
if [ "$_TEL" != "off" ] && [ -x "${ctx.paths.binDir}/gstack-telemetry-log" ]; then
|
||||||
|
${ctx.paths.binDir}/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -f "$_PF" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
done
|
||||||
\`\`\``;
|
\`\`\``;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,15 +369,20 @@ Run this bash:
|
|||||||
_TEL_END=$(date +%s)
|
_TEL_END=$(date +%s)
|
||||||
_TEL_DUR=$(( _TEL_END - _TEL_START ))
|
_TEL_DUR=$(( _TEL_END - _TEL_START ))
|
||||||
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
|
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
|
||||||
~/.claude/skills/gstack/bin/gstack-telemetry-log \\
|
# Local analytics (always available, no binary needed)
|
||||||
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \\
|
echo '{"skill":"SKILL_NAME","duration_s":"'"$_TEL_DUR"'","outcome":"OUTCOME","browse":"USED_BROWSE","session":"'"$_SESSION_ID"'","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
|
||||||
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &
|
# Remote telemetry (opt-in, requires binary)
|
||||||
|
if [ "$_TEL" != "off" ] && [ -x ~/.claude/skills/gstack/bin/gstack-telemetry-log ]; then
|
||||||
|
~/.claude/skills/gstack/bin/gstack-telemetry-log \\
|
||||||
|
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \\
|
||||||
|
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &
|
||||||
|
fi
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
Replace \`SKILL_NAME\` with the actual skill name from frontmatter, \`OUTCOME\` with
|
Replace \`SKILL_NAME\` with the actual skill name from frontmatter, \`OUTCOME\` with
|
||||||
success/error/abort, and \`USED_BROWSE\` with true/false based on whether \`$B\` was used.
|
success/error/abort, and \`USED_BROWSE\` with true/false based on whether \`$B\` was used.
|
||||||
If you cannot determine the outcome, use "unknown". This runs in the background and
|
If you cannot determine the outcome, use "unknown". The local JSONL always logs. The
|
||||||
never blocks the user.
|
remote binary only runs if telemetry is not off and the binary exists.
|
||||||
|
|
||||||
## Plan Status Footer
|
## Plan Status Footer
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user