diff --git a/CHANGELOG.md b/CHANGELOG.md index a3d5be1ad..c97871b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## [1.4.0.0] - 2026-04-20 + +## **Turn any markdown file into a PDF you wouldn't be embarrassed to send to a VC.** + +The new `/make-pdf` skill takes a `.md` file and produces a publication-quality PDF. 1 inch margins. Helvetica. Page numbers in the footer. Running header with the doc title. Curly quotes, em dashes, ellipsis (…). Optional cover page. Optional clickable table of contents. Optional diagonal DRAFT watermark. Copy any paragraph out of the PDF and paste it into a Google Doc: it pastes as one clean block, not "S a i l i n g" spaced out letter by letter. That last part is the whole point. The current state of the art in "markdown to PDF" tools is a legal document that's been through a scanner three times. This is the one that looks like a Stripe letter. + +### What you can do now + +- `$P generate letter.md` writes a clean letter PDF to `/tmp/letter.pdf` with sensible defaults. +- `$P generate --cover --toc --author "Garry Tan" --title "On Horizons" essay.md essay.pdf` adds a left-aligned cover page (title, subtitle, date, hairline rule) and a TOC from your H1/H2/H3 headings. +- `$P generate --watermark DRAFT memo.md draft.pdf` overlays a diagonal DRAFT watermark on every page. Send as draft. Drop the flag when it's final. +- `$P generate --no-chapter-breaks memo.md` disables the default "every H1 starts a new page" behavior for memos that happen to have multiple top-level headings. +- `$P generate --allow-network essay.md` lets external images load. Off by default so someone else's markdown can't phone home through a tracking pixel when you generate their PDF. +- `$P preview essay.md` renders the same HTML and opens it in your browser. Refresh as you edit. Skip the PDF round trip until you're ready. +- `$P setup` verifies browse + Chromium + pdftotext are installed and runs an end-to-end smoke test. + +### Why the text actually copies cleanly + +Headless Chromium emits per-glyph `Tj` operators for webfonts with non-standard metrics tables. That's why every other "markdown to PDF" tool produces PDFs where copy-paste turns "Sailing" into "S a i l i n g". We ship with system Helvetica for everything ... Chromium has native metrics for it and emits clean word-level `Tj` operators. The CI matrix runs a combined-features fixture (smartypants + hyphens + ligatures + bold/italic + inline code + lists + blockquote + chapter breaks, all on) through `pdftotext` and asserts the extracted text matches a handwritten expected file. If any feature breaks extraction, the gate fails. + +### Under the hood + +make-pdf shells out to `browse` for Chromium lifecycle. No second Playwright install, no second 58MB binary, no second codesigning dance. `$B pdf` grew from "take a screenshot as A4" into a real PDF engine with `--format`/`--width`/`--height`, `--margins`, `--header-template`/`--footer-template`, `--page-numbers`, `--tagged`, `--outline`, `--toc`, `--tab-id`, and `--from-file` for large payloads (Windows argv caps). `$B load-html` and `$B js` got `--tab-id` too, so parallel `$P generate` calls never race on the active tab. `$B newtab --json` returns structured output so make-pdf can parse the tab ID without regex-matching log strings. + +### For contributors + +- Skill file: `make-pdf/SKILL.md.tmpl`. Binary source: `make-pdf/src/`. Test fixtures: `make-pdf/test/fixtures/`. CI workflow: `.github/workflows/make-pdf-gate.yml`. +- New resolver `{{MAKE_PDF_SETUP}}` emits the `$P=` alias with the same discovery order as `$B`: `MAKE_PDF_BIN` env override, then local skill root, then global install, then PATH. +- Combined-features copy-paste gate is the P0 test in `make-pdf/test/e2e/combined-gate.test.ts`. Per-feature gates are P1 diagnostics. +- Phase 4 deferrals: vendored Paged.js for accurate TOC page numbers, vendored highlight.js for syntax highlighting, drop caps, pull quotes, CMYK safe conversion, two-column layout. +- Preamble bash now emits `_EXPLAIN_LEVEL` and `_QUESTION_TUNING` so downstream skills can read them at runtime. Golden-file fixtures updated to match. + ## [1.3.0.0] - 2026-04-19 ## **Your design skills learn your taste.** diff --git a/SKILL.md b/SKILL.md index 321969422..cc2736faa 100644 --- a/SKILL.md +++ b/SKILL.md @@ -49,6 +49,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"gstack","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 diff --git a/VERSION b/VERSION index 675055181..149bb3c12 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0.0 +1.4.0.0 diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index 4b380e989..d88a15276 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -58,6 +58,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"autoplan","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 diff --git a/benchmark-models/SKILL.md b/benchmark-models/SKILL.md index b383c95fc..0a3b3dddb 100644 --- a/benchmark-models/SKILL.md +++ b/benchmark-models/SKILL.md @@ -51,6 +51,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"benchmark-models","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 diff --git a/benchmark/SKILL.md b/benchmark/SKILL.md index 7e9150a66..41d2dcc44 100644 --- a/benchmark/SKILL.md +++ b/benchmark/SKILL.md @@ -51,6 +51,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"benchmark","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 diff --git a/browse/SKILL.md b/browse/SKILL.md index 48de54dfd..c85ae1ad2 100644 --- a/browse/SKILL.md +++ b/browse/SKILL.md @@ -50,6 +50,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"browse","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 diff --git a/canary/SKILL.md b/canary/SKILL.md index 5b6183f37..6f9e48916 100644 --- a/canary/SKILL.md +++ b/canary/SKILL.md @@ -50,6 +50,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"canary","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 diff --git a/codex/SKILL.md b/codex/SKILL.md index 13a7f49d8..3711260f4 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -52,6 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"codex","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 diff --git a/context-restore/SKILL.md b/context-restore/SKILL.md index 4db7fa451..b5ef118d5 100644 --- a/context-restore/SKILL.md +++ b/context-restore/SKILL.md @@ -54,6 +54,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"context-restore","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 diff --git a/context-save/SKILL.md b/context-save/SKILL.md index fc71ed282..8a022652f 100644 --- a/context-save/SKILL.md +++ b/context-save/SKILL.md @@ -54,6 +54,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"context-save","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 diff --git a/cso/SKILL.md b/cso/SKILL.md index 2e30c655b..72777f9b4 100644 --- a/cso/SKILL.md +++ b/cso/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"cso","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 diff --git a/design-consultation/SKILL.md b/design-consultation/SKILL.md index af57bca16..37182ecae 100644 --- a/design-consultation/SKILL.md +++ b/design-consultation/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"design-consultation","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 diff --git a/design-html/SKILL.md b/design-html/SKILL.md index 8934f0707..352ee8990 100644 --- a/design-html/SKILL.md +++ b/design-html/SKILL.md @@ -57,6 +57,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"design-html","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 diff --git a/design-review/SKILL.md b/design-review/SKILL.md index 5385c2bd7..f7c06a999 100644 --- a/design-review/SKILL.md +++ b/design-review/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"design-review","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 diff --git a/design-shotgun/SKILL.md b/design-shotgun/SKILL.md index a4608edfe..19ddb0638 100644 --- a/design-shotgun/SKILL.md +++ b/design-shotgun/SKILL.md @@ -52,6 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"design-shotgun","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 diff --git a/devex-review/SKILL.md b/devex-review/SKILL.md index 8a4c617a7..0a0c37e5b 100644 --- a/devex-review/SKILL.md +++ b/devex-review/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"devex-review","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 diff --git a/document-release/SKILL.md b/document-release/SKILL.md index bf7d8e561..4637449d2 100644 --- a/document-release/SKILL.md +++ b/document-release/SKILL.md @@ -52,6 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"document-release","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 diff --git a/health/SKILL.md b/health/SKILL.md index 32b82ba06..30623d7ae 100644 --- a/health/SKILL.md +++ b/health/SKILL.md @@ -52,6 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"health","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 diff --git a/investigate/SKILL.md b/investigate/SKILL.md index e3ce7a0d6..d51233520 100644 --- a/investigate/SKILL.md +++ b/investigate/SKILL.md @@ -69,6 +69,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"investigate","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 diff --git a/land-and-deploy/SKILL.md b/land-and-deploy/SKILL.md index 880841cfd..91b21206f 100644 --- a/land-and-deploy/SKILL.md +++ b/land-and-deploy/SKILL.md @@ -49,6 +49,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"land-and-deploy","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 diff --git a/learn/SKILL.md b/learn/SKILL.md index 9f7e0ea3b..52d67e78a 100644 --- a/learn/SKILL.md +++ b/learn/SKILL.md @@ -52,6 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"learn","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 diff --git a/make-pdf/SKILL.md b/make-pdf/SKILL.md index 475889a97..a22cc89e6 100644 --- a/make-pdf/SKILL.md +++ b/make-pdf/SKILL.md @@ -52,16 +52,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" -# Question tuning (opt-in; see /plan-tune + docs/designs/PLAN_TUNING_V0.md) -_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") -echo "QUESTION_TUNING: $_QUESTION_TUNING" -# Writing style (V1: default = ELI10-style, terse = V0 prose. See docs/designs/PLAN_TUNING_V1.md) +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) _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 echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" -# V1 upgrade migration pending-prompt flag -_WRITING_STYLE_PENDING=$([ -f ~/.gstack/.writing-style-prompt-pending ] && echo "yes" || echo "no") -echo "WRITING_STYLE_PENDING: $_WRITING_STYLE_PENDING" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"make-pdf","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 @@ -106,6 +104,12 @@ if [ -d ".claude/skills/gstack" ] && [ ! -L ".claude/skills/gstack" ]; then fi fi echo "VENDORED_GSTACK: $_VENDORED" +echo "MODEL_OVERLAY: claude" +# Checkpoint mode (explicit = no auto-commit, continuous = WIP commits as you go) +_CHECKPOINT_MODE=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_mode 2>/dev/null || echo "explicit") +_CHECKPOINT_PUSH=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_push 2>/dev/null || echo "false") +echo "CHECKPOINT_MODE: $_CHECKPOINT_MODE" +echo "CHECKPOINT_PUSH: $_CHECKPOINT_PUSH" # Detect spawned session (OpenClaw or other orchestrator) [ -n "$OPENCLAW_SESSION" ] && echo "SPAWNED_SESSION: true" || true ``` @@ -121,7 +125,38 @@ or invoking other gstack skills, use the `/gstack-` prefix (e.g., `/gstack-qa` i of `/qa`, `/gstack-ship` instead of `/ship`). Disk paths are unaffected — always use `~/.claude/skills/gstack/[skill-name]/SKILL.md` for reading skill files. -If output shows `UPGRADE_AVAILABLE `: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED `: tell user "Running gstack v{to} (just updated!)" and continue. +If output shows `UPGRADE_AVAILABLE `: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). + +If output shows `JUST_UPGRADED ` AND `SPAWNED_SESSION` is NOT set: tell +the user "Running gstack v{to} (just updated!)" and then check for new features to +surface. For each per-feature marker below, if the marker file is missing AND the +feature is plausibly useful for this user, use AskUserQuestion to let them try it. +Fire once per feature per user, NOT once per upgrade. + +**In spawned sessions (`SPAWNED_SESSION` = "true"): SKIP feature discovery entirely.** +Just print "Running gstack v{to}" and continue. Orchestrators do not want interactive +prompts from sub-sessions. + +**Feature discovery markers and prompts** (one at a time, max one per session): + +1. `~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint` → + Prompt: "Continuous checkpoint auto-commits your work as you go with `WIP:` prefix + so you never lose progress to a crash. Local-only by default — doesn't push + anywhere unless you turn that on. Want to try it?" + Options: A) Enable continuous mode, B) Show me first (print the section from + the preamble Continuous Checkpoint Mode), C) Skip. + If A: run `~/.claude/skills/gstack/bin/gstack-config set checkpoint_mode continuous`. + Always: `touch ~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint` + +2. `~/.claude/skills/gstack/.feature-prompted-model-overlay` → + Inform only (no prompt): "Model overlays are active. `MODEL_OVERLAY: {model}` + shown in the preamble output tells you which behavioral patch is applied. + Override with `--model` when regenerating skills (e.g., `bun run gen:skill-docs + --model gpt-5.4`). Default is claude." + Always: `touch ~/.claude/skills/gstack/.feature-prompted-model-overlay` + +After handling JUST_UPGRADED (prompts done or skipped), continue with the skill +workflow. If `WRITING_STYLE_PENDING` is `yes`: You're on the first skill run after upgrading to gstack v1. Ask the user once about the new default writing style. Use AskUserQuestion: @@ -246,8 +281,7 @@ Key routing rules: - Design system, brand → invoke design-consultation - Visual audit, design polish → invoke design-review - Architecture review → invoke plan-eng-review -- Save progress, save state, save my work → invoke context-save -- Resume, where was I, pick up where I left off → invoke context-restore +- Save progress, checkpoint, resume → invoke checkpoint - Code quality, health check → invoke health ``` @@ -297,7 +331,23 @@ AI orchestrator (e.g., OpenClaw). In spawned sessions: - Focus on completing the task and reporting results via prose output. - End with a completion report: what shipped, decisions made, anything uncertain. +## Model-Specific Behavioral Patch (claude) +The following nudges are tuned for the claude model family. They are +**subordinate** to skill workflow, STOP points, AskUserQuestion gates, plan-mode +safety, and /ship review gates. If a nudge below conflicts with skill instructions, +the skill wins. Treat these as preferences, not rules. + +**Todo-list discipline.** When working through a multi-step plan, mark each task +complete individually as you finish it. Do not batch-complete at the end. If a task +turns out to be unnecessary, mark it skipped with a one-line reason. + +**Think before heavy actions.** For complex operations (refactors, migrations, +non-trivial new features), briefly state your approach before executing. This lets +the user course-correct cheaply instead of mid-flight. + +**Dedicated tools over Bash.** Prefer Read, Edit, Write, Glob, Grep over shell +equivalents (cat, sed, find, grep). The dedicated tools are cheaper and clearer. ## Voice @@ -389,80 +439,29 @@ remote binary only runs if telemetry is not off and the binary exists. ## Plan Mode Safe Operations -When in plan mode, these operations are always allowed because they produce -artifacts that inform the plan, not code changes: - -- `$B` commands (browse: screenshots, page inspection, navigation, snapshots) -- `$D` commands (design: generate mockups, variants, comparison boards, iterate) -- `codex exec` / `codex review` (outside voice, plan review, adversarial challenge) -- Writing to `~/.gstack/` (config, analytics, review logs, design artifacts, learnings) -- Writing to the plan file (already allowed by plan mode) -- `open` commands for viewing generated artifacts (comparison boards, HTML previews) - -These are read-only in spirit — they inspect the live site, generate visual artifacts, -or get independent opinions. They do NOT modify project source files. +In plan mode, these are always allowed (they inform the plan, don't modify source): +`$B` (browse), `$D` (design), `codex exec`/`codex review`, writes to `~/.gstack/`, +writes to the plan file, `open` for generated artifacts. ## Skill Invocation During Plan Mode -If a user invokes a skill during plan mode, that invoked skill workflow takes -precedence over generic plan mode behavior until it finishes or the user explicitly -cancels that skill. - -Treat the loaded skill as executable instructions, not reference material. Follow -it step by step. Do not summarize, skip, reorder, or shortcut its steps. - -If the skill says to use AskUserQuestion, do that. Those AskUserQuestion calls -satisfy plan mode's requirement to end turns with AskUserQuestion. - -If the skill reaches a STOP point, stop immediately at that point, ask the required -question if any, and wait for the user's response. Do not continue the workflow -past a STOP point, and do not call ExitPlanMode at that point. - -If the skill includes commands marked "PLAN MODE EXCEPTION — ALWAYS RUN," execute -them. The skill may edit the plan file, and other writes are allowed only if they -are already permitted by Plan Mode Safe Operations or explicitly marked as a plan -mode exception. - -Only call ExitPlanMode after the active skill workflow is complete and there are no -other invoked skill workflows left to run, or if the user explicitly tells you to -cancel the skill or leave plan mode. +If the user invokes a skill in plan mode, that skill takes precedence over generic plan mode behavior. Treat it as executable instructions, not reference. Follow step +by step. AskUserQuestion calls satisfy plan mode's end-of-turn requirement. At a STOP +point, stop immediately. Do not continue the workflow past a STOP point and do not call ExitPlanMode there. Commands marked "PLAN +MODE EXCEPTION — ALWAYS RUN" execute. Other writes need to be already permitted +above or explicitly exception-marked. Call ExitPlanMode only after the skill +workflow completes — only then call ExitPlanMode (or if the user tells you to cancel the skill or leave plan mode). ## Plan Status Footer -When you are in plan mode and about to call ExitPlanMode: +In plan mode, before ExitPlanMode: if the plan file lacks a `## GSTACK REVIEW REPORT` +section, run `~/.claude/skills/gstack/bin/gstack-review-read` and append a report. +With JSONL entries (before `---CONFIG---`), format the standard runs/status/findings +table. With `NO_REVIEWS` or empty, append a 5-row placeholder table (CEO/Codex/Eng/ +Design/DX Review) with all zeros and verdict "NO REVIEWS YET — run `/autoplan`". +If a richer review report already exists, skip — review skills wrote it. -1. Check if the plan file already has a `## GSTACK REVIEW REPORT` section. -2. If it DOES — skip (a review skill already wrote a richer report). -3. If it does NOT — run this command: - -\`\`\`bash -~/.claude/skills/gstack/bin/gstack-review-read -\`\`\` - -Then write a `## GSTACK REVIEW REPORT` section to the end of the plan file: - -- If the output contains review entries (JSONL lines before `---CONFIG---`): format the - standard report table with runs/status/findings per skill, same format as the review - skills use. -- If the output is `NO_REVIEWS` or empty: write this placeholder table: - -\`\`\`markdown -## GSTACK REVIEW REPORT - -| Review | Trigger | Why | Runs | Status | Findings | -|--------|---------|-----|------|--------|----------| -| CEO Review | \`/plan-ceo-review\` | Scope & strategy | 0 | — | — | -| Codex Review | \`/codex review\` | Independent 2nd opinion | 0 | — | — | -| Eng Review | \`/plan-eng-review\` | Architecture & tests (required) | 0 | — | — | -| Design Review | \`/plan-design-review\` | UI/UX gaps | 0 | — | — | -| DX Review | \`/plan-devex-review\` | Developer experience gaps | 0 | — | — | - -**VERDICT:** NO REVIEWS YET — run \`/autoplan\` for full review pipeline, or individual reviews above. -\`\`\` - -**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes to the plan file, which is the one -file you are allowed to edit in plan mode. The plan file review report is part of the -plan's living status. +PLAN MODE EXCEPTION — always allowed (it's the plan file). # make-pdf: publication-quality PDFs from markdown diff --git a/office-hours/SKILL.md b/office-hours/SKILL.md index 4d1c40fa4..c01ec5fca 100644 --- a/office-hours/SKILL.md +++ b/office-hours/SKILL.md @@ -60,6 +60,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"office-hours","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 diff --git a/open-gstack-browser/SKILL.md b/open-gstack-browser/SKILL.md index 296611a74..38acd9345 100644 --- a/open-gstack-browser/SKILL.md +++ b/open-gstack-browser/SKILL.md @@ -49,6 +49,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"open-gstack-browser","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 diff --git a/package.json b/package.json index c4a5523d8..61dbd9595 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.3.0.0", + "version": "1.4.0.0", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/pair-agent/SKILL.md b/pair-agent/SKILL.md index 65f9f54cf..a5d5b5c12 100644 --- a/pair-agent/SKILL.md +++ b/pair-agent/SKILL.md @@ -50,6 +50,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"pair-agent","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 diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index d81534d71..47a231c45 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -56,6 +56,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"plan-ceo-review","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 diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index 1706143af..01945c036 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -53,6 +53,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"plan-design-review","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 diff --git a/plan-devex-review/SKILL.md b/plan-devex-review/SKILL.md index aca12e7bb..328956c37 100644 --- a/plan-devex-review/SKILL.md +++ b/plan-devex-review/SKILL.md @@ -57,6 +57,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"plan-devex-review","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 diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index ae3e7786f..8167eac7d 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"plan-eng-review","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 diff --git a/plan-tune/SKILL.md b/plan-tune/SKILL.md index 6e9d3a36b..c57467863 100644 --- a/plan-tune/SKILL.md +++ b/plan-tune/SKILL.md @@ -63,6 +63,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"plan-tune","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 diff --git a/qa-only/SKILL.md b/qa-only/SKILL.md index c4406d9fe..e97f25280 100644 --- a/qa-only/SKILL.md +++ b/qa-only/SKILL.md @@ -51,6 +51,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"qa-only","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 diff --git a/qa/SKILL.md b/qa/SKILL.md index 46eb38d29..1c2e318b0 100644 --- a/qa/SKILL.md +++ b/qa/SKILL.md @@ -57,6 +57,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"qa","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 diff --git a/retro/SKILL.md b/retro/SKILL.md index 2c4542525..f726435df 100644 --- a/retro/SKILL.md +++ b/retro/SKILL.md @@ -50,6 +50,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"retro","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 diff --git a/review/SKILL.md b/review/SKILL.md index 9a8cabfb8..548924a6e 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -54,6 +54,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"review","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 diff --git a/setup-browser-cookies/SKILL.md b/setup-browser-cookies/SKILL.md index d2c919402..806d0cee3 100644 --- a/setup-browser-cookies/SKILL.md +++ b/setup-browser-cookies/SKILL.md @@ -47,6 +47,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"setup-browser-cookies","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 diff --git a/setup-deploy/SKILL.md b/setup-deploy/SKILL.md index f5e822138..2d86f2bf9 100644 --- a/setup-deploy/SKILL.md +++ b/setup-deploy/SKILL.md @@ -53,6 +53,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"setup-deploy","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 diff --git a/ship/SKILL.md b/ship/SKILL.md index c0e143880..8e2fa0c08 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -55,6 +55,14 @@ _TEL_START=$(date +%s) _SESSION_ID="$$-$(date +%s)" echo "TELEMETRY: ${_TEL:-off}" echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_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 +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"ship","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