winter-super-cli 2026.6.24 → 2026.6.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/README.md +85 -0
  3. package/package.json +5 -1
  4. package/resources/local/gsap-skills/.claude-plugin/marketplace.json +20 -0
  5. package/resources/local/gsap-skills/.claude-plugin/plugin.json +6 -0
  6. package/resources/local/gsap-skills/.cursor-plugin/marketplace.json +13 -0
  7. package/resources/local/gsap-skills/.cursor-plugin/plugin.json +22 -0
  8. package/resources/local/gsap-skills/.github/copilot-instructions.md +17 -0
  9. package/resources/local/gsap-skills/.github/instructions/react.instructions.md +15 -0
  10. package/resources/local/gsap-skills/.github/instructions/scrolltrigger.instructions.md +18 -0
  11. package/resources/local/gsap-skills/AGENTS.md +27 -0
  12. package/resources/local/gsap-skills/CLAUDE.md +1 -0
  13. package/resources/local/gsap-skills/GEMINI.md +1 -0
  14. package/resources/local/gsap-skills/LICENSE +21 -0
  15. package/resources/local/gsap-skills/README.md +163 -0
  16. package/resources/local/gsap-skills/assets/gsap-green.svg +7 -0
  17. package/resources/local/gsap-skills/assets/gsap-icon-inverted.svg +15 -0
  18. package/resources/local/gsap-skills/assets/gsap-icon-square.svg +1 -0
  19. package/resources/local/gsap-skills/assets/gsap-white.svg +7 -0
  20. package/resources/local/gsap-skills/examples/README.md +29 -0
  21. package/resources/local/gsap-skills/examples/nuxt/app/app.vue +3 -0
  22. package/resources/local/gsap-skills/examples/nuxt/app/composables/useGSAP.ts +91 -0
  23. package/resources/local/gsap-skills/examples/nuxt/app/pages/index.vue +55 -0
  24. package/resources/local/gsap-skills/examples/nuxt/nuxt.config.ts +4 -0
  25. package/resources/local/gsap-skills/examples/nuxt/package.json +18 -0
  26. package/resources/local/gsap-skills/examples/react/App.jsx +46 -0
  27. package/resources/local/gsap-skills/examples/react/index.html +12 -0
  28. package/resources/local/gsap-skills/examples/react/main.jsx +9 -0
  29. package/resources/local/gsap-skills/examples/react/package.json +21 -0
  30. package/resources/local/gsap-skills/examples/react/vite.config.js +7 -0
  31. package/resources/local/gsap-skills/examples/vanilla/index.html +33 -0
  32. package/resources/local/gsap-skills/examples/vanilla/main.js +36 -0
  33. package/resources/local/gsap-skills/examples/vue/app.vue +47 -0
  34. package/resources/local/gsap-skills/examples/vue/index.html +15 -0
  35. package/resources/local/gsap-skills/examples/vue/main.js +9 -0
  36. package/resources/local/gsap-skills/examples/vue/package.json +19 -0
  37. package/resources/local/gsap-skills/examples/vue/vite.config.js +7 -0
  38. package/resources/local/gsap-skills/skills/gsap-core/SKILL.md +254 -0
  39. package/resources/local/gsap-skills/skills/gsap-frameworks/SKILL.md +266 -0
  40. package/resources/local/gsap-skills/skills/gsap-performance/SKILL.md +79 -0
  41. package/resources/local/gsap-skills/skills/gsap-plugins/SKILL.md +433 -0
  42. package/resources/local/gsap-skills/skills/gsap-react/SKILL.md +136 -0
  43. package/resources/local/gsap-skills/skills/gsap-scrolltrigger/SKILL.md +296 -0
  44. package/resources/local/gsap-skills/skills/gsap-timeline/SKILL.md +107 -0
  45. package/resources/local/gsap-skills/skills/gsap-utils/SKILL.md +284 -0
  46. package/resources/local/gsap-skills/skills/llms.txt +39 -0
  47. package/resources/local/hermes-agent-core/AGENTS.md +1132 -0
  48. package/resources/local/hermes-agent-core/LICENSE +21 -0
  49. package/resources/local/hermes-agent-core/README.md +215 -0
  50. package/resources/local/hermes-agent-core/docs/2026-05-07-s6-overlay-dynamic-subagent-gateways.md +434 -0
  51. package/resources/local/hermes-agent-core/hermes-already-has-routines.md +160 -0
  52. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
  53. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
  54. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
  55. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1021 -0
  56. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +277 -0
  57. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +57 -0
  58. package/resources/local/hermes-agent-core/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
  59. package/resources/local/hermes-agent-core/skills/github/DESCRIPTION.md +3 -0
  60. package/resources/local/hermes-agent-core/skills/github/codebase-inspection/SKILL.md +116 -0
  61. package/resources/local/hermes-agent-core/skills/github/github-auth/SKILL.md +247 -0
  62. package/resources/local/hermes-agent-core/skills/github/github-auth/scripts/gh-env.sh +66 -0
  63. package/resources/local/hermes-agent-core/skills/github/github-code-review/SKILL.md +481 -0
  64. package/resources/local/hermes-agent-core/skills/github/github-code-review/references/review-output-template.md +74 -0
  65. package/resources/local/hermes-agent-core/skills/github/github-issues/SKILL.md +370 -0
  66. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/bug-report.md +35 -0
  67. package/resources/local/hermes-agent-core/skills/github/github-issues/templates/feature-request.md +31 -0
  68. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/SKILL.md +367 -0
  69. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
  70. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
  71. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
  72. package/resources/local/hermes-agent-core/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
  73. package/resources/local/hermes-agent-core/skills/github/github-repo-management/SKILL.md +516 -0
  74. package/resources/local/hermes-agent-core/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
  75. package/resources/local/hermes-agent-core/skills/mcp/DESCRIPTION.md +3 -0
  76. package/resources/local/hermes-agent-core/skills/mcp/native-mcp/SKILL.md +357 -0
  77. package/resources/local/hermes-agent-core/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
  78. package/resources/local/hermes-agent-core/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
  79. package/resources/local/hermes-agent-core/skills/software-development/hermes-s6-container-supervision/SKILL.md +176 -0
  80. package/resources/local/hermes-agent-core/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
  81. package/resources/local/hermes-agent-core/skills/software-development/plan/SKILL.md +58 -0
  82. package/resources/local/hermes-agent-core/skills/software-development/python-debugpy/SKILL.md +375 -0
  83. package/resources/local/hermes-agent-core/skills/software-development/requesting-code-review/SKILL.md +280 -0
  84. package/resources/local/hermes-agent-core/skills/software-development/spike/SKILL.md +197 -0
  85. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/SKILL.md +352 -0
  86. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
  87. package/resources/local/hermes-agent-core/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
  88. package/resources/local/hermes-agent-core/skills/software-development/systematic-debugging/SKILL.md +367 -0
  89. package/resources/local/hermes-agent-core/skills/software-development/test-driven-development/SKILL.md +343 -0
  90. package/resources/local/hermes-agent-core/skills/software-development/writing-plans/SKILL.md +297 -0
  91. package/resources/local/manifest.json +12 -0
  92. package/rule.md +2 -0
  93. package/scripts/audit-pack.js +5 -0
  94. package/scripts/smoke-browser.js +53 -0
  95. package/scripts/smoke-package.js +38 -4
  96. package/skill.md +36 -4
  97. package/skills/gsap.md +26 -0
  98. package/skills/hermes-agent.md +17 -0
  99. package/src/agent/agent-definitions.js +4 -4
  100. package/src/agent/runtime.js +179 -5
  101. package/src/agent/subagent-child.js +44 -0
  102. package/src/ai/capability-scorecard.js +193 -14
  103. package/src/ai/hermes-core.js +77 -0
  104. package/src/ai/model-capabilities.js +42 -2
  105. package/src/ai/prompts/system-prompt.js +18 -2
  106. package/src/ai/small-model-amplifier.js +35 -7
  107. package/src/ai/workflow-selector.js +22 -1
  108. package/src/cli/commands.js +46 -2
  109. package/src/cli/config.js +45 -6
  110. package/src/cli/context-loader.js +253 -9
  111. package/src/cli/conversation-format.js +5 -0
  112. package/src/cli/input-controller.js +79 -10
  113. package/src/cli/prompt-builder.js +47 -8
  114. package/src/cli/repl-commands.js +115 -0
  115. package/src/cli/repl.js +343 -85
  116. package/src/cli/slash-commands.js +4 -2
  117. package/src/cli/tui.js +133 -37
  118. package/src/mcp/client.js +54 -11
  119. package/src/mcp/presets.js +114 -0
  120. package/src/tools/agent.js +316 -25
  121. package/src/tools/executor.js +412 -12
  122. package/src/tools/permission.js +20 -17
  123. package/winter.d.ts +112 -10
@@ -1,4 +1,6 @@
1
- import { existsSync } from 'fs';
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { mkdtemp, writeFile } from 'fs/promises';
3
+ import { tmpdir } from 'os';
2
4
  import path from 'path';
3
5
  import { fileURLToPath } from 'url';
4
6
 
@@ -73,8 +75,9 @@ export const CAPABILITY_AREAS = [
73
75
  target: 'Codebuff/Claude-style custom agents with scoped tools',
74
76
  probes: [
75
77
  { key: 'agentRegistry', label: 'project agent registry is active' },
76
- { key: 'agentTool', label: 'Agent tool exists' },
77
- { key: 'scopedTools', label: 'role-scoped tools are available' },
78
+ { key: 'agentTool', label: 'Agent tool runs real subagent conversations' },
79
+ { key: 'scopedTools', label: 'role-scoped tools are enforced' },
80
+ { key: 'processIsolation', label: 'subagents can run through child-process isolation' },
78
81
  ],
79
82
  },
80
83
  {
@@ -107,6 +110,7 @@ export const CAPABILITY_AREAS = [
107
110
  probes: [
108
111
  { key: 'autoDebug', label: '/debug and /auto routes exist' },
109
112
  { key: 'browserDebug', label: 'BrowserDebug tool exists' },
113
+ { key: 'browserSmoke', label: 'browser smoke covers BrowserDebug and VisibleBrowser' },
110
114
  { key: 'verificationCommands', label: 'verification command inference exists' },
111
115
  ],
112
116
  },
@@ -139,24 +143,197 @@ function scoreArea(area, probes) {
139
143
  };
140
144
  }
141
145
 
146
+ async function runBehaviorProbes() {
147
+ const result = {
148
+ agentTool: false,
149
+ scopedTools: false,
150
+ processIsolation: false,
151
+ slashMenu: false,
152
+ };
153
+
154
+ try {
155
+ const { AgentTool } = await import('../tools/agent.js');
156
+ const definitions = [{ name: 'Read' }, { name: 'Write' }];
157
+ const repl = {
158
+ projectPath: PACKAGE_ROOT,
159
+ ai: {
160
+ getActiveProvider: () => 'probe',
161
+ setProvider: () => true,
162
+ },
163
+ tools: {
164
+ getToolDefinitions: () => definitions,
165
+ },
166
+ agentRegistry: {
167
+ async get(id = 'general') {
168
+ return { id, tools: ['Read'], instructionsPrompt: 'probe' };
169
+ },
170
+ },
171
+ getAgentToolsForDefinition(definition) {
172
+ return definitions.filter(tool => definition.tools.includes(tool.name));
173
+ },
174
+ async getProjectContext() {
175
+ return '';
176
+ },
177
+ getAgentDefinitionSystemPrompt() {
178
+ return 'probe';
179
+ },
180
+ async runConversation(_messages, _label, tools) {
181
+ return {
182
+ finalContent: 'probe complete',
183
+ usedTools: true,
184
+ changedFiles: [],
185
+ toolSummaries: [`allowed=${tools.map(tool => tool.name).join(',')}`],
186
+ executedTools: [{ tool: tools[0]?.name, success: true }],
187
+ usage: {},
188
+ };
189
+ },
190
+ };
191
+ const agent = new AgentTool(repl);
192
+ const run = await agent.run('probe real subagent behavior', { role: 'general', tools: ['Read'], processIsolation: false });
193
+ result.agentTool = run.success === true && run.status === 'completed' && run.usedTools === true && run.allowedTools?.includes('Read') && !run.allowedTools?.includes('Write');
194
+ } catch {
195
+ result.agentTool = false;
196
+ }
197
+
198
+ try {
199
+ const { EventEmitter } = await import('events');
200
+ const { AgentTool } = await import('../tools/agent.js');
201
+ const projectPath = await mkdtemp(path.join(tmpdir(), 'winter-scorecard-agent-'));
202
+ await writeFile(path.join(projectPath, 'README.md'), 'scorecard workspace', 'utf8');
203
+ const repl = {
204
+ constructor: { name: 'WinterREPL' },
205
+ projectPath,
206
+ sessionId: 'scorecard',
207
+ version: 'scorecard',
208
+ ai: {
209
+ getActiveProvider: () => 'probe',
210
+ setProvider: () => true,
211
+ },
212
+ tools: { getToolDefinitions: () => [] },
213
+ subagentFork: () => {
214
+ const child = new EventEmitter();
215
+ child.pid = 101;
216
+ child.stdout = new EventEmitter();
217
+ child.stderr = new EventEmitter();
218
+ child.kill = () => {};
219
+ child.send = message => {
220
+ queueMicrotask(() => child.emit('message', {
221
+ type: 'result',
222
+ result: {
223
+ success: true,
224
+ agentId: message.options.agentId,
225
+ summary: 'isolated',
226
+ workspaceIsolated: message.options.workspaceIsolation === true,
227
+ workspacePath: message.options.projectPath,
228
+ },
229
+ }));
230
+ };
231
+ return child;
232
+ },
233
+ };
234
+ const agent = new AgentTool(repl);
235
+ const run = await agent.run('probe process isolation', { processIsolation: true });
236
+ result.processIsolation = run.success === true && run.processIsolated === true && run.workspaceIsolated === true && run.childPid === 101;
237
+ } catch {
238
+ result.processIsolation = false;
239
+ }
240
+
241
+ try {
242
+ const { AgentRuntime } = await import('../agent/runtime.js');
243
+ let executed = false;
244
+ let turns = 0;
245
+ const repl = {
246
+ hydrateSessionToolPermissions() {},
247
+ isCancelled: false,
248
+ useUnicodeUi: false,
249
+ sessionPermissionGrants: new Set(),
250
+ session: { getContext: () => ({}), updateContext: async () => {} },
251
+ ai: { tools: [], _modelTier: 'medium', setTools() {} },
252
+ tools: {
253
+ normalizeToolName: name => String(name),
254
+ execute: async () => {
255
+ executed = true;
256
+ return { success: true };
257
+ },
258
+ },
259
+ selectExecutionProfile: () => ({ provider: 'probe', model: 'probe' }),
260
+ actionRequiresTools: () => false,
261
+ async requestAssistantTurn() {
262
+ turns += 1;
263
+ if (turns === 1) {
264
+ return { assistantMsg: { content: '' }, toolCalls: [{ id: 'x', toolName: 'Bash', toolArgs: { command: 'echo no' } }] };
265
+ }
266
+ return { assistantMsg: { content: 'done' }, toolCalls: [], finalContent: 'done' };
267
+ },
268
+ buildToolCallSignature: calls => JSON.stringify(calls.map(call => call.toolName)),
269
+ formatToolCallsForMessage: calls => calls,
270
+ buildPromptToolResultForModel: async (_tool, value) => value,
271
+ formatToolResultForConsole: (_tool, value) => value.error || '',
272
+ shouldPromptForToolPermission: async () => false,
273
+ recoverToolArgs: () => null,
274
+ enrichToolArgs: (_tool, args) => args,
275
+ buildToolFallbackAnswer: values => values.join('\n'),
276
+ getLatestUserText: messages => messages.at(-1)?.content || '',
277
+ shouldAutoVerifyAfterTools: () => false,
278
+ };
279
+ const runtime = new AgentRuntime(repl);
280
+ const run = await runtime.runConversation([{ role: 'user', content: 'probe' }], 'probe', [{ name: 'Read' }]);
281
+ result.scopedTools = executed === false && run.toolSummaries?.join('\n').includes('not allowed for this agent');
282
+ } catch {
283
+ result.scopedTools = false;
284
+ }
285
+
286
+ try {
287
+ const { WinterInputController } = await import('../cli/input-controller.js');
288
+ const repl = {
289
+ slashMenu: {
290
+ open: true,
291
+ line: '/',
292
+ items: Array.from({ length: 12 }, (_, index) => ({ cmd: `/cmd${index}`, desc: `Command ${index}` })),
293
+ selected: 0,
294
+ offset: 0,
295
+ printedLines: 0,
296
+ },
297
+ rl: { line: '/', prompt() {} },
298
+ getSlashSuggestions: () => [],
299
+ };
300
+ const input = new WinterInputController(repl);
301
+ input.renderSlashMenu = () => {};
302
+ for (let i = 0; i < 8; i++) input.moveSlashSelection(1);
303
+ result.slashMenu = repl.slashMenu.selected === 8 && repl.slashMenu.offset > 0;
304
+ } catch {
305
+ result.slashMenu = false;
306
+ }
307
+
308
+ return result;
309
+ }
310
+
142
311
  export async function assessWinterCapabilities(repl = {}) {
143
312
  const projectPath = repl.projectPath || process.cwd();
144
313
  const srcPath = path.join(PACKAGE_ROOT, 'src');
145
314
  const resourceRoot = path.join(PACKAGE_ROOT, 'resources');
146
315
  const tools = repl.tools?.getToolDefinitions?.() || repl.getAgentTools?.('general') || [];
147
316
  const toolNames = new Set(tools.map(tool => tool.name || tool.function?.name).filter(Boolean));
317
+ const hasSourceText = (relativePath, pattern) => {
318
+ try {
319
+ return pattern.test(readFileSync(path.join(srcPath, relativePath), 'utf8'));
320
+ } catch {
321
+ return false;
322
+ }
323
+ };
148
324
 
325
+ const behavior = await runBehaviorProbes();
149
326
  const probes = {
150
327
  agentRuntime: Boolean(repl.agentRuntime) || existsSync(path.join(srcPath, 'agent', 'runtime.js')),
151
328
  toolEvidenceGuard: existsSync(path.join(srcPath, 'cli', 'repl.test.js')),
152
- loopProtection: typeof repl.runConversation === 'function',
329
+ loopProtection: typeof repl.runConversation === 'function' || existsSync(path.join(srcPath, 'agent', 'runtime.js')),
153
330
 
154
331
  toolExecutor: Boolean(repl.tools) || existsSync(path.join(srcPath, 'tools', 'executor.js')),
155
- toolDoctor: typeof repl.runToolDoctor === 'function',
332
+ toolDoctor: typeof repl.runToolDoctor === 'function' || existsSync(path.join(srcPath, 'cli', 'diagnostics.js')),
156
333
  fallbackParser: existsSync(path.join(srcPath, 'cli', 'tool-call-adapter.js')),
157
334
 
158
335
  codebaseIndex: typeof repl.ensureCodebaseIndex === 'function' || existsSync(path.join(srcPath, 'codebase-index', 'indexer.js')),
159
- codebaseContext: typeof repl.buildCodebaseContext === 'function',
336
+ codebaseContext: typeof repl.buildCodebaseContext === 'function' || existsSync(path.join(srcPath, 'codebase-index', 'search.js')),
160
337
  atContext: existsSync(path.join(srcPath, 'cli', 'at-context.js')),
161
338
 
162
339
  tokenJuice: Boolean(repl.tokenJuice) || existsSync(path.join(srcPath, 'context', 'token-juice.js')),
@@ -164,20 +341,22 @@ export async function assessWinterCapabilities(repl = {}) {
164
341
  sessionCompression: typeof repl.compressSessionContext === 'function' || existsSync(path.join(srcPath, 'context', 'compress.js')),
165
342
 
166
343
  agentRegistry: Boolean(repl.agentRegistry) || existsSync(path.join(srcPath, 'agent', 'agent-definitions.js')),
167
- agentTool: toolNames.has('Agent') || existsSync(path.join(srcPath, 'tools', 'agent.js')),
168
- scopedTools: typeof repl.getAgentTools === 'function',
344
+ agentTool: behavior.agentTool,
345
+ scopedTools: behavior.scopedTools,
346
+ processIsolation: behavior.processIsolation,
169
347
 
170
348
  bottomInput: Boolean(repl.inputController) || existsSync(path.join(srcPath, 'cli', 'input-controller.js')),
171
- directImagePaste: typeof repl.handleDirectClipboardPaste === 'function',
172
- slashMenu: Array.isArray(repl.getSlashSuggestions?.('/')) || existsSync(path.join(srcPath, 'cli', 'slash-commands.js')),
349
+ directImagePaste: typeof repl.handleDirectClipboardPaste === 'function' || hasSourceText(path.join('cli', 'input-controller.js'), /handleDirectClipboardPaste|clipboardImage|imageAttachments/),
350
+ slashMenu: behavior.slashMenu && (Array.isArray(repl.getSlashSuggestions?.('/')) || existsSync(path.join(srcPath, 'cli', 'slash-commands.js'))),
173
351
 
174
352
  providerManager: Boolean(repl.ai) || existsSync(path.join(srcPath, 'ai', 'providers.js')),
175
- providerSwitch: typeof repl.ai?.switchProvider === 'function',
353
+ providerSwitch: typeof repl.ai?.switchProvider === 'function' || hasSourceText(path.join('ai', 'providers.js'), /async\s+switchProvider|switchProvider\s*\(/),
176
354
  modelTier: existsSync(path.join(srcPath, 'ai', 'model-capabilities.js')),
177
355
 
178
- autoDebug: typeof repl.runAutoHealing === 'function',
179
- browserDebug: toolNames.has('BrowserDebug'),
180
- verificationCommands: existsSync(path.join(srcPath, 'ai', 'prompts', 'success-criteria.js')),
356
+ autoDebug: typeof repl.runAutoHealing === 'function' || hasSourceText(path.join('cli', 'repl.js'), /runAutoHealing|verifyAndHeal/),
357
+ browserDebug: toolNames.has('BrowserDebug') || hasSourceText(path.join('tools', 'executor.js'), /BrowserDebug|OpenBrowser/),
358
+ browserSmoke: hasSourceText(path.join('..', 'scripts', 'smoke-browser.js'), /BrowserDebug[\s\S]*VisibleBrowser|VisibleBrowser[\s\S]*BrowserDebug/),
359
+ verificationCommands: typeof repl.inferVerificationCommands === 'function' || hasSourceText(path.join('cli', 'repl.js'), /inferVerificationCommands/),
181
360
 
182
361
  mcp: existsSync(path.join(srcPath, 'mcp', 'client.js')),
183
362
  resources: existsSync(path.join(resourceRoot, 'local', 'manifest.json')),
@@ -0,0 +1,77 @@
1
+ export const HERMES_CORE_RESOURCE = 'hermes-agent-core';
2
+
3
+ export const HERMES_CORE_PATTERNS = [
4
+ {
5
+ key: 'self_improving_loop',
6
+ label: 'Closed learning loop',
7
+ rule: 'After non-trivial work, capture reusable procedures, failure modes, and verification evidence so future turns start smarter.',
8
+ },
9
+ {
10
+ key: 'skill_lifecycle',
11
+ label: 'Skill lifecycle',
12
+ rule: 'Promote repeated workflows into skills, improve skills when they fail, and keep skill instructions operational rather than decorative.',
13
+ },
14
+ {
15
+ key: 'session_search',
16
+ label: 'Session search and compression',
17
+ rule: 'Search or summarize prior context before broad guessing; compress long trajectories into high-signal facts and decisions.',
18
+ },
19
+ {
20
+ key: 'delegation',
21
+ label: 'Subagent delegation',
22
+ rule: 'Split independent workstreams into bounded subagents or parallel tool calls, then merge evidence before finalizing.',
23
+ },
24
+ {
25
+ key: 'automation_triggers',
26
+ label: 'Automation triggers',
27
+ rule: 'For recurring checks, scheduled work, webhook-like events, or background audits, design a trigger, context injection, verification, and delivery path.',
28
+ },
29
+ {
30
+ key: 'tui_gateway',
31
+ label: 'TUI gateway separation',
32
+ rule: 'Keep UI rendering, command registry, model loop, tools, and session state as separable surfaces with explicit events and status.',
33
+ },
34
+ {
35
+ key: 'tool_gateway',
36
+ label: 'Tool gateway discipline',
37
+ rule: 'Treat MCP/tools as a gateway with allowlists, diagnostics, retries, timeouts, and concrete tool-result evidence.',
38
+ },
39
+ ];
40
+
41
+ export function detectHermesCoreSignals({ taskText = '', projectSignals = [] } = {}) {
42
+ const text = `${String(taskText || '')}\n${(projectSignals || []).join('\n')}`.toLowerCase();
43
+ const has = (...keywords) => keywords.some(keyword => text.includes(keyword));
44
+
45
+ return {
46
+ agent: has('agent', 'subagent', 'multi-agent', 'multi agent', 'ai assistant', 'coding assistant'),
47
+ skills: has('skill', 'skills', 'procedural memory', 'self-improv', 'self improv', 'learning loop'),
48
+ memory: has('memory', 'memories', 'session search', 'conversation history', 'compress context', 'trajectory'),
49
+ automation: has('cron', 'schedule', 'scheduled', 'webhook', 'routine', 'automation', 'background job'),
50
+ gateway: has('gateway', 'telegram', 'discord', 'slack', 'whatsapp', 'signal', 'messaging'),
51
+ tui: has('tui', 'terminal ui', 'ink', 'composer', 'slash command', 'autocomplete'),
52
+ mcp: has('mcp', 'tool gateway', 'toolset', 'tool registry', 'tool calling'),
53
+ };
54
+ }
55
+
56
+ export function shouldApplyHermesCore(input = {}) {
57
+ const signals = detectHermesCoreSignals(input);
58
+ return Object.values(signals).some(Boolean);
59
+ }
60
+
61
+ export function buildHermesCoreContract({ compact = false } = {}) {
62
+ const selected = compact
63
+ ? HERMES_CORE_PATTERNS.filter(pattern => ['self_improving_loop', 'skill_lifecycle', 'delegation', 'tool_gateway'].includes(pattern.key))
64
+ : HERMES_CORE_PATTERNS;
65
+
66
+ const lines = [
67
+ '## Hermes Core Agent Contract',
68
+ '- Apply Hermes-inspired core behavior directly inside Winter: self-improving skills, searchable memory, delegated workstreams, scheduled automation thinking, and tool-gateway discipline.',
69
+ ...selected.map(pattern => `- ${pattern.label}: ${pattern.rule}`),
70
+ ];
71
+
72
+ if (!compact) {
73
+ lines.push('- UI/TUI work: expose model state, tool progress, interrupts, command discovery, and evidence without fake progress text.');
74
+ }
75
+
76
+ return lines.join('\n');
77
+ }
@@ -18,11 +18,51 @@ const TIER_ORDER = [MODEL_TIERS.TINY, MODEL_TIERS.SMALL, MODEL_TIERS.MEDIUM, MOD
18
18
 
19
19
  /**
20
20
  * Classify a model name into a capability tier.
21
- * Winter now treats every active model as flagship.
21
+ * Winter still pushes maximum reasoning for every model, but the real tier matters
22
+ * for prompt size, tool-result budgets, and small-model guardrails.
22
23
  * @returns {string} One of MODEL_TIERS
23
24
  */
24
25
  export function classifyModelTier(modelName, provider = '') {
25
- return MODEL_TIERS.FLAGSHIP;
26
+ const raw = `${provider || ''} ${modelName || ''}`.toLowerCase();
27
+ if (!raw.trim()) return MODEL_TIERS.MEDIUM;
28
+
29
+ if (/\b(tiny|nano|0\.5b|1b|1\.5b|2b|2\.7b)\b/.test(raw)) {
30
+ return MODEL_TIERS.TINY;
31
+ }
32
+
33
+ const paramMatch = raw.match(/(?:^|[^0-9])(\d+(?:\.\d+)?)\s*b(?:[^a-z]|$)/);
34
+ if (paramMatch) {
35
+ const params = Number(paramMatch[1]);
36
+ if (Number.isFinite(params)) {
37
+ if (params < 3) return MODEL_TIERS.TINY;
38
+ if (params < 15) return MODEL_TIERS.SMALL;
39
+ if (params < 40) return MODEL_TIERS.MEDIUM;
40
+ if (params < 120) return MODEL_TIERS.LARGE;
41
+ return MODEL_TIERS.FLAGSHIP;
42
+ }
43
+ }
44
+
45
+ if (/\b(mini|small|lite|light|fast|flash|haiku|3b|7b|8b|9b|13b|14b)\b/.test(raw)) {
46
+ return MODEL_TIERS.SMALL;
47
+ }
48
+
49
+ if (/\b(sonnet|opus|gpt-5|gpt-4\.1|gpt-4o|o3|o4|gemini-2\.5-pro|minimax-m2|m2\.5|deepseek-r1|kimi-k2)\b/.test(raw)) {
50
+ return MODEL_TIERS.FLAGSHIP;
51
+ }
52
+
53
+ if (/\b(70b|72b|90b|large|pro|command-r|llama3\.1|llama-3\.1)\b/.test(raw)) {
54
+ return MODEL_TIERS.LARGE;
55
+ }
56
+
57
+ if (/\b(32b|34b|medium|codestral|qwen2\.5-coder)\b/.test(raw)) {
58
+ return MODEL_TIERS.MEDIUM;
59
+ }
60
+
61
+ if (/\b(ollama|lmstudio|local|llama|qwen|mistral|gemma|phi|yi-coder|deepseek-coder)\b/.test(raw)) {
62
+ return MODEL_TIERS.SMALL;
63
+ }
64
+
65
+ return MODEL_TIERS.MEDIUM;
26
66
  }
27
67
 
28
68
  /**
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  import { formatRuntimeEnvironmentSummary, getRuntimeEnvironment } from '../../cli/runtime-env.js';
8
+ import { buildHermesCoreContract } from '../hermes-core.js';
8
9
  import { getModelBudgetMultiplier } from '../model-capabilities.js';
10
+ import { buildCodingMasteryContract, buildSmallModelAmplification } from '../small-model-amplifier.js';
9
11
 
10
12
  const BASE_PRINCIPLES = [
11
13
  'Execute, don\'t describe - Do the work, don\'t write plans about doing the work',
@@ -23,7 +25,7 @@ const TOOL_CATEGORIES = {
23
25
  shell: ['Bash', 'Glob', 'Grep'],
24
26
  task: ['TaskCreate', 'TaskUpdate', 'TaskList'],
25
27
  web: ['WebFetch', 'WebSearch', 'WebArchive'],
26
- context: ['LSP', 'MCP', 'Parallel', 'Agent'],
28
+ context: ['LSP', 'MCP', 'Parallel', 'Agent', 'DelegateTask', 'ParallelAgent'],
27
29
  plan: ['TodoWrite', 'TodoList', 'ScheduleWakeup'],
28
30
  notebook: ['NotebookRead', 'NotebookEdit'],
29
31
  };
@@ -86,8 +88,13 @@ function appendSharedContext(parts, { environment, session, design, resourceCont
86
88
  }
87
89
 
88
90
  function buildStandardSystemPrompt(options = {}) {
89
- const { role = 'coding', tools = [], resourceContext, modelTier = '' } = options;
91
+ const { role = 'coding', tools = [], resourceContext, modelTier = '', context } = options;
90
92
  const budgets = getPromptBudgets(modelTier);
93
+ const amplifier = buildSmallModelAmplification({
94
+ modelTier,
95
+ workflowProfile: role,
96
+ depth: context?.type || 'standard',
97
+ });
91
98
  const projectContextBudget = options.projectContextBudget ?? budgets.projectContextBudget;
92
99
  const compactSystemPrompt = options.compactSystemPrompt ?? budgets.compactSystemPrompt;
93
100
  const parts = [
@@ -100,10 +107,19 @@ function buildStandardSystemPrompt(options = {}) {
100
107
  'Use tools when they materially improve correctness. Inspect before editing. Verify after changes.',
101
108
  'Use maximum reasoning discipline for every model tier, including tiny, local, free, and routed models.',
102
109
  'Never invent file paths, APIs, command output, or test results.',
110
+ 'For visible browser launch requests such as "mở chrome" or "open Chrome", use OpenBrowser; do not use Bash, Get-Command, Start-Process, or shell launch commands.',
103
111
  'For debug work, locate the first hard failure, patch the root cause, and verify with the closest test/build/browser smoke.',
112
+ 'For live browser debugging and user-visible Chrome control, prefer MCP server chrome-devtools when configured; use its page, click, fill, snapshot, screenshot, console, network, and performance tools before falling back to headless browser automation.',
104
113
  'For design/UI work, inspect the existing interface and design resources first; avoid generic placeholder layouts.',
105
114
  'If the user attaches or pastes an image, analyze it as primary evidence.',
106
115
  '',
116
+ '## Winter Strength Amplifier',
117
+ amplifier.hint,
118
+ '',
119
+ buildCodingMasteryContract(),
120
+ '',
121
+ buildHermesCoreContract(),
122
+ '',
107
123
  ];
108
124
 
109
125
  const toolList = formatToolList(tools);
@@ -2,18 +2,46 @@ export function isWeakTier(modelTier = '') {
2
2
  return true;
3
3
  }
4
4
 
5
+ export function buildCodingMasteryContract({ compact = false } = {}) {
6
+ const rules = [
7
+ 'Read the code path before editing: entrypoint, caller, callee, config/env, and tests when they exist.',
8
+ 'Identify invariants and side effects before changing behavior: data shape, async ordering, permissions, IO, cache, UI state, and provider differences.',
9
+ 'Prefer the smallest correct patch, but update adjacent tests/docs/config when the contract changes.',
10
+ 'After editing, review the diff mentally for syntax errors, dead code, race conditions, missing imports, wrong paths, and Windows path/shell issues.',
11
+ 'Verify with the closest command. If verification is impossible, state the exact blocker and what evidence was still checked.',
12
+ 'For mutating work, expect Winter to run verification before the final answer; use failures as the next debugging input instead of claiming success early.',
13
+ 'Final answers must name concrete files changed and concrete verification results; no vague "should work" claims.',
14
+ ];
15
+
16
+ if (compact) {
17
+ return `## Coding Mastery Contract\n${rules.slice(0, 5).map(rule => `- ${rule}`).join('\n')}`;
18
+ }
19
+
20
+ return [
21
+ '## Coding Mastery Contract',
22
+ '- Act like a senior maintainer: understand the runtime path, preserve local patterns, and optimize for the user-visible failure.',
23
+ ...rules.map(rule => `- ${rule}`),
24
+ '- For reviews, lead with defects and risks. For implementation, finish with a short change summary and verification evidence.',
25
+ ].join('\n');
26
+ }
27
+
5
28
  export function buildSmallModelAmplification({ modelTier = '', workflowProfile = 'general', depth = 'standard' } = {}) {
6
29
  const deepLike = depth === 'deep' || /debug|backend|data|devops|ai/.test(workflowProfile);
7
- const maxToolTurns = deepLike ? 18 : 14;
30
+ const tier = String(modelTier || 'medium').toLowerCase();
31
+ const smallLike = /tiny|small/.test(tier);
32
+ const maxToolTurns = deepLike ? (smallLike ? 22 : 18) : (smallLike ? 18 : 14);
8
33
 
9
34
  const hint = [
10
35
  '[Winter Strength Amplifier]',
11
- '- Every model, including tiny/local/free models, must run at Winter maximum capability.',
12
- '- Mandatory internal loop: PLAN (requirements + files + risks) -> TOOL ACTIONS -> VERIFY -> PRIVATE SELF-CHECK -> FINAL.',
13
- '- Do not skip verification. If verification fails, iterate until max loops.',
14
- '- Before final answer, run a private self-critique silently; do not print the self-check or an improved-answer preface.',
15
- '- Prefer concrete evidence from tool outputs over reasoning guesses.',
16
- '- Use CodeGraph/codebase index context before broad file reads when available.',
36
+ `- Active model tier: ${tier}. Winter must compensate with stricter procedure, not weaker behavior.`,
37
+ '- Mandatory loop for action tasks: restate success criteria privately -> inspect real files/state -> make one concrete tool call -> read result -> continue -> verify -> final.',
38
+ '- If you are uncertain, call Read/Grep/Glob/Bash instead of guessing. Evidence beats reasoning guesses.',
39
+ '- For tool fallback mode, output exactly one tool call and no prose. Do not wrap tool calls in explanation.',
40
+ '- Do not claim files changed, browser checked, tests passed, or commands ran unless tool output in this turn proves it.',
41
+ '- Prefer small, high-signal context reads over broad dumps. Use CodeGraph/codebase index before broad file reads when available.',
42
+ '- Coding standard: follow the Coding Mastery Contract; inspect call sites and tests before edits, then verify the runtime path.',
43
+ '- After a failed tool or test, inspect the new failure and try the next smallest fix. Stop only at max tool turns or a real blocker.',
44
+ '- Before final answer, run a private self-check: requirement met, files touched, verification result, remaining risk. Do not print the self-check.',
17
45
  ].join('\n');
18
46
 
19
47
  return {
@@ -1,4 +1,5 @@
1
1
  import { classifyTask, TASK_CATEGORIES, TASK_TYPES } from './prompts/task-classifier.js';
2
+ import { detectHermesCoreSignals, shouldApplyHermesCore } from './hermes-core.js';
2
3
 
3
4
  function hasAny(text, keywords) {
4
5
  return keywords.some(kw => text.includes(kw));
@@ -20,6 +21,7 @@ function detectTechnology(text, signals) {
20
21
  devops: hasAny(text, ['devops', 'ci/cd', 'docker', 'kubernetes', 'helm', 'terraform', 'ansible', 'deployment']) || hasSignal(/(docker|k8s|kubernetes|helm|terraform|github-actions|gitlab-ci)/),
21
22
  game: hasAny(text, ['game', 'unity', 'unreal', 'godot', 'multiplayer']) || hasSignal(/(unity|unreal|godot)/),
22
23
  ai: hasAny(text, ['ai agent', 'llm', 'rag', 'embedding', 'inference', 'model serving', 'mcp']) || hasSignal(/(langchain|llamaindex|embedding|transformer|onnx|mcp)/),
24
+ animation: hasAny(text, ['animation', 'animate', 'motion', 'transition', 'timeline', 'scrolltrigger', 'scroll trigger', 'scroll-driven', 'scroll animation', 'parallax', 'draggable', 'flip animation', 'splittext', 'morphsvg', 'greensock', 'gsap']) || hasSignal(/(gsap|greensock|scrolltrigger|framer-motion|motion|animation)/),
23
25
  };
24
26
  }
25
27
 
@@ -33,12 +35,14 @@ function buildTechnologySuggestions(tech) {
33
35
  if (tech.devops) suggestions.push('DevOps: Docker + CI/CD + IaC (Terraform), observability/logging');
34
36
  if (tech.game) suggestions.push('Game: Unity/Unreal/Godot, profiling, asset pipeline');
35
37
  if (tech.ai) suggestions.push('AI: RAG pipeline, vector DB, evals, prompt/version control');
38
+ if (tech.animation) suggestions.push('Animation: GSAP timelines, ScrollTrigger, framework cleanup, transform/opacity performance');
36
39
  return suggestions;
37
40
  }
38
41
 
39
42
  function buildVerificationStrategy(tech, taskInfo) {
40
43
  const checks = ['unit tests'];
41
44
  if (tech.web || tech.mobile || tech.desktop) checks.push('UI smoke tests');
45
+ if (tech.animation) checks.push('animation/browser smoke test');
42
46
  if (tech.backend) checks.push('API integration tests');
43
47
  if (tech.data) checks.push('data quality tests');
44
48
  if (tech.devops) checks.push('build + deploy dry-run checks');
@@ -53,6 +57,7 @@ export function selectWorkflow({ taskText = '', projectSignals = [], skillCatalo
53
57
 
54
58
  const taskInfo = classifyTask(text);
55
59
  const tech = detectTechnology(text, signals);
60
+ const hermesCore = detectHermesCoreSignals({ taskText, projectSignals });
56
61
 
57
62
  const recommendedSkills = [];
58
63
  const recommendedPlugins = [];
@@ -82,6 +87,14 @@ export function selectWorkflow({ taskText = '', projectSignals = [], skillCatalo
82
87
  recommendedSkills.push('vercel-react-best-practices');
83
88
  }
84
89
 
90
+ if (tech.animation) {
91
+ recommendedSkills.push('gsap', 'gsap-core', 'gsap-timeline', 'gsap-performance');
92
+ recommendedResources.push('gsap-skills');
93
+ if (tech.web) {
94
+ recommendedSkills.push('gsap-react', 'gsap-scrolltrigger');
95
+ }
96
+ }
97
+
85
98
  if (tech.mobile) {
86
99
  recommendedSkills.push('debug', 'test', 'performance', 'security');
87
100
  }
@@ -104,6 +117,14 @@ export function selectWorkflow({ taskText = '', projectSignals = [], skillCatalo
104
117
  recommendedResources.push('ecc');
105
118
  }
106
119
 
120
+ if (shouldApplyHermesCore({ taskText, projectSignals })) {
121
+ recommendedResources.push('hermes-agent-core');
122
+ recommendedSkills.push('hermes-agent', 'subagent-driven-development', 'systematic-debugging');
123
+ if (hermesCore.skills) recommendedSkills.push('hermes-agent-skill-authoring');
124
+ if (hermesCore.mcp) recommendedSkills.push('native-mcp');
125
+ if (hermesCore.automation) recommendedSkills.push('plan', 'test-driven-development');
126
+ }
127
+
107
128
  // When user mentions browser automation or interacting with websites, point at page-agent
108
129
  if (hasAny(text, ['browser', 'automation', 'crawl', 'scrape', 'form fill', 'e2e', 'playwright', 'selenium', 'page agent'])) {
109
130
  recommendedResources.push('page-agent');
@@ -143,6 +164,7 @@ export function selectWorkflow({ taskText = '', projectSignals = [], skillCatalo
143
164
  profile,
144
165
  depth,
145
166
  detectedTechnologies: tech,
167
+ hermesCore,
146
168
  technologySuggestions: buildTechnologySuggestions(tech),
147
169
  verificationStrategy: buildVerificationStrategy(tech, taskInfo),
148
170
  recommendedSkills: filteredSkills,
@@ -151,4 +173,3 @@ export function selectWorkflow({ taskText = '', projectSignals = [], skillCatalo
151
173
  recommendedResources: uniq(recommendedResources),
152
174
  };
153
175
  }
154
-
@@ -10,6 +10,7 @@ import { DesignCommands } from '../design/commands.js';
10
10
  import { SkillManager } from '../skills/manager.js';
11
11
  import { PluginManager } from '../plugins/manager.js';
12
12
  import { MCPClient } from '../mcp/client.js';
13
+ import { getMcpPreset, upsertMcpServer } from '../mcp/presets.js';
13
14
  import { BenchmarkRunner } from '../ai/benchmark.js';
14
15
  import { redactSecrets } from './secret-env.js';
15
16
  import { formatRuntimeEnvironmentSummary, getRuntimeEnvironment } from './runtime-env.js';
@@ -813,6 +814,29 @@ EXECUTION CONTRACT:
813
814
  console.log(`${colors.green}✓ Added MCP server: ${name}${colors.reset}`);
814
815
  break;
815
816
  }
817
+ case 'preset':
818
+ case 'install': {
819
+ const [presetName, ...presetOptions] = rest;
820
+ if (!presetName) {
821
+ console.log(`${colors.yellow}Usage: winter mcp preset <chrome-devtools> [--isolated] [--headless] [--browser-url <url>]${colors.reset}`);
822
+ break;
823
+ }
824
+
825
+ try {
826
+ const server = getMcpPreset(presetName, presetOptions);
827
+ upsertMcpServer(config, server);
828
+ await this.config.save(config);
829
+ console.log(`${colors.green}OK Installed MCP preset: ${server.name}${colors.reset}`);
830
+ console.log(` ${colors.dim}${server.command} ${server.args.join(' ')}${colors.reset}`);
831
+ if (!server.args.includes('--headless')) {
832
+ console.log(` ${colors.dim}Visible Chrome mode: enabled. Use --headless only for background browser runs.${colors.reset}`);
833
+ }
834
+ console.log(` ${colors.dim}Inspect tools with: winter mcp tools ${server.name}${colors.reset}`);
835
+ } catch (error) {
836
+ console.log(`${colors.red}${error.message}${colors.reset}`);
837
+ }
838
+ break;
839
+ }
816
840
  case 'remove': {
817
841
  const name = rest[0];
818
842
  if (!name) {
@@ -868,7 +892,7 @@ EXECUTION CONTRACT:
868
892
  break;
869
893
  }
870
894
  default:
871
- console.log(`${colors.yellow}Usage: winter mcp <list|add|remove|allow|tools>${colors.reset}`);
895
+ console.log(`${colors.yellow}Usage: winter mcp <list|add|preset|install|remove|allow|tools>${colors.reset}`);
872
896
  }
873
897
  }
874
898
 
@@ -882,6 +906,9 @@ EXECUTION CONTRACT:
882
906
  case undefined:
883
907
  case 'list':
884
908
  console.log(`\n${colors.cyan}Permission Allowlist:${colors.reset}`);
909
+ console.log(` Full access: ${config.sandbox?.enabled === false ? 'on' : 'off'}`);
910
+ console.log(` Sandbox enabled: ${config.sandbox?.enabled !== false}`);
911
+ console.log(` Restrict workspace: ${config.sandbox?.restrictToWorkspace !== false}`);
885
912
  console.log(` Tools: ${(config.permissions.allowlist.tools || []).join(', ') || 'none'}`);
886
913
  console.log(` Commands: ${(config.permissions.allowlist.commands || []).join(', ') || 'none'}`);
887
914
  console.log(` MCP Servers: ${(config.permissions.allowlist.mcpServers || []).join(', ') || 'none'}`);
@@ -910,8 +937,25 @@ EXECUTION CONTRACT:
910
937
  console.log(`${colors.green}✓ promptByDefault = ${config.permissions.promptByDefault}${colors.reset}`);
911
938
  break;
912
939
  }
940
+ case 'full': {
941
+ const value = String(rest[0] || 'on').toLowerCase();
942
+ const enabled = !(value === 'off' || value === 'false' || value === '0' || value === 'no');
943
+ if (typeof this.config.setFullAccess === 'function') {
944
+ await this.config.setFullAccess(enabled);
945
+ } else {
946
+ config.sandbox = {
947
+ ...(config.sandbox || {}),
948
+ enabled: !enabled,
949
+ restrictToWorkspace: !enabled,
950
+ };
951
+ config.permissions.promptByDefault = !enabled;
952
+ await this.config.save(config);
953
+ }
954
+ console.log(`${colors.green}Full access ${enabled ? 'enabled' : 'disabled'}${colors.reset}`);
955
+ break;
956
+ }
913
957
  default:
914
- console.log(`${colors.yellow}Usage: winter permissions <list|allow|prompt>${colors.reset}`);
958
+ console.log(`${colors.yellow}Usage: winter permissions <list|allow|prompt|full>${colors.reset}`);
915
959
  }
916
960
  }
917
961