mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-09 18:28:15 +01:00
The Claude catalog trim drops each skill's "Voice triggers (speech-to-text
aliases)" line from its description, and the body section that used to hold
it is gone. {{VOICE_TRIGGER_ROUTING}} renders them in the root router's
routing block instead: one "Voice trigger ... → invoke /<skill>" line per
skill, read from the templates' voice-triggers lists, so disabled-skill
filtering applies to them like any other routing line. Other hosts keep the
line in each description and render nothing here.
extractVoiceTriggers moves to the new resolver so the generator and the
resolver share one parser.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 645e75b1e8)
193 lines
12 KiB
TypeScript
193 lines
12 KiB
TypeScript
/**
|
|
* RESOLVERS record — maps {{PLACEHOLDER}} names to generator functions
|
|
* or gated entries.
|
|
*
|
|
* Each resolver takes a TemplateContext and returns the replacement string.
|
|
* Resolvers may be either a bare function (always fires) or a gated entry
|
|
* ({ resolve, appliesTo }) where appliesTo can return false to skip the
|
|
* resolver for a given skill. See ./types.ts: ResolverEntry.
|
|
*
|
|
* Most resolvers don't need a gate — the {{NAME}} placeholder system is
|
|
* already conditional at the template level (the resolver only fires for
|
|
* skills that reference it). Use a gate when you want a structural
|
|
* guardrail that says "this placeholder is meaningful only in skills X, Y, Z"
|
|
* even if someone later adds {{NAME}} to skill W.
|
|
*/
|
|
|
|
import type { TemplateContext, ResolverFn } from './types';
|
|
import { getHostConfig } from '../../hosts/index';
|
|
import { outsideVoiceFor, outsideVoiceGuard, outsideVoiceInvocation, outsideVoicePreflight, outsideVoiceProvenance, generateOutsideVoiceRouting } from './outside-voice';
|
|
|
|
// Domain modules
|
|
import { generatePreamble } from './preamble';
|
|
import { generateTestFailureTriage } from './preamble';
|
|
import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunGeneration, generateDesignShotgunLoop, generateTasteProfile, generateUXPrinciples, generateOverusedFonts, generateDesignSlopBullets, generateDesignDetector, generateDesignMdCheck } from './design';
|
|
import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip, generateTestCoverageGateShip } from './testing';
|
|
import { generateReviewDashboard, generatePlanFileReviewReport } from './review-dashboard';
|
|
import { generatePlanReviewApprovalCheck, generateExitPlanModeGate, generatePlanCompletionAuditShip, generatePlanCompletionGateShip, generatePlanCompletionAuditReview, generatePlanVerificationExec } from './plan-gates';
|
|
import { generateAntiShortcutClause, generateSpecReviewLoop, generateBenefitsFrom } from './spec-review';
|
|
import { generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generateCodexDocReview } from './outside-voice-steps';
|
|
import { generateImplementationModelHandoff } from './plan-review';
|
|
import { generateScopeDrift, generateCrossReviewDedup, generateSharedCodeReuse } from './review-scope';
|
|
import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow, generateCodexWebSearchFlag, generateCodexModelConfigFlag, generateCodexReviewModelConfigFlag, generateClaudeModelFlag, generateSetupCommand } from './utility';
|
|
import { generateLearningsSearch, generateLearningsLog } from './learnings';
|
|
import { generateConfidenceCalibration } from './confidence';
|
|
import { generateGateScanBlock } from './gate-scan';
|
|
import { generateInvokeSkill, generateAutoplanReviewFile, generateAutoplanSnapshotTool, generateAutoplanPublicationHook, generateCeoModeHandoffHook } from './composition';
|
|
import { generateReviewArmy } from './review-army';
|
|
import { generateDxFramework, generateDxErrorCompact, generateDxErrorItems } from './dx';
|
|
import { generateGBrainContextLoad, generateGBrainSaveResults, generateBrainPreflight, generateBrainCacheRefresh, generateBrainWriteBack } from './gbrain';
|
|
import { generateTasksSectionEmit, generateTasksSectionAggregate } from './tasks-section';
|
|
import { SECTION, SECTION_INDEX } from './sections';
|
|
import { generateRedactInvocationBlock } from './redact-doc';
|
|
import { generateFreeTextFile } from './free-text-file';
|
|
import { FOREGROUND_DISPATCH_NOTE, codexSelect } from './constants';
|
|
import { generateThirdPartyActions } from './third-party-actions';
|
|
import { generateAsideSetup, generateAsideCookbook, generateAsideResearch, generateUntrustedContentWarning, asideExecPrelude, asideResearchSend } from './aside';
|
|
import { generateCommandReference, generateSnapshotFlags, generateBrowseSetup, generateBrowseFallback } from './browse';
|
|
import { generateDesignDocDiscovery } from './design-doc-discovery';
|
|
import { generateSharedLibsRubric, generateSafeGitPath } from './shared-libs';
|
|
import { generateTestValueBar, generateTestValueMessage } from './test-value';
|
|
import { generateImplementerDispatchRules } from './dispatch-rules';
|
|
import { generatePlanRealityRows } from './plan-reality';
|
|
import { generateSidewaysSweep, generateFlakeFixNumber } from './sideways';
|
|
import { generateCoordinatorContract } from './coordinator-contract';
|
|
import { generateAutoplanDriverCodes, generateAutoplanDriverCommands, generateAutoplanDriverFiles, generateAutoplanDriverGate, generateAutoplanDriverPhases, generateAutoplanDriverResultFormat } from './autoplan-driver';
|
|
import { generateQAScope, generateQAExploratory, generateQAFunctional, generateQAResource, generateQAReview, generateQAReviewPreflight, generateQAMethodReads } from './qa';
|
|
import { generateVoiceTriggerRouting } from './voice-triggers';
|
|
|
|
export const RESOLVERS: Record<string, ResolverFn> = {
|
|
AUTOPLAN_PUBLICATION_HOOK: generateAutoplanPublicationHook,
|
|
CEO_MODE_HANDOFF_HOOK: generateCeoModeHandoffHook,
|
|
OUTSIDE_SELF_GUARD: (ctx, args) => outsideVoiceGuard({ ...ctx, host: args?.[0] === 'claude-code' ? 'codex' : 'claude' }),
|
|
OUTSIDE_VOICE_ROUTING: generateOutsideVoiceRouting,
|
|
VOICE_TRIGGER_ROUTING: generateVoiceTriggerRouting,
|
|
OUTSIDE_LABEL: (ctx) => outsideVoiceFor(ctx).label,
|
|
NATIVE_LABEL: (ctx) => outsideVoiceFor(ctx).nativeLabel,
|
|
OUTSIDE_PROVIDER: (ctx) => outsideVoiceFor(ctx).id,
|
|
HOST_ID: (ctx) => ctx.host,
|
|
OUTSIDE_PREFLIGHT: (ctx, args) => outsideVoicePreflight(ctx, { disabledBehavior: args?.[0] === 'opt-in' ? 'opt-in' : 'codex-only', ...(args?.[0] === 'autoplan' || args?.[1] === 'plan-review' ? { role: 'plan-review' as const } : {}) }),
|
|
OUTSIDE_INVOCATION: (ctx, args) => outsideVoiceInvocation(ctx, { timeoutMs: args?.[0] === 'spec' ? 120000 : 540000, gate: args?.[0] === 'spec' ? 'spec' : 'review', reasoningEffort: args?.[0] === 'spec' ? 'medium' : 'high', ...(args?.[0] === 'autoplan' || args?.[0] === 'spec' ? { role: 'plan-review' as const } : {}) }),
|
|
OUTSIDE_PROVENANCE: (ctx, args) => outsideVoiceProvenance(ctx, args?.[0] ?? ctx.skillName),
|
|
SLUG_EVAL: generateSlugEval,
|
|
SLUG_SETUP: generateSlugSetup,
|
|
CODEX_WEB_SEARCH_FLAG: generateCodexWebSearchFlag,
|
|
CODEX_MODEL_CONFIG_FLAG: generateCodexModelConfigFlag,
|
|
CODEX_REVIEW_MODEL_CONFIG_FLAG: generateCodexReviewModelConfigFlag,
|
|
CODEX_SELECT: (_ctx, args) => codexSelect(args?.[0] === 'review' ? 'review' : 'exec', undefined, args?.[1] ? { budgetSecs: Number(args[1]), optional: true } : undefined),
|
|
CLAUDE_MODEL_FLAG: generateClaudeModelFlag,
|
|
REDACT_INVOCATION_BLOCK: generateRedactInvocationBlock,
|
|
FREE_TEXT_FILE: generateFreeTextFile,
|
|
THIRD_PARTY_ACTIONS: generateThirdPartyActions,
|
|
DESIGN_DOC_DISCOVERY: generateDesignDocDiscovery,
|
|
SHARED_LIBS_RUBRIC: generateSharedLibsRubric,
|
|
SAFE_GIT: generateSafeGitPath,
|
|
SHARED_CODE_REUSE: generateSharedCodeReuse,
|
|
UNTRUSTED_CONTENT_WARNING: generateUntrustedContentWarning,
|
|
COMMAND_REFERENCE: generateCommandReference,
|
|
SNAPSHOT_FLAGS: generateSnapshotFlags,
|
|
BROWSE_SETUP: generateBrowseSetup,
|
|
BROWSE_FALLBACK: generateBrowseFallback,
|
|
PREAMBLE: generatePreamble,
|
|
ASIDE_SETUP: generateAsideSetup,
|
|
ASIDE_COOKBOOK: generateAsideCookbook,
|
|
ASIDE_RESEARCH: generateAsideResearch,
|
|
ASIDE_EXEC_PRELUDE: asideExecPrelude,
|
|
ASIDE_RESEARCH_SEND: asideResearchSend,
|
|
BASE_BRANCH_DETECT: generateBaseBranchDetect,
|
|
QA_METHODOLOGY: generateQAMethodology,
|
|
QA_SCOPE: generateQAScope,
|
|
QA_EXPLORATORY: generateQAExploratory,
|
|
QA_FUNCTIONAL: generateQAFunctional,
|
|
QA_RESOURCE: generateQAResource,
|
|
QA_REVIEW: generateQAReview,
|
|
QA_REVIEW_PREFLIGHT: generateQAReviewPreflight,
|
|
QA_METHOD_READS: generateQAMethodReads,
|
|
DESIGN_METHODOLOGY: generateDesignMethodology,
|
|
DESIGN_HARD_RULES: generateDesignHardRules,
|
|
OVERUSED_FONTS: generateOverusedFonts,
|
|
DESIGN_DETECTOR: generateDesignDetector,
|
|
DESIGN_MD_CHECK: generateDesignMdCheck,
|
|
DESIGN_SLOP_BULLETS: generateDesignSlopBullets,
|
|
UX_PRINCIPLES: generateUXPrinciples,
|
|
DESIGN_OUTSIDE_VOICES: generateDesignOutsideVoices,
|
|
DESIGN_REVIEW_LITE: generateDesignReviewLite,
|
|
REVIEW_DASHBOARD: generateReviewDashboard,
|
|
PLAN_FILE_REVIEW_REPORT: generatePlanFileReviewReport,
|
|
EXIT_PLAN_MODE_GATE: generateExitPlanModeGate,
|
|
PLAN_REVIEW_APPROVAL_CHECK: generatePlanReviewApprovalCheck,
|
|
ANTI_SHORTCUT_CLAUSE: generateAntiShortcutClause,
|
|
TEST_BOOTSTRAP: generateTestBootstrap,
|
|
TEST_COVERAGE_AUDIT_PLAN: generateTestCoverageAuditPlan,
|
|
TEST_COVERAGE_AUDIT_SHIP: generateTestCoverageAuditShip,
|
|
TEST_COVERAGE_GATE_SHIP: generateTestCoverageGateShip,
|
|
TEST_VALUE_BAR: generateTestValueBar,
|
|
TEST_VALUE_MESSAGE: generateTestValueMessage,
|
|
IMPLEMENTER_DISPATCH_RULES: generateImplementerDispatchRules,
|
|
TEST_FAILURE_TRIAGE: generateTestFailureTriage,
|
|
SPEC_REVIEW_LOOP: generateSpecReviewLoop,
|
|
DESIGN_SKETCH: generateDesignSketch,
|
|
DESIGN_SETUP: generateDesignSetup,
|
|
DESIGN_MOCKUP: generateDesignMockup,
|
|
DESIGN_SHOTGUN_GENERATION: generateDesignShotgunGeneration,
|
|
DESIGN_SHOTGUN_LOOP: generateDesignShotgunLoop,
|
|
BENEFITS_FROM: generateBenefitsFrom,
|
|
CODEX_SECOND_OPINION: generateCodexSecondOpinion,
|
|
ADVERSARIAL_STEP: generateAdversarialStep,
|
|
SCOPE_DRIFT: generateScopeDrift,
|
|
DEPLOY_BOOTSTRAP: generateDeployBootstrap,
|
|
CODEX_PLAN_REVIEW: generateCodexPlanReview,
|
|
IMPLEMENTATION_MODEL_HANDOFF: generateImplementationModelHandoff,
|
|
CODEX_DOC_REVIEW: generateCodexDocReview,
|
|
PLAN_COMPLETION_AUDIT_SHIP: generatePlanCompletionAuditShip,
|
|
PLAN_COMPLETION_GATE_SHIP: generatePlanCompletionGateShip,
|
|
PLAN_COMPLETION_AUDIT_REVIEW: generatePlanCompletionAuditReview,
|
|
PLAN_VERIFICATION_EXEC: generatePlanVerificationExec,
|
|
PLAN_REALITY_ROWS: generatePlanRealityRows,
|
|
SIDEWAYS_SWEEP: generateSidewaysSweep,
|
|
FLAKE_FIX_NUMBER: generateFlakeFixNumber,
|
|
CO_AUTHOR_TRAILER: generateCoAuthorTrailer,
|
|
SETUP_COMMAND: generateSetupCommand,
|
|
LEARNINGS_SEARCH: generateLearningsSearch,
|
|
LEARNINGS_LOG: generateLearningsLog,
|
|
CONFIDENCE_CALIBRATION: generateConfidenceCalibration,
|
|
GATE_SCAN_BLOCK: generateGateScanBlock,
|
|
INVOKE_SKILL: generateInvokeSkill,
|
|
AUTOPLAN_REVIEW_FILE: generateAutoplanReviewFile,
|
|
AUTOPLAN_SNAPSHOT_TOOL: generateAutoplanSnapshotTool,
|
|
CHANGELOG_WORKFLOW: generateChangelogWorkflow,
|
|
REVIEW_ARMY: generateReviewArmy,
|
|
CROSS_REVIEW_DEDUP: generateCrossReviewDedup,
|
|
DX_FRAMEWORK: generateDxFramework,
|
|
DX_ERROR_ITEMS: generateDxErrorItems,
|
|
DX_ERROR_COMPACT: generateDxErrorCompact,
|
|
TASTE_PROFILE: generateTasteProfile,
|
|
BIN_DIR: (ctx) => ctx.paths.binDir,
|
|
// Quotable runtime root for paths under gstack's install (freeze/bin, bin, lib):
|
|
// $GSTACK_ROOT on env-var hosts (each fence gets the runtime prelude), the
|
|
// literal $HOME path on Claude, so a quoted path keeps working with spaces.
|
|
RUNTIME_ROOT: (ctx) => getHostConfig(ctx.host).usesEnvVars ? '$GSTACK_ROOT' : `$HOME/${getHostConfig(ctx.host).globalRoot}`,
|
|
// Literal bin dir for skills that skip the shared preamble, where
|
|
// $GSTACK_BIN is never set (#2906): the per-install root when rendering for
|
|
// one, else the host's default global root.
|
|
INSTALLED_ROOT: (ctx) => ctx.installRoot ? ctx.installRoot.replace(/\/+$/, '') : `~/${getHostConfig(ctx.host).globalRoot}`,
|
|
INSTALLED_BIN_DIR: (ctx) => ctx.installRoot ? `${ctx.installRoot.replace(/\/+$/, '')}/bin` : `~/${getHostConfig(ctx.host).globalRoot}/bin`,
|
|
FOREGROUND_DISPATCH_NOTE: () => FOREGROUND_DISPATCH_NOTE,
|
|
GBRAIN_CONTEXT_LOAD: generateGBrainContextLoad,
|
|
GBRAIN_SAVE_RESULTS: generateGBrainSaveResults,
|
|
BRAIN_PREFLIGHT: generateBrainPreflight,
|
|
BRAIN_CACHE_REFRESH: generateBrainCacheRefresh,
|
|
BRAIN_WRITE_BACK: generateBrainWriteBack,
|
|
TASKS_SECTION_EMIT: generateTasksSectionEmit,
|
|
TASKS_SECTION_AGGREGATE: generateTasksSectionAggregate,
|
|
COORDINATOR_CONTRACT: generateCoordinatorContract,
|
|
AUTOPLAN_DRIVER_PHASES: generateAutoplanDriverPhases,
|
|
AUTOPLAN_DRIVER_COMMANDS: generateAutoplanDriverCommands,
|
|
AUTOPLAN_DRIVER_RESULT_FORMAT: generateAutoplanDriverResultFormat,
|
|
AUTOPLAN_DRIVER_GATE: generateAutoplanDriverGate,
|
|
AUTOPLAN_DRIVER_FILES: generateAutoplanDriverFiles,
|
|
AUTOPLAN_DRIVER_CODES: generateAutoplanDriverCodes,
|
|
SECTION,
|
|
SECTION_INDEX,
|
|
};
|