mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-11 15:07:26 +08:00
* fix(careful): BSD sed compatibility for safe exception detection on macOS
The sed regex in check-careful.sh uses \s+, which is a GNU sed
extension not supported by BSD sed (macOS default). On macOS, this
causes the RM_ARGS strip to fail silently, making rm -rf of safe
exceptions (node_modules, .next, dist, etc.) trigger the destructive
warning instead of being permitted as designed.
Fix: replace \s+ with POSIX [[:space:]]+, which works on both GNU sed
(Linux) and BSD sed (macOS).
The existing test/hook-scripts.test.ts already documented this
limitation via a detectSafeRmWorks() helper and a platform-conditional
assertion ("if GNU sed: expect undefined, else: expect ask"). Now that
the regex works on both platforms, this dead path is removed and the
safe-exception tests assert the same expectation on every OS.
Note: the grep regex in the same file also uses \s+, but BSD grep -E
on macOS does support \s (verified via bash -x trace), so only the
sed expression needs the fix.
Discovered while translating the careful skill for a Japanese
derivative project (uzustack). Reference:
https://github.com/uzumaki-inc/uzustack/commit/bc67c8d
* docs(codex): rename Step 0 to avoid collision with platform-detect prelude
The codex skill template had its own '## Step 0: Check codex binary'
heading (line 42), which after gen-skill-docs collided with the
platform-detection prelude '## Step 0: Detect platform and base branch'
(injected by scripts/resolvers/utility.ts). The generated codex/SKILL.md
ended up with two H2 headings labeled Step 0, which is ambiguous to an
agent reading the skill in order.
Renamed the local heading to Step 0.4, slotting it between the prelude
(Step 0) and the existing Step 0.5 / Step 0.6 sections. No renumbering
of downstream steps needed.
Closes #1388
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(codex): regenerate SKILL.md after Step 0 rename
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(make-pdf): move setup before preamble footer
* chore: bump version and changelog (v1.31.1.0)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: ToraDady <tac201k@gmail.com>
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
123 lines
5.8 KiB
TypeScript
123 lines
5.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,
|
|
generatePlanModeInfo,
|
|
} 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';
|
|
|
|
// GBrain cross-machine sync (runs at skill start; end-side handled in completion-status)
|
|
import { generateBrainSyncBlock } from './preamble/generate-brain-sync-block';
|
|
|
|
// 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';
|
|
import { generateMakePdfSetup } from './make-pdf';
|
|
|
|
// 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),
|
|
...(ctx.skillName === 'make-pdf' ? [generateMakePdfSetup(ctx)] : []),
|
|
// Plan-mode-skill semantics stays near the top: after bash (so _SESSION_ID /
|
|
// _BRANCH / _TEL env vars are live) and before all onboarding gates so
|
|
// models read the authoritative "AskUserQuestion satisfies plan mode's
|
|
// end-of-turn" rule before any other instruction. Renders for all skills
|
|
// (not interactive-gated); the text applies universally.
|
|
generatePlanModeInfo(ctx),
|
|
generateUpgradeCheck(ctx),
|
|
generateWritingStyleMigration(ctx),
|
|
generateLakeIntro(),
|
|
generateTelemetryPrompt(ctx),
|
|
generateProactivePrompt(ctx),
|
|
generateRoutingInjection(ctx),
|
|
generateVendoringDeprecation(ctx),
|
|
generateSpawnedSessionCheck(),
|
|
generateBrainHealthInstruction(ctx),
|
|
// AskUserQuestion Format renders BEFORE the model overlay so the pacing rule
|
|
// is the ambient default; the overlay's behavioral nudges land as subordinate
|
|
// patches. Opus 4.7 reads top-to-bottom and absorbs the first pacing directive
|
|
// it hits; reversing this order regresses plan-review cadence (v1.6.4.0 bug).
|
|
...(tier >= 2 ? [generateAskUserFormat(ctx)] : []),
|
|
generateBrainSyncBlock(ctx),
|
|
generateModelOverlay(ctx),
|
|
generateVoiceDirective(tier),
|
|
...(tier >= 2 ? [
|
|
generateContextRecovery(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');
|
|
}
|