winter-super-cli 2026.6.26 → 2026.6.28

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 (122) hide show
  1. package/CHANGELOG.md +28 -5
  2. package/README.md +66 -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 +206 -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 +16 -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 +21 -1
  109. package/src/cli/config.js +42 -4
  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 +45 -8
  114. package/src/cli/repl-commands.js +123 -2
  115. package/src/cli/repl.js +183 -87
  116. package/src/cli/slash-commands.js +3 -1
  117. package/src/cli/tui.js +133 -37
  118. package/src/mcp/client.js +46 -5
  119. package/src/tools/agent.js +316 -25
  120. package/src/tools/executor.js +314 -11
  121. package/src/tools/permission.js +20 -17
  122. 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 = [
@@ -106,6 +113,13 @@ function buildStandardSystemPrompt(options = {}) {
106
113
  'For design/UI work, inspect the existing interface and design resources first; avoid generic placeholder layouts.',
107
114
  'If the user attaches or pastes an image, analyze it as primary evidence.',
108
115
  '',
116
+ '## Winter Strength Amplifier',
117
+ amplifier.hint,
118
+ '',
119
+ buildCodingMasteryContract(),
120
+ '',
121
+ buildHermesCoreContract(),
122
+ '',
109
123
  ];
110
124
 
111
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
-
@@ -906,6 +906,9 @@ EXECUTION CONTRACT:
906
906
  case undefined:
907
907
  case 'list':
908
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}`);
909
912
  console.log(` Tools: ${(config.permissions.allowlist.tools || []).join(', ') || 'none'}`);
910
913
  console.log(` Commands: ${(config.permissions.allowlist.commands || []).join(', ') || 'none'}`);
911
914
  console.log(` MCP Servers: ${(config.permissions.allowlist.mcpServers || []).join(', ') || 'none'}`);
@@ -934,8 +937,25 @@ EXECUTION CONTRACT:
934
937
  console.log(`${colors.green}✓ promptByDefault = ${config.permissions.promptByDefault}${colors.reset}`);
935
938
  break;
936
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
+ }
937
957
  default:
938
- 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}`);
939
959
  }
940
960
  }
941
961