mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-08 06:26:45 +02:00
merge: integrate origin/main (v1.1.0.0) — V1 + Puppeteer parity + /plan-tune
Big merge. Main shipped three releases while this branch was in flight: - v0.19.0.0 /plan-tune skill (observational layer; dual-track dev profile) - v1.0.0.0 V1 prompts (simpler, outcome-framed, jargon-glossed) + LOC receipts - v1.1.0.0 browse Puppeteer parity (load-html, file://, --selector, --scale) This branch bumps to v1.2.0.0 (above main's v1.1.0.0) per the branch-scoped-version rule in CLAUDE.md. My "0.19.0.0" CHANGELOG entry is renamed to "1.2.0.0" and dated 2026-04-18 to land above main's trail. Conflicts resolved: - VERSION / package.json: 1.2.0.0 - CHANGELOG.md: preserved my entry at top (renamed), kept main's 1.1.0.0 / 1.0.0.0 / 0.19.0.0 / 0.18.4.0 trail below in correct order - .github/docker/Dockerfile.ci: kept my xz-utils + nodejs.org tarball fix (real CI bug fix main didn't have); absorbed main's retry loop structure for both apt and the tarball curl - bin/gstack-config: kept both my checkpoint_mode/push section and main's explain_level writing-style section - scripts/resolvers/preamble.ts: kept my submodule refactor as the file shape; extracted main's new generateWritingStyle and generateWritingStyleMigration into scripts/resolvers/preamble/ submodules; absorbed main's generateQuestionTuning import - All generated SKILL.md files: resolved by regen via bun run gen:skill-docs --host all (per CLAUDE.md: never hand-merge generated files — resolve templates and regen) - Ship golden fixtures (claude/codex/factory): refreshed Tier 2 preamble composition now includes all 8 sections: context recovery, ask-user-format, writing-style, completeness, confusion, continuous checkpoint, context health, question tuning. Main also brought new test files from /plan-tune: skill-e2e-plan-tune, upgrade-migration-v1, v0-dormancy, writing-style-resolver. All absorbed. 468 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import type { TemplateContext } from '../types';
|
||||
|
||||
export function generateWritingStyleMigration(ctx: TemplateContext): string {
|
||||
return `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:
|
||||
|
||||
> v1 prompts = simpler. Technical terms get a one-sentence gloss on first use,
|
||||
> questions are framed in outcome terms, sentences are shorter.
|
||||
>
|
||||
> Keep the new default, or prefer the older tighter prose?
|
||||
|
||||
Options:
|
||||
- A) Keep the new default (recommended — good writing helps everyone)
|
||||
- B) Restore V0 prose — set \`explain_level: terse\`
|
||||
|
||||
If A: leave \`explain_level\` unset (defaults to \`default\`).
|
||||
If B: run \`${ctx.paths.binDir}/gstack-config set explain_level terse\`.
|
||||
|
||||
Always run (regardless of choice):
|
||||
\`\`\`bash
|
||||
rm -f ~/.gstack/.writing-style-prompt-pending
|
||||
touch ~/.gstack/.writing-style-prompted
|
||||
\`\`\`
|
||||
|
||||
This only happens once. If \`WRITING_STYLE_PENDING\` is \`no\`, skip this entirely.`;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import type { TemplateContext } from '../types';
|
||||
|
||||
function loadJargonList(): string[] {
|
||||
const jargonPath = path.join(__dirname, '..', '..', 'jargon-list.json');
|
||||
try {
|
||||
const raw = fs.readFileSync(jargonPath, 'utf-8');
|
||||
const data = JSON.parse(raw);
|
||||
if (Array.isArray(data?.terms)) return data.terms.filter((t: unknown): t is string => typeof t === 'string');
|
||||
} catch {
|
||||
// Missing or malformed: fall back to empty list. Writing Style block still fires,
|
||||
// but with no terms to gloss — graceful degradation.
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function generateWritingStyle(_ctx: TemplateContext): string {
|
||||
const terms = loadJargonList();
|
||||
const jargonBlock = terms.length > 0
|
||||
? `**Jargon list** (gloss each on first use per skill invocation, if the term appears in your output):\n\n${terms.map(t => `- ${t}`).join('\n')}\n\nTerms not on this list are assumed plain-English enough.`
|
||||
: `**Jargon list:** (not loaded — \`scripts/jargon-list.json\` missing or malformed). Skip the jargon-gloss rule until the list is restored.`;
|
||||
|
||||
return `## Writing Style (skip entirely if \`EXPLAIN_LEVEL: terse\` appears in the preamble echo OR the user's current message explicitly requests terse / no-explanations output)
|
||||
|
||||
These rules apply to every AskUserQuestion, every response you write to the user, and every review finding. They compose with the AskUserQuestion Format section above: Format = *how* a question is structured; Writing Style = *the prose quality of the content inside it*.
|
||||
|
||||
1. **Jargon gets a one-sentence gloss on first use per skill invocation.** Even if the user's own prompt already contained the term — users often paste jargon from someone else's plan. Gloss unconditionally on first use. No cross-invocation memory: a new skill fire is a new first-use opportunity. Example: "race condition (two things happen at the same time and step on each other)".
|
||||
2. **Frame questions in outcome terms, not implementation terms.** Bad: "Is this endpoint idempotent?" Good: "If someone double-clicks the button, is it OK for the action to run twice?" Ask the question the user would actually want to answer.
|
||||
3. **Short sentences. Concrete nouns. Active voice.** Standard advice from any good writing guide. Prefer "the cache stores the result for 60s" over "results will have been cached for a period of 60s."
|
||||
4. **Close every decision with user impact.** Connect the technical call back to who's affected. "If we skip this, your users will see a 3-second spinner on every page load." Make the user's user real.
|
||||
5. **User-turn override.** If the user's current message says "be terse" / "no explanations" / "brutally honest, just the answer" / similar, skip this entire Writing Style block for your next response, regardless of config. User's in-turn request wins.
|
||||
6. **Glossary boundary is the curated list.** Terms below get glossed. Terms not on the list are assumed plain-English enough. If you see a term that genuinely needs glossing but isn't listed, note it (once) in your response so it can be added via PR.
|
||||
|
||||
${jargonBlock}
|
||||
|
||||
Terse mode (EXPLAIN_LEVEL: terse): skip this entire section. Emit output in V0 prose style — no glosses, no outcome-framing layer, shorter responses. Power users who know the terms get tighter output this way.`;
|
||||
}
|
||||
Reference in New Issue
Block a user