Files
gstack/scripts/resolvers/preamble.ts
T
Garry Tan 2eac7009e9 merge: integrate origin/main (v1.1.3.0) — /checkpoint → /context-save + /context-restore rename
Main shipped v1.1.3.0 fixing Claude Code's native /checkpoint alias
shadowing gstack's skill. The old /checkpoint directory is gone,
replaced by context-save/ and context-restore/. Storage path
(~/.gstack/projects/$SLUG/checkpoints/) is unchanged, so existing
saved contexts still load.

Conflicts:
- VERSION / package.json: kept 1.2.0.0 (above main's 1.1.3.0)
- CHANGELOG: preserved 1.2.0.0 at top, inserted 1.1.3.0 below
- scripts/resolvers/preamble.ts: same pattern as prior merges —
  main's side edited the monolithic file inline; I kept the
  submodule composition root intact (main's inline changes don't
  apply to this shape)

Ported my continuous-checkpoint and context-health submodule prose
to reference the new skill names:
- generate-continuous-checkpoint.ts: "/checkpoint resume" →
  "/context-restore"
- generate-context-health.ts: "/checkpoint" → "/context-save"

Also updated user-facing prose in:
- CHANGELOG.md (1.2.0.0 entry): "/checkpoint resume" →
  "/context-restore (formerly /checkpoint resume pre-v1.1.3)"
- README.md Continuous checkpoint section: same rename

Storage paths in generate-context-recovery.ts (`$_PROJ/checkpoints/`)
left untouched — per main's v1.1.3.0 notes, the storage directory
name stays `checkpoints/` to preserve backward-compat with saved files.

Touchfiles.ts auto-merged cleanly — main's context-save-writes-file
and context-restore-loads-latest replaced my old checkpoint-save-resume
entry.

Regenerated SKILL.md files. Ship golden fixtures refreshed. 423 tests
pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 08:41:41 +08:00

104 lines
4.8 KiB
TypeScript

/**
* Preamble composition root.
*
* Each generator lives in its own file under ./preamble/*.ts. This file only
* wires them together via generatePreamble(). Keep composition declarative —
* no inline logic beyond tier gating.
*
* Each skill runs independently via `claude -p` (or the host's equivalent).
* There is no shared loader. The preamble provides: update checks, session
* tracking, user preferences, repo mode detection, model overlays, and
* telemetry.
*
* Telemetry data flow:
* 1. Always: local JSONL append to ~/.gstack/analytics/ (inline, inspectable)
* 2. If _TEL != "off" AND binary exists: gstack-telemetry-log for remote reporting
*/
import type { TemplateContext } from './types';
import { generateModelOverlay } from './model-overlay';
import { generateQuestionTuning } from './question-tuning';
// Core bootstrap
import { generatePreambleBash } from './preamble/generate-preamble-bash';
import { generateUpgradeCheck } from './preamble/generate-upgrade-check';
import { generateCompletionStatus } from './preamble/generate-completion-status';
// One-time onboarding prompts
import { generateLakeIntro } from './preamble/generate-lake-intro';
import { generateTelemetryPrompt } from './preamble/generate-telemetry-prompt';
import { generateProactivePrompt } from './preamble/generate-proactive-prompt';
import { generateRoutingInjection } from './preamble/generate-routing-injection';
import { generateVendoringDeprecation } from './preamble/generate-vendoring-deprecation';
import { generateSpawnedSessionCheck } from './preamble/generate-spawned-session-check';
import { generateWritingStyleMigration } from './preamble/generate-writing-style-migration';
// Host-specific instructions
import { generateBrainHealthInstruction } from './preamble/generate-brain-health-instruction';
// Behavioral / voice
import { generateVoiceDirective } from './preamble/generate-voice-directive';
// Tier 2+ context and interaction framework
import { generateContextRecovery } from './preamble/generate-context-recovery';
import { generateAskUserFormat } from './preamble/generate-ask-user-format';
import { generateWritingStyle } from './preamble/generate-writing-style';
import { generateCompletenessSection } from './preamble/generate-completeness-section';
import { generateConfusionProtocol } from './preamble/generate-confusion-protocol';
import { generateContinuousCheckpoint } from './preamble/generate-continuous-checkpoint';
import { generateContextHealth } from './preamble/generate-context-health';
// Tier 3+ repo mode + search
import { generateRepoModeSection } from './preamble/generate-repo-mode-section';
import { generateSearchBeforeBuildingSection } from './preamble/generate-search-before-building';
// Standalone export used directly by the resolver registry
export { generateTestFailureTriage } from './preamble/generate-test-failure-triage';
// Preamble Composition (tier → sections)
// ─────────────────────────────────────────────
// T1: core + upgrade + lake + telemetry + voice(trimmed) + completion
// T2: T1 + voice(full) + ask + completeness + context-recovery + confusion + checkpoint + context-health
// T3: T2 + repo-mode + search
// T4: (same as T3 — TEST_FAILURE_TRIAGE is a separate {{}} placeholder, not preamble)
//
// Skills by tier:
// T1: browse, setup-cookies, benchmark
// T2: investigate, cso, retro, doc-release, setup-deploy, canary, context-save, context-restore, health
// T3: autoplan, codex, design-consult, office-hours, ceo/design/eng-review
// T4: ship, review, qa, qa-only, design-review, land-deploy
export function generatePreamble(ctx: TemplateContext): string {
const tier = ctx.preambleTier ?? 4;
if (tier < 1 || tier > 4) {
throw new Error(`Invalid preamble-tier: ${tier} in ${ctx.tmplPath}. Must be 1-4.`);
}
const sections = [
generatePreambleBash(ctx),
generateUpgradeCheck(ctx),
generateWritingStyleMigration(ctx),
generateLakeIntro(),
generateTelemetryPrompt(ctx),
generateProactivePrompt(ctx),
generateRoutingInjection(ctx),
generateVendoringDeprecation(ctx),
generateSpawnedSessionCheck(),
generateBrainHealthInstruction(ctx),
generateModelOverlay(ctx),
generateVoiceDirective(tier),
...(tier >= 2 ? [
generateContextRecovery(ctx),
generateAskUserFormat(ctx),
generateWritingStyle(ctx),
generateCompletenessSection(),
generateConfusionProtocol(),
generateContinuousCheckpoint(),
generateContextHealth(),
generateQuestionTuning(ctx),
] : []),
...(tier >= 3 ? [generateRepoModeSection(), generateSearchBeforeBuildingSection(ctx)] : []),
generateCompletionStatus(ctx),
];
return sections.filter(s => s && s.trim().length > 0).join('\n\n');
}