mirror of https://github.com/garrytan/gstack.git
Merge d2610d6550 into a3259400a3
This commit is contained in:
commit
4331ae6d96
3
SKILL.md
3
SKILL.md
|
|
@ -68,10 +68,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -78,10 +78,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ SKILLS_DIR="${GSTACK_SKILLS_DIR:-$(dirname "$INSTALL_DIR")}"
|
|||
|
||||
# Read prefix setting
|
||||
PREFIX=$("$GSTACK_CONFIG" get skill_prefix 2>/dev/null || echo "false")
|
||||
GSTACK_HIDDEN_SKILLS_FILE="${GSTACK_HIDDEN_SKILLS_FILE:-$HOME/.gstack/hidden-skills}"
|
||||
|
||||
# Helper: remove old skill entry (symlink or real directory with symlinked SKILL.md)
|
||||
_cleanup_skill_entry() {
|
||||
|
|
@ -46,6 +47,17 @@ _cleanup_skill_entry() {
|
|||
fi
|
||||
}
|
||||
|
||||
_skill_hidden() {
|
||||
local source_name="$1" projected_name="$2"
|
||||
[ -f "$GSTACK_HIDDEN_SKILLS_FILE" ] || return 1
|
||||
grep -Fqx "$source_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null && return 0
|
||||
case "$source_name" in
|
||||
gstack-*) ;;
|
||||
*) grep -Fqx "gstack-$source_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null && return 0 ;;
|
||||
esac
|
||||
grep -Fqx "$projected_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null
|
||||
}
|
||||
|
||||
_link_root_skill_alias() {
|
||||
local target="$SKILLS_DIR/_gstack-command"
|
||||
|
||||
|
|
@ -82,6 +94,12 @@ for skill_dir in "$INSTALL_DIR"/*/; do
|
|||
*) _cleanup_skill_entry "$SKILLS_DIR/gstack-$skill" ;;
|
||||
esac
|
||||
fi
|
||||
if _skill_hidden "$skill" "$link_name"; then
|
||||
_cleanup_skill_entry "$SKILLS_DIR/$skill"
|
||||
_cleanup_skill_entry "$SKILLS_DIR/gstack-$skill"
|
||||
_cleanup_skill_entry "$SKILLS_DIR/$link_name"
|
||||
continue
|
||||
fi
|
||||
target="$SKILLS_DIR/$link_name"
|
||||
# Upgrade old directory symlinks to real directories
|
||||
[ -L "$target" ] && rm -f "$target"
|
||||
|
|
|
|||
|
|
@ -70,10 +70,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -70,10 +70,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
name: context-restore
|
||||
preamble-tier: 2
|
||||
version: 1.0.0
|
||||
description: Restore working context saved earlier by /context-save. (gstack)
|
||||
description: Restore working context saved earlier by /save or legacy /context-save. (gstack)
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
|
|
@ -26,7 +26,7 @@ Loads the most recent
|
|||
saved state (across all branches by default) so you can pick up where you
|
||||
left off — even across Conductor workspace handoffs.
|
||||
Use when asked to "resume", "restore context", "where was I", or
|
||||
"pick up where I left off". Pair with /context-save.
|
||||
"pick up where I left off". Pair with /save.
|
||||
Formerly /checkpoint resume — renamed because Claude Code treats /checkpoint
|
||||
as a native rewind alias in current environments.
|
||||
|
||||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
@ -807,8 +808,8 @@ Parse the user's input:
|
|||
|
||||
- `/context-restore` → load the most recent saved context (any branch)
|
||||
- `/context-restore <title-fragment-or-number>` → load a specific saved context
|
||||
- `/context-restore list` → tell the user "Use `/context-save list` — listing
|
||||
lives on the save side" and exit. No mode detection here.
|
||||
- `/context-restore list` → display the same cross-branch candidate list from
|
||||
Step 1 and exit without loading a file.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -852,23 +853,60 @@ enables Conductor workspace handoff.
|
|||
|
||||
Read the chosen file and present a summary:
|
||||
|
||||
Then inspect the sibling Universal Save receipt without writing anything:
|
||||
|
||||
```bash
|
||||
# Set CHOSEN_FILE to the exact checkpoint selected above.
|
||||
RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json"
|
||||
if [ -f "$RECEIPT_FILE" ]; then
|
||||
echo "RECEIPT_FILE=$RECEIPT_FILE"
|
||||
else
|
||||
echo "LEGACY_CHECKPOINT_NO_RECEIPT"
|
||||
fi
|
||||
```
|
||||
RESUMING CONTEXT
|
||||
|
||||
If `RECEIPT_FILE` exists, read it and include:
|
||||
|
||||
- `receipt_schema_version` (`missing` means supported legacy v0; versions above
|
||||
`1` are unsupported and must produce a warning rather than a green claim);
|
||||
- `verification.layers` statuses for working checkpoint, Codex Brain, Obsidian
|
||||
bridge and QMD;
|
||||
- exact `receipt_path` and `restore.command`;
|
||||
- the first item under `### Что осталось` / `### Remaining Work` as the next
|
||||
action.
|
||||
|
||||
If any layer is absent or not `ok`, start the result with
|
||||
`ВОССТАНОВЛЕНИЕ С ПРЕДУПРЕЖДЕНИЕМ` and name the exact layer. Do not run save,
|
||||
resume, QMD update/embed or any write from this read-only skill. A legacy
|
||||
checkpoint without a receipt remains restorable, but label its four-layer status
|
||||
as `не подтверждён`.
|
||||
|
||||
Present the human-facing result in Russian:
|
||||
|
||||
```
|
||||
ВОССТАНОВЛЕНИЕ КОНТЕКСТА
|
||||
════════════════════════════════════════
|
||||
Title: {title}
|
||||
Branch: {branch from frontmatter}
|
||||
Saved: {timestamp, human-readable}
|
||||
Duration: Last session was {formatted duration} (if available)
|
||||
Status: {status}
|
||||
Название: {title}
|
||||
Ветка: {branch from frontmatter}
|
||||
Сохранено: {timestamp, human-readable}
|
||||
Длительность:{formatted duration, if available}
|
||||
Статус: {status}
|
||||
Квитанция: {receipt path or legacy}
|
||||
════════════════════════════════════════
|
||||
|
||||
### Summary
|
||||
### Кратко
|
||||
{summary from saved file}
|
||||
|
||||
### Remaining Work
|
||||
### Состояние четырёх слоёв
|
||||
Checkpoint: {status}
|
||||
Codex Brain: {status}
|
||||
Obsidian: {status}
|
||||
QMD: {status}
|
||||
|
||||
### Что осталось
|
||||
{remaining work items}
|
||||
|
||||
### Notes
|
||||
### Примечания
|
||||
{notes}
|
||||
```
|
||||
|
||||
|
|
@ -892,14 +930,16 @@ If A, summarize the first remaining work item and suggest starting there.
|
|||
|
||||
If Step 1 printed `NO_CHECKPOINTS`, tell the user:
|
||||
|
||||
"No saved contexts yet. Run `/context-save` first to save your current working
|
||||
state, then `/context-restore` will find it."
|
||||
"Сохранённых контекстов пока нет. Запустите `/save`, затем
|
||||
`/context-restore` найдёт сохранение."
|
||||
|
||||
---
|
||||
|
||||
## Important Rules
|
||||
|
||||
- **Never modify code.** This skill only reads saved files and presents them.
|
||||
- **Never mutate a receipt.** Receipt inspection and four-layer verification
|
||||
display are read-only; repair belongs to `/save` resume flow.
|
||||
- **Always search across all branches by default.** Cross-branch resume is the
|
||||
whole point. Only filter by branch if the user explicitly asks via a
|
||||
title-fragment match that happens to be branch-specific.
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ name: context-restore
|
|||
preamble-tier: 2
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Restore working context saved earlier by /context-save. Loads the most recent
|
||||
Restore working context saved earlier by /save or legacy /context-save. Loads the most recent
|
||||
saved state (across all branches by default) so you can pick up where you
|
||||
left off — even across Conductor workspace handoffs.
|
||||
Use when asked to "resume", "restore context", "where was I", or
|
||||
"pick up where I left off". Pair with /context-save.
|
||||
"pick up where I left off". Pair with /save.
|
||||
Formerly /checkpoint resume — renamed because Claude Code treats /checkpoint
|
||||
as a native rewind alias in current environments. (gstack)
|
||||
allowed-tools:
|
||||
|
|
@ -51,8 +51,8 @@ Parse the user's input:
|
|||
|
||||
- `/context-restore` → load the most recent saved context (any branch)
|
||||
- `/context-restore <title-fragment-or-number>` → load a specific saved context
|
||||
- `/context-restore list` → tell the user "Use `/context-save list` — listing
|
||||
lives on the save side" and exit. No mode detection here.
|
||||
- `/context-restore list` → display the same cross-branch candidate list from
|
||||
Step 1 and exit without loading a file.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -96,23 +96,60 @@ enables Conductor workspace handoff.
|
|||
|
||||
Read the chosen file and present a summary:
|
||||
|
||||
Then inspect the sibling Universal Save receipt without writing anything:
|
||||
|
||||
```bash
|
||||
# Set CHOSEN_FILE to the exact checkpoint selected above.
|
||||
RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json"
|
||||
if [ -f "$RECEIPT_FILE" ]; then
|
||||
echo "RECEIPT_FILE=$RECEIPT_FILE"
|
||||
else
|
||||
echo "LEGACY_CHECKPOINT_NO_RECEIPT"
|
||||
fi
|
||||
```
|
||||
RESUMING CONTEXT
|
||||
|
||||
If `RECEIPT_FILE` exists, read it and include:
|
||||
|
||||
- `receipt_schema_version` (`missing` means supported legacy v0; versions above
|
||||
`1` are unsupported and must produce a warning rather than a green claim);
|
||||
- `verification.layers` statuses for working checkpoint, Codex Brain, Obsidian
|
||||
bridge and QMD;
|
||||
- exact `receipt_path` and `restore.command`;
|
||||
- the first item under `### Что осталось` / `### Remaining Work` as the next
|
||||
action.
|
||||
|
||||
If any layer is absent or not `ok`, start the result with
|
||||
`ВОССТАНОВЛЕНИЕ С ПРЕДУПРЕЖДЕНИЕМ` and name the exact layer. Do not run save,
|
||||
resume, QMD update/embed or any write from this read-only skill. A legacy
|
||||
checkpoint without a receipt remains restorable, but label its four-layer status
|
||||
as `не подтверждён`.
|
||||
|
||||
Present the human-facing result in Russian:
|
||||
|
||||
```
|
||||
ВОССТАНОВЛЕНИЕ КОНТЕКСТА
|
||||
════════════════════════════════════════
|
||||
Title: {title}
|
||||
Branch: {branch from frontmatter}
|
||||
Saved: {timestamp, human-readable}
|
||||
Duration: Last session was {formatted duration} (if available)
|
||||
Status: {status}
|
||||
Название: {title}
|
||||
Ветка: {branch from frontmatter}
|
||||
Сохранено: {timestamp, human-readable}
|
||||
Длительность:{formatted duration, if available}
|
||||
Статус: {status}
|
||||
Квитанция: {receipt path or legacy}
|
||||
════════════════════════════════════════
|
||||
|
||||
### Summary
|
||||
### Кратко
|
||||
{summary from saved file}
|
||||
|
||||
### Remaining Work
|
||||
### Состояние четырёх слоёв
|
||||
Checkpoint: {status}
|
||||
Codex Brain: {status}
|
||||
Obsidian: {status}
|
||||
QMD: {status}
|
||||
|
||||
### Что осталось
|
||||
{remaining work items}
|
||||
|
||||
### Notes
|
||||
### Примечания
|
||||
{notes}
|
||||
```
|
||||
|
||||
|
|
@ -136,14 +173,16 @@ If A, summarize the first remaining work item and suggest starting there.
|
|||
|
||||
If Step 1 printed `NO_CHECKPOINTS`, tell the user:
|
||||
|
||||
"No saved contexts yet. Run `/context-save` first to save your current working
|
||||
state, then `/context-restore` will find it."
|
||||
"Сохранённых контекстов пока нет. Запустите `/save`, затем
|
||||
`/context-restore` найдёт сохранение."
|
||||
|
||||
---
|
||||
|
||||
## Important Rules
|
||||
|
||||
- **Never modify code.** This skill only reads saved files and presents them.
|
||||
- **Never mutate a receipt.** Receipt inspection and four-layer verification
|
||||
display are read-only; repair belongs to `/save` resume flow.
|
||||
- **Always search across all branches by default.** Cross-branch resume is the
|
||||
whole point. Only filter by branch if the user explicitly asks via a
|
||||
title-fragment match that happens to be branch-specific.
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
@ -790,6 +791,14 @@ can resume without losing a beat via `/context-restore`.
|
|||
|
||||
**HARD GATE:** Do NOT implement code changes. This skill captures state only.
|
||||
|
||||
**EVGENIY LANGUAGE CONTRACT:** When the primary reader is Evgeniy, write the
|
||||
entire human-facing checkpoint and confirmation in Russian: title, headings,
|
||||
summary, decisions, risks, verification results, remaining work, notes, table
|
||||
labels, and next steps. Keep English only for exact commands, paths, filenames,
|
||||
code/API/schema fields, model/tool names, identifiers, immutable status literals,
|
||||
and source quotes. Frontmatter keys remain machine-readable. Before confirming a
|
||||
save, scan the checkpoint for leftover English prose and translate it.
|
||||
|
||||
---
|
||||
|
||||
## Detect command
|
||||
|
|
@ -915,23 +924,23 @@ files_modified:
|
|||
- path/to/file2
|
||||
---
|
||||
|
||||
## Working on: {title}
|
||||
## Текущая работа: {title}
|
||||
|
||||
### Summary
|
||||
### Кратко
|
||||
|
||||
{1-3 sentences describing the high-level goal and current progress}
|
||||
{1-3 предложения с описанием общей цели и текущего прогресса}
|
||||
|
||||
### Decisions Made
|
||||
### Принятые решения
|
||||
|
||||
{Bulleted list of architectural choices, trade-offs, and reasoning}
|
||||
{Маркированный список архитектурных решений, компромиссов и причин}
|
||||
|
||||
### Remaining Work
|
||||
### Что осталось
|
||||
|
||||
{Numbered list of concrete next steps, in priority order}
|
||||
{Нумерованный список конкретных следующих шагов в порядке приоритета}
|
||||
|
||||
### Notes
|
||||
### Примечания
|
||||
|
||||
{Gotchas, blocked items, open questions, things tried that didn't work}
|
||||
{Подводные камни, блокеры, открытые вопросы и неудачные попытки}
|
||||
```
|
||||
|
||||
The `files_modified` list comes from `git status --short` (both staged and unstaged
|
||||
|
|
@ -940,16 +949,16 @@ modified files). Use relative paths from the repo root.
|
|||
After writing, confirm to the user:
|
||||
|
||||
```
|
||||
CONTEXT SAVED
|
||||
КОНТЕКСТ СОХРАНЁН
|
||||
════════════════════════════════════════
|
||||
Title: {title}
|
||||
Branch: {branch}
|
||||
File: {path to saved file}
|
||||
Modified: {N} files
|
||||
Duration: {duration or "unknown"}
|
||||
Название: {title}
|
||||
Ветка: {branch}
|
||||
Файл: {path to saved file}
|
||||
Изменено: {N} файлов
|
||||
Длительность: {duration или "неизвестно"}
|
||||
════════════════════════════════════════
|
||||
|
||||
Restore later with /context-restore.
|
||||
Позже восстановите контекст командой /context-restore.
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -986,9 +995,9 @@ Read the frontmatter of each file to extract `status`, `branch`, and
|
|||
Present as a table:
|
||||
|
||||
```
|
||||
SAVED CONTEXTS ({branch} branch)
|
||||
СОХРАНЁННЫЕ КОНТЕКСТЫ (ветка {branch})
|
||||
════════════════════════════════════════
|
||||
# Date Title Status
|
||||
# Дата Название Статус
|
||||
─ ────────── ─────────────────────── ───────────
|
||||
1 2026-04-18 auth-refactor in-progress
|
||||
2 2026-04-17 api-pagination completed
|
||||
|
|
@ -999,9 +1008,9 @@ SAVED CONTEXTS ({branch} branch)
|
|||
If `--all` is used, add a Branch column:
|
||||
|
||||
```
|
||||
SAVED CONTEXTS (all branches)
|
||||
СОХРАНЁННЫЕ КОНТЕКСТЫ (все ветки)
|
||||
════════════════════════════════════════
|
||||
# Date Title Branch Status
|
||||
# Дата Название Ветка Статус
|
||||
─ ────────── ─────────────────────── ────────────────── ───────────
|
||||
1 2026-04-18 auth-refactor feat/auth in-progress
|
||||
2 2026-04-17 api-pagination main completed
|
||||
|
|
@ -1009,8 +1018,8 @@ SAVED CONTEXTS (all branches)
|
|||
════════════════════════════════════════
|
||||
```
|
||||
|
||||
If there are no saved contexts, tell the user: "No saved contexts yet. Run
|
||||
`/context-save` to save your current working state."
|
||||
If there are no saved contexts, tell Evgeniy: "Сохранённых контекстов пока нет.
|
||||
Запустите `/context-save`, чтобы сохранить текущее рабочее состояние."
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,14 @@ can resume without losing a beat via `/context-restore`.
|
|||
|
||||
**HARD GATE:** Do NOT implement code changes. This skill captures state only.
|
||||
|
||||
**EVGENIY LANGUAGE CONTRACT:** When the primary reader is Evgeniy, write the
|
||||
entire human-facing checkpoint and confirmation in Russian: title, headings,
|
||||
summary, decisions, risks, verification results, remaining work, notes, table
|
||||
labels, and next steps. Keep English only for exact commands, paths, filenames,
|
||||
code/API/schema fields, model/tool names, identifiers, immutable status literals,
|
||||
and source quotes. Frontmatter keys remain machine-readable. Before confirming a
|
||||
save, scan the checkpoint for leftover English prose and translate it.
|
||||
|
||||
---
|
||||
|
||||
## Detect command
|
||||
|
|
@ -160,23 +168,23 @@ files_modified:
|
|||
- path/to/file2
|
||||
---
|
||||
|
||||
## Working on: {title}
|
||||
## Текущая работа: {title}
|
||||
|
||||
### Summary
|
||||
### Кратко
|
||||
|
||||
{1-3 sentences describing the high-level goal and current progress}
|
||||
{1-3 предложения с описанием общей цели и текущего прогресса}
|
||||
|
||||
### Decisions Made
|
||||
### Принятые решения
|
||||
|
||||
{Bulleted list of architectural choices, trade-offs, and reasoning}
|
||||
{Маркированный список архитектурных решений, компромиссов и причин}
|
||||
|
||||
### Remaining Work
|
||||
### Что осталось
|
||||
|
||||
{Numbered list of concrete next steps, in priority order}
|
||||
{Нумерованный список конкретных следующих шагов в порядке приоритета}
|
||||
|
||||
### Notes
|
||||
### Примечания
|
||||
|
||||
{Gotchas, blocked items, open questions, things tried that didn't work}
|
||||
{Подводные камни, блокеры, открытые вопросы и неудачные попытки}
|
||||
```
|
||||
|
||||
The `files_modified` list comes from `git status --short` (both staged and unstaged
|
||||
|
|
@ -185,16 +193,16 @@ modified files). Use relative paths from the repo root.
|
|||
After writing, confirm to the user:
|
||||
|
||||
```
|
||||
CONTEXT SAVED
|
||||
КОНТЕКСТ СОХРАНЁН
|
||||
════════════════════════════════════════
|
||||
Title: {title}
|
||||
Branch: {branch}
|
||||
File: {path to saved file}
|
||||
Modified: {N} files
|
||||
Duration: {duration or "unknown"}
|
||||
Название: {title}
|
||||
Ветка: {branch}
|
||||
Файл: {path to saved file}
|
||||
Изменено: {N} файлов
|
||||
Длительность: {duration или "неизвестно"}
|
||||
════════════════════════════════════════
|
||||
|
||||
Restore later with /context-restore.
|
||||
Позже восстановите контекст командой /context-restore.
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -231,9 +239,9 @@ Read the frontmatter of each file to extract `status`, `branch`, and
|
|||
Present as a table:
|
||||
|
||||
```
|
||||
SAVED CONTEXTS ({branch} branch)
|
||||
СОХРАНЁННЫЕ КОНТЕКСТЫ (ветка {branch})
|
||||
════════════════════════════════════════
|
||||
# Date Title Status
|
||||
# Дата Название Статус
|
||||
─ ────────── ─────────────────────── ───────────
|
||||
1 2026-04-18 auth-refactor in-progress
|
||||
2 2026-04-17 api-pagination completed
|
||||
|
|
@ -244,9 +252,9 @@ SAVED CONTEXTS ({branch} branch)
|
|||
If `--all` is used, add a Branch column:
|
||||
|
||||
```
|
||||
SAVED CONTEXTS (all branches)
|
||||
СОХРАНЁННЫЕ КОНТЕКСТЫ (все ветки)
|
||||
════════════════════════════════════════
|
||||
# Date Title Branch Status
|
||||
# Дата Название Ветка Статус
|
||||
─ ────────── ─────────────────────── ────────────────── ───────────
|
||||
1 2026-04-18 auth-refactor feat/auth in-progress
|
||||
2 2026-04-17 api-pagination main completed
|
||||
|
|
@ -254,8 +262,8 @@ SAVED CONTEXTS (all branches)
|
|||
════════════════════════════════════════
|
||||
```
|
||||
|
||||
If there are no saved contexts, tell the user: "No saved contexts yet. Run
|
||||
`/context-save` to save your current working state."
|
||||
If there are no saved contexts, tell Evgeniy: "Сохранённых контекстов пока нет.
|
||||
Запустите `/context-save`, чтобы сохранить текущее рабочее состояние."
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -76,10 +76,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -96,10 +96,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -77,10 +77,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -91,10 +91,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -76,10 +76,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -76,10 +76,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -28,6 +28,22 @@ Voice triggers (speech-to-text aliases): "upgrade the tools", "update the tools"
|
|||
|
||||
Upgrade gstack to the latest version and show what's new.
|
||||
|
||||
## Operating boundaries
|
||||
|
||||
PRIORITY 1: preserve user work, credentials and current project state.
|
||||
PRIORITY 2: upgrade only the detected gstack install and its documented
|
||||
gstack state files.
|
||||
PRIORITY 3: summarize the result and continue the original task.
|
||||
|
||||
Each user message is an independent task. Do not carry repository state,
|
||||
upgrade results or user preferences between unrelated tasks unless the user
|
||||
explicitly asks.
|
||||
|
||||
Persistence scope: this skill may write only gstack update state such as
|
||||
`auto_upgrade`, `update_check`, `~/.gstack/update-snoozed`,
|
||||
`~/.gstack/just-upgraded-from` and `~/.gstack/last-update-check`. Do not persist
|
||||
unrelated conversation memory, project decisions, credentials or tool results.
|
||||
|
||||
## Inline upgrade flow
|
||||
|
||||
This section is referenced by all skill preambles when they detect `UPGRADE_AVAILABLE`.
|
||||
|
|
@ -46,17 +62,17 @@ echo "AUTO_UPGRADE=$_AUTO"
|
|||
|
||||
**Otherwise**, use AskUserQuestion:
|
||||
- Question: "gstack **v{new}** is available (you're on v{old}). Upgrade now?"
|
||||
- Options: ["Yes, upgrade now", "Always keep me up to date", "Not now", "Never ask again"]
|
||||
- Options: ["Yes, upgrade now", "Enable gstack auto-upgrade", "Snooze this gstack version", "Disable gstack update checks"]
|
||||
|
||||
**If "Yes, upgrade now":** Proceed to Step 2.
|
||||
|
||||
**If "Always keep me up to date":**
|
||||
**If "Enable gstack auto-upgrade":**
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set auto_upgrade true
|
||||
```
|
||||
Tell user: "Auto-upgrade enabled. Future updates will install automatically." Then proceed to Step 2.
|
||||
Tell user: "Gstack auto-upgrade enabled for this install. Future gstack updates will install automatically." Then proceed to Step 2.
|
||||
|
||||
**If "Not now":** Write snooze state with escalating backoff (first snooze = 24h, second = 48h, third+ = 1 week), then continue with the current skill. Do not mention the upgrade again.
|
||||
**If "Snooze this gstack version":** Write snooze state for this gstack version with escalating backoff (first snooze = 24h, second = 48h, third+ = 1 week), then continue with the current skill. Do not mention this gstack version again until the snooze expires.
|
||||
```bash
|
||||
_SNOOZE_FILE="$HOME/.gstack/update-snoozed"
|
||||
_REMOTE_VER="{new}"
|
||||
|
|
@ -76,11 +92,11 @@ Note: `{new}` is the remote version from the `UPGRADE_AVAILABLE` output — subs
|
|||
|
||||
Tell user the snooze duration: "Next reminder in 24h" (or 48h or 1 week, depending on level). Tip: "Set `auto_upgrade: true` in `~/.gstack/config.yaml` for automatic upgrades."
|
||||
|
||||
**If "Never ask again":**
|
||||
**If "Disable gstack update checks":**
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set update_check false
|
||||
```
|
||||
Tell user: "Update checks disabled. Run `~/.claude/skills/gstack/bin/gstack-config set update_check true` to re-enable."
|
||||
Tell user: "Gstack update checks disabled for this install. Run `~/.claude/skills/gstack/bin/gstack-config set update_check true` to re-enable."
|
||||
Continue with the current skill.
|
||||
|
||||
### Step 2: Detect install type
|
||||
|
|
|
|||
|
|
@ -25,6 +25,22 @@ allowed-tools:
|
|||
|
||||
Upgrade gstack to the latest version and show what's new.
|
||||
|
||||
## Operating boundaries
|
||||
|
||||
PRIORITY 1: preserve user work, credentials and current project state.
|
||||
PRIORITY 2: upgrade only the detected gstack install and its documented
|
||||
gstack state files.
|
||||
PRIORITY 3: summarize the result and continue the original task.
|
||||
|
||||
Each user message is an independent task. Do not carry repository state,
|
||||
upgrade results or user preferences between unrelated tasks unless the user
|
||||
explicitly asks.
|
||||
|
||||
Persistence scope: this skill may write only gstack update state such as
|
||||
`auto_upgrade`, `update_check`, `~/.gstack/update-snoozed`,
|
||||
`~/.gstack/just-upgraded-from` and `~/.gstack/last-update-check`. Do not persist
|
||||
unrelated conversation memory, project decisions, credentials or tool results.
|
||||
|
||||
## Inline upgrade flow
|
||||
|
||||
This section is referenced by all skill preambles when they detect `UPGRADE_AVAILABLE`.
|
||||
|
|
@ -43,17 +59,17 @@ echo "AUTO_UPGRADE=$_AUTO"
|
|||
|
||||
**Otherwise**, use AskUserQuestion:
|
||||
- Question: "gstack **v{new}** is available (you're on v{old}). Upgrade now?"
|
||||
- Options: ["Yes, upgrade now", "Always keep me up to date", "Not now", "Never ask again"]
|
||||
- Options: ["Yes, upgrade now", "Enable gstack auto-upgrade", "Snooze this gstack version", "Disable gstack update checks"]
|
||||
|
||||
**If "Yes, upgrade now":** Proceed to Step 2.
|
||||
|
||||
**If "Always keep me up to date":**
|
||||
**If "Enable gstack auto-upgrade":**
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set auto_upgrade true
|
||||
```
|
||||
Tell user: "Auto-upgrade enabled. Future updates will install automatically." Then proceed to Step 2.
|
||||
Tell user: "Gstack auto-upgrade enabled for this install. Future gstack updates will install automatically." Then proceed to Step 2.
|
||||
|
||||
**If "Not now":** Write snooze state with escalating backoff (first snooze = 24h, second = 48h, third+ = 1 week), then continue with the current skill. Do not mention the upgrade again.
|
||||
**If "Snooze this gstack version":** Write snooze state for this gstack version with escalating backoff (first snooze = 24h, second = 48h, third+ = 1 week), then continue with the current skill. Do not mention this gstack version again until the snooze expires.
|
||||
```bash
|
||||
_SNOOZE_FILE="$HOME/.gstack/update-snoozed"
|
||||
_REMOTE_VER="{new}"
|
||||
|
|
@ -73,11 +89,11 @@ Note: `{new}` is the remote version from the `UPGRADE_AVAILABLE` output — subs
|
|||
|
||||
Tell user the snooze duration: "Next reminder in 24h" (or 48h or 1 week, depending on level). Tip: "Set `auto_upgrade: true` in `~/.gstack/config.yaml` for automatic upgrades."
|
||||
|
||||
**If "Never ask again":**
|
||||
**If "Disable gstack update checks":**
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set update_check false
|
||||
```
|
||||
Tell user: "Update checks disabled. Run `~/.claude/skills/gstack/bin/gstack-config set update_check true` to re-enable."
|
||||
Tell user: "Gstack update checks disabled for this install. Run `~/.claude/skills/gstack/bin/gstack-config set update_check true` to re-enable."
|
||||
Continue with the current skill.
|
||||
|
||||
### Step 2: Detect install type
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Conventions:
|
|||
- [/careful](careful/SKILL.md): Safety guardrails for destructive commands.
|
||||
- [/claude](claude/SKILL.md): Claude Code CLI wrapper for non-Claude hosts - three modes.
|
||||
- [/codex](codex/SKILL.md): OpenAI Codex CLI wrapper — three modes.
|
||||
- [/context-restore](context-restore/SKILL.md): Restore working context saved earlier by /context-save.
|
||||
- [/context-restore](context-restore/SKILL.md): Restore working context saved earlier by /save or legacy /context-save.
|
||||
- [/context-save](context-save/SKILL.md): Save working context.
|
||||
- [/cso](cso/SKILL.md): Chief Security Officer mode.
|
||||
- [/design-consultation](design-consultation/SKILL.md): Design consultation: understands your product, researches the landscape, proposes a complete design system (aesthetic, typography, color, layout, spacing, motion), and generates font+color preview pages.
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -111,10 +111,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -76,10 +76,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -77,10 +77,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -80,10 +80,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -69,10 +69,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -70,10 +70,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -107,10 +107,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -69,10 +69,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -101,10 +101,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -79,10 +79,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -77,10 +77,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -82,10 +82,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -78,10 +78,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -89,10 +89,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -70,10 +70,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
"voice_line": "Voice triggers (speech-to-text aliases): \"code x\", \"code ex\", \"get another opinion\"."
|
||||
},
|
||||
"context-restore": {
|
||||
"lead": "Restore working context saved earlier by /context-save.",
|
||||
"routing": "Loads the most recent\nsaved state (across all branches by default) so you can pick up where you\nleft off — even across Conductor workspace handoffs.\nUse when asked to \"resume\", \"restore context\", \"where was I\", or\n\"pick up where I left off\". Pair with /context-save.\nFormerly /checkpoint resume — renamed because Claude Code treats /checkpoint\nas a native rewind alias in current environments.",
|
||||
"lead": "Restore working context saved earlier by /save or legacy /context-save.",
|
||||
"routing": "Loads the most recent\nsaved state (across all branches by default) so you can pick up where you\nleft off — even across Conductor workspace handoffs.\nUse when asked to \"resume\", \"restore context\", \"where was I\", or\n\"pick up where I left off\". Pair with /save.\nFormerly /checkpoint resume — renamed because Claude Code treats /checkpoint\nas a native rewind alias in current environments.",
|
||||
"voice_line": null
|
||||
},
|
||||
"context-save": {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export function generatePreambleBash(ctx: TemplateContext): string {
|
|||
const runtimeRoot = hostConfig.usesEnvVars
|
||||
? `_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
GSTACK_ROOT="$HOME/${hostConfig.globalRoot}"
|
||||
[ -n "$_ROOT" ] && [ -d "$_ROOT/${ctx.paths.localSkillRoot}" ] && GSTACK_ROOT="$_ROOT/${ctx.paths.localSkillRoot}"
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/bin/gstack-config" ] && GSTACK_ROOT="$_ROOT/${ctx.paths.localSkillRoot}"
|
||||
GSTACK_BIN="$GSTACK_ROOT/bin"
|
||||
GSTACK_BROWSE="$GSTACK_ROOT/browse/dist"
|
||||
GSTACK_DESIGN="$GSTACK_ROOT/design/dist"
|
||||
|
|
@ -57,10 +57,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(${ctx.paths.binDir}/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: \${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(${ctx.paths.binDir}/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
23
setup
23
setup
|
|
@ -531,6 +531,20 @@ fi
|
|||
# 3. Ensure ~/.gstack global state directory exists
|
||||
mkdir -p "$HOME/.gstack/projects"
|
||||
|
||||
# Optional user-level visibility denylist. One exact skill name per line;
|
||||
# either source form (context-save) or projected form (gstack-context-save).
|
||||
GSTACK_HIDDEN_SKILLS_FILE="${GSTACK_HIDDEN_SKILLS_FILE:-$HOME/.gstack/hidden-skills}"
|
||||
_gstack_skill_hidden() {
|
||||
local source_name="$1" projected_name="${2:-$1}"
|
||||
[ -f "$GSTACK_HIDDEN_SKILLS_FILE" ] || return 1
|
||||
grep -Fqx "$source_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null && return 0
|
||||
case "$source_name" in
|
||||
gstack-*) ;;
|
||||
*) grep -Fqx "gstack-$source_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null && return 0 ;;
|
||||
esac
|
||||
grep -Fqx "$projected_name" "$GSTACK_HIDDEN_SKILLS_FILE" 2>/dev/null
|
||||
}
|
||||
|
||||
# ─── Helper: link Claude skill subdirectories into a skills parent directory ──
|
||||
# Creates real directories (not symlinks) at the top level with a SKILL.md symlink
|
||||
# inside. This ensures Claude discovers them as top-level skills, not nested under
|
||||
|
|
@ -559,6 +573,14 @@ link_claude_skill_dirs() {
|
|||
link_name="$skill_name"
|
||||
fi
|
||||
target="$skills_dir/$link_name"
|
||||
if _gstack_skill_hidden "$dir_name" "$link_name"; then
|
||||
if [ -L "$target" ]; then
|
||||
rm -f "$target"
|
||||
elif [ -d "$target" ] && [ -L "$target/SKILL.md" ]; then
|
||||
rm -rf "$target"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
# Upgrade old directory symlinks to real directories
|
||||
if [ -L "$target" ]; then
|
||||
rm -f "$target"
|
||||
|
|
@ -726,6 +748,7 @@ link_codex_skill_dirs() {
|
|||
# browse/), not a skill. Linking it would overwrite the root gstack
|
||||
# symlink that Step 5 already pointed at the repo root.
|
||||
[ "$skill_name" = "gstack" ] && continue
|
||||
_gstack_skill_hidden "$skill_name" "$skill_name" && continue
|
||||
target="$skills_dir/$skill_name"
|
||||
# Create or update symlink
|
||||
if [ -L "$target" ] || [ ! -e "$target" ]; then
|
||||
|
|
|
|||
|
|
@ -66,10 +66,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -70,10 +70,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
@ -1141,10 +1142,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import { describe, expect, test } from 'bun:test';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const ROOT = path.resolve(import.meta.dir, '..');
|
||||
|
||||
describe('context-restore Universal Save receipt contract', () => {
|
||||
const sources = [
|
||||
'context-restore/SKILL.md.tmpl',
|
||||
'context-restore/SKILL.md',
|
||||
'.agents/skills/gstack-context-restore/SKILL.md',
|
||||
];
|
||||
|
||||
for (const relative of sources) {
|
||||
test(`${relative} reads four-layer receipts without mutation`, () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, relative), 'utf-8');
|
||||
expect(content).toContain('RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json"');
|
||||
expect(content).toContain('receipt_schema_version');
|
||||
expect(content).toContain('Codex Brain');
|
||||
expect(content).toContain('Obsidian');
|
||||
expect(content).toContain('QMD');
|
||||
expect(content).toContain('Never mutate a receipt');
|
||||
expect(content).toContain('ВОССТАНОВЛЕНИЕ КОНТЕКСТА');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -74,10 +74,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ description: |
|
|||
```bash
|
||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
GSTACK_ROOT="$HOME/.codex/skills/gstack"
|
||||
[ -n "$_ROOT" ] && [ -d "$_ROOT/.agents/skills/gstack" ] && GSTACK_ROOT="$_ROOT/.agents/skills/gstack"
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/.agents/skills/gstack/bin/gstack-config" ] && GSTACK_ROOT="$_ROOT/.agents/skills/gstack"
|
||||
GSTACK_BIN="$GSTACK_ROOT/bin"
|
||||
GSTACK_BROWSE="$GSTACK_ROOT/browse/dist"
|
||||
GSTACK_DESIGN="$GSTACK_ROOT/design/dist"
|
||||
|
|
@ -60,10 +60,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$($GSTACK_BIN/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$($GSTACK_BIN/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ disable-model-invocation: true
|
|||
```bash
|
||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
GSTACK_ROOT="$HOME/.factory/skills/gstack"
|
||||
[ -n "$_ROOT" ] && [ -d "$_ROOT/.factory/skills/gstack" ] && GSTACK_ROOT="$_ROOT/.factory/skills/gstack"
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/.factory/skills/gstack/bin/gstack-config" ] && GSTACK_ROOT="$_ROOT/.factory/skills/gstack"
|
||||
GSTACK_BIN="$GSTACK_ROOT/bin"
|
||||
GSTACK_BROWSE="$GSTACK_ROOT/browse/dist"
|
||||
GSTACK_DESIGN="$GSTACK_ROOT/design/dist"
|
||||
|
|
@ -62,10 +62,11 @@ echo "FIRST_TASK: $_FIRST_TASK"
|
|||
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
|
||||
echo "LAKE_INTRO: $_LAKE_SEEN"
|
||||
_TEL=$($GSTACK_BIN/gstack-config get telemetry 2>/dev/null || true)
|
||||
case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac
|
||||
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
|
||||
_TEL_START=$(date +%s)
|
||||
_SESSION_ID="$$-$(date +%s)"
|
||||
echo "TELEMETRY: ${_TEL:-off}"
|
||||
echo "TELEMETRY: $_TEL"
|
||||
echo "TEL_PROMPTED: $_TEL_PROMPTED"
|
||||
_EXPLAIN_LEVEL=$($GSTACK_BIN/gstack-config get explain_level 2>/dev/null || echo "default")
|
||||
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
|
||||
|
|
|
|||
|
|
@ -1867,6 +1867,8 @@ describe('Codex generation (--host codex)', () => {
|
|||
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gstack-review', 'SKILL.md'), 'utf-8');
|
||||
expect(content).toContain('GSTACK_ROOT');
|
||||
expect(content).toContain('$_ROOT/.agents/skills/gstack');
|
||||
expect(content).toContain('[ -x "$_ROOT/.agents/skills/gstack/bin/gstack-config" ]');
|
||||
expect(content).not.toContain('[ -d "$_ROOT/.agents/skills/gstack" ]');
|
||||
expect(content).toContain('$GSTACK_BIN/gstack-config');
|
||||
expect(content).toContain('$GSTACK_ROOT/gstack-upgrade/SKILL.md');
|
||||
expect(content).not.toContain('~/.codex/skills/gstack/bin/gstack-config get telemetry');
|
||||
|
|
@ -2316,6 +2318,7 @@ describe('setup script validation', () => {
|
|||
const fnBody = setupContent.slice(fnStart, fnEnd);
|
||||
expect(fnBody).toContain('.agents/skills');
|
||||
expect(fnBody).toContain('gstack*');
|
||||
expect(fnBody).toContain('_gstack_skill_hidden');
|
||||
});
|
||||
|
||||
test('link_claude_skill_dirs creates real directories with absolute SKILL.md symlinks', () => {
|
||||
|
|
@ -2327,6 +2330,7 @@ describe('setup script validation', () => {
|
|||
expect(fnBody).toContain('mkdir -p "$target"');
|
||||
// v1.36.0.0: routes through _link_or_copy helper for Windows fallback (cp on MSYS2/Git Bash).
|
||||
expect(fnBody).toContain('_link_or_copy "$gstack_dir/$dir_name/SKILL.md" "$target/SKILL.md"');
|
||||
expect(fnBody).toContain('_gstack_skill_hidden');
|
||||
});
|
||||
|
||||
// REGRESSION: cleanup functions must handle both old symlinks AND new real-directory pattern
|
||||
|
|
@ -2582,6 +2586,9 @@ describe('telemetry', () => {
|
|||
expect(content).toContain('TELEMETRY:');
|
||||
expect(content).toContain('TEL_PROMPTED:');
|
||||
expect(content).toContain('gstack-config get telemetry');
|
||||
expect(content).toContain('case "$_TEL" in community|anonymous) ;; *) _TEL="off" ;; esac');
|
||||
expect(content).toContain('echo "TELEMETRY: $_TEL"');
|
||||
expect(content).not.toContain('echo "TELEMETRY: ${_TEL:-off}"');
|
||||
});
|
||||
|
||||
test('generated SKILL.md contains telemetry opt-in prompt', () => {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,44 @@ describe('gstack-relink (#578)', () => {
|
|||
expect(output).toContain('flat');
|
||||
});
|
||||
|
||||
test('does not relink a skill listed in the visibility denylist', () => {
|
||||
setupMockInstall(['context-save', 'qa']);
|
||||
const hiddenFile = path.join(tmpDir, 'hidden-skills');
|
||||
fs.writeFileSync(hiddenFile, 'gstack-context-save\n');
|
||||
run(`${path.join(installDir, 'bin', 'gstack-config')} set skill_prefix true`, {
|
||||
GSTACK_INSTALL_DIR: installDir,
|
||||
GSTACK_SKILLS_DIR: skillsDir,
|
||||
});
|
||||
|
||||
run(`${path.join(installDir, 'bin', 'gstack-relink')}`, {
|
||||
GSTACK_INSTALL_DIR: installDir,
|
||||
GSTACK_SKILLS_DIR: skillsDir,
|
||||
GSTACK_HIDDEN_SKILLS_FILE: hiddenFile,
|
||||
});
|
||||
|
||||
expect(fs.existsSync(path.join(skillsDir, 'gstack-context-save'))).toBe(false);
|
||||
expect(fs.existsSync(path.join(skillsDir, 'gstack-qa'))).toBe(true);
|
||||
});
|
||||
|
||||
test('visibility denylist also applies in no-prefix mode', () => {
|
||||
setupMockInstall(['context-save', 'qa']);
|
||||
const hiddenFile = path.join(tmpDir, 'hidden-skills');
|
||||
fs.writeFileSync(hiddenFile, 'gstack-context-save\n');
|
||||
run(`${path.join(installDir, 'bin', 'gstack-config')} set skill_prefix false`, {
|
||||
GSTACK_INSTALL_DIR: installDir,
|
||||
GSTACK_SKILLS_DIR: skillsDir,
|
||||
});
|
||||
|
||||
run(`${path.join(installDir, 'bin', 'gstack-relink')}`, {
|
||||
GSTACK_INSTALL_DIR: installDir,
|
||||
GSTACK_SKILLS_DIR: skillsDir,
|
||||
GSTACK_HIDDEN_SKILLS_FILE: hiddenFile,
|
||||
});
|
||||
|
||||
expect(fs.existsSync(path.join(skillsDir, 'context-save'))).toBe(false);
|
||||
expect(fs.existsSync(path.join(skillsDir, 'qa'))).toBe(true);
|
||||
});
|
||||
|
||||
// REGRESSION: unprefixed skills must be real directories, not symlinks (#761)
|
||||
// Claude Code auto-prefixes skills nested under a parent dir symlink.
|
||||
// e.g., `qa -> gstack/qa` gets discovered as "gstack-qa", not "qa".
|
||||
|
|
|
|||
Loading…
Reference in New Issue