@hailer/mcp 1.0.29 → 1.1.2
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.
- package/.claude/.session-checked +1 -0
- package/.claude/agents/agent-ada-skill-builder.md +10 -2
- package/.claude/agents/agent-alejandro-function-fields.md +104 -37
- package/.claude/agents/agent-bjorn-config-audit.md +41 -21
- package/.claude/agents/agent-builder-agent-creator.md +13 -3
- package/.claude/agents/agent-code-simplifier.md +53 -0
- package/.claude/agents/agent-dmitri-activity-crud.md +126 -11
- package/.claude/agents/agent-giuseppe-app-builder.md +212 -22
- package/.claude/agents/agent-gunther-mcp-tools.md +7 -36
- package/.claude/agents/agent-helga-workflow-config.md +75 -10
- package/.claude/agents/agent-igor-activity-mover-automation.md +125 -0
- package/.claude/agents/agent-ingrid-doc-templates.md +164 -36
- package/.claude/agents/agent-ivan-monolith.md +154 -0
- package/.claude/agents/agent-kenji-data-reader.md +15 -8
- package/.claude/agents/agent-lars-code-inspector.md +56 -8
- package/.claude/agents/agent-marco-mockup-builder.md +110 -0
- package/.claude/agents/agent-marcus-api-documenter.md +323 -0
- package/.claude/agents/agent-marketplace-publisher.md +232 -72
- package/.claude/agents/agent-marketplace-reviewer.md +255 -79
- package/.claude/agents/agent-permissions-handler.md +208 -0
- package/.claude/agents/agent-simple-writer.md +48 -0
- package/.claude/agents/agent-svetlana-code-review.md +127 -14
- package/.claude/agents/agent-tanya-test-runner.md +333 -0
- package/.claude/agents/agent-ui-designer.md +100 -0
- package/.claude/agents/agent-viktor-sql-insights.md +19 -6
- package/.claude/agents/agent-web-search.md +55 -0
- package/.claude/agents/agent-yevgeni-discussions.md +7 -1
- package/.claude/agents/agent-zara-zapier.md +159 -0
- package/.claude/commands/app-squad.md +135 -0
- package/.claude/commands/audit-squad.md +158 -0
- package/.claude/commands/autoplan.md +563 -0
- package/.claude/commands/cleanup-squad.md +98 -0
- package/.claude/commands/config-squad.md +106 -0
- package/.claude/commands/crud-squad.md +87 -0
- package/.claude/commands/data-squad.md +97 -0
- package/.claude/commands/debug-squad.md +303 -0
- package/.claude/commands/doc-squad.md +65 -0
- package/.claude/commands/handoff.md +137 -0
- package/.claude/commands/health.md +49 -0
- package/.claude/commands/help.md +2 -1
- package/.claude/commands/help:agents.md +96 -16
- package/.claude/commands/help:commands.md +55 -11
- package/.claude/commands/help:faq.md +16 -1
- package/.claude/commands/help:skills.md +93 -0
- package/.claude/commands/hotfix-squad.md +112 -0
- package/.claude/commands/integration-squad.md +82 -0
- package/.claude/commands/janitor-squad.md +167 -0
- package/.claude/commands/learn-auto.md +120 -0
- package/.claude/commands/learn.md +120 -0
- package/.claude/commands/mcp-list.md +27 -0
- package/.claude/commands/onboard-squad.md +140 -0
- package/.claude/commands/plan-workspace.md +732 -0
- package/.claude/commands/prd.md +131 -0
- package/.claude/commands/project-status.md +82 -0
- package/.claude/commands/publish.md +138 -0
- package/.claude/commands/recap.md +69 -0
- package/.claude/commands/restore.md +64 -0
- package/.claude/commands/review-squad.md +152 -0
- package/.claude/commands/save.md +24 -0
- package/.claude/commands/stats.md +19 -0
- package/.claude/commands/swarm.md +210 -0
- package/.claude/commands/tool-builder.md +3 -1
- package/.claude/commands/ws-pull.md +1 -1
- package/.claude/commands/yolo-off.md +17 -0
- package/.claude/commands/yolo.md +82 -0
- package/.claude/hooks/_shared-memory.cjs +305 -0
- package/.claude/hooks/_utils.cjs +134 -0
- package/.claude/hooks/agent-failure-detector.cjs +164 -79
- package/.claude/hooks/agent-usage-logger.cjs +204 -0
- package/.claude/hooks/app-edit-guard.cjs +20 -4
- package/.claude/hooks/auto-learn.cjs +316 -0
- package/.claude/hooks/bash-guard.cjs +282 -0
- package/.claude/hooks/builder-mode-manager.cjs +183 -54
- package/.claude/hooks/bulk-activity-guard.cjs +283 -0
- package/.claude/hooks/context-watchdog.cjs +292 -0
- package/.claude/hooks/delegation-reminder.cjs +478 -0
- package/.claude/hooks/design-system-lint.cjs +283 -0
- package/.claude/hooks/post-scaffold-hook.cjs +16 -3
- package/.claude/hooks/prompt-guard.cjs +366 -0
- package/.claude/hooks/publish-template-guard.cjs +16 -0
- package/.claude/hooks/session-start.cjs +35 -0
- package/.claude/hooks/shared-memory-writer.cjs +147 -0
- package/.claude/hooks/skill-injector.cjs +140 -0
- package/.claude/hooks/skill-usage-logger.cjs +258 -0
- package/.claude/hooks/src-edit-guard.cjs +16 -1
- package/.claude/hooks/sync-marketplace-agents.cjs +53 -8
- package/.claude/scripts/yolo-toggle.cjs +142 -0
- package/.claude/settings.json +141 -14
- package/.claude/skills/SDK-activity-patterns/SKILL.md +428 -0
- package/.claude/skills/SDK-document-templates/SKILL.md +1033 -0
- package/.claude/skills/SDK-function-fields/SKILL.md +542 -0
- package/.claude/skills/SDK-generate-skill/SKILL.md +92 -0
- package/.claude/skills/SDK-init-skill/SKILL.md +127 -0
- package/.claude/skills/SDK-insight-queries/SKILL.md +787 -0
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +1139 -0
- package/.claude/skills/agent-structure/SKILL.md +98 -0
- package/.claude/skills/api-documentation-patterns/SKILL.md +474 -0
- package/.claude/skills/chrome-mcp-reference/SKILL.md +370 -0
- package/.claude/skills/delegation-routing/SKILL.md +202 -0
- package/.claude/skills/frontend-design/SKILL.md +254 -0
- package/.claude/skills/hailer-activity-mover/SKILL.md +213 -0
- package/.claude/skills/hailer-api-client/SKILL.md +518 -0
- package/.claude/skills/hailer-app-builder/SKILL.md +939 -11
- package/.claude/skills/hailer-apps-pictures/SKILL.md +269 -0
- package/.claude/skills/hailer-design-system/SKILL.md +235 -0
- package/.claude/skills/hailer-monolith-automations/SKILL.md +686 -0
- package/.claude/skills/hailer-permissions-system/SKILL.md +121 -0
- package/.claude/skills/hailer-project-protocol/SKILL.md +488 -0
- package/.claude/skills/hailer-rest-api/SKILL.md +61 -0
- package/.claude/skills/hailer-rest-api/hailer-activities.md +184 -0
- package/.claude/skills/hailer-rest-api/hailer-admin.md +473 -0
- package/.claude/skills/hailer-rest-api/hailer-calendar.md +256 -0
- package/.claude/skills/hailer-rest-api/hailer-feed.md +249 -0
- package/.claude/skills/hailer-rest-api/hailer-insights.md +195 -0
- package/.claude/skills/hailer-rest-api/hailer-messaging.md +276 -0
- package/.claude/skills/hailer-rest-api/hailer-workflows.md +283 -0
- package/.claude/skills/insight-join-patterns/SKILL.md +3 -0
- package/.claude/skills/integration-patterns/SKILL.md +421 -0
- package/.claude/skills/json-only-output/SKILL.md +52 -12
- package/.claude/skills/lsp-setup/SKILL.md +160 -0
- package/.claude/skills/mcp-direct-tools/SKILL.md +153 -0
- package/.claude/skills/optional-parameters/SKILL.md +32 -23
- package/.claude/skills/publish-hailer-app/SKILL.md +76 -12
- package/.claude/skills/testing-patterns/SKILL.md +630 -0
- package/.claude/skills/tool-builder/SKILL.md +250 -0
- package/.claude/skills/tool-parameter-usage/SKILL.md +59 -45
- package/.claude/skills/tool-response-verification/SKILL.md +82 -48
- package/.claude/skills/zapier-hailer-patterns/SKILL.md +581 -0
- package/.env.example +26 -7
- package/CLAUDE.md +290 -224
- package/dist/CLAUDE.md +370 -0
- package/dist/app.d.ts +1 -1
- package/dist/app.js +101 -101
- package/dist/bot/bot-config.d.ts +26 -0
- package/dist/bot/bot-config.js +135 -0
- package/dist/bot/bot-manager.d.ts +40 -0
- package/dist/bot/bot-manager.js +137 -0
- package/dist/bot/bot.d.ts +127 -0
- package/dist/bot/bot.js +1328 -0
- package/dist/bot/operation-logger.d.ts +28 -0
- package/dist/bot/operation-logger.js +132 -0
- package/dist/bot/services/conversation-manager.d.ts +60 -0
- package/dist/bot/services/conversation-manager.js +246 -0
- package/dist/bot/services/index.d.ts +9 -0
- package/dist/bot/services/index.js +18 -0
- package/dist/bot/services/message-classifier.d.ts +42 -0
- package/dist/bot/services/message-classifier.js +228 -0
- package/dist/bot/services/message-formatter.d.ts +88 -0
- package/dist/bot/services/message-formatter.js +411 -0
- package/dist/bot/services/session-logger.d.ts +162 -0
- package/dist/bot/services/session-logger.js +724 -0
- package/dist/bot/services/token-billing.d.ts +78 -0
- package/dist/bot/services/token-billing.js +233 -0
- package/dist/bot/services/types.d.ts +169 -0
- package/dist/bot/services/types.js +12 -0
- package/dist/bot/services/typing-indicator.d.ts +23 -0
- package/dist/bot/services/typing-indicator.js +60 -0
- package/dist/bot/services/workspace-schema-cache.d.ts +122 -0
- package/dist/bot/services/workspace-schema-cache.js +506 -0
- package/dist/bot/tool-executor.d.ts +28 -0
- package/dist/bot/tool-executor.js +48 -0
- package/dist/bot/workspace-overview.d.ts +12 -0
- package/dist/bot/workspace-overview.js +94 -0
- package/dist/cli.d.ts +1 -8
- package/dist/cli.js +1 -253
- package/dist/config.d.ts +96 -3
- package/dist/config.js +148 -37
- package/dist/core.d.ts +5 -0
- package/dist/core.js +61 -8
- package/dist/lib/discussion-lock.d.ts +42 -0
- package/dist/lib/discussion-lock.js +110 -0
- package/dist/lib/logger.d.ts +0 -1
- package/dist/lib/logger.js +39 -23
- package/dist/lib/request-logger.d.ts +77 -0
- package/dist/lib/request-logger.js +147 -0
- package/dist/mcp/UserContextCache.js +16 -13
- package/dist/mcp/hailer-clients.js +18 -17
- package/dist/mcp/signal-handler.js +29 -13
- package/dist/mcp/tool-registry.d.ts +4 -15
- package/dist/mcp/tool-registry.js +94 -32
- package/dist/mcp/tools/activity.js +28 -69
- package/dist/mcp/tools/app-core.js +9 -4
- package/dist/mcp/tools/app-marketplace.js +22 -12
- package/dist/mcp/tools/app-member.js +5 -2
- package/dist/mcp/tools/app-scaffold.js +32 -18
- package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
- package/dist/mcp/tools/bot-config/constants.js +94 -0
- package/dist/mcp/tools/bot-config/core.d.ts +253 -0
- package/dist/mcp/tools/bot-config/core.js +2456 -0
- package/dist/mcp/tools/bot-config/index.d.ts +10 -0
- package/dist/mcp/tools/bot-config/index.js +59 -0
- package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
- package/dist/mcp/tools/bot-config/tools.js +15 -0
- package/dist/mcp/tools/bot-config/types.d.ts +50 -0
- package/dist/mcp/tools/bot-config/types.js +6 -0
- package/dist/mcp/tools/discussion.js +107 -77
- package/dist/mcp/tools/document.d.ts +11 -0
- package/dist/mcp/tools/document.js +741 -0
- package/dist/mcp/tools/file.js +5 -2
- package/dist/mcp/tools/insight.js +36 -12
- package/dist/mcp/tools/investigate.d.ts +9 -0
- package/dist/mcp/tools/investigate.js +254 -0
- package/dist/mcp/tools/user.d.ts +2 -4
- package/dist/mcp/tools/user.js +9 -50
- package/dist/mcp/tools/workflow.d.ts +1 -0
- package/dist/mcp/tools/workflow.js +164 -52
- package/dist/mcp/utils/hailer-api-client.js +26 -17
- package/dist/mcp/webhook-handler.d.ts +64 -3
- package/dist/mcp/webhook-handler.js +219 -9
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.js +237 -25
- package/dist/plugins/bug-fixer/index.d.ts +2 -0
- package/dist/plugins/bug-fixer/index.js +18 -0
- package/dist/plugins/bug-fixer/tools.d.ts +45 -0
- package/dist/plugins/bug-fixer/tools.js +1096 -0
- package/package.json +10 -10
- package/scripts/test-hal-tools.ts +154 -0
- package/.claude/agents/agent-nora-name-functions.md +0 -123
- package/.claude/assistant-knowledge.md +0 -23
- package/.claude/commands/install-plugin.md +0 -261
- package/.claude/commands/list-plugins.md +0 -42
- package/.claude/commands/marketplace-setup.md +0 -33
- package/.claude/commands/publish-plugin.md +0 -55
- package/.claude/commands/uninstall-plugin.md +0 -87
- package/.claude/hooks/interactive-mode.cjs +0 -87
- package/.claude/hooks/mcp-server-guard.cjs +0 -108
- package/.claude/skills/marketplace-publishing.md +0 -155
- package/dist/bot/chat-bot.d.ts +0 -31
- package/dist/bot/chat-bot.js +0 -357
- package/dist/mcp/tools/metrics.d.ts +0 -13
- package/dist/mcp/tools/metrics.js +0 -546
- package/dist/stdio-server.d.ts +0 -14
- package/dist/stdio-server.js +0 -114
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* <hook-name>context-watchdog</hook-name>
|
|
4
|
+
*
|
|
5
|
+
* <purpose>
|
|
6
|
+
* Auto-detect context exhaustion and trigger handoff before context is lost.
|
|
7
|
+
* Three layers:
|
|
8
|
+
* 1. PreCompact (auto) - escalating response by compaction count:
|
|
9
|
+
* 1st: inform (context still good after one compaction)
|
|
10
|
+
* 2nd: strongly urge handoff (summary-of-summary, quality degrades)
|
|
11
|
+
* 3rd+: yolo=auto-handoff, interactive=block until acknowledged
|
|
12
|
+
* 2. PostToolUse (Task) - count agent calls, warn at thresholds
|
|
13
|
+
* 3. Stop - if yolo + compact fired, block stop until handoff written
|
|
14
|
+
* </purpose>
|
|
15
|
+
*
|
|
16
|
+
* <triggers>
|
|
17
|
+
* - PreCompact (matcher: auto)
|
|
18
|
+
* - PostToolUse (matcher: Task)
|
|
19
|
+
* - Stop (matcher: "")
|
|
20
|
+
* </triggers>
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
const path = require('path');
|
|
25
|
+
|
|
26
|
+
// --- Config ---
|
|
27
|
+
const EARLY_WARNING_CALLS = 20; // Soft heads-up
|
|
28
|
+
const URGENT_WARNING_CALLS = 35; // Strong warning
|
|
29
|
+
const MAX_STOP_BLOCKS = 2; // Prevent infinite stop-block loops
|
|
30
|
+
|
|
31
|
+
// --- Helpers ---
|
|
32
|
+
|
|
33
|
+
function ordinal(n) {
|
|
34
|
+
const s = ['th', 'st', 'nd', 'rd'];
|
|
35
|
+
const v = n % 100;
|
|
36
|
+
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getProjectRoot() {
|
|
40
|
+
let dir = process.cwd();
|
|
41
|
+
while (dir !== '/' && !fs.existsSync(path.join(dir, '.claude'))) {
|
|
42
|
+
dir = path.dirname(dir);
|
|
43
|
+
}
|
|
44
|
+
return dir;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function statePath(projectRoot) {
|
|
48
|
+
return path.join(projectRoot, '.claude', '.context-watchdog.json');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function loadState(projectRoot, sessionId) {
|
|
52
|
+
const fp = statePath(projectRoot);
|
|
53
|
+
try {
|
|
54
|
+
if (fs.existsSync(fp)) {
|
|
55
|
+
const state = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
|
56
|
+
if (state.sessionId === sessionId) return state;
|
|
57
|
+
}
|
|
58
|
+
} catch {}
|
|
59
|
+
// New session or corrupted state - reset
|
|
60
|
+
return {
|
|
61
|
+
sessionId,
|
|
62
|
+
toolCalls: 0,
|
|
63
|
+
compactCount: 0,
|
|
64
|
+
lastWarning: 'none', // none | early | urgent | compact
|
|
65
|
+
stopBlocks: 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function saveState(projectRoot, state) {
|
|
70
|
+
try {
|
|
71
|
+
fs.writeFileSync(statePath(projectRoot), JSON.stringify(state));
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isYoloMode(projectRoot) {
|
|
76
|
+
try {
|
|
77
|
+
const statePath = path.join(projectRoot, '.claude', 'yolo-state.json');
|
|
78
|
+
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
79
|
+
return state.mode === 'yolo';
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function handoffRecentlyWritten(projectRoot) {
|
|
86
|
+
const fp = path.join(projectRoot, 'SESSION-HANDOFF.md');
|
|
87
|
+
try {
|
|
88
|
+
if (fs.existsSync(fp)) {
|
|
89
|
+
const age = Date.now() - fs.statSync(fp).mtimeMs;
|
|
90
|
+
return age < 120_000; // Written within last 2 minutes
|
|
91
|
+
}
|
|
92
|
+
} catch {}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Output helpers - schema differs by hook event type
|
|
97
|
+
let _hookEvent = null; // Set during processHook
|
|
98
|
+
|
|
99
|
+
function allow(message) {
|
|
100
|
+
if (_hookEvent === 'Stop') {
|
|
101
|
+
// Stop schema: { continue?, stopReason? }
|
|
102
|
+
console.log(JSON.stringify({}));
|
|
103
|
+
} else if (_hookEvent === 'PreCompact') {
|
|
104
|
+
// PreCompact: just output empty or with message
|
|
105
|
+
if (message) {
|
|
106
|
+
console.log(JSON.stringify({ additionalContext: message }));
|
|
107
|
+
} else {
|
|
108
|
+
console.log(JSON.stringify({}));
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
// PreToolUse/PostToolUse schema
|
|
112
|
+
const out = { decision: 'allow' };
|
|
113
|
+
if (message) out.message = message;
|
|
114
|
+
console.log(JSON.stringify(out));
|
|
115
|
+
}
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function block(reason) {
|
|
120
|
+
if (_hookEvent === 'Stop') {
|
|
121
|
+
// Stop schema: continue=true means "don't stop, keep going"
|
|
122
|
+
console.log(JSON.stringify({ continue: true, stopReason: reason }));
|
|
123
|
+
} else {
|
|
124
|
+
console.log(JSON.stringify({ decision: 'block', reason }));
|
|
125
|
+
}
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// --- Main ---
|
|
130
|
+
|
|
131
|
+
let input = '';
|
|
132
|
+
process.stdin.setEncoding('utf8');
|
|
133
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
134
|
+
process.stdin.on('end', () => {
|
|
135
|
+
try {
|
|
136
|
+
processHook(JSON.parse(input));
|
|
137
|
+
} catch {
|
|
138
|
+
allow();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
function processHook(data) {
|
|
143
|
+
const projectRoot = getProjectRoot();
|
|
144
|
+
const sessionId = data.session_id || '';
|
|
145
|
+
const state = loadState(projectRoot, sessionId);
|
|
146
|
+
const yolo = isYoloMode(projectRoot);
|
|
147
|
+
const event = data.hook_event_name;
|
|
148
|
+
_hookEvent = event; // Set for allow/block output formatting
|
|
149
|
+
|
|
150
|
+
// ─── Layer 1: PreCompact (auto) ────────────────────────
|
|
151
|
+
// Context IS full. Escalating response by compaction count.
|
|
152
|
+
if (event === 'PreCompact') {
|
|
153
|
+
state.compactCount++;
|
|
154
|
+
state.lastWarning = 'compact';
|
|
155
|
+
saveState(projectRoot, state);
|
|
156
|
+
|
|
157
|
+
// 1st compaction: inform — context is still usable
|
|
158
|
+
if (state.compactCount === 1) {
|
|
159
|
+
if (yolo) {
|
|
160
|
+
allow(
|
|
161
|
+
`📋 Context compacting (1st time). Still usable.\n\n` +
|
|
162
|
+
`Save progress soon:\n` +
|
|
163
|
+
`1. Update DEVELOPMENT.md with current progress\n` +
|
|
164
|
+
`2. Write SESSION-HANDOFF.md\n` +
|
|
165
|
+
`3. Run /save\n\n` +
|
|
166
|
+
`You can continue working after this compaction.`
|
|
167
|
+
);
|
|
168
|
+
} else {
|
|
169
|
+
allow(`📋 Context compacting (1st time). Context is still good — consider running /handoff soon to preserve state.`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// 2nd compaction: strongly urge handoff — quality starts degrading
|
|
174
|
+
if (state.compactCount === 2) {
|
|
175
|
+
if (yolo) {
|
|
176
|
+
allow(
|
|
177
|
+
`⚠️ CONTEXT COMPACTING 2nd TIME — quality will degrade.\n\n` +
|
|
178
|
+
`You MUST save progress NOW before continuing:\n` +
|
|
179
|
+
`1. Update DEVELOPMENT.md with current progress\n` +
|
|
180
|
+
`2. Write SESSION-HANDOFF.md with full current state and next steps\n` +
|
|
181
|
+
`3. Run /save "Handoff: 2nd compaction"\n` +
|
|
182
|
+
`4. Tell user: "Context compacted twice. Recommend starting fresh with /recap."\n\n` +
|
|
183
|
+
`Do this BEFORE any other work. After handoff, you may continue but expect degraded recall.`
|
|
184
|
+
);
|
|
185
|
+
} else {
|
|
186
|
+
allow(
|
|
187
|
+
`⚠️ Context compacting for the 2nd time. Earlier details are now a summary-of-a-summary.\n\n` +
|
|
188
|
+
`Strongly recommended: run /handoff now and start a fresh session with /recap.\n` +
|
|
189
|
+
`Continuing risks: forgetting decisions, re-reading files, repeating mistakes.`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 3rd+ compaction: force handoff
|
|
195
|
+
if (state.compactCount >= 3) {
|
|
196
|
+
if (yolo) {
|
|
197
|
+
allow(
|
|
198
|
+
`🛑 CONTEXT COMPACTING ${ordinal(state.compactCount)} TIME — session is degraded.\n\n` +
|
|
199
|
+
`IMMEDIATELY write handoff and stop:\n` +
|
|
200
|
+
`1. Update DEVELOPMENT.md with ALL current progress\n` +
|
|
201
|
+
`2. Write SESSION-HANDOFF.md with full state, pending tasks, and next steps\n` +
|
|
202
|
+
`3. Run /save "Auto-handoff: ${state.compactCount}x compacted"\n` +
|
|
203
|
+
`4. Tell user: "Context compacted ${state.compactCount} times. Start new conversation with /recap to continue."\n\n` +
|
|
204
|
+
`Do NOT continue working. Quality is too degraded.`
|
|
205
|
+
);
|
|
206
|
+
} else {
|
|
207
|
+
allow(
|
|
208
|
+
`🛑 Context compacting for the ${ordinal(state.compactCount)} time — session is significantly degraded.\n\n` +
|
|
209
|
+
`You should run /handoff and start fresh. Continuing will lead to:\n` +
|
|
210
|
+
`- Forgotten decisions and context\n` +
|
|
211
|
+
`- Re-reading files already read\n` +
|
|
212
|
+
`- Potential mistakes from lost context\n\n` +
|
|
213
|
+
`Please run /handoff now.`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ─── Layer 2: PostToolUse (Task) - agent call counter ──
|
|
220
|
+
if (event === 'PostToolUse' && data.tool_name === 'Task') {
|
|
221
|
+
state.toolCalls++;
|
|
222
|
+
saveState(projectRoot, state);
|
|
223
|
+
|
|
224
|
+
// Skip warnings if compact already fired (more urgent message already sent)
|
|
225
|
+
if (state.lastWarning === 'compact') {
|
|
226
|
+
allow();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Urgent warning
|
|
230
|
+
if (state.toolCalls === URGENT_WARNING_CALLS && state.lastWarning !== 'urgent') {
|
|
231
|
+
state.lastWarning = 'urgent';
|
|
232
|
+
saveState(projectRoot, state);
|
|
233
|
+
|
|
234
|
+
if (yolo) {
|
|
235
|
+
allow(
|
|
236
|
+
`⚠️ Context getting full: ${state.toolCalls} agent calls this session.\n\n` +
|
|
237
|
+
`Save progress NOW before auto-compaction hits:\n` +
|
|
238
|
+
`1. Update DEVELOPMENT.md with progress\n` +
|
|
239
|
+
`2. Write SESSION-HANDOFF.md\n` +
|
|
240
|
+
`3. Run /save\n` +
|
|
241
|
+
`Then continue working (or tell user to start fresh).`
|
|
242
|
+
);
|
|
243
|
+
} else {
|
|
244
|
+
allow(`📊 ${state.toolCalls} agent calls this session. Context may be getting full - consider /handoff.`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Early warning
|
|
249
|
+
if (state.toolCalls === EARLY_WARNING_CALLS && state.lastWarning === 'none') {
|
|
250
|
+
state.lastWarning = 'early';
|
|
251
|
+
saveState(projectRoot, state);
|
|
252
|
+
|
|
253
|
+
if (yolo) {
|
|
254
|
+
allow(`📊 Context check: ${state.toolCalls} agent calls. Consider saving progress with /save soon.`);
|
|
255
|
+
}
|
|
256
|
+
// Silent in non-yolo mode at early threshold
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
allow();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ─── Layer 3: Stop - safety net ────────────────────────
|
|
263
|
+
// Block stop if context was heavily compacted and no handoff written.
|
|
264
|
+
if (event === 'Stop') {
|
|
265
|
+
// Prevent infinite loop: if stop hook already active, let it through
|
|
266
|
+
if (data.stop_hook_active) {
|
|
267
|
+
allow();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// After 2+ compactions (any mode), block stop until handoff is written
|
|
271
|
+
const shouldBlock = state.compactCount >= 2 && state.stopBlocks < MAX_STOP_BLOCKS;
|
|
272
|
+
|
|
273
|
+
if (shouldBlock && !handoffRecentlyWritten(projectRoot)) {
|
|
274
|
+
state.stopBlocks++;
|
|
275
|
+
saveState(projectRoot, state);
|
|
276
|
+
block(
|
|
277
|
+
`Context was compacted ${state.compactCount} time(s) but no handoff found.\n\n` +
|
|
278
|
+
`Before stopping, you MUST:\n` +
|
|
279
|
+
`1. Write SESSION-HANDOFF.md with current state and next steps\n` +
|
|
280
|
+
`2. Update DEVELOPMENT.md with progress\n` +
|
|
281
|
+
`3. Run /save "Handoff: ${state.compactCount}x compacted"\n` +
|
|
282
|
+
`4. Tell user: "Session degraded after ${state.compactCount} compactions. Start fresh with /recap."`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
allow();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Default - unknown event, output safe empty JSON
|
|
290
|
+
console.log(JSON.stringify({}));
|
|
291
|
+
process.exit(0);
|
|
292
|
+
}
|