@rune-kit/rune 2.8.0 → 2.11.0
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/LICENSE +21 -21
- package/README.md +68 -34
- package/agents/adversary.md +27 -0
- package/agents/architect.md +19 -29
- package/agents/asset-creator.md +18 -4
- package/agents/audit.md +25 -4
- package/agents/autopsy.md +19 -4
- package/agents/ba.md +35 -0
- package/agents/brainstorm.md +31 -4
- package/agents/browser-pilot.md +21 -4
- package/agents/coder.md +21 -29
- package/agents/completion-gate.md +20 -4
- package/agents/constraint-check.md +18 -4
- package/agents/context-engine.md +22 -4
- package/agents/context-pack.md +32 -0
- package/agents/cook.md +41 -4
- package/agents/db.md +19 -4
- package/agents/debug.md +33 -4
- package/agents/dependency-doctor.md +20 -4
- package/agents/deploy.md +27 -4
- package/agents/design.md +22 -4
- package/agents/doc-processor.md +27 -0
- package/agents/docs-seeker.md +19 -4
- package/agents/docs.md +31 -0
- package/agents/fix.md +37 -4
- package/agents/git.md +29 -0
- package/agents/hallucination-guard.md +20 -4
- package/agents/incident.md +21 -4
- package/agents/integrity-check.md +18 -4
- package/agents/journal.md +19 -4
- package/agents/launch.md +32 -4
- package/agents/logic-guardian.md +26 -11
- package/agents/marketing.md +23 -4
- package/agents/mcp-builder.md +26 -0
- package/agents/neural-memory.md +30 -0
- package/agents/onboard.md +22 -4
- package/agents/perf.md +21 -4
- package/agents/plan.md +29 -4
- package/agents/preflight.md +22 -4
- package/agents/problem-solver.md +20 -4
- package/agents/rescue.md +23 -4
- package/agents/research.md +19 -4
- package/agents/researcher.md +19 -29
- package/agents/retro.md +32 -0
- package/agents/review-intake.md +20 -4
- package/agents/review.md +32 -4
- package/agents/reviewer.md +20 -28
- package/agents/safeguard.md +19 -4
- package/agents/sast.md +18 -4
- package/agents/scaffold.md +41 -0
- package/agents/scanner.md +19 -28
- package/agents/scope-guard.md +18 -4
- package/agents/scout.md +23 -4
- package/agents/sentinel-env.md +26 -0
- package/agents/sentinel.md +33 -4
- package/agents/sequential-thinking.md +20 -4
- package/agents/session-bridge.md +24 -4
- package/agents/skill-forge.md +22 -4
- package/agents/skill-router.md +26 -4
- package/agents/slides.md +24 -0
- package/agents/surgeon.md +19 -4
- package/agents/team.md +30 -4
- package/agents/test.md +36 -4
- package/agents/trend-scout.md +17 -4
- package/agents/verification.md +20 -4
- package/agents/video-creator.md +20 -4
- package/agents/watchdog.md +19 -4
- package/agents/worktree.md +17 -4
- package/commands/rune.md +168 -168
- package/compiler/__tests__/analytics.test.js +370 -0
- package/compiler/adapters/openclaw.js +2 -2
- package/compiler/analytics.js +385 -0
- package/compiler/bin/rune.js +68 -2
- package/compiler/dashboard.js +883 -0
- package/compiler/transforms/branding.js +1 -1
- package/contexts/dev.md +34 -34
- package/contexts/research.md +43 -43
- package/contexts/review.md +55 -55
- package/extensions/ai-ml/PACK.md +88 -88
- package/extensions/ai-ml/skills/ai-agents.md +172 -172
- package/extensions/ai-ml/skills/code-sandbox.md +187 -187
- package/extensions/ai-ml/skills/deep-research.md +146 -146
- package/extensions/ai-ml/skills/embedding-search.md +66 -66
- package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -74
- package/extensions/ai-ml/skills/llm-architect.md +125 -125
- package/extensions/ai-ml/skills/llm-integration.md +64 -64
- package/extensions/ai-ml/skills/prompt-patterns.md +72 -72
- package/extensions/ai-ml/skills/rag-patterns.md +66 -66
- package/extensions/ai-ml/skills/web-extraction.md +114 -114
- package/extensions/analytics/PACK.md +92 -92
- package/extensions/analytics/skills/ab-testing.md +72 -72
- package/extensions/analytics/skills/dashboard-patterns.md +83 -83
- package/extensions/analytics/skills/data-validation.md +68 -68
- package/extensions/analytics/skills/funnel-analysis.md +81 -81
- package/extensions/analytics/skills/sql-patterns.md +57 -57
- package/extensions/analytics/skills/statistical-analysis.md +79 -79
- package/extensions/analytics/skills/tracking-setup.md +71 -71
- package/extensions/backend/PACK.md +104 -104
- package/extensions/backend/skills/api-patterns.md +84 -84
- package/extensions/backend/skills/async-pipeline.md +193 -193
- package/extensions/backend/skills/auth-patterns.md +97 -97
- package/extensions/backend/skills/background-jobs.md +133 -133
- package/extensions/backend/skills/caching-patterns.md +108 -108
- package/extensions/backend/skills/cli-generation.md +133 -133
- package/extensions/backend/skills/database-patterns.md +87 -87
- package/extensions/backend/skills/middleware-patterns.md +104 -104
- package/extensions/chrome-ext/PACK.md +93 -93
- package/extensions/chrome-ext/skills/cws-preflight.md +143 -143
- package/extensions/chrome-ext/skills/cws-publish.md +104 -104
- package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -251
- package/extensions/chrome-ext/skills/ext-messaging.md +139 -139
- package/extensions/chrome-ext/skills/ext-storage.md +133 -133
- package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -164
- package/extensions/content/PACK.md +96 -96
- package/extensions/content/skills/blog-patterns.md +88 -88
- package/extensions/content/skills/cms-integration.md +131 -131
- package/extensions/content/skills/content-scoring.md +107 -107
- package/extensions/content/skills/i18n.md +83 -83
- package/extensions/content/skills/mdx-authoring.md +137 -137
- package/extensions/content/skills/reference.md +1014 -1014
- package/extensions/content/skills/seo-patterns.md +67 -67
- package/extensions/content/skills/video-repurpose.md +153 -153
- package/extensions/devops/PACK.md +101 -101
- package/extensions/devops/skills/chaos-testing.md +67 -67
- package/extensions/devops/skills/ci-cd.md +75 -75
- package/extensions/devops/skills/docker.md +58 -58
- package/extensions/devops/skills/edge-serverless.md +163 -163
- package/extensions/devops/skills/infra-as-code.md +158 -158
- package/extensions/devops/skills/kubernetes.md +110 -110
- package/extensions/devops/skills/monitoring.md +57 -57
- package/extensions/devops/skills/server-setup.md +64 -64
- package/extensions/devops/skills/ssl-domain.md +42 -42
- package/extensions/ecommerce/PACK.md +116 -116
- package/extensions/ecommerce/skills/cart-system.md +79 -79
- package/extensions/ecommerce/skills/inventory-mgmt.md +102 -102
- package/extensions/ecommerce/skills/order-management.md +126 -126
- package/extensions/ecommerce/skills/payment-integration.md +472 -472
- package/extensions/ecommerce/skills/shopify-dev.md +69 -69
- package/extensions/ecommerce/skills/subscription-billing.md +93 -93
- package/extensions/ecommerce/skills/tax-compliance.md +117 -117
- package/extensions/gamedev/PACK.md +142 -142
- package/extensions/gamedev/skills/asset-pipeline.md +74 -74
- package/extensions/gamedev/skills/audio-system.md +129 -129
- package/extensions/gamedev/skills/camera-system.md +87 -87
- package/extensions/gamedev/skills/ecs.md +98 -98
- package/extensions/gamedev/skills/game-loops.md +72 -72
- package/extensions/gamedev/skills/input-system.md +199 -199
- package/extensions/gamedev/skills/multiplayer.md +180 -180
- package/extensions/gamedev/skills/particles.md +105 -105
- package/extensions/gamedev/skills/physics-engine.md +89 -89
- package/extensions/gamedev/skills/scene-management.md +146 -146
- package/extensions/gamedev/skills/threejs-patterns.md +90 -90
- package/extensions/gamedev/skills/webgl.md +71 -71
- package/extensions/mobile/PACK.md +106 -106
- package/extensions/mobile/skills/app-store-connect.md +152 -152
- package/extensions/mobile/skills/app-store-prep.md +66 -66
- package/extensions/mobile/skills/deep-linking.md +109 -109
- package/extensions/mobile/skills/flutter.md +60 -60
- package/extensions/mobile/skills/ios-build-pipeline.md +142 -142
- package/extensions/mobile/skills/native-bridge.md +66 -66
- package/extensions/mobile/skills/ota-updates.md +97 -97
- package/extensions/mobile/skills/push-notifications.md +111 -111
- package/extensions/mobile/skills/react-native.md +82 -82
- package/extensions/saas/PACK.md +116 -116
- package/extensions/saas/skills/billing-integration.md +200 -200
- package/extensions/saas/skills/feature-flags.md +130 -130
- package/extensions/saas/skills/multi-tenant.md +103 -103
- package/extensions/saas/skills/onboarding-flow.md +139 -139
- package/extensions/saas/skills/subscription-flow.md +95 -95
- package/extensions/saas/skills/team-management.md +144 -144
- package/extensions/security/PACK.md +99 -99
- package/extensions/security/skills/api-security.md +140 -140
- package/extensions/security/skills/compliance.md +68 -68
- package/extensions/security/skills/owasp-audit.md +64 -64
- package/extensions/security/skills/pentest-patterns.md +77 -77
- package/extensions/security/skills/secret-mgmt.md +65 -65
- package/extensions/security/skills/supply-chain.md +65 -65
- package/extensions/trading/PACK.md +80 -80
- package/extensions/trading/skills/chart-components.md +55 -55
- package/extensions/trading/skills/experiment-loop.md +125 -125
- package/extensions/trading/skills/fintech-patterns.md +47 -47
- package/extensions/trading/skills/indicator-library.md +58 -58
- package/extensions/trading/skills/quant-analysis.md +111 -111
- package/extensions/trading/skills/realtime-data.md +58 -58
- package/extensions/trading/skills/trade-logic.md +104 -104
- package/extensions/ui/PACK.md +130 -130
- package/extensions/ui/skills/a11y-audit.md +91 -91
- package/extensions/ui/skills/animation-patterns.md +127 -106
- package/extensions/ui/skills/component-patterns.md +100 -75
- package/extensions/ui/skills/design-decision.md +108 -108
- package/extensions/ui/skills/design-system.md +68 -68
- package/extensions/ui/skills/landing-patterns.md +155 -155
- package/extensions/ui/skills/palette-picker.md +173 -173
- package/extensions/ui/skills/react-health.md +90 -90
- package/extensions/ui/skills/type-system.md +125 -125
- package/extensions/ui/skills/web-vitals.md +153 -153
- package/extensions/zalo/PACK.md +145 -145
- package/extensions/zalo/skills/zalo-oa-mcp.md +317 -317
- package/extensions/zalo/skills/zalo-oa-messaging.md +429 -429
- package/extensions/zalo/skills/zalo-oa-setup.md +236 -236
- package/extensions/zalo/skills/zalo-oa-webhook.md +189 -189
- package/extensions/zalo/skills/zalo-personal-messaging.md +194 -194
- package/extensions/zalo/skills/zalo-personal-setup.md +153 -153
- package/extensions/zalo/skills/zalo-rate-guard.md +219 -219
- package/hooks/auto-format/index.cjs +48 -48
- package/hooks/context-watch/index.cjs +95 -68
- package/hooks/hooks.json +111 -111
- package/hooks/metrics-collector/index.cjs +86 -42
- package/hooks/post-session-reflect/index.cjs +189 -153
- package/hooks/pre-compact/index.cjs +95 -95
- package/hooks/run-hook.cmd +1 -1
- package/hooks/secrets-scan/index.cjs +100 -100
- package/hooks/session-start/index.cjs +71 -65
- package/hooks/typecheck/index.cjs +65 -65
- package/package.json +63 -63
- package/references/ui-pro-max-data/LICENSE-UI-PRO-MAX +21 -21
- package/references/ui-pro-max-data/charts.csv +26 -26
- package/references/ui-pro-max-data/colors.csv +161 -161
- package/references/ui-pro-max-data/styles.csv +68 -68
- package/references/ui-pro-max-data/typography.csv +74 -74
- package/references/ui-pro-max-data/ui-reasoning.csv +162 -162
- package/references/ui-pro-max-data/ux-guidelines.csv +99 -99
- package/skills/adversary/SKILL.md +283 -283
- package/skills/asset-creator/SKILL.md +157 -157
- package/skills/audit/SKILL.md +148 -2
- package/skills/autopsy/SKILL.md +335 -259
- package/skills/autopsy/references/repo-analysis-patterns.md +113 -0
- package/skills/ba/SKILL.md +72 -2
- package/skills/brainstorm/SKILL.md +342 -341
- package/skills/browser-pilot/SKILL.md +168 -168
- package/skills/constraint-check/SKILL.md +165 -165
- package/skills/context-engine/SKILL.md +404 -404
- package/skills/cook/SKILL.md +917 -834
- package/skills/cook/references/output-format.md +33 -0
- package/skills/db/SKILL.md +273 -272
- package/skills/debug/SKILL.md +465 -443
- package/skills/dependency-doctor/SKILL.md +265 -235
- package/skills/deploy/SKILL.md +274 -231
- package/skills/design/DESIGN-REFERENCE.md +365 -365
- package/skills/design/SKILL.md +589 -482
- package/skills/doc-processor/SKILL.md +254 -254
- package/skills/docs/SKILL.md +374 -373
- package/skills/docs-seeker/SKILL.md +177 -177
- package/skills/fix/SKILL.md +330 -308
- package/skills/git/SKILL.md +339 -339
- package/skills/graft/SKILL.md +352 -0
- package/skills/graft/references/challenge-framework.md +98 -0
- package/skills/graft/references/mode-decision.md +44 -0
- package/skills/hallucination-guard/SKILL.md +219 -219
- package/skills/incident/SKILL.md +254 -251
- package/skills/integrity-check/SKILL.md +169 -169
- package/skills/journal/SKILL.md +240 -238
- package/skills/launch/SKILL.md +344 -342
- package/skills/logic-guardian/SKILL.md +251 -251
- package/skills/marketing/SKILL.md +290 -245
- package/skills/mcp-builder/SKILL.md +425 -423
- package/skills/mcp-builder/references/auto-discovery-pattern.md +169 -0
- package/skills/neural-memory/SKILL.md +362 -362
- package/skills/onboard/SKILL.md +404 -403
- package/skills/perf/SKILL.md +346 -346
- package/skills/plan/SKILL.md +433 -370
- package/skills/plan/references/feature-map.md +84 -0
- package/skills/preflight/SKILL.md +415 -396
- package/skills/problem-solver/SKILL.md +380 -284
- package/skills/rescue/SKILL.md +474 -450
- package/skills/retro/SKILL.md +5 -1
- package/skills/review/SKILL.md +612 -535
- package/skills/review-intake/SKILL.md +249 -249
- package/skills/safeguard/SKILL.md +200 -200
- package/skills/sast/SKILL.md +190 -190
- package/skills/scaffold/SKILL.md +328 -286
- package/skills/scope-guard/SKILL.md +180 -162
- package/skills/scout/SKILL.md +263 -263
- package/skills/sentinel/SKILL.md +382 -353
- package/skills/sentinel-env/SKILL.md +254 -254
- package/skills/sequential-thinking/SKILL.md +234 -234
- package/skills/session-bridge/SKILL.md +543 -397
- package/skills/skill-forge/SKILL.md +581 -539
- package/skills/skill-router/{skill.md → SKILL.md} +30 -2
- package/skills/surgeon/SKILL.md +215 -215
- package/skills/team/SKILL.md +556 -514
- package/skills/test/SKILL.md +614 -587
- package/skills/trend-scout/SKILL.md +145 -145
- package/skills/verification/SKILL.md +326 -325
- package/skills/video-creator/SKILL.md +201 -201
- package/skills/watchdog/SKILL.md +168 -168
- package/skills/worktree/SKILL.md +140 -140
|
@@ -1,153 +1,189 @@
|
|
|
1
|
-
// Rune Post-Session Reflect Hook
|
|
2
|
-
// 1. Flushes session metrics from tmpdir to .rune/metrics/ (H3 Intelligence)
|
|
3
|
-
// 2. Displays structured self-review checklist at session end (Stop event)
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const os = require('os');
|
|
8
|
-
|
|
9
|
-
const cwd = process.cwd();
|
|
10
|
-
const hash = Buffer.from(cwd).toString('base64url').slice(0, 16);
|
|
11
|
-
|
|
12
|
-
// === H3: Flush Session Metrics ===
|
|
13
|
-
|
|
14
|
-
const metricsJsonl = path.join(os.tmpdir(), `rune-metrics-${hash}.jsonl`);
|
|
15
|
-
const counterFile = path.join(os.tmpdir(), `rune-context-watch-${hash}.json`);
|
|
16
|
-
const runeMetricsDir = path.join(cwd, '.rune', 'metrics');
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
//
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
1
|
+
// Rune Post-Session Reflect Hook
|
|
2
|
+
// 1. Flushes session metrics from tmpdir to .rune/metrics/ (H3 Intelligence)
|
|
3
|
+
// 2. Displays structured self-review checklist at session end (Stop event)
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
const cwd = process.cwd();
|
|
10
|
+
const hash = Buffer.from(cwd).toString('base64url').slice(0, 16);
|
|
11
|
+
|
|
12
|
+
// === H3: Flush Session Metrics ===
|
|
13
|
+
|
|
14
|
+
const metricsJsonl = path.join(os.tmpdir(), `rune-metrics-${hash}.jsonl`);
|
|
15
|
+
const counterFile = path.join(os.tmpdir(), `rune-context-watch-${hash}.json`);
|
|
16
|
+
const runeMetricsDir = path.join(cwd, '.rune', 'metrics');
|
|
17
|
+
|
|
18
|
+
// Resolve skill names → expected model from agent frontmatter
|
|
19
|
+
// Reads agents/*.md at flush time — no runtime model detection needed
|
|
20
|
+
// Map skill names → models, weighted by invocation count
|
|
21
|
+
// skillCounts: { skillName: invocationCount }
|
|
22
|
+
function resolveSkillModels(skillCounts) {
|
|
23
|
+
const models = {};
|
|
24
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.join(__dirname, '..', '..');
|
|
25
|
+
const agentsDir = path.join(pluginRoot, 'agents');
|
|
26
|
+
|
|
27
|
+
if (!fs.existsSync(agentsDir)) return models;
|
|
28
|
+
|
|
29
|
+
for (const [skill, count] of Object.entries(skillCounts)) {
|
|
30
|
+
try {
|
|
31
|
+
const agentFile = path.join(agentsDir, `${skill}.md`);
|
|
32
|
+
if (!fs.existsSync(agentFile)) continue;
|
|
33
|
+
const content = fs.readFileSync(agentFile, 'utf-8');
|
|
34
|
+
const match = content.match(/^model:\s*(\w+)/m);
|
|
35
|
+
if (match) {
|
|
36
|
+
const model = match[1];
|
|
37
|
+
models[model] = (models[model] || 0) + count;
|
|
38
|
+
}
|
|
39
|
+
} catch { /* best-effort */ }
|
|
40
|
+
}
|
|
41
|
+
return models;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
flushMetrics();
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// Metrics flush is best-effort — never block session end
|
|
48
|
+
// Silently ignore errors
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function flushMetrics() {
|
|
52
|
+
// Read session skill invocations from tmpdir JSONL
|
|
53
|
+
let skillEvents = [];
|
|
54
|
+
if (fs.existsSync(metricsJsonl)) {
|
|
55
|
+
const lines = fs.readFileSync(metricsJsonl, 'utf-8').trim().split('\n').filter(Boolean);
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
try { skillEvents.push(JSON.parse(line)); } catch { /* skip malformed */ }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Read context-watch state for tool counts and session timing
|
|
62
|
+
let watchState = { count: 0, sessionStart: null, sessionId: null, toolCounts: {} };
|
|
63
|
+
if (fs.existsSync(counterFile)) {
|
|
64
|
+
try {
|
|
65
|
+
watchState = JSON.parse(fs.readFileSync(counterFile, 'utf-8'));
|
|
66
|
+
} catch { /* use defaults */ }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Nothing to flush if no data
|
|
70
|
+
if (skillEvents.length === 0 && watchState.count === 0) return;
|
|
71
|
+
|
|
72
|
+
// Ensure .rune/metrics/ exists
|
|
73
|
+
fs.mkdirSync(runeMetricsDir, { recursive: true });
|
|
74
|
+
|
|
75
|
+
const now = new Date().toISOString();
|
|
76
|
+
const sessionStart = watchState.sessionStart || now;
|
|
77
|
+
const durationMin = Math.round((new Date(now) - new Date(sessionStart)) / 60000);
|
|
78
|
+
|
|
79
|
+
// Build skill usage map and duration aggregation
|
|
80
|
+
const skillCounts = {};
|
|
81
|
+
const skillDurations = {};
|
|
82
|
+
const skillChain = [];
|
|
83
|
+
for (const evt of skillEvents) {
|
|
84
|
+
skillCounts[evt.skill] = (skillCounts[evt.skill] || 0) + 1;
|
|
85
|
+
skillChain.push(evt.skill);
|
|
86
|
+
if (evt.duration_ms != null) {
|
|
87
|
+
skillDurations[evt.skill] = (skillDurations[evt.skill] || 0) + evt.duration_ms;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Determine primary skill (most invoked)
|
|
92
|
+
const primarySkill = Object.entries(skillCounts)
|
|
93
|
+
.sort((a, b) => b[1] - a[1])[0]?.[0] || 'none';
|
|
94
|
+
|
|
95
|
+
// Map skills to expected models from agent definitions (weighted by invocation count)
|
|
96
|
+
const modelsUsed = resolveSkillModels(skillCounts);
|
|
97
|
+
|
|
98
|
+
// Use session ID from context-watch (shared) or generate new
|
|
99
|
+
const sessionId = watchState.sessionId
|
|
100
|
+
|| `s-${now.slice(0, 10).replace(/-/g, '')}-${now.slice(11, 19).replace(/:/g, '')}`;
|
|
101
|
+
|
|
102
|
+
// 1. Append to sessions.jsonl
|
|
103
|
+
const sessionEntry = {
|
|
104
|
+
id: sessionId,
|
|
105
|
+
date: now.slice(0, 10),
|
|
106
|
+
duration_min: durationMin,
|
|
107
|
+
tool_calls: watchState.count,
|
|
108
|
+
tool_distribution: watchState.toolCounts,
|
|
109
|
+
skill_invocations: skillEvents.length,
|
|
110
|
+
skills_used: Object.keys(skillCounts),
|
|
111
|
+
primary_skill: primarySkill,
|
|
112
|
+
models_used: modelsUsed,
|
|
113
|
+
skill_durations: Object.keys(skillDurations).length > 0 ? skillDurations : undefined
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const sessionsFile = path.join(runeMetricsDir, 'sessions.jsonl');
|
|
117
|
+
fs.appendFileSync(sessionsFile, JSON.stringify(sessionEntry) + '\n');
|
|
118
|
+
|
|
119
|
+
// Cap at 100 sessions (rotate oldest)
|
|
120
|
+
try {
|
|
121
|
+
const allLines = fs.readFileSync(sessionsFile, 'utf-8').trim().split('\n').filter(Boolean);
|
|
122
|
+
if (allLines.length > 100) {
|
|
123
|
+
fs.writeFileSync(sessionsFile, allLines.slice(-100).join('\n') + '\n');
|
|
124
|
+
}
|
|
125
|
+
} catch { /* cap is best-effort */ }
|
|
126
|
+
|
|
127
|
+
// 2. Merge into skills.json (running totals)
|
|
128
|
+
const skillsFile = path.join(runeMetricsDir, 'skills.json');
|
|
129
|
+
let skillsData = { version: 1, updated: now, skills: {} };
|
|
130
|
+
if (fs.existsSync(skillsFile)) {
|
|
131
|
+
try {
|
|
132
|
+
skillsData = JSON.parse(fs.readFileSync(skillsFile, 'utf-8'));
|
|
133
|
+
} catch { /* start fresh */ }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (const [skill, count] of Object.entries(skillCounts)) {
|
|
137
|
+
if (!skillsData.skills[skill]) {
|
|
138
|
+
skillsData.skills[skill] = { total_invocations: 0, last_used: now.slice(0, 10) };
|
|
139
|
+
}
|
|
140
|
+
skillsData.skills[skill].total_invocations += count;
|
|
141
|
+
skillsData.skills[skill].last_used = now.slice(0, 10);
|
|
142
|
+
}
|
|
143
|
+
skillsData.updated = now;
|
|
144
|
+
|
|
145
|
+
fs.writeFileSync(skillsFile, JSON.stringify(skillsData, null, 2) + '\n');
|
|
146
|
+
|
|
147
|
+
// 3. Append to chains.jsonl
|
|
148
|
+
if (skillChain.length > 0) {
|
|
149
|
+
const chainsFile = path.join(runeMetricsDir, 'chains.jsonl');
|
|
150
|
+
const chainEntry = {
|
|
151
|
+
session: sessionId,
|
|
152
|
+
chain: skillChain,
|
|
153
|
+
depth: skillChain.length
|
|
154
|
+
};
|
|
155
|
+
fs.appendFileSync(chainsFile, JSON.stringify(chainEntry) + '\n');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 4. Cleanup tmpdir files
|
|
159
|
+
try { fs.unlinkSync(metricsJsonl); } catch { /* already gone */ }
|
|
160
|
+
// Note: counterFile is cleaned by session-start hook on next session
|
|
161
|
+
|
|
162
|
+
// Report metrics flush
|
|
163
|
+
const skillList = Object.entries(skillCounts)
|
|
164
|
+
.sort((a, b) => b[1] - a[1])
|
|
165
|
+
.map(([s, c]) => `${s}(${c})`)
|
|
166
|
+
.join(', ');
|
|
167
|
+
|
|
168
|
+
console.log(`\n📊 [Rune metrics] Session ${sessionId} — ${durationMin}min, ${watchState.count} tool calls, ${skillEvents.length} skill invocations`);
|
|
169
|
+
if (skillList) console.log(` Skills: ${skillList}`);
|
|
170
|
+
console.log(` Saved to .rune/metrics/\n`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// === Original: Verification Checklist ===
|
|
174
|
+
|
|
175
|
+
console.log(`
|
|
176
|
+
┌─────────────────────────────────────────────────────┐
|
|
177
|
+
│ Rune Session End — Verification Checklist │
|
|
178
|
+
├─────────────────────────────────────────────────────┤
|
|
179
|
+
│ Before closing this session, confirm: │
|
|
180
|
+
│ │
|
|
181
|
+
│ □ All TodoWrite tasks marked complete? │
|
|
182
|
+
│ □ Tests ran and passing? │
|
|
183
|
+
│ □ No hardcoded secrets introduced? │
|
|
184
|
+
│ □ If schema changed: migration + rollback exist? │
|
|
185
|
+
│ □ Verification ran (lint + types + build)? │
|
|
186
|
+
│ │
|
|
187
|
+
│ If any item is unclear → address it now. │
|
|
188
|
+
└─────────────────────────────────────────────────────┘
|
|
189
|
+
`);
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
// Rune Pre-Compact Hook
|
|
2
|
-
// Saves critical state BEFORE Claude auto-compacts context window.
|
|
3
|
-
// Prevents data loss from losing decisions, progress, and metrics mid-session.
|
|
4
|
-
//
|
|
5
|
-
// Captures: context-watch state, active task summary, decisions made this session.
|
|
6
|
-
// Writes snapshot to .rune/pre-compact-snapshot.md for post-compact recovery.
|
|
7
|
-
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const os = require('os');
|
|
11
|
-
|
|
12
|
-
const cwd = process.cwd();
|
|
13
|
-
const runeDir = path.join(cwd, '.rune');
|
|
14
|
-
|
|
15
|
-
// Read context-watch state (tool counts, session timing)
|
|
16
|
-
const hash = Buffer.from(cwd).toString('base64url').slice(0, 16);
|
|
17
|
-
const counterFile = path.join(os.tmpdir(), `rune-context-watch-${hash}.json`);
|
|
18
|
-
|
|
19
|
-
let watchState = null;
|
|
20
|
-
try {
|
|
21
|
-
const raw = fs.readFileSync(counterFile, 'utf-8');
|
|
22
|
-
watchState = JSON.parse(raw);
|
|
23
|
-
} catch {
|
|
24
|
-
// No counter file — session may be fresh
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Collect .rune/ state summaries
|
|
28
|
-
const stateFiles = ['progress.md', 'decisions.md', 'conventions.md'];
|
|
29
|
-
const summaries = [];
|
|
30
|
-
|
|
31
|
-
if (fs.existsSync(runeDir)) {
|
|
32
|
-
for (const file of stateFiles) {
|
|
33
|
-
const filePath = path.join(runeDir, file);
|
|
34
|
-
if (fs.existsSync(filePath)) {
|
|
35
|
-
try {
|
|
36
|
-
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
|
37
|
-
if (content.length > 0) {
|
|
38
|
-
// Take first 50 lines to keep snapshot compact
|
|
39
|
-
const lines = content.split('\n').slice(0, 50);
|
|
40
|
-
summaries.push({ file, preview: lines.join('\n') });
|
|
41
|
-
}
|
|
42
|
-
} catch {
|
|
43
|
-
// Skip unreadable files
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Build snapshot
|
|
50
|
-
const snapshot = [];
|
|
51
|
-
snapshot.push('# Pre-Compact Snapshot');
|
|
52
|
-
snapshot.push(`Generated: ${new Date().toISOString()}`);
|
|
53
|
-
snapshot.push('');
|
|
54
|
-
|
|
55
|
-
if (watchState) {
|
|
56
|
-
snapshot.push('## Session Metrics');
|
|
57
|
-
snapshot.push(`- Tool calls: ${watchState.count || 0}`);
|
|
58
|
-
snapshot.push(`- Session start: ${watchState.sessionStart || 'unknown'}`);
|
|
59
|
-
if (watchState.toolCounts) {
|
|
60
|
-
const top5 = Object.entries(watchState.toolCounts)
|
|
61
|
-
.sort((a, b) => b[1] - a[1])
|
|
62
|
-
.slice(0, 5);
|
|
63
|
-
snapshot.push(`- Top tools: ${top5.map(([k, v]) => `${k}(${v})`).join(', ')}`);
|
|
64
|
-
}
|
|
65
|
-
snapshot.push('');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (summaries.length > 0) {
|
|
69
|
-
snapshot.push('## State Files (preview)');
|
|
70
|
-
for (const { file, preview } of summaries) {
|
|
71
|
-
snapshot.push(`### .rune/${file}`);
|
|
72
|
-
snapshot.push(preview);
|
|
73
|
-
snapshot.push('');
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Write snapshot if we have anything worth saving
|
|
78
|
-
if (watchState || summaries.length > 0) {
|
|
79
|
-
try {
|
|
80
|
-
if (!fs.existsSync(runeDir)) {
|
|
81
|
-
fs.mkdirSync(runeDir, { recursive: true });
|
|
82
|
-
}
|
|
83
|
-
fs.writeFileSync(
|
|
84
|
-
path.join(runeDir, 'pre-compact-snapshot.md'),
|
|
85
|
-
snapshot.join('\n')
|
|
86
|
-
);
|
|
87
|
-
console.log(`[Rune pre-compact] State snapshot saved (${watchState ? watchState.count : 0} tool calls, ${summaries.length} state files).`);
|
|
88
|
-
} catch (e) {
|
|
89
|
-
console.error(`[Rune pre-compact] Failed to save snapshot: ${e.message}`);
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
console.log('[Rune pre-compact] No state to snapshot — fresh session.');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
process.exit(0);
|
|
1
|
+
// Rune Pre-Compact Hook
|
|
2
|
+
// Saves critical state BEFORE Claude auto-compacts context window.
|
|
3
|
+
// Prevents data loss from losing decisions, progress, and metrics mid-session.
|
|
4
|
+
//
|
|
5
|
+
// Captures: context-watch state, active task summary, decisions made this session.
|
|
6
|
+
// Writes snapshot to .rune/pre-compact-snapshot.md for post-compact recovery.
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const runeDir = path.join(cwd, '.rune');
|
|
14
|
+
|
|
15
|
+
// Read context-watch state (tool counts, session timing)
|
|
16
|
+
const hash = Buffer.from(cwd).toString('base64url').slice(0, 16);
|
|
17
|
+
const counterFile = path.join(os.tmpdir(), `rune-context-watch-${hash}.json`);
|
|
18
|
+
|
|
19
|
+
let watchState = null;
|
|
20
|
+
try {
|
|
21
|
+
const raw = fs.readFileSync(counterFile, 'utf-8');
|
|
22
|
+
watchState = JSON.parse(raw);
|
|
23
|
+
} catch {
|
|
24
|
+
// No counter file — session may be fresh
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Collect .rune/ state summaries
|
|
28
|
+
const stateFiles = ['progress.md', 'decisions.md', 'conventions.md'];
|
|
29
|
+
const summaries = [];
|
|
30
|
+
|
|
31
|
+
if (fs.existsSync(runeDir)) {
|
|
32
|
+
for (const file of stateFiles) {
|
|
33
|
+
const filePath = path.join(runeDir, file);
|
|
34
|
+
if (fs.existsSync(filePath)) {
|
|
35
|
+
try {
|
|
36
|
+
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
|
37
|
+
if (content.length > 0) {
|
|
38
|
+
// Take first 50 lines to keep snapshot compact
|
|
39
|
+
const lines = content.split('\n').slice(0, 50);
|
|
40
|
+
summaries.push({ file, preview: lines.join('\n') });
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// Skip unreadable files
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Build snapshot
|
|
50
|
+
const snapshot = [];
|
|
51
|
+
snapshot.push('# Pre-Compact Snapshot');
|
|
52
|
+
snapshot.push(`Generated: ${new Date().toISOString()}`);
|
|
53
|
+
snapshot.push('');
|
|
54
|
+
|
|
55
|
+
if (watchState) {
|
|
56
|
+
snapshot.push('## Session Metrics');
|
|
57
|
+
snapshot.push(`- Tool calls: ${watchState.count || 0}`);
|
|
58
|
+
snapshot.push(`- Session start: ${watchState.sessionStart || 'unknown'}`);
|
|
59
|
+
if (watchState.toolCounts) {
|
|
60
|
+
const top5 = Object.entries(watchState.toolCounts)
|
|
61
|
+
.sort((a, b) => b[1] - a[1])
|
|
62
|
+
.slice(0, 5);
|
|
63
|
+
snapshot.push(`- Top tools: ${top5.map(([k, v]) => `${k}(${v})`).join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
snapshot.push('');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (summaries.length > 0) {
|
|
69
|
+
snapshot.push('## State Files (preview)');
|
|
70
|
+
for (const { file, preview } of summaries) {
|
|
71
|
+
snapshot.push(`### .rune/${file}`);
|
|
72
|
+
snapshot.push(preview);
|
|
73
|
+
snapshot.push('');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Write snapshot if we have anything worth saving
|
|
78
|
+
if (watchState || summaries.length > 0) {
|
|
79
|
+
try {
|
|
80
|
+
if (!fs.existsSync(runeDir)) {
|
|
81
|
+
fs.mkdirSync(runeDir, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
fs.writeFileSync(
|
|
84
|
+
path.join(runeDir, 'pre-compact-snapshot.md'),
|
|
85
|
+
snapshot.join('\n')
|
|
86
|
+
);
|
|
87
|
+
console.log(`[Rune pre-compact] State snapshot saved (${watchState ? watchState.count : 0} tool calls, ${summaries.length} state files).`);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.error(`[Rune pre-compact] Failed to save snapshot: ${e.message}`);
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
console.log('[Rune pre-compact] No state to snapshot — fresh session.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.exit(0);
|
package/hooks/run-hook.cmd
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@node "%~dp0run-hook.js" %*
|
|
1
|
+
@node "%~dp0run-hook.js" %*
|