@bolloon/bolloon-agent 0.1.13 → 0.1.15

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 (47) hide show
  1. package/dist/agents/pi-sdk.js +222 -9
  2. package/dist/agents/shell-guard.js +354 -0
  3. package/dist/agents/shell-tool.js +83 -0
  4. package/dist/agents/skill-loader.js +174 -0
  5. package/dist/bollharness-integration/context-chain-router.js +3 -3
  6. package/dist/bollharness-integration/context-router.js +1 -1
  7. package/dist/heartbeat/Watchdog.js +7 -5
  8. package/dist/heartbeat/index.js +1 -0
  9. package/dist/heartbeat/self-improve-bus.js +85 -0
  10. package/dist/pi-ecosystem-judgment/index.js +1 -2
  11. package/dist/utils/auto-update.js +44 -12
  12. package/dist/web/client.js +841 -103
  13. package/dist/web/index.html +88 -8
  14. package/dist/web/style.css +506 -9
  15. package/package.json +2 -2
  16. package/scripts/build-cli.js +11 -1
  17. package/src/agents/pi-sdk.ts +230 -10
  18. package/src/agents/shell-guard.ts +417 -0
  19. package/src/agents/shell-tool.ts +103 -0
  20. package/src/agents/skill-loader.ts +202 -0
  21. package/src/bollharness-integration/context-chain-router.ts +3 -3
  22. package/src/bollharness-integration/context-router.ts +1 -1
  23. package/src/heartbeat/Watchdog.ts +7 -5
  24. package/src/heartbeat/index.ts +1 -0
  25. package/src/heartbeat/self-improve-bus.ts +110 -0
  26. package/src/types.d.ts +12 -0
  27. package/src/utils/auto-update.ts +45 -14
  28. package/src/web/client.js +841 -103
  29. package/src/web/index.html +88 -8
  30. package/src/web/server.ts +427 -101
  31. package/src/web/style.css +506 -9
  32. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.d.ts +0 -48
  33. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.js +0 -261
  34. package/dist/bollharness-integration/bollharness-integration/context-router.d.ts +0 -110
  35. package/dist/bollharness-integration/bollharness-integration/context-router.js +0 -542
  36. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.d.ts +0 -87
  37. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.js +0 -231
  38. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.d.ts +0 -30
  39. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.js +0 -91
  40. package/dist/bollharness-integration/bollharness-integration/guard-checker.d.ts +0 -105
  41. package/dist/bollharness-integration/bollharness-integration/guard-checker.js +0 -353
  42. package/dist/bollharness-integration/bollharness-integration/index.d.ts +0 -66
  43. package/dist/bollharness-integration/bollharness-integration/index.js +0 -32
  44. package/dist/bollharness-integration/bollharness-integration/integration.d.ts +0 -219
  45. package/dist/bollharness-integration/bollharness-integration/integration.js +0 -420
  46. package/dist/bollharness-integration/bollharness-integration/skill-adapter.d.ts +0 -151
  47. package/dist/bollharness-integration/bollharness-integration/skill-adapter.js +0 -518
@@ -1,420 +0,0 @@
1
- /**
2
- * Bollharness Integration for Bolloon
3
- *
4
- * Main integration class that combines:
5
- * - Gate State Machine (8-gate workflow governance)
6
- * - Guard Checker (code quality checks)
7
- * - Context Router (automatic context injection)
8
- * - Skill Adapter (bollharness skills in Bolloon)
9
- */
10
- import { GateStateMachine } from './gate-state-machine.js';
11
- import { GuardChecker, runGuards } from './guard-checker.js';
12
- import { ContextRouter } from './context-router.js';
13
- import { createSkillAdapter } from './skill-adapter.js';
14
- /**
15
- * Main integration class
16
- */
17
- export class BollharnessIntegration {
18
- config;
19
- gateMachine;
20
- guardChecker;
21
- contextRouter;
22
- skillAdapter;
23
- sessionArchives = [];
24
- currentSessionId = '';
25
- constructor(config = {}) {
26
- this.config = {
27
- enabled: config.enabled ?? true,
28
- guardsEnabled: config.guardsEnabled ?? true,
29
- contextEnabled: config.contextEnabled ?? true,
30
- skillsEnabled: config.skillsEnabled ?? true,
31
- gatesEnabled: config.gatesEnabled ?? true,
32
- };
33
- this.gateMachine = new GateStateMachine();
34
- this.guardChecker = new GuardChecker();
35
- this.contextRouter = new ContextRouter();
36
- this.skillAdapter = createSkillAdapter();
37
- }
38
- /**
39
- * Process a file edit with all enabled checks
40
- */
41
- async processFileEdit(filePath) {
42
- const errors = [];
43
- let guards;
44
- let context;
45
- // Run guards if enabled
46
- if (this.config.guardsEnabled) {
47
- try {
48
- guards = await runGuards(filePath);
49
- if (!guards.passed) {
50
- errors.push(...guards.findings.map(f => f.message));
51
- }
52
- }
53
- catch (error) {
54
- errors.push(`Guard check failed: ${error}`);
55
- }
56
- }
57
- // Get context fragments if enabled
58
- if (this.config.contextEnabled) {
59
- try {
60
- context = this.contextRouter.match(filePath);
61
- }
62
- catch (error) {
63
- errors.push(`Context routing failed: ${error}`);
64
- }
65
- }
66
- return {
67
- success: errors.length === 0,
68
- guards,
69
- context,
70
- errors,
71
- };
72
- }
73
- /**
74
- * Check file before edit (pre-check)
75
- */
76
- async preEditCheck(filePath) {
77
- const errors = [];
78
- let guards;
79
- if (this.config.guardsEnabled) {
80
- try {
81
- guards = await runGuards(filePath);
82
- if (!guards.passed && guards.blockingCount > 0) {
83
- errors.push(...guards.findings
84
- .filter(f => f.blocking)
85
- .map(f => `BLOCKING: ${f.message}`));
86
- }
87
- }
88
- catch (error) {
89
- errors.push(`Pre-check failed: ${error}`);
90
- }
91
- }
92
- return {
93
- success: errors.length === 0,
94
- guards,
95
- errors,
96
- };
97
- }
98
- /**
99
- * Get context for a file
100
- */
101
- getContext(filePath) {
102
- if (!this.config.contextEnabled) {
103
- return '';
104
- }
105
- return this.contextRouter.getContext(filePath);
106
- }
107
- /**
108
- * Get fragments for a file
109
- */
110
- getFragments(filePath) {
111
- return this.contextRouter.match(filePath);
112
- }
113
- // ==================== Gate Methods ====================
114
- /**
115
- * Get current gate state
116
- */
117
- getCurrentGate() {
118
- return this.gateMachine.getCurrentGate();
119
- }
120
- /**
121
- * Get gate pack for output
122
- */
123
- getGatePack() {
124
- return this.gateMachine.getGatePack();
125
- }
126
- /**
127
- * Submit artifact to current gate
128
- */
129
- submitGateArtifact(name, artifact) {
130
- this.gateMachine.submitArtifact(name, artifact);
131
- }
132
- /**
133
- * Attempt gate transition
134
- */
135
- async transitionGate(reviewResult) {
136
- const transition = await this.gateMachine.transition(reviewResult);
137
- return {
138
- success: transition.blockers.length === 0,
139
- transition,
140
- };
141
- }
142
- /**
143
- * Classify change type
144
- */
145
- classifyChange(description) {
146
- const isPolicy = description.includes('policy') || description.includes('boundary');
147
- const isContract = description.includes('API') || description.includes('contract');
148
- const isImplementation = !isPolicy && !isContract;
149
- return {
150
- classification: isPolicy ? 'policy' : isContract ? 'contract' : 'implementation',
151
- minimum_gates: isPolicy ? '0→8' : isContract ? '0→8' : '0→7',
152
- fast_track: isImplementation,
153
- };
154
- }
155
- // ==================== Skill Methods ====================
156
- /**
157
- * Execute a bollharness skill
158
- */
159
- async executeSkill(skillName, params) {
160
- try {
161
- const result = await this.skillAdapter.executeSkill(skillName, params);
162
- return { success: true, result };
163
- }
164
- catch (error) {
165
- return { success: false, error: String(error) };
166
- }
167
- }
168
- /**
169
- * List available skills
170
- */
171
- listSkills() {
172
- return this.skillAdapter.listSkills().map(s => ({
173
- name: s.name,
174
- description: s.description,
175
- }));
176
- }
177
- /**
178
- * Get skill registry
179
- */
180
- getSkillAdapter() {
181
- return this.skillAdapter;
182
- }
183
- /**
184
- * List harness-native skills (metadata from SKILL.md files)
185
- */
186
- listHarnessSkills() {
187
- return this.skillAdapter.listHarnessSkills().map(s => ({
188
- name: s.name,
189
- description: s.description,
190
- tier: s.tier,
191
- }));
192
- }
193
- // ==================== Configuration Methods ====================
194
- /**
195
- * Update configuration
196
- */
197
- updateConfig(config) {
198
- this.config = { ...this.config, ...config };
199
- }
200
- /**
201
- * Get current configuration
202
- */
203
- getConfig() {
204
- return { ...this.config };
205
- }
206
- /**
207
- * Enable/disable specific checks
208
- */
209
- enableCheck(checkName) {
210
- this.guardChecker.enableCheck(checkName);
211
- }
212
- disableCheck(checkName) {
213
- this.guardChecker.disableCheck(checkName);
214
- }
215
- // ==================== Metrics ====================
216
- /**
217
- * Get integration metrics
218
- */
219
- getMetrics() {
220
- return {
221
- config: this.config,
222
- currentGate: this.gateMachine.getCurrentGate(),
223
- enabledChecks: 'multiple',
224
- availableSkills: this.skillAdapter.listSkills().length,
225
- sessionArchives: this.sessionArchives.length,
226
- };
227
- }
228
- // ==================== Session Archive Methods ====================
229
- /**
230
- * Archive current session operations with compression
231
- */
232
- archiveSession(logs, options) {
233
- const id = `session_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
234
- const gate = this.gateMachine.getCurrentGate();
235
- const compressed = this.compressLogs(logs);
236
- const summary = options?.summary || this.generateSessionSummary(logs);
237
- const keyDecisions = options?.keyDecisions || this.extractKeyDecisions(logs);
238
- const archive = {
239
- id,
240
- timestamp: Date.now(),
241
- gate,
242
- summary,
243
- actionCount: logs.length,
244
- compressed,
245
- keyDecisions,
246
- };
247
- this.sessionArchives.push(archive);
248
- this.currentSessionId = id;
249
- return archive;
250
- }
251
- /**
252
- * Compress logs by removing redundancy
253
- */
254
- compressLogs(logs) {
255
- if (logs.length === 0)
256
- return '';
257
- const lines = [];
258
- const seenActions = new Set();
259
- const recentTime = logs.length > 10 ? logs[logs.length - 10].timestamp : logs[0].timestamp;
260
- lines.push(`## Session Archive (${logs.length} actions)`);
261
- lines.push(`Gate: ${this.gateMachine.getCurrentGate()}`);
262
- lines.push('');
263
- for (const log of logs.slice(-50)) {
264
- const time = new Date(log.timestamp).toISOString();
265
- const action = log.action.padEnd(30);
266
- if (seenActions.has(log.action) && log.status === 'ok') {
267
- lines.push(` ${time} [RPT] ${action}`);
268
- }
269
- else {
270
- lines.push(` ${time} [${log.status.padEnd(4)}] ${action}`);
271
- seenActions.add(log.action);
272
- }
273
- if (log.timestamp < recentTime) {
274
- lines.push(` ^ ${log.details ? JSON.stringify(log.details).substring(0, 100) : ''}`);
275
- }
276
- }
277
- return lines.join('\n');
278
- }
279
- /**
280
- * Generate a brief summary of the session
281
- */
282
- generateSessionSummary(logs) {
283
- const actions = logs.map(l => l.action);
284
- const unique = [...new Set(actions)];
285
- const okCount = logs.filter(l => l.status === 'ok').length;
286
- return `${this.gateMachine.getCurrentGate()}G: ${unique.slice(0, 3).join(', ')}${unique.length > 3 ? '...' : ''} (${okCount}/${logs.length} OK)`;
287
- }
288
- /**
289
- * Extract key decisions from logs
290
- */
291
- extractKeyDecisions(logs) {
292
- const decisions = [];
293
- for (const log of logs) {
294
- if (log.action.includes('decision') || log.action.includes('approve') || log.action.includes('commit')) {
295
- decisions.push(log.action);
296
- }
297
- }
298
- return decisions.slice(0, 10);
299
- }
300
- /**
301
- * Get session context for skills
302
- */
303
- getSessionContext(sessionId) {
304
- if (sessionId) {
305
- const archive = this.sessionArchives.find(a => a.id === sessionId);
306
- if (archive) {
307
- return `## Session ${archive.id}\nGate: ${archive.gate}\n${archive.compressed}`;
308
- }
309
- }
310
- if (this.sessionArchives.length === 0) {
311
- return 'No session archives available.';
312
- }
313
- const recent = this.sessionArchives.slice(-3);
314
- const lines = ['## Recent Sessions'];
315
- for (const archive of recent) {
316
- lines.push(`\n### ${archive.id}`);
317
- lines.push(`Gate: ${archive.gate} | Actions: ${archive.actionCount}`);
318
- lines.push(`Summary: ${archive.summary}`);
319
- if (archive.keyDecisions.length > 0) {
320
- lines.push(`Decisions: ${archive.keyDecisions.join(', ')}`);
321
- }
322
- }
323
- return lines.join('\n');
324
- }
325
- /**
326
- * Get all session archives
327
- */
328
- getSessionArchives() {
329
- return [...this.sessionArchives];
330
- }
331
- /**
332
- * Start a new session
333
- */
334
- startNewSession() {
335
- this.currentSessionId = `session_${Date.now()}`;
336
- return this.currentSessionId;
337
- }
338
- /**
339
- * Link current harness session to Pi SDK session
340
- */
341
- linkSession(sessionId) {
342
- this.currentSessionId = sessionId;
343
- }
344
- }
345
- /**
346
- * Create a default integration instance
347
- */
348
- export function createBollharnessIntegration(config) {
349
- return new BollharnessIntegration(config);
350
- }
351
- /**
352
- * Integration hooks for Bolloon's execution pipeline
353
- */
354
- export class BollharnessHooks {
355
- integration;
356
- constructor(integration) {
357
- this.integration = integration || new BollharnessIntegration();
358
- }
359
- /**
360
- * Pre-tool-use hook
361
- */
362
- async preToolUse(context) {
363
- // Check for dangerous operations
364
- if (context.tool === 'Bash') {
365
- const cmd = context.input?.command;
366
- if (cmd?.includes('rm -rf') || cmd?.includes('sudo')) {
367
- return {
368
- allowed: false,
369
- blockReason: 'Dangerous command detected',
370
- };
371
- }
372
- }
373
- // Check guards if file is being edited
374
- if (context.filePath && ['Edit', 'Write'].includes(context.tool)) {
375
- const result = await this.integration.preEditCheck(context.filePath);
376
- if (!result.success) {
377
- return {
378
- allowed: false,
379
- findings: result.guards?.findings.map(f => ({
380
- severity: f.severity,
381
- message: f.message,
382
- })),
383
- blockReason: 'Guard checks failed',
384
- };
385
- }
386
- }
387
- return { allowed: true };
388
- }
389
- /**
390
- * Post-tool-use hook
391
- */
392
- async postToolUse(context) {
393
- if (!context.filePath) {
394
- return { allowed: true };
395
- }
396
- const result = await this.integration.processFileEdit(context.filePath);
397
- return {
398
- allowed: result.success,
399
- context: result.context,
400
- findings: result.guards?.findings.map(f => ({
401
- severity: f.severity,
402
- message: f.message,
403
- })),
404
- };
405
- }
406
- /**
407
- * Session start hook
408
- */
409
- async sessionStart() {
410
- // Reset state if needed
411
- console.log('[Bollharness] Session started with governance enabled');
412
- }
413
- /**
414
- * Session end hook
415
- */
416
- async sessionEnd() {
417
- const metrics = this.integration.getMetrics();
418
- console.log('[Bollharness] Session ended', JSON.stringify(metrics, null, 2));
419
- }
420
- }
@@ -1,151 +0,0 @@
1
- /**
2
- * Skill Adapter - Bridge between Bollharness skills and Bolloon's SkillRegistry
3
- *
4
- * Loads skills from src/bollharness/.claude/skills/ and adapts them for Bolloon.
5
- *
6
- * Skill structure (from bollharness):
7
- * - arch: Project architect (architecture decisions, boundary freezing)
8
- * - lead: Development workflow commander (fail-closed state machine)
9
- * - task-arch: Task decomposition
10
- * - harness-eng: Engineering execution
11
- * - harness-dev: Development execution
12
- * - harness-eng-test: Engineering testing
13
- * - harness-ops: Operations and truth maintenance
14
- * - harness-bridge: Bridge agent coordination
15
- * - crystal-learn: Failure pattern extraction
16
- * - bug-triage: Bug classification
17
- * - bug-pipeline: Bug fix pipeline
18
- * - guardian-fixer: Issue-to-fix workflow
19
- * - plan-lock: Plan freezing
20
- * - skill-discovery: Skill discovery and recommendation
21
- * - toolkit: Toolkit management
22
- */
23
- import { SkillRegistry, Skill } from '@bolloon/constraint-runtime';
24
- export declare const BOLLHARNESS_SKILLS_DIR: any;
25
- export interface HarnessSkillMetadata {
26
- name: string;
27
- description: string;
28
- status: 'active' | 'deprecated' | 'experimental';
29
- tier: 'entry' | 'intermediate' | 'advanced' | 'meta' | 'execution';
30
- owner?: string;
31
- last_audited?: string;
32
- triggers?: string[];
33
- outputs?: string[];
34
- truth_policy?: string[];
35
- }
36
- export interface SkillTriggers {
37
- keywords: string[];
38
- patterns: RegExp[];
39
- contexts: string[];
40
- }
41
- export interface AdaptedSkill {
42
- name: string;
43
- description: string;
44
- triggers: SkillTriggers;
45
- execute: (params: Record<string, unknown>) => Promise<string>;
46
- getGatePack?: () => Record<string, unknown>;
47
- }
48
- export interface SkillMetadata {
49
- name: string;
50
- tier: 'entry' | 'intermediate' | 'advanced';
51
- status: 'active' | 'deprecated' | 'experimental';
52
- owner?: string;
53
- last_audited?: string;
54
- }
55
- /**
56
- * Base skill class for bollharness-compatible skills
57
- */
58
- export declare abstract class BaseSkill implements Skill {
59
- abstract name: string;
60
- abstract description: string;
61
- abstract execute(params: Record<string, unknown>): Promise<string>;
62
- protected log(message: string, level?: 'info' | 'warn' | 'error'): void;
63
- protected formatOutput(output: Record<string, unknown>): string;
64
- }
65
- /**
66
- * Architecture Skill - Project architect for architecture decisions
67
- */
68
- export declare class ArchSkill extends BaseSkill {
69
- name: string;
70
- description: string;
71
- execute(params: Record<string, unknown>): Promise<string>;
72
- private extractEssence;
73
- private identifyTensions;
74
- private compareAlternatives;
75
- private identifyBoundaries;
76
- private makeRecommendation;
77
- }
78
- /**
79
- * Lead Skill - Development workflow commander (fail-closed state machine)
80
- */
81
- export declare class LeadSkill extends BaseSkill {
82
- name: string;
83
- description: string;
84
- private currentGate;
85
- execute(params: Record<string, unknown>): Promise<string>;
86
- getGatePack(): string;
87
- private handleTransition;
88
- private classifyChange;
89
- }
90
- /**
91
- * Task Architecture Skill - Task decomposition
92
- */
93
- export declare class TaskArchSkill extends BaseSkill {
94
- name: string;
95
- description: string;
96
- execute(params: Record<string, unknown>): Promise<string>;
97
- private extractWorkPackages;
98
- private identifySeams;
99
- private identifyIntegration;
100
- private assignSeamOwners;
101
- }
102
- /**
103
- * Harness Engineering Skill - Engineering execution
104
- */
105
- export declare class HarnessEngSkill extends BaseSkill {
106
- name: string;
107
- description: string;
108
- execute(params: Record<string, unknown>): Promise<string>;
109
- private checkPrerequisites;
110
- private planImplementation;
111
- private createExecutionLog;
112
- }
113
- /**
114
- * Harness Engineering Test Skill - Test strategy and execution
115
- * Ported from src/bollharness/.claude/skills/harness-eng-test/SKILL.md
116
- */
117
- export declare class HarnessEngTestSkill extends BaseSkill {
118
- name: string;
119
- description: string;
120
- execute(params: Record<string, unknown>): Promise<string>;
121
- private createTestStrategy;
122
- private createTestCases;
123
- private executeTests;
124
- }
125
- /**
126
- * Crystal Learn Skill - Failure pattern extraction
127
- */
128
- export declare class CrystalLearnSkill extends BaseSkill {
129
- name: string;
130
- description: string;
131
- execute(params: Record<string, unknown>): Promise<string>;
132
- private identifyFailures;
133
- private extractPatterns;
134
- private generateInvariants;
135
- }
136
- /**
137
- * Skill Adapter - Registers all bollharness skills with Bolloon's SkillRegistry
138
- */
139
- export declare class SkillAdapter {
140
- private registry;
141
- private harnessSkills;
142
- constructor();
143
- private registerSkills;
144
- getRegistry(): SkillRegistry;
145
- getSkill(name: string): Skill | undefined;
146
- listSkills(): Skill[];
147
- listHarnessSkills(): HarnessSkillMetadata[];
148
- executeSkill(name: string, params: Record<string, unknown>): Promise<string>;
149
- private log;
150
- }
151
- export declare const createSkillAdapter: () => SkillAdapter;